1 /***********************************************************************
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 *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * David Korn <dgk@research.att.com> *
19 ***********************************************************************/
25 * shell intermediate code reader
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
*);
43 static Sfio_t
*infile
;
45 #define getnode(s,type) ((Shnode_t*)stkalloc((s),sizeof(struct type)))
47 Shnode_t
*sh_trestore(Shell_t
*shp
,Sfio_t
*in
)
55 * read in a shell tree
57 static Shnode_t
*r_tree(Shell_t
*shp
)
59 long l
= sfgetl(infile
);
61 register Shnode_t
*t
=0;
69 t
= getnode(shp
->stk
,parnod
);
70 t
->par
.partre
= r_tree(shp
);
73 t
= getnode(shp
->stk
,comnod
);
75 r_comarg(shp
,(struct comnod
*)t
);
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
);
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
);
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
);
100 t
= getnode(shp
->stk
,lstnod
);
101 t
->lst
.lstlef
= r_tree(shp
);
102 t
->lst
.lstrit
= r_tree(shp
);
105 t
= getnode(shp
->stk
,arithnod
);
106 t
->ar
.arline
= sfgetu(infile
);
107 t
->ar
.arexpr
= r_arg(shp
);
109 if((t
->ar
.arexpr
)->argflag
&ARG_RAW
)
110 t
->ar
.arcomp
= sh_arithcomp((t
->ar
.arexpr
)->argval
);
113 t
= getnode(shp
->stk
,fornod
);
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
);
122 t
= getnode(shp
->stk
,swnod
);
125 t
->sw
.swline
= sfgetu(infile
);
126 t
->sw
.swarg
= r_arg(shp
);
128 t
->sw
.swio
= r_redirect(shp
);
131 t
->sw
.swlst
= r_switch(shp
);
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
));
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
;
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
);
161 t
= getnode(shp
->stk
,tstnod
);
162 t
->tst
.tstline
= sfgetu(infile
);
163 if((type
&TPAREN
)==TPAREN
)
164 t
->lst
.lstlef
= r_tree(shp
);
167 t
->lst
.lstlef
= (Shnode_t
*)r_arg(shp
);
169 t
->lst
.lstrit
= (Shnode_t
*)r_arg(shp
);
173 t
->tre
.tretyp
= type
;
177 static struct argnod
*r_arg(Shell_t
*shp
)
179 register struct argnod
*ap
=0, *apold
, *aptop
=0;
181 Stk_t
*stkp
=shp
->stk
;
182 while((l
=sfgetu(infile
))>0)
184 ap
= (struct argnod
*)stkseek(stkp
,(unsigned)l
+ARGVAL
);
188 apold
->argnxt
.ap
= ap
;
191 sfread(infile
,ap
->argval
,(size_t)l
);
192 ccmaps(ap
->argval
, l
, CC_ASCII
, CC_NATIVE
);
196 ap
->argflag
= sfgetc(infile
);
197 if((ap
->argflag
&ARG_MESSAGE
) && *ap
->argval
)
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);
206 ap
= (struct argnod
*)stkfreeze(stkp
,0);
208 ap
->argflag
= ARG_RAW
;
212 ap
= (struct argnod
*)stkfreeze(stkp
,0);
213 if(*ap
->argval
==0 && (ap
->argflag
&~(ARG_APPEND
|ARG_MESSAGE
|ARG_QUOTED
))==0)
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
;
228 static struct ionod
*r_redirect(Shell_t
* shp
)
231 register struct ionod
*iop
=0, *iopold
, *ioptop
=0;
232 while((l
=sfgetl(infile
))>=0)
234 iop
= (struct ionod
*)getnode(shp
->stk
,ionod
);
240 iop
->ioname
= r_string(shp
->stk
);
241 if(iop
->iodelim
= r_string(shp
->stk
))
243 iop
->iosize
= sfgetl(infile
);
245 iop
->iooffset
= sfseek(shp
->heredocs
,(off_t
)0,SEEK_END
);
248 shp
->heredocs
= sftmp(512);
251 sfmove(infile
,shp
->heredocs
, iop
->iosize
, -1);
254 if(iop
->iofile
&IOVNM
)
255 iop
->iovname
= r_string(shp
->stk
);
258 iop
->iofile
&= ~IOVNM
;
265 static void r_comarg(Shell_t
*shp
,struct comnod
*com
)
268 com
->comio
= r_redirect(shp
);
269 com
->comset
= r_arg(shp
);
271 if(com
->comtyp
&COMSCAN
)
273 com
->comarg
= r_arg(shp
);
274 if(com
->comarg
->argflag
==ARG_RAW
)
275 cmdname
= com
->comarg
->argval
;
277 else if(com
->comarg
= (struct argnod
*)r_comlist(shp
))
278 cmdname
= ((struct dolnod
*)(com
->comarg
))->dolval
[ARG_SPARE
];
279 com
->comline
= sfgetu(infile
);
284 com
->comnamp
= (void*)nv_search(cmdname
,shp
->fun_tree
,0);
285 if(com
->comnamp
&& (cp
=strrchr(cmdname
+1,'.')))
288 com
->comnamp
= (void*)nv_open(cmdname
,shp
->var_tree
,NV_VARNAME
|NV_NOADD
|NV_NOARRAY
);
296 static struct dolnod
*r_comlist(Shell_t
*shp
)
298 register struct dolnod
*dol
=0;
300 register char **argv
;
301 if((l
=sfgetl(infile
))>0)
303 dol
= (struct dolnod
*)stkalloc(shp
->stk
,sizeof(struct dolnod
) + sizeof(char*)*(l
+ARG_SPARE
));
305 dol
->dolbot
= ARG_SPARE
;
306 argv
= dol
->dolval
+ARG_SPARE
;
307 while(*argv
++ = r_string(shp
->stk
));
312 static struct regnod
*r_switch(Shell_t
*shp
)
315 struct regnod
*reg
=0,*regold
,*regtop
=0;
316 while((l
=sfgetl(infile
))>=0)
318 reg
= (struct regnod
*)getnode(shp
->stk
,regnod
);
322 regold
->regnxt
= reg
;
324 reg
->regptr
= r_arg(shp
);
325 reg
->regcom
= r_tree(shp
);
333 static char *r_string(Stk_t
*stkp
)
335 register Sfio_t
*in
= infile
;
336 register unsigned long l
= sfgetu(in
);
340 ptr
= stkalloc(stkp
,(unsigned)l
);
343 if(sfread(in
,ptr
,(size_t)l
)!=(size_t)l
)
345 ccmaps(ptr
, l
, CC_ASCII
, CC_NATIVE
);