GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/ksh/tree.c Lines: 292 367 79.6 %
Date: 2017-11-07 Branches: 176 252 69.8 %

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
17199226
	struct op *t1;
32
33
 Chain:
34
10772838
	if (t == NULL)
35
100
		return;
36





10772738
	switch (t->type) {
37
	case TCOM:
38
8443369
		if (t->vars)
39
17477944
			for (w = t->vars; *w != NULL; )
40
295603
				fptreef(shf, indent, "%S ", *w++);
41
		else
42
			fptreef(shf, indent, "#no-vars# ");
43
8443369
		if (t->args)
44
61333304
			for (w = t->args; *w != NULL; )
45
22223283
				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
1041065
		t = t->left;
67
1041065
		goto Chain;
68
#endif
69
	case TPAREN:
70
48544
		fptreef(shf, indent + 2, "( %T) ", t->left);
71
48544
		break;
72
	case TPIPE:
73
453002
		fptreef(shf, indent, "%T| ", t->left);
74
453002
		t = t->right;
75
453002
		goto Chain;
76
	case TLIST:
77
679158
		fptreef(shf, indent, "%T%;", t->left);
78
679158
		t = t->right;
79
679158
		goto Chain;
80
	case TOR:
81
	case TAND:
82
58227
		fptreef(shf, indent, "%T%s %T",
83
58227
		    t->left, (t->type==TOR) ? "||" : "&&", t->right);
84
58227
		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
180
		if (t->type == TFOR)
104
180
			fptreef(shf, indent, "for %s ", t->str);
105
180
		if (t->vars != NULL) {
106
180
			fptreef(shf, indent, "in ");
107
2736
			for (w = t->vars; *w; )
108
1188
				fptreef(shf, indent, "%S ", *w++);
109
180
			fptreef(shf, indent, "%;");
110
180
		}
111
180
		fptreef(shf, indent + INDENT, "do%N%T", t->left);
112
180
		fptreef(shf, indent, "%;done ");
113
180
		break;
114
	case TCASE:
115
45044
		fptreef(shf, indent, "case %S in", t->str);
116
269682
		for (t1 = t->left; t1 != NULL; t1 = t1->right) {
117
89797
			fptreef(shf, indent, "%N(");
118
537610
			for (w = t1->vars; *w != NULL; w++)
119
179008
				fptreef(shf, indent, "%S%c", *w,
120
179008
				    (w[1] != NULL) ? '|' : ')');
121
89797
			fptreef(shf, indent + INDENT, "%;%T%N;;", t1->left);
122
		}
123
45044
		fptreef(shf, indent, "%Nesac ");
124
45044
		break;
125
	case TIF:
126
	case TELIF:
127
		/* 3 == strlen("if ") */
128
464
		fptreef(shf, indent + 3, "if %T", t->left);
129
464
		for (;;) {
130
464
			t = t->right;
131
464
			if (t->left != NULL) {
132
464
				fptreef(shf, indent, "%;");
133
928
				fptreef(shf, indent + INDENT, "then%N%T",
134
464
				    t->left);
135
464
			}
136

737
			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
464
		if (t->right != NULL) {
144
273
			fptreef(shf, indent, "%;");
145
273
			fptreef(shf, indent + INDENT, "else%;%T", t->right);
146
273
		}
147
464
		fptreef(shf, indent, "%;fi ");
148
464
		break;
149
	case TWHILE:
150
	case TUNTIL:
151
		/* 6 == strlen("while"/"until") */
152
418
		fptreef(shf, indent + 6, "%s %T",
153
209
		    (t->type==TWHILE) ? "while" : "until",
154
209
		    t->left);
155
209
		fptreef(shf, indent, "%;do");
156
209
		fptreef(shf, indent + INDENT, "%;%T", t->right);
157
209
		fptreef(shf, indent, "%;done ");
158
209
		break;
159
	case TBRACE:
160
3021
		fptreef(shf, indent + INDENT, "{%;%T", t->left);
161
3021
		fptreef(shf, indent, "%;} ");
162
3021
		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
455
		fptreef(shf, indent,
171
455
		    t->u.ksh_func ? "function %s %T" : "%s() %T",
172
455
		    t->str, t->left);
173
455
		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
8599513
	if ((ioact = t->ioact) != NULL) {
182
		int	need_nl = 0;
183
184
3851686
		while (*ioact != NULL)
185
1116436
			pioact(shf, indent, *ioact++);
186
		/* Print here documents after everything else... */
187
3851686
		for (ioact = t->ioact; *ioact != NULL; ) {
188
1116436
			struct ioword *iop = *ioact++;
189
190
			/* heredoc is 0 when tracing (set -x) */
191

1319415
			if ((iop->flag & IOTYPE) == IOHERE && iop->heredoc) {
192
202979
				tputc('\n', shf);
193
202979
				shf_puts(iop->heredoc, shf);
194
202979
				fptreef(shf, indent, "%s",
195
202979
				    evalstr(iop->delim, 0));
196
				need_nl = 1;
197
202979
			}
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
809407
		if (need_nl)
204
202954
			tputc('\n', shf);
205
809407
	}
206
17199126
}
207
208
static void
209
pioact(struct shf *shf, int indent, struct ioword *iop)
210
{
211
2233428
	int flag = iop->flag;
212
1116714
	int type = flag & IOTYPE;
213
	int expected;
214
215
2233428
	expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0 :
216
884146
	    (type == IOCAT || type == IOWRITE) ? 1 :
217

1145796
	    (type == IODUP && (iop->unit == !(flag & IORDUP))) ? iop->unit :
218
314767
	    iop->unit + 1;
219
1116714
	if (iop->unit != expected)
220
386703
		tputc('0' + iop->unit, shf);
221
222

2233428
	switch (type) {
223
	case IOREAD:
224
29561
		fptreef(shf, indent, "< ");
225
29561
		break;
226
	case IOHERE:
227
203007
		if (flag&IOSKIP)
228
650
			fptreef(shf, indent, "<<- ");
229
		else
230
202357
			fptreef(shf, indent, "<< ");
231
		break;
232
	case IOCAT:
233
135426
		fptreef(shf, indent, ">> ");
234
135426
		break;
235
	case IOWRITE:
236
366788
		if (flag&IOCLOB)
237
			fptreef(shf, indent, ">| ");
238
		else
239
366788
			fptreef(shf, indent, "> ");
240
		break;
241
	case IORDWR:
242
		fptreef(shf, indent, "<> ");
243
		break;
244
	case IODUP:
245
381932
		if (flag & IORDUP)
246
			fptreef(shf, indent, "<&");
247
		else
248
381932
			fptreef(shf, indent, ">&");
249
		break;
250
	}
251
	/* name/delim are 0 when printing syntax errors */
252
1116714
	if (type == IOHERE) {
253
203007
		if (iop->delim)
254
203007
			fptreef(shf, indent, "%S ", iop->delim);
255
913707
	} else if (iop->name)
256
913707
		fptreef(shf, indent, (iop->flag & IONAMEXP) ? "%s " : "%S ",
257
		    iop->name);
258
1116714
}
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
250054564
	if ((c&0x60) == 0) {		/* C0|C1 */
269
636239
		tputc((c&0x80) ? '$' : '^', shf);
270
636239
		tputc(((c&0x7F)|0x40), shf);
271
125027282
	} else if ((c&0x7F) == 0x7F) {	/* DEL */
272
		tputc((c&0x80) ? '$' : '^', shf);
273
		tputc('?', shf);
274
	} else
275
124391043
		tputc(c, shf);
276
125027282
}
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
47721780
	while (1)
291



283505513
		switch ((c = *wp++)) {
292
		case EOS:
293
			return;
294
		case CHAR:
295
88957887
			tputC(*wp++, shf);
296
88957887
			break;
297
		case QCHAR:
298
7569037
			c = *wp++;
299
7569037
			if (!quoted || (c == '"' || c == '`' || c == '$'))
300
619697
				tputc('\\', shf);
301
7569037
			tputC(c, shf);
302
7569037
			break;
303
		case COMSUB:
304
38759
			tputc('$', shf);
305
38759
			tputc('(', shf);
306
3087158
			while (*wp != 0)
307
1504820
				tputC(*wp++, shf);
308
38759
			tputc(')', shf);
309
38759
			wp++;
310
38759
			break;
311
		case EXPRSUB:
312
24
			tputc('$', shf);
313
24
			tputc('(', shf);
314
24
			tputc('(', shf);
315
500
			while (*wp != 0)
316
226
				tputC(*wp++, shf);
317
24
			tputc(')', shf);
318
24
			tputc(')', shf);
319
24
			wp++;
320
24
			break;
321
		case OQUOTE:
322
			quoted = 1;
323
4209000
			tputc('"', shf);
324
4209000
			break;
325
		case CQUOTE:
326
			quoted = 0;
327
4209000
			tputc('"', shf);
328
4209000
			break;
329
		case OSUBST:
330
6503647
			tputc('$', shf);
331
6503647
			if (*wp++ == '{')
332
349723
				tputc('{', shf);
333
60494271
			while ((c = *wp++) != 0)
334
26995312
				tputC(c, shf);
335
			break;
336
		case CSUBST:
337
6503672
			if (*wp++ == '}')
338
349748
				tputc('}', shf);
339
			break;
340
		case OPAT:
341
25
			tputc(*wp++, shf);
342
25
			tputc('(', shf);
343
25
			break;
344
		case SPAT:
345
			tputc('|', shf);
346
			break;
347
		case CPAT:
348
25
			tputc(')', shf);
349
25
			break;
350
		}
351
23860890
}
352
353
void
354
fptreef(struct shf *shf, int indent, const char *fmt, ...)
355
{
356
53309474
  va_list	va;
357
358
26654737
  va_start(va, fmt);
359
26654737
  vfptreef(shf, indent, fmt, va);
360
26654737
  va_end(va);
361
26654737
}
362
363
char *
364
snptreef(char *s, int n, const char *fmt, ...)
365
{
366
14415922
  va_list va;
367
7207961
  struct shf shf;
368
369
7207961
  shf_sopen(s, n, SHF_WR | (s ? 0 : SHF_DYNAMIC), &shf);
370
371
7207961
  va_start(va, fmt);
372
7207961
  vfptreef(&shf, 0, fmt, va);
373
7207961
  va_end(va);
374
375
14415922
  return shf_sclose(&shf); /* null terminates */
376
7207961
}
377
378
static void
379
vfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
380
{
381
	int c;
382
383
163736124
	while ((c = *fmt++)) {
384
62148030
		if (c == '%') {
385
			long n;
386
			char *p;
387
			int neg;
388
389


33904829
			switch ((c = *fmt++)) {
390
			case 'c':
391
537024
				tputc(va_arg(va, int), shf);
392
179008
				break;
393
			case 's':
394
786900
				p = va_arg(va, char *);
395
3185092
				while (*p)
396
1330246
					tputc(*p++, shf);
397
				break;
398
			case 'S':	/* word */
399
71582670
				p = va_arg(va, char *);
400
23860890
				tputS(p, shf);
401
23860890
				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
25798839
				ptree(va_arg(va, struct op *), indent, shf);
414
8599613
				break;
415
			case ';':	/* newline or ; */
416
			case 'N':	/* newline or space */
417
1002740
				if (shf->flags & SHF_STRING) {
418
1002740
					if (c == ';')
419
777458
						tputc(';', shf);
420
1002740
					tputc(' ', shf);
421
1002740
				} 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
834
				pioact(shf, indent, va_arg(va, struct ioword *));
433
278
				break;
434
			default:
435
				tputc(c, shf);
436
				break;
437
			}
438
33904829
		} else
439
28243201
			tputc(c, shf);
440
	}
441
33862698
}
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
12311344
	if (t == NULL)
