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
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(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
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 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
r_redirect(Shell_t * shp)232 static 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
r_comarg(Shell_t * shp,struct comnod * com)269 static 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
r_comlist(Shell_t * shp)300 static 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
r_switch(Shell_t * shp)316 static 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
r_string(Stk_t * stkp)337 static 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