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