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