Annotation of mandoc/mdoc_man.c, Revision 1.3
1.3 ! schwarze 1: /* $Id: mdoc_man.c,v 1.2 2011/09/20 13:47:55 schwarze Exp $ */
1.1 schwarze 2: /*
3: * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17: #include <stdio.h>
18: #include <string.h>
19:
20: #include "mandoc.h"
21: #include "mdoc.h"
22: #include "main.h"
23:
24: static int need_space = 0;
25: static int need_nl = 0;
26:
27: #define DECL_ARGS const struct mdoc_meta *m, \
28: const struct mdoc_node *n
29:
30: struct manact {
31: int (*cond)(DECL_ARGS);
32: int (*pre)(DECL_ARGS);
33: void (*post)(DECL_ARGS);
1.2 schwarze 34: const char *prefix;
35: const char *suffix;
1.1 schwarze 36: };
37:
38: static void print_word(const char *);
39: static void print_node(DECL_ARGS);
40:
41: static int cond_head(DECL_ARGS);
42: static int cond_body(DECL_ARGS);
43: static int pre_enc(DECL_ARGS);
44: static void post_enc(DECL_ARGS);
45: static void post_percent(DECL_ARGS);
1.3 ! schwarze 46: static int pre_sect(DECL_ARGS);
! 47: static void post_sect(DECL_ARGS);
1.1 schwarze 48:
1.3 ! schwarze 49: static int pre_ap(DECL_ARGS);
! 50: static int pre_bd(DECL_ARGS);
! 51: static void post_bd(DECL_ARGS);
! 52: static int pre_br(DECL_ARGS);
1.1 schwarze 53: static int pre_dl(DECL_ARGS);
54: static void post_dl(DECL_ARGS);
55: static int pre_it(DECL_ARGS);
56: static int pre_nm(DECL_ARGS);
57: static void post_nm(DECL_ARGS);
58: static int pre_ns(DECL_ARGS);
1.3 ! schwarze 59: static void post_pf(DECL_ARGS);
1.1 schwarze 60: static int pre_pp(DECL_ARGS);
1.3 ! schwarze 61: static int pre_sp(DECL_ARGS);
! 62: static void post_sp(DECL_ARGS);
1.1 schwarze 63: static int pre_xr(DECL_ARGS);
64:
65:
1.3 ! schwarze 66: static const struct manact manacts[MDOC_MAX + 1] = {
! 67: { NULL, pre_ap, NULL, NULL, NULL }, /* Ap */
! 68: { NULL, NULL, NULL, NULL, NULL }, /* Dd */
! 69: { NULL, NULL, NULL, NULL, NULL }, /* Dt */
1.1 schwarze 70: { NULL, NULL, NULL, NULL, NULL }, /* _Os */
1.3 ! schwarze 71: { NULL, pre_sect, post_sect, ".SH", NULL }, /* Sh */
! 72: { NULL, pre_sect, post_sect, ".SS", NULL }, /* Ss */
1.1 schwarze 73: { NULL, pre_pp, NULL, NULL, NULL }, /* Pp */
1.3 ! schwarze 74: { cond_body, pre_dl, post_dl, NULL, NULL }, /* D1 */
1.1 schwarze 75: { cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */
1.3 ! schwarze 76: { cond_body, pre_bd, post_bd, NULL, NULL }, /* Bd */
! 77: { NULL, NULL, NULL, NULL, NULL }, /* Ed */
! 78: { NULL, NULL, NULL, NULL, NULL }, /* Bl */
! 79: { NULL, NULL, NULL, NULL, NULL }, /* El */
1.1 schwarze 80: { NULL, pre_it, NULL, NULL, NULL }, /* _It */
81: { NULL, NULL, NULL, NULL, NULL }, /* _Ad */
82: { NULL, NULL, NULL, NULL, NULL }, /* _An */
83: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ar */
84: { NULL, NULL, NULL, NULL, NULL }, /* _Cd */
85: { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cm */
86: { NULL, NULL, NULL, NULL, NULL }, /* _Dv */
87: { NULL, NULL, NULL, NULL, NULL }, /* _Er */
88: { NULL, NULL, NULL, NULL, NULL }, /* _Ev */
89: { NULL, pre_enc, post_enc, "The \\fB",
90: "\\fP\nutility exits 0 on success, and >0 if an error occurs."
91: }, /* Ex */
92: { NULL, NULL, NULL, NULL, NULL }, /* _Fa */
93: { NULL, NULL, NULL, NULL, NULL }, /* _Fd */
94: { NULL, pre_enc, post_enc, "\\fB-", "\\fP" }, /* Fl */
95: { NULL, NULL, NULL, NULL, NULL }, /* _Fn */
96: { NULL, NULL, NULL, NULL, NULL }, /* _Ft */
1.3 ! schwarze 97: { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Ic */
1.1 schwarze 98: { NULL, NULL, NULL, NULL, NULL }, /* _In */
99: { NULL, NULL, NULL, NULL, NULL }, /* _Li */
100: { cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */
101: { NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */
102: { cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
103: { NULL, NULL, NULL, NULL, NULL }, /* _Ot */
104: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* _Pa */
105: { NULL, NULL, NULL, NULL, NULL }, /* _Rv */
106: { NULL, NULL, NULL, NULL, NULL }, /* _St */
107: { NULL, NULL, NULL, NULL, NULL }, /* _Va */
108: { NULL, NULL, NULL, NULL, NULL }, /* _Vt */
109: { NULL, pre_xr, NULL, NULL, NULL }, /* _Xr */
110: { NULL, NULL, post_percent, NULL, NULL }, /* _%A */
111: { NULL, NULL, NULL, NULL, NULL }, /* _%B */
112: { NULL, NULL, post_percent, NULL, NULL }, /* _%D */
113: { NULL, NULL, NULL, NULL, NULL }, /* _%I */
114: { NULL, pre_enc, post_percent, "\\fI", "\\fP" }, /* %J */
115: { NULL, NULL, NULL, NULL, NULL }, /* _%N */
116: { NULL, NULL, NULL, NULL, NULL }, /* _%O */
117: { NULL, NULL, NULL, NULL, NULL }, /* _%P */
118: { NULL, NULL, NULL, NULL, NULL }, /* _%R */
119: { NULL, pre_enc, post_percent, "\"", "\"" }, /* %T */
120: { NULL, NULL, NULL, NULL, NULL }, /* _%V */
121: { NULL, NULL, NULL, NULL, NULL }, /* _Ac */
122: { NULL, NULL, NULL, NULL, NULL }, /* _Ao */
123: { cond_body, pre_enc, post_enc, "<", ">" }, /* Aq */
124: { NULL, NULL, NULL, NULL, NULL }, /* _At */
1.3 ! schwarze 125: { NULL, NULL, NULL, NULL, NULL }, /* Bc */
1.1 schwarze 126: { NULL, NULL, NULL, NULL, NULL }, /* _Bf */
1.3 ! schwarze 127: { cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */
! 128: { cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */
1.1 schwarze 129: { NULL, NULL, NULL, NULL, NULL }, /* _Bsx */
130: { NULL, NULL, NULL, NULL, NULL }, /* _Bx */
131: { NULL, NULL, NULL, NULL, NULL }, /* _Db */
132: { NULL, NULL, NULL, NULL, NULL }, /* _Dc */
133: { NULL, NULL, NULL, NULL, NULL }, /* _Do */
134: { cond_body, pre_enc, post_enc, "``", "''" }, /* Dq */
135: { NULL, NULL, NULL, NULL, NULL }, /* _Ec */
136: { NULL, NULL, NULL, NULL, NULL }, /* _Ef */
1.3 ! schwarze 137: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Em */
1.1 schwarze 138: { NULL, NULL, NULL, NULL, NULL }, /* _Eo */
139: { NULL, NULL, NULL, NULL, NULL }, /* _Fx */
140: { NULL, NULL, NULL, NULL, NULL }, /* _Ms */
141: { NULL, NULL, NULL, NULL, NULL }, /* _No */
142: { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
143: { NULL, NULL, NULL, NULL, NULL }, /* _Nx */
144: { NULL, NULL, NULL, NULL, NULL }, /* _Ox */
1.3 ! schwarze 145: { NULL, NULL, NULL, NULL, NULL }, /* Pc */
! 146: { NULL, NULL, post_pf, NULL, NULL }, /* Pf */
! 147: { cond_body, pre_enc, post_enc, "(", ")" }, /* Po */
! 148: { cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */
1.1 schwarze 149: { NULL, NULL, NULL, NULL, NULL }, /* _Qc */
150: { cond_body, pre_enc, post_enc, "`", "'" }, /* Ql */
151: { NULL, NULL, NULL, NULL, NULL }, /* _Qo */
152: { NULL, NULL, NULL, NULL, NULL }, /* _Qq */
153: { NULL, NULL, NULL, NULL, NULL }, /* _Re */
154: { cond_body, pre_pp, NULL, NULL, NULL }, /* Rs */
155: { NULL, NULL, NULL, NULL, NULL }, /* _Sc */
156: { NULL, NULL, NULL, NULL, NULL }, /* _So */
157: { cond_body, pre_enc, post_enc, "`", "'" }, /* Sq */
158: { NULL, NULL, NULL, NULL, NULL }, /* _Sm */
1.3 ! schwarze 159: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Sx */
! 160: { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Sy */
1.1 schwarze 161: { NULL, NULL, NULL, NULL, NULL }, /* _Tn */
162: { NULL, NULL, NULL, NULL, NULL }, /* _Ux */
163: { NULL, NULL, NULL, NULL, NULL }, /* _Xc */
164: { NULL, NULL, NULL, NULL, NULL }, /* _Xo */
165: { NULL, NULL, NULL, NULL, NULL }, /* _Fo */
166: { NULL, NULL, NULL, NULL, NULL }, /* _Fc */
1.3 ! schwarze 167: { cond_body, pre_enc, post_enc, "[", "]" }, /* Oo */
1.1 schwarze 168: { NULL, NULL, NULL, NULL, NULL }, /* _Oc */
169: { NULL, NULL, NULL, NULL, NULL }, /* _Bk */
170: { NULL, NULL, NULL, NULL, NULL }, /* _Ek */
171: { NULL, NULL, NULL, NULL, NULL }, /* _Bt */
172: { NULL, NULL, NULL, NULL, NULL }, /* _Hf */
173: { NULL, NULL, NULL, NULL, NULL }, /* _Fr */
174: { NULL, NULL, NULL, NULL, NULL }, /* _Ud */
175: { NULL, NULL, NULL, NULL, NULL }, /* _Lb */
1.3 ! schwarze 176: { NULL, pre_pp, NULL, NULL, NULL }, /* Lp */
1.1 schwarze 177: { NULL, NULL, NULL, NULL, NULL }, /* _Lk */
178: { NULL, NULL, NULL, NULL, NULL }, /* _Mt */
179: { NULL, NULL, NULL, NULL, NULL }, /* _Brq */
180: { NULL, NULL, NULL, NULL, NULL }, /* _Bro */
181: { NULL, NULL, NULL, NULL, NULL }, /* _Brc */
182: { NULL, NULL, NULL, NULL, NULL }, /* _%C */
183: { NULL, NULL, NULL, NULL, NULL }, /* _Es */
184: { NULL, NULL, NULL, NULL, NULL }, /* _En */
185: { NULL, NULL, NULL, NULL, NULL }, /* _Dx */
186: { NULL, NULL, NULL, NULL, NULL }, /* _%Q */
1.3 ! schwarze 187: { NULL, pre_br, NULL, NULL, NULL }, /* br */
! 188: { NULL, pre_sp, post_sp, NULL, NULL }, /* sp */
1.1 schwarze 189: { NULL, NULL, NULL, NULL, NULL }, /* _%U */
190: { NULL, NULL, NULL, NULL, NULL }, /* _Ta */
1.3 ! schwarze 191: { NULL, NULL, NULL, NULL, NULL }, /* ROOT */
1.1 schwarze 192: };
193:
194:
195: static void
196: print_word(const char *s)
197: {
198: if (need_nl) {
199: putchar('\n');
200: need_space = 0;
201: need_nl = 0;
202: } else if (need_space &&
203: (NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]))
204: putchar(' ');
205: need_space = ('(' != s[0] && '[' != s[0]) || '\0' != s[1];
206: for ( ; *s; s++) {
207: switch (*s) {
208: case (ASCII_NBRSP):
209: printf("\\~");
210: break;
211: case (ASCII_HYPH):
212: putchar('-');
213: break;
214: default:
215: putchar(*s);
216: break;
217: }
218: }
219: }
220:
221: void
222: man_mdoc(void *arg, const struct mdoc *mdoc)
223: {
224: const struct mdoc_meta *m;
225: const struct mdoc_node *n;
226:
227: m = mdoc_meta(mdoc);
228: n = mdoc_node(mdoc);
229:
1.3 ! schwarze 230: printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
! 231: m->title, m->msec, m->date, m->os, m->vol);
1.1 schwarze 232: need_nl = 1;
233: need_space = 0;
234:
235: print_node(m, n);
1.3 ! schwarze 236: putchar('\n');
1.1 schwarze 237: }
238:
239: static void
240: print_node(DECL_ARGS)
241: {
242: const struct mdoc_node *prev, *sub;
243: const struct manact *act = NULL;
244: int cond, do_sub;
245:
246: prev = n->prev ? n->prev : n->parent;
247: if (prev && prev->line < n->line)
248: need_nl = 1;
249:
250: cond = 0;
251: do_sub = 1;
252: if (MDOC_TEXT == n->type) {
1.3 ! schwarze 253: if (need_nl && ('.' == *n->string || '\'' == *n->string)) {
! 254: print_word("\\&");
! 255: need_space = 0;
! 256: }
1.1 schwarze 257: print_word(n->string);
258: } else {
259: act = manacts + n->tok;
260: cond = NULL == act->cond || (*act->cond)(m, n);
261: if (cond && act->pre)
262: do_sub = (*act->pre)(m, n);
263: }
264:
265: if (do_sub)
266: for (sub = n->child; sub; sub = sub->next)
267: print_node(m, sub);
268:
269: if (cond && act->post)
270: (*act->post)(m, n);
271: }
272:
273: static int
274: cond_head(DECL_ARGS)
275: {
276: return(MDOC_HEAD == n->type);
277: }
278:
279: static int
280: cond_body(DECL_ARGS)
281: {
282: return(MDOC_BODY == n->type);
283: }
284:
285: static int
286: pre_enc(DECL_ARGS)
287: {
288: const char *prefix;
289:
290: prefix = manacts[n->tok].prefix;
291: if (NULL == prefix)
292: return(1);
293: print_word(prefix);
294: need_space = 0;
295: return(1);
296: }
297:
298: static void
299: post_enc(DECL_ARGS)
300: {
301: const char *suffix;
302:
303: suffix = manacts[n->tok].suffix;
304: if (NULL == suffix)
305: return;
306: need_space = 0;
307: print_word(suffix);
308: }
309:
310: static void
311: post_percent(DECL_ARGS)
312: {
313:
314: post_enc(m, n);
315: if (n->next)
316: print_word(",");
317: else {
318: print_word(".");
319: need_nl = 1;
320: }
321: }
322:
323: static int
1.3 ! schwarze 324: pre_sect(DECL_ARGS)
! 325: {
! 326:
! 327: if (MDOC_HEAD != n->type)
! 328: return(1);
! 329: need_nl = 1;
! 330: print_word(manacts[n->tok].prefix);
! 331: print_word("\"");
! 332: need_space = 0;
! 333: return(1);
! 334: }
! 335:
! 336: static void
! 337: post_sect(DECL_ARGS)
! 338: {
! 339:
! 340: if (MDOC_HEAD != n->type)
! 341: return;
! 342: need_space = 0;
! 343: print_word("\"");
! 344: need_nl = 1;
! 345: }
! 346:
! 347: static int
! 348: pre_ap(DECL_ARGS)
! 349: {
! 350:
! 351: need_space = 0;
! 352: print_word("'");
! 353: need_space = 0;
! 354: return(0);
! 355: }
! 356:
! 357: static int
! 358: pre_bd(DECL_ARGS)
! 359: {
! 360:
! 361: if (DISP_unfilled == n->norm->Bd.type ||
! 362: DISP_literal == n->norm->Bd.type) {
! 363: need_nl = 1;
! 364: print_word(".nf");
! 365: }
! 366: need_nl = 1;
! 367: return(1);
! 368: }
! 369:
! 370: static void
! 371: post_bd(DECL_ARGS)
! 372: {
! 373:
! 374: if (DISP_unfilled == n->norm->Bd.type ||
! 375: DISP_literal == n->norm->Bd.type) {
! 376: need_nl = 1;
! 377: print_word(".fi");
! 378: }
! 379: need_nl = 1;
! 380: }
! 381:
! 382: static int
! 383: pre_br(DECL_ARGS)
! 384: {
! 385:
! 386: need_nl = 1;
! 387: print_word(".br");
! 388: need_nl = 1;
! 389: return(0);
! 390: }
! 391:
! 392: static int
1.1 schwarze 393: pre_dl(DECL_ARGS)
394: {
395:
396: need_nl = 1;
397: print_word(".RS 6n");
398: need_nl = 1;
399: return(1);
400: }
401:
402: static void
403: post_dl(DECL_ARGS)
404: {
405:
406: need_nl = 1;
407: print_word(".RE");
408: need_nl = 1;
409: }
410:
411: static int
412: pre_it(DECL_ARGS)
413: {
414: const struct mdoc_node *bln;
415:
416: if (MDOC_HEAD == n->type) {
417: need_nl = 1;
418: print_word(".TP");
419: bln = n->parent->parent->prev;
1.3 ! schwarze 420: switch (bln->norm->Bl.type) {
! 421: case (LIST_bullet):
! 422: print_word("4n");
! 423: need_nl = 1;
! 424: print_word("\\fBo\\fP");
! 425: break;
! 426: default:
! 427: if (bln->norm->Bl.width)
! 428: print_word(bln->norm->Bl.width);
! 429: break;
! 430: }
1.1 schwarze 431: need_nl = 1;
432: }
433: return(1);
434: }
435:
436: static int
437: pre_nm(DECL_ARGS)
438: {
439:
440: if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
441: return(1);
442: print_word("\\fB");
443: need_space = 0;
444: if (NULL == n->child)
445: print_word(m->name);
446: return(1);
447: }
448:
449: static void
450: post_nm(DECL_ARGS)
451: {
452:
453: if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
454: return;
455: need_space = 0;
456: print_word("\\fP");
457: }
458:
459: static int
460: pre_ns(DECL_ARGS)
461: {
462:
463: need_space = 0;
464: return(0);
465: }
466:
1.3 ! schwarze 467: static void
! 468: post_pf(DECL_ARGS)
! 469: {
! 470:
! 471: need_space = 0;
! 472: }
! 473:
1.1 schwarze 474: static int
475: pre_pp(DECL_ARGS)
476: {
477:
478: need_nl = 1;
479: if (MDOC_It == n->parent->tok)
480: print_word(".sp");
481: else
482: print_word(".PP");
483: need_nl = 1;
484: return(1);
485: }
486:
487: static int
1.3 ! schwarze 488: pre_sp(DECL_ARGS)
1.1 schwarze 489: {
490:
491: need_nl = 1;
1.3 ! schwarze 492: print_word(".sp");
1.1 schwarze 493: return(1);
494: }
495:
496: static void
1.3 ! schwarze 497: post_sp(DECL_ARGS)
1.1 schwarze 498: {
499:
500: need_nl = 1;
501: }
502:
503: static int
504: pre_xr(DECL_ARGS)
505: {
506:
507: n = n->child;
508: if (NULL == n)
509: return(0);
510: print_node(m, n);
511: n = n->next;
512: if (NULL == n)
513: return(0);
514: need_space = 0;
515: print_word("(");
516: print_node(m, n);
517: print_word(")");
518: return(0);
519: }
CVSweb