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