| GCC Code Coverage Report | |||||||||||||||||||||
        
  | 
    |||||||||||||||||||||
| Line | Branch | Exec | Source | 
1  | 
    /* $OpenBSD: tree.c,v 1.27 2015/11/01 15:38:53 mmcc Exp $ */  | 
    ||
2  | 
    |||
3  | 
    /*  | 
    ||
4  | 
    * command tree climbing  | 
    ||
5  | 
    */  | 
    ||
6  | 
    |||
7  | 
    #include <string.h>  | 
    ||
8  | 
    |||
9  | 
    #include "sh.h"  | 
    ||
10  | 
    |||
11  | 
    #define INDENT 4  | 
    ||
12  | 
    |||
13  | 
    #define tputc(c, shf) shf_putchar(c, shf);  | 
    ||
14  | 
    static void ptree(struct op *, int, struct shf *);  | 
    ||
15  | 
    static void pioact(struct shf *, int, struct ioword *);  | 
    ||
16  | 
    static void tputC(int, struct shf *);  | 
    ||
17  | 
    static void tputS(char *, struct shf *);  | 
    ||
18  | 
    static void vfptreef(struct shf *, int, const char *, va_list);  | 
    ||
19  | 
    static struct ioword **iocopy(struct ioword **, Area *);  | 
    ||
20  | 
    static void iofree(struct ioword **, Area *);  | 
    ||
21  | 
    |||
22  | 
    /*  | 
    ||
23  | 
    * print a command tree  | 
    ||
24  | 
    */  | 
    ||
25  | 
    |||
26  | 
    static void  | 
    ||
27  | 
    ptree(struct op *t, int indent, struct shf *shf)  | 
    ||
