123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750 |
- /* Copyright (c) 1982 Regents of the University of California */
- static char sccsid[] = "@(#)c.c 1.7 8/16/83";
- /*
- * C-dependent symbol routines.
- */
- #include "defs.h"
- #include "symbols.h"
- #include "printsym.h"
- #include "languages.h"
- #include "c.h"
- #include "tree.h"
- #include "eval.h"
- #include "operators.h"
- #include "mappings.h"
- #include "process.h"
- #include "runtime.h"
- #include "machine.h"
- #ifndef public
- # include "tree.h"
- #endif
- #define isdouble(range) ( \
- range->symvalue.rangev.upper == 0 and range->symvalue.rangev.lower > 0 \
- )
- #define isrange(t, name) (t->class == RANGE and istypename(t->type, name))
- /*
- * Initialize C language information.
- */
- public c_init()
- {
- Language lang;
- lang = language_define("c", ".c");
- language_setop(lang, L_PRINTDECL, c_printdecl);
- language_setop(lang, L_PRINTVAL, c_printval);
- language_setop(lang, L_TYPEMATCH, c_typematch);
- language_setop(lang, L_BUILDAREF, c_buildaref);
- language_setop(lang, L_EVALAREF, c_evalaref);
- }
- /*
- * Test if two types are compatible.
- */
- public Boolean c_typematch(type1, type2)
- Symbol type1, type2;
- {
- Boolean b;
- register Symbol t1, t2, tmp;
- t1 = type1;
- t2 = type2;
- if (t1 == t2) {
- b = true;
- } else {
- t1 = rtype(t1);
- t2 = rtype(t2);
- if (t1->type == t_char or t1->type == t_int or t1->type == t_real) {
- tmp = t1;
- t1 = t2;
- t2 = tmp;
- }
- b = (Boolean) (
- (
- isrange(t1, "int") and
- (t2->type == t_int or t2->type == t_char)
- ) or (
- isrange(t1, "char") and
- (t2->type == t_char or t2->type == t_int)
- ) or (
- t1->class == RANGE and isdouble(t1) and t2->type == t_real
- ) or (
- t1->type == t2->type and (
- (t1->class == t2->class) or
- (t1->class == SCAL and t2->class == CONST) or
- (t1->class == CONST and t2->class == SCAL)
- )
- )
- );
- }
- return b;
- }
- /*
- * Decide if a field is a bit field.
- */
- private Boolean isbitfield(s)
- register Symbol s;
- {
- Boolean b;
- register Integer off, len;
- register Symbol t;
- off = s->symvalue.field.offset;
- len = s->symvalue.field.length;
- if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) {
- b = true;
- } else {
- t = rtype(s->type);
- b = (Boolean)
- (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE) or
- len != (size(t)*BITSPERBYTE)
- );
- }
- return b;
- }
- /*
- * Print out the declaration of a C variable.
- */
- public c_printdecl(s)
- Symbol s;
- {
- printdecl(s, 0);
- }
- private printdecl(s, indent)
- register Symbol s;
- Integer indent;
- {
- register Symbol t;
- Boolean semicolon, newline;
- semicolon = true;
- newline = true;
- if (indent > 0) {
- printf("%*c", indent, ' ');
- }
- if (s->class == TYPE) {
- printf("typedef ");
- }
- switch (s->class) {
- case CONST:
- if (s->type->class == SCAL) {
- printf("(enumeration constant, ord %ld)",
- s->symvalue.iconval);
- } else {
- printf("const %s = ", symname(s));
- printval(s);
- }
- break;
- case TYPE:
- case VAR:
- if (s->class != TYPE) {
- if (s->level == 2) {
- printf("static ");
- } else if (s->level < 0) {
- printf("register ");
- }
- }
- if (s->type->class == ARRAY) {
- printtype(s->type, s->type->type, indent);
- t = rtype(s->type->chain);
- assert(t->class == RANGE);
- printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1);
- } else {
- printtype(s, s->type, indent);
- if (s->type->class != PTR) {
- printf(" ");
- }
- printf("%s", symname(s));
- }
- break;
- case FIELD:
- if (s->type->class == ARRAY) {
- printtype(s->type, s->type->type, indent);
- t = rtype(s->type->chain);
- assert(t->class == RANGE);
- printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1);
- } else {
- printtype(s, s->type, indent);
- if (s->type->class != PTR) {
- printf(" ");
- }
- printf("%s", symname(s));
- }
- if (isbitfield(s)) {
- printf(" : %d", s->symvalue.field.length);
- }
- break;
- case TAG:
- if (s->type == nil) {
- findtype(s);
- if (s->type == nil) {
- error("unexpected missing type information");
- }
- }
- printtype(s, s->type, indent);
- break;
- case RANGE:
- case ARRAY:
- case RECORD:
- case VARNT:
- case PTR:
- semicolon = false;
- printtype(s, s, indent);
- break;
- case PROC:
- semicolon = false;
- printf("%s", symname(s));
- c_listparams(s);
- newline = false;
- break;
- case FUNC:
- semicolon = false;
- if (not istypename(s->type, "void")) {
- printtype(s, s->type, indent);
- printf(" ");
- }
- printf("%s", symname(s));
- c_listparams(s);
- newline = false;
- break;
- case MODULE:
- semicolon = false;
- printf("source file \"%s.c\"", symname(s));
- break;
- case PROG:
- semicolon = false;
- printf("executable file \"%s\"", symname(s));
- break;
- default:
- error("class %s in c_printdecl", classname(s));
- }
- if (semicolon) {
- putchar(';');
- }
- if (newline) {
- putchar('\n');
- }
- }
- /*
- * Recursive whiz-bang procedure to print the type portion
- * of a declaration.
- *
- * The symbol associated with the type is passed to allow
- * searching for type names without getting "type blah = blah".
- */
- private printtype(s, t, indent)
- Symbol s;
- Symbol t;
- Integer indent;
- {
- register Symbol i;
- long r0, r1;
- register String p;
- checkref(s);
- checkref(t);
- switch (t->class) {
- case VAR:
- case CONST:
- case PROC:
- panic("printtype: class %s", classname(t));
- break;
- case ARRAY:
- printf("array[");
- i = t->chain;
- if (i != nil) {
- for (;;) {
- printtype(i, i, indent);
- i = i->chain;
- if (i == nil) {
- break;
- }
- printf(", ");
- }
- }
- printf("] of ");
- printtype(t, t->type, indent);
- break;
- case RECORD:
- case VARNT:
- printf("%s ", c_classname(t));
- if (s->name != nil and s->class == TAG) {
- p = symname(s);
- if (p[0] == '$' and p[1] == '$') {
- printf("%s ", &p[2]);
- } else {
- printf("%s ", p);
- }
- }
- printf("{\n", t->class == RECORD ? "struct" : "union");
- for (i = t->chain; i != nil; i = i->chain) {
- assert(i->class == FIELD);
- printdecl(i, indent+4);
- }
- if (indent > 0) {
- printf("%*c", indent, ' ');
- }
- printf("}");
- break;
- case RANGE:
- r0 = t->symvalue.rangev.lower;
- r1 = t->symvalue.rangev.upper;
- if (istypename(t->type, "char")) {
- if (r0 < 0x20 or r0 > 0x7e) {
- printf("%ld..", r0);
- } else {
- printf("'%c'..", (char) r0);
- }
- if (r1 < 0x20 or r1 > 0x7e) {
- printf("\\%lo", r1);
- } else {
- printf("'%c'", (char) r1);
- }
- } else if (r0 > 0 and r1 == 0) {
- printf("%ld byte real", r0);
- } else if (r0 >= 0) {
- printf("%lu..%lu", r0, r1);
- } else {
- printf("%ld..%ld", r0, r1);
- }
- break;
- case PTR:
- printtype(t, t->type, indent);
- if (t->type->class != PTR) {
- printf(" ");
- }
- printf("*");
- break;
- case FUNC:
- printtype(t, t->type, indent);
- printf("()");
- break;
- case TYPE:
- if (t->name != nil) {
- printf("%s", symname(t));
- } else {
- printtype(t, t->type, indent);
- }
- break;
- case TYPEREF:
- printf("@%s", symname(t));
- break;
- case SCAL:
- printf("enum ");
- if (s->name != nil and s->class == TAG) {
- printf("%s ", symname(s));
- }
- printf("{ ");
- i = t->chain;
- if (i != nil) {
- for (;;) {
- printf("%s", symname(i));
- i = i->chain;
- if (i == nil) break;
- printf(", ");
- }
- }
- printf(" }");
- break;
- case TAG:
- if (t->type == nil) {
- printf("unresolved tag %s", symname(t));
- } else {
- i = rtype(t->type);
- printf("%s %s", c_classname(i), symname(t));
- }
- break;
- default:
- printf("(class %d)", t->class);
- break;
- }
- }
- /*
- * List the parameters of a procedure or function.
- * No attempt is made to combine like types.
- */
- public c_listparams(s)
- Symbol s;
- {
- register Symbol t;
- putchar('(');
- for (t = s->chain; t != nil; t = t->chain) {
- printf("%s", symname(t));
- if (t->chain != nil) {
- printf(", ");
- }
- }
- putchar(')');
- if (s->chain != nil) {
- printf("\n");
- for (t = s->chain; t != nil; t = t->chain) {
- if (t->class != VAR) {
- panic("unexpected class %d for parameter", t->class);
- }
- printdecl(t, 0);
- }
- } else {
- putchar('\n');
- }
- }
- /*
- * Print out the value on the top of the expression stack
- * in the format for the type of the given symbol.
- */
- public c_printval(s)
- Symbol s;
- {
- register Symbol t;
- register Address a;
- register int i, len;
- switch (s->class) {
- case CONST:
- case TYPE:
- case VAR:
- case REF:
- case FVAR:
- case TAG:
- c_printval(s->type);
- break;
- case FIELD:
- if (isbitfield(s)) {
- len = s->symvalue.field.length;
- if (len <= BITSPERBYTE) {
- i = pop(char);
- } else if (len <= sizeof(short)*BITSPERBYTE) {
- i = pop(short);
- } else {
- i = pop(long);
- }
- i >>= (s->symvalue.field.offset mod BITSPERBYTE);
- i &= ((1 << len) - 1);
- t = rtype(s->type);
- if (t->class == SCAL) {
- printenum(i, t);
- } else {
- printrange(i, t);
- }
- } else {
- c_printval(s->type);
- }
- break;
- case ARRAY:
- t = rtype(s->type);
- if (t->class == RANGE and istypename(t->type, "char")) {
- len = size(s);
- sp -= len;
- printf("\"%.*s\"", len, sp);
- } else {
- printarray(s);
- }
- break;
- case RECORD:
- c_printstruct(s);
- break;
- case RANGE:
- if (istypename(s->type, "boolean")) {
- printrange(popsmall(s), s);
- } else if (istypename(s->type, "char")) {
- printrange(pop(char), s);
- } else if (isdouble(s)) {
- switch (s->symvalue.rangev.lower) {
- case sizeof(float):
- prtreal(pop(float));
- break;
- case sizeof(double):
- prtreal(pop(double));
- break;
- default:
- panic("bad real size %d", t->symvalue.rangev.lower);
- break;
- }
- } else {
- printrange(popsmall(s), s);
- }
- break;
- case PTR:
- t = rtype(s->type);
- a = pop(Address);
- if (a == 0) {
- printf("(nil)");
- } else if (t->class == RANGE and istypename(t->type, "char")) {
- printstring(a);
- } else {
- printf("0x%x", a);
- }
- break;
- case SCAL:
- i = pop(Integer);
- printenum(i, s);
- break;
- default:
- if (ord(s->class) > ord(TYPEREF)) {
- panic("printval: bad class %d", ord(s->class));
- }
- sp -= size(s);
- printf("<%s>", c_classname(s));
- break;
- }
- }
- /*
- * Print out a C structure.
- */
- private c_printstruct(s)
- Symbol s;
- {
- register Symbol f;
- register Stack *savesp;
- register Integer n, off, len;
- sp -= size(s);
- savesp = sp;
- printf("(");
- f = s->chain;
- for (;;) {
- off = f->symvalue.field.offset;
- len = f->symvalue.field.length;
- n = (off + len + 7) div BITSPERBYTE;
- sp += n;
- printf("%s = ", symname(f));
- c_printval(f);
- sp = savesp;
- f = f->chain;
- if (f == nil) break;
- printf(", ");
- }
- printf(")");
- }
- /*
- * Print out a range type (integer, char, or boolean).
- */
- private printrange(i, t)
- Integer i;
- register Symbol t;
- {
- if (istypename(t->type, "boolean")) {
- printf(((Boolean) i) == true ? "true" : "false");
- } else if (istypename(t->type, "char")) {
- putchar('\'');
- printchar(i);
- putchar('\'');
- } else if (t->symvalue.rangev.lower >= 0) {
- printf("%lu", i);
- } else {
- printf("%ld", i);
- }
- }
- /*
- * Print out a null-terminated string (pointer to char)
- * starting at the given address.
- */
- private printstring(addr)
- Address addr;
- {
- register Address a;
- register Integer i, len;
- register Boolean endofstring;
- union {
- char ch[sizeof(Word)];
- int word;
- } u;
- putchar('"');
- a = addr;
- endofstring = false;
- while (not endofstring) {
- dread(&u, a, sizeof(u));
- i = 0;
- do {
- if (u.ch[i] == '\0') {
- endofstring = true;
- } else {
- printchar(u.ch[i]);
- }
- ++i;
- } while (i < sizeof(Word) and not endofstring);
- a += sizeof(Word);
- }
- putchar('"');
- }
- /*
- * Print out an enumerated value by finding the corresponding
- * name in the enumeration list.
- */
- private printenum(i, t)
- Integer i;
- Symbol t;
- {
- register Symbol e;
- e = t->chain;
- while (e != nil and e->symvalue.iconval != i) {
- e = e->chain;
- }
- if (e != nil) {
- printf("%s", symname(e));
- } else {
- printf("%d", i);
- }
- }
- /*
- * Return the C name for the particular class of a symbol.
- */
- public String c_classname(s)
- Symbol s;
- {
- String str;
- switch (s->class) {
- case RECORD:
- str = "struct";
- break;
- case VARNT:
- str = "union";
- break;
- case SCAL:
- str = "enum";
- break;
- default:
- str = classname(s);
- }
- return str;
- }
- public Node c_buildaref(a, slist)
- Node a, slist;
- {
- register Symbol t;
- register Node p;
- Symbol etype, atype, eltype;
- Node esub, r;
- r = a;
- t = rtype(a->nodetype);
- eltype = t->type;
- if (t->class == PTR) {
- p = slist->value.arg[0];
- if (not compatible(p->nodetype, t_int)) {
- beginerrmsg();
- fprintf(stderr, "bad type for subscript of ");
- prtree(stderr, a);
- enderrmsg();
- }
- r = build(O_MUL, p, build(O_LCON, (long) size(eltype)));
- r = build(O_ADD, build(O_RVAL, a), r);
- r->nodetype = eltype;
- } else if (t->class != ARRAY) {
- beginerrmsg();
- prtree(stderr, a);
- fprintf(stderr, " is not an array");
- enderrmsg();
- } else {
- p = slist;
- t = t->chain;
- for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) {
- esub = p->value.arg[0];
- etype = rtype(esub->nodetype);
- atype = rtype(t);
- if (not compatible(atype, etype)) {
- beginerrmsg();
- fprintf(stderr, "subscript ");
- prtree(stderr, esub);
- fprintf(stderr, " is the wrong type");
- enderrmsg();
- }
- r = build(O_INDEX, r, esub);
- r->nodetype = eltype;
- }
- if (p != nil or t != nil) {
- beginerrmsg();
- if (p != nil) {
- fprintf(stderr, "too many subscripts for ");
- } else {
- fprintf(stderr, "not enough subscripts for ");
- }
- prtree(stderr, a);
- enderrmsg();
- }
- }
- return r;
- }
- /*
- * Evaluate a subscript index.
- */
- public int c_evalaref(s, i)
- Symbol s;
- long i;
- {
- long lb, ub;
- s = rtype(s)->chain;
- lb = s->symvalue.rangev.lower;
- ub = s->symvalue.rangev.upper;
- if (i < lb or i > ub) {
- error("subscript out of range");
- }
- return (i - lb);
- }
|