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 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 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 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 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 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 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 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 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 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 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 618 zecode( n ){ 619 /* n integer words of zeros */ 620 OFFSZ temp; 621 temp = n; 622 inoff += temp*SZINT; 623 ; 624 } 625 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 * 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 * 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 745 noinit(){ 746 /* storage class for such as "int a;" */ 747 return( pflag ? EXTDEF : EXTERN ); 748 } 749 750 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 * 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 * 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 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 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 849 branch(n){;} 850 defalign(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 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 893 strforget() 894 { 895 didstr = subscr = 0; 896 } 897 898 static char * 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 * 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 * 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 * 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 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 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 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 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 1380 ctype( type ) unsigned type; { /* are there any funny types? */ 1381 return( type ); 1382 } 1383 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 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 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