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