home *** CD-ROM | disk | FTP | other *** search
- # include "lmanifest"
- # include "manifest"
-
- # define USED 01
- # define VUSED 02
- # define EUSED 04
- # define RVAL 010
- # define VARARGS 0100
-
- typedef struct { TWORD aty; int extra; } atype;
-
- struct line {
- char name[8];
- int decflag;
- atype type;
- int nargs;
- atype atyp[50];
- int fline;
- char file[100];
- }
-
- l1,
- l2,
- *pd, /* pointer to line having definition */
- *pc, /* pointer to current line read */
- *p3; /* used for swapping pc and pd */
-
- int uses = USED;
- int hflag = 0;
- int pflag = 0;
- int xflag = 0;
- int uflag = 1;
-
-
- main( argc, argv ) char *argv[]; {
-
- register char *p;
-
- /* first argument is - options */
-
- if( argc>=2 && argv[1][0] == '-' ){
- for( p=argv[1]; *p; ++p ){
- switch( *p ){
-
- case 'h':
- hflag = 1;
- break;
-
- case 'p':
- pflag = 1;
- break;
-
- case 'x':
- xflag = 1;
- break;
-
- case 'u':
- uflag = 0;
- break;
-
- }
- }
- }
-
-
-
- pd = &l1;
- pc = &l2;
- pd->name[0] = '\0' ;
- pd->fline = 0;
- pd->file[0] = '\0';
- pd->decflag = LDI;
-
- /* main loop: read a line;
- if same as last line, check compatibility
- if not same as last line, becomes df.
- */
-
- for(;;){
- lread();
- if( steq(pc->name, pd->name) ) chkcompat();
- else {
- lastone();
- setuse();
- p3=pc;
- pc = pd;
- pd = p3;
- }
- }
-
- }
-
- lread(){ /* read a line into pc */
-
- register i, n;
-
- getnam( pc->name );
-
- pc->decflag = rdin10();
- rdinty( &pc->type );
- n = pc->nargs = rdin10();
- if( n<0 ) n = -n;
-
- for( i=0; i<n; ++i ){
- rdinty( &pc->atyp[i] );
- }
-
- getnam( pc->file );
- pc->fline = rdin10();
-
- while( getchar() != '\n' ) ; /* VOID */
- }
-
- rdin10(){
- register val, c, s;
-
- val = 0;
- s = 1;
-
- while( (c=getchar()) != '\t' ){
- if( c <= 0 ) error( "unexpected EOF" );
- else if( c == '-' ) {
- s = -1;
- continue;
- }
- else if( c<'0' || c>'9' ) {
- error("rotten digit: %o\n", c );
- }
- val = val*10 + c - '0';
- }
- return( val*s );
- }
-
- rdinty( p ) atype *p; {
- register val, c, s;
-
- val = 0;
- s = 1;
-
- while( (c=getchar()) != '\t' && c!= '<' ){
- if( c <= 0 ) error( "unexpected EOF" );
- else if( c == '-' ) {
- s = -1;
- continue;
- }
- else if( c<'0' || c>'7' ) {
- error("rotten digit: %o\n", c );
- }
- val = (val<<3) + c - '0';
- }
- p->aty = val*s;
- if( c == '<' ) p->extra = rdin10();
- else p->extra = 0;
- }
-
- getnam(p) char *p; {
- register c;
- while( (c=getchar()) != '\t' ){
- if( c == '\n' ) error( "rotten name\n" );
- if( c <= 0 ) cleanup();
- *p++ = c;
- }
- *p = '\0';
- }
-
- /* VARARGS */
- error( s, a ) char *s; {
-
- fprintf( stderr, "pass 2 error: " );
- fprintf( stderr, s, a );
- fprintf( stderr, "\n" );
- exit(1);
- }
-
- steq(p,q) char *p,*q; { /* check that the p and q names are the same */
-
-
- while( *p == *q ){
- if( *p == 0 ) return(1);
- ++p;
- ++q;
- }
-
- return(0);
- }
-
- chkcompat(){
- /* are the types, etc. in pc and pd compatible */
- register int i;
-
- setuse();
-
- /* argument check */
-
- if( pd->decflag & (LDI|LIB|LUV|LUE) ){
- if( pc->decflag & (LUV|LIB|LUE) ){
- if( pd->nargs != pc->nargs ){
- if( !(uses&VARARGS) ){
- printf( "%.7s: variable # of args.", pd->name );
- viceversa();
- }
- if( pc->nargs > pd->nargs ) pc->nargs = pd->nargs;
- if( !(pd->decflag & (LDI|LIB) ) ) {
- pd->nargs = pc->nargs;
- uses |= VARARGS;
- }
- }
- for( i=0; i<pc->nargs; ++i ){
- if( chktype(&pd->atyp[i], &pc->atyp[i]) ){
- printf( "%.7s, arg. %d used inconsistently",
- pd->name, i+1 );
- viceversa();
- }
- }
- }
- }
-
- if( (pd->decflag&(LDI|LIB|LUV)) && pc->decflag==LUV ){
- if( chktype( &pc->type, &pd->type ) ){
- printf( "%.7s value used inconsistently", pd->name );
- viceversa();
- }
- }
-
- /* check for multiple declaration */
-
- if( (pd->decflag&LDI) && (pc->decflag&(LDI|LIB)) ){
- printf( "%.7s multiply declared", pd->name );
- viceversa();
- }
-
- /* do a bit of checking of definitions and uses... */
-
- if( (pd->decflag & (LDI|LIB|LDX|LDC)) && (pc->decflag & (LDX|LDC)) && pd->type.aty != pc->type.aty ){
- printf( "%.7s value declared inconsistently", pd->name );
- viceversa();
- }
-
- /* better not call functions which are declared to be structure or union returning */
-
- if( (pd->decflag & (LDI|LIB|LDX|LDC)) && (pc->decflag & LUE) && pd->type.aty != pc->type.aty ){
- /* only matters if the function returns union or structure */
- TWORD ty;
- ty = pd->type.aty;
- if( ISFTN(ty) && ((ty = DECREF(ty))==STRTY || ty==UNIONTY ) ){
- printf( "%.7s function value type must be declared before use", pd->name );
- viceversa();
- }
- }
-
- if( pflag && pd->decflag==LDX && pc->decflag == LUM && !ISFTN(pd->type.aty) ){
- /* make the external declaration go away */
- /* in effect, it was used without being defined */
-
- /* swap pc and pd */
- p3 = pc;
- pc = pd;
- pd = p3;
- }
-
- }
-
- viceversa(){
- /* print out file comparison */
- printf( " %s(%d) :: %s(%d)\n", pd->file, pd->fline, pc->file, pc->fline );
- }
-
- /* messages for defintion/use */
- char *
- mess[2][2] = {
- "",
- "%.7s used( %s(%d) ), but not defined\n",
- "%.7s defined( %s(%d) ), but never used\n",
- "%.7s declared( %s(%d) ), but never used or defined\n"
- };
-
- lastone(){
-
- /* called when pc and pd are at last different */
- register nu, nd;
-
- nu = nd = 0;
-
- if( !(uses&USED) && pd->decflag != LIB ) {
- if( !steq(pd->name,"main") )
- nu = 1;
- }
-
- if( !ISFTN(pd->type.aty) ){
- switch( pd->decflag ){
-
- case LIB:
- nu = nd = 0; /* don't complain about uses on libraries */
- break;
- case LDX:
- if( !xflag ) break;
- case LUV:
- case LUE:
- case LUM:
- nd = 1;
- }
- }
-
- if( uflag && ( nu || nd ) ) printf( mess[nu][nd], pd->name, pd->file, pd->fline );
-
- if( (uses&(RVAL+EUSED)) == (RVAL+EUSED) ){
- printf( "%.7s returns value which is %s ignored\n", pd->name,
- uses&VUSED ? "sometimes" : "always" );
- }
-
- if( (uses&(RVAL+VUSED)) == (VUSED) && (pd->decflag&(LDI|LIB)) ){
- printf( "%.7s value is used, but none returned\n", pd->name );
- }
-
- /* clean up pc, in preparation for the next thing */
-
- uses = 0;
- if( pc->nargs < 0 ){
- pc->nargs = -pc->nargs;
- uses = VARARGS;
- }
-
- }
-
- cleanup(){ /* call lastone and die gracefully */
- lastone();
- exit(0);
- }
-
- setuse(){ /* check new type to ensure that it is used */
-
- switch( pc->decflag ){
-
- case LRV:
- uses |= RVAL;
- return;
- case LUV:
- uses |= VUSED+USED;
- return;
- case LUE:
- uses |= EUSED+USED;
- return;
- case LUM:
- uses |= USED;
- return;
-
- }
- }
-
- chktype( pt1, pt2 ) register atype *pt1, *pt2; {
-
- /* check the two type words to see if they are compatible */
- /* for the moment, enums are turned into ints, and should be checked as such */
- if( pt1->aty == ENUMTY ) pt1->aty = INT;
- if( pt2->aty == ENUMTY ) pt2->aty = INT;
-
- if( pt2->extra ){ /* constant passed in */
- if( pt1->aty == UNSIGNED && pt2->aty == INT ) return( 0 );
- else if( pt1->aty == ULONG && pt2->aty == LONG ) return( 0 );
- }
- else if( pt1->extra ){ /* for symmetry */
- if( pt2->aty == UNSIGNED && pt1->aty == INT ) return( 0 );
- else if( pt2->aty == ULONG && pt1->aty == LONG ) return( 0 );
- }
-
- return( pt1->aty != pt2->aty );
- }
-