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