summaryrefslogtreecommitdiff
path: root/sys/src/cmd/acid/exec.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/acid/exec.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/acid/exec.c')
-rwxr-xr-xsys/src/cmd/acid/exec.c498
1 files changed, 498 insertions, 0 deletions
diff --git a/sys/src/cmd/acid/exec.c b/sys/src/cmd/acid/exec.c
new file mode 100755
index 000000000..3d9bd590b
--- /dev/null
+++ b/sys/src/cmd/acid/exec.c
@@ -0,0 +1,498 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ctype.h>
+#include <mach.h>
+#define Extern extern
+#include "acid.h"
+
+void
+error(char *fmt, ...)
+{
+ int i;
+ char buf[2048];
+ va_list arg;
+
+ /* Unstack io channels */
+ if(iop != 0) {
+ for(i = 1; i < iop; i++)
+ Bterm(io[i]);
+ bout = io[0];
+ iop = 0;
+ }
+
+ ret = 0;
+ gotint = 0;
+ Bflush(bout);
+ if(silent)
+ silent = 0;
+ else {
+ va_start(arg, fmt);
+ vseprint(buf, buf+sizeof(buf), fmt, arg);
+ va_end(arg);
+ fprint(2, "%L: (error) %s\n", buf);
+ }
+ while(popio())
+ ;
+ interactive = 1;
+ longjmp(err, 1);
+}
+
+void
+unwind(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;
+ }
+ }
+ }
+}
+
+void
+execute(Node *n)
+{
+ Value *v;
+ Lsym *sl;
+ Node *l, *r;
+ vlong i, s, e;
+ Node res, xx;
+ static int stmnt;
+
+ gc();
+ if(gotint)
+ error("interrupted");
+
+ if(n == 0)
+ return;
+
+ if(stmnt++ > 5000) {
+ Bflush(bout);
+ stmnt = 0;
+ }
+
+ l = n->left;
+ r = n->right;
+
+ switch(n->op) {
+ default:
+ expr(n, &res);
+ if(ret || (res.type == TLIST && res.l == 0 && n->op != OADD))
+ break;
+ prnt->right = &res;
+ expr(prnt, &xx);
+ break;
+ case OASGN:
+ case OCALL:
+ expr(n, &res);
+ break;
+ case OCOMPLEX:
+ decl(n);
+ break;
+ case OLOCAL:
+ for(n = n->left; n; n = n->left) {
+ if(ret == 0)
+ error("local not in function");
+ sl = n->sym;
+ if(sl->v->ret == ret)
+ error("%s declared twice", 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("loop must have integer start");
+ s = res.ival;
+ expr(l->right, &res);
+ if(res.type != TINT)
+ error("loop must have integer end");
+ e = res.ival;
+ for(i = s; i <= e; i++)
+ execute(r);
+ break;
+ }
+}
+
+int
+bool(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;
+}
+
+void
+convflt(Node *r, char *flt)
+{
+ char c;
+
+ c = flt[0];
+ if(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
+ r->type = TSTRING;
+ r->fmt = 's';
+ r->string = strnode(flt);
+ }
+ else {
+ r->type = TFLOAT;
+ r->fval = atof(flt);
+ }
+}
+
+void
+indir(Map *m, uvlong addr, char fmt, Node *r)
+{
+ int i;
+ ulong lval;
+ uvlong uvval;
+ int ret;
+ uchar cval;
+ ushort sval;
+ char buf[512], reg[12];
+
+ 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;
+ ret = get1(m, addr, &cval, 1);
+ if (ret < 0)
+ error("indir: %r");
+ r->ival = cval;
+ break;
+ case 'x':
+ case 'd':
+ case 'u':
+ case 'o':
+ case 'q':
+ case 'r':
+ r->type = TINT;
+ ret = get2(m, addr, &sval);
+ if (ret < 0)
+ error("indir: %r");
+ r->ival = sval;
+ break;
+ case 'a':
+ case 'A':
+ case 'W':
+ r->type = TINT;
+ ret = geta(m, addr, &uvval);
+ if (ret < 0)
+ error("indir: %r");
+ r->ival = uvval;
+ break;
+ case 'B':
+ case 'X':
+ case 'D':
+ case 'U':
+ case 'O':
+ case 'Q':
+ r->type = TINT;
+ ret = get4(m, addr, &lval);
+ if (ret < 0)
+ error("indir: %r");
+ r->ival = lval;
+ break;
+ case 'V':
+ case 'Y':
+ case 'Z':
+ r->type = TINT;
+ ret = get8(m, addr, &uvval);
+ if (ret < 0)
+ error("indir: %r");
+ r->ival = uvval;
+ break;
+ case 's':
+ r->type = TSTRING;
+ for(i = 0; i < sizeof(buf)-1; i++) {
+ ret = get1(m, addr, (uchar*)&buf[i], 1);
+ if (ret < 0)
+ error("indir: %r");
+ addr++;
+ if(buf[i] == '\0')
+ break;
+ }
+ buf[i] = 0;
+ if(i == 0)
+ strcpy(buf, "(null)");
+ r->string = strnode(buf);
+ break;
+ case 'R':
+ r->type = TSTRING;
+ for(i = 0; i < sizeof(buf)-2; i += 2) {
+ ret = get1(m, addr, (uchar*)&buf[i], 2);
+ if (ret < 0)
+ error("indir: %r");
+ addr += 2;
+ if(buf[i] == 0 && buf[i+1] == 0)
+ break;
+ }
+ buf[i++] = 0;
+ buf[i] = 0;
+ r->string = runenode((Rune*)buf);
+ break;
+ case 'i':
+ case 'I':
+ if ((*machdata->das)(m, addr, fmt, buf, sizeof(buf)) < 0)
+ error("indir: %r");
+ r->type = TSTRING;
+ r->fmt = 's';
+ r->string = strnode(buf);
+ break;
+ case 'f':
+ ret = get1(m, addr, (uchar*)buf, mach->szfloat);
+ if (ret < 0)
+ error("indir: %r");
+ machdata->sftos(buf, sizeof(buf), (void*) buf);
+ convflt(r, buf);
+ break;
+ case 'g':
+ ret = get1(m, addr, (uchar*)buf, mach->szfloat);
+ if (ret < 0)
+ error("indir: %r");
+ machdata->sftos(buf, sizeof(buf), (void*) buf);
+ r->type = TSTRING;
+ r->string = strnode(buf);
+ break;
+ case 'F':
+ ret = get1(m, addr, (uchar*)buf, mach->szdouble);
+ if (ret < 0)
+ error("indir: %r");
+ machdata->dftos(buf, sizeof(buf), (void*) buf);
+ convflt(r, buf);
+ break;
+ case '3': /* little endian ieee 80 with hole in bytes 8&9 */
+ ret = get1(m, addr, (uchar*)reg, 10);
+ if (ret < 0)
+ error("indir: %r");
+ memmove(reg+10, reg+8, 2); /* open hole */
+ memset(reg+8, 0, 2); /* fill it */
+ leieee80ftos(buf, sizeof(buf), reg);
+ convflt(r, buf);
+ break;
+ case '8': /* big-endian ieee 80 */
+ ret = get1(m, addr, (uchar*)reg, 10);
+ if (ret < 0)
+ error("indir: %r");
+ beieee80ftos(buf, sizeof(buf), reg);
+ convflt(r, buf);
+ break;
+ case 'G':
+ ret = get1(m, addr, (uchar*)buf, mach->szdouble);
+ if (ret < 0)
+ error("indir: %r");
+ machdata->dftos(buf, sizeof(buf), (void*) buf);
+ r->type = TSTRING;
+ r->string = strnode(buf);
+ break;
+ }
+}
+
+void
+windir(Map *m, Node *addr, Node *rval, Node *r)
+{
+ uchar cval;
+ ushort sval;
+ long lval;
+ Node res, aes;
+ int ret;
+
+ if(m == 0)
+ error("no map for */@=");
+
+ expr(rval, &res);
+ expr(addr, &aes);
+
+ if(aes.type != TINT)
+ error("bad type lhs of @/*");
+
+ if(m != cormap && wtflag == 0)
+ error("not in write mode");
+
+ 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;
+ ret = put1(m, aes.ival, &cval, 1);
+ break;
+ case 'r':
+ case 'x':
+ case 'd':
+ case 'u':
+ case 'o':
+ sval = res.ival;
+ ret = put2(m, aes.ival, sval);
+ r->ival = sval;
+ break;
+ case 'a':
+ case 'A':
+ case 'W':
+ ret = puta(m, aes.ival, res.ival);
+ break;
+ case 'B':
+ case 'X':
+ case 'D':
+ case 'U':
+ case 'O':
+ lval = res.ival;
+ ret = put4(m, aes.ival, lval);
+ break;
+ case 'V':
+ case 'Y':
+ case 'Z':
+ ret = put8(m, aes.ival, res.ival);
+ break;
+ case 's':
+ case 'R':
+ ret = put1(m, aes.ival, (uchar*)res.string->string, res.string->len);
+ break;
+ }
+ if (ret < 0)
+ error("windir: %r");
+}
+
+void
+call(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];
+
+ rlab.local = 0;
+
+ 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.tail = &rlab.local;
+
+ ret = &rlab;
+ for(i = 0; i < np; i++) {
+ n = ava[i];
+ switch(n->op) {
+ default:
+ error("%s: %d formal not a name", fn, i);
+ case ONAME:
+ expr(avp[i], &res);
+ s = n->sym;
+ break;
+ case OINDM:
+ res.cc = avp[i];
+ res.type = TCODE;
+ res.comt = 0;
+ if(n->left->op != ONAME)
+ error("%s: %d formal not a name", fn, i);
+ s = n->left->sym;
+ break;
+ }
+ 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);
+ }
+}