1: #ifndef lint
   2: static char sccsid[] = "@(#)lint.c	1.10	(Berkeley)	3/20/86";
   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:     int s;
 655: 
 656:     switch( o = p->in.op ){
 657: 
 658:     case SCONV:
 659:     case PCONV:
 660:         if( p->in.left->in.type==ENUMTY ){
 661:             p->in.left = pconvert( p->in.left );
 662:             }
 663:         /* assume conversion takes place; type is inherited */
 664:         t = p->in.type;
 665:         tl = p->in.left->in.type;
 666:         if( aflag && (tl==LONG||tl==ULONG) && (t!=LONG&&t!=ULONG&&t!=UNDEF) ){
 667:             werror( "long assignment may lose accuracy" );
 668:             }
 669:         if( aflag>=2 && (tl!=LONG&&tl!=ULONG) && (t==LONG||t==ULONG) && p->in.left->in.op != ICON ){
 670:             werror( "assignment to long may sign-extend incorrectly" );
 671:             }
 672:         if( ISPTR(tl) && ISPTR(t) ){
 673:             tl = DECREF(tl);
 674:             t = DECREF(t);
 675:             switch( ISFTN(t) + ISFTN(tl) ){
 676: 
 677:             case 0:  /* neither is a function pointer */
 678:                 if( talign(t,p->fn.csiz) > talign(tl,p->in.left->fn.csiz) ){
 679:                     if( hflag||pflag ) werror( "possible pointer alignment problem" );
 680:                     }
 681:                 break;
 682: 
 683:             case 1:
 684:                 werror( "questionable conversion of function pointer" );
 685: 
 686:             case 2:
 687:                 ;
 688:                 }
 689:             }
 690:         p->in.left->in.type = p->in.type;
 691:         p->in.left->fn.cdim = p->fn.cdim;
 692:         p->in.left->fn.csiz = p->fn.csiz;
 693:         p->in.op = FREE;
 694:         return( p->in.left );
 695: 
 696:     case PVCONV:
 697:     case PMCONV:
 698:         if( p->in.right->in.op != ICON ) cerror( "bad conversion");
 699:         p->in.op = FREE;
 700:         return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) );
 701: 
 702:     case RS:
 703:     case LS:
 704:     case ASG RS:
 705:     case ASG LS:
 706:         if( p->in.right->in.op != ICON )
 707:             break;
 708:         s = p->in.right->tn.lval;
 709:         if( s < 0 )
 710:             werror( "negative shift" );
 711:         else
 712:         if( s >= dimtab[ p->fn.csiz ] )
 713:             werror( "shift greater than size of object" );
 714:         break;
 715: 
 716:         }
 717: 
 718:     return(p);
 719:     }
 720: 
 721: NODE *
 722: offcon( off, t, d, s ) OFFSZ off; TWORD t;{  /* make a structure offset node */
 723:     register NODE *p;
 724:     p = bcon(0);
 725:     p->tn.lval = off/SZCHAR;
 726:     return(p);
 727:     }
 728: 
 729: noinit(){
 730:     /* storage class for such as "int a;" */
 731:     return( pflag ? EXTDEF : EXTERN );
 732:     }
 733: 
 734: 
 735: cinit( p, sz ) NODE *p; { /* initialize p into size sz */
 736:     inoff += sz;
 737:     if( p->in.op == INIT ){
 738:         if( p->in.left->in.op == ICON ) return;
 739:         if( p->in.left->in.op == NAME && p->in.left->in.type == MOE ) return;
 740:         }
 741:     uerror( "illegal initialization" );
 742:     }
 743: 
 744: char *
 745: exname( p ) char *p; {
 746:     /* make a name look like an external name in the local machine */
 747:     static char aa[8];
 748:     register int i;
 749: 
 750:     if( !pflag ) return(p);
 751:     for( i=0; i<6; ++i ){
 752:         if( isupper(*p ) ) aa[i] = tolower( *p );
 753:         else aa[i] = *p;
 754:         if( *p ) ++p;
 755:         }
 756:     aa[6] = '\0';
 757:     return( aa );
 758:     }
 759: 
 760: char *
 761: strip(s) char *s; {
 762: #ifndef FLEXNAMES
 763:     static char x[LFNM+1];
 764: #else
 765:     static char x[BUFSIZ];
 766: #endif
 767:     register char *p;
 768:     static  int stripping = 0;
 769: 
 770:     if (stripping)
 771:         return(s);
 772:     stripping++;
 773:     for( p=x; *s; ++s ){
 774:         if( *s != '"' ){
 775: #ifndef FLEXNAMES
 776: /* PATCHED by ROBERT HENRY on 8Jul80 to fix 14 character file name bug */
 777:             if( p >= &x[LFNM] )
 778: #else
 779:             if( p >= &x[BUFSIZ] )
 780: #endif
 781:                 cerror( "filename too long" );
 782:             *p++ = *s;
 783:         }
 784:     }
 785:     stripping = 0;
 786:     *p = '\0';
 787: #ifndef FLEXNAMES
 788:     return( x );
 789: #else
 790:     return( hash(x) );
 791: #endif
 792:     }
 793: 
 794: fsave( s ) char *s; {
 795:     static union rec fsname;
 796:     s = strip( s );
 797: #ifndef FLEXNAMES
 798:     if( strncmp( s, fsname.f.fn, LFNM ) )
 799: #else
 800:     if (fsname.f.fn == NULL || strcmp(s, fsname.f.fn))
 801: #endif
 802:         {
 803:         /* new one */
 804: #ifndef FLEXNAMES
 805:         strncpy( fsname.f.fn, s, LFNM );
 806: #else
 807:         fsname.f.fn = s;
 808: #endif
 809:         fsname.f.decflag = LFN;
 810:         fwrite( (char *)&fsname, sizeof(fsname), 1, stdout );
 811: #ifdef FLEXNAMES
 812:         /* if generating a library, prefix with the library name */
 813:         /* only do this for flexnames */
 814:         if( libname ){
 815:             fwrite( libname, strlen(libname), 1, stdout );
 816:             putchar( ':' );
 817:             }
 818:         fwrite( fsname.f.fn, strlen(fsname.f.fn)+1, 1, stdout );
 819: #endif
 820:         }
 821:     }
 822: 
 823: where(f){ /* print true location of error */
 824:     if( f == 'u' && nerrors > 1 )
 825:         --nerrors; /* don't get "too many errors" */
 826:     fprintf( stderr, "%s(%d): ", strip(ftitle), lineno);
 827:     }
 828: 
 829:     /* a number of dummy routines, unneeded by lint */
 830: 
 831: branch(n){;}
 832: defalign(n){;}
 833: deflab(n){;}
 834: bycode(t,i){;}
 835: cisreg(t) TWORD t; {return(1);}  /* everyting is a register variable! */
 836: 
 837: fldty(p) struct symtab *p; {
 838:     ; /* all types are OK here... */
 839:     }
 840: 
 841: fldal(t) unsigned t; { /* field alignment... */
 842:     if( t == ENUMTY ) return( ALCHAR );  /* this should be thought through better... */
 843:     if( ISPTR(t) ){ /* really for the benefit of honeywell (and someday IBM) */
 844:         if( pflag ) uerror( "nonportable field type" );
 845:         }
 846:     else uerror( "illegal field type" );
 847:     return(ALINT);
 848:     }
 849: 
 850: main( argc, argv ) char *argv[]; {
 851:     char *p;
 852:     int i;
 853: 
 854:     /* handle options */
 855: 
 856:     for( i = 1; i < argc; i++ )
 857:         for( p=argv[i]; *p; ++p ){
 858: 
 859:             switch( *p ){
 860: 
 861:             case '-':
 862:                 continue;
 863: 
 864:             case '\0':
 865:                 break;
 866: 
 867:             case 'b':
 868:                 brkflag = 1;
 869:                 continue;
 870: 
 871:             case 'p':
 872:                 pflag = 1;
 873:                 continue;
 874: 
 875:             case 'c':
 876:                 cflag = 1;
 877:                 continue;
 878: 
 879:             case 's':
 880:                 /* for the moment, -s triggers -h */
 881: 
 882:             case 'h':
 883:                 hflag = 1;
 884:                 continue;
 885: 
 886:             case 'L':
 887:                 libflag = 1;
 888:             case 'v':
 889:                 vflag = 0;
 890:                 continue;
 891: 
 892:             case 'x':
 893:                 xflag = 1;
 894:                 continue;
 895: 
 896:             case 'a':
 897:                 ++aflag;
 898:             case 'u':   /* done in second pass */
 899:             case 'n':   /* done in shell script */
 900:                 continue;
 901: 
 902:             case 'z':
 903:                 zflag = 1;
 904:                 continue;
 905: 
 906:             case 't':
 907:                 werror( "option %c now default: see `man 6 lint'", *p );
 908:                 continue;
 909: 
 910:             case 'P':   /* debugging, done in second pass */
 911:                 continue;
 912: 
 913:             case 'C':
 914:                 Cflag = 1;
 915:                 if( p[1] ) libname = p + 1;
 916:                 while( p[1] ) p++;
 917:                 continue;
 918: 
 919:             default:
 920:                 uerror( "illegal option: %c", *p );
 921:                 continue;
 922: 
 923:                 }
 924:             }
 925: 
 926:     if( !pflag ){  /* set sizes to sizes of target machine */
 927: # ifdef gcos
 928:         SZCHAR = ALCHAR = 9;
 929: # else
 930:         SZCHAR = ALCHAR = 8;
 931: # endif
 932:         SZINT = ALINT = sizeof(int)*SZCHAR;
 933:         SZFLOAT = ALFLOAT = sizeof(float)*SZCHAR;
 934:         SZDOUBLE = ALDOUBLE = sizeof(double)*SZCHAR;
 935:         SZLONG = ALLONG = sizeof(long)*SZCHAR;
 936:         SZSHORT = ALSHORT = sizeof(short)*SZCHAR;
 937:         SZPOINT = ALPOINT = sizeof(int *)*SZCHAR;
 938:         ALSTRUCT = ALINT;
 939:         /* now, fix some things up for various machines (I wish we had "alignof") */
 940: 
 941: # ifdef pdp11
 942:         ALLONG = ALDOUBLE = ALFLOAT = ALINT;
 943: #endif
 944: # ifdef ibm
 945:         ALSTRUCT = ALCHAR;
 946: #endif
 947:         }
 948: 
 949:     return( mainp1( argc, argv ) );
 950:     }
 951: 
 952: ctype( type ) unsigned type; { /* are there any funny types? */
 953:     return( type );
 954:     }
 955: 
 956: commdec( i ){
 957:     /* put out a common declaration */
 958:     if( stab[i].sclass == STATIC ) outdef( &stab[i], LST, USUAL );
 959:     else outdef( &stab[i], libflag?LIB:LDC, USUAL );
 960:     }
 961: 
 962: isitfloat ( s ) char *s; {
 963:     /* s is a character string;
 964: 	   if floating point is implemented, set dcon to the value of s */
 965:     /* lint version
 966: 	*/
 967:     dcon = atof( s );
 968:     return( DCON );
 969:     }
 970: 
 971: fldcon( p ) register NODE *p; {
 972:     /* p is an assignment of a constant to a field */
 973:     /* check to see if the assignment is going to overflow, or otherwise cause trouble */
 974:     register s;
 975:     CONSZ v;
 976: 
 977:     if( !hflag & !pflag ) return;
 978: 
 979:     s = UPKFSZ(p->in.left->tn.rval);
 980:     v = p->in.right->tn.lval;
 981: 
 982:     switch( p->in.left->in.type ){
 983: 
 984:     case CHAR:
 985:     case INT:
 986:     case SHORT:
 987:     case LONG:
 988:     case ENUMTY:
 989:         if( v>=0 && (v>>(s-1))==0 ) return;
 990:         werror( "precision lost in assignment to (possibly sign-extended) field" );
 991:     default:
 992:         return;
 993: 
 994:     case UNSIGNED:
 995:     case UCHAR:
 996:     case USHORT:
 997:     case ULONG:
 998:         if( v<0 || (v>>s)!=0 ) werror( "precision lost in field assignment" );
 999: 
1000:         return;
1001:         }
1002: 
1003:     }
1004: 
1005: outdef( p, lty, mode ) struct symtab *p; {
1006:     /* output a definition for the second pass */
1007:     /* if mode is > USUAL, it is the number of args */
1008:     char *fname;
1009:     TWORD t;
1010:     int line;
1011:     static union rec rc;
1012: 
1013:     if( mode == NOFILE ){
1014:         fname = "???";
1015:         line = p->suse;
1016:         }
1017:     else if( mode == SVLINE ){
1018:         fname = ftitle;
1019:         line = -p->suse;
1020:         }
1021:     else {
1022:         fname = ftitle;
1023:         line = lineno;
1024:         }
1025:     fsave( fname );
1026: #ifndef FLEXNAMES
1027:     strncpy( rc.l.name, exname(p->sname), LCHNM );
1028: #endif
1029:     rc.l.decflag = lty;
1030:     t = p->stype;
1031:     if( mode == DECTY ) t = DECREF(t);
1032:     rc.l.type.aty = t;
1033:     rc.l.type.extra = 0;
1034:     rc.l.type.extra1 = 0;
1035:     astype( &rc.l.type, p->sizoff );
1036:     rc.l.nargs = (mode>USUAL) ? mode : 0;
1037:     rc.l.fline = line;
1038:     fwrite( (char *)&rc, sizeof(rc), 1, stdout );
1039: #ifdef FLEXNAMES
1040:     rc.l.name = exname(p->sname);
1041:     fwrite( rc.l.name, strlen(rc.l.name)+1, 1, stdout );
1042: #endif
1043:     }
1044: int proflg;
1045: int gdebug;

