Annotation of docbook2mdoc/docbook2mdoc.c, Revision 1.115
1.115 ! schwarze 1: /* $Id: docbook2mdoc.c,v 1.114 2019/04/12 19:14:50 schwarze Exp $ */
1.1 kristaps 2: /*
3: * Copyright (c) 2014 Kristaps Dzonsons <kristaps@bsd.lv>
1.50 schwarze 4: * Copyright (c) 2019 Ingo Schwarze <schwarze@openbsd.org>
1.1 kristaps 5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18: #include <assert.h>
19: #include <ctype.h>
20: #include <stdio.h>
21: #include <stdlib.h>
1.103 schwarze 22: #include <string.h>
1.1 kristaps 23:
1.74 schwarze 24: #include "node.h"
1.75 schwarze 25: #include "macro.h"
1.74 schwarze 26: #include "format.h"
27:
28: /*
29: * The implementation of the mdoc(7) formatter.
30: */
1.12 kristaps 31:
1.74 schwarze 32: static void pnode_print(struct format *, struct pnode *);
1.25 kristaps 33:
1.37 kristaps 34:
1.54 schwarze 35: static void
1.93 schwarze 36: pnode_printtext(struct format *f, struct pnode *n)
37: {
1.94 schwarze 38: struct pnode *nn;
1.93 schwarze 39: char *cp;
1.103 schwarze 40: int accept_arg;
1.93 schwarze 41:
1.103 schwarze 42: cp = n->b;
43: accept_arg = f->flags & FMT_ARG;
1.107 schwarze 44: if (f->linestate == LINE_MACRO && !n->spc && !accept_arg) {
1.103 schwarze 45: for (;;) {
46: if (*cp == '\0')
47: return;
48: if (strchr("!),.:;?]", *cp) == NULL)
49: break;
50: printf(" %c", *cp++);
51: }
52: if (isspace((unsigned char)*cp)) {
53: while (isspace((unsigned char)*cp))
54: cp++;
55: macro_close(f);
56: } else {
57: fputs(" Ns", stdout);
58: f->flags &= FMT_IMPL;
59: accept_arg = 1;
60: }
1.94 schwarze 61: }
1.103 schwarze 62: if (f->linestate == LINE_MACRO && !accept_arg &&
63: (f->flags & (FMT_CHILD | FMT_IMPL)) == 0)
64: macro_close(f);
1.94 schwarze 65:
66: /*
67: * Text preceding a macro without intervening whitespace
68: * requires a .Pf macro.
69: * Set the spacing flag to avoid a redundant .Ns macro.
70: */
71:
72: if (f->linestate != LINE_MACRO &&
1.113 schwarze 73: (nn = TAILQ_NEXT(n, child)) != NULL && nn->spc == 0) {
74: switch (pnode_class(nn->node)) {
75: case CLASS_LINE:
76: case CLASS_ENCL:
77: macro_open(f, "Pf");
78: accept_arg = 1;
79: f->flags |= FMT_CHILD;
80: nn->spc = 1;
81: break;
82: default:
83: break;
84: }
1.93 schwarze 85: }
86:
1.103 schwarze 87: switch (f->linestate) {
1.107 schwarze 88: case LINE_NEW:
89: break;
1.103 schwarze 90: case LINE_TEXT:
1.105 schwarze 91: if (n->spc) {
1.107 schwarze 92: if (n->node == NODE_TEXT)
93: macro_close(f);
94: else
95: putchar(' ');
1.105 schwarze 96: }
1.103 schwarze 97: break;
98: case LINE_MACRO:
1.107 schwarze 99: if (accept_arg)
1.93 schwarze 100: putchar(' ');
1.107 schwarze 101: else
102: macro_close(f);
1.103 schwarze 103: break;
1.93 schwarze 104: }
105:
106: if (n->node == NODE_ESCAPE) {
107: fputs(n->b, stdout);
1.107 schwarze 108: if (f->linestate == LINE_NEW)
109: f->linestate = LINE_TEXT;
1.93 schwarze 110: return;
111: }
112:
113: /*
114: * Remove the prefix '-' from <option> elements
115: * because the arguments of .Fl macros do not need it.
116: */
117:
118: if (n->parent != NULL && n->parent->node == NODE_OPTION && *cp == '-')
119: cp++;
120:
1.107 schwarze 121: if (f->linestate == LINE_MACRO)
122: macro_addarg(f, cp, 0);
123: else
124: print_text(f, cp, 0);
1.93 schwarze 125: }
126:
127: static void
1.101 schwarze 128: pnode_printpara(struct format *f, struct pnode *n)
1.54 schwarze 129: {
1.101 schwarze 130: struct pnode *np;
1.54 schwarze 131:
1.101 schwarze 132: if (n->parent == NULL)
1.54 schwarze 133: return;
134:
1.101 schwarze 135: if ((np = TAILQ_PREV(n, pnodeq, child)) == NULL)
136: np = n->parent;
1.97 schwarze 137:
1.103 schwarze 138: f->flags = 0;
139:
1.101 schwarze 140: switch (np->node) {
1.61 schwarze 141: case NODE_ENTRY:
1.99 schwarze 142: case NODE_GLOSSTERM:
1.61 schwarze 143: case NODE_LISTITEM:
1.99 schwarze 144: case NODE_TERM:
1.61 schwarze 145: return;
1.100 schwarze 146: case NODE_APPENDIX:
147: case NODE_LEGALNOTICE:
1.61 schwarze 148: case NODE_PREFACE:
149: case NODE_SECTION:
1.101 schwarze 150: if (f->level < 3)
1.61 schwarze 151: return;
152: break;
153: default:
154: break;
155: }
1.101 schwarze 156: macro_line(f, "Pp");
1.54 schwarze 157: }
158:
1.110 schwarze 159: static void
160: pnode_printrefnamediv(struct format *f, struct pnode *n)
161: {
162: struct pnode *nc, *nn;
163: int comma;
164:
165: macro_line(f, "Sh NAME");
166: comma = 0;
167: TAILQ_FOREACH_SAFE(nc, &n->childq, child, nn) {
168: if (nc->node != NODE_REFNAME)
169: continue;
170: if (comma)
171: macro_addarg(f, ",", ARG_SPACE);
172: macro_open(f, "Nm");
173: macro_addnode(f, nc, ARG_SPACE);
174: pnode_unlink(nc);
175: comma = 1;
176: }
177: macro_close(f);
178: }
179:
1.37 kristaps 180: /*
1.10 kristaps 181: * If the SYNOPSIS macro has a superfluous title, kill it.
1.8 kristaps 182: */
1.1 kristaps 183: static void
1.101 schwarze 184: pnode_printrefsynopsisdiv(struct format *f, struct pnode *n)
1.6 kristaps 185: {
1.101 schwarze 186: struct pnode *nc, *nn;
1.6 kristaps 187:
1.101 schwarze 188: TAILQ_FOREACH_SAFE(nc, &n->childq, child, nn)
189: if (nc->node == NODE_TITLE)
190: pnode_unlink(nc);
1.71 schwarze 191:
1.101 schwarze 192: macro_line(f, "Sh SYNOPSIS");
1.6 kristaps 193: }
194:
1.8 kristaps 195: /*
196: * Start a hopefully-named `Sh' section.
197: */
1.6 kristaps 198: static void
1.101 schwarze 199: pnode_printrefsect(struct format *f, struct pnode *n)
1.1 kristaps 200: {
1.115 ! schwarze 201: struct pnode *nc, *ncc;
1.52 schwarze 202: const char *title;
203: int flags, level;
204:
1.101 schwarze 205: if (n->parent == NULL)
1.56 schwarze 206: return;
207:
1.101 schwarze 208: level = ++f->level;
1.72 schwarze 209: flags = ARG_SPACE;
210: if (level == 1)
211: flags |= ARG_UPPER;
1.64 schwarze 212: if (level < 3) {
1.101 schwarze 213: switch (n->node) {
1.62 schwarze 214: case NODE_CAUTION:
215: case NODE_NOTE:
216: case NODE_TIP:
217: case NODE_WARNING:
1.52 schwarze 218: level = 3;
219: break;
220: default:
221: break;
222: }
223: }
1.1 kristaps 224:
1.101 schwarze 225: TAILQ_FOREACH(nc, &n->childq, child)
226: if (nc->node == NODE_TITLE)
1.1 kristaps 227: break;
228:
1.101 schwarze 229: if (nc == NULL) {
230: switch (n->node) {
1.62 schwarze 231: case NODE_PREFACE:
1.52 schwarze 232: title = "Preface";
233: break;
1.100 schwarze 234: case NODE_APPENDIX:
235: title = "Appendix";
236: break;
237: case NODE_LEGALNOTICE:
238: title = "Legal Notice";
239: break;
1.62 schwarze 240: case NODE_CAUTION:
1.52 schwarze 241: title = "Caution";
242: break;
1.62 schwarze 243: case NODE_NOTE:
1.52 schwarze 244: title = "Note";
245: break;
1.62 schwarze 246: case NODE_TIP:
1.52 schwarze 247: title = "Tip";
248: break;
1.62 schwarze 249: case NODE_WARNING:
1.52 schwarze 250: title = "Warning";
251: break;
252: default:
253: title = "Unknown";
254: break;
255: }
256: }
257:
258: switch (level) {
1.62 schwarze 259: case 1:
1.101 schwarze 260: macro_close(f);
261: macro_open(f, "Sh");
1.29 kristaps 262: break;
1.62 schwarze 263: case 2:
1.101 schwarze 264: macro_close(f);
265: macro_open(f, "Ss");
1.29 kristaps 266: break;
1.52 schwarze 267: default:
1.101 schwarze 268: pnode_printpara(f, n);
269: macro_open(f, "Sy");
1.29 kristaps 270: break;
271: }
1.20 kristaps 272:
1.115 ! schwarze 273: if (nc != NULL)
1.101 schwarze 274: macro_addnode(f, nc, flags);
1.115 ! schwarze 275: else
1.101 schwarze 276: macro_addarg(f, title, flags | ARG_QUOTED);
277: macro_close(f);
1.115 ! schwarze 278:
! 279: /*
! 280: * DocBook has no equivalent for -split mode,
! 281: * so just switch the default in the AUTHORS section.
! 282: */
! 283:
! 284: if (nc != NULL) {
! 285: ncc = TAILQ_FIRST(&nc->childq);
! 286: if (ncc != NULL && ncc->node == NODE_TEXT &&
! 287: strcasecmp(ncc->b, "AUTHORS") == 0)
! 288: macro_line(f, "An -nosplit");
! 289: pnode_unlink(nc);
! 290: }
1.1 kristaps 291: }
292:
1.8 kristaps 293: /*
294: * Start a reference, extracting the title and volume.
295: */
1.1 kristaps 296: static void
1.101 schwarze 297: pnode_printciterefentry(struct format *f, struct pnode *n)
1.1 kristaps 298: {
1.101 schwarze 299: struct pnode *nc, *title, *manvol;
1.1 kristaps 300:
301: title = manvol = NULL;
1.101 schwarze 302: TAILQ_FOREACH(nc, &n->childq, child) {
303: if (nc->node == NODE_MANVOLNUM)
304: manvol = nc;
305: else if (nc->node == NODE_REFENTRYTITLE)
306: title = nc;
1.69 schwarze 307: }
1.101 schwarze 308: macro_open(f, "Xr");
1.69 schwarze 309: if (title == NULL)
1.101 schwarze 310: macro_addarg(f, "unknown", ARG_SPACE);
1.69 schwarze 311: else
1.101 schwarze 312: macro_addnode(f, title, ARG_SPACE | ARG_SINGLE);
1.69 schwarze 313: if (manvol == NULL)
1.101 schwarze 314: macro_addarg(f, "1", ARG_SPACE);
1.64 schwarze 315: else
1.101 schwarze 316: macro_addnode(f, manvol, ARG_SPACE | ARG_SINGLE);
317: pnode_unlinksub(n);
1.1 kristaps 318: }
319:
320: static void
1.101 schwarze 321: pnode_printrefmeta(struct format *f, struct pnode *n)
1.1 kristaps 322: {
1.101 schwarze 323: struct pnode *nc, *title, *manvol;
1.1 kristaps 324:
325: title = manvol = NULL;
1.101 schwarze 326: TAILQ_FOREACH(nc, &n->childq, child) {
327: if (nc->node == NODE_MANVOLNUM)
328: manvol = nc;
329: else if (nc->node == NODE_REFENTRYTITLE)
330: title = nc;
1.69 schwarze 331: }
1.101 schwarze 332: macro_close(f);
333: macro_open(f, "Dt");
1.69 schwarze 334: if (title == NULL)
1.101 schwarze 335: macro_addarg(f, "UNKNOWN", ARG_SPACE);
1.69 schwarze 336: else
1.101 schwarze 337: macro_addnode(f, title, ARG_SPACE | ARG_SINGLE | ARG_UPPER);
1.69 schwarze 338: if (manvol == NULL)
1.101 schwarze 339: macro_addarg(f, "1", ARG_SPACE);
1.13 kristaps 340: else
1.101 schwarze 341: macro_addnode(f, manvol, ARG_SPACE | ARG_SINGLE);
342: macro_close(f);
343: pnode_unlink(n);
1.1 kristaps 344: }
345:
1.3 kristaps 346: static void
1.86 schwarze 347: pnode_printfuncdef(struct format *f, struct pnode *n)
1.3 kristaps 348: {
1.86 schwarze 349: struct pnode *nc;
1.3 kristaps 350:
1.86 schwarze 351: nc = TAILQ_FIRST(&n->childq);
352: if (nc != NULL && nc->node == NODE_TEXT) {
353: macro_argline(f, "Ft", nc->b);
354: pnode_unlink(nc);
1.13 kristaps 355: }
1.86 schwarze 356: macro_nodeline(f, "Fo", n, ARG_SINGLE);
357: pnode_unlinksub(n);
1.3 kristaps 358: }
359:
1.40 kristaps 360: /*
1.41 kristaps 361: * The <mml:mfenced> node is a little peculiar.
362: * First, it can have arbitrary open and closing tokens, which default
363: * to parentheses.
364: * Second, >1 arguments are separated by commas.
365: */
366: static void
1.101 schwarze 367: pnode_printmathfenced(struct format *f, struct pnode *n)
1.41 kristaps 368: {
1.101 schwarze 369: struct pnode *nc;
1.41 kristaps 370:
1.101 schwarze 371: printf("left %s ", pnode_getattr_raw(n, ATTRKEY_OPEN, "("));
1.41 kristaps 372:
1.101 schwarze 373: nc = TAILQ_FIRST(&n->childq);
374: pnode_print(f, nc);
1.41 kristaps 375:
1.101 schwarze 376: while ((nc = TAILQ_NEXT(nc, child)) != NULL) {
1.41 kristaps 377: putchar(',');
1.101 schwarze 378: pnode_print(f, nc);
1.41 kristaps 379: }
1.101 schwarze 380: printf("right %s ", pnode_getattr_raw(n, ATTRKEY_CLOSE, ")"));
381: pnode_unlinksub(n);
1.41 kristaps 382: }
383:
384: /*
1.40 kristaps 385: * These math nodes require special handling because they have infix
386: * syntax, instead of the usual prefix or prefix.
387: * So we need to break up the first and second child node with a
388: * particular eqn(7) word.
389: */
390: static void
1.101 schwarze 391: pnode_printmath(struct format *f, struct pnode *n)
1.40 kristaps 392: {
1.101 schwarze 393: struct pnode *nc;
1.40 kristaps 394:
1.101 schwarze 395: nc = TAILQ_FIRST(&n->childq);
396: pnode_print(f, nc);
1.40 kristaps 397:
1.101 schwarze 398: switch (n->node) {
1.62 schwarze 399: case NODE_MML_MSUP:
1.42 kristaps 400: fputs(" sup ", stdout);
1.40 kristaps 401: break;
1.62 schwarze 402: case NODE_MML_MFRAC:
1.42 kristaps 403: fputs(" over ", stdout);
1.40 kristaps 404: break;
1.62 schwarze 405: case NODE_MML_MSUB:
1.42 kristaps 406: fputs(" sub ", stdout);
1.40 kristaps 407: break;
408: default:
409: break;
410: }
411:
1.101 schwarze 412: nc = TAILQ_NEXT(nc, child);
413: pnode_print(f, nc);
414: pnode_unlinksub(n);
1.40 kristaps 415: }
416:
1.3 kristaps 417: static void
1.101 schwarze 418: pnode_printfuncprototype(struct format *f, struct pnode *n)
1.3 kristaps 419: {
1.101 schwarze 420: struct pnode *nc, *fdef;
1.3 kristaps 421:
1.101 schwarze 422: TAILQ_FOREACH(fdef, &n->childq, child)
1.64 schwarze 423: if (fdef->node == NODE_FUNCDEF)
1.3 kristaps 424: break;
425:
1.86 schwarze 426: if (fdef != NULL) {
1.101 schwarze 427: pnode_printfuncdef(f, fdef);
1.86 schwarze 428: pnode_unlink(fdef);
429: } else
1.101 schwarze 430: macro_line(f, "Fo UNKNOWN");
1.3 kristaps 431:
1.101 schwarze 432: TAILQ_FOREACH(nc, &n->childq, child)
433: macro_nodeline(f, "Fa", nc, ARG_SINGLE);
1.3 kristaps 434:
1.101 schwarze 435: macro_line(f, "Fc");
436: pnode_unlinksub(n);
1.3 kristaps 437: }
438:
1.44 schwarze 439: /*
1.10 kristaps 440: * The <arg> element is more complicated than it should be because text
441: * nodes are treated like ".Ar foo", but non-text nodes need to be
442: * re-sent into the printer (i.e., without the preceding ".Ar").
1.12 kristaps 443: * This also handles the case of "repetition" (or in other words, the
444: * ellipsis following an argument) and optionality.
1.10 kristaps 445: */
1.4 kristaps 446: static void
1.101 schwarze 447: pnode_printarg(struct format *f, struct pnode *n)
1.4 kristaps 448: {
1.101 schwarze 449: struct pnode *nc;
450: struct pattr *a;
1.103 schwarze 451: int isop, isrep, was_impl;
1.12 kristaps 452:
453: isop = 1;
1.103 schwarze 454: isrep = was_impl = 0;
1.101 schwarze 455: TAILQ_FOREACH(a, &n->attrq, child) {
456: if (a->key == ATTRKEY_CHOICE &&
457: (a->val == ATTRVAL_PLAIN || a->val == ATTRVAL_REQ))
1.12 kristaps 458: isop = 0;
1.101 schwarze 459: else if (a->key == ATTRKEY_REP && a->val == ATTRVAL_REPEAT)
1.12 kristaps 460: isrep = 1;
461: }
1.103 schwarze 462: if (isop) {
463: if (f->flags & FMT_IMPL) {
464: was_impl = 1;
465: macro_open(f, "Oo");
466: } else {
467: macro_open(f, "Op");
468: f->flags |= FMT_IMPL;
469: }
470: }
1.4 kristaps 471:
1.101 schwarze 472: TAILQ_FOREACH(nc, &n->childq, child) {
473: if (nc->node == NODE_TEXT)
474: macro_open(f, "Ar");
475: pnode_print(f, nc);
476: if (isrep && nc->node == NODE_TEXT)
477: macro_addarg(f, "...", ARG_SPACE);
1.10 kristaps 478: }
1.103 schwarze 479: if (isop) {
480: if (was_impl)
481: macro_open(f, "Oc");
482: else
483: f->flags &= ~FMT_IMPL;
484: }
1.101 schwarze 485: pnode_unlinksub(n);
1.4 kristaps 486: }
487:
1.24 kristaps 488: static void
1.101 schwarze 489: pnode_printgroup(struct format *f, struct pnode *n)
1.24 kristaps 490: {
1.101 schwarze 491: struct pnode *nc, *nn;
492: struct pattr *a;
1.24 kristaps 493: int isop, sv;
494:
495: isop = 1;
1.101 schwarze 496: TAILQ_FOREACH(a, &n->attrq, child)
497: if (a->key == ATTRKEY_CHOICE &&
498: (a->val == ATTRVAL_PLAIN || a->val == ATTRVAL_REQ)) {
1.24 kristaps 499: isop = 0;
500: break;
501: }
502:
1.44 schwarze 503: /*
1.24 kristaps 504: * Make sure we're on a macro line.
505: * This will prevent pnode_print() for putting us on a
506: * subsequent line.
507: */
1.101 schwarze 508: sv = f->linestate == LINE_NEW;
1.44 schwarze 509: if (isop)
1.101 schwarze 510: macro_open(f, "Op");
1.24 kristaps 511: else if (sv)
1.101 schwarze 512: macro_open(f, "No");
1.103 schwarze 513: f->flags |= FMT_IMPL;
1.24 kristaps 514:
515: /*
516: * Keep on printing text separated by the vertical bar as long
517: * as we're within the same origin node as the group.
518: * This is kind of a nightmare.
519: * Eh, DocBook...
520: * FIXME: if there's a "Fl", we don't cut off the leading "-"
521: * like we do in pnode_print().
522: */
1.101 schwarze 523: TAILQ_FOREACH(nc, &n->childq, child) {
524: pnode_print(f, nc);
525: nn = TAILQ_NEXT(nc, child);
526: while (nn != NULL) {
527: if (nc->node != nn->node)
1.24 kristaps 528: break;
1.101 schwarze 529: macro_addarg(f, "|", ARG_SPACE);
530: macro_addnode(f, nn, ARG_SPACE);
531: nc = nn;
532: nn = TAILQ_NEXT(nn, child);
1.24 kristaps 533: }
534: }
1.69 schwarze 535: if (sv)
1.101 schwarze 536: macro_close(f);
1.103 schwarze 537: f->flags &= ~FMT_IMPL;
1.101 schwarze 538: pnode_unlinksub(n);
1.24 kristaps 539: }
540:
1.7 kristaps 541: static void
1.78 schwarze 542: pnode_printauthor(struct format *f, struct pnode *n)
543: {
1.101 schwarze 544: struct pnode *nc, *nn;
1.78 schwarze 545: int have_contrib, have_name;
546:
547: /*
548: * Print <contrib> children up front, before the .An scope,
549: * and figure out whether we a name of a person.
550: */
551:
552: have_contrib = have_name = 0;
1.101 schwarze 553: TAILQ_FOREACH_SAFE(nc, &n->childq, child, nn) {
1.78 schwarze 554: switch (nc->node) {
555: case NODE_CONTRIB:
556: if (have_contrib)
557: print_text(f, ",", 0);
558: print_textnode(f, nc);
559: pnode_unlink(nc);
560: have_contrib = 1;
561: break;
562: case NODE_PERSONNAME:
563: have_name = 1;
564: break;
565: default:
566: break;
567: }
568: }
569: if (TAILQ_FIRST(&n->childq) == NULL)
570: return;
571:
572: if (have_contrib)
573: print_text(f, ":", 0);
574:
575: /*
576: * If we have a name, print it in the .An scope and leave
577: * all other content for child handlers, to print after the
578: * scope. Otherwise, print everything in the scope.
579: */
580:
581: macro_open(f, "An");
1.101 schwarze 582: TAILQ_FOREACH_SAFE(nc, &n->childq, child, nn) {
1.78 schwarze 583: if (nc->node == NODE_PERSONNAME || have_name == 0) {
584: macro_addnode(f, nc, ARG_SPACE);
585: pnode_unlink(nc);
586: }
1.80 schwarze 587: }
588:
589: /*
590: * If there is an email address,
591: * print it on the same macro line.
592: */
593:
594: if ((nc = pnode_findfirst(n, NODE_EMAIL)) != NULL) {
1.103 schwarze 595: f->flags |= FMT_CHILD;
1.115 ! schwarze 596: macro_open(f, "Aq Mt");
! 597: macro_addnode(f, nc, ARG_SPACE);
1.80 schwarze 598: pnode_unlink(nc);
1.78 schwarze 599: }
600:
601: /*
602: * If there are still unprinted children, end the scope
603: * with a comma. Otherwise, leave the scope open in case
604: * a text node follows that starts with closing punctuation.
605: */
606:
607: if (TAILQ_FIRST(&n->childq) != NULL) {
608: macro_addarg(f, ",", ARG_SPACE);
609: macro_close(f);
610: }
611: }
612:
613: static void
1.96 schwarze 614: pnode_printlink(struct format *f, struct pnode *n)
615: {
1.109 schwarze 616: struct pnode *nc;
1.96 schwarze 617: const char *uri, *text;
618:
619: uri = pnode_getattr_raw(n, ATTRKEY_LINKEND, NULL);
620: if (uri != NULL) {
621: if (TAILQ_FIRST(&n->childq) != NULL) {
1.109 schwarze 622: TAILQ_FOREACH(nc, &n->childq, child)
623: pnode_print(f, nc);
1.96 schwarze 624: text = "";
1.109 schwarze 625: } else if ((text = pnode_getattr_raw(n,
626: ATTRKEY_ENDTERM, NULL)) != NULL) {
627: if (f->linestate == LINE_MACRO && f->flags & FMT_ARG)
628: macro_addarg(f, text, ARG_SPACE);
629: else
1.96 schwarze 630: print_text(f, text, ARG_SPACE);
631: }
1.103 schwarze 632: if (text != NULL) {
1.109 schwarze 633: if (f->flags & FMT_IMPL)
634: macro_open(f, "Po");
635: else {
636: macro_open(f, "Pq");
637: f->flags |= FMT_CHILD;
638: }
1.103 schwarze 639: }
1.96 schwarze 640: macro_open(f, "Sx");
641: macro_addarg(f, uri, ARG_SPACE);
1.109 schwarze 642: if (text != NULL && f->flags & FMT_IMPL)
643: macro_open(f, "Pc");
1.96 schwarze 644: pnode_unlinksub(n);
645: return;
646: }
647: uri = pnode_getattr_raw(n, ATTRKEY_XLINK_HREF, NULL);
648: if (uri == NULL)
649: uri = pnode_getattr_raw(n, ATTRKEY_URL, NULL);
650: if (uri != NULL) {
651: macro_open(f, "Lk");
652: macro_addarg(f, uri, ARG_SPACE | ARG_SINGLE);
653: if (TAILQ_FIRST(&n->childq) != NULL)
654: macro_addnode(f, n, ARG_SPACE | ARG_SINGLE);
655: pnode_unlinksub(n);
656: return;
657: }
658: }
659:
660: static void
1.101 schwarze 661: pnode_printprologue(struct format *f, struct ptree *tree)
1.7 kristaps 662: {
1.74 schwarze 663: struct pnode *refmeta;
1.7 kristaps 664:
1.74 schwarze 665: refmeta = tree->root == NULL ? NULL :
666: pnode_findfirst(tree->root, NODE_REFMETA);
1.9 kristaps 667:
1.101 schwarze 668: macro_line(f, "Dd $Mdocdate" "$");
1.74 schwarze 669: if (refmeta == NULL) {
1.101 schwarze 670: macro_open(f, "Dt");
671: macro_addarg(f,
1.74 schwarze 672: pnode_getattr_raw(tree->root, ATTRKEY_ID, "UNKNOWN"),
1.72 schwarze 673: ARG_SPACE | ARG_SINGLE | ARG_UPPER);
1.101 schwarze 674: macro_addarg(f, "1", ARG_SPACE);
675: macro_close(f);
1.74 schwarze 676: } else
1.101 schwarze 677: pnode_printrefmeta(f, refmeta);
678: macro_line(f, "Os");
1.7 kristaps 679: }
680:
1.42 kristaps 681: /*
682: * We can have multiple <term> elements within a <varlistentry>, which
683: * we should comma-separate as list headers.
684: */
1.13 kristaps 685: static void
1.101 schwarze 686: pnode_printvarlistentry(struct format *f, struct pnode *n)
1.13 kristaps 687: {
1.108 schwarze 688: struct pnode *nc, *nn;
1.42 kristaps 689: int first = 1;
1.13 kristaps 690:
1.101 schwarze 691: macro_open(f, "It");
1.103 schwarze 692: f->flags |= FMT_IMPL;
1.108 schwarze 693: TAILQ_FOREACH_SAFE(nc, &n->childq, child, nn) {
1.101 schwarze 694: if (nc->node != NODE_TERM && nc->node != NODE_GLOSSTERM)
1.69 schwarze 695: continue;
1.108 schwarze 696: if (first == 0) {
697: switch (f->linestate) {
698: case LINE_NEW:
699: break;
700: case LINE_TEXT:
701: print_text(f, ",", 0);
702: break;
703: case LINE_MACRO:
704: macro_addarg(f, ",", 0);
705: break;
706: }
707: }
1.101 schwarze 708: pnode_print(f, nc);
1.108 schwarze 709: pnode_unlink(nc);
1.69 schwarze 710: first = 0;
711: }
1.101 schwarze 712: macro_close(f);
1.108 schwarze 713: while ((nc = TAILQ_FIRST(&n->childq)) != NULL) {
714: pnode_print(f, nc);
715: pnode_unlink(nc);
716: }
717: macro_close(f);
1.71 schwarze 718: }
719:
720: static void
1.101 schwarze 721: pnode_printtitle(struct format *f, struct pnode *n)
1.71 schwarze 722: {
1.101 schwarze 723: struct pnode *nc, *nn;
1.71 schwarze 724:
1.101 schwarze 725: TAILQ_FOREACH_SAFE(nc, &n->childq, child, nn) {
726: if (nc->node == NODE_TITLE) {
727: pnode_printpara(f, nc);
728: pnode_print(f, nc);
729: pnode_unlink(nc);
1.71 schwarze 730: }
731: }
1.13 kristaps 732: }
733:
734: static void
1.101 schwarze 735: pnode_printrow(struct format *f, struct pnode *n)
1.25 kristaps 736: {
1.101 schwarze 737: struct pnode *nc;
1.25 kristaps 738:
1.101 schwarze 739: macro_line(f, "Bl -dash -compact");
740: TAILQ_FOREACH(nc, &n->childq, child) {
741: macro_line(f, "It");
742: pnode_print(f, nc);
1.25 kristaps 743: }
1.101 schwarze 744: macro_line(f, "El");
745: pnode_unlink(n);
1.25 kristaps 746: }
747:
748: static void
1.83 schwarze 749: pnode_printtgroup1(struct format *f, struct pnode *n)
1.16 kristaps 750: {
1.82 schwarze 751: struct pnode *nc;
752:
1.83 schwarze 753: macro_line(f, "Bl -bullet -compact");
1.82 schwarze 754: while ((nc = pnode_findfirst(n, NODE_ENTRY)) != NULL) {
1.83 schwarze 755: macro_line(f, "It");
756: pnode_print(f, nc);
1.82 schwarze 757: pnode_unlink(nc);
758: }
1.83 schwarze 759: macro_line(f, "El");
760: pnode_unlinksub(n);
761: }
762:
763: static void
764: pnode_printtgroup2(struct format *f, struct pnode *n)
765: {
766: struct pnode *nr, *ne;
767:
768: macro_line(f, "Bl -tag -width Ds");
769: while ((nr = pnode_findfirst(n, NODE_ROW)) != NULL) {
770: if ((ne = pnode_findfirst(n, NODE_ENTRY)) == NULL)
771: break;
772: macro_open(f, "It");
1.103 schwarze 773: f->flags |= FMT_IMPL;
1.83 schwarze 774: pnode_print(f, ne);
1.84 schwarze 775: macro_close(f);
1.83 schwarze 776: pnode_unlink(ne);
777: pnode_print(f, nr);
778: pnode_unlink(nr);
779: }
780: macro_line(f, "El");
1.82 schwarze 781: pnode_unlinksub(n);
782: }
783:
784: static void
1.83 schwarze 785: pnode_printtgroup(struct format *f, struct pnode *n)
1.82 schwarze 786: {
787: struct pnode *nc;
788:
789: switch (atoi(pnode_getattr_raw(n, ATTRKEY_COLS, "0"))) {
790: case 1:
1.83 schwarze 791: pnode_printtgroup1(f, n);
792: return;
793: case 2:
794: pnode_printtgroup2(f, n);
1.82 schwarze 795: return;
796: default:
797: break;
798: }
1.16 kristaps 799:
1.83 schwarze 800: macro_line(f, "Bl -ohang");
1.82 schwarze 801: while ((nc = pnode_findfirst(n, NODE_ROW)) != NULL) {
1.83 schwarze 802: macro_line(f, "It Table Row");
803: pnode_printrow(f, nc);
1.25 kristaps 804: }
1.83 schwarze 805: macro_line(f, "El");
1.82 schwarze 806: pnode_unlinksub(n);
1.25 kristaps 807: }
808:
809: static void
1.101 schwarze 810: pnode_printlist(struct format *f, struct pnode *n)
1.25 kristaps 811: {
1.101 schwarze 812: struct pnode *nc;
1.16 kristaps 813:
1.101 schwarze 814: pnode_printtitle(f, n);
815: macro_argline(f, "Bl",
816: n->node == NODE_ORDEREDLIST ? "-enum" : "-bullet");
817: TAILQ_FOREACH(nc, &n->childq, child) {
818: macro_line(f, "It");
819: pnode_print(f, nc);
1.16 kristaps 820: }
1.101 schwarze 821: macro_line(f, "El");
822: pnode_unlinksub(n);
1.16 kristaps 823: }
824:
825: static void
1.101 schwarze 826: pnode_printvariablelist(struct format *f, struct pnode *n)
1.13 kristaps 827: {
1.101 schwarze 828: struct pnode *nc;
1.13 kristaps 829:
1.101 schwarze 830: pnode_printtitle(f, n);
831: macro_line(f, "Bl -tag -width Ds");
832: TAILQ_FOREACH(nc, &n->childq, child) {
833: if (nc->node == NODE_VARLISTENTRY)
834: pnode_printvarlistentry(f, nc);
1.69 schwarze 835: else
1.101 schwarze 836: macro_nodeline(f, "It", nc, 0);
1.69 schwarze 837: }
1.101 schwarze 838: macro_line(f, "El");
839: pnode_unlinksub(n);
1.13 kristaps 840: }
841:
1.1 kristaps 842: /*
843: * Print a parsed node (or ignore it--whatever).
844: * This is a recursive function.
1.23 kristaps 845: * FIXME: if we're in a literal context (<screen> or <programlisting> or
846: * whatever), don't print inline macros.
1.1 kristaps 847: */
848: static void
1.101 schwarze 849: pnode_print(struct format *f, struct pnode *n)
1.1 kristaps 850: {
1.102 schwarze 851: struct pnode *nc, *nn;
1.112 schwarze 852: int was_impl;
1.1 kristaps 853:
1.101 schwarze 854: if (n == NULL)
1.1 kristaps 855: return;
856:
1.112 schwarze 857: was_impl = f->flags & FMT_IMPL;
1.103 schwarze 858: if (n->spc)
859: f->flags &= ~FMT_NOSPC;
860: else
861: f->flags |= FMT_NOSPC;
1.1 kristaps 862:
1.101 schwarze 863: switch (n->node) {
1.62 schwarze 864: case NODE_APPLICATION:
1.101 schwarze 865: macro_open(f, "Nm");
1.27 kristaps 866: break;
1.62 schwarze 867: case NODE_ARG:
1.101 schwarze 868: pnode_printarg(f, n);
1.4 kristaps 869: break;
1.62 schwarze 870: case NODE_AUTHOR:
1.101 schwarze 871: pnode_printauthor(f, n);
1.50 schwarze 872: break;
1.62 schwarze 873: case NODE_AUTHORGROUP:
1.101 schwarze 874: macro_line(f, "An -split");
1.50 schwarze 875: break;
1.98 schwarze 876: case NODE_BLOCKQUOTE:
1.101 schwarze 877: macro_line(f, "Bd -ragged -offset indent");
1.98 schwarze 878: break;
1.62 schwarze 879: case NODE_BOOKINFO:
1.101 schwarze 880: macro_line(f, "Sh NAME");
1.50 schwarze 881: break;
1.62 schwarze 882: case NODE_CITEREFENTRY:
1.101 schwarze 883: pnode_printciterefentry(f, n);
1.1 kristaps 884: break;
1.68 schwarze 885: case NODE_CITETITLE:
1.101 schwarze 886: macro_open(f, "%T");
1.68 schwarze 887: break;
1.62 schwarze 888: case NODE_COMMAND:
1.101 schwarze 889: macro_open(f, "Nm");
1.13 kristaps 890: break;
1.62 schwarze 891: case NODE_CONSTANT:
1.101 schwarze 892: macro_open(f, "Dv");
1.33 kristaps 893: break;
1.62 schwarze 894: case NODE_EDITOR:
1.101 schwarze 895: print_text(f, "editor:", ARG_SPACE);
896: macro_open(f, "An");
1.50 schwarze 897: break;
1.65 schwarze 898: case NODE_EMAIL:
1.115 ! schwarze 899: if (was_impl)
! 900: macro_open(f, "Ao Mt");
! 901: else {
! 902: macro_open(f, "Aq Mt");
! 903: f->flags |= FMT_IMPL;
! 904: }
1.65 schwarze 905: break;
1.62 schwarze 906: case NODE_EMPHASIS:
907: case NODE_FIRSTTERM:
1.99 schwarze 908: case NODE_GLOSSTERM:
1.101 schwarze 909: macro_open(f, "Em");
1.1 kristaps 910: break;
1.62 schwarze 911: case NODE_ENVAR:
1.101 schwarze 912: macro_open(f, "Ev");
1.79 schwarze 913: break;
1.90 schwarze 914: case NODE_ERRORNAME:
1.101 schwarze 915: macro_open(f, "Er");
1.90 schwarze 916: break;
1.62 schwarze 917: case NODE_FILENAME:
1.101 schwarze 918: macro_open(f, "Pa");
1.17 kristaps 919: break;
1.62 schwarze 920: case NODE_FUNCTION:
1.101 schwarze 921: macro_open(f, "Fn");
1.3 kristaps 922: break;
1.62 schwarze 923: case NODE_FUNCPROTOTYPE:
1.101 schwarze 924: pnode_printfuncprototype(f, n);
1.3 kristaps 925: break;
1.62 schwarze 926: case NODE_FUNCSYNOPSISINFO:
1.101 schwarze 927: macro_open(f, "Fd");
1.16 kristaps 928: break;
1.62 schwarze 929: case NODE_INFORMALEQUATION:
1.111 schwarze 930: macro_line(f, "Bd -ragged -offset indent");
931: /* FALLTHROUGH */
932: case NODE_INLINEEQUATION:
1.101 schwarze 933: macro_line(f, "EQ");
1.43 kristaps 934: break;
1.62 schwarze 935: case NODE_ITEMIZEDLIST:
1.101 schwarze 936: pnode_printlist(f, n);
1.24 kristaps 937: break;
1.62 schwarze 938: case NODE_GROUP:
1.101 schwarze 939: pnode_printgroup(f, n);
1.10 kristaps 940: break;
1.67 schwarze 941: case NODE_KEYSYM:
1.101 schwarze 942: macro_open(f, "Sy");
1.67 schwarze 943: break;
1.62 schwarze 944: case NODE_LINK:
1.101 schwarze 945: pnode_printlink(f, n);
1.96 schwarze 946: break;
1.62 schwarze 947: case NODE_LITERAL:
1.112 schwarze 948: if (was_impl)
949: macro_open(f, "So");
950: else {
951: macro_open(f, "Ql");
952: f->flags |= FMT_IMPL;
953: }
1.19 kristaps 954: break;
1.62 schwarze 955: case NODE_LITERALLAYOUT:
1.101 schwarze 956: macro_close(f);
957: macro_argline(f, "Bd", pnode_getattr(n, ATTRKEY_CLASS) ==
1.66 schwarze 958: ATTRVAL_MONOSPACED ? "-literal" : "-unfilled");
1.60 schwarze 959: break;
1.106 schwarze 960: case NODE_MARKUP:
961: macro_open(f, "Ic");
962: break;
1.62 schwarze 963: case NODE_MML_MFENCED:
1.101 schwarze 964: pnode_printmathfenced(f, n);
1.40 kristaps 965: break;
1.62 schwarze 966: case NODE_MML_MROW:
967: case NODE_MML_MI:
968: case NODE_MML_MN:
969: case NODE_MML_MO:
1.101 schwarze 970: if (TAILQ_EMPTY(&n->childq))
1.43 kristaps 971: break;
972: fputs(" { ", stdout);
1.40 kristaps 973: break;
1.62 schwarze 974: case NODE_MML_MFRAC:
975: case NODE_MML_MSUB:
976: case NODE_MML_MSUP:
1.101 schwarze 977: pnode_printmath(f, n);
1.40 kristaps 978: break;
1.62 schwarze 979: case NODE_OPTION:
1.101 schwarze 980: macro_open(f, "Fl");
1.1 kristaps 981: break;
1.62 schwarze 982: case NODE_ORDEREDLIST:
1.101 schwarze 983: pnode_printlist(f, n);
1.25 kristaps 984: break;
1.62 schwarze 985: case NODE_PARA:
1.101 schwarze 986: pnode_printpara(f, n);
1.3 kristaps 987: break;
1.87 schwarze 988: case NODE_PARAMDEF:
1.62 schwarze 989: case NODE_PARAMETER:
1.104 schwarze 990: /* More often, these appear inside NODE_FUNCPROTOTYPE. */
991: macro_open(f, "Fa");
992: macro_addnode(f, n, ARG_SPACE | ARG_SINGLE);
1.101 schwarze 993: pnode_unlinksub(n);
1.1 kristaps 994: break;
1.62 schwarze 995: case NODE_QUOTE:
1.112 schwarze 996: if (was_impl)
997: macro_open(f, "Do");
998: else {
999: macro_open(f, "Dq");
1000: f->flags |= FMT_IMPL;
1001: }
1.28 kristaps 1002: break;
1.62 schwarze 1003: case NODE_PROGRAMLISTING:
1004: case NODE_SCREEN:
1.88 schwarze 1005: case NODE_SYNOPSIS:
1.101 schwarze 1006: macro_line(f, "Bd -literal");
1.15 kristaps 1007: break;
1.62 schwarze 1008: case NODE_REFENTRYINFO:
1.15 kristaps 1009: /* Suppress. */
1.101 schwarze 1010: pnode_unlinksub(n);
1.1 kristaps 1011: break;
1.62 schwarze 1012: case NODE_REFNAME:
1.110 schwarze 1013: /* More often, these appear inside NODE_REFNAMEDIV. */
1.101 schwarze 1014: macro_open(f, "Nm");
1.10 kristaps 1015: break;
1.62 schwarze 1016: case NODE_REFNAMEDIV:
1.110 schwarze 1017: pnode_printrefnamediv(f, n);
1.1 kristaps 1018: break;
1.62 schwarze 1019: case NODE_REFPURPOSE:
1.101 schwarze 1020: macro_open(f, "Nd");
1.10 kristaps 1021: break;
1.62 schwarze 1022: case NODE_REFSYNOPSISDIV:
1.101 schwarze 1023: pnode_printrefsynopsisdiv(f, n);
1.1 kristaps 1024: break;
1.62 schwarze 1025: case NODE_PREFACE:
1026: case NODE_SECTION:
1.100 schwarze 1027: case NODE_APPENDIX:
1028: case NODE_LEGALNOTICE:
1.62 schwarze 1029: case NODE_NOTE:
1030: case NODE_TIP:
1031: case NODE_CAUTION:
1032: case NODE_WARNING:
1.101 schwarze 1033: pnode_printrefsect(f, n);
1.1 kristaps 1034: break;
1.62 schwarze 1035: case NODE_REPLACEABLE:
1.101 schwarze 1036: macro_open(f, "Ar");
1.13 kristaps 1037: break;
1.62 schwarze 1038: case NODE_SBR:
1.101 schwarze 1039: macro_line(f, "br");
1.25 kristaps 1040: break;
1.62 schwarze 1041: case NODE_TEXT:
1.93 schwarze 1042: case NODE_ESCAPE:
1.101 schwarze 1043: pnode_printtext(f, n);
1.1 kristaps 1044: break;
1.82 schwarze 1045: case NODE_TGROUP:
1.101 schwarze 1046: pnode_printtgroup(f, n);
1.82 schwarze 1047: break;
1.62 schwarze 1048: case NODE_TITLE:
1.101 schwarze 1049: if (n->parent != NULL &&
1050: n->parent->node == NODE_BOOKINFO) {
1051: macro_open(f, "Nd");
1.82 schwarze 1052: break;
1053: }
1.101 schwarze 1054: pnode_printpara(f, n);
1055: macro_nodeline(f, "Sy", n, 0);
1056: pnode_unlinksub(n);
1.50 schwarze 1057: break;
1.62 schwarze 1058: case NODE_TYPE:
1.101 schwarze 1059: macro_open(f, "Vt");
1.39 kristaps 1060: break;
1.62 schwarze 1061: case NODE_VARIABLELIST:
1.101 schwarze 1062: pnode_printvariablelist(f, n);
1.13 kristaps 1063: break;
1.62 schwarze 1064: case NODE_VARNAME:
1.101 schwarze 1065: macro_open(f, "Va");
1.23 kristaps 1066: break;
1.1 kristaps 1067: default:
1068: break;
1069: }
1070:
1.102 schwarze 1071: TAILQ_FOREACH(nc, &n->childq, child)
1072: pnode_print(f, nc);
1.1 kristaps 1073:
1.101 schwarze 1074: switch (n->node) {
1.115 ! schwarze 1075: case NODE_EMAIL:
! 1076: if (was_impl) {
! 1077: f->flags &= ~FMT_NOSPC;
! 1078: macro_open(f, "Ac");
! 1079: } else
! 1080: f->flags &= ~FMT_IMPL;
! 1081: break;
1.103 schwarze 1082: case NODE_ESCAPE:
1083: case NODE_TERM:
1084: case NODE_TEXT:
1085: /* Accept more arguments to the previous macro. */
1086: return;
1.62 schwarze 1087: case NODE_INFORMALEQUATION:
1.101 schwarze 1088: macro_line(f, "EN");
1.111 schwarze 1089: macro_line(f, "Ed");
1.40 kristaps 1090: break;
1.62 schwarze 1091: case NODE_INLINEEQUATION:
1.111 schwarze 1092: macro_line(f, "EN");
1.43 kristaps 1093: break;
1.112 schwarze 1094: case NODE_LITERAL:
1.115 ! schwarze 1095: if (was_impl) {
! 1096: f->flags &= ~FMT_NOSPC;
1.112 schwarze 1097: macro_open(f, "Sc");
1.115 ! schwarze 1098: } else
1.112 schwarze 1099: f->flags &= ~FMT_IMPL;
1100: break;
1.91 schwarze 1101: case NODE_MEMBER:
1.102 schwarze 1102: if ((nn = TAILQ_NEXT(n, child)) != NULL &&
1103: nn->node != NODE_MEMBER)
1104: nn = NULL;
1.101 schwarze 1105: switch (f->linestate) {
1.91 schwarze 1106: case LINE_TEXT:
1.102 schwarze 1107: if (nn != NULL)
1.101 schwarze 1108: print_text(f, ",", 0);
1.91 schwarze 1109: break;
1110: case LINE_MACRO:
1.102 schwarze 1111: if (nn != NULL)
1.101 schwarze 1112: macro_addarg(f, ",", ARG_SPACE);
1113: macro_close(f);
1.91 schwarze 1114: break;
1115: case LINE_NEW:
1116: break;
1117: }
1118: break;
1.62 schwarze 1119: case NODE_MML_MROW:
1120: case NODE_MML_MI:
1121: case NODE_MML_MN:
1122: case NODE_MML_MO:
1.101 schwarze 1123: if (TAILQ_EMPTY(&n->childq))
1.43 kristaps 1124: break;
1125: fputs(" } ", stdout);
1.40 kristaps 1126: break;
1.62 schwarze 1127: case NODE_QUOTE:
1.115 ! schwarze 1128: if (was_impl) {
! 1129: f->flags &= ~FMT_NOSPC;
1.112 schwarze 1130: macro_open(f, "Dc");
1.115 ! schwarze 1131: } else
1.112 schwarze 1132: f->flags &= ~FMT_IMPL;
1.52 schwarze 1133: break;
1.62 schwarze 1134: case NODE_PREFACE:
1135: case NODE_SECTION:
1.100 schwarze 1136: case NODE_APPENDIX:
1137: case NODE_LEGALNOTICE:
1.62 schwarze 1138: case NODE_NOTE:
1139: case NODE_TIP:
1140: case NODE_CAUTION:
1141: case NODE_WARNING:
1.101 schwarze 1142: f->level--;
1.12 kristaps 1143: break;
1.98 schwarze 1144: case NODE_BLOCKQUOTE:
1.62 schwarze 1145: case NODE_LITERALLAYOUT:
1146: case NODE_PROGRAMLISTING:
1147: case NODE_SCREEN:
1.88 schwarze 1148: case NODE_SYNOPSIS:
1.101 schwarze 1149: macro_line(f, "Ed");
1.50 schwarze 1150: break;
1.62 schwarze 1151: case NODE_TITLE:
1.101 schwarze 1152: if (n->parent != NULL &&
1153: n->parent->node == NODE_BOOKINFO)
1154: macro_line(f, "Sh AUTHORS");
1.1 kristaps 1155: break;
1156: default:
1157: break;
1158: }
1.103 schwarze 1159: f->flags &= ~FMT_ARG;
1.1 kristaps 1160: }
1161:
1.74 schwarze 1162: void
1.114 schwarze 1163: ptree_print_mdoc(struct ptree *tree)
1.74 schwarze 1164: {
1165: struct format formatter;
1.1 kristaps 1166:
1.74 schwarze 1167: formatter.level = 0;
1168: formatter.linestate = LINE_NEW;
1169: pnode_printprologue(&formatter, tree);
1170: pnode_print(&formatter, tree->root);
1171: if (formatter.linestate != LINE_NEW)
1172: putchar('\n');
1.1 kristaps 1173: }
CVSweb