Blob


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"
9 void
10 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 void
42 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 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;
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;
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);
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);
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;
159 int
160 bool(Node *n)
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;
185 return true;
188 void
189 convflt(Node *r, char *flt)
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);
199 else {
200 r->type = TFLOAT;
201 r->store.u.fval = atof(flt);
205 static char*
206 regbyoff(ulong addr)
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;
219 int
220 xget1(Map *m, ulong addr, u8int *a, int n)
222 if(addr < 0x100)
223 return lget1(m, correg, locreg(regbyoff(addr)), a, n);
224 else
225 return get1(m, addr, a, n);
228 int
229 xget2(Map *m, ulong addr, u16int *a)
231 if(addr < 0x100)
232 return lget2(m, correg, locreg(regbyoff(addr)), a);
233 else
234 return get2(m, addr, a);
237 int
238 xget4(Map *m, ulong addr, u32int *a)
240 if(addr < 0x100)
241 return lget4(m, correg, locreg(regbyoff(addr)), a);
242 else
243 return get4(m, addr, a);
246 int
247 xget8(Map *m, ulong addr, u64int *a)
249 if(addr < 0x100)
250 return lget8(m, correg, locreg(regbyoff(addr)), a);
251 else
252 return get8(m, addr, a);
255 void
256 indir(Map *m, ulong addr, char fmt, Node *r)
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;
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;
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;
402 void
403 windir(Map *m, Node *addr, Node *rval, Node *r)
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;
464 if (ret < 0)
465 error("windir: %r");
468 void
469 call(char *fn, Node *parameters, Node *local, Node *body, Node *retexp)
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);
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;
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;
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);