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