Blob
1 #include <u.h>2 #include <libc.h>3 #include <bio.h>4 #include <ctype.h>5 #include <mach.h>6 #define Extern extern7 #include "acid.h"9 void10 error(char *fmt, ...)11 {12 int i;13 char buf[2048];14 va_list arg;16 /* Unstack io channels */17 if(iop != 0) {18 for(i = 1; i < iop; i++)19 Bterm(io[i]);20 bout = io[0];21 iop = 0;22 }24 ret = 0;25 gotint = 0;26 Bflush(bout);27 if(silent)28 silent = 0;29 else {30 va_start(arg, fmt);31 vseprint(buf, buf+sizeof(buf), fmt, arg);32 va_end(arg);33 fprint(2, "%Z: (error) %s\n", buf);34 }35 while(popio())36 ;37 interactive = 1;38 longjmp(err, 1);39 }41 void42 unwind(void)43 {44 int i;45 Lsym *s;46 Value *v;48 for(i = 0; i < Hashsize; i++) {49 for(s = hash[i]; s; s = s->hash) {50 while(s->v->pop) {51 v = s->v->pop;52 free(s->v);53 s->v = v;54 }55 }56 }57 }59 void60 execute(Node *n)61 {62 Value *v;63 Lsym *sl;64 Node *l, *r;65 int i, s, e;66 Node res, xx;67 static int stmnt;69 gc();70 if(gotint)71 error("interrupted");73 if(n == 0)74 return;76 if(stmnt++ > 5000) {77 Bflush(bout);78 stmnt = 0;79 }81 l = n->left;82 r = n->right;84 switch(n->op) {85 default:86 expr(n, &res);87 if(ret || (res.type == TLIST && res.store.u.l == 0))88 break;89 prnt->right = &res;90 expr(prnt, &xx);91 break;92 case OASGN:93 case OCALL:94 expr(n, &res);95 break;96 case OCOMPLEX:97 decl(n);98 break;99 case OLOCAL:100 for(n = n->left; n; n = n->left) {101 if(ret == 0)102 error("local not in function");103 sl = n->sym;104 if(sl->v->ret == ret)105 error("%s declared twice", sl->name);106 v = gmalloc(sizeof(Value));107 v->ret = ret;108 v->pop = sl->v;109 sl->v = v;110 v->scope = 0;111 *(ret->tail) = sl;112 ret->tail = &v->scope;113 v->set = 0;114 }115 break;116 case ORET:117 if(ret == 0)118 error("return not in function");119 expr(n->left, ret->val);120 longjmp(ret->rlab, 1);121 case OLIST:122 execute(n->left);123 execute(n->right);124 break;125 case OIF:126 expr(l, &res);127 if(r && r->op == OELSE) {128 if(bool(&res))129 execute(r->left);130 else131 execute(r->right);132 }133 else if(bool(&res))134 execute(r);135 break;136 case OWHILE:137 for(;;) {138 expr(l, &res);139 if(!bool(&res))140 break;141 execute(r);142 }143 break;144 case ODO:145 expr(l->left, &res);146 if(res.type != TINT)147 error("loop must have integer start");148 s = res.store.u.ival;149 expr(l->right, &res);150 if(res.type != TINT)151 error("loop must have integer end");152 e = res.store.u.ival;153 for(i = s; i <= e; i++)154 execute(r);155 break;156 }157 }159 int160 bool(Node *n)161 {162 int true = 0;164 if(n->op != OCONST)165 fatal("bool: not const");167 switch(n->type) {168 case TINT:169 if(n->store.u.ival != 0)170 true = 1;171 break;172 case TFLOAT:173 if(n->store.u.fval != 0.0)174 true = 1;175 break;176 case TSTRING:177 if(n->store.u.string->len)178 true = 1;179 break;180 case TLIST:181 if(n->store.u.l)182 true = 1;183 break;184 }185 return true;186 }188 void189 convflt(Node *r, char *flt)190 {191 char c;193 c = flt[0];194 if(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {195 r->type = TSTRING;196 r->store.fmt = 's';197 r->store.u.string = strnode(flt);198 }199 else {200 r->type = TFLOAT;201 r->store.u.fval = atof(flt);202 }203 }205 void206 indir(Map *m, u64int addr, char fmt, Node *r)207 {208 int i;209 u32int ival;210 u64int vval;211 int ret;212 u8int cval;213 u16int sval;214 char buf[512], reg[12];216 r->op = OCONST;217 r->store.fmt = fmt;218 switch(fmt) {219 default:220 error("bad pointer format '%c' for *", fmt);221 case 'c':222 case 'C':223 case 'b':224 r->type = TINT;225 ret = get1(m, addr, &cval, 1);226 if (ret < 0)227 error("indir: %r");228 r->store.u.ival = cval;229 break;230 case 'x':231 case 'd':232 case 'u':233 case 'o':234 case 'q':235 case 'r':236 r->type = TINT;237 ret = get2(m, addr, &sval);238 if (ret < 0)239 error("indir: %r");240 r->store.u.ival = sval;241 break;242 case 'a':243 case 'A':244 case 'B':245 case 'X':246 case 'D':247 case 'U':248 case 'O':249 case 'Q':250 r->type = TINT;251 ret = get4(m, addr, &ival);252 if (ret < 0)253 error("indir: %r");254 r->store.u.ival = ival;255 break;256 case 'V':257 case 'W':258 case 'Y':259 case 'Z':260 r->type = TINT;261 ret = get8(m, addr, &vval);262 if (ret < 0)263 error("indir: %r");264 r->store.u.ival = vval;265 break;266 case 's':267 r->type = TSTRING;268 for(i = 0; i < sizeof(buf)-1; i++) {269 ret = get1(m, addr, (uchar*)&buf[i], 1);270 if (ret < 0)271 error("indir: %r");272 addr++;273 if(buf[i] == '\0')274 break;275 }276 buf[i] = 0;277 if(i == 0)278 strcpy(buf, "(null)");279 r->store.u.string = strnode(buf);280 break;281 case 'R':282 r->type = TSTRING;283 assert(sizeof(Rune) == 4);284 for(i = 0; i < sizeof(buf)-4; i += 4) {285 ret = get4(m, addr, &ival);286 if (ret < 0)287 error("indir: %r");288 memmove(buf+i, &ival, 4);289 addr += 4;290 if(ival == 0)291 break;292 }293 ival = 0;294 memmove(buf+i, &ival, 4);295 r->store.u.string = runenode((Rune*)buf);296 break;297 case 'i':298 case 'I':299 if ((*mach->das)(m, addr, fmt, buf, sizeof(buf)) < 0)300 error("indir: %r");301 r->type = TSTRING;302 r->store.fmt = 's';303 r->store.u.string = strnode(buf);304 break;305 case 'f':306 ret = get1(m, addr, (uchar*)buf, mach->szfloat);307 if (ret < 0)308 error("indir: %r");309 mach->ftoa32(buf, sizeof(buf), (void*) buf);310 convflt(r, buf);311 break;312 case 'g':313 ret = get1(m, addr, (uchar*)buf, mach->szfloat);314 if (ret < 0)315 error("indir: %r");316 mach->ftoa32(buf, sizeof(buf), (void*) buf);317 r->type = TSTRING;318 r->store.u.string = strnode(buf);319 break;320 case 'F':321 ret = get1(m, addr, (uchar*)buf, mach->szdouble);322 if (ret < 0)323 error("indir: %r");324 mach->ftoa64(buf, sizeof(buf), (void*) buf);325 convflt(r, buf);326 break;327 case '3': /* little endian ieee 80 with hole in bytes 8&9 */328 ret = get1(m, addr, (uchar*)reg, 10);329 if (ret < 0)330 error("indir: %r");331 memmove(reg+10, reg+8, 2); /* open hole */332 memset(reg+8, 0, 2); /* fill it */333 leieeeftoa80(buf, sizeof(buf), reg);334 convflt(r, buf);335 break;336 case '8': /* big-endian ieee 80 */337 ret = get1(m, addr, (uchar*)reg, 10);338 if (ret < 0)339 error("indir: %r");340 beieeeftoa80(buf, sizeof(buf), reg);341 convflt(r, buf);342 break;343 case 'G':344 ret = get1(m, addr, (uchar*)buf, mach->szdouble);345 if (ret < 0)346 error("indir: %r");347 mach->ftoa64(buf, sizeof(buf), (void*) buf);348 r->type = TSTRING;349 r->store.u.string = strnode(buf);350 break;351 }352 }354 void355 indirreg(Regs *regs, char *name, char fmt, Node *r)356 {357 u64int val;359 if(regs == 0)360 error("no register set for *%s=", name);362 r->op = OCONST;363 r->store.fmt = fmt;364 switch(fmt){365 default:366 error("bad pointer format '%c' for *%s", fmt, name);367 case 'c':368 case 'C':369 case 'b':370 case 'x':371 case 'd':372 case 'u':373 case 'o':374 case 'q':375 case 'r':376 case 'a':377 case 'A':378 case 'B':379 case 'X':380 case 'D':381 case 'U':382 case 'O':383 case 'Q':384 case 'V':385 case 'W':386 case 'Y':387 case 'Z':388 if(rget(regs, name, &val) < 0)389 error("reading %s: %r", name);390 r->type = TINT;391 r->store.u.ival = val;392 break;393 case 'f':394 case 'g':395 case 'F':396 case '3':397 case '8':398 case 'G':399 error("floating point registers not supported");400 break;401 }402 }404 void405 windir(Map *m, Node aes, Node *rval, Node *r)406 {407 uchar cval;408 ushort sval;409 Node res;410 int ret;412 if(m == 0)413 error("no map for */@=");415 if(aes.type != TINT)416 error("bad type lhs of */@=");418 expr(rval, &res);420 if(m != cormap && wtflag == 0)421 error("not in write mode");423 r->type = res.type;424 r->store.fmt = res.store.fmt;425 r->store = res.store;427 switch(res.store.fmt) {428 default:429 error("bad pointer format '%c' for */@=", res.store.fmt);430 case 'c':431 case 'C':432 case 'b':433 cval = res.store.u.ival;434 ret = put1(m, aes.store.u.ival, &cval, 1);435 break;436 case 'r':437 case 'x':438 case 'd':439 case 'u':440 case 'o':441 sval = res.store.u.ival;442 ret = put2(m, aes.store.u.ival, sval);443 r->store.u.ival = sval;444 break;445 case 'a':446 case 'A':447 case 'B':448 case 'X':449 case 'D':450 case 'U':451 case 'O':452 ret = put4(m, aes.store.u.ival, res.store.u.ival);453 break;454 case 'V':455 case 'W':456 case 'Y':457 case 'Z':458 ret = put8(m, aes.store.u.ival, res.store.u.ival);459 break;460 case 's':461 case 'R':462 ret = put1(m, aes.store.u.ival, (uchar*)res.store.u.string->string, res.store.u.string->len);463 break;464 }465 if (ret < 0)466 error("windir: %r");467 }469 void470 windirreg(Regs *regs, char *name, Node *rval, Node *r)471 {472 Node res;474 if(regs == 0)475 error("no register set for *%s=", name);477 expr(rval, &res);479 r->type = res.type;480 r->store.fmt = res.store.fmt;481 r->store = res.store;483 switch(res.store.fmt){484 default:485 error("bad format '%c' for *%s=", res.store.fmt, name);486 case 'c':487 case 'C':488 case 'b':489 case 'x':490 case 'd':491 case 'u':492 case 'o':493 case 'q':494 case 'r':495 case 'a':496 case 'A':497 case 'B':498 case 'X':499 case 'D':500 case 'U':501 case 'O':502 case 'Q':503 case 'V':504 case 'W':505 case 'Y':506 case 'Z':507 if(rput(regs, name, res.store.u.ival) < 0)508 error("writing %s: %r", name);509 break;510 case 'f':511 case 'g':512 case 'F':513 case '3':514 case '8':515 case 'G':516 error("floating point registers not supported");517 break;518 }519 }521 void522 call(char *fn, Node *parameters, Node *local, Node *body, Node *retexp)523 {524 int np, i;525 Rplace rlab;526 Node *n, res;527 Value *v, *f;528 Lsym *s, *next;529 Node *avp[Maxarg], *ava[Maxarg];531 rlab.local = 0;533 na = 0;534 flatten(avp, parameters);535 np = na;536 na = 0;537 flatten(ava, local);538 if(np != na) {539 if(np < na)540 error("%s: too few arguments", fn);541 error("%s: too many arguments", fn);542 }544 rlab.tail = &rlab.local;546 ret = &rlab;547 for(i = 0; i < np; i++) {548 n = ava[i];549 switch(n->op) {550 default:551 error("%s: %d formal not a name", fn, i);552 case ONAME:553 expr(avp[i], &res);554 s = n->sym;555 break;556 case OINDM:557 res.store.u.cc = avp[i];558 res.type = TCODE;559 res.store.comt = 0;560 if(n->left->op != ONAME)561 error("%s: %d formal not a name", fn, i);562 s = n->left->sym;563 break;564 }565 if(s->v->ret == ret)566 error("%s already declared at this scope", s->name);568 v = gmalloc(sizeof(Value));569 v->ret = ret;570 v->pop = s->v;571 s->v = v;572 v->scope = 0;573 *(rlab.tail) = s;574 rlab.tail = &v->scope;576 v->store = res.store;577 v->type = res.type;578 v->set = 1;579 }581 ret->val = retexp;582 if(setjmp(rlab.rlab) == 0)583 execute(body);585 for(s = rlab.local; s; s = next) {586 f = s->v;587 next = f->scope;588 s->v = f->pop;589 free(f);590 }591 }