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