28  | 
    { | 
    ||
29  | 
    char **w;  | 
    ||
30  | 
    struct ioword **ioact;  | 
    ||
31  | 
    7103706  | 
    struct op *t1;  | 
    |
32  | 
    |||
33  | 
    Chain:  | 
    ||
34  | 
    ✗✓ | 4227348  | 
    if (t == NULL)  | 
    
35  | 
    return;  | 
    ||
36  | 
    ✓✓✓✓ ✓✗✓✗ ✗✗✓✓ ✗✓✗✓ ✓✗✗✗ ✗✗  | 
    4227348  | 
    	switch (t->type) { | 
    
37  | 
    case TCOM:  | 
    ||
38  | 
    ✓✗ | 3550656  | 
    if (t->vars)  | 
    
39  | 
    ✓✓ | 7267958  | 
    for (w = t->vars; *w != NULL; )  | 
    
40  | 
    83323  | 
    fptreef(shf, indent, "%S ", *w++);  | 
    |
41  | 
    else  | 
    ||
42  | 
    fptreef(shf, indent, "#no-vars# ");  | 
    ||
43  | 
    ✓✗ | 3550656  | 
    if (t->args)  | 
    
44  | 
    ✓✓ | 25703306  | 
    for (w = t->args; *w != NULL; )  | 
    
45  | 
    9300997  | 
    fptreef(shf, indent, "%S ", *w++);  | 
    |
46  | 
    else  | 
    ||
47  | 
    fptreef(shf, indent, "#no-args# ");  | 
    ||
48  | 
    break;  | 
    ||
49  | 
    case TEXEC:  | 
    ||
50  | 
    #if 0 /* ?not useful - can't be called? */  | 
    ||
51  | 
    /* Print original vars */  | 
    ||
52  | 
    if (t->left->vars)  | 
    ||
53  | 
    for (w = t->left->vars; *w != NULL; )  | 
    ||
54  | 
    fptreef(shf, indent, "%S ", *w++);  | 
    ||
55  | 
    else  | 
    ||
56  | 
    fptreef(shf, indent, "#no-vars# ");  | 
    ||
57  | 
    /* Print expanded vars */  | 
    ||
58  | 
    if (t->args)  | 
    ||
59  | 
    for (w = t->args; *w != NULL; )  | 
    ||
60  | 
    fptreef(shf, indent, "%s ", *w++);  | 
    ||
61  | 
    else  | 
    ||
62  | 
    fptreef(shf, indent, "#no-args# ");  | 
    ||
63  | 
    /* Print original io */  | 
    ||
64  | 
    t = t->left;  | 
    ||
65  | 
    #else  | 
    ||
66  | 
    136408  | 
    t = t->left;  | 
    |
67  | 
    136408  | 
    goto Chain;  | 
    |
68  | 
    #endif  | 
    ||
69  | 
    case TPAREN:  | 
    ||
70  | 
    740  | 
    fptreef(shf, indent + 2, "( %T) ", t->left);  | 
    |
71  | 
    740  | 
    break;  | 
    |
72  | 
    case TPIPE:  | 
    ||
73  | 
    240952  | 
    fptreef(shf, indent, "%T| ", t->left);  | 
    |
74  | 
    240952  | 
    t = t->right;  | 
    |
75  | 
    240952  | 
    goto Chain;  | 
    |
76  | 
    case TLIST:  | 
    ||
77  | 
    298135  | 
    fptreef(shf, indent, "%T%;", t->left);  | 
    |
78  | 
    298135  | 
    t = t->right;  | 
    |
79  | 
    298135  | 
    goto Chain;  | 
    |
80  | 
    case TOR:  | 
    ||
81  | 
    case TAND:  | 
    ||
82  | 
    322  | 
    fptreef(shf, indent, "%T%s %T",  | 
    |
83  | 
    322  | 
    t->left, (t->type==TOR) ? "||" : "&&", t->right);  | 
    |
84  | 
    322  | 
    break;  | 
    |
85  | 
    case TBANG:  | 
    ||
86  | 
    fptreef(shf, indent, "! ");  | 
    ||
87  | 
    t = t->right;  | 
    ||
88  | 
    goto Chain;  | 
    ||
89  | 
    case TDBRACKET:  | 
    ||
90  | 
    	  { | 
    ||
91  | 
    int i;  | 
    ||
92  | 
    |||
93  | 
    fptreef(shf, indent, "[[");  | 
    ||
94  | 
    for (i = 0; t->args[i]; i++)  | 
    ||
95  | 
    fptreef(shf, indent, " %S", t->args[i]);  | 
    ||
96  | 
    fptreef(shf, indent, " ]] ");  | 
    ||
97  | 
    break;  | 
    ||
98  | 
    }  | 
    ||
99  | 
    case TSELECT:  | 
    ||
100  | 
    fptreef(shf, indent, "select %s ", t->str);  | 
    ||
101  | 
    /* FALLTHROUGH */  | 
    ||
102  | 
    case TFOR:  | 
    ||
103  | 
    ✓✗ | 9  | 
    if (t->type == TFOR)  | 
    
104  | 
    9  | 
    fptreef(shf, indent, "for %s ", t->str);  | 
    |
105  | 
    ✓✗ | 9  | 
    		if (t->vars != NULL) { | 
    
106  | 
    9  | 
    fptreef(shf, indent, "in ");  | 
    |
107  | 
    ✓✓ | 104  | 
    for (w = t->vars; *w; )  | 
    
108  | 
    43  | 
    fptreef(shf, indent, "%S ", *w++);  | 
    |
109  | 
    9  | 
    fptreef(shf, indent, "%;");  | 
    |
110  | 
    9  | 
    }  | 
    |
111  | 
    9  | 
    fptreef(shf, indent + INDENT, "do%N%T", t->left);  | 
    |
112  | 
    9  | 
    fptreef(shf, indent, "%;done ");  | 
    |
113  | 
    9  | 
    break;  | 
    |
114  | 
    case TCASE:  | 
    ||
115  | 
    27  | 
    fptreef(shf, indent, "case %S in", t->str);  | 
    |
116  | 
    ✓✓ | 108  | 
    		for (t1 = t->left; t1 != NULL; t1 = t1->right) { | 
    
117  | 
    27  | 
    			fptreef(shf, indent, "%N("); | 
    |
118  | 
    ✓✓ | 108  | 
    for (w = t1->vars; *w != NULL; w++)  | 
    
119  | 
    27  | 
    fptreef(shf, indent, "%S%c", *w,  | 
    |
120  | 
    27  | 
    (w[1] != NULL) ? '|' : ')');  | 
    |
121  | 
    27  | 
    fptreef(shf, indent + INDENT, "%;%T%N;;", t1->left);  | 
    |
122  | 
    }  | 
    ||
123  | 
    27  | 
    fptreef(shf, indent, "%Nesac ");  | 
    |
124  | 
    27  | 
    break;  | 
    |
125  | 
    case TIF:  | 
    ||
126  | 
    case TELIF:  | 
    ||
127  | 
    		/* 3 == strlen("if ") */ | 
    ||
128  | 
    4  | 
    fptreef(shf, indent + 3, "if %T", t->left);  | 
    |
129  | 
    4  | 
    		for (;;) { | 
    |
130  | 
    4  | 
    t = t->right;  | 
    |
131  | 
    ✓✗ | 4  | 
    			if (t->left != NULL) { | 
    
132  | 
    4  | 
    fptreef(shf, indent, "%;");  | 
    |
133  | 
    8  | 
    fptreef(shf, indent + INDENT, "then%N%T",  | 
    |
134  | 
    4  | 
    t->left);  | 
    |
135  | 
    4  | 
    }  | 
    |
136  | 
    ✗✓✗✗ | 
    4  | 
    if (t->right == NULL || t->right->type != TELIF)  | 
    
137  | 
    break;  | 
    ||
138  | 
    t = t->right;  | 
    ||
139  | 
    fptreef(shf, indent, "%;");  | 
    ||
140  | 
    			/* 5 == strlen("elif ") */ | 
    ||
141  | 
    fptreef(shf, indent + 5, "elif %T", t->left);  | 
    ||
142  | 
    }  | 
    ||
143  | 
    ✗✓ | 4  | 
    		if (t->right != NULL) { | 
    
144  | 
    fptreef(shf, indent, "%;");  | 
    ||
145  | 
    fptreef(shf, indent + INDENT, "else%;%T", t->right);  | 
    ||
146  | 
    }  | 
    ||
147  | 
    4  | 
    fptreef(shf, indent, "%;fi ");  | 
    |
148  | 
    4  | 
    break;  | 
    |
149  | 
    case TWHILE:  | 
    ||
150  | 
    case TUNTIL:  | 
    ||
151  | 
    		/* 6 == strlen("while"/"until") */ | 
    ||
152  | 
    120  | 
    fptreef(shf, indent + 6, "%s %T",  | 
    |
153  | 
    60  | 
    (t->type==TWHILE) ? "while" : "until",  | 
    |
154  | 
    60  | 
    t->left);  | 
    |
155  | 
    60  | 
    fptreef(shf, indent, "%;do");  | 
    |
156  | 
    60  | 
    fptreef(shf, indent + INDENT, "%;%T", t->right);  | 
    |
157  | 
    60  | 
    fptreef(shf, indent, "%;done ");  | 
    |
158  | 
    60  | 
    break;  | 
    |
159  | 
    case TBRACE:  | 
    ||
160  | 
    35  | 
    		fptreef(shf, indent + INDENT, "{%;%T", t->left); | 
    |
161  | 
    35  | 
    fptreef(shf, indent, "%;} ");  | 
    |
162  | 
    35  | 
    break;  | 
    |
163  | 
    case TCOPROC:  | 
    ||
164  | 
    fptreef(shf, indent, "%T|& ", t->left);  | 
    ||
165  | 
    break;  | 
    ||
166  | 
    case TASYNC:  | 
    ||
167  | 
    fptreef(shf, indent, "%T& ", t->left);  | 
    ||
168  | 
    break;  | 
    ||
169  | 
    case TFUNCT:  | 
    ||
170  | 
    fptreef(shf, indent,  | 
    ||
171  | 
    t->u.ksh_func ? "function %s %T" : "%s() %T",  | 
    ||
172  | 
    t->str, t->left);  | 
    ||
173  | 
    break;  | 
    ||
174  | 
    case TTIME:  | 
    ||
175  | 
    fptreef(shf, indent, "time %T", t->left);  | 
    ||
176  | 
    break;  | 
    ||
177  | 
    default:  | 
    ||
178  | 
    fptreef(shf, indent, "<botch>");  | 
    ||
179  | 
    break;  | 
    ||
180  | 
    }  | 
    ||
181  | 
    ✓✓ | 3551853  | 
    	if ((ioact = t->ioact) != NULL) { | 
    
182  | 
    int need_nl = 0;  | 
    ||
183  | 
    |||
184  | 
    ✓✓ | 674164  | 
    while (*ioact != NULL)  | 
    
185  | 
    181343  | 
    pioact(shf, indent, *ioact++);  | 
    |
186  | 
    /* Print here documents after everything else... */  | 
    ||
187  | 
    ✓✓ | 674164  | 
    		for (ioact = t->ioact; *ioact != NULL; ) { | 
    
188  | 
    181343  | 
    struct ioword *iop = *ioact++;  | 
    |
189  | 
    |||
190  | 
    /* heredoc is 0 when tracing (set -x) */  | 
    ||
191  | 
    ✓✓✓✗ | 
    183469  | 
    			if ((iop->flag & IOTYPE) == IOHERE && iop->heredoc) { | 
    
192  | 
    2126  | 
    				tputc('\n', shf); | 
    |
193  | 
    2126  | 
    shf_puts(iop->heredoc, shf);  | 
    |
194  | 
    2126  | 
    fptreef(shf, indent, "%s",  | 
    |
195  | 
    2126  | 
    evalstr(iop->delim, 0));  | 
    |
196  | 
    need_nl = 1;  | 
    ||
197  | 
    2126  | 
    }  | 
    |
198  | 
    }  | 
    ||
199  | 
    /* Last delimiter must be followed by a newline (this often  | 
    ||
200  | 
    * leads to an extra blank line, but its not worth worrying  | 
    ||
201  | 
    * about)  | 
    ||
202  | 
    */  | 
    ||
203  | 
    ✓✓ | 155739  | 
    if (need_nl)  | 
    
204  | 
    2120  | 
    			tputc('\n', shf); | 
    |
205  | 
    155739  | 
    }  | 
    |
206  | 
    7103706  | 
    }  | 
    |
