BSD 4_3 release
[unix-history] / usr / src / lib / mip / pftn.c
index c306090..87161c5 100644 (file)
@@ -1,8 +1,14 @@
-static char *sccsid ="%W% (Berkeley) %G%";
-# include "mfile1"
+#ifndef lint
+static char *sccsid ="@(#)pftn.c       1.12 (Berkeley) 4/21/86";
+#endif lint
+
+# include "pass1.h"
 
 unsigned int offsz;
 
 
 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 */
@@ -27,14 +33,15 @@ 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 dsym, ddef;
        int slev, temp;
+       int changed;
 
        if( q == NIL ) return;  /* an error was detected */
 
 
        if( q == NIL ) return;  /* an error was detected */
 
@@ -103,10 +110,14 @@ defid( q, class )  NODE *q; {
        /* test (and possibly adjust) dimensions */
        dsym = p->dimoff;
        ddef = q->fn.cdim;
        /* test (and possibly adjust) dimensions */
        dsym = p->dimoff;
        ddef = q->fn.cdim;
+       changed = 0;
        for( temp=type; temp&TMASK; temp = DECREF(temp) ){
                if( ISARY(temp) ){
        for( temp=type; temp&TMASK; temp = DECREF(temp) ){
                if( ISARY(temp) ){
-                       if( dimtab[dsym] == 0 ) dimtab[dsym] = dimtab[ddef];
-                       else if( dimtab[ddef]!=0 && dimtab[dsym] != dimtab[ddef] ){
+                       if (dimtab[dsym] == 0) {
+                               dimtab[dsym] = dimtab[ddef];
+                               changed = 1;
+                               }
+                       else if (dimtab[ddef]!=0&&dimtab[dsym]!=dimtab[ddef]) {
                                goto mismatch;
                                }
                        ++dsym;
                                goto mismatch;
                                }
                        ++dsym;
@@ -114,6 +125,10 @@ defid( q, class )  NODE *q; {
                        }
                }
 
                        }
                }
 
+       if (changed) {
+               FIXDEF(p);
+               }
+
        /* check that redeclarations are to the same structure */
        if( (temp==STRTY||temp==UNIONTY||temp==ENUMTY) && p->sizoff != q->fn.csiz
                 && class!=STNAME && class!=UNAME && class!=ENAME ){
        /* check that redeclarations are to the same structure */
        if( (temp==STRTY||temp==UNIONTY||temp==ENUMTY) && p->sizoff != q->fn.csiz
                 && class!=STNAME && class!=UNAME && class!=ENAME ){
@@ -235,13 +250,13 @@ 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 */
                p->sflags |= SNONUNIQ;  /* old entry is nonunique */
                /* determine if name has occurred in this structure/union */
-               for( memp = &paramstk[paramno-1];
+               if (paramno > 0) for( memp = &paramstk[paramno-1];
                        /* while */ *memp>=0 && stab[*memp].sclass != STNAME
                                && stab[*memp].sclass != UNAME;
                        /* while */ *memp>=0 && stab[*memp].sclass != STNAME
                                && stab[*memp].sclass != UNAME;
-                       /* iterate */ --memp){ char * cname, * oname;
+                       /* iterate */ --memp){ char *cname, *oname;
                        if( stab[*memp].sflags & SNONUNIQ ){int k;
                                cname=p->sname;
                                oname=stab[*memp].sname;
                        if( stab[*memp].sflags & SNONUNIQ ){int k;
                                cname=p->sname;
                                oname=stab[*memp].sname;
@@ -358,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);
@@ -740,7 +767,10 @@ tsize( ty, d, s )  TWORD ty; {
                }
 
        if( dimtab[s]==0 ) {
                }
 
        if( dimtab[s]==0 ) {
-               uerror( "unknown size");
+               if( ty == STRTY )
+                       uerror( "undefined structure" );
+               else
+                       uerror( "unknown size");
                return( SZINT );
                }
        return( (unsigned int) dimtab[ s ] * mult );
                return( SZINT );
                }
        return( (unsigned int) dimtab[ s ] * mult );
@@ -799,6 +829,8 @@ int idebug = 0;
 
 int ibseen = 0;  /* the number of } constructions which have been filled */
 
 
 int ibseen = 0;  /* the number of } constructions which have been filled */
 
+int ifull = 0; /* 1 if all initializers have been seen */
+
 int iclass;  /* storage class of thing being initialized */
 
 int ilocctr = 0;  /* location counter for current initialization */
 int iclass;  /* storage class of thing being initialized */
 
 int ilocctr = 0;  /* location counter for current initialization */
@@ -834,6 +866,7 @@ beginit(curid){
 
        inoff = 0;
        ibseen = 0;
 
        inoff = 0;
        ibseen = 0;
+       ifull = 0;
 
        pstk = 0;
 
 
        pstk = 0;
 
@@ -887,6 +920,11 @@ instk( id, t, d, s, off ) OFFSZ off; TWORD t; {
                        continue;
                        }
                else if( t == STRTY ){
                        continue;
                        }
                else if( t == STRTY ){
+                       if( dimtab[pstk->in_s] == 0 ){
+                               uerror( "can't initialize undefined structure" );
+                               iclass = -1;
+                               return;
+                               }
                        id = dimtab[pstk->in_x];
                        p = &stab[id];
                        if( p->sclass != MOS && !(p->sclass&FIELD) ) cerror( "insane structure member list" );
                        id = dimtab[pstk->in_x];
                        p = &stab[id];
                        if( p->sclass != MOS && !(p->sclass&FIELD) ) cerror( "insane structure member list" );
@@ -955,6 +993,7 @@ endinit(){
        case EXTERN:
        case AUTO:
        case REGISTER:
        case EXTERN:
        case AUTO:
        case REGISTER:
+       case -1:
                return;
                }
 
                return;
                }
 
@@ -978,6 +1017,7 @@ endinit(){
                if( d1!=0 && d1!=n ) uerror( "too many initializers");
                if( n==0 ) werror( "empty array declaration");
                dimtab[d] = n;
                if( d1!=0 && d1!=n ) uerror( "too many initializers");
                if( n==0 ) werror( "empty array declaration");
                dimtab[d] = n;
+               if( d1==0 ) FIXDEF(&stab[pstk->in_id]);
                }
 
        else if( t == STRTY || t == UNIONTY ){
                }
 
        else if( t == STRTY || t == UNIONTY ){
@@ -1003,6 +1043,7 @@ doinit( p ) register NODE *p; {
 
        register sz, d, s;
        register TWORD t;
 
        register sz, d, s;
        register TWORD t;
+       int o;
 
        /* note: size of an individual initializer is assumed to fit into an int */
 
 
        /* note: size of an individual initializer is assumed to fit into an int */
 
@@ -1025,6 +1066,11 @@ doinit( p ) register NODE *p; {
 
        if( p == NIL ) return;  /* for throwing away strings that have been turned into lists */
 
 
        if( p == NIL ) return;  /* for throwing away strings that have been turned into lists */
 
+       if( ifull ){
+               uerror( "too many initializers" );
+               iclass = -1;
+               goto leave;
+               }
        if( ibseen ){
                uerror( "} expected");
                goto leave;
        if( ibseen ){
                uerror( "} expected");
                goto leave;
@@ -1051,21 +1097,27 @@ doinit( p ) register NODE *p; {
        p->in.left = p->in.right;
        p->in.right = NIL;
        p->in.left = optim( p->in.left );
        p->in.left = p->in.right;
        p->in.right = NIL;
        p->in.left = optim( p->in.left );
-       if( p->in.left->in.op == UNARY AND ){
-               p->in.left->in.op = FREE;
+       o = p->in.left->in.op;
+       if( o == UNARY AND ){
+               o = p->in.left->in.op = FREE;
                p->in.left = p->in.left->in.left;
                }
        p->in.op = INIT;
 
        if( sz < SZINT ){ /* special case: bit fields, etc. */
                p->in.left = p->in.left->in.left;
                }
        p->in.op = INIT;
 
        if( sz < SZINT ){ /* special case: bit fields, etc. */
-               if( p->in.left->in.op != ICON ) uerror( "illegal initialization" );
+               if( o != ICON ) uerror( "illegal initialization" );
                else incode( p->in.left, sz );
                }
                else incode( p->in.left, sz );
                }
-       else if( p->in.left->in.op == FCON ){
-               fincode( p->in.left->fpn.dval, sz );
+       else if( o == FCON ){
+               fincode( p->in.left->fpn.fval, sz );
+               }
+       else if( o == DCON ){
+               fincode( p->in.left->dpn.dval, sz );
                }
        else {
                }
        else {
-               cinit( optim(p), sz );
+               p = optim(p);
+               if( p->in.left->in.op != ICON ) uerror( "illegal initialization" );
+               else cinit( p, sz );
                }
 
        gotscal();
                }
 
        gotscal();
@@ -1111,7 +1163,7 @@ gotscal(){
                        }
 
                }
                        }
 
                }
-
+       ifull = 1;
        }
 
 ilbrace(){ /* process an initializer's left brace */
        }
 
 ilbrace(){ /* process an initializer's left brace */
@@ -1163,6 +1215,7 @@ irbrace(){
                }
 
        /* these right braces match ignored left braces: throw out */
                }
 
        /* these right braces match ignored left braces: throw out */
+       ifull = 1;
 
        }
 
 
        }
 
@@ -1336,7 +1389,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];
@@ -1350,8 +1403,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();
@@ -1619,14 +1673,18 @@ fixclass( class, type ) TWORD type; {
                                uerror( "fortran function has wrong type" );
                                }
                        }
                                uerror( "fortran function has wrong type" );
                                }
                        }
-       case STNAME:
-       case UNAME:
-       case ENAME:
        case EXTERN:
        case STATIC:
        case EXTDEF:
        case TYPEDEF:
        case USTATIC:
        case EXTERN:
        case STATIC:
        case EXTDEF:
        case TYPEDEF:
        case USTATIC:
+               if( blevel == 1 ){
+                       uerror( "illegal class" );
+                       return( PARAM );
+                       }
+       case STNAME:
+       case UNAME:
+       case ENAME:
                return( class );
 
        default:
                return( class );
 
        default:
@@ -1785,34 +1843,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 );
@@ -1822,53 +1873,45 @@ 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, *next;
+
+               q = p;
+               next = p->snext;
+               for(;;){
+                       if( ++q >= &stab[SYMTSZ] )q = stab;
+                       if( q == p || q->stype == TNULL )break;
+                       if( (r = relook(q)) != q ) {
+                               *r = *q;
+                               q->stype = TNULL;
                                }
                        }
                                }
                        }
-               next:
-               if( ++p >= &stab[SYMTSZ] ) p = stab;
-               if( p == q ) break;
+               p = next;
                }
                }
+
        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 ){
@@ -1876,7 +1919,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