Refactoring: Replaced deprecated "match" with the new "Match"

This commit is contained in:
Daniel Marjamäki 2008-03-28 07:18:03 +00:00
parent bf6926232b
commit 4691999ede
12 changed files with 264 additions and 330 deletions

View File

@ -20,67 +20,6 @@ extern bool ShowAll;
// CallStack used when parsing into subfunctions.
static std::list<const TOKEN *> CallStack;
static std::list<const TOKEN *> FunctionList;
static void FillFunctionList()
{
FunctionList.clear();
int indentlevel = 0;
for ( const TOKEN *tok = tokens; tok; tok = tok->next )
{
if ( tok->str[0] == '{' )
indentlevel++;
else if ( tok->str[0] == '}' )
indentlevel--;
else if (indentlevel==0 && match(tok, "var ("))
{
// Check if this is the first token of a function implementation..
for ( const TOKEN *tok2 = tok; tok2; tok2 = tok2->next )
{
if ( tok2->str[0] == ';' )
{
tok = tok2;
break;
}
else if ( tok2->str[0] == '{' )
{
break;
}
else if ( tok2->str[0] == ')' )
{
if ( match(tok2, ") {") )
{
FunctionList.push_back( tok );
tok = tok2;
}
else
{
tok = tok2;
while (tok->next && !strchr(";{", tok->next->str[0]))
tok = tok->next;
}
break;
}
}
}
}
}
static const TOKEN *GetFunctionTokenByName( const char funcname[] )
{
std::list<const TOKEN *>::const_iterator it;
for ( it = FunctionList.begin(); it != FunctionList.end(); it++ )
{
if ( strcmp( (*it)->str, funcname ) == 0 )
{
return *it;
}
}
return NULL;
}
// Modified version of 'ReportError' that also reports the callstack
static void ReportError(const TOKEN *tok, const char errmsg[])
@ -92,87 +31,6 @@ static void ReportError(const TOKEN *tok, const char errmsg[])
ostr << FileLine(tok) << ": " << errmsg;
ReportErr(ostr.str());
}
static bool Match1(const TOKEN *tok, const char pattern[], const char *varname[])
{
if (!tok)
return false;
const char *p = pattern;
while (*p)
{
// Skip spaces in pattern..
while ( *p == ' ' )
p++;
// Extract token from pattern..
char str[50];
char *s = str;
while (*p && *p!=' ')
{
*s = *p;
s++;
p++;
}
*s = 0;
// No token => Success!
if (str[0] == 0)
return true;
// Any symbolname..
if (strcmp(str,"%var%")==0 || strcmp(str,"%type%")==0)
{
if (!IsName(tok->str))
return false;
}
// Variable name..
else if (strcmp(str,"%var1%")==0)
{
if (strcmp(tok->str, varname[0]) != 0)
return false;
for ( int i = 1; varname[i]; i++ )
{
if ( ! gettok(tok, 2) )
return false;
if ( strcmp(getstr(tok, 1), ".") )
return false;
if ( strcmp(getstr(tok, 2), varname[i]) )
return false;
tok = gettok(tok, 2);
}
}
else if (strcmp(str,"%num%")==0)
{
if ( ! IsNumber(tok->str) )
return false;
}
else if (strcmp(str,"%str%")==0)
{
if ( tok->str[0] != '\"' )
return false;
}
else if (strcmp(str, tok->str) != 0)
return false;
tok = tok->next;
if (!tok)
return false;
}
// The end of the pattern has been reached and nothing wrong has been found
return true;
}
//---------------------------------------------------------------------------
@ -189,7 +47,7 @@ static void CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname
// Array index..
if ( Match1(tok, "%var1% [ %num% ]", varname) )
if ( Match(tok, "%var1% [ %num% ]", varname) )
{
const char *num = getstr(tok, 2 + varc);
if (strtol(num, NULL, 10) >= size)
@ -215,7 +73,7 @@ static void CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname
}
// Array index..
if ( !IsName(tok->str) && Match1(tok->next, "%var1% [ %num% ]", varname) )
if ( !IsName(tok->str) && Match(tok->next, "%var1% [ %num% ]", varname) )
{
const char *num = getstr(tok->next, 2 + varc);
if (strtol(num, NULL, 10) >= size)
@ -235,8 +93,8 @@ static void CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname
strcmp(tok->str,"strncpy")==0 ||
strcmp(tok->str,"fgets")==0 )
{
if ( Match1( tok->next, "( %var1% , %num% , %num% )", varname ) ||
Match1( tok->next, "( %var% , %var1% , %num% )", varname ) )
if ( Match( tok->next, "( %var1% , %num% , %num% )", varname ) ||
Match( tok->next, "( %var% , %var1% , %num% )", varname ) )
{
const char *num = getstr(tok, varc + 6);
if ( atoi(num) > total_size )
@ -249,22 +107,22 @@ static void CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname
// Loop..
if ( match(tok, "for (") )
if ( Match(tok, "for (") )
{
const TOKEN *tok2 = gettok( tok, 2 );
// for - setup..
if ( match(tok2, "var = 0 ;") )
if ( Match(tok2, "%var% = 0 ;") )
tok2 = gettok(tok2, 4);
else if ( match(tok2, "type var = 0 ;") )
else if ( Match(tok2, "%type% %var% = 0 ;") )
tok2 = gettok(tok2, 5);
else if ( match(tok2, "type type var = 0 ;") )
else if ( Match(tok2, "%type% %type% %var% = 0 ;") )
tok2 = gettok(tok2, 6);
else
continue;
// for - condition..
if ( ! match(tok2, "var < num ;") && ! match(tok2, "var <= num ;"))
if ( ! Match(tok2, "%var% < %num% ;") && ! Match(tok2, "%var% <= %num% ;"))
continue;
// Get index variable and stopsize.
@ -298,7 +156,7 @@ static void CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname
break;
}
if ( Match1( tok2, pattern.str().c_str(), varname ) )
if ( Match( tok2, pattern.str().c_str(), varname ) )
{
ReportError(tok2, "Buffer overrun");
break;
@ -311,7 +169,7 @@ static void CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname
// Writing data into array..
if ( Match1(tok, "strcpy ( %var1% , %str% )", varname) )
if ( Match(tok, "strcpy ( %var1% , %str% )", varname) )
{
int len = 0;
const char *str = getstr(tok, varc + 4 );
@ -332,7 +190,7 @@ static void CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname
// Function call..
// Todo: Handle struct member variables..
if ( match( tok, "var (" ) )
if ( Match( tok, "%var% (" ) )
{
// Don't make recursive checking..
if (std::find(CallStack.begin(), CallStack.end(), tok) != CallStack.end())
@ -363,7 +221,7 @@ static void CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname
if ( parlevel == 1 &&
strchr( "(,", *getstr(tok2,0) ) &&
Match1( tok2->next, "%var1%", varname ) &&
Match( tok2->next, "%var1%", varname ) &&
strchr( ",)", *getstr(tok2, 2+varc) ) )
{
par++;
@ -393,7 +251,7 @@ static void CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname
else if ( ftok->str[0] == ',' )
par--;
else if (par==1 && parlevel==1 && (match(ftok, "var ,") || match(ftok, "var )")))
else if (par==1 && parlevel==1 && (Match(ftok, "%var% ,") || Match(ftok, "%var% )")))
{
// Parameter name..
const char *parname[2];
@ -436,7 +294,7 @@ static void CheckBufferOverrun_LocalVariable()
else if (tok->str[0]=='}')
indentlevel--;
else if (indentlevel > 0 && match(tok, "type var [ num ] ;"))
else if (indentlevel > 0 && Match(tok, "%type% %var% [ %num% ] ;"))
{
const char *varname[2];
varname[0] = getstr(tok,1);
@ -483,8 +341,8 @@ static void CheckBufferOverrun_StructVariable()
if ( strchr( ";{,(", tok2->str[0] ) )
{
// Declare array..
if ( match(tok2->next, "type var [ num ] ;") ||
match(tok2->next, "type * var [ num ] ;") )
if ( Match(tok2->next, "%type% %var% [ %num% ] ;") ||
Match(tok2->next, "%type% * %var% [ %num% ] ;") )
{
const char *varname[3] = {0,0,0};
int ivar = IsName(getstr(tok2, 2)) ? 2 : 3;
@ -501,11 +359,11 @@ static void CheckBufferOverrun_StructVariable()
continue;
// Declare variable: Fred fred1;
if ( match( tok3->next, "var ;" ) )
if ( Match( tok3->next, "%var% ;" ) )
varname[0] = getstr(tok3, 1);
// Declare pointer: Fred *fred1
else if ( match(tok3->next, "* var") && tok3->next->next->next && strchr(",);=", tok3->next->next->next->str[0]) )
else if ( Match(tok3->next, "* %var%") && tok3->next->next->next && strchr(",);=", tok3->next->next->next->str[0]) )
varname[0] = getstr(tok3, 2);
else
@ -524,11 +382,11 @@ static void CheckBufferOverrun_StructVariable()
}
// End of function declaration..
if ( match(tok3, ") ;") )
if ( Match(tok3, ") ;") )
break;
// Function implementation..
if ( match(tok3, ") {") )
if ( Match(tok3, ") {") )
{
CheckTok = gettok(tok3, 2);
break;
@ -552,7 +410,6 @@ static void CheckBufferOverrun_StructVariable()
void CheckBufferOverrun()
{
FillFunctionList();
CheckBufferOverrun_LocalVariable();
CheckBufferOverrun_StructVariable();
}
@ -573,14 +430,14 @@ void WarningDangerousFunctions()
{
for (const TOKEN *tok = tokens; tok; tok = tok->next)
{
if (match(tok, "gets ("))
if (Match(tok, "gets ("))
{
std::ostringstream ostr;
ostr << FileLine(tok) << ": Found 'gets'. You should use 'fgets' instead";
ReportErr(ostr.str());
}
else if (match(tok, "scanf (") && strcmp(getstr(tok,2),"\"%s\"") == 0)
else if (Match(tok, "scanf (") && strcmp(getstr(tok,2),"\"%s\"") == 0)
{
std::ostringstream ostr;
ostr << FileLine(tok) << ": Found 'scanf'. You should use 'fgets' instead";

View File

@ -55,7 +55,7 @@ static struct VAR *ClassChecking_GetVarList(const char classname[])
const char *varname = 0;
// Is it a variable declaration?
if ( match(next,"var var ;") )
if ( Match(next,"%type% %var% ;") )
{
const char *types[] = {"bool", "char", "int", "short", "long", "float", "double", 0};
for ( int type = 0; types[type]; type++ )
@ -69,7 +69,7 @@ static struct VAR *ClassChecking_GetVarList(const char classname[])
}
// Pointer?
else if ( match(next, "var * var ;") )
else if ( Match(next, "%type% * %var% ;") )
{
varname = getstr(next, 2);
}
@ -103,7 +103,7 @@ static const TOKEN * FindClassFunction( const TOKEN *_tokens, const char classna
else if ( indentlevel == 1 )
{
// Member function is implemented in the class declaration..
if ( match( _tokens, "var (" ) && strcmp(_tokens->str,funcname) == 0 )
if ( Match( _tokens, "%var% (" ) && strcmp(_tokens->str,funcname) == 0 )
{
const TOKEN *tok2 = _tokens;
while ( tok2 && tok2->str[0] != '{' && tok2->str[0] != ';' )
@ -114,13 +114,15 @@ static const TOKEN * FindClassFunction( const TOKEN *_tokens, const char classna
}
}
else if ( match(_tokens, "class var {") && strcmp(getstr(_tokens,1),classname)==0 )
// Todo: Match the classname directly instead
else if ( Match(_tokens, "class %var% {") && strcmp(getstr(_tokens,1),classname)==0 )
{
indentlevel = 1;
_tokens = gettok( _tokens, 2 );
}
else if ( match(_tokens, "var :: var (") &&
// Todo: Match the classname and funcname directly instead
else if ( Match(_tokens, "%var% :: %var% (") &&
strcmp(_tokens->str,classname) == 0 &&
strcmp(getstr(_tokens,2),funcname) == 0 )
{
@ -161,7 +163,7 @@ static void ClassChecking_VarList_Initialize(const TOKEN *ftok, struct VAR *varl
// clKalle::clKalle() : var(value) { }
if (indentlevel==0)
{
if (Assign && match(ftok, "var ("))
if (Assign && Match(ftok, "%var% ("))
{
InitVar( varlist, ftok->str );
}
@ -188,14 +190,14 @@ static void ClassChecking_VarList_Initialize(const TOKEN *ftok, struct VAR *varl
ftok = ftok->next;
// Clearing all variables..
if (match(ftok,"memset ( this ,"))
if (Match(ftok,"memset ( this ,"))
{
for (struct VAR *var = varlist; var; var = var->next)
var->init = true;
}
// Calling member function?
else if (match(ftok, "var ("))
else if (Match(ftok, "%var% ("))
{
unsigned int i = 0;
const TOKEN *ftok2 = FindClassFunction( tokens, classname, ftok->str, i );
@ -203,13 +205,13 @@ static void ClassChecking_VarList_Initialize(const TOKEN *ftok, struct VAR *varl
}
// Assignment of member variable?
else if (match(ftok, "var ="))
else if (Match(ftok, "%var% ="))
{
InitVar( varlist, ftok->str );
}
// The functions 'clear' and 'Clear' are supposed to initialize variable.
if (match(ftok,"var . clear (") || match(ftok,"var . Clear ("))
if (Match(ftok,"%var% . clear (") || Match(ftok,"%var% . Clear ("))
{
InitVar( varlist, ftok->str );
}
@ -347,7 +349,7 @@ void CheckUnusedPrivateFunctions()
unsigned int indent_level = 0;
for (const TOKEN *tok = tok1; tok; tok = tok->next)
{
if (match(tok,"friend class"))
if (Match(tok,"friend %var%"))
{
// Todo: Handle friend classes
FuncList.clear();
@ -464,13 +466,13 @@ void CheckMemset()
continue;
const char *type = NULL;
if (match(tok, "memset ( var , num , sizeof ( type ) )"))
if (Match(tok, "memset ( %var% , %num% , sizeof ( %type% ) )"))
type = getstr(tok, 8);
else if (match(tok, "memset ( & var , num , sizeof ( type ) )"))
else if (Match(tok, "memset ( & %var% , %num% , sizeof ( %type% ) )"))
type = getstr(tok, 9);
else if (match(tok, "memset ( var , num , sizeof ( struct type ) )"))
else if (Match(tok, "memset ( %var% , %num% , sizeof ( struct %type% ) )"))
type = getstr(tok, 9);
else if (match(tok, "memset ( & var , num , sizeof ( struct type ) )"))
else if (Match(tok, "memset ( & %var% , %num% , sizeof ( struct %type% ) )"))
type = getstr(tok, 10);
// No type defined => The tokens didn't match
@ -496,7 +498,7 @@ void CheckMemset()
if (tstruct->str[0] == '}')
break;
if (match(tstruct, "std :: type var ;"))
if (Match(tstruct, "std :: %type% %var% ;"))
{
std::ostringstream ostr;
ostr << FileLine(tok) << ": Using 'memset' on struct that contains a 'std::" << getstr(tstruct,2) << "'";

View File

@ -23,7 +23,7 @@ void WarningHeaderWithImplementation()
if (tok->FileIndex == 0)
continue;
if (match(tok, ") {"))
if (Match(tok, ") {"))
{
std::ostringstream ostr;
ostr << FileLine(tok) << ": Found implementation in header";
@ -102,21 +102,21 @@ void WarningIncludeHeader()
// Class or namespace declaration..
// --------------------------------------
if (match(tok1,"class var {") || match(tok1,"class var :") || match(tok1,"namespace var {"))
if (Match(tok1,"class %var% {") || Match(tok1,"class %var% :") || Match(tok1,"namespace %var% {"))
classlist.push_back(getstr(tok1, 1));
// Variable declaration..
// --------------------------------------
else if (match(tok1, "type var ;") || match(tok1, "type var ["))
else if (Match(tok1, "%type% %var% ;") || Match(tok1, "%type% %var% ["))
namelist.push_back(getstr(tok1, 1));
else if (match(tok1, "type * var ;") || match(tok1, "type * var ["))
else if (Match(tok1, "%type% * %var% ;") || Match(tok1, "%type% * %var% ["))
namelist.push_back(getstr(tok1, 2));
else if (match(tok1, "const type var =") || match(tok1, "const type var ["))
else if (Match(tok1, "const %type% %var% =") || Match(tok1, "const %type% %var% ["))
namelist.push_back(getstr(tok1, 2));
else if (match(tok1, "const type * var =") || match(tok1, "const type * var ["))
else if (Match(tok1, "const %type% * %var% =") || Match(tok1, "const %type% * %var% ["))
namelist.push_back(getstr(tok1, 3));
// enum..
@ -134,16 +134,16 @@ void WarningIncludeHeader()
// function..
// --------------------------------------
else if (match(tok1,"type var ("))
else if (Match(tok1,"%type% %var% ("))
namelist.push_back(getstr(tok1, 1));
else if (match(tok1,"type * var ("))
else if (Match(tok1,"%type% * %var% ("))
namelist.push_back(getstr(tok1, 2));
else if (match(tok1,"const type var ("))
else if (Match(tok1,"const %type% %var% ("))
namelist.push_back(getstr(tok1, 2));
else if (match(tok1,"const type * var ("))
else if (Match(tok1,"const %type% * %var% ("))
namelist.push_back(getstr(tok1, 3));
// typedef..
@ -166,7 +166,7 @@ void WarningIncludeHeader()
if ( tok1->str[0] == ';' )
break;
if ( match(tok1, "var ;") )
if ( Match(tok1, "%var% ;") )
namelist.push_back(tok1->str);
}
@ -184,7 +184,7 @@ void WarningIncludeHeader()
if (tok1->FileIndex != includetok->FileIndex)
continue;
if ( match(tok1, ": var {") || match(tok1, ": type var {") )
if ( Match(tok1, ": %var% {") || Match(tok1, ": %type% %var% {") )
{
std::string classname = getstr(tok1, (strcmp(getstr(tok1,2),"{")) ? 2 : 1);
if (std::find(classlist.begin(),classlist.end(),classname)!=classlist.end())

View File

@ -364,21 +364,21 @@ static void _ClassMembers_CheckVar(const char *classname, const char *varname)
{
bool err = false;
if (match(tok, "delete var ;") &&
if (Match(tok, "delete %var% ;") &&
strcmp(getstr(tok,1),varname)==0)
{
err |= ( Alloc != No && Alloc != New );
Dealloc = New;
}
else if (match(tok, "delete [ ] var ;") &&
else if (Match(tok, "delete [ ] %var% ;") &&
strcmp(getstr(tok,3),varname)==0)
{
err |= ( Alloc != No && Alloc != NewA );
Dealloc = NewA;
}
else if (match(tok, "free ( var )") &&
else if (Match(tok, "free ( %var% )") &&
strcmp(getstr(tok,2),varname)==0)
{
err |= ( Alloc != No && Alloc != Malloc );
@ -406,8 +406,8 @@ static void _ClassMembers_CheckVar(const char *classname, const char *varname)
if ( strcmp(getstr(tok,2), "new") == 0 )
{
if ( match(tok, "var = new type ;") ||
match(tok, "var = new type (") )
if ( Match(tok, "%var% = new %type% ;") ||
Match(tok, "%var% = new %type% (") )
{
if ( ! ShowAll && ! IsStandardType(getstr(tok,3)) )
continue;
@ -415,7 +415,7 @@ static void _ClassMembers_CheckVar(const char *classname, const char *varname)
Alloc = New;
}
else if ( match(tok, "var = new type [") )
else if ( Match(tok, "%var% = new %type% [") )
{
if ( ! ShowAll && ! IsStandardType(getstr(tok,3)) )
continue;
@ -424,8 +424,8 @@ static void _ClassMembers_CheckVar(const char *classname, const char *varname)
}
}
else if ( match(tok, "var = strdup (") ||
match(tok, "var = ( type * ) malloc ("))
else if ( Match(tok, "%var% = strdup (") ||
Match(tok, "%var% = ( %type% * ) malloc ("))
{
if ( ! ShowAll &&
tok->next->next->str[0] == '(' &&
@ -461,7 +461,7 @@ static void _ClassMembers()
{
// Is this a class declaration?
// -------------------------------------
if ( ! match(ClassDecl, "class var {") )
if ( ! Match(ClassDecl, "class %var% {") )
continue;
const char *classname = getstr(ClassDecl, 1);
@ -482,7 +482,7 @@ static void _ClassMembers()
else if (indentlevel == 1)
{
if ( match(ClassVar, "type * var ;") )
if ( Match(ClassVar, "%type% * %var% ;") )
{
const char *varname = getstr(ClassVar, 2);

View File

@ -19,7 +19,7 @@ void WarningOldStylePointerCast()
for (const TOKEN *tok = tokens; tok; tok = tok->next)
{
// Old style pointer casting..
if (!match(tok, "( type * ) var"))
if (!Match(tok, "( %type% * ) %var%"))
continue;
// Is "type" a class?
@ -46,10 +46,10 @@ void WarningIsDigit()
for (const TOKEN *tok = tokens; tok; tok = tok->next)
{
bool err = false;
err |= match(tok, "var >= '0' && var <= '9'");
err |= match(tok, "* var >= '0' && * var <= '9'");
err |= match(tok, "( var >= '0' ) && ( var <= '9' )");
err |= match(tok, "( * var >= '0' ) && ( * var <= '9' )");
err |= Match(tok, "%var% >= '0' && %var% <= '9'");
err |= Match(tok, "* %var% >= '0' && * %var% <= '9'");
err |= Match(tok, "( %var% >= '0' ) && ( %var% <= '9' )");
err |= Match(tok, "( * %var% >= '0' ) && ( * %var% <= '9' )");
if (err)
{
std::ostringstream ostr;
@ -75,14 +75,14 @@ void WarningIsAlpha()
if ( tok->str[0] != '(' )
continue;
err |= match(tok, "( var >= 'A' && var <= 'Z' ) || ( var >= 'a' && var <= 'z' )");
err |= match(tok, "( var >= 'a' && var <= 'z' ) || ( var >= 'A' && var <= 'Z' )");
err |= match(tok, "( * var >= 'A' && * var <= 'Z' ) || ( * var >= 'a' && * var <= 'z' )");
err |= match(tok, "( * var >= 'a' && * var <= 'z' ) || ( * var >= 'A' && * var <= 'Z' )");
err |= match(tok, "( ( var >= 'A' ) && ( var <= 'Z' ) ) || ( ( var >= 'a' ) && ( var <= 'z' ) )");
err |= match(tok, "( ( var >= 'a' ) && ( var <= 'z' ) ) || ( ( var >= 'A' ) && ( var <= 'Z' ) )");
err |= match(tok, "( ( * var >= 'A' ) && ( * var <= 'Z' ) ) || ( ( * var >= 'a' ) && ( * var <= 'z' ) )");
err |= match(tok, "( ( * var >= 'a' ) && ( * var <= 'z' ) ) || ( ( * var >= 'A' ) && ( * var <= 'Z' ) )");
err |= Match(tok, "( %var% >= 'A' && %var% <= 'Z' ) || ( %var% >= 'a' && %var% <= 'z' )");
err |= Match(tok, "( %var% >= 'a' && %var% <= 'z' ) || ( %var% >= 'A' && %var% <= 'Z' )");
err |= Match(tok, "( * %var% >= 'A' && * %var% <= 'Z' ) || ( * %var% >= 'a' && * %var% <= 'z' )");
err |= Match(tok, "( * %var% >= 'a' && * %var% <= 'z' ) || ( * %var% >= 'A' && * %var% <= 'Z' )");
err |= Match(tok, "( ( %var% >= 'A' ) && ( %var% <= 'Z' ) ) || ( ( %var% >= 'a' ) && ( %var% <= 'z' ) )");
err |= Match(tok, "( ( %var% >= 'a' ) && ( %var% <= 'z' ) ) || ( ( %var% >= 'A' ) && ( %var% <= 'Z' ) )");
err |= Match(tok, "( ( * %var% >= 'A' ) && ( * %var% <= 'Z' ) ) || ( ( * var >= 'a' ) && ( * %var% <= 'z' ) )");
err |= Match(tok, "( ( * %var% >= 'a' ) && ( * %var% <= 'z' ) ) || ( ( * var >= 'A' ) && ( * %var% <= 'Z' ) )");
if (err)
{
std::ostringstream ostr;
@ -110,12 +110,12 @@ void WarningRedundantCode()
const char *varname1 = NULL;
const TOKEN *tok2 = NULL;
if (match(tok,"if ( var )"))
if (Match(tok,"if ( %var% )"))
{
varname1 = getstr(tok, 2);
tok2 = gettok(tok, 4);
}
else if (match(tok,"if ( var != NULL )"))
else if (Match(tok,"if ( %var% != NULL )"))
{
varname1 = getstr(tok, 2);
tok2 = gettok(tok, 6);
@ -125,17 +125,17 @@ void WarningRedundantCode()
continue;
bool err = false;
if (match(tok2,"delete var ;"))
if (Match(tok2,"delete %var% ;"))
err = (strcmp(getstr(tok2,1),varname1)==0);
else if (match(tok2,"{ delete var ; }"))
else if (Match(tok2,"{ delete %var% ; }"))
err = (strcmp(getstr(tok2,2),varname1)==0);
else if (match(tok2,"delete [ ] var ;"))
else if (Match(tok2,"delete [ ] %var% ;"))
err = (strcmp(getstr(tok2,1),varname1)==0);
else if (match(tok2,"{ delete [ ] var ; }"))
else if (Match(tok2,"{ delete [ ] %var% ; }"))
err = (strcmp(getstr(tok2,2),varname1)==0);
else if (match(tok2,"free ( var )"))
else if (Match(tok2,"free ( %var% )"))
err = (strcmp(getstr(tok2,2),varname1)==0);
else if (match(tok2,"{ free ( var ) ; }"))
else if (Match(tok2,"{ free ( %var% ) ; }"))
err = (strcmp(getstr(tok2,3),varname1)==0);
if (err)
@ -147,7 +147,7 @@ void WarningRedundantCode()
}
// TODO
// TODO: Redundant condition
// if (haystack.find(needle) != haystack.end())
// haystack.remove(needle);
@ -203,7 +203,7 @@ void WarningIf()
if ( ! tok )
break;
if (!match(tok,"var = var ; if ( var"))
if (!Match(tok,"%var% = %var% ; if ( %var%"))
continue;
if ( strcmp(getstr(tok, 9), ")") != 0 )
@ -273,7 +273,7 @@ void InvalidFunctionUsage()
param++;
if (param==3)
{
if ( match(tok2, ", num )") )
if ( Match(tok2, ", %num% )") )
{
int radix = atoi(tok2->next->str);
if (!(radix==0 || (radix>=2 && radix<=36)))
@ -320,10 +320,10 @@ static const TOKEN *GetFunction( const TOKEN *content )
if (tok->str[0] == ';')
func = NULL;
else if ( match(tok, "var :: var (") )
else if ( Match(tok, "%var% :: %var% (") )
func = tok->next->next;
else if ( match(tok, "type var (") )
else if ( Match(tok, "%type% %var% (") )
func = tok->next;
}
@ -409,7 +409,9 @@ void CheckIfAssignment()
{
for (const TOKEN *tok = tokens; tok; tok = tok->next)
{
if (match(tok,"if ( a = b )"))
if (Match(tok, "if ( %var% = %num% )") ||
Match(tok, "if ( %var% = %str% )") ||
Match(tok, "if ( %var% = %var% )") )
{
std::ostringstream ostr;
ostr << FileLine(tok) << ": Possible bug. Should it be '==' instead of '='?";
@ -596,7 +598,7 @@ void CheckVariableScope()
if ( indentlevel == 0 )
func = false;
}
if ( indentlevel == 0 && match(tok, ") {") )
if ( indentlevel == 0 && Match(tok, ") {") )
{
func = true;
}
@ -611,8 +613,8 @@ void CheckVariableScope()
continue;
// Variable declaration?
if (match(tok1, "var var ;") ||
match(tok1, "var var =") )
if (Match(tok1, "%var% %var% ;") ||
Match(tok1, "%var% %var% =") )
{
CheckVariableScope_LookupVar( tok1, getstr(tok1, 1) );
}

View File

@ -9,6 +9,7 @@
bool HasErrors;
bool OnlyReportUniqueErrors;
std::ostringstream errout;
std::list<const TOKEN *> FunctionList;
//---------------------------------------------------------------------------
std::string FileLine(const TOKEN *tok)
@ -58,10 +59,10 @@ bool IsStandardType(const char str[])
}
//---------------------------------------------------------------------------
const TOKEN *FindFunction( const TOKEN *tok, const char funcname[] )
void FillFunctionList()
{
int indentlevel = 0;
for ( ; tok; tok = tok->next )
for ( const TOKEN *tok = tokens; tok; tok = tok->next )
{
if ( tok->str[0] == '{' )
indentlevel++;
@ -69,32 +70,135 @@ const TOKEN *FindFunction( const TOKEN *tok, const char funcname[] )
else if ( tok->str[0] == '}' )
indentlevel--;
else if (indentlevel==0 && match(tok,"var ("))
else if (indentlevel==0 && Match(tok, "%var% ("))
{
// Check if this is the first token of a function implementation..
bool haspar = false;
bool foundname = false;
for ( const TOKEN *tok2 = tok; tok2; tok2 = tok2->next )
{
haspar |= bool(tok2->str[0] == '(');
if ( ! haspar && match(tok2,"var (") )
{
if ( funcname && strcmp(funcname, tok2->str) != 0 )
break;
foundname = true;
}
if ( tok2->str[0] == ';' )
{
tok = tok2;
break;
}
if ( tok2->str[0] == '{' )
else if ( tok2->str[0] == '{' )
{
break;
if ( foundname && haspar && match(tok2, ") {") )
return tok;
}
else if ( tok2->str[0] == ')' )
{
if ( Match(tok2, ") {") )
{
FunctionList.push_back( tok );
tok = tok2;
}
else
{
tok = tok2;
while (tok->next && !strchr(";{", tok->next->str[0]))
tok = tok->next;
}
break;
}
}
}
}
}
//---------------------------------------------------------------------------
const TOKEN *GetFunctionTokenByName( const char funcname[] )
{
std::list<const TOKEN *>::const_iterator it;
for ( it = FunctionList.begin(); it != FunctionList.end(); it++ )
{
if ( strcmp( (*it)->str, funcname ) == 0 )
{
return *it;
}
}
return NULL;
}
//---------------------------------------------------------------------------
bool Match(const TOKEN *tok, const char pattern[], const char *varname[])
{
if (!tok)
return false;
const char *p = pattern;
while (*p)
{
// Skip spaces in pattern..
while ( *p == ' ' )
p++;
// Extract token from pattern..
char str[50];
char *s = str;
while (*p && *p!=' ')
{
*s = *p;
s++;
p++;
}
*s = 0;
// No token => Success!
if (str[0] == 0)
return true;
// Any symbolname..
if (strcmp(str,"%var%")==0 || strcmp(str,"%type%")==0)
{
if (!IsName(tok->str))
return false;
}
// Variable name..
else if (strcmp(str,"%var1%")==0)
{
if (strcmp(tok->str, varname[0]) != 0)
return false;
for ( int i = 1; varname[i]; i++ )
{
if ( ! gettok(tok, 2) )
return false;
if ( strcmp(getstr(tok, 1), ".") )
return false;
if ( strcmp(getstr(tok, 2), varname[i]) )
return false;
tok = gettok(tok, 2);
}
}
else if (strcmp(str,"%num%")==0)
{
if ( ! IsNumber(tok->str) )
return false;
}
else if (strcmp(str,"%str%")==0)
{
if ( tok->str[0] != '\"' )
return false;
}
else if (strcmp(str, tok->str) != 0)
return false;
tok = tok->next;
if (!tok)
return false;
}
// The end of the pattern has been reached and nothing wrong has been found
return true;
}
//---------------------------------------------------------------------------

View File

@ -3,13 +3,16 @@
#define CommonCheckH
//---------------------------------------------------------------------------
#include <list>
#include <string>
#include <sstream>
struct TOKEN;
extern std::list<const TOKEN *> FunctionList;
std::string FileLine(const TOKEN *tok);
extern bool OnlyReportUniqueErrors;
void ReportErr(const std::string &errmsg);
@ -21,7 +24,12 @@ bool IsNumber(const char str[]);
bool IsStandardType(const char str[]);
const TOKEN *FindFunction( const TOKEN *tok, const char funcname[] );
void FillFunctionList();
const TOKEN *GetFunctionTokenByName( const char funcname[] );
bool Match(const TOKEN *tok, const char pattern[], const char *varname[]=0);
//---------------------------------------------------------------------------
#endif

View File

@ -213,32 +213,32 @@ void CreateStatementList()
TOKEN *rs = eq->next;
bool ismalloc = false;
if (match(rs, "strdup ("))
if (Match(rs, "strdup ("))
{
ismalloc = true;
}
else if (rs->str[0]=='(' && IsName(getstr(rs,1)))
{
ismalloc |= match(rs, "( type * ) malloc (");
ismalloc |= match(rs, "( type * * ) malloc (");
ismalloc |= match(rs, "( type type * ) malloc (");
ismalloc |= match(rs, "( type type * * ) malloc (");
ismalloc |= match(rs, "( type * ) kmalloc (");
ismalloc |= match(rs, "( type * * ) kmalloc (");
ismalloc |= match(rs, "( type type * ) kmalloc (");
ismalloc |= match(rs, "( type type * * ) kmalloc (");
ismalloc |= Match(rs, "( %type% * ) malloc (");
ismalloc |= Match(rs, "( %type% * * ) malloc (");
ismalloc |= Match(rs, "( %type% %type% * ) malloc (");
ismalloc |= Match(rs, "( %type% %type% * * ) malloc (");
ismalloc |= Match(rs, "( %type% * ) kmalloc (");
ismalloc |= Match(rs, "( %type% * * ) kmalloc (");
ismalloc |= Match(rs, "( %type% %type% * ) kmalloc (");
ismalloc |= Match(rs, "( %type% %type% * * ) kmalloc (");
}
if ( ismalloc )
AppendStatement(STATEMENT::MALLOC, tok2, varname);
else if ( match(rs,"new type ;") )
else if ( Match(rs,"new %type% ;") )
AppendStatement(STATEMENT::NEW, tok2, varname);
else if ( match(rs, "new type (") )
else if ( Match(rs, "new %type% (") )
AppendStatement(STATEMENT::NEW, tok2, varname);
else if ( match(rs, "new type [") )
else if ( Match(rs, "new %type% [") )
AppendStatement(STATEMENT::NEWARRAY, tok2, varname);
else
@ -254,16 +254,16 @@ void CreateStatementList()
if (strchr("{};", tok2->str[0]))
break;
if (match(tok2, "free ( var ) ;"))
if (Match(tok2, "free ( %var% ) ;"))
AppendStatement(STATEMENT::FREE, tok2, getstr(tok2, 2));
if (match(tok2, "kfree ( var ) ;"))
if (Match(tok2, "kfree ( %var% ) ;"))
AppendStatement(STATEMENT::FREE, tok2, getstr(tok2, 2));
if (match(tok2, "delete var ;"))
if (Match(tok2, "delete %var% ;"))
AppendStatement(STATEMENT::DELETE, tok2, getstr(tok2,1));
if (match(tok2, "delete [ ] var ;"))
if (Match(tok2, "delete [ ] %var% ;"))
AppendStatement(STATEMENT::DELETEARRAY, tok2, getstr(tok2,3));
}
@ -275,7 +275,7 @@ void CreateStatementList()
if (parlevel==0 && strchr("{};", tok2->str[0]))
break;
if (match(tok2,"free ( var )"))
if (Match(tok2,"free ( %var% )"))
break;
if (tok2->str[0] == '(')

View File

@ -178,6 +178,7 @@ static void CppCheck(const char FileName[])
Files.clear();
Tokenize(FileName);
FunctionList.clear();
// Check that the memsets are valid.
// The 'memset' function can do dangerous things if used wrong.

View File

@ -86,6 +86,9 @@ static void check(void (chk)(),
if ( chk != CheckUnsignedDivision )
SimplifyTokenList();
FunctionList.clear();
FillFunctionList();
// Check for buffer overruns..
errout.str("");
chk();

View File

@ -576,7 +576,7 @@ void SimplifyTokenList()
// Replace constants..
for (TOKEN *tok = tokens; tok; tok = tok->next)
{
if (match(tok,"const type var = num ;"))
if (Match(tok,"const %type% %var% = %num% ;"))
{
const char *sym = getstr(tok,2);
const char *num = getstr(tok,4);
@ -705,12 +705,12 @@ void SimplifyTokenList()
TypeSize["double"] = sizeof(double);
for (TOKEN *tok = tokens; tok; tok = tok->next)
{
if (match(tok,"class type"))
if (Match(tok,"class %var%"))
{
TypeSize[getstr(tok,1)] = 11;
}
else if (match(tok, "struct type"))
else if (Match(tok, "struct %var%"))
{
TypeSize[getstr(tok,1)] = 13;
}
@ -723,7 +723,7 @@ void SimplifyTokenList()
if (strcmp(tok->str,"sizeof") != 0)
continue;
if (match(tok, "sizeof ( type * )"))
if (Match(tok, "sizeof ( %type% * )"))
{
free(tok->str);
char str[10];
@ -737,7 +737,7 @@ void SimplifyTokenList()
}
}
else if (match(tok, "sizeof ( type )"))
else if (Match(tok, "sizeof ( %type% )"))
{
const char *type = getstr(tok, 2);
int size = SizeOfType(type);
@ -759,7 +759,7 @@ void SimplifyTokenList()
for (TOKEN *tok = tokens; tok; tok = tok->next)
{
// type array [ num ] ;
if ( ! match(tok, "type var [ num ] ;") )
if ( ! Match(tok, "%type% %var% [ %num% ] ;") )
continue;
int size = SizeOfType(tok->str);
@ -785,7 +785,8 @@ void SimplifyTokenList()
break;
}
else if (match(tok2, "sizeof ( var )"))
// Todo: Match varname directly
else if (Match(tok2, "sizeof ( %var% )"))
{
if (strcmp(getstr(tok2,2), varname) == 0)
{
@ -815,7 +816,7 @@ void SimplifyTokenList()
for (TOKEN *tok = tokens; tok; tok = tok->next)
{
if (match(tok->next, "* 1") || match(tok->next, "1 *"))
if (Match(tok->next, "* 1") || Match(tok->next, "1 *"))
{
for (int i = 0; i < 2; i++)
DeleteNextToken(tok);
@ -869,7 +870,7 @@ void SimplifyTokenList()
if ( ! next )
break;
if (match(next, "* ( var + num )"))
if (Match(next, "* ( %var% + %num% )"))
{
const char *str[4] = {"var","[","num","]"};
str[0] = getstr(tok,3);
@ -904,56 +905,56 @@ void SimplifyTokenList()
TOKEN *tok2 = NULL;
unsigned int typelen = 0;
if ( match(type0, "type var ,") )
if ( Match(type0, "%type% %var% ,") )
{
tok2 = _gettok(type0, 2); // The ',' token
typelen = 1;
}
else if ( match(type0, "type * var ,") )
else if ( Match(type0, "%type% * %var% ,") )
{
tok2 = _gettok(type0, 3); // The ',' token
typelen = 1;
}
else if ( match(type0, "type var [ num ] ,") )
else if ( Match(type0, "%type% %var% [ %num% ] ,") )
{
tok2 = _gettok(type0, 5); // The ',' token
typelen = 1;
}
else if ( match(type0, "type * var [ num ] ,") )
else if ( Match(type0, "%type% * %var% [ %num% ] ,") )
{
tok2 = _gettok(type0, 6); // The ',' token
typelen = 1;
}
else if ( match(type0, "struct type var ,") )
else if ( Match(type0, "struct %type% %var% ,") )
{
tok2 = _gettok(type0, 3);
typelen = 2;
}
else if ( match(type0, "struct type * var ,") )
else if ( Match(type0, "struct %type% * %var% ,") )
{
tok2 = _gettok(type0, 4);
typelen = 2;
}
else if ( match(type0, "type var =") )
else if ( Match(type0, "%type% %var% =") )
{
tok2 = _gettok(type0, 2);
typelen = 1;
}
else if ( match(type0, "type * var =") )
else if ( Match(type0, "%type% * %var% =") )
{
tok2 = _gettok(type0, 3);
typelen = 1;
}
else if ( match(type0, "struct type * var =") )
else if ( Match(type0, "struct %type% * %var% =") )
{
tok2 = _gettok(type0, 4);
typelen = 2;
@ -1051,49 +1052,6 @@ const TOKEN *findtoken(const TOKEN *tok1, const char *tokenstr[])
}
//---------------------------------------------------------------------------
bool match(const TOKEN *tok, const char pattern[])
{
if (!tok)
return false;
const char *p = pattern;
while (*p)
{
char str[50];
char *s = str;
while (*p==' ')
p++;
while (*p && *p!=' ')
{
*s = *p;
s++;
p++;
}
*s = 0;
if (str[0] == 0)
return true;
if (strcmp(str,"var")==0 || strcmp(str,"type")==0)
{
if (!IsName(tok->str))
return false;
}
else if (strcmp(str,"num")==0)
{
if (!std::isdigit(tok->str[0]))
return false;
}
else if (strcmp(str, tok->str) != 0)
return false;
tok = tok->next;
if (!tok)
return false;
}
return true;
}
//---------------------------------------------------------------------------
const TOKEN *gettok(const TOKEN *tok, int index)
{
while (tok && index>0)

View File

@ -36,7 +36,6 @@ void DeallocateTokens();
// Helper functions for handling the tokens list..
const TOKEN *findtoken(const TOKEN *tok1, const char *tokenstr[]);
bool match(const TOKEN *tok, const char pattern[]);
const TOKEN *gettok(const TOKEN *tok, int index);
const char *getstr(const TOKEN *tok, int index);