Annotation of mandoc/mdoc_macro.c, Revision 1.29
1.29 ! kristaps 1: /* $Id: mdoc_macro.c,v 1.28 2009/07/29 08:46:06 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 *);
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:
602: static int
603: rew_impblock(struct mdoc *mdoc, int tok, int line, int ppos)
604: {
605: struct mdoc_node *n;
606: int c;
607:
608: /* LINTED */
609: for (n = mdoc->last; n; n = n->parent) {
610: c = rew_dohalt(tok, MDOC_BLOCK, n);
611: if (REWIND_HALT == c)
612: return(1);
613: else if (REWIND_REWIND == c)
614: break;
615: else if (rew_dobreak(tok, n))
616: continue;
617: if ( ! swarn(mdoc, MDOC_BLOCK, line, ppos, n))
618: return(0);
619: }
620:
621: assert(n);
622: return(rew_last(mdoc, n));
623: }
624:
625:
626: static int
627: append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
628: {
629: int c, lastarg;
630: char *p;
631:
632: if (0 == buf[*pos])
633: return(1);
634:
635: for (;;) {
636: lastarg = *pos;
637: c = mdoc_args(mdoc, line, pos, buf, 0, &p);
638: assert(ARGS_PHRASE != c);
639:
640: if (ARGS_ERROR == c)
641: return(0);
642: else if (ARGS_EOLN == c)
643: break;
644: assert(mdoc_isdelim(p));
645: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
646: return(0);
647: mdoc->next = MDOC_NEXT_SIBLING;
648: }
649:
650: return(1);
651: }
652:
653:
654: /*
655: * Close out block partial/full explicit.
656: */
657: static int
658: blk_exp_close(MACRO_PROT_ARGS)
659: {
660: int j, c, lastarg, maxargs, flushed;
661: char *p;
662:
663: switch (tok) {
664: case (MDOC_Ec):
665: maxargs = 1;
666: break;
667: default:
668: maxargs = 0;
669: break;
670: }
671:
672: if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
1.22 kristaps 673: if (buf[*pos])
674: if ( ! mdoc_pwarn(mdoc, line, ppos, ENOLINE))
1.1 kristaps 675: return(0);
1.22 kristaps 676:
677: if ( ! rew_subblock(MDOC_BODY, mdoc, tok, line, ppos))
678: return(0);
679: return(rew_expblock(mdoc, tok, line, ppos));
1.1 kristaps 680: }
681:
682: if ( ! rew_subblock(MDOC_BODY, mdoc, tok, line, ppos))
683: return(0);
684:
685: if (maxargs > 0) {
686: if ( ! mdoc_tail_alloc(mdoc, line,
687: ppos, rew_alt(tok)))
688: return(0);
689: mdoc->next = MDOC_NEXT_CHILD;
690: }
691:
1.27 kristaps 692: for (flushed = j = 0; ; j++) {
1.1 kristaps 693: lastarg = *pos;
694:
695: if (j == maxargs && ! flushed) {
696: if ( ! rew_expblock(mdoc, tok, line, ppos))
697: return(0);
698: flushed = 1;
699: }
700:
701: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
702:
703: if (ARGS_ERROR == c)
704: return(0);
705: if (ARGS_PUNCT == c)
706: break;
707: if (ARGS_EOLN == c)
708: break;
709:
1.29 ! kristaps 710: if (MDOC_MAX != (c = lookup(mdoc, tok, p))) {
1.1 kristaps 711: if ( ! flushed) {
712: if ( ! rew_expblock(mdoc, tok,
713: line, ppos))
714: return(0);
715: flushed = 1;
716: }
717: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
718: return(0);
719: break;
720: }
721:
722: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
723: return(0);
724: mdoc->next = MDOC_NEXT_SIBLING;
725: }
726:
727: if ( ! flushed && ! rew_expblock(mdoc, tok, line, ppos))
728: return(0);
729:
730: if (ppos > 1)
731: return(1);
732: return(append_delims(mdoc, line, pos, buf));
733: }
734:
735:
736: /*
737: * In-line macros where reserved words cause scope close-reopen.
738: */
739: static int
740: in_line(MACRO_PROT_ARGS)
741: {
1.4 kristaps 742: int la, lastpunct, c, w, cnt, d, nc;
1.1 kristaps 743: struct mdoc_arg *arg;
744: char *p;
745:
1.4 kristaps 746: /*
747: * Whether we allow ignored elements (those without content,
748: * usually because of reserved words) to squeak by.
749: */
750: switch (tok) {
1.26 kristaps 751: case (MDOC_An):
752: /* FALLTHROUGH */
753: case (MDOC_Ar):
1.4 kristaps 754: /* FALLTHROUGH */
755: case (MDOC_Fl):
756: /* FALLTHROUGH */
1.12 kristaps 757: case (MDOC_Lk):
758: /* FALLTHROUGH */
1.26 kristaps 759: case (MDOC_Nm):
760: /* FALLTHROUGH */
1.25 kristaps 761: case (MDOC_Pa):
1.4 kristaps 762: nc = 1;
763: break;
764: default:
765: nc = 0;
766: break;
767: }
768:
1.27 kristaps 769: for (arg = NULL;; ) {
1.1 kristaps 770: la = *pos;
771: c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
772:
773: if (ARGV_WORD == c) {
774: *pos = la;
775: break;
776: }
777: if (ARGV_EOLN == c)
778: break;
779: if (ARGV_ARG == c)
780: continue;
781:
782: mdoc_argv_free(arg);
783: return(0);
784: }
785:
1.4 kristaps 786: for (cnt = 0, lastpunct = 1;; ) {
1.1 kristaps 787: la = *pos;
788: w = mdoc_args(mdoc, line, pos, buf, tok, &p);
789:
790: if (ARGS_ERROR == w)
791: return(0);
792: if (ARGS_EOLN == w)
793: break;
794: if (ARGS_PUNCT == w)
795: break;
796:
797: /* Quoted words shouldn't be looked-up. */
798:
1.28 kristaps 799: c = ARGS_QWORD == w ? MDOC_MAX : lookup(mdoc, tok, p);
1.1 kristaps 800:
1.4 kristaps 801: /*
802: * In this case, we've located a submacro and must
803: * execute it. Close out scope, if open. If no
804: * elements have been generated, either create one (nc)
805: * or raise a warning.
806: */
1.1 kristaps 807:
1.29 ! kristaps 808: if (MDOC_MAX != c) {
1.1 kristaps 809: if (0 == lastpunct && ! rew_elem(mdoc, tok))
810: return(0);
1.4 kristaps 811: if (nc && 0 == cnt) {
1.3 kristaps 812: if ( ! mdoc_elem_alloc(mdoc, line, ppos,
813: tok, arg))
814: return(0);
1.12 kristaps 815: if ( ! rew_last(mdoc, mdoc->last))
816: return(0);
1.7 kristaps 817: } else if ( ! nc && 0 == cnt) {
818: mdoc_argv_free(arg);
1.16 kristaps 819: if ( ! mdoc_pwarn(mdoc, line, ppos, EIGNE))
1.3 kristaps 820: return(0);
1.7 kristaps 821: }
1.1 kristaps 822: c = mdoc_macro(mdoc, c, line, la, pos, buf);
823: if (0 == c)
824: return(0);
825: if (ppos > 1)
826: return(1);
827: return(append_delims(mdoc, line, pos, buf));
1.29 ! kristaps 828: }
1.1 kristaps 829:
1.4 kristaps 830: /*
831: * Non-quote-enclosed punctuation. Set up our scope, if
832: * a word; rewind the scope, if a delimiter; then append
833: * the word.
834: */
1.1 kristaps 835:
1.3 kristaps 836: d = mdoc_isdelim(p);
837:
838: if (ARGS_QWORD != w && d) {
1.1 kristaps 839: if (0 == lastpunct && ! rew_elem(mdoc, tok))
840: return(0);
841: lastpunct = 1;
842: } else if (lastpunct) {
843: c = mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
844: if (0 == c)
845: return(0);
846: mdoc->next = MDOC_NEXT_CHILD;
847: lastpunct = 0;
848: }
849:
1.3 kristaps 850: if ( ! d)
851: cnt++;
1.1 kristaps 852: if ( ! mdoc_word_alloc(mdoc, line, la, p))
853: return(0);
854: mdoc->next = MDOC_NEXT_SIBLING;
855: }
856:
857: if (0 == lastpunct && ! rew_elem(mdoc, tok))
858: return(0);
1.4 kristaps 859:
860: /*
861: * If no elements have been collected and we're allowed to have
862: * empties (nc), open a scope and close it out. Otherwise,
863: * raise a warning.
864: *
865: */
866: if (nc && 0 == cnt) {
1.3 kristaps 867: c = mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
868: if (0 == c)
869: return(0);
1.12 kristaps 870: if ( ! rew_last(mdoc, mdoc->last))
871: return(0);
1.7 kristaps 872: } else if ( ! nc && 0 == cnt) {
873: mdoc_argv_free(arg);
1.16 kristaps 874: if ( ! mdoc_pwarn(mdoc, line, ppos, EIGNE))
1.3 kristaps 875: return(0);
1.7 kristaps 876: }
1.4 kristaps 877:
1.1 kristaps 878: if (ppos > 1)
879: return(1);
880: return(append_delims(mdoc, line, pos, buf));
881: }
882:
883:
884: /*
885: * Block full-explicit and full-implicit.
886: */
887: static int
888: blk_full(MACRO_PROT_ARGS)
889: {
1.19 kristaps 890: int c, lastarg, reopen, dohead;
1.1 kristaps 891: struct mdoc_arg *arg;
892: char *p;
893:
1.19 kristaps 894: /*
895: * Whether to process a block-head section. If this is
896: * non-zero, then a head will be opened for all line arguments.
897: * If not, then the head will always be empty and only a body
898: * will be opened, which will stay open at the eoln.
899: */
900:
901: switch (tok) {
902: case (MDOC_Nd):
903: dohead = 0;
904: break;
905: default:
906: dohead = 1;
907: break;
908: }
909:
1.1 kristaps 910: if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
911: if ( ! rew_subblock(MDOC_BODY, mdoc,
912: tok, line, ppos))
913: return(0);
914: if ( ! rew_impblock(mdoc, tok, line, ppos))
915: return(0);
916: }
917:
918: for (arg = NULL;; ) {
919: lastarg = *pos;
920: c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
921:
922: if (ARGV_WORD == c) {
923: *pos = lastarg;
924: break;
925: }
926:
927: if (ARGV_EOLN == c)
928: break;
929: if (ARGV_ARG == c)
930: continue;
931:
932: mdoc_argv_free(arg);
933: return(0);
934: }
935:
936: if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, arg))
937: return(0);
938: mdoc->next = MDOC_NEXT_CHILD;
939:
940: if (0 == buf[*pos]) {
941: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
942: return(0);
943: if ( ! rew_subblock(MDOC_HEAD, mdoc,
944: tok, line, ppos))
945: return(0);
946: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
947: return(0);
948: mdoc->next = MDOC_NEXT_CHILD;
949: return(1);
950: }
951:
952: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
953: return(0);
1.19 kristaps 954:
955: /* Immediately close out head and enter body, if applicable. */
956:
957: if (0 == dohead) {
958: if ( ! rew_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
959: return(0);
960: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
961: return(0);
962: }
963:
1.1 kristaps 964: mdoc->next = MDOC_NEXT_CHILD;
965:
966: for (reopen = 0;; ) {
967: lastarg = *pos;
968: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
969:
970: if (ARGS_ERROR == c)
971: return(0);
972: if (ARGS_EOLN == c)
973: break;
974: if (ARGS_PHRASE == c) {
1.19 kristaps 975: assert(dohead);
1.1 kristaps 976: if (reopen && ! mdoc_head_alloc
977: (mdoc, line, ppos, tok))
978: return(0);
979: mdoc->next = MDOC_NEXT_CHILD;
980: /*
981: * Phrases are self-contained macro phrases used
982: * in the columnar output of a macro. They need
983: * special handling.
984: */
985: if ( ! phrase(mdoc, line, lastarg, buf))
986: return(0);
987: if ( ! rew_subblock(MDOC_HEAD, mdoc,
988: tok, line, ppos))
989: return(0);
990:
991: reopen = 1;
992: continue;
993: }
994:
1.29 ! kristaps 995: if (MDOC_MAX == (c = lookup(mdoc, tok, p))) {
1.1 kristaps 996: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
997: return(0);
998: mdoc->next = MDOC_NEXT_SIBLING;
999: continue;
1000: }
1001:
1002: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1003: return(0);
1004: break;
1005: }
1006:
1007: if (1 == ppos && ! append_delims(mdoc, line, pos, buf))
1008: return(0);
1.19 kristaps 1009:
1010: /* If the body's already open, then just return. */
1011: if (0 == dohead)
1012: return(1);
1013:
1.1 kristaps 1014: if ( ! rew_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
1015: return(0);
1016: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1017: return(0);
1018: mdoc->next = MDOC_NEXT_CHILD;
1019:
1020: return(1);
1021: }
1022:
1023:
1024: /*
1025: * Block partial-imnplicit scope.
1026: */
1027: static int
1028: blk_part_imp(MACRO_PROT_ARGS)
1029: {
1030: int lastarg, c;
1031: char *p;
1032: struct mdoc_node *blk, *body, *n;
1033:
1034: if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, NULL))
1035: return(0);
1036: mdoc->next = MDOC_NEXT_CHILD;
1037: blk = mdoc->last;
1038:
1039: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1040: return(0);
1041: mdoc->next = MDOC_NEXT_SIBLING;
1042:
1043: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1044: return(0);
1045: mdoc->next = MDOC_NEXT_CHILD;
1046: body = mdoc->last;
1047:
1048: /* XXX - no known argument macros. */
1049:
1.27 kristaps 1050: for (;;) {
1.1 kristaps 1051: lastarg = *pos;
1052: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1053: assert(ARGS_PHRASE != c);
1054:
1055: if (ARGS_ERROR == c)
1056: return(0);
1057: if (ARGS_PUNCT == c)
1058: break;
1059: if (ARGS_EOLN == c)
1060: break;
1061:
1.29 ! kristaps 1062: if (MDOC_MAX == (c = lookup(mdoc, tok, p))) {
1.1 kristaps 1063: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1064: return(0);
1065: mdoc->next = MDOC_NEXT_SIBLING;
1066: continue;
1067: }
1068:
1069: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1070: return(0);
1071: break;
1072: }
1073:
1074: /*
1075: * Since we know what our context is, we can rewind directly to
1076: * it. This allows us to accomodate for our scope being
1077: * violated by another token.
1078: */
1079:
1080: for (n = mdoc->last; n; n = n->parent)
1081: if (body == n)
1082: break;
1083:
1.16 kristaps 1084: if (NULL == n && ! mdoc_nwarn(mdoc, body, EIMPBRK))
1.1 kristaps 1085: return(0);
1086:
1087: if (n && ! rew_last(mdoc, body))
1088: return(0);
1089:
1090: if (1 == ppos && ! append_delims(mdoc, line, pos, buf))
1091: return(0);
1092:
1093: if (n && ! rew_last(mdoc, blk))
1094: return(0);
1095:
1096: return(1);
1097: }
1098:
1099:
1100: /*
1101: * Block partial-explicit macros.
1102: */
1103: static int
1104: blk_part_exp(MACRO_PROT_ARGS)
1105: {
1106: int lastarg, flushed, j, c, maxargs;
1107: char *p;
1108:
1109: flushed = 0;
1110:
1111: /*
1112: * Number of arguments (head arguments). Only `Eo' has these,
1113: */
1114:
1115: switch (tok) {
1116: case (MDOC_Eo):
1117: maxargs = 1;
1118: break;
1119: default:
1120: maxargs = 0;
1121: break;
1122: }
1123:
1124: if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, NULL))
1125: return(0);
1126: mdoc->next = MDOC_NEXT_CHILD;
1127:
1128: if (0 == maxargs) {
1129: if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1130: return(0);
1131: if ( ! rew_subblock(MDOC_HEAD, mdoc,
1132: tok, line, ppos))
1133: return(0);
1134: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1135: return(0);
1136: flushed = 1;
1137: } else if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
1138: return(0);
1139:
1140: mdoc->next = MDOC_NEXT_CHILD;
1141:
1142: for (j = 0; ; j++) {
1143: lastarg = *pos;
1144: if (j == maxargs && ! flushed) {
1145: if ( ! rew_subblock(MDOC_HEAD, mdoc,
1146: tok, line, ppos))
1147: return(0);
1148: flushed = 1;
1149: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1150: return(0);
1151: mdoc->next = MDOC_NEXT_CHILD;
1152: }
1153:
1154: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1155: assert(ARGS_PHRASE != c);
1156:
1157: if (ARGS_ERROR == c)
1158: return(0);
1159: if (ARGS_PUNCT == c)
1160: break;
1161: if (ARGS_EOLN == c)
1162: break;
1163:
1.29 ! kristaps 1164: if (MDOC_MAX != (c = lookup(mdoc, tok, p))) {
1.1 kristaps 1165: if ( ! flushed) {
1166: if ( ! rew_subblock(MDOC_HEAD, mdoc,
1167: tok, line, ppos))
1168: return(0);
1169: flushed = 1;
1170: if ( ! mdoc_body_alloc(mdoc, line,
1171: ppos, tok))
1172: return(0);
1173: mdoc->next = MDOC_NEXT_CHILD;
1174: }
1175: if ( ! mdoc_macro(mdoc, c, line, lastarg,
1176: pos, buf))
1177: return(0);
1178: break;
1179: }
1180:
1181: if ( ! flushed && mdoc_isdelim(p)) {
1182: if ( ! rew_subblock(MDOC_HEAD, mdoc,
1183: tok, line, ppos))
1184: return(0);
1185: flushed = 1;
1186: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1187: return(0);
1188: mdoc->next = MDOC_NEXT_CHILD;
1189: }
1190:
1191: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1192: return(0);
1193: mdoc->next = MDOC_NEXT_SIBLING;
1194: }
1195:
1196: if ( ! flushed) {
1197: if ( ! rew_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
1198: return(0);
1199: if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1200: return(0);
1201: mdoc->next = MDOC_NEXT_CHILD;
1202: }
1203:
1204: if (ppos > 1)
1205: return(1);
1206: return(append_delims(mdoc, line, pos, buf));
1207: }
1208:
1209:
1210: /*
1211: * In-line macros where reserved words signal closure of the macro.
1212: * Macros also have a fixed number of arguments.
1213: */
1214: static int
1215: in_line_argn(MACRO_PROT_ARGS)
1216: {
1217: int lastarg, flushed, j, c, maxargs;
1218: struct mdoc_arg *arg;
1219: char *p;
1220:
1221:
1222: /*
1223: * Fixed maximum arguments per macro. Some of these have none
1224: * and close as soon as the invocation is parsed.
1225: */
1226:
1227: switch (tok) {
1228: case (MDOC_Ap):
1229: /* FALLTHROUGH */
1230: case (MDOC_No):
1231: /* FALLTHROUGH */
1232: case (MDOC_Ns):
1233: /* FALLTHROUGH */
1234: case (MDOC_Ux):
1235: maxargs = 0;
1236: break;
1237: default:
1238: maxargs = 1;
1239: break;
1240: }
1241:
1.27 kristaps 1242: for (arg = NULL;; ) {
1.1 kristaps 1243: lastarg = *pos;
1244: c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1245:
1246: if (ARGV_WORD == c) {
1247: *pos = lastarg;
1248: break;
1249: }
1250:
1251: if (ARGV_EOLN == c)
1252: break;
1253: if (ARGV_ARG == c)
1254: continue;
1255:
1256: mdoc_argv_free(arg);
1257: return(0);
1258: }
1259:
1260: if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
1261: return(0);
1262: mdoc->next = MDOC_NEXT_CHILD;
1263:
1264: for (flushed = j = 0; ; j++) {
1265: lastarg = *pos;
1266:
1267: if (j == maxargs && ! flushed) {
1268: if ( ! rew_elem(mdoc, tok))
1269: return(0);
1270: flushed = 1;
1271: }
1272:
1273: c = mdoc_args(mdoc, line, pos, buf, tok, &p);
1274:
1275: if (ARGS_ERROR == c)
1276: return(0);
1277: if (ARGS_PUNCT == c)
1278: break;
1279: if (ARGS_EOLN == c)
1280: break;
1281:
1.29 ! kristaps 1282: if (MDOC_MAX != (c = lookup(mdoc, tok, p))) {
1.1 kristaps 1283: if ( ! flushed && ! rew_elem(mdoc, tok))
1284: return(0);
1285: flushed = 1;
1286: if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1287: return(0);
1288: break;
1289: }
1290:
1291: if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
1292: ! flushed && mdoc_isdelim(p)) {
1293: if ( ! rew_elem(mdoc, tok))
1294: return(0);
1295: flushed = 1;
1296: }
1297:
1298: if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
1299: return(0);
1300: mdoc->next = MDOC_NEXT_SIBLING;
1301: }
1302:
1303: if ( ! flushed && ! rew_elem(mdoc, tok))
1304: return(0);
1305:
1306: if (ppos > 1)
1307: return(1);
1308: return(append_delims(mdoc, line, pos, buf));
1309: }
1310:
1311:
1312: /*
1313: * In-line macro that spans an entire line. May be callable, but has no
1314: * subsequent parsed arguments.
1315: */
1316: static int
1317: in_line_eoln(MACRO_PROT_ARGS)
1318: {
1319: int c, w, la;
1320: struct mdoc_arg *arg;
1321: char *p;
1322:
1323: assert( ! (MDOC_PARSED & mdoc_macros[tok].flags));
1324:
1325: arg = NULL;
1326:
1327: for (;;) {
1328: la = *pos;
1329: c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
1330:
1331: if (ARGV_WORD == c) {
1332: *pos = la;
1333: break;
1334: }
1335: if (ARGV_EOLN == c)
1336: break;
1337: if (ARGV_ARG == c)
1338: continue;
1339:
1340: mdoc_argv_free(arg);
1341: return(0);
1342: }
1343:
1344: if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
1345: return(0);
1346:
1347: mdoc->next = MDOC_NEXT_CHILD;
1348:
1349: for (;;) {
1350: la = *pos;
1351: w = mdoc_args(mdoc, line, pos, buf, tok, &p);
1352:
1353: if (ARGS_ERROR == w)
1354: return(0);
1355: if (ARGS_EOLN == w)
1356: break;
1357:
1.28 kristaps 1358: c = ARGS_QWORD == w ? MDOC_MAX : lookup(mdoc, tok, p);
1.1 kristaps 1359:
1.29 ! kristaps 1360: if (MDOC_MAX != c) {
1.1 kristaps 1361: if ( ! rew_elem(mdoc, tok))
1362: return(0);
1363: return(mdoc_macro(mdoc, c, line, la, pos, buf));
1.29 ! kristaps 1364: }
1.1 kristaps 1365:
1366: if ( ! mdoc_word_alloc(mdoc, line, la, p))
1367: return(0);
1368: mdoc->next = MDOC_NEXT_SIBLING;
1369: }
1370:
1371: return(rew_elem(mdoc, tok));
1372: }
1373:
1374:
1375: /* ARGSUSED */
1376: static int
1377: obsolete(MACRO_PROT_ARGS)
1378: {
1379:
1.16 kristaps 1380: return(mdoc_pwarn(mdoc, line, ppos, EOBS));
1.1 kristaps 1381: }
1382:
1383:
1.24 kristaps 1384: /*
1385: * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs.
1386: * They're unusual because they're basically free-form text until a
1387: * macro is encountered.
1388: */
1.1 kristaps 1389: static int
1390: phrase(struct mdoc *mdoc, int line, int ppos, char *buf)
1391: {
1.24 kristaps 1392: int c, w, la, pos;
1393: char *p;
1.1 kristaps 1394:
1.24 kristaps 1395: for (pos = ppos; ; ) {
1396: la = pos;
1.1 kristaps 1397:
1.24 kristaps 1398: /* Note: no calling context! */
1399: w = mdoc_zargs(mdoc, line, &pos, buf, &p);
1.1 kristaps 1400:
1.24 kristaps 1401: if (ARGS_ERROR == w)
1402: return(0);
1403: if (ARGS_EOLN == w)
1404: break;
1.1 kristaps 1405:
1.29 ! kristaps 1406: c = ARGS_QWORD == w ? MDOC_MAX : lookup_raw(mdoc, p);
1.1 kristaps 1407:
1.29 ! kristaps 1408: if (MDOC_MAX != c) {
1.24 kristaps 1409: if ( ! mdoc_macro(mdoc, c, line, la, &pos, buf))
1.1 kristaps 1410: return(0);
1.24 kristaps 1411: return(append_delims(mdoc, line, &pos, buf));
1.29 ! kristaps 1412: }
1.1 kristaps 1413:
1.24 kristaps 1414: if ( ! mdoc_word_alloc(mdoc, line, la, p))
1.1 kristaps 1415: return(0);
1416: mdoc->next = MDOC_NEXT_SIBLING;
1417: }
1418:
1419: return(1);
1420: }
1.24 kristaps 1421:
1422:
CVSweb