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