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