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