Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - c/old/kc/cc50.c
There are no other files named cc50.c in the archive.
/* cc50.c   (C) 1981  K. Chen */

#define	    sc extern
#include    "cc.h"


/* ----------------------------------- */
/*	expression  Ref.[1]  A.9.1     */
/* ----------------------------------- */

node expression()
{
  struct NODE *ternary(), *l, *r, *fold();
  int    op;

  l = ternary();
  if (tok[token].ttype == ASOP) {
      op = token;
      nextoken();
      r = expression();
      l = defnode(N3, op, l->ntype, 0, l, r);
  }
  return fold(l);
}

/* ------------------------- */
/*	expression list      */
/* ------------------------- */

node exprlist()
{
  struct NODE *s, *t;

  s = expression();
  optexpr(s);
  while (token == COMMA) {
      nextoken();
      t = expression();
      optexpr(t);
      s = defnode(N3, EXPRESS, t->ntype, t->nflag, s, t);
  }
  return s;
}

/* --------------------------------- */
/*	statement  Ref.[1]  A.9      */
/* --------------------------------- */

node statement()
{
  struct SYMBOL *sym;
  struct NODE   *s;
  int    tokn, nlabel;

  sym = csymbol;
  tokn = token;
  nextoken();

  switch (tokn) {
  case BREAK:
       if (breaklevel == 0) {
	   error(EBREAK);
	   return NULL;
       }
       expect(SCOLON);
       return defnode(N1, BREAK);
  case CASE:
       return casestmt();
  case DEFAULT:
       return defaultstmt();
  case DO:
       return dostmt();
  case FOR:
       return forstmt();
  case IF:
       return conditional();
  case LBRACE:
       return compound();
  case RETURN:
       return returnstmt();
  case SCOLON:
       return NULL;
  case SWITCH:
       return switchstmt();
  case WHILE:
       return whilestmt();
  case GOTO:
       return gotostmt();
  case CONTINUE:
       if (breaklevel == 0) {
	   error(ECONTINUE);
	   return NULL;
       }
       expect(SCOLON);
       return defnode(N1, CONTINUE);
  case IDENT:
       if (token == COLON) {
	   nlabel = label(sym);
	   s = statement();
           return defnode(N3, LABEL, 0, nlabel, s);
       }
       /* fall through */
  default:
       tokpush(tokn, sym);
       s = exprlist();
       expect(SCOLON);
       return s;
  }
}


/* ----------------------- */
/*	define a node      */
/* ----------------------- */

node defnode(n, op, type, flag, llink, rlink)
struct NODE *llink, *rlink;
struct TY   *type;
{
  struct NODE *nd;

  nd = &nodes[maxnode++];
  if (maxnode >= MAXNODE) {
      fprintf(stderr, "Function too large.\n");
      exit(0);
  }
  nd->nop = op;

  switch (n) {
  case N1:
       nd->ntype = nd->left = nd->right = NULL;
       nd->nflag = 0;
       return nd;
  case N2:
       nd->ntype = type;
       nd->nflag = flag;
       nd->left = llink;
       nd->right = NULL;
       return nd;
  case N3:
       nd->ntype = type;
       nd->nflag = flag;
       nd->left = llink;
       nd->right = rlink;
       return nd;
  }
}


/* ----------------------------------------------- */
/*	conditional statement  Ref.[1]  A.9.3      */
/* ----------------------------------------------- */

node conditional()
{
  struct NODE *cond, *then, *elsec;

  expect(LPAREN);
  cond = expression();
  expect(RPAREN);
  then = statement();
  if (token == ELSE) {
      nextoken();
      elsec = statement();
  }
  else elsec = NULL;

  then = defnode(N3, 0,  NULL, 0, then, elsec);
  return defnode(N3, IF, NULL, 0, cond, then);
}

/* ----------------------------------------- */
/*	while statement  Ref.[1]  A.9.4      */
/* ----------------------------------------- */

node whilestmt()
{
  struct NODE *cond, *stmt;

  expect(LPAREN);
  cond = expression();
  expect(RPAREN);
  breaklevel++;
  contlevel++;
  stmt = statement();
  breaklevel--;
  contlevel--;
  return defnode(N3, WHILE, NULL, 0, cond, stmt);
}

/* -------------------------------------- */
/*	do statement  Ref.[1]  A.9.5      */
/* -------------------------------------- */

node dostmt()
{
  struct NODE *cond, *stmt;

  contlevel++;
  breaklevel++;
  stmt = statement();
  breaklevel--;
  contlevel--;
  expect(WHILE);
  expect(LPAREN);
  cond = expression();
  expect(RPAREN);
  expect(SCOLON);
  return defnode(N3, DO, NULL, 0, cond, stmt);
}