Defined functions

andable defined in line 621; never used
aocode defined in line 558; never used
astype defined in line 166; used 3 times
bfcode defined in line 207; never used
branch defined in line 831; never used
bycode defined in line 834; never used
cinit defined in line 735; never used
cisreg defined in line 835; never used
clocal defined in line 637; never used
commdec defined in line 956; never used
contx defined in line 53; used 1 times
ctargs defined in line 262; used 1 times
ctype defined in line 952; never used
defalign defined in line 832; never used
deflab defined in line 833; never used
defnam defined in line 603; never used
ecode defined in line 98; never used
efcode defined in line 539; never used
ejobcode defined in line 106; never used
exname defined in line 744; used 2 times
fldal defined in line 841; never used
fldcon defined in line 971; used 1 times
fldty defined in line 837; never used
fsave defined in line 794; used 3 times
isitfloat defined in line 962; never used
lmerge defined in line 496; used 3 times
lprt defined in line 321; used 5 times
lpta defined in line 274; used 2 times
main defined in line 850; never used
noinit defined in line 729; never used
offcon defined in line 721; never used
outdef defined in line 1005; used 10 times
strip defined in line 760; used 2 times
where defined in line 823; never used
zecode defined in line 613; never used

Defined variables

ALCHAR defined in line 22; used 4 times
ALDOUBLE defined in line 25; used 2 times
ALFLOAT defined in line 24; used 2 times
ALINT defined in line 23; used 4 times
ALLONG defined in line 26; used 2 times
ALPOINT defined in line 28; used 1 times
ALSHORT defined in line 27; used 1 times
ALSTRUCT defined in line 29; used 2 times
Cflag defined in line 38; used 6 times
SZCHAR defined in line 15; used 9 times
SZDOUBLE defined in line 18; used 1 times
SZFLOAT defined in line 17; used 1 times
SZINT defined in line 16; used 2 times
SZLONG defined in line 19; used 1 times
SZPOINT defined in line 21; used 1 times
SZSHORT defined in line 20; used 1 times
aflag defined in line 36; used 3 times
argflag defined in line 33; used 2 times
gdebug defined in line 1045; never used
libflag defined in line 34; used 5 times
libname defined in line 39; used 4 times
lnames defined in line 51; used 2 times
lnp defined in line 51; used 11 times
proflg defined in line 1044; never used
sccsid defined in line 2; never used
vaflag defined in line 35; used 6 times
vflag defined in line 31; used 5 times
xflag defined in line 32; used 2 times
zflag defined in line 37; used 3 times

Defined struct's

lnm defined in line 49; used 6 times

Defined macros

DECTY defined in line 43; used 2 times
EFF defined in line 12; used 8 times
LNAMES defined in line 47; used 2 times
NOFILE defined in line 44; used 2 times
SVLINE defined in line 45; used 2 times
USUAL defined in line 42; used 5 times
VAL defined in line 11; used 2 times
VALADDR defined in line 319; used 3 times
VALASGOP defined in line 318; used 2 times
VALSET defined in line 316; used 8 times
VALUSED defined in line 317; used 7 times
Last modified: 1986-03-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3027
Valid CSS Valid XHTML 1.0 Strict