Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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, "%L: (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
	vlong 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.l == 0 && n->op != OADD))
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.ival;
149
		expr(l->right, &res);
150
		if(res.type != TINT)
151
			error("loop must have integer end");
152
		e = res.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->ival != 0)
170
			true = 1;
171
		break;
172
	case TFLOAT:
173
		if(n->fval != 0.0)
174
			true = 1;
175
		break;
176
	case TSTRING:
177
		if(n->string->len)
178
			true = 1;
179
		break;
180
	case TLIST:
181
		if(n->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->fmt = 's';
197
		r->string = strnode(flt);
198
	}
199
	else {
200
		r->type = TFLOAT;
201
		r->fval = atof(flt);
202
	}
203
}
204
 
205
void
206
indir(Map *m, uvlong addr, char fmt, Node *r)
207
{
208
	int i;
209
	ulong lval;
210
	uvlong uvval;
211
	int ret;
212
	uchar cval;
213
	ushort sval;
214
	char buf[512], reg[12];
215
 
216
	r->op = OCONST;
217
	r->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->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->ival = sval;
241
		break;
242
	case 'a':
243
	case 'A':
244
	case 'W':
245
		r->type = TINT;
246
		ret = geta(m, addr, &uvval);
247
		if (ret < 0)
248
			error("indir: %r");
249
		r->ival = uvval;
250
		break;
251
	case 'B':
252
	case 'X':
253
	case 'D':
254
	case 'U':
255
	case 'O':
256
	case 'Q':
257
		r->type = TINT;
258
		ret = get4(m, addr, &lval);
259
		if (ret < 0)
260
			error("indir: %r");
261
		r->ival = lval;
262
		break;
263
	case 'V':
264
	case 'Y':
265
	case 'Z':
266
		r->type = TINT;
267
		ret = get8(m, addr, &uvval);
268
		if (ret < 0)
269
			error("indir: %r");
270
		r->ival = uvval;
271
		break;
272
	case 's':
273
		r->type = TSTRING;
274
		for(i = 0; i < sizeof(buf)-1; i++) {
275
			ret = get1(m, addr, (uchar*)&buf[i], 1);
276
			if (ret < 0)
277
				error("indir: %r");
278
			addr++;
279
			if(buf[i] == '\0')
280
				break;
281
		}
282
		buf[i] = 0;
283
		if(i == 0)
284
			strcpy(buf, "(null)");
285
		r->string = strnode(buf);
286
		break;
287
	case 'R':
288
		r->type = TSTRING;
289
		for(i = 0; i < sizeof(buf)-2; i += 2) {
290
			ret = get1(m, addr, (uchar*)&buf[i], 2);
291
			if (ret < 0)
292
				error("indir: %r");
293
			addr += 2;
294
			if(buf[i] == 0 && buf[i+1] == 0)
295
				break;
296
		}
297
		buf[i++] = 0;
298
		buf[i] = 0;
299
		r->string = runenode((Rune*)buf);
300
		break;
301
	case 'i':
302
	case 'I':
303
		if ((*machdata->das)(m, addr, fmt, buf, sizeof(buf)) < 0)
304
			error("indir: %r");
305
		r->type = TSTRING;
306
		r->fmt = 's';
307
		r->string = strnode(buf);
308
		break;
309
	case 'f':
310
		ret = get1(m, addr, (uchar*)buf, mach->szfloat);
311
		if (ret < 0)
312
			error("indir: %r");
313
		machdata->sftos(buf, sizeof(buf), (void*) buf);
314
		convflt(r, buf);
315
		break;
316
	case 'g':
317
		ret = get1(m, addr, (uchar*)buf, mach->szfloat);
318
		if (ret < 0)
319
			error("indir: %r");
320
		machdata->sftos(buf, sizeof(buf), (void*) buf);
321
		r->type = TSTRING;
322
		r->string = strnode(buf);
323
		break;
324
	case 'F':
325
		ret = get1(m, addr, (uchar*)buf, mach->szdouble);
326
		if (ret < 0)
327
			error("indir: %r");
328
		machdata->dftos(buf, sizeof(buf), (void*) buf);
329
		convflt(r, buf);
330
		break;
331
	case '3':	/* little endian ieee 80 with hole in bytes 8&9 */
332
		ret = get1(m, addr, (uchar*)reg, 10);
333
		if (ret < 0)
334
			error("indir: %r");
335
		memmove(reg+10, reg+8, 2);	/* open hole */
336
		memset(reg+8, 0, 2);		/* fill it */
337
		leieee80ftos(buf, sizeof(buf), reg);
338
		convflt(r, buf);
339
		break;
340
	case '8':	/* big-endian ieee 80 */
341
		ret = get1(m, addr, (uchar*)reg, 10);
342
		if (ret < 0)
343
			error("indir: %r");
344
		beieee80ftos(buf, sizeof(buf), reg);
345
		convflt(r, buf);
346
		break;
347
	case 'G':
348
		ret = get1(m, addr, (uchar*)buf, mach->szdouble);
349
		if (ret < 0)
350
			error("indir: %r");
351
		machdata->dftos(buf, sizeof(buf), (void*) buf);
352
		r->type = TSTRING;
353
		r->string = strnode(buf);
354
		break;
355
	}
