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