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 } 499