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