Deleted Added
sdiff udiff text old ( 17987 ) new ( 18018 )
full compact
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.3 1996/09/01 10:21:43 peter 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
344#ifdef DEBUG
345static void
346trstring(s)
347 char *s;
348{
349 register char *p;
350 char c;
351
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}
384#endif
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#ifdef DEBUG
409 char s[100];
410 char *getenv();
411#ifdef O_APPEND
412 int flags;
413#endif
414
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}