home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
files
/
program
/
varlnsrc
/
varlint.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-07-14
|
10KB
|
424 lines
/*###########################################################################
*
* This program is used to find those pesty errors in varags type
* functions such as printf. It only handles those functions defined
* in the structure"fu".
*
* By Daniel B. Suthers Mar 3, 1988
*
* Copyright 1988 by Daniel B. Suthers, Concord, California, USA.
* License is granted to distribute this program at will, as long as
* the source is also provided free of charge to anyone who recieves
* the binaries, or to anyone who wants it,
* AND all copyright notices are left intact.
* The
*
###move $This_File 755 uprog none /uprog/bin/src/varlint.c
##move $This_File 755 uprog none /usr/uprog/src/bin/varlint.c
*#########################################################################*/
#include <stdio.h>
#include <ctype.h>
#define VER "2.7"
#define MAX 512
#define NUMNAMES 6
#ifdef pdp11
char APPL[] ="\n##move $This_File 755 uprog none /usr/uprog/bin/varlint\n";
#else
char APPL[]="\n###move $This_File 755 uprog none /usr/lbin/varlint\n";
FILE *fopen();
void scandoos();
#endif
struct funcdat{
char nam[9]; /* stores function names*/
int len; /* number of chars in names*/
int pos; /* position of control string*/
int scan;
};
struct funcdat fu[ NUMNAMES] = {
{ "printf", 6, 0, 0},
{ "scanf", 5, 0, 1},
{ "sprintf", 7,1, 0},
{ "sscanf", 6, 1, 1},
{ "fprintf", 7,1, 0},
{ "fscanf", 6, 1, 1}
};
char *fgets(), *findname();
int in_comment = 0; /* flag = 1 when in a comment*/
main(argc, argv, env)
int argc;
char *argv[], *env[];
{
extern int optind;
extern char *optarg;
register int inta;
char filename[128];
FILE *infile ;
while( (inta = getopt( argc, argv, "vVhH")) != EOF)
{
switch (inta)
{
case 'V':
case 'v':
fprintf (stderr, "%s\n"
, VER);
return(0);
case 'h':
case 'H':
help();
return(0);
default:
printf("Bad argument\nTry -h for help.\n");
return(1);
}
}
while( optind < argc ) /* these would be files*/
{
strcpy(filename, argv[optind++]);
if( (infile = fopen(filename, "r") ) == NULL)
{
fprintf(stderr, "Unable to open source file %s\n", filename);
}
else
{
printf("Working on %s\n", filename);
scandoos(infile);
if( infile != (FILE *) NULL)
fclose(infile);
}
}
return(0);
} /*end of main*/
help()
{
printf(
"\n\tCopyright 1988 by Daniel B. Suthers, Concord, California, USA.\n");
printf(
"\tLicense is granted to distribute this program at will, as long as\n");
printf(
"\tthe source is also provided free of charge to anyone who recieves\n");
printf("\tthe binaries, or to anyone who wants it,\n");
printf("\tAND all copyright notices are left intact.\n");
printf("\n\tThis program checks for mismatched arguments in functions\n");
printf("\tthat accept variable arguments ala printf().\n");
printf("\tCurrently supports: printf, scanf and their cousins.\n");
printf("\t(Checks only for # of args and & for integers)\n");
printf("\n\tThe arguments accepted are:\n\n");
printf("\t-v\tPrint the version number and exit.\n");
printf("\t-help\tPrint the most current help.\n");
return(0);
}
#ifdef u3b5
void
#endif
scandoos(infile)
FILE *infile;
{
register int linenum, reterr, oldline;
char buff[MAX*3], *buffp; /* allow 10 lines */
char tempstr[MAX*3];
int funcindex;
linenum = oldline = 0;
reterr = 0;
while( fgets(buff, MAX, infile) != (char *)NULL )
{
if(reterr == 100 ) /* multi line statement */
{
if( oldline == 0)
oldline = linenum;
strcat(tempstr,buff);
strcpy(buff, tempstr);
reterr = 0;
}
linenum++;
if( (buffp = findname(buff,&funcindex)) == NULL )
continue;
if( in_comment )
continue;
/*
printf("%4d: %s",linenum, buffp);
*/
if( (reterr = parsedo(buffp,funcindex)) > 0)
{
if( reterr < 100 )
{
if( oldline != 0)
{
printf("***** Error at line %5d\n%s", oldline, buffp);
oldline = 0;
}
else
printf("***** Error at line %5d\n%s", linenum, buffp);
}
switch(reterr)
{
case 1:
printf("More \"%%\" in control string than there are variables.\n\n");
break;
case 2:
printf("A varible type did not match the \"%%\".\n\n");
break;
case 3:
printf("An undefined variable used.\n\n");
break;
case 4:
printf("An un-recognized construct, might be ok.\n\n");
break;
case 5:
printf("Fewer \"%%\" in control string than there are variables.\n\n");
break;
case 6:
printf("Integer type requires an ampersand (\&).\n\n");
break;
case 7:
printf("Print found a string, expecting an int.\n\n");
break;
case 8:
printf("Unknown %% specifier.\n\n");
break;
case 9:
printf("Re declaration of the function. You sure this is ok?\n\n");
break;
case 10:
printf("Null control string. You sure this is ok?\n\n");
break;
case 100:
strcpy( tempstr, buff);
break;
}
} /* end of if(parsedo) */
else
oldline = 0;
}
} /* end of scandoos() */
char *
findname(string, funcind)
char string[];
int *funcind;
{
char *ptr;
register int a;
ptr = string;
while( *ptr != NULL )
{
if( *ptr == '/') /* set flag if this */
if( *(ptr + 1) == '*') /* is start of comment*/
{
in_comment = 1;
ptr += 2;
continue;
}
if( *ptr == '*' ) /* un-set flag if end */
if( *(ptr+1) == '/') /* of comment */
{
in_comment = 0;
ptr +=2;
continue;
}
for( a = 0; a < NUMNAMES; a++)
{
if( strncmp( ptr, fu[a].nam, fu[a].len ) == 0 )
{
*funcind = a;
return(ptr);
}
}
ptr++;
}
return(NULL);
}
int
parsedo(buff, fi)
char buff[]; /* function string */
int fi; /* fu.[] index */
{
register int parens, pcntnum, c;
char *buffp;
int end=0, inquotes = 0;
int vartype[124]; /* for var type */
parens = 0;
buffp = buff;
buffp += fu[fi].len; /* get past function */
while( isspace(*buffp) ) /* skip white space */
buffp++;
if( *buffp == NULL)
return(100);
if( *buffp != '(' ) /* not a function */
return(0);
if( *(buffp +1) == ')' ) /* function definition */
return(9);
buffp++;
while( isspace(*buffp) ) /* skip white space */
buffp++;
if( *buffp == NULL)
return(100);
for(c = 0;c < fu[fi].pos; c++) /* skip to control string*/
{ /* (stop on comma) */
while( (*buffp != NULL) && (*buffp != ',') )
buffp++;
if( *buffp == NULL)
return(100);
buffp++;
}
if( *buffp == NULL)
return(100);
while( isspace( *(buffp)) ) /* for ' , "test"' */
buffp++;
if( *buffp == NULL)
return(100);
if( *buffp != '"') /* should be on first quote*/
return(4);
if( *(buffp+1) == '"') /* dont want "" as cntl str */
return(10);
/* count the percent signs */
/* starting on first quote */
pcntnum = 0;
end = 0;
while( *buffp++ != NULL )
{
switch(*buffp)
{
case '"':
if( *(buffp-1) != '\\') /* \" is not end */
end = 1;
else if( *(buffp-2) == '\\') /* \\" is end */
end = 1;
break;
case '%':
if( *(buffp-1) != '%')
pcntnum++;
else
{
pcntnum--; /* delete first % of pair */
continue;
}
if( *(buffp+1) == '*' )
{
if( fu[fi].scan == 1)
{
pcntnum--; /* no matching variable */
}
else
{
pcntnum++;
}
}
/*######################
# load array with var type
######################*/
/* throw away justification*/
if( *(buffp +1 ) == '-' || *(buffp +1) == '+')
buffp++;
/* remove blanks and sharps */
while( isspace( *(buffp + 1)) || *(buffp + 1) == '#' )
buffp++;
/* throw away size spec */
while( isdigit(*(buffp+1)) || *(buffp+1) == '.' )
buffp++;
switch (*(buffp + 1) ) /* look at next char for type */
{
case 's':
case '[':
case 'c':
vartype[pcntnum] = 's';
break;
case 'd':
case 'l':
case 'h':
case 'i':
case 'o':
case 'x':
case 'u':
case 'f':
case 'e':
case 'g':
vartype[pcntnum] = 'i';
break;
case '%': /* no action */
case '*':
break;
default:
printf("error at %s\n\n", buffp + 1);
return(8);
break;
}
break;
}
if( end )
break;
}
parens = 0;
inquotes = 1; /* start on last " */
c = 1;
while( *buffp != NULL ) /* look for variables */
{
switch( *buffp )
{
case '(':
parens--;
break;
case ')':
parens++;
break;
case '"': /* for strings */
if( parens == 0) /* at the base level */
{
if( *(buffp-1) != '\\' ) /* \" is not end of str */
{
inquotes = !inquotes;
}
else if( *(buffp-2) == '\\') /* \\" is end */
inquotes = !inquotes;
}
break;
case ',':
if( parens == 0 && inquotes != 1) /* commas outside of func*/
{
pcntnum --;
buffp++;
while( isspace(*buffp) )
buffp++;
if( *buffp == NULL)
return(100);
if( fu[fi].scan == 1 )
{
if( vartype[c] == 'i' && *buffp != '\&' )
return(6);
}
else if( vartype[c] == 'i' && *buffp == '"')
return(7);
c++;
continue; /* buffp already ++ */
}
break;
}
if( parens == 1) /* hit end of function */
{
if( pcntnum > 0 )
return(1);
if( pcntnum < 0)
return(5);
return(0);
}
buffp++;
}
if( parens < 1 )
return(100);
return(0);
} /* end of parsedo() */