⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lint.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifndef lintstatic	char sccsid[] = "@(#)lint.c 1.1 92/07/30 SMI"; /* from S5R2 1.7 */#endif#ident	"@(#)RELEASE  lint1 4.1"/* lint.c *	This file contains the major functions for the first pass of lint * *	There are basically two types of functions in this file: *	functions called directly by the portable C compiler and other *	(lint) functions. * *	lint functions: *	=============== *		astype	hashes a struct/union line number to ensure uniqueness *		ctargs	count arguments of a function *		fldcon	check assignment of a constant to a field *		fsave	write out a new filename to the intermediate file *		lmerge *		lprt *		lpta *		main	driver routine for the first pass (lint1) *		outdef	write info out to the intermediate file *		strip	strip a filename down to its basename *		where	print location of an error * *	pcc interface routines: *	======================= *		andable		returns 1 if a node can accept the & operator *		aocode		called when an automatic is removed from symbol table *		asmout		called to put an "asm" into the output *		bfcode		emit code for beginning of function *		branch		dummy, unused by lint *		cinit		 *		clocal		do local transformations on the tree *		commdec		put out a common declaration *		ctype		dummy for lint *		defalign	dummy, unused by lint *		deflab		dummy, unused by lint *		defname		 *		ecode		emit code for tree (lint processing for whole tree) *		efcode		emit code for end of function *		ejobcode	end of job processing *		exname		create external name *		fldal		check field alignment *		fldty		check field type *		isitfloat *		noinit		return storage class for uninitialized objects *		offcon		make structure offset node *		prtdcon *		zecode		create arg integer words of zero */# include "cpass1.h"# include "messages.h"#ifndef CXREF# include "lerror.h"#endif# include "lmanifest.h"# include <ctype.h># include <signal.h># define VAL 0# define EFF 1#if CXREFextern int ddebug, idebug, bdebug, tdebug, edebug, xdebug;int blocknos[20];	/* CXREF */int blockptr = 0;	/* CXREF */int nextblock = 1;	/* CXREF */#endifint vflag = 1;  /* tell about unused argments */#if CXREFint xflag = 0;  /* tell about unused externals */#else/* 28 feb 80  reverse sense of xflag */int xflag = 1;  /* tell about unused externals */#endifint argflag = 0;  /* used to turn off complaints about arguments */int libflag = 0;  /* used to generate library descriptions */int vaflag = -1;  /* used to signal functions with a variable number of args */#if CXREFint aflag = 0;  /* used to check precision of assignments */#else/* 28 feb 80  reverse sense of aflag */int aflag = 1;  /* used to check precision of assignments */int zflag = 0;  /* no 'structure never defined' error */int Cflag = 0;  /* filter out certain output, for generating libraries */#endif#if CXREFchar *flabel = "xxx";int filecount = 0;#endif#ifndef CXREF# ifdef sparc	int host = sparcAL;	int target = sparcAL;# endif# ifdef mc68000	int host = mc68020AL;	int target = mc68020AL;# endif# ifdef i386	int host = i386AL;	int target = i386AL;# endif	char sourcename[ BUFSIZ + 1 ] = "";	char *libname = 0;  /* name of the library we're generating */	char *builtin_va_alist_name;extern struct alignment altable[];extern struct alignment portalign;	/* flags for the "outdef" function */# define USUAL (-101)# define DECTY (-102)# define NOFILE (-103) /* somewhat of a misnomer */# define SVLINE (-104)# define LNAMES 250#else	/* CXREF */# define LNAMES 100#endifstruct lnm {	int lid;	short flgs;	}  lnames[LNAMES], *lnp;/* contx - check context of node *	contx is called for each node during tree walk (fwalk); *	it complains about nodes that have null effect. *	VAL is passed to a child if that child's value is used *	EFF is passed to a child if that child is used in an effects context * *	arguments: *		p - node pointer *		down - value passed down from ancestor *		pl, pr - pointers to values to be passed down to descendants */contx( p, down, pl, pr ) register NODE *p; register *pl, *pr;{	*pl = *pr = VAL;	switch( p->in.op ){		/* left side of ANDAND, OROR, and QUEST always evaluated for value	 	   (value determines if right side is to be evaluated) */		case ANDAND:		case OROR:		case QUEST:			*pr = down; break;		/* left side and right side treated identically */		case SCONV:		case PCONV:		case COLON:			*pr = *pl = down; break;		/* comma operator uses left side for effect */		case COMOP:			*pl = EFF;			*pr = down;		case FORCE:		case INIT:		case UNARY CALL:		case STCALL:		case UNARY STCALL:		case CALL:		case UNARY FORTCALL:		case FORTCALL:		case CBRANCH:			break;		default:			/* assignment ops are OK */			if( asgop(p->in.op) ) break;			/* struct x f( );  main( ) {  (void) f( ); }		 	 *  the cast call appears as U* TVOID			 */			if( p->in.op == UNARY MUL &&				( p->in.type == STRTY				|| p->in.type == UNIONTY				|| p->in.type == TVOID) )				break;  /* the compiler does this... */			/* found a null effect ... */                        if( down == EFF && hflag && p->in.type != TVOID )                                 WERROR( MESSAGE( 86 ) );	}}#ifndef CXREF/* ecode - compile code for node */ecode( p ) NODE *p;{	fwalk( p, contx, EFF );	/* do a preorder tree walk */	lnp = lnames;		/* initialize pointer to start of array */	lprt( p, EFF, 0, 0 );}ejobcode( flag ){	/* called after processing each job */	/* flag is nonzero if errors were detected */	register k;	register struct symtab *p;	int i;	extern		hdrclose( ),			unbuffer( );        for (i=0; i<SYMTSZ; ++i) {                for (p=stab[i]; p!=NULL; p=p->next) {			if( p->stype == STRTY || p->stype == UNIONTY || p->stype == ENUMTY){				if( !zflag && dimtab[p->sizoff+1] < 0 ){					if( hflag ){						if (p->stype == ENUMTY)							/* "enum %s never defined" */							WERROR( MESSAGE( 104 ), p->sname );						else							/* "struct/union %s never defined" */							WERROR( MESSAGE( 102 ), p->sname );						}					}				}			switch( p->sclass ){						case STATIC:				if( p->suse > 0 ){					k = lineno;					lineno = p->suse;					if (ISFTN(p->stype))						/* "static function %s unused" */						UERROR( MESSAGE( 141 ),						    p->sname );					else						/* "static variable %s unused" */						UERROR( MESSAGE( 101 ),						    p->sname );					lineno = k;					break;					}				/* no statics in libraries */				if( Cflag ) break;			case EXTERN:			case USTATIC:				/* with the xflag, worry about externs not used */				/* the filename may be wrong here... */				if( xflag && p->suse >= 0 && !libflag )					outdef( p, LDX, NOFILE );						case EXTDEF:				if( p->suse < 0 )  /* used */					outdef( p, LUM, SVLINE );				break;			}		}	}	hdrclose( );	unbuffer( );	exit( 0 );}/* astype - hash a struct/union/enum line number to ensure uniqueness */astype( t, i ) ATYPE *t;{ TWORD tt;	struct symtab *s;	int k=0, l=0;	if( (tt=BTYPE(t->aty))==STRTY || tt==UNIONTY || tt==ENUMTY ) {		if( i<0 || i>= curdim-3 )			uerror( "lint's little mind is blown" );		else {			s = STP(dimtab[i+3]);			if( s == NULL ) {				k = dimtab[i];				l = X_NONAME;				}			else {				if( s->suse <= 0 )					uerror( "no line number for %s",						s->sname );				else {					k = dimtab[i];					l = hashstr(s->sname);					/* XXX - -p, 8 chars? */					}				}			}				t->extra = k;		t->extra1 = l;		return( 1 );	}	else return( 0 );}/* bfcode - handle the beginning of a function */bfcode( a, n ) int a[];{	/* code for the beginning of a function; a is an array of		indices in stab for the arguments; n is the number */	/* this must also set retlab */	register i;	register struct symtab *cfp;	static ATYPE t;	retlab = 1;	cfp = STP(curftn);	if (cfp == NULL) return;	/* if creating library, don't do static functions */	if( Cflag && cfp->sclass == STATIC ) return;	/* if variable number of arguments,	  only print the ones which will be checked */	if( vaflag >= 0 ) {		if( n < vaflag )		  uerror( "declare the VARARGS arguments you want checked!" );		else n = vaflag;	} else {		/* look for varargs cookie ourselves */		for ( i=0; i<n; ++i) {			if (STP(a[i])->sname == builtin_va_alist_name){				/* make sure it looks legal */				if ( i != n - 1 )					uerror("there are parameters after va_alist");				vaflag = n = i;				break;			}		}	}	fsave( ftitle );	outdef( cfp, cfp->sclass==STATIC? LDS : (libflag?LIB:LDI),		vaflag >= 0 ? -(n + 1) : n );	vaflag = -1;	/* output the arguments */	if( n )		for( i=0; i<n; ++i ) {			register struct symtab *s;			s = STP(a[i]);			if (s == NULL) {				bzero((char *)&t, sizeof(t));				}			else {				t.aty = s->stype;				t.extra = 0;				t.extra1 = 0;				if( !astype( &t, s->sizoff ) ) 					switch( t.aty ){					case ULONG:						break;					case CHAR:					case SHORT:						t.aty = INT;						break;					case UCHAR:					case USHORT:					case UNSIGNED:						t.aty = UNSIGNED;						break;					}				}			fwrite( (char *)&t, sizeof(ATYPE), 1, stdout );			}}/* ctargs - count arguments; p points to at least one */ctargs( p ) NODE *p;{	/* the arguments are a tower of commas to the left */	register c;	c = 1; /* count the rhs */	while( p->in.op == CM ){		++c;		p = p->in.left;		}	return( c );}/* lpta */lpta( p ) NODE *p;{	static ATYPE t;	if( p->in.op == CM ){		lpta( p->in.left );		p = p->in.right;		}	t.aty = p->in.type;	if (p->in.op==ICON) {		t.extra = 1;		t.extra1 = p->tn.lval;	} else {		t.extra = t.extra1 = 0;	}	if( !astype( &t, p->fn.csiz ) )		switch( t.aty ){			case CHAR:			case SHORT:				t.aty = INT;			case LONG:			case ULONG:			case INT:			case UNSIGNED:				break;			case UCHAR:			case USHORT:				t.aty = UNSIGNED;				break;			case FLOAT:				t.aty = DOUBLE;				t.extra = 0;				break;			default:				t.extra = 0;				break;		}	fwrite( (char *)&t, sizeof(ATYPE), 1, stdout );}# define VALSET 1# define VALUSED 2# define VALASGOP 4# define VALADDR 8#define STASG_LEFT  1#define STASG_RIGHT 2lprt( p, down, uses, stasg ) register NODE *p;{	register struct symtab *q;	register acount;	register down1, down2;	register use1, use2;	register struct lnm *np1, *np2;	extern char *htmpname;	/* first, set variables which are set... */	use1 = use2 = VALUSED;	if( p->in.op == ASSIGN ) use1 = VALSET;	else if( p->in.op == UNARY AND ) use1 = VALADDR;	else if( asgop( p->in.op ) && p->in.op != STASG ){ /* =ops */		use1 = VALUSED|VALSET;		if( down == EFF ) use1 |= VALASGOP;		}	/* print the lines for lint */	down2 = down1 = VAL;	acount = 0;	switch( p->in.op ){	case EQ:	case NE:		if( ISUNSIGNED(p->in.left->in.type) &&		    p->in.right->in.op == ICON && p->in.right->tn.lval < 0 &&		    p->in.right->tn.rval == NONAME &&		    !ISUNSIGNED(p->in.right->in.type) )			/* "comparison of unsigned with negative constant" */			WERROR( MESSAGE( 21 ) );		goto charchk;	case GT:	case GE:	case LT:	case LE:		if (p->in.left->in.type == CHAR && p->in.right->in.op == ICON &&		    p->in.right->tn.lval == 0)			/* "nonportable character comparison" */			WERROR(MESSAGE(82));	charchk:		if (p->in.left->in.type == CHAR && p->in.right->in.op==ICON &&		   p->in.right->tn.lval < 0)			/* "nonportable character comparison" */			WERROR( MESSAGE( 82 ) );		break;	case UGE:	case ULT:		if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0		    && p->in.right->tn.rval == NONAME ) {			/* "degenerate unsigned comparison" */			WERROR( MESSAGE( 30 ) );			break;			}	case UGT:	case ULE:	    if ( ISUNSIGNED(p->in.left->in.type) &&		 p->in.right->in.op == ICON &&		 p->in.right->tn.rval == NONAME ) {			/* given the "usual arithmetic conversions", which */			/* apply to relational operators, can this ever */			/* happen? */			if (!ISUNSIGNED( p->in.right->in.type )			    && p->in.right->tn.lval < 0 ) 				/* "comparison of unsigned with negative constant" */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -