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