]> git.cameronkatri.com Git - mandoc.git/blob - term.c
Removed "regression" for OpenBSD (broken).
[mandoc.git] / term.c
1 /* $Id: term.c,v 1.58 2009/03/13 07:46:10 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 <sys/types.h>
20
21 #include <assert.h>
22 #include <ctype.h>
23 #include <err.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "term.h"
29
30 /*
31 * Performs actions on nodes of the abstract syntax tree. Both pre- and
32 * post-fix operations are defined here.
33 */
34
35 /* FIXME: macro arguments can be escaped. */
36
37 #define TTYPE_PROG 0
38 #define TTYPE_CMD_FLAG 1
39 #define TTYPE_CMD_ARG 2
40 #define TTYPE_SECTION 3
41 #define TTYPE_FUNC_DECL 4
42 #define TTYPE_VAR_DECL 5
43 #define TTYPE_FUNC_TYPE 6
44 #define TTYPE_FUNC_NAME 7
45 #define TTYPE_FUNC_ARG 8
46 #define TTYPE_LINK 9
47 #define TTYPE_SSECTION 10
48 #define TTYPE_FILE 11
49 #define TTYPE_EMPH 12
50 #define TTYPE_CONFIG 13
51 #define TTYPE_CMD 14
52 #define TTYPE_INCLUDE 15
53 #define TTYPE_SYMB 16
54 #define TTYPE_SYMBOL 17
55 #define TTYPE_DIAG 18
56 #define TTYPE_LINK_ANCHOR 19
57 #define TTYPE_LINK_TEXT 20
58 #define TTYPE_REF_TITLE 21
59 #define TTYPE_NMAX 22
60
61 /*
62 * These define "styles" for element types, like command arguments or
63 * executable names. This is useful when multiple macros must decorate
64 * the same thing (like .Ex -std cmd and .Nm cmd).
65 */
66
67 /* TODO: abstract this into mdocterm.c. */
68
69 const int ttypes[TTYPE_NMAX] = {
70 TERMP_BOLD, /* TTYPE_PROG */
71 TERMP_BOLD, /* TTYPE_CMD_FLAG */
72 TERMP_UNDERLINE, /* TTYPE_CMD_ARG */
73 TERMP_BOLD, /* TTYPE_SECTION */
74 TERMP_BOLD, /* TTYPE_FUNC_DECL */
75 TERMP_UNDERLINE, /* TTYPE_VAR_DECL */
76 TERMP_UNDERLINE, /* TTYPE_FUNC_TYPE */
77 TERMP_BOLD, /* TTYPE_FUNC_NAME */
78 TERMP_UNDERLINE, /* TTYPE_FUNC_ARG */
79 TERMP_UNDERLINE, /* TTYPE_LINK */
80 TERMP_BOLD, /* TTYPE_SSECTION */
81 TERMP_UNDERLINE, /* TTYPE_FILE */
82 TERMP_UNDERLINE, /* TTYPE_EMPH */
83 TERMP_BOLD, /* TTYPE_CONFIG */
84 TERMP_BOLD, /* TTYPE_CMD */
85 TERMP_BOLD, /* TTYPE_INCLUDE */
86 TERMP_BOLD, /* TTYPE_SYMB */
87 TERMP_BOLD, /* TTYPE_SYMBOL */
88 TERMP_BOLD, /* TTYPE_DIAG */
89 TERMP_UNDERLINE, /* TTYPE_LINK_ANCHOR */
90 TERMP_BOLD, /* TTYPE_LINK_TEXT */
91 TERMP_UNDERLINE /* TTYPE_REF_TITLE */
92 };
93
94 static int arg_hasattr(int, const struct mdoc_node *);
95 static int arg_getattrs(const int *, int *, size_t,
96 const struct mdoc_node *);
97 static int arg_getattr(int, const struct mdoc_node *);
98 static size_t arg_offset(const struct mdoc_argv *);
99 static size_t arg_width(const struct mdoc_argv *, int);
100 static int arg_listtype(const struct mdoc_node *);
101
102 /*
103 * What follows describes prefix and postfix operations for the abstract
104 * syntax tree descent.
105 */
106
107 #define DECL_ARGS \
108 struct termp *p, \
109 struct termpair *pair, \
110 const struct mdoc_meta *meta, \
111 const struct mdoc_node *node
112
113 #define DECL_PRE(name) \
114 static int name##_pre(DECL_ARGS)
115 #define DECL_POST(name) \
116 static void name##_post(DECL_ARGS)
117 #define DECL_PREPOST(name) \
118 DECL_PRE(name); \
119 DECL_POST(name);
120
121 DECL_PREPOST(termp_aq);
122 DECL_PREPOST(termp_bd);
123 DECL_PREPOST(termp_bq);
124 DECL_PREPOST(termp_brq);
125 DECL_PREPOST(termp_d1);
126 DECL_PREPOST(termp_dq);
127 DECL_PREPOST(termp_fd);
128 DECL_PREPOST(termp_fn);
129 DECL_PREPOST(termp_fo);
130 DECL_PREPOST(termp_ft);
131 DECL_PREPOST(termp_in);
132 DECL_PREPOST(termp_it);
133 DECL_PREPOST(termp_lb);
134 DECL_PREPOST(termp_op);
135 DECL_PREPOST(termp_pf);
136 DECL_PREPOST(termp_pq);
137 DECL_PREPOST(termp_qq);
138 DECL_PREPOST(termp_sh);
139 DECL_PREPOST(termp_ss);
140 DECL_PREPOST(termp_sq);
141 DECL_PREPOST(termp_vt);
142
143 DECL_PRE(termp__t);
144 DECL_PRE(termp_ap);
145 DECL_PRE(termp_ar);
146 DECL_PRE(termp_at);
147 DECL_PRE(termp_bf);
148 DECL_PRE(termp_bsx);
149 DECL_PRE(termp_bt);
150 DECL_PRE(termp_cd);
151 DECL_PRE(termp_cm);
152 DECL_PRE(termp_em);
153 DECL_PRE(termp_ex);
154 DECL_PRE(termp_fa);
155 DECL_PRE(termp_fl);
156 DECL_PRE(termp_fx);
157 DECL_PRE(termp_ic);
158 DECL_PRE(termp_lk);
159 DECL_PRE(termp_ms);
160 DECL_PRE(termp_mt);
161 DECL_PRE(termp_nd);
162 DECL_PRE(termp_nm);
163 DECL_PRE(termp_ns);
164 DECL_PRE(termp_nx);
165 DECL_PRE(termp_ox);
166 DECL_PRE(termp_pa);
167 DECL_PRE(termp_pp);
168 DECL_PRE(termp_rs);
169 DECL_PRE(termp_rv);
170 DECL_PRE(termp_sm);
171 DECL_PRE(termp_st);
172 DECL_PRE(termp_sx);
173 DECL_PRE(termp_sy);
174 DECL_PRE(termp_ud);
175 DECL_PRE(termp_ux);
176 DECL_PRE(termp_va);
177 DECL_PRE(termp_xr);
178
179 DECL_POST(termp___);
180 DECL_POST(termp_bl);
181 DECL_POST(termp_bx);
182
183 const struct termact __termacts[MDOC_MAX] = {
184 { NULL, NULL }, /* \" */
185 { NULL, NULL }, /* Dd */
186 { NULL, NULL }, /* Dt */
187 { NULL, NULL }, /* Os */
188 { termp_sh_pre, termp_sh_post }, /* Sh */
189 { termp_ss_pre, termp_ss_post }, /* Ss */
190 { termp_pp_pre, NULL }, /* Pp */
191 { termp_d1_pre, termp_d1_post }, /* D1 */
192 { termp_d1_pre, termp_d1_post }, /* Dl */
193 { termp_bd_pre, termp_bd_post }, /* Bd */
194 { NULL, NULL }, /* Ed */
195 { NULL, termp_bl_post }, /* Bl */
196 { NULL, NULL }, /* El */
197 { termp_it_pre, termp_it_post }, /* It */
198 { NULL, NULL }, /* Ad */
199 { NULL, NULL }, /* An */
200 { termp_ar_pre, NULL }, /* Ar */
201 { termp_cd_pre, NULL }, /* Cd */
202 { termp_cm_pre, NULL }, /* Cm */
203 { NULL, NULL }, /* Dv */
204 { NULL, NULL }, /* Er */
205 { NULL, NULL }, /* Ev */
206 { termp_ex_pre, NULL }, /* Ex */
207 { termp_fa_pre, NULL }, /* Fa */
208 { termp_fd_pre, termp_fd_post }, /* Fd */
209 { termp_fl_pre, NULL }, /* Fl */
210 { termp_fn_pre, termp_fn_post }, /* Fn */
211 { termp_ft_pre, termp_ft_post }, /* Ft */
212 { termp_ic_pre, NULL }, /* Ic */
213 { termp_in_pre, termp_in_post }, /* In */
214 { NULL, NULL }, /* Li */
215 { termp_nd_pre, NULL }, /* Nd */
216 { termp_nm_pre, NULL }, /* Nm */
217 { termp_op_pre, termp_op_post }, /* Op */
218 { NULL, NULL }, /* Ot */
219 { termp_pa_pre, NULL }, /* Pa */
220 { termp_rv_pre, NULL }, /* Rv */
221 { termp_st_pre, NULL }, /* St */
222 { termp_va_pre, NULL }, /* Va */
223 { termp_vt_pre, termp_vt_post }, /* Vt */
224 { termp_xr_pre, NULL }, /* Xr */
225 { NULL, termp____post }, /* %A */
226 { NULL, termp____post }, /* %B */
227 { NULL, termp____post }, /* %D */
228 { NULL, termp____post }, /* %I */
229 { NULL, termp____post }, /* %J */
230 { NULL, termp____post }, /* %N */
231 { NULL, termp____post }, /* %O */
232 { NULL, termp____post }, /* %P */
233 { NULL, termp____post }, /* %R */
234 { termp__t_pre, termp____post }, /* %T */
235 { NULL, termp____post }, /* %V */
236 { NULL, NULL }, /* Ac */
237 { termp_aq_pre, termp_aq_post }, /* Ao */
238 { termp_aq_pre, termp_aq_post }, /* Aq */
239 { termp_at_pre, NULL }, /* At */
240 { NULL, NULL }, /* Bc */
241 { termp_bf_pre, NULL }, /* Bf */
242 { termp_bq_pre, termp_bq_post }, /* Bo */
243 { termp_bq_pre, termp_bq_post }, /* Bq */
244 { termp_bsx_pre, NULL }, /* Bsx */
245 { NULL, termp_bx_post }, /* Bx */
246 { NULL, NULL }, /* Db */
247 { NULL, NULL }, /* Dc */
248 { termp_dq_pre, termp_dq_post }, /* Do */
249 { termp_dq_pre, termp_dq_post }, /* Dq */
250 { NULL, NULL }, /* Ec */
251 { NULL, NULL }, /* Ef */
252 { termp_em_pre, NULL }, /* Em */
253 { NULL, NULL }, /* Eo */
254 { termp_fx_pre, NULL }, /* Fx */
255 { termp_ms_pre, NULL }, /* Ms */
256 { NULL, NULL }, /* No */
257 { termp_ns_pre, NULL }, /* Ns */
258 { termp_nx_pre, NULL }, /* Nx */
259 { termp_ox_pre, NULL }, /* Ox */
260 { NULL, NULL }, /* Pc */
261 { termp_pf_pre, termp_pf_post }, /* Pf */
262 { termp_pq_pre, termp_pq_post }, /* Po */
263 { termp_pq_pre, termp_pq_post }, /* Pq */
264 { NULL, NULL }, /* Qc */
265 { termp_sq_pre, termp_sq_post }, /* Ql */
266 { termp_qq_pre, termp_qq_post }, /* Qo */
267 { termp_qq_pre, termp_qq_post }, /* Qq */
268 { NULL, NULL }, /* Re */
269 { termp_rs_pre, NULL }, /* Rs */
270 { NULL, NULL }, /* Sc */
271 { termp_sq_pre, termp_sq_post }, /* So */
272 { termp_sq_pre, termp_sq_post }, /* Sq */
273 { termp_sm_pre, NULL }, /* Sm */
274 { termp_sx_pre, NULL }, /* Sx */
275 { termp_sy_pre, NULL }, /* Sy */
276 { NULL, NULL }, /* Tn */
277 { termp_ux_pre, NULL }, /* Ux */
278 { NULL, NULL }, /* Xc */
279 { NULL, NULL }, /* Xo */
280 { termp_fo_pre, termp_fo_post }, /* Fo */
281 { NULL, NULL }, /* Fc */
282 { termp_op_pre, termp_op_post }, /* Oo */
283 { NULL, NULL }, /* Oc */
284 { NULL, NULL }, /* Bk */
285 { NULL, NULL }, /* Ek */
286 { termp_bt_pre, NULL }, /* Bt */
287 { NULL, NULL }, /* Hf */
288 { NULL, NULL }, /* Fr */
289 { termp_ud_pre, NULL }, /* Ud */
290 { termp_lb_pre, termp_lb_post }, /* Lb */
291 { termp_ap_pre, NULL }, /* Lb */
292 { termp_pp_pre, NULL }, /* Pp */
293 { termp_lk_pre, NULL }, /* Lk */
294 { termp_mt_pre, NULL }, /* Mt */
295 { termp_brq_pre, termp_brq_post }, /* Brq */
296 { termp_brq_pre, termp_brq_post }, /* Bro */
297 { NULL, NULL }, /* Brc */
298 { NULL, NULL }, /* %C */
299 };
300
301 const struct termact *termacts = __termacts;
302
303
304 static size_t
305 arg_width(const struct mdoc_argv *arg, int pos)
306 {
307 size_t v;
308 int i, len;
309
310 assert(pos < (int)arg->sz && pos >= 0);
311 assert(arg->value[pos]);
312 if (0 == strcmp(arg->value[pos], "indent"))
313 return(INDENT);
314 if (0 == strcmp(arg->value[pos], "indent-two"))
315 return(INDENT * 2);
316
317 len = (int)strlen(arg->value[pos]);
318 assert(len > 0);
319
320 for (i = 0; i < len - 1; i++)
321 if ( ! isdigit((u_char)arg->value[pos][i]))
322 break;
323
324 if (i == len - 1) {
325 if ('n' == arg->value[pos][len - 1]) {
326 v = (size_t)atoi(arg->value[pos]);
327 return(v);
328 }
329
330 }
331 return(strlen(arg->value[pos]) + 1);
332 }
333
334
335 static int
336 arg_listtype(const struct mdoc_node *n)
337 {
338 int i, len;
339
340 assert(MDOC_BLOCK == n->type);
341
342 len = (int)(n->args ? n->args->argc : 0);
343
344 for (i = 0; i < len; i++)
345 switch (n->args->argv[i].arg) {
346 case (MDOC_Bullet):
347 /* FALLTHROUGH */
348 case (MDOC_Dash):
349 /* FALLTHROUGH */
350 case (MDOC_Enum):
351 /* FALLTHROUGH */
352 case (MDOC_Hyphen):
353 /* FALLTHROUGH */
354 case (MDOC_Tag):
355 /* FALLTHROUGH */
356 case (MDOC_Inset):
357 /* FALLTHROUGH */
358 case (MDOC_Diag):
359 /* FALLTHROUGH */
360 case (MDOC_Item):
361 /* FALLTHROUGH */
362 case (MDOC_Column):
363 /* FALLTHROUGH */
364 case (MDOC_Ohang):
365 return(n->args->argv[i].arg);
366 default:
367 break;
368 }
369
370 errx(1, "list type not supported");
371 /* NOTREACHED */
372 }
373
374
375 static size_t
376 arg_offset(const struct mdoc_argv *arg)
377 {
378
379 /* TODO */
380 assert(*arg->value);
381 if (0 == strcmp(*arg->value, "indent"))
382 return(INDENT);
383 if (0 == strcmp(*arg->value, "indent-two"))
384 return(INDENT * 2);
385 return(strlen(*arg->value));
386 }
387
388
389 static int
390 arg_hasattr(int arg, const struct mdoc_node *n)
391 {
392
393 return(-1 != arg_getattr(arg, n));
394 }
395
396
397 static int
398 arg_getattr(int v, const struct mdoc_node *n)
399 {
400 int val;
401
402 return(arg_getattrs(&v, &val, 1, n) ? val : -1);
403 }
404
405
406 static int
407 arg_getattrs(const int *keys, int *vals,
408 size_t sz, const struct mdoc_node *n)
409 {
410 int i, j, k;
411
412 if (NULL == n->args)
413 return(0);
414
415 for (k = i = 0; i < (int)n->args->argc; i++)
416 for (j = 0; j < (int)sz; j++)
417 if (n->args->argv[i].arg == keys[j]) {
418 vals[j] = i;
419 k++;
420 }
421 return(k);
422 }
423
424
425 /* ARGSUSED */
426 static int
427 termp_dq_pre(DECL_ARGS)
428 {
429
430 if (MDOC_BODY != node->type)
431 return(1);
432
433 word(p, "\\(lq");
434 p->flags |= TERMP_NOSPACE;
435 return(1);
436 }
437
438
439 /* ARGSUSED */
440 static void
441 termp_dq_post(DECL_ARGS)
442 {
443
444 if (MDOC_BODY != node->type)
445 return;
446
447 p->flags |= TERMP_NOSPACE;
448 word(p, "\\(rq");
449 }
450
451
452 /* ARGSUSED */
453 static int
454 termp_it_pre_block(DECL_ARGS)
455 {
456
457 newln(p);
458 if ( ! arg_hasattr(MDOC_Compact, node->parent->parent))
459 /* FIXME: parent->parent->parent? */
460 if (node->prev || node->parent->parent->prev)
461 vspace(p);
462
463 return(1);
464 }
465
466
467 /* ARGSUSED */
468 static int
469 termp_it_pre(DECL_ARGS)
470 {
471 const struct mdoc_node *bl, *n;
472 char buf[7];
473 int i, type, keys[3], vals[3];
474 size_t width, offset;
475
476 if (MDOC_BLOCK == node->type)
477 return(termp_it_pre_block(p, pair, meta, node));
478
479 bl = node->parent->parent->parent;
480
481 /* Save parent attributes. */
482
483 pair->offset = p->offset;
484 pair->rmargin = p->rmargin;
485 pair->flag = p->flags;
486
487 /* Get list width and offset. */
488
489 keys[0] = MDOC_Width;
490 keys[1] = MDOC_Offset;
491 keys[2] = MDOC_Column;
492
493 vals[0] = vals[1] = vals[2] = -1;
494
495 width = offset = 0;
496
497 (void)arg_getattrs(keys, vals, 3, bl);
498
499 type = arg_listtype(bl);
500
501 /* Calculate real width and offset. */
502
503 switch (type) {
504 case (MDOC_Column):
505 if (MDOC_BODY == node->type)
506 break;
507 for (i = 0, n = node->prev; n; n = n->prev, i++)
508 offset += arg_width
509 (&bl->args->argv[vals[2]], i);
510 assert(i < (int)bl->args->argv[vals[2]].sz);
511 width = arg_width(&bl->args->argv[vals[2]], i);
512 if (vals[1] >= 0)
513 offset += arg_offset(&bl->args->argv[vals[1]]);
514 break;
515 default:
516 if (vals[0] >= 0)
517 width = arg_width(&bl->args->argv[vals[0]], 0);
518 if (vals[1] >= 0)
519 offset = arg_offset(&bl->args->argv[vals[1]]);
520 break;
521 }
522
523 /*
524 * List-type can override the width in the case of fixed-head
525 * values (bullet, dash/hyphen, enum). Tags need a non-zero
526 * offset.
527 */
528
529 switch (type) {
530 case (MDOC_Bullet):
531 /* FALLTHROUGH */
532 case (MDOC_Dash):
533 /* FALLTHROUGH */
534 case (MDOC_Enum):
535 /* FALLTHROUGH */
536 case (MDOC_Hyphen):
537 if (width < 4)
538 width = 4;
539 break;
540 case (MDOC_Tag):
541 if (0 == width)
542 width = 10;
543 break;
544 default:
545 break;
546 }
547
548 /*
549 * Whitespace control. Inset bodies need an initial space.
550 */
551
552 switch (type) {
553 case (MDOC_Diag):
554 /* FALLTHROUGH */
555 case (MDOC_Inset):
556 if (MDOC_BODY == node->type)
557 p->flags &= ~TERMP_NOSPACE;
558 else
559 p->flags |= TERMP_NOSPACE;
560 break;
561 default:
562 p->flags |= TERMP_NOSPACE;
563 break;
564 }
565
566 /*
567 * Style flags. Diagnostic heads need TTYPE_DIAG.
568 */
569
570 switch (type) {
571 case (MDOC_Diag):
572 if (MDOC_HEAD == node->type)
573 p->flags |= ttypes[TTYPE_DIAG];
574 break;
575 default:
576 break;
577 }
578
579 /*
580 * Pad and break control. This is the tricker part. Lists with
581 * set right-margins for the head get TERMP_NOBREAK because, if
582 * they overrun the margin, they wrap to the new margin.
583 * Correspondingly, the body for these types don't left-pad, as
584 * the head will pad out to to the right.
585 */
586
587 switch (type) {
588 case (MDOC_Bullet):
589 /* FALLTHROUGH */
590 case (MDOC_Dash):
591 /* FALLTHROUGH */
592 case (MDOC_Enum):
593 /* FALLTHROUGH */
594 case (MDOC_Hyphen):
595 /* FALLTHROUGH */
596 case (MDOC_Tag):
597 if (MDOC_HEAD == node->type)
598 p->flags |= TERMP_NOBREAK;
599 else
600 p->flags |= TERMP_NOLPAD;
601 if (MDOC_HEAD == node->type && MDOC_Tag == type)
602 if (NULL == node->next ||
603 NULL == node->next->child)
604 p->flags |= TERMP_NONOBREAK;
605 break;
606 case (MDOC_Column):
607 if (MDOC_HEAD == node->type) {
608 assert(node->next);
609 if (MDOC_BODY == node->next->type)
610 p->flags &= ~TERMP_NOBREAK;
611 else
612 p->flags |= TERMP_NOBREAK;
613 if (node->prev)
614 p->flags |= TERMP_NOLPAD;
615 }
616 break;
617 case (MDOC_Diag):
618 if (MDOC_HEAD == node->type)
619 p->flags |= TERMP_NOBREAK;
620 break;
621 default:
622 break;
623 }
624
625 /*
626 * Margin control. Set-head-width lists have their right
627 * margins shortened. The body for these lists has the offset
628 * necessarily lengthened. Everybody gets the offset.
629 */
630
631 p->offset += offset;
632
633 switch (type) {
634 case (MDOC_Bullet):
635 /* FALLTHROUGH */
636 case (MDOC_Dash):
637 /* FALLTHROUGH */
638 case (MDOC_Enum):
639 /* FALLTHROUGH */
640 case (MDOC_Hyphen):
641 /* FALLTHROUGH */
642 case (MDOC_Tag):
643 if (MDOC_HEAD == node->type)
644 p->rmargin = p->offset + width;
645 else
646 p->offset += width;
647 break;
648 case (MDOC_Column):
649 p->rmargin = p->offset + width;
650 break;
651 default:
652 break;
653 }
654
655 /*
656 * The dash, hyphen, bullet and enum lists all have a special
657 * HEAD character. Print it now.
658 */
659
660 if (MDOC_HEAD == node->type)
661 switch (type) {
662 case (MDOC_Bullet):
663 word(p, "\\[bu]");
664 break;
665 case (MDOC_Dash):
666 /* FALLTHROUGH */
667 case (MDOC_Hyphen):
668 word(p, "\\-");
669 break;
670 case (MDOC_Enum):
671 (pair->ppair->ppair->count)++;
672 (void)snprintf(buf, sizeof(buf), "%d.",
673 pair->ppair->ppair->count);
674 word(p, buf);
675 break;
676 default:
677 break;
678 }
679
680 /*
681 * If we're not going to process our children, indicate so here.
682 */
683
684 switch (type) {
685 case (MDOC_Bullet):
686 /* FALLTHROUGH */
687 case (MDOC_Item):
688 /* FALLTHROUGH */
689 case (MDOC_Dash):
690 /* FALLTHROUGH */
691 case (MDOC_Hyphen):
692 /* FALLTHROUGH */
693 case (MDOC_Enum):
694 if (MDOC_HEAD == node->type)
695 return(0);
696 break;
697 case (MDOC_Column):
698 if (MDOC_BODY == node->type)
699 return(0);
700 break;
701 default:
702 break;
703 }
704
705 return(1);
706 }
707
708
709 /* ARGSUSED */
710 static void
711 termp_it_post(DECL_ARGS)
712 {
713 int type;
714
715 if (MDOC_BODY != node->type && MDOC_HEAD != node->type)
716 return;
717
718 type = arg_listtype(node->parent->parent->parent);
719
720 switch (type) {
721 case (MDOC_Diag):
722 /* FALLTHROUGH */
723 case (MDOC_Item):
724 /* FALLTHROUGH */
725 case (MDOC_Inset):
726 if (MDOC_BODY == node->type)
727 flushln(p);
728 break;
729 case (MDOC_Column):
730 if (MDOC_HEAD == node->type)
731 flushln(p);
732 break;
733 default:
734 flushln(p);
735 break;
736 }
737
738 p->offset = pair->offset;
739 p->rmargin = pair->rmargin;
740 p->flags = pair->flag;
741 }
742
743
744 /* ARGSUSED */
745 static int
746 termp_nm_pre(DECL_ARGS)
747 {
748
749 if (SEC_SYNOPSIS == node->sec)
750 newln(p);
751
752 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_PROG]);
753 if (NULL == node->child)
754 word(p, meta->name);
755
756 return(1);
757 }
758
759
760 /* ARGSUSED */
761 static int
762 termp_fl_pre(DECL_ARGS)
763 {
764
765 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_CMD_FLAG]);
766 word(p, "\\-");
767 p->flags |= TERMP_NOSPACE;
768 return(1);
769 }
770
771
772 /* ARGSUSED */
773 static int
774 termp_ar_pre(DECL_ARGS)
775 {
776
777 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_CMD_ARG]);
778 return(1);
779 }
780
781
782 /* ARGSUSED */
783 static int
784 termp_ns_pre(DECL_ARGS)
785 {
786
787 p->flags |= TERMP_NOSPACE;
788 return(1);
789 }
790
791
792 /* ARGSUSED */
793 static int
794 termp_pp_pre(DECL_ARGS)
795 {
796
797 vspace(p);
798 return(1);
799 }
800
801
802 /* ARGSUSED */
803 static int
804 termp_st_pre(DECL_ARGS)
805 {
806 const char *cp;
807
808 if (node->child && (cp = mdoc_a2st(node->child->string)))
809 word(p, cp);
810 return(0);
811 }
812
813
814 /* ARGSUSED */
815 static int
816 termp_rs_pre(DECL_ARGS)
817 {
818
819 if (MDOC_BLOCK == node->type && node->prev)
820 vspace(p);
821 return(1);
822 }
823
824
825 /* ARGSUSED */
826 static int
827 termp_rv_pre(DECL_ARGS)
828 {
829 int i;
830
831 if (-1 == (i = arg_getattr(MDOC_Std, node)))
832 errx(1, "expected -std argument");
833 if (1 != node->args->argv[i].sz)
834 errx(1, "expected -std argument");
835
836 newln(p);
837 word(p, "The");
838
839 p->flags |= ttypes[TTYPE_FUNC_NAME];
840 word(p, *node->args->argv[i].value);
841 p->flags &= ~ttypes[TTYPE_FUNC_NAME];
842 p->flags |= TERMP_NOSPACE;
843
844 word(p, "() function returns the value 0 if successful;");
845 word(p, "otherwise the value -1 is returned and the");
846 word(p, "global variable");
847
848 p->flags |= ttypes[TTYPE_VAR_DECL];
849 word(p, "errno");
850 p->flags &= ~ttypes[TTYPE_VAR_DECL];
851
852 word(p, "is set to indicate the error.");
853
854 return(1);
855 }
856
857
858 /* ARGSUSED */
859 static int
860 termp_ex_pre(DECL_ARGS)
861 {
862 int i;
863
864 if (-1 == (i = arg_getattr(MDOC_Std, node)))
865 errx(1, "expected -std argument");
866 if (1 != node->args->argv[i].sz)
867 errx(1, "expected -std argument");
868
869 word(p, "The");
870 p->flags |= ttypes[TTYPE_PROG];
871 word(p, *node->args->argv[i].value);
872 p->flags &= ~ttypes[TTYPE_PROG];
873 word(p, "utility exits 0 on success, and >0 if an error occurs.");
874
875 return(1);
876 }
877
878
879 /* ARGSUSED */
880 static int
881 termp_nd_pre(DECL_ARGS)
882 {
883
884 word(p, "\\-");
885 return(1);
886 }
887
888
889 /* ARGSUSED */
890 static void
891 termp_bl_post(DECL_ARGS)
892 {
893
894 if (MDOC_BLOCK == node->type)
895 newln(p);
896 }
897
898
899 /* ARGSUSED */
900 static void
901 termp_op_post(DECL_ARGS)
902 {
903
904 if (MDOC_BODY != node->type)
905 return;
906 p->flags |= TERMP_NOSPACE;
907 word(p, "\\(rB");
908 }
909
910
911 /* ARGSUSED */
912 static int
913 termp_xr_pre(DECL_ARGS)
914 {
915 const struct mdoc_node *n;
916
917 if (NULL == (n = node->child))
918 errx(1, "expected text line argument");
919 word(p, n->string);
920 if (NULL == (n = n->next))
921 return(0);
922 p->flags |= TERMP_NOSPACE;
923 word(p, "(");
924 p->flags |= TERMP_NOSPACE;
925 word(p, n->string);
926 p->flags |= TERMP_NOSPACE;
927 word(p, ")");
928 return(0);
929 }
930
931
932 /* ARGSUSED */
933 static int
934 termp_vt_pre(DECL_ARGS)
935 {
936
937 /* FIXME: this can be "type name". */
938 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_VAR_DECL]);
939 return(1);
940 }
941
942
943 /* ARGSUSED */
944 static void
945 termp_vt_post(DECL_ARGS)
946 {
947
948 if (node->sec == SEC_SYNOPSIS)
949 vspace(p);
950 }
951
952
953 /* ARGSUSED */
954 static int
955 termp_fd_pre(DECL_ARGS)
956 {
957
958 /*
959 * FIXME: this naming is bad. This value is used, in general,
960 * for the #include header or other preprocessor statement.
961 */
962 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_FUNC_DECL]);
963 return(1);
964 }
965
966
967 /* ARGSUSED */
968 static void
969 termp_fd_post(DECL_ARGS)
970 {
971
972 if (node->sec != SEC_SYNOPSIS)
973 return;
974 newln(p);
975 if (node->next && MDOC_Fd != node->next->tok)
976 vspace(p);
977 }
978
979
980 /* ARGSUSED */
981 static int
982 termp_sh_pre(DECL_ARGS)
983 {
984
985 switch (node->type) {
986 case (MDOC_HEAD):
987 vspace(p);
988 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_SECTION]);
989 break;
990 case (MDOC_BODY):
991 p->offset = INDENT;
992 break;
993 default:
994 break;
995 }
996 return(1);
997 }
998
999
1000 /* ARGSUSED */
1001 static void
1002 termp_sh_post(DECL_ARGS)
1003 {
1004
1005 switch (node->type) {
1006 case (MDOC_HEAD):
1007 newln(p);
1008 break;
1009 case (MDOC_BODY):
1010 newln(p);
1011 p->offset = 0;
1012 break;
1013 default:
1014 break;
1015 }
1016 }
1017
1018
1019 /* ARGSUSED */
1020 static int
1021 termp_op_pre(DECL_ARGS)
1022 {
1023
1024 switch (node->type) {
1025 case (MDOC_BODY):
1026 word(p, "\\(lB");
1027 p->flags |= TERMP_NOSPACE;
1028 break;
1029 default:
1030 break;
1031 }
1032 return(1);
1033 }
1034
1035
1036 /* ARGSUSED */
1037 static int
1038 termp_bt_pre(DECL_ARGS)
1039 {
1040
1041 word(p, "is currently in beta test.");
1042 return(1);
1043 }
1044
1045
1046 /* ARGSUSED */
1047 static int
1048 termp_lb_pre(DECL_ARGS)
1049 {
1050 const char *lb;
1051
1052 if (NULL == node->child)
1053 errx(1, "expected text line argument");
1054 if ((lb = mdoc_a2lib(node->child->string))) {
1055 word(p, lb);
1056 return(0);
1057 }
1058 word(p, "library");
1059 return(1);
1060 }
1061
1062
1063 /* ARGSUSED */
1064 static void
1065 termp_lb_post(DECL_ARGS)
1066 {
1067
1068 newln(p);
1069 }
1070
1071
1072 /* ARGSUSED */
1073 static int
1074 termp_ud_pre(DECL_ARGS)
1075 {
1076
1077 word(p, "currently under development.");
1078 return(1);
1079 }
1080
1081
1082 /* ARGSUSED */
1083 static int
1084 termp_d1_pre(DECL_ARGS)
1085 {
1086
1087 if (MDOC_BODY != node->type)
1088 return(1);
1089 newln(p);
1090 p->offset += (pair->offset = INDENT);
1091 return(1);
1092 }
1093
1094
1095 /* ARGSUSED */
1096 static void
1097 termp_d1_post(DECL_ARGS)
1098 {
1099
1100 if (MDOC_BODY != node->type)
1101 return;
1102 newln(p);
1103 p->offset -= pair->offset;
1104 }
1105
1106
1107 /* ARGSUSED */
1108 static int
1109 termp_aq_pre(DECL_ARGS)
1110 {
1111
1112 if (MDOC_BODY != node->type)
1113 return(1);
1114 word(p, "\\(la");
1115 p->flags |= TERMP_NOSPACE;
1116 return(1);
1117 }
1118
1119
1120 /* ARGSUSED */
1121 static void
1122 termp_aq_post(DECL_ARGS)
1123 {
1124
1125 if (MDOC_BODY != node->type)
1126 return;
1127 p->flags |= TERMP_NOSPACE;
1128 word(p, "\\(ra");
1129 }
1130
1131
1132 /* ARGSUSED */
1133 static int
1134 termp_ft_pre(DECL_ARGS)
1135 {
1136
1137 if (SEC_SYNOPSIS == node->sec)
1138 if (node->prev && MDOC_Fo == node->prev->tok)
1139 vspace(p);
1140 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_FUNC_TYPE]);
1141 return(1);
1142 }
1143
1144
1145 /* ARGSUSED */
1146 static void
1147 termp_ft_post(DECL_ARGS)
1148 {
1149
1150 if (SEC_SYNOPSIS == node->sec)
1151 newln(p);
1152 }
1153
1154
1155 /* ARGSUSED */
1156 static int
1157 termp_fn_pre(DECL_ARGS)
1158 {
1159 const struct mdoc_node *n;
1160
1161 if (NULL == node->child)
1162 errx(1, "expected text line arguments");
1163
1164 /* FIXME: can be "type funcname" "type varname"... */
1165
1166 p->flags |= ttypes[TTYPE_FUNC_NAME];
1167 word(p, node->child->string);
1168 p->flags &= ~ttypes[TTYPE_FUNC_NAME];
1169
1170 word(p, "(");
1171
1172 p->flags |= TERMP_NOSPACE;
1173 for (n = node->child->next; n; n = n->next) {
1174 p->flags |= ttypes[TTYPE_FUNC_ARG];
1175 word(p, n->string);
1176 p->flags &= ~ttypes[TTYPE_FUNC_ARG];
1177 if (n->next)
1178 word(p, ",");
1179 }
1180
1181 word(p, ")");
1182
1183 if (SEC_SYNOPSIS == node->sec)
1184 word(p, ";");
1185
1186 return(0);
1187 }
1188
1189
1190 /* ARGSUSED */
1191 static void
1192 termp_fn_post(DECL_ARGS)
1193 {
1194
1195 if (node->sec == SEC_SYNOPSIS && node->next)
1196 vspace(p);
1197
1198 }
1199
1200
1201 /* ARGSUSED */
1202 static int
1203 termp_sx_pre(DECL_ARGS)
1204 {
1205
1206 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_LINK]);
1207 return(1);
1208 }
1209
1210
1211 /* ARGSUSED */
1212 static int
1213 termp_fa_pre(DECL_ARGS)
1214 {
1215 struct mdoc_node *n;
1216
1217 if (node->parent->tok != MDOC_Fo) {
1218 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_FUNC_ARG]);
1219 return(1);
1220 }
1221
1222 for (n = node->child; n; n = n->next) {
1223 p->flags |= ttypes[TTYPE_FUNC_ARG];
1224 word(p, n->string);
1225 p->flags &= ~ttypes[TTYPE_FUNC_ARG];
1226 if (n->next)
1227 word(p, ",");
1228 }
1229
1230 if (node->next && node->next->tok == MDOC_Fa)
1231 word(p, ",");
1232
1233 return(0);
1234 }
1235
1236
1237 /* ARGSUSED */
1238 static int
1239 termp_va_pre(DECL_ARGS)
1240 {
1241
1242 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_VAR_DECL]);
1243 return(1);
1244 }
1245
1246
1247 /* ARGSUSED */
1248 static int
1249 termp_bd_pre(DECL_ARGS)
1250 {
1251 const struct mdoc_node *n;
1252 int i, type;
1253
1254 if (MDOC_BLOCK == node->type) {
1255 /* FIXME: parent prev? */
1256 if (node->prev)
1257 vspace(p);
1258 return(1);
1259 } else if (MDOC_BODY != node->type)
1260 return(1);
1261
1262 if (NULL == node->parent->args)
1263 errx(1, "missing display type");
1264
1265 pair->offset = p->offset;
1266
1267 for (type = -1, i = 0;
1268 i < (int)node->parent->args->argc; i++) {
1269 switch (node->parent->args->argv[i].arg) {
1270 case (MDOC_Ragged):
1271 /* FALLTHROUGH */
1272 case (MDOC_Filled):
1273 /* FALLTHROUGH */
1274 case (MDOC_Unfilled):
1275 /* FALLTHROUGH */
1276 case (MDOC_Literal):
1277 type = node->parent->args->argv[i].arg;
1278 i = (int)node->parent->args->argc;
1279 break;
1280 default:
1281 break;
1282 }
1283 }
1284
1285 if (NULL == node->parent->args)
1286 errx(1, "missing display type");
1287
1288 i = arg_getattr(MDOC_Offset, node->parent);
1289 if (-1 != i) {
1290 if (1 != node->parent->args->argv[i].sz)
1291 errx(1, "expected single value");
1292 p->offset += arg_offset(&node->parent->args->argv[i]);
1293 }
1294
1295 switch (type) {
1296 case (MDOC_Literal):
1297 /* FALLTHROUGH */
1298 case (MDOC_Unfilled):
1299 break;
1300 default:
1301 return(1);
1302 }
1303
1304 p->flags |= TERMP_LITERAL;
1305
1306 for (n = node->child; n; n = n->next) {
1307 if (MDOC_TEXT != n->type) {
1308 warnx("non-text children not yet allowed");
1309 continue;
1310 }
1311 word(p, n->string);
1312 flushln(p);
1313 }
1314
1315 return(0);
1316 }
1317
1318
1319 /* ARGSUSED */
1320 static void
1321 termp_bd_post(DECL_ARGS)
1322 {
1323
1324 if (MDOC_BODY != node->type)
1325 return;
1326
1327 if ( ! (p->flags & TERMP_LITERAL))
1328 flushln(p);
1329
1330 p->flags &= ~TERMP_LITERAL;
1331 p->offset = pair->offset;
1332 }
1333
1334
1335 /* ARGSUSED */
1336 static int
1337 termp_qq_pre(DECL_ARGS)
1338 {
1339
1340 if (MDOC_BODY != node->type)
1341 return(1);
1342 word(p, "\"");
1343 p->flags |= TERMP_NOSPACE;
1344 return(1);
1345 }
1346
1347
1348 /* ARGSUSED */
1349 static void
1350 termp_qq_post(DECL_ARGS)
1351 {
1352
1353 if (MDOC_BODY != node->type)
1354 return;
1355 p->flags |= TERMP_NOSPACE;
1356 word(p, "\"");
1357 }
1358
1359
1360 /* ARGSUSED */
1361 static int
1362 termp_bsx_pre(DECL_ARGS)
1363 {
1364
1365 word(p, "BSDI BSD/OS");
1366 return(1);
1367 }
1368
1369
1370 /* ARGSUSED */
1371 static void
1372 termp_bx_post(DECL_ARGS)
1373 {
1374
1375 if (node->child)
1376 p->flags |= TERMP_NOSPACE;
1377 word(p, "BSD");
1378 }
1379
1380
1381 /* ARGSUSED */
1382 static int
1383 termp_ox_pre(DECL_ARGS)
1384 {
1385
1386 word(p, "OpenBSD");
1387 return(1);
1388 }
1389
1390
1391 /* ARGSUSED */
1392 static int
1393 termp_ux_pre(DECL_ARGS)
1394 {
1395
1396 word(p, "UNIX");
1397 return(1);
1398 }
1399
1400
1401 /* ARGSUSED */
1402 static int
1403 termp_fx_pre(DECL_ARGS)
1404 {
1405
1406 word(p, "FreeBSD");
1407 return(1);
1408 }
1409
1410
1411 /* ARGSUSED */
1412 static int
1413 termp_nx_pre(DECL_ARGS)
1414 {
1415
1416 word(p, "NetBSD");
1417 return(1);
1418 }
1419
1420
1421 /* ARGSUSED */
1422 static int
1423 termp_sq_pre(DECL_ARGS)
1424 {
1425
1426 if (MDOC_BODY != node->type)
1427 return(1);
1428 word(p, "\\(oq");
1429 p->flags |= TERMP_NOSPACE;
1430 return(1);
1431 }
1432
1433
1434 /* ARGSUSED */
1435 static void
1436 termp_sq_post(DECL_ARGS)
1437 {
1438
1439 if (MDOC_BODY != node->type)
1440 return;
1441 p->flags |= TERMP_NOSPACE;
1442 word(p, "\\(aq");
1443 }
1444
1445
1446 /* ARGSUSED */
1447 static int
1448 termp_pf_pre(DECL_ARGS)
1449 {
1450
1451 p->flags |= TERMP_IGNDELIM;
1452 return(1);
1453 }
1454
1455
1456 /* ARGSUSED */
1457 static void
1458 termp_pf_post(DECL_ARGS)
1459 {
1460
1461 p->flags &= ~TERMP_IGNDELIM;
1462 p->flags |= TERMP_NOSPACE;
1463 }
1464
1465
1466 /* ARGSUSED */
1467 static int
1468 termp_ss_pre(DECL_ARGS)
1469 {
1470
1471 switch (node->type) {
1472 case (MDOC_BLOCK):
1473 newln(p);
1474 if (node->prev)
1475 vspace(p);
1476 break;
1477 case (MDOC_HEAD):
1478 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_SSECTION]);
1479 p->offset = INDENT / 2;
1480 break;
1481 default:
1482 break;
1483 }
1484
1485 return(1);
1486 }
1487
1488
1489 /* ARGSUSED */
1490 static void
1491 termp_ss_post(DECL_ARGS)
1492 {
1493
1494 switch (node->type) {
1495 case (MDOC_HEAD):
1496 newln(p);
1497 p->offset = INDENT;
1498 break;
1499 default:
1500 break;
1501 }
1502 }
1503
1504
1505 /* ARGSUSED */
1506 static int
1507 termp_pa_pre(DECL_ARGS)
1508 {
1509
1510 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_FILE]);
1511 return(1);
1512 }
1513
1514
1515 /* ARGSUSED */
1516 static int
1517 termp_em_pre(DECL_ARGS)
1518 {
1519
1520 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_EMPH]);
1521 return(1);
1522 }
1523
1524
1525 /* ARGSUSED */
1526 static int
1527 termp_cd_pre(DECL_ARGS)
1528 {
1529
1530 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_CONFIG]);
1531 newln(p);
1532 return(1);
1533 }
1534
1535
1536 /* ARGSUSED */
1537 static int
1538 termp_cm_pre(DECL_ARGS)
1539 {
1540
1541 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_CMD_FLAG]);
1542 return(1);
1543 }
1544
1545
1546 /* ARGSUSED */
1547 static int
1548 termp_ic_pre(DECL_ARGS)
1549 {
1550
1551 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_CMD]);
1552 return(1);
1553 }
1554
1555
1556 /* ARGSUSED */
1557 static int
1558 termp_in_pre(DECL_ARGS)
1559 {
1560
1561 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_INCLUDE]);
1562 word(p, "#include");
1563 word(p, "<");
1564 p->flags |= TERMP_NOSPACE;
1565 return(1);
1566 }
1567
1568
1569 /* ARGSUSED */
1570 static void
1571 termp_in_post(DECL_ARGS)
1572 {
1573
1574 p->flags |= TERMP_NOSPACE;
1575 word(p, ">");
1576
1577 newln(p);
1578 if (SEC_SYNOPSIS != node->sec)
1579 return;
1580 if (node->next && MDOC_In != node->next->tok)
1581 vspace(p);
1582 }
1583
1584
1585 /* ARGSUSED */
1586 static int
1587 termp_at_pre(DECL_ARGS)
1588 {
1589 const char *att;
1590
1591 att = NULL;
1592
1593 if (node->child)
1594 att = mdoc_a2att(node->child->string);
1595 if (NULL == att)
1596 att = "AT&T UNIX";
1597
1598 word(p, att);
1599 return(0);
1600 }
1601
1602
1603 /* ARGSUSED */
1604 static int
1605 termp_brq_pre(DECL_ARGS)
1606 {
1607
1608 if (MDOC_BODY != node->type)
1609 return(1);
1610 word(p, "\\(lC");
1611 p->flags |= TERMP_NOSPACE;
1612 return(1);
1613 }
1614
1615
1616 /* ARGSUSED */
1617 static void
1618 termp_brq_post(DECL_ARGS)
1619 {
1620
1621 if (MDOC_BODY != node->type)
1622 return;
1623 p->flags |= TERMP_NOSPACE;
1624 word(p, "\\(rC");
1625 }
1626
1627
1628 /* ARGSUSED */
1629 static int
1630 termp_bq_pre(DECL_ARGS)
1631 {
1632
1633 if (MDOC_BODY != node->type)
1634 return(1);
1635 word(p, "\\(lB");
1636 p->flags |= TERMP_NOSPACE;
1637 return(1);
1638 }
1639
1640
1641 /* ARGSUSED */
1642 static void
1643 termp_bq_post(DECL_ARGS)
1644 {
1645
1646 if (MDOC_BODY != node->type)
1647 return;
1648 p->flags |= TERMP_NOSPACE;
1649 word(p, "\\(rB");
1650 }
1651
1652
1653 /* ARGSUSED */
1654 static int
1655 termp_pq_pre(DECL_ARGS)
1656 {
1657
1658 if (MDOC_BODY != node->type)
1659 return(1);
1660 word(p, "\\&(");
1661 p->flags |= TERMP_NOSPACE;
1662 return(1);
1663 }
1664
1665
1666 /* ARGSUSED */
1667 static void
1668 termp_pq_post(DECL_ARGS)
1669 {
1670
1671 if (MDOC_BODY != node->type)
1672 return;
1673 word(p, ")");
1674 }
1675
1676
1677 /* ARGSUSED */
1678 static int
1679 termp_fo_pre(DECL_ARGS)
1680 {
1681 const struct mdoc_node *n;
1682
1683 if (MDOC_BODY == node->type) {
1684 word(p, "(");
1685 p->flags |= TERMP_NOSPACE;
1686 return(1);
1687 } else if (MDOC_HEAD != node->type)
1688 return(1);
1689
1690 /* XXX - groff shows only first parameter */
1691
1692 p->flags |= ttypes[TTYPE_FUNC_NAME];
1693 for (n = node->child; n; n = n->next) {
1694 if (MDOC_TEXT != n->type)
1695 errx(1, "expected text line argument");
1696 word(p, n->string);
1697 }
1698 p->flags &= ~ttypes[TTYPE_FUNC_NAME];
1699
1700 return(0);
1701 }
1702
1703
1704 /* ARGSUSED */
1705 static void
1706 termp_fo_post(DECL_ARGS)
1707 {
1708
1709 if (MDOC_BODY != node->type)
1710 return;
1711 p->flags |= TERMP_NOSPACE;
1712 word(p, ")");
1713 p->flags |= TERMP_NOSPACE;
1714 word(p, ";");
1715 newln(p);
1716 }
1717
1718
1719 /* ARGSUSED */
1720 static int
1721 termp_bf_pre(DECL_ARGS)
1722 {
1723 const struct mdoc_node *n;
1724
1725 if (MDOC_HEAD == node->type) {
1726 return(0);
1727 } else if (MDOC_BLOCK != node->type)
1728 return(1);
1729
1730 if (NULL == (n = node->head->child)) {
1731 if (arg_hasattr(MDOC_Emphasis, node))
1732 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_EMPH]);
1733 else if (arg_hasattr(MDOC_Symbolic, node))
1734 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_SYMB]);
1735
1736 return(1);
1737 }
1738
1739 if (MDOC_TEXT != n->type)
1740 errx(1, "expected text line arguments");
1741
1742 if (0 == strcmp("Em", n->string))
1743 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_EMPH]);
1744 else if (0 == strcmp("Sy", n->string))
1745 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_EMPH]);
1746
1747 return(1);
1748 }
1749
1750
1751 /* ARGSUSED */
1752 static int
1753 termp_sy_pre(DECL_ARGS)
1754 {
1755
1756 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_SYMB]);
1757 return(1);
1758 }
1759
1760
1761 /* ARGSUSED */
1762 static int
1763 termp_ms_pre(DECL_ARGS)
1764 {
1765
1766 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_SYMBOL]);
1767 return(1);
1768 }
1769
1770
1771
1772 /* ARGSUSED */
1773 static int
1774 termp_sm_pre(DECL_ARGS)
1775 {
1776
1777 #if notyet
1778 assert(node->child);
1779 if (0 == strcmp("off", node->child->data.text.string)) {
1780 p->flags &= ~TERMP_NONOSPACE;
1781 p->flags &= ~TERMP_NOSPACE;
1782 } else {
1783 p->flags |= TERMP_NONOSPACE;
1784 p->flags |= TERMP_NOSPACE;
1785 }
1786 #endif
1787
1788 return(0);
1789 }
1790
1791
1792 /* ARGSUSED */
1793 static int
1794 termp_ap_pre(DECL_ARGS)
1795 {
1796
1797 p->flags |= TERMP_NOSPACE;
1798 word(p, "\\(aq");
1799 p->flags |= TERMP_NOSPACE;
1800 return(1);
1801 }
1802
1803
1804 /* ARGSUSED */
1805 static int
1806 termp__t_pre(DECL_ARGS)
1807 {
1808
1809 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_REF_TITLE]);
1810 return(1);
1811 }
1812
1813
1814 /* ARGSUSED */
1815 static void
1816 termp____post(DECL_ARGS)
1817 {
1818
1819 p->flags |= TERMP_NOSPACE;
1820 word(p, node->next ? "," : ".");
1821 }
1822
1823
1824 /* ARGSUSED */
1825 static int
1826 termp_lk_pre(DECL_ARGS)
1827 {
1828 const struct mdoc_node *n;
1829
1830 if (NULL == (n = node->child))
1831 errx(1, "expected line argument");
1832
1833 p->flags |= ttypes[TTYPE_LINK_ANCHOR];
1834 word(p, n->string);
1835 p->flags &= ~ttypes[TTYPE_LINK_ANCHOR];
1836 p->flags |= TERMP_NOSPACE;
1837 word(p, ":");
1838
1839 p->flags |= ttypes[TTYPE_LINK_TEXT];
1840 for ( ; n; n = n->next) {
1841 word(p, n->string);
1842 }
1843 p->flags &= ~ttypes[TTYPE_LINK_TEXT];
1844
1845 return(0);
1846 }
1847
1848
1849 /* ARGSUSED */
1850 static int
1851 termp_mt_pre(DECL_ARGS)
1852 {
1853
1854 TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_LINK_ANCHOR]);
1855 return(1);
1856 }
1857