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