Annotation of mandoc/mdoc_action.c, Revision 1.1
1.1 ! kristaps 1: /* $Id: action.c,v 1.51 2009/03/23 14:31:58 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/utsname.h>
! 20:
! 21: #include <assert.h>
! 22: #include <err.h>
! 23: #include <errno.h>
! 24: #include <stdio.h>
! 25: #include <stdlib.h>
! 26: #include <string.h>
! 27:
! 28: #include "libmdoc.h"
! 29:
! 30: /*
! 31: * Actions are executed on macros after they've been post-validated: in
! 32: * other words, a macro will not be "acted upon" until all of its
! 33: * children have been filled in (post-fix order).
! 34: */
! 35:
! 36: enum mwarn {
! 37: WBADSEC,
! 38: WNOWIDTH,
! 39: WBADDATE
! 40: };
! 41:
! 42: #define PRE_ARGS struct mdoc *m, const struct mdoc_node *n
! 43: #define POST_ARGS struct mdoc *m
! 44:
! 45: struct actions {
! 46: int (*pre)(PRE_ARGS);
! 47: int (*post)(POST_ARGS);
! 48: };
! 49:
! 50: static int pwarn(struct mdoc *, int, int, enum mwarn);
! 51:
! 52: static int post_ar(POST_ARGS);
! 53: static int post_bl(POST_ARGS);
! 54: static int post_bl_width(POST_ARGS);
! 55: static int post_bl_tagwidth(POST_ARGS);
! 56: static int post_dd(POST_ARGS);
! 57: static int post_display(POST_ARGS);
! 58: static int post_dt(POST_ARGS);
! 59: static int post_nm(POST_ARGS);
! 60: static int post_os(POST_ARGS);
! 61: static int post_prol(POST_ARGS);
! 62: static int post_sh(POST_ARGS);
! 63: static int post_std(POST_ARGS);
! 64:
! 65: static int pre_bd(PRE_ARGS);
! 66: static int pre_dl(PRE_ARGS);
! 67:
! 68: #define mwarn(m, t) pwarn((m), (m)->last->line, (m)->last->pos, (t))
! 69:
! 70: const struct actions mdoc_actions[MDOC_MAX] = {
! 71: { NULL, NULL }, /* \" */
! 72: { NULL, post_dd }, /* Dd */
! 73: { NULL, post_dt }, /* Dt */
! 74: { NULL, post_os }, /* Os */
! 75: { NULL, post_sh }, /* Sh */
! 76: { NULL, NULL }, /* Ss */
! 77: { NULL, NULL }, /* Pp */
! 78: { NULL, NULL }, /* D1 */
! 79: { pre_dl, post_display }, /* Dl */
! 80: { pre_bd, post_display }, /* Bd */
! 81: { NULL, NULL }, /* Ed */
! 82: { NULL, post_bl }, /* Bl */
! 83: { NULL, NULL }, /* El */
! 84: { NULL, NULL }, /* It */
! 85: { NULL, NULL }, /* Ad */
! 86: { NULL, NULL }, /* An */
! 87: { NULL, post_ar }, /* Ar */
! 88: { NULL, NULL }, /* Cd */
! 89: { NULL, NULL }, /* Cm */
! 90: { NULL, NULL }, /* Dv */
! 91: { NULL, NULL }, /* Er */
! 92: { NULL, NULL }, /* Ev */
! 93: { NULL, post_std }, /* Ex */
! 94: { NULL, NULL }, /* Fa */
! 95: { NULL, NULL }, /* Fd */
! 96: { NULL, NULL }, /* Fl */
! 97: { NULL, NULL }, /* Fn */
! 98: { NULL, NULL }, /* Ft */
! 99: { NULL, NULL }, /* Ic */
! 100: { NULL, NULL }, /* In */
! 101: { NULL, NULL }, /* Li */
! 102: { NULL, NULL }, /* Nd */
! 103: { NULL, post_nm }, /* Nm */
! 104: { NULL, NULL }, /* Op */
! 105: { NULL, NULL }, /* Ot */
! 106: { NULL, NULL }, /* Pa */
! 107: { NULL, post_std }, /* Rv */
! 108: { NULL, NULL }, /* St */
! 109: { NULL, NULL }, /* Va */
! 110: { NULL, NULL }, /* Vt */
! 111: { NULL, NULL }, /* Xr */
! 112: { NULL, NULL }, /* %A */
! 113: { NULL, NULL }, /* %B */
! 114: { NULL, NULL }, /* %D */
! 115: { NULL, NULL }, /* %I */
! 116: { NULL, NULL }, /* %J */
! 117: { NULL, NULL }, /* %N */
! 118: { NULL, NULL }, /* %O */
! 119: { NULL, NULL }, /* %P */
! 120: { NULL, NULL }, /* %R */
! 121: { NULL, NULL }, /* %T */
! 122: { NULL, NULL }, /* %V */
! 123: { NULL, NULL }, /* Ac */
! 124: { NULL, NULL }, /* Ao */
! 125: { NULL, NULL }, /* Aq */
! 126: { NULL, NULL }, /* At */
! 127: { NULL, NULL }, /* Bc */
! 128: { NULL, NULL }, /* Bf */
! 129: { NULL, NULL }, /* Bo */
! 130: { NULL, NULL }, /* Bq */
! 131: { NULL, NULL }, /* Bsx */
! 132: { NULL, NULL }, /* Bx */
! 133: { NULL, NULL }, /* Db */
! 134: { NULL, NULL }, /* Dc */
! 135: { NULL, NULL }, /* Do */
! 136: { NULL, NULL }, /* Dq */
! 137: { NULL, NULL }, /* Ec */
! 138: { NULL, NULL }, /* Ef */
! 139: { NULL, NULL }, /* Em */
! 140: { NULL, NULL }, /* Eo */
! 141: { NULL, NULL }, /* Fx */
! 142: { NULL, NULL }, /* Ms */
! 143: { NULL, NULL }, /* No */
! 144: { NULL, NULL }, /* Ns */
! 145: { NULL, NULL }, /* Nx */
! 146: { NULL, NULL }, /* Ox */
! 147: { NULL, NULL }, /* Pc */
! 148: { NULL, NULL }, /* Pf */
! 149: { NULL, NULL }, /* Po */
! 150: { NULL, NULL }, /* Pq */
! 151: { NULL, NULL }, /* Qc */
! 152: { NULL, NULL }, /* Ql */
! 153: { NULL, NULL }, /* Qo */
! 154: { NULL, NULL }, /* Qq */
! 155: { NULL, NULL }, /* Re */
! 156: { NULL, NULL }, /* Rs */
! 157: { NULL, NULL }, /* Sc */
! 158: { NULL, NULL }, /* So */
! 159: { NULL, NULL }, /* Sq */
! 160: { NULL, NULL }, /* Sm */
! 161: { NULL, NULL }, /* Sx */
! 162: { NULL, NULL }, /* Sy */
! 163: { NULL, NULL }, /* Tn */
! 164: { NULL, NULL }, /* Ux */
! 165: { NULL, NULL }, /* Xc */
! 166: { NULL, NULL }, /* Xo */
! 167: { NULL, NULL }, /* Fo */
! 168: { NULL, NULL }, /* Fc */
! 169: { NULL, NULL }, /* Oo */
! 170: { NULL, NULL }, /* Oc */
! 171: { NULL, NULL }, /* Bk */
! 172: { NULL, NULL }, /* Ek */
! 173: { NULL, NULL }, /* Bt */
! 174: { NULL, NULL }, /* Hf */
! 175: { NULL, NULL }, /* Fr */
! 176: { NULL, NULL }, /* Ud */
! 177: { NULL, NULL }, /* Lb */
! 178: { NULL, NULL }, /* Ap */
! 179: { NULL, NULL }, /* Lp */
! 180: { NULL, NULL }, /* Lk */
! 181: { NULL, NULL }, /* Mt */
! 182: { NULL, NULL }, /* Brq */
! 183: { NULL, NULL }, /* Bro */
! 184: { NULL, NULL }, /* Brc */
! 185: { NULL, NULL }, /* %C */
! 186: { NULL, NULL }, /* Es */
! 187: { NULL, NULL }, /* En */
! 188: { NULL, NULL }, /* Dx */
! 189: { NULL, NULL }, /* %Q */
! 190: };
! 191:
! 192:
! 193: int
! 194: mdoc_action_pre(struct mdoc *m, const struct mdoc_node *n)
! 195: {
! 196:
! 197: switch (n->type) {
! 198: case (MDOC_ROOT):
! 199: break;
! 200: case (MDOC_TEXT):
! 201: break;
! 202: default:
! 203: if (NULL == mdoc_actions[m->last->tok].pre)
! 204: break;
! 205: return((*mdoc_actions[m->last->tok].pre)(m, n));
! 206: }
! 207: return(1);
! 208: }
! 209:
! 210:
! 211: int
! 212: mdoc_action_post(struct mdoc *m)
! 213: {
! 214:
! 215: if (MDOC_ACTED & m->last->flags)
! 216: return(1);
! 217: m->last->flags |= MDOC_ACTED;
! 218:
! 219: switch (m->last->type) {
! 220: case (MDOC_TEXT):
! 221: break;
! 222: case (MDOC_ROOT):
! 223: break;
! 224: default:
! 225: if (NULL == mdoc_actions[m->last->tok].post)
! 226: break;
! 227: return((*mdoc_actions[m->last->tok].post)(m));
! 228: }
! 229: return(1);
! 230: }
! 231:
! 232:
! 233: static int
! 234: pwarn(struct mdoc *m, int line, int pos, enum mwarn type)
! 235: {
! 236: char *p;
! 237: int c;
! 238:
! 239: p = NULL;
! 240: c = WARN_SYNTAX;
! 241:
! 242: switch (type) {
! 243: case (WBADSEC):
! 244: p = "inappropriate document section in manual section";
! 245: c = WARN_COMPAT;
! 246: break;
! 247: case (WNOWIDTH):
! 248: p = "cannot determine default width";
! 249: break;
! 250: case (WBADDATE):
! 251: p = "malformed date syntax";
! 252: break;
! 253: }
! 254:
! 255: assert(p);
! 256: return(mdoc_pwarn(m, line, pos, c, p));
! 257: }
! 258:
! 259:
! 260: static int
! 261: post_std(POST_ARGS)
! 262: {
! 263:
! 264: /*
! 265: * If '-std' is invoked without an argument, fill it in with our
! 266: * name (if it's been set).
! 267: */
! 268:
! 269: if (NULL == m->last->args)
! 270: return(1);
! 271: if (m->last->args->argv[0].sz)
! 272: return(1);
! 273:
! 274: assert(m->meta.name);
! 275:
! 276: m->last->args->argv[0].value = calloc(1, sizeof(char *));
! 277: if (NULL == m->last->args->argv[0].value)
! 278: err(1, "calloc");
! 279:
! 280: m->last->args->argv[0].sz = 1;
! 281: m->last->args->argv[0].value[0] = xstrdup(m->meta.name);
! 282: return(1);
! 283: }
! 284:
! 285:
! 286: static int
! 287: post_nm(POST_ARGS)
! 288: {
! 289: char buf[64];
! 290:
! 291: if (m->meta.name)
! 292: return(1);
! 293:
! 294: (void)xstrlcpys(buf, m->last->child, sizeof(buf));
! 295: m->meta.name = xstrdup(buf);
! 296:
! 297: return(1);
! 298: }
! 299:
! 300:
! 301: static int
! 302: post_sh(POST_ARGS)
! 303: {
! 304: enum mdoc_sec sec;
! 305: char buf[64];
! 306:
! 307: /*
! 308: * We keep track of the current section /and/ the "named"
! 309: * section, which is one of the conventional ones, in order to
! 310: * check ordering.
! 311: */
! 312:
! 313: if (MDOC_HEAD != m->last->type)
! 314: return(1);
! 315:
! 316: (void)xstrlcpys(buf, m->last->child, sizeof(buf));
! 317: if (SEC_CUSTOM != (sec = mdoc_atosec(buf)))
! 318: m->lastnamed = sec;
! 319:
! 320: switch ((m->lastsec = sec)) {
! 321: case (SEC_RETURN_VALUES):
! 322: /* FALLTHROUGH */
! 323: case (SEC_ERRORS):
! 324: switch (m->meta.msec) {
! 325: case (2):
! 326: /* FALLTHROUGH */
! 327: case (3):
! 328: /* FALLTHROUGH */
! 329: case (9):
! 330: break;
! 331: default:
! 332: return(mwarn(m, WBADSEC));
! 333: }
! 334: break;
! 335: default:
! 336: break;
! 337: }
! 338: return(1);
! 339: }
! 340:
! 341:
! 342: static int
! 343: post_dt(POST_ARGS)
! 344: {
! 345: struct mdoc_node *n;
! 346: const char *cp;
! 347: char *ep;
! 348: long lval;
! 349:
! 350: if (m->meta.title)
! 351: free(m->meta.title);
! 352: if (m->meta.vol)
! 353: free(m->meta.vol);
! 354: if (m->meta.arch)
! 355: free(m->meta.arch);
! 356:
! 357: m->meta.title = m->meta.vol = m->meta.arch = NULL;
! 358: m->meta.msec = 0;
! 359:
! 360: /* Handles: `.Dt'
! 361: * --> title = unknown, volume = local, msec = 0, arch = NULL
! 362: */
! 363:
! 364: if (NULL == (n = m->last->child)) {
! 365: m->meta.title = xstrdup("unknown");
! 366: m->meta.vol = xstrdup("local");
! 367: return(post_prol(m));
! 368: }
! 369:
! 370: /* Handles: `.Dt TITLE'
! 371: * --> title = TITLE, volume = local, msec = 0, arch = NULL
! 372: */
! 373:
! 374: m->meta.title = xstrdup(n->string);
! 375:
! 376: if (NULL == (n = n->next)) {
! 377: m->meta.vol = xstrdup("local");
! 378: return(post_prol(m));
! 379: }
! 380:
! 381: /* Handles: `.Dt TITLE SEC'
! 382: * --> title = TITLE, volume = SEC is msec ?
! 383: * format(msec) : SEC,
! 384: * msec = SEC is msec ? atoi(msec) : 0,
! 385: * arch = NULL
! 386: */
! 387:
! 388: cp = mdoc_a2msec(n->string);
! 389: if (cp) {
! 390: m->meta.vol = xstrdup(cp);
! 391: errno = 0;
! 392: lval = strtol(n->string, &ep, 10);
! 393: if (n->string[0] != '\0' && *ep == '\0')
! 394: m->meta.msec = (int)lval;
! 395: } else
! 396: m->meta.vol = xstrdup(n->string);
! 397:
! 398: if (NULL == (n = n->next))
! 399: return(post_prol(m));
! 400:
! 401: /* Handles: `.Dt TITLE SEC VOL'
! 402: * --> title = TITLE, volume = VOL is vol ?
! 403: * format(VOL) :
! 404: * VOL is arch ? format(arch) :
! 405: * VOL
! 406: */
! 407:
! 408: cp = mdoc_a2vol(n->string);
! 409: if (cp) {
! 410: free(m->meta.vol);
! 411: m->meta.vol = xstrdup(cp);
! 412: n = n->next;
! 413: } else {
! 414: cp = mdoc_a2arch(n->string);
! 415: if (NULL == cp) {
! 416: free(m->meta.vol);
! 417: m->meta.vol = xstrdup(n->string);
! 418: } else
! 419: m->meta.arch = xstrdup(cp);
! 420: }
! 421:
! 422: /* Ignore any subsequent parameters... */
! 423:
! 424: return(post_prol(m));
! 425: }
! 426:
! 427:
! 428: static int
! 429: post_os(POST_ARGS)
! 430: {
! 431: char buf[64];
! 432: struct utsname utsname;
! 433:
! 434: if (m->meta.os)
! 435: free(m->meta.os);
! 436:
! 437: (void)xstrlcpys(buf, m->last->child, sizeof(buf));
! 438:
! 439: if (0 == buf[0]) {
! 440: if (-1 == uname(&utsname))
! 441: return(mdoc_err(m, "utsname"));
! 442: (void)xstrlcpy(buf, utsname.sysname, sizeof(buf));
! 443: (void)xstrlcat(buf, " ", sizeof(buf));
! 444: (void)xstrlcat(buf, utsname.release, sizeof(buf));
! 445: }
! 446:
! 447: m->meta.os = xstrdup(buf);
! 448: m->lastnamed = m->lastsec = SEC_BODY;
! 449:
! 450: return(post_prol(m));
! 451: }
! 452:
! 453:
! 454: /*
! 455: * Calculate the -width for a `Bl -tag' list if it hasn't been provided.
! 456: * Uses the first head macro.
! 457: */
! 458: static int
! 459: post_bl_tagwidth(struct mdoc *m)
! 460: {
! 461: struct mdoc_node *n;
! 462: int sz;
! 463: char buf[32];
! 464:
! 465: /*
! 466: * Use the text width, if a text node, or the default macro
! 467: * width if a macro.
! 468: */
! 469:
! 470: if ((n = m->last->body->child)) {
! 471: assert(MDOC_BLOCK == n->type);
! 472: assert(MDOC_It == n->tok);
! 473: n = n->head->child;
! 474: }
! 475:
! 476: sz = 10; /* Default size. */
! 477:
! 478: if (n) {
! 479: if (MDOC_TEXT != n->type) {
! 480: if (0 == (sz = (int)mdoc_macro2len(n->tok)))
! 481: if ( ! mwarn(m, WNOWIDTH))
! 482: return(0);
! 483: } else
! 484: sz = (int)strlen(n->string) + 1;
! 485: }
! 486:
! 487: (void)snprintf(buf, sizeof(buf), "%dn", sz);
! 488:
! 489: /*
! 490: * We have to dynamically add this to the macro's argument list.
! 491: * We're guaranteed that a MDOC_Width doesn't already exist.
! 492: */
! 493:
! 494: n = m->last;
! 495: assert(n->args);
! 496:
! 497: sz = (int)(n->args->argc)++;
! 498: n->args->argv = xrealloc(n->args->argv,
! 499: n->args->argc * sizeof(struct mdoc_argv));
! 500:
! 501: n->args->argv[sz].arg = MDOC_Width;
! 502: n->args->argv[sz].line = m->last->line;
! 503: n->args->argv[sz].pos = m->last->pos;
! 504: n->args->argv[sz].sz = 1;
! 505: n->args->argv[sz].value = calloc(1, sizeof(char *));
! 506: if (NULL == n->args->argv[sz].value)
! 507: err(1, "calloc");
! 508: n->args->argv[sz].value[0] = xstrdup(buf);
! 509:
! 510: return(1);
! 511: }
! 512:
! 513:
! 514: static int
! 515: post_bl_width(struct mdoc *m)
! 516: {
! 517: size_t width;
! 518: int i, tok;
! 519: char buf[32];
! 520: char *p;
! 521:
! 522: if (NULL == m->last->args)
! 523: return(1);
! 524:
! 525: for (i = 0; i < (int)m->last->args->argc; i++)
! 526: if (MDOC_Width == m->last->args->argv[i].arg)
! 527: break;
! 528:
! 529: if (i == (int)m->last->args->argc)
! 530: return(1);
! 531:
! 532: p = m->last->args->argv[i].value[0];
! 533:
! 534: /*
! 535: * If the value to -width is a macro, then we re-write it to be
! 536: * the macro's width as set in share/tmac/mdoc/doc-common.
! 537: */
! 538:
! 539: if (xstrcmp(p, "Ds"))
! 540: width = 8;
! 541: else if (MDOC_MAX == (tok = mdoc_tokhash_find(m->htab, p)))
! 542: return(1);
! 543: else if (0 == (width = mdoc_macro2len(tok)))
! 544: return(mwarn(m, WNOWIDTH));
! 545:
! 546: /* The value already exists: free and reallocate it. */
! 547:
! 548: (void)snprintf(buf, sizeof(buf), "%zun", width);
! 549:
! 550: free(m->last->args->argv[i].value[0]);
! 551: m->last->args->argv[i].value[0] = xstrdup(buf);
! 552:
! 553: return(1);
! 554: }
! 555:
! 556:
! 557: static int
! 558: post_bl(POST_ARGS)
! 559: {
! 560: int i, r, len;
! 561:
! 562: if (MDOC_BLOCK != m->last->type)
! 563: return(1);
! 564:
! 565: /*
! 566: * These are fairly complicated, so we've broken them into two
! 567: * functions. post_bl_tagwidth() is called when a -tag is
! 568: * specified, but no -width (it must be guessed). The second
! 569: * when a -width is specified (macro indicators must be
! 570: * rewritten into real lengths).
! 571: */
! 572:
! 573: len = (int)(m->last->args ? m->last->args->argc : 0);
! 574:
! 575: for (r = i = 0; i < len; i++) {
! 576: if (MDOC_Tag == m->last->args->argv[i].arg)
! 577: r |= 1 << 0;
! 578: if (MDOC_Width == m->last->args->argv[i].arg)
! 579: r |= 1 << 1;
! 580: }
! 581:
! 582: if (r & (1 << 0) && ! (r & (1 << 1))) {
! 583: if ( ! post_bl_tagwidth(m))
! 584: return(0);
! 585: } else if (r & (1 << 1))
! 586: if ( ! post_bl_width(m))
! 587: return(0);
! 588:
! 589: return(1);
! 590: }
! 591:
! 592:
! 593: static int
! 594: post_ar(POST_ARGS)
! 595: {
! 596: struct mdoc_node *n;
! 597:
! 598: if (m->last->child)
! 599: return(1);
! 600:
! 601: n = m->last;
! 602: m->next = MDOC_NEXT_CHILD;
! 603: if ( ! mdoc_word_alloc(m, m->last->line,
! 604: m->last->pos, "file"))
! 605: return(0);
! 606: m->next = MDOC_NEXT_SIBLING;
! 607: if ( ! mdoc_word_alloc(m, m->last->line,
! 608: m->last->pos, "..."))
! 609: return(0);
! 610:
! 611: m->last = n;
! 612: m->next = MDOC_NEXT_SIBLING;
! 613: return(1);
! 614: }
! 615:
! 616:
! 617: static int
! 618: post_dd(POST_ARGS)
! 619: {
! 620: char buf[64];
! 621:
! 622: (void)xstrlcpys(buf, m->last->child, sizeof(buf));
! 623:
! 624: if (0 == (m->meta.date = mdoc_atotime(buf))) {
! 625: if ( ! mwarn(m, WBADDATE))
! 626: return(0);
! 627: m->meta.date = time(NULL);
! 628: }
! 629:
! 630: return(post_prol(m));
! 631: }
! 632:
! 633:
! 634: static int
! 635: post_prol(POST_ARGS)
! 636: {
! 637: struct mdoc_node *n;
! 638:
! 639: /*
! 640: * The end document shouldn't have the prologue macros as part
! 641: * of the syntax tree (they encompass only meta-data).
! 642: */
! 643:
! 644: if (m->last->parent->child == m->last)
! 645: m->last->parent->child = m->last->prev;
! 646: if (m->last->prev)
! 647: m->last->prev->next = NULL;
! 648:
! 649: n = m->last;
! 650: assert(NULL == m->last->next);
! 651:
! 652: if (m->last->prev) {
! 653: m->last = m->last->prev;
! 654: m->next = MDOC_NEXT_SIBLING;
! 655: } else {
! 656: m->last = m->last->parent;
! 657: m->next = MDOC_NEXT_CHILD;
! 658: }
! 659:
! 660: mdoc_node_freelist(n);
! 661: return(1);
! 662: }
! 663:
! 664:
! 665: static int
! 666: pre_dl(PRE_ARGS)
! 667: {
! 668:
! 669: if (MDOC_BODY != n->type)
! 670: return(1);
! 671: m->flags |= MDOC_LITERAL;
! 672: return(1);
! 673: }
! 674:
! 675:
! 676: static int
! 677: pre_bd(PRE_ARGS)
! 678: {
! 679: int i;
! 680:
! 681: if (MDOC_BODY != n->type)
! 682: return(1);
! 683:
! 684: /*
! 685: * We ONLY enter a literal context if `Bd -literal' or `Bd
! 686: * -unfilled'.
! 687: */
! 688:
! 689: n = n->parent;
! 690:
! 691: for (i = 0; i < (int)n->args->argc; i++)
! 692: if (MDOC_Literal == n->args->argv[i].arg)
! 693: break;
! 694: else if (MDOC_Unfilled == n->args->argv[i].arg)
! 695: break;
! 696:
! 697: if (i < (int)n->args->argc)
! 698: m->flags |= MDOC_LITERAL;
! 699:
! 700: return(1);
! 701: }
! 702:
! 703:
! 704: static int
! 705: post_display(POST_ARGS)
! 706: {
! 707:
! 708: if (MDOC_BODY == m->last->type)
! 709: m->flags &= ~MDOC_LITERAL;
! 710: return(1);
! 711: }
! 712:
! 713:
CVSweb