]> git.cameronkatri.com Git - mandoc.git/blob - action.c
Cleaned up ctype functions (netbsd).
[mandoc.git] / action.c
1 /* $Id: action.c,v 1.30 2009/03/05 13:12:12 kristaps Exp $ */
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 <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <time.h>
24
25 #include "private.h"
26
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 */
32
33 struct actions {
34 int (*post)(struct mdoc *);
35 };
36
37 /* Per-macro action routines. */
38
39 static int post_ar(struct mdoc *);
40 static int post_bl(struct mdoc *);
41 static int post_bl_width(struct mdoc *);
42 static int post_bl_tagwidth(struct mdoc *);
43 static int post_dd(struct mdoc *);
44 static int post_dt(struct mdoc *);
45 static int post_nm(struct mdoc *);
46 static int post_os(struct mdoc *);
47 static int post_sh(struct mdoc *);
48 static int post_ex(struct mdoc *);
49
50 static int post_prologue(struct mdoc *);
51
52 /* Array of macro action routines. */
53
54 const struct actions mdoc_actions[MDOC_MAX] = {
55 { NULL }, /* \" */
56 { post_dd }, /* Dd */
57 { post_dt }, /* Dt */
58 { post_os }, /* Os */
59 { post_sh }, /* Sh */
60 { NULL }, /* Ss */
61 { NULL }, /* Pp */
62 { NULL }, /* D1 */
63 { NULL }, /* Dl */
64 { NULL }, /* Bd */
65 { NULL }, /* Ed */
66 { post_bl }, /* Bl */
67 { NULL }, /* El */
68 { NULL }, /* It */
69 { NULL }, /* Ad */
70 { NULL }, /* An */
71 { post_ar }, /* Ar */
72 { NULL }, /* Cd */
73 { NULL }, /* Cm */
74 { NULL }, /* Dv */
75 { NULL }, /* Er */
76 { NULL }, /* Ev */
77 { post_ex }, /* Ex */
78 { NULL }, /* Fa */
79 { NULL }, /* Fd */
80 { NULL }, /* Fl */
81 { NULL }, /* Fn */
82 { NULL }, /* Ft */
83 { NULL }, /* Ic */
84 { NULL }, /* In */
85 { NULL }, /* Li */
86 { NULL }, /* Nd */
87 { post_nm }, /* Nm */
88 { NULL }, /* Op */
89 { NULL }, /* Ot */
90 { NULL }, /* Pa */
91 { NULL }, /* Rv */
92 { NULL }, /* St */
93 { NULL }, /* Va */
94 { NULL }, /* Vt */
95 { NULL }, /* Xr */
96 { NULL }, /* %A */
97 { NULL }, /* %B */
98 { NULL }, /* %D */
99 { NULL }, /* %I */
100 { NULL }, /* %J */
101 { NULL }, /* %N */
102 { NULL }, /* %O */
103 { NULL }, /* %P */
104 { NULL }, /* %R */
105 { NULL }, /* %T */
106 { NULL }, /* %V */
107 { NULL }, /* Ac */
108 { NULL }, /* Ao */
109 { NULL }, /* Aq */
110 { NULL }, /* At */
111 { NULL }, /* Bc */
112 { NULL }, /* Bf */
113 { NULL }, /* Bo */
114 { NULL }, /* Bq */
115 { NULL }, /* Bsx */
116 { NULL }, /* Bx */
117 { NULL }, /* Db */
118 { NULL }, /* Dc */
119 { NULL }, /* Do */
120 { NULL }, /* Dq */
121 { NULL }, /* Ec */
122 { NULL }, /* Ef */
123 { NULL }, /* Em */
124 { NULL }, /* Eo */
125 { NULL }, /* Fx */
126 { NULL }, /* Ms */
127 { NULL }, /* No */
128 { NULL }, /* Ns */
129 { NULL }, /* Nx */
130 { NULL }, /* Ox */
131 { NULL }, /* Pc */
132 { NULL }, /* Pf */
133 { NULL }, /* Po */
134 { NULL }, /* Pq */
135 { NULL }, /* Qc */
136 { NULL }, /* Ql */
137 { NULL }, /* Qo */
138 { NULL }, /* Qq */
139 { NULL }, /* Re */
140 { NULL }, /* Rs */
141 { NULL }, /* Sc */
142 { NULL }, /* So */
143 { NULL }, /* Sq */
144 { NULL }, /* Sm */
145 { NULL }, /* Sx */
146 { NULL }, /* Sy */
147 { NULL }, /* Tn */
148 { NULL }, /* Ux */
149 { NULL }, /* Xc */
150 { NULL }, /* Xo */
151 { NULL }, /* Fo */
152 { NULL }, /* Fc */
153 { NULL }, /* Oo */
154 { NULL }, /* Oc */
155 { NULL }, /* Bk */
156 { NULL }, /* Ek */
157 { NULL }, /* Bt */
158 { NULL }, /* Hf */
159 { NULL }, /* Fr */
160 { NULL }, /* Ud */
161 };
162
163
164 static int
165 post_ex(struct mdoc *mdoc)
166 {
167
168 /*
169 * If `.Ex -std' is invoked without an argument, fill it in with
170 * our name (if it's been set).
171 */
172
173 if (0 == mdoc->last->data.elem.argc)
174 return(1);
175 if (mdoc->last->data.elem.argv[0].sz)
176 return(1);
177
178 assert(mdoc->meta.name);
179
180 mdoc_msg(mdoc, "writing %s argument: %s",
181 mdoc_argnames[MDOC_Std], mdoc->meta.name);
182
183 mdoc->last->data.elem.argv[0].sz = 1;
184 mdoc->last->data.elem.argv[0].value = xcalloc(1, sizeof(char *));
185 mdoc->last->data.elem.argv[0].value[0] = xstrdup(mdoc->meta.name);
186 return(1);
187 }
188
189
190 static int
191 post_nm(struct mdoc *mdoc)
192 {
193 char buf[64];
194
195 assert(MDOC_ELEM == mdoc->last->type);
196 assert(MDOC_Nm == mdoc->last->tok);
197
198 /*
199 * The `Nm' macro sets the document's name when used the first
200 * time with an argument. Subsequent calls without a value will
201 * result in the name value being used.
202 */
203
204 if (mdoc->meta.name)
205 return(1);
206
207 if (xstrlcats(buf, mdoc->last->child, 64)) {
208 mdoc->meta.name = xstrdup(buf);
209 return(1);
210 }
211
212 return(mdoc_err(mdoc, "macro parameters too long"));
213 }
214
215
216 static int
217 post_sh(struct mdoc *mdoc)
218 {
219 enum mdoc_sec sec;
220 char buf[64];
221
222 /*
223 * We keep track of the current section /and/ the "named"
224 * section, which is one of the conventional ones, in order to
225 * check ordering.
226 */
227
228 if (MDOC_HEAD != mdoc->last->type)
229 return(1);
230 if (xstrlcats(buf, mdoc->last->child, 64)) {
231 if (SEC_CUSTOM != (sec = mdoc_atosec(buf)))
232 mdoc->lastnamed = sec;
233 mdoc->lastsec = sec;
234 } else
235 return(mdoc_err(mdoc, "parameters too long"));
236
237 switch (mdoc->lastsec) {
238 case (SEC_RETURN_VALUES):
239 /* FALLTHROUGH */
240 case (SEC_ERRORS):
241 switch (mdoc->meta.msec) {
242 case (MSEC_2):
243 /* FALLTHROUGH */
244 case (MSEC_3):
245 /* FALLTHROUGH */
246 case (MSEC_9):
247 break;
248 default:
249 return(mdoc_warn(mdoc, WARN_COMPAT,
250 "inappropriate section for "
251 "manual section"));
252 }
253 break;
254 default:
255 break;
256 }
257 return(1);
258 }
259
260
261 static int
262 post_dt(struct mdoc *mdoc)
263 {
264 int i;
265 char *p;
266 struct mdoc_node *n;
267
268 /*
269 * Prologue title must be parsed into document meta-data.
270 */
271
272 assert(MDOC_ELEM == mdoc->last->type);
273 assert(MDOC_Dt == mdoc->last->tok);
274
275 assert(NULL == mdoc->meta.title);
276
277 /* LINTED */
278 for (i = 0, n = mdoc->last->child; n; n = n->next, i++) {
279 assert(MDOC_TEXT == n->type);
280 p = n->data.text.string;
281
282 switch (i) {
283 case (0):
284 mdoc->meta.title = xstrdup(p);
285 break;
286 case (1):
287 mdoc->meta.msec = mdoc_atomsec(p);
288 if (MSEC_DEFAULT != mdoc->meta.msec)
289 break;
290 return(mdoc_nerr(mdoc, n,
291 "invalid parameter syntax"));
292 case (2):
293 mdoc->meta.vol = mdoc_atovol(p);
294 if (VOL_DEFAULT != mdoc->meta.vol)
295 break;
296 mdoc->meta.arch = mdoc_atoarch(p);
297 if (ARCH_DEFAULT != mdoc->meta.arch)
298 break;
299 return(mdoc_nerr(mdoc, n,
300 "invalid parameter syntax"));
301 default:
302 return(mdoc_nerr(mdoc, n,
303 "too many parameters"));
304 }
305 }
306
307 if (NULL == mdoc->meta.title)
308 mdoc->meta.title = xstrdup("UNTITLED");
309
310 mdoc_msg(mdoc, "title: %s", mdoc->meta.title);
311
312 return(post_prologue(mdoc));
313 }
314
315
316 static int
317 post_os(struct mdoc *mdoc)
318 {
319 char buf[64];
320
321 /*
322 * Prologue operating system must be parsed into document
323 * meta-data.
324 */
325
326 assert(MDOC_ELEM == mdoc->last->type);
327 assert(MDOC_Os == mdoc->last->tok);
328 assert(NULL == mdoc->meta.os);
329
330 if ( ! xstrlcats(buf, mdoc->last->child, 64))
331 return(mdoc_err(mdoc, "macro parameters too long"));
332
333 mdoc->meta.os = xstrdup(buf[0] ? buf : "LOCAL");
334 mdoc->lastnamed = SEC_BODY;
335
336 return(post_prologue(mdoc));
337 }
338
339
340 static int
341 post_bl_tagwidth(struct mdoc *mdoc)
342 {
343 struct mdoc_node *n;
344 struct mdoc_block *b;
345 int sz;
346 char buf[32];
347
348 /*
349 * If -tag has been specified and -width has not been, then try
350 * to intuit our width from the first body element.
351 */
352
353 b = &mdoc->last->data.block;
354
355 if (NULL == (n = b->body->child))
356 return(1);
357 assert(MDOC_It == n->tok);
358
359 /*
360 * Use the text width, if a text node, or the default macro
361 * width if a macro.
362 */
363
364 if ((n = n->data.block.head->child)) {
365 if (MDOC_TEXT != n->type) {
366 if (0 == (sz = mdoc_macro2len(n->tok)))
367 sz = -1;
368 } else
369 sz = (int)strlen(n->data.text.string) + 1;
370 } else
371 sz = -1;
372
373 if (-1 == sz) {
374 if ( ! mdoc_warn(mdoc, WARN_SYNTAX,
375 "cannot determine default %s",
376 mdoc_argnames[MDOC_Width]))
377 return(0);
378 sz = 10;
379 }
380
381 (void)snprintf(buf, sizeof(buf), "%dn", sz);
382
383 /*
384 * We have to dynamically add this to the macro's argument list.
385 * We're guaranteed that a MDOC_Width doesn't already exist.
386 */
387
388 (b->argc)++;
389 b->argv = xrealloc(b->argv, b->argc * sizeof(struct mdoc_arg));
390
391 b->argv[b->argc - 1].arg = MDOC_Width;
392 b->argv[b->argc - 1].line = mdoc->last->line;
393 b->argv[b->argc - 1].pos = mdoc->last->pos;
394 b->argv[b->argc - 1].sz = 1;
395 b->argv[b->argc - 1].value = xcalloc(1, sizeof(char *));
396 b->argv[b->argc - 1].value[0] = xstrdup(buf);
397
398 mdoc_msg(mdoc, "adding %s argument: %dn",
399 mdoc_argnames[MDOC_Width], sz);
400
401 return(1);
402 }
403
404
405 static int
406 post_bl_width(struct mdoc *mdoc)
407 {
408 size_t width;
409 int i, tok;
410 char buf[32];
411 char **p;
412
413 for (i = 0; i < (int)mdoc->last->data.block.argc; i++)
414 if (MDOC_Width == mdoc->last->data.block.argv[i].arg)
415 break;
416
417 assert(i < (int)mdoc->last->data.block.argc);
418 assert(1 == mdoc->last->data.block.argv[i].sz);
419 p = &mdoc->last->data.block.argv[i].value[0];
420
421 /*
422 * If the value to -width is a macro, then we re-write it to be
423 * the macro's width as set in share/tmac/mdoc/doc-common.
424 */
425
426 if (xstrcmp(*p, "Ds"))
427 width = 8;
428 else if (MDOC_MAX == (tok = mdoc_find(mdoc, *p)))
429 return(1);
430 else if (0 == (width = mdoc_macro2len(tok)))
431 return(mdoc_warn(mdoc, WARN_SYNTAX,
432 "%s macro has no length",
433 mdoc_argnames[MDOC_Width]));
434
435 mdoc_msg(mdoc, "re-writing %s argument: %s -> %zun",
436 mdoc_argnames[MDOC_Width], *p, width);
437
438 /* The value already exists: free and reallocate it. */
439
440 (void)snprintf(buf, sizeof(buf), "%zun", width);
441
442 free(*p);
443 *p = strdup(buf);
444
445 return(1);
446 }
447
448
449 static int
450 post_bl(struct mdoc *mdoc)
451 {
452 int i, r;
453
454 if (MDOC_BLOCK != mdoc->last->type)
455 return(1);
456
457 /*
458 * These are fairly complicated, so we've broken them into two
459 * functions. post_bl_tagwidth() is called when a -tag is
460 * specified, but no -width (it must be guessed). The second
461 * when a -width is specified (macro indicators must be
462 * rewritten into real lengths).
463 */
464
465 for (r = i = 0; i < (int)mdoc->last->data.block.argc; i++) {
466 if (MDOC_Tag == mdoc->last->data.block.argv[i].arg)
467 r |= 1 << 0;
468 if (MDOC_Width == mdoc->last->data.block.argv[i].arg)
469 r |= 1 << 1;
470 }
471
472 if (r & (1 << 0) && ! (r & (1 << 1))) {
473 if ( ! post_bl_tagwidth(mdoc))
474 return(0);
475 } else if (r & (1 << 1))
476 if ( ! post_bl_width(mdoc))
477 return(0);
478
479 return(1);
480 }
481
482
483 static int
484 post_ar(struct mdoc *mdoc)
485 {
486 struct mdoc_node *n;
487
488 if (mdoc->last->child)
489 return(1);
490
491 n = mdoc->last;
492
493 mdoc->next = MDOC_NEXT_CHILD;
494 mdoc_word_alloc(mdoc, mdoc->last->line,
495 mdoc->last->pos, "file");
496 mdoc->next = MDOC_NEXT_SIBLING;
497 mdoc_word_alloc(mdoc, mdoc->last->line,
498 mdoc->last->pos, "...");
499
500 mdoc->last = n;
501 mdoc->next = MDOC_NEXT_SIBLING;
502 return(1);
503 }
504
505
506 static int
507 post_dd(struct mdoc *mdoc)
508 {
509 char buf[64];
510
511 /*
512 * Prologue date must be parsed into document meta-data. We
513 * accept multiple kinds of dates, described mostly in
514 * mdoc_atotime().
515 */
516
517 assert(MDOC_ELEM == mdoc->last->type);
518 assert(MDOC_Dd == mdoc->last->tok);
519
520 assert(0 == mdoc->meta.date);
521
522 if ( ! xstrlcats(buf, mdoc->last->child, 64))
523 return(mdoc_err(mdoc, "macro parameters too long"));
524 if (0 == (mdoc->meta.date = mdoc_atotime(buf)))
525 return(mdoc_err(mdoc, "invalid parameter syntax"));
526
527 mdoc_msg(mdoc, "date: %u", mdoc->meta.date);
528
529 return(post_prologue(mdoc));
530 }
531
532
533 static int
534 post_prologue(struct mdoc *mdoc)
535 {
536 struct mdoc_node *n;
537
538 /*
539 * The end document shouldn't have the prologue macros as part
540 * of the syntax tree (they encompass only meta-data).
541 */
542
543 if (mdoc->last->parent->child == mdoc->last)
544 mdoc->last->parent->child = mdoc->last->prev;
545 if (mdoc->last->prev)
546 mdoc->last->prev->next = NULL;
547
548 n = mdoc->last;
549 assert(NULL == mdoc->last->next);
550
551 if (mdoc->last->prev) {
552 mdoc->last = mdoc->last->prev;
553 mdoc->next = MDOC_NEXT_SIBLING;
554 } else {
555 mdoc->last = mdoc->last->parent;
556 mdoc->next = MDOC_NEXT_CHILD;
557 }
558
559 mdoc_node_freelist(n);
560 return(1);
561 }
562
563
564 int
565 mdoc_action_post(struct mdoc *mdoc)
566 {
567
568 if (MDOC_ACTED & mdoc->last->flags)
569 return(1);
570 mdoc->last->flags |= MDOC_ACTED;
571
572 if (MDOC_TEXT == mdoc->last->type)
573 return(1);
574 if (MDOC_ROOT == mdoc->last->type)
575 return(1);
576 if (NULL == mdoc_actions[mdoc->last->tok].post)
577 return(1);
578 return((*mdoc_actions[mdoc->last->tok].post)(mdoc));
579 }