207  | 
    |||
208  | 
    static void  | 
    ||
209  | 
    pioact(struct shf *shf, int indent, struct ioword *iop)  | 
    ||
210  | 
    { | 
    ||
211  | 
    362686  | 
    int flag = iop->flag;  | 
    |
212  | 
    181343  | 
    int type = flag & IOTYPE;  | 
    |
213  | 
    int expected;  | 
    ||
214  | 
    |||
215  | 
    ✓✓ | 362686  | 
    expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0 :  | 
    
216  | 
    ✓✓ | 171089  | 
    (type == IOCAT || type == IOWRITE) ? 1 :  | 
    
217  | 
    ✓✗✓✓ | 
    408834  | 
    (type == IODUP && (iop->unit == !(flag & IORDUP))) ? iop->unit :  | 
    
218  | 
    136277  | 
    iop->unit + 1;  | 
    |
219  | 
    ✓✓ | 181343  | 
    if (iop->unit != expected)  | 
    
220  | 
    138356  | 
    		tputc('0' + iop->unit, shf); | 
    |
221  | 
    |||
222  | 
    ✓✓✓✓ ✗✓✓  | 
    362686  | 
    	switch (type) { | 
    
223  | 
    case IOREAD:  | 
    ||
224  | 
    8128  | 
    fptreef(shf, indent, "< ");  | 
    |
225  | 
    8128  | 
    break;  | 
    |
226  | 
    case IOHERE:  | 
    ||
227  | 
    ✓✓ | 2126  | 
    if (flag&IOSKIP)  | 
    
228  | 
    156  | 
    fptreef(shf, indent, "<<- ");  | 
    |
229  | 
    else  | 
    ||
230  | 
    1970  | 
    fptreef(shf, indent, "<< ");  | 
    |
231  | 
    break;  | 
    ||
232  | 
    case IOCAT:  | 
    ||
233  | 
    845  | 
    fptreef(shf, indent, ">> ");  | 
    |
234  | 
    845  | 
    break;  | 
    |
235  | 
    case IOWRITE:  | 
    ||
236  | 
    ✗✓ | 33966  | 
    if (flag&IOCLOB)  | 
    
237  | 
    fptreef(shf, indent, ">| ");  | 
    ||
238  | 
    else  | 
    ||
239  | 
    33966  | 
    fptreef(shf, indent, "> ");  | 
    |
240  | 
    break;  | 
    ||
241  | 
    case IORDWR:  | 
    ||
242  | 
    fptreef(shf, indent, "<> ");  | 
    ||
243  | 
    break;  | 
    ||
244  | 
    case IODUP:  | 
    ||
245  | 
    ✗✓ | 136278  | 
    if (flag & IORDUP)  | 
    
246  | 
    fptreef(shf, indent, "<&");  | 
    ||
247  | 
    else  | 
    ||
248  | 
    136278  | 
    fptreef(shf, indent, ">&");  | 
    |
249  | 
    break;  | 
    ||
250  | 
    }  | 
    ||
251  | 
    /* name/delim are 0 when printing syntax errors */  | 
    ||
252  | 
    ✓✓ | 181343  | 
    	if (type == IOHERE) { | 
    
253  | 
    ✓✗ | 2126  | 
    if (iop->delim)  | 
    
254  | 
    2126  | 
    fptreef(shf, indent, "%S ", iop->delim);  | 
    |
255  | 
    ✓✗ | 179217  | 
    } else if (iop->name)  | 
    
256  | 
    179217  | 
    fptreef(shf, indent, (iop->flag & IONAMEXP) ? "%s " : "%S ",  | 
    |
257  | 
    iop->name);  | 
    ||
258  | 
    181343  | 
    }  | 
    |
