Annotation of mandoc/term.c, Revision 1.51
1.51 ! kristaps 1: /* $Id: term.c,v 1.50 2009/03/09 13:17:49 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.44 kristaps 736: if (node->child) {
737: if (MDOC_TEXT != node->child->type)
738: errx(1, "expected text line arguments");
739: if ((cp = mdoc_a2st(node->child->string)))
1.43 kristaps 740: word(p, cp);
1.44 kristaps 741: }
1.43 kristaps 742: return(0);
1.14 kristaps 743: }
744:
745:
746: /* ARGSUSED */
747: static int
1.28 kristaps 748: termp_rs_pre(DECL_ARGS)
749: {
750:
1.30 kristaps 751: if (MDOC_BLOCK == node->type && node->prev)
1.28 kristaps 752: vspace(p);
753: return(1);
754: }
755:
756:
757: /* ARGSUSED */
758: static int
1.14 kristaps 759: termp_rv_pre(DECL_ARGS)
760: {
761: int i;
762:
1.44 kristaps 763: if (-1 == (i = arg_getattr(MDOC_Std, node)))
764: errx(1, "expected -std argument");
765: if (1 != node->args->argv[i].sz)
766: errx(1, "expected -std argument");
1.14 kristaps 767:
768: newln(p);
769: word(p, "The");
770:
771: p->flags |= ttypes[TTYPE_FUNC_NAME];
1.44 kristaps 772: word(p, *node->args->argv[i].value);
1.14 kristaps 773: p->flags &= ~ttypes[TTYPE_FUNC_NAME];
774:
775: word(p, "() function returns the value 0 if successful;");
776: word(p, "otherwise the value -1 is returned and the");
777: word(p, "global variable");
778:
779: p->flags |= ttypes[TTYPE_VAR_DECL];
780: word(p, "errno");
781: p->flags &= ~ttypes[TTYPE_VAR_DECL];
782:
783: word(p, "is set to indicate the error.");
784:
785: return(1);
786: }
787:
788:
789: /* ARGSUSED */
790: static int
1.10 kristaps 791: termp_ex_pre(DECL_ARGS)
792: {
793: int i;
794:
1.44 kristaps 795: if (-1 == (i = arg_getattr(MDOC_Std, node)))
796: errx(1, "expected -std argument");
797: if (1 != node->args->argv[i].sz)
798: errx(1, "expected -std argument");
1.10 kristaps 799:
800: word(p, "The");
801: p->flags |= ttypes[TTYPE_PROG];
1.44 kristaps 802: word(p, *node->args->argv[i].value);
1.10 kristaps 803: p->flags &= ~ttypes[TTYPE_PROG];
804: word(p, "utility exits 0 on success, and >0 if an error occurs.");
805:
806: return(1);
807: }
808:
809:
810: /* ARGSUSED */
811: static int
812: termp_nd_pre(DECL_ARGS)
813: {
814:
815: word(p, "\\-");
816: return(1);
817: }
818:
819:
820: /* ARGSUSED */
821: static void
822: termp_bl_post(DECL_ARGS)
823: {
824:
825: if (MDOC_BLOCK == node->type)
826: newln(p);
827: }
828:
829:
830: /* ARGSUSED */
831: static void
832: termp_op_post(DECL_ARGS)
833: {
834:
835: if (MDOC_BODY != node->type)
1.2 kristaps 836: return;
1.10 kristaps 837: p->flags |= TERMP_NOSPACE;
838: word(p, "\\(rB");
839: }
840:
841:
842: /* ARGSUSED */
843: static int
844: termp_xr_pre(DECL_ARGS)
845: {
846: const struct mdoc_node *n;
847:
1.44 kristaps 848: if (NULL == (n = node->child))
849: errx(1, "expected text line argument");
850: if (MDOC_TEXT != n->type)
851: errx(1, "expected text line argument");
1.10 kristaps 852:
1.44 kristaps 853: word(p, n->string);
1.10 kristaps 854:
855: if (NULL == (n = n->next))
856: return(0);
1.44 kristaps 857: if (MDOC_TEXT != n->type)
858: errx(1, "expected text line argument");
1.10 kristaps 859:
860: p->flags |= TERMP_NOSPACE;
861: word(p, "(");
862: p->flags |= TERMP_NOSPACE;
1.44 kristaps 863: word(p, n->string);
1.10 kristaps 864: p->flags |= TERMP_NOSPACE;
865: word(p, ")");
866:
867: return(0);
1.2 kristaps 868: }
869:
870:
1.10 kristaps 871: /* ARGSUSED */
872: static int
873: termp_vt_pre(DECL_ARGS)
1.2 kristaps 874: {
875:
1.10 kristaps 876: /* FIXME: this can be "type name". */
1.31 kristaps 877: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_VAR_DECL]);
1.10 kristaps 878: return(1);
1.2 kristaps 879: }
880:
881:
1.10 kristaps 882: /* ARGSUSED */
1.2 kristaps 883: static void
1.10 kristaps 884: termp_vt_post(DECL_ARGS)
885: {
886:
887: if (node->sec == SEC_SYNOPSIS)
888: vspace(p);
889: }
890:
891:
892: /* ARGSUSED */
893: static int
894: termp_fd_pre(DECL_ARGS)
1.2 kristaps 895: {
896:
1.10 kristaps 897: /*
898: * FIXME: this naming is bad. This value is used, in general,
899: * for the #include header or other preprocessor statement.
900: */
1.31 kristaps 901: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_FUNC_DECL]);
1.10 kristaps 902: return(1);
1.2 kristaps 903: }
904:
905:
1.10 kristaps 906: /* ARGSUSED */
1.2 kristaps 907: static void
1.10 kristaps 908: termp_fd_post(DECL_ARGS)
1.2 kristaps 909: {
910:
1.30 kristaps 911: if (node->sec != SEC_SYNOPSIS)
912: return;
913: newln(p);
914: if (node->next && MDOC_Fd != node->next->tok)
1.10 kristaps 915: vspace(p);
916: }
917:
918:
919: /* ARGSUSED */
920: static int
921: termp_sh_pre(DECL_ARGS)
922: {
1.2 kristaps 923:
1.10 kristaps 924: switch (node->type) {
925: case (MDOC_HEAD):
926: vspace(p);
1.31 kristaps 927: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_SECTION]);
1.2 kristaps 928: break;
1.10 kristaps 929: case (MDOC_BODY):
930: p->offset = INDENT;
1.2 kristaps 931: break;
1.10 kristaps 932: default:
933: break;
934: }
935: return(1);
936: }
937:
938:
939: /* ARGSUSED */
1.19 kristaps 940: static void
941: termp_sh_post(DECL_ARGS)
942: {
943:
944: switch (node->type) {
945: case (MDOC_HEAD):
946: newln(p);
947: break;
948: case (MDOC_BODY):
949: newln(p);
950: p->offset = 0;
951: break;
952: default:
953: break;
954: }
955: }
956:
957:
958: /* ARGSUSED */
1.10 kristaps 959: static int
960: termp_op_pre(DECL_ARGS)
961: {
962:
963: switch (node->type) {
964: case (MDOC_BODY):
965: word(p, "\\(lB");
966: p->flags |= TERMP_NOSPACE;
1.2 kristaps 967: break;
968: default:
1.10 kristaps 969: break;
1.2 kristaps 970: }
1.10 kristaps 971: return(1);
972: }
973:
974:
975: /* ARGSUSED */
976: static int
1.17 kristaps 977: termp_bt_pre(DECL_ARGS)
978: {
979:
980: word(p, "is currently in beta test.");
981: return(1);
982: }
983:
984:
985: /* ARGSUSED */
1.47 kristaps 986: static int
987: termp_lb_pre(DECL_ARGS)
988: {
989: const char *lb;
990:
991: if (NULL == node->child)
992: errx(1, "expected text line argument");
993: if (MDOC_TEXT != node->child->type)
994: errx(1, "expected text line argument");
995:
996: if ((lb = mdoc_a2lib(node->child->string))) {
997: word(p, lb);
998: return(0);
999: }
1000:
1001: word(p, "library");
1002: return(1);
1003: }
1004:
1005:
1006: /* ARGSUSED */
1.43 kristaps 1007: static void
1008: termp_lb_post(DECL_ARGS)
1009: {
1010:
1011: newln(p);
1012: }
1013:
1014:
1015: /* ARGSUSED */
1.17 kristaps 1016: static int
1.10 kristaps 1017: termp_ud_pre(DECL_ARGS)
1018: {
1019:
1020: word(p, "currently under development.");
1021: return(1);
1022: }
1023:
1024:
1025: /* ARGSUSED */
1026: static int
1027: termp_d1_pre(DECL_ARGS)
1028: {
1029:
1030: if (MDOC_BODY != node->type)
1031: return(1);
1032: newln(p);
1.19 kristaps 1033: p->offset += (pair->offset = INDENT);
1.10 kristaps 1034: return(1);
1.2 kristaps 1035: }
1036:
1037:
1.10 kristaps 1038: /* ARGSUSED */
1.2 kristaps 1039: static void
1.10 kristaps 1040: termp_d1_post(DECL_ARGS)
1041: {
1042:
1043: if (MDOC_BODY != node->type)
1044: return;
1045: newln(p);
1.19 kristaps 1046: p->offset -= pair->offset;
1.10 kristaps 1047: }
1048:
1049:
1050: /* ARGSUSED */
1051: static int
1052: termp_aq_pre(DECL_ARGS)
1.6 kristaps 1053: {
1054:
1.10 kristaps 1055: if (MDOC_BODY != node->type)
1056: return(1);
1.40 kristaps 1057: word(p, "\\(la");
1.10 kristaps 1058: p->flags |= TERMP_NOSPACE;
1059: return(1);
1060: }
1.6 kristaps 1061:
1062:
1.10 kristaps 1063: /* ARGSUSED */
1064: static void
1065: termp_aq_post(DECL_ARGS)
1066: {
1.6 kristaps 1067:
1.10 kristaps 1068: if (MDOC_BODY != node->type)
1.6 kristaps 1069: return;
1.10 kristaps 1070: p->flags |= TERMP_NOSPACE;
1.40 kristaps 1071: word(p, "\\(ra");
1.10 kristaps 1072: }
1.6 kristaps 1073:
1.10 kristaps 1074:
1075: /* ARGSUSED */
1076: static int
1077: termp_ft_pre(DECL_ARGS)
1078: {
1079:
1.34 kristaps 1080: if (SEC_SYNOPSIS == node->sec)
1081: if (node->prev && MDOC_Fo == node->prev->tok)
1082: vspace(p);
1.31 kristaps 1083: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_FUNC_TYPE]);
1.10 kristaps 1084: return(1);
1.6 kristaps 1085: }
1086:
1087:
1.10 kristaps 1088: /* ARGSUSED */
1.6 kristaps 1089: static void
1.10 kristaps 1090: termp_ft_post(DECL_ARGS)
1.2 kristaps 1091: {
1092:
1.34 kristaps 1093: if (SEC_SYNOPSIS == node->sec)
1.10 kristaps 1094: newln(p);
1095: }
1.2 kristaps 1096:
1097:
1.10 kristaps 1098: /* ARGSUSED */
1099: static int
1100: termp_fn_pre(DECL_ARGS)
1101: {
1102: const struct mdoc_node *n;
1103:
1.44 kristaps 1104: if (NULL == node->child)
1105: errx(1, "expected text line arguments");
1106: if (MDOC_TEXT != node->child->type)
1107: errx(1, "expected text line arguments");
1.2 kristaps 1108:
1.10 kristaps 1109: /* FIXME: can be "type funcname" "type varname"... */
1.2 kristaps 1110:
1.10 kristaps 1111: p->flags |= ttypes[TTYPE_FUNC_NAME];
1.44 kristaps 1112: word(p, node->child->string);
1.10 kristaps 1113: p->flags &= ~ttypes[TTYPE_FUNC_NAME];
1114:
1115: word(p, "(");
1116:
1117: p->flags |= TERMP_NOSPACE;
1118: for (n = node->child->next; n; n = n->next) {
1.44 kristaps 1119: if (MDOC_TEXT != n->type)
1120: errx(1, "expected text line arguments");
1.10 kristaps 1121: p->flags |= ttypes[TTYPE_FUNC_ARG];
1.44 kristaps 1122: word(p, n->string);
1.10 kristaps 1123: p->flags &= ~ttypes[TTYPE_FUNC_ARG];
1.16 kristaps 1124: if (n->next)
1.10 kristaps 1125: word(p, ",");
1.6 kristaps 1126: }
1.2 kristaps 1127:
1.10 kristaps 1128: word(p, ")");
1129:
1130: if (SEC_SYNOPSIS == node->sec)
1131: word(p, ";");
1132:
1133: return(0);
1.2 kristaps 1134: }
1135:
1136:
1.10 kristaps 1137: /* ARGSUSED */
1138: static void
1139: termp_fn_post(DECL_ARGS)
1.2 kristaps 1140: {
1141:
1.30 kristaps 1142: if (node->sec == SEC_SYNOPSIS && node->next)
1.10 kristaps 1143: vspace(p);
1144:
1145: }
1.2 kristaps 1146:
1147:
1.10 kristaps 1148: /* ARGSUSED */
1149: static int
1150: termp_sx_pre(DECL_ARGS)
1151: {
1.8 kristaps 1152:
1.31 kristaps 1153: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_LINK]);
1.10 kristaps 1154: return(1);
1.2 kristaps 1155: }
1156:
1157:
1.10 kristaps 1158: /* ARGSUSED */
1159: static int
1160: termp_fa_pre(DECL_ARGS)
1161: {
1.16 kristaps 1162: struct mdoc_node *n;
1163:
1164: if (node->parent->tok != MDOC_Fo) {
1.31 kristaps 1165: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_FUNC_ARG]);
1.16 kristaps 1166: return(1);
1167: }
1168:
1169: for (n = node->child; n; n = n->next) {
1.44 kristaps 1170: if (MDOC_TEXT != n->type)
1171: errx(1, "expected text line arguments");
1.16 kristaps 1172:
1173: p->flags |= ttypes[TTYPE_FUNC_ARG];
1.44 kristaps 1174: word(p, n->string);
1.16 kristaps 1175: p->flags &= ~ttypes[TTYPE_FUNC_ARG];
1176:
1177: if (n->next)
1178: word(p, ",");
1179: }
1180:
1181: if (node->next && node->next->tok == MDOC_Fa)
1182: word(p, ",");
1.2 kristaps 1183:
1.16 kristaps 1184: return(0);
1.10 kristaps 1185: }
1.2 kristaps 1186:
1187:
1.10 kristaps 1188: /* ARGSUSED */
1189: static int
1190: termp_va_pre(DECL_ARGS)
1191: {
1.2 kristaps 1192:
1.31 kristaps 1193: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_VAR_DECL]);
1.10 kristaps 1194: return(1);
1.2 kristaps 1195: }
1196:
1197:
1.10 kristaps 1198: /* ARGSUSED */
1199: static int
1200: termp_bd_pre(DECL_ARGS)
1201: {
1.35 kristaps 1202: const struct mdoc_node *n;
1.44 kristaps 1203: int i, type;
1.1 kristaps 1204:
1.10 kristaps 1205: if (MDOC_BLOCK == node->type) {
1.30 kristaps 1206: if (node->prev)
1207: vspace(p);
1.10 kristaps 1208: return(1);
1209: } else if (MDOC_BODY != node->type)
1210: return(1);
1211:
1.44 kristaps 1212: if (NULL == node->parent->args)
1213: errx(1, "missing display type");
1214:
1.20 kristaps 1215: pair->offset = p->offset;
1.10 kristaps 1216:
1.44 kristaps 1217: for (type = -1, i = 0;
1218: i < (int)node->parent->args->argc; i++) {
1219: switch (node->parent->args->argv[i].arg) {
1.35 kristaps 1220: case (MDOC_Ragged):
1221: /* FALLTHROUGH */
1222: case (MDOC_Filled):
1223: /* FALLTHROUGH */
1224: case (MDOC_Unfilled):
1225: /* FALLTHROUGH */
1226: case (MDOC_Literal):
1.44 kristaps 1227: type = node->parent->args->argv[i].arg;
1228: i = (int)node->parent->args->argc;
1.35 kristaps 1229: break;
1230: default:
1.44 kristaps 1231: break;
1.35 kristaps 1232: }
1233: }
1234:
1.44 kristaps 1235: if (NULL == node->parent->args)
1236: errx(1, "missing display type");
1.12 kristaps 1237:
1.44 kristaps 1238: i = arg_getattr(MDOC_Offset, node->parent);
1.12 kristaps 1239: if (-1 != i) {
1.45 kristaps 1240: if (1 != node->parent->args->argv[i].sz)
1.44 kristaps 1241: errx(1, "expected single value");
1.45 kristaps 1242: p->offset += arg_offset(&node->parent->args->argv[i]);
1.12 kristaps 1243: }
1244:
1.35 kristaps 1245: switch (type) {
1246: case (MDOC_Literal):
1247: /* FALLTHROUGH */
1248: case (MDOC_Unfilled):
1249: break;
1250: default:
1251: return(1);
1252: }
1253:
1.10 kristaps 1254: p->flags |= TERMP_LITERAL;
1255:
1256: for (n = node->child; n; n = n->next) {
1.35 kristaps 1257: if (MDOC_TEXT != n->type) {
1258: warnx("non-text children not yet allowed");
1259: continue;
1260: }
1.44 kristaps 1261: word(p, n->string);
1.35 kristaps 1262: flushln(p);
1.10 kristaps 1263: }
1.1 kristaps 1264:
1.10 kristaps 1265: return(0);
1266: }
1.1 kristaps 1267:
1268:
1.10 kristaps 1269: /* ARGSUSED */
1.12 kristaps 1270: static void
1271: termp_bd_post(DECL_ARGS)
1272: {
1273:
1.20 kristaps 1274: if (MDOC_BODY != node->type)
1275: return;
1.35 kristaps 1276:
1277: if ( ! (p->flags & TERMP_LITERAL))
1278: flushln(p);
1279:
1280: p->flags &= ~TERMP_LITERAL;
1.20 kristaps 1281: p->offset = pair->offset;
1.12 kristaps 1282: }
1283:
1284:
1285: /* ARGSUSED */
1.10 kristaps 1286: static int
1287: termp_qq_pre(DECL_ARGS)
1288: {
1.1 kristaps 1289:
1.10 kristaps 1290: if (MDOC_BODY != node->type)
1291: return(1);
1292: word(p, "\"");
1293: p->flags |= TERMP_NOSPACE;
1294: return(1);
1.1 kristaps 1295: }
1296:
1297:
1.10 kristaps 1298: /* ARGSUSED */
1.1 kristaps 1299: static void
1.10 kristaps 1300: termp_qq_post(DECL_ARGS)
1.1 kristaps 1301: {
1302:
1.10 kristaps 1303: if (MDOC_BODY != node->type)
1304: return;
1305: p->flags |= TERMP_NOSPACE;
1306: word(p, "\"");
1307: }
1308:
1309:
1310: /* ARGSUSED */
1311: static int
1.15 kristaps 1312: termp_bsx_pre(DECL_ARGS)
1313: {
1314:
1315: word(p, "BSDI BSD/OS");
1316: return(1);
1317: }
1318:
1319:
1320: /* ARGSUSED */
1.31 kristaps 1321: static void
1322: termp_bx_post(DECL_ARGS)
1.10 kristaps 1323: {
1.1 kristaps 1324:
1.34 kristaps 1325: if (node->child)
1326: p->flags |= TERMP_NOSPACE;
1.10 kristaps 1327: word(p, "BSD");
1328: }
1329:
1330:
1331: /* ARGSUSED */
1332: static int
1333: termp_ox_pre(DECL_ARGS)
1334: {
1335:
1336: word(p, "OpenBSD");
1337: return(1);
1338: }
1339:
1340:
1341: /* ARGSUSED */
1342: static int
1.16 kristaps 1343: termp_ux_pre(DECL_ARGS)
1344: {
1345:
1346: word(p, "UNIX");
1347: return(1);
1348: }
1349:
1350:
1351: /* ARGSUSED */
1352: static int
1353: termp_fx_pre(DECL_ARGS)
1354: {
1355:
1356: word(p, "FreeBSD");
1357: return(1);
1358: }
1359:
1360:
1361: /* ARGSUSED */
1362: static int
1.10 kristaps 1363: termp_nx_pre(DECL_ARGS)
1364: {
1365:
1366: word(p, "NetBSD");
1367: return(1);
1368: }
1369:
1370:
1371: /* ARGSUSED */
1372: static int
1373: termp_sq_pre(DECL_ARGS)
1374: {
1375:
1376: if (MDOC_BODY != node->type)
1377: return(1);
1.28 kristaps 1378: word(p, "`");
1.10 kristaps 1379: p->flags |= TERMP_NOSPACE;
1380: return(1);
1381: }
1.1 kristaps 1382:
1383:
1.10 kristaps 1384: /* ARGSUSED */
1385: static void
1386: termp_sq_post(DECL_ARGS)
1387: {
1388:
1389: if (MDOC_BODY != node->type)
1390: return;
1391: p->flags |= TERMP_NOSPACE;
1392: word(p, "\'");
1393: }
1.2 kristaps 1394:
1395:
1.10 kristaps 1396: /* ARGSUSED */
1397: static int
1398: termp_pf_pre(DECL_ARGS)
1399: {
1.1 kristaps 1400:
1.10 kristaps 1401: p->flags |= TERMP_IGNDELIM;
1402: return(1);
1403: }
1.1 kristaps 1404:
1405:
1.10 kristaps 1406: /* ARGSUSED */
1407: static void
1408: termp_pf_post(DECL_ARGS)
1409: {
1.1 kristaps 1410:
1.10 kristaps 1411: p->flags &= ~TERMP_IGNDELIM;
1412: p->flags |= TERMP_NOSPACE;
1413: }
1.1 kristaps 1414:
1415:
1.10 kristaps 1416: /* ARGSUSED */
1417: static int
1418: termp_ss_pre(DECL_ARGS)
1419: {
1.1 kristaps 1420:
1.10 kristaps 1421: switch (node->type) {
1422: case (MDOC_HEAD):
1423: vspace(p);
1.31 kristaps 1424: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_SSECTION]);
1.10 kristaps 1425: p->offset = INDENT / 2;
1426: break;
1427: default:
1428: break;
1429: }
1.1 kristaps 1430:
1.10 kristaps 1431: return(1);
1.1 kristaps 1432: }
1433:
1434:
1.10 kristaps 1435: /* ARGSUSED */
1436: static void
1437: termp_ss_post(DECL_ARGS)
1.1 kristaps 1438: {
1439:
1.10 kristaps 1440: switch (node->type) {
1441: case (MDOC_HEAD):
1442: newln(p);
1443: p->offset = INDENT;
1444: break;
1445: default:
1446: break;
1447: }
1448: }
1.2 kristaps 1449:
1450:
1.10 kristaps 1451: /* ARGSUSED */
1452: static int
1453: termp_pa_pre(DECL_ARGS)
1454: {
1.2 kristaps 1455:
1.31 kristaps 1456: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_FILE]);
1.10 kristaps 1457: return(1);
1.1 kristaps 1458: }
1459:
1460:
1.10 kristaps 1461: /* ARGSUSED */
1.11 kristaps 1462: static int
1463: termp_em_pre(DECL_ARGS)
1464: {
1465:
1.31 kristaps 1466: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_EMPH]);
1.11 kristaps 1467: return(1);
1468: }
1469:
1470:
1471: /* ARGSUSED */
1.14 kristaps 1472: static int
1473: termp_cd_pre(DECL_ARGS)
1474: {
1475:
1.31 kristaps 1476: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_CONFIG]);
1.33 kristaps 1477: newln(p);
1.14 kristaps 1478: return(1);
1479: }
1480:
1481:
1482: /* ARGSUSED */
1483: static int
1484: termp_cm_pre(DECL_ARGS)
1485: {
1486:
1.31 kristaps 1487: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_CMD_FLAG]);
1.14 kristaps 1488: return(1);
1489: }
1490:
1491:
1492: /* ARGSUSED */
1493: static int
1494: termp_ic_pre(DECL_ARGS)
1495: {
1496:
1.31 kristaps 1497: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_CMD]);
1.14 kristaps 1498: return(1);
1499: }
1500:
1501:
1502: /* ARGSUSED */
1503: static int
1504: termp_in_pre(DECL_ARGS)
1505: {
1506:
1.31 kristaps 1507: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_INCLUDE]);
1.30 kristaps 1508: word(p, "#include");
1509: word(p, "<");
1510: p->flags |= TERMP_NOSPACE;
1.14 kristaps 1511: return(1);
1512: }
1513:
1514:
1515: /* ARGSUSED */
1.30 kristaps 1516: static void
1517: termp_in_post(DECL_ARGS)
1518: {
1519:
1520: p->flags |= TERMP_NOSPACE;
1521: word(p, ">");
1522:
1523: newln(p);
1524: if (SEC_SYNOPSIS != node->sec)
1525: return;
1526: if (node->next && MDOC_In != node->next->tok)
1527: vspace(p);
1528: }
1529:
1530:
1531: /* ARGSUSED */
1.14 kristaps 1532: static int
1533: termp_at_pre(DECL_ARGS)
1534: {
1.43 kristaps 1535: const char *att;
1536:
1537: att = NULL;
1.14 kristaps 1538:
1539: if (node->child) {
1.44 kristaps 1540: if (MDOC_TEXT != node->child->type)
1541: errx(1, "expected text line argument");
1542: att = mdoc_a2att(node->child->string);
1.14 kristaps 1543: }
1544:
1.43 kristaps 1545: if (NULL == att)
1546: att = "AT&T UNIX";
1547:
1548: word(p, att);
1.14 kristaps 1549: return(0);
1550: }
1.15 kristaps 1551:
1552:
1553: /* ARGSUSED */
1554: static int
1555: termp_bq_pre(DECL_ARGS)
1556: {
1557:
1558: if (MDOC_BODY != node->type)
1559: return(1);
1.30 kristaps 1560: word(p, "[");
1.15 kristaps 1561: p->flags |= TERMP_NOSPACE;
1562: return(1);
1563: }
1564:
1565:
1566: /* ARGSUSED */
1567: static void
1568: termp_bq_post(DECL_ARGS)
1569: {
1570:
1571: if (MDOC_BODY != node->type)
1572: return;
1573: word(p, "]");
1574: }
1575:
1576:
1577: /* ARGSUSED */
1578: static int
1579: termp_pq_pre(DECL_ARGS)
1580: {
1581:
1582: if (MDOC_BODY != node->type)
1583: return(1);
1.31 kristaps 1584: word(p, "\\&(");
1.15 kristaps 1585: p->flags |= TERMP_NOSPACE;
1586: return(1);
1587: }
1588:
1589:
1590: /* ARGSUSED */
1591: static void
1592: termp_pq_post(DECL_ARGS)
1593: {
1594:
1595: if (MDOC_BODY != node->type)
1596: return;
1597: word(p, ")");
1598: }
1599:
1600:
1.16 kristaps 1601: /* ARGSUSED */
1602: static int
1603: termp_fo_pre(DECL_ARGS)
1604: {
1605: const struct mdoc_node *n;
1606:
1607: if (MDOC_BODY == node->type) {
1608: word(p, "(");
1609: p->flags |= TERMP_NOSPACE;
1610: return(1);
1611: } else if (MDOC_HEAD != node->type)
1612: return(1);
1613:
1.17 kristaps 1614: /* XXX - groff shows only first parameter */
1615:
1.16 kristaps 1616: p->flags |= ttypes[TTYPE_FUNC_NAME];
1617: for (n = node->child; n; n = n->next) {
1.44 kristaps 1618: if (MDOC_TEXT != n->type)
1619: errx(1, "expected text line argument");
1620: word(p, n->string);
1.16 kristaps 1621: }
1622: p->flags &= ~ttypes[TTYPE_FUNC_NAME];
1623:
1624: return(0);
1625: }
1626:
1627:
1628: /* ARGSUSED */
1629: static void
1630: termp_fo_post(DECL_ARGS)
1631: {
1632:
1633: if (MDOC_BODY != node->type)
1634: return;
1635: word(p, ")");
1636: word(p, ";");
1637: newln(p);
1638: }
1639:
1640:
1.17 kristaps 1641: /* ARGSUSED */
1642: static int
1643: termp_bf_pre(DECL_ARGS)
1644: {
1645: const struct mdoc_node *n;
1646:
1.44 kristaps 1647: if (MDOC_HEAD == node->type) {
1.17 kristaps 1648: return(0);
1.44 kristaps 1649: } else if (MDOC_BLOCK != node->type)
1.17 kristaps 1650: return(1);
1651:
1.44 kristaps 1652: if (NULL == (n = node->head->child)) {
1653: if (arg_hasattr(MDOC_Emphasis, node))
1.31 kristaps 1654: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_EMPH]);
1.44 kristaps 1655: else if (arg_hasattr(MDOC_Symbolic, node))
1.31 kristaps 1656: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_SYMB]);
1.17 kristaps 1657:
1658: return(1);
1659: }
1660:
1.44 kristaps 1661: if (MDOC_TEXT != n->type)
1662: errx(1, "expected text line arguments");
1.17 kristaps 1663:
1.44 kristaps 1664: if (0 == strcmp("Em", n->string))
1.31 kristaps 1665: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_EMPH]);
1.44 kristaps 1666: else if (0 == strcmp("Sy", n->string))
1.31 kristaps 1667: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_EMPH]);
1.17 kristaps 1668:
1669: return(1);
1670: }
1671:
1672:
1673: /* ARGSUSED */
1674: static int
1675: termp_sy_pre(DECL_ARGS)
1676: {
1677:
1.31 kristaps 1678: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_SYMB]);
1.17 kristaps 1679: return(1);
1680: }
1681:
1682:
1683: /* ARGSUSED */
1684: static int
1685: termp_ms_pre(DECL_ARGS)
1686: {
1687:
1.31 kristaps 1688: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_SYMBOL]);
1.17 kristaps 1689: return(1);
1690: }
1691:
1.22 kristaps 1692:
1693:
1694: /* ARGSUSED */
1695: static int
1696: termp_sm_pre(DECL_ARGS)
1697: {
1698:
1699: #if notyet
1700: assert(node->child);
1701: if (0 == strcmp("off", node->child->data.text.string)) {
1702: p->flags &= ~TERMP_NONOSPACE;
1703: p->flags &= ~TERMP_NOSPACE;
1704: } else {
1705: p->flags |= TERMP_NONOSPACE;
1706: p->flags |= TERMP_NOSPACE;
1707: }
1708: #endif
1709:
1710: return(0);
1711: }
1.28 kristaps 1712:
1713:
1714: /* ARGSUSED */
1715: static int
1.48 kristaps 1716: termp_ap_pre(DECL_ARGS)
1717: {
1718:
1719: p->flags |= TERMP_NOSPACE;
1720: word(p, "\\(aq");
1721: p->flags |= TERMP_NOSPACE;
1722: return(1);
1723: }
1724:
1725:
1726: /* ARGSUSED */
1727: static int
1.28 kristaps 1728: termp__t_pre(DECL_ARGS)
1729: {
1730:
1.41 kristaps 1731: /* FIXME: titles are underlined. */
1.28 kristaps 1732: word(p, "\"");
1733: p->flags |= TERMP_NOSPACE;
1734: return(1);
1735: }
1736:
1737:
1738: /* ARGSUSED */
1739: static void
1740: termp__t_post(DECL_ARGS)
1741: {
1742:
1743: p->flags |= TERMP_NOSPACE;
1.41 kristaps 1744: /* FIXME: titles are underlined. */
1.28 kristaps 1745: word(p, "\"");
1746: word(p, node->next ? "," : ".");
1747: }
1748:
1749:
1750: /* ARGSUSED */
1751: static void
1752: termp____post(DECL_ARGS)
1753: {
1754:
1755: p->flags |= TERMP_NOSPACE;
1756: word(p, node->next ? "," : ".");
1757: }
1.51 ! kristaps 1758:
! 1759:
! 1760: /* ARGSUSED */
! 1761: static int
! 1762: termp_lk_pre(DECL_ARGS)
! 1763: {
! 1764: const struct mdoc_node *n;
! 1765:
! 1766: if (NULL == (n = node->child))
! 1767: errx(1, "expected text line argument");
! 1768: if (MDOC_TEXT != n->type)
! 1769: errx(1, "expected text line argument");
! 1770:
! 1771: p->flags |= ttypes[TTYPE_LINK_ANCHOR];
! 1772: word(p, n->string);
! 1773: p->flags &= ~ttypes[TTYPE_LINK_ANCHOR];
! 1774: p->flags |= TERMP_NOSPACE;
! 1775: word(p, ":");
! 1776:
! 1777: p->flags |= ttypes[TTYPE_LINK_TEXT];
! 1778: for ( ; n; n = n->next) {
! 1779: if (MDOC_TEXT != n->type)
! 1780: errx(1, "expected text line argument");
! 1781: word(p, n->string);
! 1782: }
! 1783: p->flags &= ~ttypes[TTYPE_LINK_TEXT];
! 1784:
! 1785: return(0);
! 1786: }
! 1787:
! 1788:
! 1789: /* ARGSUSED */
! 1790: static int
! 1791: termp_mt_pre(DECL_ARGS)
! 1792: {
! 1793:
! 1794: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_LINK_ANCHOR]);
! 1795: return(1);
! 1796: }
! 1797:
CVSweb