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