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