/* --------------------------------------- */
/*	for statement  Ref.[1]  A.9.6      */
/* --------------------------------------- */

node forstmt()
{
  struct NODE *preamble, *e1, *e2, *e3, *s;

  e1 = e2 = e3 = NULL;
  expect(LPAREN);
  if (token != SCOLON) e1 = exprlist(); 
  expect(SCOLON);
  if (token != SCOLON) e2 = exprlist();
  expect(SCOLON);
  if (token != RPAREN) e3 = exprlist();
  expect(RPAREN);
  contlevel++;
  breaklevel++;
  s = statement();
  breaklevel--;
  contlevel--;
  preamble = defnode(N3, 0, NULL, 0, e1, e2);
  preamble = defnode(N3, 0, NULL, 0, preamble, defnode(N2, 0, NULL, 0, e3));
  return defnode(N3, FOR, NULL, 0, preamble, s);
}

/* ------------------------------------------ */
/*	switch statement  Ref.[1]  A.9.7      */
/* ------------------------------------------ */

node switchstmt()
{
  struct NODE *cond, *stmt;

  expect(LPAREN); 
  cond = expression();
  expect(RPAREN);
  breaklevel++;
  stmt = statement();
  breaklevel--;
  return defnode(N3, SWITCH, NULL, 0, cond, stmt);
}

/* ------------------------------------ */
/*	case label  Ref.[1]  A.9.7      */
/* ------------------------------------ */

node casestmt()
{
  int    c;
  struct NODE *n, *rn;

  n = expression();
  if (n->nop != ICONST) error(ECONST);
  rn = n = defnode(N3, CASE, deftype, 0, NULL, n);
  expect(COLON);
  while (!incase()) {
      n = n->left = defnode(N3, STATEMENT, NULL, 0, NULL, statement());
  }
  return rn;
}

/* ------------------------------------- */
/*	default label  Ref.[1]  A.9.7    */
/* ------------------------------------- */

node defaultstmt()
{
  struct NODE *n, *rn;

  rn = n = defnode(N2, DEFAULT, deftype, NULL, NULL);
  expect(COLON);
  while (!incase()) {
      n = n->left = defnode(N3, STATEMENT, NULL, 0, NULL, statement());
  }
  return rn;
}

incase()
{
  return (token==CASE || token==DEFAULT || token==RBRACE || token==EOF);
}

/* ------------------------------------------- */
/*	return statement  Ref.[1]  A.9.10      */
/* ------------------------------------------- */

node returnstmt()
{ 
  struct NODE *e;

  if (token != SCOLON) {
      e = expression();
      expect(SCOLON);
      return defnode(N3, RETURN, NULL, 0, NULL, e);
  }
  nextoken();
  return defnode(N1, RETURN);
}

/* -------------------------- */
/*	primary operator      */
/* -------------------------- */

