1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)@(#)pascal.c 1.1 12/15/82"; 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 /* 24 * Initialize Pascal information. 25 */ 26 27 public pascal_init() 28 { 29 Language lang; 30 31 lang = language_define("pascal", ".p"); 32 language_setop(lang, L_PRINTDECL, pascal_printdecl); 33 language_setop(lang, L_PRINTVAL, pascal_printval); 34 language_setop(lang, L_TYPEMATCH, pascal_typematch); 35 } 36 37 /* 38 * Compatible tests if two types are compatible. The issue 39 * is complicated a bit by ranges. 40 * 41 * Integers and reals are not compatible since they cannot always be mixed. 42 */ 43 44 public Boolean pascal_typematch(type1, type2) 45 Symbol type1, type2; 46 { 47 Boolean b; 48 register Symbol t1, t2; 49 50 t1 = rtype(t1); 51 t2 = rtype(t2); 52 b = (Boolean) 53 (t1->type == t2->type and ( 54 (t1->class == RANGE and t2->class == RANGE) or 55 (t1->class == SCAL and t2->class == CONST) or 56 (t1->class == CONST and t2->class == SCAL) or 57 (t1->type == t_char and t1->class == ARRAY and t2->class == ARRAY) 58 ) or 59 (t1 == t_nil and t2->class == PTR) or 60 (t1->class == PTR and t2 == t_nil) 61 ); 62 return b; 63 } 64 65 public pascal_printdecl(s) 66 Symbol s; 67 { 68 register Symbol t; 69 Boolean semicolon; 70 71 semicolon = true; 72 switch (s->class) { 73 case CONST: 74 if (s->type->class == SCAL) { 75 printf("(enumeration constant, ord %ld)", 76 s->symvalue.iconval); 77 } else { 78 printf("const %s = ", symname(s)); 79 printval(s); 80 } 81 break; 82 83 case TYPE: 84 printf("type %s = ", symname(s)); 85 printtype(s, s->type); 86 break; 87 88 case VAR: 89 if (isparam(s)) { 90 printf("(parameter) %s : ", symname(s)); 91 } else { 92 printf("var %s : ", symname(s)); 93 } 94 printtype(s, s->type); 95 break; 96 97 case REF: 98 printf("(var parameter) %s : ", symname(s)); 99 printtype(s, s->type); 100 break; 101 102 case RANGE: 103 case ARRAY: 104 case RECORD: 105 case VARNT: 106 case PTR: 107 printtype(s, s); 108 semicolon = false; 109 break; 110 111 case FVAR: 112 printf("(function variable) %s : ", symname(s)); 113 printtype(s, s->type); 114 break; 115 116 case FIELD: 117 printf("(field) %s : ", symname(s)); 118 printtype(s, s->type); 119 break; 120 121 case PROC: 122 printf("procedure %s", symname(s)); 123 listparams(s); 124 break; 125 126 case PROG: 127 printf("program %s", symname(s)); 128 t = s->chain; 129 if (t != nil) { 130 printf("(%s", symname(t)); 131 for (t = t->chain; t != nil; t = t->chain) { 132 printf(", %s", symname(t)); 133 } 134 printf(")"); 135 } 136 break; 137 138 case FUNC: 139 printf("function %s", symname(s)); 140 listparams(s); 141 printf(" : "); 142 printtype(s, s->type); 143 break; 144 145 default: 146 error("class %s in printdecl", classname(s)); 147 } 148 if (semicolon) { 149 putchar(';'); 150 } 151 putchar('\n'); 152 } 153 154 /* 155 * Recursive whiz-bang procedure to print the type portion 156 * of a declaration. Doesn't work quite right for variant records. 157 * 158 * The symbol associated with the type is passed to allow 159 * searching for type names without getting "type blah = blah". 160 */ 161 162 private printtype(s, t) 163 Symbol s; 164 Symbol t; 165 { 166 register Symbol tmp; 167 168 switch (t->class) { 169 case VAR: 170 case CONST: 171 case FUNC: 172 case PROC: 173 panic("printtype: class %s", classname(t)); 174 break; 175 176 case ARRAY: 177 printf("array["); 178 tmp = t->chain; 179 if (tmp != nil) { 180 for (;;) { 181 printtype(tmp, tmp); 182 tmp = tmp->chain; 183 if (tmp == nil) { 184 break; 185 } 186 printf(", "); 187 } 188 } 189 printf("] of "); 190 printtype(t, t->type); 191 break; 192 193 case RECORD: 194 printf("record\n"); 195 if (t->chain != nil) { 196 printtype(t->chain, t->chain); 197 } 198 printf("end"); 199 break; 200 201 case FIELD: 202 if (t->chain != nil) { 203 printtype(t->chain, t->chain); 204 } 205 printf("\t%s : ", symname(t)); 206 printtype(t, t->type); 207 printf(";\n"); 208 break; 209 210 case RANGE: { 211 long r0, r1; 212 213 r0 = t->symvalue.rangev.lower; 214 r1 = t->symvalue.rangev.upper; 215 if (t == t_char) { 216 if (r0 < 0x20 or r0 > 0x7e) { 217 printf("%ld..", r0); 218 } else { 219 printf("'%c'..", (char) r0); 220 } 221 if (r1 < 0x20 or r1 > 0x7e) { 222 printf("\\%lo", r1); 223 } else { 224 printf("'%c'", (char) r1); 225 } 226 } else if (r0 > 0 and r1 == 0) { 227 printf("%ld byte real", r0); 228 } else if (r0 >= 0) { 229 printf("%lu..%lu", r0, r1); 230 } else { 231 printf("%ld..%ld", r0, r1); 232 } 233 break; 234 } 235 236 case PTR: 237 putchar('*'); 238 printtype(t, t->type); 239 break; 240 241 case TYPE: 242 if (symname(t) != nil) { 243 printf("%s", symname(t)); 244 } else { 245 printtype(t, t->type); 246 } 247 break; 248 249 case SCAL: 250 printf("("); 251 t = t->type->chain; 252 if (t != nil) { 253 printf("%s", symname(t)); 254 t = t->chain; 255 while (t != nil) { 256 printf(", %s", symname(t)); 257 t = t->chain; 258 } 259 } else { 260 panic("empty enumeration"); 261 } 262 printf(")"); 263 break; 264 265 default: 266 printf("(class %d)", t->class); 267 break; 268 } 269 } 270 271 /* 272 * List the parameters of a procedure or function. 273 * No attempt is made to combine like types. 274 */ 275 276 private listparams(s) 277 Symbol s; 278 { 279 Symbol t; 280 281 if (s->chain != nil) { 282 putchar('('); 283 for (t = s->chain; t != nil; t = t->chain) { 284 switch (t->class) { 285 case REF: 286 printf("var "); 287 break; 288 289 case FPROC: 290 printf("procedure "); 291 break; 292 293 case FFUNC: 294 printf("function "); 295 break; 296 297 case VAR: 298 break; 299 300 default: 301 panic("unexpected class %d for parameter", t->class); 302 } 303 printf("%s : ", symname(t)); 304 printtype(t, t->type); 305 if (t->chain != nil) { 306 printf("; "); 307 } 308 } 309 putchar(')'); 310 } 311 } 312 313 /* 314 * Print out the value on the top of the expression stack 315 * in the format for the type of the given symbol. 316 */ 317 318 public pascal_printval(s) 319 Symbol s; 320 { 321 Symbol t; 322 Address a; 323 int len; 324 double r; 325 326 if (s->class == REF) { 327 s = s->type; 328 } 329 switch (s->class) { 330 case TYPE: 331 pascal_printval(s->type); 332 break; 333 334 case ARRAY: 335 t = rtype(s->type); 336 if (t==t_char or (t->class==RANGE and t->type==t_char)) { 337 len = size(s); 338 sp -= len; 339 printf("'%.*s'", len, sp); 340 break; 341 } else { 342 printarray(s); 343 } 344 break; 345 346 case RECORD: 347 printrecord(s); 348 break; 349 350 case VARNT: 351 error("can't print out variant records"); 352 break; 353 354 355 case RANGE: 356 if (s == t_boolean) { 357 printf(((Boolean) popsmall(s)) == true ? "true" : "false"); 358 } else if (s == t_char) { 359 printf("'%c'", pop(char)); 360 } else if (s->symvalue.rangev.upper == 0 and 361 s->symvalue.rangev.lower > 0) { 362 switch (s->symvalue.rangev.lower) { 363 case sizeof(float): 364 prtreal(pop(float)); 365 break; 366 367 case sizeof(double): 368 prtreal(pop(double)); 369 break; 370 371 default: 372 panic("bad real size %d", s->symvalue.rangev.lower); 373 break; 374 } 375 } else if (s->symvalue.rangev.lower >= 0) { 376 printf("%lu", popsmall(s)); 377 } else { 378 printf("%ld", popsmall(s)); 379 } 380 break; 381 382 case FILET: 383 case PTR: { 384 Address addr; 385 386 addr = pop(Address); 387 if (addr == 0) { 388 printf("0, (nil)"); 389 } else { 390 printf("0x%x, 0%o", addr, addr); 391 } 392 break; 393 } 394 395 case FIELD: 396 error("missing record specification"); 397 break; 398 399 case SCAL: { 400 int scalar; 401 Boolean found; 402 403 scalar = popsmall(s); 404 found = false; 405 for (t = s->chain; t != nil; t = t->chain) { 406 if (t->symvalue.iconval == scalar) { 407 printf("%s", symname(t)); 408 found = true; 409 break; 410 } 411 } 412 if (not found) { 413 printf("(scalar = %d)", scalar); 414 } 415 break; 416 } 417 418 case FPROC: 419 case FFUNC: 420 { 421 Address a; 422 423 a = fparamaddr(pop(long)); 424 t = whatblock(a); 425 if (t == nil) { 426 printf("(proc %d)", a); 427 } else { 428 printf("%s", symname(t)); 429 } 430 break; 431 } 432 433 default: 434 if (ord(s->class) < ord(BADUSE) or ord(s->class) > ord(TYPEREF)) { 435 panic("printval: bad class %d", ord(s->class)); 436 } 437 error("don't know how to print a %s", classname(s)); 438 /* NOTREACHED */ 439 } 440 } 441