454
3119337
		return NULL;
455
456
3036335
	r = alloc(sizeof(struct op), ap);
457
458
3036335
	r->type = t->type;
459
3036335
	r->u.evalflags = t->u.evalflags;
460
461
9109005
	r->str = t->type == TCASE ? wdcopy(t->str, ap) : str_save(t->str, ap);
462
463
3036335
	if (t->vars == NULL)
464
1550820
		r->vars = NULL;
465
	else {
466
3261611
		for (tw = t->vars; *tw++ != NULL; )
467
			;
468
1485515
		rw = r->vars = areallocarray(NULL, tw - t->vars + 1,
469
		    sizeof(*tw), ap);
470
3552192
		for (tw = t->vars; *tw != NULL; )
471
290581
			*rw++ = wdcopy(*tw++, ap);
472
1485515
		*rw = NULL;
473
	}
474
475
3036335
	if (t->args == NULL)
476
1583079
		r->args = NULL;
477
	else {
478
6313583
		for (tw = t->args; *tw++ != NULL; )
479
			;
480
1453256
		rw = r->args = areallocarray(NULL, tw - t->args + 1,
481
		    sizeof(*tw), ap);
482
9720654
		for (tw = t->args; *tw != NULL; )
483
3407071
			*rw++ = wdcopy(*tw++, ap);
484
1453256
		*rw = NULL;
485
	}
