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