tell openssl to look for the ca-bundle.crt in our common location
[AROS-Contrib.git] / gnu / abc-shell / tree.c
blob509a839e6fdba7124e9a47a7c5ed523bf61bf436
1 /*
2 * command tree climbing
3 */
5 #include "sh.h"
7 #define INDENT 4
9 #define tputc(c, shf) shf_putchar(c, shf);
10 static void ptree(struct op *, int, struct shf *);
11 static void pioact(struct shf *, int, struct ioword *);
12 static void tputC(int, struct shf *);
13 static void tputS(char *, struct shf *);
14 static void vfptreef(struct shf *, int, const char *, va_list);
15 static struct ioword **iocopy(struct ioword **, Area *);
16 static void iofree(struct ioword **, Area *);
19 * print a command tree
22 static void
23 ptree(struct op *t, int indent, struct shf *shf)
25 char **w;
26 struct ioword **ioact;
27 struct op *t1;
29 Chain:
30 if (t == NULL)
31 return;
32 switch (t->type) {
33 case TCOM:
34 if (t->vars)
35 for (w = t->vars; *w != NULL; )
36 fptreef(shf, indent, "%S ", *w++);
37 else
38 fptreef(shf, indent, "#no-vars# ");
39 if (t->args)
40 for (w = t->args; *w != NULL; )
41 fptreef(shf, indent, "%S ", *w++);
42 else
43 fptreef(shf, indent, "#no-args# ");
44 break;
45 case TEXEC:
46 #if 0 /* ?not useful - can't be called? */
47 /* Print original vars */
48 if (t->left->vars)
49 for (w = t->left->vars; *w != NULL; )
50 fptreef(shf, indent, "%S ", *w++);
51 else
52 fptreef(shf, indent, "#no-vars# ");
53 /* Print expanded vars */
54 if (t->args)
55 for (w = t->args; *w != NULL; )
56 fptreef(shf, indent, "%s ", *w++);
57 else
58 fptreef(shf, indent, "#no-args# ");
59 /* Print original io */
60 t = t->left;
61 #else
62 t = t->left;
63 goto Chain;
64 #endif
65 case TPAREN:
66 fptreef(shf, indent + 2, "( %T) ", t->left);
67 break;
68 case TPIPE:
69 fptreef(shf, indent, "%T| ", t->left);
70 t = t->right;
71 goto Chain;
72 case TLIST:
73 fptreef(shf, indent, "%T%;", t->left);
74 t = t->right;
75 goto Chain;
76 case TOR:
77 case TAND:
78 fptreef(shf, indent, "%T%s %T",
79 t->left, (t->type==TOR) ? "||" : "&&", t->right);
80 break;
81 case TBANG:
82 fptreef(shf, indent, "! ");
83 t = t->right;
84 goto Chain;
85 case TDBRACKET:
87 int i;
89 fptreef(shf, indent, "[[");
90 for (i = 0; t->args[i]; i++)
91 fptreef(shf, indent, " %S", t->args[i]);
92 fptreef(shf, indent, " ]] ");
93 break;
95 case TSELECT:
96 fptreef(shf, indent, "select %s ", t->str);
97 /* FALLTHROUGH */
98 case TFOR:
99 if (t->type == TFOR)
100 fptreef(shf, indent, "for %s ", t->str);
101 if (t->vars != NULL) {
102 fptreef(shf, indent, "in ");
103 for (w = t->vars; *w; )
104 fptreef(shf, indent, "%S ", *w++);
105 fptreef(shf, indent, "%;");
107 fptreef(shf, indent + INDENT, "do%N%T", t->left);
108 fptreef(shf, indent, "%;done ");
109 break;
110 case TCASE:
111 fptreef(shf, indent, "case %S in", t->str);
112 for (t1 = t->left; t1 != NULL; t1 = t1->right) {
113 fptreef(shf, indent, "%N(");
114 for (w = t1->vars; *w != NULL; w++)
115 fptreef(shf, indent, "%S%c", *w,
116 (w[1] != NULL) ? '|' : ')');
117 fptreef(shf, indent + INDENT, "%;%T%N;;", t1->left);
119 fptreef(shf, indent, "%Nesac ");
120 break;
121 case TIF:
122 case TELIF:
123 /* 3 == strlen("if ") */
124 fptreef(shf, indent + 3, "if %T", t->left);
125 for (;;) {
126 t = t->right;
127 if (t->left != NULL) {
128 fptreef(shf, indent, "%;");
129 fptreef(shf, indent + INDENT, "then%N%T",
130 t->left);
132 if (t->right == NULL || t->right->type != TELIF)
133 break;
134 t = t->right;
135 fptreef(shf, indent, "%;");
136 /* 5 == strlen("elif ") */
137 fptreef(shf, indent + 5, "elif %T", t->left);
139 if (t->right != NULL) {
140 fptreef(shf, indent, "%;");
141 fptreef(shf, indent + INDENT, "else%;%T", t->right);
143 fptreef(shf, indent, "%;fi ");
144 break;
145 case TWHILE:
146 case TUNTIL:
147 /* 6 == strlen("while"/"until") */
148 fptreef(shf, indent + 6, "%s %T",
149 (t->type==TWHILE) ? "while" : "until",
150 t->left);
151 fptreef(shf, indent, "%;do");
152 fptreef(shf, indent + INDENT, "%;%T", t->right);
153 fptreef(shf, indent, "%;done ");
154 break;
155 case TBRACE:
156 fptreef(shf, indent + INDENT, "{%;%T", t->left);
157 fptreef(shf, indent, "%;} ");
158 break;
159 case TCOPROC:
160 fptreef(shf, indent, "%T|& ", t->left);
161 break;
162 case TASYNC:
163 fptreef(shf, indent, "%T& ", t->left);
164 break;
165 case TFUNCT:
166 fptreef(shf, indent,
167 t->u.ksh_func ? "function %s %T" : "%s() %T",
168 t->str, t->left);
169 break;
170 case TTIME:
171 fptreef(shf, indent, "time %T", t->left);
172 break;
173 default:
174 fptreef(shf, indent, "<botch>");
175 break;
177 if ((ioact = t->ioact) != NULL) {
178 int need_nl = 0;
180 while (*ioact != NULL)
181 pioact(shf, indent, *ioact++);
182 /* Print here documents after everything else... */
183 for (ioact = t->ioact; *ioact != NULL; ) {
184 struct ioword *iop = *ioact++;
186 /* heredoc is 0 when tracing (set -x) */
187 if ((iop->flag & IOTYPE) == IOHERE && iop->heredoc) {
188 tputc('\n', shf);
189 shf_puts(iop->heredoc, shf);
190 fptreef(shf, indent, "%s",
191 evalstr(iop->delim, 0));
192 need_nl = 1;
195 /* Last delimiter must be followed by a newline (this often
196 * leads to an extra blank line, but its not worth worrying
197 * about)
199 if (need_nl)
200 tputc('\n', shf);
204 static void
205 pioact(struct shf *shf, int indent, struct ioword *iop)
207 int flag = iop->flag;
208 int type = flag & IOTYPE;
209 int expected;
211 expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0
212 : (type == IOCAT || type == IOWRITE) ? 1
213 : (type == IODUP && (iop->unit == !(flag & IORDUP))) ?
214 iop->unit
215 : iop->unit + 1;
216 if (iop->unit != expected)
217 tputc('0' + iop->unit, shf);
219 switch (type) {
220 case IOREAD:
221 fptreef(shf, indent, "< ");
222 break;
223 case IOHERE:
224 if (flag&IOSKIP)
225 fptreef(shf, indent, "<<- ");
226 else
227 fptreef(shf, indent, "<< ");
228 break;
229 case IOCAT:
230 fptreef(shf, indent, ">> ");
231 break;
232 case IOWRITE:
233 if (flag&IOCLOB)
234 fptreef(shf, indent, ">| ");
235 else
236 fptreef(shf, indent, "> ");
237 break;
238 case IORDWR:
239 fptreef(shf, indent, "<> ");
240 break;
241 case IODUP:
242 if (flag & IORDUP)
243 fptreef(shf, indent, "<&");
244 else
245 fptreef(shf, indent, ">&");
246 break;
248 /* name/delim are 0 when printing syntax errors */
249 if (type == IOHERE) {
250 if (iop->delim)
251 fptreef(shf, indent, "%S ", iop->delim);
252 } else if (iop->name)
253 fptreef(shf, indent, (iop->flag & IONAMEXP) ? "%s " : "%S ",
254 iop->name);
259 * variants of fputc, fputs for ptreef and snptreef
262 static void
263 tputC(int c, struct shf *shf)
265 if ((c&0x60) == 0) { /* C0|C1 */
266 tputc((c&0x80) ? '$' : '^', shf);
267 tputc(((c&0x7F)|0x40), shf);
268 } else if ((c&0x7F) == 0x7F) { /* DEL */
269 tputc((c&0x80) ? '$' : '^', shf);
270 tputc('?', shf);
271 } else
272 tputc(c, shf);
275 static void
276 tputS(char *wp, struct shf *shf)
278 int c, quoted=0;
280 /* problems:
281 * `...` -> $(...)
282 * 'foo' -> "foo"
283 * could change encoding to:
284 * OQUOTE ["'] ... CQUOTE ["']
285 * COMSUB [(`] ...\0 (handle $ ` \ and maybe " in `...` case)
287 while (1)
288 switch ((c = *wp++)) {
289 case EOS:
290 return;
291 case CHAR:
292 tputC(*wp++, shf);
293 break;
294 case QCHAR:
295 c = *wp++;
296 if (!quoted || (c == '"' || c == '`' || c == '$'))
297 tputc('\\', shf);
298 tputC(c, shf);
299 break;
300 case COMSUB:
301 tputc('$', shf);
302 tputc('(', shf);
303 while (*wp != 0)
304 tputC(*wp++, shf);
305 tputc(')', shf);
306 wp++;
307 break;
308 case EXPRSUB:
309 tputc('$', shf);
310 tputc('(', shf);
311 tputc('(', shf);
312 while (*wp != 0)
313 tputC(*wp++, shf);
314 tputc(')', shf);
315 tputc(')', shf);
316 wp++;
317 break;
318 case OQUOTE:
319 quoted = 1;
320 tputc('"', shf);
321 break;
322 case CQUOTE:
323 quoted = 0;
324 tputc('"', shf);
325 break;
326 case OSUBST:
327 tputc('$', shf);
328 if (*wp++ == '{')
329 tputc('{', shf);
330 while ((c = *wp++) != 0)
331 tputC(c, shf);
332 break;
333 case CSUBST:
334 if (*wp++ == '}')
335 tputc('}', shf);
336 break;
337 case OPAT:
338 tputc(*wp++, shf);
339 tputc('(', shf);
340 break;
341 case SPAT:
342 tputc('|', shf);
343 break;
344 case CPAT:
345 tputc(')', shf);
346 break;
351 * this is the _only_ way to reliably handle
352 * variable args with an ANSI compiler
354 /* VARARGS */
356 fptreef(struct shf *shf, int indent, const char *fmt, ...)
358 va_list va;
360 va_start(va, fmt);
362 vfptreef(shf, indent, fmt, va);
363 va_end(va);
364 return 0;
367 /* VARARGS */
368 char *
369 snptreef(char *s, int n, const char *fmt, ...)
371 va_list va;
372 struct shf shf;
374 shf_sopen(s, n, SHF_WR | (s ? 0 : SHF_DYNAMIC), &shf);
376 va_start(va, fmt);
377 vfptreef(&shf, 0, fmt, va);
378 va_end(va);
380 return shf_sclose(&shf); /* null terminates */
383 static void
384 vfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
386 int c;
388 while ((c = *fmt++))
389 if (c == '%') {
390 long n;
391 char *p;
392 int neg;
394 switch ((c = *fmt++)) {
395 case 'c':
396 tputc(va_arg(va, int), shf);
397 break;
398 case 's':
399 p = va_arg(va, char *);
400 while (*p)
401 tputc(*p++, shf);
402 break;
403 case 'S': /* word */
404 p = va_arg(va, char *);
405 tputS(p, shf);
406 break;
407 case 'd': case 'u': /* decimal */
408 n = (c == 'd') ? va_arg(va, int)
409 : va_arg(va, unsigned int);
410 neg = c=='d' && n<0;
411 p = ulton((neg) ? -n : n, 10);
412 if (neg)
413 *--p = '-';
414 while (*p)
415 tputc(*p++, shf);
416 break;
417 case 'T': /* format tree */
418 ptree(va_arg(va, struct op *), indent, shf);
419 break;
420 case ';': /* newline or ; */
421 case 'N': /* newline or space */
422 if (shf->flags & SHF_STRING) {
423 if (c == ';')
424 tputc(';', shf);
425 tputc(' ', shf);
426 } else {
427 int i;
429 tputc('\n', shf);
430 for (i = indent; i >= 8; i -= 8)
431 tputc('\t', shf);
432 for (; i > 0; --i)
433 tputc(' ', shf);
435 break;
436 case 'R':
437 pioact(shf, indent, va_arg(va, struct ioword *));
438 break;
439 default:
440 tputc(c, shf);
441 break;
443 } else
444 tputc(c, shf);
448 * copy tree (for function definition)
451 struct op *
452 tcopy(struct op *t, Area *ap)
454 struct op *r;
455 char **tw, **rw;
457 if (t == NULL)
458 return NULL;
460 r = (struct op *) alloc(sizeof(struct op), ap);
462 r->type = t->type;
463 r->u.evalflags = t->u.evalflags;
465 fflush(stdout);
466 r->str = t->type == TCASE ? wdcopy(t->str, ap) : str_save(t->str, ap);
468 if (t->vars == NULL)
469 r->vars = NULL;
470 else {
471 for (tw = t->vars; *tw++ != NULL; )
473 rw = r->vars = (char **)
474 alloc((tw - t->vars + 1) * sizeof(*tw), ap);
475 for (tw = t->vars; *tw != NULL; )
476 *rw++ = wdcopy(*tw++, ap);
477 *rw = NULL;
480 if (t->args == NULL)
481 r->args = NULL;
482 else {
483 for (tw = t->args; *tw++ != NULL; )
485 rw = r->args = (char **)
486 alloc((tw - t->args + 1) * sizeof(*tw), ap);
487 for (tw = t->args; *tw != NULL; )
488 *rw++ = wdcopy(*tw++, ap);
489 *rw = NULL;
492 r->ioact = (t->ioact == NULL) ? NULL : iocopy(t->ioact, ap);
494 r->left = tcopy(t->left, ap);
495 r->right = tcopy(t->right, ap);
496 r->lineno = t->lineno;
498 return r;
501 char *
502 wdcopy(const char *wp, Area *ap)
504 size_t len = wdscan(wp, EOS) - wp;
505 return memcpy(alloc(len, ap), wp, len);
508 /* return the position of prefix c in wp plus 1 */
509 char *
510 wdscan(const char *wp, int c)
512 int nest = 0;
514 while (1)
515 switch (*wp++) {
516 case EOS:
517 return (char *) wp;
518 case CHAR:
519 case QCHAR:
520 wp++;
521 break;
522 case COMSUB:
523 case EXPRSUB:
524 while (*wp++ != 0)
526 break;
527 case OQUOTE:
528 case CQUOTE:
529 break;
530 case OSUBST:
531 nest++;
532 while (*wp++ != '\0')
534 break;
535 case CSUBST:
536 wp++;
537 if (c == CSUBST && nest == 0)
538 return (char *) wp;
539 nest--;
540 break;
541 case OPAT:
542 nest++;
543 wp++;
544 break;
545 case SPAT:
546 case CPAT:
547 if (c == wp[-1] && nest == 0)
548 return (char *) wp;
549 if (wp[-1] == CPAT)
550 nest--;
551 break;
552 default:
553 /* removed bogus error message */
554 break;
558 /* return a copy of wp without any of the mark up characters and
559 * with quote characters (" ' \) stripped.
560 * (string is allocated from ATEMP)
562 char *
563 wdstrip(const char *wp)
565 struct shf shf;
566 int c;
568 shf_sopen((char *) 0, 32, SHF_WR | SHF_DYNAMIC, &shf);
570 /* problems:
571 * `...` -> $(...)
572 * x${foo:-"hi"} -> x${foo:-hi}
573 * x${foo:-'hi'} -> x${foo:-hi}
575 while (1)
576 switch ((c = *wp++)) {
577 case EOS:
578 return shf_sclose(&shf); /* null terminates */
579 case CHAR:
580 case QCHAR:
581 shf_putchar(*wp++, &shf);
582 break;
583 case COMSUB:
584 shf_putchar('$', &shf);
585 shf_putchar('(', &shf);
586 while (*wp != 0)
587 shf_putchar(*wp++, &shf);
588 shf_putchar(')', &shf);
589 break;
590 case EXPRSUB:
591 shf_putchar('$', &shf);
592 shf_putchar('(', &shf);
593 shf_putchar('(', &shf);
594 while (*wp != 0)
595 shf_putchar(*wp++, &shf);
596 shf_putchar(')', &shf);
597 shf_putchar(')', &shf);
598 break;
599 case OQUOTE:
600 break;
601 case CQUOTE:
602 break;
603 case OSUBST:
604 shf_putchar('$', &shf);
605 if (*wp++ == '{')
606 shf_putchar('{', &shf);
607 while ((c = *wp++) != 0)
608 shf_putchar(c, &shf);
609 break;
610 case CSUBST:
611 if (*wp++ == '}')
612 shf_putchar('}', &shf);
613 break;
614 case OPAT:
615 shf_putchar(*wp++, &shf);
616 shf_putchar('(', &shf);
617 break;
618 case SPAT:
619 shf_putchar('|', &shf);
620 break;
621 case CPAT:
622 shf_putchar(')', &shf);
623 break;
627 static struct ioword **
628 iocopy(struct ioword **iow, Area *ap)
630 struct ioword **ior;
631 int i;
633 for (ior = iow; *ior++ != NULL; )
635 ior = (struct ioword **) alloc((ior - iow + 1) * sizeof(*ior), ap);
637 for (i = 0; iow[i] != NULL; i++) {
638 struct ioword *p, *q;
640 p = iow[i];
641 q = (struct ioword *) alloc(sizeof(*p), ap);
642 ior[i] = q;
643 *q = *p;
644 if (p->name != (char *) 0)
645 q->name = wdcopy(p->name, ap);
646 if (p->delim != (char *) 0)
647 q->delim = wdcopy(p->delim, ap);
648 if (p->heredoc != (char *) 0)
649 q->heredoc = str_save(p->heredoc, ap);
651 ior[i] = NULL;
653 return ior;
657 * free tree (for function definition)
660 void
661 tfree(struct op *t, Area *ap)
663 char **w;
665 if (t == NULL)
666 return;
668 if (t->str != NULL)
669 afree((void*)t->str, ap);
671 if (t->vars != NULL) {
672 for (w = t->vars; *w != NULL; w++)
673 afree((void*)*w, ap);
674 afree((void*)t->vars, ap);
677 if (t->args != NULL) {
678 for (w = t->args; *w != NULL; w++)
679 afree((void*)*w, ap);
680 afree((void*)t->args, ap);
683 if (t->ioact != NULL)
684 iofree(t->ioact, ap);
686 tfree(t->left, ap);
687 tfree(t->right, ap);
689 afree((void*)t, ap);
692 static void
693 iofree(struct ioword **iow, Area *ap)
695 struct ioword **iop;
696 struct ioword *p;
698 for (iop = iow; (p = *iop++) != NULL; ) {
699 if (p->name != NULL)
700 afree((void*)p->name, ap);
701 if (p->delim != NULL)
702 afree((void*)p->delim, ap);
703 if (p->heredoc != NULL)
704 afree((void*)p->heredoc, ap);
705 afree((void*)p, ap);