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