356
}
357
 
358
void
359
windir(Map *m, Node *addr, Node *rval, Node *r)
360
{
361
	uchar cval;
362
	ushort sval;
363
	long lval;
364
	Node res, aes;
365
	int ret;
366
 
367
	if(m == 0)
368
		error("no map for */@=");
369
 
370
	expr(rval, &res);
371
	expr(addr, &aes);
372
 
373
	if(aes.type != TINT)
374
		error("bad type lhs of @/*");
375
 
376
	if(m != cormap && wtflag == 0)
377
		error("not in write mode");
378
 
379
	r->type = res.type;
380
	r->fmt = res.fmt;
381
	r->Store = res.Store;
382
 
383
	switch(res.fmt) {
384
	default:
385
		error("bad pointer format '%c' for */@=", res.fmt);
386
	case 'c':
387
	case 'C':
388
	case 'b':
389
		cval = res.ival;
390
		ret = put1(m, aes.ival, &cval, 1);
391
		break;
392
	case 'r':
393
	case 'x':
394
	case 'd':
395
	case 'u':
396
	case 'o':
397
		sval = res.ival;
398
		ret = put2(m, aes.ival, sval);
399
		r->ival = sval;
400
		break;
401
	case 'a':
402
	case 'A':
403
	case 'W':
404
		ret = puta(m, aes.ival, res.ival);
405
		break;
406
	case 'B':
407
	case 'X':
408
	case 'D':
409
	case 'U':
410
	case 'O':
411
		lval = res.ival;
412
		ret = put4(m, aes.ival, lval);
413
		break;
414
	case 'V':
415
	case 'Y':
416
	case 'Z':
417
		ret = put8(m, aes.ival, res.ival);
418
		break;
419
	case 's':
420
	case 'R':
421
		ret = put1(m, aes.ival, (uchar*)res.string->string, res.string->len);
422
		break;
423
	}
424
	if (ret < 0)
425
		error("windir: %r");
426
}
427
 
428
void
429
call(char *fn, Node *parameters, Node *local, Node *body, Node *retexp)
430
{
431
	int np, i;
432
	Rplace rlab;
433
	Node *n, res;
434
	Value *v, *f;
435
	Lsym *s, *next;
436
	Node *avp[Maxarg], *ava[Maxarg];
437
 
438
	rlab.local = 0;
439
 
440
	na = 0;
441
	flatten(avp, parameters);
442
	np = na;
443
	na = 0;
444
	flatten(ava, local);
445
	if(np != na) {
446
		if(np < na)
447
			error("%s: too few arguments", fn);
448
		error("%s: too many arguments", fn);
449
	}
450
 
451
	rlab.tail = &rlab.local;
452
 
453
	ret = &rlab;
454
	for(i = 0; i < np; i++) {
455
		n = ava[i];
456
		switch(n->op) {
457
		default:
458
			error("%s: %d formal not a name", fn, i);
459
		case ONAME:
460
			expr(avp[i], &res);
461
			s = n->sym;
462
			break;
463
		case OINDM:
464
			res.cc = avp[i];
465
			res.type = TCODE;
466
			res.comt = 0;
467
			if(n->left->op != ONAME)
468
				error("%s: %d formal not a name", fn, i);
469
			s = n->left->sym;
470
			break;
471
		}
472
		if(s->v->ret == ret)
473
			error("%s already declared at this scope", s->name);
474
 
475
		v = gmalloc(sizeof(Value));
476
		v->ret = ret;
477
		v->pop = s->v;
478
		s->v = v;
479
		v->scope = 0;
480
		*(rlab.tail) = s;
481
		rlab.tail = &v->scope;
482
 
483
		v->Store = res.Store;
484
		v->type = res.type;
485
		v->set = 1;
486
	}
487
 
488
	ret->val = retexp;
489
	if(setjmp(rlab.rlab) == 0)
490
		execute(body);
491
 
492
	for(s = rlab.local; s; s = next) {
493
		f = s->v;
494
		next = f->scope;
495
		s->v = f->pop;
496
		free(f);
497
	}
498
}