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