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