SysIII/usr/src/cmd/lint/lpass2.c

Compare this file to the similar file:
Show the results in this format:

# include "manifest"
# include "lerror.h"
# include "lmanifest"
# include "lpass2.h"

# define USED 01
# define VUSED 02
# define EUSED 04
# define RVAL 010
# define VARARGS 0100

# define NSZ 1024
# define TYSZ 2500
# define FSZ 150

STAB stab[NSZ];
STAB *find();

STYPE tary[TYSZ];
STYPE *tget();

char fnm[FSZ][LFNM];

int tfree;  /* used to allocate types */
int ffree;  /* used to save filenames */

struct ty atyp[50];
	/* r is where all the input ends up */
union rec r;

/* 28 feb 80  reverse sense of hflag */
int hflag = 1;
int pflag = 0;
/* 28 feb 80  reverse the sense of the xflag */
int xflag = 1;
int uflag = 1;
int ddddd = 0;

int cfno;  /* current file number */

main( argc, argv ) char *argv[]; {
	register char *p;
	char		*ifilename;
	extern char	*htmpname;


	ifilename = NULL;
	for ( --argc, ++argv; argc > 0; --argc, ++argv ) {
	    if ( **argv == '-' ) {
		p = ++*argv;
		if ( *p == 'H' ) {
		    /* we have here the name of the header buffer file */
		    htmpname = ++p;
		} else if ( *p == 'T' ) {
		    /* we have here the name of the intermediate file */
		    ifilename = ++p;
		} else {
		    for( 	; *p; ++p ){
			switch( *p ){

			case 'h':
				/* 28 feb 80 reverse sense of hflag */
				hflag = 0;
				break;

			case 'p':
				pflag = 1;
				break;

			case 'x':
				/* 28 feb 80  reverse sense of xflag */
				xflag = 0;
				break;

			case 'X':
				ddddd = 1;
				break;

			case 'u':
				uflag = 0;
				break;

			}
		    }
		}
	    }
	}

    tmpopen( );
    unbuffer( );
    if ( !freopen( ifilename, "r", stdin ) ){
		lerror( "cannot open intermediate file", FATAL | CCLOSE | 
			 ERRMSG );
		}

	mloop( LDI|LIB );
	rewind( stdin );
	mloop( LDC|LDX );
	rewind( stdin );
	mloop( LRV|LUV|LUE|LUM );
	cleanup();
	un2buffer( );
	return(0);
	}

mloop( m ){
	/* do the main loop */
	register STAB *q;

	while( lread(m) ){
		q = find();
		if( q->decflag ) chkcompat(q);
		else setuse(q);
		}
	}

lread(m){ /* read a line into r.l */

	register n;

	for(;;) {
		if( fread( (char *)&r, sizeof(r), 1, stdin ) <= 0 ) return(0);
		if( r.l.decflag & LFN ){
			/* new filename */
			setfno( r.f.fn );
			continue;
			}

		n = r.l.nargs;
		if( n<0 ) n = -n;
		if( n ){
			fread( (char *)atyp, sizeof(ATYPE), n, stdin );
			}
		if( ( r.l.decflag & m ) ) return( 1 );
		}
	}

setfno( s ) char *s; {
	/* look up current file names */
	/* first, strip backwards to the beginning or to the first / */
	int i;

	/* now look up s */
	for( i=0; i<ffree; ++i ){
		if( !strncmp( s, fnm[i], LFNM ) ){
			cfno = i;
			return;
			}
		}
	/* make a new entry */
	strncpy( fnm[ffree], s, LFNM );
	cfno = ffree++;
	}

STAB *
find(){
	/* for this to work, NSZ should be a power of 2 */
	register h=0;
	{	register char *p, *q;
		for( h=0,p=r.l.name,q=p+LCHNM; *p&&p<q; ++p) {
			h = (h<<1)+ *p;
			if( h>=NSZ ){
				h = (h+1)&(NSZ-1);
				}
			}
		}
	{	register STAB *p, *q;
		for( p=q= &stab[h]; q->decflag; ){
			/* this call to strncmp should be taken out... */
			if( !strncmp( r.l.name, q->name, LCHNM)) return(q);
			if( ++q >= &stab[NSZ] ) q = stab;
			if( q == p ) lerror( "too many names defined", CCLOSE |
					      FATAL | ERRMSG );
			}
		strncpy( q->name, r.l.name, LCHNM );
		return( q );
		}
	}

STYPE *
tget(){
	if( tfree >= TYSZ ){
		lerror( "too many types needed", CCLOSE | FATAL | ERRMSG );
		}
	return( &tary[tfree++] );
	}

