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