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 static char*206 regbyoff(ulong addr)207 {208 Regdesc *r;210 if(mach == nil)211 error("no mach, no registers");212 for(r=mach->reglist; r->name; r++)213 if(r->offset == addr)214 return r->name;215 error("no register at %#lux", addr);216 return nil;217 }219 int220 xget1(Map *m, ulong addr, u8int *a, int n)221 {222 if(addr < 0x100)223 return lget1(m, correg, locreg(regbyoff(addr)), a, n);224 else225 return get1(m, addr, a, n);226 }228 int229 xget2(Map *m, ulong addr, u16int *a)230 {231 if(addr < 0x100)232 return lget2(m, correg, locreg(regbyoff(addr)), a);233 else234 return get2(m, addr, a);235 }237 int238 xget4(Map *m, ulong addr, u32int *a)239 {240 if(addr < 0x100)241 return lget4(m, correg, locreg(regbyoff(addr)), a);242 else243 return get4(m, addr, a);244 }246 int247 xget8(Map *m, ulong addr, u64int *a)248 {249 if(addr < 0x100)250 return lget8(m, correg, locreg(regbyoff(addr)), a);251 else252 return get8(m, addr, a);253 }255 void256 indir(Map *m, ulong addr, char fmt, Node *r)257 {258 int i;259 u32int ival;260 u64int vval;261 int ret;262 u8int cval;263 u16int sval;264 char buf[512], reg[12];266 r->op = OCONST;267 r->store.fmt = fmt;268 switch(fmt) {269 default:270 error("bad pointer format '%c' for *", fmt);271 case 'c':272 case 'C':273 case 'b':274 r->type = TINT;275 ret = xget1(m, addr, &cval, 1);276 if (ret < 0)277 error("indir: %r");278 r->store.u.ival = cval;279 break;280 case 'x':281 case 'd':282 case 'u':283 case 'o':284 case 'q':285 case 'r':286 r->type = TINT;287 ret = xget2(m, addr, &sval);288 if (ret < 0)289 error("indir: %r");290 r->store.u.ival = sval;291 break;292 case 'a':293 case 'A':294 case 'B':295 case 'X':296 case 'D':297 case 'U':298 case 'O':299 case 'Q':300 r->type = TINT;301 ret = xget4(m, addr, &ival);302 if (ret < 0)303 error("indir: %r");304 r->store.u.ival = ival;305 break;306 case 'V':307 case 'W':308 case 'Y':309 case 'Z':310 r->type = TINT;311 ret = xget8(m, addr, &vval);312 if (ret < 0)313 error("indir: %r");314 r->store.u.ival = vval;315 break;316 case 's':317 r->type = TSTRING;318 for(i = 0; i < sizeof(buf)-1; i++) {319 ret = xget1(m, addr, (uchar*)&buf[i], 1);320 if (ret < 0)321 error("indir: %r");322 addr++;323 if(buf[i] == '\0')324 break;325 }326 buf[i] = 0;327 if(i == 0)328 strcpy(buf, "(null)");329 r->store.u.string = strnode(buf);330 break;331 case 'R':332 r->type = TSTRING;333 for(i = 0; i < sizeof(buf)-2; i += 2) {334 ret = xget1(m, addr, (uchar*)&buf[i], 2);335 if (ret < 0)336 error("indir: %r");337 addr += 2;338 if(buf[i] == 0 && buf[i+1] == 0)339 break;340 }341 buf[i++] = 0;342 buf[i] = 0;343 r->store.u.string = runenode((Rune*)buf);344 break;345 case 'i':346 case 'I':347 if ((*mach->das)(m, addr, fmt, buf, sizeof(buf)) < 0)348 error("indir: %r");349 r->type = TSTRING;350 r->store.fmt = 's';351 r->store.u.string = strnode(buf);352 break;353 case 'f':354 ret = xget1(m, addr, (uchar*)buf, mach->szfloat);355 if (ret < 0)356 error("indir: %r");357 mach->ftoa32(buf, sizeof(buf), (void*) buf);358 convflt(r, buf);359 break;360 case 'g':361 ret = xget1(m, addr, (uchar*)buf, mach->szfloat);362 if (ret < 0)363 error("indir: %r");364 mach->ftoa32(buf, sizeof(buf), (void*) buf);365 r->type = TSTRING;366 r->store.u.string = strnode(buf);367 break;368 case 'F':369 ret = xget1(m, addr, (uchar*)buf, mach->szdouble);370 if (ret < 0)371 error("indir: %r");372 mach->ftoa64(buf, sizeof(buf), (void*) buf);373 convflt(r, buf);374 break;375 case '3': /* little endian ieee 80 with hole in bytes 8&9 */376 ret = xget1(m, addr, (uchar*)reg, 10);377 if (ret < 0)378 error("indir: %r");379 memmove(reg+10, reg+8, 2); /* open hole */380 memset(reg+8, 0, 2); /* fill it */381 leieeeftoa80(buf, sizeof(buf), reg);382 convflt(r, buf);383 break;384 case '8': /* big-endian ieee 80 */385 ret = xget1(m, addr, (uchar*)reg, 10);386 if (ret < 0)387 error("indir: %r");388 beieeeftoa80(buf, sizeof(buf), reg);389 convflt(r, buf);390 break;391 case 'G':392 ret = xget1(m, addr, (uchar*)buf, mach->szdouble);393 if (ret < 0)394 error("indir: %r");395 mach->ftoa64(buf, sizeof(buf), (void*) buf);396 r->type = TSTRING;397 r->store.u.string = strnode(buf);398 break;399 }400 }402 void403 windir(Map *m, Node *addr, Node *rval, Node *r)404 {405 uchar cval;406 ushort sval;407 Node res, aes;408 int ret;410 if(m == 0)411 error("no map for */@=");413 expr(rval, &res);414 expr(addr, &aes);416 if(aes.type != TINT)417 error("bad type lhs of @/*");419 if(m != cormap && wtflag == 0)420 error("not in write mode");422 r->type = res.type;423 r->store.fmt = res.store.fmt;424 r->store = res.store;426 switch(res.store.fmt) {427 default:428 error("bad pointer format '%c' for */@=", res.store.fmt);429 case 'c':430 case 'C':431 case 'b':432 cval = res.store.u.ival;433 ret = put1(m, aes.store.u.ival, &cval, 1);434 break;435 case 'r':436 case 'x':437 case 'd':438 case 'u':439 case 'o':440 sval = res.store.u.ival;441 ret = put2(m, aes.store.u.ival, sval);442 r->store.u.ival = sval;443 break;444 case 'a':445 case 'A':446 case 'B':447 case 'X':448 case 'D':449 case 'U':450 case 'O':451 ret = put4(m, aes.store.u.ival, res.store.u.ival);452 break;453 case 'V':454 case 'W':455 case 'Y':456 case 'Z':457 ret = put8(m, aes.store.u.ival, res.store.u.ival);458 break;459 case 's':460 case 'R':461 ret = put1(m, aes.store.u.ival, (uchar*)res.store.u.string->string, res.store.u.string->len);462 break;463 }464 if (ret < 0)465 error("windir: %r");466 }468 void469 call(char *fn, Node *parameters, Node *local, Node *body, Node *retexp)470 {471 int np, i;472 Rplace rlab;473 Node *n, res;474 Value *v, *f;475 Lsym *s, *next;476 Node *avp[Maxarg], *ava[Maxarg];478 rlab.local = 0;480 na = 0;481 flatten(avp, parameters);482 np = na;483 na = 0;484 flatten(ava, local);485 if(np != na) {486 if(np < na)487 error("%s: too few arguments", fn);488 error("%s: too many arguments", fn);489 }491 rlab.tail = &rlab.local;493 ret = &rlab;494 for(i = 0; i < np; i++) {495 n = ava[i];496 switch(n->op) {497 default:498 error("%s: %d formal not a name", fn, i);499 case ONAME:500 expr(avp[i], &res);501 s = n->sym;502 break;503 case OINDM:504 res.store.u.cc = avp[i];505 res.type = TCODE;506 res.store.comt = 0;507 if(n->left->op != ONAME)508 error("%s: %d formal not a name", fn, i);509 s = n->left->sym;510 break;511 }512 if(s->v->ret == ret)513 error("%s already declared at this scope", s->name);515 v = gmalloc(sizeof(Value));516 v->ret = ret;517 v->pop = s->v;518 s->v = v;519 v->scope = 0;520 *(rlab.tail) = s;521 rlab.tail = &v->scope;523 v->store = res.store;524 v->type = res.type;525 v->set = 1;526 }528 ret->val = retexp;529 if(setjmp(rlab.rlab) == 0)530 execute(body);532 for(s = rlab.local; s; s = next) {533 f = s->v;534 next = f->scope;535 s->v = f->pop;536 free(f);537 }538 }