259  | 
    |||
260  | 
    |||
261  | 
    /*  | 
    ||
262  | 
    * variants of fputc, fputs for ptreef and snptreef  | 
    ||
263  | 
    */  | 
    ||
264  | 
    |||
265  | 
    static void  | 
    ||
266  | 
    tputC(int c, struct shf *shf)  | 
    ||
267  | 
    { | 
    ||
268  | 
    ✓✓ | 79386378  | 
    	if ((c&0x60) == 0) {		/* C0|C1 */ | 
    
269  | 
    51999  | 
    tputc((c&0x80) ? '$' : '^', shf);  | 
    |
270  | 
    51999  | 
    tputc(((c&0x7F)|0x40), shf);  | 
    |
271  | 
    ✗✓ | 39693189  | 
    	} else if ((c&0x7F) == 0x7F) {	/* DEL */ | 
    
272  | 
    tputc((c&0x80) ? '$' : '^', shf);  | 
    ||
273  | 
    		tputc('?', shf); | 
    ||
274  | 
    } else  | 
    ||
275  | 
    39641190  | 
    tputc(c, shf);  | 
    |
276  | 
    39693189  | 
    }  | 
    |
277  | 
    |||
278  | 
    static void  | 
    ||
279  | 
    tputS(char *wp, struct shf *shf)  | 
    ||
280  | 
    { | 
    ||
281  | 
    int c, quoted=0;  | 
    ||
282  | 
    |||
283  | 
    /* problems:  | 
    ||
284  | 
    * `...` -> $(...)  | 
    ||
285  | 
    * 'foo' -> "foo"  | 
    ||
286  | 
    * could change encoding to:  | 
    ||
287  | 
    * OQUOTE ["'] ... CQUOTE ["']  | 
    ||
288  | 
    * COMSUB [(`] ...\0 (handle $ ` \ and maybe " in `...` case)  | 
    ||
289  | 
    */  | 
    ||
290  | 
    59295647  | 
    while (1)  | 
    |
291  | 
    ✓✓✓✓ ✓✓✓✓ ✓✓✗✓ ✓  | 
    89893798  | 
    		switch ((c = *wp++)) { | 
    
292  | 
    case EOS:  | 
    ||
293  | 
    return;  | 
    ||
294  | 
    case CHAR:  | 
    ||
295  | 
    30534140  | 
    tputC(*wp++, shf);  | 
    |
296  | 
    30534140  | 
    break;  | 
    |
297  | 
    case QCHAR:  | 
    ||
298  | 
    1428889  | 
    c = *wp++;  | 
    |
299  | 
    ✓✓ | 1428889  | 
    if (!quoted || (c == '"' || c == '`' || c == '$'))  | 
    
300  | 
    32557  | 
    				tputc('\\', shf); | 
    |
301  | 
    1428889  | 
    tputC(c, shf);  | 
    |
302  | 
    1428889  | 
    break;  | 
    |
303  | 
    case COMSUB:  | 
    ||
304  | 
    1684  | 
    			tputc('$', shf); | 
    |
305  | 
    1684  | 
    			tputc('(', shf); | 
    |
306  | 
    ✓✓ | 406384  | 
    while (*wp != 0)  | 
    
307  | 
    201508  | 
    tputC(*wp++, shf);  | 
    |
308  | 
    1684  | 
    			tputc(')', shf); | 
    |
309  | 
    1684  | 
    wp++;  | 
    |
310  | 
    1684  | 
    break;  | 
    |
311  | 
    case EXPRSUB:  | 
    ||
312  | 
    10  | 
    			tputc('$', shf); | 
    |
313  | 
    10  | 
    			tputc('(', shf); | 
    |
314  | 
    10  | 
    			tputc('(', shf); | 
    |
315  | 
    ✓✓ | 204  | 
    while (*wp != 0)  | 
    
316  | 
    92  | 
    tputC(*wp++, shf);  | 
    |
317  | 
    10  | 
    			tputc(')', shf); | 
    |
318  | 
    10  | 
    			tputc(')', shf); | 
    |
319  | 
    10  | 
    wp++;  | 
    |
320  | 
    10  | 
    break;  | 
    |
321  | 
    case OQUOTE:  | 
    ||
322  | 
    quoted = 1;  | 
    ||
323  | 
    1619461  | 
    			tputc('"', shf); | 
    |
324  | 
    1619461  | 
    break;  | 
    |
325  | 
    case CQUOTE:  | 
    ||
326  | 
    quoted = 0;  | 
    ||
327  | 
    1619461  | 
    			tputc('"', shf); | 
    |
328  | 
    1619461  | 
    break;  | 
    |
329  | 
    case OSUBST:  | 
    ||
330  | 
    2480160  | 
    			tputc('$', shf); | 
    |
331  | 
    ✓✓ | 2480160  | 
    			if (*wp++ == '{') | 
    
332  | 
    65175  | 
    				tputc('{', shf); | 
    |
333  | 
    ✓✓ | 20017440  | 
    while ((c = *wp++) != 0)  | 
    
334  | 
    7528560  | 
    tputC(c, shf);  | 
    |
335  | 
    break;  | 
    ||
336  | 
    case CSUBST:  | 
    ||
337  | 
    ✓✓ | 2480166  | 
    if (*wp++ == '}')  | 
    
338  | 
    65181  | 
    				tputc('}', shf); | 
    |
339  | 
    break;  | 
    ||
340  | 
    case OPAT:  | 
    ||
341  | 
    6  | 
    tputc(*wp++, shf);  | 
    |
342  | 
    6  | 
    			tputc('(', shf); | 
    |
343  | 
    6  | 
    break;  | 
    |
344  | 
    case SPAT:  | 
    ||
345  | 
    			tputc('|', shf); | 
    ||
346  | 
    break;  | 
    ||
347  | 
    case CPAT:  | 
    ||
348  | 
    6  | 
    			tputc(')', shf); | 
    |
349  | 
    6  | 
    break;  | 
    |
350  | 
    }  | 
    ||
351  | 
    9565832  | 
    }  | 
    |
