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 { 12219b2ee8SDavid du Colombier int i; 13219b2ee8SDavid du Colombier char buf[2048]; 14*7dd7cddfSDavid du Colombier va_list arg; 15219b2ee8SDavid du Colombier 16219b2ee8SDavid du Colombier /* Unstack io channels */ 17219b2ee8SDavid du Colombier if(iop != 0) { 18219b2ee8SDavid du Colombier for(i = 1; i < iop; i++) 19219b2ee8SDavid du Colombier Bterm(io[i]); 20219b2ee8SDavid du Colombier bout = io[0]; 21219b2ee8SDavid du Colombier iop = 0; 22219b2ee8SDavid du Colombier } 23bd389b36SDavid du Colombier 24bd389b36SDavid du Colombier ret = 0; 25bd389b36SDavid du Colombier gotint = 0; 26bd389b36SDavid du Colombier Bflush(bout); 27219b2ee8SDavid du Colombier if(silent) 28219b2ee8SDavid du Colombier silent = 0; 29219b2ee8SDavid du Colombier else { 30*7dd7cddfSDavid du Colombier va_start(arg, fmt); 31*7dd7cddfSDavid du Colombier doprint(buf, buf+sizeof(buf), fmt, arg); 32*7dd7cddfSDavid du Colombier va_end(arg); 33219b2ee8SDavid du Colombier fprint(2, "%L: (error) %s\n", buf); 34219b2ee8SDavid du Colombier } 35219b2ee8SDavid du Colombier while(popio()) 36219b2ee8SDavid du Colombier ; 37219b2ee8SDavid du Colombier interactive = 1; 38bd389b36SDavid du Colombier longjmp(err, 1); 39bd389b36SDavid du Colombier } 40bd389b36SDavid du Colombier 41bd389b36SDavid du Colombier void 42bd389b36SDavid du Colombier unwind(void) 43bd389b36SDavid du Colombier { 44bd389b36SDavid du Colombier int i; 45bd389b36SDavid du Colombier Lsym *s; 46bd389b36SDavid du Colombier Value *v; 47bd389b36SDavid du Colombier 48bd389b36SDavid du Colombier for(i = 0; i < Hashsize; i++) { 49bd389b36SDavid du Colombier for(s = hash[i]; s; s = s->hash) { 50bd389b36SDavid du Colombier while(s->v->pop) { 51bd389b36SDavid du Colombier v = s->v->pop; 52bd389b36SDavid du Colombier free(s->v); 53bd389b36SDavid du Colombier s->v = v; 54bd389b36SDavid du Colombier } 55bd389b36SDavid du Colombier } 56bd389b36SDavid du Colombier } 57bd389b36SDavid du Colombier } 58bd389b36SDavid du Colombier 59bd389b36SDavid du Colombier void 60bd389b36SDavid du Colombier execute(Node *n) 61bd389b36SDavid du Colombier { 62bd389b36SDavid du Colombier Value *v; 63bd389b36SDavid du Colombier Lsym *sl; 64bd389b36SDavid du Colombier Node *l, *r; 65bd389b36SDavid du Colombier int i, s, e; 66219b2ee8SDavid du Colombier Node res, xx; 67bd389b36SDavid du Colombier static int stmnt; 68bd389b36SDavid du Colombier 69bd389b36SDavid du Colombier if(gotint) 70bd389b36SDavid du Colombier error("interrupted"); 71bd389b36SDavid du Colombier 72bd389b36SDavid du Colombier if(n == 0) 73bd389b36SDavid du Colombier return; 74bd389b36SDavid du Colombier 75219b2ee8SDavid du Colombier if(stmnt++ > 5000) { 76bd389b36SDavid du Colombier Bflush(bout); 77bd389b36SDavid du Colombier stmnt = 0; 78bd389b36SDavid du Colombier } 79bd389b36SDavid du Colombier 80bd389b36SDavid du Colombier l = n->left; 81bd389b36SDavid du Colombier r = n->right; 82bd389b36SDavid du Colombier 83bd389b36SDavid du Colombier switch(n->op) { 84bd389b36SDavid du Colombier default: 85bd389b36SDavid du Colombier expr(n, &res); 86219b2ee8SDavid du Colombier if(ret || (res.type == TLIST && res.l == 0)) 87219b2ee8SDavid du Colombier break; 88219b2ee8SDavid du Colombier prnt->right = &res; 89219b2ee8SDavid du Colombier expr(prnt, &xx); 90219b2ee8SDavid du Colombier break; 91219b2ee8SDavid du Colombier case OASGN: 92219b2ee8SDavid du Colombier case OCALL: 93219b2ee8SDavid du Colombier expr(n, &res); 94bd389b36SDavid du Colombier break; 95bd389b36SDavid du Colombier case OCOMPLEX: 96219b2ee8SDavid du Colombier decl(n); 97bd389b36SDavid du Colombier break; 98bd389b36SDavid du Colombier case OLOCAL: 99219b2ee8SDavid du Colombier for(n = n->left; n; n = n->left) { 100bd389b36SDavid du Colombier if(ret == 0) 101bd389b36SDavid du Colombier error("local not in function"); 102bd389b36SDavid du Colombier sl = n->sym; 103bd389b36SDavid du Colombier if(sl->v->ret == ret) 104219b2ee8SDavid du Colombier error("%s declared twice", sl->name); 105bd389b36SDavid du Colombier v = gmalloc(sizeof(Value)); 106bd389b36SDavid du Colombier v->ret = ret; 107bd389b36SDavid du Colombier v->pop = sl->v; 108bd389b36SDavid du Colombier sl->v = v; 109bd389b36SDavid du Colombier v->scope = 0; 110bd389b36SDavid du Colombier *(ret->tail) = sl; 111bd389b36SDavid du Colombier ret->tail = &v->scope; 112bd389b36SDavid du Colombier v->set = 0; 113219b2ee8SDavid du Colombier } 114bd389b36SDavid du Colombier break; 115bd389b36SDavid du Colombier case ORET: 116bd389b36SDavid du Colombier if(ret == 0) 117bd389b36SDavid du Colombier error("return not in function"); 118bd389b36SDavid du Colombier expr(n->left, ret->val); 119bd389b36SDavid du Colombier longjmp(ret->rlab, 1); 120bd389b36SDavid du Colombier case OLIST: 121bd389b36SDavid du Colombier execute(n->left); 122bd389b36SDavid du Colombier execute(n->right); 123bd389b36SDavid du Colombier break; 124bd389b36SDavid du Colombier case OIF: 125bd389b36SDavid du Colombier expr(l, &res); 126bd389b36SDavid du Colombier if(r && r->op == OELSE) { 127bd389b36SDavid du Colombier if(bool(&res)) 128bd389b36SDavid du Colombier execute(r->left); 129bd389b36SDavid du Colombier else 130bd389b36SDavid du Colombier execute(r->right); 131bd389b36SDavid du Colombier } 132bd389b36SDavid du Colombier else if(bool(&res)) 133bd389b36SDavid du Colombier execute(r); 134bd389b36SDavid du Colombier break; 135bd389b36SDavid du Colombier case OWHILE: 136bd389b36SDavid du Colombier for(;;) { 137bd389b36SDavid du Colombier expr(l, &res); 138bd389b36SDavid du Colombier if(!bool(&res)) 139bd389b36SDavid du Colombier break; 140bd389b36SDavid du Colombier execute(r); 141bd389b36SDavid du Colombier } 142bd389b36SDavid du Colombier break; 143bd389b36SDavid du Colombier case ODO: 144bd389b36SDavid du Colombier expr(l->left, &res); 145bd389b36SDavid du Colombier if(res.type != TINT) 146219b2ee8SDavid du Colombier error("loop must have integer start"); 147bd389b36SDavid du Colombier s = res.ival; 148bd389b36SDavid du Colombier expr(l->right, &res); 149bd389b36SDavid du Colombier if(res.type != TINT) 150219b2ee8SDavid du Colombier error("loop must have integer end"); 151bd389b36SDavid du Colombier e = res.ival; 152219b2ee8SDavid du Colombier for(i = s; i <= e; i++) 153bd389b36SDavid du Colombier execute(r); 154bd389b36SDavid du Colombier break; 155bd389b36SDavid du Colombier } 156bd389b36SDavid du Colombier } 157bd389b36SDavid du Colombier 158bd389b36SDavid du Colombier int 159bd389b36SDavid du Colombier bool(Node *n) 160bd389b36SDavid du Colombier { 161bd389b36SDavid du Colombier int true = 0; 162bd389b36SDavid du Colombier 163bd389b36SDavid du Colombier if(n->op != OCONST) 164bd389b36SDavid du Colombier fatal("bool: not const"); 165bd389b36SDavid du Colombier 166bd389b36SDavid du Colombier switch(n->type) { 167bd389b36SDavid du Colombier case TINT: 168bd389b36SDavid du Colombier if(n->ival != 0) 169bd389b36SDavid du Colombier true = 1; 170bd389b36SDavid du Colombier break; 171bd389b36SDavid du Colombier case TFLOAT: 172bd389b36SDavid du Colombier if(n->fval != 0.0) 173bd389b36SDavid du Colombier true = 1; 174bd389b36SDavid du Colombier break; 175bd389b36SDavid du Colombier case TSTRING: 176bd389b36SDavid du Colombier if(n->string->len) 177bd389b36SDavid du Colombier true = 1; 178bd389b36SDavid du Colombier break; 179bd389b36SDavid du Colombier case TLIST: 180bd389b36SDavid du Colombier if(n->l) 181bd389b36SDavid du Colombier true = 1; 182bd389b36SDavid du Colombier break; 183bd389b36SDavid du Colombier } 184bd389b36SDavid du Colombier return true; 185bd389b36SDavid du Colombier } 186bd389b36SDavid du Colombier 187bd389b36SDavid du Colombier void 188219b2ee8SDavid du Colombier convflt(Node *r, char *flt) 189219b2ee8SDavid du Colombier { 190219b2ee8SDavid du Colombier char c; 191219b2ee8SDavid du Colombier 192219b2ee8SDavid du Colombier c = flt[0]; 193219b2ee8SDavid du Colombier if(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) { 194219b2ee8SDavid du Colombier r->type = TSTRING; 195219b2ee8SDavid du Colombier r->fmt = 's'; 196219b2ee8SDavid du Colombier r->string = strnode(flt); 197219b2ee8SDavid du Colombier } 198219b2ee8SDavid du Colombier else { 199219b2ee8SDavid du Colombier r->type = TFLOAT; 200219b2ee8SDavid du Colombier r->fval = atof(flt); 201219b2ee8SDavid du Colombier } 202219b2ee8SDavid du Colombier } 203219b2ee8SDavid du Colombier 204219b2ee8SDavid du Colombier void 205bd389b36SDavid du Colombier indir(Map *m, ulong addr, char fmt, Node *r) 206bd389b36SDavid du Colombier { 207bd389b36SDavid du Colombier int i; 208219b2ee8SDavid du Colombier long ival; 209*7dd7cddfSDavid du Colombier vlong vval; 210219b2ee8SDavid du Colombier int ret; 211bd389b36SDavid du Colombier uchar cval; 212bd389b36SDavid du Colombier ushort sval; 213219b2ee8SDavid du Colombier char buf[512], reg[12]; 214bd389b36SDavid du Colombier 215bd389b36SDavid du Colombier r->op = OCONST; 216bd389b36SDavid du Colombier r->fmt = fmt; 217bd389b36SDavid du Colombier switch(fmt) { 218bd389b36SDavid du Colombier default: 219bd389b36SDavid du Colombier error("bad pointer format '%c' for *", fmt); 220bd389b36SDavid du Colombier case 'c': 221bd389b36SDavid du Colombier case 'C': 222bd389b36SDavid du Colombier case 'b': 223bd389b36SDavid du Colombier r->type = TINT; 224219b2ee8SDavid du Colombier ret = get1(m, addr, &cval, 1); 225219b2ee8SDavid du Colombier if (ret < 0) 226219b2ee8SDavid du Colombier error("indir: %r"); 227bd389b36SDavid du Colombier r->ival = cval; 228bd389b36SDavid du Colombier break; 229bd389b36SDavid du Colombier case 'x': 230bd389b36SDavid du Colombier case 'd': 231bd389b36SDavid du Colombier case 'u': 232bd389b36SDavid du Colombier case 'o': 233bd389b36SDavid du Colombier case 'q': 234219b2ee8SDavid du Colombier case 'r': 235bd389b36SDavid du Colombier r->type = TINT; 236219b2ee8SDavid du Colombier ret = get2(m, addr, &sval); 237219b2ee8SDavid du Colombier if (ret < 0) 238219b2ee8SDavid du Colombier error("indir: %r"); 239bd389b36SDavid du Colombier r->ival = sval; 240bd389b36SDavid du Colombier break; 241219b2ee8SDavid du Colombier case 'a': 242219b2ee8SDavid du Colombier case 'A': 243219b2ee8SDavid du Colombier case 'B': 244bd389b36SDavid du Colombier case 'X': 245bd389b36SDavid du Colombier case 'D': 246bd389b36SDavid du Colombier case 'U': 247bd389b36SDavid du Colombier case 'O': 248bd389b36SDavid du Colombier case 'Q': 249bd389b36SDavid du Colombier r->type = TINT; 250219b2ee8SDavid du Colombier ret = get4(m, addr, &ival); 251219b2ee8SDavid du Colombier if (ret < 0) 252219b2ee8SDavid du Colombier error("indir: %r"); 253bd389b36SDavid du Colombier r->ival = ival; 254bd389b36SDavid du Colombier break; 255*7dd7cddfSDavid du Colombier case 'V': 256*7dd7cddfSDavid du Colombier case 'W': 257*7dd7cddfSDavid du Colombier case 'Y': 258*7dd7cddfSDavid du Colombier case 'Z': 259*7dd7cddfSDavid du Colombier r->type = TINT; 260*7dd7cddfSDavid du Colombier ret = get8(m, addr, &vval); 261*7dd7cddfSDavid du Colombier if (ret < 0) 262*7dd7cddfSDavid du Colombier error("indir: %r"); 263*7dd7cddfSDavid du Colombier r->ival = vval; 264*7dd7cddfSDavid du Colombier break; 265bd389b36SDavid du Colombier case 's': 266bd389b36SDavid du Colombier r->type = TSTRING; 267bd389b36SDavid du Colombier for(i = 0; i < sizeof(buf)-1; i++) { 268219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)&buf[i], 1); 269219b2ee8SDavid du Colombier if (ret < 0) 270219b2ee8SDavid du Colombier error("indir: %r"); 271bd389b36SDavid du Colombier addr++; 272bd389b36SDavid du Colombier if(buf[i] == '\0') 273bd389b36SDavid du Colombier break; 274bd389b36SDavid du Colombier } 275bd389b36SDavid du Colombier buf[i] = 0; 276219b2ee8SDavid du Colombier if(i == 0) 277219b2ee8SDavid du Colombier strcpy(buf, "(null)"); 278bd389b36SDavid du Colombier r->string = strnode(buf); 279bd389b36SDavid du Colombier break; 280bd389b36SDavid du Colombier case 'R': 281bd389b36SDavid du Colombier r->type = TSTRING; 282219b2ee8SDavid du Colombier for(i = 0; i < sizeof(buf)-2; i += 2) { 283219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)&buf[i], 2); 284219b2ee8SDavid du Colombier if (ret < 0) 285219b2ee8SDavid du Colombier error("indir: %r"); 286bd389b36SDavid du Colombier addr += 2; 287bd389b36SDavid du Colombier if(buf[i] == 0 && buf[i+1] == 0) 288bd389b36SDavid du Colombier break; 289bd389b36SDavid du Colombier } 290219b2ee8SDavid du Colombier buf[i++] = 0; 291bd389b36SDavid du Colombier buf[i] = 0; 292219b2ee8SDavid du Colombier r->string = runenode((Rune*)buf); 293bd389b36SDavid du Colombier break; 294bd389b36SDavid du Colombier case 'i': 295bd389b36SDavid du Colombier case 'I': 296219b2ee8SDavid du Colombier if ((*machdata->das)(m, addr, fmt, buf, sizeof(buf)) < 0) 297219b2ee8SDavid du Colombier error("indir: %r"); 298bd389b36SDavid du Colombier r->type = TSTRING; 299bd389b36SDavid du Colombier r->fmt = 's'; 300219b2ee8SDavid du Colombier r->string = strnode(buf); 301bd389b36SDavid du Colombier break; 302bd389b36SDavid du Colombier case 'f': 303219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)buf, mach->szfloat); 304219b2ee8SDavid du Colombier if (ret < 0) 305219b2ee8SDavid du Colombier error("indir: %r"); 306219b2ee8SDavid du Colombier machdata->sftos(buf, sizeof(buf), (void*) buf); 307219b2ee8SDavid du Colombier convflt(r, buf); 308219b2ee8SDavid du Colombier break; 309219b2ee8SDavid du Colombier case 'g': 310219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)buf, mach->szfloat); 311219b2ee8SDavid du Colombier if (ret < 0) 312219b2ee8SDavid du Colombier error("indir: %r"); 313219b2ee8SDavid du Colombier machdata->sftos(buf, sizeof(buf), (void*) buf); 314219b2ee8SDavid du Colombier r->type = TSTRING; 315219b2ee8SDavid du Colombier r->string = strnode(buf); 316bd389b36SDavid du Colombier break; 317bd389b36SDavid du Colombier case 'F': 318219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)buf, mach->szdouble); 319219b2ee8SDavid du Colombier if (ret < 0) 320219b2ee8SDavid du Colombier error("indir: %r"); 321219b2ee8SDavid du Colombier machdata->dftos(buf, sizeof(buf), (void*) buf); 322219b2ee8SDavid du Colombier convflt(r, buf); 323219b2ee8SDavid du Colombier break; 324219b2ee8SDavid du Colombier case '3': /* little endian ieee 80 with hole in bytes 8&9 */ 325219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)reg, 10); 326219b2ee8SDavid du Colombier if (ret < 0) 327219b2ee8SDavid du Colombier error("indir: %r"); 328219b2ee8SDavid du Colombier memmove(reg+10, reg+8, 2); /* open hole */ 329219b2ee8SDavid du Colombier memset(reg+8, 0, 2); /* fill it */ 330219b2ee8SDavid du Colombier leieee80ftos(buf, sizeof(buf), reg); 331219b2ee8SDavid du Colombier convflt(r, buf); 332219b2ee8SDavid du Colombier break; 333219b2ee8SDavid du Colombier case '8': /* big-endian ieee 80 */ 334219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)reg, 10); 335219b2ee8SDavid du Colombier if (ret < 0) 336219b2ee8SDavid du Colombier error("indir: %r"); 337219b2ee8SDavid du Colombier beieee80ftos(buf, sizeof(buf), reg); 338219b2ee8SDavid du Colombier convflt(r, buf); 339219b2ee8SDavid du Colombier break; 340219b2ee8SDavid du Colombier case 'G': 341219b2ee8SDavid du Colombier ret = get1(m, addr, (uchar*)buf, mach->szdouble); 342219b2ee8SDavid du Colombier if (ret < 0) 343219b2ee8SDavid du Colombier error("indir: %r"); 344219b2ee8SDavid du Colombier machdata->dftos(buf, sizeof(buf), (void*) buf); 345219b2ee8SDavid du Colombier r->type = TSTRING; 346219b2ee8SDavid du Colombier r->string = strnode(buf); 347bd389b36SDavid du Colombier break; 348bd389b36SDavid du Colombier } 349bd389b36SDavid du Colombier } 350bd389b36SDavid du Colombier 351bd389b36SDavid du Colombier void 352bd389b36SDavid du Colombier windir(Map *m, Node *addr, Node *rval, Node *r) 353bd389b36SDavid du Colombier { 354bd389b36SDavid du Colombier uchar cval; 355bd389b36SDavid du Colombier ushort sval; 356bd389b36SDavid du Colombier Node res, aes; 357219b2ee8SDavid du Colombier int ret; 358bd389b36SDavid du Colombier 359bd389b36SDavid du Colombier if(m == 0) 360bd389b36SDavid du Colombier error("no map for */@="); 361bd389b36SDavid du Colombier 362bd389b36SDavid du Colombier expr(rval, &res); 363bd389b36SDavid du Colombier expr(addr, &aes); 364bd389b36SDavid du Colombier 365bd389b36SDavid du Colombier if(aes.type != TINT) 366bd389b36SDavid du Colombier error("bad type lhs of @/*"); 367bd389b36SDavid du Colombier 368219b2ee8SDavid du Colombier if(m != cormap && wtflag == 0) 369219b2ee8SDavid du Colombier error("not in write mode"); 370219b2ee8SDavid du Colombier 371bd389b36SDavid du Colombier r->type = res.type; 372bd389b36SDavid du Colombier r->fmt = res.fmt; 373bd389b36SDavid du Colombier r->Store = res.Store; 374bd389b36SDavid du Colombier 375bd389b36SDavid du Colombier switch(res.fmt) { 376bd389b36SDavid du Colombier default: 377bd389b36SDavid du Colombier error("bad pointer format '%c' for */@=", res.fmt); 378bd389b36SDavid du Colombier case 'c': 379bd389b36SDavid du Colombier case 'C': 380bd389b36SDavid du Colombier case 'b': 381bd389b36SDavid du Colombier cval = res.ival; 382219b2ee8SDavid du Colombier ret = put1(m, aes.ival, &cval, 1); 383bd389b36SDavid du Colombier break; 384bd389b36SDavid du Colombier case 'r': 385bd389b36SDavid du Colombier case 'x': 386bd389b36SDavid du Colombier case 'd': 387bd389b36SDavid du Colombier case 'u': 388bd389b36SDavid du Colombier case 'o': 389bd389b36SDavid du Colombier sval = res.ival; 390219b2ee8SDavid du Colombier ret = put2(m, aes.ival, sval); 391bd389b36SDavid du Colombier r->ival = sval; 392bd389b36SDavid du Colombier break; 393219b2ee8SDavid du Colombier case 'a': 394219b2ee8SDavid du Colombier case 'A': 395219b2ee8SDavid du Colombier case 'B': 396bd389b36SDavid du Colombier case 'X': 397bd389b36SDavid du Colombier case 'D': 398bd389b36SDavid du Colombier case 'U': 399bd389b36SDavid du Colombier case 'O': 400219b2ee8SDavid du Colombier ret = put4(m, aes.ival, res.ival); 401bd389b36SDavid du Colombier break; 402*7dd7cddfSDavid du Colombier case 'V': 403*7dd7cddfSDavid du Colombier case 'W': 404*7dd7cddfSDavid du Colombier case 'Y': 405*7dd7cddfSDavid du Colombier case 'Z': 406*7dd7cddfSDavid du Colombier ret = put8(m, aes.ival, res.ival); 407*7dd7cddfSDavid du Colombier break; 408bd389b36SDavid du Colombier case 's': 409bd389b36SDavid du Colombier case 'R': 410219b2ee8SDavid du Colombier ret = put1(m, aes.ival, (uchar*)res.string->string, res.string->len); 411bd389b36SDavid du Colombier break; 412bd389b36SDavid du Colombier } 413219b2ee8SDavid du Colombier if (ret < 0) 414219b2ee8SDavid du Colombier error("windir: %r"); 415bd389b36SDavid du Colombier } 416bd389b36SDavid du Colombier 417bd389b36SDavid du Colombier void 418bd389b36SDavid du Colombier call(char *fn, Node *parameters, Node *local, Node *body, Node *retexp) 419bd389b36SDavid du Colombier { 420bd389b36SDavid du Colombier int np, i; 421bd389b36SDavid du Colombier Rplace rlab; 422bd389b36SDavid du Colombier Node *n, res; 423bd389b36SDavid du Colombier Value *v, *f; 424bd389b36SDavid du Colombier Lsym *s, *next; 425bd389b36SDavid du Colombier Node *avp[Maxarg], *ava[Maxarg]; 426bd389b36SDavid du Colombier 427219b2ee8SDavid du Colombier rlab.local = 0; 428219b2ee8SDavid du Colombier 429bd389b36SDavid du Colombier na = 0; 430bd389b36SDavid du Colombier flatten(avp, parameters); 431bd389b36SDavid du Colombier np = na; 432bd389b36SDavid du Colombier na = 0; 433bd389b36SDavid du Colombier flatten(ava, local); 434bd389b36SDavid du Colombier if(np != na) { 435bd389b36SDavid du Colombier if(np < na) 436bd389b36SDavid du Colombier error("%s: too few arguments", fn); 437bd389b36SDavid du Colombier error("%s: too many arguments", fn); 438bd389b36SDavid du Colombier } 439bd389b36SDavid du Colombier 440bd389b36SDavid du Colombier rlab.tail = &rlab.local; 441bd389b36SDavid du Colombier 442bd389b36SDavid du Colombier ret = &rlab; 443bd389b36SDavid du Colombier for(i = 0; i < np; i++) { 444bd389b36SDavid du Colombier n = ava[i]; 445219b2ee8SDavid du Colombier switch(n->op) { 446219b2ee8SDavid du Colombier default: 447bd389b36SDavid du Colombier error("%s: %d formal not a name", fn, i); 448219b2ee8SDavid du Colombier case ONAME: 449bd389b36SDavid du Colombier expr(avp[i], &res); 450bd389b36SDavid du Colombier s = n->sym; 451219b2ee8SDavid du Colombier break; 452219b2ee8SDavid du Colombier case OINDM: 453219b2ee8SDavid du Colombier res.cc = avp[i]; 454219b2ee8SDavid du Colombier res.type = TCODE; 455219b2ee8SDavid du Colombier res.comt = 0; 456219b2ee8SDavid du Colombier if(n->left->op != ONAME) 457219b2ee8SDavid du Colombier error("%s: %d formal not a name", fn, i); 458219b2ee8SDavid du Colombier s = n->left->sym; 459219b2ee8SDavid du Colombier break; 460219b2ee8SDavid du Colombier } 461bd389b36SDavid du Colombier if(s->v->ret == ret) 462bd389b36SDavid du Colombier error("%s already declared at this scope", s->name); 463bd389b36SDavid du Colombier 464bd389b36SDavid du Colombier v = gmalloc(sizeof(Value)); 465bd389b36SDavid du Colombier v->ret = ret; 466bd389b36SDavid du Colombier v->pop = s->v; 467bd389b36SDavid du Colombier s->v = v; 468bd389b36SDavid du Colombier v->scope = 0; 469bd389b36SDavid du Colombier *(rlab.tail) = s; 470bd389b36SDavid du Colombier rlab.tail = &v->scope; 471bd389b36SDavid du Colombier 472bd389b36SDavid du Colombier v->Store = res.Store; 473bd389b36SDavid du Colombier v->type = res.type; 474bd389b36SDavid du Colombier v->set = 1; 475bd389b36SDavid du Colombier } 476bd389b36SDavid du Colombier 477bd389b36SDavid du Colombier ret->val = retexp; 478bd389b36SDavid du Colombier if(setjmp(rlab.rlab) == 0) 479bd389b36SDavid du Colombier execute(body); 480bd389b36SDavid du Colombier 481bd389b36SDavid du Colombier for(s = rlab.local; s; s = next) { 482bd389b36SDavid du Colombier f = s->v; 483bd389b36SDavid du Colombier next = f->scope; 484bd389b36SDavid du Colombier s->v = f->pop; 485bd389b36SDavid du Colombier free(f); 486bd389b36SDavid du Colombier } 487bd389b36SDavid du Colombier } 488