Annotation of mandoc/action.c, Revision 1.14
1.14 ! kristaps 1: /* $Id: action.c,v 1.13 2009/01/20 12:51:28 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: */
19: #include <assert.h>
20: #include <stdlib.h>
1.5 kristaps 21: #include <time.h>
1.1 kristaps 22:
23: #include "private.h"
24:
1.14 ! kristaps 25: /*
! 26: * Actions are executed on macros after they've been post-validated: in
! 27: * other words, a macro will not be "acted upon" until all of its
! 28: * children have been filled in (post-fix order).
! 29: */
1.1 kristaps 30:
31: struct actions {
1.10 kristaps 32: int (*post)(struct mdoc *);
1.1 kristaps 33: };
34:
1.11 kristaps 35: /* Per-macro action routines. */
1.1 kristaps 36:
1.13 kristaps 37: static int post_sh(struct mdoc *);
38: static int post_os(struct mdoc *);
39: static int post_dt(struct mdoc *);
40: static int post_dd(struct mdoc *);
41: static int post_nm(struct mdoc *);
42:
43: static int post_prologue(struct mdoc *);
1.3 kristaps 44:
1.11 kristaps 45: /* Array of macro action routines. */
46:
1.1 kristaps 47: const struct actions mdoc_actions[MDOC_MAX] = {
1.10 kristaps 48: { NULL }, /* \" */
49: { post_dd }, /* Dd */
50: { post_dt }, /* Dt */
51: { post_os }, /* Os */
52: { post_sh }, /* Sh */
53: { NULL }, /* Ss */
54: { NULL }, /* Pp */
55: { NULL }, /* D1 */
56: { NULL }, /* Dl */
57: { NULL }, /* Bd */
58: { NULL }, /* Ed */
59: { NULL }, /* Bl */
60: { NULL }, /* El */
61: { NULL }, /* It */
62: { NULL }, /* Ad */
63: { NULL }, /* An */
64: { NULL }, /* Ar */
65: { NULL }, /* Cd */
66: { NULL }, /* Cm */
67: { NULL }, /* Dv */
68: { NULL }, /* Er */
69: { NULL }, /* Ev */
70: { NULL }, /* Ex */
71: { NULL }, /* Fa */
72: { NULL }, /* Fd */
73: { NULL }, /* Fl */
74: { NULL }, /* Fn */
75: { NULL }, /* Ft */
76: { NULL }, /* Ic */
77: { NULL }, /* In */
78: { NULL }, /* Li */
79: { NULL }, /* Nd */
80: { post_nm }, /* Nm */
81: { NULL }, /* Op */
82: { NULL }, /* Ot */
83: { NULL }, /* Pa */
84: { NULL }, /* Rv */
85: { NULL }, /* St */
86: { NULL }, /* Va */
87: { NULL }, /* Vt */
88: { NULL }, /* Xr */
89: { NULL }, /* %A */
90: { NULL }, /* %B */
91: { NULL }, /* %D */
92: { NULL }, /* %I */
93: { NULL }, /* %J */
94: { NULL }, /* %N */
95: { NULL }, /* %O */
96: { NULL }, /* %P */
97: { NULL }, /* %R */
98: { NULL }, /* %T */
99: { NULL }, /* %V */
100: { NULL }, /* Ac */
101: { NULL }, /* Ao */
102: { NULL }, /* Aq */
103: { NULL }, /* At */
104: { NULL }, /* Bc */
105: { NULL }, /* Bf */
106: { NULL }, /* Bo */
107: { NULL }, /* Bq */
108: { NULL }, /* Bsx */
109: { NULL }, /* Bx */
110: { NULL }, /* Db */
111: { NULL }, /* Dc */
112: { NULL }, /* Do */
113: { NULL }, /* Dq */
114: { NULL }, /* Ec */
115: { NULL }, /* Ef */
116: { NULL }, /* Em */
117: { NULL }, /* Eo */
118: { NULL }, /* Fx */
119: { NULL }, /* Ms */
120: { NULL }, /* No */
121: { NULL }, /* Ns */
122: { NULL }, /* Nx */
123: { NULL }, /* Ox */
124: { NULL }, /* Pc */
125: { NULL }, /* Pf */
126: { NULL }, /* Po */
127: { NULL }, /* Pq */
128: { NULL }, /* Qc */
129: { NULL }, /* Ql */
130: { NULL }, /* Qo */
131: { NULL }, /* Qq */
132: { NULL }, /* Re */
133: { NULL }, /* Rs */
134: { NULL }, /* Sc */
135: { NULL }, /* So */
136: { NULL }, /* Sq */
137: { NULL }, /* Sm */
138: { NULL }, /* Sx */
139: { NULL }, /* Sy */
140: { NULL }, /* Tn */
141: { NULL }, /* Ux */
142: { NULL }, /* Xc */
143: { NULL }, /* Xo */
144: { NULL }, /* Fo */
145: { NULL }, /* Fc */
146: { NULL }, /* Oo */
147: { NULL }, /* Oc */
148: { NULL }, /* Bk */
149: { NULL }, /* Ek */
150: { NULL }, /* Bt */
151: { NULL }, /* Hf */
152: { NULL }, /* Fr */
153: { NULL }, /* Ud */
1.1 kristaps 154: };
155:
156:
1.14 ! kristaps 157: /*
! 158: * The `Nm' macro sets the document's name when used the first time with
! 159: * an argument. Subsequent calls without a value will result in the
! 160: * name value being used.
! 161: */
1.3 kristaps 162: static int
1.10 kristaps 163: post_nm(struct mdoc *mdoc)
164: {
165: char buf[64];
166:
167: assert(MDOC_ELEM == mdoc->last->type);
168: assert(MDOC_Nm == mdoc->last->tok);
169:
170: if (mdoc->meta.name)
171: return(1);
172:
1.11 kristaps 173: if (xstrlcats(buf, mdoc->last->child, 64)) {
174: mdoc->meta.name = xstrdup(buf);
175: return(1);
176: }
1.10 kristaps 177:
1.11 kristaps 178: return(mdoc_err(mdoc, "macro parameters too long"));
1.10 kristaps 179: }
180:
181:
1.14 ! kristaps 182: /*
! 183: * We keep track of the current section in order to provide warnings on
! 184: * section ordering, per-section macros, and so on.
! 185: */
1.10 kristaps 186: static int
1.4 kristaps 187: post_sh(struct mdoc *mdoc)
1.1 kristaps 188: {
1.10 kristaps 189: enum mdoc_sec sec;
190: char buf[64];
1.3 kristaps 191:
192: if (MDOC_HEAD != mdoc->last->type)
193: return(1);
1.11 kristaps 194: if (xstrlcats(buf, mdoc->last->child, 64)) {
195: if (SEC_CUSTOM != (sec = mdoc_atosec(buf)))
196: mdoc->sec_lastn = sec;
197: mdoc->sec_last = sec;
198: return(1);
199: }
1.1 kristaps 200:
1.11 kristaps 201: return(mdoc_err(mdoc, "macro parameters too long"));
1.1 kristaps 202: }
203:
1.3 kristaps 204:
1.14 ! kristaps 205: /*
! 206: * Prologue title must be parsed into document meta-data.
! 207: */
1.4 kristaps 208: static int
209: post_dt(struct mdoc *mdoc)
210: {
1.5 kristaps 211: int i;
212: char *p;
213: struct mdoc_node *n;
214:
215: assert(MDOC_ELEM == mdoc->last->type);
1.7 kristaps 216: assert(MDOC_Dt == mdoc->last->tok);
1.5 kristaps 217:
1.10 kristaps 218: assert(NULL == mdoc->meta.title);
1.4 kristaps 219:
1.5 kristaps 220: for (i = 0, n = mdoc->last->child; n; n = n->next, i++) {
221: assert(MDOC_TEXT == n->type);
222: p = n->data.text.string;
1.4 kristaps 223:
1.5 kristaps 224: switch (i) {
225: case (0):
1.10 kristaps 226: mdoc->meta.title = xstrdup(p);
227: break;
1.5 kristaps 228: case (1):
229: mdoc->meta.msec = mdoc_atomsec(p);
230: if (MSEC_DEFAULT != mdoc->meta.msec)
231: break;
1.10 kristaps 232: return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
1.5 kristaps 233: case (2):
234: mdoc->meta.vol = mdoc_atovol(p);
235: if (VOL_DEFAULT != mdoc->meta.vol)
236: break;
237: mdoc->meta.arch = mdoc_atoarch(p);
238: if (ARCH_DEFAULT != mdoc->meta.arch)
239: break;
1.10 kristaps 240: return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
1.5 kristaps 241: default:
1.8 kristaps 242: return(mdoc_nerr(mdoc, n, "too many parameters"));
1.5 kristaps 243: }
1.4 kristaps 244: }
245:
1.10 kristaps 246: if (NULL == mdoc->meta.title)
247: mdoc->meta.title = xstrdup("untitled");
1.13 kristaps 248:
249: return(post_prologue(mdoc));
1.4 kristaps 250: }
251:
252:
1.14 ! kristaps 253: /*
! 254: * Prologue operating system must be parsed into document meta-data.
! 255: */
1.4 kristaps 256: static int
257: post_os(struct mdoc *mdoc)
258: {
1.10 kristaps 259: char buf[64];
1.5 kristaps 260:
261: assert(MDOC_ELEM == mdoc->last->type);
1.7 kristaps 262: assert(MDOC_Os == mdoc->last->tok);
1.10 kristaps 263: assert(NULL == mdoc->meta.os);
1.5 kristaps 264:
1.10 kristaps 265: if ( ! xstrlcats(buf, mdoc->last->child, 64))
266: return(mdoc_err(mdoc, "macro parameters too long"));
1.6 kristaps 267:
1.10 kristaps 268: mdoc->meta.os = xstrdup(buf[0] ? buf : "local");
1.5 kristaps 269: mdoc->sec_lastn = mdoc->sec_last = SEC_BODY;
1.13 kristaps 270: mdoc->flags |= MDOC_BODYPARSE;
271:
272: return(post_prologue(mdoc));
1.4 kristaps 273: }
274:
275:
1.14 ! kristaps 276: /*
! 277: * Prologue date must be parsed into document meta-data.
! 278: */
1.4 kristaps 279: static int
280: post_dd(struct mdoc *mdoc)
281: {
1.5 kristaps 282: char date[64];
283: size_t sz;
284: char *p;
285: struct mdoc_node *n;
1.4 kristaps 286:
1.5 kristaps 287: assert(MDOC_ELEM == mdoc->last->type);
1.7 kristaps 288: assert(MDOC_Dd == mdoc->last->tok);
1.5 kristaps 289:
290: n = mdoc->last->child;
291: assert(0 == mdoc->meta.date);
1.4 kristaps 292: date[0] = 0;
293:
1.5 kristaps 294: sz = 64;
295:
296: for ( ; 0 == mdoc->meta.date && n; n = n->next) {
297: assert(MDOC_TEXT == n->type);
298: p = n->data.text.string;
299:
300: if (xstrcmp(p, "$Mdocdate$")) {
301: mdoc->meta.date = time(NULL);
302: continue;
303: } else if (xstrcmp(p, "$")) {
304: mdoc->meta.date = mdoc_atotime(date);
305: continue;
306: } else if (xstrcmp(p, "$Mdocdate:"))
307: continue;
308:
309: if ( ! xstrlcat(date, n->data.text.string, sz))
1.10 kristaps 310: return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
1.9 kristaps 311: if (n->next && ! xstrlcat(date, " ", sz))
1.10 kristaps 312: return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
1.5 kristaps 313: }
314:
1.11 kristaps 315: if (mdoc->meta.date && NULL == n)
1.13 kristaps 316: return(post_prologue(mdoc));
1.11 kristaps 317: else if (n)
1.10 kristaps 318: return(mdoc_err(mdoc, "invalid parameter syntax"));
1.11 kristaps 319: if ((mdoc->meta.date = mdoc_atotime(date)))
1.13 kristaps 320: return(post_prologue(mdoc));
1.10 kristaps 321: return(mdoc_err(mdoc, "invalid parameter syntax"));
1.4 kristaps 322: }
323:
324:
1.14 ! kristaps 325: /*
! 326: * The end document shouldn't have the prologue macros as part of the
! 327: * syntax tree (they encompass only meta-data).
! 328: */
1.13 kristaps 329: static int
330: post_prologue(struct mdoc *mdoc)
331: {
332: struct mdoc_node *n;
333:
334: if (mdoc->last->parent->child == mdoc->last)
335: mdoc->last->parent->child = mdoc->last->prev;
336: if (mdoc->last->prev)
337: mdoc->last->prev->next = NULL;
338:
339: n = mdoc->last;
340: assert(NULL == mdoc->last->next);
341:
342: if (mdoc->last->prev) {
343: mdoc->last = mdoc->last->prev;
344: mdoc->next = MDOC_NEXT_SIBLING;
345: } else {
346: mdoc->last = mdoc->last->parent;
347: mdoc->next = MDOC_NEXT_CHILD;
348: }
349:
350: mdoc_node_freelist(n);
351: return(1);
352: }
353:
354:
1.4 kristaps 355: int
356: mdoc_action_post(struct mdoc *mdoc)
1.3 kristaps 357: {
358:
1.12 kristaps 359: if (MDOC_ACTED & mdoc->last->flags)
360: return(1);
361: mdoc->last->flags |= MDOC_ACTED;
362:
1.7 kristaps 363: if (MDOC_TEXT == mdoc->last->type)
364: return(1);
365: if (MDOC_ROOT == mdoc->last->type)
1.3 kristaps 366: return(1);
1.7 kristaps 367: if (NULL == mdoc_actions[mdoc->last->tok].post)
1.3 kristaps 368: return(1);
1.7 kristaps 369: return((*mdoc_actions[mdoc->last->tok].post)(mdoc));
1.3 kristaps 370: }
CVSweb