📄 pftn.c
字号:
}/* Declaration check for struct, union, and enum. Are allowed to * specify const || volatile, but no other types. */cvcheck(p)NODE *p;{ NODE *t; unsigned int rtype; rtype = 0; for (t = p; t != NIL; t = t->in.left) { t->in.op = FREE; switch( t->in.type ) { default: bad: uerror( "illegal declaration"); return rtype; case CONST: /* const declaration */ rtype |= BCONST; /* set const bit */ continue; case VOLATILE: /* volatile declaration */ rtype |= BVOLATILE; /* set volatile bit */ continue; } } return rtype;}NODE *tymerge( typ, idp ) NODE *typ, *idp; { /* merge type typ with identifier idp */ register unsigned t; register i; extern int eprint(); if( typ->in.op != TYPE ) cerror( "tymerge: arg 1" ); if(idp == NIL ) return( NIL );# ifndef BUG1 if( ddebug > 2 ) fwalk( idp, eprint, 0 );# endif /* For the case: const x; Types() is not called when only one * type specifier is present. */ if (typ->in.type == CONST) { typ->in.typattr = BCONST; typ->in.type = INT; } else if (typ->in.type == VOLATILE) { typ->in.typattr = BVOLATILE; typ->in.type = INT; } idp->in.type = typ->in.type; idp->fn.cdim = curdim; tyreduce( idp ); idp->in.typattr |= typ->in.typattr; idp->fn.csiz = typ->fn.csiz; for( t=typ->in.type, i=typ->fn.cdim; t&TMASK; t = DECREF(t) ){ if( ISARY(t) ) dstash( dimtab[i++] ); } /* now idp is a single node: fix up type */ idp->in.type = ctype( idp->in.type ); if( (t = BTYPE(idp->in.type)) != STRTY && t != UNIONTY && t != ENUMTY ){ idp->fn.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->in.op; p->in.op = FREE; if( o == NAME ) return; t = INCREF( p->in.type ); if( o == UNARY CALL ) t += (FTN-PTR); else if( o == LB ){ t += (ARY-PTR); temp = p->in.right->tn.lval; p->in.right->in.op = FREE; if( ( temp == 0 ) & ( p->in.left->tn.op == LB ) ) uerror( "Null dimension" ); } p->in.left->in.type = t; p->in.left->in.typattr = INCATTR(p->in.left->in.typattr) | p->in.typattr; tyreduce( p->in.left ); if( o == LB ) dstash( temp ); p->tn.rval = p->in.left->tn.rval; p->in.type = p->in.left->in.type; p->in.typattr = p->in.left->in.typattr; }fixtype( p, class ) register NODE *p; { register unsigned t, type; register mod1, mod2; /* fix up the types, and check for legality */ if( (type = p->in.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 */ /* for example, beware of f(x) struct [ int a[10]; } *x; { ... } */ /* the danger is that "a" will be converted to a pointer */ 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->fn.cdim; type += (PTR-ARY); } else if( ISFTN(type) ){ werror( "a function is declared as an argument" ); type = INCREF(type); } } if( instruct && ISFTN(type) ){ uerror( "function illegal in structure or union" ); type = INCREF(type); } p->in.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 */ } }struct symtab *mknonuniq(idindex) int *idindex; {/* locate a symbol table entry for */ /* an occurrence of a nonunique structure member name */ /* or field */ register i; register struct symtab * sp; char *p,*q; sp = & stab[ i= *idindex ]; /* position search at old entry */ while( sp->stype != TNULL ){ /* locate unused entry */ if( ++i >= SYMTSZ ){/* wrap around symbol table */ i = 0; sp = stab; } else ++sp; if( i == *idindex ) cerror("Symbol table full"); } sp->sflags = SNONUNIQ | SMOS; p = sp->sname; q = stab[*idindex].sname; /* old entry name */#ifdef FLEXNAMES sp->sname = stab[*idindex].sname;#endif# ifndef BUG1 if( ddebug ){ printf("\tnonunique entry for %s from %d to %d\n", q, *idindex, i ); }# endif *idindex = i;#ifndef FLEXNAMES for( i=1; i<=NCHNAM; ++i ){ /* copy name */ if( *p++ = *q /* assign */ ) ++q; }#endif return ( sp ); }lookup( name, s) char *name; { /* look up name: must agree with s w.r.t. STAG, SMOS and SHIDDEN */ register char *p, *q; int i, j, ii; register struct symtab *sp; /* compute initial hash index */# ifndef BUG1 if( ddebug > 2 ){ printf( "lookup( %s, %d ), stwart=%d, instruct=%d\n", name, s, stwart, instruct ); }# endif i = 0;#ifndef FLEXNAMES for( p=name, j=0; *p != '\0'; ++p ){ i += *p; if( ++j >= NCHNAM ) break; }#else i = (int)name;#endif i = i%SYMTSZ; sp = &stab[ii=i]; for(;;){ /* look for name */ if( sp->stype == TNULL ){ /* empty slot */ sp->sflags = s; /* set STAG, SMOS if needed, turn off all others */#ifndef FLEXNAMES p = sp->sname; for( j=0; j<NCHNAM; ++j ) if( *p++ = *name ) ++name;#else sp->sname = name;#endif sp->stype = UNDEF; sp->sclass = SNULL; return( i ); } if( (sp->sflags & (STAG|SMOS|SHIDDEN)) != s ) goto next; p = sp->sname; q = name;#ifndef FLEXNAMES for( j=0; j<NCHNAM;++j ){ if( *p++ != *q ) goto next; if( !*q++ ) break; } return( i );#else if (p == q) return ( i );#endif 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|STAG) ); if( j != i ){ q = &stab[j]; if( q->stype == UNDEF || q->slevel <= p->slevel ){#ifndef FLEXNAMES cerror( "check error: %.8s", q->sname );#else cerror( "check error: %s", q->sname );#endif } }#ifndef FLEXNAMES else if( p->slevel > lev ) cerror( "%.8s check at level %d", p->sname, lev );#else else if( p->slevel > lev ) cerror( "%s check at level %d", p->sname, lev );#endif } }#endifstruct 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&(STAG|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;#ifndef FLEXNAMES uerror( "%.8s undefined", p->sname );#else uerror( "%s undefined", p->sname );#endif } else aocode(p);# ifndef BUG1#ifndef FLEXNAMES if (ddebug) printf("removing %8s from stab[ %d], flags %o level %d\n",#else if (ddebug) printf("removing %s from stab[ %d], flags %o level %d\n",#endif p->sname,p-stab,p->sflags,p->slevel);# endif 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;#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 ){ 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|STAG)) | SHIDES;#ifndef FLEXNAMES if( hflag ) werror( "%.8s redefinition hides earlier one", p->sname );#else if( hflag ) werror( "%s redefinition hides earlier one", p->sname );#endif# ifndef BUG1 if( ddebug ) printf( " %d hidden in %d\n", p-stab, q-stab );# endif return( idname = q-stab ); }unhide( p ) register struct symtab *p; { register struct symtab *q; register s, j; s = p->sflags & (SMOS|STAG); q = p; for(;;){ if( q == stab ) q = &stab[SYMTSZ-1]; else --q; if( q == p ) break; if( (q->sflags&(SMOS|STAG)) == s ){#ifndef FLEXNAMES for( j =0; j<NCHNAM; ++j ) if( p->sname[j] != q->sname[j] ) break; if( j == NCHNAM ){ /* found the name */#else if (p->sname == q->sname) {#endif q->sflags &= ~SHIDDEN;# ifndef BUG1 if( ddebug ) printf( "unhide uncovered %d from %d\n", q-stab,p-stab);# endif return; } } } cerror( "unhide fails" ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -