Annotation of mandoc/mdoc_man.c, Revision 1.2
1.2 ! schwarze 1: /* $Id: mdoc_man.c,v 1.1 2011/09/17 15:00:51 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);
46:
47: static int pre_dl(DECL_ARGS);
48: static void post_dl(DECL_ARGS);
49: static int pre_it(DECL_ARGS);
50: static int pre_nm(DECL_ARGS);
51: static void post_nm(DECL_ARGS);
52: static int pre_ns(DECL_ARGS);
53: static int pre_pp(DECL_ARGS);
54: static int pre_sh(DECL_ARGS);
55: static void post_sh(DECL_ARGS);
56: static int pre_xr(DECL_ARGS);
57:
58:
59: static const struct manact manacts[MDOC_MAX] = {
60: { NULL, NULL, NULL, NULL, NULL }, /* _Ap */
61: { NULL, NULL, NULL, NULL, NULL }, /* _Dd */
62: { NULL, NULL, NULL, NULL, NULL }, /* _Dt */
63: { NULL, NULL, NULL, NULL, NULL }, /* _Os */
64: { NULL, pre_sh, post_sh, NULL, NULL }, /* Sh */
65: { NULL, NULL, NULL, NULL, NULL }, /* _Ss */
66: { NULL, pre_pp, NULL, NULL, NULL }, /* Pp */
67: { NULL, NULL, NULL, NULL, NULL }, /* _D1 */
68: { cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */
69: { NULL, NULL, NULL, NULL, NULL }, /* _Bd */
70: { NULL, NULL, NULL, NULL, NULL }, /* _Ed */
71: { NULL, NULL, NULL, NULL, NULL }, /* _Bl */
72: { NULL, NULL, NULL, NULL, NULL }, /* _El */
73: { NULL, pre_it, NULL, NULL, NULL }, /* _It */
74: { NULL, NULL, NULL, NULL, NULL }, /* _Ad */
75: { NULL, NULL, NULL, NULL, NULL }, /* _An */
76: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ar */
77: { NULL, NULL, NULL, NULL, NULL }, /* _Cd */
78: { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cm */
79: { NULL, NULL, NULL, NULL, NULL }, /* _Dv */
80: { NULL, NULL, NULL, NULL, NULL }, /* _Er */
81: { NULL, NULL, NULL, NULL, NULL }, /* _Ev */
82: { NULL, pre_enc, post_enc, "The \\fB",
83: "\\fP\nutility exits 0 on success, and >0 if an error occurs."
84: }, /* Ex */
85: { NULL, NULL, NULL, NULL, NULL }, /* _Fa */
86: { NULL, NULL, NULL, NULL, NULL }, /* _Fd */
87: { NULL, pre_enc, post_enc, "\\fB-", "\\fP" }, /* Fl */
88: { NULL, NULL, NULL, NULL, NULL }, /* _Fn */
89: { NULL, NULL, NULL, NULL, NULL }, /* _Ft */
90: { NULL, NULL, NULL, NULL, NULL }, /* _Ic */
91: { NULL, NULL, NULL, NULL, NULL }, /* _In */
92: { NULL, NULL, NULL, NULL, NULL }, /* _Li */
93: { cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */
94: { NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */
95: { cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
96: { NULL, NULL, NULL, NULL, NULL }, /* _Ot */
97: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* _Pa */
98: { NULL, NULL, NULL, NULL, NULL }, /* _Rv */
99: { NULL, NULL, NULL, NULL, NULL }, /* _St */
100: { NULL, NULL, NULL, NULL, NULL }, /* _Va */
101: { NULL, NULL, NULL, NULL, NULL }, /* _Vt */
102: { NULL, pre_xr, NULL, NULL, NULL }, /* _Xr */
103: { NULL, NULL, post_percent, NULL, NULL }, /* _%A */
104: { NULL, NULL, NULL, NULL, NULL }, /* _%B */
105: { NULL, NULL, post_percent, NULL, NULL }, /* _%D */
106: { NULL, NULL, NULL, NULL, NULL }, /* _%I */
107: { NULL, pre_enc, post_percent, "\\fI", "\\fP" }, /* %J */
108: { NULL, NULL, NULL, NULL, NULL }, /* _%N */
109: { NULL, NULL, NULL, NULL, NULL }, /* _%O */
110: { NULL, NULL, NULL, NULL, NULL }, /* _%P */
111: { NULL, NULL, NULL, NULL, NULL }, /* _%R */
112: { NULL, pre_enc, post_percent, "\"", "\"" }, /* %T */
113: { NULL, NULL, NULL, NULL, NULL }, /* _%V */
114: { NULL, NULL, NULL, NULL, NULL }, /* _Ac */
115: { NULL, NULL, NULL, NULL, NULL }, /* _Ao */
116: { cond_body, pre_enc, post_enc, "<", ">" }, /* Aq */
117: { NULL, NULL, NULL, NULL, NULL }, /* _At */
118: { NULL, NULL, NULL, NULL, NULL }, /* _Bc */
119: { NULL, NULL, NULL, NULL, NULL }, /* _Bf */
120: { NULL, NULL, NULL, NULL, NULL }, /* _Bo */
121: { NULL, NULL, NULL, NULL, NULL }, /* _Bq */
122: { NULL, NULL, NULL, NULL, NULL }, /* _Bsx */
123: { NULL, NULL, NULL, NULL, NULL }, /* _Bx */
124: { NULL, NULL, NULL, NULL, NULL }, /* _Db */
125: { NULL, NULL, NULL, NULL, NULL }, /* _Dc */
126: { NULL, NULL, NULL, NULL, NULL }, /* _Do */
127: { cond_body, pre_enc, post_enc, "``", "''" }, /* Dq */
128: { NULL, NULL, NULL, NULL, NULL }, /* _Ec */
129: { NULL, NULL, NULL, NULL, NULL }, /* _Ef */
130: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* _Em */
131: { NULL, NULL, NULL, NULL, NULL }, /* _Eo */
132: { NULL, NULL, NULL, NULL, NULL }, /* _Fx */
133: { NULL, NULL, NULL, NULL, NULL }, /* _Ms */
134: { NULL, NULL, NULL, NULL, NULL }, /* _No */
135: { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
136: { NULL, NULL, NULL, NULL, NULL }, /* _Nx */
137: { NULL, NULL, NULL, NULL, NULL }, /* _Ox */
138: { NULL, NULL, NULL, NULL, NULL }, /* _Pc */
139: { NULL, NULL, NULL, NULL, NULL }, /* _Pf */
140: { NULL, NULL, NULL, NULL, NULL }, /* _Po */
141: { cond_body, pre_enc, post_enc, "(", ")" }, /* _Pq */
142: { NULL, NULL, NULL, NULL, NULL }, /* _Qc */
143: { cond_body, pre_enc, post_enc, "`", "'" }, /* Ql */
144: { NULL, NULL, NULL, NULL, NULL }, /* _Qo */
145: { NULL, NULL, NULL, NULL, NULL }, /* _Qq */
146: { NULL, NULL, NULL, NULL, NULL }, /* _Re */
147: { cond_body, pre_pp, NULL, NULL, NULL }, /* Rs */
148: { NULL, NULL, NULL, NULL, NULL }, /* _Sc */
149: { NULL, NULL, NULL, NULL, NULL }, /* _So */
150: { cond_body, pre_enc, post_enc, "`", "'" }, /* Sq */
151: { NULL, NULL, NULL, NULL, NULL }, /* _Sm */
152: { NULL, NULL, NULL, NULL, NULL }, /* _Sx */
153: { NULL, NULL, NULL, NULL, NULL }, /* _Sy */
154: { NULL, NULL, NULL, NULL, NULL }, /* _Tn */
155: { NULL, NULL, NULL, NULL, NULL }, /* _Ux */
156: { NULL, NULL, NULL, NULL, NULL }, /* _Xc */
157: { NULL, NULL, NULL, NULL, NULL }, /* _Xo */
158: { NULL, NULL, NULL, NULL, NULL }, /* _Fo */
159: { NULL, NULL, NULL, NULL, NULL }, /* _Fc */
160: { NULL, NULL, NULL, NULL, NULL }, /* _Oo */
161: { NULL, NULL, NULL, NULL, NULL }, /* _Oc */
162: { NULL, NULL, NULL, NULL, NULL }, /* _Bk */
163: { NULL, NULL, NULL, NULL, NULL }, /* _Ek */
164: { NULL, NULL, NULL, NULL, NULL }, /* _Bt */
165: { NULL, NULL, NULL, NULL, NULL }, /* _Hf */
166: { NULL, NULL, NULL, NULL, NULL }, /* _Fr */
167: { NULL, NULL, NULL, NULL, NULL }, /* _Ud */
168: { NULL, NULL, NULL, NULL, NULL }, /* _Lb */
169: { NULL, NULL, NULL, NULL, NULL }, /* _Lp */
170: { NULL, NULL, NULL, NULL, NULL }, /* _Lk */
171: { NULL, NULL, NULL, NULL, NULL }, /* _Mt */
172: { NULL, NULL, NULL, NULL, NULL }, /* _Brq */
173: { NULL, NULL, NULL, NULL, NULL }, /* _Bro */
174: { NULL, NULL, NULL, NULL, NULL }, /* _Brc */
175: { NULL, NULL, NULL, NULL, NULL }, /* _%C */
176: { NULL, NULL, NULL, NULL, NULL }, /* _Es */
177: { NULL, NULL, NULL, NULL, NULL }, /* _En */
178: { NULL, NULL, NULL, NULL, NULL }, /* _Dx */
179: { NULL, NULL, NULL, NULL, NULL }, /* _%Q */
180: { NULL, NULL, NULL, NULL, NULL }, /* _br */
181: { NULL, NULL, NULL, NULL, NULL }, /* _sp */
182: { NULL, NULL, NULL, NULL, NULL }, /* _%U */
183: { NULL, NULL, NULL, NULL, NULL }, /* _Ta */
184: };
185:
186:
187: static void
188: print_word(const char *s)
189: {
190: if (need_nl) {
191: putchar('\n');
192: need_space = 0;
193: need_nl = 0;
194: } else if (need_space &&
195: (NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]))
196: putchar(' ');
197: need_space = ('(' != s[0] && '[' != s[0]) || '\0' != s[1];
198: for ( ; *s; s++) {
199: switch (*s) {
200: case (ASCII_NBRSP):
201: printf("\\~");
202: break;
203: case (ASCII_HYPH):
204: putchar('-');
205: break;
206: default:
207: putchar(*s);
208: break;
209: }
210: }
211: }
212:
213: void
214: man_mdoc(void *arg, const struct mdoc *mdoc)
215: {
216: const struct mdoc_meta *m;
217: const struct mdoc_node *n;
218:
219: m = mdoc_meta(mdoc);
220: n = mdoc_node(mdoc);
221:
222: printf(".TH \"%s\" \"%s\" \"%s\"", m->title, m->msec, m->date);
223: need_nl = 1;
224: need_space = 0;
225:
226: print_node(m, n);
227: }
228:
229: static void
230: print_node(DECL_ARGS)
231: {
232: const struct mdoc_node *prev, *sub;
233: const struct manact *act = NULL;
234: int cond, do_sub;
235:
236: prev = n->prev ? n->prev : n->parent;
237: if (prev && prev->line < n->line)
238: need_nl = 1;
239:
240: cond = 0;
241: do_sub = 1;
242: if (MDOC_TEXT == n->type) {
243: print_word(n->string);
244: } else {
245: act = manacts + n->tok;
246: cond = NULL == act->cond || (*act->cond)(m, n);
247: if (cond && act->pre)
248: do_sub = (*act->pre)(m, n);
249: }
250:
251: if (do_sub)
252: for (sub = n->child; sub; sub = sub->next)
253: print_node(m, sub);
254:
255: if (cond && act->post)
256: (*act->post)(m, n);
257: }
258:
259: static int
260: cond_head(DECL_ARGS)
261: {
262: return(MDOC_HEAD == n->type);
263: }
264:
265: static int
266: cond_body(DECL_ARGS)
267: {
268: return(MDOC_BODY == n->type);
269: }
270:
271: static int
272: pre_enc(DECL_ARGS)
273: {
274: const char *prefix;
275:
276: prefix = manacts[n->tok].prefix;
277: if (NULL == prefix)
278: return(1);
279: print_word(prefix);
280: need_space = 0;
281: return(1);
282: }
283:
284: static void
285: post_enc(DECL_ARGS)
286: {
287: const char *suffix;
288:
289: suffix = manacts[n->tok].suffix;
290: if (NULL == suffix)
291: return;
292: need_space = 0;
293: print_word(suffix);
294: }
295:
296: static void
297: post_percent(DECL_ARGS)
298: {
299:
300: post_enc(m, n);
301: if (n->next)
302: print_word(",");
303: else {
304: print_word(".");
305: need_nl = 1;
306: }
307: }
308:
309: static int
310: pre_dl(DECL_ARGS)
311: {
312:
313: need_nl = 1;
314: print_word(".RS 6n");
315: need_nl = 1;
316: return(1);
317: }
318:
319: static void
320: post_dl(DECL_ARGS)
321: {
322:
323: need_nl = 1;
324: print_word(".RE");
325: need_nl = 1;
326: }
327:
328: static int
329: pre_it(DECL_ARGS)
330: {
331: const struct mdoc_node *bln;
332:
333: if (MDOC_HEAD == n->type) {
334: need_nl = 1;
335: print_word(".TP");
336: bln = n->parent->parent->prev;
337: print_word(bln->norm->Bl.width);
338: need_nl = 1;
339: }
340: return(1);
341: }
342:
343: static int
344: pre_nm(DECL_ARGS)
345: {
346:
347: if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
348: return(1);
349: print_word("\\fB");
350: need_space = 0;
351: if (NULL == n->child)
352: print_word(m->name);
353: return(1);
354: }
355:
356: static void
357: post_nm(DECL_ARGS)
358: {
359:
360: if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
361: return;
362: need_space = 0;
363: print_word("\\fP");
364: }
365:
366: static int
367: pre_ns(DECL_ARGS)
368: {
369:
370: need_space = 0;
371: return(0);
372: }
373:
374: static int
375: pre_pp(DECL_ARGS)
376: {
377:
378: need_nl = 1;
379: if (MDOC_It == n->parent->tok)
380: print_word(".sp");
381: else
382: print_word(".PP");
383: need_nl = 1;
384: return(1);
385: }
386:
387: static int
388: pre_sh(DECL_ARGS)
389: {
390:
391: if (MDOC_HEAD != n->type)
392: return(1);
393: need_nl = 1;
394: print_word(".SH \"");
395: need_space = 0;
396: return(1);
397: }
398:
399: static void
400: post_sh(DECL_ARGS)
401: {
402:
403: if (MDOC_HEAD != n->type)
404: return;
405: need_space = 0;
406: print_word("\"");
407: need_nl = 1;
408: }
409:
410: static int
411: pre_xr(DECL_ARGS)
412: {
413:
414: n = n->child;
415: if (NULL == n)
416: return(0);
417: print_node(m, n);
418: n = n->next;
419: if (NULL == n)
420: return(0);
421: need_space = 0;
422: print_word("(");
423: print_node(m, n);
424: print_word(")");
425: return(0);
426: }
CVSweb