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