home *** CD-ROM | disk | FTP | other *** search
- /* 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 <stdio.h>
- #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
- #define HIBITS 0xffff0000L
-
- if ((l & HIBITS) == 0) /* upper 16 bits zero */
- return 0;
-
- if ((l & HIBITS) == HIBITS) { /* upper bits all on */
- if (l & 0x8000L)
- return 0; /* upper bits aren't significant */
- else
- return 1;
- }
- return 1;
- #else
- return 0;
- #endif
- }
-
- 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<<n)) == 0) {
- xp->e_rno = n;
- *rp |= (1<<n);
- return 1;
- }
- return 0;
- }
-
- al_dreg(rp,xp)
- int *rp;
- NODEP xp;
- {
- register rmask, n;
-
- rmask = *rp;
- for (n=DRV_START; n<=DRV_END; n++)
- if ((rmask & (1<<n)) == 0) {
- xp->e_rno = n;
- *rp |= (1<<n);
- return 1;
- }
- return 0;
- }
-
- long
- arg_size(sz,np)
- long sz;
- NODEP np;
- {
- np->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:
- if (sz & 1)
- sz++;
- 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 */
- };
-
- maxt(t1, t2)
- {
- extern nmerrors;
-
- if (nmerrors)
- return K_INT;
- if (pri_t[t1-FIRST_BAS] > pri_t[t2-FIRST_BAS])
- return t1;
- return t2;
- }
-