| GCC Code Coverage Report | |||||||||||||||||||||
        
  | 
    |||||||||||||||||||||
| Line | Branch | Exec | Source | 
1  | 
    /* $OpenBSD: mdoc_macro.c,v 1.181 2017/05/30 16:21:07 schwarze Exp $ */  | 
    ||
2  | 
    /*  | 
    ||
3  | 
    * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>  | 
    ||
4  | 
    * Copyright (c) 2010, 2012-2017 Ingo Schwarze <schwarze@openbsd.org>  | 
    ||
5  | 
    *  | 
    ||
6  | 
    * Permission to use, copy, modify, and distribute this software for any  | 
    ||
7  | 
    * purpose with or without fee is hereby granted, provided that the above  | 
    ||
8  | 
    * copyright notice and this permission notice appear in all copies.  | 
    ||
9  | 
    *  | 
    ||
10  | 
    * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES  | 
    ||
11  | 
    * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF  | 
    ||
12  | 
    * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR  | 
    ||
13  | 
    * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES  | 
    ||
14  | 
    * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN  | 
    ||
15  | 
    * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF  | 
    ||
16  | 
    * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  | 
    ||
17  | 
    */  | 
    ||
18  | 
    #include <sys/types.h>  | 
    ||
19  | 
    |||
20  | 
    #include <assert.h>  | 
    ||
21  | 
    #include <ctype.h>  | 
    ||
22  | 
    #include <stdlib.h>  | 
    ||
23  | 
    #include <stdio.h>  | 
    ||
24  | 
    #include <string.h>  | 
    ||
25  | 
    #include <time.h>  | 
    ||
26  | 
    |||
27  | 
    #include "mandoc.h"  | 
    ||
28  | 
    #include "roff.h"  | 
    ||
29  | 
    #include "mdoc.h"  | 
    ||
30  | 
    #include "libmandoc.h"  | 
    ||
31  | 
    #include "roff_int.h"  | 
    ||
32  | 
    #include "libmdoc.h"  | 
    ||
33  | 
    |||
34  | 
    static void blk_full(MACRO_PROT_ARGS);  | 
    ||
35  | 
    static void blk_exp_close(MACRO_PROT_ARGS);  | 
    ||
36  | 
    static void blk_part_exp(MACRO_PROT_ARGS);  | 
    ||
37  | 
    static void blk_part_imp(MACRO_PROT_ARGS);  | 
    ||
38  | 
    static void ctx_synopsis(MACRO_PROT_ARGS);  | 
    ||
39  | 
    static void in_line_eoln(MACRO_PROT_ARGS);  | 
    ||
40  | 
    static void in_line_argn(MACRO_PROT_ARGS);  | 
    ||
41  | 
    static void in_line(MACRO_PROT_ARGS);  | 
    ||
42  | 
    static void phrase_ta(MACRO_PROT_ARGS);  | 
    ||
43  | 
    |||
44  | 
    static void append_delims(struct roff_man *, int, int *, char *);  | 
    ||
45  | 
    static void dword(struct roff_man *, int, int, const char *,  | 
    ||
46  | 
    enum mdelim, int);  | 
    ||
47  | 
    static int find_pending(struct roff_man *, enum roff_tok,  | 
    ||
48  | 
    int, int, struct roff_node *);  | 
    ||
49  | 
    static int lookup(struct roff_man *, int, int, int, const char *);  | 
    ||
50  | 
    static int macro_or_word(MACRO_PROT_ARGS, int);  | 
    ||
51  | 
    static void break_intermediate(struct roff_node *,  | 
    ||
52  | 
    struct roff_node *);  | 
    ||
53  | 
    static int parse_rest(struct roff_man *, enum roff_tok,  | 
    ||
54  | 
    int, int *, char *);  | 
    ||
55  | 
    static enum roff_tok rew_alt(enum roff_tok);  | 
    ||
56  | 
    static void rew_elem(struct roff_man *, enum roff_tok);  | 
    ||
57  | 
    static void rew_last(struct roff_man *, const struct roff_node *);  | 
    ||
58  | 
    static void rew_pending(struct roff_man *,  | 
    ||
59  | 
    const struct roff_node *);  | 
    ||
60  | 
    |||
