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