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) |