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