node primary()
{
  int    op, flag, ty;
  char   temp[16];
  struct NODE *n, *s;
  struct TY   tt, *tp;
  struct SYMBOL *sy, *findsymbol();

  switch (token) {
  case IDENT:
       if (csymbol->sclass == SUNDEF) {
	   sy = csymbol;
	   nextoken();
           if (token == LPAREN) {
	       tt.ttype = FUNCTION;
	       tt.tsize = INTSIZE;
	       tt.tptr = deftype;
	       sy = findsym(sy->sname);
	       sy->sptr = gettype(&tt);
	       sy->sclass = SEXTERN;
	       sy->svalue = 0;
               n = defnode(N2, IDENT, sy->sptr, 0, sy);
	   }
	   else {
	       n = NULL;
	       error(EUNDEF, sy->sname);
	       freesym(sy);
	   }
       }
       else {
           flag = lvalue(csymbol);
           n = defnode(N2, IDENT, csymbol->sptr, flag, csymbol);
           nextoken();
       }
       break;
  case CONST:
       n = defnode(N2, CONST, constant.ctype, 0, NULL);
       switch (constant.ctype->ttype) {
       case INT:
	    n->nop = ICONST;
	    n->niconst = constant.cvalue;
	    n->ntype = deftype;
	    break;
       case PTR:
	    n->nop = SCONST;
	    n->nsconst = constant.csptr;
	    tt.ttype = PTR;
	    tt.tsize = PTRSIZE;
	    tt.tptr = &types[CHAR-INT];
	    n->ntype = gettype(&tt);
       }
       nextoken();
       break;
  case LPAREN:
       nextoken();
       n = expression();
       expect(RPAREN);
       break;
  default:
       error(EPRIM);
       return;
  }

  while (1) {
      switch (token) {
      case LPAREN:
           nextoken();
           s = (token != RPAREN) ? exprlist() : NULL;
           n = defnode(N3, FNCALL, n->ntype, 0, n, s);
           expect(RPAREN);
           break;

      case LBRACK:
           nextoken();
           tp = n->ntype;
           ty = tp->ttype;
           if (ty != ARRAY && ty != PTR) error(EARRAY);
           s = expression();
           op = s->ntype->ttype;
	   if (op ==FUNCTION) {
	       op = s->ntype->tptr->ttype;
	   }
           if (op != INT && 
               op != CHAR && 
               op != SHORT &&
	       op != LONG) error(EINT, "array index");

           flag = n->nflag;
           tp = tp->tptr;
           n = typecheck(defnode(N3, PLUS, n->ntype, flag, n, s));
           flag = flag|LVALUE;
           n = defnode(N2, PTR, tp, flag, n);
           expect(RBRACK);
           break;

      case DOT:
      case MEMBER: 
           op = token;
           nextoken();
           if (token != IDENT) error(EMEMBER);
           else {
              if (csymbol->sclass == UNDEF) {
	          freesymbol(csymbol->sname);
    	      }
              symcpy(temp, "#");  /* change identifier into a member */
  	      symapp(temp, csymbol->sname);
	      csymbol = findsymbol(temp);
	  
	      /* check that identifiers are indeed usable */
	  
  	      tp = n->ntype;
	      if (op == DOT) {
	          if (tp->ttype != STRUCT)
	              error(ESTRUCT);
	      }
	      else {
	          if (tp->ttype != PTR && tp->tptr->ttype != STRUCT) 
		      error(EPSTRUCT);
	      }
	      if (csymbol->sclass != SMEMBER) error(EMEMBER);
              s = defnode(N2,IDENT,csymbol->sptr,lvalue(csymbol),csymbol);
	      nextoken();
   	      n = defnode(N3, op, s->ntype, LVALUE, n, s);
           }
	   break;
      default:
           return n;
      }
  }
  return n;
}

/* ------------------------- */
/*	unary operators      */
/* ------------------------- */

node unary()
{
  struct SYMBOL *tag, *findsym();
  struct TY     *typename(), *typespec(), new, *t;
  struct NODE   *n, *m;
  int    op, scl, k, f, s;
  char   sname[32];
  
  switch (token) {
  case MPLY:
       token = PTR;
       break;
  case AND:
       token = ADDR;
       break;
  case MINUS:
       token = NEG;
       break;
  case INC:
       token = PINC;
       break;
  case DEC:
       token = PDEC;
       break;
  case LPAREN:
       nextoken();
       if (csymbol != NULL) {
	   scl = csymbol->sclass;
	   if (scl == SRW) {
	       k = csymbol->skey;
	       if (k == TYPESPEC || k == SUSPEC) {
		   t = typename();
	           expect(RPAREN);
		   n = expression();
		   m = defnode(N2, COERCE, t, n->nflag, n);
		   m->nc = coertype(t, n->ntype);
		   return m;
	       }
	   }
	   else if (scl == STYPEDEF) {
	       t = typename();
	       expect(RPAREN);
	       n = expression();
	       return defnode(N2, COERCE, t, n->nflag, n);
           }
       }
       tokpush(LPAREN, NULL);
       return primary();
  case NOT:
  case COMPL:
       break;
  case SIZEOF:
       nextoken();
       if (token == LPAREN) {
           expect(LPAREN);
           if (csymbol->sclass != SUNDEF) s = tsize(csymbol->sptr)*NBYTES;
           else {
               symcpy(sname, "%");
	       symapp(sname, csymbol->sname);
    	       tag = findsym(sname);
  	       if (tag == NULL) {
	           error(EUNDEF,csymbol->sname);
	           s = 0;
	       }
	       else s = tsize(tag->sptr)*NBYTES;
	   }
           expect(IDENT);
           expect(RPAREN);
       }
       else {
           n = expression();
	   s = tsize(n->ntype)*NBYTES;
       }
       n = defnode(N1, ICONST);
       n->ntype = deftype;
       n->niconst = s;
       return n;
  default:
       n = primary();
       switch (token) {
       case INC:
       case DEC:
	    n = defnode(N2, token, n->ntype, n->nflag, n);
	    t = n->left->ntype->tptr;
	    n->nsize = (t == NULL) ? 1 : tsize(t);
	    nextoken();
       }
       return n;
  }
  op = token;
  nextoken();
  n = unary();
  t = n->ntype;
  f = n->nflag;

  if (op == ADDR) {
      if (!(LVALUE & f))
	  error(ELVALUE, "operand of &(.)");
      new.ttype = PTR;		/* "pointer to ..." */
      new.tsize = PTRSIZE;
      new.tptr = t;
      t = gettype(&new);
      f = f & (~LVALUE);
  }
  else {
      if (op == PTR) {
	  k = t->ttype;
	  if (k != PTR && k != ARRAY) 
	      error(EPTR);
	  else t = t->tptr;
	  f = f | LVALUE;
      }
  }
  n = defnode(N2, op, t, f, n);
  if (op == PINC || op == PDEC) {
      t = n->left->ntype->tptr;
      n->nsize = (t == NULL) ? 1 : tsize(t);
  }
  return n;
}

