2009-01-26 17:38:08 +01:00
|
|
|
/*
|
|
|
|
* Cppcheck - A tool for static C/C++ code analysis
|
2022-02-05 11:45:17 +01:00
|
|
|
* Copyright (C) 2007-2022 Cppcheck team.
|
2009-01-26 17:38:08 +01:00
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2009-09-27 17:08:31 +02:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2009-01-26 17:38:08 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
#ifndef tokenizeH
|
|
|
|
#define tokenizeH
|
|
|
|
//---------------------------------------------------------------------------
|
2010-08-06 17:44:26 +02:00
|
|
|
|
2017-05-27 04:33:47 +02:00
|
|
|
#include "config.h"
|
2020-05-23 07:16:49 +02:00
|
|
|
#include "errortypes.h"
|
2012-05-05 18:33:26 +02:00
|
|
|
#include "tokenlist.h"
|
2012-01-06 17:31:10 +01:00
|
|
|
|
2022-01-27 19:03:20 +01:00
|
|
|
#include <iosfwd>
|
2017-05-27 04:33:47 +02:00
|
|
|
#include <list>
|
|
|
|
#include <map>
|
|
|
|
#include <string>
|
2022-01-27 19:03:20 +01:00
|
|
|
#include <vector>
|
2009-07-13 19:11:31 +02:00
|
|
|
|
|
|
|
class Settings;
|
2010-11-23 18:41:07 +01:00
|
|
|
class SymbolDatabase;
|
2012-04-10 13:45:34 +02:00
|
|
|
class TimerResults;
|
2017-05-27 04:33:47 +02:00
|
|
|
class Token;
|
2018-09-01 11:26:10 +02:00
|
|
|
class TemplateSimplifier;
|
2020-05-23 07:16:49 +02:00
|
|
|
class ErrorLogger;
|
2020-06-30 10:59:57 +02:00
|
|
|
class Preprocessor;
|
2022-06-11 08:11:16 +02:00
|
|
|
class VariableMap;
|
2009-01-26 17:38:08 +01:00
|
|
|
|
2017-05-17 15:38:31 +02:00
|
|
|
namespace simplecpp {
|
|
|
|
class TokenList;
|
|
|
|
}
|
|
|
|
|
2009-07-17 10:49:01 +02:00
|
|
|
/// @addtogroup Core
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
/** @brief The main purpose is to tokenize the source code. It also has functions that simplify the token list */
|
2012-06-10 14:19:09 +02:00
|
|
|
class CPPCHECKLIB Tokenizer {
|
2015-06-24 20:47:04 +02:00
|
|
|
|
|
|
|
friend class TestSimplifyTokens;
|
|
|
|
friend class TestSimplifyTypedef;
|
2019-02-05 08:52:23 +01:00
|
|
|
friend class TestSimplifyUsing;
|
2015-06-24 20:47:04 +02:00
|
|
|
friend class TestTokenizer;
|
2017-03-30 10:07:58 +02:00
|
|
|
friend class SymbolDatabase;
|
2018-12-22 10:05:10 +01:00
|
|
|
friend class TestSimplifyTemplate;
|
|
|
|
friend class TemplateSimplifier;
|
2018-05-29 18:41:05 +02:00
|
|
|
|
2009-01-26 17:38:08 +01:00
|
|
|
public:
|
|
|
|
Tokenizer();
|
2009-07-13 19:11:31 +02:00
|
|
|
Tokenizer(const Settings * settings, ErrorLogger *errorLogger);
|
2012-02-24 20:45:56 +01:00
|
|
|
~Tokenizer();
|
2009-01-26 17:38:08 +01:00
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
void setTimerResults(TimerResults *tr) {
|
2018-06-16 22:14:59 +02:00
|
|
|
mTimerResults = tr;
|
2012-04-10 13:45:34 +02:00
|
|
|
}
|
|
|
|
|
2011-10-26 21:17:27 +02:00
|
|
|
/** Is the code C. Used for bailouts */
|
2014-11-20 14:20:09 +01:00
|
|
|
bool isC() const {
|
2014-06-04 18:00:22 +02:00
|
|
|
return list.isC();
|
|
|
|
}
|
2011-10-26 21:17:27 +02:00
|
|
|
|
|
|
|
/** Is the code CPP. Used for bailouts */
|
2014-11-20 14:20:09 +01:00
|
|
|
bool isCPP() const {
|
2014-06-04 18:00:22 +02:00
|
|
|
return list.isCPP();
|
|
|
|
}
|
2011-10-26 21:17:27 +02:00
|
|
|
|
2011-12-27 18:00:12 +01:00
|
|
|
/**
|
|
|
|
* Check if inner scope ends with a call to a noreturn function
|
|
|
|
* \param endScopeToken The '}' token
|
|
|
|
* \param unknown set to true if it's unknown if the scope is noreturn
|
|
|
|
* \return true if scope ends with a function call that might be 'noreturn'
|
|
|
|
*/
|
2019-11-20 15:37:09 +01:00
|
|
|
bool isScopeNoReturn(const Token *endScopeToken, bool *unknown = nullptr) const;
|
2011-12-27 18:00:12 +01:00
|
|
|
|
2017-05-17 14:57:54 +02:00
|
|
|
bool createTokens(std::istream &code, const std::string& FileName);
|
2020-05-16 18:44:17 +02:00
|
|
|
void createTokens(simplecpp::TokenList&& tokenList);
|
2015-12-11 10:22:06 +01:00
|
|
|
|
2016-07-25 12:12:11 +02:00
|
|
|
bool simplifyTokens1(const std::string &configuration);
|
2009-01-26 17:38:08 +01:00
|
|
|
/**
|
|
|
|
* Tokenize code
|
2009-06-20 22:13:19 +02:00
|
|
|
* @param code input stream for code, e.g.
|
2009-07-18 10:25:22 +02:00
|
|
|
* \code
|
2009-06-20 22:13:19 +02:00
|
|
|
* #file "p.h"
|
|
|
|
* class Foo
|
|
|
|
* {
|
|
|
|
* private:
|
|
|
|
* void Bar();
|
|
|
|
* };
|
|
|
|
*
|
|
|
|
* #endfile
|
|
|
|
* void Foo::Bar()
|
|
|
|
* {
|
|
|
|
* }
|
2009-07-18 10:25:22 +02:00
|
|
|
* \endcode
|
2009-06-20 22:13:19 +02:00
|
|
|
*
|
2009-01-26 17:38:08 +01:00
|
|
|
* @param FileName The filename
|
2010-01-23 22:18:11 +01:00
|
|
|
* @param configuration E.g. "A" for code where "#ifdef A" is true
|
2010-12-30 22:13:31 +01:00
|
|
|
* @return false if source code contains syntax errors
|
2009-01-26 17:38:08 +01:00
|
|
|
*/
|
2010-09-02 23:01:12 +02:00
|
|
|
bool tokenize(std::istream &code,
|
|
|
|
const char FileName[],
|
2016-07-25 12:12:11 +02:00
|
|
|
const std::string &configuration = emptyString);
|
2009-01-26 17:38:08 +01:00
|
|
|
|
|
|
|
/** Set variable id */
|
2012-04-22 11:36:31 +02:00
|
|
|
void setVarId();
|
2016-05-12 18:20:20 +02:00
|
|
|
void setVarIdPass1();
|
|
|
|
void setVarIdPass2();
|
2009-01-26 17:38:08 +01:00
|
|
|
|
2009-11-10 22:10:56 +01:00
|
|
|
/**
|
2021-08-07 20:51:18 +02:00
|
|
|
* Basic simplification of tokenlist
|
|
|
|
*
|
|
|
|
* @param FileName The filename to run; used to do
|
|
|
|
* markup checks.
|
|
|
|
*
|
|
|
|
* @return false if there is an error that requires aborting
|
|
|
|
* the checking of this file.
|
|
|
|
*/
|
2014-03-11 15:57:28 +01:00
|
|
|
bool simplifyTokenList1(const char FileName[]);
|
2013-12-30 17:45:28 +01:00
|
|
|
|
2019-03-02 19:52:15 +01:00
|
|
|
/**
|
|
|
|
* If --check-headers=no has been given; then remove unneeded code in headers.
|
|
|
|
* - All executable code.
|
|
|
|
* - Unused types/variables/etc
|
|
|
|
*/
|
2020-11-22 16:43:36 +01:00
|
|
|
void simplifyHeadersAndUnusedTemplates();
|
2019-03-02 19:52:15 +01:00
|
|
|
|
2020-11-28 21:55:28 +01:00
|
|
|
/**
|
|
|
|
* Remove extra "template" keywords that are not used by Cppcheck
|
|
|
|
*/
|
|
|
|
void removeExtraTemplateKeywords();
|
|
|
|
|
2020-11-29 16:07:56 +01:00
|
|
|
|
|
|
|
/** Split up template right angle brackets.
|
|
|
|
* foo < bar < >> => foo < bar < > >
|
|
|
|
*/
|
|
|
|
void splitTemplateRightAngleBrackets(bool check);
|
|
|
|
|
|
|
|
|
2009-10-07 09:54:34 +02:00
|
|
|
/**
|
|
|
|
* Calculates sizeof value for given type.
|
|
|
|
* @param type Token which will contain e.g. "int", "*", or string.
|
|
|
|
* @return sizeof for given type, or 0 if it can't be calculated.
|
|
|
|
*/
|
2022-06-19 12:01:55 +02:00
|
|
|
nonneg int sizeOfType(const Token* type) const;
|
|
|
|
nonneg int sizeOfType(const std::string& type) const;
|
2009-01-26 17:38:08 +01:00
|
|
|
|
2022-06-01 06:53:21 +02:00
|
|
|
void simplifyDebug();
|
2012-06-24 13:39:14 +02:00
|
|
|
/**
|
|
|
|
* Try to determine if function parameter is passed by value by looking
|
|
|
|
* at the function declaration.
|
|
|
|
* @param fpar token for function parameter in the function call
|
|
|
|
* @return true if the parameter is passed by value. if unsure, false is returned
|
|
|
|
*/
|
|
|
|
bool isFunctionParameterPassedByValue(const Token *fpar) const;
|
|
|
|
|
2012-09-22 18:41:33 +02:00
|
|
|
/** Simplify assignment where rhs is a block : "x=({123;});" => "{x=123;}" */
|
|
|
|
void simplifyAssignmentBlock();
|
|
|
|
|
2010-02-20 18:13:09 +01:00
|
|
|
/** Insert array size where it isn't given */
|
|
|
|
void arraySize();
|
|
|
|
|
2012-10-09 20:44:30 +02:00
|
|
|
/** Simplify labels and 'case|default' syntaxes.
|
2021-08-07 20:51:18 +02:00
|
|
|
*/
|
2014-03-27 18:41:52 +01:00
|
|
|
void simplifyLabelsCaseDefault();
|
2010-02-21 09:47:41 +01:00
|
|
|
|
2015-11-06 18:39:03 +01:00
|
|
|
/** simplify case ranges (gcc extension)
|
2021-08-07 20:51:18 +02:00
|
|
|
*/
|
2015-11-06 18:39:03 +01:00
|
|
|
void simplifyCaseRange();
|
|
|
|
|
2011-01-30 08:34:58 +01:00
|
|
|
/** Remove macros in global scope */
|
|
|
|
void removeMacrosInGlobalScope();
|
|
|
|
|
2019-11-02 19:34:19 +01:00
|
|
|
void addSemicolonAfterUnknownMacro();
|
|
|
|
|
2020-11-15 14:57:18 +01:00
|
|
|
// Remove C99 and CPP11 _Pragma(str)
|
|
|
|
void removePragma();
|
|
|
|
|
2015-01-17 07:42:49 +01:00
|
|
|
/** Remove undefined macro in class definition:
|
2021-08-07 20:51:18 +02:00
|
|
|
* class DLLEXPORT Fred { };
|
|
|
|
* class Fred FINAL : Base { };
|
|
|
|
*/
|
2015-01-17 07:42:49 +01:00
|
|
|
void removeMacroInClassDef();
|
|
|
|
|
2013-11-02 23:56:10 +01:00
|
|
|
/** Add parentheses for sizeof: sizeof x => sizeof(x) */
|
|
|
|
void sizeofAddParentheses();
|
|
|
|
|
2009-03-18 20:32:05 +01:00
|
|
|
/**
|
2010-01-30 09:33:16 +01:00
|
|
|
* Simplify variable declarations (split up)
|
2011-11-05 12:23:05 +01:00
|
|
|
* \param only_k_r_fpar Only simplify K&R function parameters
|
2009-03-18 20:32:05 +01:00
|
|
|
*/
|
2016-10-31 17:18:27 +01:00
|
|
|
void simplifyVarDecl(const bool only_k_r_fpar);
|
|
|
|
void simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, const bool only_k_r_fpar);
|
2009-03-18 20:32:05 +01:00
|
|
|
|
2010-01-30 09:33:16 +01:00
|
|
|
/**
|
|
|
|
* Simplify variable initialization
|
2012-01-27 13:56:06 +01:00
|
|
|
* '; int *p(0);' => '; int *p = 0;'
|
2010-01-30 09:33:16 +01:00
|
|
|
*/
|
|
|
|
void simplifyInitVar();
|
2022-05-11 20:01:22 +02:00
|
|
|
static Token* initVar(Token* tok);
|
2010-01-30 09:33:16 +01:00
|
|
|
|
2014-07-02 08:59:04 +02:00
|
|
|
/**
|
|
|
|
* Simplify the location of "static" and "const" qualifiers in
|
|
|
|
* a variable declaration or definition.
|
|
|
|
* Example: "int static const a;" => "static const a;"
|
|
|
|
* Example: "long long const static b;" => "static const long long b;"
|
|
|
|
*/
|
|
|
|
void simplifyStaticConst();
|
|
|
|
|
2010-05-01 10:26:15 +02:00
|
|
|
/**
|
2010-12-15 18:45:53 +01:00
|
|
|
* Simplify multiple assignments.
|
2010-05-01 10:26:15 +02:00
|
|
|
* Example: "a = b = c = 0;" => "a = 0; b = 0; c = 0;"
|
|
|
|
*/
|
|
|
|
void simplifyVariableMultipleAssign();
|
|
|
|
|
2009-05-31 10:42:27 +02:00
|
|
|
/**
|
2014-03-16 18:51:05 +01:00
|
|
|
* Simplify the 'C Alternative Tokens'
|
2009-08-29 15:29:19 +02:00
|
|
|
* Examples:
|
2014-03-16 18:51:05 +01:00
|
|
|
* "if(s and t)" => "if(s && t)"
|
|
|
|
* "while((r bitand s) and not t)" => while((r & s) && !t)"
|
|
|
|
* "a and_eq b;" => "a &= b;"
|
2009-05-31 10:42:27 +02:00
|
|
|
*/
|
2014-03-16 18:51:05 +01:00
|
|
|
bool simplifyCAlternativeTokens();
|
2009-05-31 10:42:27 +02:00
|
|
|
|
2013-02-02 16:01:34 +01:00
|
|
|
/** Add braces to an if-block, for-block, etc.
|
2013-02-05 21:13:57 +01:00
|
|
|
* @return true if no syntax errors
|
2009-02-07 21:06:00 +01:00
|
|
|
*/
|
2013-02-05 21:13:57 +01:00
|
|
|
bool simplifyAddBraces();
|
2009-01-26 17:38:08 +01:00
|
|
|
|
2013-02-02 16:01:34 +01:00
|
|
|
/** Add braces to an if-block, for-block, etc.
|
|
|
|
* for command starting at token including else-block
|
2013-02-05 21:13:57 +01:00
|
|
|
* @return last token of command
|
|
|
|
* or input token in case of an error where no braces are added
|
|
|
|
* or NULL when syntaxError is called
|
2013-02-02 16:01:34 +01:00
|
|
|
*/
|
|
|
|
Token * simplifyAddBracesToCommand(Token * tok);
|
|
|
|
|
|
|
|
/** Add pair of braces to an single if-block, else-block, for-block, etc.
|
|
|
|
* for command starting at token
|
2013-02-05 21:13:57 +01:00
|
|
|
* @return last token of command
|
|
|
|
* or input token in case of an error where no braces are added
|
|
|
|
* or NULL when syntaxError is called
|
2009-08-22 12:42:19 +02:00
|
|
|
*/
|
2013-02-02 16:01:34 +01:00
|
|
|
Token * simplifyAddBracesPair(Token *tok, bool commandWithCondition);
|
2009-08-22 12:42:19 +02:00
|
|
|
|
2020-05-29 11:16:49 +02:00
|
|
|
// Convert "using ...;" to corresponding typedef
|
|
|
|
void simplifyUsingToTypedef();
|
|
|
|
|
2009-09-30 13:35:00 +02:00
|
|
|
/**
|
|
|
|
* typedef A mytype;
|
|
|
|
* mytype c;
|
|
|
|
*
|
|
|
|
* Becomes:
|
|
|
|
* typedef A mytype;
|
|
|
|
* A c;
|
|
|
|
*/
|
|
|
|
void simplifyTypedef();
|
|
|
|
|
2019-10-08 19:30:41 +02:00
|
|
|
/**
|
|
|
|
*/
|
|
|
|
bool isMemberFunction(const Token *openParen) const;
|
|
|
|
|
2019-03-26 07:09:56 +01:00
|
|
|
/**
|
|
|
|
*/
|
|
|
|
bool simplifyUsing();
|
|
|
|
|
2015-01-31 10:50:39 +01:00
|
|
|
/** Simplify useless C++ empty namespaces, like: 'namespace %name% { }'*/
|
2012-08-28 22:32:12 +02:00
|
|
|
void simplifyEmptyNamespaces();
|
|
|
|
|
2009-02-17 20:18:26 +01:00
|
|
|
/** Simplify "if else" */
|
2009-08-29 21:28:39 +02:00
|
|
|
void elseif();
|
2009-02-17 20:18:26 +01:00
|
|
|
|
2021-04-25 14:37:27 +02:00
|
|
|
/** Simplify C++17/C++20 if/switch/for initialization expression */
|
|
|
|
void simplifyIfSwitchForInit();
|
|
|
|
|
2010-10-27 10:34:06 +02:00
|
|
|
/**
|
|
|
|
* Reduces "; ;" to ";", except in "( ; ; )"
|
|
|
|
*/
|
|
|
|
void removeRedundantSemicolons();
|
|
|
|
|
2010-03-18 18:14:52 +01:00
|
|
|
/** Struct simplification
|
|
|
|
* "struct S { } s;" => "struct S { }; S s;"
|
|
|
|
*/
|
|
|
|
|
|
|
|
void simplifyStructDecl();
|
|
|
|
|
2009-01-26 17:38:08 +01:00
|
|
|
/**
|
2013-01-16 15:37:07 +01:00
|
|
|
* Remove redundant parentheses:
|
2009-06-12 15:04:58 +02:00
|
|
|
* - "((x))" => "(x)"
|
|
|
|
* - "(function())" => "function()"
|
2009-06-12 16:14:01 +02:00
|
|
|
* - "(delete x)" => "delete x"
|
|
|
|
* - "(delete [] x)" => "delete [] x"
|
2009-01-26 17:38:08 +01:00
|
|
|
* @return true if modifications to token-list are done.
|
|
|
|
* false if no modifications are done.
|
|
|
|
*/
|
2013-01-16 15:37:07 +01:00
|
|
|
bool simplifyRedundantParentheses();
|
2009-01-26 17:38:08 +01:00
|
|
|
|
2009-01-26 23:26:50 +01:00
|
|
|
/**
|
|
|
|
* Simplify functions like "void f(x) int x; {"
|
|
|
|
* into "void f(int x) {"
|
|
|
|
*/
|
2014-03-27 18:41:52 +01:00
|
|
|
void simplifyFunctionParameters();
|
2009-01-26 23:26:50 +01:00
|
|
|
|
2021-05-02 09:05:12 +02:00
|
|
|
/** Simplify function level try blocks:
|
|
|
|
* Convert "void f() try {} catch (int) {}"
|
|
|
|
* to "void f() { try {} catch (int) {} }"
|
|
|
|
*/
|
|
|
|
void simplifyFunctionTryCatch();
|
|
|
|
|
2009-05-03 21:23:47 +02:00
|
|
|
/**
|
|
|
|
* Simplify templates
|
|
|
|
*/
|
|
|
|
void simplifyTemplates();
|
|
|
|
|
2011-12-24 21:51:55 +01:00
|
|
|
void simplifyDoublePlusAndDoubleMinus();
|
|
|
|
|
2011-12-24 22:23:08 +01:00
|
|
|
void simplifyRedundantConsecutiveBraces();
|
|
|
|
|
|
|
|
void simplifyArrayAccessSyntax();
|
|
|
|
|
|
|
|
void simplifyParameterVoid();
|
|
|
|
|
2013-03-02 18:19:53 +01:00
|
|
|
void fillTypeSizes();
|
|
|
|
|
|
|
|
void combineOperators();
|
|
|
|
|
2016-10-08 01:57:09 +02:00
|
|
|
void combineStringAndCharLiterals();
|
2013-03-02 18:19:53 +01:00
|
|
|
|
2012-12-01 00:43:23 +01:00
|
|
|
void concatenateNegativeNumberAndAnyPositive();
|
2012-01-04 12:55:51 +01:00
|
|
|
|
2012-04-16 16:25:04 +02:00
|
|
|
void simplifyExternC();
|
|
|
|
|
2013-01-16 15:37:07 +01:00
|
|
|
void simplifyRoundCurlyParentheses();
|
2019-05-28 08:50:38 +02:00
|
|
|
|
2019-05-27 06:54:21 +02:00
|
|
|
void simplifyTypeIntrinsics();
|
2012-01-04 12:55:51 +01:00
|
|
|
|
|
|
|
void simplifySQL();
|
|
|
|
|
2015-08-19 19:03:57 +02:00
|
|
|
void checkForEnumsWithTypedef();
|
2011-12-24 22:23:08 +01:00
|
|
|
|
2014-03-27 18:41:52 +01:00
|
|
|
void findComplicatedSyntaxErrorsInTemplates();
|
2011-12-24 22:23:08 +01:00
|
|
|
|
2009-09-27 16:04:10 +02:00
|
|
|
/**
|
|
|
|
* Modify strings in the token list by replacing hex and oct
|
|
|
|
* values. E.g. "\x61" -> "a" and "\000" -> "\0"
|
|
|
|
* @param source The string to be modified, e.g. "\x61"
|
|
|
|
* @return Modified string, e.g. "a"
|
|
|
|
*/
|
2012-05-17 10:33:24 +02:00
|
|
|
static std::string simplifyString(const std::string &source);
|
2009-09-27 16:04:10 +02:00
|
|
|
|
2015-07-16 00:29:48 +02:00
|
|
|
/**
|
|
|
|
* is token pointing at function head?
|
|
|
|
* @param tok A '(' or ')' token in a possible function head
|
|
|
|
* @param endsWith string after function head
|
|
|
|
* @return token matching with endsWith if syntax seems to be a function head else nullptr
|
|
|
|
*/
|
|
|
|
const Token * isFunctionHead(const Token *tok, const std::string &endsWith) const;
|
|
|
|
|
2016-01-03 22:52:24 +01:00
|
|
|
/**
|
|
|
|
* is token pointing at function head?
|
|
|
|
* @param tok A '(' or ')' token in a possible function head
|
|
|
|
* @param endsWith string after function head
|
|
|
|
* @param cpp c++ code
|
|
|
|
* @return token matching with endsWith if syntax seems to be a function head else nullptr
|
|
|
|
*/
|
|
|
|
static const Token * isFunctionHead(const Token *tok, const std::string &endsWith, bool cpp);
|
|
|
|
|
2020-06-30 10:59:57 +02:00
|
|
|
void setPreprocessor(const Preprocessor *preprocessor) {
|
|
|
|
mPreprocessor = preprocessor;
|
|
|
|
}
|
|
|
|
const Preprocessor *getPreprocessor() const {
|
|
|
|
return mPreprocessor;
|
|
|
|
}
|
|
|
|
|
2020-06-30 18:26:24 +02:00
|
|
|
bool hasIfdef(const Token *start, const Token *end) const;
|
|
|
|
|
2017-12-25 08:19:46 +01:00
|
|
|
private:
|
|
|
|
|
2011-10-16 08:09:57 +02:00
|
|
|
/** Simplify pointer to standard type (C only) */
|
|
|
|
void simplifyPointerToStandardType();
|
|
|
|
|
2010-01-20 21:19:06 +01:00
|
|
|
/** Simplify function pointers */
|
|
|
|
void simplifyFunctionPointers();
|
|
|
|
|
2009-11-28 22:08:43 +01:00
|
|
|
/**
|
|
|
|
* Send error message to error logger about internal bug.
|
2010-01-17 16:38:28 +01:00
|
|
|
* @param tok the token that this bug concerns.
|
2009-11-28 22:08:43 +01:00
|
|
|
*/
|
2021-04-25 12:52:09 +02:00
|
|
|
NORETURN void cppcheckError(const Token *tok) const;
|
2009-11-28 22:08:43 +01:00
|
|
|
|
2009-03-15 00:39:45 +01:00
|
|
|
/**
|
|
|
|
* Setup links for tokens so that one can call Token::link().
|
|
|
|
*/
|
2014-03-27 18:41:52 +01:00
|
|
|
void createLinks();
|
2009-03-15 00:39:45 +01:00
|
|
|
|
2012-03-20 19:00:16 +01:00
|
|
|
/**
|
|
|
|
* Setup links between < and >.
|
|
|
|
*/
|
|
|
|
void createLinks2();
|
|
|
|
|
2015-06-24 20:47:04 +02:00
|
|
|
public:
|
|
|
|
|
2010-07-22 19:57:48 +02:00
|
|
|
/** Syntax error */
|
2022-07-10 10:57:29 +02:00
|
|
|
NORETURN void syntaxError(const Token *tok, const std::string &code = emptyString) const;
|
2010-07-22 19:57:48 +02:00
|
|
|
|
2019-01-05 11:56:21 +01:00
|
|
|
/** Syntax error. Unmatched character. */
|
2020-06-29 22:54:51 +02:00
|
|
|
NORETURN void unmatchedToken(const Token *tok) const;
|
2009-05-07 22:17:29 +02:00
|
|
|
|
2017-04-06 08:50:35 +02:00
|
|
|
/** Syntax error. C++ code in C file. */
|
2020-06-29 22:54:51 +02:00
|
|
|
NORETURN void syntaxErrorC(const Token *tok, const std::string &what) const;
|
2017-04-06 08:50:35 +02:00
|
|
|
|
2018-11-13 16:49:02 +01:00
|
|
|
/** Warn about unknown macro(s), configuration is recommended */
|
2020-06-29 22:54:51 +02:00
|
|
|
NORETURN void unknownMacroError(const Token *tok1) const;
|
2018-11-13 16:49:02 +01:00
|
|
|
|
2021-05-08 11:20:29 +02:00
|
|
|
void unhandledCharLiteral(const Token *tok, const std::string& msg) const;
|
|
|
|
|
2015-06-24 20:47:04 +02:00
|
|
|
private:
|
|
|
|
|
2013-03-18 19:09:04 +01:00
|
|
|
/** Report that there is an unhandled "class x y {" code */
|
2013-06-01 14:35:21 +02:00
|
|
|
void unhandled_macro_class_x_y(const Token *tok) const;
|
2013-03-18 19:09:04 +01:00
|
|
|
|
2017-04-07 19:19:10 +02:00
|
|
|
/** Check configuration (unknown macros etc) */
|
|
|
|
void checkConfiguration() const;
|
|
|
|
void macroWithSemicolonError(const Token *tok, const std::string ¯oName) const;
|
|
|
|
|
2017-04-06 08:50:35 +02:00
|
|
|
/**
|
|
|
|
* Is there C++ code in C file?
|
|
|
|
*/
|
|
|
|
void validateC() const;
|
|
|
|
|
2009-09-13 15:35:37 +02:00
|
|
|
/**
|
|
|
|
* assert that tokens are ok - used during debugging for example
|
2014-09-01 08:47:46 +02:00
|
|
|
* to catch problems in simplifyTokenList1/2.
|
2009-09-13 15:35:37 +02:00
|
|
|
*/
|
2014-03-27 18:41:52 +01:00
|
|
|
void validate() const;
|
2009-09-13 15:35:37 +02:00
|
|
|
|
2020-02-19 21:11:54 +01:00
|
|
|
/** Detect unknown macros and throw unknownMacro */
|
2021-01-09 20:32:38 +01:00
|
|
|
void reportUnknownMacros() const;
|
2020-02-19 21:11:54 +01:00
|
|
|
|
2018-02-05 21:47:33 +01:00
|
|
|
/** Detect garbage code and call syntaxError() if found. */
|
|
|
|
void findGarbageCode() const;
|
2016-07-26 08:16:10 +02:00
|
|
|
|
|
|
|
/** Detect garbage expression */
|
2019-04-12 09:10:25 +02:00
|
|
|
static bool isGarbageExpr(const Token *start, const Token *end, bool allowSemicolon);
|
2016-07-22 16:54:24 +02:00
|
|
|
|
2010-04-24 09:40:05 +02:00
|
|
|
/**
|
|
|
|
* Remove __declspec()
|
|
|
|
*/
|
|
|
|
void simplifyDeclspec();
|
|
|
|
|
2010-04-21 21:08:47 +02:00
|
|
|
/**
|
|
|
|
* Remove calling convention
|
|
|
|
*/
|
|
|
|
void simplifyCallingConvention();
|
|
|
|
|
2010-05-27 18:15:42 +02:00
|
|
|
/**
|
2018-12-30 19:31:50 +01:00
|
|
|
* Remove \__attribute\__ ((?))
|
2010-05-27 18:15:42 +02:00
|
|
|
*/
|
|
|
|
void simplifyAttribute();
|
|
|
|
|
2019-07-12 11:09:24 +02:00
|
|
|
/**
|
|
|
|
* Remove \__cppcheck\__ ((?))
|
|
|
|
*/
|
|
|
|
void simplifyCppcheckAttribute();
|
|
|
|
|
2021-04-15 20:26:53 +02:00
|
|
|
/** Remove alignas */
|
|
|
|
void removeAlignas();
|
|
|
|
|
2021-04-22 19:15:22 +02:00
|
|
|
/** Simplify c++20 spaceship operator */
|
|
|
|
void simplifySpaceshipOperator();
|
|
|
|
|
2010-06-30 08:10:39 +02:00
|
|
|
/**
|
|
|
|
* Remove keywords "volatile", "inline", "register", and "restrict"
|
|
|
|
*/
|
|
|
|
void simplifyKeyword();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove __asm
|
|
|
|
*/
|
|
|
|
void simplifyAsm();
|
|
|
|
|
2015-06-17 09:09:23 +02:00
|
|
|
/**
|
2015-06-16 20:53:11 +02:00
|
|
|
* asm heuristics, Put ^{} statements in asm()
|
|
|
|
*/
|
|
|
|
void simplifyAsm2();
|
|
|
|
|
2018-12-04 16:52:41 +01:00
|
|
|
/**
|
2018-12-30 19:31:50 +01:00
|
|
|
* Simplify \@… (compiler extension)
|
2018-12-04 16:52:41 +01:00
|
|
|
*/
|
|
|
|
void simplifyAt();
|
|
|
|
|
2010-08-15 11:54:28 +02:00
|
|
|
/**
|
|
|
|
* Simplify bitfields - the field width is removed as we don't use it.
|
|
|
|
*/
|
|
|
|
void simplifyBitfields();
|
|
|
|
|
2011-02-02 07:40:08 +01:00
|
|
|
/**
|
|
|
|
* Remove unnecessary member qualification
|
|
|
|
*/
|
|
|
|
void removeUnnecessaryQualification();
|
|
|
|
|
2012-07-15 11:05:19 +02:00
|
|
|
/**
|
|
|
|
* Add std:: in front of std classes, when using namespace std; was given
|
|
|
|
*/
|
|
|
|
void simplifyNamespaceStd();
|
|
|
|
|
2010-09-01 18:10:12 +02:00
|
|
|
/**
|
2021-08-07 20:51:18 +02:00
|
|
|
* Convert Microsoft memory functions
|
|
|
|
* CopyMemory(dst, src, len) -> memcpy(dst, src, len)
|
|
|
|
* FillMemory(dst, len, val) -> memset(dst, val, len)
|
|
|
|
* MoveMemory(dst, src, len) -> memmove(dst, src, len)
|
|
|
|
* ZeroMemory(dst, len) -> memset(dst, 0, len)
|
|
|
|
*/
|
2011-09-23 01:59:56 +02:00
|
|
|
void simplifyMicrosoftMemoryFunctions();
|
|
|
|
|
2011-09-24 20:51:03 +02:00
|
|
|
/**
|
2021-08-07 20:51:18 +02:00
|
|
|
* Convert Microsoft string functions
|
|
|
|
* _tcscpy -> strcpy
|
|
|
|
*/
|
2011-09-24 20:51:03 +02:00
|
|
|
void simplifyMicrosoftStringFunctions();
|
|
|
|
|
2011-09-23 01:59:56 +02:00
|
|
|
/**
|
2021-08-07 20:51:18 +02:00
|
|
|
* Remove Borland code
|
|
|
|
*/
|
2010-09-01 18:10:12 +02:00
|
|
|
void simplifyBorland();
|
|
|
|
|
2010-12-02 17:41:49 +01:00
|
|
|
/**
|
|
|
|
* Remove Qt signals and slots
|
|
|
|
*/
|
|
|
|
void simplifyQtSignalsSlots();
|
|
|
|
|
2011-01-27 18:44:20 +01:00
|
|
|
/**
|
|
|
|
* Collapse operator name tokens into single token
|
|
|
|
* operator = => operator=
|
|
|
|
*/
|
|
|
|
void simplifyOperatorName();
|
|
|
|
|
2020-09-06 21:02:06 +02:00
|
|
|
/** simplify overloaded operators: 'obj(123)' => 'obj . operator() ( 123 )' */
|
|
|
|
void simplifyOverloadedOperators();
|
|
|
|
|
2015-05-10 12:35:47 +02:00
|
|
|
/**
|
2021-08-07 20:51:18 +02:00
|
|
|
* Remove [[attribute]] (C++11 and later) from TokenList
|
|
|
|
*/
|
2018-02-16 22:25:51 +01:00
|
|
|
void simplifyCPPAttribute();
|
2015-05-10 12:35:47 +02:00
|
|
|
|
2020-05-30 11:23:22 +02:00
|
|
|
/**
|
|
|
|
* Replace strlen(str)
|
|
|
|
* @return true if any replacement took place, false else
|
|
|
|
* */
|
|
|
|
bool simplifyStrlen();
|
|
|
|
|
2018-05-08 06:35:51 +02:00
|
|
|
/**
|
|
|
|
* Convert namespace aliases
|
|
|
|
*/
|
|
|
|
void simplifyNamespaceAliases();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert C++17 style nested namespace to older style
|
|
|
|
*/
|
|
|
|
void simplifyNestedNamespace();
|
|
|
|
|
2021-04-18 19:42:22 +02:00
|
|
|
/**
|
|
|
|
* Simplify coroutines - just put parentheses around arguments for
|
|
|
|
* co_* keywords so they can be handled like function calls in data
|
|
|
|
* flow.
|
|
|
|
*/
|
|
|
|
void simplifyCoroutines();
|
|
|
|
|
2015-10-12 18:14:56 +02:00
|
|
|
/**
|
2021-08-07 20:51:18 +02:00
|
|
|
* Prepare ternary operators with parentheses so that the AST can be created
|
|
|
|
* */
|
2015-10-12 18:14:56 +02:00
|
|
|
void prepareTernaryOpForAST();
|
|
|
|
|
2012-04-22 11:28:46 +02:00
|
|
|
/**
|
|
|
|
* report error message
|
|
|
|
*/
|
|
|
|
void reportError(const Token* tok, const Severity::SeverityType severity, const std::string& id, const std::string& msg, bool inconclusive = false) const;
|
|
|
|
void reportError(const std::list<const Token*>& callstack, Severity::SeverityType severity, const std::string& id, const std::string& msg, bool inconclusive = false) const;
|
|
|
|
|
2016-02-06 20:50:44 +01:00
|
|
|
bool duplicateTypedef(Token **tokPtr, const Token *name, const Token *typeDef) const;
|
2010-12-04 15:49:25 +01:00
|
|
|
|
2010-08-26 20:44:13 +02:00
|
|
|
void unsupportedTypedef(const Token *tok) const;
|
|
|
|
|
2016-10-31 16:11:11 +01:00
|
|
|
void setVarIdClassDeclaration(const Token * const startToken,
|
2018-05-29 18:41:05 +02:00
|
|
|
const VariableMap &variableMap,
|
2019-07-14 15:48:20 +02:00
|
|
|
const nonneg int scopeStartVarId,
|
2022-06-11 08:11:16 +02:00
|
|
|
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers);
|
2015-11-05 19:00:08 +01:00
|
|
|
|
2019-04-18 20:22:39 +02:00
|
|
|
void setVarIdStructMembers(Token **tok1,
|
2022-06-11 08:11:16 +02:00
|
|
|
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
2021-01-09 20:32:38 +01:00
|
|
|
nonneg int *varId) const;
|
2019-04-18 20:22:39 +02:00
|
|
|
|
|
|
|
void setVarIdClassFunction(const std::string &classname,
|
|
|
|
Token * const startToken,
|
|
|
|
const Token * const endToken,
|
2022-06-11 08:11:16 +02:00
|
|
|
const std::map<std::string, nonneg int> &varlist,
|
|
|
|
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
2019-07-14 15:48:20 +02:00
|
|
|
nonneg int *varId_);
|
2016-01-02 19:14:03 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Output list of unknown types.
|
|
|
|
*/
|
|
|
|
void printUnknownTypes() const;
|
|
|
|
|
2017-11-03 11:31:33 +01:00
|
|
|
/** Find end of SQL (or PL/SQL) block */
|
2018-01-14 15:46:20 +01:00
|
|
|
static const Token *findSQLBlockEnd(const Token *tokSQLStart);
|
2017-11-03 11:31:33 +01:00
|
|
|
|
2019-11-15 07:03:57 +01:00
|
|
|
bool operatorEnd(const Token * tok) const;
|
|
|
|
|
2015-06-24 20:47:04 +02:00
|
|
|
public:
|
|
|
|
|
2010-09-30 21:22:49 +02:00
|
|
|
/** Was there templates in the code? */
|
2014-11-20 14:20:09 +01:00
|
|
|
bool codeWithTemplates() const {
|
2018-06-16 22:03:04 +02:00
|
|
|
return mCodeWithTemplates;
|
2010-09-30 21:22:49 +02:00
|
|
|
}
|
|
|
|
|
2015-06-24 20:47:04 +02:00
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
void setSettings(const Settings *settings) {
|
2018-06-16 16:10:28 +02:00
|
|
|
mSettings = settings;
|
2012-05-05 18:33:26 +02:00
|
|
|
list.setSettings(settings);
|
2010-12-01 18:00:55 +01:00
|
|
|
}
|
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
const SymbolDatabase *getSymbolDatabase() const {
|
2018-06-16 16:25:27 +02:00
|
|
|
return mSymbolDatabase;
|
2012-08-12 12:01:24 +02:00
|
|
|
}
|
|
|
|
void createSymbolDatabase();
|
2010-12-07 07:08:49 +01:00
|
|
|
|
2015-07-28 12:46:32 +02:00
|
|
|
/** print --debug output if debug flags match the simplification:
|
|
|
|
* 0=unknown/both simplifications
|
|
|
|
* 1=1st simplifications
|
|
|
|
* 2=2nd simplifications
|
|
|
|
*/
|
2020-05-30 11:23:22 +02:00
|
|
|
void printDebugOutput(int simplification) const;
|
2014-03-27 18:41:52 +01:00
|
|
|
|
2014-07-14 15:51:45 +02:00
|
|
|
void dump(std::ostream &out) const;
|
|
|
|
|
2011-01-16 18:13:54 +01:00
|
|
|
Token *deleteInvalidTypedef(Token *typeDef);
|
2011-01-04 07:43:40 +01:00
|
|
|
|
2011-02-26 14:42:19 +01:00
|
|
|
/**
|
|
|
|
* Get variable count.
|
|
|
|
* @return number of variables
|
|
|
|
*/
|
2019-07-14 15:48:20 +02:00
|
|
|
nonneg int varIdCount() const {
|
2018-06-16 16:38:50 +02:00
|
|
|
return mVarId;
|
2011-02-26 14:42:19 +01:00
|
|
|
}
|
|
|
|
|
2012-05-05 18:33:26 +02:00
|
|
|
/**
|
|
|
|
* Token list: stores all tokens.
|
|
|
|
*/
|
|
|
|
TokenList list;
|
2016-11-27 11:40:42 +01:00
|
|
|
// Implement tokens() as a wrapper for convenience when using the TokenList
|
2014-11-20 14:20:09 +01:00
|
|
|
const Token* tokens() const {
|
2012-05-05 18:33:26 +02:00
|
|
|
return list.front();
|
|
|
|
}
|
|
|
|
|
2013-10-01 20:30:59 +02:00
|
|
|
/**
|
2021-08-07 20:51:18 +02:00
|
|
|
* Helper function to check whether number is one (1 or 0.1E+1 or 1E+0) or not?
|
|
|
|
* @param s the string to check
|
|
|
|
* @return true in case is is one and false otherwise.
|
|
|
|
*/
|
2013-10-01 20:30:59 +02:00
|
|
|
static bool isOneNumber(const std::string &s);
|
|
|
|
|
2014-04-26 18:31:56 +02:00
|
|
|
/**
|
2021-08-07 20:51:18 +02:00
|
|
|
* Helper function to check for start of function execution scope.
|
|
|
|
* Do not use this in checks. Use the symbol database.
|
|
|
|
* @param tok pointer to end parentheses of parameter list
|
|
|
|
* @return pointer to start brace of function scope or nullptr if not start.
|
|
|
|
*/
|
2014-04-26 18:31:56 +02:00
|
|
|
static const Token * startOfExecutableScope(const Token * tok);
|
|
|
|
|
2016-02-11 16:10:52 +01:00
|
|
|
#ifdef MAXTIME
|
2017-02-27 14:00:06 +01:00
|
|
|
bool isMaxTime() const {
|
2018-06-18 09:49:00 +02:00
|
|
|
return (std::time(0) > mMaxTime);
|
2016-02-11 16:10:52 +01:00
|
|
|
#else
|
2017-02-27 14:00:06 +01:00
|
|
|
static bool isMaxTime() {
|
2016-02-11 16:10:52 +01:00
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-03-23 11:20:35 +01:00
|
|
|
const Settings *getSettings() const {
|
|
|
|
return mSettings;
|
|
|
|
}
|
|
|
|
|
2019-07-31 09:19:27 +02:00
|
|
|
void calculateScopes();
|
|
|
|
|
2018-05-28 12:44:18 +02:00
|
|
|
/** Disable copy constructor */
|
|
|
|
Tokenizer(const Tokenizer &) = delete;
|
2012-09-08 12:42:24 +02:00
|
|
|
|
2018-05-28 12:44:18 +02:00
|
|
|
/** Disable assignment operator */
|
|
|
|
Tokenizer &operator=(const Tokenizer &) = delete;
|
2012-09-08 12:42:24 +02:00
|
|
|
|
2019-09-20 21:58:09 +02:00
|
|
|
private:
|
2015-06-03 08:59:38 +02:00
|
|
|
Token *processFunc(Token *tok2, bool inOperator) const;
|
|
|
|
|
2017-03-30 10:07:58 +02:00
|
|
|
/**
|
2021-08-07 20:51:18 +02:00
|
|
|
* Get new variable id.
|
|
|
|
* @return new variable id
|
|
|
|
*/
|
2019-07-14 15:48:20 +02:00
|
|
|
nonneg int newVarId() {
|
2018-06-16 16:38:50 +02:00
|
|
|
return ++mVarId;
|
2017-03-30 10:07:58 +02:00
|
|
|
}
|
|
|
|
|
2014-06-08 13:28:15 +02:00
|
|
|
/** Set pod types */
|
|
|
|
void setPodTypes();
|
|
|
|
|
2011-01-01 11:26:48 +01:00
|
|
|
/** settings */
|
2018-06-16 16:10:28 +02:00
|
|
|
const Settings * mSettings;
|
2011-01-01 11:26:48 +01:00
|
|
|
|
|
|
|
/** errorlogger */
|
2018-06-16 16:10:28 +02:00
|
|
|
ErrorLogger* const mErrorLogger;
|
2010-01-23 22:18:11 +01:00
|
|
|
|
2011-10-24 02:52:55 +02:00
|
|
|
/** Symbol database that all checks etc can use */
|
2018-06-16 16:25:27 +02:00
|
|
|
SymbolDatabase *mSymbolDatabase;
|
2011-10-24 02:52:55 +02:00
|
|
|
|
2018-09-01 11:26:10 +02:00
|
|
|
TemplateSimplifier *mTemplateSimplifier;
|
|
|
|
|
2010-01-23 22:18:11 +01:00
|
|
|
/** E.g. "A" for code where "#ifdef A" is true. This is used to
|
|
|
|
print additional information in error situations. */
|
2018-06-16 21:57:48 +02:00
|
|
|
std::string mConfiguration;
|
2010-09-30 21:22:49 +02:00
|
|
|
|
2011-10-24 02:52:55 +02:00
|
|
|
/** sizeof information for known types */
|
2019-07-14 15:48:20 +02:00
|
|
|
std::map<std::string, int> mTypeSize;
|
2011-10-24 02:52:55 +02:00
|
|
|
|
2021-07-07 10:58:13 +02:00
|
|
|
struct TypedefInfo {
|
|
|
|
std::string name;
|
|
|
|
std::string filename;
|
|
|
|
int lineNumber;
|
2021-07-07 15:16:53 +02:00
|
|
|
int column;
|
2021-07-07 10:58:13 +02:00
|
|
|
bool used;
|
|
|
|
};
|
|
|
|
std::vector<TypedefInfo> mTypedefInfo;
|
|
|
|
|
2011-10-24 02:52:55 +02:00
|
|
|
/** variable count */
|
2019-07-14 15:48:20 +02:00
|
|
|
nonneg int mVarId;
|
2011-10-24 02:52:55 +02:00
|
|
|
|
2018-06-07 08:33:32 +02:00
|
|
|
/** unnamed count "Unnamed0", "Unnamed1", "Unnamed2", ... */
|
2019-07-14 15:48:20 +02:00
|
|
|
nonneg int mUnnamedCount;
|
2018-03-14 09:41:27 +01:00
|
|
|
|
2010-09-30 21:22:49 +02:00
|
|
|
/**
|
|
|
|
* was there any templates? templates that are "unused" are
|
|
|
|
* removed from the token list
|
|
|
|
*/
|
2018-06-16 22:03:04 +02:00
|
|
|
bool mCodeWithTemplates;
|
2012-04-10 13:45:34 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* TimerResults
|
|
|
|
*/
|
2018-06-16 22:14:59 +02:00
|
|
|
TimerResults *mTimerResults;
|
2016-02-11 16:10:52 +01:00
|
|
|
|
2013-11-02 17:31:14 +01:00
|
|
|
#ifdef MAXTIME
|
|
|
|
/** Tokenizer maxtime */
|
2018-06-18 09:49:00 +02:00
|
|
|
const std::time_t mMaxTime;
|
2013-11-02 17:31:14 +01:00
|
|
|
#endif
|
2020-06-30 10:59:57 +02:00
|
|
|
|
|
|
|
const Preprocessor *mPreprocessor;
|
2009-01-26 17:38:08 +01:00
|
|
|
};
|
|
|
|
|
2009-07-17 10:49:01 +02:00
|
|
|
/// @}
|
|
|
|
|
2009-01-26 17:38:08 +01:00
|
|
|
//---------------------------------------------------------------------------
|
2013-09-04 20:59:49 +02:00
|
|
|
#endif // tokenizeH
|