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