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