xref: /original-bsd/old/dbx/c.c (revision f0fd5f8a)
1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)c.c 1.2 12/15/82";
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 
32 public 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 
48 public Boolean c_typematch(type1, type2)
49 Symbol 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 
89 private Boolean isbitfield(s)
90 register 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 
114 public c_printdecl(s)
115 Symbol s;
116 {
117     printdecl(s, 0);
118 }
119 
120 private printdecl(s, indent)
121 register Symbol s;
122 Integer 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 
253 private printtype(s, t, indent)
254 Symbol s;
255 Symbol t;
256 Integer 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 
396 public c_listparams(s)
397 Symbol 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 
427 public c_printval(s)
428 Symbol 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 
537 private c_printstruct(s)
538 Symbol 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 
567 private printrange(i, t)
568 Integer i;
569 register 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 
589 private printstring(addr)
590 Address 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 
624 private printenum(i, t)
625 Integer i;
626 Symbol 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 
645 public String c_classname(s)
646 Symbol 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 }
668