/* ----------------------------------------- */
/*	binary operator  Ref.[1] A.18.1      */
/* ----------------------------------------- */

node binary(prec)
{
  int r, op;
  struct NODE *f, *s;

  f = unary();
  while((op = tok[token].ttype) == BINOP || op == BOOLOP) {
      if ((r = tok[token].tprec) <= prec) break;
      op = token;
      nextoken();
      s = binary(r);
      f = typecheck(defnode(N3, op, f->ntype, f->nflag, f, s));
  }
  return f;
}

/* -------------------------- */
/*	ternary operator      */
/* -------------------------- */

node ternary()
{
  struct NODE *c, *t, *f;

  c = binary(1);
  if (token == QUERY) {
      nextoken();
      t = expression();
      expect(COLON);
      f = expression();
      t = defnode(N3, 0, t->ntype, t->nflag, t, f);
      return defnode(N3, QUERY, t->ntype, t->nflag, c, t);
  }
  return c;
}

/* -------------------------------------------- */
/*	compound statement  Ref.[1]  A.9.2      */
/* -------------------------------------------- */

node compound()
{
  int saveauto, savemin;
  struct NODE *u;

  saveauto = maxauto;
  savemin = minloc;
  scope++;
  decllist();
  if (token == RBRACE) {
      return defnode(N1, NULL);
  }
  u = stmtlist();
  expect(RBRACE);
  scope--;
  ridauto(savemin);
  maxauto = saveauto;
  return u;
}

/* -------------------------------- */
/*	label  Ref.[1]  A.9.12      */
/* -------------------------------- */

label(sym)
struct SYMBOL *sym;
{
  int n;
  struct NODE *nod;

  n = plabel(sym);
  expect(COLON);
  return n;
}

/* ----------------------------------------- */
/*	goto statement  Ref.[1]  A.9.11      */
/* ----------------------------------------- */

node gotostmt()
{
  int n;
  struct NODE *nod;

  if (token == IDENT) {
      n = plabel(csymbol);
      nextoken();
      expect(SCOLON);
      nod = defnode(N1, GOTO);
      nod->nflag = n;
      return nod;
  }
  error (ELABEL);
}


/* --------------------- */
/*	parse label      */
/* --------------------- */

plabel(sym)
struct SYMBOL *sym;
{
  int n;
  struct SYMBOL *s, *creatloc();

  n = sym->sclass;
  if (n == SUNDEF) {
      maxlabel++;
      freesym(sym->sname);
      s = creatsym(sym->sname);
      s->sclass = SAUTO;
      s->svalue = maxlabel;
      s->sptr = deflabel;
      return maxlabel;
  }
  if (n == SAUTO && sym->sptr->ttype == LABEL) {
      return sym->svalue;
  }
  error(ELABEL, sym->sname);
  return 0;
}


/* ------------------------------- */
/*	return an lvalue flag      */
/* ------------------------------- */

lvalue(s)
struct SYMBOL *s;
{
  int n;
  n = s->sptr->ttype;
  if ((n >= INT && n <= UNSIGNED) || n == PTR) return LVALUE;
  return 0;
}

/* --------------------------------- */
/*	decide on type coercion      */
/* --------------------------------- */

coertype(t,u)
struct TY *t, *u;
{
  if ((t == u) || (t == deftype && u == chartype) ||
      (t == chartype && u == deftype)) return NOCOER;

  switch (t->ttype) {		/* destination */
  case PTR:
       t = t->tptr;
       switch (u->ttype) {	/* source */
       case PTR:
            u = u->tptr;
            if (t == u) return NOCOER;
            if (t == chartype) return PI_PC;
            if (u == chartype) return PC_PI;
            error(ECOER);
            return NOCOER;
       default:	    
            return (t == chartype) ? PI_PC : PI_PI;
       }
  }
  return NOCOER;
}