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