update from donn@utah-cs
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Fri, 23 Aug 1985 10:09:06 +0000 (02:09 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Fri, 23 Aug 1985 10:09:06 +0000 (02:09 -0800)
SCCS-vsn: old/pcc/c2.vax/c2.h 4.10
SCCS-vsn: old/pcc/c2.vax/c20.c 4.10
SCCS-vsn: old/pcc/c2.vax/c21.c 4.16
SCCS-vsn: old/pcc/mip/allo.c 4.7
SCCS-vsn: old/pcc/mip/cgram.y 4.4
SCCS-vsn: old/pcc/mip/common.c 4.2
SCCS-vsn: old/pcc/mip/config.h 4.3
SCCS-vsn: old/pcc/mip/fort.c 4.7
SCCS-vsn: old/pcc/mip/match.c 4.4
SCCS-vsn: old/pcc/mip/optim.c 4.6
SCCS-vsn: old/pcc/mip/pass1.h 4.2
SCCS-vsn: old/pcc/mip/pftn.c 1.9
SCCS-vsn: old/pcc/mip/reader.c 4.4
SCCS-vsn: old/pcc/mip/scan.c 1.7
SCCS-vsn: old/pcc/mip/trees.c 4.9

15 files changed:
usr/src/old/pcc/c2.vax/c2.h
usr/src/old/pcc/c2.vax/c20.c
usr/src/old/pcc/c2.vax/c21.c
usr/src/old/pcc/mip/allo.c
usr/src/old/pcc/mip/cgram.y
usr/src/old/pcc/mip/common.c
usr/src/old/pcc/mip/config.h
usr/src/old/pcc/mip/fort.c
usr/src/old/pcc/mip/match.c
usr/src/old/pcc/mip/optim.c
usr/src/old/pcc/mip/pass1.h
usr/src/old/pcc/mip/pftn.c
usr/src/old/pcc/mip/reader.c
usr/src/old/pcc/mip/scan.c
usr/src/old/pcc/mip/trees.c

index 134f5bd..b30d8ef 100644 (file)
@@ -1,4 +1,4 @@
-/*     c2.h    4.9     85/03/19        */
+/*     c2.h    4.10    85/08/22        */
 
 /*
  * Header for object code improver
 
 /*
  * Header for object code improver
@@ -171,9 +171,6 @@ int nfield;
 int    nchange;
 long   isn;
 int    debug;
 int    nchange;
 long   isn;
 int    debug;
-char   *lasta;
-char   *lastr;
-char   *firstr;
 char   revbr[];
 #define        NREG    12
 char   *regs[NREG+5]; /* 0-11, 4 for operands, 1 for running off end */
 char   revbr[];
 #define        NREG    12
 char   *regs[NREG+5]; /* 0-11, 4 for operands, 1 for running off end */
@@ -192,7 +189,6 @@ long getnum();
 struct node *codemove();
 struct node *insertl();
 struct node *nonlab();
 struct node *codemove();
 struct node *insertl();
 struct node *nonlab();
-struct node *alloc();
 
 #ifdef notdef
 #define decref(p) \
 
 #ifdef notdef
 #define decref(p) \
@@ -200,3 +196,15 @@ struct node *alloc();
 #define delnode(p) \
        ((p)->back->forw = (p)->forw, (p)->forw->back = (p)->back)
 #endif notdef
 #define delnode(p) \
        ((p)->back->forw = (p)->forw, (p)->forw->back = (p)->back)
 #endif notdef
+
+char *xalloc();
+extern char *newa;
+extern char *lasta;
+extern char *lastr;
+#define        XALIGN(n) \
+               (((n)+(sizeof (char *) - 1)) & ~(sizeof (char *) - 1))
+#define        alloc(n) \
+               ((struct node *) \
+                ((newa = lasta) + (n) > lastr ? \
+                       xalloc(n) : \
+                       (lasta += XALIGN(n), newa)))
index 553cd69..9db3f4c 100644 (file)
@@ -11,37 +11,57 @@ static      char sccsid[] = "@(#)c20.c      4.10 (Berkeley) %G%";
 #include <ctype.h>
 #include <sys/types.h>
 
 #include <ctype.h>
 #include <sys/types.h>
 
-char _sibuf[BUFSIZ], _sobuf[BUFSIZ];
-caddr_t sbrk();
+char *malloc();
+char firstr[sizeof (char *)];
+char *currentb;
+char *newa;
+char *lasta;
+char *lastr;
+int ncore;
+
 int ioflag;
 int fflag;
 int ioflag;
 int fflag;
+
 long   isn     = 2000000;
 long   isn     = 2000000;
+
 struct optab *oplook();
 struct optab *getline();
 struct optab *oplook();
 struct optab *getline();
+
 long lgensym[10] =
   {100000L,200000L,300000L,400000L,500000L,600000L,700000L,800000L,900000L,1000000L};
 
 #define ALLOCSIZE      4096
 
 long lgensym[10] =
   {100000L,200000L,300000L,400000L,500000L,600000L,700000L,800000L,900000L,1000000L};
 
 #define ALLOCSIZE      4096
 
-struct node *
-alloc(an)
+/*
+ * Cheapo space allocator.  Works much like the old one but uses malloc()
+ * and doesn't clash with stdio.  Assumes that no one requests more than
+ * ALLOCSIZE bytes at a time.
+ */
+char *
+xalloc(n)
+int n;
 {
 {
-       register int n;
-       register struct node *p;
-
-       n = an;
-       n+=sizeof(char *)-1;
-       n &= ~(sizeof(char *)-1);
-       if (lasta+n >= lastr) {
-               if ((int) sbrk(ALLOCSIZE) == -1) {
+       register char *nextb = * (char **) currentb;
+
+       if (n == 0) {   /* Free everything */
+               currentb = firstr;
+               nextb = * (char **) currentb;
+       }
+       if (nextb == NULL) {
+               if ((nextb = malloc(ALLOCSIZE)) == NULL) {
                        fprintf(stderr, "Optimizer: out of space\n");
                        exit(1);
                }
                        fprintf(stderr, "Optimizer: out of space\n");
                        exit(1);
                }
-               lastr += ALLOCSIZE;
+               ncore += (ALLOCSIZE/1024);
+               * (char **) currentb = nextb;
+               * (char **) nextb = NULL;
        }
        }
-       p = (struct node *) lasta;
-       lasta += n;
-       return(p);
+       lasta = nextb + sizeof nextb;
+       lastr = nextb + ALLOCSIZE;
+       currentb = nextb;
+       newa = lasta;
+       lasta += XALIGN(n);
+       return(newa);
 }
 
 main(argc, argv)
 }
 
 main(argc, argv)
@@ -69,13 +89,10 @@ char **argv;
                }
                argc--; argv++;
        }
                }
                argc--; argv++;
        }
