henesyinit from p9f47575dc5 years agoHistory
359 lines · 5.5 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <bio.h>#include <ctype.h>#include <mach.h>#define Extern extern#include "acid.h" voiderror(char *fmt, ...){	char buf[128]; 	ret = 0;	gotint = 0;	Bflush(bin);	Bflush(bout);	doprint(buf, buf+sizeof(buf), fmt, (&fmt+1));	if(filename)		fprint(2, "%d: (%s) %s\n", line, filename, buf);	else		fprint(2, "%d: (error) %s\n", line, buf); 	longjmp(err, 1);} voidunwind(void){	int i;	Lsym *s;	Value *v; 	for(i = 0; i < Hashsize; i++) {		for(s = hash[i]; s; s = s->hash) {			while(s->v->pop) {				v = s->v->pop;				free(s->v);				s->v = v;			}		}	}} voidexecute(Node *n){	Node res;	Value *v;	Lsym *sl;	Node *l, *r;	int i, s, e;	static int stmnt; 	if(gotint)		error("interrupted"); 	if(n == 0)		return; 	if(stmnt++ > 10000) {		Bflush(bout);		stmnt = 0;	} 	l = n->left;	r = n->right; 	switch(n->op) {	default:		expr(n, &res);		break;	case OCOMPLEX:		decl(n->sym, l->sym);		break;	case OLOCAL:		if(ret == 0)			error("local not in function");		sl = n->sym;		if(sl->v->ret == ret)			error("%s already declared at this scope", sl->name);		v = gmalloc(sizeof(Value));		v->ret = ret;		v->pop = sl->v;		sl->v = v;		v->scope = 0;		*(ret->tail) = sl;		ret->tail = &v->scope;		v->set = 0;		break;	case ORET:		if(ret == 0)			error("return not in function");		expr(n->left, ret->val);		longjmp(ret->rlab, 1);	case OLIST:		execute(n->left);		execute(n->right);		break;	case OIF:		expr(l, &res);		if(r && r->op == OELSE) {			if(bool(&res))				execute(r->left);			else				execute(r->right);		}		else if(bool(&res))			execute(r);		break;	case OWHILE:		for(;;) {			expr(l, &res);			if(!bool(&res))				break;			execute(r);		}		break;	case ODO:		expr(l->left, &res);		if(res.type != TINT)			error("do must have integer start");		s = res.ival;		expr(l->right, &res);		if(res.type != TINT)			error("do must have integer end");		e = res.ival;		for(i = s; i < e; i++)			execute(r);		break;	}} intbool(Node *n){	int true = 0; 	if(n->op != OCONST)		fatal("bool: not const"); 	switch(n->type) {	case TINT:		if(n->ival != 0)			true = 1;		break;	case TFLOAT:		if(n->fval != 0.0)			true = 1;		break;	case TSTRING:		if(n->string->len)			true = 1;		break;	case TLIST:		if(n->l)			true = 1;		break;	}	return true;} voidindir(Map *m, ulong addr, char fmt, Node *r){	int i;	int ival;	uchar cval;	ushort sval;	char buf[512]; 	r->op = OCONST;	r->fmt = fmt;	switch(fmt) {	default:		error("bad pointer format '%c' for *", fmt);	case 'c':	case 'C':	case 'b':		r->type = TINT;		get1(m, addr, SEGANY, &cval, 1);		r->ival = cval;		break;	case 'x':	case 'd':	case 'u':	case 'o':	case 'q':		r->type = TINT;		get2(m, addr, SEGANY, &sval);		r->ival = sval;		break;	case 'X':	case 'D':	case 'U':	case 'O':	case 'Q':	case 'Y':		r->type = TINT;		get4(m, addr, SEGANY, &ival);		r->ival = ival;		break;	case 's':		r->type = TSTRING;		for(i = 0; i < sizeof(buf)-1; i++) {			get1(m, addr, SEGANY, (uchar*)&buf[i], 1);			addr++;			if(buf[i] == '\0')				break;		}		buf[i] = 0;		r->string = strnode(buf);		break;	case 'R':		r->type = TSTRING;		for(i = 0; i < sizeof(buf)-1; i += 2) {			get1(m, addr, SEGANY, (uchar*)&buf[i], 2);			addr += 2;			if(buf[i] == 0 && buf[i+1] == 0)				break;		}		buf[i] = 0;		r->string = strnode(buf);		break;	case 'i':	case 'I':		xprint = 1;		asmbuf[0] = '\0';		dot = addr;		(*machdata->printins)(m, fmt, SEGANY);		xprint = 0;		r->type = TSTRING;		r->fmt = 's';		r->string = strnode(asmbuf);		break;	case 'f':		r->type = TFLOAT;		get1(m, addr, SEGANY, (uchar*)buf, mach->szfloat);		break;	case 'F':		r->type = TFLOAT;		get1(m, addr, SEGANY, (uchar*)buf, mach->szdouble);		break;	}} voidwindir(Map *m, Node *addr, Node *rval, Node *r){	uchar cval;	ushort sval;	Node res, aes; 	if(m == 0)		error("no map for */@="); 	expr(rval, &res);	expr(addr, &aes); 	if(aes.type != TINT)		error("bad type lhs of @/*"); 	r->type = res.type;	r->fmt = res.fmt;	r->Store = res.Store; 	switch(res.fmt) {	default:		error("bad pointer format '%c' for */@=", res.fmt);	case 'c':	case 'C':	case 'b':		cval = res.ival;		put1(m, aes.ival, SEGANY, &cval, 1);		break;	case 'r':	case 'x':	case 'd':	case 'u':	case 'o':		sval = res.ival;		put2(m, aes.ival, SEGANY, sval);		r->ival = sval;		break;	case 'X':	case 'D':	case 'U':	case 'O':	case 'Y':		put4(m, aes.ival, SEGANY, res.ival);		break;	case 's':	case 'R':		put1(m, aes.ival, SEGANY, (uchar*)res.string->string, res.string->len);		break;	}} voidcall(char *fn, Node *parameters, Node *local, Node *body, Node *retexp){	int np, i;	Rplace rlab;	Node *n, res;	Value *v, *f;	Lsym *s, *next;	Node *avp[Maxarg], *ava[Maxarg]; 	na = 0;	flatten(avp, parameters);	np = na;	na = 0;	flatten(ava, local);	if(np != na) {		if(np < na)			error("%s: too few arguments", fn); 		error("%s: too many arguments", fn);	} 	rlab.local = 0;	rlab.tail = &rlab.local; 	ret = &rlab;	for(i = 0; i < np; i++) {		n = ava[i];		if(n->op != ONAME)			error("%s: %d formal not a name", fn, i); 		expr(avp[i], &res); 		s = n->sym;		if(s->v->ret == ret)			error("%s already declared at this scope", s->name); 		v = gmalloc(sizeof(Value));		v->ret = ret;		v->pop = s->v;		s->v = v;		v->scope = 0;		*(rlab.tail) = s;		rlab.tail = &v->scope; 		v->Store = res.Store;		v->type = res.type;		v->set = 1;	} 	ret->val = retexp;	if(setjmp(rlab.rlab) == 0)		execute(body); 	for(s = rlab.local; s; s = next) {		f = s->v;		next = f->scope;		s->v = f->pop;		free(f);	}}