1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1982-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
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
35 static struct dolnod *r_comlist(Shell_t*);
36 static struct argnod *r_arg(Shell_t*);
37 static struct ionod *r_redirect(Shell_t*);
38 static struct regnod *r_switch(Shell_t*);
39 static Shnode_t *r_tree(Shell_t*);
40 static char *r_string(Stk_t*);
41 static void r_comarg(Shell_t*,struct comnod*);
42
43 static Sfio_t *infile;
44
45 #define getnode(s,type) ((Shnode_t*)stkalloc((s),sizeof(struct type)))
46
sh_trestore(Shell_t * shp,Sfio_t * in)47 Shnode_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 */
r_tree(Shell_t * shp)57 static 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((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 slp->slptr = stakinstall(savstak,0);
156 slp->slchild = shp->st.staklist;
157 t->funct.functargs = (struct comnod*)r_tree(shp);
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
r_arg(Shell_t * shp)177 static 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((ap->argflag&ARG_MESSAGE) && *ap->argval)
198 {
199 /* replace international messages */
200 ap = sh_endword(shp,1);
201 ap->argflag &= ~ARG_MESSAGE;
202 if(!(ap->argflag&(ARG_MAC|ARG_EXP)))
203 ap = sh_endword(shp,0);
204 else
205 {
206 ap = (struct argnod*)stkfreeze(stkp,0);
207 if(ap->argflag==0)
208 ap->argflag = ARG_RAW;
209 }
210 }
211 else
212 ap = (struct argnod*)stkfreeze(stkp,0);
213 if(*ap->argval==0 && (ap->argflag&~(ARG_APPEND|ARG_MESSAGE|ARG_QUOTED))==0)
214 {
215 struct fornod *fp = (struct fornod*)getnode(shp->stk,fornod);
216 fp->fortyp = sfgetu(infile);
217 fp->fortre = r_tree(shp);
218 fp->fornam = ap->argval+1;
219 ap->argchn.ap = (struct argnod*)fp;
220 }
221 apold = ap;
222 }
223 if(ap)
224 ap->argnxt.ap = 0;
225 return(aptop);
226 }
227
r_redirect(Shell_t * shp)228 static struct ionod *r_redirect(Shell_t* shp)
229 {
230 register long l;
231 register struct ionod *iop=0, *iopold, *ioptop=0;
232 while((l=sfgetl(infile))>=0)
233 {
234 iop = (struct ionod*)getnode(shp->stk,ionod);
235 if(!ioptop)
236 ioptop = iop;
237 else
238 iopold->ionxt = iop;
239 iop->iofile = l;
240 iop->ioname = r_string(shp->stk);
241 if(iop->iodelim = r_string(shp->stk))
242 {
243 iop->iosize = sfgetl(infile);
244 if(shp->heredocs)
245 iop->iooffset = sfseek(shp->heredocs,(off_t)0,SEEK_END);
246 else
247 {
248 shp->heredocs = sftmp(512);
249 iop->iooffset = 0;
250 }
251 sfmove(infile,shp->heredocs, iop->iosize, -1);
252 }
253 iopold = iop;
254 if(iop->iofile&IOVNM)
255 iop->iovname = r_string(shp->stk);
256 else
257 iop->iovname = 0;
258 iop->iofile &= ~IOVNM;
259 }
260 if(iop)
261 iop->ionxt = 0;
262 return(ioptop);
263 }
264
r_comarg(Shell_t * shp,struct comnod * com)265 static void r_comarg(Shell_t *shp,struct comnod *com)
266 {
267 char *cmdname=0;
268 com->comio = r_redirect(shp);
269 com->comset = r_arg(shp);
270 com->comstate = 0;
271 if(com->comtyp&COMSCAN)
272 {
273 com->comarg = r_arg(shp);
274 if(com->comarg->argflag==ARG_RAW)
275 cmdname = com->comarg->argval;
276 }
277 else if(com->comarg = (struct argnod*)r_comlist(shp))
278 cmdname = ((struct dolnod*)(com->comarg))->dolval[ARG_SPARE];
279 com->comline = sfgetu(infile);
280 com->comnamq = 0;
281 if(cmdname)
282 {
283 char *cp;
284 com->comnamp = (void*)nv_search(cmdname,shp->fun_tree,0);
285 if(com->comnamp && (cp =strrchr(cmdname+1,'.')))
286 {
287 *cp = 0;
288 com->comnamp = (void*)nv_open(cmdname,shp->var_tree,NV_VARNAME|NV_NOADD|NV_NOARRAY);
289 *cp = '.';
290 }
291 }
292 else
293 com->comnamp = 0;
294 }
295
r_comlist(Shell_t * shp)296 static struct dolnod *r_comlist(Shell_t *shp)
297 {
298 register struct dolnod *dol=0;
299 register long l;
300 register char **argv;
301 if((l=sfgetl(infile))>0)
302 {
303 dol = (struct dolnod*)stkalloc(shp->stk,sizeof(struct dolnod) + sizeof(char*)*(l+ARG_SPARE));
304 dol->dolnum = l;
305 dol->dolbot = ARG_SPARE;
306 argv = dol->dolval+ARG_SPARE;
307 while(*argv++ = r_string(shp->stk));
308 }
309 return(dol);
310 }
311
r_switch(Shell_t * shp)312 static struct regnod *r_switch(Shell_t *shp)
313 {
314 register long l;
315 struct regnod *reg=0,*regold,*regtop=0;
316 while((l=sfgetl(infile))>=0)
317 {
318 reg = (struct regnod*)getnode(shp->stk,regnod);
319 if(!regtop)
320 regtop = reg;
321 else
322 regold->regnxt = reg;
323 reg->regflag = l;
324 reg->regptr = r_arg(shp);
325 reg->regcom = r_tree(shp);
326 regold = reg;
327 }
328 if(reg)
329 reg->regnxt = 0;
330 return(regtop);
331 }
332
r_string(Stk_t * stkp)333 static char *r_string(Stk_t *stkp)
334 {
335 register Sfio_t *in = infile;
336 register unsigned long l = sfgetu(in);
337 register char *ptr;
338 if(l == 0)
339 return(NIL(char*));
340 ptr = stkalloc(stkp,(unsigned)l);
341 if(--l > 0)
342 {
343 if(sfread(in,ptr,(size_t)l)!=(size_t)l)
344 return(NIL(char*));
345 ccmaps(ptr, l, CC_ASCII, CC_NATIVE);
346 }
347 ptr[l] = 0;
348 return(ptr);
349 }
350