show.c revision 17987
1/*-
2 * Copyright (c) 1991, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 *	$Id: show.c,v 1.2 1994/09/24 02:58:16 davidg Exp $
37 */
38
39#ifndef lint
40static char sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
41#endif /* not lint */
42
43#include <stdio.h>
44#if __STDC__
45#include <stdarg.h>
46#else
47#include <varargs.h>
48#endif
49
50#include "shell.h"
51#include "parser.h"
52#include "nodes.h"
53#include "mystring.h"
54#include "show.h"
55
56
57#ifdef DEBUG
58static void shtree __P((union node *, int, char *, FILE*));
59static void shcmd __P((union node *, FILE *));
60static void sharg __P((union node *, FILE *));
61static void indent __P((int, char *, FILE *));
62static void trstring __P((char *));
63
64
65void
66showtree(n)
67	union node *n;
68{
69	trputs("showtree called\n");
70	shtree(n, 1, NULL, stdout);
71}
72
73
74static void
75shtree(n, ind, pfx, fp)
76	union node *n;
77	int ind;
78	char *pfx;
79	FILE *fp;
80{
81	struct nodelist *lp;
82	char *s;
83
84	if (n == NULL)
85		return;
86
87	indent(ind, pfx, fp);
88	switch(n->type) {
89	case NSEMI:
90		s = "; ";
91		goto binop;
92	case NAND:
93		s = " && ";
94		goto binop;
95	case NOR:
96		s = " || ";
97binop:
98		shtree(n->nbinary.ch1, ind, NULL, fp);
99	   /*    if (ind < 0) */
100			fputs(s, fp);
101		shtree(n->nbinary.ch2, ind, NULL, fp);
102		break;
103	case NCMD:
104		shcmd(n, fp);
105		if (ind >= 0)
106			putc('\n', fp);
107		break;
108	case NPIPE:
109		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
110			shcmd(lp->n, fp);
111			if (lp->next)
112				fputs(" | ", fp);
113		}
114		if (n->npipe.backgnd)
115			fputs(" &", fp);
116		if (ind >= 0)
117			putc('\n', fp);
118		break;
119	default:
120		fprintf(fp, "<node type %d>", n->type);
121		if (ind >= 0)
122			putc('\n', fp);
123		break;
124	}
125}
126
127
128
129static void
130shcmd(cmd, fp)
131	union node *cmd;
132	FILE *fp;
133{
134	union node *np;
135	int first;
136	char *s;
137	int dftfd;
138
139	first = 1;
140	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
141		if (! first)
142			putchar(' ');
143		sharg(np, fp);
144		first = 0;
145	}
146	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
147		if (! first)
148			putchar(' ');
149		switch (np->nfile.type) {
150			case NTO:	s = ">";  dftfd = 1; break;
151			case NAPPEND:	s = ">>"; dftfd = 1; break;
152			case NTOFD:	s = ">&"; dftfd = 1; break;
153			case NFROM:	s = "<";  dftfd = 0; break;
154			case NFROMFD:	s = "<&"; dftfd = 0; break;
155			default:  	s = "*error*"; dftfd = 0; break;
156		}
157		if (np->nfile.fd != dftfd)
158			fprintf(fp, "%d", np->nfile.fd);
159		fputs(s, fp);
160		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
161			fprintf(fp, "%d", np->ndup.dupfd);
162		} else {
163			sharg(np->nfile.fname, fp);
164		}
165		first = 0;
166	}
167}
168
169
170
171static void
172sharg(arg, fp)
173	union node *arg;
174	FILE *fp;
175	{
176	char *p;
177	struct nodelist *bqlist;
178	int subtype;
179
180	if (arg->type != NARG) {
181		printf("<node type %d>\n", arg->type);
182		fflush(stdout);
183		abort();
184	}
185	bqlist = arg->narg.backquote;
186	for (p = arg->narg.text ; *p ; p++) {
187		switch (*p) {
188		case CTLESC:
189			putc(*++p, fp);
190			break;
191		case CTLVAR:
192			putc('$', fp);
193			putc('{', fp);
194			subtype = *++p;
195			if (subtype == VSLENGTH)
196				putc('#', fp);
197
198			while (*p != '=')
199				putc(*p++, fp);
200
201			if (subtype & VSNUL)
202				putc(':', fp);
203
204			switch (subtype & VSTYPE) {
205			case VSNORMAL:
206				putc('}', fp);
207				break;
208			case VSMINUS:
209				putc('-', fp);
210				break;
211			case VSPLUS:
212				putc('+', fp);
213				break;
214			case VSQUESTION:
215				putc('?', fp);
216				break;
217			case VSASSIGN:
218				putc('=', fp);
219				break;
220			case VSTRIMLEFT:
221				putc('#', fp);
222				break;
223			case VSTRIMLEFTMAX:
224				putc('#', fp);
225				putc('#', fp);
226				break;
227			case VSTRIMRIGHT:
228				putc('%', fp);
229				break;
230			case VSTRIMRIGHTMAX:
231				putc('%', fp);
232				putc('%', fp);
233				break;
234			case VSLENGTH:
235				break;
236			default:
237				printf("<subtype %d>", subtype);
238			}
239			break;
240		case CTLENDVAR:
241		     putc('}', fp);
242		     break;
243		case CTLBACKQ:
244		case CTLBACKQ|CTLQUOTE:
245			putc('$', fp);
246			putc('(', fp);
247			shtree(bqlist->n, -1, NULL, fp);
248			putc(')', fp);
249			break;
250		default:
251			putc(*p, fp);
252			break;
253		}
254	}
255}
256
257
258static void
259indent(amount, pfx, fp)
260	int amount;
261	char *pfx;
262	FILE *fp;
263{
264	int i;
265
266	for (i = 0 ; i < amount ; i++) {
267		if (pfx && i == amount - 1)
268			fputs(pfx, fp);
269		putc('\t', fp);
270	}
271}
272#endif
273
274
275
276/*
277 * Debugging stuff.
278 */
279
280
281FILE *tracefile;
282
283#if DEBUG == 2
284int debug = 1;
285#else
286int debug = 0;
287#endif
288
289
290void
291trputc(c)
292	int c;
293{
294#ifdef DEBUG
295	if (tracefile == NULL)
296		return;
297	putc(c, tracefile);
298	if (c == '\n')
299		fflush(tracefile);
300#endif
301}
302
303void
304#if __STDC__
305shtrace(const char *fmt, ...)
306#else
307shtrace(va_alist)
308	va_dcl
309#endif
310{
311#ifdef DEBUG
312	va_list va;
313#if __STDC__
314	va_start(va, fmt);
315#else
316	char *fmt;
317	va_start(va);
318	fmt = va_arg(va, char *);
319#endif
320	if (tracefile != NULL) {
321		(void) vfprintf(tracefile, fmt, va);
322		if (strchr(fmt, '\n'))
323			(void) fflush(tracefile);
324	}
325	va_end(va);
326#endif
327}
328
329
330void
331trputs(s)
332	char *s;
333{
334#ifdef DEBUG
335	if (tracefile == NULL)
336		return;
337	fputs(s, tracefile);
338	if (strchr(s, '\n'))
339		fflush(tracefile);
340#endif
341}
342
343
344static void
345trstring(s)
346	char *s;
347{
348	register char *p;
349	char c;
350
351#ifdef DEBUG
352	if (tracefile == NULL)
353		return;
354	putc('"', tracefile);
355	for (p = s ; *p ; p++) {
356		switch (*p) {
357		case '\n':  c = 'n';  goto backslash;
358		case '\t':  c = 't';  goto backslash;
359		case '\r':  c = 'r';  goto backslash;
360		case '"':  c = '"';  goto backslash;
361		case '\\':  c = '\\';  goto backslash;
362		case CTLESC:  c = 'e';  goto backslash;
363		case CTLVAR:  c = 'v';  goto backslash;
364		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
365		case CTLBACKQ:  c = 'q';  goto backslash;
366		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
367backslash:	  putc('\\', tracefile);
368			putc(c, tracefile);
369			break;
370		default:
371			if (*p >= ' ' && *p <= '~')
372				putc(*p, tracefile);
373			else {
374				putc('\\', tracefile);
375				putc(*p >> 6 & 03, tracefile);
376				putc(*p >> 3 & 07, tracefile);
377				putc(*p & 07, tracefile);
378			}
379			break;
380		}
381	}
382	putc('"', tracefile);
383#endif
384}
385
386
387void
388trargs(ap)
389	char **ap;
390{
391#ifdef DEBUG
392	if (tracefile == NULL)
393		return;
394	while (*ap) {
395		trstring(*ap++);
396		if (*ap)
397			putc(' ', tracefile);
398		else
399			putc('\n', tracefile);
400	}
401	fflush(tracefile);
402#endif
403}
404
405
406void
407opentrace() {
408	char s[100];
409	char *getenv();
410#ifdef O_APPEND
411	int flags;
412#endif
413
414#ifdef DEBUG
415	if (!debug)
416		return;
417#ifdef not_this_way
418	{
419		char *p;
420		if ((p = getenv("HOME")) == NULL) {
421			if (geteuid() == 0)
422				p = "/";
423			else
424				p = "/tmp";
425		}
426		scopy(p, s);
427		strcat(s, "/trace");
428	}
429#else
430	scopy("./trace", s);
431#endif /* not_this_way */
432	if ((tracefile = fopen(s, "a")) == NULL) {
433		fprintf(stderr, "Can't open %s\n", s);
434		return;
435	}
436#ifdef O_APPEND
437	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
438		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
439#endif
440	fputs("\nTracing started.\n", tracefile);
441	fflush(tracefile);
442#endif /* DEBUG */
443}
444