486
487
6192663
	r->ioact = (t->ioact == NULL) ? NULL : iocopy(t->ioact, ap);
488
489
3036335
	r->left = tcopy(t->left, ap);
490
3036335
	r->right = tcopy(t->right, ap);
491
3036335
	r->lineno = t->lineno;
492
493
3036335
	return r;
494
6155672
}
495
496
char *
497
wdcopy(const char *wp, Area *ap)
498
{
499
7708506
	size_t len = wdscan(wp, EOS) - wp;
500
3854253
	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
42541334
	while (1)
510



91846489
		switch (*wp++) {
511
		case EOS:
512
3854528
			return (char *) wp;
513
		case CHAR:
514
		case QCHAR:
515
19480660
			wp++;
516
19480660
			break;
517
		case COMSUB:
518
		case EXPRSUB:
519
2997017
			while (*wp++ != 0)
520
				;
521
			break;
522
		case OQUOTE:
523
		case CQUOTE:
524
			break;
525
		case OSUBST:
526
1376221
			nest++;
527
10742392
			while (*wp++ != '\0')
528
				;
529
			break;
530
		case CSUBST:
531
18792360
			wp++;
532
18792360
			if (c == CSUBST && nest == 0)
533
17416139
				return (char *) wp;
534
1376221
			nest--;
535
1376221
			break;
536
		case OPAT:
537
5845
			nest++;
538
5845
			wp++;
539
5845
			break;
540
		case SPAT:
541
		case CPAT:
542
9121
			if (c == wp[-1] && nest == 0)
543
				return (char *) wp;
544
9121
			if (wp[-1] == CPAT)
545
5845
				nest--;
546
			break;
547
		default:
548
			internal_errorf(0,
549
			    "wdscan: unknown char 0x%x (carrying on)",
550
			    wp[-1]);
551
		}
552
21270667
}
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
168540
	struct shf shf;
