]> git.cameronkatri.com Git - mandoc.git/blob - mdoc_man.c
If -Tman is specified and input is -man, echo the preprocessed (`so'
[mandoc.git] / mdoc_man.c
1 /* $Id: mdoc_man.c,v 1.4 2011/10/06 22:29:12 kristaps Exp $ */
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 "man.h"
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);
35 const char *prefix;
36 const char *suffix;
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);
47 static int pre_sect(DECL_ARGS);
48 static void post_sect(DECL_ARGS);
49
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);
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);
60 static void post_pf(DECL_ARGS);
61 static int pre_pp(DECL_ARGS);
62 static int pre_sp(DECL_ARGS);
63 static void post_sp(DECL_ARGS);
64 static int pre_xr(DECL_ARGS);
65
66
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 */
71 { NULL, NULL, NULL, NULL, NULL }, /* _Os */
72 { NULL, pre_sect, post_sect, ".SH", NULL }, /* Sh */
73 { NULL, pre_sect, post_sect, ".SS", NULL }, /* Ss */
74 { NULL, pre_pp, NULL, NULL, NULL }, /* Pp */
75 { cond_body, pre_dl, post_dl, NULL, NULL }, /* D1 */
76 { cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */
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 */
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 */
98 { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Ic */
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 */
126 { NULL, NULL, NULL, NULL, NULL }, /* Bc */
127 { NULL, NULL, NULL, NULL, NULL }, /* _Bf */
128 { cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */
129 { cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */
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 */
138 { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Em */
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 */
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 */
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 */
160 { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Sx */
161 { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Sy */
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 */
168 { cond_body, pre_enc, post_enc, "[", "]" }, /* Oo */
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 */
177 { NULL, pre_pp, NULL, NULL, NULL }, /* Lp */
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 */
188 { NULL, pre_br, NULL, NULL, NULL }, /* br */
189 { NULL, pre_sp, post_sp, NULL, NULL }, /* sp */
190 { NULL, NULL, NULL, NULL, NULL }, /* _%U */
191 { NULL, NULL, NULL, NULL, NULL }, /* _Ta */
192 { NULL, NULL, NULL, NULL, NULL }, /* ROOT */
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 }
220 }
221
222 void
223 man_man(void *arg, const struct man *man)
224 {
225
226 fputs(mparse_getkeep(man_mparse(man)), stdout);
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
238 printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
239 m->title, m->msec, m->date, m->os, m->vol);
240 need_nl = 1;
241 need_space = 0;
242
243 print_node(m, n);
244 putchar('\n');
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) {
261 if (need_nl && ('.' == *n->string || '\'' == *n->string)) {
262 print_word("\\&");
263 need_space = 0;
264 }
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
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
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;
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 }
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
475 static void
476 post_pf(DECL_ARGS)
477 {
478
479 need_space = 0;
480 }
481
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
496 pre_sp(DECL_ARGS)
497 {
498
499 need_nl = 1;
500 print_word(".sp");
501 return(1);
502 }
503
504 static void
505 post_sp(DECL_ARGS)
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 }