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