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