352  | 
    |||
353  | 
    void  | 
    ||
354  | 
    fptreef(struct shf *shf, int indent, const char *fmt, ...)  | 
    ||
355  | 
    { | 
    ||
356  | 
    20579660  | 
    va_list va;  | 
    |
357  | 
    |||
358  | 
    10289830  | 
    va_start(va, fmt);  | 
    |
359  | 
    10289830  | 
    vfptreef(shf, indent, fmt, va);  | 
    |
360  | 
    10289830  | 
    va_end(va);  | 
    |
361  | 
    10289830  | 
    }  | 
    |
362  | 
    |||
363  | 
    char *  | 
    ||
364  | 
    snptreef(char *s, int n, const char *fmt, ...)  | 
    ||
365  | 
    { | 
    ||
366  | 
    6022510  | 
    va_list va;  | 
    |
367  | 
    3011255  | 
    struct shf shf;  | 
    |
368  | 
    |||
369  | 
    3011255  | 
    shf_sopen(s, n, SHF_WR | (s ? 0 : SHF_DYNAMIC), &shf);  | 
    |
370  | 
    |||
371  | 
    3011255  | 
    va_start(va, fmt);  | 
    |
372  | 
    3011255  | 
    vfptreef(&shf, 0, fmt, va);  | 
    |
373  | 
    3011255  | 
    va_end(va);  | 
    |
374  | 
    |||
375  | 
    6022510  | 
    return shf_sclose(&shf); /* null terminates */  | 
    |
376  | 
    3011255  | 
    }  | 
    |
377  | 
    |||
378  | 
    static void  | 
    ||
379  | 
    vfptreef(struct shf *shf, int indent, const char *fmt, va_list va)  | 
    ||
380  | 
    { | 
    ||
381  | 
    int c;  | 
    ||
382  | 
    |||
383  | 
    ✓✓ | 87576571  | 
    	while ((c = *fmt++)) { | 
    
384  | 
    ✓✓ | 23836658  | 
    		if (c == '%') { | 
    
385  | 
    long n;  | 
    ||
386  | 
    char *p;  | 
    ||
387  | 
    int neg;  | 
    ||
388  | 
    |||
389  | 
    ✓✓✓✗ ✗✓✗✓ ✗✗  | 
    13418761  | 
    			switch ((c = *fmt++)) { | 
    
390  | 
    case 'c':  | 
    ||
391  | 
    ✓✗ | 81  | 
    tputc(va_arg(va, int), shf);  | 
    
392  | 
    27  | 
    break;  | 
    |
393  | 
    case 's':  | 
    ||
394  | 
    ✓✗ | 7551  | 
    p = va_arg(va, char *);  | 
    
395  | 
    ✓✓ | 16340  | 
    while (*p)  | 
    
396  | 
    5653  | 
    tputc(*p++, shf);  | 
    |
397  | 
    break;  | 
    ||
398  | 
    case 'S': /* word */  | 
    ||
399  | 
    ✓✗ | 28697496  | 
    p = va_arg(va, char *);  | 
    
400  | 
    9565832  | 
    tputS(p, shf);  | 
    |
401  | 
    9565832  | 
    break;  | 
    |
402  | 
    case 'd': case 'u': /* decimal */  | 
    ||
403  | 
    n = (c == 'd') ? va_arg(va, int) :  | 
    ||
404  | 
    va_arg(va, unsigned int);  | 
    ||
405  | 
    neg = c=='d' && n<0;  | 
    ||
406  | 
    p = ulton((neg) ? -n : n, 10);  | 
    ||
407  | 
    if (neg)  | 
    ||
408  | 
    *--p = '-';  | 
    ||
409  | 
    while (*p)  | 
    ||
410  | 
    tputc(*p++, shf);  | 
    ||
411  | 
    break;  | 
    ||
412  | 
    case 'T': /* format tree */  | 
    ||
413  | 
    ✓✗ | 10655559  | 
    ptree(va_arg(va, struct op *), indent, shf);  | 
    
414  | 
    3551853  | 
    break;  | 
    |
415  | 
    case ';': /* newline or ; */  | 
    ||
416  | 
    case 'N': /* newline or space */  | 
    ||
417  | 
    ✓✗ | 298532  | 
    				if (shf->flags & SHF_STRING) { | 
    
418  | 
    ✓✓ | 298532  | 
    if (c == ';')  | 
    
419  | 
    298438  | 
    						tputc(';', shf); | 
    |
420  | 
    298532  | 
    					tputc(' ', shf); | 
    |
421  | 
    298532  | 
    				} else { | 
    |
422  | 
    int i;  | 
    ||
423  | 
    |||
424  | 
    					tputc('\n', shf); | 
    ||
425  | 
    for (i = indent; i >= 8; i -= 8)  | 
    ||
426  | 
    						tputc('\t', shf); | 
    ||
427  | 
    for (; i > 0; --i)  | 
    ||
428  | 
    						tputc(' ', shf); | 
    ||
429  | 
    }  | 
    ||
430  | 
    break;  | 
    ||
431  | 
    case 'R':  | 
    ||
432  | 
    pioact(shf, indent, va_arg(va, struct ioword *));  | 
    ||
433  | 
    break;  | 
    ||
434  | 
    default:  | 
    ||
435  | 
    tputc(c, shf);  | 
    ||
436  | 
    break;  | 
    ||
437  | 
    }  | 
    ||
438  | 
    13418761  | 
    } else  | 
    |
439  | 
    10417897  | 
    tputc(c, shf);  | 
    |
440  | 
    }  | 
    ||
441  | 
    13301085  | 
    }  | 
    |
