/* 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. * * md.c * * Machine dependant parts of first pass (parse) * Also type checking subroutines. */ #include #include "param.h" #include "tok.h" #include "nodes.h" #include "cookie.h" NODEP bas_type(); int adjtab[] = { K_INT, /* none */ K_SHORT, /* short */ K_LONG, /* long */ 0, /* short long */ K_UNSIGNED, /* unsigned */ K_UNSIGNED, /* unsigned short */ T_ULONG, /* unsigned long */ 0, /* unsigned short long */ }; adj_type(old, adj) { int rv; switch (old) { case K_CHAR: if (adj & SAW_UNS) return T_UCHAR; break; case K_INT: rv = adjtab[adj]; if (rv == 0) { error("bad type spec"); return K_INT; } return rv; case K_FLOAT: if (adj & SAW_LONG) return K_DOUBLE; break; } return old; } /* given ICON value, and flags SEE_L,SEE_U determine final type */ icon_ty(tp) NODE *tp; { int flags; long val; int islong, isuns; flags = tp->e_flags; val = tp->e_ival; islong = (flags & SEE_L); isuns = (flags & SEE_U); if (islong && isuns) return T_ULONG; if (islong || islongv(val)) return K_LONG; if (isuns) return K_UNSIGNED; return isintv((int)val) ? K_INT : K_CHAR; } isintv(i) { if (i > 0x7f || i < -0x80) return 1; return 0; } islongv(l) long l; { #ifndef NOLONGS if (l > MAXUNS || l < MININT) return 1; #endif return 0; } mkint(l) long l; { return l; } lc_reg(rp, xp) int *rp; NODE *xp; { switch (xp->n_tptr->t_token) { case STAR: return al_areg(rp,xp); case K_CHAR: case T_UCHAR: case T_ULONG: case K_INT: case K_UNSIGNED: case K_LONG: return al_dreg(rp,xp); default: return 0; } } al_areg(rp,xp) int *rp; NODEP xp; { register rmask, n; rmask = *rp; for (n=ARV_START; n<=ARV_END; n++) if ((rmask & (1<e_rno = n; *rp |= (1<e_rno = n; *rp |= (1<e_offs = 0; switch (np->n_tptr->t_token) { case '[': printf("GAK! array arg "); return SIZE_P; case K_CHAR: case T_UCHAR: np->e_offs = SIZE_I - SIZE_C; return SIZE_I; #if SIZE_I != SIZE_S case K_SHORT: np->e_offs = SIZE_I - SIZE_S; return SIZE_I; #endif default: return sz; } } mustlval(np) NODEP np; { switch (np->e_token) { case ID: case STAR: case '.': break; default: errorn("not lvalue", np); return 1; } return 0; } mustty(np, flags) NODEP np; { switch (np->n_tptr->t_token) { case STAR: if (flags & R_POINTER) return 0; error("pointer not allowed"); return 1; case K_STRUCT: case K_UNION: if (flags & R_STRUCT) return 0; error("struct/union not allowed"); return 1; case K_CHAR: case K_SHORT: case K_INT: case K_UNSIGNED: case K_LONG: case T_UCHAR: case T_ULONG: if (flags & R_INTEGRAL) return 0; error("integral not allowed"); return 1; case K_FLOAT: case K_DOUBLE: if (flags & R_FLOATING) return 0; error("floating not allowed"); return 1; default: error("bad type"); return 1; } return 0; } NODEP functy(np) NODEP np; { int lt; lt = np->n_tptr->t_token; if (lt != K_VOID) mustty(np, R_ASSN); switch (lt) { case STAR: case K_STRUCT: case K_UNION: return np->n_tptr; } lt = widen(lt); return bas_type(lt); } NODEP normalty(lp, rp) NODEP lp, rp; { /* already checked types are R_ARITH */ /* rp may be NULL */ int lt, rt, rett; lt = lp->n_tptr->t_token; if (rp) rt = rp->n_tptr->t_token; else rt = K_INT; rett = maxt(widen(lt), widen(rt)); return bas_type(rett); } asn_chk(ltp, rp) NODEP ltp, rp; { switch (ltp->t_token) { case K_STRUCT: case K_UNION: if (same_type(ltp, rp->n_tptr) == 0) error("bad struct assign"); return; case STAR: if (mayzero(rp)) return; if (mustty(rp, R_POINTER)) return; if (same_type(ltp->n_tptr, rp->n_tptr->n_tptr) == 0) warn("pointer types mismatch"); return; default: if (mustty(rp, R_ARITH)) return; } } chkcmp(np) NODEP np; { /* already checked types are R_SCALAR */ int lt, rt; NODEP lp = np->n_left, rp = np->n_right; lt = lp->n_tptr->t_token; lt = (lt == STAR); rt = rp->n_tptr->t_token; rt = (rt == STAR); if (lt && rt) { /* ptr cmp ptr */ if (same_type(lp->n_tptr, rp->n_tptr) == 0) { warn("cmp of diff ptrs"); } } else if (lt) { /* ptr cmp intg */ mustzero(rp); } else if (rt) { /* intg +-[ ptr */ mustzero(lp); } /* else both ARITH */ } NODEP colonty(np) NODEP np; { /* already checked types are R_SCALAR */ int lt, rt; NODEP lp = np->n_left, rp = np->n_right; lt = lp->n_tptr->t_token; lt = (lt == STAR); rt = rp->n_tptr->t_token; rt = (rt == STAR); if (lt && rt) { /* ptr : ptr */ warn(": diff ptrs"); return lp->n_tptr; } else if (lt) { /* ptr : intg */ mustzero(rp); return lp->n_tptr; } else if (rt) { mustzero(lp); return rp->n_tptr; } else return normalty(lp, rp); } NODEP addty(np) NODEP np; { /* already checked types are R_SCALAR */ /* op is '+' or '-' or '+=' or '-=' or '[' */ int oop = np->e_token; int op; int lt, rt; NODEP lp = np->n_left, rp = np->n_right; op = oop; if (isassign(op)) op -= ASSIGN 0; lt = lp->n_tptr->t_token; lt = (lt == STAR); rt = rp->n_tptr->t_token; rt = (rt == STAR); if (lt && rt) { /* ptr - ptr */ if (oop != '-' || same_type(lp->n_tptr, rp->n_tptr) == 0) { error("bad +/-"); return lp->n_tptr; } np->e_token = PTRDIFF; np->e_offs = lp->n_tptr->n_tptr->t_size; return bas_type(K_INT); } else if (lt) { /* ptr +-[ intg */ pandi: mustty(rp, R_INTEGRAL); np->e_offs = lp->n_tptr->n_tptr->t_size; if (op == '+') np->e_token += PTRADD-'+'; else if (op == '-') np->e_token += PTRSUB-'-'; return lp->n_tptr; } else if (rt) { /* intg +-[ ptr */ if (isassign(oop) || op == '-') { error("illegal int op ptr"); return bas_type(K_INT); } /* switch sides so intg is on right */ np->n_left = rp; np->n_right = lp; lp = rp; rp = np->n_right; goto pandi; } else { /* intg +- intg */ return normalty(lp, rp); } } mustzero(np) NODEP np; { if (np->e_token == ICON && np->e_ival == 0) { return; } error("bad ':' combination"); } mayzero(np) NODEP np; { if (np->e_token == ICON && np->e_ival == 0) { return 1; } return 0; } widen(ty) { switch (ty) { case K_CHAR: case T_UCHAR: return K_INT; case K_SHORT: return K_INT; case K_FLOAT: return K_DOUBLE; default: return ty; } } int pri_t[] = { 1, 6, /* uchar, ulong */ 5,2,4,3,0, /* long, short, uns, int, char */ 7,8,9 /* float, double, void */ }; extern nmerrors; maxt(t1, t2) { if (nmerrors) return K_INT; if (pri_t[t1-FIRST_BAS] > pri_t[t2-FIRST_BAS]) return t1; return t2; }