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