1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1982-2011 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                 Eclipse Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*          http://www.eclipse.org/org/documents/epl-v10.html           *
11*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                  David Korn <dgk@research.att.com>                   *
18*                                                                      *
19***********************************************************************/
20#pragma prototyped
21/*
22 * David Korn
23 * AT&T Labs
24 *
25 * shell parse tree dump
26 *
27 */
28
29#include	"defs.h"
30#include	"shnodes.h"
31#include	"path.h"
32#include	"io.h"
33#include	<ccode.h>
34
35static int p_comlist(const struct dolnod*);
36static int p_arg(const struct argnod*);
37static int p_comarg(const struct comnod*);
38static int p_redirect(const struct ionod*);
39static int p_switch(const struct regnod*);
40static int p_tree(const Shnode_t*);
41static int p_string(const char*);
42
43static Sfio_t *outfile;
44
45int sh_tdump(Sfio_t *out, const Shnode_t *t)
46{
47	outfile = out;
48	return(p_tree(t));
49}
50
51/*
52 *  convert to ASCII to write and back again if needed
53 */
54static int outstring(Sfio_t *out, const char *string, int n)
55{
56	int r;
57	char *cp = (char*)string;
58	ccmaps(cp, n, CC_NATIVE, CC_ASCII);
59	r = sfwrite(out,cp,n);
60	ccmaps(cp, n, CC_ASCII, CC_NATIVE);
61	return(r);
62}
63
64/*
65 * print script corresponding to shell tree <t>
66 */
67static int p_tree(register const Shnode_t *t)
68{
69	if(!t)
70		return(sfputl(outfile,-1));
71	if(sfputl(outfile,t->tre.tretyp)<0)
72		return(-1);
73	switch(t->tre.tretyp&COMMSK)
74	{
75		case TTIME:
76		case TPAR:
77			return(p_tree(t->par.partre));
78		case TCOM:
79			return(p_comarg((struct comnod*)t));
80		case TSETIO:
81		case TFORK:
82			if(sfputu(outfile,t->fork.forkline)<0)
83				return(-1);
84			if(p_tree(t->fork.forktre)<0)
85				return(-1);
86			return(p_redirect(t->fork.forkio));
87		case TIF:
88			if(p_tree(t->if_.iftre)<0)
89				return(-1);
90			if(p_tree(t->if_.thtre)<0)
91				return(-1);
92			return(p_tree(t->if_.eltre));
93		case TWH:
94			if(t->wh.whinc)
95			{
96				if(p_tree((Shnode_t*)(t->wh.whinc))<0)
97					return(-1);
98			}
99			else
100			{
101				if(sfputl(outfile,-1)<0)
102					return(-1);
103			}
104			if(p_tree(t->wh.whtre)<0)
105				return(-1);
106			return(p_tree(t->wh.dotre));
107		case TLST:
108		case TAND:
109		case TORF:
110		case TFIL:
111			if(p_tree(t->lst.lstlef)<0)
112				return(-1);
113			return(p_tree(t->lst.lstrit));
114		case TARITH:
115			if(sfputu(outfile,t->ar.arline)<0)
116				return(-1);
117			return(p_arg(t->ar.arexpr));
118		case TFOR:
119			if(sfputu(outfile,t->for_.forline)<0)
120				return(-1);
121			if(p_tree(t->for_.fortre)<0)
122				return(-1);
123			if(p_string(t->for_.fornam)<0)
124				return(-1);
125			return(p_tree((Shnode_t*)t->for_.forlst));
126		case TSW:
127			if(sfputu(outfile,t->sw.swline)<0)
128				return(-1);
129			if(p_arg(t->sw.swarg)<0)
130				return(-1);
131			return(p_switch(t->sw.swlst));
132		case TFUN:
133			if(sfputu(outfile,t->funct.functline)<0)
134				return(-1);
135			if(p_string(t->funct.functnam)<0)
136				return(-1);
137			if(p_tree(t->funct.functtre)<0)
138				return(-1);
139			return(p_tree((Shnode_t*)t->funct.functargs));
140		case TTST:
141			if(sfputu(outfile,t->tst.tstline)<0)
142				return(-1);
143			if((t->tre.tretyp&TPAREN)==TPAREN)
144				return(p_tree(t->lst.lstlef));
145			else
146			{
147				if(p_arg(&(t->lst.lstlef->arg))<0)
148					return(-1);
149				if((t->tre.tretyp&TBINARY))
150					return(p_arg(&(t->lst.lstrit->arg)));
151				return(0);
152			}
153	}
154	return(-1);
155}
156
157static int p_arg(register const struct argnod *arg)
158{
159	register int n;
160	struct fornod *fp;
161	while(arg)
162	{
163		if((n = strlen(arg->argval)) || (arg->argflag&~(ARG_APPEND|ARG_MESSAGE|ARG_QUOTED)))
164			fp=0;
165		else
166		{
167			fp=(struct fornod*)arg->argchn.ap;
168			n = strlen(fp->fornam)+1;
169		}
170		sfputu(outfile,n+1);
171		if(fp)
172		{
173			sfputc(outfile,0);
174			outstring(outfile,fp->fornam,n-1);
175		}
176		else
177			outstring(outfile,arg->argval,n);
178		sfputc(outfile,arg->argflag);
179		if(fp)
180		{
181			sfputu(outfile,fp->fortyp);
182			p_tree(fp->fortre);
183		}
184		else if(n==0 && (arg->argflag&ARG_EXP) && arg->argchn.ap)
185			p_tree((Shnode_t*)arg->argchn.ap);
186		arg = arg->argnxt.ap;
187	}
188	return(sfputu(outfile,0));
189}
190
191static int p_redirect(register const struct ionod *iop)
192{
193	while(iop)
194	{
195		if(iop->iovname)
196			sfputl(outfile,iop->iofile|IOVNM);
197		else
198			sfputl(outfile,iop->iofile);
199		p_string(iop->ioname);
200		if(iop->iodelim)
201		{
202			p_string(iop->iodelim);
203			sfputl(outfile,iop->iosize);
204			sfseek(sh.heredocs,iop->iooffset,SEEK_SET);
205			sfmove(sh.heredocs,outfile, iop->iosize,-1);
206		}
207		else
208			sfputu(outfile,0);
209		if(iop->iovname)
210			p_string(iop->iovname);
211		iop = iop->ionxt;
212	}
213	return(sfputl(outfile,-1));
214}
215
216static int p_comarg(register const struct comnod *com)
217{
218	p_redirect(com->comio);
219	p_arg(com->comset);
220	if(!com->comarg)
221		sfputl(outfile,-1);
222	else if(com->comtyp&COMSCAN)
223		p_arg(com->comarg);
224	else
225		p_comlist((struct dolnod*)com->comarg);
226	return(sfputu(outfile,com->comline));
227}
228
229static int p_comlist(const struct dolnod *dol)
230{
231	register char *cp, *const*argv;
232	register int n;
233	argv = dol->dolval+ARG_SPARE;
234	while(cp = *argv)
235		argv++;
236	n = argv - (dol->dolval+1);
237	sfputl(outfile,n);
238	argv = dol->dolval+ARG_SPARE;
239	while(cp  = *argv++)
240		p_string(cp);
241	return(sfputu(outfile,0));
242}
243
244static int p_switch(register const struct regnod *reg)
245{
246	while(reg)
247	{
248		sfputl(outfile,reg->regflag);
249		p_arg(reg->regptr);
250		p_tree(reg->regcom);
251		reg = reg->regnxt;
252	}
253	return(sfputl(outfile,-1));
254}
255
256static int p_string(register const char *string)
257{
258	register size_t n=strlen(string);
259	if(sfputu(outfile,n+1)<0)
260		return(-1);
261	return(outstring(outfile,string,n));
262}
263