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