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