562
	int c;
563
564
84270
	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
84270
	while (1)
572


1635209
		switch ((c = *wp++)) {
573
		case EOS:
574
168540
			return shf_sclose(&shf); /* null terminates */
575
		case CHAR:
576
		case QCHAR:
577
747643
			shf_putchar(*wp++, &shf);
578
747643
			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
84270
}
622
623
static	struct ioword **
624
iocopy(struct ioword **iow, Area *ap)
625
{
626
	struct ioword **ior;
627
	int i;
628
629
505982
	for (ior = iow; *ior++ != NULL; )
630
		;
631
119993
	ior = areallocarray(NULL, ior - iow + 1, sizeof(*ior), ap);
632
633
531992
	for (i = 0; iow[i] != NULL; i++) {
634
		struct ioword *p, *q;
635
636
		p = iow[i];
637
146003
		q = alloc(sizeof(*p), ap);
638
146003
		ior[i] = q;
639
146003
		*q = *p;
640
146003
		if (p->name != NULL)
641
134933
			q->name = wdcopy(p->name, ap);
642
146003
		if (p->delim != NULL)
643
11070
			q->delim = wdcopy(p->delim, ap);
644
146003
		if (p->heredoc != NULL)
645
11070
			q->heredoc = str_save(p->heredoc, ap);
646
	}
647
119993
	ior[i] = NULL;
648
649
119993
	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
1220
	if (t == NULL)
662
346
		return;
663
664
264
	afree(t->str, ap);
665
666
264
	if (t->vars != NULL) {
667
214
		for (w = t->vars; *w != NULL; w++)
668
			afree(*w, ap);
669
107
		afree(t->vars, ap);
670
107
	}
671
672
264
	if (t->args != NULL) {
673
498
		for (w = t->args; *w != NULL; w++)
674
142
			afree(*w, ap);
675
107
		afree(t->args, ap);
676
107
	}
677
678
264
	if (t->ioact != NULL)
679
100
		iofree(t->ioact, ap);
680
681
264
	tfree(t->left, ap);
682
264
	tfree(t->right, ap);
683
684
264
	afree(t, ap);
685
874
}
686
687
static	void
688
iofree(struct ioword **iow, Area *ap)
689
{
690
	struct ioword **iop;
691
	struct ioword *p;
692
693
500
	for (iop = iow; (p = *iop++) != NULL; ) {
694
100
		afree(p->name, ap);
695
100
		afree(p->delim, ap);
696
100
		afree(p->heredoc, ap);
697
100
		afree(p, ap);
698
	}
699
100
	afree(iow, ap);
700
100
}