-       setbuf(stdin, _sibuf);
-       setbuf(stdout, _sobuf);
-       lasta = lastr = (char *) sbrk(2);
        opsetup();
        opsetup();
-       lasta = firstr = lastr = (char *) alloc(0);
        maxiter = 0;
        do {
        maxiter = 0;
        do {
+               (void) xalloc(0);
                isend = input();
                niter = 0;
                bmove();
                isend = input();
                niter = 0;
                bmove();
@@ -93,7 +110,6 @@ char **argv;
                output();
                if (niter > maxiter)
                        maxiter = niter;
                output();
                if (niter > maxiter)
                        maxiter = niter;
-               lasta = firstr;
        } while (isend);
        if (nflag) {
                fprintf(stderr,"%d iterations\n", maxiter);
        } while (isend);
        if (nflag) {
                fprintf(stderr,"%d iterations\n", maxiter);
@@ -114,7 +130,7 @@ char **argv;
                fprintf(stderr,"%d redundant tst's\n", nrtst);
                fprintf(stderr,"%d jump on bit\n", nbj);
                fprintf(stderr,"%d field operations\n", nfield);
                fprintf(stderr,"%d redundant tst's\n", nrtst);
                fprintf(stderr,"%d jump on bit\n", nbj);
                fprintf(stderr,"%d field operations\n", nfield);
-               fprintf(stderr,"%dK core\n", ((unsigned)lastr+01777) >> 10);
+               fprintf(stderr,"%dK core\n", ncore);
        }
        putc('\n',stdout);
        fflush(stdout); exit(0);
        }
        putc('\n',stdout);
        fflush(stdout); exit(0);
@@ -409,7 +425,7 @@ opsetup()
        register struct optab *optp, **ophp;
        register int i,t;
 
        register struct optab *optp, **ophp;
        register int i,t;
 
-       for(i=NREG+5;--i>=0;) regs[i]=(char *) alloc(C2_ASIZE);
+       for(i=NREG+5;--i>=0;) regs[i] = malloc(C2_ASIZE);
        for (optp = optab; optp->opstring[0]; optp++) {
                t=7; i=0; while (--t>=0) i+= i+optp->opstring[t];
                ophp = &ophash[i % OPHS];
        for (optp = optab; optp->opstring[0]; optp++) {
                t=7; i=0; while (--t>=0) i+= i+optp->opstring[t];
                ophp = &ophash[i % OPHS];
@@ -417,7 +433,7 @@ opsetup()
 /*                     fprintf(stderr,"\ncollision: %d %s %s",
 /*                             ophp-1-ophash,optp->opstring,(*(ophp-1))->opstring);
 */
 /*                     fprintf(stderr,"\ncollision: %d %s %s",
 /*                             ophp-1-ophash,optp->opstring,(*(ophp-1))->opstring);
 */
-                       if (ophp > &ophash[OPHS])
+                       if (ophp >= &ophash[OPHS])
                                ophp = ophash;
                }
                *--ophp = optp;
                                ophp = ophash;
                }
                *--ophp = optp;
index e0042b3..ef11950 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)c21.c 4.15 %G%";
+static char sccsid[] = "@(#)c21.c 4.16 %G%";
 #endif
 /* char C21[] = {"@(#)c21.c 1.83 80/10/16 21:18:22 JFR"}; /* sccs ident */
 
 #endif
 /* char C21[] = {"@(#)c21.c 1.83 80/10/16 21:18:22 JFR"}; /* sccs ident */
 
@@ -723,7 +723,10 @@ register struct node *p;
                        do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']';
                        if (!equstr(regs[RT3],"-(sp)")) p->combop=T(MOVA,BYTE);
                        else {p->combop=T(PUSHA,BYTE); *cp2=0;}
                        do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']';
                        if (!equstr(regs[RT3],"-(sp)")) p->combop=T(MOVA,BYTE);
                        else {p->combop=T(PUSHA,BYTE); *cp2=0;}
-                       if (uses[r]==0) {uses[r]=p; regs[r][0]=OPX<<4;}
+                       if (r < NUSE && uses[r] == 0) {
+                               uses[r]=p;
+                               regs[r][0]=OPX<<4;
+                       }
                        p->pop=0;
                }
        }
                        p->pop=0;
                }
        }
index 9d4b3e2..5843d88 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char *sccsid ="@(#)allo.c       4.6 (Berkeley) %G%";
+static char *sccsid ="@(#)allo.c       4.7 (Berkeley) %G%";
 #endif lint
 
 # include "pass2.h"
 #endif lint
 
 # include "pass2.h"
@@ -507,6 +507,7 @@ reclaim( p, rw, cookie ) NODE *p; {
 
        }
 
 
        }
 
