Annotation of mandoc/termact.c, Revision 1.5
1.5 ! kristaps 1: /* $Id: termact.c,v 1.4 2009/02/22 14:31:08 kristaps Exp $ */
1.1 kristaps 2: /*
3: * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
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:
23: #include "term.h"
24:
1.4 kristaps 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:
1.1 kristaps 32: #define TTYPE_PROG 0
33: #define TTYPE_CMD_FLAG 1
34: #define TTYPE_CMD_ARG 2
35: #define TTYPE_SECTION 3
1.4 kristaps 36: #define TTYPE_FUNC_DECL 4
37: #define TTYPE_VAR_DECL 5
38: #define TTYPE_FUNC_TYPE 6
39: #define TTYPE_FUNC_NAME 7
40: #define TTYPE_FUNC_ARG 8
41: #define TTYPE_LINK 9
42: #define TTYPE_NMAX 10
1.1 kristaps 43:
44: /*
45: * These define "styles" for element types, like command arguments or
46: * executable names. This is useful when multiple macros must decorate
47: * the same thing (like .Ex -std cmd and .Nm cmd).
48: */
49:
50: const int ttypes[TTYPE_NMAX] = {
51: TERMP_BOLD, /* TTYPE_PROG */
52: TERMP_BOLD, /* TTYPE_CMD_FLAG */
53: TERMP_UNDERLINE, /* TTYPE_CMD_ARG */
1.4 kristaps 54: TERMP_BOLD, /* TTYPE_SECTION */
55: TERMP_BOLD, /* TTYPE_FUNC_DECL */
56: TERMP_UNDERLINE, /* TTYPE_VAR_DECL */
57: TERMP_UNDERLINE, /* TTYPE_FUNC_TYPE */
58: TERMP_BOLD, /* TTYPE_FUNC_NAME */
59: TERMP_UNDERLINE, /* TTYPE_FUNC_ARG */
60: TERMP_UNDERLINE /* TTYPE_LINK */
1.1 kristaps 61: };
62:
63: static int arg_hasattr(int, size_t,
64: const struct mdoc_arg *);
65: static int arg_getattr(int, size_t,
66: const struct mdoc_arg *);
1.4 kristaps 67: static size_t arg_offset(const char *);
1.1 kristaps 68:
69: /*
70: * What follows describes prefix and postfix operations for the abstract
71: * syntax tree descent.
72: */
73:
74: #define DECL_ARGS \
75: struct termp *p, \
76: const struct mdoc_meta *meta, \
77: const struct mdoc_node *node
78:
1.2 kristaps 79: #define DECL_PRE(name) \
80: static int name##_pre(DECL_ARGS)
81: #define DECL_POST(name) \
82: static void name##_post(DECL_ARGS)
1.1 kristaps 83:
84: DECL_PRE(termp_aq);
85: DECL_PRE(termp_ar);
1.5 ! kristaps 86: DECL_PRE(termp_bd);
1.1 kristaps 87: DECL_PRE(termp_d1);
88: DECL_PRE(termp_dq);
89: DECL_PRE(termp_ex);
1.4 kristaps 90: DECL_PRE(termp_fa);
91: DECL_PRE(termp_fd);
1.1 kristaps 92: DECL_PRE(termp_fl);
1.4 kristaps 93: DECL_PRE(termp_fn);
94: DECL_PRE(termp_ft);
1.1 kristaps 95: DECL_PRE(termp_it);
96: DECL_PRE(termp_nd);
97: DECL_PRE(termp_nm);
98: DECL_PRE(termp_ns);
99: DECL_PRE(termp_op);
100: DECL_PRE(termp_pp);
1.5 ! kristaps 101: DECL_PRE(termp_qq);
1.1 kristaps 102: DECL_PRE(termp_sh);
1.4 kristaps 103: DECL_PRE(termp_sx);
1.1 kristaps 104: DECL_PRE(termp_ud);
1.5 ! kristaps 105: DECL_PRE(termp_va);
1.4 kristaps 106: DECL_PRE(termp_vt);
1.1 kristaps 107: DECL_PRE(termp_xr);
108:
109: DECL_POST(termp_aq);
110: DECL_POST(termp_ar);
111: DECL_POST(termp_bl);
112: DECL_POST(termp_d1);
113: DECL_POST(termp_dq);
1.4 kristaps 114: DECL_POST(termp_fa);
115: DECL_POST(termp_fd);
1.1 kristaps 116: DECL_POST(termp_fl);
1.4 kristaps 117: DECL_POST(termp_fn);
118: DECL_POST(termp_ft);
1.1 kristaps 119: DECL_POST(termp_it);
120: DECL_POST(termp_nm);
121: DECL_POST(termp_op);
1.5 ! kristaps 122: DECL_POST(termp_qq);
1.1 kristaps 123: DECL_POST(termp_sh);
1.4 kristaps 124: DECL_POST(termp_sx);
1.5 ! kristaps 125: DECL_POST(termp_va);
1.4 kristaps 126: DECL_POST(termp_vt);
1.1 kristaps 127:
128: const struct termact __termacts[MDOC_MAX] = {
129: { NULL, NULL }, /* \" */
130: { NULL, NULL }, /* Dd */
131: { NULL, NULL }, /* Dt */
132: { NULL, NULL }, /* Os */
133: { termp_sh_pre, termp_sh_post }, /* Sh */
134: { NULL, NULL }, /* Ss */
135: { termp_pp_pre, NULL }, /* Pp */
136: { termp_d1_pre, termp_d1_post }, /* D1 */
137: { NULL, NULL }, /* Dl */
1.5 ! kristaps 138: { termp_bd_pre, NULL }, /* Bd */
1.1 kristaps 139: { NULL, NULL }, /* Ed */
140: { NULL, termp_bl_post }, /* Bl */
141: { NULL, NULL }, /* El */
142: { termp_it_pre, termp_it_post }, /* It */
143: { NULL, NULL }, /* Ad */
144: { NULL, NULL }, /* An */
145: { termp_ar_pre, termp_ar_post }, /* Ar */
146: { NULL, NULL }, /* Cd */
147: { NULL, NULL }, /* Cm */
148: { NULL, NULL }, /* Dv */
149: { NULL, NULL }, /* Er */
150: { NULL, NULL }, /* Ev */
151: { termp_ex_pre, NULL }, /* Ex */
1.4 kristaps 152: { termp_fa_pre, termp_fa_post }, /* Fa */
153: { termp_fd_pre, termp_fd_post }, /* Fd */
1.1 kristaps 154: { termp_fl_pre, termp_fl_post }, /* Fl */
1.4 kristaps 155: { termp_fn_pre, termp_fn_post }, /* Fn */
156: { termp_ft_pre, termp_ft_post }, /* Ft */
1.1 kristaps 157: { NULL, NULL }, /* Ic */
158: { NULL, NULL }, /* In */
159: { NULL, NULL }, /* Li */
160: { termp_nd_pre, NULL }, /* Nd */
161: { termp_nm_pre, termp_nm_post }, /* Nm */
162: { termp_op_pre, termp_op_post }, /* Op */
163: { NULL, NULL }, /* Ot */
164: { NULL, NULL }, /* Pa */
165: { NULL, NULL }, /* Rv */
166: { NULL, NULL }, /* St */
1.5 ! kristaps 167: { termp_va_pre, termp_va_post }, /* Va */
1.4 kristaps 168: { termp_vt_pre, termp_vt_post }, /* Vt */
1.1 kristaps 169: { termp_xr_pre, NULL }, /* Xr */
170: { NULL, NULL }, /* %A */
171: { NULL, NULL }, /* %B */
172: { NULL, NULL }, /* %D */
173: { NULL, NULL }, /* %I */
174: { NULL, NULL }, /* %J */
175: { NULL, NULL }, /* %N */
176: { NULL, NULL }, /* %O */
177: { NULL, NULL }, /* %P */
178: { NULL, NULL }, /* %R */
179: { NULL, NULL }, /* %T */
180: { NULL, NULL }, /* %V */
181: { NULL, NULL }, /* Ac */
182: { NULL, NULL }, /* Ao */
183: { termp_aq_pre, termp_aq_post }, /* Aq */
184: { NULL, NULL }, /* At */
185: { NULL, NULL }, /* Bc */
186: { NULL, NULL }, /* Bf */
187: { NULL, NULL }, /* Bo */
188: { NULL, NULL }, /* Bq */
189: { NULL, NULL }, /* Bsx */
190: { NULL, NULL }, /* Bx */
191: { NULL, NULL }, /* Db */
192: { NULL, NULL }, /* Dc */
193: { NULL, NULL }, /* Do */
194: { termp_dq_pre, termp_dq_post }, /* Dq */
195: { NULL, NULL }, /* Ec */
196: { NULL, NULL }, /* Ef */
197: { NULL, NULL }, /* Em */
198: { NULL, NULL }, /* Eo */
199: { NULL, NULL }, /* Fx */
200: { NULL, NULL }, /* Ms */
201: { NULL, NULL }, /* No */
202: { termp_ns_pre, NULL }, /* Ns */
203: { NULL, NULL }, /* Nx */
204: { NULL, NULL }, /* Ox */
205: { NULL, NULL }, /* Pc */
206: { NULL, NULL }, /* Pf */
207: { NULL, NULL }, /* Po */
208: { NULL, NULL }, /* Pq */
209: { NULL, NULL }, /* Qc */
210: { NULL, NULL }, /* Ql */
211: { NULL, NULL }, /* Qo */
1.5 ! kristaps 212: { termp_qq_pre, termp_qq_post }, /* Qq */
1.1 kristaps 213: { NULL, NULL }, /* Re */
214: { NULL, NULL }, /* Rs */
215: { NULL, NULL }, /* Sc */
216: { NULL, NULL }, /* So */
217: { NULL, NULL }, /* Sq */
218: { NULL, NULL }, /* Sm */
1.4 kristaps 219: { termp_sx_pre, termp_sx_post }, /* Sx */
1.1 kristaps 220: { NULL, NULL }, /* Sy */
221: { NULL, NULL }, /* Tn */
222: { NULL, NULL }, /* Ux */
223: { NULL, NULL }, /* Xc */
224: { NULL, NULL }, /* Xo */
225: { NULL, NULL }, /* Fo */
226: { NULL, NULL }, /* Fc */
227: { NULL, NULL }, /* Oo */
228: { NULL, NULL }, /* Oc */
229: { NULL, NULL }, /* Bk */
230: { NULL, NULL }, /* Ek */
231: { NULL, NULL }, /* Bt */
232: { NULL, NULL }, /* Hf */
233: { NULL, NULL }, /* Fr */
234: { termp_ud_pre, NULL }, /* Ud */
235: };
236:
237: const struct termact *termacts = __termacts;
238:
239:
1.4 kristaps 240: static size_t
241: arg_offset(const char *v)
242: {
243: if (0 == strcmp(v, "indent"))
244: return(INDENT);
245: if (0 == strcmp(v, "indent-two"))
246: return(INDENT * 2);
247:
248: /* TODO */
249: return(0);
250: }
251:
252:
253: static int
254: arg_hasattr(int arg, size_t argc, const struct mdoc_arg *argv)
255: {
256:
257: return(-1 != arg_getattr(arg, argc, argv));
258: }
259:
260:
261: static int
262: arg_getattr(int arg, size_t argc, const struct mdoc_arg *argv)
263: {
264: int i;
265:
266: for (i = 0; i < (int)argc; i++)
267: if (argv[i].arg == arg)
268: return(i);
269: return(-1);
270: }
271:
272:
1.1 kristaps 273: /* ARGSUSED */
274: static int
275: termp_dq_pre(DECL_ARGS)
276: {
277:
278: if (MDOC_BODY != node->type)
279: return(1);
280:
281: word(p, "``");
282: p->flags |= TERMP_NOSPACE;
283: return(1);
284: }
285:
286:
287: /* ARGSUSED */
1.2 kristaps 288: static void
1.1 kristaps 289: termp_dq_post(DECL_ARGS)
290: {
291:
292: if (MDOC_BODY != node->type)
1.2 kristaps 293: return;
1.1 kristaps 294:
295: p->flags |= TERMP_NOSPACE;
296: word(p, "''");
297: }
298:
299:
300: /* ARGSUSED */
1.2 kristaps 301: static void
1.1 kristaps 302: termp_it_post(DECL_ARGS)
303: {
304: const struct mdoc_node *n, *it;
305: const struct mdoc_block *bl;
306: int i;
307: size_t width;
308:
309: /*
310: * This (and termp_it_pre()) are the most complicated functions
311: * here. They must account for a considerable number of
312: * switches that completely change the output behaviour, like
313: * -tag versus -column. Yech.
314: */
315:
316: switch (node->type) {
317: case (MDOC_BODY):
318: /* FALLTHROUGH */
319: case (MDOC_HEAD):
320: break;
321: default:
1.2 kristaps 322: return;
1.1 kristaps 323: }
324:
325: it = node->parent;
326: assert(MDOC_BLOCK == it->type);
327: assert(MDOC_It == it->tok);
328:
329: n = it->parent;
330: assert(MDOC_BODY == n->type);
331: assert(MDOC_Bl == n->tok);
332: n = n->parent;
333: bl = &n->data.block;
334:
335: /* If `-tag', adjust our margins accordingly. */
336:
337: if (arg_hasattr(MDOC_Tag, bl->argc, bl->argv)) {
338: i = arg_getattr(MDOC_Width, bl->argc, bl->argv);
339: assert(i >= 0);
340: assert(1 == bl->argv[i].sz);
341: width = strlen(*bl->argv[i].value); /* XXX */
342:
343: if (MDOC_HEAD == node->type) {
344: flushln(p);
345: /* FIXME: nested lists. */
346: p->rmargin = p->maxrmargin;
347: p->flags &= ~TERMP_NOBREAK;
348: } else {
349: flushln(p);
350: p->offset -= width + 1;
351: p->flags &= ~TERMP_NOLPAD;
352: }
1.4 kristaps 353: return;
354: }
355:
356: if (arg_hasattr(MDOC_Ohang, bl->argc, bl->argv)) {
357: i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
358: assert(i >= 0);
359: assert(1 == bl->argv[i].sz);
360: width = arg_offset(*bl->argv[i].value);
361:
362: flushln(p);
363: p->offset -= width + 1;
364: return;
1.1 kristaps 365: }
366: }
367:
368:
369: /* ARGSUSED */
370: static int
371: termp_it_pre(DECL_ARGS)
372: {
373: const struct mdoc_node *n, *it;
374: const struct mdoc_block *bl;
375: int i;
376: size_t width;
377:
378: /*
379: * Also see termp_it_post() for general comments.
380: */
381:
382: switch (node->type) {
383: case (MDOC_BODY):
384: /* FALLTHROUGH */
385: case (MDOC_HEAD):
386: it = node->parent;
387: break;
388: case (MDOC_BLOCK):
389: it = node;
390: break;
391: default:
392: return(1);
393: }
394:
395: assert(MDOC_BLOCK == it->type);
396: assert(MDOC_It == it->tok);
397:
398: n = it->parent;
399: assert(MDOC_BODY == n->type);
400: assert(MDOC_Bl == n->tok);
401: n = n->parent;
402: bl = &n->data.block;
403:
404: /* If `-compact', don't assert vertical space. */
405:
406: if (MDOC_BLOCK == node->type) {
407: if (arg_hasattr(MDOC_Compact, bl->argc, bl->argv))
408: newln(p);
409: else
410: vspace(p);
411: return(1);
412: }
413:
414: assert(MDOC_HEAD == node->type
415: || MDOC_BODY == node->type);
416:
417: /* If `-tag', adjust our margins accordingly. */
418:
419: if (arg_hasattr(MDOC_Tag, bl->argc, bl->argv)) {
420: i = arg_getattr(MDOC_Width, bl->argc, bl->argv);
421: assert(i >= 0); /* XXX */
422: assert(1 == bl->argv[i].sz);
423: width = strlen(*bl->argv[i].value); /* XXX */
424:
425: /* FIXME: nested lists. */
426:
427: if (MDOC_HEAD == node->type) {
428: p->flags |= TERMP_NOBREAK;
429: p->flags |= TERMP_NOSPACE;
430: p->rmargin = p->offset + width;
431: } else {
432: p->flags |= TERMP_NOSPACE;
433: p->flags |= TERMP_NOLPAD;
434: p->offset += width + 1;
435: }
1.4 kristaps 436: return(1);
437: }
438:
439: /* If `-ohang', adjust left-margin. */
440:
441: if (arg_hasattr(MDOC_Ohang, bl->argc, bl->argv)) {
442: i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
443: assert(i >= 0);
444: assert(1 == bl->argv[i].sz);
445: width = arg_offset(*bl->argv[i].value);
446:
447: p->flags |= TERMP_NOSPACE;
448: p->offset += width + 1;
449: return(1);
1.1 kristaps 450: }
451:
452: return(1);
453: }
454:
455:
456: /* ARGSUSED */
1.2 kristaps 457: static void
1.1 kristaps 458: termp_nm_post(DECL_ARGS)
459: {
460:
461: p->flags &= ~ttypes[TTYPE_PROG];
462: }
463:
464:
465: /* ARGSUSED */
1.2 kristaps 466: static void
1.1 kristaps 467: termp_fl_post(DECL_ARGS)
468: {
469:
470: p->flags &= ~ttypes[TTYPE_CMD_FLAG];
471: }
472:
473:
474: /* ARGSUSED */
475: static int
476: termp_ar_pre(DECL_ARGS)
477: {
478:
479: p->flags |= ttypes[TTYPE_CMD_ARG];
480: if (NULL == node->child)
481: word(p, "...");
482: return(1);
483: }
484:
485:
486: /* ARGSUSED */
487: static int
488: termp_nm_pre(DECL_ARGS)
489: {
490:
491: p->flags |= ttypes[TTYPE_PROG];
492: if (NULL == node->child)
493: word(p, meta->name);
494: return(1);
495: }
496:
497:
498: /* ARGSUSED */
499: static int
500: termp_ns_pre(DECL_ARGS)
501: {
502:
503: p->flags |= TERMP_NOSPACE;
504: return(1);
505: }
506:
507:
508: /* ARGSUSED */
509: static int
510: termp_pp_pre(DECL_ARGS)
511: {
512:
513: vspace(p);
514: return(1);
515: }
516:
517:
518: /* ARGSUSED */
1.2 kristaps 519: static void
1.1 kristaps 520: termp_ar_post(DECL_ARGS)
521: {
522:
523: p->flags &= ~ttypes[TTYPE_CMD_ARG];
524: }
525:
526:
527: /* ARGSUSED */
528: static int
529: termp_ex_pre(DECL_ARGS)
530: {
531: int i;
532:
533: i = arg_getattr(MDOC_Std, node->data.elem.argc,
534: node->data.elem.argv);
535: assert(i >= 0);
536:
537: word(p, "The");
538: p->flags |= ttypes[TTYPE_PROG];
539: word(p, *node->data.elem.argv[i].value);
540: p->flags &= ~ttypes[TTYPE_PROG];
541: word(p, "utility exits 0 on success, and >0 if an error occurs.");
542:
543: return(1);
544: }
545:
546:
547: /* ARGSUSED */
548: static int
549: termp_nd_pre(DECL_ARGS)
550: {
551:
552: word(p, "\\-");
553: return(1);
554: }
555:
556:
557: /* ARGSUSED */
1.2 kristaps 558: static void
1.1 kristaps 559: termp_bl_post(DECL_ARGS)
560: {
561:
1.2 kristaps 562: if (MDOC_BLOCK == node->type)
1.1 kristaps 563: newln(p);
564: }
565:
566:
567: /* ARGSUSED */
1.2 kristaps 568: static void
1.1 kristaps 569: termp_op_post(DECL_ARGS)
570: {
571:
1.2 kristaps 572: if (MDOC_BODY != node->type)
573: return;
574: p->flags |= TERMP_NOSPACE;
575: word(p, "\\(rB");
1.1 kristaps 576: }
577:
578:
579: /* ARGSUSED */
1.2 kristaps 580: static void
1.1 kristaps 581: termp_sh_post(DECL_ARGS)
582: {
583:
584: switch (node->type) {
585: case (MDOC_HEAD):
586: p->flags &= ~ttypes[TTYPE_SECTION];
587: newln(p);
588: break;
589: case (MDOC_BODY):
590: newln(p);
1.4 kristaps 591: p->offset -= INDENT;
1.1 kristaps 592: break;
593: default:
594: break;
595: }
596: }
597:
598:
599: /* ARGSUSED */
600: static int
601: termp_xr_pre(DECL_ARGS)
602: {
603: const struct mdoc_node *n;
604:
605: n = node->child;
606: assert(n);
607:
608: assert(MDOC_TEXT == n->type);
609: word(p, n->data.text.string);
610:
611: if (NULL == (n = n->next))
612: return(0);
613:
614: assert(MDOC_TEXT == n->type);
615: p->flags |= TERMP_NOSPACE;
1.2 kristaps 616: word(p, "(");
1.1 kristaps 617: p->flags |= TERMP_NOSPACE;
618: word(p, n->data.text.string);
619: p->flags |= TERMP_NOSPACE;
1.2 kristaps 620: word(p, ")");
1.1 kristaps 621:
622: return(0);
623: }
624:
625:
626: /* ARGSUSED */
627: static int
1.4 kristaps 628: termp_vt_pre(DECL_ARGS)
629: {
630:
631: /* FIXME: this can be "type name". */
632: p->flags |= ttypes[TTYPE_VAR_DECL];
633: return(1);
634: }
635:
636:
637: /* ARGSUSED */
638: static void
639: termp_vt_post(DECL_ARGS)
640: {
641:
642: p->flags &= ~ttypes[TTYPE_VAR_DECL];
643: if (node->sec == SEC_SYNOPSIS)
644: vspace(p);
645: }
646:
647:
648: /* ARGSUSED */
649: static int
650: termp_fd_pre(DECL_ARGS)
651: {
652:
653: /*
654: * FIXME: this naming is bad. This value is used, in general,
655: * for the #include header or other preprocessor statement.
656: */
657: p->flags |= ttypes[TTYPE_FUNC_DECL];
658: return(1);
659: }
660:
661:
662: /* ARGSUSED */
663: static void
664: termp_fd_post(DECL_ARGS)
665: {
666:
667: p->flags &= ~ttypes[TTYPE_FUNC_DECL];
668: if (node->sec == SEC_SYNOPSIS)
669: vspace(p);
670:
671: }
672:
673:
674: /* ARGSUSED */
675: static int
1.1 kristaps 676: termp_sh_pre(DECL_ARGS)
677: {
678:
679: switch (node->type) {
680: case (MDOC_HEAD):
681: vspace(p);
682: p->flags |= ttypes[TTYPE_SECTION];
683: break;
684: case (MDOC_BODY):
1.4 kristaps 685: p->offset += INDENT;
1.1 kristaps 686: break;
687: default:
688: break;
689: }
690: return(1);
691: }
692:
693:
694: /* ARGSUSED */
695: static int
696: termp_op_pre(DECL_ARGS)
697: {
698:
699: switch (node->type) {
700: case (MDOC_BODY):
1.2 kristaps 701: word(p, "\\(lB");
1.1 kristaps 702: p->flags |= TERMP_NOSPACE;
703: break;
704: default:
705: break;
706: }
707: return(1);
708: }
709:
710:
711: /* ARGSUSED */
712: static int
713: termp_ud_pre(DECL_ARGS)
714: {
715:
716: word(p, "currently under development.");
717: return(1);
718: }
719:
720:
721: /* ARGSUSED */
722: static int
723: termp_fl_pre(DECL_ARGS)
724: {
725:
726: p->flags |= ttypes[TTYPE_CMD_FLAG];
727: word(p, "\\-");
728: p->flags |= TERMP_NOSPACE;
729: return(1);
730: }
731:
732:
733: /* ARGSUSED */
734: static int
735: termp_d1_pre(DECL_ARGS)
736: {
737:
738: if (MDOC_BODY != node->type)
739: return(1);
740: newln(p);
1.4 kristaps 741: p->offset += INDENT;
1.1 kristaps 742: return(1);
743: }
744:
745:
746: /* ARGSUSED */
1.2 kristaps 747: static void
1.1 kristaps 748: termp_d1_post(DECL_ARGS)
749: {
750:
1.2 kristaps 751: if (MDOC_BODY != node->type)
752: return;
1.1 kristaps 753: newln(p);
1.4 kristaps 754: p->offset -= INDENT;
1.1 kristaps 755: }
756:
757:
758: /* ARGSUSED */
759: static int
760: termp_aq_pre(DECL_ARGS)
761: {
762:
763: if (MDOC_BODY != node->type)
764: return(1);
1.3 kristaps 765: word(p, "<");
1.1 kristaps 766: p->flags |= TERMP_NOSPACE;
767: return(1);
768: }
769:
770:
771: /* ARGSUSED */
1.2 kristaps 772: static void
1.1 kristaps 773: termp_aq_post(DECL_ARGS)
774: {
775:
776: if (MDOC_BODY != node->type)
1.2 kristaps 777: return;
1.1 kristaps 778: p->flags |= TERMP_NOSPACE;
1.3 kristaps 779: word(p, ">");
1.1 kristaps 780: }
781:
782:
1.4 kristaps 783: /* ARGSUSED */
784: static int
785: termp_ft_pre(DECL_ARGS)
786: {
787:
788: p->flags |= ttypes[TTYPE_FUNC_TYPE];
789: return(1);
790: }
791:
792:
793: /* ARGSUSED */
794: static void
795: termp_ft_post(DECL_ARGS)
796: {
797:
798: p->flags &= ~ttypes[TTYPE_FUNC_TYPE];
799: if (node->sec == SEC_SYNOPSIS)
800: newln(p);
801:
802: }
803:
804:
805: /* ARGSUSED */
1.1 kristaps 806: static int
1.4 kristaps 807: termp_fn_pre(DECL_ARGS)
808: {
809: const struct mdoc_node *n;
810:
811: assert(node->child);
812: assert(MDOC_TEXT == node->child->type);
813:
814: /* FIXME: can be "type funcname" "type varname"... */
815:
816: p->flags |= ttypes[TTYPE_FUNC_NAME];
817: word(p, node->child->data.text.string);
818: p->flags &= ~ttypes[TTYPE_FUNC_NAME];
819:
820: p->flags |= TERMP_NOSPACE;
821: word(p, "(");
822:
823: p->flags |= TERMP_NOSPACE;
824: for (n = node->child->next; n; n = n->next) {
825: assert(MDOC_TEXT == n->type);
826: p->flags |= ttypes[TTYPE_FUNC_ARG];
827: word(p, n->data.text.string);
828: p->flags &= ~ttypes[TTYPE_FUNC_ARG];
829: if ((n->next))
830: word(p, ",");
831: }
832:
833: p->flags |= TERMP_NOSPACE;
834: word(p, ")");
835:
836: if (SEC_SYNOPSIS == node->sec)
837: word(p, ";");
838:
839: return(0);
840: }
841:
842:
843: /* ARGSUSED */
844: static void
845: termp_fn_post(DECL_ARGS)
846: {
847:
848: if (node->sec == SEC_SYNOPSIS)
849: vspace(p);
850:
851: }
852:
853:
854: /* ARGSUSED */
855: static int
856: termp_sx_pre(DECL_ARGS)
857: {
858:
859: p->flags |= ttypes[TTYPE_LINK];
860: return(1);
861: }
862:
863:
864: /* ARGSUSED */
865: static void
866: termp_sx_post(DECL_ARGS)
1.1 kristaps 867: {
868:
1.4 kristaps 869: p->flags &= ~ttypes[TTYPE_LINK];
1.1 kristaps 870: }
871:
872:
1.4 kristaps 873: /* ARGSUSED */
1.1 kristaps 874: static int
1.4 kristaps 875: termp_fa_pre(DECL_ARGS)
876: {
877:
878: p->flags |= ttypes[TTYPE_FUNC_ARG];
879: return(1);
880: }
881:
882:
883: /* ARGSUSED */
884: static void
885: termp_fa_post(DECL_ARGS)
1.1 kristaps 886: {
887:
1.4 kristaps 888: p->flags &= ~ttypes[TTYPE_FUNC_ARG];
1.1 kristaps 889: }
890:
1.4 kristaps 891:
1.5 ! kristaps 892: /* ARGSUSED */
! 893: static int
! 894: termp_va_pre(DECL_ARGS)
! 895: {
! 896:
! 897: p->flags |= ttypes[TTYPE_VAR_DECL];
! 898: return(1);
! 899: }
! 900:
! 901:
! 902: /* ARGSUSED */
! 903: static void
! 904: termp_va_post(DECL_ARGS)
! 905: {
! 906:
! 907: p->flags &= ~ttypes[TTYPE_VAR_DECL];
! 908: }
! 909:
! 910:
! 911: /* ARGSUSED */
! 912: static int
! 913: termp_bd_pre(DECL_ARGS)
! 914: {
! 915: const struct mdoc_block *bl;
! 916: const struct mdoc_node *n;
! 917:
! 918: if (MDOC_BLOCK == node->type) {
! 919: vspace(p);
! 920: return(1);
! 921: } else if (MDOC_BODY != node->type)
! 922: return(1);
! 923:
! 924: assert(MDOC_BLOCK == node->parent->type);
! 925:
! 926: bl = &node->parent->data.block;
! 927: if ( ! arg_hasattr(MDOC_Literal, bl->argc, bl->argv))
! 928: return(1);
! 929:
! 930: p->flags |= TERMP_LITERAL;
! 931:
! 932: for (n = node->child; n; n = n->next) {
! 933: assert(MDOC_TEXT == n->type); /* FIXME */
! 934: if ((*n->data.text.string)) {
! 935: word(p, n->data.text.string);
! 936: flushln(p);
! 937: } else
! 938: vspace(p);
! 939:
! 940: }
! 941:
! 942: p->flags &= ~TERMP_LITERAL;
! 943: return(0);
! 944: }
! 945:
! 946:
! 947: /* ARGSUSED */
! 948: static int
! 949: termp_qq_pre(DECL_ARGS)
! 950: {
! 951:
! 952: if (MDOC_BODY != node->type)
! 953: return(1);
! 954: word(p, "\"");
! 955: p->flags |= TERMP_NOSPACE;
! 956: return(1);
! 957: }
! 958:
! 959:
! 960: /* ARGSUSED */
! 961: static void
! 962: termp_qq_post(DECL_ARGS)
! 963: {
! 964:
! 965: if (MDOC_BODY != node->type)
! 966: return;
! 967: p->flags |= TERMP_NOSPACE;
! 968: word(p, "\"");
! 969: }
! 970:
! 971:
CVSweb