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