home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / lint / lpass2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-01-15  |  6.8 KB  |  368 lines

  1. # include "lmanifest"
  2. # include "manifest"
  3.  
  4. # define USED 01
  5. # define VUSED 02
  6. # define EUSED 04
  7. # define RVAL 010
  8. # define VARARGS 0100
  9.  
  10. typedef struct { TWORD aty; int extra; } atype;
  11.  
  12. struct line {
  13.     char name[8];
  14.     int decflag;
  15.     atype type;
  16.     int nargs;
  17.     atype atyp[50];
  18.     int fline;
  19.     char file[100];
  20.     }
  21.  
  22.     l1,
  23.     l2,
  24.     *pd,    /* pointer to line having definition */
  25.     *pc,    /* pointer to current line read */
  26.     *p3;    /* used for swapping pc and pd */
  27.  
  28. int uses = USED;
  29. int hflag = 0;
  30. int pflag = 0;
  31. int xflag = 0;
  32. int uflag = 1;
  33.  
  34.  
  35. main( argc, argv ) char *argv[]; {
  36.  
  37.     register char *p;
  38.  
  39.     /* first argument is - options */
  40.  
  41.     if( argc>=2 && argv[1][0] == '-' ){
  42.         for( p=argv[1]; *p; ++p ){
  43.             switch( *p ){
  44.  
  45.             case 'h':
  46.                 hflag = 1;
  47.                 break;
  48.  
  49.             case 'p':
  50.                 pflag = 1;
  51.                 break;
  52.  
  53.             case 'x':
  54.                 xflag = 1;
  55.                 break;
  56.  
  57.             case 'u':
  58.                 uflag = 0;
  59.                 break;
  60.  
  61.                 }
  62.             }
  63.         }
  64.  
  65.  
  66.  
  67.     pd = &l1;
  68.     pc = &l2;
  69.     pd->name[0] = '\0' ;
  70.     pd->fline = 0;
  71.     pd->file[0] = '\0';
  72.     pd->decflag = LDI;
  73.  
  74.     /* main loop: read a line;
  75.         if same as last line, check compatibility
  76.         if not same as last line, becomes df.
  77.         */
  78.  
  79.     for(;;){
  80.         lread();
  81.         if( steq(pc->name, pd->name) ) chkcompat();
  82.         else {
  83.             lastone();
  84.             setuse();
  85.             p3=pc;
  86.             pc = pd;
  87.             pd = p3;
  88.             }
  89.         }
  90.  
  91.     }
  92.  
  93. lread(){ /* read a line into pc */
  94.  
  95.     register i, n;
  96.  
  97.     getnam( pc->name );
  98.  
  99.     pc->decflag = rdin10();
  100.     rdinty( &pc->type );
  101.     n = pc->nargs = rdin10();
  102.     if( n<0 ) n = -n;
  103.  
  104.     for( i=0; i<n; ++i ){
  105.         rdinty( &pc->atyp[i] );
  106.         }
  107.  
  108.     getnam( pc->file );
  109.     pc->fline = rdin10();
  110.  
  111.     while( getchar() != '\n' ) ; /* VOID */
  112.     }
  113.  
  114. rdin10(){
  115.     register val, c, s;
  116.  
  117.     val = 0;
  118.     s = 1;
  119.  
  120.     while( (c=getchar()) != '\t' ){
  121.         if( c <= 0 ) error( "unexpected EOF" );
  122.         else if( c == '-' ) {
  123.             s = -1;
  124.             continue;
  125.             }
  126.         else if( c<'0' || c>'9' ) {
  127.             error("rotten digit: %o\n", c );
  128.             }
  129.         val = val*10 + c - '0';
  130.         }
  131.     return( val*s );
  132.     }
  133.  
  134. rdinty( p ) atype *p; {
  135.     register val, c, s;
  136.  
  137.     val = 0;
  138.     s = 1;
  139.  
  140.     while( (c=getchar()) != '\t' && c!= '<' ){
  141.         if( c <= 0 ) error( "unexpected EOF" );
  142.         else if( c == '-' ) {
  143.             s = -1;
  144.             continue;
  145.             }
  146.         else if( c<'0' || c>'7' ) {
  147.             error("rotten digit: %o\n", c );
  148.             }
  149.         val = (val<<3) + c - '0';
  150.         }
  151.     p->aty = val*s;
  152.     if( c == '<' ) p->extra = rdin10();
  153.     else p->extra = 0;
  154.     }
  155.  
  156. getnam(p) char *p; {
  157.     register c;
  158.     while( (c=getchar()) != '\t' ){
  159.         if( c == '\n' ) error( "rotten name\n" );
  160.         if( c <= 0 ) cleanup();
  161.         *p++ = c;
  162.         }
  163.     *p = '\0';
  164.     }
  165.  
  166. /* VARARGS */
  167. error( s, a ) char *s; {
  168.  
  169.     fprintf( stderr, "pass 2 error: " );
  170.     fprintf( stderr, s, a );
  171.     fprintf( stderr, "\n" );
  172.     exit(1);
  173.     }
  174.  
  175. steq(p,q) char *p,*q; { /* check that the p and q names are the same */
  176.  
  177.  
  178.     while( *p == *q ){
  179.         if( *p == 0 ) return(1);
  180.         ++p;
  181.         ++q;
  182.         }
  183.  
  184.     return(0);
  185.     }
  186.  
  187. chkcompat(){
  188.     /* are the types, etc. in pc and pd compatible */
  189.     register int i;
  190.  
  191.     setuse();
  192.  
  193.     /* argument check */
  194.  
  195.     if( pd->decflag & (LDI|LIB|LUV|LUE) ){
  196.         if( pc->decflag & (LUV|LIB|LUE) ){
  197.             if( pd->nargs != pc->nargs ){
  198.                 if( !(uses&VARARGS) ){
  199.                     printf( "%.7s: variable # of args.", pd->name );
  200.                     viceversa();
  201.                     }
  202.                 if( pc->nargs > pd->nargs ) pc->nargs = pd->nargs;
  203.                 if( !(pd->decflag & (LDI|LIB) ) ) {
  204.                     pd->nargs = pc->nargs;
  205.                     uses |= VARARGS;
  206.                     }
  207.                 }
  208.             for( i=0; i<pc->nargs; ++i ){
  209.                 if( chktype(&pd->atyp[i], &pc->atyp[i]) ){
  210.                     printf( "%.7s, arg. %d used inconsistently",
  211.                         pd->name, i+1 );
  212.                     viceversa();
  213.                     }
  214.                 }
  215.             }
  216.         }
  217.  
  218.     if( (pd->decflag&(LDI|LIB|LUV)) && pc->decflag==LUV ){
  219.         if( chktype( &pc->type, &pd->type ) ){
  220.             printf( "%.7s value used inconsistently", pd->name );
  221.             viceversa();
  222.             }
  223.         }
  224.  
  225.     /* check for multiple declaration */
  226.  
  227.     if( (pd->decflag&LDI) && (pc->decflag&(LDI|LIB)) ){
  228.         printf( "%.7s multiply declared", pd->name );
  229.         viceversa();
  230.         }
  231.  
  232.     /* do a bit of checking of definitions and uses... */
  233.  
  234.     if( (pd->decflag & (LDI|LIB|LDX|LDC)) && (pc->decflag & (LDX|LDC)) && pd->type.aty != pc->type.aty ){
  235.         printf( "%.7s value declared inconsistently", pd->name );
  236.         viceversa();
  237.         }
  238.  
  239.     /* better not call functions which are declared to be structure or union returning */
  240.  
  241.     if( (pd->decflag & (LDI|LIB|LDX|LDC)) && (pc->decflag & LUE) && pd->type.aty != pc->type.aty ){
  242.         /* only matters if the function returns union or structure */
  243.         TWORD ty;
  244.         ty = pd->type.aty;
  245.         if( ISFTN(ty) && ((ty = DECREF(ty))==STRTY || ty==UNIONTY ) ){
  246.             printf( "%.7s function value type must be declared before use", pd->name );
  247.             viceversa();
  248.             }
  249.         }
  250.  
  251.     if( pflag && pd->decflag==LDX && pc->decflag == LUM && !ISFTN(pd->type.aty) ){
  252.         /* make the external declaration go away */
  253.         /* in effect, it was used without being defined */
  254.  
  255.         /* swap pc and pd */
  256.         p3 = pc;
  257.         pc = pd;
  258.         pd = p3;
  259.         }
  260.  
  261.     }
  262.  
  263. viceversa(){
  264.     /* print out file comparison */
  265.     printf( "    %s(%d)  ::  %s(%d)\n", pd->file, pd->fline, pc->file, pc->fline );
  266.     }
  267.  
  268.     /* messages for defintion/use */
  269. char *
  270. mess[2][2] = {
  271.     "",
  272.     "%.7s used( %s(%d) ), but not defined\n",
  273.     "%.7s defined( %s(%d) ), but never used\n",
  274.     "%.7s declared( %s(%d) ), but never used or defined\n"
  275.     };
  276.  
  277. lastone(){
  278.  
  279.     /* called when pc and pd are at last different */
  280.     register nu, nd;
  281.  
  282.     nu = nd = 0;
  283.  
  284.     if( !(uses&USED) && pd->decflag != LIB ) {
  285.         if( !steq(pd->name,"main") )
  286.             nu = 1;
  287.         }
  288.  
  289.     if( !ISFTN(pd->type.aty) ){
  290.         switch( pd->decflag ){
  291.  
  292.         case LIB:
  293.             nu = nd = 0;  /* don't complain about uses on libraries */
  294.             break;
  295.         case LDX:
  296.             if( !xflag ) break;
  297.         case LUV:
  298.         case LUE:
  299.         case LUM:
  300.             nd = 1;
  301.             }
  302.         }
  303.  
  304.     if( uflag && ( nu || nd ) ) printf( mess[nu][nd], pd->name, pd->file, pd->fline );
  305.  
  306.     if( (uses&(RVAL+EUSED)) == (RVAL+EUSED) ){
  307.         printf( "%.7s returns value which is %s ignored\n", pd->name,
  308.             uses&VUSED ? "sometimes" : "always" );
  309.         }
  310.  
  311.     if( (uses&(RVAL+VUSED)) == (VUSED) && (pd->decflag&(LDI|LIB)) ){
  312.         printf( "%.7s value is used, but none returned\n", pd->name );
  313.         }
  314.  
  315.     /* clean up pc, in preparation for the next thing */
  316.  
  317.     uses = 0;
  318.     if( pc->nargs < 0 ){
  319.         pc->nargs = -pc->nargs;
  320.         uses = VARARGS;
  321.         }
  322.  
  323.     }
  324.  
  325. cleanup(){ /* call lastone and die gracefully */
  326.     lastone();
  327.     exit(0);
  328.     }
  329.  
  330. setuse(){ /* check new type to ensure that it is used */
  331.  
  332.     switch( pc->decflag ){
  333.  
  334.     case LRV:
  335.         uses |= RVAL;
  336.         return;
  337.     case LUV:
  338.         uses |= VUSED+USED;
  339.         return;
  340.     case LUE:
  341.         uses |= EUSED+USED;
  342.         return;
  343.     case LUM:
  344.         uses |= USED;
  345.         return;
  346.  
  347.         }
  348.     }
  349.  
  350. chktype( pt1, pt2 ) register atype *pt1, *pt2; {
  351.  
  352.     /* check the two type words to see if they are compatible */
  353.     /* for the moment, enums are turned into ints, and should be checked as such */
  354.     if( pt1->aty == ENUMTY ) pt1->aty =  INT;
  355.     if( pt2->aty == ENUMTY ) pt2->aty = INT;
  356.  
  357.     if( pt2->extra ){ /* constant passed in */
  358.         if( pt1->aty == UNSIGNED && pt2->aty == INT ) return( 0 );
  359.         else if( pt1->aty == ULONG && pt2->aty == LONG ) return( 0 );
  360.         }
  361.     else if( pt1->extra ){ /* for symmetry */
  362.         if( pt2->aty == UNSIGNED && pt1->aty == INT ) return( 0 );
  363.         else if( pt2->aty == ULONG && pt1->aty == LONG ) return( 0 );
  364.         }
  365.  
  366.     return( pt1->aty != pt2->aty );
  367.     }
  368.