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