BSD 4_3_Tahoe release
[unix-history] / usr / src / ucb / dbx / c.c
CommitLineData
2a24676e
DF
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 */
438ea14e 6
2a24676e 7#ifndef lint
ca67e7b4 8static char sccsid[] = "@(#)c.c 5.8 (Berkeley) 5/11/88";
2a24676e 9#endif not lint
0022c355 10
02fcaf87 11static char rcsid[] = "$Header: c.c,v 1.5 88/04/02 01:25:44 donn Exp $";
438ea14e
ML
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
567549ac 30#ifndef public
adbf81b2 31# include "tree.h"
567549ac
AF
32#endif
33
438ea14e
ML
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
2fd0f574 40private Language langC;
adbf81b2 41private Language langCplpl;
2fd0f574 42
438ea14e
ML
43/*
44 * Initialize C language information.
45 */
46
47public c_init()
48{
2fd0f574
SL
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);
adbf81b2
DS
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);
438ea14e
ML
68}
69
70/*
71 * Test if two types are compatible.
438ea14e
ML
72 */
73
74public Boolean c_typematch(type1, type2)
75Symbol 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);
2fd0f574 87 if (t1 == t_char->type or t1 == t_int->type or t1 == t_real->type) {
438ea14e
ML
88 tmp = t1;
89 t1 = t2;
90 t2 = tmp;
91 }
92 b = (Boolean) (
93 (
02fcaf87 94 isrange(t1, "int") and !isdouble(t1) /* sigh */ and
2fd0f574 95 (t2 == t_int->type or t2 == t_char->type)
438ea14e
ML
96 ) or (
97 isrange(t1, "char") and
2fd0f574 98 (t2 == t_char->type or t2 == t_int->type)
7297918f 99 ) or (
2fd0f574 100 t1->class == RANGE and isdouble(t1) and t2 == t_real->type
0022c355
ML
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
438ea14e 105 ) or (
02fcaf87 106 t1->class != RANGE and t1->type == t2->type and (
438ea14e
ML
107 (t1->class == t2->class) or
108 (t1->class == SCAL and t2->class == CONST) or
109 (t1->class == CONST and t2->class == SCAL)
110 )
2fd0f574
SL
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
438ea14e
ML
115 )
116 );
117 }
118 return b;
119}
120
438ea14e
ML
121/*
122 * Print out the declaration of a C variable.
123 */
124
125public c_printdecl(s)
126Symbol s;
127{
128 printdecl(s, 0);
129}
130
131private printdecl(s, indent)
132register Symbol s;
133Integer 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) {
0022c355
ML
149 printf("enumeration constant with value ");
150 eval(s->symvalue.constval);
151 c_printval(s);
438ea14e
ML
152 } else {
153 printf("const %s = ", symname(s));
154 printval(s);
155 }
156 break;
157
158 case TYPE:
159 case VAR:
adbf81b2 160 if (s->class != TYPE and s->storage == INREG) {
0022c355 161 printf("register ");
438ea14e
ML
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:
0022c355 210 case FFUNC:
438ea14e
ML
211 semicolon = false;
212 printtype(s, s, indent);
213 break;
214
0022c355
ML
215 case SCAL:
216 printf("(enumeration constant, value %d)", s->symvalue.iconval);
217 break;
218
438ea14e
ML
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:
0022c355
ML
248 printf("[%s]", classname(s));
249 break;
438ea14e
ML
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
267private printtype(s, t, indent)
268Symbol s;
269Symbol t;
270Integer 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 }
56fc1e71 313 printf("{\n");
438ea14e
ML
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:
2fd0f574 356 case FFUNC:
438ea14e
ML
357 printtype(t, t->type, indent);
358 printf("()");
359 break;
360
361 case TYPE:
362 if (t->name != nil) {
2fd0f574 363 printname(stdout, t);
438ea14e
ML
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
411public c_listparams(s)
412Symbol 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
442public c_printval(s)
443Symbol s;
444{
445 register Symbol t;
446 register Address a;
2fd0f574 447 integer i, len;
594c02f6 448 register String str;
438ea14e
ML
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)) {
adbf81b2 462 i = extractField(s);
438ea14e
ML
463 t = rtype(s->type);
464 if (t->class == SCAL) {
0022c355 465 printEnum(i, t);
438ea14e 466 } else {
0022c355 467 printRangeVal(i, t);
438ea14e
ML
468 }
469 } else {
470 c_printval(s->type);
471 }
472 break;
473
474 case ARRAY:
475 t = rtype(s->type);
2fd0f574
SL
476 if ((t->class == RANGE and istypename(t->type, "char")) or
477 t == t_char->type
478 ) {
438ea14e 479 len = size(s);
594c02f6
SL
480 str = (String) (sp -= len);
481 if (s->language != primlang) {
482 putchar('"');
483 }
3b80d068 484 while (--len > 0 and *str != '\0') {
594c02f6 485 printchar(*str++);
3b80d068
SL
486 }
487 if (*str != '\0') { /* XXX - pitch trailing null */
488 printchar(*str);
594c02f6
SL
489 }
490 if (s->language != primlang) {
491 putchar('"');
0022c355 492 }
438ea14e
ML
493 } else {
494 printarray(s);
495 }
496 break;
497
498 case RECORD:
438ea14e
ML
499 c_printstruct(s);
500 break;
501
502 case RANGE:
0022c355
ML
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)) {
438ea14e
ML
508 switch (s->symvalue.rangev.lower) {
509 case sizeof(float):
adbf81b2 510 prtreal((double) (pop(float)));
438ea14e
ML
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 {
0022c355 522 printRangeVal(popsmall(s), s);
438ea14e
ML
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")) {
0022c355 532 printString(a, (boolean) (s->language != primlang));
438ea14e
ML
533 } else {
534 printf("0x%x", a);
535 }
536 break;
537
538 case SCAL:
539 i = pop(Integer);
0022c355
ML
540 printEnum(i, s);
541 break;
542
543 /*
544 * Unresolved structure pointers?
545 */
546 case BADUSE:
547 a = pop(Address);
548 printf("@%x", a);
438ea14e
ML
549 break;
550
551 default:
552 if (ord(s->class) > ord(TYPEREF)) {
553 panic("printval: bad class %d", ord(s->class));
554 }
05044e0a 555 sp -= size(s);
2fd0f574 556 printf("[%s]", c_classname(s));
05044e0a 557 break;
438ea14e
ML
558 }
559}
560
561/*
562 * Print out a C structure.
563 */
564
0022c355 565private c_printstruct (s)
438ea14e
ML
566Symbol s;
567{
0022c355
ML
568 Symbol f;
569 Stack *savesp;
570 integer n, off, len;
438ea14e
ML
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;
2fd0f574 579 n = (off + len + BITSPERBYTE - 1) div BITSPERBYTE;
438ea14e
ML
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
438ea14e
ML
591/*
592 * Return the C name for the particular class of a symbol.
593 */
594
595public String c_classname(s)
596Symbol 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}
0022c355 618
bc5322a9
AF
619public Node c_buildaref(a, slist)
620Node a, slist;
621{
622 register Symbol t;
623 register Node p;
624 Symbol etype, atype, eltype;
0022c355 625 Node r, esub;
bc5322a9 626
bc5322a9
AF
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();
0022c355 633 fprintf(stderr, "subscript must be integer-compatible");
bc5322a9
AF
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();
0022c355 641 fprintf(stderr, "\"");
bc5322a9 642 prtree(stderr, a);
0022c355 643 fprintf(stderr, "\" is not an array");
bc5322a9
AF
644 enderrmsg();
645 } else {
0022c355 646 r = a;
bc5322a9
AF
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();
0022c355 655 fprintf(stderr, "subscript \"");
bc5322a9 656 prtree(stderr, esub);
0022c355 657 fprintf(stderr, "\" is the wrong type");
bc5322a9
AF
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) {
0022c355 666 fprintf(stderr, "too many subscripts for \"");
bc5322a9 667 } else {
0022c355 668 fprintf(stderr, "not enough subscripts for \"");
bc5322a9
AF
669 }
670 prtree(stderr, a);
0022c355 671 fprintf(stderr, "\"");
bc5322a9
AF
672 enderrmsg();
673 }
674 }
675 return r;
676}
677
678/*
679 * Evaluate a subscript index.
680 */
681
0022c355 682public c_evalaref(s, base, i)
bc5322a9 683Symbol s;
0022c355 684Address base;
bc5322a9
AF
685long i;
686{
0022c355 687 Symbol t;
bc5322a9
AF
688 long lb, ub;
689
0022c355
ML
690 t = rtype(s);
691 s = t->chain;
bc5322a9
AF
692 lb = s->symvalue.rangev.lower;
693 ub = s->symvalue.rangev.upper;
694 if (i < lb or i > ub) {
594c02f6 695 warning("subscript out of range");
bc5322a9 696 }
0022c355 697 push(long, base + (i - lb) * size(t->type));
bc5322a9 698}
2fd0f574
SL
699
700/*
701 * Initialize typetable information.
702 */
703
704public c_modinit (typetable)
705Symbol typetable[];
706{
707 /* nothing right now */
708}
709
710public boolean c_hasmodules ()
711{
712 return false;
713}
714
715public boolean c_passaddr (param, exprtype)
716Symbol param, exprtype;
717{
718 boolean b;
719 Symbol t;
720
721 t = rtype(exprtype);
722 b = (boolean) (t->class == ARRAY);
723 return b;
724}