Annotation of mandoc/mdoc_macro.c, Revision 1.18
1.18 ! kristaps 1: /* $Id: mdoc_macro.c,v 1.17 2009/07/07 09:29:15 kristaps Exp $ */
1.1 kristaps 2: /*
1.9 kristaps 3: * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
1.1 kristaps 4: *
5: * Permission to use, copy, modify, and distribute this software for any
1.8 kristaps 6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
1.1 kristaps 8: *
1.8 kristaps 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1 kristaps 16: */
17: #include <assert.h>
18: #include <ctype.h>
19: #include <stdlib.h>
20: #include <stdio.h>
21: #include <string.h>
22:
23: #include "libmdoc.h"
24:
25: #define REWIND_REWIND (1 << 0)
26: #define REWIND_NOHALT (1 << 1)
27: #define REWIND_HALT (1 << 2)
28:
29: static int obsolete(MACRO_PROT_ARGS);
30: static int blk_part_exp(MACRO_PROT_ARGS);
31: static int in_line_eoln(MACRO_PROT_ARGS);
32: static int in_line_argn(MACRO_PROT_ARGS);
33: static int in_line(MACRO_PROT_ARGS);
34: static int blk_full(MACRO_PROT_ARGS);
35: static int blk_exp_close(MACRO_PROT_ARGS);
36: static int blk_part_imp(MACRO_PROT_ARGS);
37:
38: static int phrase(struct mdoc *, int, int, char *);
39: static int rew_dohalt(int, enum mdoc_type,
40: const struct mdoc_node *);
41: static int rew_alt(int);
42: static int rew_dobreak(int, const struct mdoc_node *);
43: static int rew_elem(struct mdoc *, int);
44: static int rew_impblock(struct mdoc *, int, int, int);
45: static int rew_expblock(struct mdoc *, int, int, int);
46: static int rew_subblock(enum mdoc_type,
47: struct mdoc *, int, int, int);
48: static int rew_last(struct mdoc *, struct mdoc_node *);
49: static int append_delims(struct mdoc *, int, int *, char *);
50: static int lookup(struct mdoc *, int, int, int, const char *);
51: static int swarn(struct mdoc *, enum mdoc_type, int, int,
52: const struct mdoc_node *);
53:
54: /* Central table of library: who gets parsed how. */
55:
56: const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
1.13 kristaps 57: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */
1.1 kristaps 58: { in_line_eoln, MDOC_PROLOGUE }, /* Dd */
59: { in_line_eoln, MDOC_PROLOGUE }, /* Dt */
60: { in_line_eoln, MDOC_PROLOGUE }, /* Os */
61: { blk_full, 0 }, /* Sh */
62: { blk_full, 0 }, /* Ss */
63: { in_line, 0 }, /* Pp */
64: { blk_part_imp, MDOC_PARSED }, /* D1 */
65: { blk_part_imp, MDOC_PARSED }, /* Dl */
66: { blk_full, MDOC_EXPLICIT }, /* Bd */
67: { blk_exp_close, MDOC_EXPLICIT }, /* Ed */
68: { blk_full, MDOC_EXPLICIT }, /* Bl */
69: { blk_exp_close, MDOC_EXPLICIT }, /* El */
70: { blk_full, MDOC_PARSED }, /* It */
71: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
1.10 kristaps 72: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* An */
1.1 kristaps 73: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
74: { in_line_eoln, MDOC_CALLABLE }, /* Cd */
75: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
76: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
77: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
78: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */
79: { in_line_eoln, 0 }, /* Ex */
80: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */
81: { in_line_eoln, 0 }, /* Fd */
82: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
83: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */
1.11 kristaps 84: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */
1.1 kristaps 85: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */
1.18 ! kristaps 86: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */
1.1 kristaps 87: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Li */
88: { in_line_eoln, 0 }, /* Nd */
89: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */
90: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
91: { obsolete, 0 }, /* Ot */
92: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
93: { in_line_eoln, 0 }, /* Rv */
94: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */
95: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
96: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */
97: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
98: { in_line_eoln, 0 }, /* %A */
99: { in_line_eoln, 0 }, /* %B */
100: { in_line_eoln, 0 }, /* %D */
101: { in_line_eoln, 0 }, /* %I */
102: { in_line_eoln, 0 }, /* %J */
103: { in_line_eoln, 0 }, /* %N */
104: { in_line_eoln, 0 }, /* %O */
105: { in_line_eoln, 0 }, /* %P */
106: { in_line_eoln, 0 }, /* %R */
107: { in_line_eoln, 0 }, /* %T */
108: { in_line_eoln, 0 }, /* %V */
109: { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */
110: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */
111: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */
112: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */
113: { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */
114: { blk_full, MDOC_EXPLICIT }, /* Bf */
115: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */
116: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */
117: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */
118: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */
119: { in_line_eoln, 0 }, /* Db */
120: { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */
121: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */
122: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */
123: { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */
124: { blk_exp_close, MDOC_EXPLICIT }, /* Ef */
125: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Em */
126: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
127: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */
1.11 kristaps 128: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */
1.1 kristaps 129: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* No */
130: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ns */
131: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */
132: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */
133: { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */
134: { in_line_argn, MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */
135: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */
136: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */
137: { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */
138: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */
139: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */
140: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */
141: { blk_exp_close, MDOC_EXPLICIT }, /* Re */
142: { blk_full, MDOC_EXPLICIT }, /* Rs */
143: { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */
144: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */
145: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */
146: { in_line_eoln, 0 }, /* Sm */
147: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */
148: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */
149: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
150: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */
151: { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
152: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
153: { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */
154: { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */
155: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */
156: { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */
157: { blk_full, MDOC_EXPLICIT }, /* Bk */
158: { blk_exp_close, MDOC_EXPLICIT }, /* Ek */
159: { in_line_eoln, 0 }, /* Bt */
160: { in_line_eoln, 0 }, /* Hf */
161: { obsolete, 0 }, /* Fr */
162: { in_line_eoln, 0 }, /* Ud */
163: { in_line_eoln, 0 }, /* Lb */
164: { in_line, 0 }, /* Lp */
1.12 kristaps 165: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */
166: { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */
1.1 kristaps 167: { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */
168: { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */
169: { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */
170: { in_line_eoln, 0 }, /* %C */
171: { obsolete, 0 }, /* Es */
172: { obsolete, 0 }, /* En */
173: { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */
174: { in_line_eoln, 0 }, /* %Q */
175: };
176:
177: const struct mdoc_macro * const mdoc_macros = __mdoc_macros;
178:
179:
180: static int
181: swarn(struct mdoc *mdoc, enum mdoc_type type,
182: int line, int pos, const struct mdoc_node *p)
183: {
184: const char *n, *t, *tt;
185:
186: n = t = "<root>";
187: tt = "block";
188:
189: switch (type) {
190: case (MDOC_BODY):
191: tt = "multi-line";
192: break;
193: case (MDOC_HEAD):
194: tt = "line";
195: break;
196: default:
197: break;
198: }
199:
200: switch (p->type) {
201: case (MDOC_BLOCK):
202: n = mdoc_macronames[p->tok];
203: t = "block";
204: break;
205: case (MDOC_BODY):
206: n = mdoc_macronames[p->tok];
207: t = "multi-line";
208: break;
209: case (MDOC_HEAD):
210: n = mdoc_macronames[p->tok];
211: t = "line";
212: break;
213: default:
214: break;
215: }
216:
217: if ( ! (MDOC_IGN_SCOPE & mdoc->pflags))
1.16 kristaps 218: return(mdoc_verr(mdoc, line, pos,
1.1 kristaps 219: "%s scope breaks %s scope of %s",
220: tt, t, n));
1.16 kristaps 221: return(mdoc_vwarn(mdoc, line, pos,
1.1 kristaps 222: "%s scope breaks %s scope of %s",
223: tt, t, n));
224: }
225:
226:
227: /*
228: * This is called at the end of parsing. It must traverse up the tree,
229: * closing out open [implicit] scopes. Obviously, open explicit scopes
230: * are errors.
231: */
232: int
1.2 kristaps 233: mdoc_macroend(struct mdoc *mdoc)
1.1 kristaps 234: {
235: struct mdoc_node *n;
236:
237: /* Scan for open explicit scopes. */
238:
239: n = MDOC_VALID & mdoc->last->flags ?
240: mdoc->last->parent : mdoc->last;
241:
242: for ( ; n; n = n->parent) {
243: if (MDOC_BLOCK != n->type)
244: continue;
245: if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags))
246: continue;
1.16 kristaps 247: return(mdoc_nerr(mdoc, n, EOPEN));
1.1 kristaps 248: }
249:
250: return(rew_last(mdoc, mdoc->first));
251: }
252:
253: static int
254: lookup(struct mdoc *mdoc, int line, int pos, int from, const char *p)
255: {
256: int res;
257:
1.6 kristaps 258: res = mdoc_hash_find(mdoc->htab, p);
1.1 kristaps 259: if (MDOC_PARSED & mdoc_macros[from].flags)
260: return(res);
261: if (MDOC_MAX == res)
262: return(res);
1.16 kristaps 263: if ( ! mdoc_pwarn(mdoc, line, pos, EMACPARM))
1.1 kristaps 264: return(-1);
265: return(MDOC_MAX);
266: }
267:
268:
269: static int
270: rew_last(struct mdoc *mdoc, struct mdoc_node *to)
271: {
272:
273: assert(to);
274: mdoc->next = MDOC_NEXT_SIBLING;
275:
276: /* LINTED */
277: while (mdoc->last != to) {
278: if ( ! mdoc_valid_post(mdoc))
279: return(0);
280: if ( ! mdoc_action_post(mdoc))
281: return(0);
282: mdoc->last = mdoc->last->parent;
283: assert(mdoc->last);
284: }
285:
286: if ( ! mdoc_valid_post(mdoc))
287: return(0);
288: return(mdoc_action_post(mdoc));
289: }
290:
291:
292: static int
293: rew_alt(int tok)
294: {
295: switch (tok) {
296: case (MDOC_Ac):
297: return(MDOC_Ao);
298: case (MDOC_Bc):
299: return(MDOC_Bo);
300: case (MDOC_Brc):
301: return(MDOC_Bro);
302: case (MDOC_Dc):
303: return(MDOC_Do);
304: case (MDOC_Ec):
305: return(MDOC_Eo);
306: case (MDOC_Ed):
307: return(MDOC_Bd);
308: case (MDOC_Ef):
309: return(MDOC_Bf);
310: case (MDOC_Ek):
311: return(MDOC_Bk);
312: case (MDOC_El):
313: return(MDOC_Bl);
314: case (MDOC_Fc):
315: return(MDOC_Fo);
316: case (MDOC_Oc):
317: return(MDOC_Oo);
318: case (MDOC_Pc):
319: return(MDOC_Po);
320: case (MDOC_Qc):
321: return(MDOC_Qo);
322: case (MDOC_Re):
323: return(MDOC_Rs);
324: case (MDOC_Sc):
325: return(MDOC_So);
326: case (MDOC_Xc):
327: return(MDOC_Xo);
328: default:
329: break;
330: }
331: abort();
332: /* NOTREACHED */
333: }
334:
335:
336: /*
337: * Rewind rules. This indicates whether to stop rewinding
338: * (REWIND_HALT) without touching our current scope, stop rewinding and
339: * close our current scope (REWIND_REWIND), or continue (REWIND_NOHALT).
340: * The scope-closing and so on occurs in the various rew_* routines.
341: */
342: static int
343: rew_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p)
344: {
345:
346: if (MDOC_ROOT == p->type)
347: return(REWIND_HALT);
348: if (MDOC_VALID & p->flags)
349: return(REWIND_NOHALT);
350:
351: switch (tok) {
352: case (MDOC_Aq):
353: /* FALLTHROUGH */
354: case (MDOC_Bq):
355: /* FALLTHROUGH */
356: case (MDOC_Brq):
357: /* FALLTHROUGH */
358: case (MDOC_D1):
359: /* FALLTHROUGH */
360: case (MDOC_Dl):
361: /* FALLTHROUGH */
362: case (MDOC_Dq):
363: /* FALLTHROUGH */
364: case (MDOC_Op):
365: /* FALLTHROUGH */
366: case (MDOC_Pq):
367: /* FALLTHROUGH */
368: case (MDOC_Ql):
369: /* FALLTHROUGH */
370: case (MDOC_Qq):
371: /* FALLTHROUGH */
372: case (MDOC_Sq):
373: assert(MDOC_HEAD != type);
374: assert(MDOC_TAIL != type);
375: if (type == p->type && tok == p->tok)
376: return(REWIND_REWIND);
377: break;
378: case (MDOC_It):
379: assert(MDOC_TAIL != type);
380: if (type == p->type && tok == p->tok)
381: return(REWIND_REWIND);
382: if (MDOC_BODY == p->type && MDOC_Bl == p->tok)
383: return(REWIND_HALT);
384: break;
385: case (MDOC_Sh):
386: if (type == p->type && tok == p->tok)
387: return(REWIND_REWIND);
388: break;
389: case (MDOC_Ss):
390: assert(MDOC_TAIL != type);
391: if (type == p->type && tok == p->tok)
392: return(REWIND_REWIND);
393: if (MDOC_BODY == p->type && MDOC_Sh == p->tok)
394: return(REWIND_HALT);
395: break;
396: case (MDOC_Ao):
397: /* FALLTHROUGH */
398: case (MDOC_Bd):
399: /* FALLTHROUGH */
400: case (MDOC_Bf):
401: /* FALLTHROUGH */
402: case (MDOC_Bk):
403: /* FALLTHROUGH */
404: case (MDOC_Bl):
405: /* FALLTHROUGH */
406: case (MDOC_Bo):
407: /* FALLTHROUGH */
408: case (MDOC_Bro):
409: /* FALLTHROUGH */
410: case (MDOC_Do):
411: /* FALLTHROUGH */
412: case (MDOC_Eo):
413: /* FALLTHROUGH */
414: case (MDOC_Fo):
415: /* FALLTHROUGH */
416: case (MDOC_Oo):
417: /* FALLTHROUGH */
418: case (MDOC_Po):
419: /* FALLTHROUGH */
420: case (MDOC_Qo):
421: /* FALLTHROUGH */
422: case (MDOC_Rs):
423: /* FALLTHROUGH */
424: case (MDOC_So):
425: /* FALLTHROUGH */
426: case (MDOC_Xo):
427: if (type == p->type && tok == p->tok)
428: return(REWIND_REWIND);
429: break;
430:
431: /* Multi-line explicit scope close. */
432: case (MDOC_Ac):
433: /* FALLTHROUGH */
434: case (MDOC_Bc):
435: /* FALLTHROUGH */
436: case (MDOC_Brc):
437: /* FALLTHROUGH */
438: case (MDOC_Dc):
439: /* FALLTHROUGH */
440: case (MDOC_Ec):
441: /* FALLTHROUGH */
442: case (MDOC_Ed):
443: /* FALLTHROUGH */
444: case (MDOC_Ek):
445: /* FALLTHROUGH */
446: case (MDOC_El):
447: /* FALLTHROUGH */
448: case (MDOC_Fc):
449: /* FALLTHROUGH */
450: case (MDOC_Ef):
451: /* FALLTHROUGH */
452: case (MDOC_Oc):
453: /* FALLTHROUGH */
454: case (MDOC_Pc):
455: /* FALLTHROUGH */
456: case (MDOC_Qc):
457: /* FALLTHROUGH */
458: case (MDOC_Re):
459: /* FALLTHROUGH */
460: case (MDOC_Sc):
461: /* FALLTHROUGH */
462: case (MDOC_Xc):
463: if (type == p->type && rew_alt(tok) == p->tok)
464: return(REWIND_REWIND);
465: break;
466: default:
467: abort();
468: /* NOTREACHED */
469: }
470:
471: return(REWIND_NOHALT);
472: }
473:
474:
475: /*
476: * See if we can break an encountered scope (the rew_dohalt has returned
477: * REWIND_NOHALT).
478: */
479: static int
480: rew_dobreak(int tok, const struct mdoc_node *p)
481: {
482:
483: assert(MDOC_ROOT != p->type);
484: if (MDOC_ELEM == p->type)
485: return(1);
486: if (MDOC_TEXT == p->type)
487: return(1);
488: if (MDOC_VALID & p->flags)
489: return(1);
490:
491: switch (tok) {
492: case (MDOC_It):
493: return(MDOC_It == p->tok);
494: case (MDOC_Ss):
495: return(MDOC_Ss == p->tok);
496: case (MDOC_Sh):
497: if (MDOC_Ss == p->tok)
498: return(1);
499: return(MDOC_Sh == p->tok);
500: case (MDOC_El):
501: if (MDOC_It == p->tok)
502: return(1);
503: break;
504: case (MDOC_Oc):
505: /* XXX - experimental! */
506: if (MDOC_Op == p->tok)
507: return(1);
508: break;
509: default:
510: break;
511: }
512:
513: if (MDOC_EXPLICIT & mdoc_macros[tok].flags)
514: return(p->tok == rew_alt(tok));
515: else if (MDOC_BLOCK == p->type)
516: return(1);
517:
518: return(tok == p->tok);
519: }
520:
521:
522: static int
523: rew_elem(struct mdoc *mdoc, int tok)
524: {
525: struct mdoc_node *n;
526:
527: n = mdoc->last;
528: if (MDOC_ELEM != n->type)
529: n = n->parent;
530: assert(MDOC_ELEM == n->type);
531: assert(tok == n->tok);
532:
533: return(rew_last(mdoc, n));
534: }
535:
536:
537: static int
538: rew_subblock(enum mdoc_type type, struct mdoc *mdoc,
539: int tok, int line, int ppos)
540: {
541: struct mdoc_node *n;
542: int c;
543:
544: /* LINTED */
545: for (n = mdoc->last; n; n = n->parent) {
546: c = rew_dohalt(tok, type, n);
547: if (REWIND_HALT == c)
548: return(1);
549: if (REWIND_REWIND == c)
550: break;
551: else if (rew_dobreak(tok, n))
552: continue;
553: if ( ! swarn(mdoc, type, line, ppos, n))
554: return(0);
555: }
556:
557: assert(n);
558: return(rew_last(mdoc, n));
559: }
560:
561:
562: static int
563: rew_expblock(struct mdoc *mdoc, int tok, int line, int ppos)
564: {
565: struct mdoc_node *n;
566: int c;
567:
568: /* LINTED */
569: for (n = mdoc->last; n; n = n->parent) {
570: c = rew_dohalt(tok, MDOC_BLOCK, n);
571: if (REWIND_HALT == c)
1.16 kristaps 572: return(mdoc_perr(mdoc, line, ppos, ENOCTX));
1.1 kristaps 573: if (REWIND_REWIND == c)
574: break;
575: else if (rew_dobreak(tok, n))
576: continue;
577: if ( ! swarn(mdoc, MDOC_BLOCK, line, ppos, n))
578: return(0);
579: }
580:
581: assert(n);
582: return(rew_last(mdoc, n));
583: }
584:
585:
586: static int
587: rew_impblock(struct mdoc *mdoc, int tok, int line, int ppos)
588: {
589: struct mdoc_node *n;
590: int c;
591:
592: /* LINTED */
593: for (n = mdoc->last; n; n = n->parent) {
594: c = rew_dohalt(tok, MDOC_BLOCK, n);
595: if (REWIND_HALT == c)
596: return(1);
597: else if (REWIND_REWIND == c)
598: break;
599: else if (rew_dobreak(tok, n))
600: continue;
601: if ( ! swarn(mdoc, MDOC_BLOCK, line, ppos, n))
602: return(0);
603: }
604:
605: assert(n);
606: return(rew_last(mdoc, n));
607: }
608:
609:
610: static int
611: append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
612: {
613: int c, lastarg;
614: char *p;
615:
616: if (0 == buf[*pos])
617: return(1);
618:
619: for (;;) {
620: lastarg = *pos;
621: c = mdoc_args(mdoc, line, pos, buf, 0, &p);
622: assert(ARGS_PHRASE != c);
623:
624: if (ARGS_ERROR == c)
625: return(0);
626: else if (ARGS_EOLN == c)
627: break;
628: assert(mdoc_isdelim(p));
629: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
630: return(0);
631: mdoc->next = MDOC_NEXT_SIBLING;
632: }
633:
634: return(1);
635: }
636:
637:
638: /*
639: * Close out block partial/full explicit.
640: */
641: static int
642: blk_exp_close(MACRO_PROT_ARGS)
643: {
644: int j, c, lastarg, maxargs, flushed;
645: char *p;
646:
647: switch (tok) {
648: case (MDOC_Ec):
649: maxargs = 1;
650: break;
651: default:
652: maxargs = 0;
653: break;
654: }
655:
656: if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
657: if (0 == buf[*pos]) {
658: if ( ! rew_subblock(MDOC_BODY, mdoc,
659: tok, line, ppos))
660: return(0);
661: return(rew_expblock(mdoc, tok, line, ppos));
662: }
1.17 kristaps 663: return(mdoc_perr(mdoc, line, ppos, ENOLINE));
1.1 kristaps 664: }
665:
666: if ( ! rew_subblock(MDOC_BODY, mdoc, tok, line, ppos))
667: return(0);
668:
669: if (maxargs > 0) {
670: if ( ! mdoc_tail_alloc(mdoc, line,
671: ppos, rew_alt(tok)))
672: return(0);
673: mdoc->next = MDOC_NEXT_CHILD;
674: }
675:
676: for (lastarg = ppos, flushed = j = 0; ; j++) {
677: lastarg = *pos;
678:
679: if (j == maxargs && ! flushed) {
680: if ( ! rew_expblock(mdoc, tok, line, ppos))
681: return(0);
682: flushed = 1;
683: }
684:
685: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
686:
687: if (ARGS_ERROR == c)
688: return(0);
689: if (ARGS_PUNCT == c)
690: break;
691: if (ARGS_EOLN == c)
692: break;
693:
694: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
695: return(0);
696: else if (MDOC_MAX != c) {
697: if ( ! flushed) {
698: if ( ! rew_expblock(mdoc, tok,
699: line, ppos))
700: return(0);
701: flushed = 1;
702: }
703: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
704: return(0);
705: break;
706: }
707:
708: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
709: return(0);
710: mdoc->next = MDOC_NEXT_SIBLING;
711: }
712:
713: if ( ! flushed && ! rew_expblock(mdoc, tok, line, ppos))
714: return(0);
715:
716: if (ppos > 1)
717: return(1);
718: return(append_delims(mdoc, line, pos, buf));
719: }
720:
721:
722: /*
723: * In-line macros where reserved words cause scope close-reopen.
724: */
725: static int
726: in_line(MACRO_PROT_ARGS)
727: {
1.4 kristaps 728: int la, lastpunct, c, w, cnt, d, nc;
1.1 kristaps 729: struct mdoc_arg *arg;
730: char *p;
731:
1.4 kristaps 732: /*
733: * Whether we allow ignored elements (those without content,
734: * usually because of reserved words) to squeak by.
735: */
736: switch (tok) {
737: case (MDOC_Lp):
738: /* FALLTHROUGH */
739: case (MDOC_Pp):
740: /* FALLTHROUGH */
741: case (MDOC_Nm):
742: /* FALLTHROUGH */
743: case (MDOC_Fl):
744: /* FALLTHROUGH */
1.12 kristaps 745: case (MDOC_Lk):
746: /* FALLTHROUGH */
1.4 kristaps 747: case (MDOC_Ar):
748: nc = 1;
749: break;
750: default:
751: nc = 0;
752: break;
753: }
754:
1.1 kristaps 755: for (la = ppos, arg = NULL;; ) {
756: la = *pos;
757: c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
758:
759: if (ARGV_WORD == c) {
760: *pos = la;
761: break;
762: }
763: if (ARGV_EOLN == c)
764: break;
765: if (ARGV_ARG == c)
766: continue;
767:
768: mdoc_argv_free(arg);
769: return(0);
770: }
771:
1.4 kristaps 772: for (cnt = 0, lastpunct = 1;; ) {
1.1 kristaps 773: la = *pos;
774: w = mdoc_args(mdoc, line, pos, buf, tok, &p);
775:
776: if (ARGS_ERROR == w)
777: return(0);
778: if (ARGS_EOLN == w)
779: break;
780: if (ARGS_PUNCT == w)
781: break;
782:
783: /* Quoted words shouldn't be looked-up. */
784:
785: c = ARGS_QWORD == w ? MDOC_MAX :
786: lookup(mdoc, line, la, tok, p);
787:
1.4 kristaps 788: /*
789: * In this case, we've located a submacro and must
790: * execute it. Close out scope, if open. If no
791: * elements have been generated, either create one (nc)
792: * or raise a warning.
793: */
1.1 kristaps 794:
795: if (MDOC_MAX != c && -1 != c) {
796: if (0 == lastpunct && ! rew_elem(mdoc, tok))
797: return(0);
1.4 kristaps 798: if (nc && 0 == cnt) {
1.3 kristaps 799: if ( ! mdoc_elem_alloc(mdoc, line, ppos,
800: tok, arg))
801: return(0);
1.12 kristaps 802: if ( ! rew_last(mdoc, mdoc->last))
803: return(0);
1.7 kristaps 804: } else if ( ! nc && 0 == cnt) {
805: mdoc_argv_free(arg);
1.16 kristaps 806: if ( ! mdoc_pwarn(mdoc, line, ppos, EIGNE))
1.3 kristaps 807: return(0);
1.7 kristaps 808: }
1.1 kristaps 809: c = mdoc_macro(mdoc, c, line, la, pos, buf);
810: if (0 == c)
811: return(0);
812: if (ppos > 1)
813: return(1);
814: return(append_delims(mdoc, line, pos, buf));
815: } else if (-1 == c)
816: return(0);
817:
1.4 kristaps 818: /*
819: * Non-quote-enclosed punctuation. Set up our scope, if
820: * a word; rewind the scope, if a delimiter; then append
821: * the word.
822: */
1.1 kristaps 823:
1.3 kristaps 824: d = mdoc_isdelim(p);
825:
826: if (ARGS_QWORD != w && d) {
1.1 kristaps 827: if (0 == lastpunct && ! rew_elem(mdoc, tok))
828: return(0);
829: lastpunct = 1;
830: } else if (lastpunct) {
831: c = mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
832: if (0 == c)
833: return(0);
834: mdoc->next = MDOC_NEXT_CHILD;
835: lastpunct = 0;
836: }
837:
1.3 kristaps 838: if ( ! d)
839: cnt++;
1.1 kristaps 840: if ( ! mdoc_word_alloc(mdoc, line, la, p))
841: return(0);
842: mdoc->next = MDOC_NEXT_SIBLING;
843: }
844:
845: if (0 == lastpunct && ! rew_elem(mdoc, tok))
846: return(0);
1.4 kristaps 847:
848: /*
849: * If no elements have been collected and we're allowed to have
850: * empties (nc), open a scope and close it out. Otherwise,
851: * raise a warning.
852: *
853: */
854: if (nc && 0 == cnt) {
1.3 kristaps 855: c = mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
856: if (0 == c)
857: return(0);
1.12 kristaps 858: if ( ! rew_last(mdoc, mdoc->last))
859: return(0);
1.7 kristaps 860: } else if ( ! nc && 0 == cnt) {
861: mdoc_argv_free(arg);
1.16 kristaps 862: if ( ! mdoc_pwarn(mdoc, line, ppos, EIGNE))
1.3 kristaps 863: return(0);
1.7 kristaps 864: }
1.4 kristaps 865:
1.1 kristaps 866: if (ppos > 1)
867: return(1);
868: return(append_delims(mdoc, line, pos, buf));
869: }
870:
871:
872: /*
873: * Block full-explicit and full-implicit.
874: */
875: static int
876: blk_full(MACRO_PROT_ARGS)
877: {
878: int c, lastarg, reopen;
879: struct mdoc_arg *arg;
880: char *p;
881:
882: if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
883: if ( ! rew_subblock(MDOC_BODY, mdoc,
884: tok, line, ppos))
885: return(0);
886: if ( ! rew_impblock(mdoc, tok, line, ppos))
887: return(0);
888: }
889:
890: for (arg = NULL;; ) {
891: lastarg = *pos;
892: c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
893:
894: if (ARGV_WORD == c) {
895: *pos = lastarg;
896: break;
897: }
898:
899: if (ARGV_EOLN == c)
900: break;
901: if (ARGV_ARG == c)
902: continue;
903:
904: mdoc_argv_free(arg);
905: return(0);
906: }
907:
908: if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, arg))
909: return(0);
910: mdoc->next = MDOC_NEXT_CHILD;
911:
912: if (0 == buf[*pos]) {
913: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
914: return(0);
915: if ( ! rew_subblock(MDOC_HEAD, mdoc,
916: tok, line, ppos))
917: return(0);
918: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
919: return(0);
920: mdoc->next = MDOC_NEXT_CHILD;
921: return(1);
922: }
923:
924: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
925: return(0);
926: mdoc->next = MDOC_NEXT_CHILD;
927:
928: for (reopen = 0;; ) {
929: lastarg = *pos;
930: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
931:
932: if (ARGS_ERROR == c)
933: return(0);
934: if (ARGS_EOLN == c)
935: break;
936: if (ARGS_PHRASE == c) {
937: if (reopen && ! mdoc_head_alloc
938: (mdoc, line, ppos, tok))
939: return(0);
940: mdoc->next = MDOC_NEXT_CHILD;
941: /*
942: * Phrases are self-contained macro phrases used
943: * in the columnar output of a macro. They need
944: * special handling.
945: */
946: if ( ! phrase(mdoc, line, lastarg, buf))
947: return(0);
948: if ( ! rew_subblock(MDOC_HEAD, mdoc,
949: tok, line, ppos))
950: return(0);
951:
952: reopen = 1;
953: continue;
954: }
955:
956: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
957: return(0);
958:
959: if (MDOC_MAX == c) {
960: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
961: return(0);
962: mdoc->next = MDOC_NEXT_SIBLING;
963: continue;
964: }
965:
966: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
967: return(0);
968: break;
969: }
970:
971: if (1 == ppos && ! append_delims(mdoc, line, pos, buf))
972: return(0);
973: if ( ! rew_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
974: return(0);
975:
976: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
977: return(0);
978: mdoc->next = MDOC_NEXT_CHILD;
979:
980: return(1);
981: }
982:
983:
984: /*
985: * Block partial-imnplicit scope.
986: */
987: static int
988: blk_part_imp(MACRO_PROT_ARGS)
989: {
990: int lastarg, c;
991: char *p;
992: struct mdoc_node *blk, *body, *n;
993:
994: if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, NULL))
995: return(0);
996: mdoc->next = MDOC_NEXT_CHILD;
997: blk = mdoc->last;
998:
999: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1000: return(0);
1001: mdoc->next = MDOC_NEXT_SIBLING;
1002:
1003: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1004: return(0);
1005: mdoc->next = MDOC_NEXT_CHILD;
1006: body = mdoc->last;
1007:
1008: /* XXX - no known argument macros. */
1009:
1010: for (lastarg = ppos;; ) {
1011: lastarg = *pos;
1012: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1013: assert(ARGS_PHRASE != c);
1014:
1015: if (ARGS_ERROR == c)
1016: return(0);
1017: if (ARGS_PUNCT == c)
1018: break;
1019: if (ARGS_EOLN == c)
1020: break;
1021:
1022: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
1023: return(0);
1024: else if (MDOC_MAX == c) {
1025: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1026: return(0);
1027: mdoc->next = MDOC_NEXT_SIBLING;
1028: continue;
1029: }
1030:
1031: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1032: return(0);
1033: break;
1034: }
1035:
1036: /*
1037: * Since we know what our context is, we can rewind directly to
1038: * it. This allows us to accomodate for our scope being
1039: * violated by another token.
1040: */
1041:
1042: for (n = mdoc->last; n; n = n->parent)
1043: if (body == n)
1044: break;
1045:
1.16 kristaps 1046: if (NULL == n && ! mdoc_nwarn(mdoc, body, EIMPBRK))
1.1 kristaps 1047: return(0);
1048:
1049: if (n && ! rew_last(mdoc, body))
1050: return(0);
1051:
1052: if (1 == ppos && ! append_delims(mdoc, line, pos, buf))
1053: return(0);
1054:
1055: if (n && ! rew_last(mdoc, blk))
1056: return(0);
1057:
1058: return(1);
1059: }
1060:
1061:
1062: /*
1063: * Block partial-explicit macros.
1064: */
1065: static int
1066: blk_part_exp(MACRO_PROT_ARGS)
1067: {
1068: int lastarg, flushed, j, c, maxargs;
1069: char *p;
1070:
1071: lastarg = ppos;
1072: flushed = 0;
1073:
1074: /*
1075: * Number of arguments (head arguments). Only `Eo' has these,
1076: */
1077:
1078: switch (tok) {
1079: case (MDOC_Eo):
1080: maxargs = 1;
1081: break;
1082: default:
1083: maxargs = 0;
1084: break;
1085: }
1086:
1087: if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, NULL))
1088: return(0);
1089: mdoc->next = MDOC_NEXT_CHILD;
1090:
1091: if (0 == maxargs) {
1092: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1093: return(0);
1094: if ( ! rew_subblock(MDOC_HEAD, mdoc,
1095: tok, line, ppos))
1096: return(0);
1097: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1098: return(0);
1099: flushed = 1;
1100: } else if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1101: return(0);
1102:
1103: mdoc->next = MDOC_NEXT_CHILD;
1104:
1105: for (j = 0; ; j++) {
1106: lastarg = *pos;
1107: if (j == maxargs && ! flushed) {
1108: if ( ! rew_subblock(MDOC_HEAD, mdoc,
1109: tok, line, ppos))
1110: return(0);
1111: flushed = 1;
1112: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1113: return(0);
1114: mdoc->next = MDOC_NEXT_CHILD;
1115: }
1116:
1117: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1118: assert(ARGS_PHRASE != c);
1119:
1120: if (ARGS_ERROR == c)
1121: return(0);
1122: if (ARGS_PUNCT == c)
1123: break;
1124: if (ARGS_EOLN == c)
1125: break;
1126:
1127: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
1128: return(0);
1129: else if (MDOC_MAX != c) {
1130: if ( ! flushed) {
1131: if ( ! rew_subblock(MDOC_HEAD, mdoc,
1132: tok, line, ppos))
1133: return(0);
1134: flushed = 1;
1135: if ( ! mdoc_body_alloc(mdoc, line,
1136: ppos, tok))
1137: return(0);
1138: mdoc->next = MDOC_NEXT_CHILD;
1139: }
1140: if ( ! mdoc_macro(mdoc, c, line, lastarg,
1141: pos, buf))
1142: return(0);
1143: break;
1144: }
1145:
1146: if ( ! flushed && mdoc_isdelim(p)) {
1147: if ( ! rew_subblock(MDOC_HEAD, mdoc,
1148: tok, line, ppos))
1149: return(0);
1150: flushed = 1;
1151: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1152: return(0);
1153: mdoc->next = MDOC_NEXT_CHILD;
1154: }
1155:
1156: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1157: return(0);
1158: mdoc->next = MDOC_NEXT_SIBLING;
1159: }
1160:
1161: if ( ! flushed) {
1162: if ( ! rew_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
1163: return(0);
1164: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1165: return(0);
1166: mdoc->next = MDOC_NEXT_CHILD;
1167: }
1168:
1169: if (ppos > 1)
1170: return(1);
1171: return(append_delims(mdoc, line, pos, buf));
1172: }
1173:
1174:
1175: /*
1176: * In-line macros where reserved words signal closure of the macro.
1177: * Macros also have a fixed number of arguments.
1178: */
1179: static int
1180: in_line_argn(MACRO_PROT_ARGS)
1181: {
1182: int lastarg, flushed, j, c, maxargs;
1183: struct mdoc_arg *arg;
1184: char *p;
1185:
1186:
1187: /*
1188: * Fixed maximum arguments per macro. Some of these have none
1189: * and close as soon as the invocation is parsed.
1190: */
1191:
1192: switch (tok) {
1193: case (MDOC_Ap):
1194: /* FALLTHROUGH */
1195: case (MDOC_No):
1196: /* FALLTHROUGH */
1197: case (MDOC_Ns):
1198: /* FALLTHROUGH */
1199: case (MDOC_Ux):
1200: maxargs = 0;
1201: break;
1202: default:
1203: maxargs = 1;
1204: break;
1205: }
1206:
1207: for (lastarg = ppos, arg = NULL;; ) {
1208: lastarg = *pos;
1209: c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1210:
1211: if (ARGV_WORD == c) {
1212: *pos = lastarg;
1213: break;
1214: }
1215:
1216: if (ARGV_EOLN == c)
1217: break;
1218: if (ARGV_ARG == c)
1219: continue;
1220:
1221: mdoc_argv_free(arg);
1222: return(0);
1223: }
1224:
1225: if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
1226: return(0);
1227: mdoc->next = MDOC_NEXT_CHILD;
1228:
1229: for (flushed = j = 0; ; j++) {
1230: lastarg = *pos;
1231:
1232: if (j == maxargs && ! flushed) {
1233: if ( ! rew_elem(mdoc, tok))
1234: return(0);
1235: flushed = 1;
1236: }
1237:
1238: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1239:
1240: if (ARGS_ERROR == c)
1241: return(0);
1242: if (ARGS_PUNCT == c)
1243: break;
1244: if (ARGS_EOLN == c)
1245: break;
1246:
1247: if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
1248: return(0);
1249: else if (MDOC_MAX != c) {
1250: if ( ! flushed && ! rew_elem(mdoc, tok))
1251: return(0);
1252: flushed = 1;
1253: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1254: return(0);
1255: break;
1256: }
1257:
1258: if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
1259: ! flushed && mdoc_isdelim(p)) {
1260: if ( ! rew_elem(mdoc, tok))
1261: return(0);
1262: flushed = 1;
1263: }
1264:
1265: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1266: return(0);
1267: mdoc->next = MDOC_NEXT_SIBLING;
1268: }
1269:
1270: if ( ! flushed && ! rew_elem(mdoc, tok))
1271: return(0);
1272:
1273: if (ppos > 1)
1274: return(1);
1275: return(append_delims(mdoc, line, pos, buf));
1276: }
1277:
1278:
1279: /*
1280: * In-line macro that spans an entire line. May be callable, but has no
1281: * subsequent parsed arguments.
1282: */
1283: static int
1284: in_line_eoln(MACRO_PROT_ARGS)
1285: {
1286: int c, w, la;
1287: struct mdoc_arg *arg;
1288: char *p;
1289:
1290: assert( ! (MDOC_PARSED & mdoc_macros[tok].flags));
1291:
1292: arg = NULL;
1293:
1294: for (;;) {
1295: la = *pos;
1296: c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1297:
1298: if (ARGV_WORD == c) {
1299: *pos = la;
1300: break;
1301: }
1302: if (ARGV_EOLN == c)
1303: break;
1304: if (ARGV_ARG == c)
1305: continue;
1306:
1307: mdoc_argv_free(arg);
1308: return(0);
1309: }
1310:
1311: if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
1312: return(0);
1313:
1314: mdoc->next = MDOC_NEXT_CHILD;
1315:
1316: for (;;) {
1317: la = *pos;
1318: w = mdoc_args(mdoc, line, pos, buf, tok, &p);
1319:
1320: if (ARGS_ERROR == w)
1321: return(0);
1322: if (ARGS_EOLN == w)
1323: break;
1324:
1325: c = ARGS_QWORD == w ? MDOC_MAX :
1326: lookup(mdoc, line, la, tok, p);
1327:
1328: if (MDOC_MAX != c && -1 != c) {
1329: if ( ! rew_elem(mdoc, tok))
1330: return(0);
1331: return(mdoc_macro(mdoc, c, line, la, pos, buf));
1332: } else if (-1 == c)
1333: return(0);
1334:
1335: if ( ! mdoc_word_alloc(mdoc, line, la, p))
1336: return(0);
1337: mdoc->next = MDOC_NEXT_SIBLING;
1338: }
1339:
1340: return(rew_elem(mdoc, tok));
1341: }
1342:
1343:
1344: /* ARGSUSED */
1345: static int
1346: obsolete(MACRO_PROT_ARGS)
1347: {
1348:
1.16 kristaps 1349: return(mdoc_pwarn(mdoc, line, ppos, EOBS));
1.1 kristaps 1350: }
1351:
1352:
1353: static int
1354: phrase(struct mdoc *mdoc, int line, int ppos, char *buf)
1355: {
1356: int i, la, c, quoted;
1357:
1358: /*
1359: * Parse over words in a phrase. We have to handle this
1360: * specially because we assume no calling context -- in normal
1361: * circumstances, we switch argument parsing based on whether
1362: * the parent macro accepts quotes, tabs, etc. Here, anything
1363: * goes.
1364: */
1365:
1366: for (i = ppos; buf[i]; ) {
1367: assert(' ' != buf[i]);
1368: la = i;
1369: quoted = 0;
1370:
1371: /*
1372: * Read to next token. If quoted (check not escaped),
1373: * scan ahead to next unescaped quote. If not quoted or
1374: * escape-quoted, then scan ahead to next space.
1375: */
1376:
1377: if ((i && '\"' == buf[i] && '\\' != buf[i - 1]) ||
1378: (0 == i && '\"' == buf[i])) {
1379: for (la = ++i; buf[i]; i++)
1380: if ('\"' != buf[i])
1381: continue;
1382: else if ('\\' != buf[i - 1])
1383: break;
1384: if (0 == buf[i])
1.17 kristaps 1385: return(mdoc_perr(mdoc, line, la, EQUOTPHR));
1.1 kristaps 1386: quoted = 1;
1387: } else
1388: for ( ; buf[i]; i++)
1389: if (i && ' ' == buf[i]) {
1390: if ('\\' != buf[i - 1])
1391: break;
1392: } else if (' ' == buf[i])
1393: break;
1394:
1395: /* If not end-of-line, terminate argument. */
1396:
1397: if (buf[i])
1398: buf[i++] = 0;
1399:
1400: /* Read to next argument. */
1401:
1402: for ( ; buf[i] && ' ' == buf[i]; i++)
1403: /* Spin. */ ;
1404:
1405: /*
1406: * If we're a non-quoted string, try to look up the
1407: * value as a macro and execute it, if found.
1408: */
1409:
1410: c = quoted ? MDOC_MAX :
1.6 kristaps 1411: mdoc_hash_find(mdoc->htab, &buf[la]);
1.1 kristaps 1412:
1413: if (MDOC_MAX != c) {
1414: if ( ! mdoc_macro(mdoc, c, line, la, &i, buf))
1415: return(0);
1416: return(append_delims(mdoc, line, &i, buf));
1417: }
1418:
1419: /* A regular word or quoted string. */
1420:
1421: if ( ! mdoc_word_alloc(mdoc, line, la, &buf[la]))
1422: return(0);
1423: mdoc->next = MDOC_NEXT_SIBLING;
1424: }
1425:
1426: return(1);
1427: }
CVSweb