chkcompat(q) STAB *q; {
	/* are the types, etc. in r.l and q compatible */
	register int i;
	STYPE *qq;

	setuse(q);

	/* argument check */

	if( q->decflag & (LDI|LIB|LUV|LUE) ){
		if( r.l.decflag & (LUV|LIB|LUE) ){
			if( q->nargs != r.l.nargs ){
				if( !(q->use&VARARGS) ){
					/* "%.8s: variable # of args." */
					buffer( 7, q );
					}
				if( r.l.nargs > q->nargs ) r.l.nargs = q->nargs;
				if( !(q->decflag & (LDI|LIB) ) ) {
					q->nargs = r.l.nargs;
					q->use |= VARARGS;
					}
				}
			for( i=0,qq=q->symty.next; i<r.l.nargs; ++i,qq=qq->next){
				if( chktype( &qq->t, &atyp[i] ) ){
					/* "%.8s, arg. %d used inconsistently" */
					buffer( 6, q, i+1 );
					}
				}
			}
		}

	if( (q->decflag&(LDI|LIB|LUV)) && r.l.decflag==LUV ){
		if( chktype( &r.l.type, &q->symty.t ) ){
			/* "%.8s value used inconsistently" */
			buffer( 4, q );
			}
		}

	/* check for multiple declaration */

	if( (q->decflag&LDI) && (r.l.decflag&(LDI|LIB)) ){
		/* "%.8s multiply declared" */
		buffer( 3, q );
		}

	/* do a bit of checking of definitions and uses... */

	if( (q->decflag & (LDI|LIB|LDX|LDC|LUM)) && (r.l.decflag & (LDX|LDC|LUM)) && q->symty.t.aty != r.l.type.aty ){
		/* "%.8s value declared inconsistently" */
		buffer( 5, q );
		}

	/* better not call functions which are declared to be structure or union returning */

	if( (q->decflag & (LDI|LIB|LDX|LDC)) && (r.l.decflag & LUE) && q->symty.t.aty != r.l.type.aty ){
		/* only matters if the function returns union or structure */
		TWORD ty;
		ty = q->symty.t.aty;
		if( ISFTN(ty) && ((ty = DECREF(ty))==STRTY || ty==UNIONTY ) ){
			/* "%.8s function value type must be declared before use" */
			buffer( 8, q );
			}
		}

	if( pflag && q->decflag==LDX && r.l.decflag == LUM && !ISFTN(q->symty.t.aty) ){
		/* make the external declaration go away */
		/* in effect, it was used without being defined */
		}
	}

	/* messages for defintion/use */
int	mess[2][2] = {
	12,
	0,
	1,
	2
};

lastone(q) STAB *q; {

	register nu, nd, uses;

	if( ddddd ) pst(q);

	nu = nd = 0;
	uses = q->use;

	if( !(uses&USED) && q->decflag != LIB ) {
		if( strncmp(q->name,"main",7) )
			nu = 1;
		}

	if( !ISFTN(q->symty.t.aty) ){
		switch( q->decflag ){

		case LIB:
			nu = nd = 0;  /* don't complain about uses on libraries */
			break;
		case LDX:
			if( !xflag ) break;
		case LUV:
		case LUE:
/* 01/04/80 */	case LUV | LUE:
		case LUM:
			nd = 1;
			}
		}
	if( uflag && ( nu || nd ) ) buffer( mess[nu][nd], q );

	if( (uses&(RVAL+EUSED)) == (RVAL+EUSED) ){
	    if ( uses & VUSED ) {
		/* "%.8s returns value which is sometimes ignored\n" */
		buffer( 11, q );
	    } else {
		/* "%.8s returns value which is always ignored\n" */
		buffer( 10, q );
	    }
		}

	if( (uses&(RVAL+VUSED)) == (VUSED) && (q->decflag&(LDI|LIB)) ){
		/* "%.8s value is used, but none returned\n" */
		buffer( 9, q );
		}
	}

cleanup(){ /* call lastone and die gracefully */
	STAB *q;
	for( q=stab; q< &stab[NSZ]; ++q ){
		if( q->decflag ) lastone(q);
		}
	return;
	}

setuse(q) STAB *q; { /* check new type to ensure that it is used */

	if( !q->decflag ){ /* new one */
		q->decflag = r.l.decflag;
		q->symty.t = r.l.type;
		if( r.l.nargs < 0 ){
			q->nargs = -r.l.nargs;
			q->use = VARARGS;
			}
		else {
			q->nargs = r.l.nargs;
			q->use = 0;
			}
		q->fline = r.l.fline;
		q->fno = cfno;
		if( q->nargs ){
			int i;
			STYPE *qq;
			for( i=0,qq= &q->symty; i<q->nargs; ++i,qq=qq->next ){
				qq->next = tget();
				qq->next->t = atyp[i];
				}
			}
		}

	switch( r.l.decflag ){

	case LRV:
		q->use |= RVAL;
		return;
	case LUV:
		q->use |= VUSED+USED;
		return;
	case LUE:
		q->use |= EUSED+USED;
		return;
/* 01/04/80 */	case LUV | LUE:
	case LUM:
		q->use |= USED;
		return;

		}
	}

chktype( pt1, pt2 ) register ATYPE *pt1, *pt2; {
	TWORD t;

	/* 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( (t=BTYPE(pt1->aty)==STRTY) || t==UNIONTY ){
		return( pt1->aty!=pt2->aty || pt1->extra!=pt2->extra );
		}

	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 );
	}

struct tb { int m; char * nm };
ptb( v, tp ) struct tb *tp; {
	/* print a value from the table */
	int flag;
	flag = 0;
	for( ; tp->m; ++tp ){
		if( v&tp->m ){
			if( flag++ ) putchar( '|' );
			printf( "%s", tp->nm );
			}
		}
	}

pst( q ) STAB *q; {
	/* give a debugging output for q */
	static struct tb dfs[] = {
		LDI, "LDI",
		LIB, "LIB",
		LDC, "LDC",
		LDX, "LDX",
		LRV, "LRV",
		LUV, "LUV",
		LUE, "LUE",
		LUM, "LUM",
		0, "" };

	static struct tb us[] = {
		USED, "USED",
		VUSED, "VUSED",
		EUSED, "EUSED",
		RVAL, "RVAL",
		VARARGS, "VARARGS",
		0,	0,
		};

	printf( "%.8s (", q->name );
	ptb( q->decflag, dfs );
	printf( "), use= " );
	ptb( q->use, us );
	printf( ", line %d, nargs=%d\n", q->fline, q->nargs );
	}