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