xref: /original-bsd/old/dbx/c.c (revision a6ded71d)
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.6 (Berkeley) 07/02/87";
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");
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 = extractfield(i, s);
454 		t = rtype(s->type);
455 		if (t->class == SCAL) {
456 		    printEnum(i, t);
457 		} else {
458 		    printRangeVal(i, t);
459 		}
460 	    } else {
461 		c_printval(s->type);
462 	    }
463 	    break;
464 
465 	case ARRAY:
466 	    t = rtype(s->type);
467 	    if ((t->class == RANGE and istypename(t->type, "char")) or
468 		t == t_char->type
469 	    ) {
470 		len = size(s);
471 		str = (String) (sp -= len);
472 		if (s->language != primlang) {
473 		    putchar('"');
474 		}
475 		while (--len > 0 and *str != '\0') {
476 		    printchar(*str++);
477 		}
478 		if (*str != '\0') {	/* XXX - pitch trailing null */
479 		    printchar(*str);
480 		}
481 		if (s->language != primlang) {
482 		    putchar('"');
483 		}
484 	    } else {
485 		printarray(s);
486 	    }
487 	    break;
488 
489 	case RECORD:
490 	    c_printstruct(s);
491 	    break;
492 
493 	case RANGE:
494 	    if (s == t_boolean->type or istypename(s->type, "boolean")) {
495 		printRangeVal(popsmall(s), s);
496 	    } else if (s == t_char->type or istypename(s->type, "char")) {
497 		printRangeVal(pop(char), s);
498 	    } else if (s == t_real->type or isdouble(s)) {
499 		switch (s->symvalue.rangev.lower) {
500 		    case sizeof(float):
501 			prtreal(pop(float));
502 			break;
503 
504 		    case sizeof(double):
505 			prtreal(pop(double));
506 			break;
507 
508 		    default:
509 			panic("bad real size %d", t->symvalue.rangev.lower);
510 			break;
511 		}
512 	    } else {
513 		printRangeVal(popsmall(s), s);
514 	    }
515 	    break;
516 
517 	case PTR:
518 	    t = rtype(s->type);
519 	    a = pop(Address);
520 	    if (a == 0) {
521 		printf("(nil)");
522 	    } else if (t->class == RANGE and istypename(t->type, "char")) {
523 		printString(a, (boolean) (s->language != primlang));
524 	    } else {
525 		printf("0x%x", a);
526 	    }
527 	    break;
528 
529 	case SCAL:
530 	    i = pop(Integer);
531 	    printEnum(i, s);
532 	    break;
533 
534 	/*
535 	 * Unresolved structure pointers?
536 	 */
537 	case BADUSE:
538 	    a = pop(Address);
539 	    printf("@%x", a);
540 	    break;
541 
542 	default:
543 	    if (ord(s->class) > ord(TYPEREF)) {
544 		panic("printval: bad class %d", ord(s->class));
545 	    }
546 	    sp -= size(s);
547 	    printf("[%s]", c_classname(s));
548 	    break;
549     }
550 }
551 
552 /*
553  * Print out a C structure.
554  */
555 
556 private c_printstruct (s)
557 Symbol s;
558 {
559     Symbol f;
560     Stack *savesp;
561     integer n, off, len;
562 
563     sp -= size(s);
564     savesp = sp;
565     printf("(");
566     f = s->chain;
567     for (;;) {
568 	off = f->symvalue.field.offset;
569 	len = f->symvalue.field.length;
570 	n = (off + len + BITSPERBYTE - 1) div BITSPERBYTE;
571 	sp += n;
572 	printf("%s = ", symname(f));
573 	c_printval(f);
574 	sp = savesp;
575 	f = f->chain;
576     if (f == nil) break;
577 	printf(", ");
578     }
579     printf(")");
580 }
581 
582 /*
583  * Return the C name for the particular class of a symbol.
584  */
585 
586 public String c_classname(s)
587 Symbol s;
588 {
589     String str;
590 
591     switch (s->class) {
592 	case RECORD:
593 	    str = "struct";
594 	    break;
595 
596 	case VARNT:
597 	    str = "union";
598 	    break;
599 
600 	case SCAL:
601 	    str = "enum";
602 	    break;
603 
604 	default:
605 	    str = classname(s);
606     }
607     return str;
608 }
609 
610 public Node c_buildaref(a, slist)
611 Node a, slist;
612 {
613     register Symbol t;
614     register Node p;
615     Symbol etype, atype, eltype;
616     Node r, esub;
617 
618     t = rtype(a->nodetype);
619     eltype = t->type;
620     if (t->class == PTR) {
621 	p = slist->value.arg[0];
622 	if (not compatible(p->nodetype, t_int)) {
623 	    beginerrmsg();
624 	    fprintf(stderr, "subscript must be integer-compatible");
625 	    enderrmsg();
626 	}
627 	r = build(O_MUL, p, build(O_LCON, (long) size(eltype)));
628 	r = build(O_ADD, build(O_RVAL, a), r);
629 	r->nodetype = eltype;
630     } else if (t->class != ARRAY) {
631 	beginerrmsg();
632 	fprintf(stderr, "\"");
633 	prtree(stderr, a);
634 	fprintf(stderr, "\" is not an array");
635 	enderrmsg();
636     } else {
637 	r = a;
638 	p = slist;
639 	t = t->chain;
640 	for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) {
641 	    esub = p->value.arg[0];
642 	    etype = rtype(esub->nodetype);
643 	    atype = rtype(t);
644 	    if (not compatible(atype, etype)) {
645 		beginerrmsg();
646 		fprintf(stderr, "subscript \"");
647 		prtree(stderr, esub);
648 		fprintf(stderr, "\" is the wrong type");
649 		enderrmsg();
650 	    }
651 	    r = build(O_INDEX, r, esub);
652 	    r->nodetype = eltype;
653 	}
654 	if (p != nil or t != nil) {
655 	    beginerrmsg();
656 	    if (p != nil) {
657 		fprintf(stderr, "too many subscripts for \"");
658 	    } else {
659 		fprintf(stderr, "not enough subscripts for \"");
660 	    }
661 	    prtree(stderr, a);
662 	    fprintf(stderr, "\"");
663 	    enderrmsg();
664 	}
665     }
666     return r;
667 }
668 
669 /*
670  * Evaluate a subscript index.
671  */
672 
673 public c_evalaref(s, base, i)
674 Symbol s;
675 Address base;
676 long i;
677 {
678     Symbol t;
679     long lb, ub;
680 
681     t = rtype(s);
682     s = t->chain;
683     lb = s->symvalue.rangev.lower;
684     ub = s->symvalue.rangev.upper;
685     if (i < lb or i > ub) {
686 	warning("subscript out of range");
687     }
688     push(long, base + (i - lb) * size(t->type));
689 }
690 
691 /*
692  * Initialize typetable information.
693  */
694 
695 public c_modinit (typetable)
696 Symbol typetable[];
697 {
698     /* nothing right now */
699 }
700 
701 public boolean c_hasmodules ()
702 {
703     return false;
704 }
705 
706 public boolean c_passaddr (param, exprtype)
707 Symbol param, exprtype;
708 {
709     boolean b;
710     Symbol t;
711 
712     t = rtype(exprtype);
713     b = (boolean) (t->class == ARRAY);
714     return b;
715 }
716