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