xref: /original-bsd/bin/sh/show.c (revision 51537d50)
1 /*-
2  * Copyright (c) 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char sccsid[] = "@(#)show.c	5.1 (Berkeley) 03/07/91";
13 #endif /* not lint */
14 
15 #include <stdio.h>
16 #include "shell.h"
17 #include "parser.h"
18 #include "nodes.h"
19 #include "mystring.h"
20 
21 
22 #ifdef DEBUG
23 static shtree(), shcmd(), sharg(), indent();
24 
25 
26 showtree(n)
27 	union node *n;
28 	{
29 	trputs("showtree called\n");
30 	shtree(n, 1, NULL, stdout);
31 }
32 
33 
34 static
35 shtree(n, ind, pfx, fp)
36 	union node *n;
37 	char *pfx;
38 	FILE *fp;
39 	{
40 	struct nodelist *lp;
41 	char *s;
42 
43 	indent(ind, pfx, fp);
44 	switch(n->type) {
45 	case NSEMI:
46 		s = "; ";
47 		goto binop;
48 	case NAND:
49 		s = " && ";
50 		goto binop;
51 	case NOR:
52 		s = " || ";
53 binop:
54 		shtree(n->nbinary.ch1, ind, NULL, fp);
55 	   /*    if (ind < 0) */
56 			fputs(s, fp);
57 		shtree(n->nbinary.ch2, ind, NULL, fp);
58 		break;
59 	case NCMD:
60 		shcmd(n, fp);
61 		if (ind >= 0)
62 			putc('\n', fp);
63 		break;
64 	case NPIPE:
65 		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
66 			shcmd(lp->n, fp);
67 			if (lp->next)
68 				fputs(" | ", fp);
69 		}
70 		if (n->npipe.backgnd)
71 			fputs(" &", fp);
72 		if (ind >= 0)
73 			putc('\n', fp);
74 		break;
75 	default:
76 		fprintf(fp, "<node type %d>", n->type);
77 		if (ind >= 0)
78 			putc('\n', fp);
79 		break;
80 	}
81 }
82 
83 
84 
85 static
86 shcmd(cmd, fp)
87 	union node *cmd;
88 	FILE *fp;
89 	{
90 	union node *np;
91 	int first;
92 	char *s;
93 	int dftfd;
94 
95 	first = 1;
96 	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
97 		if (! first)
98 			putchar(' ');
99 		sharg(np, fp);
100 		first = 0;
101 	}
102 	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
103 		if (! first)
104 			putchar(' ');
105 		switch (np->nfile.type) {
106 			case NTO:	s = ">";  dftfd = 1; break;
107 			case NAPPEND:	s = ">>"; dftfd = 1; break;
108 			case NTOFD:	s = ">&"; dftfd = 1; break;
109 			case NFROM:	s = "<";  dftfd = 0; break;
110 			case NFROMFD:	s = "<&"; dftfd = 0; break;
111 		}
112 		if (np->nfile.fd != dftfd)
113 			fprintf(fp, "%d", np->nfile.fd);
114 		fputs(s, fp);
115 		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
116 			fprintf(fp, "%d", np->ndup.dupfd);
117 		} else {
118 			sharg(np->nfile.fname, fp);
119 		}
120 		first = 0;
121 	}
122 }
123 
124 
125 
126 static
127 sharg(arg, fp)
128 	union node *arg;
129 	FILE *fp;
130 	{
131 	char *p;
132 	struct nodelist *bqlist;
133 	int subtype;
134 
135 	if (arg->type != NARG) {
136 		printf("<node type %d>\n", arg->type);
137 		fflush(stdout);
138 		abort();
139 	}
140 	bqlist = arg->narg.backquote;
141 	for (p = arg->narg.text ; *p ; p++) {
142 		switch (*p) {
143 		case CTLESC:
144 			putc(*++p, fp);
145 			break;
146 		case CTLVAR:
147 			putc('$', fp);
148 			putc('{', fp);
149 			subtype = *++p;
150 			while (*p != '=')
151 				putc(*p++, fp);
152 			if (subtype & VSNUL)
153 				putc(':', fp);
154 			switch (subtype & VSTYPE) {
155 			case VSNORMAL:
156 				putc('}', fp);
157 				break;
158 			case VSMINUS:
159 				putc('-', fp);
160 				break;
161 			case VSPLUS:
162 				putc('+', fp);
163 				break;
164 			case VSQUESTION:
165 				putc('?', fp);
166 				break;
167 			case VSASSIGN:
168 				putc('=', fp);
169 				break;
170 			default:
171 				printf("<subtype %d>", subtype);
172 			}
173 			break;
174 		case CTLENDVAR:
175 		     putc('}', fp);
176 		     break;
177 		case CTLBACKQ:
178 		case CTLBACKQ|CTLQUOTE:
179 			putc('$', fp);
180 			putc('(', fp);
181 			shtree(bqlist->n, -1, NULL, fp);
182 			putc(')', fp);
183 			break;
184 		default:
185 			putc(*p, fp);
186 			break;
187 		}
188 	}
189 }
190 
191 
192 static
193 indent(amount, pfx, fp)
194 	char *pfx;
195 	FILE *fp;
196 	{
197 	int i;
198 
199 	for (i = 0 ; i < amount ; i++) {
200 		if (pfx && i == amount - 1)
201 			fputs(pfx, fp);
202 		putc('\t', fp);
203 	}
204 }
205 #endif
206 
207 
208 
209 /*
210  * Debugging stuff.
211  */
212 
213 
214 FILE *tracefile;
215 
216 
217 
218 trputc(c) {
219 #ifdef DEBUG
220 	if (tracefile == NULL)
221 		return;
222 	putc(c, tracefile);
223 	if (c == '\n')
224 		fflush(tracefile);
225 #endif
226 }
227 
228 
229 trace(fmt, a1, a2, a3, a4, a5, a6, a7, a8)
230 	char *fmt;
231 	{
232 #ifdef DEBUG
233 	if (tracefile == NULL)
234 		return;
235 	fprintf(tracefile, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
236 	if (strchr(fmt, '\n'))
237 		fflush(tracefile);
238 #endif
239 }
240 
241 
242 trputs(s)
243 	char *s;
244 	{
245 #ifdef DEBUG
246 	if (tracefile == NULL)
247 		return;
248 	fputs(s, tracefile);
249 	if (strchr(s, '\n'))
250 		fflush(tracefile);
251 #endif
252 }
253 
254 
255 trstring(s)
256 	char *s;
257 	{
258 	register char *p;
259 	char c;
260 
261 #ifdef DEBUG
262 	if (tracefile == NULL)
263 		return;
264 	putc('"', tracefile);
265 	for (p = s ; *p ; p++) {
266 		switch (*p) {
267 		case '\n':  c = 'n';  goto backslash;
268 		case '\t':  c = 't';  goto backslash;
269 		case '\r':  c = 'r';  goto backslash;
270 		case '"':  c = '"';  goto backslash;
271 		case '\\':  c = '\\';  goto backslash;
272 		case CTLESC:  c = 'e';  goto backslash;
273 		case CTLVAR:  c = 'v';  goto backslash;
274 		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
275 		case CTLBACKQ:  c = 'q';  goto backslash;
276 		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
277 backslash:	  putc('\\', tracefile);
278 			putc(c, tracefile);
279 			break;
280 		default:
281 			if (*p >= ' ' && *p <= '~')
282 				putc(*p, tracefile);
283 			else {
284 				putc('\\', tracefile);
285 				putc(*p >> 6 & 03, tracefile);
286 				putc(*p >> 3 & 07, tracefile);
287 				putc(*p & 07, tracefile);
288 			}
289 			break;
290 		}
291 	}
292 	putc('"', tracefile);
293 #endif
294 }
295 
296 
297 trargs(ap)
298 	char **ap;
299 	{
300 #ifdef DEBUG
301 	if (tracefile == NULL)
302 		return;
303 	while (*ap) {
304 		trstring(*ap++);
305 		if (*ap)
306 			putc(' ', tracefile);
307 		else
308 			putc('\n', tracefile);
309 	}
310 	fflush(tracefile);
311 #endif
312 }
313 
314 
315 opentrace() {
316 	char s[100];
317 	char *p;
318 	char *getenv();
319 	int flags;
320 
321 #ifdef DEBUG
322 	if ((p = getenv("HOME")) == NULL)
323 		p = "/tmp";
324 	scopy(p, s);
325 	strcat(s, "/trace");
326 	if ((tracefile = fopen(s, "a")) == NULL) {
327 		fprintf(stderr, "Can't open %s\n", s);
328 		exit(2);
329 	}
330 #ifdef O_APPEND
331 	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
332 		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
333 #endif
334 	fputs("\nTracing started.\n", tracefile);
335 	fflush(tracefile);
336 #endif
337 }
338