Commit | Line | Data |
---|---|---|
2a24676e DF |
1 | /* |
2 | * Copyright (c) 1983 Regents of the University of California. | |
3 | * All rights reserved. The Berkeley software License Agreement | |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
438ea14e | 6 | |
2a24676e | 7 | #ifndef lint |
ca67e7b4 | 8 | static char sccsid[] = "@(#)c.c 5.8 (Berkeley) 5/11/88"; |
2a24676e | 9 | #endif not lint |
0022c355 | 10 | |
02fcaf87 | 11 | static char rcsid[] = "$Header: c.c,v 1.5 88/04/02 01:25:44 donn Exp $"; |
438ea14e ML |
12 | |
13 | /* | |
14 | * C-dependent symbol routines. | |
15 | */ | |
16 | ||
17 | #include "defs.h" | |
18 | #include "symbols.h" | |
19 | #include "printsym.h" | |
20 | #include "languages.h" | |
21 | #include "c.h" | |
22 | #include "tree.h" | |
23 | #include "eval.h" | |
24 | #include "operators.h" | |
25 | #include "mappings.h" | |
26 | #include "process.h" | |
27 | #include "runtime.h" | |
28 | #include "machine.h" | |
29 | ||
567549ac | 30 | #ifndef public |
adbf81b2 | 31 | # include "tree.h" |
567549ac AF |
32 | #endif |
33 | ||
438ea14e ML |
34 | #define isdouble(range) ( \ |
35 | range->symvalue.rangev.upper == 0 and range->symvalue.rangev.lower > 0 \ | |
36 | ) | |
37 | ||
38 | #define isrange(t, name) (t->class == RANGE and istypename(t->type, name)) | |
39 | ||
2fd0f574 | 40 | private Language langC; |
adbf81b2 | 41 | private Language langCplpl; |
2fd0f574 | 42 | |
438ea14e ML |
43 | /* |
44 | * Initialize C language information. | |
45 | */ | |
46 | ||
47 | public c_init() | |
48 | { | |
2fd0f574 SL |
49 | langC = language_define("c", ".c"); |
50 | language_setop(langC, L_PRINTDECL, c_printdecl); | |
51 | language_setop(langC, L_PRINTVAL, c_printval); | |
52 | language_setop(langC, L_TYPEMATCH, c_typematch); | |
53 | language_setop(langC, L_BUILDAREF, c_buildaref); | |
54 | language_setop(langC, L_EVALAREF, c_evalaref); | |
55 | language_setop(langC, L_MODINIT, c_modinit); | |
56 | language_setop(langC, L_HASMODULES, c_hasmodules); | |
57 | language_setop(langC, L_PASSADDR, c_passaddr); | |
adbf81b2 DS |
58 | |
59 | langCplpl = language_define("c++", "..c"); | |
60 | language_setop(langCplpl, L_PRINTDECL, c_printdecl); | |
61 | language_setop(langCplpl, L_PRINTVAL, c_printval); | |
62 | language_setop(langCplpl, L_TYPEMATCH, c_typematch); | |
63 | language_setop(langCplpl, L_BUILDAREF, c_buildaref); | |
64 | language_setop(langCplpl, L_EVALAREF, c_evalaref); | |
65 | language_setop(langCplpl, L_MODINIT, c_modinit); | |
66 | language_setop(langCplpl, L_HASMODULES, c_hasmodules); | |
67 | language_setop(langCplpl, L_PASSADDR, c_passaddr); | |
438ea14e ML |
68 | } |
69 | ||
70 | /* | |
71 | * Test if two types are compatible. | |
438ea14e ML |
72 | */ |
73 | ||
74 | public Boolean c_typematch(type1, type2) | |
75 | Symbol type1, type2; | |
76 | { | |
77 | Boolean b; | |
78 | register Symbol t1, t2, tmp; | |
79 | ||
80 | t1 = type1; | |
81 | t2 = type2; | |
82 | if (t1 == t2) { | |
83 | b = true; | |
84 | } else { | |
85 | t1 = rtype(t1); | |
86 | t2 = rtype(t2); | |
2fd0f574 | 87 | if (t1 == t_char->type or t1 == t_int->type or t1 == t_real->type) { |
438ea14e ML |
88 | tmp = t1; |
89 | t1 = t2; | |
90 | t2 = tmp; | |
91 | } | |
92 | b = (Boolean) ( | |
93 | ( | |
02fcaf87 | 94 | isrange(t1, "int") and !isdouble(t1) /* sigh */ and |
2fd0f574 | 95 | (t2 == t_int->type or t2 == t_char->type) |
438ea14e ML |
96 | ) or ( |
97 | isrange(t1, "char") and | |
2fd0f574 | 98 | (t2 == t_char->type or t2 == t_int->type) |
7297918f | 99 | ) or ( |
2fd0f574 | 100 | t1->class == RANGE and isdouble(t1) and t2 == t_real->type |
0022c355 ML |
101 | ) or ( |
102 | t1->class == RANGE and t2->class == RANGE and | |
103 | t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and | |
104 | t1->symvalue.rangev.upper == t2->symvalue.rangev.upper | |
438ea14e | 105 | ) or ( |
02fcaf87 | 106 | t1->class != RANGE and t1->type == t2->type and ( |
438ea14e ML |
107 | (t1->class == t2->class) or |
108 | (t1->class == SCAL and t2->class == CONST) or | |
109 | (t1->class == CONST and t2->class == SCAL) | |
110 | ) | |
2fd0f574 SL |
111 | ) or ( |
112 | t1->class == PTR and c_typematch(t1->type, t_char) and | |
113 | t2->class == ARRAY and c_typematch(t2->type, t_char) and | |
114 | t2->language == primlang | |
438ea14e ML |
115 | ) |
116 | ); | |
117 | } | |
118 | return b; | |
119 | } | |
120 | ||
438ea14e ML |
121 | /* |
122 | * Print out the declaration of a C variable. | |
123 | */ | |
124 | ||
125 | public c_printdecl(s) | |
126 | Symbol s; | |
127 | { | |
128 | printdecl(s, 0); | |
129 | } | |
130 | ||
131 | private printdecl(s, indent) | |
132 | register Symbol s; | |
133 | Integer indent; | |
134 | { | |
135 | register Symbol t; | |
136 | Boolean semicolon, newline; | |
137 | ||
138 | semicolon = true; | |
139 | newline = true; | |
140 | if (indent > 0) { | |
141 | printf("%*c", indent, ' '); | |
142 | } | |
143 | if (s->class == TYPE) { | |
144 | printf("typedef "); | |
145 | } | |
146 | switch (s->class) { | |
147 | case CONST: | |
148 | if (s->type->class == SCAL) { | |
0022c355 ML |
149 | printf("enumeration constant with value "); |
150 | eval(s->symvalue.constval); | |
151 | c_printval(s); | |
438ea14e ML |
152 | } else { |
153 | printf("const %s = ", symname(s)); | |
154 | printval(s); | |
155 | } | |
156 | break; | |
157 | ||
158 | case TYPE: | |
159 | case VAR: | |
adbf81b2 | 160 | if (s->class != TYPE and s->storage == INREG) { |
0022c355 | 161 | printf("register "); |
438ea14e ML |
162 | } |
163 | if (s->type->class == ARRAY) { | |
164 | printtype(s->type, s->type->type, indent); | |
165 | t = rtype(s->type->chain); | |
166 | assert(t->class == RANGE); | |
167 | printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1); | |
168 | } else { | |
169 | printtype(s, s->type, indent); | |
170 | if (s->type->class != PTR) { | |
171 | printf(" "); | |
172 | } | |
173 | printf("%s", symname(s)); | |
174 | } | |
175 | break; | |
176 | ||
177 | case FIELD: | |
178 | if (s->type->class == ARRAY) { | |
179 | printtype(s->type, s->type->type, indent); | |
180 | t = rtype(s->type->chain); | |
181 | assert(t->class == RANGE); | |
182 | printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1); | |
183 | } else { | |
184 | printtype(s, s->type, indent); | |
185 | if (s->type->class != PTR) { | |
186 | printf(" "); | |
187 | } | |
188 | printf("%s", symname(s)); | |
189 | } | |
190 | if (isbitfield(s)) { | |
191 | printf(" : %d", s->symvalue.field.length); | |
192 | } | |
193 | break; | |
194 | ||
195 | case TAG: | |
196 | if (s->type == nil) { | |
197 | findtype(s); | |
198 | if (s->type == nil) { | |
199 | error("unexpected missing type information"); | |
200 | } | |
201 | } | |
202 | printtype(s, s->type, indent); | |
203 | break; | |
204 | ||
205 | case RANGE: | |
206 | case ARRAY: | |
207 | case RECORD: | |
208 | case VARNT: | |
209 | case PTR: | |
0022c355 | 210 | case FFUNC: |
438ea14e ML |
211 | semicolon = false; |
212 | printtype(s, s, indent); | |
213 | break; | |
214 | ||
0022c355 ML |
215 | case SCAL: |
216 | printf("(enumeration constant, value %d)", s->symvalue.iconval); | |
217 | break; | |
218 | ||
438ea14e ML |
219 | case PROC: |
220 | semicolon = false; | |
221 | printf("%s", symname(s)); | |
222 | c_listparams(s); | |
223 | newline = false; | |
224 | break; | |
225 | ||
226 | case FUNC: | |
227 | semicolon = false; | |
228 | if (not istypename(s->type, "void")) { | |
229 | printtype(s, s->type, indent); | |
230 | printf(" "); | |
231 | } | |
232 | printf("%s", symname(s)); | |
233 | c_listparams(s); | |
234 | newline = false; | |
235 | break; | |
236 | ||
237 | case MODULE: | |
238 | semicolon = false; | |
239 | printf("source file \"%s.c\"", symname(s)); | |
240 | break; | |
241 | ||
242 | case PROG: | |
243 | semicolon = false; | |
244 | printf("executable file \"%s\"", symname(s)); | |
245 | break; | |
246 | ||
247 | default: | |
0022c355 ML |
248 | printf("[%s]", classname(s)); |
249 | break; | |
438ea14e ML |
250 | } |
251 | if (semicolon) { | |
252 | putchar(';'); | |
253 | } | |
254 | if (newline) { | |
255 | putchar('\n'); | |
256 | } | |
257 | } | |
258 | ||
259 | /* | |
260 | * Recursive whiz-bang procedure to print the type portion | |
261 | * of a declaration. | |
262 | * | |
263 | * The symbol associated with the type is passed to allow | |
264 | * searching for type names without getting "type blah = blah". | |
265 | */ | |
266 | ||
267 | private printtype(s, t, indent) | |
268 | Symbol s; | |
269 | Symbol t; | |
270 | Integer indent; | |
271 | { | |
272 | register Symbol i; | |
273 | long r0, r1; | |
274 | register String p; | |
275 | ||
276 | checkref(s); | |
277 | checkref(t); | |
278 | switch (t->class) { | |
279 | case VAR: | |
280 | case CONST: | |
281 | case PROC: | |
282 | panic("printtype: class %s", classname(t)); | |
283 | break; | |
284 | ||
285 | case ARRAY: | |
286 | printf("array["); | |
287 | i = t->chain; | |
288 | if (i != nil) { | |
289 | for (;;) { | |
290 | printtype(i, i, indent); | |
291 | i = i->chain; | |
292 | if (i == nil) { | |
293 | break; | |
294 | } | |
295 | printf(", "); | |
296 | } | |
297 | } | |
298 | printf("] of "); | |
299 | printtype(t, t->type, indent); | |
300 | break; | |
301 | ||
302 | case RECORD: | |
303 | case VARNT: | |
304 | printf("%s ", c_classname(t)); | |
305 | if (s->name != nil and s->class == TAG) { | |
306 | p = symname(s); | |
307 | if (p[0] == '$' and p[1] == '$') { | |
308 | printf("%s ", &p[2]); | |
309 | } else { | |
310 | printf("%s ", p); | |
311 | } | |
312 | } | |
56fc1e71 | 313 | printf("{\n"); |
438ea14e ML |
314 | for (i = t->chain; i != nil; i = i->chain) { |
315 | assert(i->class == FIELD); | |
316 | printdecl(i, indent+4); | |
317 | } | |
318 | if (indent > 0) { | |
319 | printf("%*c", indent, ' '); | |
320 | } | |
321 | printf("}"); | |
322 | break; | |
323 | ||
324 | case RANGE: | |
325 | r0 = t->symvalue.rangev.lower; | |
326 | r1 = t->symvalue.rangev.upper; | |
327 | if (istypename(t->type, "char")) { | |
328 | if (r0 < 0x20 or r0 > 0x7e) { | |
329 | printf("%ld..", r0); | |
330 | } else { | |
331 | printf("'%c'..", (char) r0); | |
332 | } | |
333 | if (r1 < 0x20 or r1 > 0x7e) { | |
334 | printf("\\%lo", r1); | |
335 | } else { | |
336 | printf("'%c'", (char) r1); | |
337 | } | |
338 | } else if (r0 > 0 and r1 == 0) { | |
339 | printf("%ld byte real", r0); | |
340 | } else if (r0 >= 0) { | |
341 | printf("%lu..%lu", r0, r1); | |
342 | } else { | |
343 | printf("%ld..%ld", r0, r1); | |
344 | } | |
345 | break; | |
346 | ||
347 | case PTR: | |
348 | printtype(t, t->type, indent); | |
349 | if (t->type->class != PTR) { | |
350 | printf(" "); | |
351 | } | |
352 | printf("*"); | |
353 | break; | |
354 | ||
355 | case FUNC: | |
2fd0f574 | 356 | case FFUNC: |
438ea14e ML |
357 | printtype(t, t->type, indent); |
358 | printf("()"); | |
359 | break; | |
360 | ||
361 | case TYPE: | |
362 | if (t->name != nil) { | |
2fd0f574 | 363 | printname(stdout, t); |
438ea14e ML |
364 | } else { |
365 | printtype(t, t->type, indent); | |
366 | } | |
367 | break; | |
368 | ||
369 | case TYPEREF: | |
370 | printf("@%s", symname(t)); | |
371 | break; | |
372 | ||
373 | case SCAL: | |
374 | printf("enum "); | |
375 | if (s->name != nil and s->class == TAG) { | |
376 | printf("%s ", symname(s)); | |
377 | } | |
378 | printf("{ "); | |
379 | i = t->chain; | |
380 | if (i != nil) { | |
381 | for (;;) { | |
382 | printf("%s", symname(i)); | |
383 | i = i->chain; | |
384 | if (i == nil) break; | |
385 | printf(", "); | |
386 | } | |
387 | } | |
388 | printf(" }"); | |
389 | break; | |
390 | ||
391 | case TAG: | |
392 | if (t->type == nil) { | |
393 | printf("unresolved tag %s", symname(t)); | |
394 | } else { | |
395 | i = rtype(t->type); | |
396 | printf("%s %s", c_classname(i), symname(t)); | |
397 | } | |
398 | break; | |
399 | ||
400 | default: | |
401 | printf("(class %d)", t->class); | |
402 | break; | |
403 | } | |
404 | } | |
405 | ||
406 | /* | |
407 | * List the parameters of a procedure or function. | |
408 | * No attempt is made to combine like types. | |
409 | */ | |
410 | ||
411 | public c_listparams(s) | |
412 | Symbol s; | |
413 | { | |
414 | register Symbol t; | |
415 | ||
416 | putchar('('); | |
417 | for (t = s->chain; t != nil; t = t->chain) { | |
418 | printf("%s", symname(t)); | |
419 | if (t->chain != nil) { | |
420 | printf(", "); | |
421 | } | |
422 | } | |
423 | putchar(')'); | |
424 | if (s->chain != nil) { | |
425 | printf("\n"); | |
426 | for (t = s->chain; t != nil; t = t->chain) { | |
427 | if (t->class != VAR) { | |
428 | panic("unexpected class %d for parameter", t->class); | |
429 | } | |
430 | printdecl(t, 0); | |
431 | } | |
432 | } else { | |
433 | putchar('\n'); | |
434 | } | |
435 | } | |
436 | ||
437 | /* | |
438 | * Print out the value on the top of the expression stack | |
439 | * in the format for the type of the given symbol. | |
440 | */ | |
441 | ||
442 | public c_printval(s) | |
443 | Symbol s; | |
444 | { | |
445 | register Symbol t; | |
446 | register Address a; | |
2fd0f574 | 447 | integer i, len; |
594c02f6 | 448 | register String str; |
438ea14e ML |
449 | |
450 | switch (s->class) { | |
451 | case CONST: | |
452 | case TYPE: | |
453 | case VAR: | |
454 | case REF: | |
455 | case FVAR: | |
456 | case TAG: | |
457 | c_printval(s->type); | |
458 | break; | |
459 | ||
460 | case FIELD: | |
461 | if (isbitfield(s)) { | |
adbf81b2 | 462 | i = extractField(s); |
438ea14e ML |
463 | t = rtype(s->type); |
464 | if (t->class == SCAL) { | |
0022c355 | 465 | printEnum(i, t); |
438ea14e | 466 | } else { |
0022c355 | 467 | printRangeVal(i, t); |
438ea14e ML |
468 | } |
469 | } else { | |
470 | c_printval(s->type); | |
471 | } | |
472 | break; | |
473 | ||
474 | case ARRAY: | |
475 | t = rtype(s->type); | |
2fd0f574 SL |
476 | if ((t->class == RANGE and istypename(t->type, "char")) or |
477 | t == t_char->type | |
478 | ) { | |
438ea14e | 479 | len = size(s); |
594c02f6 SL |
480 | str = (String) (sp -= len); |
481 | if (s->language != primlang) { | |
482 | putchar('"'); | |
483 | } | |
3b80d068 | 484 | while (--len > 0 and *str != '\0') { |
594c02f6 | 485 | printchar(*str++); |
3b80d068 SL |
486 | } |
487 | if (*str != '\0') { /* XXX - pitch trailing null */ | |
488 | printchar(*str); | |
594c02f6 SL |
489 | } |
490 | if (s->language != primlang) { | |
491 | putchar('"'); | |
0022c355 | 492 | } |
438ea14e ML |
493 | } else { |
494 | printarray(s); | |
495 | } | |
496 | break; | |
497 | ||
498 | case RECORD: | |
438ea14e ML |
499 | c_printstruct(s); |
500 | break; | |
501 | ||
502 | case RANGE: | |
0022c355 ML |
503 | if (s == t_boolean->type or istypename(s->type, "boolean")) { |
504 | printRangeVal(popsmall(s), s); | |
505 | } else if (s == t_char->type or istypename(s->type, "char")) { | |
506 | printRangeVal(pop(char), s); | |
507 | } else if (s == t_real->type or isdouble(s)) { | |
438ea14e ML |
508 | switch (s->symvalue.rangev.lower) { |
509 | case sizeof(float): | |
adbf81b2 | 510 | prtreal((double) (pop(float))); |
438ea14e ML |
511 | break; |
512 | ||
513 | case sizeof(double): | |
514 | prtreal(pop(double)); | |
515 | break; | |
516 | ||
517 | default: | |
518 | panic("bad real size %d", t->symvalue.rangev.lower); | |
519 | break; | |
520 | } | |
521 | } else { | |
0022c355 | 522 | printRangeVal(popsmall(s), s); |
438ea14e ML |
523 | } |
524 | break; | |
525 | ||
526 | case PTR: | |
527 | t = rtype(s->type); | |
528 | a = pop(Address); | |
529 | if (a == 0) { | |
530 | printf("(nil)"); | |
531 | } else if (t->class == RANGE and istypename(t->type, "char")) { | |
0022c355 | 532 | printString(a, (boolean) (s->language != primlang)); |
438ea14e ML |
533 | } else { |
534 | printf("0x%x", a); | |
535 | } | |
536 | break; | |
537 | ||
538 | case SCAL: | |
539 | i = pop(Integer); | |
0022c355 ML |
540 | printEnum(i, s); |
541 | break; | |
542 | ||
543 | /* | |
544 | * Unresolved structure pointers? | |
545 | */ | |
546 | case BADUSE: | |
547 | a = pop(Address); | |
548 | printf("@%x", a); | |
438ea14e ML |
549 | break; |
550 | ||
551 | default: | |
552 | if (ord(s->class) > ord(TYPEREF)) { | |
553 | panic("printval: bad class %d", ord(s->class)); | |
554 | } | |
05044e0a | 555 | sp -= size(s); |
2fd0f574 | 556 | printf("[%s]", c_classname(s)); |
05044e0a | 557 | break; |
438ea14e ML |
558 | } |
559 | } | |
560 | ||
561 | /* | |
562 | * Print out a C structure. | |
563 | */ | |
564 | ||
0022c355 | 565 | private c_printstruct (s) |
438ea14e ML |
566 | Symbol s; |
567 | { | |
0022c355 ML |
568 | Symbol f; |
569 | Stack *savesp; | |
570 | integer n, off, len; | |
438ea14e ML |
571 | |
572 | sp -= size(s); | |
573 | savesp = sp; | |
574 | printf("("); | |
575 | f = s->chain; | |
576 | for (;;) { | |
577 | off = f->symvalue.field.offset; | |
578 | len = f->symvalue.field.length; | |
2fd0f574 | 579 | n = (off + len + BITSPERBYTE - 1) div BITSPERBYTE; |
438ea14e ML |
580 | sp += n; |
581 | printf("%s = ", symname(f)); | |
582 | c_printval(f); | |
583 | sp = savesp; | |
584 | f = f->chain; | |
585 | if (f == nil) break; | |
586 | printf(", "); | |
587 | } | |
588 | printf(")"); | |
589 | } | |
590 | ||
438ea14e ML |
591 | /* |
592 | * Return the C name for the particular class of a symbol. | |
593 | */ | |
594 | ||
595 | public String c_classname(s) | |
596 | Symbol s; | |
597 | { | |
598 | String str; | |
599 | ||
600 | switch (s->class) { | |
601 | case RECORD: | |
602 | str = "struct"; | |
603 | break; | |
604 | ||
605 | case VARNT: | |
606 | str = "union"; | |
607 | break; | |
608 | ||
609 | case SCAL: | |
610 | str = "enum"; | |
611 | break; | |
612 | ||
613 | default: | |
614 | str = classname(s); | |
615 | } | |
616 | return str; | |
617 | } | |
0022c355 | 618 | |
bc5322a9 AF |
619 | public Node c_buildaref(a, slist) |
620 | Node a, slist; | |
621 | { | |
622 | register Symbol t; | |
623 | register Node p; | |
624 | Symbol etype, atype, eltype; | |
0022c355 | 625 | Node r, esub; |
bc5322a9 | 626 | |
bc5322a9 AF |
627 | t = rtype(a->nodetype); |
628 | eltype = t->type; | |
629 | if (t->class == PTR) { | |
630 | p = slist->value.arg[0]; | |
631 | if (not compatible(p->nodetype, t_int)) { | |
632 | beginerrmsg(); | |
0022c355 | 633 | fprintf(stderr, "subscript must be integer-compatible"); |
bc5322a9 AF |
634 | enderrmsg(); |
635 | } | |
636 | r = build(O_MUL, p, build(O_LCON, (long) size(eltype))); | |
637 | r = build(O_ADD, build(O_RVAL, a), r); | |
638 | r->nodetype = eltype; | |
639 | } else if (t->class != ARRAY) { | |
640 | beginerrmsg(); | |
0022c355 | 641 | fprintf(stderr, "\""); |
bc5322a9 | 642 | prtree(stderr, a); |
0022c355 | 643 | fprintf(stderr, "\" is not an array"); |
bc5322a9 AF |
644 | enderrmsg(); |
645 | } else { | |
0022c355 | 646 | r = a; |
bc5322a9 AF |
647 | p = slist; |
648 | t = t->chain; | |
649 | for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) { | |
650 | esub = p->value.arg[0]; | |
651 | etype = rtype(esub->nodetype); | |
652 | atype = rtype(t); | |
653 | if (not compatible(atype, etype)) { | |
654 | beginerrmsg(); | |
0022c355 | 655 | fprintf(stderr, "subscript \""); |
bc5322a9 | 656 | prtree(stderr, esub); |
0022c355 | 657 | fprintf(stderr, "\" is the wrong type"); |
bc5322a9 AF |
658 | enderrmsg(); |
659 | } | |
660 | r = build(O_INDEX, r, esub); | |
661 | r->nodetype = eltype; | |
662 | } | |
663 | if (p != nil or t != nil) { | |
664 | beginerrmsg(); | |
665 | if (p != nil) { | |
0022c355 | 666 | fprintf(stderr, "too many subscripts for \""); |
bc5322a9 | 667 | } else { |
0022c355 | 668 | fprintf(stderr, "not enough subscripts for \""); |
bc5322a9 AF |
669 | } |
670 | prtree(stderr, a); | |
0022c355 | 671 | fprintf(stderr, "\""); |
bc5322a9 AF |
672 | enderrmsg(); |
673 | } | |
674 | } | |
675 | return r; | |
676 | } | |
677 | ||
678 | /* | |
679 | * Evaluate a subscript index. | |
680 | */ | |
681 | ||
0022c355 | 682 | public c_evalaref(s, base, i) |
bc5322a9 | 683 | Symbol s; |
0022c355 | 684 | Address base; |
bc5322a9 AF |
685 | long i; |
686 | { | |
0022c355 | 687 | Symbol t; |
bc5322a9 AF |
688 | long lb, ub; |
689 | ||
0022c355 ML |
690 | t = rtype(s); |
691 | s = t->chain; | |
bc5322a9 AF |
692 | lb = s->symvalue.rangev.lower; |
693 | ub = s->symvalue.rangev.upper; | |
694 | if (i < lb or i > ub) { | |
594c02f6 | 695 | warning("subscript out of range"); |
bc5322a9 | 696 | } |
0022c355 | 697 | push(long, base + (i - lb) * size(t->type)); |
bc5322a9 | 698 | } |
2fd0f574 SL |
699 | |
700 | /* | |
701 | * Initialize typetable information. | |
702 | */ | |
703 | ||
704 | public c_modinit (typetable) | |
705 | Symbol typetable[]; | |
706 | { | |
707 | /* nothing right now */ | |
708 | } | |
709 | ||
710 | public boolean c_hasmodules () | |
711 | { | |
712 | return false; | |
713 | } | |
714 | ||
715 | public boolean c_passaddr (param, exprtype) | |
716 | Symbol param, exprtype; | |
717 | { | |
718 | boolean b; | |
719 | Symbol t; | |
720 | ||
721 | t = rtype(exprtype); | |
722 | b = (boolean) (t->class == ARRAY); | |
723 | return b; | |
724 | } |