GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/ksh/tree.c Lines: 282 366 77.0 %
Date: 2017-11-13 Branches: 169 252 67.1 %

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
}