1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1982-2008 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 <ccode.h> 30 #include "defs.h" 31 #include "shnodes.h" 32 #include "path.h" 33 #include "io.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 t = getnode(shp->stk,functnod); 138 t->funct.functloc = -1; 139 t->funct.functline = sfgetu(infile); 140 t->funct.functnam = r_string(shp->stk); 141 savstak = stakcreate(STAK_SMALL); 142 savstak = stakinstall(savstak, 0); 143 slp = (struct slnod*)stkalloc(shp->stk,sizeof(struct slnod)); 144 slp->slchild = 0; 145 slp->slnext = shp->st.staklist; 146 shp->st.staklist = 0; 147 t->funct.functtre = r_tree(shp); 148 t->funct.functstak = slp; 149 slp->slptr = stakinstall(savstak,0); 150 slp->slchild = shp->st.staklist; 151 t->funct.functargs = (struct comnod*)r_tree(shp); 152 break; 153 } 154 case TTST: 155 t = getnode(shp->stk,tstnod); 156 t->tst.tstline = sfgetu(infile); 157 if((type&TPAREN)==TPAREN) 158 t->lst.lstlef = r_tree(shp); 159 else 160 { 161 t->lst.lstlef = (Shnode_t*)r_arg(shp); 162 if((type&TBINARY)) 163 t->lst.lstrit = (Shnode_t*)r_arg(shp); 164 } 165 } 166 if(t) 167 t->tre.tretyp = type; 168 return(t); 169 } 170 171 static struct argnod *r_arg(Shell_t *shp) 172 { 173 register struct argnod *ap=0, *apold, *aptop=0; 174 register long l; 175 Stk_t *stkp=shp->stk; 176 while((l=sfgetu(infile))>0) 177 { 178 ap = (struct argnod*)stkseek(stkp,(unsigned)l+ARGVAL); 179 if(!aptop) 180 aptop = ap; 181 else 182 apold->argnxt.ap = ap; 183 if(--l > 0) 184 { 185 sfread(infile,ap->argval,(size_t)l); 186 ccmaps(ap->argval, l, CC_ASCII, CC_NATIVE); 187 } 188 ap->argval[l] = 0; 189 ap->argchn.cp = 0; 190 ap->argflag = sfgetc(infile); 191 if((ap->argflag&ARG_MESSAGE) && *ap->argval) 192 { 193 /* replace international messages */ 194 ap = sh_endword(shp,1); 195 ap->argflag &= ~ARG_MESSAGE; 196 if(!(ap->argflag&(ARG_MAC|ARG_EXP))) 197 ap = sh_endword(shp,0); 198 else 199 { 200 ap = (struct argnod*)stkfreeze(stkp,0); 201 if(ap->argflag==0) 202 ap->argflag = ARG_RAW; 203 } 204 } 205 else 206 ap = (struct argnod*)stkfreeze(stkp,0); 207 if(*ap->argval==0 && (ap->argflag&~(ARG_APPEND|ARG_MESSAGE|ARG_QUOTED))==0) 208 { 209 struct fornod *fp = (struct fornod*)getnode(shp->stk,fornod); 210 fp->fortyp = sfgetu(infile); 211 fp->fortre = r_tree(shp); 212 fp->fornam = ap->argval+1; 213 ap->argchn.ap = (struct argnod*)fp; 214 } 215 apold = ap; 216 } 217 if(ap) 218 ap->argnxt.ap = 0; 219 return(aptop); 220 } 221 222 static struct ionod *r_redirect(Shell_t* shp) 223 { 224 register long l; 225 register struct ionod *iop=0, *iopold, *ioptop=0; 226 while((l=sfgetl(infile))>=0) 227 { 228 iop = (struct ionod*)getnode(shp->stk,ionod); 229 if(!ioptop) 230 ioptop = iop; 231 else 232 iopold->ionxt = iop; 233 iop->iofile = l; 234 iop->ioname = r_string(shp->stk); 235 if(iop->iodelim = r_string(shp->stk)) 236 { 237 iop->iosize = sfgetl(infile); 238 if(shp->heredocs) 239 iop->iooffset = sfseek(shp->heredocs,(off_t)0,SEEK_END); 240 else 241 { 242 shp->heredocs = sftmp(512); 243 iop->iooffset = 0; 244 } 245 sfmove(infile,shp->heredocs, iop->iosize, -1); 246 } 247 iopold = iop; 248 if(iop->iofile&IOVNM) 249 iop->iovname = r_string(shp->stk); 250 else 251 iop->iovname = 0; 252 iop->iofile &= ~IOVNM; 253 } 254 if(iop) 255 iop->ionxt = 0; 256 return(ioptop); 257 } 258 259 static void r_comarg(Shell_t *shp,struct comnod *com) 260 { 261 char *cmdname=0; 262 com->comio = r_redirect(shp); 263 com->comset = r_arg(shp); 264 com->comstate = 0; 265 if(com->comtyp&COMSCAN) 266 { 267 com->comarg = r_arg(shp); 268 if(com->comarg->argflag==ARG_RAW) 269 cmdname = com->comarg->argval; 270 } 271 else if(com->comarg = (struct argnod*)r_comlist(shp)) 272 cmdname = ((struct dolnod*)(com->comarg))->dolval[ARG_SPARE]; 273 com->comline = sfgetu(infile); 274 com->comnamq = 0; 275 if(cmdname) 276 { 277 char *cp; 278 com->comnamp = (void*)nv_search(cmdname,shp->fun_tree,0); 279 if(com->comnamp && (cp =strrchr(cmdname+1,'.'))) 280 { 281 *cp = 0; 282 com->comnamp = (void*)nv_open(cmdname,shp->var_tree,NV_VARNAME|NV_NOADD|NV_NOARRAY); 283 *cp = '.'; 284 } 285 } 286 else 287 com->comnamp = 0; 288 } 289 290 static struct dolnod *r_comlist(Shell_t *shp) 291 { 292 register struct dolnod *dol=0; 293 register long l; 294 register char **argv; 295 if((l=sfgetl(infile))>0) 296 { 297 dol = (struct dolnod*)stkalloc(shp->stk,sizeof(struct dolnod) + sizeof(char*)*(l+ARG_SPARE)); 298 dol->dolnum = l; 299 dol->dolbot = ARG_SPARE; 300 argv = dol->dolval+ARG_SPARE; 301 while(*argv++ = r_string(shp->stk)); 302 } 303 return(dol); 304 } 305 306 static struct regnod *r_switch(Shell_t *shp) 307 { 308 register long l; 309 struct regnod *reg=0,*regold,*regtop=0; 310 while((l=sfgetl(infile))>=0) 311 { 312 reg = (struct regnod*)getnode(shp->stk,regnod); 313 if(!regtop) 314 regtop = reg; 315 else 316 regold->regnxt = reg; 317 reg->regflag = l; 318 reg->regptr = r_arg(shp); 319 reg->regcom = r_tree(shp); 320 regold = reg; 321 } 322 if(reg) 323 reg->regnxt = 0; 324 return(regtop); 325 } 326 327 static char *r_string(Stk_t *stkp) 328 { 329 register Sfio_t *in = infile; 330 register unsigned long l = sfgetu(in); 331 register char *ptr; 332 if(l == 0) 333 return(NIL(char*)); 334 ptr = stkalloc(stkp,(unsigned)l); 335 if(--l > 0) 336 { 337 if(sfread(in,ptr,(size_t)l)!=(size_t)l) 338 return(NIL(char*)); 339 ccmaps(ptr, l, CC_ASCII, CC_NATIVE); 340 } 341 ptr[l] = 0; 342 return(ptr); 343 } 344