442  | 
    |||
443  | 
    /*  | 
    ||
444  | 
    * copy tree (for function definition)  | 
    ||
445  | 
    */  | 
    ||
446  | 
    |||
447  | 
    struct op *  | 
    ||
448  | 
    tcopy(struct op *t, Area *ap)  | 
    ||
449  | 
    { | 
    ||
450  | 
    struct op *r;  | 
    ||
451  | 
    char **tw, **rw;  | 
    ||
452  | 
    |||
453  | 
    ✓✓ | 4348672  | 
    if (t == NULL)  | 
    
454  | 
    1100252  | 
    return NULL;  | 
    |
455  | 
    |||
456  | 
    1074084  | 
    r = alloc(sizeof(struct op), ap);  | 
    |
457  | 
    |||
458  | 
    1074084  | 
    r->type = t->type;  | 
    |
459  | 
    1074084  | 
    r->u.evalflags = t->u.evalflags;  | 
    |
460  | 
    |||
461  | 
    ✓✓ | 3222252  | 
    r->str = t->type == TCASE ? wdcopy(t->str, ap) : str_save(t->str, ap);  | 
    
462  | 
    |||
463  | 
    ✓✓ | 1074084  | 
    if (t->vars == NULL)  | 
    
464  | 
    544826  | 
    r->vars = NULL;  | 
    |
465  | 
    	else { | 
    ||
466  | 
    ✓✓ | 1238666  | 
    for (tw = t->vars; *tw++ != NULL; )  | 
    
467  | 
    ;  | 
    ||
468  | 
    529258  | 
    rw = r->vars = areallocarray(NULL, tw - t->vars + 1,  | 
    |
469  | 
    sizeof(*tw), ap);  | 
    ||
470  | 
    ✓✓ | 1238666  | 
    for (tw = t->vars; *tw != NULL; )  | 
    
471  | 
    90075  | 
    *rw++ = wdcopy(*tw++, ap);  | 
    |
472  | 
    529258  | 
    *rw = NULL;  | 
    |
473  | 
    }  | 
    ||
474  | 
    |||
475  | 
    ✓✓ | 1074084  | 
    if (t->args == NULL)  | 
    
476  | 
    550308  | 
    r->args = NULL;  | 
    |
477  | 
    	else { | 
    ||
478  | 
    ✓✓ | 3550674  | 
    for (tw = t->args; *tw++ != NULL; )  | 
    
479  | 
    ;  | 
    ||
480  | 
    523776  | 
    rw = r->args = areallocarray(NULL, tw - t->args + 1,  | 
    |
481  | 
    sizeof(*tw), ap);  | 
    ||
482  | 
    ✓✓ | 3550674  | 
    for (tw = t->args; *tw != NULL; )  | 
    
483  | 
    1251561  | 
    *rw++ = wdcopy(*tw++, ap);  | 
    |
484  | 
    523776  | 
    *rw = NULL;  | 
    |
485  | 
    }  | 
    ||
486  | 
    |||
487  | 
    ✓✓ | 2170155  | 
    r->ioact = (t->ioact == NULL) ? NULL : iocopy(t->ioact, ap);  | 
    
488  | 
    |||
489  | 
    1074084  | 
    r->left = tcopy(t->left, ap);  | 
    |
490  | 
    1074084  | 
    r->right = tcopy(t->right, ap);  | 
    |
491  | 
    1074084  | 
    r->lineno = t->lineno;  | 
    |
492  | 
    |||
493  | 
    1074084  | 
    return r;  | 
    |
494  | 
    2174336  | 
    }  | 
    |
495  | 
    |||
496  | 
    char *  | 
    ||
497  | 
    wdcopy(const char *wp, Area *ap)  | 
    ||
498  | 
    { | 
    ||
499  | 
    2745538  | 
    size_t len = wdscan(wp, EOS) - wp;  | 
    |
500  | 
    1372769  | 
    return memcpy(alloc(len, ap), wp, len);  | 
    |
501  | 
    }  | 
    ||
502  | 
    |||
503  | 
    /* return the position of prefix c in wp plus 1 */  | 
    ||
504  | 
    char *  | 
    ||
505  | 
    wdscan(const char *wp, int c)  | 
    ||
