1bd389b36SDavid du Colombier #include <u.h> 2bd389b36SDavid du Colombier #include <libc.h> 3bd389b36SDavid du Colombier #include <bio.h> 4bd389b36SDavid du Colombier #include <ctype.h> 5bd389b36SDavid du Colombier #include <mach.h> 6bd389b36SDavid du Colombier #define Extern extern 7bd389b36SDavid du Colombier #include "acid.h" 8bd389b36SDavid du Colombier 9bd389b36SDavid du Colombier void 10bd389b36SDavid du Colombier error(char *fmt, ...) 11bd389b36SDavid du Colombier { 12*219b2ee8SDavid du Colombier int i; 13*219b2ee8SDavid du Colombier char buf[2048]; 14*219b2ee8SDavid du Colombier 15*219b2ee8SDavid du Colombier /* Unstack io channels */ 16*219b2ee8SDavid du Colombier if(iop != 0) { 17*219b2ee8SDavid du Colombier for(i = 1; i < iop; i++) 18*219b2ee8SDavid du Colombier Bterm(io[i]); 19*219b2ee8SDavid du Colombier bout = io[0]; 20*219b2ee8SDavid du Colombier iop = 0; 21*219b2ee8SDavid du Colombier } 22bd389b36SDavid du Colombier 23bd389b36SDavid du Colombier ret = 0; 24bd389b36SDavid du Colombier gotint = 0; 25bd389b36SDavid du Colombier Bflush(bout); 26*219b2ee8SDavid du Colombier if(silent) 27*219b2ee8SDavid du Colombier silent = 0; 28*219b2ee8SDavid du Colombier else { 29bd389b36SDavid du Colombier doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)); 30*219b2ee8SDavid du Colombier fprint(2, "%L: (error) %s\n", buf); 31*219b2ee8SDavid du Colombier } 32*219b2ee8SDavid du Colombier while(popio()) 33*219b2ee8SDavid du Colombier ; 34*219b2ee8SDavid du Colombier interactive = 1; 35bd389b36SDavid du Colombier longjmp(err, 1); 36bd389b36SDavid du Colombier } 37bd389b36SDavid du Colombier 38bd389b36SDavid du Colombier void 39bd389b36SDavid du Colombier unwind(void) 40bd389b36SDavid du Colombier { 41bd389b36SDavid du Colombier int i; 42bd389b36SDavid du Colombier Lsym *s; 43bd389b36SDavid du Colombier Value *v; 44bd389b36SDavid du Colombier 45bd389b36SDavid du Colombier for(i = 0; i < Hashsize; i++) { 46bd389b36SDavid du Colombier for(s = hash[i]; s; s = s->hash) { 47bd389b36SDavid du Colombier while(s->v->pop) { 48bd389b36SDavid du Colombier v = s->v->pop; 49bd389b36SDavid du Colombier free(s->v); 50bd389b36SDavid du Colombier s->v = v; 51bd389b36SDavid du Colombier } 52bd389b36SDavid du Colombier } 53bd389b36SDavid du Colombier } 54bd389b36SDavid du Colombier } 55bd389b36SDavid du Colombier 56bd389b36SDavid du Colombier void 57bd389b36SDavid du Colombier execute(Node *n) 58bd389b36SDavid du Colombier { 59bd389b36SDavid du Colombier Value *v; 60bd389b36SDavid du Colombier Lsym *sl; 61bd389b36SDavid du Colombier Node *l, *r; 62bd389b36SDavid du Colombier int i, s, e; 63*219b2ee8SDavid du Colombier Node res, xx; 64bd389b36SDavid du Colombier static int stmnt; 65bd389b36SDavid du Colombier 66bd389b36SDavid du Colombier if(gotint) 67bd389b36SDavid du Colombier error("interrupted"); 68bd389b36SDavid du Colombier 69bd389b36SDavid du Colombier if(n == 0) 70bd389b36SDavid du Colombier return; 71bd389b36SDavid du Colombier 72*219b2ee8SDavid du Colombier if(stmnt++ > 5000) { 73bd389b36SDavid du Colombier Bflush(bout); 74bd389b36SDavid du Colombier stmnt = 0; 75bd389b36SDavid du Colombier } 76bd389b36SDavid du Colombier 77bd389b36SDavid du Colombier l = n->left; 78bd389b36SDavid du Colombier r = n->right; 79bd389b36SDavid du Colombier 80bd389b36SDavid du Colombier switch(n->op) { 81bd389b36SDavid du Colombier default: 82bd389b36SDavid du Colombier expr(n, &res); 83*219b2ee8SDavid du Colombier if(ret || (res.type == TLIST && res.l == 0)) 84*219b2ee8SDavid du Colombier break; 85*219b2ee8SDavid du Colombier prnt->right = &res; 86*219b2ee8SDavid du Colombier expr(prnt, &xx); 87*219b2ee8SDavid du Colombier break; 88*219b2ee8SDavid du Colombier case OASGN: 89*219b2ee8SDavid du Colombier case OCALL: 90*219b2ee8SDavid du Colombier expr(n, &res); 91bd389b36SDavid du Colombier break; 92bd389b36SDavid du Colombier case OCOMPLEX: 93*219b2ee8SDavid du Colombier decl(n); 94bd389b36SDavid du Colombier break; 95bd389b36SDavid du Colombier case OLOCAL: 96*219b2ee8SDavid du Colombier for(n = n->left; n; n = n->left) { 97bd389b36SDavid du Colombier if(ret == 0) 98bd389b36SDavid du Colombier error("local not in function"); 99bd389b36SDavid du Colombier sl = n->sym; 100bd389b36SDavid du Colombier if(sl->v->ret == ret) 101*219b2ee8SDavid du Colombier error("%s declared twice", sl->name); 102bd389b36SDavid du Colombier v = gmalloc(sizeof(Value)); 103bd389b36SDavid du Colombier v->ret = ret; 104bd389b36SDavid du Colombier v->pop = sl->v; 105bd389b36SDavid du Colombier sl->v = v; 106bd389b36SDavid du Colombier v->scope = 0; 107bd389b36SDavid du Colombier *(ret->tail) = sl; 108bd389b36SDavid du Colombier ret->tail = &v->scope; 109bd389b36SDavid du Colombier v->set = 0; 110*219b2ee8SDavid du Colombier } 111bd389b36SDavid du Colombier break; 112bd389b36SDavid du Colombier case ORET: 113bd389b36SDavid du Colombier if(ret == 0) 114bd389b36SDavid du Colombier error("return not in function"); 115bd389b36SDavid du Colombier expr(n->left, ret->val); 116bd389b36SDavid du Colombier longjmp(ret->rlab, 1); 117bd389b36SDavid du Colombier case OLIST: 118bd389b36SDavid du Colombier execute(n->left); 119bd389b36SDavid du Colombier execute(n->right); 120bd389b36SDavid du Colombier break; 121bd389b36SDavid du Colombier case OIF: 122bd389b36SDavid du Colombier expr(l, &res); 123bd389b36SDavid du Colombier if(r && r->op == OELSE) { 124bd389b36SDavid du Colombier if(bool(&res)) 125bd389b36SDavid du Colombier execute(r->left); 126bd389b36SDavid du Colombier else 127bd389b36SDavid du Colombier execute(r->right); 128bd389b36SDavid du Colombier } 129bd389b36SDavid du Colombier else if(bool(&res)) 130bd389b36SDavid du Colombier execute(r); 131bd389b36SDavid du Colombier break; 132bd389b36SDavid du Colombier case OWHILE: 133bd389b36SDavid du Colombier for(;;) { 134bd389b36SDavid du Colombier expr(l, &res); 135bd389b36SDavid du Colombier if(!bool(&res)) 136bd389b36SDavid du Colombier break; 137bd389b36SDavid du Colombier execute(r); 138bd389b36SDavid du Colombier } 139bd389b36SDavid du Colombier break; 140bd389b36SDavid du Colombier case ODO: 141bd389b36SDavid du Colombier expr(l->left, &res); 142bd389b36SDavid du Colombier if(res.type != TINT) 143*219b2ee8SDavid du Colombier error("loop must have integer start"); 144bd389b36SDavid du Colombier s = res.ival; 145bd389b36SDavid du Colombier expr(l->right, &res); 146bd389b36SDavid du Colombier if(res.type != TINT) 147*219b2ee8SDavid du Colombier error("loop must have integer end"); 148bd389b36SDavid du Colombier e = res.ival; 149*219b2ee8SDavid du Colombier for(i = s; i <= e; i++) 150bd389b36SDavid du Colombier execute(r); 151bd389b36SDavid du Colombier break; 152bd389b36SDavid du Colombier } 153bd389b36SDavid du Colombier } 154bd389b36SDavid du Colombier 155bd389b36SDavid du Colombier int 156bd389b36SDavid du Colombier bool(Node *n) 157bd389b36SDavid du Colombier { 158bd389b36SDavid du Colombier int true = 0; 159bd389b36SDavid du Colombier 160bd389b36SDavid du Colombier if(n->op != OCONST) 161bd389b36SDavid du Colombier fatal("bool: not const"); 162bd389b36SDavid du Colombier 163bd389b36SDavid du Colombier switch(n->type) { 164bd389b36SDavid du Colombier case TINT: 165bd389b36SDavid du Colombier if(n->ival != 0) 166bd389b36SDavid du Colombier true = 1; 167bd389b36SDavid du Colombier break; 168bd389b36SDavid du Colombier case TFLOAT: 169bd389b36SDavid du Colombier if(n->fval != 0.0) 170bd389b36SDavid du Colombier true = 1; 171bd389b36SDavid du Colombier break; 172bd389b36SDavid du Colombier case TSTRING: 173bd389b36SDavid du Colombier if(n->string->len) 174bd389b36SDavid du Colombier true = 1; 175bd389b36SDavid du Colombier break; 176bd389b36SDavid du Colombier case TLIST: 177bd389b36SDavid du Colombier if(n->l) 178bd389b36SDavid du Colombier true = 1; 179bd389b36SDavid du Colombier break; 180bd389b36SDavid du Colombier } 181bd389b36SDavid du Colombier return true; 182bd389b36SDavid du Colombier } 183bd389b36SDavid du Colombier 184bd389b36SDavid du Colombier void 185*219b2ee8SDavid du Colombier convflt(Node *r, char *flt) 186*219b2ee8SDavid du Colombier { 187*219b2ee8SDavid du Colombier char c; 188*219b2ee8SDavid du Colombier 189*219b2ee8SDavid du Colombier c = flt[0]; 190*219b2ee8SDavid du Colombier if(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) { 191*219b2ee8SDavid du Colombier r->type = TSTRING; 192*219b2ee8SDavid du Colombier r->fmt = 's'; 193*219b2ee8SDavid du Colombier r->string = strnode(flt); 194*219b2ee8SDavid du Colombier } 195*219b2ee8SDavid du Colombier else { 196*219b2ee8SDavid du Colombier r->type = TFLOAT; 197*219b2ee8SDavid du Colombier r->fval = atof(flt); 198*219b2ee8SDavid du Colombier } 199*219b2ee8SDavid du Colombier } 200*219b2ee8SDavid du Colombier 201*219b2ee8SDavid du Colombier void 202bd389b36SDavid du Colombier indir(Map *m, ulong addr, char fmt, Node *r) 203bd389b36SDavid du Colombier { 204bd389b36SDavid du Colombier int i; 205*219b2ee8SDavid du Colombier long ival; 206*219b2ee8SDavid du Colombier int ret; 207bd389b36SDavid du Colombier uchar cval; 208bd389b36SDavid du Colombier ushort sval; 209*219b2ee8SDavid du Colombier char buf[512], reg[12]; 210bd389b36SDavid du Colombier 211bd389b36SDavid du Colombier r->op = OCONST; 212bd389b36SDavid du Colombier r->fmt = fmt; 213bd389b36SDavid du Colombier switch(fmt) { 214bd389b36SDavid du Colombier default: 215bd389b36SDavid du Colombier error("bad pointer format '%c' for *", fmt); 216bd389b36SDavid du Colombier case 'c': 217bd389b36SDavid du Colombier case 'C': 218bd389b36SDavid du Colombier case 'b': 219bd389b36SDavid du Colombier r->type = TINT; 220*219b2ee8SDavid du Colombier ret = get1(m, addr, &cval, 1); 221*219b2ee8SDavid du Colombier if (ret < 0) 222*219b2ee8SDavid du Colombier error("indir: %r"); 223bd389b36SDavid du Colombier r->ival = cval; 224bd389b36SDavid du Colombier break; 225bd389b36SDavid du Colombier case 'x': 226bd389b36SDavid du Colombier case 'd': 227bd389b36SDavid du Colombier case 'u': 228bd389b36SDavid du Colombier case 'o': 229bd389b36SDavid du Colombier case 'q': 230*219b2ee8SDavid du Colombier case 'r': 231bd389b36SDavid du Colombier r->type = TINT; 232*219b2ee8SDavid du Colombier ret = get2(m, addr, &sval); 233*219b2ee8SDavid du Colombier if (ret < 0) 234*219b2ee8SDavid du Colombier error("indir: %r"); 235bd389b36SDavid du Colombier r->ival = sval; 236bd389b36SDavid du Colombier break; 237*219b2ee8SDavid du Colombier case 'a': 238*219b2ee8SDavid du Colombier case 'A': 239*219b2ee8SDavid du Colombier case 'B': 240bd389b36SDavid du Colombier case 'X': 241bd389b36SDavid du Colombier case 'D': 242bd389b36SDavid du Colombier case 'U': 243bd389b36SDavid du Colombier case 'O': 244bd389b36SDavid du Colombier case 'Q': 245bd389b36SDavid du Colombier case 'Y': 246bd389b36SDavid du Colombier r->type = TINT; 247*219b2ee8SDavid du Colombier ret = get4(m, addr, &ival); 248*219b2ee8SDavid du Colombier if (ret < 0) 249*219b2ee8SDavid du Colombier error("indir: %r"); 250bd389b36SDavid du Colombier r->ival = ival; 251bd389b36SDavid du Colombier break; 252bd389b36SDavid du Colombier case 's': 253bd389b36SDavid du Colombier r->type = TSTRING; 254bd389b36SDavid du Colombier for(i = 0; i < sizeof(buf)-1; i++) { 255*219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)&buf[i], 1); 256*219b2ee8SDavid du Colombier if (ret < 0) 257*219b2ee8SDavid du Colombier error("indir: %r"); 258bd389b36SDavid du Colombier addr++; 259bd389b36SDavid du Colombier if(buf[i] == '\0') 260bd389b36SDavid du Colombier break; 261bd389b36SDavid du Colombier } 262bd389b36SDavid du Colombier buf[i] = 0; 263*219b2ee8SDavid du Colombier if(i == 0) 264*219b2ee8SDavid du Colombier strcpy(buf, "(null)"); 265bd389b36SDavid du Colombier r->string = strnode(buf); 266bd389b36SDavid du Colombier break; 267bd389b36SDavid du Colombier case 'R': 268bd389b36SDavid du Colombier r->type = TSTRING; 269*219b2ee8SDavid du Colombier for(i = 0; i < sizeof(buf)-2; i += 2) { 270*219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)&buf[i], 2); 271*219b2ee8SDavid du Colombier if (ret < 0) 272*219b2ee8SDavid du Colombier error("indir: %r"); 273bd389b36SDavid du Colombier addr += 2; 274bd389b36SDavid du Colombier if(buf[i] == 0 && buf[i+1] == 0) 275bd389b36SDavid du Colombier break; 276bd389b36SDavid du Colombier } 277*219b2ee8SDavid du Colombier buf[i++] = 0; 278bd389b36SDavid du Colombier buf[i] = 0; 279*219b2ee8SDavid du Colombier r->string = runenode((Rune*)buf); 280bd389b36SDavid du Colombier break; 281bd389b36SDavid du Colombier case 'i': 282bd389b36SDavid du Colombier case 'I': 283*219b2ee8SDavid du Colombier if ((*machdata->das)(m, addr, fmt, buf, sizeof(buf)) < 0) 284*219b2ee8SDavid du Colombier error("indir: %r"); 285bd389b36SDavid du Colombier r->type = TSTRING; 286bd389b36SDavid du Colombier r->fmt = 's'; 287*219b2ee8SDavid du Colombier r->string = strnode(buf); 288bd389b36SDavid du Colombier break; 289bd389b36SDavid du Colombier case 'f': 290*219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)buf, mach->szfloat); 291*219b2ee8SDavid du Colombier if (ret < 0) 292*219b2ee8SDavid du Colombier error("indir: %r"); 293*219b2ee8SDavid du Colombier machdata->sftos(buf, sizeof(buf), (void*) buf); 294*219b2ee8SDavid du Colombier convflt(r, buf); 295*219b2ee8SDavid du Colombier break; 296*219b2ee8SDavid du Colombier case 'g': 297*219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)buf, mach->szfloat); 298*219b2ee8SDavid du Colombier if (ret < 0) 299*219b2ee8SDavid du Colombier error("indir: %r"); 300*219b2ee8SDavid du Colombier machdata->sftos(buf, sizeof(buf), (void*) buf); 301*219b2ee8SDavid du Colombier r->type = TSTRING; 302*219b2ee8SDavid du Colombier r->string = strnode(buf); 303bd389b36SDavid du Colombier break; 304bd389b36SDavid du Colombier case 'F': 305*219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)buf, mach->szdouble); 306*219b2ee8SDavid du Colombier if (ret < 0) 307*219b2ee8SDavid du Colombier error("indir: %r"); 308*219b2ee8SDavid du Colombier machdata->dftos(buf, sizeof(buf), (void*) buf); 309*219b2ee8SDavid du Colombier convflt(r, buf); 310*219b2ee8SDavid du Colombier break; 311*219b2ee8SDavid du Colombier case '3': /* little endian ieee 80 with hole in bytes 8&9 */ 312*219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)reg, 10); 313*219b2ee8SDavid du Colombier if (ret < 0) 314*219b2ee8SDavid du Colombier error("indir: %r"); 315*219b2ee8SDavid du Colombier memmove(reg+10, reg+8, 2); /* open hole */ 316*219b2ee8SDavid du Colombier memset(reg+8, 0, 2); /* fill it */ 317*219b2ee8SDavid du Colombier leieee80ftos(buf, sizeof(buf), reg); 318*219b2ee8SDavid du Colombier convflt(r, buf); 319*219b2ee8SDavid du Colombier break; 320*219b2ee8SDavid du Colombier case '8': /* big-endian ieee 80 */ 321*219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)reg, 10); 322*219b2ee8SDavid du Colombier if (ret < 0) 323*219b2ee8SDavid du Colombier error("indir: %r"); 324*219b2ee8SDavid du Colombier beieee80ftos(buf, sizeof(buf), reg); 325*219b2ee8SDavid du Colombier convflt(r, buf); 326*219b2ee8SDavid du Colombier break; 327*219b2ee8SDavid du Colombier case 'G': 328*219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)buf, mach->szdouble); 329*219b2ee8SDavid du Colombier if (ret < 0) 330*219b2ee8SDavid du Colombier error("indir: %r"); 331*219b2ee8SDavid du Colombier machdata->dftos(buf, sizeof(buf), (void*) buf); 332*219b2ee8SDavid du Colombier r->type = TSTRING; 333*219b2ee8SDavid du Colombier r->string = strnode(buf); 334bd389b36SDavid du Colombier break; 335bd389b36SDavid du Colombier } 336bd389b36SDavid du Colombier } 337bd389b36SDavid du Colombier 338bd389b36SDavid du Colombier void 339bd389b36SDavid du Colombier windir(Map *m, Node *addr, Node *rval, Node *r) 340bd389b36SDavid du Colombier { 341bd389b36SDavid du Colombier uchar cval; 342bd389b36SDavid du Colombier ushort sval; 343bd389b36SDavid du Colombier Node res, aes; 344*219b2ee8SDavid du Colombier int ret; 345bd389b36SDavid du Colombier 346bd389b36SDavid du Colombier if(m == 0) 347bd389b36SDavid du Colombier error("no map for */@="); 348bd389b36SDavid du Colombier 349bd389b36SDavid du Colombier expr(rval, &res); 350bd389b36SDavid du Colombier expr(addr, &aes); 351bd389b36SDavid du Colombier 352bd389b36SDavid du Colombier if(aes.type != TINT) 353bd389b36SDavid du Colombier error("bad type lhs of @/*"); 354bd389b36SDavid du Colombier 355*219b2ee8SDavid du Colombier if(m != cormap && wtflag == 0) 356*219b2ee8SDavid du Colombier error("not in write mode"); 357*219b2ee8SDavid du Colombier 358bd389b36SDavid du Colombier r->type = res.type; 359bd389b36SDavid du Colombier r->fmt = res.fmt; 360bd389b36SDavid du Colombier r->Store = res.Store; 361bd389b36SDavid du Colombier 362bd389b36SDavid du Colombier switch(res.fmt) { 363bd389b36SDavid du Colombier default: 364bd389b36SDavid du Colombier error("bad pointer format '%c' for */@=", res.fmt); 365bd389b36SDavid du Colombier case 'c': 366bd389b36SDavid du Colombier case 'C': 367bd389b36SDavid du Colombier case 'b': 368bd389b36SDavid du Colombier cval = res.ival; 369*219b2ee8SDavid du Colombier ret = put1(m, aes.ival, &cval, 1); 370bd389b36SDavid du Colombier break; 371bd389b36SDavid du Colombier case 'r': 372bd389b36SDavid du Colombier case 'x': 373bd389b36SDavid du Colombier case 'd': 374bd389b36SDavid du Colombier case 'u': 375bd389b36SDavid du Colombier case 'o': 376bd389b36SDavid du Colombier sval = res.ival; 377*219b2ee8SDavid du Colombier ret = put2(m, aes.ival, sval); 378bd389b36SDavid du Colombier r->ival = sval; 379bd389b36SDavid du Colombier break; 380*219b2ee8SDavid du Colombier case 'a': 381*219b2ee8SDavid du Colombier case 'A': 382*219b2ee8SDavid du Colombier case 'B': 383bd389b36SDavid du Colombier case 'X': 384bd389b36SDavid du Colombier case 'D': 385bd389b36SDavid du Colombier case 'U': 386bd389b36SDavid du Colombier case 'O': 387bd389b36SDavid du Colombier case 'Y': 388*219b2ee8SDavid du Colombier ret = put4(m, aes.ival, res.ival); 389bd389b36SDavid du Colombier break; 390bd389b36SDavid du Colombier case 's': 391bd389b36SDavid du Colombier case 'R': 392*219b2ee8SDavid du Colombier ret = put1(m, aes.ival, (uchar*)res.string->string, res.string->len); 393bd389b36SDavid du Colombier break; 394bd389b36SDavid du Colombier } 395*219b2ee8SDavid du Colombier if (ret < 0) 396*219b2ee8SDavid du Colombier error("windir: %r"); 397bd389b36SDavid du Colombier } 398bd389b36SDavid du Colombier 399bd389b36SDavid du Colombier void 400bd389b36SDavid du Colombier call(char *fn, Node *parameters, Node *local, Node *body, Node *retexp) 401bd389b36SDavid du Colombier { 402bd389b36SDavid du Colombier int np, i; 403bd389b36SDavid du Colombier Rplace rlab; 404bd389b36SDavid du Colombier Node *n, res; 405bd389b36SDavid du Colombier Value *v, *f; 406bd389b36SDavid du Colombier Lsym *s, *next; 407bd389b36SDavid du Colombier Node *avp[Maxarg], *ava[Maxarg]; 408bd389b36SDavid du Colombier 409*219b2ee8SDavid du Colombier rlab.local = 0; 410*219b2ee8SDavid du Colombier 411bd389b36SDavid du Colombier na = 0; 412bd389b36SDavid du Colombier flatten(avp, parameters); 413bd389b36SDavid du Colombier np = na; 414bd389b36SDavid du Colombier na = 0; 415bd389b36SDavid du Colombier flatten(ava, local); 416bd389b36SDavid du Colombier if(np != na) { 417bd389b36SDavid du Colombier if(np < na) 418bd389b36SDavid du Colombier error("%s: too few arguments", fn); 419bd389b36SDavid du Colombier error("%s: too many arguments", fn); 420bd389b36SDavid du Colombier } 421bd389b36SDavid du Colombier 422bd389b36SDavid du Colombier rlab.tail = &rlab.local; 423bd389b36SDavid du Colombier 424bd389b36SDavid du Colombier ret = &rlab; 425bd389b36SDavid du Colombier for(i = 0; i < np; i++) { 426bd389b36SDavid du Colombier n = ava[i]; 427*219b2ee8SDavid du Colombier switch(n->op) { 428*219b2ee8SDavid du Colombier default: 429bd389b36SDavid du Colombier error("%s: %d formal not a name", fn, i); 430*219b2ee8SDavid du Colombier case ONAME: 431bd389b36SDavid du Colombier expr(avp[i], &res); 432bd389b36SDavid du Colombier s = n->sym; 433*219b2ee8SDavid du Colombier break; 434*219b2ee8SDavid du Colombier case OINDM: 435*219b2ee8SDavid du Colombier res.cc = avp[i]; 436*219b2ee8SDavid du Colombier res.type = TCODE; 437*219b2ee8SDavid du Colombier res.comt = 0; 438*219b2ee8SDavid du Colombier if(n->left->op != ONAME) 439*219b2ee8SDavid du Colombier error("%s: %d formal not a name", fn, i); 440*219b2ee8SDavid du Colombier s = n->left->sym; 441*219b2ee8SDavid du Colombier break; 442*219b2ee8SDavid du Colombier } 443bd389b36SDavid du Colombier if(s->v->ret == ret) 444bd389b36SDavid du Colombier error("%s already declared at this scope", s->name); 445bd389b36SDavid du Colombier 446bd389b36SDavid du Colombier v = gmalloc(sizeof(Value)); 447bd389b36SDavid du Colombier v->ret = ret; 448bd389b36SDavid du Colombier v->pop = s->v; 449bd389b36SDavid du Colombier s->v = v; 450bd389b36SDavid du Colombier v->scope = 0; 451bd389b36SDavid du Colombier *(rlab.tail) = s; 452bd389b36SDavid du Colombier rlab.tail = &v->scope; 453bd389b36SDavid du Colombier 454bd389b36SDavid du Colombier v->Store = res.Store; 455bd389b36SDavid du Colombier v->type = res.type; 456bd389b36SDavid du Colombier v->set = 1; 457bd389b36SDavid du Colombier } 458bd389b36SDavid du Colombier 459bd389b36SDavid du Colombier ret->val = retexp; 460bd389b36SDavid du Colombier if(setjmp(rlab.rlab) == 0) 461bd389b36SDavid du Colombier execute(body); 462bd389b36SDavid du Colombier 463bd389b36SDavid du Colombier for(s = rlab.local; s; s = next) { 464bd389b36SDavid du Colombier f = s->v; 465bd389b36SDavid du Colombier next = f->scope; 466bd389b36SDavid du Colombier s->v = f->pop; 467bd389b36SDavid du Colombier free(f); 468bd389b36SDavid du Colombier } 469bd389b36SDavid du Colombier } 470