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 static char *binop[] = 10 { 11 [OMUL] "*", 12 [ODIV] "/", 13 [OMOD] "%", 14 [OADD] "+", 15 [OSUB] "-", 16 [ORSH] ">>", 17 [OLSH] "<<", 18 [OLT] "<", 19 [OGT] ">", 20 [OLEQ] "<=", 21 [OGEQ] ">=", 22 [OEQ] "==", 23 [ONEQ] "!=", 24 [OLAND] "&", 25 [OXOR] "^", 26 [OLOR] "|", 27 [OCAND] "&&", 28 [OCOR] "||", 29 [OASGN] " = ", 30 }; 31 32 static char *tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; 33 char *typestr[] = 34 { 35 [TINT] "integer", 36 [TFLOAT] "float", 37 [TSTRING] "string", 38 [TLIST] "list", 39 [TCODE] "code", 40 }; 41 42 int 43 cmp(char **a, char **b) 44 { 45 return strcmp(*a, *b); 46 } 47 48 void 49 fundefs(void) 50 { 51 Lsym *l; 52 char **vec; 53 int i, j, n, max, col, f, g, s; 54 55 max = 0; 56 f = 0; 57 g = 100; 58 vec = malloc(sizeof(char*)*g); 59 if(vec == 0) 60 fatal("out of memory"); 61 62 for(i = 0; i < Hashsize; i++) { 63 for(l = hash[i]; l; l = l->hash) { 64 if(l->proc == 0 && l->builtin == 0) 65 continue; 66 n = strlen(l->name); 67 if(n > max) 68 max = n; 69 if(f >= g) { 70 g *= 2; 71 vec = realloc(vec, sizeof(char*)*g); 72 if(vec == 0) 73 fatal("out of memory"); 74 } 75 vec[f++] = l->name; 76 } 77 } 78 qsort(vec, f, sizeof(char*), cmp); 79 max++; 80 col = 60/max; 81 s = (f+col-1)/col; 82 83 for(i = 0; i < s; i++) { 84 for(j = i; j < f; j += s) 85 Bprint(bout, "%-*s", max, vec[j]); 86 Bprint(bout, "\n"); 87 } 88 } 89 90 void 91 whatis(Lsym *l) 92 { 93 int t; 94 int def; 95 Type *ti; 96 97 if(l == 0) { 98 fundefs(); 99 return; 100 } 101 102 def = 0; 103 if(l->v->set) { 104 t = l->v->type; 105 Bprint(bout, "%s variable", typestr[t]); 106 if(t == TINT || t == TFLOAT) 107 Bprint(bout, " format %c", l->v->fmt); 108 if(l->v->comt) 109 Bprint(bout, " complex %s", 110 l->v->comt->base->name); 111 Bputc(bout, '\n'); 112 def = 1; 113 } 114 if(l->lt) { 115 Bprint(bout, "complex %s {\n", l->name); 116 for(ti = l->lt; ti; ti = ti->next) { 117 if(ti->type) { 118 if(ti->fmt == 'a') { 119 Bprint(bout, "\t%s %d %s;\n", 120 ti->type->name, ti->offset, 121 ti->tag->name); 122 } 123 else { 124 Bprint(bout, "\t'%c' %s %d %s;\n", 125 ti->fmt, ti->type->name, ti->offset, 126 ti->tag->name); 127 } 128 } 129 else 130 Bprint(bout, "\t'%c' %d %s;\n", 131 ti->fmt, ti->offset, ti->tag->name); 132 } 133 Bprint(bout, "};\n"); 134 def = 1; 135 } 136 if(l->proc) { 137 Bprint(bout, "defn %s(", l->name); 138 pexpr(l->proc->left); 139 Bprint(bout, ") {\n"); 140 pcode(l->proc->right, 1); 141 Bprint(bout, "}\n"); 142 def = 1; 143 } 144 if(l->builtin) { 145 Bprint(bout, "builtin function\n"); 146 def = 1; 147 } 148 if(def == 0) 149 Bprint(bout, "%s is undefined\n", l->name); 150 } 151 152 void 153 slist(Node *n, int d) 154 { 155 if(n == 0) 156 return; 157 if(n->op == OLIST) 158 Bprint(bout, "%.*s{\n", d-1, tabs); 159 pcode(n, d); 160 if(n->op == OLIST) 161 Bprint(bout, "%.*s}\n", d-1, tabs); 162 } 163 164 void 165 pcode(Node *n, int d) 166 { 167 Node *r, *l; 168 169 if(n == 0) 170 return; 171 172 r = n->right; 173 l = n->left; 174 175 switch(n->op) { 176 default: 177 Bprint(bout, "%.*s", d, tabs); 178 pexpr(n); 179 Bprint(bout, ";\n"); 180 break; 181 case OLIST: 182 pcode(n->left, d); 183 pcode(n->right, d); 184 break; 185 case OLOCAL: 186 Bprint(bout, "%.*slocal", d, tabs); 187 while(l) { 188 Bprint(bout, " %s", l->sym->name); 189 l = l->left; 190 if(l == 0) 191 Bprint(bout, ";\n"); 192 else 193 Bprint(bout, ","); 194 } 195 break; 196 case OCOMPLEX: 197 Bprint(bout, "%.*scomplex %s %s;\n", d, tabs, n->sym->name, l->sym->name); 198 break; 199 case OIF: 200 Bprint(bout, "%.*sif ", d, tabs); 201 pexpr(l); 202 d++; 203 Bprint(bout, " then\n", d, tabs); 204 if(r && r->op == OELSE) { 205 slist(r->left, d); 206 Bprint(bout, "%.*selse\n", d-1, tabs, d, tabs); 207 slist(r->right, d); 208 } 209 else 210 slist(r, d); 211 break; 212 case OWHILE: 213 Bprint(bout, "%.*swhile ", d, tabs); 214 pexpr(l); 215 d++; 216 Bprint(bout, " do\n", d, tabs); 217 slist(r, d); 218 break; 219 case ORET: 220 Bprint(bout, "%.*sreturn ", d, tabs); 221 pexpr(l); 222 Bprint(bout, ";\n"); 223 break; 224 case ODO: 225 Bprint(bout, "%.*sloop ", d, tabs); 226 pexpr(l->left); 227 Bprint(bout, ", "); 228 pexpr(l->right); 229 Bprint(bout, " do\n"); 230 slist(r, d+1); 231 } 232 } 233 234 void 235 pexpr(Node *n) 236 { 237 Node *r, *l; 238 239 if(n == 0) 240 return; 241 242 r = n->right; 243 l = n->left; 244 245 switch(n->op) { 246 case ONAME: 247 Bprint(bout, "%s", n->sym->name); 248 break; 249 case OCONST: 250 switch(n->type) { 251 case TINT: 252 Bprint(bout, "%d", n->ival); 253 break; 254 case TFLOAT: 255 Bprint(bout, "%g", n->fval); 256 break; 257 case TSTRING: 258 pstr(n->string); 259 break; 260 case TLIST: 261 break; 262 } 263 break; 264 case OMUL: 265 case ODIV: 266 case OMOD: 267 case OADD: 268 case OSUB: 269 case ORSH: 270 case OLSH: 271 case OLT: 272 case OGT: 273 case OLEQ: 274 case OGEQ: 275 case OEQ: 276 case ONEQ: 277 case OLAND: 278 case OXOR: 279 case OLOR: 280 case OCAND: 281 case OCOR: 282 Bputc(bout, '('); 283 pexpr(l); 284 Bprint(bout, binop[n->op]); 285 pexpr(r); 286 Bputc(bout, ')'); 287 break; 288 case OASGN: 289 pexpr(l); 290 Bprint(bout, binop[n->op]); 291 pexpr(r); 292 break; 293 case OINDM: 294 Bprint(bout, "*"); 295 pexpr(l); 296 break; 297 case OEDEC: 298 Bprint(bout, "--"); 299 pexpr(l); 300 break; 301 case OEINC: 302 Bprint(bout, "++"); 303 pexpr(l); 304 break; 305 case OPINC: 306 pexpr(l); 307 Bprint(bout, "++"); 308 break; 309 case OPDEC: 310 pexpr(l); 311 Bprint(bout, "--"); 312 break; 313 case ONOT: 314 Bprint(bout, "!"); 315 pexpr(l); 316 break; 317 case OLIST: 318 pexpr(l); 319 if(r) { 320 Bprint(bout, ","); 321 pexpr(r); 322 } 323 break; 324 case OCALL: 325 pexpr(l); 326 Bprint(bout, "("); 327 pexpr(r); 328 Bprint(bout, ")"); 329 break; 330 case OCTRUCT: 331 Bprint(bout, "{"); 332 pexpr(l); 333 Bprint(bout, "}"); 334 break; 335 case OHEAD: 336 Bprint(bout, "head "); 337 pexpr(l); 338 break; 339 case OTAIL: 340 Bprint(bout, "tail "); 341 pexpr(l); 342 break; 343 case OAPPEND: 344 Bprint(bout, "append "); 345 pexpr(l); 346 Bprint(bout, ","); 347 pexpr(r); 348 break; 349 case ODELETE: 350 Bprint(bout, "delete "); 351 pexpr(l); 352 Bprint(bout, ","); 353 pexpr(r); 354 break; 355 case ORET: 356 Bprint(bout, "return "); 357 pexpr(l); 358 break; 359 case OINDEX: 360 pexpr(l); 361 Bprint(bout, "["); 362 pexpr(r); 363 Bprint(bout, "]"); 364 break; 365 case OINDC: 366 Bprint(bout, "@"); 367 pexpr(l); 368 break; 369 case ODOT: 370 pexpr(l); 371 Bprint(bout, ".%s", n->sym->name); 372 break; 373 case OFRAME: 374 Bprint(bout, "%s:%s", n->sym->name, l->sym->name); 375 break; 376 case OCAST: 377 Bprint(bout, "(%s)", n->sym->name); 378 pexpr(l); 379 break; 380 case OFMT: 381 pexpr(l); 382 Bprint(bout, "\\%c", r->ival); 383 break; 384 case OEVAL: 385 Bprint(bout, "eval "); 386 pexpr(l); 387 break; 388 case OWHAT: 389 Bprint(bout, "whatis", n->sym->name); 390 if(n->sym) 391 Bprint(bout, " %s", n->sym->name); 392 break; 393 } 394 } 395 396 void 397 pstr(String *s) 398 { 399 int i, c; 400 401 Bputc(bout, '"'); 402 for(i = 0; i < s->len; i++) { 403 c = s->string[i]; 404 switch(c) { 405 case '\0': 406 c = '0'; 407 break; 408 case '\n': 409 c = 'n'; 410 break; 411 case '\r': 412 c = 'r'; 413 break; 414 case '\t': 415 c = 't'; 416 break; 417 case '\b': 418 c = 'b'; 419 break; 420 case '\f': 421 c = 'f'; 422 break; 423 case '\a': 424 c = 'a'; 425 break; 426 case '\v': 427 c = 'v'; 428 break; 429 case '\\': 430 c = '\\'; 431 break; 432 case '"': 433 c = '"'; 434 break; 435 default: 436 Bputc(bout, c); 437 continue; 438 } 439 Bputc(bout, '\\'); 440 Bputc(bout, c); 441 } 442 Bputc(bout, '"'); 443 } 444