506  | 
    { | 
    ||
507  | 
    int nest = 0;  | 
    ||
508  | 
    |||
509  | 
    19699271  | 
    while (1)  | 
    |
510  | 
    ✓✗✓✗ ✓✓✓✓ ✗✓✗✗ ✓  | 
    20474402  | 
    		switch (*wp++) { | 
    
511  | 
    case EOS:  | 
    ||
512  | 
    1372835  | 
    return (char *) wp;  | 
    |
513  | 
    case CHAR:  | 
    ||
514  | 
    case QCHAR:  | 
    ||
515  | 
    6145002  | 
    wp++;  | 
    |
516  | 
    6145002  | 
    break;  | 
    |
517  | 
    case COMSUB:  | 
    ||
518  | 
    case EXPRSUB:  | 
    ||
519  | 
    ✓✓ | 2232714  | 
    while (*wp++ != 0)  | 
    
520  | 
    ;  | 
    ||
521  | 
    break;  | 
    ||
522  | 
    case OQUOTE:  | 
    ||
523  | 
    case CQUOTE:  | 
    ||
524  | 
    break;  | 
    ||
525  | 
    case OSUBST:  | 
    ||
526  | 
    337995  | 
    nest++;  | 
    |
527  | 
    ✓✓ | 3825176  | 
    while (*wp++ != '\0')  | 
    
528  | 
    ;  | 
    ||
529  | 
    break;  | 
    ||
530  | 
    case CSUBST:  | 
    ||
531  | 
    5051792  | 
    wp++;  | 
    |
532  | 
    ✓✓ | 5051792  | 
    if (c == CSUBST && nest == 0)  | 
    
533  | 
    4713797  | 
    return (char *) wp;  | 
    |
534  | 
    337995  | 
    nest--;  | 
    |
535  | 
    337995  | 
    break;  | 
    |
536  | 
    case OPAT:  | 
    ||
537  | 
    330  | 
    nest++;  | 
    |
538  | 
    330  | 
    wp++;  | 
    |
539  | 
    330  | 
    break;  | 
    |
540  | 
    case SPAT:  | 
    ||
541  | 
    case CPAT:  | 
    ||
542  | 
    ✗✓ | 546  | 
    if (c == wp[-1] && nest == 0)  | 
    
543  | 
    return (char *) wp;  | 
    ||
544  | 
    ✓✓ | 546  | 
    if (wp[-1] == CPAT)  | 
    
545  | 
    330  | 
    nest--;  | 
    |
546  | 
    break;  | 
    ||
547  | 
    default:  | 
    ||
548  | 
    internal_errorf(0,  | 
    ||
549  | 
    "wdscan: unknown char 0x%x (carrying on)",  | 
    ||
550  | 
    wp[-1]);  | 
    ||
551  | 
    }  | 
    ||
552  | 
    6086632  | 
    }  | 
    |
553  | 
    |||
554  | 
    /* return a copy of wp without any of the mark up characters and  | 
    ||
555  | 
     * with quote characters (" ' \) stripped. | 
    ||
556  | 
    * (string is allocated from ATEMP)  | 
    ||
557  | 
    */  | 
    ||
558  | 
    char *  | 
    ||
559  | 
    wdstrip(const char *wp)  | 
    ||
560  | 
    { | 
    ||
561  | 
    52324  | 
    struct shf shf;  | 
    |
562  | 
    int c;  | 
    ||
563  | 
    |||
564  | 
    26162  | 
    shf_sopen(NULL, 32, SHF_WR | SHF_DYNAMIC, &shf);  | 
    |
565  | 
    |||
566  | 
    /* problems:  | 
    ||
567  | 
    * `...` -> $(...)  | 
    ||
568  | 
    	 *	x${foo:-"hi"} -> x${foo:-hi} | 
    ||
569  | 
    	 *	x${foo:-'hi'} -> x${foo:-hi} | 
    ||
570  | 
    */  | 
    ||
571  | 
    199091  | 
    while (1)  | 
    |
572  | 
    ✓✗✓✗ ✗✗✗✗ ✗✗✓  | 
    372020  | 
    		switch ((c = *wp++)) { | 
    
573  | 
    case EOS:  | 
    ||
574  | 
    52324  | 
    return shf_sclose(&shf); /* null terminates */  | 
    |
575  | 
    case CHAR:  | 
    ||
576  | 
    case QCHAR:  | 
    ||
577  | 
    172929  | 
    shf_putchar(*wp++, &shf);  | 
    |
578  | 
    172929  | 
    break;  | 
    |
579  | 
    case COMSUB:  | 
    ||
580  | 
    			shf_putchar('$', &shf); | 
    ||
581  | 
    			shf_putchar('(', &shf); | 
    ||
582  | 
    while (*wp != 0)  | 
    ||
583  | 
    shf_putchar(*wp++, &shf);  | 
    ||
584  | 
    			shf_putchar(')', &shf); | 
    ||
585  | 
    break;  | 
    ||
586  | 
    case EXPRSUB:  | 
    ||
587  | 
    			shf_putchar('$', &shf); | 
    ||
588  | 
    			shf_putchar('(', &shf); | 
    ||
589  | 
    			shf_putchar('(', &shf); | 
    ||
590  | 
    while (*wp != 0)  | 
    ||
591  | 
    shf_putchar(*wp++, &shf);  | 
    ||
592  | 
    			shf_putchar(')', &shf); | 
    ||
593  | 
    			shf_putchar(')', &shf); | 
    ||
594  | 
    break;  | 
    ||
595  | 
    case OQUOTE:  | 
    ||
596  | 
    break;  | 
    ||
597  | 
    case CQUOTE:  | 
    ||
598  | 
    break;  | 
    ||
599  | 
    case OSUBST:  | 
    ||
600  | 
    			shf_putchar('$', &shf); | 
    ||
601  | 
    			if (*wp++ == '{') | 
    ||
602  | 
    			    shf_putchar('{', &shf); | 
    ||
603  | 
    while ((c = *wp++) != 0)  | 
    ||
604  | 
    shf_putchar(c, &shf);  | 
    ||
605  | 
    break;  | 
    ||
606  | 
    case CSUBST:  | 
    ||
607  | 
    if (*wp++ == '}')  | 
    ||
608  | 
    				shf_putchar('}', &shf); | 
    ||
609  | 
    break;  | 
    ||
610  | 
    case OPAT:  | 
    ||
611  | 
    shf_putchar(*wp++, &shf);  | 
    ||
612  | 
    			shf_putchar('(', &shf); | 
    ||
613  | 
    break;  | 
    ||
614  | 
    case SPAT:  | 
    ||
615  | 
    			shf_putchar('|', &shf); | 
    ||
616  | 
    break;  | 
    ||
617  | 
    case CPAT:  | 
    ||
618  | 
    			shf_putchar(')', &shf); | 
    ||
619  | 
    break;  | 
    ||
620  | 
    }  | 
    ||
621  | 
    26162  | 
    }  | 
    |
