/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg * * Permission is granted to anyone to use this software for any purpose * on any computer system, and to redistribute it freely, with the * following restrictions: * 1) No charge may be made other than reasonable charges for reproduction. * 2) Modified versions must be clearly marked as such. * 3) The authors are not responsible for any harmful consequences * of using this software, even if they result from defects in it. * * d2.c * * Declaration subroutines * * Mostly routines for initializations */ #include #include "param.h" #include "tok.h" #include "nodes.h" #include "cookie.h" #if MMCC overlay "pass2" #endif extern NODEP cur; extern NODEP symtab[]; extern level; extern int oflags[]; #define debugi oflags['i'-'a'] su_size(lp, cp, xp, isunion) register long *lp; char *cp; register NODE *xp; { long sz; char al; sz = xp->n_tptr->t_size; al = xp->n_tptr->t_aln; if (isunion) { *lp = *lp > sz ? *lp : sz; } else { while (al & (*lp)) { /* align new field */ (*lp)++; xp->e_offs++; } *lp += sz; } *cp = *cp > al ? *cp : al; } lc_size(lp, rp, xp) register long *lp; int *rp; register NODE *xp; { long sz; char al; long arg_size(); if (level > 1 && xp->e_sc == K_REGISTER) { if (lc_reg(rp, xp)) return; else xp->e_sc = K_AUTO; } if (xp->e_sc == K_AUTO || level == 1) { sz = xp->n_tptr->t_size; al = xp->n_tptr->t_aln; while (al & (*lp)) { /* align new field */ (*lp)++; xp->e_offs++; } if (level == 1) { sz = arg_size(sz,xp); xp->e_offs += ARG_BASE + *lp; } *lp += sz; if (level != 1) xp->e_offs = LOC_BASE - *lp; } } su_fld(lp, alp, xp, fldw, fop) register long *lp; char *alp; register NODE *xp; int *fop; { if (*alp < ALN_I) *alp = ALN_I; if (fldw == 0) { afterfld(lp, fop); return; } if (fldw + *fop > 8*SIZE_I) afterfld(lp, fop); if (xp) { xp->e_fldw = fldw; xp->e_fldo = *fop; } *fop += fldw; } afterfld(szp, fop) long *szp; int *fop; { if (*fop) { *szp += SIZE_I; *fop = 0; } } ok_gsh(sc, np) NODE *np; { if (sc == K_REGISTER || sc == K_AUTO) { error("reg/auto outside fun"); return 0; } return ok_ty(np, NULL); } ok_gx(np, endp) NODEP np, endp; { if (np) return ok_ty(np->n_tptr, endp); return 0; } ok_lsh(sc, np) NODE *np; { return ok_ty(np, NULL); } arytoptr(np) NODEP np; { NODEP tp = np->n_tptr; NODEP copyone(); if (np->n_flags & N_COPYT) { /* cant change if a dupl. */ tp = copyone(tp); np->n_tptr = tp; np->n_flags &= ~N_COPYT; } tp->t_token = STAR; strcpy(tp->n_name, "Aptr to"); } ok_lx(np,endp) NODEP np, endp; { if (np) { if (level == 1 && np->n_tptr->t_token == '[') arytoptr(np); return ok_ty(np->n_tptr, endp); } return 0; } ok_suh(np) NODEP np; { return 1; } ok_sux(np, endp) NODEP np, endp; { if (np) return ok_ty(np->n_tptr, endp); return 0; } ok_enx(np, endp) NODEP np, endp; { if (np && np->n_tptr == endp) /* no modifiers */ return 1; return 0; } ok_cast(np, endp) NODEP np, endp; { if (np) return ok_ty(np, endp); return 0; } ok_ty(np, endp) register NODEP np, endp; { NODEP child; long csize; long conlval(); if (np == endp) return 1; child = np->n_tptr; if (child) { if (ok_ty(child, endp) == 0) return 0; csize = child->t_size; } switch (np->t_token) { case STAR: np->t_size = SIZE_P; np->t_aln = ALN_P; break; case '(': /* size 0 okay - fun ret void */ if (child->t_token == '[') { error("bad func"); return 0; } /* size 0 */ break; case '[': if (csize == 0) { error("bad array"); return 0; } if (np->n_right) { csize *= conlval(np->n_right); np->n_right = NULL; np->t_size = csize; } np->t_aln = child->t_aln; break; default: return 1; } return 1; } ok_revx(rv,forcast) NODEP rv; { if (rv == NULL) return 1; if (forcast == 0 && rv->e_token != ID) { error("need ID"); return 0; } if (forcast && rv->e_token == ID) { error("ID in cast"); return 0; } return 1; } opt_ginit(xp) NODEP xp; { if (xp->e_token != ID) return; if (xp->n_tptr->t_token == '(') return; switch (xp->e_sc) { case K_STATIC: case HERE_SC: if (cur->e_token == '=') { out_gv(xp, 0); /* place in data segment */ fadvnode(); g_init(xp->n_tptr); } else out_gv(xp, 1); /* place in BSS segment */ break; /* ? added external case ? */ case K_EXTERN: out_gv(xp,0); } } opt_linit(xp) NODEP xp; { if (xp->e_token != ID) return; if (xp->n_tptr->t_token == '(') return; switch (xp->e_sc) { case K_STATIC: if (cur->e_token == '=') { out_gv(xp, 0); fadvnode(); g_init(xp->n_tptr); } else out_gv(xp, 1); to_text(); break; case K_AUTO: case K_REGISTER: if (cur->e_token == '=') a_init(xp); break; } } a_init(op) NODEP op; { register NODEP np, xp; NODEP assignx(), copynode(); np = cur; advnode(); xp = assignx(); op = copynode(op); np->n_left = op; np->n_right = xp; np->e_type = E_BIN; do_expr(np, FORSIDE); return; } opt_enval(intp) int *intp; { NODEP np; NODEP questx(); if (cur->e_token == '=') { fadvnode(); np = questx(); *intp = conxval(np); return; } } opt_field(xp,wdp,isunion) NODE *xp; int *wdp; { NODEP np; NODEP questx(); int i; *wdp = -1; if (isunion) return; if (cur->e_token == ':') { fadvnode(); np = questx(); i = conxval(np); if (i > 8*SIZE_I) { error("field too big"); i = 8*SIZE_I; } if (xp) { if (i <= 0 || bad_fty(xp->n_tptr)) { error("bad field"); return; } } else if (i < 0) { error("neg field width"); return; } *wdp = i; return; } } bad_fty(tp) NODEP tp; { int tok; tok = tp->t_token; if (tok == K_INT || tok == K_UNSIGNED) return 0; return 1; } field(xp, wd, ofp) NODEP xp; int *ofp; { } NODEP def_type() { NODEP bas_type(); return bas_type(K_INT); } #define NSC LAST_SC-FIRST_SC+1 #define NBAS LAST_BAS-FIRST_BAS+1 NODE basics[NBAS]; NODE str_ptr, fun_int; struct bt { char *name; int size; char align; } btbl[] = { {"Uchar", SIZE_C, ALN_C}, {"Ulong", SIZE_L, ALN_L}, {"Long", SIZE_L, ALN_L}, {"Short", SIZE_S, ALN_S}, {"Uns", SIZE_U, ALN_U}, {"Int", SIZE_I, ALN_I}, {"Char", SIZE_C, ALN_C}, {"Float", SIZE_F, ALN_F}, {"Dbl", SIZE_D, ALN_D}, {"Void", 0}, }; NODEP bas_type(btype) { NODEP rv; static once = 0; if (once == 0) { once++; sprintf(str_ptr.n_name, "Ptr to"); str_ptr.t_token = STAR; str_ptr.n_tptr = bas_type(K_CHAR); str_ptr.n_flags = N_COPYT; str_ptr.t_size = SIZE_P; str_ptr.t_aln = ALN_P; sprintf(fun_int.n_name, "Fun ret"); fun_int.t_token = '('; fun_int.n_tptr = bas_type(K_INT); fun_int.n_flags = N_COPYT; } if (btype == SCON) return &str_ptr; else if (btype == '(') return &fun_int; rv = &basics[btype-FIRST_BAS]; if (rv->t_token == 0) { rv->t_token = btype; rv->t_size = btbl[btype-FIRST_BAS].size; rv->t_aln = btbl[btype-FIRST_BAS].align; sprintf(rv->n_name, btbl[btype-FIRST_BAS].name); } return rv; } /* new function name seen in expr */ NODEP new_fun(op) NODE *op; { NODEP np; NODEP copyone(); /* we know left, right and tptr are NULL */ np = copyone(op); /* ID node */ np->n_tptr = bas_type('('); np->n_flags = N_COPYT; np->e_sc = K_EXTERN; new_sym(symtab, np); return np; } /* declare arg name as int */ def_arg(listpp, op) NODE **listpp, *op; { register NODEP np; NODEP copyone(); np = copyone(op); np->n_tptr = bas_type(K_INT); np->n_flags = N_COPYT; np->e_sc = K_AUTO; new_sym(listpp, np); } /* initialize 0 or 1 thing of any type (tp) */ g_init(tp) register NODEP tp; { int nsee; long sz; int oldsize; int seebr = 0; if (cur->e_token == SCON && tp->t_token == '[' && tp->n_tptr->t_token == K_CHAR) { /* hack for SCON ary */ nsee = out_scon(cur); fadvnode(); a_fix(tp, nsee); return 1; } if (cur->e_token == '{') { fadvnode(); seebr = 1; } switch (tp->t_token) { case '[': if (tp->t_size) oldsize = tp->t_size / tp->n_tptr->t_size; else oldsize = 0; nsee = inita(tp->n_tptr, oldsize); if (nsee) a_fix(tp, nsee); break; case K_STRUCT: o_aln(tp->t_aln); nsee = inits(tp->n_right); break; case K_UNION: o_aln(tp->t_aln); nsee = g_init(tp->n_right->n_tptr); if (nsee) { sz = tp->t_size - tp->n_right->n_tptr->t_size; if (sz) o_nz(sz, 0); } break; default: nsee = init1(tp); break; } if (seebr) { if (cur->e_token == ',') fadvnode(); eat('}'); } return nsee ? 1 : 0; } /* initialize one (or 0) scalar to an expr */ init1(tp) register NODEP tp; { NODEP xp; NODEP assignx(); if (debugi) { printf("init1"); printnode(tp); } xp = assignx(); if (xp) { if (debugi) printnode(xp); o_vinit(tp, xp); return 1; } else return 0; } /* set array size or fill array with zeros */ a_fix(tp, nsee) register NODEP tp; { int oldsize; if (tp->t_size) { oldsize = tp->t_size / tp->n_tptr->t_size; if (oldsize > nsee) { o_nz(tp->n_tptr->t_size * (oldsize-nsee), tp->n_tptr->t_aln); } else if (oldsize < nsee) { error("too many init exprs"); } } else tp->t_size = nsee * tp->n_tptr->t_size; } /* initialize up to max items of type tp */ /* if max is 0, any number is okay */ inita(tp, maxi) NODEP tp; { int nsee; nsee = g_init(tp); if (nsee == 0) return 0; while (cur->e_token == ',') { if (nsee == maxi) break; fadvnode(); nsee += g_init(tp); } return nsee; } /* initialize (possible) structure */ inits(np) register NODEP np; { int see1; see1 = g_init(np->n_tptr); if (see1 == 0) return 0; while (np->n_next) { np = np->n_next; if (cur->e_token == ',') { fadvnode(); see1 = g_init(np->n_tptr); } else see1 = 0; if (see1 == 0) z_init(np->n_tptr); } return 1; } z_init(tp) register NODEP tp; { switch (tp->t_token) { case '[': case K_STRUCT: case K_UNION: o_nz(tp->t_size, tp->t_aln); break; default: out_zi(tp); } }