Bell 32V development
authorTom London <tbl@research.uucp>
Tue, 13 Mar 1979 05:09:49 +0000 (00:09 -0500)
committerTom London <tbl@research.uucp>
Tue, 13 Mar 1979 05:09:49 +0000 (00:09 -0500)
Work on file usr/src/cmd/mip/pftn.c

Co-Authored-By: John Reiser <jfr@research.uucp>
Synthesized-from: 32v

usr/src/cmd/mip/pftn.c [new file with mode: 0644]

diff --git a/usr/src/cmd/mip/pftn.c b/usr/src/cmd/mip/pftn.c
new file mode 100644 (file)
index 0000000..fbb9f2d
--- /dev/null
@@ -0,0 +1,1682 @@
+# include "mfile1"
+# include <a.out.h>
+
+struct instk {
+       int in_sz;   /* size of array element */
+       int in_x;    /* current index for structure member in structure initializations */
+       int in_n;    /* number of initializations seen */
+       int in_s;    /* sizoff */
+       int in_d;    /* dimoff */
+       TWORD in_t;    /* type */
+       int in_id;   /* stab index */
+       int in_fl;   /* flag which says if this level is controlled by {} */
+       OFFSZ in_off;  /* offset of the beginning of this level */
+       }
+instack[10],
+*pstk;
+
+       /* defines used for getting things off of the initialization stack */
+
+
+struct symtab *relook();
+
+
+int ddebug = 0;
+int gdebug;
+
+defid( q, class )  NODE *q; {
+       register struct symtab *p;
+       int idp;
+       TWORD type;
+       TWORD stp;
+       int scl;
+       int dsym, ddef;
+       int slev, temp;
+
+       if( q == NIL ) return;  /* an error was detected */
+
+       if( q < node || q >= &node[TREESZ] ) cerror( "defid call" );
+
+       idp = q->rval;
+
+       if( idp < 0 ) cerror( "tyreduce" );
+       p = &stab[idp];
+
+       if( ddebug ){
+               printf( "defid( %.8s (%d), ", p->sname, idp );
+               tprint( q->type );
+               printf( ", %s, (%d,%d) ), level %d\n", scnames(class), q->cdim, q->csiz, blevel );
+               }
+
+       fixtype( q, class );
+
+       type = q->type;
+       class = fixclass( class, type );
+
+       stp = p->stype;
+       slev = p->slevel;
+
+       if( ddebug ){
+               printf( "       modified to " );
+               tprint( type );
+               printf( ", %s\n", scnames(class) );
+               printf( "       previous def'n: " );
+               tprint( stp );
+               printf( ", %s, (%d,%d) ), level %d\n", scnames(p->sclass), p->dimoff, p->sizoff, slev );
+               }
+
+       if( stp == UNDEF|| stp == FARG ){
+               if( blevel==1 && stp!=FARG ) switch( class ){
+
+               default:
+                       if(!(class&FIELD)) uerror( "declared argument %.8s is missing", p->sname );
+               case MOS:
+               case STNAME:
+               case MOU:
+               case UNAME:
+               case MOE:
+               case ENAME:
+               case TYPEDEF:
+                       ;
+                       }
+               goto enter;
+               }
+       if( type != stp ) goto mismatch;
+       /* test (and possibly adjust) dimensions */
+       dsym = p->dimoff;
+       ddef = q->cdim;
+       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] ){
+                               goto mismatch;
+                               }
+                       ++dsym;
+                       ++ddef;
+                       }
+               }
+
+       /* check that redeclarations are to the same structure */
+       if( (temp==STRTY||temp==UNIONTY||temp==ENUMTY) && p->sizoff != q->csiz && (type&TMASK) ) {
+               goto mismatch;
+               }
+
+       scl = ( p->sclass );
+
+       if( ddebug ){
+               printf( "       previous class: %s\n", scnames(scl) );
+               }
+
+       if( class&FIELD ){
+               /* redefinition */
+               if( !falloc( p, class&FLDSIZ, 1, NIL ) ) {
+                       /* successful allocation */
+                       psave( idp );
+                       return;
+                       }
+               /* blew it: resume at end of switch... */
+               }
+
+       else switch( class ){
+
+       case EXTERN:
+               switch( scl ){
+               case STATIC:
+               case USTATIC:
+                       if( slev==0 ) return;
+                       break;
+               case EXTDEF:
+               case EXTERN:
+               case FORTRAN:
+               case UFORTRAN:
+                       return;
+                       }
+               break;
+
+       case STATIC:
+               if( scl==USTATIC || (scl==EXTERN && blevel==0) ){
+                       p->sclass = STATIC;
+                       if( ISFTN(type) ) curftn = idp;
+                       return;
+                       }
+               break;
+
+       case USTATIC:
+               if( scl==STATIC || scl==USTATIC ) return;
+               break;
+
+       case LABEL:
+               if( scl == ULABEL ){
+                       p->sclass = LABEL;
+                       deflab( p->offset );
+                       return;
+                       }
+               break;
+
+       case TYPEDEF:
+               if( scl == class ) return;
+               break;
+
+       case UFORTRAN:
+               if( scl == UFORTRAN || scl == FORTRAN ) return;
+               break;
+
+       case FORTRAN:
+               if( scl == UFORTRAN ){
+                       p->sclass = FORTRAN;
+                       if( ISFTN(type) ) curftn = idp;
+                       return;
+                       }
+               break;
+
+       case MOU:
+       case MOS:
+               if( scl == class ) {
+                       if( oalloc( p, &strucoff ) ) break;
+                       if( class == MOU ) strucoff = 0;
+                       psave( idp );
+                       return;
+                       }
+               break;
+
+       case MOE:
+               if( scl == class ){
+                       if( p->offset!= strucoff++ ) break;
+                       psave( idp );
+                       }
+               break;
+
+       case EXTDEF:
+               if( scl == EXTERN ) {
+                       p->sclass = EXTDEF;
+                       if( ISFTN(type) ) curftn = idp;
+                       return;
+                       }
+               break;
+
+       case STNAME:
+       case UNAME:
+       case ENAME:
+               if( scl != class ) break;
+               if( dimtab[p->sizoff] == 0 ) return;  /* previous entry just a mention */
+               break;
+
+       case ULABEL:
+               if( scl == LABEL || scl == ULABEL ) return;
+       case PARAM:
+       case AUTO:
+       case REGISTER:
+               ;  /* mismatch.. */
+
+               }
+
+       mismatch:
+       if( blevel > slev && class != EXTERN && class != FORTRAN &&
+               class != UFORTRAN && !( class == LABEL && slev >= 2 ) ){
+               q->rval = idp = hide( p );
+               p = &stab[idp];
+               goto enter;
+               }
+       uerror( "redeclaration of %.8s", p->sname );
+       if( class==EXTDEF && ISFTN(type) ) curftn = idp;
+       return;
+
+       enter:  /* make a new entry */
+
+       if( ddebug ) printf( "  new entry made\n" );
+       p->stype = type;
+       p->sclass = class;
+       p->slevel = blevel;
+       p->offset = NOOFFSET;
+       p->suse = lineno;
+       if( class == STNAME || class == UNAME || class == ENAME ) {
+               p->sizoff = curdim;
+               dstash( 0 );  /* size */
+               dstash( -1 ); /* index to members of str or union */
+               dstash( ALSTRUCT );  /* alignment */
+               }
+       else {
+               switch( BTYPE(type) ){
+               case STRTY:
+               case UNIONTY:
+               case ENUMTY:
+                       p->sizoff = q->csiz;
+                       break;
+               default:
+                       p->sizoff = BTYPE(type);
+                       }
+               }
+
+       /* copy dimensions */
+
+       p->dimoff = q->cdim;
+
+       /* allocate offsets */
+       if( class&FIELD ){
+               falloc( p, class&FLDSIZ, 0, NIL );  /* new entry */
+               psave( idp );
+               }
+       else switch( class ){
+
+       case AUTO:
+               oalloc( p, &autooff );
+               break;
+       case STATIC:
+       case EXTDEF:
+               p->offset = getlab();
+               if( ISFTN(type) ) curftn = idp;
+               break;
+       case ULABEL:
+       case LABEL:
+               p->offset = getlab();
+               p->slevel = 2;
+               if( class == LABEL ){
+                       locctr( PROG );
+                       deflab( p->offset );
+                       }
+               break;
+
+       case EXTERN:
+       case UFORTRAN:
+       case FORTRAN:
+               p->offset = getlab();
+               p->slevel = 0;
+               break;
+       case MOU:
+       case MOS:
+               oalloc( p, &strucoff );
+               if( class == MOU ) strucoff = 0;
+               psave( idp );
+               break;
+
+       case MOE:
+               p->offset = strucoff++;
+               psave( idp );
+               break;
+       case REGISTER:
+               p->offset = regvar--;
+               if( blevel == 1 ) p->sflags |= SSET;
+               if( regvar < minrvar ) minrvar = regvar;
+               break;
+               }
+
+       /* user-supplied routine to fix up new definitions */
+
+#ifndef LINT
+       FIXDEF(p);
+#endif
+
+       if( ddebug ) printf( "  dimoff, sizoff, offset: %d, %d, %d\n", p->dimoff, p->sizoff, p->offset );
+
+       }
+
+psave( i ){
+       if( paramno >= PARAMSZ ){
+               cerror( "parameter stack overflow");
+               }
+       paramstk[ paramno++ ] = i;
+       }
+
+ftnend(){ /* end of function */
+       if( retlab != NOLAB ){ /* inside a real function */
+               efcode();
+               }
+       checkst(0);
+       retstat = 0;
+       tcheck();
+       curclass = SNULL;
+       brklab = contlab = retlab = NOLAB;
+       flostat = 0;
+       if( nerrors == 0 ){
+               if( psavbc != & asavbc[0] ) cerror("bcsave error");
+               if( paramno != 0 ) cerror("parameter reset error");
+               if( swx != 0 ) cerror( "switch error");
+               }
+       psavbc = &asavbc[0];
+       paramno = 0;
+       autooff = AUTOINIT;
+       minrvar = regvar = MAXRVAR;
+       reached = 1;
+       swx = 0;
+       swp = swtab;
+       locctr(DATA);
+       }
+
+dclargs(){
+       register i, j;
+       register struct symtab *p;
+       register NODE *q;
+       argoff = ARGINIT;
+       for( i=0; i<paramno; ++i ){
+               if( (j = paramstk[i]) < 0 ) continue;
+               p = &stab[j];
+               if( p->stype == FARG ) {
+                       q = block(FREE,NIL,NIL,INT,0,INT);
+                       q->rval = j;
+                       defid( q, PARAM );
+                       }
+#ifndef LINT
+               pstab(p->sname, N_PSYM);
+               if (gdebug) printf("0,%d,%d\n", p->stype, argoff/SZCHAR);
+               poffs(N_RSYM, p);
+#endif
+               oalloc( p, &argoff );  /* always set aside space, even for register arguments */
+               }
+       cendarg();
+       locctr(PROG);
+       defalign(ALINT);
+       ++ftnno;
+       bfcode( paramstk, paramno );
+       paramno = 0;
+       }
+
+NODE *
+rstruct( idn, soru ){ /* reference to a structure or union, with no definition */
+       register struct symtab *p;
+       register NODE *q;
+       p = &stab[idn];
+       switch( p->stype ){
+
+       case UNDEF:
+       def:
+               q = block( FREE, NIL, NIL, 0, 0, 0 );
+               q->rval = idn;
+               q->type = (soru&INSTRUCT) ? STRTY : ( (soru&INUNION) ? UNIONTY : ENUMTY );
+               defid( q, (soru&INSTRUCT) ? STNAME : ( (soru&INUNION) ? UNAME : ENAME ) );
+               break;
+
+       case STRTY:
+               if( soru & INSTRUCT ) break;
+               goto def;
+
+       case UNIONTY:
+               if( soru & INUNION ) break;
+               goto def;
+
+       case ENUMTY:
+               if( !(soru&(INUNION|INSTRUCT)) ) break;
+               goto def;
+
+               }
+       stwart = instruct;
+       return( mkty( p->stype, 0, p->sizoff ) );
+       }
+
+moedef( idn ){
+       register NODE *q;
+
+       q = block( FREE, NIL, NIL, MOETY, 0, 0 );
+       q -> rval = idn;
+       if( idn>=0 ) defid( q, MOE );
+       }
+
+bstruct( idn, soru ){ /* begining of structure or union declaration */
+       register NODE *q;
+
+       psave( instruct );
+       psave( curclass );
+       psave( strucoff );
+       strucoff = 0;
+       instruct = soru;
+       q = block( FREE, NIL, NIL, 0, 0, 0 );
+       q->rval = idn;
+       if( instruct==INSTRUCT ){
+               curclass = MOS;
+               q->type = STRTY;
+               if( idn >= 0 ) defid( q, STNAME );
+               }
+       else if( instruct == INUNION ) {
+               curclass = MOU;
+               q->type = UNIONTY;
+               if( idn >= 0 ) defid( q, UNAME );
+               }
+       else { /* enum */
+               curclass = MOE;
+               q->type = ENUMTY;
+               if( idn >= 0 ) defid( q, ENAME );
+               }
+       psave( q->rval );
+       return( paramno-4 );
+       }
+
+NODE *
+dclstruct( oparam ){
+       register struct symtab *p;
+       register i, al, sa, j, sz, szindex;
+       register TWORD temp;
+       register high, low;
+
+       /* paramstack contains:
+               paramstack[ oparam ] = previous instruct
+               paramstack[ oparam+1 ] = previous class
+               paramstk[ oparam+2 ] = previous strucoff
+               paramstk[ oparam+3 ] = structure name
+
+               paramstk[ oparam+4, ... ]  = member stab indices
+
+               */
+
+
+       if( (i=paramstk[oparam+3]) < 0 ){
+               szindex = curdim;
+               dstash( 0 );  /* size */
+               dstash( -1 );  /* index to member names */
+               dstash( ALSTRUCT );  /* alignment */
+               }
+       else {
+               szindex = stab[i].sizoff;
+               }
+
+       if( ddebug ){
+               printf( "dclstruct( %.8s ), szindex = %d\n", (i>=0)? stab[i].sname : "??", szindex );
+               }
+       temp = (instruct&INSTRUCT)?STRTY:((instruct&INUNION)?UNIONTY:ENUMTY);
+       stwart = instruct = paramstk[ oparam ];
+       curclass = paramstk[ oparam+1 ];
+       dimtab[ szindex+1 ] = curdim;
+       al = ALSTRUCT;
+
+       high = low = 0;
+
+       for( i = oparam+4;  i< paramno; ++i ){
+               dstash( j=paramstk[i] );
+               if( j<0 || j>= SYMTSZ ) cerror( "gummy structure member" );
+               p = &stab[j];
+               if( temp == ENUMTY ){
+                       if( p->offset < low ) low = p->offset;
+                       if( p->offset > high ) high = p->offset;
+                       p->sizoff = szindex;
+                       continue;
+                       }
+               sa = talign( p->stype, p->sizoff );
+               if( p->sclass & FIELD ){
+                       sz = p->sclass&FLDSIZ;
+                       }
+               else {
+                       sz = tsize( p->stype, p->dimoff, p->sizoff );
+                       }
+               if( sz == 0 ){
+                       uerror( "illegal zero sized structure member: %.8s", p->sname );
+                       }
+               if( sz > strucoff ) strucoff = sz;  /* for use with unions */
+               SETOFF( al, sa );
+               /* set al, the alignment, to the lcm of the alignments of the members */
+               }
+       dstash( -1 );  /* endmarker */
+       SETOFF( strucoff, al );
+
+       if( temp == ENUMTY ){
+               register TWORD ty;
+
+# ifdef ENUMSIZE
+               ty = ENUMSIZE(high,low);
+# else
+               if( (char)high == high && (char)low == low ) ty = ctype( CHAR );
+               else if( (short)high == high && (short)low == low ) ty = ctype( SHORT );
+               else ty = ctype(INT);
+#endif
+               strucoff = tsize( ty, 0, (int)ty );
+               dimtab[ szindex+2 ] = al = talign( ty, (int)ty );
+               }
+
+       if( strucoff == 0 ) uerror( "zero sized structure" );
+       dimtab[ szindex ] = strucoff;
+       dimtab[ szindex+2 ] = al;
+
+       if( ddebug>1 ){
+               printf( "\tdimtab[%d,%d,%d] = %d,%d,%d\n", szindex,szindex+1,szindex+2,
+                               dimtab[szindex],dimtab[szindex+1],dimtab[szindex+2] );
+               for( i = dimtab[szindex+1]; dimtab[i] >= 0; ++i ){
+                       printf( "\tmember %.8s(%d)\n", stab[dimtab[i]].sname, dimtab[i] );
+                       }
+               }
+
+       strucoff = paramstk[ oparam+2 ];
+       paramno = oparam;
+
+       return( mkty( temp, 0, szindex ) );
+       }
+
+       /* VARARGS */
+yyerror( s ) char *s; { /* error printing routine in parser */
+
+       uerror( s );
+
+       }
+
+yyaccpt(){
+       ftnend();
+       }
+
+ftnarg( idn ) {
+       if( stab[idn].stype != UNDEF ){
+               idn = hide( &stab[idn]);
+               }
+       stab[idn].stype = FARG;
+       stab[idn].sclass = PARAM;
+       psave( idn );
+       }
+
+talign( ty, s) register unsigned ty; register s; {
+       /* compute the alignment of an object with type ty, sizeoff index s */
+
+       register i;
+       if( s<0 && ty!=INT && ty!=CHAR && ty!=SHORT && ty!=UNSIGNED && ty!=UCHAR && ty!=USHORT 
+#ifdef LONGFIELDS
+               && ty!=LONG && ty!=ULONG
+#endif
+                                       ){
+               return( fldal( ty ) );
+               }
+
+       for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
+               switch( (ty>>i)&TMASK ){
+
+               case FTN:
+                       cerror( "compiler takes alignment of function");
+               case PTR:
+                       return( ALPOINT );
+               case ARY:
+                       continue;
+               case 0:
+                       break;
+                       }
+               }
+
+       switch( BTYPE(ty) ){
+
+       case UNIONTY:
+       case ENUMTY:
+       case STRTY:
+               return( dimtab[ s+2 ] );
+       case CHAR:
+       case UCHAR:
+               return( ALCHAR );
+       case FLOAT:
+               return( ALFLOAT );
+       case DOUBLE:
+               return( ALDOUBLE );
+       case LONG:
+       case ULONG:
+               return( ALLONG );
+       case SHORT:
+       case USHORT:
+               return( ALSHORT );
+       default:
+               return( ALINT );
+               }
+       }
+
+OFFSZ
+tsize( ty, d, s )  TWORD ty; {
+       /* compute the size associated with type ty,
+           dimoff d, and sizoff s */
+       /* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */
+
+       int i;
+       OFFSZ mult;
+
+       mult = 1;
+
+       for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
+               switch( (ty>>i)&TMASK ){
+
+               case FTN:
+                       cerror( "compiler takes size of function");
+               case PTR:
+                       return( SZPOINT * mult );
+               case ARY:
+                       mult *= dimtab[ d++ ];
+                       continue;
+               case 0:
+                       break;
+
+                       }
+               }
+
+       if( dimtab[s]==0 ) {
+               uerror( "unknown size");
+               return( SZINT );
+               }
+       return( dimtab[ s ] * mult );
+       }
+
+inforce( n ) OFFSZ n; {  /* force inoff to have the value n */
+       /* inoff is updated to have the value n */
+       OFFSZ wb;
+       register rest;
+       /* rest is used to do a lot of conversion to ints... */
+
+       if( inoff == n ) return;
+       if( inoff > n ) {
+               cerror( "initialization alignment error");
+               }
+
+       wb = inoff;
+       SETOFF( wb, SZINT );
+
+       /* wb now has the next higher word boundary */
+
+       if( wb >= n ){ /* in the same word */
+               rest = n - inoff;
+               vfdzero( rest );
+               return;
+               }
+
+       /* otherwise, extend inoff to be word aligned */
+
+       rest = wb - inoff;
+       vfdzero( rest );
+
+       /* now, skip full words until near to n */
+
+       rest = (n-inoff)/SZINT;
+       zecode( rest );
+
+       /* now, the remainder of the last word */
+
+       rest = n-inoff;
+       vfdzero( rest );
+       if( inoff != n ) cerror( "inoff error");
+
+       }
+
+vfdalign( n ){ /* make inoff have the offset the next alignment of n */
+       OFFSZ m;
+
+       m = inoff;
+       SETOFF( m, n );
+       inforce( m );
+       }
+
+
+int idebug = 0;
+
+int ibseen = 0;  /* the number of } constructions which have been filled */
+
+int iclass;  /* storage class of thing being initialized */
+
+int ilocctr = 0;  /* location counter for current initialization */
+
+beginit(curid){
+       /* beginning of initilization; set location ctr and set type */
+       register struct symtab *p;
+
+       if( idebug >= 3 ) printf( "beginit(), curid = %d\n", curid );
+
+       p = &stab[curid];
+
+       iclass = p->sclass;
+       if( curclass == EXTERN || curclass == FORTRAN ) iclass = EXTERN;
+       switch( iclass ){
+
+       case UNAME:
+       case EXTERN:
+               return;
+       case AUTO:
+       case REGISTER:
+               break;
+       case EXTDEF:
+       case STATIC:
+               ilocctr = ISARY(p->stype)?ADATA:DATA;
+               locctr( ilocctr );
+               defalign( talign( p->stype, p->sizoff ) );
+               defnam( p );
+
+               }
+
+       inoff = 0;
+       ibseen = 0;
+
+       pstk = 0;
+
+       instk( curid, p->stype, p->dimoff, p->sizoff, inoff );
+
+       }
+
+instk( id, t, d, s, off ) OFFSZ off; TWORD t; {
+       /* make a new entry on the parameter stack to initialize id */
+
+       register struct symtab *p;
+
+       for(;;){
+               if( idebug ) printf( "instk((%d, %o,%d,%d, %d)\n", id, t, d, s, off );
+
+               /* save information on the stack */
+
+               if( !pstk ) pstk = instack;
+               else ++pstk;
+
+               pstk->in_fl = 0;        /* { flag */
+               pstk->in_id =  id ;
+               pstk->in_t =  t ;
+               pstk->in_d =  d ;
+               pstk->in_s =  s ;
+               pstk->in_n = 0;  /* number seen */
+               pstk->in_x =  t==STRTY ?dimtab[s+1] : 0 ;
+               pstk->in_off =  off;   /* offset at the beginning of this element */
+               /* if t is an array, DECREF(t) can't be a field */
+               /* INS_sz has size of array elements, and -size for fields */
+               if( ISARY(t) ){
+                       pstk->in_sz = tsize( DECREF(t), d+1, s );
+                       }
+               else if( stab[id].sclass & FIELD ){
+                       pstk->in_sz = - ( stab[id].sclass & FLDSIZ );
+                       }
+               else {
+                       pstk->in_sz = 0;
+                       }
+
+               if( (iclass==AUTO || iclass == REGISTER ) &&
+                       (ISARY(t) || t==STRTY) ) uerror( "no automatic aggregate initialization" );
+
+               /* now, if this is not a scalar, put on another element */
+
+               if( ISARY(t) ){
+                       t = DECREF(t);
+                       ++d;
+                       continue;
+                       }
+               else if( t == STRTY ){
+                       id = dimtab[pstk->in_x];
+                       p = &stab[id];
+                       if( p->sclass != MOS && !(p->sclass&FIELD) ) cerror( "insane structure member list" );
+                       t = p->stype;
+                       d = p->dimoff;
+                       s = p->sizoff;
+                       off += p->offset;
+                       continue;
+                       }
+               else return;
+               }
+       }
+
+NODE *
+getstr(){ /* decide if the string is external or an initializer, and get the contents accordingly */
+
+       register l, temp;
+       register NODE *p;
+
+       if( (iclass==EXTDEF||iclass==STATIC) && (pstk->in_t == CHAR || pstk->in_t == UCHAR) &&
+                       pstk!=instack && ISARY( pstk[-1].in_t ) ){
+               /* treat "abc" as { 'a', 'b', 'c', 0 } */
+               strflg = 1;
+               ilbrace();  /* simulate { */
+               inforce( pstk->in_off );
+               /* if the array is inflexible (not top level), pass in the size and
+                       be prepared to throw away unwanted initializers */
+               lxstr((pstk-1)!=instack?dimtab[(pstk-1)->in_d]:0);  /* get the contents */
+               irbrace();  /* simulate } */
+               return( NIL );
+               }
+       else { /* make a label, and get the contents and stash them away */
+               if( iclass != SNULL ){ /* initializing */
+                       /* fill out previous word, to permit pointer */
+                       vfdalign( ALPOINT );
+                       }
+               temp = locctr( blevel==0?ISTRNG:STRNG ); /* set up location counter */
+               deflab( l = getlab() );
+               strflg = 0;
+               lxstr(0); /* get the contents */
+               locctr( blevel==0?ilocctr:temp );
+               p = buildtree( STRING, NIL, NIL );
+               p->rval = -l;
+               return(p);
+               }
+       }
+
+putbyte( v ){ /* simulate byte v appearing in a list of integer values */
+       register NODE *p;
+       p = bcon(v);
+       incode( p, SZCHAR );
+       tfree( p );
+       gotscal();
+       }
+
+endinit(){
+       register TWORD t;
+       register d, s, n, d1;
+
+       if( idebug ) printf( "endinit(), inoff = %d\n", inoff );
+
+       switch( iclass ){
+
+       case EXTERN:
+       case AUTO:
+       case REGISTER:
+               return;
+               }
+
+       pstk = instack;
+
+       t = pstk->in_t;
+       d = pstk->in_d;
+       s = pstk->in_s;
+       n = pstk->in_n;
+
+       if( ISARY(t) ){
+               d1 = dimtab[d];
+
+               vfdalign( pstk->in_sz );  /* fill out part of the last element, if needed */
+               n = inoff/pstk->in_sz;  /* real number of initializers */
+               if( d1 >= n ){
+                       /* once again, t is an array, so no fields */
+                       inforce( tsize( t, d, s ) );
+                       n = d1;
+                       }
+               if( d1!=0 && d1!=n ) uerror( "too many initializers");
+               if( n==0 ) werror( "empty array declaration");
+               dimtab[d] = n;
+               }
+
+       else if( t == STRTY || t == UNIONTY ){
+               /* clearly not fields either */
+               inforce( tsize( t, d, s ) );
+               }
+       else if( n > 1 ) uerror( "bad scalar initialization");
+       /* this will never be called with a field element... */
+       else inforce( tsize(t,d,s) );
+
+       paramno = 0;
+       vfdalign( AL_INIT );
+       inoff = 0;
+       iclass = SNULL;
+
+       }
+
+doinit( p ) register NODE *p; {
+
+       /* take care of generating a value for the initializer p */
+       /* inoff has the current offset (last bit written)
+               in the current word being generated */
+
+       register sz, d, s;
+       register TWORD t;
+
+       /* note: size of an individual initializer is assumed to fit into an int */
+
+       if( iclass < 0 ) goto leave;
+       if( iclass == EXTERN || iclass == UNAME ){
+               uerror( "cannot initialize extern or union" );
+               iclass = -1;
+               goto leave;
+               }
+
+       if( iclass == AUTO || iclass == REGISTER ){
+               /* do the initialization and get out, without regard 
+                   for filing out the variable with zeros, etc. */
+               bccode();
+               idname = pstk->in_id;
+               p = buildtree( ASSIGN, buildtree( NAME, NIL, NIL ), p );
+               ecomp(p);
+               return;
+               }
+
+       if( p == NIL ) return;  /* for throwing away strings that have been turned into lists */
+
+       if( ibseen ){
+               uerror( "} expected");
+               goto leave;
+               }
+
+       if( idebug > 1 ) printf( "doinit(%o)\n", p );
+
+       t = pstk->in_t;  /* type required */
+       d = pstk->in_d;
+       s = pstk->in_s;
+       if( pstk->in_sz < 0 ){  /* bit field */
+               sz = -pstk->in_sz;
+               }
+       else {
+               sz = tsize( t, d, s );
+               }
+
+       inforce( pstk->in_off );
+
+       p = buildtree( ASSIGN, block( NAME, NIL,NIL, t, d, s ), p );
+       p->left->op = FREE;
+       p->left = p->right;
+       p->right = NIL;
+       p->left = optim( p->left );
+       if( p->left->op == UNARY AND ){
+               p->left->op = FREE;
+               p->left = p->left->left;
+               }
+       p->op = INIT;
+
+       if( sz < SZINT ){ /* special case: bit fields, etc. */
+               if( p->left->op != ICON ) uerror( "illegal initialization" );
+               else incode( p->left, sz );
+               }
+       else if( p->left->op == FCON ){
+               fincode( p->left->dval, sz );
+               }
+       else {
+               cinit( optim(p), sz );
+               }
+
+       gotscal();
+
+       leave:
+       tfree(p);
+       }
+
+gotscal(){
+       register t, ix;
+       register n, id;
+       struct symtab *p;
+       OFFSZ temp;
+
+       for( ; pstk > instack; ) {
+
+               if( pstk->in_fl ) ++ibseen;
+
+               --pstk;
+               
+               t = pstk->in_t;
+
+               if( t == STRTY ){
+                       ix = ++pstk->in_x;
+                       if( (id=dimtab[ix]) < 0 ) continue;
+
+                       /* otherwise, put next element on the stack */
+
+                       p = &stab[id];
+                       instk( id, p->stype, p->dimoff, p->sizoff, p->offset+pstk->in_off );
+                       return;
+                       }
+               else if( ISARY(t) ){
+                       n = ++pstk->in_n;
+                       if( n >= dimtab[pstk->in_d] && pstk > instack ) continue;
+
+                       /* put the new element onto the stack */
+
+                       temp = pstk->in_sz;
+                       instk( pstk->in_id, (TWORD)DECREF(pstk->in_t), pstk->in_d+1, pstk->in_s,
+                               pstk->in_off+n*temp );
+                       return;
+                       }
+
+               }
+
+       }
+
+ilbrace(){ /* process an initializer's left brace */
+       register t;
+       struct instk *temp;
+
+       temp = pstk;
+
+       for( ; pstk > instack; --pstk ){
+
+               t = pstk->in_t;
+               if( t != STRTY && !ISARY(t) ) continue; /* not an aggregate */
+               if( pstk->in_fl ){ /* already associated with a { */
+                       if( pstk->in_n ) uerror( "illegal {");
+                       continue;
+                       }
+
+               /* we have one ... */
+               pstk->in_fl = 1;
+               break;
+               }
+
+       /* cannot find one */
+       /* ignore such right braces */
+
+       pstk = temp;
+       }
+
+irbrace(){
+       /* called when a '}' is seen */
+
+       if( idebug ) printf( "irbrace(): paramno = %d on entry\n", paramno );
+
+       if( ibseen ) {
+               --ibseen;
+               return;
+               }
+
+       for( ; pstk > instack; --pstk ){
+               if( !pstk->in_fl ) continue;
+
+               /* we have one now */
+
+               pstk->in_fl = 0;  /* cancel { */
+               gotscal();  /* take it away... */
+               return;
+               }
+
+       /* these right braces match ignored left braces: throw out */
+
+       }
+
+upoff( size, alignment, poff ) register alignment, *poff; {
+       /* update the offset pointed to by poff; return the
+       /* offset of a value of size `size', alignment `alignment',
+       /* given that off is increasing */
+
+       register off;
+
+       off = *poff;
+       SETOFF( off, alignment );
+       *poff = off+size;
+       return( off );
+       }
+
+oalloc( p, poff ) register struct symtab *p; register *poff; {
+       /* allocate p with offset *poff, and update *poff */
+       register al, off, tsz;
+       int noff;
+
+       al = talign( p->stype, p->sizoff );
+       noff = off = *poff;
+       tsz = tsize( p->stype, p->dimoff, p->sizoff );
+#ifdef BACKAUTO
+       if( p->sclass == AUTO ){
+               noff = off + tsz;
+               SETOFF( noff, al );
+               off = -noff;
+               }
+       else
+#endif
+               if( p->sclass == PARAM && (p->stype==CHAR||p->stype==UCHAR||p->stype==SHORT||
+                               p->stype==USHORT) ){
+                       off = upoff( SZINT, ALINT, &noff );
+# ifndef RTOLBYTES
+                       off = noff - tsz;
+#endif
+                       }
+               else
+               {
+               off = upoff( tsz, al, &noff );
+               }
+
+       if( p->sclass != REGISTER ){ /* in case we are allocating stack space for register arguments */
+               if( p->offset == NOOFFSET ) p->offset = off;
+               else if( off != p->offset ) return(1);
+               }
+
+       *poff = noff;
+       return(0);
+       }
+
+falloc( p, w, new, pty )  register struct symtab *p; NODE *pty; {
+       /* allocate a field of width w */
+       /* new is 0 if new entry, 1 if redefinition, -1 if alignment */
+
+       register al,sz,type;
+
+       type = (new<0)? pty->type : p->stype;
+
+       /* this must be fixed to use the current type in alignments */
+       switch( new<0?pty->type:p->stype ){
+
+       case ENUMTY:
+               {
+                       int s;
+                       s = new<0 ? pty->csiz : p->sizoff;
+                       al = dimtab[s+2];
+                       sz = dimtab[s];
+                       break;
+                       }
+
+       case CHAR:
+       case UCHAR:
+               al = ALCHAR;
+               sz = SZCHAR;
+               break;
+
+       case SHORT:
+       case USHORT:
+               al = ALSHORT;
+               sz = SZSHORT;
+               break;
+
+       case INT:
+       case UNSIGNED:
+               al = ALINT;
+               sz = SZINT;
+               break;
+#ifdef LONGFIELDS
+
+       case LONG:
+       case ULONG:
+               al = ALLONG;
+               sz = SZLONG;
+               break;
+#endif
+
+       default:
+               if( new < 0 ) {
+                       uerror( "illegal field type" );
+                       al = ALINT;
+                       }
+               else {
+                       al = fldal( p->stype );
+                       sz =SZINT;
+                       }
+               }
+
+       if( w > sz ) {
+               uerror( "field too big");
+               w = sz;
+               }
+
+       if( w == 0 ){ /* align only */
+               SETOFF( strucoff, al );
+               if( new >= 0 ) uerror( "zero size field");
+               return(0);
+               }
+
+       if( strucoff%al + w > sz ) SETOFF( strucoff, al );
+       if( new < 0 ) {
+               strucoff += w;  /* we know it will fit */
+               return(0);
+               }
+
+       /* establish the field */
+
+       if( new == 1 ) { /* previous definition */
+               if( p->offset != strucoff || p->sclass != (FIELD|w) ) return(1);
+               }
+       p->offset = strucoff;
+       strucoff += w;
+       p->stype = type;
+       fldty( p );
+       return(0);
+       }
+
+nidcl( p ) NODE *p; { /* handle unitialized declarations */
+       /* assumed to be not functions */
+       register class;
+       register commflag;  /* flag for labelled common declarations */
+
+       commflag = 0;
+
+       /* compute class */
+       if( (class=curclass) == SNULL ){
+               if( blevel > 1 ) class = AUTO;
+               else if( blevel != 0 || instruct ) cerror( "nidcl error" );
+               else { /* blevel = 0 */
+                       class = noinit();
+                       if( class == EXTERN ) commflag = 1;
+                       }
+               }
+
+       defid( p, class );
+
+       if( class==EXTDEF || class==STATIC ){
+               /* simulate initialization by 0 */
+               beginit(p->rval);
+               endinit();
+               }
+       if( commflag ) commdec( p->rval );
+       }
+
+TWORD
+types( t1, t2, t3 ) TWORD t1, t2, t3; {
+       /* return a basic type from basic types t1, t2, and t3 */
+
+       TWORD t[3], noun, adj, unsg;
+       register i;
+
+       t[0] = t1;
+       t[1] = t2;
+       t[2] = t3;
+
+       unsg = INT;  /* INT or UNSIGNED */
+       noun = UNDEF;  /* INT, CHAR, or FLOAT */
+       adj = INT;  /* INT, LONG, or SHORT */
+
+       for( i=0; i<3; ++i ){
+               switch( t[i] ){
+
+               default:
+               bad:
+                       uerror( "illegal type combination" );
+                       return( INT );
+
+               case UNDEF:
+                       continue;
+
+               case UNSIGNED:
+                       if( unsg != INT ) goto bad;
+                       unsg = UNSIGNED;
+                       continue;
+
+               case LONG:
+               case SHORT:
+                       if( adj != INT ) goto bad;
+                       adj = t[i];
+                       continue;
+
+               case INT:
+               case CHAR:
+               case FLOAT:
+                       if( noun != UNDEF ) goto bad;
+                       noun = t[i];
+                       continue;
+                       }
+               }
+
+       /* now, construct final type */
+       if( noun == UNDEF ) noun = INT;
+       else if( noun == FLOAT ){
+               if( unsg != INT || adj == SHORT ) goto bad;
+               return( adj==LONG ? DOUBLE : FLOAT );
+               }
+       else if( noun == CHAR && adj != INT ) goto bad;
+
+       /* now, noun is INT or CHAR */
+       if( adj != INT ) noun = adj;
+       if( unsg == UNSIGNED ) return( noun + (UNSIGNED-INT) );
+       else return( noun );
+       }
+
+NODE *
+tymerge( typ, idp ) NODE *typ, *idp; {
+       /* merge type typ with identifier idp  */
+
+       register unsigned t;
+       register i;
+       extern int eprint();
+
+       if( typ->op != TYPE ) cerror( "tymerge: arg 1" );
+       if(idp == NIL ) return( NIL );
+
+       if( ddebug > 2 ) fwalk( idp, eprint, 0 );
+
+       idp->type = typ->type;
+       idp->cdim = curdim;
+       tyreduce( idp );
+       idp->csiz = typ->csiz;
+
+       for( t=typ->type, i=typ->cdim; t&TMASK; t = DECREF(t) ){
+               if( ISARY(t) ) dstash( dimtab[i++] );
+               }
+
+       /* now idp is a single node: fix up type */
+
+       idp->type = ctype( idp->type );
+
+       if( (t = BTYPE(idp->type)) != STRTY && t != UNIONTY && t != ENUMTY ){
+               idp->csiz = t;  /* in case ctype has rewritten things */
+               }
+
+       return( idp );
+       }
+
+tyreduce( p ) register NODE *p; {
+
+       /* build a type, and stash away dimensions, from a parse tree of the declaration */
+       /* the type is build top down, the dimensions bottom up */
+       register o, temp;
+       register unsigned t;
+
+       o = p->op;
+       p->op = FREE;
+
+       if( o == NAME ) return;
+
+       t = INCREF( p->type );
+       if( o == UNARY CALL ) t += (FTN-PTR);
+       else if( o == LB ){
+               t += (ARY-PTR);
+               temp = p->right->lval;
+               p->right->op = FREE;
+               }
+
+       p->left->type = t;
+       tyreduce( p->left );
+
+       if( o == LB ) dstash( temp );
+
+       p->rval = p->left->rval;
+       p->type = p->left->type;
+
+       }
+
+fixtype( p, class ) register NODE *p; {
+       register unsigned t, type;
+       register mod1, mod2;
+       /* fix up the types, and check for legality */
+
+       if( (type = p->type) == UNDEF ) return;
+       if( mod2 = (type&TMASK) ){
+               t = DECREF(type);
+               while( mod1=mod2, mod2 = (t&TMASK) ){
+                       if( mod1 == ARY && mod2 == FTN ){
+                               uerror( "array of functions is illegal" );
+                               type = 0;
+                               }
+                       else if( mod1 == FTN && ( mod2 == ARY || mod2 == FTN ) ){
+                               uerror( "function returns illegal type" );
+                               type = 0;
+                               }
+                       t = DECREF(t);
+                       }
+               }
+
+       /* detect function arguments, watching out for structure declarations */
+
+       if( class==SNULL && blevel==1 && !(instruct&(INSTRUCT|INUNION)) ) class = PARAM;
+       if( class == PARAM || ( class==REGISTER && blevel==1 ) ){
+               if( type == FLOAT ) type = DOUBLE;
+               else if( ISARY(type) ){
+                       ++p->cdim;
+                       type += (PTR-ARY);
+                       }
+               else if( ISFTN(type) ) type = INCREF(type);
+
+               }
+
+       if( instruct && ISFTN(type) ){
+               uerror( "function illegal in structure or union" );
+               type = INCREF(type);
+               }
+       p->type = type;
+       }
+
+uclass( class ) register class; {
+       /* give undefined version of class */
+       if( class == SNULL ) return( EXTERN );
+       else if( class == STATIC ) return( USTATIC );
+       else if( class == FORTRAN ) return( UFORTRAN );
+       else return( class );
+       }
+
+fixclass( class, type ) TWORD type; {
+
+       /* first, fix null class */
+
+       if( class == SNULL ){
+               if( instruct&INSTRUCT ) class = MOS;
+               else if( instruct&INUNION ) class = MOU;
+               else if( blevel == 0 ) class = EXTDEF;
+               else if( blevel == 1 ) class = PARAM;
+               else class = AUTO;
+
+               }
+
+       /* now, do general checking */
+
+       if( ISFTN( type ) ){
+               switch( class ) {
+               default:
+                       uerror( "function has illegal storage class" );
+               case AUTO:
+                       class = EXTERN;
+               case EXTERN:
+               case EXTDEF:
+               case FORTRAN:
+               case TYPEDEF:
+               case STATIC:
+               case UFORTRAN:
+               case USTATIC:
+                       ;
+                       }
+               }
+
+       if( class&FIELD ){
+               if( !(instruct&INSTRUCT) ) uerror( "illegal use of field" );
+               return( class );
+               }
+
+       switch( class ){
+
+       case MOU:
+               if( !(instruct&INUNION) ) uerror( "illegal class" );
+               return( class );
+
+       case MOS:
+               if( !(instruct&INSTRUCT) ) uerror( "illegal class" );
+               return( class );
+
+       case MOE:
+               if( instruct & (INSTRUCT|INUNION) ) uerror( "illegal class" );
+               return( class );
+
+       case REGISTER:
+               if( blevel == 0 ) uerror( "illegal register declaration" );
+               else if( regvar >= MINRVAR && cisreg( type ) ) return( class );
+               if( blevel == 1 ) return( PARAM );
+               else return( AUTO );
+
+       case AUTO:
+       case LABEL:
+       case ULABEL:
+               if( blevel < 2 ) uerror( "illegal class" );
+               return( class );
+
+       case PARAM:
+               if( blevel != 1 ) uerror( "illegal class" );
+               return( class );
+
+       case UFORTRAN:
+       case FORTRAN:
+# ifdef NOFORTRAN
+                       NOFORTRAN;    /* a condition which can regulate the FORTRAN usage */
+# endif
+               if( !ISFTN(type) ) uerror( "fortran declaration must apply to function" );
+               else {
+                       type = DECREF(type);
+                       if( ISFTN(type) || ISARY(type) || ISPTR(type) ) {
+                               uerror( "fortran function has wrong type" );
+                               }
+                       }
+       case STNAME:
+       case UNAME:
+       case ENAME:
+       case EXTERN:
+       case STATIC:
+       case EXTDEF:
+       case TYPEDEF:
+       case USTATIC:
+               return( class );
+
+       default:
+               cerror( "illegal class: %d", class );
+               /* NOTREACHED */
+
+               }
+       }
+
+lookup( name, s) char *name; { 
+       /* look up name: must agree with s w.r.t. SMOS and SHIDDEN */
+
+       register char *p, *q;
+       int i, j, ii;
+       register struct symtab *sp;
+
+       /* compute initial hash index */
+       if( ddebug > 2 ){
+               printf( "lookup( %s, %d ), stwart=%d, instruct=%d\n", name, s, stwart, instruct );
+               }
+
+       i = 0;
+       for( p=name, j=0; *p != '\0'; ++p ){
+               i += *p;
+               if( ++j >= NCHNAM ) break;
+               }
+       i = i%SYMTSZ;
+       sp = &stab[ii=i];
+
+       for(;;){ /* look for name */
+
+               if( sp->stype == TNULL ){ /* empty slot */
+                       p = sp->sname;
+                       sp->sflags = s;  /* set SMOS if needed, turn off all others */
+                       for( j=0; j<NCHNAM; ++j ) if( *p++ = *name ) ++name;
+                       sp->stype = UNDEF;
+                       sp->sclass = SNULL;
+                       return( i );
+                       }
+               if( (sp->sflags & (SMOS|SHIDDEN)) != s ) goto next;
+               p = sp->sname;
+               q = name;
+               for( j=0; j<NCHNAM;++j ){
+                       if( *p++ != *q ) goto next;
+                       if( !*q++ ) break;
+                       }
+               return( i );
+       next:
+               if( ++i >= SYMTSZ ){
+                       i = 0;
+                       sp = stab;
+                       }
+               else ++sp;
+               if( i == ii ) cerror( "symbol table full" );
+               }
+       }
+
+#ifndef checkst
+/* if not debugging, make checkst a macro */
+checkst(lev){
+       register int s, i, j;
+       register struct symtab *p, *q;
+
+       for( i=0, p=stab; i<SYMTSZ; ++i, ++p ){
+               if( p->stype == TNULL ) continue;
+               j = lookup( p->sname, p->sflags&SMOS );
+               if( j != i ){
+                       q = &stab[j];
+                       if( q->stype == UNDEF ||
+                           q->slevel <= p->slevel ){
+                               cerror( "check error: %.8s", q->sname );
+                               }
+                       }
+               else if( p->slevel > lev ) cerror( "%.8s check at level %d", p->sname, lev );
+               }
+       }
+#endif
+
+struct symtab *
+relook(p) register struct symtab *p; {  /* look up p again, and see where it lies */
+
+       register struct symtab *q;
+
+       /* I'm not sure that this handles towers of several hidden definitions in all cases */
+       q = &stab[lookup( p->sname, p->sflags&(SMOS|SHIDDEN) )];
+       /* make relook always point to either p or an empty cell */
+       if( q->stype == UNDEF ){
+               q->stype = TNULL;
+               return(q);
+               }
+       while( q != p ){
+               if( q->stype == TNULL ) break;
+               if( ++q >= &stab[SYMTSZ] ) q=stab;
+               }
+       return(q);
+       }
+
+clearst( lev ){ /* clear entries of internal scope  from the symbol table */
+       register struct symtab *p, *q, *r;
+       register int temp, rehash;
+
+       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 ) ){
+                               lineno = temp;
+                               uerror( "%.8s undefined", p->sname );
+                               }
+                       else aocode(p);
+                       if (ddebug) printf("removing %8s from stab[ %d], flags %o level %d\n",
+                               p->sname,p-stab,p->sflags,p->slevel);
+                       if( p->sflags & SHIDES ) unhide(p);
+                       p->stype = TNULL;
+                       rehash = 1;
+                       goto next;
+                       }
+               if( rehash ){
+                       if( (r=relook(p)) != p ){
+                               movestab( r, p );
+                               p->stype = TNULL;
+                               }
+                       }
+               next:
+               if( ++p >= &stab[SYMTSZ] ) p = stab;
+               if( p == q ) break;
+               }
+       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;
+       for( k=0; k<NCHNAM; ++k ){
+               p->sname[k] = q->sname[k];
+               }
+       }
+
+hide( p ) register struct symtab *p; {
+       register struct symtab *q;
+       for( q=p+1; ; ++q ){
+               if( q >= &stab[SYMTSZ] ) q = stab;
+               if( q == p ) cerror( "symbol table full" );
+               if( q->stype == TNULL ) break;
+               }
+       movestab( q, p );
+       p->sflags |= SHIDDEN;
+       q->sflags = (p->sflags&SMOS) | SHIDES;
+       if( hflag ) werror( "%.8s redefinition hides earlier one", p->sname );
+       if( ddebug ) printf( "  %d hidden in %d\n", p-stab, q-stab );
+       return( idname = q-stab );
+       }
+
+unhide( p ) register struct symtab *p; {
+       register struct symtab *q;
+       register s, j;
+
+       s = p->sflags & SMOS;
+       q = p;
+
+       for(;;){
+
+               if( q == stab ) q = &stab[SYMTSZ-1];
+               else --q;
+
+               if( q == p ) break;
+
+               if( (q->sflags&SMOS) == s ){
+                       for( j =0; j<NCHNAM; ++j ) if( p->sname[j] != q->sname[j] ) break;
+                       if( j == NCHNAM ){ /* found the name */
+                               q->sflags &= ~SHIDDEN;
+                               if( ddebug ) printf( "unhide uncovered %d from %d\n", q-stab,p-stab);
+                               return;
+                               }
+                       }
+
+               }
+       cerror( "unhide fails" );
+       }