Annotation of mandoc/term.c, Revision 1.13
1.13 ! kristaps 1: /* $Id: term.c,v 1.12 2009/02/23 15:19:47 kristaps Exp $ */
1.1 kristaps 2: /*
1.10 kristaps 3: * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
1.1 kristaps 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
7: * above copyright notice and this permission notice appear in all
8: * copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11: * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12: * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13: * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16: * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17: * PERFORMANCE OF THIS SOFTWARE.
18: */
19: #include <assert.h>
20: #include <stdlib.h>
21: #include <string.h>
22:
1.10 kristaps 23: #include "term.h"
24:
25: #define INDENT 4
26:
27: /*
28: * Performs actions on nodes of the abstract syntax tree. Both pre- and
29: * post-fix operations are defined here.
30: */
31:
32: /* FIXME: indent/tab. */
1.12 kristaps 33: /* FIXME: handle nested lists. */
1.10 kristaps 34:
35: #define TTYPE_PROG 0
36: #define TTYPE_CMD_FLAG 1
37: #define TTYPE_CMD_ARG 2
38: #define TTYPE_SECTION 3
39: #define TTYPE_FUNC_DECL 4
40: #define TTYPE_VAR_DECL 5
41: #define TTYPE_FUNC_TYPE 6
42: #define TTYPE_FUNC_NAME 7
43: #define TTYPE_FUNC_ARG 8
44: #define TTYPE_LINK 9
45: #define TTYPE_SSECTION 10
46: #define TTYPE_FILE 11
1.11 kristaps 47: #define TTYPE_EMPH 12
48: #define TTYPE_NMAX 13
1.10 kristaps 49:
50: /*
51: * These define "styles" for element types, like command arguments or
52: * executable names. This is useful when multiple macros must decorate
53: * the same thing (like .Ex -std cmd and .Nm cmd).
54: */
55:
56: const int ttypes[TTYPE_NMAX] = {
57: TERMP_BOLD, /* TTYPE_PROG */
58: TERMP_BOLD, /* TTYPE_CMD_FLAG */
59: TERMP_UNDERLINE, /* TTYPE_CMD_ARG */
60: TERMP_BOLD, /* TTYPE_SECTION */
61: TERMP_BOLD, /* TTYPE_FUNC_DECL */
62: TERMP_UNDERLINE, /* TTYPE_VAR_DECL */
63: TERMP_UNDERLINE, /* TTYPE_FUNC_TYPE */
64: TERMP_BOLD, /* TTYPE_FUNC_NAME */
65: TERMP_UNDERLINE, /* TTYPE_FUNC_ARG */
66: TERMP_UNDERLINE, /* TTYPE_LINK */
67: TERMP_BOLD, /* TTYPE_SSECTION */
1.11 kristaps 68: TERMP_UNDERLINE, /* TTYPE_FILE */
69: TERMP_UNDERLINE /* TTYPE_EMPH */
1.10 kristaps 70: };
1.7 kristaps 71:
1.10 kristaps 72: static int arg_hasattr(int, size_t,
73: const struct mdoc_arg *);
74: static int arg_getattr(int, size_t,
75: const struct mdoc_arg *);
1.12 kristaps 76: static size_t arg_offset(const struct mdoc_arg *);
77: static size_t arg_width(const struct mdoc_arg *);
1.10 kristaps 78:
79: /*
80: * What follows describes prefix and postfix operations for the abstract
81: * syntax tree descent.
82: */
1.1 kristaps 83:
1.10 kristaps 84: #define DECL_ARGS \
85: struct termp *p, \
86: const struct mdoc_meta *meta, \
87: const struct mdoc_node *node
88:
89: #define DECL_PRE(name) \
90: static int name##_pre(DECL_ARGS)
91: #define DECL_POST(name) \
92: static void name##_post(DECL_ARGS)
93: #define DECL_PREPOST(name) \
94: DECL_PRE(name); \
95: DECL_POST(name);
96:
97: DECL_PREPOST(termp_aq);
98: DECL_PREPOST(termp_ar);
1.12 kristaps 99: DECL_PREPOST(termp_bd);
1.10 kristaps 100: DECL_PREPOST(termp_d1);
101: DECL_PREPOST(termp_dq);
1.11 kristaps 102: DECL_PREPOST(termp_em);
1.10 kristaps 103: DECL_PREPOST(termp_fa);
104: DECL_PREPOST(termp_fd);
105: DECL_PREPOST(termp_fl);
106: DECL_PREPOST(termp_fn);
107: DECL_PREPOST(termp_ft);
108: DECL_PREPOST(termp_it);
109: DECL_PREPOST(termp_nm);
110: DECL_PREPOST(termp_op);
111: DECL_PREPOST(termp_pa);
112: DECL_PREPOST(termp_pf);
1.11 kristaps 113: DECL_PREPOST(termp_qo);
1.10 kristaps 114: DECL_PREPOST(termp_qq);
115: DECL_PREPOST(termp_sh);
116: DECL_PREPOST(termp_ss);
117: DECL_PREPOST(termp_sq);
118: DECL_PREPOST(termp_sx);
119: DECL_PREPOST(termp_va);
120: DECL_PREPOST(termp_vt);
121:
122: DECL_PRE(termp_bx);
123: DECL_PRE(termp_ex);
124: DECL_PRE(termp_nd);
125: DECL_PRE(termp_ns);
126: DECL_PRE(termp_nx);
127: DECL_PRE(termp_ox);
128: DECL_PRE(termp_pp);
129: DECL_PRE(termp_ud);
130: DECL_PRE(termp_xr);
131:
132: DECL_POST(termp_bl);
133:
134: const struct termact __termacts[MDOC_MAX] = {
135: { NULL, NULL }, /* \" */
136: { NULL, NULL }, /* Dd */
137: { NULL, NULL }, /* Dt */
138: { NULL, NULL }, /* Os */
139: { termp_sh_pre, termp_sh_post }, /* Sh */
140: { termp_ss_pre, termp_ss_post }, /* Ss */
141: { termp_pp_pre, NULL }, /* Pp */
142: { termp_d1_pre, termp_d1_post }, /* D1 */
143: { NULL, NULL }, /* Dl */
1.12 kristaps 144: { termp_bd_pre, termp_bd_post }, /* Bd */
1.10 kristaps 145: { NULL, NULL }, /* Ed */
146: { NULL, termp_bl_post }, /* Bl */
147: { NULL, NULL }, /* El */
148: { termp_it_pre, termp_it_post }, /* It */
149: { NULL, NULL }, /* Ad */
150: { NULL, NULL }, /* An */
151: { termp_ar_pre, termp_ar_post }, /* Ar */
152: { NULL, NULL }, /* Cd */
153: { NULL, NULL }, /* Cm */
154: { NULL, NULL }, /* Dv */
155: { NULL, NULL }, /* Er */
156: { NULL, NULL }, /* Ev */
157: { termp_ex_pre, NULL }, /* Ex */
158: { termp_fa_pre, termp_fa_post }, /* Fa */
159: { termp_fd_pre, termp_fd_post }, /* Fd */
160: { termp_fl_pre, termp_fl_post }, /* Fl */
161: { termp_fn_pre, termp_fn_post }, /* Fn */
162: { termp_ft_pre, termp_ft_post }, /* Ft */
163: { NULL, NULL }, /* Ic */
164: { NULL, NULL }, /* In */
165: { NULL, NULL }, /* Li */
166: { termp_nd_pre, NULL }, /* Nd */
167: { termp_nm_pre, termp_nm_post }, /* Nm */
168: { termp_op_pre, termp_op_post }, /* Op */
169: { NULL, NULL }, /* Ot */
170: { termp_pa_pre, termp_pa_post }, /* Pa */
171: { NULL, NULL }, /* Rv */
172: { NULL, NULL }, /* St */
173: { termp_va_pre, termp_va_post }, /* Va */
174: { termp_vt_pre, termp_vt_post }, /* Vt */
175: { termp_xr_pre, NULL }, /* Xr */
176: { NULL, NULL }, /* %A */
177: { NULL, NULL }, /* %B */
178: { NULL, NULL }, /* %D */
179: { NULL, NULL }, /* %I */
180: { NULL, NULL }, /* %J */
181: { NULL, NULL }, /* %N */
182: { NULL, NULL }, /* %O */
183: { NULL, NULL }, /* %P */
184: { NULL, NULL }, /* %R */
185: { NULL, NULL }, /* %T */
186: { NULL, NULL }, /* %V */
187: { NULL, NULL }, /* Ac */
188: { NULL, NULL }, /* Ao */
189: { termp_aq_pre, termp_aq_post }, /* Aq */
190: { NULL, NULL }, /* At */
191: { NULL, NULL }, /* Bc */
192: { NULL, NULL }, /* Bf */
193: { NULL, NULL }, /* Bo */
194: { NULL, NULL }, /* Bq */
195: { NULL, NULL }, /* Bsx */
196: { termp_bx_pre, NULL }, /* Bx */
197: { NULL, NULL }, /* Db */
198: { NULL, NULL }, /* Dc */
199: { NULL, NULL }, /* Do */
200: { termp_dq_pre, termp_dq_post }, /* Dq */
201: { NULL, NULL }, /* Ec */
202: { NULL, NULL }, /* Ef */
1.11 kristaps 203: { termp_em_pre, termp_em_post }, /* Em */
1.10 kristaps 204: { NULL, NULL }, /* Eo */
205: { NULL, NULL }, /* Fx */
206: { NULL, NULL }, /* Ms */
207: { NULL, NULL }, /* No */
208: { termp_ns_pre, NULL }, /* Ns */
209: { termp_nx_pre, NULL }, /* Nx */
210: { termp_ox_pre, NULL }, /* Ox */
211: { NULL, NULL }, /* Pc */
212: { termp_pf_pre, termp_pf_post }, /* Pf */
213: { NULL, NULL }, /* Po */
214: { NULL, NULL }, /* Pq */
215: { NULL, NULL }, /* Qc */
216: { NULL, NULL }, /* Ql */
1.11 kristaps 217: { termp_qo_pre, termp_qo_post }, /* Qo */
1.10 kristaps 218: { termp_qq_pre, termp_qq_post }, /* Qq */
219: { NULL, NULL }, /* Re */
220: { NULL, NULL }, /* Rs */
221: { NULL, NULL }, /* Sc */
222: { NULL, NULL }, /* So */
223: { termp_sq_pre, termp_sq_post }, /* Sq */
224: { NULL, NULL }, /* Sm */
225: { termp_sx_pre, termp_sx_post }, /* Sx */
226: { NULL, NULL }, /* Sy */
227: { NULL, NULL }, /* Tn */
228: { NULL, NULL }, /* Ux */
229: { NULL, NULL }, /* Xc */
230: { NULL, NULL }, /* Xo */
231: { NULL, NULL }, /* Fo */
232: { NULL, NULL }, /* Fc */
233: { NULL, NULL }, /* Oo */
234: { NULL, NULL }, /* Oc */
235: { NULL, NULL }, /* Bk */
236: { NULL, NULL }, /* Ek */
237: { NULL, NULL }, /* Bt */
238: { NULL, NULL }, /* Hf */
239: { NULL, NULL }, /* Fr */
240: { termp_ud_pre, NULL }, /* Ud */
1.2 kristaps 241: };
242:
1.10 kristaps 243: const struct termact *termacts = __termacts;
244:
245:
246: static size_t
1.12 kristaps 247: arg_width(const struct mdoc_arg *arg)
1.10 kristaps 248: {
1.12 kristaps 249:
250: /* TODO */
251: assert(*arg->value);
252: return(strlen(*arg->value));
253: }
254:
255:
256: static size_t
257: arg_offset(const struct mdoc_arg *arg)
258: {
259:
260: /* TODO */
261: assert(*arg->value);
262: if (0 == strcmp(*arg->value, "indent"))
1.10 kristaps 263: return(INDENT);
1.12 kristaps 264: if (0 == strcmp(*arg->value, "indent-two"))
1.10 kristaps 265: return(INDENT * 2);
266:
1.12 kristaps 267: return(strlen(*arg->value));
1.10 kristaps 268: }
269:
1.3 kristaps 270:
1.10 kristaps 271: static int
272: arg_hasattr(int arg, size_t argc, const struct mdoc_arg *argv)
1.2 kristaps 273: {
274:
1.10 kristaps 275: return(-1 != arg_getattr(arg, argc, argv));
276: }
277:
278:
279: static int
280: arg_getattr(int arg, size_t argc, const struct mdoc_arg *argv)
281: {
282: int i;
283:
284: for (i = 0; i < (int)argc; i++)
285: if (argv[i].arg == arg)
286: return(i);
287: return(-1);
288: }
289:
290:
291: /* ARGSUSED */
292: static int
293: termp_dq_pre(DECL_ARGS)
294: {
295:
296: if (MDOC_BODY != node->type)
297: return(1);
298:
299: word(p, "``");
300: p->flags |= TERMP_NOSPACE;
301: return(1);
302: }
303:
304:
305: /* ARGSUSED */
306: static void
307: termp_dq_post(DECL_ARGS)
308: {
309:
310: if (MDOC_BODY != node->type)
311: return;
1.3 kristaps 312:
1.10 kristaps 313: p->flags |= TERMP_NOSPACE;
314: word(p, "''");
315: }
1.2 kristaps 316:
1.3 kristaps 317:
1.10 kristaps 318: /* ARGSUSED */
319: static void
320: termp_it_post(DECL_ARGS)
321: {
322: const struct mdoc_node *n, *it;
323: const struct mdoc_block *bl;
324: int i;
1.12 kristaps 325: size_t width, offset;
1.2 kristaps 326:
1.8 kristaps 327: /*
1.10 kristaps 328: * This (and termp_it_pre()) are the most complicated functions
329: * here. They must account for a considerable number of
330: * switches that completely change the output behaviour, like
331: * -tag versus -column. Yech.
1.8 kristaps 332: */
1.10 kristaps 333:
334: switch (node->type) {
335: case (MDOC_BODY):
336: /* FALLTHROUGH */
337: case (MDOC_HEAD):
338: break;
339: default:
1.8 kristaps 340: return;
341: }
342:
1.10 kristaps 343: it = node->parent;
344: assert(MDOC_BLOCK == it->type);
345: assert(MDOC_It == it->tok);
346:
347: n = it->parent;
348: assert(MDOC_BODY == n->type);
349: assert(MDOC_Bl == n->tok);
350: n = n->parent;
351: bl = &n->data.block;
352:
353: /* If `-tag', adjust our margins accordingly. */
354:
355: if (arg_hasattr(MDOC_Tag, bl->argc, bl->argv)) {
1.12 kristaps 356: flushln(p);
357:
358: /* FIXME: this should auto-size. */
1.10 kristaps 359: i = arg_getattr(MDOC_Width, bl->argc, bl->argv);
1.12 kristaps 360: width = i >= 0 ? arg_width(&bl->argv[i]) : 10;
361:
362: /* FIXME: nesting! Should happen at block. */
363: i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
364: offset = i >= 0 ? arg_width(&bl->argv[i]) : 0;
1.10 kristaps 365:
366: if (MDOC_HEAD == node->type) {
367: p->rmargin = p->maxrmargin;
1.12 kristaps 368: p->offset -= offset;
1.10 kristaps 369: p->flags &= ~TERMP_NOBREAK;
370: } else {
1.12 kristaps 371: p->offset -= width;
1.10 kristaps 372: p->flags &= ~TERMP_NOLPAD;
1.2 kristaps 373: }
1.10 kristaps 374: }
1.2 kristaps 375:
1.10 kristaps 376: if (arg_hasattr(MDOC_Ohang, bl->argc, bl->argv)) {
377: i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
1.12 kristaps 378: offset = i >= 0 ? arg_offset(&bl->argv[i]) : 0;
1.3 kristaps 379:
1.10 kristaps 380: flushln(p);
1.12 kristaps 381: p->offset -= offset;
1.10 kristaps 382: return;
1.2 kristaps 383: }
1.10 kristaps 384: }
385:
386:
387: /* ARGSUSED */
388: static int
389: termp_it_pre(DECL_ARGS)
390: {
391: const struct mdoc_node *n, *it;
392: const struct mdoc_block *bl;
393: int i;
1.12 kristaps 394: size_t width, offset;
1.2 kristaps 395:
1.3 kristaps 396: /*
1.10 kristaps 397: * Also see termp_it_post() for general comments.
1.3 kristaps 398: */
399:
1.10 kristaps 400: switch (node->type) {
401: case (MDOC_BODY):
402: /* FALLTHROUGH */
403: case (MDOC_HEAD):
404: it = node->parent;
405: break;
406: case (MDOC_BLOCK):
407: it = node;
408: break;
409: default:
410: return(1);
411: }
412:
413: assert(MDOC_BLOCK == it->type);
414: assert(MDOC_It == it->tok);
415:
416: n = it->parent;
417: assert(MDOC_BODY == n->type);
418: assert(MDOC_Bl == n->tok);
419: n = n->parent;
420: bl = &n->data.block;
421:
422: /* If `-compact', don't assert vertical space. */
423:
424: if (MDOC_BLOCK == node->type) {
425: if (arg_hasattr(MDOC_Compact, bl->argc, bl->argv))
426: newln(p);
427: else
428: vspace(p);
429: return(1);
430: }
431:
432: assert(MDOC_HEAD == node->type
433: || MDOC_BODY == node->type);
434:
1.12 kristaps 435: /* FIXME: see termp_it_post(). */
436:
1.10 kristaps 437: /* If `-tag', adjust our margins accordingly. */
438:
439: if (arg_hasattr(MDOC_Tag, bl->argc, bl->argv)) {
1.12 kristaps 440: p->flags |= TERMP_NOSPACE;
441:
1.10 kristaps 442: i = arg_getattr(MDOC_Width, bl->argc, bl->argv);
1.12 kristaps 443: width = i >= 0 ? arg_width(&bl->argv[i]) : 10;
1.10 kristaps 444:
1.12 kristaps 445: i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
446: offset = i >= 0 ? arg_offset(&bl->argv[i]) : 0;
1.10 kristaps 447:
448: if (MDOC_HEAD == node->type) {
449: p->flags |= TERMP_NOBREAK;
1.12 kristaps 450: p->offset += offset;
1.10 kristaps 451: p->rmargin = p->offset + width;
452: } else {
453: p->flags |= TERMP_NOSPACE;
454: p->flags |= TERMP_NOLPAD;
1.12 kristaps 455: p->offset += width;
1.10 kristaps 456: }
457: return(1);
458: }
459:
460: /* If `-ohang', adjust left-margin. */
461:
462: if (arg_hasattr(MDOC_Ohang, bl->argc, bl->argv)) {
463: i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
1.12 kristaps 464: offset = i >= 0 ? arg_offset(&bl->argv[i]) : 0;
1.10 kristaps 465:
466: p->flags |= TERMP_NOSPACE;
1.12 kristaps 467: p->offset += offset;
1.10 kristaps 468: return(1);
469: }
1.3 kristaps 470:
1.10 kristaps 471: return(1);
1.2 kristaps 472: }
473:
474:
1.10 kristaps 475: /* ARGSUSED */
476: static void
477: termp_nm_post(DECL_ARGS)
478: {
479:
480: p->flags &= ~ttypes[TTYPE_PROG];
481: }
482:
483:
484: /* ARGSUSED */
485: static void
486: termp_fl_post(DECL_ARGS)
487: {
488:
489: p->flags &= ~ttypes[TTYPE_CMD_FLAG];
490: }
491:
492:
493: /* ARGSUSED */
494: static int
495: termp_ar_pre(DECL_ARGS)
496: {
497:
498: p->flags |= ttypes[TTYPE_CMD_ARG];
499: if (NULL == node->child)
500: word(p, "...");
501: return(1);
502: }
503:
504:
505: /* ARGSUSED */
506: static int
507: termp_nm_pre(DECL_ARGS)
508: {
509:
510: p->flags |= ttypes[TTYPE_PROG];
511: if (NULL == node->child)
512: word(p, meta->name);
513: return(1);
514: }
515:
516:
517: /* ARGSUSED */
518: static int
519: termp_ns_pre(DECL_ARGS)
1.2 kristaps 520: {
521:
522: p->flags |= TERMP_NOSPACE;
1.10 kristaps 523: return(1);
524: }
525:
526:
527: /* ARGSUSED */
528: static int
529: termp_pp_pre(DECL_ARGS)
530: {
531:
532: vspace(p);
533: return(1);
534: }
535:
536:
537: /* ARGSUSED */
538: static void
539: termp_ar_post(DECL_ARGS)
540: {
541:
542: p->flags &= ~ttypes[TTYPE_CMD_ARG];
543: }
544:
545:
546: /* ARGSUSED */
547: static int
548: termp_ex_pre(DECL_ARGS)
549: {
550: int i;
551:
552: i = arg_getattr(MDOC_Std, node->data.elem.argc,
553: node->data.elem.argv);
554: assert(i >= 0);
555:
556: word(p, "The");
557: p->flags |= ttypes[TTYPE_PROG];
558: word(p, *node->data.elem.argv[i].value);
559: p->flags &= ~ttypes[TTYPE_PROG];
560: word(p, "utility exits 0 on success, and >0 if an error occurs.");
561:
562: return(1);
563: }
564:
565:
566: /* ARGSUSED */
567: static int
568: termp_nd_pre(DECL_ARGS)
569: {
570:
571: word(p, "\\-");
572: return(1);
573: }
574:
575:
576: /* ARGSUSED */
577: static void
578: termp_bl_post(DECL_ARGS)
579: {
580:
581: if (MDOC_BLOCK == node->type)
582: newln(p);
583: }
584:
585:
586: /* ARGSUSED */
587: static void
588: termp_op_post(DECL_ARGS)
589: {
590:
591: if (MDOC_BODY != node->type)
1.2 kristaps 592: return;
1.10 kristaps 593: p->flags |= TERMP_NOSPACE;
594: word(p, "\\(rB");
595: }
596:
597:
598: /* ARGSUSED */
599: static void
600: termp_sh_post(DECL_ARGS)
601: {
602:
603: switch (node->type) {
604: case (MDOC_HEAD):
605: p->flags &= ~ttypes[TTYPE_SECTION];
606: newln(p);
607: break;
608: case (MDOC_BODY):
609: newln(p);
610: p->offset = 0;
611: break;
612: default:
613: break;
614: }
615: }
616:
617:
618: /* ARGSUSED */
619: static int
620: termp_xr_pre(DECL_ARGS)
621: {
622: const struct mdoc_node *n;
623:
624: n = node->child;
625: assert(n);
626:
627: assert(MDOC_TEXT == n->type);
628: word(p, n->data.text.string);
629:
630: if (NULL == (n = n->next))
631: return(0);
632:
633: assert(MDOC_TEXT == n->type);
634: p->flags |= TERMP_NOSPACE;
635: word(p, "(");
636: p->flags |= TERMP_NOSPACE;
637: word(p, n->data.text.string);
638: p->flags |= TERMP_NOSPACE;
639: word(p, ")");
640:
641: return(0);
1.2 kristaps 642: }
643:
644:
1.10 kristaps 645: /* ARGSUSED */
646: static int
647: termp_vt_pre(DECL_ARGS)
1.2 kristaps 648: {
649:
1.10 kristaps 650: /* FIXME: this can be "type name". */
651: p->flags |= ttypes[TTYPE_VAR_DECL];
652: return(1);
1.2 kristaps 653: }
654:
655:
1.10 kristaps 656: /* ARGSUSED */
1.2 kristaps 657: static void
1.10 kristaps 658: termp_vt_post(DECL_ARGS)
659: {
660:
661: p->flags &= ~ttypes[TTYPE_VAR_DECL];
662: if (node->sec == SEC_SYNOPSIS)
663: vspace(p);
664: }
665:
666:
667: /* ARGSUSED */
668: static int
669: termp_fd_pre(DECL_ARGS)
1.2 kristaps 670: {
671:
1.10 kristaps 672: /*
673: * FIXME: this naming is bad. This value is used, in general,
674: * for the #include header or other preprocessor statement.
675: */
676: p->flags |= ttypes[TTYPE_FUNC_DECL];
677: return(1);
1.2 kristaps 678: }
679:
680:
1.10 kristaps 681: /* ARGSUSED */
1.2 kristaps 682: static void
1.10 kristaps 683: termp_fd_post(DECL_ARGS)
1.2 kristaps 684: {
685:
1.10 kristaps 686: p->flags &= ~ttypes[TTYPE_FUNC_DECL];
687: if (node->sec == SEC_SYNOPSIS)
688: vspace(p);
689:
690: }
691:
692:
693: /* ARGSUSED */
694: static int
695: termp_sh_pre(DECL_ARGS)
696: {
1.2 kristaps 697:
1.10 kristaps 698: switch (node->type) {
699: case (MDOC_HEAD):
700: vspace(p);
701: p->flags |= ttypes[TTYPE_SECTION];
1.2 kristaps 702: break;
1.10 kristaps 703: case (MDOC_BODY):
704: p->offset = INDENT;
1.2 kristaps 705: break;
1.10 kristaps 706: default:
707: break;
708: }
709: return(1);
710: }
711:
712:
713: /* ARGSUSED */
714: static int
715: termp_op_pre(DECL_ARGS)
716: {
717:
718: switch (node->type) {
719: case (MDOC_BODY):
720: word(p, "\\(lB");
721: p->flags |= TERMP_NOSPACE;
1.2 kristaps 722: break;
723: default:
1.10 kristaps 724: break;
1.2 kristaps 725: }
1.10 kristaps 726: return(1);
727: }
728:
729:
730: /* ARGSUSED */
731: static int
732: termp_ud_pre(DECL_ARGS)
733: {
734:
735: word(p, "currently under development.");
736: return(1);
737: }
738:
739:
740: /* ARGSUSED */
741: static int
742: termp_fl_pre(DECL_ARGS)
743: {
744:
745: p->flags |= ttypes[TTYPE_CMD_FLAG];
746: word(p, "\\-");
747: p->flags |= TERMP_NOSPACE;
748: return(1);
749: }
750:
751:
752: /* ARGSUSED */
753: static int
754: termp_d1_pre(DECL_ARGS)
755: {
756:
757: if (MDOC_BODY != node->type)
758: return(1);
759: newln(p);
760: p->offset += INDENT;
761: return(1);
1.2 kristaps 762: }
763:
764:
1.10 kristaps 765: /* ARGSUSED */
1.2 kristaps 766: static void
1.10 kristaps 767: termp_d1_post(DECL_ARGS)
768: {
769:
770: if (MDOC_BODY != node->type)
771: return;
772: newln(p);
773: p->offset -= INDENT;
774: }
775:
776:
777: /* ARGSUSED */
778: static int
779: termp_aq_pre(DECL_ARGS)
1.6 kristaps 780: {
781:
1.10 kristaps 782: if (MDOC_BODY != node->type)
783: return(1);
784: word(p, "<");
785: p->flags |= TERMP_NOSPACE;
786: return(1);
787: }
1.6 kristaps 788:
789:
1.10 kristaps 790: /* ARGSUSED */
791: static void
792: termp_aq_post(DECL_ARGS)
793: {
1.6 kristaps 794:
1.10 kristaps 795: if (MDOC_BODY != node->type)
1.6 kristaps 796: return;
1.10 kristaps 797: p->flags |= TERMP_NOSPACE;
798: word(p, ">");
799: }
1.6 kristaps 800:
1.10 kristaps 801:
802: /* ARGSUSED */
803: static int
804: termp_ft_pre(DECL_ARGS)
805: {
806:
807: p->flags |= ttypes[TTYPE_FUNC_TYPE];
808: return(1);
1.6 kristaps 809: }
810:
811:
1.10 kristaps 812: /* ARGSUSED */
1.6 kristaps 813: static void
1.10 kristaps 814: termp_ft_post(DECL_ARGS)
1.2 kristaps 815: {
816:
1.10 kristaps 817: p->flags &= ~ttypes[TTYPE_FUNC_TYPE];
818: if (node->sec == SEC_SYNOPSIS)
819: newln(p);
820:
821: }
1.2 kristaps 822:
823:
1.10 kristaps 824: /* ARGSUSED */
825: static int
826: termp_fn_pre(DECL_ARGS)
827: {
828: const struct mdoc_node *n;
829:
830: assert(node->child);
831: assert(MDOC_TEXT == node->child->type);
1.2 kristaps 832:
1.10 kristaps 833: /* FIXME: can be "type funcname" "type varname"... */
1.2 kristaps 834:
1.10 kristaps 835: p->flags |= ttypes[TTYPE_FUNC_NAME];
836: word(p, node->child->data.text.string);
837: p->flags &= ~ttypes[TTYPE_FUNC_NAME];
838:
839: p->flags |= TERMP_NOSPACE;
840: word(p, "(");
841:
842: p->flags |= TERMP_NOSPACE;
843: for (n = node->child->next; n; n = n->next) {
844: assert(MDOC_TEXT == n->type);
845: p->flags |= ttypes[TTYPE_FUNC_ARG];
846: word(p, n->data.text.string);
847: p->flags &= ~ttypes[TTYPE_FUNC_ARG];
848: if ((n->next))
849: word(p, ",");
1.6 kristaps 850: }
1.2 kristaps 851:
1.10 kristaps 852: p->flags |= TERMP_NOSPACE;
853: word(p, ")");
854:
855: if (SEC_SYNOPSIS == node->sec)
856: word(p, ";");
857:
858: return(0);
1.2 kristaps 859: }
860:
861:
1.10 kristaps 862: /* ARGSUSED */
863: static void
864: termp_fn_post(DECL_ARGS)
1.2 kristaps 865: {
866:
1.10 kristaps 867: if (node->sec == SEC_SYNOPSIS)
868: vspace(p);
869:
870: }
1.2 kristaps 871:
872:
1.10 kristaps 873: /* ARGSUSED */
874: static int
875: termp_sx_pre(DECL_ARGS)
876: {
1.8 kristaps 877:
1.10 kristaps 878: p->flags |= ttypes[TTYPE_LINK];
879: return(1);
1.2 kristaps 880: }
881:
882:
1.10 kristaps 883: /* ARGSUSED */
1.1 kristaps 884: static void
1.10 kristaps 885: termp_sx_post(DECL_ARGS)
1.2 kristaps 886: {
887:
1.10 kristaps 888: p->flags &= ~ttypes[TTYPE_LINK];
889: }
1.2 kristaps 890:
1.4 kristaps 891:
1.10 kristaps 892: /* ARGSUSED */
893: static int
894: termp_fa_pre(DECL_ARGS)
895: {
1.2 kristaps 896:
1.10 kristaps 897: p->flags |= ttypes[TTYPE_FUNC_ARG];
898: return(1);
899: }
1.2 kristaps 900:
901:
1.10 kristaps 902: /* ARGSUSED */
903: static void
904: termp_fa_post(DECL_ARGS)
905: {
906:
907: p->flags &= ~ttypes[TTYPE_FUNC_ARG];
908: }
1.2 kristaps 909:
910:
1.10 kristaps 911: /* ARGSUSED */
912: static int
913: termp_va_pre(DECL_ARGS)
914: {
1.2 kristaps 915:
1.10 kristaps 916: p->flags |= ttypes[TTYPE_VAR_DECL];
917: return(1);
1.2 kristaps 918: }
919:
920:
1.10 kristaps 921: /* ARGSUSED */
1.2 kristaps 922: static void
1.10 kristaps 923: termp_va_post(DECL_ARGS)
1.1 kristaps 924: {
925:
1.10 kristaps 926: p->flags &= ~ttypes[TTYPE_VAR_DECL];
927: }
1.1 kristaps 928:
1.7 kristaps 929:
1.10 kristaps 930: /* ARGSUSED */
931: static int
932: termp_bd_pre(DECL_ARGS)
933: {
934: const struct mdoc_block *bl;
935: const struct mdoc_node *n;
1.12 kristaps 936: int i;
1.1 kristaps 937:
1.10 kristaps 938: if (MDOC_BLOCK == node->type) {
939: vspace(p);
940: return(1);
941: } else if (MDOC_BODY != node->type)
942: return(1);
943:
944: assert(MDOC_BLOCK == node->parent->type);
945:
946: bl = &node->parent->data.block;
1.12 kristaps 947:
948: i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
949: if (-1 != i) {
950: assert(1 == bl->argv[i].sz);
951: p->offset += arg_offset(&bl->argv[i]);
952: }
953:
1.10 kristaps 954: if ( ! arg_hasattr(MDOC_Literal, bl->argc, bl->argv))
955: return(1);
956:
957: p->flags |= TERMP_LITERAL;
958:
959: for (n = node->child; n; n = n->next) {
960: assert(MDOC_TEXT == n->type); /* FIXME */
961: if ((*n->data.text.string)) {
962: word(p, n->data.text.string);
963: flushln(p);
964: } else
965: vspace(p);
1.1 kristaps 966:
1.10 kristaps 967: }
1.1 kristaps 968:
1.10 kristaps 969: p->flags &= ~TERMP_LITERAL;
970: return(0);
971: }
1.1 kristaps 972:
973:
1.10 kristaps 974: /* ARGSUSED */
1.12 kristaps 975: static void
976: termp_bd_post(DECL_ARGS)
977: {
978: int i;
979: const struct mdoc_block *bl;
980:
981: if (MDOC_BODY != node->type)
982: return;
983:
984: assert(MDOC_BLOCK == node->parent->type);
985: bl = &node->parent->data.block;
986:
987: i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
988: if (-1 != i) {
989: assert(1 == bl->argv[i].sz);
990: p->offset -= arg_offset(&bl->argv[i]);
991: }
992: }
993:
994:
995: /* ARGSUSED */
1.10 kristaps 996: static int
997: termp_qq_pre(DECL_ARGS)
998: {
1.1 kristaps 999:
1.10 kristaps 1000: if (MDOC_BODY != node->type)
1001: return(1);
1002: word(p, "\"");
1003: p->flags |= TERMP_NOSPACE;
1004: return(1);
1.1 kristaps 1005: }
1006:
1007:
1.10 kristaps 1008: /* ARGSUSED */
1.1 kristaps 1009: static void
1.10 kristaps 1010: termp_qq_post(DECL_ARGS)
1.1 kristaps 1011: {
1012:
1.10 kristaps 1013: if (MDOC_BODY != node->type)
1014: return;
1015: p->flags |= TERMP_NOSPACE;
1016: word(p, "\"");
1017: }
1018:
1019:
1020: /* ARGSUSED */
1021: static int
1022: termp_bx_pre(DECL_ARGS)
1023: {
1.1 kristaps 1024:
1.10 kristaps 1025: word(p, "BSD");
1026: return(1);
1027: }
1028:
1029:
1030: /* ARGSUSED */
1031: static int
1032: termp_ox_pre(DECL_ARGS)
1033: {
1034:
1035: word(p, "OpenBSD");
1036: return(1);
1037: }
1038:
1039:
1040: /* ARGSUSED */
1041: static int
1042: termp_nx_pre(DECL_ARGS)
1043: {
1044:
1045: word(p, "NetBSD");
1046: return(1);
1047: }
1048:
1049:
1050: /* ARGSUSED */
1051: static int
1052: termp_sq_pre(DECL_ARGS)
1053: {
1054:
1055: if (MDOC_BODY != node->type)
1056: return(1);
1.13 ! kristaps 1057: word(p, "\'");
1.10 kristaps 1058: p->flags |= TERMP_NOSPACE;
1059: return(1);
1060: }
1.1 kristaps 1061:
1062:
1.10 kristaps 1063: /* ARGSUSED */
1064: static void
1065: termp_sq_post(DECL_ARGS)
1066: {
1067:
1068: if (MDOC_BODY != node->type)
1069: return;
1070: p->flags |= TERMP_NOSPACE;
1071: word(p, "\'");
1072: }
1.2 kristaps 1073:
1074:
1.10 kristaps 1075: /* ARGSUSED */
1076: static int
1077: termp_pf_pre(DECL_ARGS)
1078: {
1.1 kristaps 1079:
1.10 kristaps 1080: p->flags |= TERMP_IGNDELIM;
1081: return(1);
1082: }
1.1 kristaps 1083:
1084:
1.10 kristaps 1085: /* ARGSUSED */
1086: static void
1087: termp_pf_post(DECL_ARGS)
1088: {
1.1 kristaps 1089:
1.10 kristaps 1090: p->flags &= ~TERMP_IGNDELIM;
1091: p->flags |= TERMP_NOSPACE;
1092: }
1.1 kristaps 1093:
1094:
1.10 kristaps 1095: /* ARGSUSED */
1096: static int
1097: termp_ss_pre(DECL_ARGS)
1098: {
1.1 kristaps 1099:
1.10 kristaps 1100: switch (node->type) {
1101: case (MDOC_HEAD):
1102: vspace(p);
1103: p->flags |= ttypes[TTYPE_SSECTION];
1104: p->offset = INDENT / 2;
1105: break;
1106: default:
1107: break;
1108: }
1.1 kristaps 1109:
1.10 kristaps 1110: return(1);
1.1 kristaps 1111: }
1112:
1113:
1.10 kristaps 1114: /* ARGSUSED */
1115: static void
1116: termp_ss_post(DECL_ARGS)
1.1 kristaps 1117: {
1118:
1.10 kristaps 1119: switch (node->type) {
1120: case (MDOC_HEAD):
1121: p->flags &= ~ttypes[TTYPE_SSECTION];
1122: newln(p);
1123: p->offset = INDENT;
1124: break;
1125: default:
1126: break;
1127: }
1128: }
1.2 kristaps 1129:
1130:
1.10 kristaps 1131: /* ARGSUSED */
1132: static int
1133: termp_pa_pre(DECL_ARGS)
1134: {
1.2 kristaps 1135:
1.10 kristaps 1136: p->flags |= ttypes[TTYPE_FILE];
1137: return(1);
1.1 kristaps 1138: }
1139:
1140:
1.10 kristaps 1141: /* ARGSUSED */
1142: static void
1143: termp_pa_post(DECL_ARGS)
1144: {
1145:
1146: p->flags &= ~ttypes[TTYPE_FILE];
1147: }
1.11 kristaps 1148:
1149:
1150: /* ARGSUSED */
1151: static int
1152: termp_qo_pre(DECL_ARGS)
1153: {
1154:
1155: if (MDOC_BODY != node->type)
1156: return(1);
1157: word(p, "\"");
1158: p->flags |= TERMP_NOSPACE;
1159: return(1);
1160: }
1161:
1162:
1163: /* ARGSUSED */
1164: static void
1165: termp_qo_post(DECL_ARGS)
1166: {
1167:
1168: if (MDOC_BODY != node->type)
1169: return;
1170: p->flags |= TERMP_NOSPACE;
1171: word(p, "\"");
1172: }
1173:
1174:
1175: /* ARGSUSED */
1176: static int
1177: termp_em_pre(DECL_ARGS)
1178: {
1179:
1180: p->flags |= ttypes[TTYPE_EMPH];
1181: return(1);
1182: }
1183:
1184:
1185: /* ARGSUSED */
1186: static void
1187: termp_em_post(DECL_ARGS)
1188: {
1189:
1190: p->flags &= ~ttypes[TTYPE_EMPH];
1191: }
CVSweb