texec.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
texec.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.stri… | |
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->na… | |
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 } |