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 |
23557 |
{ |
|
29 |
char **w; |
||
30 |
struct ioword **ioact; |
||
31 |
struct op *t1; |
||
32 |
|||
33 |
23557 |
Chain: |
|
34 |
✓✓ | 23557 |
if (t == NULL) |
35 |
4 |
return; |
|
36 |
✓✓✓✓ ✓✓✗✗ ✗✓✓✓ ✓✓✗✗ ✓✗✗ |
23553 |
switch (t->type) { |
37 |
case TCOM: |
||
38 |
✓✗ | 15248 |
if (t->vars) |
39 |
✓✓ | 30950 |
for (w = t->vars; *w != NULL; ) |
40 |
454 |
fptreef(shf, indent, "%S ", *w++); |
|
41 |
else |
||
42 |
fptreef(shf, indent, "#no-vars# "); |
||
43 |
✓✗ | 15248 |
if (t->args) |
44 |
✓✓ | 83221 |
for (w = t->args; *w != NULL; ) |
45 |
52725 |
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 |
6993 |
t = t->left; |
|
67 |
6993 |
goto Chain; |
|
68 |
#endif |
||
69 |
case TPAREN: |
||
70 |
194 |
fptreef(shf, indent + 2, "( %T) ", t->left); |
|
71 |
194 |
break; |
|
72 |
case TPIPE: |
||
73 |
115 |
fptreef(shf, indent, "%T| ", t->left); |
|
74 |
115 |
t = t->right; |
|
75 |
115 |
goto Chain; |
|
76 |
case TLIST: |
||
77 |
627 |
fptreef(shf, indent, "%T%;", t->left); |
|
78 |
627 |
t = t->right; |
|
79 |
627 |
goto Chain; |
|
80 |
case TOR: |
||
81 |
case TAND: |
||
82 |
✓✓ | 188 |
fptreef(shf, indent, "%T%s %T", |
83 |
t->left, (t->type==TOR) ? "||" : "&&", t->right); |
||
84 |
188 |
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 |
✓✓ | 238 |
for (w = t->vars; *w; ) |
108 |
220 |
fptreef(shf, indent, "%S ", *w++); |
|
109 |
9 |
fptreef(shf, indent, "%;"); |
|
110 |
} |
||
111 |
9 |
fptreef(shf, indent + INDENT, "do%N%T", t->left); |
|
112 |
9 |
fptreef(shf, indent, "%;done "); |
|
113 |
9 |
break; |
|
114 |
case TCASE: |
||
115 |
137 |
fptreef(shf, indent, "case %S in", t->str); |
|
116 |
✓✓ | 402 |
for (t1 = t->left; t1 != NULL; t1 = t1->right) { |
117 |
265 |
fptreef(shf, indent, "%N("); |
|
118 |
✓✓ | 768 |
for (w = t1->vars; *w != NULL; w++) |
119 |
✓✓ | 503 |
fptreef(shf, indent, "%S%c", *w, |
120 |
(w[1] != NULL) ? '|' : ')'); |
||
121 |
265 |
fptreef(shf, indent + INDENT, "%;%T%N;;", t1->left); |
|
122 |
} |
||
123 |
137 |
fptreef(shf, indent, "%Nesac "); |
|
124 |
137 |
break; |
|
125 |
case TIF: |
||
126 |
case TELIF: |
||
127 |
/* 3 == strlen("if ") */ |
||
128 |
10 |
fptreef(shf, indent + 3, "if %T", t->left); |
|
129 |
for (;;) { |
||
130 |
10 |
t = t->right; |
|
131 |
✓✗ | 10 |
if (t->left != NULL) { |
132 |
10 |
fptreef(shf, indent, "%;"); |
|
133 |
10 |
fptreef(shf, indent + INDENT, "then%N%T", |
|
134 |
t->left); |
||
135 |
} |
||
136 |
✓✓✗✓ |
10 |
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 |
✓✓ | 10 |
if (t->right != NULL) { |
144 |
6 |
fptreef(shf, indent, "%;"); |
|
145 |
6 |
fptreef(shf, indent + INDENT, "else%;%T", t->right); |
|
146 |
} |
||
147 |
10 |
fptreef(shf, indent, "%;fi "); |
|
148 |
10 |
break; |
|
149 |
case TWHILE: |
||
150 |
case TUNTIL: |
||
151 |
/* 6 == strlen("while"/"until") */ |
||
152 |
✓✗ | 4 |
fptreef(shf, indent + 6, "%s %T", |
153 |
(t->type==TWHILE) ? "while" : "until", |
||
154 |
t->left); |
||
155 |
4 |
fptreef(shf, indent, "%;do"); |
|
156 |
4 |
fptreef(shf, indent + INDENT, "%;%T", t->right); |
|
157 |
4 |
fptreef(shf, indent, "%;done "); |
|
158 |
4 |
break; |
|
159 |
case TBRACE: |
||
160 |
18 |
fptreef(shf, indent + INDENT, "{%;%T", t->left); |
|
161 |
18 |
fptreef(shf, indent, "%;} "); |
|
162 |
18 |
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 |
✗✓ | 10 |
fptreef(shf, indent, |
171 |
t->u.ksh_func ? "function %s %T" : "%s() %T", |
||
172 |
t->str, t->left); |
||
173 |
10 |
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 |
✓✓ | 15818 |
if ((ioact = t->ioact) != NULL) { |
182 |
3494 |
int need_nl = 0; |
|
183 |
|||
184 |
✓✓ | 12015 |
while (*ioact != NULL) |
185 |
5027 |
pioact(shf, indent, *ioact++); |
|
186 |
/* Print here documents after everything else... */ |
||
187 |
✓✓ | 12015 |
for (ioact = t->ioact; *ioact != NULL; ) { |
188 |
5027 |
struct ioword *iop = *ioact++; |
|
189 |
|||
190 |
/* heredoc is 0 when tracing (set -x) */ |
||
191 |
✓✓✓✗ |
5027 |
if ((iop->flag & IOTYPE) == IOHERE && iop->heredoc) { |
192 |
844 |
tputc('\n', shf); |
|
193 |
844 |
shf_puts(iop->heredoc, shf); |
|
194 |
844 |
fptreef(shf, indent, "%s", |
|
195 |
evalstr(iop->delim, 0)); |
||
196 |
844 |
need_nl = 1; |
|
197 |
} |
||
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 |
✓✓ | 3494 |
if (need_nl) |
204 |
842 |
tputc('\n', shf); |
|
205 |
} |
||
206 |
} |
||
207 |
|||
208 |
static void |
||
209 |
pioact(struct shf *shf, int indent, struct ioword *iop) |
||
210 |
5027 |
{ |
|
211 |
5027 |
int flag = iop->flag; |
|
212 |
5027 |
int type = flag & IOTYPE; |
|
213 |
int expected; |
||
214 |
|||
215 |
✓✓✓✓ ✓✓✓✗ ✓✓ |
5027 |
expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0 : |
216 |
(type == IOCAT || type == IOWRITE) ? 1 : |
||
217 |
(type == IODUP && (iop->unit == !(flag & IORDUP))) ? iop->unit : |
||
218 |
iop->unit + 1; |
||
219 |
✓✓ | 5027 |
if (iop->unit != expected) |
220 |
1288 |
tputc('0' + iop->unit, shf); |
|
221 |
|||
222 |
✓✓✓✓ ✗✓✗ |
5027 |
switch (type) { |
223 |
case IOREAD: |
||
224 |
68 |
fptreef(shf, indent, "< "); |
|
225 |
68 |
break; |
|
226 |
case IOHERE: |
||
227 |
✓✓ | 844 |
if (flag&IOSKIP) |
228 |
46 |
fptreef(shf, indent, "<<- "); |
|
229 |
else |
||
230 |
798 |
fptreef(shf, indent, "<< "); |
|
231 |
break; |
||
232 |
case IOCAT: |
||
233 |
444 |
fptreef(shf, indent, ">> "); |
|
234 |
444 |
break; |
|
235 |
case IOWRITE: |
||
236 |
✗✓ | 2031 |
if (flag&IOCLOB) |
237 |
fptreef(shf, indent, ">| "); |
||
238 |
else |
||
239 |
2031 |
fptreef(shf, indent, "> "); |
|
240 |
break; |
||
241 |
case IORDWR: |
||
242 |
fptreef(shf, indent, "<> "); |
||
243 |
break; |
||
244 |
case IODUP: |
||
245 |
✗✓ | 1640 |
if (flag & IORDUP) |
246 |
fptreef(shf, indent, "<&"); |
||
247 |
else |
||
248 |
1640 |
fptreef(shf, indent, ">&"); |
|
249 |
break; |
||
250 |
} |
||
251 |
/* name/delim are 0 when printing syntax errors */ |
||
252 |
✓✓ | 5027 |
if (type == IOHERE) { |
253 |
✓✗ | 844 |
if (iop->delim) |
254 |
844 |
fptreef(shf, indent, "%S ", iop->delim); |
|
255 |
✓✗ | 4183 |
} else if (iop->name) |
256 |
✗✓ | 4183 |
fptreef(shf, indent, (iop->flag & IONAMEXP) ? "%s " : "%S ", |
257 |
iop->name); |
||
258 |
5027 |
} |
|
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 |
573450 |
{ |
|
268 |
✓✓ | 573450 |
if ((c&0x60) == 0) { /* C0|C1 */ |
269 |
✗✓ | 6206 |
tputc((c&0x80) ? '$' : '^', shf); |
270 |
6206 |
tputc(((c&0x7F)|0x40), shf); |
|
271 |
✗✓ | 567244 |
} else if ((c&0x7F) == 0x7F) { /* DEL */ |
272 |
tputc((c&0x80) ? '$' : '^', shf); |
||
273 |
tputc('?', shf); |
||
274 |
} else |
||
275 |
567244 |
tputc(c, shf); |
|
276 |
573450 |
} |
|
277 |
|||
278 |
static void |
||
279 |
tputS(char *wp, struct shf *shf) |
||
280 |
59070 |
{ |
|
281 |
59070 |
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 |
while (1) |
||
291 |
✗✓✓✓ ✗✓✓✓ ✓✗✗✗ ✓ |
558296 |
switch ((c = *wp++)) { |
292 |
case EOS: |
||
293 |
return; |
||
294 |
case CHAR: |
||
295 |
359738 |
tputC(*wp++, shf); |
|
296 |
359738 |
break; |
|
297 |
case QCHAR: |
||
298 |
91949 |
c = *wp++; |
|
299 |
✓✓✓✓ ✓✓ |
91949 |
if (!quoted || (c == '"' || c == '`' || c == '$')) |
300 |
3356 |
tputc('\\', shf); |
|
301 |
91949 |
tputC(c, shf); |
|
302 |
91949 |
break; |
|
303 |
case COMSUB: |
||
304 |
109 |
tputc('$', shf); |
|
305 |
109 |
tputc('(', shf); |
|
306 |
✓✓ | 4612 |
while (*wp != 0) |
307 |
4394 |
tputC(*wp++, shf); |
|
308 |
109 |
tputc(')', shf); |
|
309 |
109 |
wp++; |
|
310 |
109 |
break; |
|
311 |
case EXPRSUB: |
||
312 |
tputc('$', shf); |
||
313 |
tputc('(', shf); |
||
314 |
tputc('(', shf); |
||
315 |
while (*wp != 0) |
||
316 |
tputC(*wp++, shf); |
||
317 |
tputc(')', shf); |
||
318 |
tputc(')', shf); |
||
319 |
wp++; |
||
320 |
break; |
||
321 |
case OQUOTE: |
||
322 |
8821 |
quoted = 1; |
|
323 |
8821 |
tputc('"', shf); |
|
324 |
8821 |
break; |
|
325 |
case CQUOTE: |
||
326 |
8821 |
quoted = 0; |
|
327 |
8821 |
tputc('"', shf); |
|
328 |
8821 |
break; |
|
329 |
case OSUBST: |
||
330 |
14894 |
tputc('$', shf); |
|
331 |
✓✓ | 14894 |
if (*wp++ == '{') |
332 |
5402 |
tputc('{', shf); |
|
333 |
✓✓ | 132263 |
while ((c = *wp++) != 0) |
334 |
117369 |
tputC(c, shf); |
|
335 |
break; |
||
336 |
case CSUBST: |
||
337 |
✓✓ | 14894 |
if (*wp++ == '}') |
338 |
5402 |
tputc('}', shf); |
|
339 |
break; |
||
340 |
case OPAT: |
||
341 |
tputc(*wp++, shf); |
||
342 |
tputc('(', shf); |
||
343 |
break; |
||
344 |
case SPAT: |
||
345 |
tputc('|', shf); |
||
346 |
break; |
||
347 |
case CPAT: |
||
348 |
tputc(')', shf); |
||
349 |
break; |
||
350 |
} |
||
351 |
} |
||
352 |
|||
353 |
void |
||
354 |
fptreef(struct shf *shf, int indent, const char *fmt, ...) |
||
355 |
66887 |
{ |
|
356 |
va_list va; |
||
357 |
|||
358 |
66887 |
va_start(va, fmt); |
|
359 |
66887 |
vfptreef(shf, indent, fmt, va); |
|
360 |
66887 |
va_end(va); |
|
361 |
66887 |
} |
|
362 |
|||
363 |
char * |
||
364 |
snptreef(char *s, int n, const char *fmt, ...) |
||
365 |
14178 |
{ |
|
366 |
va_list va; |
||
367 |
struct shf shf; |
||
368 |
|||
369 |
✓✓ | 14178 |
shf_sopen(s, n, SHF_WR | (s ? 0 : SHF_DYNAMIC), &shf); |
370 |
|||
371 |
14178 |
va_start(va, fmt); |
|
372 |
14178 |
vfptreef(&shf, 0, fmt, va); |
|
373 |
14178 |
va_end(va); |
|
374 |
|||
375 |
14178 |
return shf_sclose(&shf); /* null terminates */ |
|
376 |
} |
||
377 |
|||
378 |
static void |
||
379 |
vfptreef(struct shf *shf, int indent, const char *fmt, va_list va) |
||
380 |
81065 |
{ |
|
381 |
int c; |
||
382 |
|||
383 |
✓✓ | 314215 |
while ((c = *fmt++)) { |
384 |
✓✓ | 152085 |
if (c == '%') { |
385 |
long n; |
||
386 |
char *p; |
||
387 |
int neg; |
||
388 |
|||
389 |
✓✓✓✗ ✓✓✗✗ |
78126 |
switch ((c = *fmt++)) { |
390 |
case 'c': |
||
391 |
✓✗ | 503 |
tputc(va_arg(va, int), shf); |
392 |
503 |
break; |
|
393 |
case 's': |
||
394 |
✓✗ | 1055 |
p = va_arg(va, char *); |
395 |
✓✓ | 7379 |
while (*p) |
396 |
5269 |
tputc(*p++, shf); |
|
397 |
break; |
||
398 |
case 'S': /* word */ |
||
399 |
✓✗ | 59070 |
p = va_arg(va, char *); |
400 |
59070 |
tputS(p, shf); |
|
401 |
59070 |
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 |
✓✗ | 15822 |
ptree(va_arg(va, struct op *), indent, shf); |
414 |
15822 |
break; |
|
415 |
case ';': /* newline or ; */ |
||
416 |
case 'N': /* newline or space */ |
||
417 |
✓✗ | 1676 |
if (shf->flags & SHF_STRING) { |
418 |
✓✓ | 1676 |
if (c == ';') |
419 |
990 |
tputc(';', shf); |
|
420 |
1676 |
tputc(' ', shf); |
|
421 |
} 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 |
} else |
||
439 |
73959 |
tputc(c, shf); |
|
440 |
} |
||
441 |
81065 |
} |
|
442 |
|||
443 |
/* |
||
444 |
* copy tree (for function definition) |
||
445 |
*/ |
||
446 |
|||
447 |
struct op * |
||
448 |
tcopy(struct op *t, Area *ap) |
||
449 |
21456 |
{ |
|
450 |
struct op *r; |
||
451 |
char **tw, **rw; |
||
452 |
|||
453 |
✓✓ | 21456 |
if (t == NULL) |
454 |
10905 |
return NULL; |
|
455 |
|||
456 |
10551 |
r = alloc(sizeof(struct op), ap); |
|
457 |
|||
458 |
10551 |
r->type = t->type; |
|
459 |
10551 |
r->u.evalflags = t->u.evalflags; |
|
460 |
|||
461 |
✓✓ | 10551 |
r->str = t->type == TCASE ? wdcopy(t->str, ap) : str_save(t->str, ap); |
462 |
|||
463 |
✓✓ | 10551 |
if (t->vars == NULL) |
464 |
5208 |
r->vars = NULL; |
|
465 |
else { |
||
466 |
✓✓ | 5343 |
for (tw = t->vars; *tw++ != NULL; ) |
467 |
; |
||
468 |
5343 |
rw = r->vars = areallocarray(NULL, tw - t->vars + 1, |
|
469 |
sizeof(*tw), ap); |
||
470 |
✓✓ | 12417 |
for (tw = t->vars; *tw != NULL; ) |
471 |
1731 |
*rw++ = wdcopy(*tw++, ap); |
|
472 |
5343 |
*rw = NULL; |
|
473 |
} |
||
474 |
|||
475 |
✓✓ | 10551 |
if (t->args == NULL) |
476 |
5758 |
r->args = NULL; |
|
477 |
else { |
||
478 |
✓✓ | 4793 |
for (tw = t->args; *tw++ != NULL; ) |
479 |
; |
||
480 |
4793 |
rw = r->args = areallocarray(NULL, tw - t->args + 1, |
|
481 |
sizeof(*tw), ap); |
||
482 |
✓✓ | 21247 |
for (tw = t->args; *tw != NULL; ) |
483 |
11661 |
*rw++ = wdcopy(*tw++, ap); |
|
484 |
4793 |
*rw = NULL; |
|
485 |
} |
||
486 |
|||
487 |
✓✓ | 10551 |
r->ioact = (t->ioact == NULL) ? NULL : iocopy(t->ioact, ap); |
488 |
|||
489 |
10551 |
r->left = tcopy(t->left, ap); |
|
490 |
10551 |
r->right = tcopy(t->right, ap); |
|
491 |
10551 |
r->lineno = t->lineno; |
|
492 |
|||
493 |
10551 |
return r; |
|
494 |
} |
||
495 |
|||
496 |
char * |
||
497 |
wdcopy(const char *wp, Area *ap) |
||
498 |
14114 |
{ |
|
499 |
14114 |
size_t len = wdscan(wp, EOS) - wp; |
|
500 |
14114 |
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 |
149669 |
{ |
|
507 |
149669 |
int nest = 0; |
|
508 |
|||
509 |
while (1) |
||
510 |
✓✓✓✓ ✓✓✗✗ ✗ |
300222 |
switch (*wp++) { |
511 |
case EOS: |
||
512 |
14118 |
return (char *) wp; |
|
513 |
case CHAR: |
||
514 |
case QCHAR: |
||
515 |
135044 |
wp++; |
|
516 |
135044 |
break; |
|
517 |
case COMSUB: |
||
518 |
case EXPRSUB: |
||
519 |
✓✓ | 3600 |
while (*wp++ != 0) |
520 |
; |
||
521 |
break; |
||
522 |
case OQUOTE: |
||
523 |
case CQUOTE: |
||
524 |
break; |
||
525 |
case OSUBST: |
||
526 |
5979 |
nest++; |
|
527 |
✓✓ | 38129 |
while (*wp++ != '\0') |
528 |
; |
||
529 |
break; |
||
530 |
case CSUBST: |
||
531 |
141530 |
wp++; |
|
532 |
✓✓ | 141530 |
if (c == CSUBST && nest == 0) |
533 |
135551 |
return (char *) wp; |
|
534 |
5979 |
nest--; |
|
535 |
5979 |
break; |
|
536 |
case OPAT: |
||
537 |
nest++; |
||
538 |
wp++; |
||
539 |
break; |
||
540 |
case SPAT: |
||
541 |
case CPAT: |
||
542 |
if (c == wp[-1] && nest == 0) |
||
543 |
return (char *) wp; |
||
544 |
if (wp[-1] == CPAT) |
||
545 |
nest--; |
||
546 |
break; |
||
547 |
default: |
||
548 |
internal_errorf(0, |
||
549 |
"wdscan: unknown char 0x%x (carrying on)", |
||
550 |
wp[-1]); |
||
551 |
} |
||
552 |
} |
||
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 |
354 |
{ |
|
561 |
struct shf shf; |
||
562 |
int c; |
||
563 |
|||
564 |
354 |
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 |
while (1) |
||
572 |
✗✓✓✗ ✗✗✗✗ ✗✗ |
2901 |
switch ((c = *wp++)) { |
573 |
case EOS: |
||
574 |
354 |
return shf_sclose(&shf); /* null terminates */ |
|
575 |
case CHAR: |
||
576 |
case QCHAR: |
||
577 |
2547 |
shf_putchar(*wp++, &shf); |
|
578 |
2547 |
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 |
} |
||
622 |
|||
623 |
static struct ioword ** |
||
624 |
iocopy(struct ioword **iow, Area *ap) |
||
625 |
644 |
{ |
|
626 |
struct ioword **ior; |
||
627 |
int i; |
||
628 |
|||
629 |
✓✓ | 644 |
for (ior = iow; *ior++ != NULL; ) |
630 |
; |
||
631 |
644 |
ior = areallocarray(NULL, ior - iow + 1, sizeof(*ior), ap); |
|
632 |
|||
633 |
✓✓ | 1331 |
for (i = 0; iow[i] != NULL; i++) { |
634 |
struct ioword *p, *q; |
||
635 |
|||
636 |
687 |
p = iow[i]; |
|
637 |
687 |
q = alloc(sizeof(*p), ap); |
|
638 |
687 |
ior[i] = q; |
|
639 |
687 |
*q = *p; |
|
640 |
✓✓ | 687 |
if (p->name != NULL) |
641 |
644 |
q->name = wdcopy(p->name, ap); |
|
642 |
✓✓ | 687 |
if (p->delim != NULL) |
643 |
43 |
q->delim = wdcopy(p->delim, ap); |
|
644 |
✓✓ | 687 |
if (p->heredoc != NULL) |
645 |
43 |
q->heredoc = str_save(p->heredoc, ap); |
|
646 |
} |
||
647 |
644 |
ior[i] = NULL; |
|
648 |
|||
649 |
644 |
return ior; |
|
650 |
} |
||
651 |
|||
652 |
/* |
||
653 |
* free tree (for function definition) |
||
654 |
*/ |
||
655 |
|||
656 |
void |
||
657 |
tfree(struct op *t, Area *ap) |
||
658 |
46 |
{ |
|
659 |
char **w; |
||
660 |
|||
661 |
✓✓ | 46 |
if (t == NULL) |
662 |
26 |
return; |
|
663 |
|||
664 |
20 |
afree(t->str, ap); |
|
665 |
|||
666 |
✓✓ | 20 |
if (t->vars != NULL) { |
667 |
✗✓ | 8 |
for (w = t->vars; *w != NULL; w++) |
668 |
afree(*w, ap); |
||
669 |
8 |
afree(t->vars, ap); |
|
670 |
} |
||
671 |
|||
672 |
✓✓ | 20 |
if (t->args != NULL) { |
673 |
✓✓ | 16 |
for (w = t->args; *w != NULL; w++) |
674 |
8 |
afree(*w, ap); |
|
675 |
8 |
afree(t->args, ap); |
|
676 |
} |
||
677 |
|||
678 |
✓✓ | 20 |
if (t->ioact != NULL) |
679 |
8 |
iofree(t->ioact, ap); |
|
680 |
|||
681 |
20 |
tfree(t->left, ap); |
|
682 |
20 |
tfree(t->right, ap); |
|
683 |
|||
684 |
20 |
afree(t, ap); |
|
685 |
} |
||
686 |
|||
687 |
static void |
||
688 |
iofree(struct ioword **iow, Area *ap) |
||
689 |
8 |
{ |
|
690 |
struct ioword **iop; |
||
691 |
struct ioword *p; |
||
692 |
|||
693 |
✓✓ | 24 |
for (iop = iow; (p = *iop++) != NULL; ) { |
694 |
8 |
afree(p->name, ap); |
|
695 |
8 |
afree(p->delim, ap); |
|
696 |
8 |
afree(p->heredoc, ap); |
|
697 |
8 |
afree(p, ap); |
|
698 |
} |
||
699 |
8 |
afree(iow, ap); |
|
700 |
8 |
} |
Generated by: GCOVR (Version 3.3) |