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