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 intermediate code reader
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 struct dolnod	*r_comlist(Shell_t*);
36static struct argnod	*r_arg(Shell_t*);
37static struct ionod	*r_redirect(Shell_t*);
38static struct regnod	*r_switch(Shell_t*);
39static Shnode_t		*r_tree(Shell_t*);
40static char		*r_string(Stk_t*);
41static void		r_comarg(Shell_t*,struct comnod*);
42
43static Sfio_t *infile;
44
45#define getnode(s,type)   ((Shnode_t*)stkalloc((s),sizeof(struct type)))
46
47Shnode_t *sh_trestore(Shell_t *shp,Sfio_t *in)
48{
49	Shnode_t *t;
50	infile = in;
51	t = r_tree(shp);
52	return(t);
53}
54/*
55 * read in a shell tree
56 */
57static Shnode_t *r_tree(Shell_t *shp)
58{
59	long l = sfgetl(infile);
60	register int type;
61	register Shnode_t *t=0;
62	if(l<0)
63		return(t);
64	type = l;
65	switch(type&COMMSK)
66	{
67		case TTIME:
68		case TPAR:
69			t = getnode(shp->stk,parnod);
70			t->par.partre = r_tree(shp);
71			break;
72		case TCOM:
73			t = getnode(shp->stk,comnod);
74			t->tre.tretyp = type;
75			r_comarg(shp,(struct comnod*)t);
76			break;
77		case TSETIO:
78		case TFORK:
79			t = getnode(shp->stk,forknod);
80			t->fork.forkline = sfgetu(infile);
81			t->fork.forktre = r_tree(shp);
82			t->fork.forkio = r_redirect(shp);
83			break;
84		case TIF:
85			t = getnode(shp->stk,ifnod);
86			t->if_.iftre = r_tree(shp);
87			t->if_.thtre = r_tree(shp);
88			t->if_.eltre = r_tree(shp);
89			break;
90		case TWH:
91			t = getnode(shp->stk,whnod);
92			t->wh.whinc = (struct arithnod*)r_tree(shp);
93			t->wh.whtre = r_tree(shp);
94			t->wh.dotre = r_tree(shp);
95			break;
96		case TLST:
97		case TAND:
98		case TORF:
99		case TFIL:
100			t = getnode(shp->stk,lstnod);
101			t->lst.lstlef = r_tree(shp);
102			t->lst.lstrit = r_tree(shp);
103			break;
104		case TARITH:
105			t = getnode(shp->stk,arithnod);
106			t->ar.arline = sfgetu(infile);
107			t->ar.arexpr = r_arg(shp);
108			t->ar.arcomp = 0;
109			if((t->ar.arexpr)->argflag&ARG_RAW)
110				 t->ar.arcomp = sh_arithcomp(shp,(t->ar.arexpr)->argval);
111			break;
112		case TFOR:
113			t = getnode(shp->stk,fornod);
114			t->for_.forline = 0;
115			if(type&FLINENO)
116				t->for_.forline = sfgetu(infile);
117			t->for_.fortre = r_tree(shp);
118			t->for_.fornam = r_string(shp->stk);
119			t->for_.forlst = (struct comnod*)r_tree(shp);
120			break;
121		case TSW:
122			t = getnode(shp->stk,swnod);
123			t->sw.swline = 0;
124			if(type&FLINENO)
125				t->sw.swline = sfgetu(infile);
126			t->sw.swarg = r_arg(shp);
127			if(type&COMSCAN)
128				t->sw.swio = r_redirect(shp);
129			else
130				t->sw.swio = 0;
131			t->sw.swlst = r_switch(shp);
132			break;
133		case TFUN:
134		{
135			Stak_t *savstak;
136			struct slnod *slp;
137			struct functnod *fp;
138			t = getnode(shp->stk,functnod);
139			t->funct.functloc = -1;
140			t->funct.functline = sfgetu(infile);
141			t->funct.functnam = r_string(shp->stk);
142			savstak = stakcreate(STAK_SMALL);
143			savstak = stakinstall(savstak, 0);
144			slp = (struct slnod*)stkalloc(shp->stk,sizeof(struct slnod)+sizeof(struct functnod));
145			slp->slchild = 0;
146			slp->slnext = shp->st.staklist;
147			shp->st.staklist = 0;
148			fp = (struct functnod*)(slp+1);
149			memset(fp, 0, sizeof(*fp));
150			fp->functtyp = TFUN|FAMP;
151			if(shp->st.filename)
152				fp->functnam = stkcopy(shp->stk,shp->st.filename);
153			t->funct.functtre = r_tree(shp);
154			t->funct.functstak = slp;
155			t->funct.functargs = (struct comnod*)r_tree(shp);
156			slp->slptr =  stakinstall(savstak,0);
157			slp->slchild = shp->st.staklist;
158			break;
159		}
160		case TTST:
161			t = getnode(shp->stk,tstnod);
162			t->tst.tstline = sfgetu(infile);
163			if((type&TPAREN)==TPAREN)
164				t->lst.lstlef = r_tree(shp);
165			else
166			{
167				t->lst.lstlef = (Shnode_t*)r_arg(shp);
168				if((type&TBINARY))
169					t->lst.lstrit = (Shnode_t*)r_arg(shp);
170			}
171	}
172	if(t)
173		t->tre.tretyp = type;
174	return(t);
175}
176
177static struct argnod *r_arg(Shell_t *shp)
178{
179	register struct argnod *ap=0, *apold, *aptop=0;
180	register long l;
181	Stk_t		*stkp=shp->stk;
182	while((l=sfgetu(infile))>0)
183	{
184		ap = (struct argnod*)stkseek(stkp,(unsigned)l+ARGVAL);
185		if(!aptop)
186			aptop = ap;
187		else
188			apold->argnxt.ap = ap;
189		if(--l > 0)
190		{
191			sfread(infile,ap->argval,(size_t)l);
192			ccmaps(ap->argval, l, CC_ASCII, CC_NATIVE);
193		}
194		ap->argval[l] = 0;
195		ap->argchn.cp = 0;
196		ap->argflag = sfgetc(infile);
197#if 0
198		if((ap->argflag&ARG_MESSAGE) && *ap->argval)
199		{
200			/* replace international messages */
201			sh_endword(shp,1);
202			ap->argflag &= ~ARG_MESSAGE;
203			if(!(ap->argflag&(ARG_MAC|ARG_EXP)))
204				ap = sh_endword(shp,0);
205			else
206			{
207				ap = (struct argnod*)stkfreeze(stkp,0);
208				if(ap->argflag==0)
209					ap->argflag = ARG_RAW;
210			}
211		}
212		else
213#endif
214			ap = (struct argnod*)stkfreeze(stkp,0);
215		if(*ap->argval==0 && (ap->argflag&ARG_EXP))
216			ap->argchn.ap = (struct argnod*)r_tree(shp);
217		else if(*ap->argval==0 && (ap->argflag&~(ARG_APPEND|ARG_MESSAGE|ARG_QUOTED))==0)
218		{
219			struct fornod *fp = (struct fornod*)getnode(shp->stk,fornod);
220			fp->fortyp = sfgetu(infile);
221			fp->fortre = r_tree(shp);
222			fp->fornam = ap->argval+1;
223			ap->argchn.ap = (struct argnod*)fp;
224		}
225		apold = ap;
226	}
227	if(ap)
228		ap->argnxt.ap = 0;
229	return(aptop);
230}
231
232static struct ionod *r_redirect(Shell_t* shp)
233{
234	register long l;
235	register struct ionod *iop=0, *iopold, *ioptop=0;
236	while((l=sfgetl(infile))>=0)
237	{
238		iop = (struct ionod*)getnode(shp->stk,ionod);
239		if(!ioptop)
240			ioptop = iop;
241		else
242			iopold->ionxt = iop;
243		iop->iofile = l;
244		iop->ioname = r_string(shp->stk);
245		if(iop->iodelim = r_string(shp->stk))
246		{
247			iop->iosize = sfgetl(infile);
248			if(shp->heredocs)
249				iop->iooffset = sfseek(shp->heredocs,(off_t)0,SEEK_END);
250			else
251			{
252				shp->heredocs = sftmp(512);
253				iop->iooffset = 0;
254			}
255			sfmove(infile,shp->heredocs, iop->iosize, -1);
256		}
257		iopold = iop;
258		if(iop->iofile&IOVNM)
259			iop->iovname = r_string(shp->stk);
260		else
261			iop->iovname = 0;
262		iop->iofile &= ~IOVNM;
263	}
264	if(iop)
265		iop->ionxt = 0;
266	return(ioptop);
267}
268
269static void r_comarg(Shell_t *shp,struct comnod *com)
270{
271	char *cmdname=0;
272	com->comio = r_redirect(shp);
273	com->comset = r_arg(shp);
274	com->comstate = 0;
275	if(com->comtyp&COMSCAN)
276	{
277		com->comarg = r_arg(shp);
278		if(com->comarg->argflag==ARG_RAW)
279			cmdname = com->comarg->argval;
280	}
281	else if(com->comarg = (struct argnod*)r_comlist(shp))
282		cmdname = ((struct dolnod*)(com->comarg))->dolval[ARG_SPARE];
283	com->comline = sfgetu(infile);
284	com->comnamq = 0;
285	if(cmdname)
286	{
287		char *cp;
288		com->comnamp = (void*)nv_search(cmdname,shp->fun_tree,0);
289		if(com->comnamp && (cp =strrchr(cmdname+1,'.')))
290		{
291			*cp = 0;
292			com->comnamp =  (void*)nv_open(cmdname,shp->var_tree,NV_VARNAME|NV_NOADD|NV_NOARRAY);
293			*cp = '.';
294		}
295	}
296	else
297		com->comnamp  = 0;
298}
299
300static struct dolnod *r_comlist(Shell_t *shp)
301{
302	register struct dolnod *dol=0;
303	register long l;
304	register char **argv;
305	if((l=sfgetl(infile))>0)
306	{
307		dol = (struct dolnod*)stkalloc(shp->stk,sizeof(struct dolnod) + sizeof(char*)*(l+ARG_SPARE));
308		dol->dolnum = l;
309		dol->dolbot = ARG_SPARE;
310		argv = dol->dolval+ARG_SPARE;
311		while(*argv++ = r_string(shp->stk));
312	}
313	return(dol);
314}
315
316static struct regnod *r_switch(Shell_t *shp)
317{
318	register long l;
319	struct regnod *reg=0,*regold,*regtop=0;
320	while((l=sfgetl(infile))>=0)
321	{
322		reg = (struct regnod*)getnode(shp->stk,regnod);
323		if(!regtop)
324			regtop = reg;
325		else
326			regold->regnxt = reg;
327		reg->regflag = l;
328		reg->regptr = r_arg(shp);
329		reg->regcom = r_tree(shp);
330		regold = reg;
331	}
332	if(reg)
333		reg->regnxt = 0;
334	return(regtop);
335}
336
337static char *r_string(Stk_t *stkp)
338{
339	register Sfio_t *in = infile;
340	register unsigned long l = sfgetu(in);
341	register char *ptr;
342	if(l == 0)
343		return(NIL(char*));
344	ptr = stkalloc(stkp,(unsigned)l);
345	if(--l > 0)
346	{
347		if(sfread(in,ptr,(size_t)l)!=(size_t)l)
348			return(NIL(char*));
349		ccmaps(ptr, l, CC_ASCII, CC_NATIVE);
350	}
351	ptr[l] = 0;
352	return(ptr);
353}
354