Annotation of mandoc/macro.c, Revision 1.12
1.12 ! kristaps 1: /* $Id: macro.c,v 1.11 2008/12/29 18:08:44 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.2 kristaps 19: #include <assert.h>
20: #include <ctype.h>
1.1 kristaps 21: #include <stdlib.h>
1.2 kristaps 22: #include <stdio.h>
1.5 kristaps 23: #include <string.h>
1.11 kristaps 24: #ifdef __linux__
25: #include <time.h>
26: #endif
1.2 kristaps 27:
28: #include "private.h"
29:
1.10 kristaps 30: /* FIXME: maxlineargs should be per LINE, no per TOKEN. */
31:
1.3 kristaps 32: #define _CC(p) ((const char **)p)
1.2 kristaps 33:
1.6 kristaps 34: static int scope_rewind_exp(struct mdoc *, int, int, int);
1.7 kristaps 35: static int scope_rewind_imp(struct mdoc *, int, int);
1.3 kristaps 36: static int append_text(struct mdoc *, int,
37: int, int, char *[]);
1.10 kristaps 38: static int append_const(struct mdoc *, int, int, int, char *[]);
1.6 kristaps 39: static int append_scoped(struct mdoc *, int, int, int,
40: const char *[], int, const struct mdoc_arg *);
1.7 kristaps 41: static int append_delims(struct mdoc *, int, int *, char *);
1.6 kristaps 42:
43:
44: static int
1.7 kristaps 45: append_delims(struct mdoc *mdoc, int tok, int *pos, char *buf)
1.6 kristaps 46: {
1.7 kristaps 47: int c, lastarg;
48: char *p;
1.6 kristaps 49:
50: if (0 == buf[*pos])
1.7 kristaps 51: return(1);
1.6 kristaps 52:
1.8 kristaps 53: mdoc_msg(mdoc, *pos, "`%s' flushing punctuation",
54: mdoc_macronames[tok]);
1.6 kristaps 55:
1.7 kristaps 56: for (;;) {
57: lastarg = *pos;
58: c = mdoc_args(mdoc, tok, pos, buf, 0, &p);
59: if (ARGS_ERROR == c)
60: return(0);
61: else if (ARGS_EOLN == c)
62: break;
63: assert(mdoc_isdelim(p));
64: mdoc_word_alloc(mdoc, lastarg, p);
1.6 kristaps 65: }
66:
67: return(1);
68: }
69:
70:
71: static int
1.7 kristaps 72: scope_rewind_imp(struct mdoc *mdoc, int ppos, int tok)
1.6 kristaps 73: {
74: struct mdoc_node *n;
1.7 kristaps 75: int t;
76:
77: n = mdoc->last ? mdoc->last->parent : NULL;
1.6 kristaps 78:
79: /* LINTED */
1.7 kristaps 80: for ( ; n; n = n->parent) {
1.6 kristaps 81: if (MDOC_BLOCK != n->type)
82: continue;
1.7 kristaps 83: if (tok == (t = n->data.block.tok))
1.6 kristaps 84: break;
1.7 kristaps 85: if ( ! (MDOC_EXPLICIT & mdoc_macros[t].flags))
86: continue;
1.6 kristaps 87: return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_BREAK));
88: }
89:
1.7 kristaps 90: if (n) {
91: mdoc->last = n;
92: mdoc_msg(mdoc, ppos, "scope: rewound implicit `%s'",
93: mdoc_macronames[tok]);
94: return(1);
95: }
1.6 kristaps 96:
1.7 kristaps 97: mdoc_msg(mdoc, ppos, "scope: new implicit `%s'",
98: mdoc_macronames[tok]);
1.6 kristaps 99: return(1);
100: }
101:
102:
103: static int
1.7 kristaps 104: scope_rewind_exp(struct mdoc *mdoc, int ppos, int tok, int dst)
1.6 kristaps 105: {
1.7 kristaps 106: struct mdoc_node *n;
1.6 kristaps 107:
1.7 kristaps 108: assert(mdoc->last);
1.6 kristaps 109:
1.7 kristaps 110: /* LINTED */
111: for (n = mdoc->last->parent; n; n = n->parent) {
112: if (MDOC_BLOCK != n->type)
113: continue;
114: if (dst == n->data.block.tok)
115: break;
116: return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_BREAK));
1.6 kristaps 117: }
118:
1.7 kristaps 119: if (NULL == (mdoc->last = n))
120: return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_NOCTX));
1.6 kristaps 121:
1.7 kristaps 122: mdoc_msg(mdoc, ppos, "scope: rewound explicit `%s' to `%s'",
123: mdoc_macronames[tok], mdoc_macronames[dst]);
1.2 kristaps 124:
1.1 kristaps 125: return(1);
126: }
127:
1.2 kristaps 128:
129: static int
1.6 kristaps 130: append_scoped(struct mdoc *mdoc, int tok, int pos,
131: int sz, const char *args[],
132: int argc, const struct mdoc_arg *argv)
1.2 kristaps 133: {
1.7 kristaps 134: enum mdoc_sec sec;
135: struct mdoc_node *node;
1.5 kristaps 136:
1.4 kristaps 137: switch (tok) {
138: /* ======= ADD MORE MACRO CHECKS BELOW. ======= */
139: case (MDOC_Sh):
1.6 kristaps 140: if (0 == sz)
141: return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
142:
1.5 kristaps 143: sec = mdoc_atosec((size_t)sz, _CC(args));
144: if (SEC_CUSTOM != sec && sec < mdoc->sec_lastn)
145: if ( ! mdoc_warn(mdoc, tok, pos, WARN_SEC_OO))
146: return(0);
147:
148: if (SEC_BODY == mdoc->sec_last && SEC_NAME != sec)
149: return(mdoc_err(mdoc, tok, pos, ERR_SEC_NAME));
150:
151: if (SEC_CUSTOM != sec)
152: mdoc->sec_lastn = sec;
153: mdoc->sec_last = sec;
1.4 kristaps 154: break;
1.6 kristaps 155:
1.4 kristaps 156: case (MDOC_Ss):
1.6 kristaps 157: if (0 == sz)
158: return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
159: break;
1.7 kristaps 160:
161: case (MDOC_Bd):
162: assert(mdoc->last);
1.9 kristaps 163: node = mdoc->last->parent;
164: /* LINTED */
165: for ( ; node; node = node->parent) {
1.7 kristaps 166: if (node->type != MDOC_BLOCK)
167: continue;
168: if (node->data.block.tok != MDOC_Bd)
169: continue;
170: return(mdoc_err(mdoc, tok, pos, ERR_SCOPE_NONEST));
171: }
172: break;
1.6 kristaps 173:
174: case (MDOC_Bl):
1.4 kristaps 175: break;
1.6 kristaps 176:
1.4 kristaps 177: /* ======= ADD MORE MACRO CHECKS ABOVE. ======= */
178: default:
179: abort();
180: /* NOTREACHED */
181: }
182:
1.6 kristaps 183: mdoc_block_alloc(mdoc, pos, tok, (size_t)argc, argv);
1.3 kristaps 184: mdoc_head_alloc(mdoc, pos, tok, (size_t)sz, _CC(args));
1.2 kristaps 185: mdoc_body_alloc(mdoc, pos, tok);
186: return(1);
187: }
188:
189:
1.1 kristaps 190: static int
1.10 kristaps 191: append_const(struct mdoc *mdoc, int tok,
192: int pos, int sz, char *args[])
193: {
194:
195: switch (tok) {
196: /* ======= ADD MORE MACRO CHECKS BELOW. ======= */
1.11 kristaps 197: case (MDOC_At):
198: /* This needs special handling. */
199: if (0 == sz)
200: break;
201: else if (sz > 2)
202: return(mdoc_err(mdoc, tok, pos, ERR_ARGS_LE2));
203:
204: if (ATT_DEFAULT != mdoc_atoatt(args[0])) {
205: mdoc_elem_alloc(mdoc, pos, tok, 0,
206: NULL, 1, _CC(&args[0]));
207: } else {
208: mdoc_elem_alloc(mdoc, pos, tok,
209: 0, NULL, 0, NULL);
210: if (mdoc_isdelim(args[0]))
211: return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_NOPUNCT));
212: mdoc_word_alloc(mdoc, pos, args[0]);
213: }
214:
215: if (1 == sz)
216: return(1);
217: if (mdoc_isdelim(args[1]))
218: return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_NOPUNCT));
219: mdoc_word_alloc(mdoc, pos, args[1]);
220: return(1);
221:
1.12 ! kristaps 222: case (MDOC_Nd):
! 223: if (sz > 0)
! 224: break;
! 225: if ( ! mdoc_warn(mdoc, tok, pos, WARN_ARGS_GE1))
! 226: return(0);
! 227: break;
! 228:
! 229: case (MDOC_Hf):
! 230: if (1 == sz)
! 231: break;
! 232: return(mdoc_err(mdoc, tok, pos, ERR_ARGS_EQ1));
! 233:
1.10 kristaps 234: case (MDOC_Bx):
235: /* FALLTHROUGH */
236: case (MDOC_Bsx):
237: /* FALLTHROUGH */
238: case (MDOC_Os):
239: /* FALLTHROUGH */
240: case (MDOC_Fx):
241: /* FALLTHROUGH */
242: case (MDOC_Nx):
243: assert(sz <= 1);
244: break;
245:
246: case (MDOC_Ux):
247: assert(0 == sz);
248: break;
249:
1.11 kristaps 250: case (MDOC_Bt):
251: /* FALLTHROUGH */
252: case (MDOC_Ud):
253: if (0 == sz)
254: break;
255: return(mdoc_err(mdoc, tok, pos, ERR_ARGS_EQ0));
256:
1.10 kristaps 257: /* ======= ADD MORE MACRO CHECKS ABOVE. ======= */
258: default:
259: abort();
260: /* NOTREACHED */
261: }
262:
263: mdoc_elem_alloc(mdoc, pos, tok, 0, NULL, (size_t)sz, _CC(args));
264: return(1);
265: }
266:
267:
268: static int
1.3 kristaps 269: append_text(struct mdoc *mdoc, int tok,
270: int pos, int sz, char *args[])
1.1 kristaps 271: {
272:
1.3 kristaps 273: assert(sz >= 0);
1.2 kristaps 274: args[sz] = NULL;
275:
276: switch (tok) {
1.4 kristaps 277: /* ======= ADD MORE MACRO CHECKS BELOW. ======= */
1.7 kristaps 278: case (MDOC_Pp):
279: if (0 == sz)
280: break;
281: if ( ! mdoc_warn(mdoc, tok, pos, WARN_ARGS_EQ0))
282: return(0);
283: break;
284:
1.2 kristaps 285: case (MDOC_Ft):
286: /* FALLTHROUGH */
287: case (MDOC_Li):
288: /* FALLTHROUGH */
289: case (MDOC_Ms):
290: /* FALLTHROUGH */
291: case (MDOC_Pa):
292: /* FALLTHROUGH */
293: case (MDOC_Tn):
1.4 kristaps 294: if (0 < sz)
295: break;
296: if ( ! mdoc_warn(mdoc, tok, pos, WARN_ARGS_GE1))
1.1 kristaps 297: return(0);
1.4 kristaps 298: break;
1.7 kristaps 299:
1.2 kristaps 300: case (MDOC_Ar):
301: /* FALLTHROUGH */
302: case (MDOC_Cm):
303: /* FALLTHROUGH */
304: case (MDOC_Fl):
1.7 kristaps 305: /* These can have no arguments. */
1.4 kristaps 306: break;
1.7 kristaps 307:
1.2 kristaps 308: case (MDOC_Ad):
309: /* FALLTHROUGH */
310: case (MDOC_Em):
311: /* FALLTHROUGH */
312: case (MDOC_Er):
313: /* FALLTHROUGH */
314: case (MDOC_Ev):
315: /* FALLTHROUGH */
316: case (MDOC_Fa):
317: /* FALLTHROUGH */
318: case (MDOC_Dv):
319: /* FALLTHROUGH */
320: case (MDOC_Ic):
321: /* FALLTHROUGH */
1.12 ! kristaps 322: case (MDOC_Sy):
! 323: /* FALLTHROUGH */
! 324: case (MDOC_Sx):
! 325: /* FALLTHROUGH */
1.2 kristaps 326: case (MDOC_Va):
327: /* FALLTHROUGH */
328: case (MDOC_Vt):
1.4 kristaps 329: if (0 < sz)
330: break;
331: return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
332: /* ======= ADD MORE MACRO CHECKS ABOVE. ======= */
1.2 kristaps 333: default:
1.4 kristaps 334: abort();
335: /* NOTREACHED */
1.2 kristaps 336: }
337:
1.7 kristaps 338: mdoc_elem_alloc(mdoc, pos, tok, 0, NULL, (size_t)sz, _CC(args));
1.4 kristaps 339: return(1);
1.2 kristaps 340: }
341:
1.1 kristaps 342:
1.2 kristaps 343: int
1.5 kristaps 344: macro_text(MACRO_PROT_ARGS)
1.2 kristaps 345: {
1.7 kristaps 346: int lastarg, lastpunct, c, j;
1.2 kristaps 347: char *args[MDOC_LINEARG_MAX], *p;
1.1 kristaps 348:
1.5 kristaps 349: if (SEC_PROLOGUE == mdoc->sec_lastn)
350: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
351:
1.7 kristaps 352: /* Token pre-processing. */
353:
354: switch (tok) {
355: case (MDOC_Pp):
356: /* `.Pp' ignored when following `.Sh' or `.Ss'. */
357: assert(mdoc->last);
358: if (MDOC_BODY != mdoc->last->type)
359: break;
360: switch (mdoc->last->data.body.tok) {
361: case (MDOC_Ss):
362: /* FALLTHROUGH */
363: case (MDOC_Sh):
364: if ( ! mdoc_warn(mdoc, tok, ppos, WARN_IGN_AFTER_BLK))
365: return(0);
366: return(1);
367: default:
368: break;
369: }
370: break;
371: default:
372: break;
373: }
374:
375: /* Process line parameters. */
376:
377: j = 0;
378: lastarg = ppos;
379: lastpunct = 0;
380:
1.2 kristaps 381: again:
1.7 kristaps 382: if (j == MDOC_LINEARG_MAX)
383: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
384:
385: /*
386: * Parse out the next argument, unquoted and unescaped. If
387: * we're a word (which may be punctuation followed eventually by
388: * a real word), then fall into checking for callables. If
389: * only punctuation remains and we're the first, then flush
390: * arguments, punctuation and exit; else, return to the caller.
391: */
392:
1.6 kristaps 393: lastarg = *pos;
1.2 kristaps 394:
1.7 kristaps 395: switch (mdoc_args(mdoc, tok, pos, buf, ARGS_DELIM, &args[j])) {
396: case (ARGS_ERROR):
1.2 kristaps 397: return(0);
1.7 kristaps 398: case (ARGS_WORD):
399: break;
400: case (ARGS_PUNCT):
401: if ( ! lastpunct && ! append_text(mdoc, tok, ppos, j, args))
402: return(0);
1.8 kristaps 403: if (ppos > 1)
404: return(1);
1.7 kristaps 405: return(append_delims(mdoc, tok, pos, buf));
406: case (ARGS_EOLN):
1.8 kristaps 407: if (lastpunct)
408: return(1);
1.7 kristaps 409: return(append_text(mdoc, tok, ppos, j, args));
410: default:
411: abort();
412: /* NOTREACHED */
413: }
1.2 kristaps 414:
1.7 kristaps 415: /*
416: * Command found. First flush out arguments, then call the
417: * command. If we're the line macro when it exits, flush
418: * terminal punctuation.
419: */
1.2 kristaps 420:
421: if (MDOC_MAX != (c = mdoc_find(mdoc, args[j]))) {
1.7 kristaps 422: if ( ! lastpunct && ! append_text(mdoc, tok, ppos, j, args))
423: return(0);
424: if ( ! mdoc_macro(mdoc, c, lastarg, pos, buf))
425: return(0);
426: if (ppos > 1)
427: return(1);
428: return(append_delims(mdoc, tok, pos, buf));
1.2 kristaps 429: }
430:
1.7 kristaps 431: /* Word/non-term-punctuation found. */
1.2 kristaps 432:
1.4 kristaps 433: if ( ! mdoc_isdelim(args[j])) {
1.7 kristaps 434: /* Words are appended to the array of arguments. */
1.2 kristaps 435: j++;
1.8 kristaps 436: lastpunct = 0;
1.2 kristaps 437: goto again;
438: }
439:
1.7 kristaps 440: /*
441: * For punctuation, flush all collected words, then flush
442: * punctuation, then start collecting again. Of course, this
443: * is non-terminal punctuation.
444: */
1.2 kristaps 445:
1.7 kristaps 446: p = args[j];
447: if ( ! lastpunct && ! append_text(mdoc, tok, ppos, j, args))
448: return(0);
1.2 kristaps 449:
1.7 kristaps 450: mdoc_word_alloc(mdoc, lastarg, p);
451: j = 0;
1.2 kristaps 452: lastpunct = 1;
453:
454: goto again;
455: /* NOTREACHED */
456: }
1.1 kristaps 457:
458:
1.2 kristaps 459: int
1.5 kristaps 460: macro_prologue_dtitle(MACRO_PROT_ARGS)
461: {
1.7 kristaps 462: int lastarg, j;
1.5 kristaps 463: char *args[MDOC_LINEARG_MAX];
464:
465: if (SEC_PROLOGUE != mdoc->sec_lastn)
466: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_NPROLOGUE));
467: if (0 == mdoc->meta.date)
468: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_OO));
469: if (mdoc->meta.title[0])
470: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_REP));
471:
472: j = -1;
1.7 kristaps 473: lastarg = ppos;
1.5 kristaps 474:
475: again:
1.6 kristaps 476: if (j == MDOC_LINEARG_MAX)
477: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
1.5 kristaps 478:
1.7 kristaps 479: lastarg = *pos;
480:
481: switch (mdoc_args(mdoc, tok, pos, buf, 0, &args[++j])) {
482: case (ARGS_EOLN):
1.5 kristaps 483: if (mdoc->meta.title)
484: return(1);
485: if ( ! mdoc_warn(mdoc, tok, ppos, WARN_ARGS_GE1))
486: return(0);
487: (void)xstrlcpy(mdoc->meta.title,
488: "UNTITLED", META_TITLE_SZ);
489: return(1);
1.7 kristaps 490: case (ARGS_ERROR):
1.5 kristaps 491: return(0);
1.7 kristaps 492: default:
493: break;
494: }
495:
1.5 kristaps 496: if (MDOC_MAX != mdoc_find(mdoc, args[j]) && ! mdoc_warn
497: (mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
498: return(0);
499:
500: if (0 == j) {
501: if (xstrlcpy(mdoc->meta.title, args[0], META_TITLE_SZ))
502: goto again;
1.7 kristaps 503: return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.5 kristaps 504:
505: } else if (1 == j) {
506: mdoc->meta.msec = mdoc_atomsec(args[1]);
507: if (MSEC_DEFAULT != mdoc->meta.msec)
508: goto again;
1.7 kristaps 509: return(mdoc_err(mdoc, tok, -1, ERR_SYNTAX_ARGFORM));
1.5 kristaps 510:
511: } else if (2 == j) {
512: mdoc->meta.vol = mdoc_atovol(args[2]);
513: if (VOL_DEFAULT != mdoc->meta.vol)
514: goto again;
515: mdoc->meta.arch = mdoc_atoarch(args[2]);
516: if (ARCH_DEFAULT != mdoc->meta.arch)
517: goto again;
1.7 kristaps 518: return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.5 kristaps 519: }
520:
521: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
522: }
523:
524:
525: int
1.6 kristaps 526: macro_prologue_os(MACRO_PROT_ARGS)
527: {
1.7 kristaps 528: int lastarg, j;
1.6 kristaps 529: char *args[MDOC_LINEARG_MAX];
530:
531: if (SEC_PROLOGUE != mdoc->sec_lastn)
532: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_NPROLOGUE));
533: if (0 == mdoc->meta.title[0])
534: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_OO));
535: if (mdoc->meta.os[0])
536: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_REP));
537:
538: j = -1;
1.7 kristaps 539: lastarg = ppos;
1.6 kristaps 540:
541: again:
542: if (j == MDOC_LINEARG_MAX)
543: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
544:
1.7 kristaps 545: lastarg = *pos;
546:
547: switch (mdoc_args(mdoc, tok, pos, buf,
548: ARGS_QUOTED, &args[++j])) {
549: case (ARGS_EOLN):
1.6 kristaps 550: mdoc->sec_lastn = mdoc->sec_last = SEC_BODY;
551: return(1);
1.7 kristaps 552: case (ARGS_ERROR):
1.6 kristaps 553: return(0);
1.7 kristaps 554: default:
555: break;
556: }
1.6 kristaps 557:
558: if ( ! xstrlcat(mdoc->meta.os, args[j], sizeof(mdoc->meta.os)))
1.7 kristaps 559: return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.6 kristaps 560: if ( ! xstrlcat(mdoc->meta.os, " ", sizeof(mdoc->meta.os)))
1.7 kristaps 561: return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.6 kristaps 562:
563: goto again;
564: /* NOTREACHED */
565: }
566:
567:
568: int
1.5 kristaps 569: macro_prologue_ddate(MACRO_PROT_ARGS)
570: {
1.7 kristaps 571: int lastarg, j;
1.5 kristaps 572: char *args[MDOC_LINEARG_MAX], date[64];
573:
574: if (SEC_PROLOGUE != mdoc->sec_lastn)
575: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_NPROLOGUE));
576: if (mdoc->meta.title[0])
577: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_OO));
578: if (mdoc->meta.date)
579: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_REP));
580:
581: j = -1;
582: date[0] = 0;
1.7 kristaps 583: lastarg = ppos;
1.5 kristaps 584:
585: again:
1.6 kristaps 586: if (j == MDOC_LINEARG_MAX)
587: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
588:
1.7 kristaps 589: lastarg = *pos;
590: switch (mdoc_args(mdoc, tok, pos, buf, 0, &args[++j])) {
591: case (ARGS_EOLN):
1.5 kristaps 592: if (mdoc->meta.date)
593: return(1);
594: mdoc->meta.date = mdoc_atotime(date);
595: if (mdoc->meta.date)
596: return(1);
1.7 kristaps 597: return(mdoc_err(mdoc, tok, ppos, ERR_SYNTAX_ARGFORM));
598: case (ARGS_ERROR):
1.5 kristaps 599: return(0);
1.7 kristaps 600: default:
601: break;
602: }
1.5 kristaps 603:
604: if (MDOC_MAX != mdoc_find(mdoc, args[j]) && ! mdoc_warn
605: (mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
606: return(0);
607:
608: if (0 == j) {
609: if (xstrcmp("$Mdocdate$", args[j])) {
610: mdoc->meta.date = time(NULL);
611: goto again;
612: } else if (xstrcmp("$Mdocdate:", args[j]))
613: goto again;
614: } else if (4 == j)
615: if ( ! xstrcmp("$", args[j]))
616: goto again;
617:
618: if ( ! xstrlcat(date, args[j], sizeof(date)))
1.7 kristaps 619: return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.5 kristaps 620: if ( ! xstrlcat(date, " ", sizeof(date)))
1.7 kristaps 621: return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.5 kristaps 622:
623: goto again;
624: /* NOTREACHED */
625: }
626:
627:
628: int
1.6 kristaps 629: macro_scoped_explicit(MACRO_PROT_ARGS)
630: {
631: int c, lastarg, j;
632: struct mdoc_arg argv[MDOC_LINEARG_MAX];
1.7 kristaps 633: struct mdoc_node *n;
1.6 kristaps 634:
635: if (SEC_PROLOGUE == mdoc->sec_lastn)
636: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
637:
638: /*
639: * First close out the explicit scope. The `end' tags (such as
640: * `.El' to `.Bl' don't cause anything to happen: we merely
641: * readjust our last parse point.
642: */
643:
644: switch (tok) {
645: case (MDOC_El):
646: return(scope_rewind_exp(mdoc, ppos, tok, MDOC_Bl));
1.7 kristaps 647: case (MDOC_Ed):
648: return(scope_rewind_exp(mdoc, ppos, tok, MDOC_Bd));
1.6 kristaps 649: default:
650: break;
651: }
652:
653: assert(MDOC_EXPLICIT & mdoc_macros[tok].flags);
654:
1.7 kristaps 655: /* Token pre-processing. */
656:
657: switch (tok) {
658: case (MDOC_Bl):
659: /* FALLTHROUGH */
660: case (MDOC_Bd):
661: /* `.Pp' ignored when preceding `.Bl' or `.Bd'. */
662: assert(mdoc->last);
663: if (MDOC_ELEM != mdoc->last->type)
664: break;
665: if (MDOC_Pp != mdoc->last->data.elem.tok)
666: break;
667: if ( ! mdoc_warn(mdoc, tok, ppos, WARN_IGN_BEFORE_BLK))
668: return(0);
669: assert(mdoc->last->prev);
670: n = mdoc->last;
671: mdoc->last = mdoc->last->prev;
672: mdoc->last->next = NULL;
673: mdoc_node_free(n);
674: break;
675: default:
676: break;
677: }
678:
1.6 kristaps 679: lastarg = *pos;
680:
681: for (j = 0; j < MDOC_LINEARG_MAX; j++) {
682: lastarg = *pos;
1.7 kristaps 683: c = mdoc_argv(mdoc, tok, &argv[j], pos, buf);
1.6 kristaps 684: if (0 == c)
685: break;
686: else if (1 == c)
687: continue;
688:
689: mdoc_argv_free(j, argv);
690: return(0);
691: }
692:
693: if (MDOC_LINEARG_MAX == j) {
694: mdoc_argv_free(j, argv);
695: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
696: }
697:
698: c = append_scoped(mdoc, tok, ppos, 0, NULL, j, argv);
699: mdoc_argv_free(j, argv);
700: return(c);
701: }
702:
703:
1.8 kristaps 704: /*
705: * Implicity-scoped macros, like `.Ss', have a scope that terminates
706: * with a subsequent call to the same macro. Implicit macros cannot
707: * break the scope of explicitly-scoped macros; however, they can break
708: * the scope of other implicit macros (so `.Sh' can break `.Ss'). This
709: * is ok with macros like `.It' because they exist only within an
710: * explicit context.
711: *
712: * These macros put line arguments (which it's allowed to have) into the
713: * HEAD section and open a BODY scope to be used until the macro scope
714: * closes.
715: */
1.6 kristaps 716: int
1.5 kristaps 717: macro_scoped_implicit(MACRO_PROT_ARGS)
1.2 kristaps 718: {
1.7 kristaps 719: int lastarg, j;
1.2 kristaps 720: char *args[MDOC_LINEARG_MAX];
721: struct mdoc_node *n;
722:
1.5 kristaps 723: assert( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags));
1.1 kristaps 724:
1.5 kristaps 725: if (SEC_PROLOGUE == mdoc->sec_lastn)
726: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
1.1 kristaps 727:
1.7 kristaps 728: /* Token pre-processing. */
1.6 kristaps 729:
1.7 kristaps 730: switch (tok) {
731: case (MDOC_Ss):
732: /* FALLTHROUGH */
733: case (MDOC_Sh):
734: /* `.Pp' ignored when preceding `.Ss' or `.Sh'. */
735: if (NULL == mdoc->last)
736: break;
737: if (MDOC_ELEM != mdoc->last->type)
738: break;
739: if (MDOC_Pp != mdoc->last->data.elem.tok)
1.1 kristaps 740: break;
1.7 kristaps 741: if ( ! mdoc_warn(mdoc, tok, ppos, WARN_IGN_BEFORE_BLK))
742: return(0);
743: assert(mdoc->last->prev);
744: n = mdoc->last;
1.8 kristaps 745: mdoc_msg(mdoc, ppos, "removing prior `Pp' macro");
1.7 kristaps 746: mdoc->last = mdoc->last->prev;
747: mdoc->last->next = NULL;
748: mdoc_node_free(n);
749: break;
750: default:
751: break;
1.2 kristaps 752: }
753:
1.8 kristaps 754: /* Rewind our scope. */
755:
756: if ( ! scope_rewind_imp(mdoc, ppos, tok))
757: return(0);
1.2 kristaps 758:
759: j = 0;
1.7 kristaps 760: lastarg = ppos;
1.2 kristaps 761:
1.8 kristaps 762: /*
763: * Process until we hit a line. Note that current implicit
764: * macros don't have any arguments, so we don't need to do any
765: * argument processing.
766: */
767:
1.2 kristaps 768: again:
1.7 kristaps 769: if (j == MDOC_LINEARG_MAX)
770: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
771:
1.6 kristaps 772: lastarg = *pos;
1.2 kristaps 773:
1.7 kristaps 774: switch (mdoc_args(mdoc, tok, pos, buf, 0, &args[j])) {
775: case (ARGS_ERROR):
1.2 kristaps 776: return(0);
1.7 kristaps 777: case (ARGS_EOLN):
778: return(append_scoped(mdoc, tok, ppos, j, _CC(args), 0, NULL));
779: default:
780: break;
781: }
1.1 kristaps 782:
1.7 kristaps 783: if (MDOC_MAX != mdoc_find(mdoc, args[j]))
1.3 kristaps 784: if ( ! mdoc_warn(mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
1.1 kristaps 785: return(0);
786:
1.2 kristaps 787: j++;
788: goto again;
1.8 kristaps 789: /* NOTREACHED */
790: }
791:
792:
793: /*
794: * A line-scoped macro opens a scope for the contents of its line, which
795: * are placed under the HEAD node. Punctuation trailing the line is put
796: * as a sibling to the HEAD node, under the BLOCK node.
797: */
798: int
799: macro_scoped_line(MACRO_PROT_ARGS)
800: {
801: int lastarg, c, j;
802: char *p;
803: struct mdoc_node *n;
804:
805: if (SEC_PROLOGUE == mdoc->sec_lastn)
806: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
807:
808: assert(1 == ppos);
809:
810: /* Token pre-processing. */
811:
812: switch (tok) {
813: case (MDOC_D1):
814: /* FALLTHROUGH */
815: case (MDOC_Dl):
816: /* These can't be nested in a display block. */
817: assert(mdoc->last);
818: for (n = mdoc->last->parent ; n; n = n->parent)
819: if (MDOC_BLOCK != n->type)
820: continue;
821: else if (MDOC_Bd == n->data.block.tok)
822: break;
823: if (NULL == n)
824: break;
825: return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_NONEST));
826: default:
827: break;
828: }
829:
830: /*
831: * All line-scoped macros have a HEAD and optionally a BODY
832: * section. We open our scope here; when we exit this function,
833: * we'll rewind our scope appropriately.
834: */
835:
836: mdoc_block_alloc(mdoc, ppos, tok, 0, NULL);
837: mdoc_head_alloc(mdoc, ppos, tok, 0, NULL);
838:
839: /* Process line parameters. */
840:
841: j = 0;
842: lastarg = ppos;
843:
844: again:
845: if (j == MDOC_LINEARG_MAX)
846: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
847:
848: lastarg = *pos;
849: c = mdoc_args(mdoc, tok, pos, buf, ARGS_DELIM, &p);
850:
851: switch (c) {
852: case (ARGS_ERROR):
853: return(0);
854: case (ARGS_WORD):
855: break;
856: case (ARGS_PUNCT):
857: if ( ! append_delims(mdoc, tok, pos, buf))
858: return(0);
859: return(scope_rewind_imp(mdoc, ppos, tok));
860: case (ARGS_EOLN):
861: return(scope_rewind_imp(mdoc, ppos, tok));
862: default:
863: abort();
864: /* NOTREACHED */
865: }
866:
867: if (MDOC_MAX != (c = mdoc_find(mdoc, p))) {
868: if ( ! mdoc_macro(mdoc, c, lastarg, pos, buf))
869: return(0);
870: if ( ! append_delims(mdoc, tok, pos, buf))
871: return(0);
872: return(scope_rewind_imp(mdoc, ppos, tok));
873: }
1.1 kristaps 874:
1.8 kristaps 875: if (mdoc_isdelim(p))
876: j = 0;
877:
878: mdoc_word_alloc(mdoc, lastarg, p);
879: goto again;
1.2 kristaps 880: /* NOTREACHED */
1.1 kristaps 881: }
1.5 kristaps 882:
1.7 kristaps 883:
1.9 kristaps 884: /*
885: * Partial-line scope is identical to line scope (macro_scoped_line())
886: * except that trailing punctuation is appended to the BLOCK, instead of
887: * contained within the HEAD.
888: */
1.7 kristaps 889: int
1.8 kristaps 890: macro_scoped_pline(MACRO_PROT_ARGS)
1.7 kristaps 891: {
1.8 kristaps 892: int lastarg, c, j;
893: char *p;
1.7 kristaps 894:
1.8 kristaps 895: if (SEC_PROLOGUE == mdoc->sec_lastn)
896: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
897:
898: /* Token pre-processing. */
899:
900: switch (tok) {
1.9 kristaps 901: case (MDOC_Ql):
902: if ( ! mdoc_warn(mdoc, tok, ppos, WARN_COMPAT_TROFF))
903: return(0);
904: break;
1.8 kristaps 905: default:
906: break;
907: }
908:
909: mdoc_block_alloc(mdoc, ppos, tok, 0, NULL);
910: mdoc_head_alloc(mdoc, ppos, tok, 0, NULL);
911:
912: /* Process line parameters. */
913:
914: j = 0;
915: lastarg = ppos;
916:
917: again:
918: if (j == MDOC_LINEARG_MAX)
919: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
920:
921: lastarg = *pos;
922: c = mdoc_args(mdoc, tok, pos, buf, ARGS_DELIM, &p);
923:
924: switch (c) {
925: case (ARGS_ERROR):
926: return(0);
927: case (ARGS_WORD):
928: break;
929: case (ARGS_PUNCT):
930: if ( ! scope_rewind_imp(mdoc, ppos, tok))
931: return(0);
932: if (ppos > 1)
933: return(1);
934: return(append_delims(mdoc, tok, pos, buf));
935: case (ARGS_EOLN):
936: return(scope_rewind_imp(mdoc, ppos, tok));
937: default:
938: abort();
939: /* NOTREACHED */
940: }
941:
942: if (MDOC_MAX != (c = mdoc_find(mdoc, p))) {
943: if ( ! mdoc_macro(mdoc, c, lastarg, pos, buf))
944: return(0);
945: if ( ! scope_rewind_imp(mdoc, ppos, tok))
946: return(0);
947: if (ppos > 1)
948: return(1);
949: return(append_delims(mdoc, tok, pos, buf));
950: }
951:
952: if (mdoc_isdelim(p))
953: j = 0;
954:
955: mdoc_word_alloc(mdoc, lastarg, p);
956: goto again;
957: /* NOTREACHED */
1.7 kristaps 958: }
1.8 kristaps 959:
1.10 kristaps 960:
961: /*
962: * A delimited-constant macro is similar to a general text macro: the
963: * macro is followed by a 0 or 1 arguments (possibly-unspecified) then
964: * terminating punctuation, other words, or another callable macro.
965: */
966: int
967: macro_constant_delimited(MACRO_PROT_ARGS)
968: {
969: int lastarg, flushed, c, maxargs;
970: char *p, *pp;
971:
972: if (SEC_PROLOGUE == mdoc->sec_lastn)
973: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
974:
975: /* Process line parameters. */
976:
977: lastarg = ppos;
978: flushed = 0;
979:
1.11 kristaps 980: /* Token pre-processing. */
981:
1.10 kristaps 982: switch (tok) {
983: case (MDOC_Ux):
984: maxargs = 0;
985: break;
986: default:
987: maxargs = 1;
988: break;
989: }
990:
991: again:
992: lastarg = *pos;
993:
994: switch (mdoc_args(mdoc, tok, pos, buf, ARGS_DELIM, &p)) {
995: case (ARGS_ERROR):
996: return(0);
997: case (ARGS_WORD):
998: break;
999: case (ARGS_PUNCT):
1000: if ( ! flushed && ! append_const(mdoc, tok, ppos, 0, &p))
1001: return(0);
1002: if (ppos > 1)
1003: return(1);
1004: return(append_delims(mdoc, tok, pos, buf));
1005: case (ARGS_EOLN):
1006: if (flushed)
1007: return(1);
1008: return(append_const(mdoc, tok, ppos, 0, &p));
1009: default:
1010: abort();
1011: /* NOTREACHED */
1012: }
1013:
1.11 kristaps 1014: /* Accepts no arguments: flush out symbol and continue. */
1015:
1.10 kristaps 1016: if (0 == maxargs) {
1017: pp = p;
1018: if ( ! append_const(mdoc, tok, ppos, 0, &p))
1019: return(0);
1020: p = pp;
1021: flushed = 1;
1022: }
1023:
1024: if (MDOC_MAX != (c = mdoc_find(mdoc, p))) {
1025: if ( ! flushed && ! append_const(mdoc, tok, ppos, 0, &p))
1026: return(0);
1027: if ( ! mdoc_macro(mdoc, c, lastarg, pos, buf))
1028: return(0);
1029: if (ppos > 1)
1030: return(1);
1031: return(append_delims(mdoc, tok, pos, buf));
1032: }
1033:
1.11 kristaps 1034: /*
1035: * We only accept one argument; subsequent tokens are considered
1036: * as literal words (until a macro).
1037: */
1038:
1.10 kristaps 1039: if ( ! flushed && ! mdoc_isdelim(p)) {
1040: if ( ! append_const(mdoc, tok, ppos, 1, &p))
1041: return(0);
1042: flushed = 1;
1043: goto again;
1044: } else if ( ! flushed) {
1045: pp = p;
1046: if ( ! append_const(mdoc, tok, ppos, 0, &p))
1047: return(0);
1048: p = pp;
1049: flushed = 1;
1050: }
1051:
1052: mdoc_word_alloc(mdoc, lastarg, p);
1053: goto again;
1054: /* NOTREACHED */
1055: }
1.11 kristaps 1056:
1057:
1058: int
1059: macro_constant(MACRO_PROT_ARGS)
1060: {
1061: int lastarg, j;
1062: char *args[MDOC_LINEARG_MAX];
1063:
1064: if (SEC_PROLOGUE == mdoc->sec_lastn)
1065: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
1066:
1067: j = 0;
1068:
1069: again:
1070: if (j == MDOC_LINEARG_MAX)
1071: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
1072:
1073: lastarg = *pos;
1074:
1075: switch (mdoc_args(mdoc, tok, pos, buf, 0, &args[j])) {
1076: case (ARGS_ERROR):
1077: return(0);
1078: case (ARGS_WORD):
1079: break;
1080: case (ARGS_EOLN):
1081: return(append_const(mdoc, tok, ppos, j, args));
1082: default:
1083: abort();
1084: /* NOTREACHED */
1085: }
1086:
1087: if (MDOC_MAX != mdoc_find(mdoc, args[j]))
1088: if ( ! mdoc_warn(mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
1089: return(0);
1090:
1091: j++;
1092: goto again;
1093: /* NOTREACHED */
1094: }
CVSweb