19659Slinton /* Copyright (c) 1982 Regents of the University of California */ 29659Slinton 3*12533Scsvaf static char sccsid[] = "@(#)c.c 1.3 05/18/83"; 49659Slinton 59659Slinton /* 69659Slinton * C-dependent symbol routines. 79659Slinton */ 89659Slinton 99659Slinton #include "defs.h" 109659Slinton #include "symbols.h" 119659Slinton #include "printsym.h" 129659Slinton #include "languages.h" 139659Slinton #include "c.h" 149659Slinton #include "tree.h" 159659Slinton #include "eval.h" 169659Slinton #include "operators.h" 179659Slinton #include "mappings.h" 189659Slinton #include "process.h" 199659Slinton #include "runtime.h" 209659Slinton #include "machine.h" 219659Slinton 229659Slinton #define isdouble(range) ( \ 239659Slinton range->symvalue.rangev.upper == 0 and range->symvalue.rangev.lower > 0 \ 249659Slinton ) 259659Slinton 269659Slinton #define isrange(t, name) (t->class == RANGE and istypename(t->type, name)) 279659Slinton 289659Slinton /* 299659Slinton * Initialize C language information. 309659Slinton */ 319659Slinton 329659Slinton public c_init() 339659Slinton { 349659Slinton Language lang; 359659Slinton 369659Slinton lang = language_define("c", ".c"); 379659Slinton language_setop(lang, L_PRINTDECL, c_printdecl); 389659Slinton language_setop(lang, L_PRINTVAL, c_printval); 399659Slinton language_setop(lang, L_TYPEMATCH, c_typematch); 40*12533Scsvaf language_setop(lang, L_BUILDAREF, c_buildaref); 41*12533Scsvaf language_setop(lang, L_EVALAREF, c_evalaref); 429659Slinton } 439659Slinton 449659Slinton /* 459659Slinton * Test if two types are compatible. 469659Slinton * 479659Slinton * Integers and reals are not compatible since they cannot always be mixed. 489659Slinton */ 499659Slinton 509659Slinton public Boolean c_typematch(type1, type2) 519659Slinton Symbol type1, type2; 529659Slinton { 539659Slinton Boolean b; 549659Slinton register Symbol t1, t2, tmp; 559659Slinton 569659Slinton t1 = type1; 579659Slinton t2 = type2; 589659Slinton if (t1 == t2) { 599659Slinton b = true; 609659Slinton } else { 619659Slinton t1 = rtype(t1); 629659Slinton t2 = rtype(t2); 639659Slinton if (t1->type == t_int or t1->type == t_char) { 649659Slinton tmp = t1; 659659Slinton t1 = t2; 669659Slinton t2 = tmp; 679659Slinton } 689659Slinton b = (Boolean) ( 699659Slinton ( 709659Slinton isrange(t1, "int") and 719659Slinton (t2->type == t_int or t2->type == t_char) 729659Slinton ) or ( 739659Slinton isrange(t1, "char") and 749659Slinton (t2->type == t_char or t2->type == t_int) 759659Slinton ) or ( 769659Slinton t1->type == t2->type and ( 779659Slinton (t1->class == t2->class) or 789659Slinton (t1->class == SCAL and t2->class == CONST) or 799659Slinton (t1->class == CONST and t2->class == SCAL) 809659Slinton ) 819659Slinton ) 829659Slinton ); 839659Slinton } 849659Slinton return b; 859659Slinton } 869659Slinton 879659Slinton /* 889659Slinton * Decide if a field is a bit field. 899659Slinton */ 909659Slinton 919659Slinton private Boolean isbitfield(s) 929659Slinton register Symbol s; 939659Slinton { 949659Slinton Boolean b; 959659Slinton register Integer off, len; 969659Slinton register Symbol t; 979659Slinton 989659Slinton off = s->symvalue.field.offset; 999659Slinton len = s->symvalue.field.length; 1009659Slinton if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) { 1019659Slinton b = true; 1029659Slinton } else { 1039659Slinton t = rtype(s->type); 1049659Slinton b = (Boolean) 1059659Slinton (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE) or 1069659Slinton len != (size(t)*BITSPERBYTE) 1079659Slinton ); 1089659Slinton } 1099659Slinton return b; 1109659Slinton } 1119659Slinton 1129659Slinton /* 1139659Slinton * Print out the declaration of a C variable. 1149659Slinton */ 1159659Slinton 1169659Slinton public c_printdecl(s) 1179659Slinton Symbol s; 1189659Slinton { 1199659Slinton printdecl(s, 0); 1209659Slinton } 1219659Slinton 1229659Slinton private printdecl(s, indent) 1239659Slinton register Symbol s; 1249659Slinton Integer indent; 1259659Slinton { 1269659Slinton register Symbol t; 1279659Slinton Boolean semicolon, newline; 1289659Slinton 1299659Slinton semicolon = true; 1309659Slinton newline = true; 1319659Slinton if (indent > 0) { 1329659Slinton printf("%*c", indent, ' '); 1339659Slinton } 1349659Slinton if (s->class == TYPE) { 1359659Slinton printf("typedef "); 1369659Slinton } 1379659Slinton switch (s->class) { 1389659Slinton case CONST: 1399659Slinton if (s->type->class == SCAL) { 1409659Slinton printf("(enumeration constant, ord %ld)", 1419659Slinton s->symvalue.iconval); 1429659Slinton } else { 1439659Slinton printf("const %s = ", symname(s)); 1449659Slinton printval(s); 1459659Slinton } 1469659Slinton break; 1479659Slinton 1489659Slinton case TYPE: 1499659Slinton case VAR: 1509659Slinton if (s->class != TYPE) { 1519659Slinton if (s->level == 2) { 1529659Slinton printf("static "); 1539659Slinton } else if (s->level < 0) { 1549659Slinton printf("register "); 1559659Slinton } 1569659Slinton } 1579659Slinton if (s->type->class == ARRAY) { 1589659Slinton printtype(s->type, s->type->type, indent); 1599659Slinton t = rtype(s->type->chain); 1609659Slinton assert(t->class == RANGE); 1619659Slinton printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1); 1629659Slinton } else { 1639659Slinton printtype(s, s->type, indent); 1649659Slinton if (s->type->class != PTR) { 1659659Slinton printf(" "); 1669659Slinton } 1679659Slinton printf("%s", symname(s)); 1689659Slinton } 1699659Slinton break; 1709659Slinton 1719659Slinton case FIELD: 1729659Slinton if (s->type->class == ARRAY) { 1739659Slinton printtype(s->type, s->type->type, indent); 1749659Slinton t = rtype(s->type->chain); 1759659Slinton assert(t->class == RANGE); 1769659Slinton printf(" %s[%d]", symname(s), t->symvalue.rangev.upper + 1); 1779659Slinton } else { 1789659Slinton printtype(s, s->type, indent); 1799659Slinton if (s->type->class != PTR) { 1809659Slinton printf(" "); 1819659Slinton } 1829659Slinton printf("%s", symname(s)); 1839659Slinton } 1849659Slinton if (isbitfield(s)) { 1859659Slinton printf(" : %d", s->symvalue.field.length); 1869659Slinton } 1879659Slinton break; 1889659Slinton 1899659Slinton case TAG: 1909659Slinton if (s->type == nil) { 1919659Slinton findtype(s); 1929659Slinton if (s->type == nil) { 1939659Slinton error("unexpected missing type information"); 1949659Slinton } 1959659Slinton } 1969659Slinton printtype(s, s->type, indent); 1979659Slinton break; 1989659Slinton 1999659Slinton case RANGE: 2009659Slinton case ARRAY: 2019659Slinton case RECORD: 2029659Slinton case VARNT: 2039659Slinton case PTR: 2049659Slinton semicolon = false; 2059659Slinton printtype(s, s, indent); 2069659Slinton break; 2079659Slinton 2089659Slinton case PROC: 2099659Slinton semicolon = false; 2109659Slinton printf("%s", symname(s)); 2119659Slinton c_listparams(s); 2129659Slinton newline = false; 2139659Slinton break; 2149659Slinton 2159659Slinton case FUNC: 2169659Slinton semicolon = false; 2179659Slinton if (not istypename(s->type, "void")) { 2189659Slinton printtype(s, s->type, indent); 2199659Slinton printf(" "); 2209659Slinton } 2219659Slinton printf("%s", symname(s)); 2229659Slinton c_listparams(s); 2239659Slinton newline = false; 2249659Slinton break; 2259659Slinton 2269659Slinton case MODULE: 2279659Slinton semicolon = false; 2289659Slinton printf("source file \"%s.c\"", symname(s)); 2299659Slinton break; 2309659Slinton 2319659Slinton case PROG: 2329659Slinton semicolon = false; 2339659Slinton printf("executable file \"%s\"", symname(s)); 2349659Slinton break; 2359659Slinton 2369659Slinton default: 2379659Slinton error("class %s in c_printdecl", classname(s)); 2389659Slinton } 2399659Slinton if (semicolon) { 2409659Slinton putchar(';'); 2419659Slinton } 2429659Slinton if (newline) { 2439659Slinton putchar('\n'); 2449659Slinton } 2459659Slinton } 2469659Slinton 2479659Slinton /* 2489659Slinton * Recursive whiz-bang procedure to print the type portion 2499659Slinton * of a declaration. 2509659Slinton * 2519659Slinton * The symbol associated with the type is passed to allow 2529659Slinton * searching for type names without getting "type blah = blah". 2539659Slinton */ 2549659Slinton 2559659Slinton private printtype(s, t, indent) 2569659Slinton Symbol s; 2579659Slinton Symbol t; 2589659Slinton Integer indent; 2599659Slinton { 2609659Slinton register Symbol i; 2619659Slinton long r0, r1; 2629659Slinton register String p; 2639659Slinton 2649659Slinton checkref(s); 2659659Slinton checkref(t); 2669659Slinton switch (t->class) { 2679659Slinton case VAR: 2689659Slinton case CONST: 2699659Slinton case PROC: 2709659Slinton panic("printtype: class %s", classname(t)); 2719659Slinton break; 2729659Slinton 2739659Slinton case ARRAY: 2749659Slinton printf("array["); 2759659Slinton i = t->chain; 2769659Slinton if (i != nil) { 2779659Slinton for (;;) { 2789659Slinton printtype(i, i, indent); 2799659Slinton i = i->chain; 2809659Slinton if (i == nil) { 2819659Slinton break; 2829659Slinton } 2839659Slinton printf(", "); 2849659Slinton } 2859659Slinton } 2869659Slinton printf("] of "); 2879659Slinton printtype(t, t->type, indent); 2889659Slinton break; 2899659Slinton 2909659Slinton case RECORD: 2919659Slinton case VARNT: 2929659Slinton printf("%s ", c_classname(t)); 2939659Slinton if (s->name != nil and s->class == TAG) { 2949659Slinton p = symname(s); 2959659Slinton if (p[0] == '$' and p[1] == '$') { 2969659Slinton printf("%s ", &p[2]); 2979659Slinton } else { 2989659Slinton printf("%s ", p); 2999659Slinton } 3009659Slinton } 3019659Slinton printf("{\n", t->class == RECORD ? "struct" : "union"); 3029659Slinton for (i = t->chain; i != nil; i = i->chain) { 3039659Slinton assert(i->class == FIELD); 3049659Slinton printdecl(i, indent+4); 3059659Slinton } 3069659Slinton if (indent > 0) { 3079659Slinton printf("%*c", indent, ' '); 3089659Slinton } 3099659Slinton printf("}"); 3109659Slinton break; 3119659Slinton 3129659Slinton case RANGE: 3139659Slinton r0 = t->symvalue.rangev.lower; 3149659Slinton r1 = t->symvalue.rangev.upper; 3159659Slinton if (istypename(t->type, "char")) { 3169659Slinton if (r0 < 0x20 or r0 > 0x7e) { 3179659Slinton printf("%ld..", r0); 3189659Slinton } else { 3199659Slinton printf("'%c'..", (char) r0); 3209659Slinton } 3219659Slinton if (r1 < 0x20 or r1 > 0x7e) { 3229659Slinton printf("\\%lo", r1); 3239659Slinton } else { 3249659Slinton printf("'%c'", (char) r1); 3259659Slinton } 3269659Slinton } else if (r0 > 0 and r1 == 0) { 3279659Slinton printf("%ld byte real", r0); 3289659Slinton } else if (r0 >= 0) { 3299659Slinton printf("%lu..%lu", r0, r1); 3309659Slinton } else { 3319659Slinton printf("%ld..%ld", r0, r1); 3329659Slinton } 3339659Slinton break; 3349659Slinton 3359659Slinton case PTR: 3369659Slinton printtype(t, t->type, indent); 3379659Slinton if (t->type->class != PTR) { 3389659Slinton printf(" "); 3399659Slinton } 3409659Slinton printf("*"); 3419659Slinton break; 3429659Slinton 3439659Slinton case FUNC: 3449659Slinton printtype(t, t->type, indent); 3459659Slinton printf("()"); 3469659Slinton break; 3479659Slinton 3489659Slinton case TYPE: 3499659Slinton if (t->name != nil) { 3509659Slinton printname(stdout, t); 3519659Slinton } else { 3529659Slinton printtype(t, t->type, indent); 3539659Slinton } 3549659Slinton break; 3559659Slinton 3569659Slinton case TYPEREF: 3579659Slinton printf("@%s", symname(t)); 3589659Slinton break; 3599659Slinton 3609659Slinton case SCAL: 3619659Slinton printf("enum "); 3629659Slinton if (s->name != nil and s->class == TAG) { 3639659Slinton printf("%s ", symname(s)); 3649659Slinton } 3659659Slinton printf("{ "); 3669659Slinton i = t->chain; 3679659Slinton if (i != nil) { 3689659Slinton for (;;) { 3699659Slinton printf("%s", symname(i)); 3709659Slinton i = i->chain; 3719659Slinton if (i == nil) break; 3729659Slinton printf(", "); 3739659Slinton } 3749659Slinton } 3759659Slinton printf(" }"); 3769659Slinton break; 3779659Slinton 3789659Slinton case TAG: 3799659Slinton if (t->type == nil) { 3809659Slinton printf("unresolved tag %s", symname(t)); 3819659Slinton } else { 3829659Slinton i = rtype(t->type); 3839659Slinton printf("%s %s", c_classname(i), symname(t)); 3849659Slinton } 3859659Slinton break; 3869659Slinton 3879659Slinton default: 3889659Slinton printf("(class %d)", t->class); 3899659Slinton break; 3909659Slinton } 3919659Slinton } 3929659Slinton 3939659Slinton /* 3949659Slinton * List the parameters of a procedure or function. 3959659Slinton * No attempt is made to combine like types. 3969659Slinton */ 3979659Slinton 3989659Slinton public c_listparams(s) 3999659Slinton Symbol s; 4009659Slinton { 4019659Slinton register Symbol t; 4029659Slinton 4039659Slinton putchar('('); 4049659Slinton for (t = s->chain; t != nil; t = t->chain) { 4059659Slinton printf("%s", symname(t)); 4069659Slinton if (t->chain != nil) { 4079659Slinton printf(", "); 4089659Slinton } 4099659Slinton } 4109659Slinton putchar(')'); 4119659Slinton if (s->chain != nil) { 4129659Slinton printf("\n"); 4139659Slinton for (t = s->chain; t != nil; t = t->chain) { 4149659Slinton if (t->class != VAR) { 4159659Slinton panic("unexpected class %d for parameter", t->class); 4169659Slinton } 4179659Slinton printdecl(t, 0); 4189659Slinton } 4199659Slinton } else { 4209659Slinton putchar('\n'); 4219659Slinton } 4229659Slinton } 4239659Slinton 4249659Slinton /* 4259659Slinton * Print out the value on the top of the expression stack 4269659Slinton * in the format for the type of the given symbol. 4279659Slinton */ 4289659Slinton 4299659Slinton public c_printval(s) 4309659Slinton Symbol s; 4319659Slinton { 4329659Slinton register Symbol t; 4339659Slinton register Address a; 4349659Slinton register int i, len; 4359659Slinton 4369659Slinton switch (s->class) { 4379659Slinton case CONST: 4389659Slinton case TYPE: 4399659Slinton case VAR: 4409659Slinton case REF: 4419659Slinton case FVAR: 4429659Slinton case TAG: 4439659Slinton c_printval(s->type); 4449659Slinton break; 4459659Slinton 4469659Slinton case FIELD: 4479659Slinton if (isbitfield(s)) { 4489659Slinton len = s->symvalue.field.length; 4499659Slinton if (len <= BITSPERBYTE) { 4509659Slinton i = pop(char); 4519659Slinton } else if (len <= sizeof(short)*BITSPERBYTE) { 4529659Slinton i = pop(short); 4539659Slinton } else { 4549659Slinton i = pop(long); 4559659Slinton } 4569659Slinton i >>= (s->symvalue.field.offset mod BITSPERBYTE); 4579659Slinton i &= ((1 << len) - 1); 4589659Slinton t = rtype(s->type); 4599659Slinton if (t->class == SCAL) { 4609659Slinton printenum(i, t); 4619659Slinton } else { 4629659Slinton printrange(i, t); 4639659Slinton } 4649659Slinton } else { 4659659Slinton c_printval(s->type); 4669659Slinton } 4679659Slinton break; 4689659Slinton 4699659Slinton case ARRAY: 4709659Slinton t = rtype(s->type); 4719659Slinton if (t->class == RANGE and istypename(t->type, "char")) { 4729659Slinton len = size(s); 4739659Slinton sp -= len; 4749659Slinton printf("\"%.*s\"", len, sp); 4759659Slinton } else { 4769659Slinton printarray(s); 4779659Slinton } 4789659Slinton break; 4799659Slinton 4809659Slinton case RECORD: 4819659Slinton case VARNT: 4829659Slinton c_printstruct(s); 4839659Slinton break; 4849659Slinton 4859659Slinton case RANGE: 4869659Slinton if (istypename(s->type, "boolean")) { 4879659Slinton printrange(popsmall(s), s); 4889659Slinton } else if (istypename(s->type, "char")) { 4899659Slinton printrange(pop(char), s); 4909659Slinton } else if (isdouble(s)) { 4919659Slinton switch (s->symvalue.rangev.lower) { 4929659Slinton case sizeof(float): 4939659Slinton prtreal(pop(float)); 4949659Slinton break; 4959659Slinton 4969659Slinton case sizeof(double): 4979659Slinton prtreal(pop(double)); 4989659Slinton break; 4999659Slinton 5009659Slinton default: 5019659Slinton panic("bad real size %d", t->symvalue.rangev.lower); 5029659Slinton break; 5039659Slinton } 5049659Slinton } else { 5059659Slinton printrange(popsmall(s), s); 5069659Slinton } 5079659Slinton break; 5089659Slinton 5099659Slinton case PTR: 5109659Slinton t = rtype(s->type); 5119659Slinton a = pop(Address); 5129659Slinton if (a == 0) { 5139659Slinton printf("(nil)"); 5149659Slinton } else if (t->class == RANGE and istypename(t->type, "char")) { 5159659Slinton printstring(a); 5169659Slinton } else { 5179659Slinton printf("0x%x", a); 5189659Slinton } 5199659Slinton break; 5209659Slinton 5219659Slinton case SCAL: 5229659Slinton i = pop(Integer); 5239659Slinton printenum(i, s); 5249659Slinton break; 5259659Slinton 5269659Slinton default: 5279659Slinton if (ord(s->class) > ord(TYPEREF)) { 5289659Slinton panic("printval: bad class %d", ord(s->class)); 5299659Slinton } 5309659Slinton error("don't know how to print a %s", c_classname(s)); 5319659Slinton /* NOTREACHED */ 5329659Slinton } 5339659Slinton } 5349659Slinton 5359659Slinton /* 5369659Slinton * Print out a C structure. 5379659Slinton */ 5389659Slinton 5399659Slinton private c_printstruct(s) 5409659Slinton Symbol s; 5419659Slinton { 5429659Slinton register Symbol f; 5439659Slinton register Stack *savesp; 5449659Slinton register Integer n, off, len; 5459659Slinton 5469659Slinton sp -= size(s); 5479659Slinton savesp = sp; 5489659Slinton printf("("); 5499659Slinton f = s->chain; 5509659Slinton for (;;) { 5519659Slinton off = f->symvalue.field.offset; 5529659Slinton len = f->symvalue.field.length; 5539659Slinton n = (off + len + 7) div BITSPERBYTE; 5549659Slinton sp += n; 5559659Slinton printf("%s = ", symname(f)); 5569659Slinton c_printval(f); 5579659Slinton sp = savesp; 5589659Slinton f = f->chain; 5599659Slinton if (f == nil) break; 5609659Slinton printf(", "); 5619659Slinton } 5629659Slinton printf(")"); 5639659Slinton } 5649659Slinton 5659659Slinton /* 5669659Slinton * Print out a range type (integer, char, or boolean). 5679659Slinton */ 5689659Slinton 5699659Slinton private printrange(i, t) 5709659Slinton Integer i; 5719659Slinton register Symbol t; 5729659Slinton { 5739659Slinton if (istypename(t->type, "boolean")) { 5749659Slinton printf(((Boolean) i) == true ? "true" : "false"); 5759659Slinton } else if (istypename(t->type, "char")) { 5769659Slinton putchar('\''); 5779659Slinton printchar(i); 5789659Slinton putchar('\''); 5799659Slinton } else if (t->symvalue.rangev.lower >= 0) { 5809659Slinton printf("%lu", i); 5819659Slinton } else { 5829659Slinton printf("%ld", i); 5839659Slinton } 5849659Slinton } 5859659Slinton 5869659Slinton /* 5879659Slinton * Print out a null-terminated string (pointer to char) 5889659Slinton * starting at the given address. 5899659Slinton */ 5909659Slinton 5919659Slinton private printstring(addr) 5929659Slinton Address addr; 5939659Slinton { 5949659Slinton register Address a; 5959659Slinton register Integer i, len; 5969659Slinton register Boolean endofstring; 5979659Slinton union { 5989659Slinton char ch[sizeof(Word)]; 5999659Slinton int word; 6009659Slinton } u; 6019659Slinton 6029659Slinton putchar('"'); 6039659Slinton a = addr; 6049659Slinton endofstring = false; 6059659Slinton while (not endofstring) { 6069659Slinton dread(&u, a, sizeof(u)); 6079659Slinton i = 0; 6089659Slinton do { 6099659Slinton if (u.ch[i] == '\0') { 6109659Slinton endofstring = true; 6119659Slinton } else { 6129659Slinton printchar(u.ch[i]); 6139659Slinton } 6149659Slinton ++i; 6159659Slinton } while (i < sizeof(Word) and not endofstring); 6169659Slinton a += sizeof(Word); 6179659Slinton } 6189659Slinton putchar('"'); 6199659Slinton } 6209659Slinton 6219659Slinton /* 6229659Slinton * Print out an enumerated value by finding the corresponding 6239659Slinton * name in the enumeration list. 6249659Slinton */ 6259659Slinton 6269659Slinton private printenum(i, t) 6279659Slinton Integer i; 6289659Slinton Symbol t; 6299659Slinton { 6309659Slinton register Symbol e; 6319659Slinton 6329659Slinton e = t->chain; 6339659Slinton while (e != nil and e->symvalue.iconval != i) { 6349659Slinton e = e->chain; 6359659Slinton } 6369659Slinton if (e != nil) { 6379659Slinton printf("%s", symname(e)); 6389659Slinton } else { 6399659Slinton printf("%d", i); 6409659Slinton } 6419659Slinton } 6429659Slinton 6439659Slinton /* 6449659Slinton * Return the C name for the particular class of a symbol. 6459659Slinton */ 6469659Slinton 6479659Slinton public String c_classname(s) 6489659Slinton Symbol s; 6499659Slinton { 6509659Slinton String str; 6519659Slinton 6529659Slinton switch (s->class) { 6539659Slinton case RECORD: 6549659Slinton str = "struct"; 6559659Slinton break; 6569659Slinton 6579659Slinton case VARNT: 6589659Slinton str = "union"; 6599659Slinton break; 6609659Slinton 6619659Slinton case SCAL: 6629659Slinton str = "enum"; 6639659Slinton break; 6649659Slinton 6659659Slinton default: 6669659Slinton str = classname(s); 6679659Slinton } 6689659Slinton return str; 6699659Slinton } 670*12533Scsvaf public Node c_buildaref(a, slist) 671*12533Scsvaf Node a, slist; 672*12533Scsvaf { 673*12533Scsvaf register Symbol t; 674*12533Scsvaf register Node p; 675*12533Scsvaf Symbol etype, atype, eltype; 676*12533Scsvaf Node esub, r; 677*12533Scsvaf 678*12533Scsvaf r = a; 679*12533Scsvaf t = rtype(a->nodetype); 680*12533Scsvaf eltype = t->type; 681*12533Scsvaf if (t->class == PTR) { 682*12533Scsvaf p = slist->value.arg[0]; 683*12533Scsvaf if (not compatible(p->nodetype, t_int)) { 684*12533Scsvaf beginerrmsg(); 685*12533Scsvaf fprintf(stderr, "bad type for subscript of "); 686*12533Scsvaf prtree(stderr, a); 687*12533Scsvaf enderrmsg(); 688*12533Scsvaf } 689*12533Scsvaf r = build(O_MUL, p, build(O_LCON, (long) size(eltype))); 690*12533Scsvaf r = build(O_ADD, build(O_RVAL, a), r); 691*12533Scsvaf r->nodetype = eltype; 692*12533Scsvaf } else if (t->class != ARRAY) { 693*12533Scsvaf beginerrmsg(); 694*12533Scsvaf prtree(stderr, a); 695*12533Scsvaf fprintf(stderr, " is not an array"); 696*12533Scsvaf enderrmsg(); 697*12533Scsvaf } else { 698*12533Scsvaf p = slist; 699*12533Scsvaf t = t->chain; 700*12533Scsvaf for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) { 701*12533Scsvaf esub = p->value.arg[0]; 702*12533Scsvaf etype = rtype(esub->nodetype); 703*12533Scsvaf atype = rtype(t); 704*12533Scsvaf if (not compatible(atype, etype)) { 705*12533Scsvaf beginerrmsg(); 706*12533Scsvaf fprintf(stderr, "subscript "); 707*12533Scsvaf prtree(stderr, esub); 708*12533Scsvaf fprintf(stderr, " is the wrong type"); 709*12533Scsvaf enderrmsg(); 710*12533Scsvaf } 711*12533Scsvaf r = build(O_INDEX, r, esub); 712*12533Scsvaf r->nodetype = eltype; 713*12533Scsvaf } 714*12533Scsvaf if (p != nil or t != nil) { 715*12533Scsvaf beginerrmsg(); 716*12533Scsvaf if (p != nil) { 717*12533Scsvaf fprintf(stderr, "too many subscripts for "); 718*12533Scsvaf } else { 719*12533Scsvaf fprintf(stderr, "not enough subscripts for "); 720*12533Scsvaf } 721*12533Scsvaf prtree(stderr, a); 722*12533Scsvaf enderrmsg(); 723*12533Scsvaf } 724*12533Scsvaf } 725*12533Scsvaf return r; 726*12533Scsvaf } 727*12533Scsvaf 728*12533Scsvaf /* 729*12533Scsvaf * Evaluate a subscript index. 730*12533Scsvaf */ 731*12533Scsvaf 732*12533Scsvaf public int c_evalaref(s, i) 733*12533Scsvaf Symbol s; 734*12533Scsvaf long i; 735*12533Scsvaf { 736*12533Scsvaf long lb, ub; 737*12533Scsvaf 738*12533Scsvaf s = rtype(s)->chain; 739*12533Scsvaf lb = s->symvalue.rangev.lower; 740*12533Scsvaf ub = s->symvalue.rangev.upper; 741*12533Scsvaf if (i < lb or i > ub) { 742*12533Scsvaf error("subscript out of range"); 743*12533Scsvaf } 744*12533Scsvaf return (i - lb); 745*12533Scsvaf } 746