1: #if !defined(lint) && defined(DOSCCS)
   2: static char sccsid[] = "@(#)lint.c	1.10.1	(2.11BSD GTE)	1/17/95";
   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: char *hash();
  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 = (int)dimtab[i+3];
 176:             if( j<0 || j>SYMTSZ ){
 177:                 k = (int)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 = (int)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 ) OFFSZ 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:     ATYPE t;        /* XXX static */
 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:     ATYPE t;        /* XXX static */
 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:     CONSZ 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; OFFSZ sz; { /* 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:     static char x[128];     /* was BUFSIZ */
 763:     register char *p;
 764:     static  int stripping = 0;
 765: 
 766:     if (stripping)
 767:         return(s);
 768:     stripping++;
 769:     for( p=x; *s; ++s ){
 770:         if( *s != '"' ){
 771:             if( p >= &x[sizeof (x)] )
 772:                 cerror("filename too long" );
 773:             *p++ = *s;
 774:         }
 775:     }
 776:     stripping = 0;
 777:     *p = '\0';
 778:     return( hash(x) );
 779:     }
 780: 
 781: fsave( s ) char *s; {
 782:     static union rec fsname;
 783: 
 784:     s = strip( s );
 785:     if (fsname.f.fn == NULL || strcmp(s, fsname.f.fn))
 786:         {
 787:         /* new one */
 788:         fsname.f.fn = s;
 789:         fsname.f.decflag = LFN;
 790:         fwrite( (char *)&fsname, sizeof(fsname), 1, stdout );
 791:         /* if generating a library, prefix with the library name */
 792:         if( libname ){
 793:             fwrite( libname, strlen(libname), 1, stdout );
 794:             putchar( ':' );
 795:             }
 796:         fwrite( fsname.f.fn, strlen(fsname.f.fn)+1, 1, stdout );
 797:         }
 798:     }
 799: 
 800: where(f){ /* print true location of error */
 801:     if( f == 'u' && nerrors > 1 )
 802:         --nerrors; /* don't get "too many errors" */
 803:     fprintf( stderr, "%s(%d): ", strip(ftitle), lineno);
 804:     }
 805: 
 806:     /* a number of dummy routines, unneeded by lint */
 807: 
 808: branch(n){;}
 809: defalign(n){;}
 810: deflab(n){;}
 811: bycode(t,i){;}
 812: cisreg(t) TWORD t; {return(1);}  /* everyting is a register variable! */
 813: 
 814: fldty(p) struct symtab *p; {
 815:     ; /* all types are OK here... */
 816:     }
 817: 
 818: fldal(t) unsigned t; { /* field alignment... */
 819:     if( t == ENUMTY ) return( ALCHAR );  /* this should be thought through better... */
 820:     if( ISPTR(t) ){ /* really for the benefit of honeywell (and someday IBM) */
 821:         if( pflag ) uerror("nonportable field type" );
 822:         }
 823:     else uerror("illegal field type" );
 824:     return(ALINT);
 825:     }
 826: 
 827: main( argc, argv ) char *argv[]; {
 828:     char *p;
 829:     int i;
 830:     char ibuf[BUFSIZ];
 831: 
 832:     setbuf(stdin, ibuf);
 833: 
 834:     /* handle options */
 835: 
 836:     for( i = 1; i < argc; i++ )
 837:         for( p=argv[i]; *p; ++p ){
 838: 
 839:             switch( *p ){
 840: 
 841:             case '-':
 842:                 continue;
 843: 
 844:             case '\0':
 845:                 break;
 846: 
 847:             case 'b':
 848:                 brkflag = 1;
 849:                 continue;
 850: 
 851:             case 'p':
 852:                 pflag = 1;
 853:                 continue;
 854: 
 855:             case 'c':
 856:                 cflag = 1;
 857:                 continue;
 858: 
 859:             case 's':
 860:                 /* for the moment, -s triggers -h */
 861: 
 862:             case 'h':
 863:                 hflag = 1;
 864:                 continue;
 865: 
 866:             case 'L':
 867:                 libflag = 1;
 868:             case 'v':
 869:                 vflag = 0;
 870:                 continue;
 871: 
 872:             case 'x':
 873:                 xflag = 1;
 874:                 continue;
 875: 
 876:             case 'a':
 877:                 ++aflag;
 878:             case 'u':   /* done in second pass */
 879:             case 'n':   /* done in shell script */
 880:                 continue;
 881: 
 882:             case 'z':
 883:                 zflag = 1;
 884:                 continue;
 885: 
 886:             case 't':
 887:                 werror("option %c now default: see `man 6 lint'", *p );
 888:                 continue;
 889: 
 890:             case 'P':   /* debugging, done in second pass */
 891:                 continue;
 892: 
 893:             case 'C':
 894:                 Cflag = 1;
 895:                 if( p[1] ) libname = p + 1;
 896:                 while( p[1] ) p++;
 897:                 continue;
 898: 
 899:             default:
 900:                 uerror("illegal option: %c", *p );
 901:                 continue;
 902: 
 903:                 }
 904:             }
 905: 
 906:     if( !pflag ){  /* set sizes to sizes of target machine */
 907: # ifdef gcos
 908:         SZCHAR = ALCHAR = 9;
 909: # else
 910:         SZCHAR = ALCHAR = 8;
 911: # endif
 912:         SZINT = ALINT = sizeof(int)*SZCHAR;
 913:         SZFLOAT = ALFLOAT = sizeof(float)*SZCHAR;
 914:         SZDOUBLE = ALDOUBLE = sizeof(double)*SZCHAR;
 915:         SZLONG = ALLONG = sizeof(long)*SZCHAR;
 916:         SZSHORT = ALSHORT = sizeof(short)*SZCHAR;
 917:         SZPOINT = ALPOINT = sizeof(int *)*SZCHAR;
 918:         ALSTRUCT = ALINT;
 919:         /* now, fix some things up for various machines (I wish we had "alignof") */
 920: 
 921: # ifdef pdp11
 922:         ALLONG = ALDOUBLE = ALFLOAT = ALINT;
 923: #endif
 924: # ifdef ibm
 925:         ALSTRUCT = ALCHAR;
 926: #endif
 927:         }
 928: 
 929:     return( mainp1( argc, argv ) );
 930:     }
 931: 
 932: ctype( type ) unsigned type; { /* are there any funny types? */
 933:     return( type );
 934:     }
 935: 
 936: commdec( i ){
 937:     /* put out a common declaration */
 938:     if( stab[i].sclass == STATIC ) outdef( &stab[i], LST, USUAL );
 939:     else outdef( &stab[i], libflag?LIB:LDC, USUAL );
 940:     }
 941: 
 942: isitfloat ( s ) char *s; {
 943:     /* s is a character string;
 944: 	   if floating point is implemented, set dcon to the value of s */
 945:     /* lint version
 946: 	*/
 947:     dcon = atof( s );
 948:     return( DCON );
 949:     }
 950: 
 951: fldcon( p ) register NODE *p; {
 952:     /* p is an assignment of a constant to a field */
 953:     /* check to see if the assignment is going to overflow, or otherwise cause trouble */
 954:     register s;
 955:     CONSZ v;
 956: 
 957:     if( !hflag & !pflag ) return;
 958: 
 959:     s = UPKFSZ(p->in.left->tn.rval);
 960:     v = p->in.right->tn.lval;
 961: 
 962:     switch( p->in.left->in.type ){
 963: 
 964:     case CHAR:
 965:     case INT:
 966:     case SHORT:
 967:     case LONG:
 968:     case ENUMTY:
 969:         if( v>=0 && (v>>(s-1))==0 ) return;
 970:         werror("precision lost in assignment to (possibly sign-extended) field" );
 971:     default:
 972:         return;
 973: 
 974:     case UNSIGNED:
 975:     case UCHAR:
 976:     case USHORT:
 977:     case ULONG:
 978:         if( v<0 || (v>>s)!=0 ) werror("precision lost in field assignment" );
 979: 
 980:         return;
 981:         }
 982: 
 983:     }
 984: 
 985: outdef( p, lty, mode ) struct symtab *p; {
 986:     /* output a definition for the second pass */
 987:     /* if mode is > USUAL, it is the number of args */
 988:     char *fname;
 989:     TWORD t;
 990:     int line;
 991:     static union rec rc;
 992: 
 993:     if( mode == NOFILE ){
 994:         fname = "???";
 995:         line = p->suse;
 996:         }
 997:     else if( mode == SVLINE ){
 998:         fname = ftitle;
 999:         line = -p->suse;
1000:         }
1001:     else {
1002:         fname = ftitle;
1003:         line = lineno;
1004:         }
1005:     fsave( fname );
1006: #ifndef FLEXNAMES
1007:     strncpy( rc.l.name, exname(p->sname), LCHNM );
1008: #endif
1009:     rc.l.decflag = lty;
1010:     t = p->stype;
1011:     if( mode == DECTY ) t = DECREF(t);
1012:     rc.l.type.aty = t;
1013:     rc.l.type.extra = 0;
1014:     rc.l.type.extra1 = 0;
1015:     astype( &rc.l.type, p->sizoff );
1016:     rc.l.nargs = (mode>USUAL) ? mode : 0;
1017:     rc.l.fline = line;
1018:     fwrite( (char *)&rc, sizeof(rc), 1, stdout );
1019: #ifdef FLEXNAMES
1020:     rc.l.name = exname(p->sname);
1021:     fwrite( rc.l.name, strlen(rc.l.name)+1, 1, stdout );
1022: #endif
1023:     }
1024: int proflg;
1025: 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 808; never used
bycode defined in line 811; never used
cinit defined in line 735; never used
cisreg defined in line 812; never used
clocal defined in line 637; never used
commdec defined in line 936; never used
contx defined in line 53; used 1 times
ctargs defined in line 262; used 1 times
ctype defined in line 932; never used
defalign defined in line 809; never used
deflab defined in line 810; 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 818; never used
fldcon defined in line 951; used 1 times
fldty defined in line 814; never used
fsave defined in line 781; used 3 times
isitfloat defined in line 942; 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 827; never used
noinit defined in line 729; never used
offcon defined in line 721; never used
outdef defined in line 985; used 10 times
strip defined in line 760; used 2 times
where defined in line 800; 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 1025; 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 1024; 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: 1995-01-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5304
Valid CSS Valid XHTML 1.0 Strict