19675Slinton /* Copyright (c) 1982 Regents of the University of California */ 29675Slinton 39689Slinton static char sccsid[] = "@(#)pascal.c 1.2 12/15/82"; 49675Slinton 5*16615Ssam static char rcsid[] = "$Header: pascal.c,v 1.3 84/03/27 10:23:04 linton Exp $"; 6*16615Ssam 79675Slinton /* 89675Slinton * Pascal-dependent symbol routines. 99675Slinton */ 109675Slinton 119675Slinton #include "defs.h" 129675Slinton #include "symbols.h" 139675Slinton #include "pascal.h" 149675Slinton #include "languages.h" 159675Slinton #include "tree.h" 169675Slinton #include "eval.h" 179675Slinton #include "mappings.h" 189675Slinton #include "process.h" 199675Slinton #include "runtime.h" 209675Slinton #include "machine.h" 219675Slinton 229675Slinton #ifndef public 239675Slinton #endif 249675Slinton 25*16615Ssam private Language pasc; 26*16615Ssam 279675Slinton /* 289675Slinton * Initialize Pascal information. 299675Slinton */ 309675Slinton 319675Slinton public pascal_init() 329675Slinton { 33*16615Ssam pasc = language_define("pascal", ".p"); 34*16615Ssam language_setop(pasc, L_PRINTDECL, pascal_printdecl); 35*16615Ssam language_setop(pasc, L_PRINTVAL, pascal_printval); 36*16615Ssam language_setop(pasc, L_TYPEMATCH, pascal_typematch); 37*16615Ssam language_setop(pasc, L_BUILDAREF, pascal_buildaref); 38*16615Ssam language_setop(pasc, L_EVALAREF, pascal_evalaref); 39*16615Ssam language_setop(pasc, L_MODINIT, pascal_modinit); 40*16615Ssam language_setop(pasc, L_HASMODULES, pascal_hasmodules); 41*16615Ssam language_setop(pasc, L_PASSADDR, pascal_passaddr); 42*16615Ssam initTypes(); 439675Slinton } 449675Slinton 459675Slinton /* 469675Slinton * Compatible tests if two types are compatible. The issue 479675Slinton * is complicated a bit by ranges. 489675Slinton * 499675Slinton * Integers and reals are not compatible since they cannot always be mixed. 509675Slinton */ 519675Slinton 529675Slinton public Boolean pascal_typematch(type1, type2) 539675Slinton Symbol type1, type2; 549675Slinton { 559675Slinton Boolean b; 569675Slinton register Symbol t1, t2; 579675Slinton 589675Slinton t1 = rtype(t1); 599675Slinton t2 = rtype(t2); 609675Slinton b = (Boolean) 619675Slinton (t1->type == t2->type and ( 629675Slinton (t1->class == RANGE and t2->class == RANGE) or 639675Slinton (t1->class == SCAL and t2->class == CONST) or 649675Slinton (t1->class == CONST and t2->class == SCAL) or 659675Slinton (t1->type == t_char and t1->class == ARRAY and t2->class == ARRAY) 669675Slinton ) or 679675Slinton (t1 == t_nil and t2->class == PTR) or 689675Slinton (t1->class == PTR and t2 == t_nil) 699675Slinton ); 709675Slinton return b; 719675Slinton } 729675Slinton 739675Slinton public pascal_printdecl(s) 749675Slinton Symbol s; 759675Slinton { 769675Slinton register Symbol t; 779675Slinton Boolean semicolon; 789675Slinton 799675Slinton semicolon = true; 809675Slinton switch (s->class) { 819675Slinton case CONST: 829675Slinton if (s->type->class == SCAL) { 839675Slinton printf("(enumeration constant, ord %ld)", 849675Slinton s->symvalue.iconval); 859675Slinton } else { 869675Slinton printf("const %s = ", symname(s)); 879675Slinton printval(s); 889675Slinton } 899675Slinton break; 909675Slinton 919675Slinton case TYPE: 929675Slinton printf("type %s = ", symname(s)); 939675Slinton printtype(s, s->type); 949675Slinton break; 959675Slinton 969675Slinton case VAR: 979675Slinton if (isparam(s)) { 989675Slinton printf("(parameter) %s : ", symname(s)); 999675Slinton } else { 1009675Slinton printf("var %s : ", symname(s)); 1019675Slinton } 1029675Slinton printtype(s, s->type); 1039675Slinton break; 1049675Slinton 1059675Slinton case REF: 1069675Slinton printf("(var parameter) %s : ", symname(s)); 1079675Slinton printtype(s, s->type); 1089675Slinton break; 1099675Slinton 1109675Slinton case RANGE: 1119675Slinton case ARRAY: 1129675Slinton case RECORD: 1139675Slinton case VARNT: 1149675Slinton case PTR: 1159675Slinton printtype(s, s); 1169675Slinton semicolon = false; 1179675Slinton break; 1189675Slinton 1199675Slinton case FVAR: 1209675Slinton printf("(function variable) %s : ", symname(s)); 1219675Slinton printtype(s, s->type); 1229675Slinton break; 1239675Slinton 1249675Slinton case FIELD: 1259675Slinton printf("(field) %s : ", symname(s)); 1269675Slinton printtype(s, s->type); 1279675Slinton break; 1289675Slinton 1299675Slinton case PROC: 1309675Slinton printf("procedure %s", symname(s)); 1319675Slinton listparams(s); 1329675Slinton break; 1339675Slinton 1349675Slinton case PROG: 1359675Slinton printf("program %s", symname(s)); 1369675Slinton t = s->chain; 1379675Slinton if (t != nil) { 1389675Slinton printf("(%s", symname(t)); 1399675Slinton for (t = t->chain; t != nil; t = t->chain) { 1409675Slinton printf(", %s", symname(t)); 1419675Slinton } 1429675Slinton printf(")"); 1439675Slinton } 1449675Slinton break; 1459675Slinton 1469675Slinton case FUNC: 1479675Slinton printf("function %s", symname(s)); 1489675Slinton listparams(s); 1499675Slinton printf(" : "); 1509675Slinton printtype(s, s->type); 1519675Slinton break; 1529675Slinton 1539675Slinton default: 1549675Slinton error("class %s in printdecl", classname(s)); 1559675Slinton } 1569675Slinton if (semicolon) { 1579675Slinton putchar(';'); 1589675Slinton } 1599675Slinton putchar('\n'); 1609675Slinton } 1619675Slinton 1629675Slinton /* 1639675Slinton * Recursive whiz-bang procedure to print the type portion 1649675Slinton * of a declaration. Doesn't work quite right for variant records. 1659675Slinton * 1669675Slinton * The symbol associated with the type is passed to allow 1679675Slinton * searching for type names without getting "type blah = blah". 1689675Slinton */ 1699675Slinton 1709675Slinton private printtype(s, t) 1719675Slinton Symbol s; 1729675Slinton Symbol t; 1739675Slinton { 1749675Slinton register Symbol tmp; 1759675Slinton 1769675Slinton switch (t->class) { 1779675Slinton case VAR: 1789675Slinton case CONST: 1799675Slinton case FUNC: 1809675Slinton case PROC: 1819675Slinton panic("printtype: class %s", classname(t)); 1829675Slinton break; 1839675Slinton 1849675Slinton case ARRAY: 1859675Slinton printf("array["); 1869675Slinton tmp = t->chain; 1879675Slinton if (tmp != nil) { 1889675Slinton for (;;) { 1899675Slinton printtype(tmp, tmp); 1909675Slinton tmp = tmp->chain; 1919675Slinton if (tmp == nil) { 1929675Slinton break; 1939675Slinton } 1949675Slinton printf(", "); 1959675Slinton } 1969675Slinton } 1979675Slinton printf("] of "); 1989675Slinton printtype(t, t->type); 1999675Slinton break; 2009675Slinton 2019675Slinton case RECORD: 2029675Slinton printf("record\n"); 2039675Slinton if (t->chain != nil) { 2049675Slinton printtype(t->chain, t->chain); 2059675Slinton } 2069675Slinton printf("end"); 2079675Slinton break; 2089675Slinton 2099675Slinton case FIELD: 2109675Slinton if (t->chain != nil) { 2119675Slinton printtype(t->chain, t->chain); 2129675Slinton } 2139675Slinton printf("\t%s : ", symname(t)); 2149675Slinton printtype(t, t->type); 2159675Slinton printf(";\n"); 2169675Slinton break; 2179675Slinton 2189675Slinton case RANGE: { 2199675Slinton long r0, r1; 2209675Slinton 2219675Slinton r0 = t->symvalue.rangev.lower; 2229675Slinton r1 = t->symvalue.rangev.upper; 223*16615Ssam if (t == t_char or istypename(t,"char")) { 2249675Slinton if (r0 < 0x20 or r0 > 0x7e) { 2259675Slinton printf("%ld..", r0); 2269675Slinton } else { 2279675Slinton printf("'%c'..", (char) r0); 2289675Slinton } 2299675Slinton if (r1 < 0x20 or r1 > 0x7e) { 2309675Slinton printf("\\%lo", r1); 2319675Slinton } else { 2329675Slinton printf("'%c'", (char) r1); 2339675Slinton } 2349675Slinton } else if (r0 > 0 and r1 == 0) { 2359675Slinton printf("%ld byte real", r0); 2369675Slinton } else if (r0 >= 0) { 2379675Slinton printf("%lu..%lu", r0, r1); 2389675Slinton } else { 2399675Slinton printf("%ld..%ld", r0, r1); 2409675Slinton } 2419675Slinton break; 2429675Slinton } 2439675Slinton 2449675Slinton case PTR: 2459675Slinton putchar('*'); 2469675Slinton printtype(t, t->type); 2479675Slinton break; 2489675Slinton 2499675Slinton case TYPE: 2509675Slinton if (symname(t) != nil) { 2519675Slinton printf("%s", symname(t)); 2529675Slinton } else { 2539675Slinton printtype(t, t->type); 2549675Slinton } 2559675Slinton break; 2569675Slinton 2579675Slinton case SCAL: 2589675Slinton printf("("); 259*16615Ssam t = t->chain; 2609675Slinton if (t != nil) { 2619675Slinton printf("%s", symname(t)); 2629675Slinton t = t->chain; 2639675Slinton while (t != nil) { 2649675Slinton printf(", %s", symname(t)); 2659675Slinton t = t->chain; 2669675Slinton } 2679675Slinton } else { 2689675Slinton panic("empty enumeration"); 2699675Slinton } 2709675Slinton printf(")"); 2719675Slinton break; 2729675Slinton 2739675Slinton default: 2749675Slinton printf("(class %d)", t->class); 2759675Slinton break; 2769675Slinton } 2779675Slinton } 2789675Slinton 2799675Slinton /* 2809675Slinton * List the parameters of a procedure or function. 2819675Slinton * No attempt is made to combine like types. 2829675Slinton */ 2839675Slinton 2849675Slinton private listparams(s) 2859675Slinton Symbol s; 2869675Slinton { 2879675Slinton Symbol t; 2889675Slinton 2899675Slinton if (s->chain != nil) { 2909675Slinton putchar('('); 2919675Slinton for (t = s->chain; t != nil; t = t->chain) { 2929675Slinton switch (t->class) { 2939675Slinton case REF: 2949675Slinton printf("var "); 2959675Slinton break; 2969675Slinton 2979675Slinton case FPROC: 2989675Slinton printf("procedure "); 2999675Slinton break; 3009675Slinton 3019675Slinton case FFUNC: 3029675Slinton printf("function "); 3039675Slinton break; 3049675Slinton 3059675Slinton case VAR: 3069675Slinton break; 3079675Slinton 3089675Slinton default: 3099675Slinton panic("unexpected class %d for parameter", t->class); 3109675Slinton } 3119675Slinton printf("%s : ", symname(t)); 3129675Slinton printtype(t, t->type); 3139675Slinton if (t->chain != nil) { 3149675Slinton printf("; "); 3159675Slinton } 3169675Slinton } 3179675Slinton putchar(')'); 3189675Slinton } 3199675Slinton } 3209675Slinton 3219675Slinton /* 3229675Slinton * Print out the value on the top of the expression stack 3239675Slinton * in the format for the type of the given symbol. 3249675Slinton */ 3259675Slinton 3269675Slinton public pascal_printval(s) 3279675Slinton Symbol s; 3289675Slinton { 3299675Slinton Symbol t; 3309675Slinton Address a; 3319675Slinton int len; 3329675Slinton double r; 3339675Slinton 3349675Slinton switch (s->class) { 335*16615Ssam case CONST: 3369675Slinton case TYPE: 337*16615Ssam case VAR: 338*16615Ssam case REF: 339*16615Ssam case FVAR: 340*16615Ssam case TAG: 341*16615Ssam case FIELD: 3429675Slinton pascal_printval(s->type); 3439675Slinton break; 3449675Slinton 3459675Slinton case ARRAY: 3469675Slinton t = rtype(s->type); 347*16615Ssam if (t->class==RANGE and istypename(t->type,"char")) { 3489675Slinton len = size(s); 3499675Slinton sp -= len; 3509675Slinton printf("'%.*s'", len, sp); 3519675Slinton break; 3529675Slinton } else { 3539675Slinton printarray(s); 3549675Slinton } 3559675Slinton break; 3569675Slinton 3579675Slinton case RECORD: 3589675Slinton printrecord(s); 3599675Slinton break; 3609675Slinton 3619675Slinton case VARNT: 3629675Slinton error("can't print out variant records"); 3639675Slinton break; 3649675Slinton 3659675Slinton 3669675Slinton case RANGE: 3679675Slinton if (s == t_boolean) { 3689675Slinton printf(((Boolean) popsmall(s)) == true ? "true" : "false"); 369*16615Ssam } else if (s == t_char or istypename(s,"char")) { 3709675Slinton printf("'%c'", pop(char)); 3719675Slinton } else if (s->symvalue.rangev.upper == 0 and 3729675Slinton s->symvalue.rangev.lower > 0) { 3739675Slinton switch (s->symvalue.rangev.lower) { 3749675Slinton case sizeof(float): 3759675Slinton prtreal(pop(float)); 3769675Slinton break; 3779675Slinton 3789675Slinton case sizeof(double): 3799675Slinton prtreal(pop(double)); 3809675Slinton break; 3819675Slinton 3829675Slinton default: 3839675Slinton panic("bad real size %d", s->symvalue.rangev.lower); 3849675Slinton break; 3859675Slinton } 3869675Slinton } else if (s->symvalue.rangev.lower >= 0) { 3879675Slinton printf("%lu", popsmall(s)); 3889675Slinton } else { 3899675Slinton printf("%ld", popsmall(s)); 3909675Slinton } 3919675Slinton break; 3929675Slinton 3939675Slinton case FILET: 3949675Slinton case PTR: { 3959675Slinton Address addr; 3969675Slinton 3979675Slinton addr = pop(Address); 3989675Slinton if (addr == 0) { 3999675Slinton printf("0, (nil)"); 4009675Slinton } else { 4019675Slinton printf("0x%x, 0%o", addr, addr); 4029675Slinton } 4039675Slinton break; 4049675Slinton } 4059675Slinton 4069675Slinton 4079675Slinton case SCAL: { 4089675Slinton int scalar; 4099675Slinton Boolean found; 4109675Slinton 4119675Slinton scalar = popsmall(s); 4129675Slinton found = false; 4139675Slinton for (t = s->chain; t != nil; t = t->chain) { 4149675Slinton if (t->symvalue.iconval == scalar) { 4159675Slinton printf("%s", symname(t)); 4169675Slinton found = true; 4179675Slinton break; 4189675Slinton } 4199675Slinton } 4209675Slinton if (not found) { 4219675Slinton printf("(scalar = %d)", scalar); 4229675Slinton } 4239675Slinton break; 4249675Slinton } 4259675Slinton 4269675Slinton case FPROC: 4279675Slinton case FFUNC: 4289675Slinton { 4299675Slinton Address a; 4309675Slinton 4319675Slinton a = fparamaddr(pop(long)); 4329675Slinton t = whatblock(a); 4339675Slinton if (t == nil) { 4349675Slinton printf("(proc %d)", a); 4359675Slinton } else { 4369675Slinton printf("%s", symname(t)); 4379675Slinton } 4389675Slinton break; 4399675Slinton } 4409675Slinton 4419675Slinton default: 4429675Slinton if (ord(s->class) < ord(BADUSE) or ord(s->class) > ord(TYPEREF)) { 4439675Slinton panic("printval: bad class %d", ord(s->class)); 4449675Slinton } 4459675Slinton error("don't know how to print a %s", classname(s)); 4469675Slinton /* NOTREACHED */ 4479675Slinton } 4489675Slinton } 449*16615Ssam 450*16615Ssam /* 451*16615Ssam * Construct a node for subscripting. 452*16615Ssam */ 453*16615Ssam 454*16615Ssam public Node pascal_buildaref (a, slist) 455*16615Ssam Node a, slist; 456*16615Ssam { 457*16615Ssam register Symbol t; 458*16615Ssam register Node p; 459*16615Ssam Symbol etype, atype, eltype; 460*16615Ssam Node esub, r; 461*16615Ssam 462*16615Ssam r = a; 463*16615Ssam t = rtype(a->nodetype); 464*16615Ssam eltype = t->type; 465*16615Ssam if (t->class != ARRAY) { 466*16615Ssam beginerrmsg(); 467*16615Ssam prtree(stderr, a); 468*16615Ssam fprintf(stderr, " is not an array"); 469*16615Ssam enderrmsg(); 470*16615Ssam } else { 471*16615Ssam p = slist; 472*16615Ssam t = t->chain; 473*16615Ssam for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) { 474*16615Ssam esub = p->value.arg[0]; 475*16615Ssam etype = rtype(esub->nodetype); 476*16615Ssam atype = rtype(t); 477*16615Ssam if (not compatible(atype, etype)) { 478*16615Ssam beginerrmsg(); 479*16615Ssam fprintf(stderr, "subscript "); 480*16615Ssam prtree(stderr, esub); 481*16615Ssam fprintf(stderr, " is the wrong type"); 482*16615Ssam enderrmsg(); 483*16615Ssam } 484*16615Ssam r = build(O_INDEX, r, esub); 485*16615Ssam r->nodetype = eltype; 486*16615Ssam } 487*16615Ssam if (p != nil or t != nil) { 488*16615Ssam beginerrmsg(); 489*16615Ssam if (p != nil) { 490*16615Ssam fprintf(stderr, "too many subscripts for "); 491*16615Ssam } else { 492*16615Ssam fprintf(stderr, "not enough subscripts for "); 493*16615Ssam } 494*16615Ssam prtree(stderr, a); 495*16615Ssam enderrmsg(); 496*16615Ssam } 497*16615Ssam } 498*16615Ssam return r; 499*16615Ssam } 500*16615Ssam 501*16615Ssam /* 502*16615Ssam * Evaluate a subscript index. 503*16615Ssam */ 504*16615Ssam 505*16615Ssam public int pascal_evalaref (s, i) 506*16615Ssam Symbol s; 507*16615Ssam long i; 508*16615Ssam { 509*16615Ssam long lb, ub; 510*16615Ssam 511*16615Ssam s = rtype(rtype(s)->chain); 512*16615Ssam lb = s->symvalue.rangev.lower; 513*16615Ssam ub = s->symvalue.rangev.upper; 514*16615Ssam if (i < lb or i > ub) { 515*16615Ssam error("subscript %d out of range [%d..%d]", i, lb, ub); 516*16615Ssam } 517*16615Ssam return (i - lb); 518*16615Ssam } 519*16615Ssam 520*16615Ssam /* 521*16615Ssam * Initial Pascal type information. 522*16615Ssam */ 523*16615Ssam 524*16615Ssam #define NTYPES 4 525*16615Ssam 526*16615Ssam private Symbol inittype[NTYPES]; 527*16615Ssam private integer count; 528*16615Ssam 529*16615Ssam private addType (s, lower, upper) 530*16615Ssam String s; 531*16615Ssam long lower, upper; 532*16615Ssam { 533*16615Ssam register Symbol t; 534*16615Ssam 535*16615Ssam if (count > NTYPES) { 536*16615Ssam panic("too many initial types"); 537*16615Ssam } 538*16615Ssam t = maketype(s, lower, upper); 539*16615Ssam t->language = pasc; 540*16615Ssam inittype[count] = t; 541*16615Ssam ++count; 542*16615Ssam } 543*16615Ssam 544*16615Ssam private initTypes () 545*16615Ssam { 546*16615Ssam count = 1; 547*16615Ssam addType("integer", 0x80000000L, 0x7fffffffL); 548*16615Ssam addType("char", 0L, 255L); 549*16615Ssam addType("boolean", 0L, 1L); 550*16615Ssam addType("real", 4L, 0L); 551*16615Ssam } 552*16615Ssam 553*16615Ssam /* 554*16615Ssam * Initialize typetable. 555*16615Ssam */ 556*16615Ssam 557*16615Ssam public pascal_modinit (typetable) 558*16615Ssam Symbol typetable[]; 559*16615Ssam { 560*16615Ssam register integer i; 561*16615Ssam 562*16615Ssam for (i = 1; i < NTYPES; i++) { 563*16615Ssam typetable[i] = inittype[i]; 564*16615Ssam } 565*16615Ssam } 566*16615Ssam 567*16615Ssam public boolean pascal_hasmodules () 568*16615Ssam { 569*16615Ssam return false; 570*16615Ssam } 571*16615Ssam 572*16615Ssam public boolean pascal_passaddr (param, exprtype) 573*16615Ssam Symbol param, exprtype; 574*16615Ssam { 575*16615Ssam return false; 576*16615Ssam } 577