xref: /original-bsd/old/pcc/lint/lpass1/lint.c (revision 7e7b101a)
1 #ifndef lint
2 static char sccsid[] = "@(#)lint.c	1.6	(Berkeley)	04/08/85";
3 #endif lint
4 
5 # include "pass1.h"
6 
7 # include "lmanifest.h"
8 
9 # include <ctype.h>
10 
11 # define VAL 0
12 # define EFF 1
13 
14 /* these are appropriate for the -p flag */
15 int  SZCHAR = 8;
16 int  SZINT = 16;
17 int  SZFLOAT = 32;
18 int  SZDOUBLE = 64;
19 int  SZLONG = 32;
20 int  SZSHORT = 16;
21 int SZPOINT = 16;
22 int ALCHAR = 8;
23 int ALINT = 16;
24 int ALFLOAT = 32;
25 int ALDOUBLE = 64;
26 int ALLONG = 32;
27 int ALSHORT = 16;
28 int ALPOINT = 16;
29 int ALSTRUCT = 16;
30 
31 int vflag = 1;  /* tell about unused argments */
32 int xflag = 0;  /* tell about unused externals */
33 int argflag = 0;  /* used to turn off complaints about arguments */
34 int libflag = 0;  /* used to generate library descriptions */
35 int vaflag = -1;  /* used to signal functions with a variable number of args */
36 int aflag = 0;  /* used to check precision of assignments */
37 int zflag = 0;  /* no 'structure never defined' error */
38 int Cflag = 0;  /* filter out certain output, for generating libraries */
39 char *libname = 0;  /* name of the library we're generating */
40 
41 	/* flags for the "outdef" function */
42 # define USUAL (-101)
43 # define DECTY (-102)
44 # define NOFILE (-103)
45 # define SVLINE (-104)
46 
47 # define LNAMES 250
48 
49 struct lnm {
50 	short lid, flgs;
51 	}  lnames[LNAMES], *lnp;
52 
53 contx( p, down, pl, pr ) register NODE *p; register *pl, *pr; {
54 
55 	*pl = *pr = VAL;
56 	switch( p->in.op ){
57 
58 	case ANDAND:
59 	case OROR:
60 	case QUEST:
61 		*pr = down;
62 		break;
63 
64 	case SCONV:
65 	case PCONV:
66 	case COLON:
67 		*pr = *pl = down;
68 		break;
69 
70 	case COMOP:
71 		*pl = EFF;
72 		*pr = down;
73 
74 	case FORCE:
75 	case INIT:
76 	case UNARY CALL:
77 	case STCALL:
78 	case UNARY STCALL:
79 	case CALL:
80 	case UNARY FORTCALL:
81 	case FORTCALL:
82 	case CBRANCH:
83 		break;
84 
85 	default:
86 		if( asgop(p->in.op) ) break;
87 		if( p->in.op == UNARY MUL && ( p->in.type == STRTY || p->in.type == UNIONTY || p->in.type == UNDEF) ) {
88 		/* struct x f( );  main( ) {  (void) f( ); }
89 		 * the the cast call appears as U* UNDEF
90 		 */
91 			break;  /* the compiler does this... */
92 			}
93 		if( down == EFF && hflag ) werror( "null effect" );
94 
95 		}
96 	}
97 
98 ecode( p ) NODE *p; {
99 	/* compile code for p */
100 
101 	fwalk( p, contx, EFF );
102 	lnp = lnames;
103 	lprt( p, EFF, 0 );
104 	}
105 
106 ejobcode( flag ){
107 	/* called after processing each job */
108 	/* flag is nonzero if errors were detected */
109 	register k;
110 	register struct symtab *p;
111 
112 	for( p=stab; p< &stab[SYMTSZ]; ++p ){
113 
114 		if( p->stype != TNULL ) {
115 
116 			if( p->stype == STRTY || p->stype == UNIONTY ){
117 				if( !zflag && dimtab[p->sizoff+1] < 0 ){
118 					/* never defined */
119 #ifndef FLEXNAMES
120 					if( hflag ) werror( "struct/union %.8s never defined", p->sname );
121 #else
122 					if( hflag ) werror( "struct/union %s never defined", p->sname );
123 #endif
124 					}
125 				}
126 
127 			switch( p->sclass ){
128 
129 			case STATIC:
130 				if( p->suse > 0 ){
131 					k = lineno;
132 					lineno = p->suse;
133 #ifndef FLEXNAMES
134 					uerror( "static variable %.8s unused",
135 #else
136 					uerror( "static variable %s unused",
137 #endif
138 						p->sname );
139 					lineno = k;
140 					break;
141 					}
142 				/* no statics in libraries */
143 				if( Cflag ) break;
144 
145 			case EXTERN:
146 			case USTATIC:
147 				/* with the xflag, worry about externs not used */
148 				/* the filename may be wrong here... */
149 				if( xflag && p->suse >= 0 && !libflag ){
150 					outdef( p, LDX, NOFILE );
151 					}
152 
153 			case EXTDEF:
154 				if( p->suse < 0 ){  /* used */
155 					outdef( p, LUM, SVLINE );
156 					}
157 				break;
158 				}
159 
160 			}
161 
162 		}
163 	exit( 0 );
164 	}
165 
166 astype( t, i ) ATYPE *t; {
167 	TWORD tt;
168 	int j, k=0, l=0;
169 
170 	if( (tt=BTYPE(t->aty))==STRTY || tt==UNIONTY ){
171 		if( i<0 || i>= DIMTABSZ-3 ){
172 			werror( "lint's little mind is blown" );
173 			}
174 		else {
175 			j = dimtab[i+3];
176 			if( j<0 || j>SYMTSZ ){
177 				k = dimtab[i];
178 				l = X_NONAME | stab[j].suse;
179 				}
180 			else {
181 				if( stab[j].suse <= 0 ) {
182 #ifndef FLEXNAMES
183 					werror( "no line number for %.8s",
184 #else
185 					werror( "no line number for %s",
186 #endif
187 						stab[j].sname );
188 					}
189 				else {
190 					k = dimtab[i];
191 #ifdef FLEXNAMES
192 					l = hashstr(stab[j].sname);
193 #else
194 					l = hashstr(stab[j].sname, LCHNM);
195 #endif
196 					}
197 				}
198 			}
199 
200 		t->extra = k;
201 		t->extra1 = l;
202 		return( 1 );
203 		}
204 	else return( 0 );
205 	}
206 
207 bfcode( a, n ) int a[]; {
208 	/* code for the beginning of a function; a is an array of
209 		indices in stab for the arguments; n is the number */
210 	/* this must also set retlab */
211 	register i;
212 	register struct symtab *cfp;
213 	static ATYPE t;
214 
215 	retlab = 1;
216 
217 	cfp = &stab[curftn];
218 
219 	/* if creating library, don't do static functions */
220 	if( Cflag && cfp->sclass == STATIC ) return;
221 
222 	/* if variable number of arguments, only print the ones which will be checked */
223 	if( vaflag > 0 ){
224 		if( n < vaflag ) werror( "declare the VARARGS arguments you want checked!" );
225 		else n = vaflag;
226 		}
227 	fsave( ftitle );
228 	if( cfp->sclass == STATIC ) outdef( cfp, LST, vaflag>=0?-n:n );
229 	else outdef( cfp, libflag?LIB:LDI, vaflag>=0?-n:n );
230 	vaflag = -1;
231 
232 	/* output the arguments */
233 	if( n ){
234 		for( i=0; i<n; ++i ) {
235 			t.aty = stab[a[i]].stype;
236 			t.extra = 0;
237 			t.extra1 = 0;
238 			if( !astype( &t, stab[a[i]].sizoff ) ) {
239 				switch( t.aty ){
240 
241 				case ULONG:
242 					break;
243 
244 				case CHAR:
245 				case SHORT:
246 					t.aty = INT;
247 					break;
248 
249 				case UCHAR:
250 				case USHORT:
251 				case UNSIGNED:
252 					t.aty = UNSIGNED;
253 					break;
254 
255 					}
256 				}
257 			fwrite( (char *)&t, sizeof(ATYPE), 1, stdout );
258 			}
259 		}
260 	}
261 
262 ctargs( p ) NODE *p; {
263 	/* count arguments; p points to at least one */
264 	/* the arguemnts are a tower of commas to the left */
265 	register c;
266 	c = 1; /* count the rhs */
267 	while( p->in.op == CM ){
268 		++c;
269 		p = p->in.left;
270 		}
271 	return( c );
272 	}
273 
274 lpta( p ) NODE *p; {
275 	static ATYPE t;
276 
277 	if( p->in.op == CM ){
278 		lpta( p->in.left );
279 		p = p->in.right;
280 		}
281 
282 	t.aty = p->in.type;
283 	t.extra = (p->in.op==ICON);
284 	t.extra1 = 0;
285 
286 	if( !astype( &t, p->fn.csiz ) ) {
287 		switch( t.aty ){
288 
289 			case CHAR:
290 			case SHORT:
291 				t.aty = INT;
292 			case LONG:
293 			case ULONG:
294 			case INT:
295 			case UNSIGNED:
296 				break;
297 
298 			case UCHAR:
299 			case USHORT:
300 				t.aty = UNSIGNED;
301 				break;
302 
303 			case FLOAT:
304 				t.aty = DOUBLE;
305 				t.extra = 0;
306 				break;
307 
308 			default:
309 				t.extra = 0;
310 				break;
311 			}
312 		}
313 	fwrite( (char *)&t, sizeof(ATYPE), 1, stdout );
314 	}
315 
316 # define VALSET 1
317 # define VALUSED 2
318 # define VALASGOP 4
319 # define VALADDR 8
320 
321 lprt( p, down, uses ) register NODE *p; {
322 	register struct symtab *q;
323 	register id;
324 	register acount;
325 	register down1, down2;
326 	register use1, use2;
327 	register struct lnm *np1, *np2;
328 
329 	/* first, set variables which are set... */
330 
331 	use1 = use2 = VALUSED;
332 	if( p->in.op == ASSIGN ) use1 = VALSET;
333 	else if( p->in.op == UNARY AND ) use1 = VALADDR;
334 	else if( asgop( p->in.op ) ){ /* =ops */
335 		use1 = VALUSED|VALSET;
336 		if( down == EFF ) use1 |= VALASGOP;
337 		}
338 
339 
340 	/* print the lines for lint */
341 
342 	down2 = down1 = VAL;
343 	acount = 0;
344 
345 	switch( p->in.op ){
346 
347 	case EQ:
348 	case NE:
349 	case GT:
350 	case GE:
351 	case LT:
352 	case LE:
353 		if( p->in.left->in.type == CHAR && p->in.right->in.op==ICON && p->in.right->tn.lval < 0 ){
354 			werror( "nonportable character comparison" );
355 			}
356 		if( (p->in.op==EQ || p->in.op==NE ) && ISUNSIGNED(p->in.left->in.type) && p->in.right->in.op == ICON ){
357 			if( p->in.right->tn.lval < 0 && p->in.right->tn.rval == NONAME && !ISUNSIGNED(p->in.right->in.type) ){
358 				werror( "comparison of unsigned with negative constant" );
359 				}
360 			}
361 		break;
362 
363 	case UGE:
364 	case ULT:
365 		if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->tn.rval == NONAME ){
366 			werror( "unsigned comparison with 0?" );
367 			break;
368 			}
369 	case UGT:
370 	case ULE:
371 		if( p->in.right->in.op == ICON && p->in.right->tn.lval <= 0 && !ISUNSIGNED(p->in.right->in.type) && p->in.right->tn.rval == NONAME ){
372 			werror( "degenerate unsigned comparison" );
373 			}
374 		break;
375 
376 	case COMOP:
377 		down1 = EFF;
378 
379 	case ANDAND:
380 	case OROR:
381 	case QUEST:
382 		down2 = down;
383 		/* go recursively left, then right  */
384 		np1 = lnp;
385 		lprt( p->in.left, down1, use1 );
386 		np2 = lnp;
387 		lprt( p->in.right, down2, use2 );
388 		lmerge( np1, np2, 0 );
389 		return;
390 
391 	case SCONV:
392 	case PCONV:
393 	case COLON:
394 		down1 = down2 = down;
395 		break;
396 
397 	case CALL:
398 	case STCALL:
399 	case FORTCALL:
400 		acount = ctargs( p->in.right );
401 	case UNARY CALL:
402 	case UNARY STCALL:
403 	case UNARY FORTCALL:
404 		if( p->in.left->in.op == ICON && (id=p->in.left->tn.rval) != NONAME ){ /* used to be &name */
405 			struct symtab *sp = &stab[id];
406 			int lty;
407 
408 			fsave( ftitle );
409 			/*
410 			 * if we're generating a library -C then
411 			 * we don't want to output references to functions
412 			 */
413 			if( Cflag ) break;
414 			/*  if a function used in an effects context is
415 			 *  cast to type  void  then consider its value
416 			 *  to have been disposed of properly
417 			 *  thus a call of type  undef  in an effects
418 			 *  context is construed to be used in a value
419 			 *  context
420 			 */
421 			if ((down == EFF) && (p->in.type != UNDEF)) {
422 				lty = LUE;
423 			} else if (down == EFF) {
424 				lty = LUV | LUE;
425 			} else {
426 				lty = LUV;
427 			}
428 			outdef( sp, lty, acount );
429 			if( acount ) {
430 				lpta( p->in.right );
431 				}
432 			}
433 		break;
434 
435 	case ICON:
436 		/* look for &name case */
437 		if( (id = p->tn.rval) >= 0 && id != NONAME ){
438 			q = &stab[id];
439 			q->sflags |= (SREF|SSET);
440 			q->suse = -lineno;
441 			}
442 		return;
443 
444 	case NAME:
445 		if( (id = p->tn.rval) >= 0 && id != NONAME ){
446 			q = &stab[id];
447 			if( (uses&VALUSED) && !(q->sflags&SSET) ){
448 				if( q->sclass == AUTO || q->sclass == REGISTER ){
449 					if( !ISARY(q->stype ) && !ISFTN(q->stype) && q->stype!=STRTY && q->stype!=UNIONTY ){
450 #ifndef FLEXNAMES
451 						werror( "%.8s may be used before set", q->sname );
452 #else
453 						werror( "%s may be used before set", q->sname );
454 #endif
455 						q->sflags |= SSET;
456 						}
457 					}
458 				}
459 			if( uses & VALASGOP ) break;  /* not a real use */
460 			if( uses & VALSET ) q->sflags |= SSET;
461 			if( uses & VALUSED ) q->sflags |= SREF;
462 			if( uses & VALADDR ) q->sflags |= (SREF|SSET);
463 			if( p->tn.lval == 0 ){
464 				lnp->lid = id;
465 				lnp->flgs = (uses&VALADDR)?0:((uses&VALSET)?VALSET:VALUSED);
466 				if( ++lnp >= &lnames[LNAMES] ) --lnp;
467 				}
468 			}
469 		return;
470 
471 		}
472 
473 	/* recurse, going down the right side first if we can */
474 
475 	switch( optype(p->in.op) ){
476 
477 	case BITYPE:
478 		np1 = lnp;
479 		lprt( p->in.right, down2, use2 );
480 	case UTYPE:
481 		np2 = lnp;
482 		lprt( p->in.left, down1, use1 );
483 		}
484 
485 	if( optype(p->in.op) == BITYPE ){
486 		if( p->in.op == ASSIGN && p->in.left->in.op == NAME ){ /* special case for a =  .. a .. */
487 			lmerge( np1, np2, 0 );
488 			}
489 		else lmerge( np1, np2, p->in.op != COLON );
490 		/* look for assignments to fields, and complain */
491 		if( p->in.op == ASSIGN && p->in.left->in.op == FLD && p->in.right->in.op == ICON ) fldcon( p );
492 		}
493 
494 	}
495 
496 lmerge( np1, np2, flag ) struct lnm *np1, *np2; {
497 	/* np1 and np2 point to lists of lnm members, for the two sides
498 	 * of a binary operator
499 	 * flag is 1 if commutation is possible, 0 otherwise
500 	 * lmerge returns a merged list, starting at np1, resetting lnp
501 	 * it also complains, if appropriate, about side effects
502 	 */
503 
504 	register struct lnm *npx, *npy;
505 
506 	for( npx = np2; npx < lnp; ++npx ){
507 
508 		/* is it already there? */
509 		for( npy = np1; npy < np2; ++npy ){
510 			if( npx->lid == npy->lid ){ /* yes */
511 				if( npx->flgs == 0 || npx->flgs == (VALSET|VALUSED) )
512 					;  /* do nothing */
513 				else if( (npx->flgs|npy->flgs)== (VALSET|VALUSED) ||
514 					(npx->flgs&npy->flgs&VALSET) ){
515 #ifndef FLEXNAMES
516 					if( flag ) werror( "%.8s evaluation order undefined", stab[npy->lid].sname );
517 #else
518 					if( flag ) werror( "%s evaluation order undefined", stab[npy->lid].sname );
519 #endif
520 					}
521 				if( npy->flgs == 0 ) npx->flgs = 0;
522 				else npy->flgs |= npx->flgs;
523 				goto foundit;
524 				}
525 			}
526 
527 		/* not there: update entry */
528 		np2->lid = npx->lid;
529 		np2->flgs = npx->flgs;
530 		++np2;
531 
532 		foundit: ;
533 		}
534 
535 	/* all finished: merged list is at np1 */
536 	lnp = np2;
537 	}
538 
539 efcode(){
540 	/* code for the end of a function */
541 	register struct symtab *cfp;
542 
543 	cfp = &stab[curftn];
544 	if( retstat & RETVAL && !(Cflag && cfp->sclass==STATIC) )
545 		outdef( cfp, LRV, DECTY );
546 	if( !vflag ){
547 		vflag = argflag;
548 		argflag = 0;
549 		}
550 	if( retstat == RETVAL+NRETVAL )
551 #ifndef FLEXNAMES
552 		werror( "function %.8s has return(e); and return;", cfp->sname);
553 #else
554 		werror( "function %s has return(e); and return;", cfp->sname);
555 #endif
556 	}
557 
558 aocode(p) struct symtab *p; {
559 	/* called when automatic p removed from stab */
560 	register struct symtab *cfs;
561 	cfs = &stab[curftn];
562 	if(p->suse>0 && !(p->sflags&(SMOS|STAG)) ){
563 		if( p->sclass == PARAM ){
564 #ifndef FLEXNAMES
565 			if( vflag ) werror( "argument %.8s unused in function %.8s",
566 #else
567 			if( vflag ) werror( "argument %s unused in function %s",
568 #endif
569 				p->sname,
570 				cfs->sname );
571 			}
572 		else {
573 #ifndef FLEXNAMES
574 			if( p->sclass != TYPEDEF ) werror( "%.8s unused in function %.8s",
575 #else
576 			if( p->sclass != TYPEDEF ) werror( "%s unused in function %s",
577 #endif
578 				p->sname, cfs->sname );
579 			}
580 		}
581 
582 	if( p->suse < 0 && (p->sflags & (SSET|SREF|SMOS)) == SSET &&
583 		!ISARY(p->stype) && !ISFTN(p->stype) ){
584 
585 #ifndef FLEXNAMES
586 		werror( "%.8s set but not used in function %.8s", p->sname, cfs->sname );
587 #else
588 		werror( "%s set but not used in function %s", p->sname, cfs->sname );
589 #endif
590 		}
591 
592 	if( p->stype == STRTY || p->stype == UNIONTY || p->stype == ENUMTY ){
593 		if( !zflag && dimtab[p->sizoff+1] < 0 )
594 #ifndef FLEXNAMES
595 			werror( "structure %.8s never defined", p->sname );
596 #else
597 			werror( "structure %s never defined", p->sname );
598 #endif
599 		}
600 
601 	}
602 
603 defnam( p ) register struct symtab *p; {
604 	/* define the current location as the name p->sname */
605 
606 	if( p->sclass == STATIC && (p->slevel>1 || Cflag) ) return;
607 
608 	if( !ISFTN( p->stype ) )
609 		if( p->sclass == STATIC ) outdef( p, LST, USUAL );
610 		else outdef( p, libflag?LIB:LDI, USUAL );
611 	}
612 
613 zecode( n ){
614 	/* n integer words of zeros */
615 	OFFSZ temp;
616 	temp = n;
617 	inoff += temp*SZINT;
618 	;
619 	}
620 
621 andable( p ) NODE *p; {  /* p is a NAME node; can it accept & ? */
622 	register r;
623 
624 	if( p->in.op != NAME ) cerror( "andable error" );
625 
626 	if( (r = p->tn.rval) < 0 ) return(1);  /* labels are andable */
627 
628 	if( stab[r].sclass == AUTO || stab[r].sclass == PARAM ) return(0);
629 #ifndef FLEXNAMES
630 	if( stab[r].sclass == REGISTER ) uerror( "can't take & of %.8s", stab[r].sname );
631 #else
632 	if( stab[r].sclass == REGISTER ) uerror( "can't take & of %s", stab[r].sname );
633 #endif
634 	return(1);
635 	}
636 
637 NODE *
638 clocal(p) NODE *p; {
639 
640 	/* this is called to do local transformations on
641 	   an expression tree preparitory to its being
642 	   written out in intermediate code.
643 	*/
644 
645 	/* the major essential job is rewriting the
646 	   automatic variables and arguments in terms of
647 	   REG and OREG nodes */
648 	/* conversion ops which are not necessary are also clobbered here */
649 	/* in addition, any special features (such as rewriting
650 	   exclusive or) are easily handled here as well */
651 
652 	register o;
653 	register unsigned t, tl;
654 
655 	switch( o = p->in.op ){
656 
657 	case SCONV:
658 	case PCONV:
659 		if( p->in.left->in.type==ENUMTY ){
660 			p->in.left = pconvert( p->in.left );
661 			}
662 		/* assume conversion takes place; type is inherited */
663 		t = p->in.type;
664 		tl = p->in.left->in.type;
665 		if( aflag && (tl==LONG||tl==ULONG) && (t!=LONG&&t!=ULONG) ){
666 			werror( "long assignment may lose accuracy" );
667 			}
668 		if( aflag>=2 && (tl!=LONG&&tl!=ULONG) && (t==LONG||t==ULONG) && p->in.left->in.op != ICON ){
669 			werror( "assignment to long may sign-extend incorrectly" );
670 			}
671 		if( ISPTR(tl) && ISPTR(t) ){
672 			tl = DECREF(tl);
673 			t = DECREF(t);
674 			switch( ISFTN(t) + ISFTN(tl) ){
675 
676 			case 0:  /* neither is a function pointer */
677 				if( talign(t,p->fn.csiz) > talign(tl,p->in.left->fn.csiz) ){
678 					if( hflag||pflag ) werror( "possible pointer alignment problem" );
679 					}
680 				break;
681 
682 			case 1:
683 				werror( "questionable conversion of function pointer" );
684 
685 			case 2:
686 				;
687 				}
688 			}
689 		p->in.left->in.type = p->in.type;
690 		p->in.left->fn.cdim = p->fn.cdim;
691 		p->in.left->fn.csiz = p->fn.csiz;
692 		p->in.op = FREE;
693 		return( p->in.left );
694 
695 	case PVCONV:
696 	case PMCONV:
697 		if( p->in.right->in.op != ICON ) cerror( "bad conversion");
698 		p->in.op = FREE;
699 		return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) );
700 
701 		}
702 
703 	return(p);
704 	}
705 
706 NODE *
707 offcon( off, t, d, s ) OFFSZ off; TWORD t;{  /* make a structure offset node */
708 	register NODE *p;
709 	p = bcon(0);
710 	p->tn.lval = off/SZCHAR;
711 	return(p);
712 	}
713 
714 noinit(){
715 	/* storage class for such as "int a;" */
716 	return( pflag ? EXTDEF : EXTERN );
717 	}
718 
719 
720 cinit( p, sz ) NODE *p; { /* initialize p into size sz */
721 	inoff += sz;
722 	if( p->in.op == INIT ){
723 		if( p->in.left->in.op == ICON ) return;
724 		if( p->in.left->in.op == NAME && p->in.left->in.type == MOE ) return;
725 		}
726 	uerror( "illegal initialization" );
727 	}
728 
729 char *
730 exname( p ) char *p; {
731 	/* make a name look like an external name in the local machine */
732 	static char aa[8];
733 	register int i;
734 
735 	if( !pflag ) return(p);
736 	for( i=0; i<6; ++i ){
737 		if( isupper(*p ) ) aa[i] = tolower( *p );
738 		else aa[i] = *p;
739 		if( *p ) ++p;
740 		}
741 	aa[6] = '\0';
742 	return( aa );
743 	}
744 
745 char *
746 strip(s) char *s; {
747 #ifndef FLEXNAMES
748 	static char x[LFNM+1];
749 #else
750 	static char x[BUFSIZ];
751 #endif
752 	register char *p;
753 	static	int	stripping = 0;
754 
755 	if (stripping)
756 		return(s);
757 	stripping++;
758 	for( p=x; *s; ++s ){
759 		if( *s != '"' ){
760 #ifndef FLEXNAMES
761 /* PATCHED by ROBERT HENRY on 8Jul80 to fix 14 character file name bug */
762 			if( p >= &x[LFNM] )
763 #else
764 			if( p >= &x[BUFSIZ] )
765 #endif
766 				cerror( "filename too long" );
767 			*p++ = *s;
768 		}
769 	}
770 	stripping = 0;
771 	*p = '\0';
772 #ifndef FLEXNAMES
773 	return( x );
774 #else
775 	return( hash(x) );
776 #endif
777 	}
778 
779 fsave( s ) char *s; {
780 	static union rec fsname;
781 	s = strip( s );
782 #ifndef FLEXNAMES
783 	if( strncmp( s, fsname.f.fn, LFNM ) ){
784 #else
785 	if (fsname.f.fn == NULL || strcmp(s, fsname.f.fn)) {
786 #endif
787 		/* new one */
788 #ifndef FLEXNAMES
789 		strncpy( fsname.f.fn, s, LFNM );
790 #else
791 		fsname.f.fn = s;
792 #endif
793 		fsname.f.decflag = LFN;
794 		fwrite( (char *)&fsname, sizeof(fsname), 1, stdout );
795 #ifdef FLEXNAMES
796 		/* if generating a library, prefix with the library name */
797 		/* only do this for flexnames */
798 		if( libname ){
799 			fwrite( libname, strlen(libname), 1, stdout );
800 			putchar( ':' );
801 			}
802 		fwrite( fsname.f.fn, strlen(fsname.f.fn)+1, 1, stdout );
803 #endif
804 		}
805 	}
806 
807 where(f){ /* print true location of error */
808 	if( f == 'u' && nerrors > 1 )
809 		--nerrors; /* don't get "too many errors" */
810 	fprintf( stderr, "%s(%d): ", strip(ftitle), lineno);
811 	}
812 
813 	/* a number of dummy routines, unneeded by lint */
814 
815 branch(n){;}
816 defalign(n){;}
817 deflab(n){;}
818 bycode(t,i){;}
819 cisreg(t) TWORD t; {return(1);}  /* everyting is a register variable! */
820 
821 fldty(p) struct symtab *p; {
822 	; /* all types are OK here... */
823 	}
824 
825 fldal(t) unsigned t; { /* field alignment... */
826 	if( t == ENUMTY ) return( ALCHAR );  /* this should be thought through better... */
827 	if( ISPTR(t) ){ /* really for the benefit of honeywell (and someday IBM) */
828 		if( pflag ) uerror( "nonportable field type" );
829 		}
830 	else uerror( "illegal field type" );
831 	return(ALINT);
832 	}
833 
834 main( argc, argv ) char *argv[]; {
835 	char *p;
836 	int i;
837 
838 	/* handle options */
839 
840 	for( i = 1; i < argc; i++ )
841 		for( p=argv[i]; *p; ++p ){
842 
843 			switch( *p ){
844 
845 			case '-':
846 				continue;
847 
848 			case '\0':
849 				break;
850 
851 			case 'b':
852 				brkflag = 1;
853 				continue;
854 
855 			case 'p':
856 				pflag = 1;
857 				continue;
858 
859 			case 'c':
860 				cflag = 1;
861 				continue;
862 
863 			case 's':
864 				/* for the moment, -s triggers -h */
865 
866 			case 'h':
867 				hflag = 1;
868 				continue;
869 
870 			case 'L':
871 				libflag = 1;
872 			case 'v':
873 				vflag = 0;
874 				continue;
875 
876 			case 'x':
877 				xflag = 1;
878 				continue;
879 
880 			case 'a':
881 				++aflag;
882 			case 'u':	/* done in second pass */
883 			case 'n':	/* done in shell script */
884 				continue;
885 
886 			case 'z':
887 				zflag = 1;
888 				continue;
889 
890 			case 't':
891 				werror( "option %c now default: see `man 6 lint'", *p );
892 				continue;
893 
894 			case 'P':	/* debugging, done in second pass */
895 				continue;
896 
897 			case 'C':
898 				Cflag = 1;
899 				if( p[1] ) libname = p + 1;
900 				while( p[1] ) p++;
901 				continue;
902 
903 			default:
904 				uerror( "illegal option: %c", *p );
905 				continue;
906 
907 				}
908 			}
909 
910 	if( !pflag ){  /* set sizes to sizes of target machine */
911 # ifdef gcos
912 		SZCHAR = ALCHAR = 9;
913 # else
914 		SZCHAR = ALCHAR = 8;
915 # endif
916 		SZINT = ALINT = sizeof(int)*SZCHAR;
917 		SZFLOAT = ALFLOAT = sizeof(float)*SZCHAR;
918 		SZDOUBLE = ALDOUBLE = sizeof(double)*SZCHAR;
919 		SZLONG = ALLONG = sizeof(long)*SZCHAR;
920 		SZSHORT = ALSHORT = sizeof(short)*SZCHAR;
921 		SZPOINT = ALPOINT = sizeof(int *)*SZCHAR;
922 		ALSTRUCT = ALINT;
923 		/* now, fix some things up for various machines (I wish we had "alignof") */
924 
925 # ifdef pdp11
926 		ALLONG = ALDOUBLE = ALFLOAT = ALINT;
927 #endif
928 # ifdef ibm
929 		ALSTRUCT = ALCHAR;
930 #endif
931 		}
932 
933 	return( mainp1( argc, argv ) );
934 	}
935 
936 ctype( type ) unsigned type; { /* are there any funny types? */
937 	return( type );
938 	}
939 
940 commdec( i ){
941 	/* put out a common declaration */
942 	if( stab[i].sclass == STATIC ) outdef( &stab[i], LST, USUAL );
943 	else outdef( &stab[i], libflag?LIB:LDC, USUAL );
944 	}
945 
946 isitfloat ( s ) char *s; {
947 	/* s is a character string;
948 	   if floating point is implemented, set dcon to the value of s */
949 	/* lint version
950 	*/
951 	dcon = atof( s );
952 	return( FCON );
953 	}
954 
955 fldcon( p ) register NODE *p; {
956 	/* p is an assignment of a constant to a field */
957 	/* check to see if the assignment is going to overflow, or otherwise cause trouble */
958 	register s;
959 	CONSZ v;
960 
961 	if( !hflag & !pflag ) return;
962 
963 	s = UPKFSZ(p->in.left->tn.rval);
964 	v = p->in.right->tn.lval;
965 
966 	switch( p->in.left->in.type ){
967 
968 	case CHAR:
969 	case INT:
970 	case SHORT:
971 	case LONG:
972 	case ENUMTY:
973 		if( v>=0 && (v>>(s-1))==0 ) return;
974 		werror( "precision lost in assignment to (possibly sign-extended) field" );
975 	default:
976 		return;
977 
978 	case UNSIGNED:
979 	case UCHAR:
980 	case USHORT:
981 	case ULONG:
982 		if( v<0 || (v>>s)!=0 ) werror( "precision lost in field assignment" );
983 
984 		return;
985 		}
986 
987 	}
988 
989 outdef( p, lty, mode ) struct symtab *p; {
990 	/* output a definition for the second pass */
991 	/* if mode is > USUAL, it is the number of args */
992 	char *fname;
993 	TWORD t;
994 	int line;
995 	static union rec rc;
996 
997 	if( mode == NOFILE ){
998 		fname = "???";
999 		line = p->suse;
1000 		}
1001 	else if( mode == SVLINE ){
1002 		fname = ftitle;
1003 		line = -p->suse;
1004 		}
1005 	else {
1006 		fname = ftitle;
1007 		line = lineno;
1008 		}
1009 	fsave( fname );
1010 #ifndef FLEXNAMES
1011 	strncpy( rc.l.name, exname(p->sname), LCHNM );
1012 #endif
1013 	rc.l.decflag = lty;
1014 	t = p->stype;
1015 	if( mode == DECTY ) t = DECREF(t);
1016 	rc.l.type.aty = t;
1017 	rc.l.type.extra = 0;
1018 	rc.l.type.extra1 = 0;
1019 	astype( &rc.l.type, p->sizoff );
1020 	rc.l.nargs = (mode>USUAL) ? mode : 0;
1021 	rc.l.fline = line;
1022 	fwrite( (char *)&rc, sizeof(rc), 1, stdout );
1023 #ifdef FLEXNAMES
1024 	rc.l.name = exname(p->sname);
1025 	fwrite( rc.l.name, strlen(rc.l.name)+1, 1, stdout );
1026 #endif
1027 	}
1028 int proflg;
1029 int gdebug;
1030