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