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