+#ifndef ncopy
 ncopy( q, p ) NODE *p, *q; {
        /* copy the contents of p into q, without any feeling for
           the contents */
 ncopy( q, p ) NODE *p, *q; {
        /* copy the contents of p into q, without any feeling for
           the contents */
@@ -530,6 +531,7 @@ ncopy( q, p ) NODE *p, *q; {
 #endif
 
        }
 #endif
 
        }
+#endif
 
 NODE *
 tcopy( p ) register NODE *p; {
 
 NODE *
 tcopy( p ) register NODE *p; {
index a1be22d..a5f3931 100644 (file)
@@ -1,9 +1,10 @@
-/*     cgram.y 4.3     85/03/19        */
+/*     cgram.y 4.4     85/08/22        */
 
 /*
  * Grammar for the C compiler.
  *
 
 /*
  * Grammar for the C compiler.
  *
- * This grammar requires definitions of terminals extracted from pcclocal.h.
+ * This grammar requires the definitions of terminals in the file 'pcctokens'.
+ * (YACC doesn't have an 'include' mechanism, unfortunately.)
  */
 
 
  */
 
 
@@ -563,9 +564,22 @@ forprefix:   FOR  LP  .e  SM .e  SM
                            }
                ;
 switchpart:       SWITCH  LP  e  RP
                            }
                ;
 switchpart:       SWITCH  LP  e  RP
-                       ={  savebc();
+                       ={  register NODE *q;
+                       
+                           savebc();
                            brklab = getlab();
                            brklab = getlab();
-                           ecomp( buildtree( FORCE, $3, NIL ) );
+                           q = $3;
+                           switch( q->in.type ) {
+                           case CHAR:  case UCHAR:
+                           case SHORT: case USHORT:
+                           case INT:   case UNSIGNED:
+                           case MOE:   case ENUMTY:
+                                   break;
+                           default:
+                               werror("switch expression not type int");
+                               q = makety( q, INT, q->fn.cdim, q->fn.csiz );
+                               }
+                           ecomp( buildtree( FORCE, q, NIL ) );
                            branch( $$ = getlab() );
                            swstart();
                            reached = 0;
                            branch( $$ = getlab() );
                            swstart();
                            reached = 0;
index 74c510c..e77339f 100644 (file)
@@ -1,4 +1,4 @@
-/*     common.c        4.1     85/03/19        */
+/*     common.c        4.2     85/08/22        */
 
 #ifdef PASS1COMMON
 #include "pass1.h"
 
 #ifdef PASS1COMMON
 #include "pass1.h"
@@ -86,7 +86,7 @@ werror( s, a, b ) char *s; {  /* warning */
 
 tinit(){ /* initialize expression tree search */
 
 
 tinit(){ /* initialize expression tree search */
 
-       NODE *p;
+       register NODE *p;
 
        for( p=node; p<= &node[TREESZ-1]; ++p ) p->in.op = FREE;
        lastfree = node;
 
        for( p=node; p<= &node[TREESZ-1]; ++p ) p->in.op = FREE;
        lastfree = node;
@@ -97,7 +97,7 @@ tinit(){ /* initialize expression tree search */
 
 NODE *
 talloc(){
 
 NODE *
 talloc(){
-       NODE *p, *q;
+       register NODE *p, *q;
 
        q = lastfree;
        for( p = TNEXT(q); p!=q; p= TNEXT(p))
 
        q = lastfree;
        for( p = TNEXT(q); p!=q; p= TNEXT(p))
@@ -109,7 +109,7 @@ talloc(){
 
 tcheck(){ /* ensure that all nodes have been freed */
 
 
 tcheck(){ /* ensure that all nodes have been freed */
 
-       NODE *p;
+       register NODE *p;
 
        if( !nerrors )
                for( p=node; p<= &node[TREESZ-1]; ++p )
 
        if( !nerrors )
                for( p=node; p<= &node[TREESZ-1]; ++p )
@@ -157,6 +157,7 @@ fwalk( t, f, down ) register NODE *t; int (*f)(); {
                }
        }
 
                }
        }
 
+#ifndef vax
 walkf( t, f ) register NODE *t;  int (*f)(); {
        register opty;
 
 walkf( t, f ) register NODE *t;  int (*f)(); {
        register opty;
 
@@ -166,6 +167,46 @@ walkf( t, f ) register NODE *t;  int (*f)(); {
        if( opty == BITYPE ) walkf( t->in.right, f );
        (*f)( t );
        }
        if( opty == BITYPE ) walkf( t->in.right, f );
        (*f)( t );
        }
+#else
+#define        NR      100
+
+/*
+ * Deliberately avoids recursion -- use this version on machines with
+ * expensive procedure calls.
+ */
+walkf(t, f)
+       register NODE *t;
+       register int (*f)();
+{
+       register int i = 1;
+       register int opty = optype(t->in.op);
+       static NODE *at[NR];
+       static int ao[NR];
+
+#define        PUSH(dir, state) \
+       (ao[i] = state, at[i++] = t, t = t->in.dir, opty = optype(t->in.op))
+#define        POP() \
+       (opty = ao[--i], t = at[i])
+
+       do {
+               switch (opty) {
+               case LTYPE:     (*f)(t); POP(); break;
+               case UTYPE:     PUSH(left, LTYPE); break;
+               case BITYPE:    PUSH(left, BITYPE+1); break;
+               case BITYPE+1:  PUSH(right, LTYPE); break;
+               default:
+                       cerror("bad op type in walkf");
+               }
+               if (i >= NR) {
+                       walkf(t, f);
+                       POP();
+               }
+       } while (i > 0);
+}
+#undef NR
+#undef PUSH
+#undef POP
+#endif
 
 
 
 
 
 
index bbb2f2f..f4e98c8 100644 (file)
@@ -1,4 +1,4 @@
-/*     config.h        4.2     85/04/08        */
+/*     config.h        4.3     85/08/22        */
 
 #ifndef _CONFIG_
 #define        _CONFIG_
 
 #ifndef _CONFIG_
 #define        _CONFIG_
@@ -28,6 +28,7 @@
 #define SWITSZ         500             /* switch table size */
 #define        DELAYS          20              /* delayed evaluation table size */
 #define NRECUR         (10*TREESZ)     /* maximum eval recursion depth */
 #define SWITSZ         500             /* switch table size */
 #define        DELAYS          20              /* delayed evaluation table size */
 #define NRECUR         (10*TREESZ)     /* maximum eval recursion depth */
+#define        MAXSCOPES       (SYMTSZ/30)     /* maximum active scopes */
 
 /* in case anyone still uses fixed length names */
 #ifndef FLEXNAMES
 
 /* in case anyone still uses fixed length names */
 #ifndef FLEXNAMES
index 0f66adb..60111fe 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char *sccsid ="@(#)fort.c       4.6 (Berkeley) %G%";
+static char *sccsid ="@(#)fort.c       4.7 (Berkeley) %G%";
 #endif lint
 
 # ifndef FORT
 #endif lint
 
 # ifndef FORT
@@ -24,6 +24,18 @@ static char *sccsid ="@(#)fort.c     4.6 (Berkeley) %G%";
 # define REST(x) (((x)>>16)&0177777)
 # endif
 
 # define REST(x) (((x)>>16)&0177777)
 # endif
 
+# ifndef FIXINT
+# if SZINT == SZLONG
+# define FIXINT(x) ((x) == LONG || (x) == ULONG ? (x) - 1 : (x))
+# else
+# if SZINT == SZSHORT
+# define FIXINT(x) ((x) == SHORT || (x) == USHORT ? (x) + 1 : (x))
+# else
+# define FIXINT(x) (x)
+# endif
+# endif
+# endif
+
 FILE * lrd;  /* for default reading routines */
 
 # ifndef NOLNREAD
 FILE * lrd;  /* for default reading routines */
 
 # ifndef NOLNREAD
@@ -169,7 +181,7 @@ mainp2( argc, argv ) char *argv[]; {
                case ICON:
                        p = talloc();
                        p->in.op = ICON;
                case ICON:
                        p = talloc();
                        p->in.op = ICON;
-                       p->in.type = REST(x);
+                       p->in.type = FIXINT(REST(x));
                        p->tn.rval = 0;
                        p->tn.lval = lread();
                        if( VAL(x) ){
                        p->tn.rval = 0;
                        p->tn.lval = lread();
                        if( VAL(x) ){
@@ -195,7 +207,7 @@ mainp2( argc, argv ) char *argv[]; {
                case NAME:
                        p = talloc();
                        p->in.op = NAME;
                case NAME:
                        p = talloc();
                        p->in.op = NAME;
-                       p->in.type = REST(x);
+                       p->in.type = FIXINT(REST(x));
                        p->tn.rval = 0;
                        if( VAL(x) ) p->tn.lval = lread();
                        else p->tn.lval = 0;
                        p->tn.rval = 0;
                        if( VAL(x) ) p->tn.lval = lread();
                        else p->tn.lval = 0;
@@ -209,8 +221,9 @@ mainp2( argc, argv ) char *argv[]; {
                case OREG:
                        p = talloc();
                        p->in.op = OREG;
                case OREG:
                        p = talloc();
                        p->in.op = OREG;
-                       p->in.type = REST(x);
+                       p->in.type = FIXINT(REST(x));
                        p->tn.rval = VAL(x);
                        p->tn.rval = VAL(x);
+                       rbusy( p->tn.rval, PTR | p->in.type );
                        p->tn.lval = lread();
 #ifndef FLEXNAMES
                        lcread( p->in.name, 2 );
                        p->tn.lval = lread();
 #ifndef FLEXNAMES
                        lcread( p->in.name, 2 );
@@ -222,7 +235,7 @@ mainp2( argc, argv ) char *argv[]; {
                case REG:
                        p = talloc();
                        p->in.op = REG;
                case REG:
                        p = talloc();
                        p->in.op = REG;
-                       p->in.type = REST(x);
+                       p->in.type = FIXINT(REST(x));
                        p->tn.rval = VAL(x);
                        rbusy( p->tn.rval, p->in.type );
                        p->tn.lval = 0;
                        p->tn.rval = VAL(x);
                        rbusy( p->tn.rval, p->in.type );
                        p->tn.lval = 0;
@@ -287,7 +300,7 @@ mainp2( argc, argv ) char *argv[]; {
                        p = talloc();
                defa:
                        p->in.op = FOP(x);
                        p = talloc();
                defa:
                        p->in.op = FOP(x);
-                       p->in.type = REST(x);
+                       p->in.type = FIXINT(REST(x));
 
                        switch( optype( p->in.op ) ){
 
 
                        switch( optype( p->in.op ) ){
 
index 7579cc9..77eaddd 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char *sccsid ="@(#)match.c      4.3 (Berkeley) %G%";
+static char *sccsid ="@(#)match.c      4.4 (Berkeley) %G%";
 #endif lint
 
 # include "pass2.h"
 #endif lint
 
 # include "pass2.h"
@@ -50,7 +50,9 @@ tshape( p, shape ) NODE *p; {
 
 # ifndef BUG3
        if( sdebug ){
 
 # ifndef BUG3
        if( sdebug ){
-               printf( "tshape( %o, %o), op = %d\n", p, shape, o );
+               printf( "tshape( %o, ", p );
+               prcook( shape );
+               printf( " ) op = %s\n", opst[o] );
                }
 # endif
 
                }
 # endif
 
index 52ffd0a..763a5d4 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char *sccsid ="@(#)optim.c      4.5 (Berkeley) %G%";
+static char *sccsid ="@(#)optim.c      4.6 (Berkeley) %G%";
 #endif lint
 
 # include "pass1.h"
 #endif lint
 
 # include "pass1.h"
@@ -12,6 +12,9 @@ static char *sccsid ="@(#)optim.c     4.5 (Berkeley) %G%";
 # define LO(p) p->in.left->in.op
 # define LV(p) p->in.left->tn.lval
 
 # define LO(p) p->in.left->in.op
 # define LV(p) p->in.left->tn.lval
 
+       /* is p a constant without a name */
+# define nncon(p)      ((p)->in.op == ICON && (p)->tn.rval == NONAME)
+
 int oflag = 0;
 
 NODE *
 int oflag = 0;
 
 NODE *
@@ -106,32 +109,45 @@ optim(p) register NODE *p; {
                        p->in.right = t3;
                        }
                if(o == PLUS && LO(p) == MINUS && RCON(p) && RCON(p->in.left) &&
                        p->in.right = t3;
                        }
                if(o == PLUS && LO(p) == MINUS && RCON(p) && RCON(p->in.left) &&
-                 conval(p->in.right, MINUS, p->in.left->in.right)){
+                  conval(p->in.right, MINUS, p->in.left->in.right)){
                        zapleft:
                        RO(p->in.left) = FREE;
                        LO(p) = FREE;
                        p->in.left = p->in.left->in.left;
                }
                        zapleft:
                        RO(p->in.left) = FREE;
                        LO(p) = FREE;
                        p->in.left = p->in.left->in.left;
                }
-               if( RCON(p) && LO(p)==o && RCON(p->in.left) && conval( p->in.right, o, p->in.left->in.right ) ){
+               if( RCON(p) && LO(p)==o && RCON(p->in.left) &&
+                   conval( p->in.right, o, p->in.left->in.right ) ){
                        goto zapleft;
                        }
                        goto zapleft;
                        }
-               else if( LCON(p) && RCON(p) && conval( p->in.left, o, p->in.right ) ){
+               else if( LCON(p) && RCON(p) &&
+                        conval( p->in.left, o, p->in.right ) ){
                        zapright:
                        RO(p) = FREE;
                        p->in.left = makety( p->in.left, p->in.type, p->fn.cdim, p->fn.csiz );
                        p->in.op = FREE;
                        return( clocal( p->in.left ) );
                        }
                        zapright:
                        RO(p) = FREE;
                        p->in.left = makety( p->in.left, p->in.type, p->fn.cdim, p->fn.csiz );
                        p->in.op = FREE;
                        return( clocal( p->in.left ) );
                        }
+               /* FALL THROUGH */
 
 
-               /* change muls to shifts */
+       case ASG MUL:
+               /* change muls to adds or shifts */
 
 
-               if( o==MUL && nncon(p->in.right) && (i=ispow2(RV(p)))>=0){
-                       if( i == 0 ){ /* multiplication by 1 */
+               if( (o == MUL || o == ASG MUL) &&
+                   nncon(p->in.right) && (i=ispow2(RV(p)))>=0){
+                       if( i == 0 ) /* multiplication by 1 */
                                goto zapright;
                                goto zapright;
+                       if( i == 1 && optype(LO(p)) == LTYPE){
+                               /* multiplication by 2 */
+                               p->in.op = (asgop(o) ? ASG PLUS : PLUS);
+                               o = p->in.op;
+                               ncopy(p->in.right, p->in.left);
+                               }
+                       else {
+                               p->in.op = (asgop(o) ? ASG LS : LS);
+                               o = p->in.op;
+                               p->in.right->in.type = p->in.right->fn.csiz = INT;
+                               RV(p) = i;
                                }
                                }
-                       o = p->in.op = LS;
-                       p->in.right->in.type = p->in.right->fn.csiz = INT;
-                       RV(p) = i;
                        }
 
                /* change +'s of negative consts back to - */
                        }
 
                /* change +'s of negative consts back to - */
@@ -139,31 +155,73 @@ optim(p) register NODE *p; {
                        RV(p) = -RV(p);
                        o = p->in.op = MINUS;
                        }
                        RV(p) = -RV(p);
                        o = p->in.op = MINUS;
                        }
-               /*FALLTHROUGH*/
+               /* FALL THROUGH */
+       case ASG AND:
+       case ASG PLUS:
+       case ASG MINUS:
        case RS:
        case LS:
        case RS:
        case LS:
-               /* Operations with zero -- DAS 1/20/85 */
-               if( (o==PLUS || o==MINUS || o==OR || o==ER || o==LS || o==RS)
-                   && nncon(p->in.right) && RV(p)==0 ) goto zapright;
-                       break;
+               /* Operations with zero */
+               if( nncon(p->in.right) && RV(p) == 0 ) {
+                       if( o == MUL || o == ASG MUL ||
+                           o == AND || o == ASG AND ) {
+                               if( asgop(o) )
+                                       p->in.op = ASSIGN;
+                               else if( optype(LO(p)) == LTYPE ) {
+                                       p->in.op = FREE;
+                                       LO(p) = FREE;
+                                       p = p->in.right;
+                                       }
+                               else
+                                       p->in.op = COMOP; /* side effects */
+                               }
+                       else if( o == PLUS || o == MINUS ||
+                                o == ASG PLUS || o == ASG MINUS ||
+                                o == OR || o == ER ||
+                                o == LS || o == RS )
+                               goto zapright;
+                       }
+               break;
 
 
+       case ASG DIV:
        case DIV:
        case DIV:
-               if( nncon( p->in.right ) && p->in.right->tn.lval == 1 ) goto zapright;
-               /* Unsigned division by a power of two -- DAS 1/13/85 */
-               if( nncon(p->in.right) && (i=ispow2(RV(p)))>=0 &&
-                   ISUNSIGNED(p->in.type) ){
-                       o = p->in.op = RS;
-                       p->in.right->in.type = p->in.right->fn.csiz = INT;
-                       RV(p) = i;
+               if( nncon( p->in.right ) ){
+                       if( RV(p) == 0 ) uerror("division by zero");
+                       else if( RV(p) == 1 ) goto zapright;
+                       /* Unsigned division by a power of two */
+                       else if( (i=ispow2(RV(p)))>=0 &&
+                                (ISUNSIGNED(p->in.left->in.type) ||
+                                 ISUNSIGNED(p->in.right->in.type)) ){
+                               p->in.op = (asgop(o) ? ASG RS : RS);
+                               p->in.right->in.type = p->in.right->fn.csiz = INT;
+                               RV(p) = i;
+                               }
                        }
                break;
 
                        }
                break;
 
+       case ASG MOD:
        case MOD:
        case MOD:
-               /* Unsigned mod by a power of two -- DAS 1/13/85 */
-               if( nncon(p->in.right) && (i=ispow2(RV(p)))>=0 &&
-                   ISUNSIGNED(p->in.type) ){
-                       o = p->in.op = AND;
-                       RV(p)--;
+               if( nncon(p->in.right) ){
+                       if( RV(p) == 0 ) uerror("modulus of zero");
+                       else if( RV(p) == 1 ){ /* mod by one gives zero */
+                               RV(p) = 0;
+                               if( asgop(o) )
+                                       p->in.op = ASSIGN;
+                               else if( optype(LO(p)) == LTYPE ) {
+                                       p->in.op = FREE;
+                                       LO(p) = FREE;
+                                       p = p->in.right;
+                                       }
+                               else
+                                       p->in.op = COMOP; /* side effects */
+                               }
+                       else if ((i=ispow2(RV(p)))>=0 &&
+                                (ISUNSIGNED(p->in.left->in.type) ||
+                                 ISUNSIGNED(p->in.right->in.type)) ){
+                               /* Unsigned mod by a power of two */
+                               p->in.op = (asgop(o) ? ASG AND : AND);
+                               RV(p)--;
+                               }
                        }
                break;
 
                        }
                break;
 
@@ -198,8 +256,3 @@ ispow2( c ) CONSZ c; {
        for( i=0; c>1; ++i) c >>= 1;
        return(i);
        }
        for( i=0; c>1; ++i) c >>= 1;
        return(i);
        }
-
-nncon( p ) NODE *p; {
-       /* is p a constant without a name */
-       return( p->in.op == ICON && p->tn.rval == NONAME );
-       }
index 5c81f0e..3526d4b 100644 (file)
@@ -1,4 +1,4 @@
-/*     pass1.h 4.1     85/03/19        */
+/*     pass1.h 4.2     85/08/22        */
 
 #ifndef _PASS1_
 #define        _PASS1_
 
 #ifndef _PASS1_
 #define        _PASS1_
@@ -8,6 +8,10 @@
 
 /*
  * Symbol table definition.
 
 /*
  * Symbol table definition.
+ *
+ * Colliding entries are moved down with a standard
+ * probe (no quadratic rehash here) and moved back when
+ * entries are cleared.
  */
 struct symtab {
 #ifndef FLEXNAMES
  */
 struct symtab {
 #ifndef FLEXNAMES
@@ -15,6 +19,7 @@ struct        symtab {
 #else
        char    *sname;
 #endif
 #else
        char    *sname;
 #endif
+       struct  symtab *snext;  /* link to other symbols in the same scope */
        TWORD   stype;          /* type word */
        char    sclass;         /* storage class */
        char    slevel;         /* scope level */
        TWORD   stype;          /* type word */
        char    sclass;         /* storage class */
        char    slevel;         /* scope level */
@@ -22,7 +27,7 @@ struct        symtab {
        int     offset;         /* offset or value */
        short   dimoff;         /* offset into the dimension table */
        short   sizoff;         /* offset into the size table */
        int     offset;         /* offset or value */
        short   dimoff;         /* offset into the dimension table */
        short   sizoff;         /* offset into the size table */
-       short   suse;           /* line number of last use of the variable */
+       int     suse;           /* line number of last use of the variable */
 };
 
 /*
 };
 
 /*
index aaea85d..09217dd 100644 (file)
@@ -1,11 +1,14 @@
 #ifndef lint
 #ifndef lint
-static char *sccsid ="@(#)pftn.c       1.8 (Berkeley) %G%";
+static char *sccsid ="@(#)pftn.c       1.9 (Berkeley) %G%";
 #endif lint
 
 # include "pass1.h"
 
 unsigned int offsz;
 
 #endif lint
 
 # include "pass1.h"
 
 unsigned int offsz;
 
+struct symtab *schain[MAXSCOPES];      /* sym chains for clearst */
+int chaintop;                          /* highest active entry */
+
 struct instk {
        int in_sz;   /* size of array element */
        int in_x;    /* current index for structure member in structure initializations */
 struct instk {
        int in_sz;   /* size of array element */
        int in_x;    /* current index for structure member in structure initializations */
@@ -30,12 +33,12 @@ int ddebug = 0;
 
 struct symtab * mknonuniq();
 
 
 struct symtab * mknonuniq();
 
-defid( q, class )  NODE *q; {
+defid( q, class ) register NODE *q; register int class; {
        register struct symtab *p;
        int idp;
        register struct symtab *p;
        int idp;
-       TWORD type;
+       register TWORD type;
        TWORD stp;
        TWORD stp;
-       int scl;
+       register int scl;
        int dsym, ddef;
        int slev, temp;
        int changed;
        int dsym, ddef;
        int slev, temp;
        int changed;
@@ -247,7 +250,7 @@ defid( q, class )  NODE *q; {
        /* allow nonunique structure/union member names */
 
        if( class==MOU || class==MOS || class & FIELD ){/* make a new entry */
        /* allow nonunique structure/union member names */
 
        if( class==MOU || class==MOS || class & FIELD ){/* make a new entry */
-               int * memp;
+               register int *memp;
                p->sflags |= SNONUNIQ;  /* old entry is nonunique */
                /* determine if name has occurred in this structure/union */
                if (paramno > 0) for( memp = &paramstk[paramno-1];
                p->sflags |= SNONUNIQ;  /* old entry is nonunique */
                /* determine if name has occurred in this structure/union */
                if (paramno > 0) for( memp = &paramstk[paramno-1];
@@ -370,6 +373,18 @@ defid( q, class )  NODE *q; {
                break;
                }
 
                break;
                }
 
+       {
+               register int l = p->slevel;
+
+               if( l >= MAXSCOPES )
+                       cerror( "scopes nested too deep" );
+
+               p->snext = schain[l];
+               schain[l] = p;
+               if( l >= chaintop )
+                       chaintop = l + 1;
+               }
+
        /* user-supplied routine to fix up new definitions */
 
        FIXDEF(p);
        /* user-supplied routine to fix up new definitions */
 
        FIXDEF(p);
@@ -1356,7 +1371,7 @@ nidcl( p ) NODE *p; { /* handle unitialized declarations */
        defid( p, class );
 
 #ifndef LCOMM
        defid( p, class );
 
 #ifndef LCOMM
-       if( class==EXTDEF || class==STATIC ){
+       if( class==EXTDEF || class==STATIC )
 #else
        if (class==STATIC) {
                register struct symtab *s = &stab[p->tn.rval];
 #else
        if (class==STATIC) {
                register struct symtab *s = &stab[p->tn.rval];
@@ -1370,8 +1385,9 @@ nidcl( p ) NODE *p; { /* handle unitialized declarations */
                        printf("        .lcomm  L%d,%d\n", s->offset, sz);
                else
                        printf("        .lcomm  %s,%d\n", exname(s->sname), sz);
                        printf("        .lcomm  L%d,%d\n", s->offset, sz);
                else
                        printf("        .lcomm  %s,%d\n", exname(s->sname), sz);
-       }else if (class == EXTDEF) {
+       }else if (class == EXTDEF)
 #endif
 #endif
+               {
                /* simulate initialization by 0 */
                beginit(p->tn.rval);
                endinit();
                /* simulate initialization by 0 */
                beginit(p->tn.rval);
                endinit();
@@ -1809,34 +1825,27 @@ relook(p) register struct symtab *p; {  /* look up p again, and see where it lie
        return(q);
        }
 
        return(q);
        }
 
-clearst( lev ){ /* clear entries of internal scope  from the symbol table */
-       register struct symtab *p, *q, *r;
-       register int temp, rehash;
+clearst( lev ) register int lev; {
+       register struct symtab *p, *q;
+       register int temp;
+       struct symtab *clist = 0;
 
        temp = lineno;
        aobeg();
 
 
        temp = lineno;
        aobeg();
 
-       /* first, find an empty slot to prevent newly hashed entries from
-          being slopped into... */
-
-       for( q=stab; q< &stab[SYMTSZ]; ++q ){
-               if( q->stype == TNULL )goto search;
-               }
-
-       cerror( "symbol table full");
-
-       search:
-       p = q;
-
-       for(;;){
-               if( p->stype == TNULL ) {
-                       rehash = 0;
-                       goto next;
-                       }
-               lineno = p->suse;
-               if( lineno < 0 ) lineno = - lineno;
-               if( p->slevel>lev ){ /* must clobber */
-                       if( p->stype == UNDEF || ( p->sclass == ULABEL && lev < 2 ) ){
+       /* step 1: remove entries */
+       while( chaintop-1 > lev ){
+               register int type;
+
+               p = schain[--chaintop];
+               schain[chaintop] = 0;
+               for( ; p; p = q ){
+                       q = p->snext;
+                       type = p->stype;
+                       if( p->stype == TNULL || p->slevel <= lev )
+                               cerror( "schain botch" );
+                       lineno = p->suse < 0 ? -p->suse : p->suse;
+                       if( p->stype==UNDEF || ( p->sclass==ULABEL && lev<2 ) ){
                                lineno = temp;
 #ifndef FLEXNAMES
                                uerror( "%.8s undefined", p->sname );
                                lineno = temp;
 #ifndef FLEXNAMES
                                uerror( "%.8s undefined", p->sname );
@@ -1846,53 +1855,44 @@ clearst( lev ){ /* clear entries of internal scope  from the symbol table */
                                }
                        else aocode(p);
 # ifndef BUG1
                                }
                        else aocode(p);
 # ifndef BUG1
+                       if( ddebug ){
 #ifndef FLEXNAMES
 #ifndef FLEXNAMES
-                       if (ddebug) printf("removing %8s from stab[ %d], flags %o level %d\n",
+                               printf( "removing %.8s", p->sname );
 #else
 #else
-                       if (ddebug) printf("removing %s from stab[ %d], flags %o level %d\n",
+                               printf( "removing %s", p->sname );
 #endif
 #endif
-                               p->sname,p-stab,p->sflags,p->slevel);
+                               printf( " from stab[%d], flags %o level %d\n",
+                                       p-stab, p->sflags, p->slevel);
+                               }
 # endif
 # endif
-                       if( p->sflags & SHIDES ) unhide(p);
+                       if( p->sflags & SHIDES )unhide( p );
                        p->stype = TNULL;
                        p->stype = TNULL;
-                       rehash = 1;
-                       goto next;
+                       p->snext = clist;
+                       clist = p;
                        }
                        }
-               if( rehash ){
-                       if( (r=relook(p)) != p ){
-                               movestab( r, p );
-                               p->stype = TNULL;
+               }
+
+       /* step 2: fix any mishashed entries */
+       p = clist;
+       while( p ){
+               register struct symtab *r;
+
+               q = p;
+               for(;;){
+                       if( ++q >= &stab[SYMTSZ] )q = stab;
+                       if( q == p || q->stype == TNULL )break;
+                       if( (r = relook(q)) != q ) {
+                               *r = *q;
+                               q->stype = NULL;
                                }
                        }
                                }
                        }
-               next:
-               if( ++p >= &stab[SYMTSZ] ) p = stab;
-               if( p == q ) break;
+               p = p->snext;
                }
                }
+
        lineno = temp;
        aoend();
        }
 
        lineno = temp;
        aoend();
        }
 
-movestab( p, q ) register struct symtab *p, *q; {
-       int k;
-       /* structure assignment: *p = *q; */
-       p->stype = q->stype;
-       p->sclass = q->sclass;
-       p->slevel = q->slevel;
-       p->offset = q->offset;
-       p->sflags = q->sflags;
-       p->dimoff = q->dimoff;
-       p->sizoff = q->sizoff;
-       p->suse = q->suse;
-#ifndef FLEXNAMES
-       for( k=0; k<NCHNAM; ++k ){
-               p->sname[k] = q->sname[k];
-               }
-#else
-       p->sname = q->sname;
-#endif
-       }
-
-
 hide( p ) register struct symtab *p; {
        register struct symtab *q;
        for( q=p+1; ; ++q ){
 hide( p ) register struct symtab *p; {
        register struct symtab *q;
        for( q=p+1; ; ++q ){
@@ -1900,7 +1900,7 @@ hide( p ) register struct symtab *p; {
                if( q == p ) cerror( "symbol table full" );
                if( q->stype == TNULL ) break;
                }
                if( q == p ) cerror( "symbol table full" );
                if( q->stype == TNULL ) break;
                }
-       movestab( q, p );
+       *q = *p;
        p->sflags |= SHIDDEN;
        q->sflags = (p->sflags&(SMOS|STAG)) | SHIDES;
 #ifndef FLEXNAMES
        p->sflags |= SHIDDEN;
        q->sflags = (p->sflags&(SMOS|STAG)) | SHIDES;
 #ifndef FLEXNAMES
index 41ccda0..c8e3076 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char *sccsid ="@(#)reader.c     4.3 (Berkeley) %G%";
+static char *sccsid ="@(#)reader.c     4.4 (Berkeley) %G%";
 #endif lint
 
 # include "pass2.h"
 #endif lint
 
 # include "pass2.h"
@@ -344,7 +344,7 @@ delay2( p ) register NODE *p; {
        case UNARY FORTCALL:
        case COMOP:
        case CBRANCH:
        case UNARY FORTCALL:
        case COMOP:
        case CBRANCH:
-               /* for the moment, don7t delay past a conditional context, or
+               /* for the moment, don't delay past a conditional context, or
                /* inside of a call */
                return;
 
                /* inside of a call */
                return;
 
@@ -438,6 +438,9 @@ prcook( cookie ){
                if( cookie == SZERO ) printf( "SZERO" );
                else if( cookie == SONE ) printf( "SONE" );
                else if( cookie == SMONE ) printf( "SMONE" );
                if( cookie == SZERO ) printf( "SZERO" );
                else if( cookie == SONE ) printf( "SONE" );
                else if( cookie == SMONE ) printf( "SMONE" );
+               else if( cookie == SCCON ) printf( "SCCON" );
+               else if( cookie == SSCON ) printf( "SSCON" );
+               else if( cookie == SSOREG ) printf( "SSOREG" );
                else printf( "SPECIAL+%d", cookie & ~SPECIAL );
                return;
                }
                else printf( "SPECIAL+%d", cookie & ~SPECIAL );
                return;
                }
index 6f9ab12..2368889 100644 (file)
@@ -1,11 +1,13 @@
 #ifndef lint
 #ifndef lint
-static char *sccsid ="@(#)scan.c       1.6 (Berkeley) %G%";
+static char *sccsid ="@(#)scan.c       1.7 (Berkeley) %G%";
 #endif lint
 
 # include "pass1.h"
 # include <a.out.h>
 # include <stab.h>
 # include <ctype.h>
 #endif lint
 
 # include "pass1.h"
 # include <a.out.h>
 # include <stab.h>
 # include <ctype.h>
+# include <signal.h>
+
        /* temporarily */
 
 int asm_esc = 0; /* asm escaped used in file */
        /* temporarily */
 
 int asm_esc = 0; /* asm escaped used in file */
@@ -61,6 +63,8 @@ char * lxgcp;
 
 extern int proflg;
 extern int gdebug;
 
 extern int proflg;
 extern int gdebug;
+extern int fpe();
+struct sigvec fpe_sigvec;
 int oldway;            /* allocate storage so lint will compile as well */
 #ifndef LINT
 extern int lastloc;
 int oldway;            /* allocate storage so lint will compile as well */
 #ifndef LINT
 extern int lastloc;
@@ -168,6 +172,9 @@ mainp1( argc, argv ) int argc; char *argv[]; {  /* control multiple files */
        curdim = 16;
        reached = 1;
 
        curdim = 16;
        reached = 1;
 
+       fpe_sigvec.sv_handler = fpe;
+       (void) sigvec(SIGFPE, &fpe_sigvec, (struct sigvec *) NULL);
+
        yyparse();
        yyaccpt();
 
        yyparse();
        yyaccpt();
 
index cc9c007..79fa310 100644 (file)
@@ -1,9 +1,11 @@
 #ifndef lint
 #ifndef lint
-static char *sccsid ="@(#)trees.c      4.8 (Berkeley) %G%";
+static char *sccsid ="@(#)trees.c      4.9 (Berkeley) %G%";
 #endif
 
 # include "pass1.h"
 
 #endif
 
 # include "pass1.h"
 
+# include <setjmp.h>
+
 int bdebug = 0;
 int adebug = 0;
 extern ddebug;
 int bdebug = 0;
 int adebug = 0;
 extern ddebug;
@@ -172,84 +174,59 @@ buildtree( o, l, r ) register NODE *l, *r; {
                        break;
                        }
                }
                        break;
                        }
                }
-       else if (opty == BITYPE) {
-               if ((l->in.op == FCON || l->in.op == ICON) &&
-                   (r->in.op == FCON || r->in.op == ICON))
-                       switch (o) {
-
-                       case PLUS:
-                       case MINUS:
-                       case MUL:
-                       case DIV:
-                               if (l->in.op == ICON)
-                                       l->fpn.fval = l->tn.lval;
-                               if (r->in.op == ICON)
-                                       r->fpn.fval = r->tn.lval;
-                               l->in.op = FCON;
-                               l->in.type = l->fn.csiz = FLOAT;
-                               r->in.op = FREE;
-                               switch (o) {
-
-                               case PLUS:
-                                       l->fpn.fval += r->fpn.fval;
-                                       return (l);
-
-                               case MINUS:
-                                       l->fpn.fval -= r->fpn.fval;
-                                       return (l);
-
-                               case MUL:
-                                       l->fpn.fval *= r->fpn.fval;
-                                       return (l);
-
-                               case DIV:
-                                       if (r->fpn.fval == 0)
-                                               uerror("division by 0.");
-                                       else
-                                               l->fpn.fval /= r->fpn.fval;
-                                       return (l);
-                               }
-                       }
-               else if ((l->in.op == DCON || l->in.op == ICON) &&
-                   (r->in.op == DCON || r->in.op == ICON))
-                       switch (o) {
-
-                       case PLUS:
-                       case MINUS:
-                       case MUL:
-                       case DIV:
+       else if (opty == BITYPE &&
+               (l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) &&
+               (r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) {
+                       if (o == PLUS || o == MINUS || o == MUL || o == DIV) {
+                               extern int fpe_count;
+                               extern jmp_buf gotfpe;
+
+                               fpe_count = 0;
+                               if (setjmp(gotfpe))
+                                       goto treatfpe;
                                if (l->in.op == ICON)
                                        l->dpn.dval = l->tn.lval;
                                if (l->in.op == ICON)
                                        l->dpn.dval = l->tn.lval;
+                               else if (l->in.op == FCON)
+                                       l->dpn.dval = l->fpn.fval;
                                if (r->in.op == ICON)
                                        r->dpn.dval = r->tn.lval;
                                if (r->in.op == ICON)
                                        r->dpn.dval = r->tn.lval;
-                               l->in.op = DCON;
-                               l->in.type = l->fn.csiz = DOUBLE;
-                               r->in.op = FREE;
+                               else if (r->in.op == FCON)
+                                       r->dpn.dval = r->fpn.fval;
                                switch (o) {
 
                                case PLUS:
                                        l->dpn.dval += r->dpn.dval;
                                switch (o) {
 
                                case PLUS:
                                        l->dpn.dval += r->dpn.dval;
-                                       return (l);
+                                       break;
 
                                case MINUS:
                                        l->dpn.dval -= r->dpn.dval;
 
                                case MINUS:
                                        l->dpn.dval -= r->dpn.dval;
-                                       return (l);
+                                       break;
 
                                case MUL:
                                        l->dpn.dval *= r->dpn.dval;
 
                                case MUL:
                                        l->dpn.dval *= r->dpn.dval;
-                                       return (l);
+                                       break;
 
                                case DIV:
                                        if (r->dpn.dval == 0)
                                                uerror("division by 0.");
                                        else
                                                l->dpn.dval /= r->dpn.dval;
 
                                case DIV:
                                        if (r->dpn.dval == 0)
                                                uerror("division by 0.");
                                        else
                                                l->dpn.dval /= r->dpn.dval;
-                                       return (l);
-                               }
+                                       break;
+                                       }
+                       treatfpe:
+                               if (fpe_count > 0) {
+                                       uerror("floating point exception in constant expression");
+                                       l->dpn.dval = 1.0; /* Fairly harmless */
+                                       }
+                               fpe_count = -1;
+                               l->in.op = DCON;
+                               l->in.type = l->fn.csiz = DOUBLE;
+                               r->in.op = FREE;
+                               return (l);
                        }
                        }
-       }
+               }
 
 
-       /* its real; we must make a new node */
+       /* it's real; we must make a new node */
 
        p = block( o, l, r, INT, 0, INT );
 
 
        p = block( o, l, r, INT, 0, INT );
 
@@ -587,6 +564,16 @@ buildtree( o, l, r ) register NODE *l, *r; {
 
        }
 
 
        }
 
+int fpe_count = -1;
+jmp_buf gotfpe;
+
+fpe() {
+       if (fpe_count < 0)
+               cerror("floating point exception");
+       ++fpe_count;
+       longjmp(gotfpe, 1);
+       }
+
 /*
  * Rewrite arguments in a function call.
  * Structure arguments are massaged, single
 /*
  * Rewrite arguments in a function call.
  * Structure arguments are massaged, single
@@ -1301,21 +1288,35 @@ icons(p) register NODE *p; {
 # define MPTR 010  /* pointer */
 # define MPTI 020  /* pointer or integer */
 # define MENU 040 /* enumeration variable or member */
 # define MPTR 010  /* pointer */
 # define MPTI 020  /* pointer or integer */
 # define MENU 040 /* enumeration variable or member */
+# define MVOID 0100000 /* void type */
 
 opact( p )  NODE *p; {
 
        register mt12, mt1, mt2, o;
 
 
 opact( p )  NODE *p; {
 
        register mt12, mt1, mt2, o;
 
-       mt12 = 0;
+       mt1 = mt2 = mt12 = 0;
 
        switch( optype(o=p->in.op) ){
 
        case BITYPE:
 
        switch( optype(o=p->in.op) ){
 
        case BITYPE:
-               mt12=mt2 = moditype( p->in.right->in.type );
+               mt2 = moditype( p->in.right->in.type );
        case UTYPE:
        case UTYPE:
-               mt12 &= (mt1 = moditype( p->in.left->in.type ));
+               mt1 = moditype( p->in.left->in.type );
+               break;
+
+               }
 
 
+       if( ((mt1 | mt2) & MVOID) &&
+           o != COMOP &&
+           !(o == CAST && (mt1 & MVOID)) ){
+               /* if lhs of RETURN is void, grammar will complain */
+               if( o != RETURN )
+                       uerror( "value of void expression used" );
+               return( NCVT );
                }
                }
+       mt1 &= ~MVOID;
+       mt2 &= ~MVOID;
+       mt12 = mt1 & mt2;
 
        switch( o ){
 
 
        switch( o ){
 
@@ -1449,7 +1450,10 @@ opact( p )  NODE *p; {
                else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
 
                }
                else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
 
                }
-       uerror( "operands of %s have incompatible types", opst[o] );
+       if( mt12 == MSTR )
+               uerror( "%s is not a permitted struct/union operation", opst[o] );
+       else
+               uerror( "operands of %s have incompatible types", opst[o] );
        return( NCVT );
        }
 
        return( NCVT );
        }
 
@@ -1460,7 +1464,7 @@ moditype( ty ) TWORD ty; {
        case TVOID:
                return( MPTR );
        case UNDEF:
        case TVOID:
                return( MPTR );
        case UNDEF:
-               return(0); /* type is void */
+               return( MVOID );
        case ENUMTY:
        case MOETY:
                return( MENU );
        case ENUMTY:
        case MOETY:
                return( MENU );