|
|
1.1 root 1: /*
2: * command tree climbing
3: */
4:
5: static char *RCSid = "$Header: /newbits/usr/bin/korn/RCS/tree.c,v 1.2 91/08/01 12:41:25 bin Exp Locker: bin $";
6:
7: #include <stddef.h>
8: #include <stdlib.h>
9: #include <string.h>
10: #include <stdio.h>
11: #include <errno.h>
12: #include <setjmp.h>
13: #include <varargs.h>
14: #include "sh.h"
15: #include "tree.h"
16:
17: #define FSTRING (FILE*)NULL
18:
19: static int tputc ARGS((int c, FILE *f));
20: static void tputC ARGS((int c, FILE *f));
21: static void tputS ARGS((char *wp, FILE *f));
22:
23: /*
24: * print a command tree
25: */
26:
27: void
28: ptree(t, f)
29: register struct op *t;
30: register FILE *f;
31: {
32: register char **w;
33: struct ioword **ioact;
34: struct op *t1;
35:
36: Chain:
37: if (t == NULL)
38: return;
39: switch (t->type) {
40: case TCOM:
41: for (w = t->vars; *w != NULL; )
42: fptreef(f, "%S ", *w++);
43: for (w = t->args; *w != NULL; )
44: fptreef(f, "%S ", *w++);
45: break;
46: case TEXEC:
47: t = t->left;
48: goto Chain;
49: case TPAREN:
50: fptreef(f, "(%T)", t->left);
51: break;
52: case TPIPE:
53: fptreef(f, "%T | ", t->left);
54: t = t->right;
55: goto Chain;
56: case TLIST:
57: fptreef(f, "%T%;", t->left);
58: t = t->right;
59: goto Chain;
60: case TOR:
61: case TAND:
62: fptreef(f, "%T %s %T",
63: t->left, (t->type==TOR) ? "||" : "&&", t->right);
64: break;
65: case TFOR:
66: fptreef(f, "for %s ", t->str);
67: if (t->vars != NULL) {
68: fptreef(f, "in ");
69: for (w = t->vars; *w; )
70: fptreef(f, "%S ", *w++);
71: fptreef(f, "%;");
72: }
73: fptreef(f, "do %T%;done ", t->left);
74: break;
75: case TCASE:
76: fptreef(f, "case %S in%;", t->str);
77: for (t1 = t->left; t1 != NULL; t1 = t1->right) {
78: fptreef(f, "(");
79: for (w = t1->vars; *w != NULL; w++)
80: fptreef(f, "%S%c", *w, (w[1] != NULL) ? '|' : ')');
81: fptreef(f, " %T;;%;", t1->left);
82: }
83: fptreef(f, "esac ");
84: break;
85: case TIF:
86: fptreef(f, "if %T%;", t->left);
87: t = t->right;
88: if (t->left != NULL)
89: fptreef(f, "then %T%;", t->left);
90: if (t->right != NULL)
91: fptreef(f, "else %T%;", t->right);
92: fptreef(f, "fi ");
93: break;
94: case TWHILE:
95: case TUNTIL:
96: fptreef(f, "%s %T%;do %T%;done ",
97: (t->type==TWHILE) ? "while" : "until",
98: t->left, t->right);
99: break;
100: case TBRACE:
101: fptreef(f, "{%;%T%;} ", t->left);
102: break;
103: case TASYNC:
104: fptreef(f, "%T &", t->left);
105: break;
106: case TFUNCT:
107: fptreef(f, "function %s %T", t->str, t->left);
108: break;
109: case TTIME:
110: fptreef(f, "time %T", t->left);
111: break;
112: default:
113: fptreef(f, "<botch>");
114: break;
115: }
116: if ((ioact = t->ioact) != NULL)
117: while (*ioact != NULL)
118: pioact(f, *ioact++);
119: }
120:
121: /*
122: * print out a redirection node.
123: */
124: pioact(f, iop)
125: register FILE *f;
126: register struct ioword *iop;
127: {
128: char *redir = NULL;
129:
130: switch (iop->flag & (IOREAD|IOHERE|IOWRITE|IOCAT|IOXHERE|IODUP)) {
131: case IOREAD: redir = "<"; break;
132: case IOREAD|IOHERE: redir = "<<"; break;
133: case IOREAD|IODUP: redir = "<&"; break;
134: case IOWRITE: redir = ">"; break;
135: case IOWRITE|IOCAT: redir = ">>"; break;
136: case IOWRITE|IODUP: redir = ">&"; break;
137: case IOXHERE: redir = "<<"; break;
138: default: redir = ">?<"; break;
139: }
140: fptreef(f, "%c%s%S ", '0' + iop->unit, redir, iop->name);
141: }
142:
143:
144: /*
145: * variants of fputc, fputs for ptreef and snptreef
146: */
147:
148: static char *snpf_s; /* snptreef string */
149: static int snpf_n; /* snptreef length */
150:
151: static int
152: tputc(c, f)
153: int c;
154: register FILE *f;
155: {
156: if (f != NULL)
157: putc(c, f);
158: else
159: if (--snpf_n >= 0)
160: *snpf_s++ = c;
161: return c;
162: }
163:
164: static void
165: tputC(c, f)
166: register int c;
167: register FILE *f;
168: {
169: if ((c&0x60) == 0) { /* C0|C1 */
170: tputc((c&0x80) ? '$' : '^', f);
171: tputc((c&0x7F|0x40), f);
172: } else if ((c&0x7F) == 0x7F) { /* DEL */
173: tputc((c&0x80) ? '$' : '^', f);
174: tputc('?', f);
175: } else
176: tputc(c, f);
177: }
178:
179: static void
180: tputS(wp, f)
181: register char *wp;
182: register FILE *f;
183: {
184: register int c;
185:
186: while (1)
187: switch ((c = *wp++)) {
188: case EOS:
189: return;
190: case CHAR:
191: tputC(*wp++, f);
192: break;
193: case QCHAR:
194: tputc('\\', f);
195: tputC(*wp++, f);
196: break;
197: case OQUOTE:
198: case CQUOTE:
199: tputc('"', f);
200: break;
201: case OSUBST:
202: tputc('$', f);
203: tputc('{', f);
204: while ((c = *wp++) != 0)
205: tputc(c, f);
206: if (*wp != CSUBST)
207: tputC(*wp++, f);
208: break;
209: case CSUBST:
210: tputc('}', f);
211: break;
212: case COMSUB:
213: tputc('$', f);
214: tputc('(', f);
215: while (*wp != 0)
216: tputC(*wp++, f);
217: tputc(')', f);
218: break;
219: }
220: }
221:
222: /* TODO: use varargs properly */
223:
224: /* VARARGS */ int
225: fptreef(f, va_alist) va_dcl
226: register FILE *f;
227: {
228: va_list va;
229: char *fmt;
230:
231: va_start(va);
232: fmt = va_arg(va, char *);
233: vfptreef(f, fmt, va);
234: va_end(va);
235: return 0;
236: }
237:
238: /* VARARGS */ int
239: snptreef(s, n, va_alist) va_dcl
240: char *s;
241: int n;
242: {
243: va_list va;
244: char *fmt;
245:
246: snpf_s = s;
247: snpf_n = n;
248: va_start(va);
249: fmt = va_arg(va, char *);
250: vfptreef(FSTRING, fmt, va);
251: tputc('\0', FSTRING);
252: va_end(va);
253: return 0;
254: }
255:
256: vfptreef(f, fmt, va)
257: register FILE *f;
258: register char *fmt;
259: register va_list va;
260: {
261: register int c;
262:
263: while ((c = *fmt++))
264: if (c == '%') {
265: register long n;
266: register char *p;
267: int neg;
268:
269: switch ((c = *fmt++)) {
270: case 'c':
271: tputc(va_arg(va, int), f);
272: break;
273: case 's':
274: p = va_arg(va, char *);
275: while (*p)
276: tputc(*p++, f);
277: break;
278: case 'S': /* word */
279: p = va_arg(va, char *);
280: tputS(p, f);
281: break;
282: case 'd': case 'u': /* decimal */
283: n = (c == 'd') ? va_arg(va, int) : va_arg(va, unsigned int);
284: neg = c=='d' && n<0;
285: p = ulton((neg) ? -n : n, 10);
286: if (neg)
287: *--p = '-';
288: while (*p)
289: tputc(*p++, f);
290: break;
291: case 'T': /* format tree */
292: ptree(va_arg(va, struct op *), f);
293: break;
294: case ';': /* newline or ; */
295: p = (f == FSTRING) ? "; " : "\n";
296: while (*p)
297: tputc(*p++, f);
298: break;
299: default:
300: tputc(c, f);
301: break;
302: }
303: } else
304: tputc(c, f);
305: }
306:
307: /*
308: * copy tree (for function definition)
309: */
310:
311: static struct ioword **iocopy();
312:
313: struct op *
314: tcopy(t, ap)
315: register struct op *t;
316: Area *ap;
317: {
318: register struct op *r;
319: register char **tw, **rw;
320:
321: if (t == NULL)
322: return NULL;
323:
324: r = (struct op *) alloc(sizeof(struct op), ap);
325:
326: r->type = t->type;
327:
328: /* this will copy function and for identifiers quite accidently */
329: r->str = (t->str == NULL) ? NULL : wdcopy(t->str, ap);
330:
331: if (t->vars == NULL)
332: r->vars = NULL;
333: else {
334: for (tw = t->vars; *tw++ != NULL; )
335: ;
336: rw = r->vars = (char **)
337: alloc((int)(tw - t->vars) * sizeof(*tw), ap);
338: for (tw = t->vars; *tw != NULL; )
339: *rw++ = wdcopy(*tw++, ap);
340: *rw = NULL;
341: }
342:
343: if (t->args == NULL)
344: r->args = NULL;
345: else {
346: for (tw = t->args; *tw++ != NULL; )
347: ;
348: rw = r->args = (char **)
349: alloc((int)(tw - t->args) * sizeof(*tw), ap);
350: for (tw = t->args; *tw != NULL; )
351: *rw++ = wdcopy(*tw++, ap);
352: *rw = NULL;
353: }
354:
355: r->ioact = (t->ioact == NULL) ? NULL : iocopy(t->ioact, ap);
356:
357: r->left = tcopy(t->left, ap);
358: r->right = tcopy(t->right, ap);
359:
360: return r;
361: }
362:
363: char *
364: wdcopy(wp, ap)
365: char *wp;
366: Area *ap;
367: {
368: size_t len = wdscan(wp, EOS) - wp;
369: return memcpy(alloc(len, ap), wp, len);
370: }
371:
372: /* return the position of prefix c in wp plus 1 */
373: char *
374: wdscan(wp, c)
375: register char *wp;
376: register int c;
377: {
378: register int nest = 0;
379:
380: while (1)
381: switch (*wp++) {
382: case EOS:
383: return wp;
384: case CHAR:
385: case QCHAR:
386: wp++;
387: break;
388: case OQUOTE:
389: case CQUOTE:
390: break;
391: case OSUBST:
392: nest++;
393: while (*wp++ != 0)
394: ;
395: if (*wp != CSUBST)
396: wp++;
397: break;
398: case CSUBST:
399: if (c == CSUBST && nest == 0)
400: return wp;
401: nest--;
402: break;
403: case COMSUB:
404: while (*wp++ != 0)
405: ;
406: break;
407: }
408: }
409:
410: static struct ioword **
411: iocopy(iow, ap)
412: register struct ioword **iow;
413: Area *ap;
414: {
415: register struct ioword **ior;
416: register int i;
417:
418: for (ior = iow; *ior++ != NULL; )
419: ;
420: ior = (struct ioword **) alloc((int)(ior - iow) * sizeof(*ior), ap);
421:
422: for (i = 0; iow[i] != NULL; i++) {
423: register struct ioword *p, *q;
424:
425: p = iow[i];
426: q = (struct ioword *) alloc(sizeof(*p), ap);
427: ior[i] = q;
428: *q = *p;
429: if (p->name != NULL)
430: q->name = wdcopy(p->name, ap);
431: }
432: ior[i] = NULL;
433:
434: return ior;
435: }
436:
437: /*
438: * free tree (for function definition)
439: */
440:
441: static void iofree();
442:
443: void
444: tfree(t, ap)
445: register struct op *t;
446: Area *ap;
447: {
448: register char **w;
449:
450: if (t == NULL)
451: return;
452:
453: if (t->str != NULL)
454: afree((Void*)t->str, ap);
455:
456: if (t->vars != NULL) {
457: for (w = t->vars; *w != NULL; w++)
458: afree((Void*)*w, ap);
459: afree((Void*)t->vars, ap);
460: }
461:
462: if (t->args != NULL) {
463: for (w = t->args; *w != NULL; w++)
464: afree((Void*)*w, ap);
465: afree((Void*)t->args, ap);
466: }
467:
468: if (t->ioact != NULL)
469: iofree(t->ioact, ap);
470:
471: tfree(t->left, ap);
472: tfree(t->right, ap);
473:
474: afree((Void*)t, ap);
475: }
476:
477: static void
478: iofree(iow, ap)
479: struct ioword **iow;
480: Area *ap;
481: {
482: register struct ioword **iop;
483: register struct ioword *p;
484:
485: for (iop = iow; (p = *iop++) != NULL; ) {
486: if (p->name != NULL)
487: afree((Void*)p->name, ap);
488: afree((Void*)p, ap);
489: }
490: }
491:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.