plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

exec.c (9985B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <bio.h>
      4 #include <ctype.h>
      5 #include <mach.h>
      6 #define Extern extern
      7 #include "acid.h"
      8 
      9 void
     10 error(char *fmt, ...)
     11 {
     12 	int i;
     13 	char buf[2048];
     14 	va_list arg;
     15 
     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 	}
     23 
     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 }
     40 
     41 void
     42 unwind(void)
     43 {
     44 	int i;
     45 	Lsym *s;
     46 	Value *v;
     47 
     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 }
     58 
     59 void
     60 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;
     68 
     69 	gc();
     70 	if(gotint)
     71 		error("interrupted");
     72 
     73 	if(n == 0)
     74 		return;
     75 
     76 	if(stmnt++ > 5000) {
     77 		Bflush(bout);
     78 		stmnt = 0;
     79 	}
     80 
     81 	l = n->left;
     82 	r = n->right;
     83 
     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 			else
    131 				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 }
    158 
    159 int
    160 bool(Node *n)
    161 {
    162 	int true = 0;
    163 
    164 	if(n->op != OCONST)
    165 		fatal("bool: not const");
    166 
    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 }
    187 
    188 void
    189 convflt(Node *r, char *flt)
    190 {
    191 	char c;
    192 
    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 }
    204 
    205 void
    206 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];
    215 
    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 }
    353 
    354 void
    355 indirreg(Regs *regs, char *name, char fmt, Node *r)
    356 {
    357 	u64int val;
    358 
    359 	if(regs == 0)
    360 		error("no register set for *%s=", name);
    361 
    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 }
    403 
    404 void
    405 windir(Map *m, Node aes, Node *rval, Node *r)
    406 {
    407 	uchar cval;
    408 	ushort sval;
    409 	Node res;
    410 	int ret;
    411 
    412 	if(m == 0)
    413 		error("no map for */@=");
    414 
    415 	if(aes.type != TINT)
    416 		error("bad type lhs of */@=");
    417 
    418 	expr(rval, &res);
    419 
    420 	if(m != cormap && wtflag == 0)
    421 		error("not in write mode");
    422 
    423 	r->type = res.type;
    424 	r->store.fmt = res.store.fmt;
    425 	r->store = res.store;
    426 
    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 }
    468 
    469 void
    470 windirreg(Regs *regs, char *name, Node *rval, Node *r)
    471 {
    472 	Node res;
    473 
    474 	if(regs == 0)
    475 		error("no register set for *%s=", name);
    476 
    477 	expr(rval, &res);
    478 
    479 	r->type = res.type;
    480 	r->store.fmt = res.store.fmt;
    481 	r->store = res.store;
    482 
    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 }
    520 
    521 void
    522 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];
    530 
    531 	rlab.local = 0;
    532 
    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 	}
    543 
    544 	rlab.tail = &rlab.local;
    545 
    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);
    567 
    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;
    575 
    576 		v->store = res.store;
    577 		v->type = res.type;
    578 		v->set = 1;
    579 	}
    580 
    581 	ret->val = retexp;
    582 	if(setjmp(rlab.rlab) == 0)
    583 		execute(body);
    584 
    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 }