1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1982-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 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(void); 36 static struct argnod *r_arg(void); 37 static struct ionod *r_redirect(void); 38 static struct regnod *r_switch(void); 39 static Shnode_t *r_tree(void); 40 static char *r_string(void); 41 static void r_comarg(struct comnod*); 42 43 static Sfio_t *infile; 44 45 #define getnode(type) ((Shnode_t*)stakalloc(sizeof(struct type))) 46 47 Shnode_t *sh_trestore(Sfio_t *in) 48 { 49 Shnode_t *t; 50 infile = in; 51 t = r_tree(); 52 return(t); 53 } 54 /* 55 * read in a shell tree 56 */ 57 static Shnode_t *r_tree() 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(parnod); 70 t->par.partre = r_tree(); 71 break; 72 case TCOM: 73 t = getnode(comnod); 74 t->tre.tretyp = type; 75 r_comarg((struct comnod*)t); 76 break; 77 case TSETIO: 78 case TFORK: 79 t = getnode(forknod); 80 t->fork.forkline = sfgetu(infile); 81 t->fork.forktre = r_tree(); 82 t->fork.forkio = r_redirect(); 83 break; 84 case TIF: 85 t = getnode(ifnod); 86 t->if_.iftre = r_tree(); 87 t->if_.thtre = r_tree(); 88 t->if_.eltre = r_tree(); 89 break; 90 case TWH: 91 t = getnode(whnod); 92 t->wh.whinc = (struct arithnod*)r_tree(); 93 t->wh.whtre = r_tree(); 94 t->wh.dotre = r_tree(); 95 break; 96 case TLST: 97 case TAND: 98 case TORF: 99 case TFIL: 100 t = getnode(lstnod); 101 t->lst.lstlef = r_tree(); 102 t->lst.lstrit = r_tree(); 103 break; 104 case TARITH: 105 t = getnode(arithnod); 106 t->ar.arline = sfgetu(infile); 107 t->ar.arexpr = r_arg(); 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(fornod); 114 t->for_.forline = 0; 115 if(type&FLINENO) 116 t->for_.forline = sfgetu(infile); 117 t->for_.fortre = r_tree(); 118 t->for_.fornam = r_string(); 119 t->for_.forlst = (struct comnod*)r_tree(); 120 break; 121 case TSW: 122 t = getnode(swnod); 123 t->sw.swline = 0; 124 if(type&FLINENO) 125 t->sw.swline = sfgetu(infile); 126 t->sw.swarg = r_arg(); 127 if(type&COMSCAN) 128 t->sw.swio = r_redirect(); 129 else 130 t->sw.swio = 0; 131 t->sw.swlst = r_switch(); 132 break; 133 case TFUN: 134 { 135 Stak_t *savstak; 136 struct slnod *slp; 137 t = getnode(functnod); 138 t->funct.functloc = -1; 139 t->funct.functline = sfgetu(infile); 140 t->funct.functnam = r_string(); 141 savstak = stakcreate(STAK_SMALL); 142 savstak = stakinstall(savstak, 0); 143 slp = (struct slnod*)stakalloc(sizeof(struct slnod)); 144 slp->slchild = 0; 145 slp->slnext = sh.st.staklist; 146 sh.st.staklist = 0; 147 t->funct.functtre = r_tree(); 148 t->funct.functstak = slp; 149 slp->slptr = stakinstall(savstak,0); 150 slp->slchild = sh.st.staklist; 151 t->funct.functargs = (struct comnod*)r_tree(); 152 break; 153 } 154 case TTST: 155 t = getnode(tstnod); 156 t->tst.tstline = sfgetu(infile); 157 if((type&TPAREN)==TPAREN) 158 t->lst.lstlef = r_tree(); 159 else 160 { 161 t->lst.lstlef = (Shnode_t*)r_arg(); 162 if((type&TBINARY)) 163 t->lst.lstrit = (Shnode_t*)r_arg(); 164 } 165 } 166 if(t) 167 t->tre.tretyp = type; 168 return(t); 169 } 170 171 static struct argnod *r_arg(void) 172 { 173 register struct argnod *ap=0, *apold, *aptop=0; 174 register long l; 175 while((l=sfgetu(infile))>0) 176 { 177 ap = (struct argnod*)stakseek((unsigned)l+ARGVAL); 178 if(!aptop) 179 aptop = ap; 180 else 181 apold->argnxt.ap = ap; 182 if(--l > 0) 183 { 184 sfread(infile,ap->argval,(size_t)l); 185 ccmaps(ap->argval, l, CC_ASCII, CC_NATIVE); 186 } 187 ap->argval[l] = 0; 188 ap->argchn.cp = 0; 189 ap->argflag = sfgetc(infile); 190 if(ap->argflag&ARG_MESSAGE) 191 { 192 /* replace international messages */ 193 ap = sh_endword(1); 194 ap->argflag &= ~ARG_MESSAGE; 195 if(!(ap->argflag&(ARG_MAC|ARG_EXP))) 196 ap = sh_endword(0); 197 else 198 { 199 ap = (struct argnod*)stakfreeze(0); 200 if(ap->argflag==0) 201 ap->argflag = ARG_RAW; 202 } 203 } 204 else 205 ap = (struct argnod*)stakfreeze(0); 206 if(*ap->argval==0 && (ap->argflag&~ARG_APPEND)==0) 207 { 208 struct fornod *fp = (struct fornod*)getnode(fornod); 209 fp->fortyp = sfgetu(infile); 210 fp->fortre = r_tree(); 211 fp->fornam = ap->argval+1; 212 ap->argchn.ap = (struct argnod*)fp; 213 } 214 apold = ap; 215 } 216 if(ap) 217 ap->argnxt.ap = 0; 218 return(aptop); 219 } 220 221 static struct ionod *r_redirect(void) 222 { 223 register long l; 224 register struct ionod *iop=0, *iopold, *ioptop=0; 225 while((l=sfgetl(infile))>=0) 226 { 227 iop = (struct ionod*)getnode(ionod); 228 if(!ioptop) 229 ioptop = iop; 230 else 231 iopold->ionxt = iop; 232 iop->iofile = l; 233 iop->ioname = r_string(); 234 if(iop->iodelim = r_string()) 235 { 236 iop->iosize = sfgetl(infile); 237 if(sh.heredocs) 238 iop->iooffset = sfseek(sh.heredocs,(off_t)0,SEEK_END); 239 else 240 { 241 sh.heredocs = sftmp(512); 242 iop->iooffset = 0; 243 } 244 sfmove(infile,sh.heredocs, iop->iosize, -1); 245 } 246 iopold = iop; 247 if(iop->iofile&IOVNM) 248 iop->iovname = r_string(); 249 else 250 iop->iovname = 0; 251 iop->iofile &= ~IOVNM; 252 } 253 if(iop) 254 iop->ionxt = 0; 255 return(ioptop); 256 } 257 258 static void r_comarg(struct comnod *com) 259 { 260 char *cmdname=0; 261 com->comio = r_redirect(); 262 com->comset = r_arg(); 263 com->comstate = 0; 264 if(com->comtyp&COMSCAN) 265 { 266 com->comarg = r_arg(); 267 if(com->comarg->argflag==ARG_RAW) 268 cmdname = com->comarg->argval; 269 } 270 else if(com->comarg = (struct argnod*)r_comlist()) 271 cmdname = ((struct dolnod*)(com->comarg))->dolval[ARG_SPARE]; 272 com->comline = sfgetu(infile); 273 com->comnamq = 0; 274 if(cmdname) 275 { 276 char *cp; 277 com->comnamp = (void*)nv_search(cmdname,sh.fun_tree,0); 278 if(com->comnamp && (cp =strrchr(cmdname+1,'.'))) 279 { 280 *cp = 0; 281 com->comnamp = (void*)nv_open(cmdname,sh.var_tree,NV_VARNAME|NV_NOADD|NV_NOARRAY); 282 *cp = '.'; 283 } 284 } 285 else 286 com->comnamp = 0; 287 } 288 289 static struct dolnod *r_comlist(void) 290 { 291 register struct dolnod *dol=0; 292 register long l; 293 register char **argv; 294 if((l=sfgetl(infile))>0) 295 { 296 dol = (struct dolnod*)stakalloc(sizeof(struct dolnod) + sizeof(char*)*(l+ARG_SPARE)); 297 dol->dolnum = l; 298 dol->dolbot = ARG_SPARE; 299 argv = dol->dolval+ARG_SPARE; 300 while(*argv++ = r_string()); 301 } 302 return(dol); 303 } 304 305 static struct regnod *r_switch(void) 306 { 307 register long l; 308 struct regnod *reg=0,*regold,*regtop=0; 309 while((l=sfgetl(infile))>=0) 310 { 311 reg = (struct regnod*)getnode(regnod); 312 if(!regtop) 313 regtop = reg; 314 else 315 regold->regnxt = reg; 316 reg->regflag = l; 317 reg->regptr = r_arg(); 318 reg->regcom = r_tree(); 319 regold = reg; 320 } 321 if(reg) 322 reg->regnxt = 0; 323 return(regtop); 324 } 325 326 static char *r_string(void) 327 { 328 register Sfio_t *in = infile; 329 register unsigned long l = sfgetu(in); 330 register char *ptr; 331 if(l == 0) 332 return(NIL(char*)); 333 ptr = stakalloc((unsigned)l); 334 if(--l > 0) 335 { 336 if(sfread(in,ptr,(size_t)l)!=(size_t)l) 337 return(NIL(char*)); 338 ccmaps(ptr, l, CC_ASCII, CC_NATIVE); 339 } 340 ptr[l] = 0; 341 return(ptr); 342 } 343