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 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 */ 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 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 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 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 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 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 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