Annotation of mandoc/macro.c, Revision 1.7
1.7 ! kristaps 1: /* $Id: macro.c,v 1.6 2008/12/23 05:30:49 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.2 kristaps 24:
25: #include "private.h"
26:
1.3 kristaps 27: #define _CC(p) ((const char **)p)
1.2 kristaps 28:
1.6 kristaps 29: static int scope_rewind_exp(struct mdoc *, int, int, int);
1.7 ! kristaps 30: static int scope_rewind_imp(struct mdoc *, int, int);
1.3 kristaps 31: static int append_text(struct mdoc *, int,
32: int, int, char *[]);
1.6 kristaps 33: static int append_scoped(struct mdoc *, int, int, int,
34: const char *[], int, const struct mdoc_arg *);
1.7 ! kristaps 35: static int append_delims(struct mdoc *, int, int *, char *);
1.6 kristaps 36:
37:
38: static int
1.7 ! kristaps 39: append_delims(struct mdoc *mdoc, int tok, int *pos, char *buf)
1.6 kristaps 40: {
1.7 ! kristaps 41: int c, lastarg;
! 42: char *p;
1.6 kristaps 43:
44: if (0 == buf[*pos])
1.7 ! kristaps 45: return(1);
1.6 kristaps 46:
1.7 ! kristaps 47: mdoc_msg(mdoc, *pos, "appending delimiters");
1.6 kristaps 48:
1.7 ! kristaps 49: for (;;) {
! 50: lastarg = *pos;
! 51: c = mdoc_args(mdoc, tok, pos, buf, 0, &p);
! 52: if (ARGS_ERROR == c)
! 53: return(0);
! 54: else if (ARGS_EOLN == c)
! 55: break;
! 56: assert(mdoc_isdelim(p));
! 57: mdoc_word_alloc(mdoc, lastarg, p);
1.6 kristaps 58: }
59:
60: return(1);
61: }
62:
63:
64: static int
1.7 ! kristaps 65: scope_rewind_imp(struct mdoc *mdoc, int ppos, int tok)
1.6 kristaps 66: {
67: struct mdoc_node *n;
1.7 ! kristaps 68: int t;
! 69:
! 70: n = mdoc->last ? mdoc->last->parent : NULL;
1.6 kristaps 71:
72: /* LINTED */
1.7 ! kristaps 73: for ( ; n; n = n->parent) {
1.6 kristaps 74: if (MDOC_BLOCK != n->type)
75: continue;
1.7 ! kristaps 76: if (tok == (t = n->data.block.tok))
1.6 kristaps 77: break;
1.7 ! kristaps 78: if ( ! (MDOC_EXPLICIT & mdoc_macros[t].flags))
! 79: continue;
1.6 kristaps 80: return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_BREAK));
81: }
82:
1.7 ! kristaps 83: if (n) {
! 84: mdoc->last = n;
! 85: mdoc_msg(mdoc, ppos, "scope: rewound implicit `%s'",
! 86: mdoc_macronames[tok]);
! 87: return(1);
! 88: }
1.6 kristaps 89:
1.7 ! kristaps 90: mdoc_msg(mdoc, ppos, "scope: new implicit `%s'",
! 91: mdoc_macronames[tok]);
1.6 kristaps 92: return(1);
93: }
94:
95:
96: static int
1.7 ! kristaps 97: scope_rewind_exp(struct mdoc *mdoc, int ppos, int tok, int dst)
1.6 kristaps 98: {
1.7 ! kristaps 99: struct mdoc_node *n;
1.6 kristaps 100:
1.7 ! kristaps 101: assert(mdoc->last);
1.6 kristaps 102:
1.7 ! kristaps 103: /* LINTED */
! 104: for (n = mdoc->last->parent; n; n = n->parent) {
! 105: if (MDOC_BLOCK != n->type)
! 106: continue;
! 107: if (dst == n->data.block.tok)
! 108: break;
! 109: return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_BREAK));
1.6 kristaps 110: }
111:
1.7 ! kristaps 112: if (NULL == (mdoc->last = n))
! 113: return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_NOCTX));
1.6 kristaps 114:
1.7 ! kristaps 115: mdoc_msg(mdoc, ppos, "scope: rewound explicit `%s' to `%s'",
! 116: mdoc_macronames[tok], mdoc_macronames[dst]);
1.2 kristaps 117:
1.1 kristaps 118: return(1);
119: }
120:
1.2 kristaps 121:
122: static int
1.6 kristaps 123: append_scoped(struct mdoc *mdoc, int tok, int pos,
124: int sz, const char *args[],
125: int argc, const struct mdoc_arg *argv)
1.2 kristaps 126: {
1.7 ! kristaps 127: enum mdoc_sec sec;
! 128: struct mdoc_node *node;
1.5 kristaps 129:
1.4 kristaps 130: switch (tok) {
131: /* ======= ADD MORE MACRO CHECKS BELOW. ======= */
132: case (MDOC_Sh):
1.6 kristaps 133: if (0 == sz)
134: return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
135:
1.5 kristaps 136: sec = mdoc_atosec((size_t)sz, _CC(args));
137: if (SEC_CUSTOM != sec && sec < mdoc->sec_lastn)
138: if ( ! mdoc_warn(mdoc, tok, pos, WARN_SEC_OO))
139: return(0);
140:
141: if (SEC_BODY == mdoc->sec_last && SEC_NAME != sec)
142: return(mdoc_err(mdoc, tok, pos, ERR_SEC_NAME));
143:
144: if (SEC_CUSTOM != sec)
145: mdoc->sec_lastn = sec;
146: mdoc->sec_last = sec;
1.4 kristaps 147: break;
1.6 kristaps 148:
1.4 kristaps 149: case (MDOC_Ss):
1.6 kristaps 150: if (0 == sz)
151: return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
152: break;
1.7 ! kristaps 153:
! 154: case (MDOC_Bd):
! 155: assert(mdoc->last);
! 156: for (node = mdoc->last->parent; node; node = node->parent) {
! 157: if (node->type != MDOC_BLOCK)
! 158: continue;
! 159: if (node->data.block.tok != MDOC_Bd)
! 160: continue;
! 161: return(mdoc_err(mdoc, tok, pos, ERR_SCOPE_NONEST));
! 162: }
! 163: break;
1.6 kristaps 164:
165: case (MDOC_Bl):
1.4 kristaps 166: break;
1.6 kristaps 167:
1.4 kristaps 168: /* ======= ADD MORE MACRO CHECKS ABOVE. ======= */
169: default:
170: abort();
171: /* NOTREACHED */
172: }
173:
1.6 kristaps 174: mdoc_block_alloc(mdoc, pos, tok, (size_t)argc, argv);
1.3 kristaps 175: mdoc_head_alloc(mdoc, pos, tok, (size_t)sz, _CC(args));
1.2 kristaps 176: mdoc_body_alloc(mdoc, pos, tok);
177: return(1);
178: }
179:
180:
1.1 kristaps 181: static int
1.3 kristaps 182: append_text(struct mdoc *mdoc, int tok,
183: int pos, int sz, char *args[])
1.1 kristaps 184: {
185:
1.3 kristaps 186: assert(sz >= 0);
1.2 kristaps 187: args[sz] = NULL;
188:
189: switch (tok) {
1.4 kristaps 190: /* ======= ADD MORE MACRO CHECKS BELOW. ======= */
1.7 ! kristaps 191: case (MDOC_Pp):
! 192: if (0 == sz)
! 193: break;
! 194: if ( ! mdoc_warn(mdoc, tok, pos, WARN_ARGS_EQ0))
! 195: return(0);
! 196: break;
! 197:
1.2 kristaps 198: case (MDOC_Ft):
199: /* FALLTHROUGH */
200: case (MDOC_Li):
201: /* FALLTHROUGH */
202: case (MDOC_Ms):
203: /* FALLTHROUGH */
204: case (MDOC_Pa):
205: /* FALLTHROUGH */
206: case (MDOC_Tn):
1.4 kristaps 207: if (0 < sz)
208: break;
209: if ( ! mdoc_warn(mdoc, tok, pos, WARN_ARGS_GE1))
1.1 kristaps 210: return(0);
1.4 kristaps 211: break;
1.7 ! kristaps 212:
1.2 kristaps 213: case (MDOC_Ar):
214: /* FALLTHROUGH */
215: case (MDOC_Cm):
216: /* FALLTHROUGH */
217: case (MDOC_Fl):
1.7 ! kristaps 218: /* These can have no arguments. */
1.4 kristaps 219: break;
1.7 ! kristaps 220:
1.2 kristaps 221: case (MDOC_Ad):
222: /* FALLTHROUGH */
223: case (MDOC_Em):
224: /* FALLTHROUGH */
225: case (MDOC_Er):
226: /* FALLTHROUGH */
227: case (MDOC_Ev):
228: /* FALLTHROUGH */
229: case (MDOC_Fa):
230: /* FALLTHROUGH */
231: case (MDOC_Dv):
232: /* FALLTHROUGH */
233: case (MDOC_Ic):
234: /* FALLTHROUGH */
235: case (MDOC_Va):
236: /* FALLTHROUGH */
237: case (MDOC_Vt):
1.4 kristaps 238: if (0 < sz)
239: break;
240: return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
241: /* ======= ADD MORE MACRO CHECKS ABOVE. ======= */
1.2 kristaps 242: default:
1.4 kristaps 243: abort();
244: /* NOTREACHED */
1.2 kristaps 245: }
246:
1.7 ! kristaps 247: mdoc_elem_alloc(mdoc, pos, tok, 0, NULL, (size_t)sz, _CC(args));
1.4 kristaps 248: return(1);
1.2 kristaps 249: }
250:
1.1 kristaps 251:
1.2 kristaps 252: int
1.5 kristaps 253: macro_text(MACRO_PROT_ARGS)
1.2 kristaps 254: {
1.7 ! kristaps 255: int lastarg, lastpunct, c, j;
1.2 kristaps 256: char *args[MDOC_LINEARG_MAX], *p;
1.1 kristaps 257:
1.5 kristaps 258: if (SEC_PROLOGUE == mdoc->sec_lastn)
259: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
260:
1.7 ! kristaps 261: /* Token pre-processing. */
! 262:
! 263: switch (tok) {
! 264: case (MDOC_Pp):
! 265: /* `.Pp' ignored when following `.Sh' or `.Ss'. */
! 266: assert(mdoc->last);
! 267: if (MDOC_BODY != mdoc->last->type)
! 268: break;
! 269: switch (mdoc->last->data.body.tok) {
! 270: case (MDOC_Ss):
! 271: /* FALLTHROUGH */
! 272: case (MDOC_Sh):
! 273: if ( ! mdoc_warn(mdoc, tok, ppos, WARN_IGN_AFTER_BLK))
! 274: return(0);
! 275: return(1);
! 276: default:
! 277: break;
! 278: }
! 279: break;
! 280: default:
! 281: break;
! 282: }
! 283:
! 284: /* Process line parameters. */
! 285:
! 286: j = 0;
! 287: lastarg = ppos;
! 288: lastpunct = 0;
! 289:
1.2 kristaps 290: again:
1.7 ! kristaps 291: if (j == MDOC_LINEARG_MAX)
! 292: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
! 293:
! 294: /*
! 295: * Parse out the next argument, unquoted and unescaped. If
! 296: * we're a word (which may be punctuation followed eventually by
! 297: * a real word), then fall into checking for callables. If
! 298: * only punctuation remains and we're the first, then flush
! 299: * arguments, punctuation and exit; else, return to the caller.
! 300: */
! 301:
1.6 kristaps 302: lastarg = *pos;
1.2 kristaps 303:
1.7 ! kristaps 304: switch (mdoc_args(mdoc, tok, pos, buf, ARGS_DELIM, &args[j])) {
! 305: case (ARGS_ERROR):
1.2 kristaps 306: return(0);
1.7 ! kristaps 307: case (ARGS_WORD):
! 308: break;
! 309: case (ARGS_PUNCT):
! 310: if ( ! lastpunct && ! append_text(mdoc, tok, ppos, j, args))
! 311: return(0);
! 312: return(append_delims(mdoc, tok, pos, buf));
! 313: case (ARGS_EOLN):
! 314: return(append_text(mdoc, tok, ppos, j, args));
! 315: default:
! 316: abort();
! 317: /* NOTREACHED */
! 318: }
1.2 kristaps 319:
1.7 ! kristaps 320: /*
! 321: * Command found. First flush out arguments, then call the
! 322: * command. If we're the line macro when it exits, flush
! 323: * terminal punctuation.
! 324: */
1.2 kristaps 325:
326: if (MDOC_MAX != (c = mdoc_find(mdoc, args[j]))) {
1.7 ! kristaps 327: if ( ! lastpunct && ! append_text(mdoc, tok, ppos, j, args))
! 328: return(0);
! 329: if ( ! mdoc_macro(mdoc, c, lastarg, pos, buf))
! 330: return(0);
! 331: if (ppos > 1)
! 332: return(1);
! 333: return(append_delims(mdoc, tok, pos, buf));
1.2 kristaps 334: }
335:
1.7 ! kristaps 336: /* Word/non-term-punctuation found. */
1.2 kristaps 337:
1.4 kristaps 338: if ( ! mdoc_isdelim(args[j])) {
1.7 ! kristaps 339: /* Words are appended to the array of arguments. */
1.2 kristaps 340: j++;
1.7 ! kristaps 341: lastpunct = 1;
1.2 kristaps 342: goto again;
343: }
344:
1.7 ! kristaps 345: /*
! 346: * For punctuation, flush all collected words, then flush
! 347: * punctuation, then start collecting again. Of course, this
! 348: * is non-terminal punctuation.
! 349: */
1.2 kristaps 350:
1.7 ! kristaps 351: p = args[j];
! 352: if ( ! lastpunct && ! append_text(mdoc, tok, ppos, j, args))
! 353: return(0);
1.2 kristaps 354:
1.7 ! kristaps 355: mdoc_word_alloc(mdoc, lastarg, p);
! 356: j = 0;
1.2 kristaps 357: lastpunct = 1;
358:
359: goto again;
360:
361: /* NOTREACHED */
362: }
1.1 kristaps 363:
364:
1.2 kristaps 365: int
1.5 kristaps 366: macro_prologue_dtitle(MACRO_PROT_ARGS)
367: {
1.7 ! kristaps 368: int lastarg, j;
1.5 kristaps 369: char *args[MDOC_LINEARG_MAX];
370:
371: if (SEC_PROLOGUE != mdoc->sec_lastn)
372: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_NPROLOGUE));
373: if (0 == mdoc->meta.date)
374: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_OO));
375: if (mdoc->meta.title[0])
376: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_REP));
377:
378: j = -1;
1.7 ! kristaps 379: lastarg = ppos;
1.5 kristaps 380:
381: again:
1.6 kristaps 382: if (j == MDOC_LINEARG_MAX)
383: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
1.5 kristaps 384:
1.7 ! kristaps 385: lastarg = *pos;
! 386:
! 387: switch (mdoc_args(mdoc, tok, pos, buf, 0, &args[++j])) {
! 388: case (ARGS_EOLN):
1.5 kristaps 389: if (mdoc->meta.title)
390: return(1);
391: if ( ! mdoc_warn(mdoc, tok, ppos, WARN_ARGS_GE1))
392: return(0);
393: (void)xstrlcpy(mdoc->meta.title,
394: "UNTITLED", META_TITLE_SZ);
395: return(1);
1.7 ! kristaps 396: case (ARGS_ERROR):
1.5 kristaps 397: return(0);
1.7 ! kristaps 398: default:
! 399: break;
! 400: }
! 401:
1.5 kristaps 402: if (MDOC_MAX != mdoc_find(mdoc, args[j]) && ! mdoc_warn
403: (mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
404: return(0);
405:
406: if (0 == j) {
407: if (xstrlcpy(mdoc->meta.title, args[0], META_TITLE_SZ))
408: goto again;
1.7 ! kristaps 409: return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.5 kristaps 410:
411: } else if (1 == j) {
412: mdoc->meta.msec = mdoc_atomsec(args[1]);
413: if (MSEC_DEFAULT != mdoc->meta.msec)
414: goto again;
1.7 ! kristaps 415: return(mdoc_err(mdoc, tok, -1, ERR_SYNTAX_ARGFORM));
1.5 kristaps 416:
417: } else if (2 == j) {
418: mdoc->meta.vol = mdoc_atovol(args[2]);
419: if (VOL_DEFAULT != mdoc->meta.vol)
420: goto again;
421: mdoc->meta.arch = mdoc_atoarch(args[2]);
422: if (ARCH_DEFAULT != mdoc->meta.arch)
423: goto again;
1.7 ! kristaps 424: return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.5 kristaps 425: }
426:
427: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
428: }
429:
430:
431: int
1.6 kristaps 432: macro_prologue_os(MACRO_PROT_ARGS)
433: {
1.7 ! kristaps 434: int lastarg, j;
1.6 kristaps 435: char *args[MDOC_LINEARG_MAX];
436:
437: if (SEC_PROLOGUE != mdoc->sec_lastn)
438: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_NPROLOGUE));
439: if (0 == mdoc->meta.title[0])
440: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_OO));
441: if (mdoc->meta.os[0])
442: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_REP));
443:
444: j = -1;
1.7 ! kristaps 445: lastarg = ppos;
1.6 kristaps 446:
447: again:
448: if (j == MDOC_LINEARG_MAX)
449: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
450:
1.7 ! kristaps 451: lastarg = *pos;
! 452:
! 453: switch (mdoc_args(mdoc, tok, pos, buf,
! 454: ARGS_QUOTED, &args[++j])) {
! 455: case (ARGS_EOLN):
1.6 kristaps 456: mdoc->sec_lastn = mdoc->sec_last = SEC_BODY;
457: return(1);
1.7 ! kristaps 458: case (ARGS_ERROR):
1.6 kristaps 459: return(0);
1.7 ! kristaps 460: default:
! 461: break;
! 462: }
1.6 kristaps 463:
464: if ( ! xstrlcat(mdoc->meta.os, args[j], sizeof(mdoc->meta.os)))
1.7 ! kristaps 465: return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.6 kristaps 466: if ( ! xstrlcat(mdoc->meta.os, " ", sizeof(mdoc->meta.os)))
1.7 ! kristaps 467: return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.6 kristaps 468:
469: goto again;
470: /* NOTREACHED */
471: }
472:
473:
474: int
1.5 kristaps 475: macro_prologue_ddate(MACRO_PROT_ARGS)
476: {
1.7 ! kristaps 477: int lastarg, j;
1.5 kristaps 478: char *args[MDOC_LINEARG_MAX], date[64];
479:
480: if (SEC_PROLOGUE != mdoc->sec_lastn)
481: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_NPROLOGUE));
482: if (mdoc->meta.title[0])
483: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_OO));
484: if (mdoc->meta.date)
485: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_REP));
486:
487: j = -1;
488: date[0] = 0;
1.7 ! kristaps 489: lastarg = ppos;
1.5 kristaps 490:
491: again:
1.6 kristaps 492: if (j == MDOC_LINEARG_MAX)
493: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
494:
1.7 ! kristaps 495: lastarg = *pos;
! 496: switch (mdoc_args(mdoc, tok, pos, buf, 0, &args[++j])) {
! 497: case (ARGS_EOLN):
1.5 kristaps 498: if (mdoc->meta.date)
499: return(1);
500: mdoc->meta.date = mdoc_atotime(date);
501: if (mdoc->meta.date)
502: return(1);
1.7 ! kristaps 503: return(mdoc_err(mdoc, tok, ppos, ERR_SYNTAX_ARGFORM));
! 504: case (ARGS_ERROR):
1.5 kristaps 505: return(0);
1.7 ! kristaps 506: default:
! 507: break;
! 508: }
1.5 kristaps 509:
510: if (MDOC_MAX != mdoc_find(mdoc, args[j]) && ! mdoc_warn
511: (mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
512: return(0);
513:
514: if (0 == j) {
515: if (xstrcmp("$Mdocdate$", args[j])) {
516: mdoc->meta.date = time(NULL);
517: goto again;
518: } else if (xstrcmp("$Mdocdate:", args[j]))
519: goto again;
520: } else if (4 == j)
521: if ( ! xstrcmp("$", args[j]))
522: goto again;
523:
524: if ( ! xstrlcat(date, args[j], sizeof(date)))
1.7 ! kristaps 525: return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.5 kristaps 526: if ( ! xstrlcat(date, " ", sizeof(date)))
1.7 ! kristaps 527: return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.5 kristaps 528:
529: goto again;
530: /* NOTREACHED */
531: }
532:
533:
534: int
1.6 kristaps 535: macro_scoped_explicit(MACRO_PROT_ARGS)
536: {
537: int c, lastarg, j;
538: struct mdoc_arg argv[MDOC_LINEARG_MAX];
1.7 ! kristaps 539: struct mdoc_node *n;
1.6 kristaps 540:
541: if (SEC_PROLOGUE == mdoc->sec_lastn)
542: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
543:
544: /*
545: * First close out the explicit scope. The `end' tags (such as
546: * `.El' to `.Bl' don't cause anything to happen: we merely
547: * readjust our last parse point.
548: */
549:
550: switch (tok) {
551: case (MDOC_El):
552: return(scope_rewind_exp(mdoc, ppos, tok, MDOC_Bl));
1.7 ! kristaps 553: case (MDOC_Ed):
! 554: return(scope_rewind_exp(mdoc, ppos, tok, MDOC_Bd));
1.6 kristaps 555: default:
556: break;
557: }
558:
559: assert(MDOC_EXPLICIT & mdoc_macros[tok].flags);
560:
1.7 ! kristaps 561: /* Token pre-processing. */
! 562:
! 563: switch (tok) {
! 564: case (MDOC_Bl):
! 565: /* FALLTHROUGH */
! 566: case (MDOC_Bd):
! 567: /* `.Pp' ignored when preceding `.Bl' or `.Bd'. */
! 568: assert(mdoc->last);
! 569: if (MDOC_ELEM != mdoc->last->type)
! 570: break;
! 571: if (MDOC_Pp != mdoc->last->data.elem.tok)
! 572: break;
! 573: if ( ! mdoc_warn(mdoc, tok, ppos, WARN_IGN_BEFORE_BLK))
! 574: return(0);
! 575: assert(mdoc->last->prev);
! 576: n = mdoc->last;
! 577: mdoc->last = mdoc->last->prev;
! 578: mdoc->last->next = NULL;
! 579: mdoc_node_free(n);
! 580: break;
! 581: default:
! 582: break;
! 583: }
! 584:
1.6 kristaps 585: lastarg = *pos;
586:
587: for (j = 0; j < MDOC_LINEARG_MAX; j++) {
588: lastarg = *pos;
1.7 ! kristaps 589: c = mdoc_argv(mdoc, tok, &argv[j], pos, buf);
1.6 kristaps 590: if (0 == c)
591: break;
592: else if (1 == c)
593: continue;
594:
595: mdoc_argv_free(j, argv);
596: return(0);
597: }
598:
599: if (MDOC_LINEARG_MAX == j) {
600: mdoc_argv_free(j, argv);
601: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
602: }
603:
604: c = append_scoped(mdoc, tok, ppos, 0, NULL, j, argv);
605: mdoc_argv_free(j, argv);
606: return(c);
607: }
608:
609:
610: int
1.5 kristaps 611: macro_scoped_implicit(MACRO_PROT_ARGS)
1.2 kristaps 612: {
1.7 ! kristaps 613: int lastarg, j;
1.2 kristaps 614: char *args[MDOC_LINEARG_MAX];
615: struct mdoc_node *n;
616:
1.5 kristaps 617: assert( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags));
1.1 kristaps 618:
1.5 kristaps 619: if (SEC_PROLOGUE == mdoc->sec_lastn)
620: return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
1.1 kristaps 621:
1.7 ! kristaps 622: /* Token pre-processing. */
1.6 kristaps 623:
1.7 ! kristaps 624: switch (tok) {
! 625: case (MDOC_Ss):
! 626: /* FALLTHROUGH */
! 627: case (MDOC_Sh):
! 628: /* `.Pp' ignored when preceding `.Ss' or `.Sh'. */
! 629: if (NULL == mdoc->last)
! 630: break;
! 631: if (MDOC_ELEM != mdoc->last->type)
! 632: break;
! 633: if (MDOC_Pp != mdoc->last->data.elem.tok)
1.1 kristaps 634: break;
1.7 ! kristaps 635: if ( ! mdoc_warn(mdoc, tok, ppos, WARN_IGN_BEFORE_BLK))
! 636: return(0);
! 637: assert(mdoc->last->prev);
! 638: n = mdoc->last;
! 639: mdoc->last = mdoc->last->prev;
! 640: mdoc->last->next = NULL;
! 641: mdoc_node_free(n);
! 642: break;
! 643: default:
! 644: break;
1.2 kristaps 645: }
646:
1.7 ! kristaps 647: switch (tok) {
! 648: case (MDOC_Sh):
! 649: /* FALLTHROUGH */
! 650: case (MDOC_Ss):
! 651: if ( ! scope_rewind_imp(mdoc, ppos, tok))
! 652: return(0);
! 653: break;
! 654: default:
! 655: break;
! 656: }
1.2 kristaps 657:
658: j = 0;
1.7 ! kristaps 659: lastarg = ppos;
1.2 kristaps 660:
661: again:
1.7 ! kristaps 662: if (j == MDOC_LINEARG_MAX)
! 663: return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
! 664:
1.6 kristaps 665: lastarg = *pos;
1.2 kristaps 666:
1.7 ! kristaps 667: switch (mdoc_args(mdoc, tok, pos, buf, 0, &args[j])) {
! 668: case (ARGS_ERROR):
1.2 kristaps 669: return(0);
1.7 ! kristaps 670: case (ARGS_EOLN):
! 671: return(append_scoped(mdoc, tok, ppos, j, _CC(args), 0, NULL));
! 672: default:
! 673: break;
! 674: }
1.1 kristaps 675:
1.2 kristaps 676: /* Command found. */
1.1 kristaps 677:
1.7 ! kristaps 678: if (MDOC_MAX != mdoc_find(mdoc, args[j]))
1.3 kristaps 679: if ( ! mdoc_warn(mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
1.1 kristaps 680: return(0);
681:
1.2 kristaps 682: /* Word found. */
683:
684: j++;
685: goto again;
1.1 kristaps 686:
1.2 kristaps 687: /* NOTREACHED */
1.1 kristaps 688: }
1.5 kristaps 689:
1.7 ! kristaps 690:
! 691: int
! 692: macro_scoped_line(MACRO_PROT_ARGS)
! 693: {
! 694:
! 695: return(1);
! 696: }
CVSweb