Annotation of docbook2mdoc/docbook2mdoc.c, Revision 1.118
1.118 ! schwarze 1: /* $Id: docbook2mdoc.c,v 1.117 2019/04/13 15:13:31 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.86 schwarze 321: pnode_printfuncdef(struct format *f, struct pnode *n)
1.3 kristaps 322: {
1.86 schwarze 323: struct pnode *nc;
1.3 kristaps 324:
1.86 schwarze 325: nc = TAILQ_FIRST(&n->childq);
326: if (nc != NULL && nc->node == NODE_TEXT) {
327: macro_argline(f, "Ft", nc->b);
328: pnode_unlink(nc);
1.13 kristaps 329: }
1.86 schwarze 330: macro_nodeline(f, "Fo", n, ARG_SINGLE);
331: pnode_unlinksub(n);
1.3 kristaps 332: }
333:
1.40 kristaps 334: /*
1.41 kristaps 335: * The <mml:mfenced> node is a little peculiar.
336: * First, it can have arbitrary open and closing tokens, which default
337: * to parentheses.
338: * Second, >1 arguments are separated by commas.
339: */
340: static void
1.101 schwarze 341: pnode_printmathfenced(struct format *f, struct pnode *n)
1.41 kristaps 342: {
1.101 schwarze 343: struct pnode *nc;
1.41 kristaps 344:
1.101 schwarze 345: printf("left %s ", pnode_getattr_raw(n, ATTRKEY_OPEN, "("));
1.41 kristaps 346:
1.101 schwarze 347: nc = TAILQ_FIRST(&n->childq);
348: pnode_print(f, nc);
1.41 kristaps 349:
1.101 schwarze 350: while ((nc = TAILQ_NEXT(nc, child)) != NULL) {
1.41 kristaps 351: putchar(',');
1.101 schwarze 352: pnode_print(f, nc);
1.41 kristaps 353: }
1.101 schwarze 354: printf("right %s ", pnode_getattr_raw(n, ATTRKEY_CLOSE, ")"));
355: pnode_unlinksub(n);
1.41 kristaps 356: }
357:
358: /*
1.40 kristaps 359: * These math nodes require special handling because they have infix
360: * syntax, instead of the usual prefix or prefix.
361: * So we need to break up the first and second child node with a
362: * particular eqn(7) word.
363: */
364: static void
1.101 schwarze 365: pnode_printmath(struct format *f, struct pnode *n)
1.40 kristaps 366: {
1.101 schwarze 367: struct pnode *nc;
1.40 kristaps 368:
1.101 schwarze 369: nc = TAILQ_FIRST(&n->childq);
370: pnode_print(f, nc);
1.40 kristaps 371:
1.101 schwarze 372: switch (n->node) {
1.62 schwarze 373: case NODE_MML_MSUP:
1.42 kristaps 374: fputs(" sup ", stdout);
1.40 kristaps 375: break;
1.62 schwarze 376: case NODE_MML_MFRAC:
1.42 kristaps 377: fputs(" over ", stdout);
1.40 kristaps 378: break;
1.62 schwarze 379: case NODE_MML_MSUB:
1.42 kristaps 380: fputs(" sub ", stdout);
1.40 kristaps 381: break;
382: default:
383: break;
384: }
385:
1.101 schwarze 386: nc = TAILQ_NEXT(nc, child);
387: pnode_print(f, nc);
388: pnode_unlinksub(n);
1.40 kristaps 389: }
390:
1.3 kristaps 391: static void
1.101 schwarze 392: pnode_printfuncprototype(struct format *f, struct pnode *n)
1.3 kristaps 393: {
1.101 schwarze 394: struct pnode *nc, *fdef;
1.3 kristaps 395:
1.101 schwarze 396: TAILQ_FOREACH(fdef, &n->childq, child)
1.64 schwarze 397: if (fdef->node == NODE_FUNCDEF)
1.3 kristaps 398: break;
399:
1.86 schwarze 400: if (fdef != NULL) {
1.101 schwarze 401: pnode_printfuncdef(f, fdef);
1.86 schwarze 402: pnode_unlink(fdef);
403: } else
1.101 schwarze 404: macro_line(f, "Fo UNKNOWN");
1.3 kristaps 405:
1.101 schwarze 406: TAILQ_FOREACH(nc, &n->childq, child)
407: macro_nodeline(f, "Fa", nc, ARG_SINGLE);
1.3 kristaps 408:
1.101 schwarze 409: macro_line(f, "Fc");
410: pnode_unlinksub(n);
1.3 kristaps 411: }
412:
1.44 schwarze 413: /*
1.10 kristaps 414: * The <arg> element is more complicated than it should be because text
415: * nodes are treated like ".Ar foo", but non-text nodes need to be
416: * re-sent into the printer (i.e., without the preceding ".Ar").
1.12 kristaps 417: * This also handles the case of "repetition" (or in other words, the
418: * ellipsis following an argument) and optionality.
1.10 kristaps 419: */
1.4 kristaps 420: static void
1.101 schwarze 421: pnode_printarg(struct format *f, struct pnode *n)
1.4 kristaps 422: {
1.101 schwarze 423: struct pnode *nc;
424: struct pattr *a;
1.103 schwarze 425: int isop, isrep, was_impl;
1.12 kristaps 426:
427: isop = 1;
1.103 schwarze 428: isrep = was_impl = 0;
1.101 schwarze 429: TAILQ_FOREACH(a, &n->attrq, child) {
430: if (a->key == ATTRKEY_CHOICE &&
431: (a->val == ATTRVAL_PLAIN || a->val == ATTRVAL_REQ))
1.12 kristaps 432: isop = 0;
1.101 schwarze 433: else if (a->key == ATTRKEY_REP && a->val == ATTRVAL_REPEAT)
1.12 kristaps 434: isrep = 1;
435: }
1.103 schwarze 436: if (isop) {
437: if (f->flags & FMT_IMPL) {
438: was_impl = 1;
439: macro_open(f, "Oo");
440: } else {
441: macro_open(f, "Op");
442: f->flags |= FMT_IMPL;
443: }
444: }
1.101 schwarze 445: TAILQ_FOREACH(nc, &n->childq, child) {
446: if (nc->node == NODE_TEXT)
447: macro_open(f, "Ar");
448: pnode_print(f, nc);
1.10 kristaps 449: }
1.117 schwarze 450: if (isrep && f->linestate == LINE_MACRO)
451: macro_addarg(f, "...", ARG_SPACE);
1.103 schwarze 452: if (isop) {
453: if (was_impl)
454: macro_open(f, "Oc");
455: else
456: f->flags &= ~FMT_IMPL;
457: }
1.101 schwarze 458: pnode_unlinksub(n);
1.4 kristaps 459: }
460:
1.24 kristaps 461: static void
1.101 schwarze 462: pnode_printgroup(struct format *f, struct pnode *n)
1.24 kristaps 463: {
1.117 schwarze 464: struct pnode *nc;
1.101 schwarze 465: struct pattr *a;
1.117 schwarze 466: int bar, isop, isrep, was_impl;
1.24 kristaps 467:
468: isop = 1;
1.117 schwarze 469: isrep = was_impl = 0;
470: TAILQ_FOREACH(a, &n->attrq, child) {
1.101 schwarze 471: if (a->key == ATTRKEY_CHOICE &&
1.117 schwarze 472: (a->val == ATTRVAL_PLAIN || a->val == ATTRVAL_REQ))
1.24 kristaps 473: isop = 0;
1.117 schwarze 474: else if (a->key == ATTRKEY_REP && a->val == ATTRVAL_REPEAT)
475: isrep = 1;
476: }
477: if (isop) {
478: if (f->flags & FMT_IMPL) {
479: was_impl = 1;
480: macro_open(f, "Oo");
481: } else {
482: macro_open(f, "Op");
483: f->flags |= FMT_IMPL;
484: }
485: } else if (isrep) {
486: if (f->flags & FMT_IMPL) {
487: was_impl = 1;
488: macro_open(f, "Bro");
489: } else {
490: macro_open(f, "Brq");
491: f->flags |= FMT_IMPL;
1.24 kristaps 492: }
1.117 schwarze 493: }
494: bar = 0;
1.101 schwarze 495: TAILQ_FOREACH(nc, &n->childq, child) {
1.117 schwarze 496: if (bar && f->linestate == LINE_MACRO)
497: macro_addarg(f, "|", ARG_SPACE);
1.101 schwarze 498: pnode_print(f, nc);
1.117 schwarze 499: bar = 1;
500: }
501: if (isop) {
502: if (was_impl)
503: macro_open(f, "Oc");
504: else
505: f->flags &= ~FMT_IMPL;
506: } else if (isrep) {
507: if (was_impl)
508: macro_open(f, "Brc");
509: else
510: f->flags &= ~FMT_IMPL;
1.24 kristaps 511: }
1.117 schwarze 512: if (isrep && f->linestate == LINE_MACRO)
513: macro_addarg(f, "...", ARG_SPACE);
1.101 schwarze 514: pnode_unlinksub(n);
1.24 kristaps 515: }
516:
1.7 kristaps 517: static void
1.118 ! schwarze 518: pnode_printsystemitem(struct format *f, struct pnode *n)
! 519: {
! 520: switch (pnode_getattr(n, ATTRKEY_CLASS)) {
! 521: case ATTRVAL_IPADDRESS:
! 522: break;
! 523: case ATTRVAL_SYSTEMNAME:
! 524: macro_open(f, "Pa");
! 525: break;
! 526: case ATTRVAL_EVENT:
! 527: default:
! 528: macro_open(f, "Sy");
! 529: break;
! 530: }
! 531: }
! 532:
! 533: static void
1.78 schwarze 534: pnode_printauthor(struct format *f, struct pnode *n)
535: {
1.101 schwarze 536: struct pnode *nc, *nn;
1.78 schwarze 537: int have_contrib, have_name;
538:
539: /*
540: * Print <contrib> children up front, before the .An scope,
541: * and figure out whether we a name of a person.
542: */
543:
544: have_contrib = have_name = 0;
1.101 schwarze 545: TAILQ_FOREACH_SAFE(nc, &n->childq, child, nn) {
1.78 schwarze 546: switch (nc->node) {
547: case NODE_CONTRIB:
548: if (have_contrib)
549: print_text(f, ",", 0);
550: print_textnode(f, nc);
551: pnode_unlink(nc);
552: have_contrib = 1;
553: break;
554: case NODE_PERSONNAME:
555: have_name = 1;
556: break;
557: default:
558: break;
559: }
560: }
561: if (TAILQ_FIRST(&n->childq) == NULL)
562: return;
563:
564: if (have_contrib)
565: print_text(f, ":", 0);
566:
567: /*
568: * If we have a name, print it in the .An scope and leave
569: * all other content for child handlers, to print after the
570: * scope. Otherwise, print everything in the scope.
571: */
572:
573: macro_open(f, "An");
1.101 schwarze 574: TAILQ_FOREACH_SAFE(nc, &n->childq, child, nn) {
1.78 schwarze 575: if (nc->node == NODE_PERSONNAME || have_name == 0) {
576: macro_addnode(f, nc, ARG_SPACE);
577: pnode_unlink(nc);
578: }
1.80 schwarze 579: }
580:
581: /*
582: * If there is an email address,
583: * print it on the same macro line.
584: */
585:
586: if ((nc = pnode_findfirst(n, NODE_EMAIL)) != NULL) {
1.103 schwarze 587: f->flags |= FMT_CHILD;
1.115 schwarze 588: macro_open(f, "Aq Mt");
589: macro_addnode(f, nc, ARG_SPACE);
1.80 schwarze 590: pnode_unlink(nc);
1.78 schwarze 591: }
592:
593: /*
594: * If there are still unprinted children, end the scope
595: * with a comma. Otherwise, leave the scope open in case
596: * a text node follows that starts with closing punctuation.
597: */
598:
599: if (TAILQ_FIRST(&n->childq) != NULL) {
600: macro_addarg(f, ",", ARG_SPACE);
601: macro_close(f);
602: }
603: }
604:
605: static void
1.96 schwarze 606: pnode_printlink(struct format *f, struct pnode *n)
607: {
1.109 schwarze 608: struct pnode *nc;
1.96 schwarze 609: const char *uri, *text;
610:
611: uri = pnode_getattr_raw(n, ATTRKEY_LINKEND, NULL);
612: if (uri != NULL) {
613: if (TAILQ_FIRST(&n->childq) != NULL) {
1.109 schwarze 614: TAILQ_FOREACH(nc, &n->childq, child)
615: pnode_print(f, nc);
1.96 schwarze 616: text = "";
1.109 schwarze 617: } else if ((text = pnode_getattr_raw(n,
618: ATTRKEY_ENDTERM, NULL)) != NULL) {
619: if (f->linestate == LINE_MACRO && f->flags & FMT_ARG)
620: macro_addarg(f, text, ARG_SPACE);
621: else
1.96 schwarze 622: print_text(f, text, ARG_SPACE);
623: }
1.103 schwarze 624: if (text != NULL) {
1.109 schwarze 625: if (f->flags & FMT_IMPL)
626: macro_open(f, "Po");
627: else {
628: macro_open(f, "Pq");
629: f->flags |= FMT_CHILD;
630: }
1.103 schwarze 631: }
1.96 schwarze 632: macro_open(f, "Sx");
633: macro_addarg(f, uri, ARG_SPACE);
1.109 schwarze 634: if (text != NULL && f->flags & FMT_IMPL)
635: macro_open(f, "Pc");
1.96 schwarze 636: pnode_unlinksub(n);
637: return;
638: }
639: uri = pnode_getattr_raw(n, ATTRKEY_XLINK_HREF, NULL);
640: if (uri == NULL)
641: uri = pnode_getattr_raw(n, ATTRKEY_URL, NULL);
642: if (uri != NULL) {
643: macro_open(f, "Lk");
644: macro_addarg(f, uri, ARG_SPACE | ARG_SINGLE);
645: if (TAILQ_FIRST(&n->childq) != NULL)
646: macro_addnode(f, n, ARG_SPACE | ARG_SINGLE);
647: pnode_unlinksub(n);
648: return;
649: }
650: }
651:
652: static void
1.116 schwarze 653: pnode_printprologue(struct format *f, struct pnode *root)
1.7 kristaps 654: {
1.116 schwarze 655: struct pnode *date, *refmeta, *name, *vol, *descr, *nc;
656: const char *sname;
1.7 kristaps 657:
1.116 schwarze 658: /* Collect information. */
1.9 kristaps 659:
1.116 schwarze 660: if ((date = pnode_takefirst(root, NODE_PUBDATE)) == NULL)
661: date = pnode_takefirst(root, NODE_DATE);
662:
663: name = vol = NULL;
664: if ((refmeta = pnode_takefirst(root, NODE_REFMETA)) != NULL) {
665: TAILQ_FOREACH(nc, &refmeta->childq, child) {
666: switch (nc->node) {
667: case NODE_REFENTRYTITLE:
668: name = nc;
669: break;
670: case NODE_MANVOLNUM:
671: vol = nc;
672: break;
673: default:
674: break;
675: }
676: }
677: }
678:
679: if (pnode_findfirst(root, NODE_REFNAMEDIV) == NULL &&
680: ((nc = pnode_findfirst(root, NODE_BOOKINFO)) != NULL ||
681: (nc = pnode_findfirst(root, NODE_REFENTRYINFO)) != NULL))
682: descr = pnode_takefirst(nc, NODE_TITLE);
683: else
684: descr = NULL;
685:
686: /* Print prologue. */
687:
688: if (date == NULL)
689: macro_line(f, "Dd $Mdocdate" "$");
690: else
691: macro_nodeline(f, "Dd", date, 0);
692:
693: macro_open(f, "Dt");
694: if (name == NULL) {
695: sname = pnode_getattr_raw(root, ATTRKEY_ID, "UNKNOWN");
696: macro_addarg(f, sname, ARG_SPACE | ARG_SINGLE | ARG_UPPER);
697: } else
698: macro_addnode(f, name, ARG_SPACE | ARG_SINGLE | ARG_UPPER);
699: if (vol == NULL)
1.101 schwarze 700: macro_addarg(f, "1", ARG_SPACE);
1.116 schwarze 701: else
702: macro_addnode(f, vol, ARG_SPACE | ARG_SINGLE);
703:
1.101 schwarze 704: macro_line(f, "Os");
1.116 schwarze 705:
706: if (descr != NULL) {
707: macro_line(f, "Sh NAME");
708: if (name == NULL)
709: macro_argline(f, "Nm", sname);
710: else
711: macro_nodeline(f, "Nm", name, ARG_SINGLE);
712: macro_nodeline(f, "Nd", descr, 0);
713: }
714:
715: /* Clean up. */
716:
717: pnode_unlink(date);
718: pnode_unlink(refmeta);
719: pnode_unlink(descr);
1.7 kristaps 720: }
721:
1.42 kristaps 722: /*
723: * We can have multiple <term> elements within a <varlistentry>, which
724: * we should comma-separate as list headers.
725: */
1.13 kristaps 726: static void
1.101 schwarze 727: pnode_printvarlistentry(struct format *f, struct pnode *n)
1.13 kristaps 728: {
1.108 schwarze 729: struct pnode *nc, *nn;
1.42 kristaps 730: int first = 1;
1.13 kristaps 731:
1.101 schwarze 732: macro_open(f, "It");
1.103 schwarze 733: f->flags |= FMT_IMPL;
1.108 schwarze 734: TAILQ_FOREACH_SAFE(nc, &n->childq, child, nn) {
1.101 schwarze 735: if (nc->node != NODE_TERM && nc->node != NODE_GLOSSTERM)
1.69 schwarze 736: continue;
1.108 schwarze 737: if (first == 0) {
738: switch (f->linestate) {
739: case LINE_NEW:
740: break;
741: case LINE_TEXT:
742: print_text(f, ",", 0);
743: break;
744: case LINE_MACRO:
745: macro_addarg(f, ",", 0);
746: break;
747: }
748: }
1.101 schwarze 749: pnode_print(f, nc);
1.108 schwarze 750: pnode_unlink(nc);
1.69 schwarze 751: first = 0;
752: }
1.101 schwarze 753: macro_close(f);
1.108 schwarze 754: while ((nc = TAILQ_FIRST(&n->childq)) != NULL) {
755: pnode_print(f, nc);
756: pnode_unlink(nc);
757: }
758: macro_close(f);
1.71 schwarze 759: }
760:
761: static void
1.101 schwarze 762: pnode_printtitle(struct format *f, struct pnode *n)
1.71 schwarze 763: {
1.101 schwarze 764: struct pnode *nc, *nn;
1.71 schwarze 765:
1.101 schwarze 766: TAILQ_FOREACH_SAFE(nc, &n->childq, child, nn) {
767: if (nc->node == NODE_TITLE) {
768: pnode_printpara(f, nc);
769: pnode_print(f, nc);
770: pnode_unlink(nc);
1.71 schwarze 771: }
772: }
1.13 kristaps 773: }
774:
775: static void
1.101 schwarze 776: pnode_printrow(struct format *f, struct pnode *n)
1.25 kristaps 777: {
1.101 schwarze 778: struct pnode *nc;
1.25 kristaps 779:
1.101 schwarze 780: macro_line(f, "Bl -dash -compact");
781: TAILQ_FOREACH(nc, &n->childq, child) {
782: macro_line(f, "It");
783: pnode_print(f, nc);
1.25 kristaps 784: }
1.101 schwarze 785: macro_line(f, "El");
786: pnode_unlink(n);
1.25 kristaps 787: }
788:
789: static void
1.83 schwarze 790: pnode_printtgroup1(struct format *f, struct pnode *n)
1.16 kristaps 791: {
1.82 schwarze 792: struct pnode *nc;
793:
1.83 schwarze 794: macro_line(f, "Bl -bullet -compact");
1.82 schwarze 795: while ((nc = pnode_findfirst(n, NODE_ENTRY)) != NULL) {
1.83 schwarze 796: macro_line(f, "It");
797: pnode_print(f, nc);
1.82 schwarze 798: pnode_unlink(nc);
799: }
1.83 schwarze 800: macro_line(f, "El");
801: pnode_unlinksub(n);
802: }
803:
804: static void
805: pnode_printtgroup2(struct format *f, struct pnode *n)
806: {
807: struct pnode *nr, *ne;
808:
809: macro_line(f, "Bl -tag -width Ds");
810: while ((nr = pnode_findfirst(n, NODE_ROW)) != NULL) {
811: if ((ne = pnode_findfirst(n, NODE_ENTRY)) == NULL)
812: break;
813: macro_open(f, "It");
1.103 schwarze 814: f->flags |= FMT_IMPL;
1.83 schwarze 815: pnode_print(f, ne);
1.84 schwarze 816: macro_close(f);
1.83 schwarze 817: pnode_unlink(ne);
818: pnode_print(f, nr);
819: pnode_unlink(nr);
820: }
821: macro_line(f, "El");
1.82 schwarze 822: pnode_unlinksub(n);
823: }
824:
825: static void
1.83 schwarze 826: pnode_printtgroup(struct format *f, struct pnode *n)
1.82 schwarze 827: {
828: struct pnode *nc;
829:
830: switch (atoi(pnode_getattr_raw(n, ATTRKEY_COLS, "0"))) {
831: case 1:
1.83 schwarze 832: pnode_printtgroup1(f, n);
833: return;
834: case 2:
835: pnode_printtgroup2(f, n);
1.82 schwarze 836: return;
837: default:
838: break;
839: }
1.16 kristaps 840:
1.83 schwarze 841: macro_line(f, "Bl -ohang");
1.82 schwarze 842: while ((nc = pnode_findfirst(n, NODE_ROW)) != NULL) {
1.83 schwarze 843: macro_line(f, "It Table Row");
844: pnode_printrow(f, nc);
1.25 kristaps 845: }
1.83 schwarze 846: macro_line(f, "El");
1.82 schwarze 847: pnode_unlinksub(n);
1.25 kristaps 848: }
849:
850: static void
1.101 schwarze 851: pnode_printlist(struct format *f, struct pnode *n)
1.25 kristaps 852: {
1.101 schwarze 853: struct pnode *nc;
1.16 kristaps 854:
1.101 schwarze 855: pnode_printtitle(f, n);
856: macro_argline(f, "Bl",
857: n->node == NODE_ORDEREDLIST ? "-enum" : "-bullet");
858: TAILQ_FOREACH(nc, &n->childq, child) {
859: macro_line(f, "It");
860: pnode_print(f, nc);
1.16 kristaps 861: }
1.101 schwarze 862: macro_line(f, "El");
863: pnode_unlinksub(n);
1.16 kristaps 864: }
865:
866: static void
1.101 schwarze 867: pnode_printvariablelist(struct format *f, struct pnode *n)
1.13 kristaps 868: {
1.101 schwarze 869: struct pnode *nc;
1.13 kristaps 870:
1.101 schwarze 871: pnode_printtitle(f, n);
872: macro_line(f, "Bl -tag -width Ds");
873: TAILQ_FOREACH(nc, &n->childq, child) {
874: if (nc->node == NODE_VARLISTENTRY)
875: pnode_printvarlistentry(f, nc);
1.69 schwarze 876: else
1.101 schwarze 877: macro_nodeline(f, "It", nc, 0);
1.69 schwarze 878: }
1.101 schwarze 879: macro_line(f, "El");
880: pnode_unlinksub(n);
1.13 kristaps 881: }
882:
1.1 kristaps 883: /*
884: * Print a parsed node (or ignore it--whatever).
885: * This is a recursive function.
1.23 kristaps 886: * FIXME: if we're in a literal context (<screen> or <programlisting> or
887: * whatever), don't print inline macros.
1.1 kristaps 888: */
889: static void
1.101 schwarze 890: pnode_print(struct format *f, struct pnode *n)
1.1 kristaps 891: {
1.102 schwarze 892: struct pnode *nc, *nn;
1.112 schwarze 893: int was_impl;
1.1 kristaps 894:
1.101 schwarze 895: if (n == NULL)
1.1 kristaps 896: return;
897:
1.112 schwarze 898: was_impl = f->flags & FMT_IMPL;
1.103 schwarze 899: if (n->spc)
900: f->flags &= ~FMT_NOSPC;
901: else
902: f->flags |= FMT_NOSPC;
1.1 kristaps 903:
1.101 schwarze 904: switch (n->node) {
1.62 schwarze 905: case NODE_APPLICATION:
1.101 schwarze 906: macro_open(f, "Nm");
1.27 kristaps 907: break;
1.62 schwarze 908: case NODE_ARG:
1.101 schwarze 909: pnode_printarg(f, n);
1.4 kristaps 910: break;
1.62 schwarze 911: case NODE_AUTHOR:
1.101 schwarze 912: pnode_printauthor(f, n);
1.50 schwarze 913: break;
1.62 schwarze 914: case NODE_AUTHORGROUP:
1.101 schwarze 915: macro_line(f, "An -split");
1.50 schwarze 916: break;
1.98 schwarze 917: case NODE_BLOCKQUOTE:
1.101 schwarze 918: macro_line(f, "Bd -ragged -offset indent");
1.98 schwarze 919: break;
1.62 schwarze 920: case NODE_CITEREFENTRY:
1.101 schwarze 921: pnode_printciterefentry(f, n);
1.1 kristaps 922: break;
1.68 schwarze 923: case NODE_CITETITLE:
1.101 schwarze 924: macro_open(f, "%T");
1.68 schwarze 925: break;
1.62 schwarze 926: case NODE_COMMAND:
1.101 schwarze 927: macro_open(f, "Nm");
1.13 kristaps 928: break;
1.62 schwarze 929: case NODE_CONSTANT:
1.101 schwarze 930: macro_open(f, "Dv");
1.33 kristaps 931: break;
1.62 schwarze 932: case NODE_EDITOR:
1.101 schwarze 933: print_text(f, "editor:", ARG_SPACE);
934: macro_open(f, "An");
1.50 schwarze 935: break;
1.65 schwarze 936: case NODE_EMAIL:
1.115 schwarze 937: if (was_impl)
938: macro_open(f, "Ao Mt");
939: else {
940: macro_open(f, "Aq Mt");
941: f->flags |= FMT_IMPL;
942: }
1.65 schwarze 943: break;
1.62 schwarze 944: case NODE_EMPHASIS:
945: case NODE_FIRSTTERM:
1.99 schwarze 946: case NODE_GLOSSTERM:
1.101 schwarze 947: macro_open(f, "Em");
1.1 kristaps 948: break;
1.62 schwarze 949: case NODE_ENVAR:
1.101 schwarze 950: macro_open(f, "Ev");
1.79 schwarze 951: break;
1.90 schwarze 952: case NODE_ERRORNAME:
1.101 schwarze 953: macro_open(f, "Er");
1.90 schwarze 954: break;
1.62 schwarze 955: case NODE_FILENAME:
1.101 schwarze 956: macro_open(f, "Pa");
1.17 kristaps 957: break;
1.62 schwarze 958: case NODE_FUNCTION:
1.101 schwarze 959: macro_open(f, "Fn");
1.3 kristaps 960: break;
1.62 schwarze 961: case NODE_FUNCPROTOTYPE:
1.101 schwarze 962: pnode_printfuncprototype(f, n);
1.3 kristaps 963: break;
1.62 schwarze 964: case NODE_FUNCSYNOPSISINFO:
1.101 schwarze 965: macro_open(f, "Fd");
1.16 kristaps 966: break;
1.62 schwarze 967: case NODE_INFORMALEQUATION:
1.111 schwarze 968: macro_line(f, "Bd -ragged -offset indent");
969: /* FALLTHROUGH */
970: case NODE_INLINEEQUATION:
1.101 schwarze 971: macro_line(f, "EQ");
1.43 kristaps 972: break;
1.62 schwarze 973: case NODE_ITEMIZEDLIST:
1.101 schwarze 974: pnode_printlist(f, n);
1.24 kristaps 975: break;
1.62 schwarze 976: case NODE_GROUP:
1.101 schwarze 977: pnode_printgroup(f, n);
1.10 kristaps 978: break;
1.67 schwarze 979: case NODE_KEYSYM:
1.101 schwarze 980: macro_open(f, "Sy");
1.67 schwarze 981: break;
1.62 schwarze 982: case NODE_LINK:
1.101 schwarze 983: pnode_printlink(f, n);
1.96 schwarze 984: break;
1.62 schwarze 985: case NODE_LITERAL:
1.112 schwarze 986: if (was_impl)
987: macro_open(f, "So");
988: else {
989: macro_open(f, "Ql");
990: f->flags |= FMT_IMPL;
991: }
1.19 kristaps 992: break;
1.62 schwarze 993: case NODE_LITERALLAYOUT:
1.101 schwarze 994: macro_close(f);
995: macro_argline(f, "Bd", pnode_getattr(n, ATTRKEY_CLASS) ==
1.66 schwarze 996: ATTRVAL_MONOSPACED ? "-literal" : "-unfilled");
1.60 schwarze 997: break;
1.106 schwarze 998: case NODE_MARKUP:
999: macro_open(f, "Ic");
1000: break;
1.62 schwarze 1001: case NODE_MML_MFENCED:
1.101 schwarze 1002: pnode_printmathfenced(f, n);
1.40 kristaps 1003: break;
1.62 schwarze 1004: case NODE_MML_MROW:
1005: case NODE_MML_MI:
1006: case NODE_MML_MN:
1007: case NODE_MML_MO:
1.101 schwarze 1008: if (TAILQ_EMPTY(&n->childq))
1.43 kristaps 1009: break;
1010: fputs(" { ", stdout);
1.40 kristaps 1011: break;
1.62 schwarze 1012: case NODE_MML_MFRAC:
1013: case NODE_MML_MSUB:
1014: case NODE_MML_MSUP:
1.101 schwarze 1015: pnode_printmath(f, n);
1.40 kristaps 1016: break;
1.62 schwarze 1017: case NODE_OPTION:
1.101 schwarze 1018: macro_open(f, "Fl");
1.1 kristaps 1019: break;
1.62 schwarze 1020: case NODE_ORDEREDLIST:
1.101 schwarze 1021: pnode_printlist(f, n);
1.25 kristaps 1022: break;
1.62 schwarze 1023: case NODE_PARA:
1.101 schwarze 1024: pnode_printpara(f, n);
1.3 kristaps 1025: break;
1.87 schwarze 1026: case NODE_PARAMDEF:
1.62 schwarze 1027: case NODE_PARAMETER:
1.104 schwarze 1028: /* More often, these appear inside NODE_FUNCPROTOTYPE. */
1029: macro_open(f, "Fa");
1030: macro_addnode(f, n, ARG_SPACE | ARG_SINGLE);
1.101 schwarze 1031: pnode_unlinksub(n);
1.1 kristaps 1032: break;
1.62 schwarze 1033: case NODE_QUOTE:
1.112 schwarze 1034: if (was_impl)
1035: macro_open(f, "Do");
1036: else {
1037: macro_open(f, "Dq");
1038: f->flags |= FMT_IMPL;
1039: }
1.28 kristaps 1040: break;
1.62 schwarze 1041: case NODE_PROGRAMLISTING:
1042: case NODE_SCREEN:
1.88 schwarze 1043: case NODE_SYNOPSIS:
1.101 schwarze 1044: macro_line(f, "Bd -literal");
1.118 ! schwarze 1045: break;
! 1046: case NODE_SYSTEMITEM:
! 1047: pnode_printsystemitem(f, n);
1.15 kristaps 1048: break;
1.62 schwarze 1049: case NODE_REFENTRYINFO:
1.15 kristaps 1050: /* Suppress. */
1.101 schwarze 1051: pnode_unlinksub(n);
1.1 kristaps 1052: break;
1.62 schwarze 1053: case NODE_REFNAME:
1.110 schwarze 1054: /* More often, these appear inside NODE_REFNAMEDIV. */
1.101 schwarze 1055: macro_open(f, "Nm");
1.10 kristaps 1056: break;
1.62 schwarze 1057: case NODE_REFNAMEDIV:
1.110 schwarze 1058: pnode_printrefnamediv(f, n);
1.1 kristaps 1059: break;
1.62 schwarze 1060: case NODE_REFPURPOSE:
1.101 schwarze 1061: macro_open(f, "Nd");
1.10 kristaps 1062: break;
1.62 schwarze 1063: case NODE_REFSYNOPSISDIV:
1.101 schwarze 1064: pnode_printrefsynopsisdiv(f, n);
1.1 kristaps 1065: break;
1.62 schwarze 1066: case NODE_PREFACE:
1067: case NODE_SECTION:
1.100 schwarze 1068: case NODE_APPENDIX:
1069: case NODE_LEGALNOTICE:
1.62 schwarze 1070: case NODE_NOTE:
1071: case NODE_TIP:
1072: case NODE_CAUTION:
1073: case NODE_WARNING:
1.101 schwarze 1074: pnode_printrefsect(f, n);
1.1 kristaps 1075: break;
1.62 schwarze 1076: case NODE_REPLACEABLE:
1.101 schwarze 1077: macro_open(f, "Ar");
1.13 kristaps 1078: break;
1.62 schwarze 1079: case NODE_SBR:
1.101 schwarze 1080: macro_line(f, "br");
1.25 kristaps 1081: break;
1.62 schwarze 1082: case NODE_TEXT:
1.93 schwarze 1083: case NODE_ESCAPE:
1.101 schwarze 1084: pnode_printtext(f, n);
1.1 kristaps 1085: break;
1.82 schwarze 1086: case NODE_TGROUP:
1.101 schwarze 1087: pnode_printtgroup(f, n);
1.82 schwarze 1088: break;
1.62 schwarze 1089: case NODE_TITLE:
1.101 schwarze 1090: pnode_printpara(f, n);
1091: macro_nodeline(f, "Sy", n, 0);
1092: pnode_unlinksub(n);
1.50 schwarze 1093: break;
1.62 schwarze 1094: case NODE_TYPE:
1.101 schwarze 1095: macro_open(f, "Vt");
1.39 kristaps 1096: break;
1.62 schwarze 1097: case NODE_VARIABLELIST:
1.101 schwarze 1098: pnode_printvariablelist(f, n);
1.13 kristaps 1099: break;
1.62 schwarze 1100: case NODE_VARNAME:
1.101 schwarze 1101: macro_open(f, "Va");
1.23 kristaps 1102: break;
1.1 kristaps 1103: default:
1104: break;
1105: }
1106:
1.102 schwarze 1107: TAILQ_FOREACH(nc, &n->childq, child)
1108: pnode_print(f, nc);
1.1 kristaps 1109:
1.101 schwarze 1110: switch (n->node) {
1.115 schwarze 1111: case NODE_EMAIL:
1112: if (was_impl) {
1113: f->flags &= ~FMT_NOSPC;
1114: macro_open(f, "Ac");
1115: } else
1116: f->flags &= ~FMT_IMPL;
1117: break;
1.103 schwarze 1118: case NODE_ESCAPE:
1119: case NODE_TERM:
1120: case NODE_TEXT:
1121: /* Accept more arguments to the previous macro. */
1122: return;
1.62 schwarze 1123: case NODE_INFORMALEQUATION:
1.101 schwarze 1124: macro_line(f, "EN");
1.111 schwarze 1125: macro_line(f, "Ed");
1.40 kristaps 1126: break;
1.62 schwarze 1127: case NODE_INLINEEQUATION:
1.111 schwarze 1128: macro_line(f, "EN");
1.43 kristaps 1129: break;
1.112 schwarze 1130: case NODE_LITERAL:
1.115 schwarze 1131: if (was_impl) {
1132: f->flags &= ~FMT_NOSPC;
1.112 schwarze 1133: macro_open(f, "Sc");
1.115 schwarze 1134: } else
1.112 schwarze 1135: f->flags &= ~FMT_IMPL;
1136: break;
1.91 schwarze 1137: case NODE_MEMBER:
1.102 schwarze 1138: if ((nn = TAILQ_NEXT(n, child)) != NULL &&
1139: nn->node != NODE_MEMBER)
1140: nn = NULL;
1.101 schwarze 1141: switch (f->linestate) {
1.91 schwarze 1142: case LINE_TEXT:
1.102 schwarze 1143: if (nn != NULL)
1.101 schwarze 1144: print_text(f, ",", 0);
1.91 schwarze 1145: break;
1146: case LINE_MACRO:
1.102 schwarze 1147: if (nn != NULL)
1.101 schwarze 1148: macro_addarg(f, ",", ARG_SPACE);
1149: macro_close(f);
1.91 schwarze 1150: break;
1151: case LINE_NEW:
1152: break;
1153: }
1154: break;
1.62 schwarze 1155: case NODE_MML_MROW:
1156: case NODE_MML_MI:
1157: case NODE_MML_MN:
1158: case NODE_MML_MO:
1.101 schwarze 1159: if (TAILQ_EMPTY(&n->childq))
1.43 kristaps 1160: break;
1161: fputs(" } ", stdout);
1.40 kristaps 1162: break;
1.62 schwarze 1163: case NODE_QUOTE:
1.115 schwarze 1164: if (was_impl) {
1165: f->flags &= ~FMT_NOSPC;
1.112 schwarze 1166: macro_open(f, "Dc");
1.115 schwarze 1167: } else
1.112 schwarze 1168: f->flags &= ~FMT_IMPL;
1.52 schwarze 1169: break;
1.62 schwarze 1170: case NODE_PREFACE:
1171: case NODE_SECTION:
1.100 schwarze 1172: case NODE_APPENDIX:
1173: case NODE_LEGALNOTICE:
1.62 schwarze 1174: case NODE_NOTE:
1175: case NODE_TIP:
1176: case NODE_CAUTION:
1177: case NODE_WARNING:
1.101 schwarze 1178: f->level--;
1.12 kristaps 1179: break;
1.98 schwarze 1180: case NODE_BLOCKQUOTE:
1.62 schwarze 1181: case NODE_LITERALLAYOUT:
1182: case NODE_PROGRAMLISTING:
1183: case NODE_SCREEN:
1.88 schwarze 1184: case NODE_SYNOPSIS:
1.101 schwarze 1185: macro_line(f, "Ed");
1.50 schwarze 1186: break;
1.1 kristaps 1187: default:
1188: break;
1189: }
1.103 schwarze 1190: f->flags &= ~FMT_ARG;
1.1 kristaps 1191: }
1192:
1.74 schwarze 1193: void
1.114 schwarze 1194: ptree_print_mdoc(struct ptree *tree)
1.74 schwarze 1195: {
1196: struct format formatter;
1.1 kristaps 1197:
1.74 schwarze 1198: formatter.level = 0;
1199: formatter.linestate = LINE_NEW;
1.116 schwarze 1200: pnode_printprologue(&formatter, tree->root);
1.74 schwarze 1201: pnode_print(&formatter, tree->root);
1202: if (formatter.linestate != LINE_NEW)
1203: putchar('\n');
1.1 kristaps 1204: }
CVSweb