1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)pascal.c 1.3 (Berkeley) 06/23/84"; 4 5 /* 6 * Pascal-dependent symbol routines. 7 */ 8 9 #include "defs.h" 10 #include "symbols.h" 11 #include "pascal.h" 12 #include "languages.h" 13 #include "tree.h" 14 #include "eval.h" 15 #include "mappings.h" 16 #include "process.h" 17 #include "runtime.h" 18 #include "machine.h" 19 20 #ifndef public 21 #endif 22 23 private Language pasc; 24 25 /* 26 * Initialize Pascal information. 27 */ 28 29 public pascal_init() 30 { 31 pasc = language_define("pascal", ".p"); 32 language_setop(pasc, L_PRINTDECL, pascal_printdecl); 33 language_setop(pasc, L_PRINTVAL, pascal_printval); 34 language_setop(pasc, L_TYPEMATCH, pascal_typematch); 35 language_setop(pasc, L_BUILDAREF, pascal_buildaref); 36 language_setop(pasc, L_EVALAREF, pascal_evalaref); 37 language_setop(pasc, L_MODINIT, pascal_modinit); 38 language_setop(pasc, L_HASMODULES, pascal_hasmodules); 39 language_setop(pasc, L_PASSADDR, pascal_passaddr); 40 initTypes(); 41 } 42 43 /* 44 * Compatible tests if two types are compatible. The issue 45 * is complicated a bit by ranges. 46 * 47 * Integers and reals are not compatible since they cannot always be mixed. 48 */ 49 50 public Boolean pascal_typematch(type1, type2) 51 Symbol type1, type2; 52 { 53 Boolean b; 54 register Symbol t1, t2; 55 56 t1 = rtype(t1); 57 t2 = rtype(t2); 58 b = (Boolean) 59 (t1->type == t2->type and ( 60 (t1->class == RANGE and t2->class == RANGE) or 61 (t1->class == SCAL and t2->class == CONST) or 62 (t1->class == CONST and t2->class == SCAL) or 63 (t1->type == t_char and t1->class == ARRAY and t2->class == ARRAY) 64 ) or 65 (t1 == t_nil and t2->class == PTR) or 66 (t1->class == PTR and t2 == t_nil) 67 ); 68 return b; 69 } 70 71 public pascal_printdecl(s) 72 Symbol s; 73 { 74 register Symbol t; 75 Boolean semicolon; 76 77 semicolon = true; 78 switch (s->class) { 79 case CONST: 80 if (s->type->class == SCAL) { 81 printf("(enumeration constant, ord %ld)", 82 s->symvalue.iconval); 83 } else { 84 printf("const %s = ", symname(s)); 85 printval(s); 86 } 87 break; 88 89 case TYPE: 90 printf("type %s = ", symname(s)); 91 printtype(s, s->type); 92 break; 93 94 case VAR: 95 if (isparam(s)) { 96 printf("(parameter) %s : ", symname(s)); 97 } else { 98 printf("var %s : ", symname(s)); 99 } 100 printtype(s, s->type); 101 break; 102 103 case REF: 104 printf("(var parameter) %s : ", symname(s)); 105 printtype(s, s->type); 106 break; 107 108 case RANGE: 109 case ARRAY: 110 case RECORD: 111 case VARNT: 112 case PTR: 113 printtype(s, s); 114 semicolon = false; 115 break; 116 117 case FVAR: 118 printf("(function variable) %s : ", symname(s)); 119 printtype(s, s->type); 120 break; 121 122 case FIELD: 123 printf("(field) %s : ", symname(s)); 124 printtype(s, s->type); 125 break; 126 127 case PROC: 128 printf("procedure %s", symname(s)); 129 listparams(s); 130 break; 131 132 case PROG: 133 printf("program %s", symname(s)); 134 t = s->chain; 135 if (t != nil) { 136 printf("(%s", symname(t)); 137 for (t = t->chain; t != nil; t = t->chain) { 138 printf(", %s", symname(t)); 139 } 140 printf(")"); 141 } 142 break; 143 144 case FUNC: 145 printf("function %s", symname(s)); 146 listparams(s); 147 printf(" : "); 148 printtype(s, s->type); 149 break; 150 151 default: 152 error("class %s in printdecl", classname(s)); 153 } 154 if (semicolon) { 155 putchar(';'); 156 } 157 putchar('\n'); 158 } 159 160 /* 161 * Recursive whiz-bang procedure to print the type portion 162 * of a declaration. Doesn't work quite right for variant records. 163 * 164 * The symbol associated with the type is passed to allow 165 * searching for type names without getting "type blah = blah". 166 */ 167 168 private printtype(s, t) 169 Symbol s; 170 Symbol t; 171 { 172 register Symbol tmp; 173 174 switch (t->class) { 175 case VAR: 176 case CONST: 177 case FUNC: 178 case PROC: 179 panic("printtype: class %s", classname(t)); 180 break; 181 182 case ARRAY: 183 printf("array["); 184 tmp = t->chain; 185 if (tmp != nil) { 186 for (;;) { 187 printtype(tmp, tmp); 188 tmp = tmp->chain; 189 if (tmp == nil) { 190 break; 191 } 192 printf(", "); 193 } 194 } 195 printf("] of "); 196 printtype(t, t->type); 197 break; 198 199 case RECORD: 200 printf("record\n"); 201 if (t->chain != nil) { 202 printtype(t->chain, t->chain); 203 } 204 printf("end"); 205 break; 206 207 case FIELD: 208 if (t->chain != nil) { 209 printtype(t->chain, t->chain); 210 } 211 printf("\t%s : ", symname(t)); 212 printtype(t, t->type); 213 printf(";\n"); 214 break; 215 216 case RANGE: { 217 long r0, r1; 218 219 r0 = t->symvalue.rangev.lower; 220 r1 = t->symvalue.rangev.upper; 221 if (t == t_char or istypename(t,"char")) { 222 if (r0 < 0x20 or r0 > 0x7e) { 223 printf("%ld..", r0); 224 } else { 225 printf("'%c'..", (char) r0); 226 } 227 if (r1 < 0x20 or r1 > 0x7e) { 228 printf("\\%lo", r1); 229 } else { 230 printf("'%c'", (char) r1); 231 } 232 } else if (r0 > 0 and r1 == 0) { 233 printf("%ld byte real", r0); 234 } else if (r0 >= 0) { 235 printf("%lu..%lu", r0, r1); 236 } else { 237 printf("%ld..%ld", r0, r1); 238 } 239 break; 240 } 241 242 case PTR: 243 putchar('*'); 244 printtype(t, t->type); 245 break; 246 247 case TYPE: 248 if (symname(t) != nil) { 249 printf("%s", symname(t)); 250 } else { 251 printtype(t, t->type); 252 } 253 break; 254 255 case SCAL: 256 printf("("); 257 t = t->chain; 258 if (t != nil) { 259 printf("%s", symname(t)); 260 t = t->chain; 261 while (t != nil) { 262 printf(", %s", symname(t)); 263 t = t->chain; 264 } 265 } else { 266 panic("empty enumeration"); 267 } 268 printf(")"); 269 break; 270 271 default: 272 printf("(class %d)", t->class); 273 break; 274 } 275 } 276 277 /* 278 * List the parameters of a procedure or function. 279 * No attempt is made to combine like types. 280 */ 281 282 private listparams(s) 283 Symbol s; 284 { 285 Symbol t; 286 287 if (s->chain != nil) { 288 putchar('('); 289 for (t = s->chain; t != nil; t = t->chain) { 290 switch (t->class) { 291 case REF: 292 printf("var "); 293 break; 294 295 case FPROC: 296 printf("procedure "); 297 break; 298 299 case FFUNC: 300 printf("function "); 301 break; 302 303 case VAR: 304 break; 305 306 default: 307 panic("unexpected class %d for parameter", t->class); 308 } 309 printf("%s : ", symname(t)); 310 printtype(t, t->type); 311 if (t->chain != nil) { 312 printf("; "); 313 } 314 } 315 putchar(')'); 316 } 317 } 318 319 /* 320 * Print out the value on the top of the expression stack 321 * in the format for the type of the given symbol. 322 */ 323 324 public pascal_printval(s) 325 Symbol s; 326 { 327 Symbol t; 328 Address a; 329 int len; 330 double r; 331 332 switch (s->class) { 333 case CONST: 334 case TYPE: 335 case VAR: 336 case REF: 337 case FVAR: 338 case TAG: 339 case FIELD: 340 pascal_printval(s->type); 341 break; 342 343 case ARRAY: 344 t = rtype(s->type); 345 if (t->class==RANGE and istypename(t->type,"char")) { 346 len = size(s); 347 sp -= len; 348 printf("'%.*s'", len, sp); 349 break; 350 } else { 351 printarray(s); 352 } 353 break; 354 355 case RECORD: 356 printrecord(s); 357 break; 358 359 case VARNT: 360 error("can't print out variant records"); 361 break; 362 363 364 case RANGE: 365 if (s == t_boolean) { 366 printf(((Boolean) popsmall(s)) == true ? "true" : "false"); 367 } else if (s == t_char or istypename(s,"char")) { 368 printf("'%c'", pop(char)); 369 } else if (s->symvalue.rangev.upper == 0 and 370 s->symvalue.rangev.lower > 0) { 371 switch (s->symvalue.rangev.lower) { 372 case sizeof(float): 373 prtreal(pop(float)); 374 break; 375 376 case sizeof(double): 377 prtreal(pop(double)); 378 break; 379 380 default: 381 panic("bad real size %d", s->symvalue.rangev.lower); 382 break; 383 } 384 } else if (s->symvalue.rangev.lower >= 0) { 385 printf("%lu", popsmall(s)); 386 } else { 387 printf("%ld", popsmall(s)); 388 } 389 break; 390 391 case FILET: 392 case PTR: { 393 Address addr; 394 395 addr = pop(Address); 396 if (addr == 0) { 397 printf("0, (nil)"); 398 } else { 399 printf("0x%x, 0%o", addr, addr); 400 } 401 break; 402 } 403 404 405 case SCAL: { 406 int scalar; 407 Boolean found; 408 409 scalar = popsmall(s); 410 found = false; 411 for (t = s->chain; t != nil; t = t->chain) { 412 if (t->symvalue.iconval == scalar) { 413 printf("%s", symname(t)); 414 found = true; 415 break; 416 } 417 } 418 if (not found) { 419 printf("(scalar = %d)", scalar); 420 } 421 break; 422 } 423 424 case FPROC: 425 case FFUNC: 426 { 427 Address a; 428 429 a = fparamaddr(pop(long)); 430 t = whatblock(a); 431 if (t == nil) { 432 printf("(proc %d)", a); 433 } else { 434 printf("%s", symname(t)); 435 } 436 break; 437 } 438 439 default: 440 if (ord(s->class) < ord(BADUSE) or ord(s->class) > ord(TYPEREF)) { 441 panic("printval: bad class %d", ord(s->class)); 442 } 443 error("don't know how to print a %s", classname(s)); 444 /* NOTREACHED */ 445 } 446 } 447 448 /* 449 * Construct a node for subscripting. 450 */ 451 452 public Node pascal_buildaref (a, slist) 453 Node a, slist; 454 { 455 register Symbol t; 456 register Node p; 457 Symbol etype, atype, eltype; 458 Node esub, r; 459 460 r = a; 461 t = rtype(a->nodetype); 462 eltype = t->type; 463 if (t->class != ARRAY) { 464 beginerrmsg(); 465 prtree(stderr, a); 466 fprintf(stderr, " is not an array"); 467 enderrmsg(); 468 } else { 469 p = slist; 470 t = t->chain; 471 for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) { 472 esub = p->value.arg[0]; 473 etype = rtype(esub->nodetype); 474 atype = rtype(t); 475 if (not compatible(atype, etype)) { 476 beginerrmsg(); 477 fprintf(stderr, "subscript "); 478 prtree(stderr, esub); 479 fprintf(stderr, " is the wrong type"); 480 enderrmsg(); 481 } 482 r = build(O_INDEX, r, esub); 483 r->nodetype = eltype; 484 } 485 if (p != nil or t != nil) { 486 beginerrmsg(); 487 if (p != nil) { 488 fprintf(stderr, "too many subscripts for "); 489 } else { 490 fprintf(stderr, "not enough subscripts for "); 491 } 492 prtree(stderr, a); 493 enderrmsg(); 494 } 495 } 496 return r; 497 } 498 499 /* 500 * Evaluate a subscript index. 501 */ 502 503 public int pascal_evalaref (s, i) 504 Symbol s; 505 long i; 506 { 507 long lb, ub; 508 509 s = rtype(rtype(s)->chain); 510 lb = s->symvalue.rangev.lower; 511 ub = s->symvalue.rangev.upper; 512 if (i < lb or i > ub) { 513 error("subscript %d out of range [%d..%d]", i, lb, ub); 514 } 515 return (i - lb); 516 } 517 518 /* 519 * Initial Pascal type information. 520 */ 521 522 #define NTYPES 4 523 524 private Symbol inittype[NTYPES]; 525 private integer count; 526 527 private addType (s, lower, upper) 528 String s; 529 long lower, upper; 530 { 531 register Symbol t; 532 533 if (count > NTYPES) { 534 panic("too many initial types"); 535 } 536 t = maketype(s, lower, upper); 537 t->language = pasc; 538 inittype[count] = t; 539 ++count; 540 } 541 542 private initTypes () 543 { 544 count = 1; 545 addType("integer", 0x80000000L, 0x7fffffffL); 546 addType("char", 0L, 255L); 547 addType("boolean", 0L, 1L); 548 addType("real", 4L, 0L); 549 } 550 551 /* 552 * Initialize typetable. 553 */ 554 555 public pascal_modinit (typetable) 556 Symbol typetable[]; 557 { 558 register integer i; 559 560 for (i = 1; i < NTYPES; i++) { 561 typetable[i] = inittype[i]; 562 } 563 } 564 565 public boolean pascal_hasmodules () 566 { 567 return false; 568 } 569 570 public boolean pascal_passaddr (param, exprtype) 571 Symbol param, exprtype; 572 { 573 return false; 574 } 575