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