61  | 
    const	struct mdoc_macro __mdoc_macros[MDOC_MAX - MDOC_Dd] = { | 
    ||
62  | 
    	{ in_line_eoln, MDOC_PROLOGUE }, /* Dd */ | 
    ||
63  | 
    	{ in_line_eoln, MDOC_PROLOGUE }, /* Dt */ | 
    ||
64  | 
    	{ in_line_eoln, MDOC_PROLOGUE }, /* Os */ | 
    ||
65  | 
    	{ blk_full, MDOC_PARSED | MDOC_JOIN }, /* Sh */ | 
    ||
66  | 
    	{ blk_full, MDOC_PARSED | MDOC_JOIN }, /* Ss */ | 
    ||
67  | 
    	{ in_line_eoln, 0 }, /* Pp */ | 
    ||
68  | 
    	{ blk_part_imp, MDOC_PARSED | MDOC_JOIN }, /* D1 */ | 
    ||
69  | 
    	{ blk_part_imp, MDOC_PARSED | MDOC_JOIN }, /* Dl */ | 
    ||
70  | 
    	{ blk_full, MDOC_EXPLICIT }, /* Bd */ | 
    ||
71  | 
    	{ blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ed */ | 
    ||
72  | 
    	{ blk_full, MDOC_EXPLICIT }, /* Bl */ | 
    ||
73  | 
    	{ blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* El */ | 
    ||
74  | 
    	{ blk_full, MDOC_PARSED | MDOC_JOIN }, /* It */ | 
    ||
75  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */ | 
    ||
76  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* An */ | 
    ||
77  | 
    	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
78  | 
    MDOC_IGNDELIM | MDOC_JOIN }, /* Ap */  | 
    ||
79  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */ | 
    ||
80  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Cd */ | 
    ||
81  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */ | 
    ||
82  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */ | 
    ||
83  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */ | 
    ||
84  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */ | 
    ||
85  | 
    	{ in_line_eoln, 0 }, /* Ex */ | 
    ||
86  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */ | 
    ||
87  | 
    	{ in_line_eoln, 0 }, /* Fd */ | 
    ||
88  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */ | 
    ||
89  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */ | 
    ||
90  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */ | 
    ||
91  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ic */ | 
    ||
92  | 
    	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */ | 
    ||
93  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Li */ | 
    ||
94  | 
    	{ blk_full, MDOC_JOIN }, /* Nd */ | 
    ||
95  | 
    	{ ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */ | 
    ||
96  | 
    	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */ | 
    ||
97  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ot */ | 
    ||
98  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */ | 
    ||
99  | 
    	{ in_line_eoln, 0 }, /* Rv */ | 
    ||
100  | 
    	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */ | 
    ||
101  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */ | 
    ||
102  | 
    	{ ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */ | 
    ||
103  | 
    	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */ | 
    ||
104  | 
    	{ in_line_eoln, MDOC_JOIN }, /* %A */ | 
    ||
105  | 
    	{ in_line_eoln, MDOC_JOIN }, /* %B */ | 
    ||
106  | 
    	{ in_line_eoln, MDOC_JOIN }, /* %D */ | 
    ||
107  | 
    	{ in_line_eoln, MDOC_JOIN }, /* %I */ | 
    ||
108  | 
    	{ in_line_eoln, MDOC_JOIN }, /* %J */ | 
    ||
109  | 
    	{ in_line_eoln, 0 }, /* %N */ | 
    ||
110  | 
    	{ in_line_eoln, MDOC_JOIN }, /* %O */ | 
    ||
111  | 
    	{ in_line_eoln, 0 }, /* %P */ | 
    ||
112  | 
    	{ in_line_eoln, MDOC_JOIN }, /* %R */ | 
    ||
113  | 
    	{ in_line_eoln, MDOC_JOIN }, /* %T */ | 
    ||
114  | 
    	{ in_line_eoln, 0 }, /* %V */ | 
    ||
115  | 
    	{ blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
116  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Ac */  | 
    ||
117  | 
    	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
118  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Ao */  | 
    ||
119  | 
    	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Aq */ | 
    ||
120  | 
    	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */ | 
    ||
121  | 
    	{ blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
122  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Bc */  | 
    ||
123  | 
    	{ blk_full, MDOC_EXPLICIT }, /* Bf */ | 
    ||
124  | 
    	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
125  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Bo */  | 
    ||
126  | 
    	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Bq */ | 
    ||
127  | 
    	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */ | 
    ||
128  | 
    	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */ | 
    ||
129  | 
    	{ in_line_eoln, 0 }, /* Db */ | 
    ||
130  | 
    	{ blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
131  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Dc */  | 
    ||
132  | 
    	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
133  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Do */  | 
    ||
134  | 
    	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Dq */ | 
    ||
135  | 
    	{ blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ec */ | 
    ||
136  | 
    	{ blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ef */ | 
    ||
137  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Em */ | 
    ||
138  | 
    	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */ | 
    ||
139  | 
    	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */ | 
    ||
140  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */ | 
    ||
141  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* No */ | 
    ||
142  | 
    	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
143  | 
    MDOC_IGNDELIM | MDOC_JOIN }, /* Ns */  | 
    ||
144  | 
    	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */ | 
    ||
145  | 
    	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */ | 
    ||
146  | 
    	{ blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
147  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Pc */  | 
    ||
148  | 
    	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */ | 
    ||
149  | 
    	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
150  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Po */  | 
    ||
151  | 
    	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Pq */ | 
    ||
152  | 
    	{ blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
153  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Qc */  | 
    ||
154  | 
    	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ql */ | 
    ||
155  | 
    	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
156  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Qo */  | 
    ||
157  | 
    	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Qq */ | 
    ||
158  | 
    	{ blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Re */ | 
    ||
159  | 
    	{ blk_full, MDOC_EXPLICIT }, /* Rs */ | 
    ||
160  | 
    	{ blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
161  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Sc */  | 
    ||
162  | 
    	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
163  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* So */  | 
    ||
164  | 
    	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sq */ | 
    ||
165  | 
    	{ in_line_argn, 0 }, /* Sm */ | 
    ||
166  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sx */ | 
    ||
167  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sy */ | 
    ||
168  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */ | 
    ||
169  | 
    	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ux */ | 
    ||
170  | 
    	{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */ | 
    ||
171  | 
    	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */ | 
    ||
172  | 
    	{ blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */ | 
    ||
173  | 
    	{ blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
174  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Fc */  | 
    ||
175  | 
    	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
176  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Oo */  | 
    ||
177  | 
    	{ blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
178  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Oc */  | 
    ||
179  | 
    	{ blk_full, MDOC_EXPLICIT }, /* Bk */ | 
    ||
180  | 
    	{ blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ek */ | 
    ||
181  | 
    	{ in_line_eoln, 0 }, /* Bt */ | 
    ||
182  | 
    	{ in_line_eoln, 0 }, /* Hf */ | 
    ||
183  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fr */ | 
    ||
184  | 
    	{ in_line_eoln, 0 }, /* Ud */ | 
    ||
185  | 
    	{ in_line, 0 }, /* Lb */ | 
    ||
186  | 
    	{ in_line_eoln, 0 }, /* Lp */ | 
    ||
187  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */ | 
    ||
188  | 
    	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */ | 
    ||
189  | 
    	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Brq */ | 
    ||
190  | 
    	{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
191  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Bro */  | 
    ||
192  | 
    	{ blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | | 
    ||
193  | 
    MDOC_EXPLICIT | MDOC_JOIN }, /* Brc */  | 
    ||
194  | 
    	{ in_line_eoln, MDOC_JOIN }, /* %C */ | 
    ||
195  | 
    	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Es */ | 
    ||
196  | 
    	{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* En */ | 
    ||
197  | 
    	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */ | 
    ||
198  | 
    	{ in_line_eoln, MDOC_JOIN }, /* %Q */ | 
    ||
199  | 
    	{ in_line_eoln, 0 }, /* %U */ | 
    ||
200  | 
    	{ phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */ | 
    ||
201  | 
    };  | 
    ||
202  | 
    const struct mdoc_macro *const mdoc_macros = __mdoc_macros - MDOC_Dd;  | 
    ||
203  | 
    |||
204  | 
    |||
205  | 
    /*  | 
    ||
206  | 
    * This is called at the end of parsing. It must traverse up the tree,  | 
    ||
207  | 
    * closing out open [implicit] scopes. Obviously, open explicit scopes  | 
    ||
208  | 
    * are errors.  | 
    ||
209  | 
    */  | 
    ||
210  | 
    void  | 
    ||
211  | 
    mdoc_endparse(struct roff_man *mdoc)  | 
    ||
212  | 
    { | 
    ||
213  | 
    struct roff_node *n;  | 
    ||
214  | 
    |||
215  | 
    /* Scan for open explicit scopes. */  | 
    ||
216  | 
    |||
217  | 
    ✓✓ | 68914  | 
    n = mdoc->last->flags & NODE_VALID ?  | 
    
218  | 
    17164  | 
    mdoc->last->parent : mdoc->last;  | 
    |
219  | 
    |||
220  | 
    ✓✓ | 139964  | 
    for ( ; n; n = n->parent)  | 
    
221  | 
    ✓✓✓✓ | 
    70473  | 
    if (n->type == ROFFT_BLOCK &&  | 
    
222  | 
    17741  | 
    mdoc_macros[n->tok].flags & MDOC_EXPLICIT)  | 
    |
223  | 
    216  | 
    mandoc_msg(MANDOCERR_BLK_NOEND, mdoc->parse,  | 
    |
224  | 
    108  | 
    n->line, n->pos, roff_name[n->tok]);  | 
    |
225  | 
    |||
226  | 
    /* Rewind to the first. */  | 
    ||
227  | 
    |||
228  | 
    17250  | 
    rew_last(mdoc, mdoc->first);  | 
    |
229  | 
    17250  | 
    mdoc_state_reset(mdoc);  | 
    |
230  | 
    17250  | 
    }  | 
    |
231  | 
    |||
232  | 
    /*  | 
    ||
233  | 
    * Look up the macro at *p called by "from",  | 
    ||
234  | 
    * or as a line macro if from == TOKEN_NONE.  | 
    ||
235  | 
    */  | 
    ||
236  | 
    static int  | 
    ||
237  | 
    lookup(struct roff_man *mdoc, int from, int line, int ppos, const char *p)  | 
    ||
238  | 
    { | 
    ||
239  | 
    enum roff_tok res;  | 
    ||
240  | 
    |||
241  | 
    ✓✓ | 2545536  | 
    	if (mdoc->flags & MDOC_PHRASEQF) { | 
    
242  | 
    1596  | 
    mdoc->flags &= ~MDOC_PHRASEQF;  | 
    |
243  | 
    1596  | 
    return TOKEN_NONE;  | 
    |
244  | 
    }  | 
    ||
245  | 
    ✓✓✓✓ | 
    2492598  | 
    	if (from == TOKEN_NONE || mdoc_macros[from].flags & MDOC_PARSED) { | 
    
246  | 
    1031036  | 
    res = roffhash_find(mdoc->mdocmac, p, 0);  | 
    |
247  | 
    ✓✓ | 1031036  | 
    		if (res != TOKEN_NONE) { | 
    
248  | 
    ✓✓ | 196436  | 
    if (mdoc_macros[res].flags & MDOC_CALLABLE)  | 
    
249  | 
    196427  | 
    return res;  | 
    |
250  | 
    9  | 
    mandoc_msg(MANDOCERR_MACRO_CALL,  | 
    |
251  | 
    9  | 
    mdoc->parse, line, ppos, p);  | 
    |
252  | 
    9  | 
    }  | 
    |
253  | 
    }  | 
    ||
254  | 
    1074745  | 
    return TOKEN_NONE;  | 
    |
255  | 
    1272768  | 
    }  | 
    |
256  | 
    |||
257  | 
    /*  | 
    ||
258  | 
    * Rewind up to and including a specific node.  | 
    ||
259  | 
    */  | 
    ||
260  | 
    static void  | 
    ||
261  | 
    rew_last(struct roff_man *mdoc, const struct roff_node *to)  | 
    ||
262  | 
    { | 
    ||
263  | 
    |||
264  | 
    ✓✓ | 2977222  | 
    if (to->flags & NODE_VALID)  | 
    
265  | 
    return;  | 
    ||
266  | 
    |||
267  | 
    ✓✓ | 7242978  | 
    	while (mdoc->last != to) { | 
    
268  | 
    2904407  | 
    mdoc_state(mdoc, mdoc->last);  | 
    |
269  | 
    mdoc->last->flags |= NODE_VALID | NODE_ENDED;  | 
    ||
270  | 
    1434164  | 
    mdoc->last = mdoc->last->parent;  | 
    |
271  | 
    }  | 
    ||
272  | 
    mdoc_state(mdoc, mdoc->last);  | 
    ||
273  | 
    mdoc->last->flags |= NODE_VALID | NODE_ENDED;  | 
    ||
274  | 
    1470243  | 
    mdoc->next = ROFF_NEXT_SIBLING;  | 
    |
275  | 
    2958854  | 
    }  | 
    |
276  | 
    |||
277  | 
    /*  | 
    ||
278  | 
    * Rewind up to a specific block, including all blocks that broke it.  | 
    ||
279  | 
    */  | 
    ||
280  | 
    static void  | 
    ||
281  | 
    rew_pending(struct roff_man *mdoc, const struct roff_node *n)  | 
    ||
282  | 
    { | 
    ||
283  | 
    |||
284  | 
    567456  | 
    	for (;;) { | 
    |
285  | 
    288393  | 
    rew_last(mdoc, n);  | 
    |
286  | 
    |||
287  | 
    ✓✓ | 288393  | 
    		if (mdoc->last == n) { | 
    
288  | 
    ✓✓✓ | 570919  | 
    			switch (n->type) { | 
    
289  | 
    case ROFFT_HEAD:  | 
    ||
290  | 
    5730  | 
    roff_body_alloc(mdoc, n->line, n->pos,  | 
    |
291  | 
    2865  | 
    n->tok);  | 
    |
292  | 
    2865  | 
    break;  | 
    |
293  | 
    case ROFFT_BLOCK:  | 
    ||
294  | 
    break;  | 
    ||
295  | 
    default:  | 
    ||
296  | 
    return;  | 
    ||
297  | 
    }  | 
    ||
298  | 
    ✓✓ | 284326  | 
    if ( ! (n->flags & NODE_BROKEN))  | 
    
299  | 
    return;  | 
    ||
300  | 
    } else  | 
    ||
301  | 
    n = mdoc->last;  | 
    ||
302  | 
    |||
303  | 
    		for (;;) { | 
    ||
304  | 
    ✓✗ | 13102  | 
    if ((n = n->parent) == NULL)  | 
    
305  | 
    return;  | 
    ||
306  | 
    |||
307  | 
    ✓✓✓✓ | 
    21297  | 
    if (n->type == ROFFT_BLOCK ||  | 
    
308  | 
    8195  | 
    			    n->type == ROFFT_HEAD) { | 
    |
309  | 
    ✓✓ | 8237  | 
    if (n->flags & NODE_ENDED)  | 
    
310  | 
    break;  | 
    ||
311  | 
    else  | 
    ||
312  | 
    return;  | 
    ||
313  | 
    }  | 
    ||
314  | 
    }  | 
    ||
315  | 
    }  | 
    ||
316  | 
    283728  | 
    }  | 
    |
317  | 
    |||
318  | 
    /*  | 
    ||
319  | 
    * For a block closing macro, return the corresponding opening one.  | 
    ||
320  | 
    * Otherwise, return the macro itself.  | 
    ||
321  | 
    */  | 
    ||
322  | 
    static enum roff_tok  | 
    ||
323  | 
    rew_alt(enum roff_tok tok)  | 
    ||
324  | 
    { | 
    ||
325  | 
    ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✗  | 
    99126  | 
    	switch (tok) { | 
    
326  | 
    case MDOC_Ac:  | 
    ||
327  | 
    636  | 
    return MDOC_Ao;  | 
    |
328  | 
    case MDOC_Bc:  | 
    ||
329  | 
    1311  | 
    return MDOC_Bo;  | 
    |
330  | 
    case MDOC_Brc:  | 
    ||
331  | 
    282  | 
    return MDOC_Bro;  | 
    |
332  | 
    case MDOC_Dc:  | 
    ||
333  | 
    276  | 
    return MDOC_Do;  | 
    |
334  | 
    case MDOC_Ec:  | 
    ||
335  | 
    660  | 
    return MDOC_Eo;  | 
    |
336  | 
    case MDOC_Ed:  | 
    ||
337  | 
    8582  | 
    return MDOC_Bd;  | 
    |
338  | 
    case MDOC_Ef:  | 
    ||
339  | 
    519  | 
    return MDOC_Bf;  | 
    |
340  | 
    case MDOC_Ek:  | 
    ||
341  | 
    762  | 
    return MDOC_Bk;  | 
    |
342  | 
    case MDOC_El:  | 
    ||
343  | 
    21863  | 
    return MDOC_Bl;  | 
    |
344  | 
    case MDOC_Fc:  | 
    ||
345  | 
    6548  | 
    return MDOC_Fo;  | 
    |
346  | 
    case MDOC_Oc:  | 
    ||
347  | 
    2567  | 
    return MDOC_Oo;  | 
    |
348  | 
    case MDOC_Pc:  | 
    ||
349  | 
    938  | 
    return MDOC_Po;  | 
    |
350  | 
    case MDOC_Qc:  | 
    ||
351  | 
    138  | 
    return MDOC_Qo;  | 
    |
352  | 
    case MDOC_Re:  | 
    ||
353  | 
    1697  | 
    return MDOC_Rs;  | 
    |
354  | 
    case MDOC_Sc:  | 
    ||
355  | 
    114  | 
    return MDOC_So;  | 
    |
356  | 
    case MDOC_Xc:  | 
    ||
357  | 
    2670  | 
    return MDOC_Xo;  | 
    |
358  | 
    default:  | 
    ||
359  | 
    return tok;  | 
    ||
360  | 
    }  | 
    ||
361  | 
    49563  | 
    }  | 
    |
362  | 
    |||
363  | 
    static void  | 
    ||
364  | 
    rew_elem(struct roff_man *mdoc, enum roff_tok tok)  | 
    ||
365  | 
    { | 
    ||
366  | 
    struct roff_node *n;  | 
    ||
367  | 
    |||
368  | 
    1359420  | 
    n = mdoc->last;  | 
    |
369  | 
    ✓✓ | 679710  | 
    if (n->type != ROFFT_ELEM)  | 
    
370  | 
    575489  | 
    n = n->parent;  | 
    |
371  | 
    ✗✓ | 679710  | 
    assert(n->type == ROFFT_ELEM);  | 
    
372  | 
    ✗✓ | 679710  | 
    assert(tok == n->tok);  | 
    
373  | 
    679710  | 
    rew_last(mdoc, n);  | 
    |
374  | 
    679710  | 
    }  | 
    |
375  | 
    |||
376  | 
    static void  | 
    ||
377  | 
    break_intermediate(struct roff_node *n, struct roff_node *breaker)  | 
    ||
378  | 
    { | 
    ||
379  | 
    ✓✗✓✓ | 
    12222  | 
    if (n != breaker &&  | 
    
380  | 
    ✓✓✓✗ | 
    9774  | 
    n->type != ROFFT_BLOCK && n->type != ROFFT_HEAD &&  | 
    
381  | 
    ✓✓ | 7326  | 
    (n->type != ROFFT_BODY || n->end != ENDBODY_NOT))  | 
    
382  | 
    2640  | 
    n = n->parent;  | 
    |
383  | 
    ✓✓ | 28818  | 
    	while (n != breaker) { | 
    
384  | 
    ✓✓ | 11964  | 
    if ( ! (n->flags & NODE_VALID))  | 
    
385  | 
    11958  | 
    n->flags |= NODE_BROKEN;  | 
    |
386  | 
    11964  | 
    n = n->parent;  | 
    |
387  | 
    }  | 
    ||
388  | 
    4890  | 
    }  | 
    |
389  | 
    |||
390  | 
    /*  | 
    ||
391  | 
    * If there is an open sub-block of the target requiring  | 
    ||
392  | 
    * explicit close-out, postpone closing out the target until  | 
    ||
393  | 
    * the rew_pending() call closing out the sub-block.  | 
    ||
394  | 
    */  | 
    ||
395  | 
    static int  | 
    ||
396  | 
    find_pending(struct roff_man *mdoc, enum roff_tok tok, int line, int ppos,  | 
    ||
397  | 
    struct roff_node *target)  | 
    ||
398  | 
    { | 
    ||
399  | 
    struct roff_node *n;  | 
    ||
400  | 
    int irc;  | 
    ||
401  | 
    |||
402  | 
    ✓✓ | 568206  | 
    if (target->flags & NODE_VALID)  | 
    
403  | 
    120  | 
    return 0;  | 
    |
404  | 
    |||
405  | 
    irc = 0;  | 
    ||
406  | 
    ✓✗✓✓ | 
    1580001  | 
    	for (n = mdoc->last; n != NULL && n != target; n = n->parent) { | 
    
407  | 
    ✓✓ | 242684  | 
    if (n->flags & NODE_ENDED)  | 
    
408  | 
    continue;  | 
    ||
409  | 
    ✓✓✓✗ | 
    10134  | 
    if (n->type == ROFFT_BLOCK &&  | 
    
410  | 
    3360  | 
    		    mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { | 
    |
411  | 
    irc = 1;  | 
    ||
412  | 
    3360  | 
    break_intermediate(mdoc->last, target);  | 
    |
413  | 
    ✓✓ | 3360  | 
    if (target->type == ROFFT_HEAD)  | 
    
414  | 
    2910  | 
    target->flags |= NODE_ENDED;  | 
    |
415  | 
    ✓✓ | 450  | 
    			else if ( ! (target->flags & NODE_ENDED)) { | 
    
416  | 
    288  | 
    mandoc_vmsg(MANDOCERR_BLK_NEST,  | 
    |
417  | 
    288  | 
    mdoc->parse, line, ppos,  | 
    |
418  | 
    288  | 
    "%s breaks %s", roff_name[tok],  | 
    |
419  | 
    288  | 
    roff_name[n->tok]);  | 
    |
420  | 
    288  | 
    mdoc_endbody_alloc(mdoc, line, ppos,  | 
    |
421  | 
    tok, target);  | 
    ||
422  | 
    288  | 
    }  | 
    |
423  | 
    }  | 
    ||
424  | 
    }  | 
    ||
425  | 
    283983  | 
    return irc;  | 
    |
426  | 
    284103  | 
    }  | 
    |
427  | 
    |||
428  | 
    /*  | 
    ||
429  | 
    * Allocate a word and check whether it's punctuation or not.  | 
    ||
430  | 
    * Punctuation consists of those tokens found in mdoc_isdelim().  | 
    ||
431  | 
    */  | 
    ||
432  | 
    static void  | 
    ||
433  | 
    dword(struct roff_man *mdoc, int line, int col, const char *p,  | 
    ||
434  | 
    enum mdelim d, int may_append)  | 
    ||
435  | 
    { | 
    ||
436  | 
    |||
437  | 
    ✓✓ | 2596058  | 
    if (d == DELIM_MAX)  | 
    
438  | 
    774874  | 
    d = mdoc_isdelim(p);  | 
    |
439  | 
    |||
440  | 
    ✓✓✓✓ | 
    1444168  | 
    if (may_append &&  | 
    
441  | 
    ✓✓ | 1145072  | 
    ! (mdoc->flags & (MDOC_SYNOPSIS | MDOC_KEEP | MDOC_SMOFF)) &&  | 
    
442  | 
    ✓✓ | 973833  | 
    d == DELIM_NONE && mdoc->last->type == ROFFT_TEXT &&  | 
    
443  | 
    146139  | 
    	    mdoc_isdelim(mdoc->last->string) == DELIM_NONE) { | 
    |
444  | 
    145632  | 
    roff_word_append(mdoc, p);  | 
    |
445  | 
    145632  | 
    return;  | 
    |
446  | 
    }  | 
    ||
447  | 
    |||
448  | 
    1152397  | 
    roff_word_alloc(mdoc, line, col, p);  | 
    |
449  | 
    |||
450  | 
    /*  | 
    ||
451  | 
    * If the word consists of a bare delimiter,  | 
    ||
452  | 
    * flag the new node accordingly,  | 
    ||
453  | 
    * unless doing so was vetoed by the invoking macro.  | 
    ||
454  | 
    * Always clear the veto, it is only valid for one word.  | 
    ||
455  | 
    */  | 
    ||
456  | 
    |||
457  | 
    ✓✓ | 1152397  | 
    if (d == DELIM_OPEN)  | 
    
458  | 
    4152  | 
    mdoc->last->flags |= NODE_DELIMO;  | 
    |
459  | 
    ✓✓✓✓ | 
    1302928  | 
    else if (d == DELIM_CLOSE &&  | 
    
460  | 
    ✓✓ | 156196  | 
    ! (mdoc->flags & MDOC_NODELIMC) &&  | 
    
461  | 
    154683  | 
    mdoc->last->parent->tok != MDOC_Fd)  | 
    |
462  | 
    154665  | 
    mdoc->last->flags |= NODE_DELIMC;  | 
    |
463  | 
    1152397  | 
    mdoc->flags &= ~MDOC_NODELIMC;  | 
    |
464  | 
    2450426  | 
    }  | 
    |
465  | 
    |||
466  | 
    static void  | 
    ||
467  | 
    append_delims(struct roff_man *mdoc, int line, int *pos, char *buf)  | 
    ||
468  | 
    { | 
    ||
469  | 
    1465174  | 
    char *p;  | 
    |
470  | 
    int la;  | 
    ||
471  | 
    |||
472  | 
    ✓✓ | 732587  | 
    if (buf[*pos] == '\0')  | 
    
473  | 
    592255  | 
    return;  | 
    |
474  | 
    |||
475  | 
    	for (;;) { | 
    ||
476  | 
    283762  | 
    la = *pos;  | 
    |
477  | 
    ✓✓ | 283762  | 
    if (mdoc_args(mdoc, line, pos, buf, TOKEN_NONE, &p) ==  | 
    
478  | 
    ARGS_EOLN)  | 
    ||
479  | 
    break;  | 
    ||
480  | 
    143430  | 
    dword(mdoc, line, la, p, DELIM_MAX, 1);  | 
    |
481  | 
    |||
482  | 
    /*  | 
    ||
483  | 
    * If we encounter end-of-sentence symbols, then trigger  | 
    ||
484  | 
    * the double-space.  | 
    ||
485  | 
    *  | 
    ||
486  | 
    * XXX: it's easy to allow this to propagate outward to  | 
    ||
487  | 
    * the last symbol, such that `. )' will cause the  | 
    ||
488  | 
    * correct double-spacing. However, (1) groff isn't  | 
    ||
489  | 
    * smart enough to do this and (2) it would require  | 
    ||
490  | 
    * knowing which symbols break this behaviour, for  | 
    ||
491  | 
    * example, `. ;' shouldn't propagate the double-space.  | 
    ||
492  | 
    */  | 
    ||
493  | 
    |||
494  | 
    ✓✓ | 143430  | 
    if (mandoc_eos(p, strlen(p)))  | 
    
495  | 
    51693  | 
    mdoc->last->flags |= NODE_EOS;  | 
    |
496  | 
    }  | 
    ||
497  | 
    872919  | 
    }  | 
    |
498  | 
    |||
499  | 
    /*  | 
    ||
500  | 
    * Parse one word.  | 
    ||
501  | 
    * If it is a macro, call it and return 1.  | 
    ||
502  | 
    * Otherwise, allocate it and return 0.  | 
    ||
503  | 
    */  | 
    ||
504  | 
    static int  | 
    ||
505  | 
    macro_or_word(MACRO_PROT_ARGS, int parsed)  | 
    ||
506  | 
    { | 
    ||
507  | 
    char *p;  | 
    ||
508  | 
    int ntok;  | 
    ||
509  | 
    |||
510  | 
    1178922  | 
    p = buf + ppos;  | 
    |
511  | 
    ntok = TOKEN_NONE;  | 
    ||
512  | 
    ✓✓ | 589461  | 
    if (*p == '"')  | 
    
513  | 
    14929  | 
    p++;  | 
    |
514  | 
    ✓✓✓✓ | 
    1147261  | 
    else if (parsed && ! (mdoc->flags & MDOC_PHRASELIT))  | 
    
515  | 
    572702  | 
    ntok = lookup(mdoc, tok, line, ppos, p);  | 
    |
516  | 
    |||
517  | 
    ✓✓ | 589461  | 
    	if (ntok == TOKEN_NONE) { | 
    
518  | 
    ✓✓ | 1343016  | 
    dword(mdoc, line, ppos, p, DELIM_MAX, tok == TOKEN_NONE ||  | 
    
519  | 
    423756  | 
    mdoc_macros[tok].flags & MDOC_JOIN);  | 
    |
520  | 
    459630  | 
    return 0;  | 
    |
521  | 
    	} else { | 
    ||
522  | 
    ✓✓✗✓ | 
    232167  | 
    if (tok != TOKEN_NONE &&  | 
    
523  | 
    102336  | 
    mdoc_macros[tok].fp == in_line_eoln)  | 
    |
524  | 
    rew_elem(mdoc, tok);  | 
    ||
525  | 
    129831  | 
    mdoc_macro(mdoc, ntok, line, ppos, pos, buf);  | 
    |
526  | 
    ✓✓ | 129831  | 
    if (tok == TOKEN_NONE)  | 
    
527  | 
    27495  | 
    append_delims(mdoc, line, pos, buf);  | 
    |
528  | 
    129831  | 
    return 1;  | 
    |
529  | 
    }  | 
    ||
530  | 
    589461  | 
    }  | 
    |
531  | 
    |||
532  | 
    /*  | 
    ||
533  | 
    * Close out block partial/full explicit.  | 
    ||
534  | 
    */  | 
    ||
535  | 
    static void  | 
    ||
536  | 
    blk_exp_close(MACRO_PROT_ARGS)  | 
    ||
537  | 
    { | 
    ||
538  | 
    struct roff_node *body; /* Our own body. */  | 
    ||
539  | 
    struct roff_node *endbody; /* Our own end marker. */  | 
    ||
540  | 
    struct roff_node *itblk; /* An It block starting later. */  | 
    ||
541  | 
    struct roff_node *later; /* A sub-block starting later. */  | 
    ||
542  | 
    struct roff_node *n; /* Search back to our block. */  | 
    ||
543  | 
    struct roff_node *target; /* For find_pending(). */  | 
    ||
544  | 
    |||
545  | 
    int j, lastarg, maxargs, nl, pending;  | 
    ||
546  | 
    enum margserr ac;  | 
    ||
547  | 
    enum roff_tok atok, ntok;  | 
    ||
548  | 
    99888  | 
    char *p;  | 
    |
549  | 
    |||
550  | 
    50325  | 
    nl = MDOC_NEWLINE & mdoc->flags;  | 
    |
551  | 
    |||
552  | 
    ✓✓✓ | 50325  | 
    	switch (tok) { | 
    
553  | 
    case MDOC_Ec:  | 
    ||
554  | 
    maxargs = 1;  | 
    ||
555  | 
    660  | 
    break;  | 
    |
556  | 
    case MDOC_Ek:  | 
    ||
557  | 
    762  | 
    mdoc->flags &= ~MDOC_KEEP;  | 
    |
558  | 
    /* FALLTHROUGH */  | 
    ||
559  | 
    default:  | 
    ||
560  | 
    maxargs = 0;  | 
    ||
561  | 
    48903  | 
    break;  | 
    |
562  | 
    }  | 
    ||
563  | 
    |||
564  | 
    /* Search backwards for the beginning of our own body. */  | 
    ||
565  | 
    |||
566  | 
    49563  | 
    atok = rew_alt(tok);  | 
    |
567  | 
    body = NULL;  | 
    ||
568  | 
    ✓✓ | 289352  | 
    	for (n = mdoc->last; n; n = n->parent) { | 
    
569  | 
    ✓✓✓✓ ✓✗  | 
    290519  | 
    if (n->flags & NODE_ENDED || n->tok != atok ||  | 
    
570  | 
    ✓✗ | 98928  | 
    n->type != ROFFT_BODY || n->end != ENDBODY_NOT)  | 
    
571  | 
    continue;  | 
    ||
572  | 
    body = n;  | 
    ||
573  | 
    49464  | 
    break;  | 
    |
574  | 
    }  | 
    ||
575  | 
    |||
576  | 
    /*  | 
    ||
577  | 
    * Search backwards for beginnings of blocks,  | 
    ||
578  | 
    * both of our own and of pending sub-blocks.  | 
    ||
579  | 
    */  | 
    ||
580  | 
    |||
581  | 
    endbody = itblk = later = NULL;  | 
    ||
582  | 
    ✓✓ | 388280  | 
    	for (n = mdoc->last; n; n = n->parent) { | 
    
583  | 
    ✓✓ | 388082  | 
    if (n->flags & NODE_ENDED)  | 
    
584  | 
    continue;  | 
    ||
585  | 
    |||
586  | 
    /*  | 
    ||
587  | 
    * Mismatching end macros can never break anything  | 
    ||
588  | 
    * and we only care about the breaking of BLOCKs.  | 
    ||
589  | 
    */  | 
    ||
590  | 
    |||
591  | 
    ✓✓ | 339398  | 
    if (body == NULL || n->type != ROFFT_BLOCK)  | 
    
592  | 
    continue;  | 
    ||
593  | 
    |||
594  | 
    /*  | 
    ||
595  | 
    * SYNOPSIS name blocks can not be broken themselves,  | 
    ||
596  | 
    * but they do get broken together with a broken child.  | 
    ||
597  | 
    */  | 
    ||
598  | 
    |||
599  | 
    ✓✓ | 72605  | 
    		if (n->tok == MDOC_Nm) { | 
    
600  | 
    ✓✓ | 93  | 
    if (later != NULL)  | 
    
601  | 
    27  | 
    n->flags |= NODE_BROKEN | NODE_ENDED;  | 
    |
602  | 
    continue;  | 
    ||
603  | 
    }  | 
    ||
604  | 
    |||
605  | 
    ✓✓ | 72512  | 
    		if (n->tok == MDOC_It) { | 
    
606  | 
    itblk = n;  | 
    ||
607  | 
    21437  | 
    continue;  | 
    |
608  | 
    }  | 
    ||
609  | 
    |||
610  | 
    ✓✓ | 51075  | 
    		if (atok == n->tok) { | 
    
611  | 
    |||
612  | 
    /*  | 
    ||
613  | 
    * Found the start of our own block.  | 
    ||
614  | 
    * When there is no pending sub block,  | 
    ||
615  | 
    * just proceed to closing out.  | 
    ||
616  | 
    */  | 
    ||
617  | 
    |||
618  | 
    ✓✓ | 49464  | 
    if (later == NULL ||  | 
    
619  | 
    ✓✗ | 1359  | 
    (tok == MDOC_El && itblk == NULL))  | 
    
620  | 
    break;  | 
    ||
621  | 
    |||
622  | 
    /*  | 
    ||
623  | 
    * When there is a pending sub block, postpone  | 
    ||
624  | 
    * closing out the current block until the  | 
    ||
625  | 
    * rew_pending() closing out the sub-block.  | 
    ||
626  | 
    * Mark the place where the formatting - but not  | 
    ||
627  | 
    * the scope - of the current block ends.  | 
    ||
628  | 
    */  | 
    ||
629  | 
    |||
630  | 
    2718  | 
    mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse,  | 
    |
631  | 
    line, ppos, "%s breaks %s",  | 
    ||
632  | 
    1359  | 
    roff_name[atok], roff_name[later->tok]);  | 
    |
633  | 
    |||
634  | 
    1359  | 
    endbody = mdoc_endbody_alloc(mdoc, line, ppos,  | 
    |
635  | 
    atok, body);  | 
    ||
636  | 
    |||
637  | 
    ✓✓ | 1359  | 
    if (tok == MDOC_El)  | 
    
638  | 
    162  | 
    itblk->flags |= NODE_ENDED | NODE_BROKEN;  | 
    |
639  | 
    |||
640  | 
    /*  | 
    ||
641  | 
    * If a block closing macro taking arguments  | 
    ||
642  | 
    * breaks another block, put the arguments  | 
    ||
643  | 
    * into the end marker.  | 
    ||
644  | 
    */  | 
    ||
645  | 
    |||
646  | 
    ✓✓ | 1359  | 
    if (maxargs)  | 
    
647  | 
    144  | 
    mdoc->next = ROFF_NEXT_CHILD;  | 
    |
648  | 
    break;  | 
    ||
649  | 
    }  | 
    ||
650  | 
    |||
651  | 
    /*  | 
    ||
652  | 
    * Explicit blocks close out description lines, but  | 
    ||
653  | 
    * even those can get broken together with a child.  | 
    ||
654  | 
    */  | 
    ||
655  | 
    |||
656  | 
    ✓✓ | 1611  | 
    		if (n->tok == MDOC_Nd) { | 
    
657  | 
    ✓✓ | 81  | 
    if (later != NULL)  | 
    
658  | 
    27  | 
    n->flags |= NODE_BROKEN | NODE_ENDED;  | 
    |
659  | 
    else  | 
    ||
660  | 
    54  | 
    rew_last(mdoc, n);  | 
    |
661  | 
    continue;  | 
    ||
662  | 
    }  | 
    ||
663  | 
    |||
664  | 
    /* Breaking an open sub block. */  | 
    ||
665  | 
    |||
666  | 
    1530  | 
    break_intermediate(mdoc->last, body);  | 
    |
667  | 
    1530  | 
    n->flags |= NODE_BROKEN;  | 
    |
668  | 
    ✓✓ | 1530  | 
    if (later == NULL)  | 
    
669  | 
    1359  | 
    later = n;  | 
    |
670  | 
    }  | 
    ||
671  | 
    |||
672  | 
    ✓✓ | 49563  | 
    	if (body == NULL) { | 
    
673  | 
    198  | 
    mandoc_msg(MANDOCERR_BLK_NOTOPEN, mdoc->parse,  | 
    |
674  | 
    99  | 
    line, ppos, roff_name[tok]);  | 
    |
675  | 
    ✓✓ | 99  | 
    		if (maxargs && endbody == NULL) { | 
    
676  | 
    /*  | 
    ||
677  | 
    * Stray .Ec without previous .Eo:  | 
    ||
678  | 
    * Break the output line, keep the arguments.  | 
    ||
679  | 
    */  | 
    ||
680  | 
    27  | 
    roff_elem_alloc(mdoc, line, ppos, ROFF_br);  | 
    |
681  | 
    27  | 
    rew_elem(mdoc, ROFF_br);  | 
    |
682  | 
    27  | 
    }  | 
    |
683  | 
    ✓✓ | 49464  | 
    	} else if (endbody == NULL) { | 
    
684  | 
    48105  | 
    rew_last(mdoc, body);  | 
    |
685  | 
    ✓✓ | 48105  | 
    if (maxargs)  | 
    
686  | 
    489  | 
    mdoc_tail_alloc(mdoc, line, ppos, atok);  | 
    |
687  | 
    }  | 
    ||
688  | 
    |||
689  | 
    ✓✓ | 49563  | 
    	if ( ! (mdoc_macros[tok].flags & MDOC_PARSED)) { | 
    
690  | 
    ✓✓ | 33423  | 
    if (buf[*pos] != '\0')  | 
    
691  | 
    153  | 
    mandoc_vmsg(MANDOCERR_ARG_SKIP,  | 
    |
692  | 
    153  | 
    mdoc->parse, line, ppos,  | 
    |
693  | 
    153  | 
    "%s %s", roff_name[tok],  | 
    |
694  | 
    buf + *pos);  | 
    ||
695  | 
    ✓✓ | 33423  | 
    if (endbody == NULL && n != NULL)  | 
    
696  | 
    33207  | 
    rew_pending(mdoc, n);  | 
    |
697  | 
    33423  | 
    return;  | 
    |
698  | 
    }  | 
    ||
699  | 
    |||
700  | 
    ✓✓ | 16140  | 
    if (endbody != NULL)  | 
    
701  | 
    1143  | 
    n = endbody;  | 
    |
702  | 
    |||
703  | 
    ntok = TOKEN_NONE;  | 
    ||
704  | 
    18276  | 
    	for (j = 0; ; j++) { | 
    |
705  | 
    18276  | 
    lastarg = *pos;  | 
    |
706  | 
    |||
707  | 
    ✓✓ | 18276  | 
    if (j == maxargs && n != NULL)  | 
    
708  | 
    15807  | 
    rew_last(mdoc, n);  | 
    |
709  | 
    |||
710  | 
    18276  | 
    ac = mdoc_args(mdoc, line, pos, buf, tok, &p);  | 
    |
711  | 
    ✓✓ | 18276  | 
    if (ac == ARGS_PUNCT || ac == ARGS_EOLN)  | 
    
712  | 
    break;  | 
    ||
713  | 
    |||
714  | 
    4736  | 
    ntok = lookup(mdoc, tok, line, lastarg, p);  | 
    |
715  | 
    |||
716  | 
    ✓✓ | 4736  | 
    		if (ntok == TOKEN_NONE) { | 
    
717  | 
    4272  | 
    dword(mdoc, line, lastarg, p, DELIM_MAX,  | 
    |
718  | 
    2136  | 
    MDOC_JOIN & mdoc_macros[tok].flags);  | 
    |
719  | 
    continue;  | 
    ||
720  | 
    }  | 
    ||
721  | 
    |||
722  | 
    ✓✗ | 2600  | 
    if (n != NULL)  | 
    
723  | 
    2600  | 
    rew_last(mdoc, n);  | 
    |
724  | 
    2600  | 
    mdoc->flags &= ~MDOC_NEWLINE;  | 
    |
725  | 
    2600  | 
    mdoc_macro(mdoc, ntok, line, lastarg, pos, buf);  | 
    |
726  | 
    2600  | 
    break;  | 
    |
727  | 
    }  | 
    ||
728  | 
    |||
729  | 
    ✓✓ | 16140  | 
    	if (n != NULL) { | 
    
730  | 
    pending = 0;  | 
    ||
731  | 
    ✓✓✓✓ | 
    18641  | 
    		if (ntok != TOKEN_NONE && n->flags & NODE_BROKEN) { | 
    
732  | 
    target = n;  | 
    ||
733  | 
    180  | 
    do  | 
    |
734  | 
    ✗✓ | 360  | 
    target = target->parent;  | 
    
735  | 
    180  | 
    while ( ! (target->flags & NODE_ENDED));  | 
    |
736  | 
    180  | 
    pending = find_pending(mdoc, ntok, line, ppos, target);  | 
    |
737  | 
    180  | 
    }  | 
    |
738  | 
    ✓✓ | 16041  | 
    if ( ! pending)  | 
    
739  | 
    15960  | 
    rew_pending(mdoc, n);  | 
    |
740  | 
    }  | 
    ||
741  | 
    ✓✓ | 16140  | 
    if (nl)  | 
    
742  | 
    12997  | 
    append_delims(mdoc, line, pos, buf);  | 
    |
743  | 
    65703  | 
    }  | 
    |
744  | 
    |||
745  | 
    static void  | 
    ||
746  | 
    in_line(MACRO_PROT_ARGS)  | 
    ||
747  | 
    { | 
    ||
748  | 
    int la, scope, cnt, firstarg, mayopen, nc, nl;  | 
    ||
749  | 
    enum roff_tok ntok;  | 
    ||
750  | 
    enum margserr ac;  | 
    ||
751  | 
    enum mdelim d;  | 
    ||
752  | 
    923536  | 
    struct mdoc_arg *arg;  | 
    |
753  | 
    461768  | 
    char *p;  | 
    |
754  | 
    |||
755  | 
    461768  | 
    nl = MDOC_NEWLINE & mdoc->flags;  | 
    |
756  | 
    |||
757  | 
    /*  | 
    ||
758  | 
    * Whether we allow ignored elements (those without content,  | 
    ||
759  | 
    * usually because of reserved words) to squeak by.  | 
    ||
760  | 
    */  | 
    ||
761  | 
    |||
762  | 
    ✗✗✗✗ ✗✓✓  | 
    461768  | 
    	switch (tok) { | 
    
763  | 
    case MDOC_An:  | 
    ||
764  | 
    case MDOC_Ar:  | 
    ||
765  | 
    case MDOC_Fl:  | 
    ||
766  | 
    case MDOC_Mt:  | 
    ||
767  | 
    case MDOC_Nm:  | 
    ||
768  | 
    case MDOC_Pa:  | 
    ||
769  | 
    nc = 1;  | 
    ||
770  | 
    178498  | 
    break;  | 
    |
771  | 
    default:  | 
    ||
772  | 
    nc = 0;  | 
    ||
773  | 
    283270  | 
    break;  | 
    |
774  | 
    }  | 
    ||
775  | 
    |||
776  | 
    461768  | 
    mdoc_argv(mdoc, line, tok, &arg, pos, buf);  | 
    |
777  | 
    |||
778  | 
    d = DELIM_NONE;  | 
    ||
779  | 
    firstarg = 1;  | 
    ||
780  | 
    mayopen = 1;  | 
    ||
781  | 
    461768  | 
    	for (cnt = scope = 0;; ) { | 
    |
782  | 
    984329  | 
    la = *pos;  | 
    |
783  | 
    984329  | 
    ac = mdoc_args(mdoc, line, pos, buf, tok, &p);  | 
    |
784  | 
    |||
785  | 
    /*  | 
    ||
786  | 
    * At the end of a macro line,  | 
    ||
787  | 
    * opening delimiters do not suppress spacing.  | 
    ||
788  | 
    */  | 
    ||
789  | 
    |||
790  | 
    ✓✓ | 984329  | 
    		if (ac == ARGS_EOLN) { | 
    
791  | 
    ✓✓ | 329386  | 
    if (d == DELIM_OPEN)  | 
    
792  | 
    576  | 
    mdoc->last->flags &= ~NODE_DELIMO;  | 
    |
793  | 
    break;  | 
    ||
794  | 
    }  | 
    ||
795  | 
    |||
796  | 
    /*  | 
    ||
797  | 
    * The rest of the macro line is only punctuation,  | 
    ||
798  | 
    * to be handled by append_delims().  | 
    ||
799  | 
    * If there were no other arguments,  | 
    ||
800  | 
    * do not allow the first one to suppress spacing,  | 
    ||
801  | 
    * even if it turns out to be a closing one.  | 
    ||
802  | 
    */  | 
    ||
803  | 
    |||
804  | 
    ✓✓ | 654943  | 
    		if (ac == ARGS_PUNCT) { | 
    
805  | 
    ✓✓✓✓ | 
    81324  | 
    if (cnt == 0 && (nc == 0 || tok == MDOC_An))  | 
    
806  | 
    1513  | 
    mdoc->flags |= MDOC_NODELIMC;  | 
    |
807  | 
    break;  | 
    ||
808  | 
    }  | 
    ||
809  | 
    |||
810  | 
    ✓✓ | 1669747  | 
    ntok = (tok == MDOC_Fn && !cnt) ?  | 
    
811  | 
    517419  | 
    TOKEN_NONE : lookup(mdoc, tok, line, la, p);  | 
    |
812  | 
    |||
813  | 
    /*  | 
    ||
814  | 
    * In this case, we've located a submacro and must  | 
    ||
815  | 
    * execute it. Close out scope, if open. If no  | 
    ||
816  | 
    * elements have been generated, either create one (nc)  | 
    ||
817  | 
    * or raise a warning.  | 
    ||
818  | 
    */  | 
    ||
819  | 
    |||
820  | 
    ✓✓ | 576164  | 
    		if (ntok != TOKEN_NONE) { | 
    
821  | 
    ✓✓ | 53603  | 
    if (scope)  | 
    
822  | 
    33879  | 
    rew_elem(mdoc, tok);  | 
    |
823  | 
    ✓✓ | 53603  | 
    			if (nc && ! cnt) { | 
    
824  | 
    685  | 
    mdoc_elem_alloc(mdoc, line, ppos, tok, arg);  | 
    |
825  | 
    685  | 
    rew_last(mdoc, mdoc->last);  | 
    |
826  | 
    ✓✓ | 53603  | 
    			} else if ( ! nc && ! cnt) { | 
    
827  | 
    2016  | 
    mdoc_argv_free(arg);  | 
    |
828  | 
    2016  | 
    mandoc_msg(MANDOCERR_MACRO_EMPTY,  | 
    |
829  | 
    2016  | 
    mdoc->parse, line, ppos,  | 
    |
830  | 
    2016  | 
    roff_name[tok]);  | 
    |
831  | 
    2016  | 
    }  | 
    |
832  | 
    53603  | 
    mdoc_macro(mdoc, ntok, line, la, pos, buf);  | 
    |
833  | 
    ✓✓ | 53603  | 
    if (nl)  | 
    
834  | 
    13569  | 
    append_delims(mdoc, line, pos, buf);  | 
    |
835  | 
    53603  | 
    return;  | 
    |
836  | 
    }  | 
    ||
837  | 
    |||
838  | 
    /*  | 
    ||
839  | 
    * Handle punctuation. Set up our scope, if a word;  | 
    ||
840  | 
    * rewind the scope, if a delimiter; then append the word.  | 
    ||
841  | 
    */  | 
    ||
842  | 
    |||
843  | 
    ✓✓ | 522561  | 
    		if ((d = mdoc_isdelim(p)) != DELIM_NONE) { | 
    
844  | 
    /*  | 
    ||
845  | 
    * If we encounter closing punctuation, no word  | 
    ||
846  | 
    * has been emitted, no scope is open, and we're  | 
    ||
847  | 
    * allowed to have an empty element, then start  | 
    ||
848  | 
    * a new scope.  | 
    ||
849  | 
    */  | 
    ||
850  | 
    ✓✓ | 18334  | 
    if ((d == DELIM_CLOSE ||  | 
    
851  | 
    ✓✓ | 28596  | 
    (d == DELIM_MIDDLE && tok == MDOC_Fl)) &&  | 
    
852  | 
    ✓✓ | 32632  | 
    			    !cnt && !scope && nc && mayopen) { | 
    
853  | 
    1359  | 
    mdoc_elem_alloc(mdoc, line, ppos, tok, arg);  | 
    |
854  | 
    scope = 1;  | 
    ||
855  | 
    1359  | 
    cnt++;  | 
    |
856  | 
    ✓✓ | 1359  | 
    if (tok == MDOC_Nm)  | 
    
857  | 
    324  | 
    mayopen = 0;  | 
    |
858  | 
    }  | 
    ||
859  | 
    /*  | 
    ||
860  | 
    * Close out our scope, if one is open, before  | 
    ||
861  | 
    * any punctuation.  | 
    ||
862  | 
    */  | 
    ||
863  | 
    ✓✓ | 18334  | 
    			if (scope && tok != MDOC_Lk) { | 
    
864  | 
    10456  | 
    rew_elem(mdoc, tok);  | 
    |
865  | 
    scope = 0;  | 
    ||
866  | 
    ✓✓ | 10456  | 
    if (tok == MDOC_Fn)  | 
    
867  | 
    36  | 
    mayopen = 0;  | 
    |
868  | 
    }  | 
    ||
869  | 
    ✓✓ | 504227  | 
    		} else if (mayopen && !scope) { | 
    
870  | 
    439503  | 
    mdoc_elem_alloc(mdoc, line, ppos, tok, arg);  | 
    |
871  | 
    scope = 1;  | 
    ||
872  | 
    439503  | 
    cnt++;  | 
    |
873  | 
    439503  | 
    }  | 
    |
874  | 
    |||
875  | 
    1045122  | 
    dword(mdoc, line, la, p, d,  | 
    |
876  | 
    522561  | 
    mdoc_macros[tok].flags & MDOC_JOIN);  | 
    |
877  | 
    |||
878  | 
    /*  | 
    ||
879  | 
    * If the first argument is a closing delimiter,  | 
    ||
880  | 
    * do not suppress spacing before it.  | 
    ||
881  | 
    */  | 
    ||
882  | 
    |||
883  | 
    ✓✓ | 522561  | 
    if (firstarg && d == DELIM_CLOSE && !nc)  | 
    
884  | 
    3564  | 
    mdoc->last->flags &= ~NODE_DELIMC;  | 
    |
885  | 
    firstarg = 0;  | 
    ||
886  | 
    |||
887  | 
    /*  | 
    ||
888  | 
    * `Fl' macros have their scope re-opened with each new  | 
    ||
889  | 
    * word so that the `-' can be added to each one without  | 
    ||
890  | 
    * having to parse out spaces.  | 
    ||
891  | 
    */  | 
    ||
892  | 
    ✓✓ | 522561  | 
    		if (scope && tok == MDOC_Fl) { | 
    
893  | 
    41025  | 
    rew_elem(mdoc, tok);  | 
    |
894  | 
    scope = 0;  | 
    ||
895  | 
    41025  | 
    }  | 
    |
896  | 
    }  | 
    ||
897  | 
    |||
898  | 
    ✓✓ | 408165  | 
    	if (scope && tok != MDOC_Lk) { | 
    
899  | 
    354998  | 
    rew_elem(mdoc, tok);  | 
    |
900  | 
    scope = 0;  | 
    ||
901  | 
    354998  | 
    }  | 
    |
902  | 
    |||
903  | 
    /*  | 
    ||
904  | 
    * If no elements have been collected and we're allowed to have  | 
    ||
905  | 
    * empties (nc), open a scope and close it out. Otherwise,  | 
    ||
906  | 
    * raise a warning.  | 
    ||
907  | 
    */  | 
    ||
908  | 
    |||
909  | 
    ✓✓ | 408165  | 
    	if ( ! cnt) { | 
    
910  | 
    ✓✓ | 27392  | 
    		if (nc) { | 
    
911  | 
    24547  | 
    mdoc_elem_alloc(mdoc, line, ppos, tok, arg);  | 
    |
912  | 
    24547  | 
    rew_last(mdoc, mdoc->last);  | 
    |
913  | 
    24547  | 
    		} else { | 
    |
914  | 
    2845  | 
    mdoc_argv_free(arg);  | 
    |
915  | 
    5690  | 
    mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,  | 
    |
916  | 
    2845  | 
    line, ppos, roff_name[tok]);  | 
    |
917  | 
    }  | 
    ||
918  | 
    }  | 
    ||
919  | 
    ✓✓ | 408165  | 
    if (nl)  | 
    
920  | 
    314370  | 
    append_delims(mdoc, line, pos, buf);  | 
    |
921  | 
    ✓✓ | 408165  | 
    if (scope)  | 
    
922  | 
    504  | 
    rew_elem(mdoc, tok);  | 
    |
923  | 
    869933  | 
    }  | 
    |
924  | 
    |||
925  | 
    static void  | 
    ||
926  | 
    blk_full(MACRO_PROT_ARGS)  | 
    ||
927  | 
    { | 
    ||
928  | 
    501246  | 
    int la, nl, parsed;  | 
    |
929  | 
    250623  | 
    struct mdoc_arg *arg;  | 
    |
930  | 
    struct roff_node *blk; /* Our own or a broken block. */  | 
    ||
931  | 
    struct roff_node *head; /* Our own head. */  | 
    ||
932  | 
    struct roff_node *body; /* Our own body. */  | 
    ||
933  | 
    struct roff_node *n;  | 
    ||
934  | 
    enum margserr ac, lac;  | 
    ||
935  | 
    250623  | 
    char *p;  | 
    |
936  | 
    |||
937  | 
    250623  | 
    nl = MDOC_NEWLINE & mdoc->flags;  | 
    |
938  | 
    |||
939  | 
    ✓✓✓✓ | 
    264885  | 
    	if (buf[*pos] == '\0' && (tok == MDOC_Sh || tok == MDOC_Ss)) { | 
    
940  | 
    144  | 
    mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,  | 
    |
941  | 
    72  | 
    line, ppos, roff_name[tok]);  | 
    |
942  | 
    72  | 
    return;  | 
    |
943  | 
    }  | 
    ||
944  | 
    |||
945  | 
    ✓✓ | 250551  | 
    	if ( ! (mdoc_macros[tok].flags & MDOC_EXPLICIT)) { | 
    
946  | 
    |||
947  | 
    /* Here, tok is one of Sh Ss Nm Nd It. */  | 
    ||
948  | 
    |||
949  | 
    blk = NULL;  | 
    ||
950  | 
    ✓✓ | 1888192  | 
    		for (n = mdoc->last; n != NULL; n = n->parent) { | 
    
951  | 
    ✓✓ | 868405  | 
    			if (n->flags & NODE_ENDED) { | 
    
952  | 
    ✓✓ | 180918  | 
    if ( ! (n->flags & NODE_VALID))  | 
    
953  | 
    108  | 
    n->flags |= NODE_BROKEN;  | 
    |
954  | 
    continue;  | 
    ||
955  | 
    }  | 
    ||
956  | 
    ✓✓ | 687487  | 
    if (n->type != ROFFT_BLOCK)  | 
    
957  | 
    continue;  | 
    ||
958  | 
    |||
959  | 
    ✓✓✓✓ | 
    506182  | 
    			if (tok == MDOC_It && n->tok == MDOC_Bl) { | 
    
960  | 
    ✓✓ | 110649  | 
    				if (blk != NULL) { | 
    
961  | 
    144  | 
    mandoc_vmsg(MANDOCERR_BLK_BROKEN,  | 
    |
962  | 
    144  | 
    mdoc->parse, line, ppos,  | 
    |
963  | 
    "It breaks %s",  | 
    ||
964  | 
    144  | 
    roff_name[blk->tok]);  | 
    |
965  | 
    144  | 
    rew_pending(mdoc, blk);  | 
    |
966  | 
    144  | 
    }  | 
    |
967  | 
    break;  | 
    ||
968  | 
    }  | 
    ||
969  | 
    |||
970  | 
    ✓✓ | 195249  | 
    			if (mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { | 
    
971  | 
    ✗✓✓✓ | 
    144555  | 
    				switch (tok) { | 
    
972  | 
    case MDOC_Sh:  | 
    ||
973  | 
    case MDOC_Ss:  | 
    ||
974  | 
    162  | 
    mandoc_vmsg(MANDOCERR_BLK_BROKEN,  | 
    |
975  | 
    162  | 
    mdoc->parse, line, ppos,  | 
    |
976  | 
    162  | 
    "%s breaks %s", roff_name[tok],  | 
    |
977  | 
    162  | 
    roff_name[n->tok]);  | 
    |
978  | 
    162  | 
    rew_pending(mdoc, n);  | 
    |
979  | 
    162  | 
    n = mdoc->last;  | 
    |
980  | 
    162  | 
    continue;  | 
    |
981  | 
    case MDOC_It:  | 
    ||
982  | 
    /* Delay in case it's astray. */  | 
    ||
983  | 
    blk = n;  | 
    ||
984  | 
    351  | 
    continue;  | 
    |
985  | 
    default:  | 
    ||
986  | 
    break;  | 
    ||
987  | 
    }  | 
    ||
988  | 
    break;  | 
    ||
989  | 
    }  | 
    ||
990  | 
    |||
991  | 
    /* Here, n is one of Sh Ss Nm Nd It. */  | 
    ||
992  | 
    |||
993  | 
    ✓✓✓✓ ✓✓  | 
    312240  | 
    if (tok != MDOC_Sh && (n->tok == MDOC_Sh ||  | 
    
994  | 
    ✓✓✓✗ | 
    183127  | 
    (tok != MDOC_Ss && (n->tok == MDOC_Ss ||  | 
    
995  | 
    ✓✓ | 91493  | 
    (tok != MDOC_It && n->tok == MDOC_It)))))  | 
    
996  | 
    break;  | 
    ||
997  | 
    |||
998  | 
    /* Item breaking an explicit block. */  | 
    ||
999  | 
    |||
1000  | 
    ✓✓ | 170775  | 
    			if (blk != NULL) { | 
    
1001  | 
    171  | 
    mandoc_vmsg(MANDOCERR_BLK_BROKEN,  | 
    |
1002  | 
    171  | 
    mdoc->parse, line, ppos,  | 
    |
1003  | 
    171  | 
    "It breaks %s", roff_name[blk->tok]);  | 
    |
1004  | 
    171  | 
    rew_pending(mdoc, blk);  | 
    |
1005  | 
    blk = NULL;  | 
    ||
1006  | 
    171  | 
    }  | 
    |
1007  | 
    |||
1008  | 
    /* Close out prior implicit scopes. */  | 
    ||
1009  | 
    |||
1010  | 
    170775  | 
    rew_pending(mdoc, n);  | 
    |
1011  | 
    170775  | 
    }  | 
    |
1012  | 
    |||
1013  | 
    /* Skip items outside lists. */  | 
    ||
1014  | 
    |||
1015  | 
    ✓✓✓✗ ✓✓  | 
    431869  | 
    		if (tok == MDOC_It && (n == NULL || n->tok != MDOC_Bl)) { | 
    
1016  | 
    270  | 
    mandoc_vmsg(MANDOCERR_IT_STRAY, mdoc->parse,  | 
    |
1017  | 
    135  | 
    line, ppos, "It %s", buf + *pos);  | 
    |
1018  | 
    135  | 
    roff_elem_alloc(mdoc, line, ppos, ROFF_br);  | 
    |
1019  | 
    135  | 
    rew_elem(mdoc, ROFF_br);  | 
    |
1020  | 
    135  | 
    return;  | 
    |
1021  | 
    }  | 
    ||
1022  | 
    }  | 
    ||
1023  | 
    |||
1024  | 
    /*  | 
    ||
1025  | 
    * This routine accommodates implicitly- and explicitly-scoped  | 
    ||
1026  | 
    * macro openings. Implicit ones first close out prior scope  | 
    ||
1027  | 
    * (seen above). Delay opening the head until necessary to  | 
    ||
1028  | 
    * allow leading punctuation to print. Special consideration  | 
    ||
1029  | 
    * for `It -column', which has phrase-part syntax instead of  | 
    ||
1030  | 
    * regular child nodes.  | 
    ||
1031  | 
    */  | 
    ||
1032  | 
    |||
1033  | 
    250416  | 
    mdoc_argv(mdoc, line, tok, &arg, pos, buf);  | 
    |
1034  | 
    250416  | 
    blk = mdoc_block_alloc(mdoc, line, ppos, tok, arg);  | 
    |
1035  | 
    head = body = NULL;  | 
    ||
1036  | 
    |||
1037  | 
    /*  | 
    ||
1038  | 
    * Exception: Heads of `It' macros in `-diag' lists are not  | 
    ||
1039  | 
    * parsed, even though `It' macros in general are parsed.  | 
    ||
1040  | 
    */  | 
    ||
1041  | 
    |||
1042  | 
    ✓✓ | 250416  | 
    parsed = tok != MDOC_It ||  | 
    
1043  | 
    ✓✗ | 471714  | 
    mdoc->last->parent->tok != MDOC_Bl ||  | 
    
1044  | 
    110649  | 
    mdoc->last->parent->norm->Bl.type != LIST_diag;  | 
    |
1045  | 
    |||
1046  | 
    /*  | 
    ||
1047  | 
    * The `Nd' macro has all arguments in its body: it's a hybrid  | 
    ||
1048  | 
    * of block partial-explicit and full-implicit. Stupid.  | 
    ||
1049  | 
    */  | 
    ||
1050  | 
    |||
1051  | 
    ✓✓ | 250416  | 
    	if (tok == MDOC_Nd) { | 
    
1052  | 
    17187  | 
    head = roff_head_alloc(mdoc, line, ppos, tok);  | 
    |
1053  | 
    17187  | 
    rew_last(mdoc, head);  | 
    |
1054  | 
    17187  | 
    body = roff_body_alloc(mdoc, line, ppos, tok);  | 
    |
1055  | 
    17187  | 
    }  | 
    |
1056  | 
    |||
1057  | 
    ✓✓ | 250416  | 
    if (tok == MDOC_Bk)  | 
    
1058  | 
    789  | 
    mdoc->flags |= MDOC_KEEP;  | 
    |
1059  | 
    |||
1060  | 
    ac = ARGS_EOLN;  | 
    ||
1061  | 
    250416  | 
    	for (;;) { | 
    |
1062  | 
    |||
1063  | 
    /*  | 
    ||
1064  | 
    * If we are right after a tab character,  | 
    ||
1065  | 
    * do not parse the first word for macros.  | 
    ||
1066  | 
    */  | 
    ||
1067  | 
    |||
1068  | 
    ✓✓ | 488212  | 
    		if (mdoc->flags & MDOC_PHRASEQN) { | 
    
1069  | 
    1002  | 
    mdoc->flags &= ~MDOC_PHRASEQN;  | 
    |
1070  | 
    1002  | 
    mdoc->flags |= MDOC_PHRASEQF;  | 
    |
1071  | 
    1002  | 
    }  | 
    |
1072  | 
    |||
1073  | 
    488212  | 
    la = *pos;  | 
    |
1074  | 
    lac = ac;  | 
    ||
1075  | 
    488212  | 
    ac = mdoc_args(mdoc, line, pos, buf, tok, &p);  | 
    |
1076  | 
    ✓✓ | 488212  | 
    		if (ac == ARGS_EOLN) { | 
    
1077  | 
    ✓✓✓✓ | 
    195542  | 
    if (lac != ARGS_PHRASE ||  | 
    
1078  | 
    12876  | 
    ! (mdoc->flags & MDOC_PHRASEQF))  | 
    |
1079  | 
    break;  | 
    ||
1080  | 
    |||
1081  | 
    /*  | 
    ||
1082  | 
    * This line ends in a tab; start the next  | 
    ||
1083  | 
    * column now, with a leading blank.  | 
    ||
1084  | 
    */  | 
    ||
1085  | 
    |||
1086  | 
    ✓✗ | 27  | 
    if (body != NULL)  | 
    
1087  | 
    27  | 
    rew_last(mdoc, body);  | 
    |
1088  | 
    27  | 
    body = roff_body_alloc(mdoc, line, ppos, tok);  | 
    |
1089  | 
    27  | 
    roff_word_alloc(mdoc, line, ppos, "\\&");  | 
    |
1090  | 
    27  | 
    break;  | 
    |
1091  | 
    }  | 
    ||
1092  | 
    |||
1093  | 
    ✓✓ | 305546  | 
    		if (tok == MDOC_Bd || tok == MDOC_Bk) { | 
    
1094  | 
    126  | 
    mandoc_vmsg(MANDOCERR_ARG_EXCESS,  | 
    |
1095  | 
    126  | 
    mdoc->parse, line, la, "%s ... %s",  | 
    |
1096  | 
    126  | 
    roff_name[tok], buf + la);  | 
    |
1097  | 
    126  | 
    break;  | 
    |
1098  | 
    }  | 
    ||
1099  | 
    ✓✓ | 305420  | 
    		if (tok == MDOC_Rs) { | 
    
1100  | 
    144  | 
    mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse,  | 
    |
1101  | 
    72  | 
    line, la, "Rs %s", buf + la);  | 
    |
1102  | 
    72  | 
    break;  | 
    |
1103  | 
    }  | 
    ||
1104  | 
    ✓✗ | 305348  | 
    if (ac == ARGS_PUNCT)  | 
    
1105  | 
    break;  | 
    ||
1106  | 
    |||
1107  | 
    /*  | 
    ||
1108  | 
    * Emit leading punctuation (i.e., punctuation before  | 
    ||
1109  | 
    * the ROFFT_HEAD) for non-phrase types.  | 
    ||
1110  | 
    */  | 
    ||
1111  | 
    |||
1112  | 
    ✓✓✗✓ | 
    785490  | 
    if (head == NULL &&  | 
    
1113  | 
    305348  | 
    ac != ARGS_PHRASE &&  | 
    |
1114  | 
    174794  | 
    		    mdoc_isdelim(p) == DELIM_OPEN) { | 
    |
1115  | 
    dword(mdoc, line, la, p, DELIM_OPEN, 0);  | 
    ||
1116  | 
    continue;  | 
    ||
1117  | 
    }  | 
    ||
1118  | 
    |||
1119  | 
    /* Open a head if one hasn't been opened. */  | 
    ||
1120  | 
    |||
1121  | 
    ✓✓ | 305348  | 
    if (head == NULL)  | 
    
1122  | 
    187670  | 
    head = roff_head_alloc(mdoc, line, ppos, tok);  | 
    |
1123  | 
    |||
1124  | 
    ✓✓ | 305348  | 
    		if (ac == ARGS_PHRASE) { | 
    
1125  | 
    |||
1126  | 
    /*  | 
    ||
1127  | 
    * If we haven't opened a body yet, rewind the  | 
    ||
1128  | 
    * head; if we have, rewind that instead.  | 
    ||
1129  | 
    */  | 
    ||
1130  | 
    |||
1131  | 
    13905  | 
    rew_last(mdoc, body == NULL ? head : body);  | 
    |
1132  | 
    13905  | 
    body = roff_body_alloc(mdoc, line, ppos, tok);  | 
    |
1133  | 
    |||
1134  | 
    /* Process to the tab or to the end of the line. */  | 
    ||
1135  | 
    |||
1136  | 
    13905  | 
    mdoc->flags |= MDOC_PHRASE;  | 
    |
1137  | 
    13905  | 
    parse_rest(mdoc, TOKEN_NONE, line, &la, buf);  | 
    |
1138  | 
    13905  | 
    mdoc->flags &= ~MDOC_PHRASE;  | 
    |
1139  | 
    |||
1140  | 
    /* There may have been `Ta' macros. */  | 
    ||
1141  | 
    |||
1142  | 
    ✓✓ | 79506  | 
    while (body->next != NULL)  | 
    
1143  | 
    body = body->next;  | 
    ||
1144  | 
    continue;  | 
    ||
1145  | 
    }  | 
    ||
1146  | 
    |||
1147  | 
    ✓✓ | 291443  | 
    if (macro_or_word(mdoc, tok, line, la, pos, buf, parsed))  | 
    
1148  | 
    break;  | 
    ||
1149  | 
    }  | 
    ||
1150  | 
    |||
1151  | 
    ✓✓ | 250416  | 
    if (blk->flags & NODE_VALID)  | 
    
1152  | 
    27  | 
    return;  | 
    |
1153  | 
    ✓✓ | 250389  | 
    if (head == NULL)  | 
    
1154  | 
    45559  | 
    head = roff_head_alloc(mdoc, line, ppos, tok);  | 
    |
1155  | 
    ✓✓ | 250389  | 
    if (nl && tok != MDOC_Bd && tok != MDOC_Bl && tok != MDOC_Rs)  | 
    
1156  | 
    217995  | 
    append_delims(mdoc, line, pos, buf);  | 
    |
1157  | 
    ✓✓ | 250389  | 
    if (body != NULL)  | 
    
1158  | 
    goto out;  | 
    ||
1159  | 
    ✓✓ | 220326  | 
    if (find_pending(mdoc, tok, line, ppos, head))  | 
    
1160  | 
    2883  | 
    return;  | 
    |
1161  | 
    |||
1162  | 
    /* Close out scopes to remain in a consistent state. */  | 
    ||
1163  | 
    |||
1164  | 
    217443  | 
    rew_last(mdoc, head);  | 
    |
1165  | 
    217443  | 
    body = roff_body_alloc(mdoc, line, ppos, tok);  | 
    |
1166  | 
    out:  | 
    ||
1167  | 
    ✓✓ | 247506  | 
    	if (mdoc->flags & MDOC_FREECOL) { | 
    
1168  | 
    90  | 
    rew_last(mdoc, body);  | 
    |
1169  | 
    90  | 
    rew_last(mdoc, blk);  | 
    |
1170  | 
    90  | 
    mdoc->flags &= ~MDOC_FREECOL;  | 
    |
1171  | 
    90  | 
    }  | 
    |
1172  | 
    498129  | 
    }  | 
    |
1173  | 
    |||
1174  | 
    static void  | 
    ||
1175  | 
    blk_part_imp(MACRO_PROT_ARGS)  | 
    ||
1176  | 
    { | 
    ||
1177  | 
    int la, nl;  | 
    ||
1178  | 
    enum margserr ac;  | 
    ||
1179  | 
    127194  | 
    char *p;  | 
    |
1180  | 
    struct roff_node *blk; /* saved block context */  | 
    ||
1181  | 
    struct roff_node *body; /* saved body context */  | 
    ||
1182  | 
    struct roff_node *n;  | 
    ||
1183  | 
    |||
1184  | 
    63597  | 
    nl = MDOC_NEWLINE & mdoc->flags;  | 
    |
1185  | 
    |||
1186  | 
    /*  | 
    ||
1187  | 
    * A macro that spans to the end of the line. This is generally  | 
    ||
1188  | 
    * (but not necessarily) called as the first macro. The block  | 
    ||
1189  | 
    * has a head as the immediate child, which is always empty,  | 
    ||
1190  | 
    * followed by zero or more opening punctuation nodes, then the  | 
    ||
1191  | 
    * body (which may be empty, depending on the macro), then zero  | 
    ||
1192  | 
    * or more closing punctuation nodes.  | 
    ||
1193  | 
    */  | 
    ||
1194  | 
    |||
1195  | 
    63597  | 
    blk = mdoc_block_alloc(mdoc, line, ppos, tok, NULL);  | 
    |
1196  | 
    63597  | 
    rew_last(mdoc, roff_head_alloc(mdoc, line, ppos, tok));  | 
    |
1197  | 
    |||
1198  | 
    /*  | 
    ||
1199  | 
    * Open the body scope "on-demand", that is, after we've  | 
    ||
1200  | 
    * processed all our the leading delimiters (open parenthesis,  | 
    ||
1201  | 
    * etc.).  | 
    ||
1202  | 
    */  | 
    ||
1203  | 
    |||
1204  | 
    63597  | 
    	for (body = NULL; ; ) { | 
    |
1205  | 
    115284  | 
    la = *pos;  | 
    |
1206  | 
    115284  | 
    ac = mdoc_args(mdoc, line, pos, buf, tok, &p);  | 
    |
1207  | 
    ✓✓ | 115284  | 
    if (ac == ARGS_EOLN || ac == ARGS_PUNCT)  | 
    
1208  | 
    break;  | 
    ||
1209  | 
    |||
1210  | 
    ✓✓✓✓ | 
    146684  | 
    		if (body == NULL && mdoc_isdelim(p) == DELIM_OPEN) { | 
    
1211  | 
    336  | 
    dword(mdoc, line, la, p, DELIM_OPEN, 0);  | 
    |
1212  | 
    336  | 
    continue;  | 
    |
1213  | 
    }  | 
    ||
1214  | 
    |||
1215  | 
    ✓✓ | 82901  | 
    if (body == NULL)  | 
    
1216  | 
    63111  | 
    body = roff_body_alloc(mdoc, line, ppos, tok);  | 
    |
1217  | 
    |||
1218  | 
    ✓✓ | 82901  | 
    if (macro_or_word(mdoc, tok, line, la, pos, buf, 1))  | 
    
1219  | 
    break;  | 
    ||
1220  | 
    }  | 
    ||
1221  | 
    ✓✓ | 63597  | 
    if (body == NULL)  | 
    
1222  | 
    486  | 
    body = roff_body_alloc(mdoc, line, ppos, tok);  | 
    |
1223  | 
    |||
1224  | 
    ✓✓ | 63597  | 
    if (find_pending(mdoc, tok, line, ppos, body))  | 
    
1225  | 
    288  | 
    return;  | 
    |
1226  | 
    |||
1227  | 
    63309  | 
    rew_last(mdoc, body);  | 
    |
1228  | 
    ✓✓ | 63309  | 
    if (nl)  | 
    
1229  | 
    48697  | 
    append_delims(mdoc, line, pos, buf);  | 
    |
1230  | 
    63309  | 
    rew_pending(mdoc, blk);  | 
    |
1231  | 
    |||
1232  | 
    /* Move trailing .Ns out of scope. */  | 
    ||
1233  | 
    |||
1234  | 
    ✓✓✓✓ | 
    246525  | 
    for (n = body->child; n && n->next; n = n->next)  | 
    
1235  | 
    /* Do nothing. */ ;  | 
    ||
1236  | 
    ✓✓✓✓ | 
    126132  | 
    if (n && n->tok == MDOC_Ns)  | 
    
1237  | 
    147  | 
    mdoc_node_relink(mdoc, n);  | 
    |
1238  | 
    126906  | 
    }  | 
    |
1239  | 
    |||
1240  | 
    static void  | 
    ||
1241  | 
    blk_part_exp(MACRO_PROT_ARGS)  | 
    ||
1242  | 
    { | 
    ||
1243  | 
    int la, nl;  | 
    ||
1244  | 
    enum margserr ac;  | 
    ||
1245  | 
    struct roff_node *head; /* keep track of head */  | 
    ||
1246  | 
    19562  | 
    char *p;  | 
    |
1247  | 
    |||
1248  | 
    9781  | 
    nl = MDOC_NEWLINE & mdoc->flags;  | 
    |
1249  | 
    |||
1250  | 
    /*  | 
    ||
1251  | 
    * The opening of an explicit macro having zero or more leading  | 
    ||
1252  | 
    * punctuation nodes; a head with optional single element (the  | 
    ||
1253  | 
    * case of `Eo'); and a body that may be empty.  | 
    ||
1254  | 
    */  | 
    ||
1255  | 
    |||
1256  | 
    9781  | 
    roff_block_alloc(mdoc, line, ppos, tok);  | 
    |
1257  | 
    head = NULL;  | 
    ||
1258  | 
    9781  | 
    	for (;;) { | 
    |
1259  | 
    15391  | 
    la = *pos;  | 
    |
1260  | 
    15391  | 
    ac = mdoc_args(mdoc, line, pos, buf, tok, &p);  | 
    |
1261  | 
    ✓✓ | 15391  | 
    if (ac == ARGS_PUNCT || ac == ARGS_EOLN)  | 
    
1262  | 
    break;  | 
    ||
1263  | 
    |||
1264  | 
    /* Flush out leading punctuation. */  | 
    ||
1265  | 
    |||
1266  | 
    ✓✓✓✓ | 
    15048  | 
    		if (head == NULL && mdoc_isdelim(p) == DELIM_OPEN) { | 
    
1267  | 
    183  | 
    dword(mdoc, line, la, p, DELIM_OPEN, 0);  | 
    |
1268  | 
    183  | 
    continue;  | 
    |
1269  | 
    }  | 
    ||
1270  | 
    |||
1271  | 
    ✓✓ | 8661  | 
    		if (head == NULL) { | 
    
1272  | 
    6021  | 
    head = roff_head_alloc(mdoc, line, ppos, tok);  | 
    |
1273  | 
    ✓✓ | 6021  | 
    if (tok == MDOC_Eo) /* Not parsed. */  | 
    
1274  | 
    408  | 
    dword(mdoc, line, la, p, DELIM_MAX, 0);  | 
    |
1275  | 
    6021  | 
    rew_last(mdoc, head);  | 
    |
1276  | 
    6021  | 
    roff_body_alloc(mdoc, line, ppos, tok);  | 
    |
1277  | 
    ✓✓ | 6021  | 
    if (tok == MDOC_Eo)  | 
    
1278  | 
    continue;  | 
    ||
1279  | 
    }  | 
    ||
1280  | 
    |||
1281  | 
    ✓✓ | 8253  | 
    if (macro_or_word(mdoc, tok, line, la, pos, buf, 1))  | 
    
1282  | 
    break;  | 
    ||
1283  | 
    }  | 
    ||
1284  | 
    |||
1285  | 
    /* Clean-up to leave in a consistent state. */  | 
    ||
1286  | 
    |||
1287  | 
    ✓✓ | 9781  | 
    	if (head == NULL) { | 
    
1288  | 
    3760  | 
    rew_last(mdoc, roff_head_alloc(mdoc, line, ppos, tok));  | 
    |
1289  | 
    3760  | 
    roff_body_alloc(mdoc, line, ppos, tok);  | 
    |
1290  | 
    3760  | 
    }  | 
    |
1291  | 
    ✓✓ | 9781  | 
    if (nl)  | 
    
1292  | 
    4893  | 
    append_delims(mdoc, line, pos, buf);  | 
    |
1293  | 
    9781  | 
    }  | 
    |
1294  | 
    |||
1295  | 
    static void  | 
    ||
1296  | 
    in_line_argn(MACRO_PROT_ARGS)  | 
    ||
1297  | 
    { | 
    ||
1298  | 
    213150  | 
    struct mdoc_arg *arg;  | 
    |
1299  | 
    106575  | 
    char *p;  | 
    |
1300  | 
    enum margserr ac;  | 
    ||
1301  | 
    enum roff_tok ntok;  | 
    ||
1302  | 
    int state; /* arg#; -1: not yet open; -2: closed */  | 
    ||
1303  | 
    int la, maxargs, nl;  | 
    ||
1304  | 
    |||
1305  | 
    106575  | 
    nl = mdoc->flags & MDOC_NEWLINE;  | 
    |
1306  | 
    |||
1307  | 
    /*  | 
    ||
1308  | 
    * A line macro that has a fixed number of arguments (maxargs).  | 
    ||
1309  | 
    * Only open the scope once the first non-leading-punctuation is  | 
    ||
1310  | 
    * found (unless MDOC_IGNDELIM is noted, like in `Pf'), then  | 
    ||
1311  | 
    * keep it open until the maximum number of arguments are  | 
    ||
1312  | 
    * exhausted.  | 
    ||
1313  | 
    */  | 
    ||
1314  | 
    |||
1315  | 
    ✗✗✓✗ ✗✓✓  | 
    106575  | 
    	switch (tok) { | 
    
1316  | 
    case MDOC_Ap:  | 
    ||
1317  | 
    case MDOC_Ns:  | 
    ||
1318  | 
    case MDOC_Ux:  | 
    ||
1319  | 
    maxargs = 0;  | 
    ||
1320  | 
    10850  | 
    break;  | 
    |
1321  | 
    case MDOC_Bx:  | 
    ||
1322  | 
    case MDOC_Es:  | 
    ||
1323  | 
    case MDOC_Xr:  | 
    ||
1324  | 
    maxargs = 2;  | 
    ||
1325  | 
    73859  | 
    break;  | 
    |
1326  | 
    default:  | 
    ||
1327  | 
    maxargs = 1;  | 
    ||
1328  | 
    21866  | 
    break;  | 
    |
1329  | 
    }  | 
    ||
1330  | 
    |||
1331  | 
    106575  | 
    mdoc_argv(mdoc, line, tok, &arg, pos, buf);  | 
    |
1332  | 
    |||
1333  | 
    state = -1;  | 
    ||
1334  | 
    106575  | 
    p = NULL;  | 
    |
1335  | 
    275845  | 
    	for (;;) { | 
    |
1336  | 
    275920  | 
    la = *pos;  | 
    |
1337  | 
    275920  | 
    ac = mdoc_args(mdoc, line, pos, buf, tok, &p);  | 
    |
1338  | 
    |||
1339  | 
    ✓✓✓✓ | 
    366794  | 
    if (ac == ARGS_WORD && state == -1 &&  | 
    
1340  | 
    ✓✓ | 102665  | 
    ! (mdoc_macros[tok].flags & MDOC_IGNDELIM) &&  | 
    
1341  | 
    90874  | 
    		    mdoc_isdelim(p) == DELIM_OPEN) { | 
    |
1342  | 
    75  | 
    dword(mdoc, line, la, p, DELIM_OPEN, 0);  | 
    |
1343  | 
    75  | 
    continue;  | 
    |
1344  | 
    }  | 
    ||
1345  | 
    |||
1346  | 
    ✓✓ | 827535  | 
    if (state == -1 && tok != MDOC_In &&  | 
    
1347  | 
    551690  | 
    		    tok != MDOC_St && tok != MDOC_Xr) { | 
    |
1348  | 
    25985  | 
    mdoc_elem_alloc(mdoc, line, ppos, tok, arg);  | 
    |
1349  | 
    state = 0;  | 
    ||
1350  | 
    25985  | 
    }  | 
    |
1351  | 
    |||
1352  | 
    ✓✓ | 275845  | 
    		if (ac == ARGS_PUNCT || ac == ARGS_EOLN) { | 
    
1353  | 
    ✓✓ | 96182  | 
    if (abs(state) < 2 && tok == MDOC_Pf)  | 
    
1354  | 
    108  | 
    mandoc_vmsg(MANDOCERR_PF_SKIP,  | 
    |
1355  | 
    108  | 
    mdoc->parse, line, ppos, "Pf %s",  | 
    |
1356  | 
    108  | 
    p == NULL ? "at eol" : p);  | 
    |
1357  | 
    break;  | 
    ||
1358  | 
    }  | 
    ||
1359  | 
    |||
1360  | 
    ✓✓ | 179663  | 
    		if (state == maxargs) { | 
    
1361  | 
    12721  | 
    rew_elem(mdoc, tok);  | 
    |
1362  | 
    state = -2;  | 
    ||
1363  | 
    12721  | 
    }  | 
    |
1364  | 
    |||
1365  | 
    ✓✓ | 537237  | 
    ntok = (tok == MDOC_Pf && state == 0) ?  | 
    
1366  | 
    177911  | 
    TOKEN_NONE : lookup(mdoc, tok, line, la, p);  | 
    |
1367  | 
    |||
1368  | 
    ✓✓ | 179663  | 
    		if (ntok != TOKEN_NONE) { | 
    
1369  | 
    ✓✓ | 10393  | 
    			if (state >= 0) { | 
    
1370  | 
    312  | 
    rew_elem(mdoc, tok);  | 
    |
1371  | 
    state = -2;  | 
    ||
1372  | 
    312  | 
    }  | 
    |
1373  | 
    10393  | 
    mdoc_macro(mdoc, ntok, line, la, pos, buf);  | 
    |
1374  | 
    10393  | 
    break;  | 
    |
1375  | 
    }  | 
    ||
1376  | 
    |||
1377  | 
    ✓✓✓✓ | 
    332362  | 
    if (mdoc_macros[tok].flags & MDOC_IGNDELIM ||  | 
    
1378  | 
    163092  | 
    		    mdoc_isdelim(p) == DELIM_NONE) { | 
    |
1379  | 
    ✓✓ | 169093  | 
    			if (state == -1) { | 
    
1380  | 
    80369  | 
    mdoc_elem_alloc(mdoc, line, ppos, tok, arg);  | 
    |
1381  | 
    state = 1;  | 
    ||
1382  | 
    ✓✓ | 169093  | 
    } else if (state >= 0)  | 
    
1383  | 
    83635  | 
    state++;  | 
    |
1384  | 
    ✓✓ | 177  | 
    		} else if (state >= 0) { | 
    
1385  | 
    45  | 
    rew_elem(mdoc, tok);  | 
    |
1386  | 
    state = -2;  | 
    ||
1387  | 
    45  | 
    }  | 
    |
1388  | 
    |||
1389  | 
    338540  | 
    dword(mdoc, line, la, p, DELIM_MAX,  | 
    |
1390  | 
    169270  | 
    mdoc_macros[tok].flags & MDOC_JOIN);  | 
    |
1391  | 
    }  | 
    ||
1392  | 
    |||
1393  | 
    ✓✓ | 106575  | 
    	if (state == -1) { | 
    
1394  | 
    442  | 
    mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,  | 
    |
1395  | 
    221  | 
    line, ppos, roff_name[tok]);  | 
    |
1396  | 
    221  | 
    return;  | 
    |
1397  | 
    }  | 
    ||
1398  | 
    |||
1399  | 
    ✓✓ | 106354  | 
    if (state == 0 && tok == MDOC_Pf)  | 
    
1400  | 
    72  | 
    append_delims(mdoc, line, pos, buf);  | 
    |
1401  | 
    ✓✓ | 106354  | 
    if (state >= 0)  | 
    
1402  | 
    93276  | 
    rew_elem(mdoc, tok);  | 
    |
1403  | 
    ✓✓ | 106354  | 
    if (nl)  | 
    
1404  | 
    92499  | 
    append_delims(mdoc, line, pos, buf);  | 
    |
1405  | 
    212929  | 
    }  | 
    |
1406  | 
    |||
1407  | 
    static void  | 
    ||
1408  | 
    in_line_eoln(MACRO_PROT_ARGS)  | 
    ||
1409  | 
    { | 
    ||
1410  | 
    struct roff_node *n;  | 
    ||
1411  | 
    264808  | 
    struct mdoc_arg *arg;  | 
    |
1412  | 
    |||
1413  | 
    ✓✓✓✓ | 
    203017  | 
    if ((tok == MDOC_Pp || tok == MDOC_Lp) &&  | 
    
1414  | 
    70613  | 
    	    ! (mdoc->flags & MDOC_SYNOPSIS)) { | 
    |
1415  | 
    69869  | 
    n = mdoc->last;  | 
    |
1416  | 
    ✓✓ | 69869  | 
    if (mdoc->next == ROFF_NEXT_SIBLING)  | 
    
1417  | 
    69452  | 
    n = n->parent;  | 
    |
1418  | 
    ✓✓ | 69869  | 
    if (n->tok == MDOC_Nm)  | 
    
1419  | 
    129  | 
    rew_last(mdoc, n->parent);  | 
    |
1420  | 
    }  | 
    ||
1421  | 
    |||
1422  | 
    ✓✓✗✓ | 
    220392  | 
    if (buf[*pos] == '\0' &&  | 
    
1423  | 
    ✓✓ | 176048  | 
    	    (tok == MDOC_Fd || *roff_name[tok] == '%')) { | 
    
1424  | 
    144  | 
    mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,  | 
    |
1425  | 
    72  | 
    line, ppos, roff_name[tok]);  | 
    |
1426  | 
    72  | 
    return;  | 
    |
1427  | 
    }  | 
    ||
1428  | 
    |||
1429  | 
    132332  | 
    mdoc_argv(mdoc, line, tok, &arg, pos, buf);  | 
    |
1430  | 
    132332  | 
    mdoc_elem_alloc(mdoc, line, ppos, tok, arg);  | 
    |
1431  | 
    ✗✓ | 132332  | 
    if (parse_rest(mdoc, tok, line, pos, buf))  | 
    
1432  | 
    return;  | 
    ||
1433  | 
    132332  | 
    rew_elem(mdoc, tok);  | 
    |
1434  | 
    264736  | 
    }  | 
    |
1435  | 
    |||
1436  | 
    /*  | 
    ||
1437  | 
    * The simplest argument parser available: Parse the remaining  | 
    ||
1438  | 
    * words until the end of the phrase or line and return 0  | 
    ||
1439  | 
    * or until the next macro, call that macro, and return 1.  | 
    ||
1440  | 
    */  | 
    ||
1441  | 
    static int  | 
    ||
1442  | 
    parse_rest(struct roff_man *mdoc, enum roff_tok tok,  | 
    ||
1443  | 
    int line, int *pos, char *buf)  | 
    ||
1444  | 
    { | 
    ||
1445  | 
    int la;  | 
    ||
1446  | 
    |||
1447  | 
    344278  | 
    	for (;;) { | 
    |
1448  | 
    351508  | 
    la = *pos;  | 
    |
1449  | 
    ✓✓ | 351508  | 
    if (mdoc_args(mdoc, line, pos, buf, tok, NULL) == ARGS_EOLN)  | 
    
1450  | 
    144644  | 
    return 0;  | 
    |
1451  | 
    ✓✓ | 206864  | 
    if (macro_or_word(mdoc, tok, line, la, pos, buf, 1))  | 
    
1452  | 
    27495  | 
    return 1;  | 
    |
1453  | 
    }  | 
    ||
1454  | 
    172139  | 
    }  | 
    |
1455  | 
    |||
1456  | 
    static void  | 
    ||
1457  | 
    ctx_synopsis(MACRO_PROT_ARGS)  | 
    ||
1458  | 
    { | 
    ||
1459  | 
    |||
1460  | 
    ✓✓ | 139868  | 
    if (~mdoc->flags & (MDOC_SYNOPSIS | MDOC_NEWLINE))  | 
    
1461  | 
    66189  | 
    in_line(mdoc, tok, line, ppos, pos, buf);  | 
    |
1462  | 
    ✓✓ | 3745  | 
    else if (tok == MDOC_Nm)  | 
    
1463  | 
    3536  | 
    blk_full(mdoc, tok, line, ppos, pos, buf);  | 
    |
1464  | 
    	else { | 
    ||
1465  | 
    ✗✓ | 209  | 
    assert(tok == MDOC_Vt);  | 
    
1466  | 
    209  | 
    blk_part_imp(mdoc, tok, line, ppos, pos, buf);  | 
    |
1467  | 
    }  | 
    ||
1468  | 
    69934  | 
    }  | 
    |
1469  | 
    |||
1470  | 
    /*  | 
    ||
1471  | 
    * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs.  | 
    ||
1472  | 
    * They're unusual because they're basically free-form text until a  | 
    ||
1473  | 
    * macro is encountered.  | 
    ||
1474  | 
    */  | 
    ||
1475  | 
    static void  | 
    ||
1476  | 
    phrase_ta(MACRO_PROT_ARGS)  | 
    ||
1477  | 
    { | 
    ||
1478  | 
    struct roff_node *body, *n;  | 
    ||
1479  | 
    |||
1480  | 
    /* Make sure we are in a column list or ignore this macro. */  | 
    ||
1481  | 
    |||
1482  | 
    body = NULL;  | 
    ||
1483  | 
    ✓✓ | 233295  | 
    	for (n = mdoc->last; n != NULL; n = n->parent) { | 
    
1484  | 
    ✓✓ | 103602  | 
    if (n->flags & NODE_ENDED)  | 
    
1485  | 
    continue;  | 
    ||
1486  | 
    ✓✓✓✓ | 
    130047  | 
    if (n->tok == MDOC_It && n->type == ROFFT_BODY)  | 
    
1487  | 
    25947  | 
    body = n;  | 
    |
1488  | 
    ✓✓✓✓ | 
    104091  | 
    if (n->tok == MDOC_Bl && n->end == ENDBODY_NOT)  | 
    
1489  | 
    break;  | 
    ||
1490  | 
    }  | 
    ||
1491  | 
    |||
1492  | 
    ✓✓✓✓ | 
    51957  | 
    	if (n == NULL || n->norm->Bl.type != LIST_column) { | 
    
1493  | 
    99  | 
    mandoc_msg(MANDOCERR_TA_STRAY, mdoc->parse,  | 
    |
1494  | 
    line, ppos, "Ta");  | 
    ||
1495  | 
    99  | 
    return;  | 
    |
1496  | 
    }  | 
    ||
1497  | 
    |||
1498  | 
    /* Advance to the next column. */  | 
    ||
1499  | 
    |||
1500  | 
    25902  | 
    rew_last(mdoc, body);  | 
    |
1501  | 
    25902  | 
    roff_body_alloc(mdoc, line, ppos, MDOC_It);  | 
    |
1502  | 
    25902  | 
    parse_rest(mdoc, TOKEN_NONE, line, pos, buf);  | 
    |
1503  | 
    51903  | 
    }  | 
    
| Generated by: GCOVR (Version 3.3) |