622  | 
    |||
623  | 
    static struct ioword **  | 
    ||
624  | 
    iocopy(struct ioword **iow, Area *ap)  | 
    ||
625  | 
    { | 
    ||
626  | 
    struct ioword **ior;  | 
    ||
627  | 
    int i;  | 
    ||
628  | 
    |||
629  | 
    ✓✓ | 127159  | 
    for (ior = iow; *ior++ != NULL; )  | 
    
630  | 
    ;  | 
    ||
631  | 
    21987  | 
    ior = areallocarray(NULL, ior - iow + 1, sizeof(*ior), ap);  | 
    |
632  | 
    |||
633  | 
    ✓✓ | 105172  | 
    	for (i = 0; iow[i] != NULL; i++) { | 
    
634  | 
    struct ioword *p, *q;  | 
    ||
635  | 
    |||
636  | 
    p = iow[i];  | 
    ||
637  | 
    30599  | 
    q = alloc(sizeof(*p), ap);  | 
    |
638  | 
    30599  | 
    ior[i] = q;  | 
    |
639  | 
    30599  | 
    *q = *p;  | 
    |
640  | 
    ✓✓ | 30599  | 
    if (p->name != NULL)  | 
    
641  | 
    29775  | 
    q->name = wdcopy(p->name, ap);  | 
    |
642  | 
    ✓✓ | 30599  | 
    if (p->delim != NULL)  | 
    
643  | 
    824  | 
    q->delim = wdcopy(p->delim, ap);  | 
    |
644  | 
    ✓✓ | 30599  | 
    if (p->heredoc != NULL)  | 
    
645  | 
    824  | 
    q->heredoc = str_save(p->heredoc, ap);  | 
    |
646  | 
    }  | 
    ||
647  | 
    21987  | 
    ior[i] = NULL;  | 
    |
648  | 
    |||
649  | 
    21987  | 
    return ior;  | 
    |
650  | 
    }  | 
    ||
651  | 
    |||
652  | 
    /*  | 
    ||
653  | 
    * free tree (for function definition)  | 
    ||
654  | 
    */  | 
    ||
655  | 
    |||
656  | 
    void  | 
    ||
657  | 
    tfree(struct op *t, Area *ap)  | 
    ||
658  | 
    { | 
    ||
659  | 
    char **w;  | 
    ||
660  | 
    |||
661  | 
    ✓✓ | 276  | 
    if (t == NULL)  | 
    
662  | 
    78  | 
    return;  | 
    |
663  | 
    |||
664  | 
    60  | 
    afree(t->str, ap);  | 
    |
665  | 
    |||
666  | 
    ✓✓ | 60  | 
    	if (t->vars != NULL) { | 
    
667  | 
    ✗✓ | 48  | 
    for (w = t->vars; *w != NULL; w++)  | 
    
668  | 
    afree(*w, ap);  | 
    ||
669  | 
    24  | 
    afree(t->vars, ap);  | 
    |
670  | 
    24  | 
    }  | 
    |
671  | 
    |||
672  | 
    ✓✓ | 60  | 
    	if (t->args != NULL) { | 
    
673  | 
    ✓✓ | 96  | 
    for (w = t->args; *w != NULL; w++)  | 
    
674  | 
    24  | 
    afree(*w, ap);  | 
    |
675  | 
    24  | 
    afree(t->args, ap);  | 
    |
676  | 
    24  | 
    }  | 
    |
677  | 
    |||
678  | 
    ✓✓ | 60  | 
    if (t->ioact != NULL)  | 
    
679  | 
    24  | 
    iofree(t->ioact, ap);  | 
    |
680  | 
    |||
681  | 
    60  | 
    tfree(t->left, ap);  | 
    |
682  | 
    60  | 
    tfree(t->right, ap);  | 
    |
683  | 
    |||
684  | 
    60  | 
    afree(t, ap);  | 
    |
685  | 
    198  | 
    }  | 
    |
686  | 
    |||
687  | 
    static void  | 
    ||
688  | 
    iofree(struct ioword **iow, Area *ap)  | 
    ||
689  | 
    { | 
    ||
690  | 
    struct ioword **iop;  | 
    ||
691  | 
    struct ioword *p;  | 
    ||
692  | 
    |||
693  | 
    ✓✓ | 120  | 
    	for (iop = iow; (p = *iop++) != NULL; ) { | 
    
694  | 
    24  | 
    afree(p->name, ap);  | 
    |
695  | 
    24  | 
    afree(p->delim, ap);  | 
    |
696  | 
    24  | 
    afree(p->heredoc, ap);  | 
    |
697  | 
    24  | 
    afree(p, ap);  | 
    |
698  | 
    }  | 
    ||
699  | 
    24  | 
    afree(iow, ap);  | 
    |
700  | 
    24  | 
    }  | 
    
| Generated by: GCOVR (Version 3.3) |