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