xref: /original-bsd/old/pcc/lint/lpass1/lint.c (revision 2e655d5d)
1 #ifndef lint
2 static char sccsid[] = "@(#)lint.c	1.14	(Berkeley)	12/11/87";
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 nflag = 0;		/* avoid gripes about printf et al. */
32 int vflag = 1;		/* tell about unused argments */
33 int xflag = 0;		/* tell about unused externals */
34 int argflag = 0;	/* used to turn off complaints about arguments */
35 int libflag = 0;	/* used to generate library descriptions */
36 int vaflag = -1;	/* signal functions with a variable number of args */
37 int aflag = 0;		/* used to check precision of assignments */
38 int zflag = 0;		/* no 'structure never defined' error */
39 int Cflag = 0;	/* filter out certain output, for generating libraries */
40 char *libname = 0;	/* name of the library we're generating */
41 
42 			/* flags for the "outdef" function */
43 # define USUAL (-101)
44 # define DECTY (-102)
45 # define NOFILE (-103)
46 # define SVLINE (-104)
47 
48 # define LNAMES 250
49 
50 struct lnm {
51 	short lid, flgs;
52 	}  lnames[LNAMES], *lnp;
53 
contx(p,down,pl,pr)54 contx( p, down, pl, pr ) register NODE *p; register *pl, *pr; {
55 
56 	*pl = *pr = VAL;
57 	switch( p->in.op ){
58 
59 	case ANDAND:
60 	case OROR:
61 	case QUEST:
62 		*pr = down;
63 		break;
64 
65 	case SCONV:
66 	case PCONV:
67 	case COLON:
68 		*pr = *pl = down;
69 		break;
70 
71 	case COMOP:
72 		*pl = EFF;
73 		*pr = down;
74 
75 	case FORCE:
76 	case INIT:
77 	case UNARY CALL:
78 	case STCALL:
79 	case UNARY STCALL:
80 	case CALL:
81 	case UNARY FORTCALL:
82 	case FORTCALL:
83 	case CBRANCH:
84 		break;
85 
86 	default:
87 		if( asgop(p->in.op) ) break;
88 		if( p->in.op == UNARY MUL && ( p->in.type == STRTY || p->in.type == UNIONTY || p->in.type == UNDEF) ) {
89 		/* struct x f( );  main( ) {  (void) f( ); }
90 		 * the the cast call appears as U* UNDEF
91 		 */
92 			break;  /* the compiler does this... */
93 			}
94 		if( down == EFF && hflag ) werror( "null effect" );
95 
96 		}
97 	}
98 
ecode(p)99 ecode( p ) NODE *p; {
100 	/* compile code for p */
101 
102 	fwalk( p, contx, EFF );
103 	lnp = lnames;
104 	lprt( p, EFF, 0 );
105 	strforget();
106 	}
107 
ejobcode(flag)108 ejobcode( flag ){
109 	/* called after processing each job */
110 	/* flag is nonzero if errors were detected */
111 	register k;
112 	register struct symtab *p;
113 
114 	for( p=stab; p< &stab[SYMTSZ]; ++p ){
115 
116 		if( p->stype != TNULL ) {
117 
118 			if( p->stype == STRTY || p->stype == UNIONTY ){
119 				if( !zflag && dimtab[p->sizoff+1] < 0 ){
120 					/* never defined */
121 #ifndef FLEXNAMES
122 					if( hflag ) werror( "struct/union %.8s never defined", p->sname );
123 #else
124 					if( hflag ) werror( "struct/union %s never defined", p->sname );
125 #endif
126 					}
127 				}
128 
129 			switch( p->sclass ){
130 
131 			case STATIC:
132 				if( p->suse > 0 ){
133 					k = lineno;
134 					lineno = p->suse;
135 #ifndef FLEXNAMES
136 					uerror( "static variable %.8s unused",
137 #else
138 					uerror( "static variable %s unused",
139 #endif
140 						p->sname );
141 					lineno = k;
142 					break;
143 					}
144 				/* no statics in libraries */
145 				if( Cflag ) break;
146 
147 			case EXTERN:
148 			case USTATIC:
149 				/* with the xflag, worry about externs not used */
150 				/* the filename may be wrong here... */
151 				if( xflag && p->suse >= 0 && !libflag ){
152 					outdef( p, LDX, NOFILE );
153 					}
154 
155 			case EXTDEF:
156 				if( p->suse < 0 ){  /* used */
157 					outdef( p, LUM, SVLINE );
158 					}
159 				break;
160 				}
161 
162 			}
163 
164 		}
165 	exit( 0 );
166 	}
167 
astype(t,i)168 astype( t, i ) ATYPE *t; {
169 	TWORD tt;
170 	int j, k=0, l=0;
171 
172 	if( (tt=BTYPE(t->aty))==STRTY || tt==UNIONTY ){
173 		if( i<0 || i>= DIMTABSZ-3 ){
174 			werror( "lint's little mind is blown" );
175 			}
176 		else {
177 			j = dimtab[i+3];
178 			if( j<0 || j>SYMTSZ ){
179 				k = dimtab[i];
180 				l = X_NONAME | stab[j].suse;
181 				}
182 			else {
183 				if( stab[j].suse <= 0 ) {
184 #ifndef FLEXNAMES
185 					werror( "no line number for %.8s",
186 #else
187 					werror( "no line number for %s",
188 #endif
189 						stab[j].sname );
190 					}
191 				else {
192 					k = dimtab[i];
193 #ifdef FLEXNAMES
194 					l = hashstr(stab[j].sname);
195 #else
196 					l = hashstr(stab[j].sname, LCHNM);
197 #endif
198 					}
199 				}
200 			}
201 
202 		t->extra = k;
203 		t->extra1 = l;
204 		return( 1 );
205 		}
206 	else return( 0 );
207 	}
208 
bfcode(a,n)209 bfcode( a, n ) int a[]; {
210 	/* code for the beginning of a function; a is an array of
211 		indices in stab for the arguments; n is the number */
212 	/* this must also set retlab */
213 	register i;
214 	register struct symtab *cfp;
215 	static ATYPE t;
216 
217 	strforget();
218 	retlab = 1;
219 
220 	cfp = &stab[curftn];
221 
222 	/* if creating library, don't do static functions */
223 	if( Cflag && cfp->sclass == STATIC ) return;
224 
225 	/* if variable number of arguments, only print the ones which will be checked */
226 	if( vaflag >= 0 ){
227 		if( n < vaflag ) werror( "declare the VARARGS arguments you want checked!" );
228 		else n = vaflag;
229 		}
230 	fsave( ftitle );
231 	if( cfp->sclass == STATIC ) outdef( cfp, LST, vaflag>=0?~n:n );
232 	else outdef( cfp, libflag?LIB:LDI, vaflag>=0?~n:n );
233 	vaflag = -1;
234 
235 	/* output the arguments */
236 	if( n ){
237 		for( i=0; i<n; ++i ) {
238 			t.aty = stab[a[i]].stype;
239 			t.extra = 0;
240 			t.extra1 = 0;
241 			if( !astype( &t, stab[a[i]].sizoff ) ) {
242 				switch( t.aty ){
243 
244 				case ULONG:
245 					break;
246 
247 				case CHAR:
248 				case SHORT:
249 					t.aty = INT;
250 					break;
251 
252 				case UCHAR:
253 				case USHORT:
254 				case UNSIGNED:
255 					t.aty = UNSIGNED;
256 					break;
257 
258 					}
259 				}
260 			fwrite( (char *)&t, sizeof(ATYPE), 1, stdout );
261 			}
262 		}
263 	}
264 
ctargs(p)265 ctargs( p ) NODE *p; {
266 	/* count arguments; p points to at least one */
267 	/* the arguemnts are a tower of commas to the left */
268 	register c;
269 	c = 1; /* count the rhs */
270 	while( p->in.op == CM ){
271 		++c;
272 		p = p->in.left;
273 		}
274 	return( c );
275 	}
276 
lpta(p)277 lpta( p ) NODE *p; {
278 	static ATYPE t;
279 
280 	if( p->in.op == CM ){
281 		lpta( p->in.left );
282 		p = p->in.right;
283 		}
284 
285 	t.aty = p->in.type;
286 	t.extra = (p->in.op==ICON);
287 	t.extra1 = 0;
288 
289 	if( !astype( &t, p->fn.csiz ) ) {
290 		switch( t.aty ){
291 
292 			case CHAR:
293 			case SHORT:
294 				t.aty = INT;
295 			case LONG:
296 			case ULONG:
297 			case INT:
298 			case UNSIGNED:
299 				break;
300 
301 			case UCHAR:
302 			case USHORT:
303 				t.aty = UNSIGNED;
304 				break;
305 
306 			case FLOAT:
307 				t.aty = DOUBLE;
308 				t.extra = 0;
309 				break;
310 
311 			default:
312 				t.extra = 0;
313 				break;
314 			}
315 		}
316 	fwrite( (char *)&t, sizeof(ATYPE), 1, stdout );
317 	}
318 
319 # define VALSET 1
320 # define VALUSED 2
321 # define VALASGOP 4
322 # define VALADDR 8
323 
lprt(p,down,uses)324 lprt( p, down, uses ) register NODE *p; {
325 	register struct symtab *q;
326 	register id;
327 	register acount;
328 	register down1, down2;
329 	register use1, use2;
330 	register struct lnm *np1, *np2;
331 
332 	/* first, set variables which are set... */
333 
334 	use1 = use2 = VALUSED;
335 	if( p->in.op == ASSIGN ) use1 = VALSET;
336 	else if( p->in.op == UNARY AND ) use1 = VALADDR;
337 	else if( asgop( p->in.op ) ){ /* =ops */
338 		use1 = VALUSED|VALSET;
339 		if( down == EFF ) use1 |= VALASGOP;
340 		}
341 
342 
343 	/* print the lines for lint */
344 
345 	down2 = down1 = VAL;
346 	acount = 0;
347 
348 	switch( p->in.op ){
349 
350 	case EQ:
351 	case NE:
352 	case GT:
353 	case GE:
354 	case LT:
355 	case LE:
356 		if( p->in.left->in.type == CHAR && p->in.right->in.op==ICON && p->in.right->tn.lval < 0 ){
357 			werror( "nonportable character comparison" );
358 			}
359 		if( (p->in.op==EQ || p->in.op==NE ) && ISUNSIGNED(p->in.left->in.type) && p->in.right->in.op == ICON ){
360 			if( p->in.right->tn.lval < 0 && p->in.right->tn.rval == NONAME && !ISUNSIGNED(p->in.right->in.type) ){
361 				werror( "comparison of unsigned with negative constant" );
362 				}
363 			}
364 		break;
365 
366 	case UGE:
367 	case ULT:
368 		if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->tn.rval == NONAME ){
369 			werror( "unsigned comparison with 0?" );
370 			break;
371 			}
372 	case UGT:
373 	case ULE:
374 		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 ){
375 			werror( "degenerate unsigned comparison" );
376 			}
377 		break;
378 
379 	case COMOP:
380 		down1 = EFF;
381 
382 	case ANDAND:
383 	case OROR:
384 	case QUEST:
385 		down2 = down;
386 		/* go recursively left, then right  */
387 		np1 = lnp;
388 		lprt( p->in.left, down1, use1 );
389 		np2 = lnp;
390 		lprt( p->in.right, down2, use2 );
391 		lmerge( np1, np2, 0 );
392 		return;
393 
394 	case SCONV:
395 	case PCONV:
396 	case COLON:
397 		down1 = down2 = down;
398 		break;
399 
400 	case CALL:
401 	case STCALL:
402 	case FORTCALL:
403 		acount = ctargs( p->in.right );
404 	case UNARY CALL:
405 	case UNARY STCALL:
406 	case UNARY FORTCALL:
407 		if( p->in.left->in.op == ICON && (id=p->in.left->tn.rval) != NONAME ){ /* used to be &name */
408 			struct symtab *sp = &stab[id];
409 			int lty;
410 
411 			fsave( ftitle );
412 			if (!nflag)
413 				doform(p, sp, acount);
414 			/*
415 			 * if we're generating a library -C then
416 			 * we don't want to output references to functions
417 			 */
418 			if( Cflag ) break;
419 			/*  if a function used in an effects context is
420 			 *  cast to type  void  then consider its value
421 			 *  to have been disposed of properly
422 			 *  thus a call of type  undef  in an effects
423 			 *  context is construed to be used in a value
424 			 *  context
425 			 */
426 			if ((down == EFF) && (p->in.type != UNDEF)) {
427 				lty = LUE;
428 			} else if (down == EFF) {
429 				lty = LUV | LUE;
430 			} else {
431 				lty = LUV;
432 			}
433 			outdef( sp, lty, acount );
434 			if( acount ) {
435 				lpta( p->in.right );
436 				}
437 			}
438 		break;
439 
440 	case ICON:
441 		/* look for &name case */
442 		if( (id = p->tn.rval) >= 0 && id != NONAME ){
443 			q = &stab[id];
444 			q->sflags |= (SREF|SSET);
445 			q->suse = -lineno;
446 			}
447 		return;
448 
449 	case NAME:
450 		if( (id = p->tn.rval) >= 0 && id != NONAME ){
451 			q = &stab[id];
452 			if( (uses&VALUSED) && !(q->sflags&SSET) ){
453 				if( q->sclass == AUTO || q->sclass == REGISTER ){
454 					if( !ISARY(q->stype ) && !ISFTN(q->stype) && q->stype!=STRTY && q->stype!=UNIONTY ){
455 #ifndef FLEXNAMES
456 						werror( "%.8s may be used before set", q->sname );
457 #else
458 						werror( "%s may be used before set", q->sname );
459 #endif
460 						q->sflags |= SSET;
461 						}
462 					}
463 				}
464 			if( uses & VALASGOP ) break;  /* not a real use */
465 			if( uses & VALSET ) q->sflags |= SSET;
466 			if( uses & VALUSED ) q->sflags |= SREF;
467 			if( uses & VALADDR ) q->sflags |= (SREF|SSET);
468 			if( p->tn.lval == 0 ){
469 				lnp->lid = id;
470 				lnp->flgs = (uses&VALADDR)?0:((uses&VALSET)?VALSET:VALUSED);
471 				if( ++lnp >= &lnames[LNAMES] ) --lnp;
472 				}
473 			}
474 		return;
475 
476 		}
477 
478 	/* recurse, going down the right side first if we can */
479 
480 	switch( optype(p->in.op) ){
481 
482 	case BITYPE:
483 		np1 = lnp;
484 		lprt( p->in.right, down2, use2 );
485 	case UTYPE:
486 		np2 = lnp;
487 		lprt( p->in.left, down1, use1 );
488 		}
489 
490 	if( optype(p->in.op) == BITYPE ){
491 		if( p->in.op == ASSIGN && p->in.left->in.op == NAME ){ /* special case for a =  .. a .. */
492 			lmerge( np1, np2, 0 );
493 			}
494 		else lmerge( np1, np2, p->in.op != COLON );
495 		/* look for assignments to fields, and complain */
496 		if( p->in.op == ASSIGN && p->in.left->in.op == FLD && p->in.right->in.op == ICON ) fldcon( p );
497 		}
498 
499 	}
500 
501 lmerge( np1, np2, flag ) struct lnm *np1, *np2; {
502 	/* np1 and np2 point to lists of lnm members, for the two sides
503 	 * of a binary operator
504 	 * flag is 1 if commutation is possible, 0 otherwise
505 	 * lmerge returns a merged list, starting at np1, resetting lnp
506 	 * it also complains, if appropriate, about side effects
507 	 */
508 
509 	register struct lnm *npx, *npy;
510 
511 	for( npx = np2; npx < lnp; ++npx ){
512 
513 		/* is it already there? */
514 		for( npy = np1; npy < np2; ++npy ){
515 			if( npx->lid == npy->lid ){ /* yes */
516 				if( npx->flgs == 0 || npx->flgs == (VALSET|VALUSED) )
517 					;  /* do nothing */
518 				else if( (npx->flgs|npy->flgs)== (VALSET|VALUSED) ||
519 					(npx->flgs&npy->flgs&VALSET) ){
520 #ifndef FLEXNAMES
521 					if( flag ) werror( "%.8s evaluation order undefined", stab[npy->lid].sname );
522 #else
523 					if( flag ) werror( "%s evaluation order undefined", stab[npy->lid].sname );
524 #endif
525 					}
526 				if( npy->flgs == 0 ) npx->flgs = 0;
527 				else npy->flgs |= npx->flgs;
528 				goto foundit;
529 				}
530 			}
531 
532 		/* not there: update entry */
533 		np2->lid = npx->lid;
534 		np2->flgs = npx->flgs;
535 		++np2;
536 
537 		foundit: ;
538 		}
539 
540 	/* all finished: merged list is at np1 */
541 	lnp = np2;
542 	}
543 
efcode()544 efcode(){
545 	/* code for the end of a function */
546 	register struct symtab *cfp;
547 
548 	cfp = &stab[curftn];
549 	if( retstat & RETVAL && !(Cflag && cfp->sclass==STATIC) )
550 		outdef( cfp, LRV, DECTY );
551 	if( !vflag ){
552 		vflag = argflag;
553 		argflag = 0;
554 		}
555 	if( retstat == RETVAL+NRETVAL )
556 #ifndef FLEXNAMES
557 		werror( "function %.8s has return(e); and return;", cfp->sname);
558 #else
559 		werror( "function %s has return(e); and return;", cfp->sname);
560 #endif
561 	}
562 
563 aocode(p) struct symtab *p; {
564 	/* called when automatic p removed from stab */
565 	register struct symtab *cfs;
566 	cfs = &stab[curftn];
567 	if(p->suse>0 && !(p->sflags&(SMOS|STAG)) ){
568 		if( p->sclass == PARAM ){
569 #ifndef FLEXNAMES
570 			if( vflag ) werror( "argument %.8s unused in function %.8s",
571 #else
572 			if( vflag ) werror( "argument %s unused in function %s",
573 #endif
574 				p->sname,
575 				cfs->sname );
576 			}
577 		else {
578 #ifndef FLEXNAMES
579 			if( p->sclass != TYPEDEF ) werror( "%.8s unused in function %.8s",
580 #else
581 			if( p->sclass != TYPEDEF ) werror( "%s unused in function %s",
582 #endif
583 				p->sname, cfs->sname );
584 			}
585 		}
586 
587 	if( p->suse < 0 && (p->sflags & (SSET|SREF|SMOS)) == SSET &&
588 		!ISARY(p->stype) && !ISFTN(p->stype) ){
589 
590 #ifndef FLEXNAMES
591 		werror( "%.8s set but not used in function %.8s", p->sname, cfs->sname );
592 #else
593 		werror( "%s set but not used in function %s", p->sname, cfs->sname );
594 #endif
595 		}
596 
597 	if( p->stype == STRTY || p->stype == UNIONTY || p->stype == ENUMTY ){
598 		if( !zflag && dimtab[p->sizoff+1] < 0 )
599 #ifndef FLEXNAMES
600 			werror( "structure %.8s never defined", p->sname );
601 #else
602 			werror( "structure %s never defined", p->sname );
603 #endif
604 		}
605 
606 	}
607 
defnam(p)608 defnam( p ) register struct symtab *p; {
609 	/* define the current location as the name p->sname */
610 
611 	if( p->sclass == STATIC && (p->slevel>1 || Cflag) ) return;
612 
613 	if( !ISFTN( p->stype ) )
614 		if( p->sclass == STATIC ) outdef( p, LST, USUAL );
615 		else outdef( p, libflag?LIB:LDI, USUAL );
616 	}
617 
zecode(n)618 zecode( n ){
619 	/* n integer words of zeros */
620 	OFFSZ temp;
621 	temp = n;
622 	inoff += temp*SZINT;
623 	;
624 	}
625 
andable(p)626 andable( p ) NODE *p; {  /* p is a NAME node; can it accept & ? */
627 	register r;
628 
629 	if( p->in.op != NAME ) cerror( "andable error" );
630 
631 	if( (r = p->tn.rval) < 0 ) return(1);  /* labels are andable */
632 
633 	if( stab[r].sclass == AUTO || stab[r].sclass == PARAM ) return(0);
634 #ifndef FLEXNAMES
635 	if( stab[r].sclass == REGISTER ) uerror( "can't take & of %.8s", stab[r].sname );
636 #else
637 	if( stab[r].sclass == REGISTER ) uerror( "can't take & of %s", stab[r].sname );
638 #endif
639 	return(1);
640 	}
641 
642 NODE *
clocal(p)643 clocal(p) NODE *p; {
644 
645 	/* this is called to do local transformations on
646 	   an expression tree preparitory to its being
647 	   written out in intermediate code.
648 	*/
649 
650 	/* the major essential job is rewriting the
651 	   automatic variables and arguments in terms of
652 	   REG and OREG nodes */
653 	/* conversion ops which are not necessary are also clobbered here */
654 	/* in addition, any special features (such as rewriting
655 	   exclusive or) are easily handled here as well */
656 
657 	register o;
658 	register unsigned t, tl;
659 	int s;
660 
661 	switch( o = p->in.op ){
662 	case NAME:
663 		{
664 			extern int	didstr, subscr;
665 			extern NODE *	strnodes[];
666 
667 			if (didstr) {
668 				didstr = 0;
669 				strnodes[subscr] = p;
670 			}
671 		}
672 		break;
673 
674 	case SCONV:
675 	case PCONV:
676 		if( p->in.left->in.type==ENUMTY ){
677 			p->in.left = pconvert( p->in.left );
678 			}
679 		/* assume conversion takes place; type is inherited */
680 		t = p->in.type;
681 		tl = p->in.left->in.type;
682 		if( aflag && (tl==LONG||tl==ULONG) && (t!=LONG&&t!=ULONG&&t!=UNDEF) ){
683 			werror( "long assignment may lose accuracy" );
684 			}
685 		if( aflag>=2 && (tl!=LONG&&tl!=ULONG) && (t==LONG||t==ULONG) && p->in.left->in.op != ICON ){
686 			werror( "assignment to long may sign-extend incorrectly" );
687 			}
688 		if( ISPTR(tl) && ISPTR(t) ){
689 			tl = DECREF(tl);
690 			t = DECREF(t);
691 			switch( ISFTN(t) + ISFTN(tl) ){
692 
693 			case 0:  /* neither is a function pointer */
694 				if( talign(t,p->fn.csiz) > talign(tl,p->in.left->fn.csiz) ){
695 					if( hflag||pflag ) werror( "possible pointer alignment problem" );
696 					}
697 				break;
698 
699 			case 1:
700 				werror( "questionable conversion of function pointer" );
701 
702 			case 2:
703 				;
704 				}
705 			}
706 		p->in.left->in.type = p->in.type;
707 		p->in.left->fn.cdim = p->fn.cdim;
708 		p->in.left->fn.csiz = p->fn.csiz;
709 		p->in.op = FREE;
710 		return( p->in.left );
711 
712 	case PVCONV:
713 	case PMCONV:
714 		if( p->in.right->in.op != ICON ) cerror( "bad conversion");
715 		p->in.op = FREE;
716 		return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) );
717 
718 	case RS:
719 	case LS:
720 	case ASG RS:
721 	case ASG LS:
722 		if( p->in.right->in.op != ICON )
723 			break;
724 		s = p->in.right->tn.lval;
725 		if( s < 0 )
726 			werror( "negative shift" );
727 		else
728 		if( s >= dimtab[ p->fn.csiz ] )
729 			werror( "shift greater than size of object" );
730 		break;
731 
732 		}
733 
734 	return(p);
735 	}
736 
737 NODE *
offcon(off,t,d,s)738 offcon( off, t, d, s ) OFFSZ off; TWORD t;{  /* make a structure offset node */
739 	register NODE *p;
740 	p = bcon(0);
741 	p->tn.lval = off/SZCHAR;
742 	return(p);
743 	}
744 
noinit()745 noinit(){
746 	/* storage class for such as "int a;" */
747 	return( pflag ? EXTDEF : EXTERN );
748 	}
749 
750 
cinit(p,sz)751 cinit( p, sz ) NODE *p; { /* initialize p into size sz */
752 	register int id;
753 
754 	inoff += sz;
755 	if( p->in.op == INIT ){
756 		if( p->in.left->in.op == ICON ) return;
757 		if( p->in.left->in.op == NAME && p->in.left->in.type == MOE ) return;
758 		}
759 	uerror( "illegal initialization" );
760 	}
761 
762 char *
exname(p)763 exname( p ) char *p; {
764 	/* make a name look like an external name in the local machine */
765 	static char aa[8];
766 	register int i;
767 
768 	if( !pflag ) return(p);
769 	for( i=0; i<6; ++i ){
770 		if( isupper(*p ) ) aa[i] = tolower( *p );
771 		else aa[i] = *p;
772 		if( *p ) ++p;
773 		}
774 	aa[6] = '\0';
775 	return( aa );
776 	}
777 
778 char *
strip(s)779 strip(s) char *s; {
780 #ifndef FLEXNAMES
781 	static char x[LFNM+1];
782 #else
783 	static char x[BUFSIZ];
784 #endif
785 	register char *p;
786 	static	int	stripping = 0;
787 
788 	if (stripping)
789 		return(s);
790 	stripping++;
791 	for( p=x; *s; ++s ){
792 		if( *s != '"' ){
793 #ifndef FLEXNAMES
794 /* PATCHED by ROBERT HENRY on 8Jul80 to fix 14 character file name bug */
795 			if( p >= &x[LFNM] )
796 #else
797 			if( p >= &x[BUFSIZ] )
798 #endif
799 				cerror( "filename too long" );
800 			*p++ = *s;
801 		}
802 	}
803 	stripping = 0;
804 	*p = '\0';
805 #ifndef FLEXNAMES
806 	return( x );
807 #else
808 	return( hash(x) );
809 #endif
810 	}
811 
fsave(s)812 fsave( s ) char *s; {
813 	static union rec fsname;
814 	s = strip( s );
815 #ifndef FLEXNAMES
816 	if( strncmp( s, fsname.f.fn, LFNM ) )
817 #else
818 	if (fsname.f.fn == NULL || strcmp(s, fsname.f.fn))
819 #endif
820 		{
821 		/* new one */
822 #ifndef FLEXNAMES
823 		strncpy( fsname.f.fn, s, LFNM );
824 #else
825 		fsname.f.fn = s;
826 #endif
827 		fsname.f.decflag = LFN;
828 		fwrite( (char *)&fsname, sizeof(fsname), 1, stdout );
829 #ifdef FLEXNAMES
830 		/* if generating a library, prefix with the library name */
831 		/* only do this for flexnames */
832 		if( libname ){
833 			fwrite( libname, strlen(libname), 1, stdout );
834 			putchar( ':' );
835 			}
836 		fwrite( fsname.f.fn, strlen(fsname.f.fn)+1, 1, stdout );
837 #endif
838 		}
839 	}
840 
where(f)841 where(f){ /* print true location of error */
842 	if( f == 'u' && nerrors > 1 )
843 		--nerrors; /* don't get "too many errors" */
844 	fprintf( stderr, "%s(%d): ", strip(ftitle), lineno);
845 	}
846 
847 	/* a number of dummy routines, unneeded by lint */
848 
branch(n)849 branch(n){;}
defalign(n)850 defalign(n){;}
deflab(n)851 deflab(n){;}
852 
853 extern char *	strchr();
854 
855 #define SBUFSIZE	16
856 #define SCLICK		80
857 
858 #ifndef size_t
859 #define size_t	unsigned
860 #endif /* !size_t */
861 
862 static char *	strings[SBUFSIZE];
863 static NODE *	strnodes[SBUFSIZE];
864 static int	didstr;
865 static int	subscr;
866 static int	strapped;
867 
bycode(t,i)868 bycode(t, i)
869 {
870 	extern char *	calloc();
871 	extern char *	realloc();
872 
873 	if (nflag || strapped)
874 		return;
875 	if (i == 0)
876 		if (subscr < (SBUFSIZE - 1))
877 			++subscr;
878 	if (subscr >= SBUFSIZE)
879 		return;
880 	didstr = 1;
881 	if ((i % SCLICK) == 0) {
882 		strings[subscr] = (strings[subscr] == NULL) ?
883 			calloc((size_t) (SCLICK + 1), 1) :
884 			realloc(strings[subscr], (size_t) (i + SCLICK + 1));
885 		if (strings[subscr] == NULL) {
886 			strapped = 1;
887 			return;
888 		}
889 	}
890 	strings[subscr][i] = t;
891 }
892 
strforget()893 strforget()
894 {
895 	didstr = subscr = 0;
896 }
897 
898 static char *
typestr(t)899 typestr(t)
900 {
901 	switch (t) {
902 		case CHAR:		return "char";
903 		case UCHAR:		return "unsigned char";
904 		case SHORT:		return "short";
905 		case USHORT:		return "unsigned short";
906 		case INT:		return "int";
907 		case UNSIGNED:		return "unsigned";
908 		case ENUMTY:		return "enum";
909 		case LONG:		return "long";
910 		case ULONG:		return "unsigned long";
911 		case FLOAT:		return "float";
912 		case DOUBLE:		return "double";
913 		case STRTY:		return "struct";
914 		case UNIONTY:		return "union";
915 		case PTR|CHAR:		return "char *";
916 		case PTR|UCHAR:		return "unsigned char *";
917 		case PTR|SHORT:		return "short *";
918 		case PTR|USHORT:	return "unsigned short *";
919 		case PTR|INT:		return "int *";
920 		case PTR|UNSIGNED:	return "unsigned *";
921 		case PTR|ENUMTY:	return "enum *";
922 		case PTR|LONG:		return "long *";
923 		case PTR|ULONG:		return "unsigned long *";
924 		case PTR|FLOAT:		return "float *";
925 		case PTR|DOUBLE:	return "double *";
926 		case PTR|STRTY:		return "struct *";
927 		case PTR|UNIONTY:	return "union *";
928 		default:		return ISPTR(t) ?
929 						"pointer" : "non-scalar";
930 	}
931 }
932 
933 NODE *
ntharg(p,n,acount)934 ntharg(p, n, acount)
935 NODE *		p;
936 register int	n;
937 register int	acount;
938 {
939 	if (n > acount)
940 		return NULL;
941 	p = p->in.right;
942 	while (n != acount) {
943 		p = p->in.left;
944 		--acount;
945 	}
946 	return (n == 1) ? p : p->in.right;
947 }
948 
949 struct entry {
950 	/* If argument to print/scan is of type... */	int	argtype;
951 	/* ...and this length character is used... */	char	lchar;
952 	/* ...and one of these is control char... */	char *	cchars;
953 	/* ...then use this format with werror... */	char *	werror;
954 	/* ...(where NULL means it's hunky dory)... */
955 };
956 
957 /*
958 ** Portable printf.
959 ** H&S says "%o" takes an unsigned argument;
960 ** X3J11 says "%o" takes an int argument;
961 ** we'll allow either here.
962 */
963 
964 static struct entry pprintf[] = {
965 	CHAR,		'\0',	"c",		NULL, /* this is deliberate */
966 	INT,		'\0',	"cdoxX",	NULL,
967 	UNSIGNED,	'\0',	"uoxX",		NULL,
968 	CHAR,		'\0',	"cdoxX",	NULL,
969 	UCHAR,		'\0',	"udoxX",	NULL, /* yes, d is okay */
970 	SHORT,		'\0',	"cdoxX",	NULL,
971 	USHORT,		'\0',	"uoxX",		NULL,
972 	ENUMTY,		'\0',	"duoxX",	NULL,
973 	LONG,		'l',	"doxX",		NULL,
974 	ULONG,		'l',	"uoxX",		NULL,
975 	FLOAT,		'\0',	"eEfgG",	NULL,
976 	DOUBLE,		'\0',	"eEfgG",	NULL,
977 	PTR|CHAR,	'\0',	"s",		NULL,
978 	UNDEF,		'\0',	"",		NULL
979 };
980 
981 /*
982 ** Berkeley printf.
983 ** It allows %D, %O, and %U, which we deprecate.
984 ** Since
985 **	sizeof (char *) == sizeof (int) &&
986 **	sizeof (int) == sizeof (long) &&
987 **	sizeof (char *) == sizeof (int *)
988 ** you can be lax--and we tolerate *some* laxness.
989 ** g/lax/p to find lax table entries and code.
990 */
991 
992 static char	uppercase[] = "deprecated upper-case control character (%c)";
993 #define lax	NULL
994 
995 static struct entry bprintf[] = {
996 	CHAR,		'\0',	"c",		NULL,	/* this is deliberate */
997 	INT,		'\0',	"cdoxX",	NULL,
998 	INT,		'\0',	"DO",		uppercase,
999 	UNSIGNED,	'\0',	"uoxX",		NULL,
1000 	UNSIGNED,	'\0',	"UO",		uppercase,
1001 	CHAR,		'\0',	"cdoxX",	NULL,
1002 	CHAR,		'\0',	"DO",		uppercase,
1003 	UCHAR,		'\0',	"duoxX",	NULL,	/* yes, d is okay */
1004 	UCHAR,		'\0',	"DUO",		uppercase,
1005 	SHORT,		'\0',	"cdoxX",	NULL,
1006 	SHORT,		'\0',	"DO",		uppercase,
1007 	USHORT,		'\0',	"duoxX",	NULL,	/* d okay on BSD */
1008 	USHORT,		'\0',	"DUO",		uppercase,
1009 	ENUMTY,		'\0',	"duoxX",	NULL,
1010 	ENUMTY,		'\0',	"DUO",		uppercase,
1011 	LONG,		'\0',	"doxX",		lax,
1012 	LONG,		'\0',	"DO",		uppercase,
1013 	LONG,		'l',	"doxX",		NULL,
1014 	INT,		'l',	"doxX",		lax,
1015 	ULONG,		'\0',	"uoxX",		lax,
1016 	ULONG,		'\0',	"UO",		uppercase,
1017 	ULONG,		'l',	"uoxX",		NULL,
1018 	UNSIGNED,	'l',	"uoxX",		lax,
1019 	FLOAT,		'\0',	"eEfgG",	NULL,
1020 	DOUBLE,		'\0',	"eEfgG",	NULL,
1021 	PTR|CHAR,	'\0',	"s",		NULL,
1022 	UNDEF,		'\0',	NULL,		NULL,
1023 };
1024 
1025 /*
1026 ** Portable scanf.  'l' and 'h' are universally ignored preceding 'c' and 's',
1027 ** and 'h' is universally ignored preceding 'e' and 'f',
1028 ** but you won't find such cruft here.
1029 */
1030 
1031 static struct entry pscanf[] = {
1032 	INT,		'\0',	"dox",	NULL,
1033 	UNSIGNED,	'\0',	"uox",	NULL,
1034 	CHAR,		'\0',	"cs[",	NULL,
1035 	SHORT,		'h',	"dox",	NULL,
1036 	USHORT,		'h',	"uox",	NULL,
1037 	LONG,		'l',	"dox",	NULL,
1038 	ULONG,		'l',	"uox",	NULL,
1039 	FLOAT,		'\0',	"ef",	NULL,	/* BSD doesn't handle g */
1040 	DOUBLE,		'l',	"ef",	NULL,
1041 	UNDEF,		'\0',	NULL,	NULL,
1042 };
1043 
1044 /*
1045 ** Berkeley scanf.  An upper case letter equals an l plus the lower case char,
1046 ** but this is deprecated.
1047 ** Even though sizeof (int) == sizeof (long), we'll be picky here.
1048 */
1049 
1050 static struct entry bscanf[] = {
1051 	INT,		'\0',	"dox",	NULL,
1052 	UNSIGNED,	'\0',	"uox",	NULL,
1053 	CHAR,		'\0',	"cs[",	NULL,
1054 	SHORT,		'h',	"dox",	NULL,
1055 	USHORT,		'h',	"uox",	NULL,
1056 	LONG,		'\0',	"dox",	lax,
1057 	LONG,		'\0',	"DOX",	uppercase,
1058 	LONG,		'l',	"dox",	NULL,
1059 	ULONG,		'\0',	"uox",	lax,
1060 	ULONG,		'\0',	"UOX",	uppercase,
1061 	ULONG,		'l',	"uox",	NULL,
1062 	FLOAT,		'\0',	"ef",	NULL,
1063 	DOUBLE,		'\0',	"EF",	uppercase,
1064 	DOUBLE,		'l',	"ef",	NULL,
1065 	UNDEF,		'\0',	NULL,	NULL,
1066 };
1067 
1068 static struct item {
1069 	char *		name;		/* such as "printf" */
1070 	int		isscan;		/* scanf/printf */
1071 	int		fmtarg;		/* number of format argument */
1072 	struct entry *	ptable;		/* portable checking table */
1073 	struct entry *	btable;		/* berkeley checking table */
1074 } items[] = {
1075 	"printf",	0,	1,	pprintf,	bprintf,
1076 	"fprintf",	0,	2,	pprintf,	bprintf,
1077 	"sprintf",	0,	2,	pprintf,	bprintf,
1078 	"scanf",	1,	1,	pscanf,		bscanf,
1079 	"fscanf",	1,	2,	pscanf,		bscanf,
1080 	"sscanf",	1,	2,	pscanf,		bscanf,
1081 	NULL,		-1,	-1,	NULL,		NULL
1082 };
1083 
1084 static char	pwf[]	= "possible wild format";
1085 static char	pfacm[]	= "possible format/argument count mismatch";
1086 
1087 static struct entry *
findlc(ep,lchar,cchar)1088 findlc(ep, lchar, cchar)
1089 register struct entry *	ep;
1090 register int		lchar;
1091 register int		cchar;
1092 {
1093 	for ( ; ep->argtype != UNDEF; ++ep)
1094 		if (ep->lchar == lchar && strchr(ep->cchars, cchar) != 0)
1095 			return ep;
1096 	return NULL;
1097 }
1098 
1099 static char *
subform(p,sp,acount)1100 subform(p, sp, acount)
1101 register NODE *			p;
1102 register struct symtab *	sp;
1103 {
1104 	register int		i, j, isscan;
1105 	register NODE *		tp;
1106 	register char *		cp;
1107 	register struct entry *	basep;
1108 	register struct entry *	ep;
1109 	register struct item *	ip;
1110 	register int		lchar;
1111 	register int		cchar;
1112 	register int		t;
1113 	register int		suppressed;
1114 	static char		errbuf[132];
1115 
1116 	if (nflag || strapped)
1117 		return NULL;
1118 	cp = sp->sname;
1119 	for (ip = items; ; ++ip)
1120 		if (ip->name == NULL)
1121 			return NULL;	/* not a print/scan function */
1122 		else if (strcmp(ip->name, sp->sname) == 0)
1123 			break;
1124 	isscan = ip->isscan;
1125 	i = ip->fmtarg;
1126 	if (i > acount)
1127 		return NULL;	/* handled in pass 2 */
1128 	tp = ntharg(p, i, acount);
1129 	if (tp->in.type != (PTR|CHAR))
1130 		return NULL;	/* handled in pass 2 */
1131 	if (tp->in.op != ICON || tp->tn.lval != 0)
1132 		return NULL;	/* can't check it */
1133 	for (j = 1; j <= subscr; ++j)
1134 		if (tp == strnodes[j])
1135 			break;
1136 	if (j > subscr)
1137 		return NULL;	/* oh well. . . */
1138 	cp = strings[j];
1139 	/*
1140 	** cp now points to format string.
1141 	*/
1142 	/*
1143 	** For now, ALWAYS use "portable" table, rather than doing this:
1144 	**	basep = pflag ? ip->ptable : ip->btable;
1145 	*/
1146 	basep = ip->ptable;
1147 	for ( ; ; ) {
1148 		if (*cp == '\0')
1149 			return (i == acount) ? NULL : pfacm;
1150 		if (*cp++ != '%')
1151 			continue;
1152 		if (*cp == '\0')
1153 			return "wild trailing %% in format";
1154 		if (*cp == '%') {
1155 			++cp;
1156 			continue;
1157 		}
1158 		if (isscan) {
1159 			suppressed = *cp == '*';
1160 			if (suppressed)
1161 				++cp;
1162 			while (isdigit(*cp))
1163 				++cp;
1164 			if (!suppressed && ++i <= acount) {
1165 				t = ntharg(p, i, acount)->in.type;
1166 				if (!ISPTR(t)) {
1167 (void) sprintf(errbuf,
1168 	"%s argument is type (%s) rather than pointer (arg %d)",
1169 	ip->name, typestr(t), i);
1170 					return errbuf;
1171 				}
1172 				t = DECREF(t);
1173 			}
1174 		} else {
1175 			int	nspace, ndash, nplus, nhash;
1176 
1177 			suppressed = 0;
1178 			nspace = ndash = nplus = nhash = 0;
1179 			for ( ; ; ) {
1180 				if (*cp == ' ')
1181 					++nspace;
1182 				else if (*cp == '+')
1183 					++nplus;
1184 				else if (*cp == '-')
1185 					++ndash;
1186 				else if (*cp == '#')
1187 					++nhash;
1188 				else	break;
1189 				++cp;
1190 			}
1191 			if (nspace > 1 || ndash > 1 || nplus > 1 || nhash > 1)
1192 				return "wild repeated flag character in format";
1193 			if (*cp == '*') {
1194 				++cp;
1195 				if (++i > acount)
1196 					break;
1197 				t = ntharg(p, i, acount)->in.type;
1198 				/*
1199 				** Width other than INT or UNSIGNED is suspect.
1200 				*/
1201 				if (t != INT && t != UNSIGNED) {
1202 (void) sprintf(errbuf,
1203 	"field width argument is type (%s) rather than (int) (arg %d)",
1204 	typestr(t), i);
1205 					return errbuf;
1206 				}
1207 			} else while (isdigit(*cp))
1208 				++cp;
1209 			if (*cp == '.') {
1210 				++cp;
1211 				if (*cp == '*') {
1212 					++cp;
1213 					if (++i > acount)
1214 						return pfacm;
1215 					t = ntharg(p, i, acount)->in.type;
1216 					if (t != INT && t != UNSIGNED) {
1217 (void) sprintf(errbuf,
1218 	"precision argument is type (%s) rather than (int) (arg %d)",
1219 	typestr(t), i);
1220 						return errbuf;
1221 					}
1222 				} else while (isdigit(*cp))
1223 					++cp;
1224 			}
1225 			if (++i <= acount)
1226 				t = ntharg(p, i, acount)->in.type;
1227 		}
1228 		if (*cp == 'h' || *cp == 'l')
1229 			lchar = *cp++;
1230 		else	lchar = '\0';
1231 		if ((cchar = *cp++) == '\0')
1232 			return pwf;
1233 		if (i > acount)
1234 			return (findlc(basep, lchar, cchar) == NULL) ?
1235 				pwf : pfacm;
1236 		if (!isscan && !pflag && ISPTR(t) &&
1237 			strchr("douxX", cchar) != 0)
1238 				continue;	/* lax--printf("%d", (int *)) */
1239 		if (suppressed) {
1240 			if (findlc(basep, lchar, cchar) == NULL)
1241 				return pwf;
1242 		} else for (ep = basep; ; ++ep) {
1243 			if (ep->argtype == UNDEF) {	/* end of table */
1244 				ep = findlc(basep, lchar, cchar);
1245 				if (ep == NULL)
1246 					return pwf;
1247 (void) sprintf(errbuf, "%s: (%s) format, (%s) arg (arg %d)",
1248 					ip->name,
1249 					typestr(ep->argtype),
1250 					typestr(isscan ? (t | PTR) : t), i);
1251 				return errbuf;
1252 			}
1253 			if (ep->argtype == t && ep->lchar == lchar &&
1254 				strchr(ep->cchars, cchar) != 0)
1255 					if (ep->werror == 0)
1256 						break;
1257 					else {
1258 						werror(ep->werror, cchar);
1259 						return NULL;
1260 					}
1261 		}
1262 		if (cchar != '[')
1263 			continue;
1264 		do {
1265 			if (*cp == '\0')
1266 				return "possible unmatched '[' in format";
1267 		} while (*cp++ != ']');
1268 	}
1269 	/*NOTREACHED*/
1270 }
1271 
doform(p,sp,acount)1272 doform(p, sp, acount)
1273 NODE *		p;
1274 struct symtab *	sp;
1275 {
1276 	char *	cp;
1277 
1278 	if ((cp = subform(p, sp, acount)) != NULL)
1279 		werror(cp);
1280 }
1281 
cisreg(t)1282 cisreg(t) TWORD t; {return(1);}  /* everyting is a register variable! */
1283 
1284 fldty(p) struct symtab *p; {
1285 	; /* all types are OK here... */
1286 	}
1287 
fldal(t)1288 fldal(t) unsigned t; { /* field alignment... */
1289 	if( t == ENUMTY ) return( ALCHAR );  /* this should be thought through better... */
1290 	if( ISPTR(t) ){ /* really for the benefit of honeywell (and someday IBM) */
1291 		if( pflag ) uerror( "nonportable field type" );
1292 		}
1293 	else uerror( "illegal field type" );
1294 	return(ALINT);
1295 	}
1296 
main(argc,argv)1297 main(argc, argv)
1298 	int	argc;
1299 	char	**argv;
1300 {
1301 	extern char	*optarg;
1302 	extern int	optind;
1303 	int	ch;
1304 
1305 	while ((ch = getopt(argc,argv,"C:D:I:U:LX:Pabchnpuvxz")) != EOF)
1306 		switch((char)ch) {
1307 			case 'C':
1308 				Cflag = 1;
1309 				libname = optarg;
1310 				continue;
1311 			case 'D':	/* #define */
1312 			case 'I':	/* include path */
1313 			case 'U':	/* #undef */
1314 			case 'X':	/* debugging, done in first pass */
1315 			case 'P':	/* debugging, done in second pass */
1316 				break;
1317 			case 'L':
1318 				libflag = 1;
1319 				/*FALLTHROUGH*/
1320 			case 'v':	/* unused arguments in functions */
1321 				vflag = 0;
1322 				break;
1323 			case 'a':	/* long to int assignment */
1324 				++aflag;
1325 				break;
1326 			case 'b':	/* unreached break statements */
1327 				brkflag = 1;
1328 				break;
1329 			case 'c':	/* questionable casts */
1330 				cflag = 1;
1331 				break;
1332 			case 'h':	/* heuristics */
1333 				hflag = 1;
1334 				break;
1335 			case 'n':	/* standard library check */
1336 				nflag = 1;
1337 				break;
1338 			case 'p':	/* IBM & GCOS portability */
1339 				pflag = 1;
1340 				break;
1341 			case 'u':	/* 2nd pass: undefined or unused */
1342 				break;
1343 			case 'x':	/* unused externs */
1344 				xflag = 1;
1345 				break;
1346 			case 'z':	/* use of undefined structures */
1347 				zflag = 1;
1348 				break;
1349 			case '?':
1350 			default:
1351 				fputs("usage: lint [-C lib] [-D def] [-I include] [-U undef] [-Labchnpuvx] file ...\n",stderr);
1352 				exit(1);
1353 		}
1354 
1355 	if (!pflag) {		/* set sizes to sizes of target machine */
1356 # ifdef gcos
1357 		SZCHAR = ALCHAR = 9;
1358 # else
1359 		SZCHAR = ALCHAR = 8;
1360 # endif
1361 		SZINT = ALINT = sizeof(int)*SZCHAR;
1362 		SZFLOAT = ALFLOAT = sizeof(float)*SZCHAR;
1363 		SZDOUBLE = ALDOUBLE = sizeof(double)*SZCHAR;
1364 		SZLONG = ALLONG = sizeof(long)*SZCHAR;
1365 		SZSHORT = ALSHORT = sizeof(short)*SZCHAR;
1366 		SZPOINT = ALPOINT = sizeof(int *)*SZCHAR;
1367 		ALSTRUCT = ALINT;
1368 		/* now, fix some things up for various machines (I wish we had "alignof") */
1369 
1370 # ifdef pdp11
1371 		ALLONG = ALDOUBLE = ALFLOAT = ALINT;
1372 # endif
1373 # ifdef ibm
1374 		ALSTRUCT = ALCHAR;
1375 # endif
1376 	}
1377 	return(mainp1(argc,argv));
1378 }
1379 
ctype(type)1380 ctype( type ) unsigned type; { /* are there any funny types? */
1381 	return( type );
1382 	}
1383 
commdec(i)1384 commdec( i ){
1385 	/* put out a common declaration */
1386 	if( stab[i].sclass == STATIC ) outdef( &stab[i], LST, USUAL );
1387 	else outdef( &stab[i], libflag?LIB:LDC, USUAL );
1388 	}
1389 
isitfloat(s)1390 isitfloat ( s ) char *s; {
1391 	/* s is a character string;
1392 	   if floating point is implemented, set dcon to the value of s */
1393 	/* lint version
1394 	*/
1395 	dcon = atof( s );
1396 	return( DCON );
1397 	}
1398 
fldcon(p)1399 fldcon( p ) register NODE *p; {
1400 	/* p is an assignment of a constant to a field */
1401 	/* check to see if the assignment is going to overflow, or otherwise cause trouble */
1402 	register s;
1403 	CONSZ v;
1404 
1405 	if( !hflag & !pflag ) return;
1406 
1407 	s = UPKFSZ(p->in.left->tn.rval);
1408 	v = p->in.right->tn.lval;
1409 
1410 	switch( p->in.left->in.type ){
1411 
1412 	case CHAR:
1413 	case INT:
1414 	case SHORT:
1415 	case LONG:
1416 	case ENUMTY:
1417 		if( v>=0 && (v>>(s-1))==0 ) return;
1418 		werror( "precision lost in assignment to (possibly sign-extended) field" );
1419 	default:
1420 		return;
1421 
1422 	case UNSIGNED:
1423 	case UCHAR:
1424 	case USHORT:
1425 	case ULONG:
1426 		if( v<0 || (v>>s)!=0 ) werror( "precision lost in field assignment" );
1427 
1428 		return;
1429 		}
1430 
1431 	}
1432 
1433 outdef( p, lty, mode ) struct symtab *p; {
1434 	/* output a definition for the second pass */
1435 	/* if mode is > USUAL, it is the number of args */
1436 	char *fname;
1437 	TWORD t;
1438 	int line;
1439 	static union rec rc;
1440 
1441 	if( mode == NOFILE ){
1442 		fname = "???";
1443 		line = p->suse;
1444 		}
1445 	else if( mode == SVLINE ){
1446 		fname = ftitle;
1447 		line = -p->suse;
1448 		}
1449 	else {
1450 		fname = ftitle;
1451 		line = lineno;
1452 		}
1453 	fsave( fname );
1454 #ifndef FLEXNAMES
1455 	strncpy( rc.l.name, exname(p->sname), LCHNM );
1456 #endif
1457 	rc.l.decflag = lty;
1458 	t = p->stype;
1459 	if( mode == DECTY ) t = DECREF(t);
1460 	rc.l.type.aty = t;
1461 	rc.l.type.extra = 0;
1462 	rc.l.type.extra1 = 0;
1463 	astype( &rc.l.type, p->sizoff );
1464 	rc.l.nargs = (mode>USUAL) ? mode : 0;
1465 	rc.l.fline = line;
1466 	fwrite( (char *)&rc, sizeof(rc), 1, stdout );
1467 #ifdef FLEXNAMES
1468 	rc.l.name = exname(p->sname);
1469 	fwrite( rc.l.name, strlen(rc.l.name)+1, 1, stdout );
1470 #endif
1471 	}
1472 int proflg;
1473 int gdebug;
1474