2009-01-24 20:28:30 +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-24 20:28:30 +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-24 20:28:30 +01:00
*/
# include "preprocessor.h"
2017-05-27 04:33:47 +02:00
2010-07-24 22:12:56 +02:00
# include "errorlogger.h"
2022-01-27 19:03:20 +01:00
# include "errortypes.h"
2017-05-27 04:33:47 +02:00
# include "library.h"
# include "path.h"
2010-07-26 22:05:17 +02:00
# include "settings.h"
2022-01-27 19:03:20 +01:00
# include "standards.h"
2017-05-27 04:33:47 +02:00
# include "suppressions.h"
2009-01-24 20:28:30 +01:00
# include <algorithm>
2022-01-27 19:03:20 +01:00
# include <cstddef>
2016-10-29 15:55:03 +02:00
# include <cstdint>
2022-07-07 12:16:01 +02:00
# include <functional>
2019-05-09 06:55:36 +02:00
# include <iterator> // back_inserter
2022-01-27 19:03:20 +01:00
# include <memory>
2017-05-27 04:33:47 +02:00
# include <utility>
2009-01-24 20:28:30 +01:00
2022-01-27 19:03:20 +01:00
# include <simplecpp.h>
2020-02-23 19:49:53 +01:00
static bool sameline ( const simplecpp : : Token * tok1 , const simplecpp : : Token * tok2 )
{
return tok1 & & tok2 & & tok1 - > location . sameline ( tok2 - > location ) ;
}
2015-12-07 19:54:41 +01:00
/**
* Remove heading and trailing whitespaces from the input parameter .
* If string is all spaces / tabs , return empty string .
* @ param s The string to trim .
*/
static std : : string trim ( const std : : string & s )
{
const std : : string : : size_type beg = s . find_first_not_of ( " \t " ) ;
if ( beg = = std : : string : : npos )
return " " ;
const std : : string : : size_type end = s . find_last_not_of ( " \t " ) ;
return s . substr ( beg , end - beg + 1 ) ;
}
2022-07-28 22:51:45 +02:00
Directive : : Directive ( std : : string _file , const int _linenr , const std : : string & _str ) :
file ( std : : move ( _file ) ) ,
2017-03-26 11:40:53 +02:00
linenr ( _linenr ) ,
str ( trim ( _str ) )
2021-08-07 20:51:18 +02:00
{ }
2015-12-07 19:54:41 +01:00
2019-12-19 18:37:51 +01:00
std : : atomic < bool > Preprocessor : : missingIncludeFlag ;
std : : atomic < bool > Preprocessor : : missingSystemIncludeFlag ;
2011-05-02 14:58:16 +02:00
2012-03-27 19:35:41 +02:00
char Preprocessor : : macroChar = char ( 1 ) ;
2018-06-16 16:10:28 +02:00
Preprocessor : : Preprocessor ( Settings & settings , ErrorLogger * errorLogger ) : mSettings ( settings ) , mErrorLogger ( errorLogger )
2021-08-07 20:51:18 +02:00
{ }
2009-06-26 13:19:55 +02:00
2016-07-20 12:21:00 +02:00
Preprocessor : : ~ Preprocessor ( )
{
2022-05-29 17:06:33 +02:00
for ( const std : : pair < const std : : string , simplecpp : : TokenList * > & tokenList : mTokenLists )
2020-09-21 19:30:47 +02:00
delete tokenList . second ;
2009-06-26 13:19:55 +02:00
}
2018-04-11 08:18:00 +02:00
namespace {
struct BadInlineSuppression {
2022-07-28 22:51:45 +02:00
BadInlineSuppression ( const simplecpp : : Location & l , std : : string msg ) : location ( l ) , errmsg ( std : : move ( msg ) ) { }
2018-04-11 08:18:00 +02:00
simplecpp : : Location location ;
std : : string errmsg ;
} ;
}
2009-01-24 20:28:30 +01:00
2020-02-23 19:49:53 +01:00
static bool parseInlineSuppressionCommentToken ( const simplecpp : : Token * tok , std : : list < Suppressions : : Suppression > & inlineSuppressions , std : : list < BadInlineSuppression > * bad )
2012-01-02 15:52:19 +01:00
{
2020-09-10 21:46:15 +02:00
const std : : string cppchecksuppress ( " cppcheck-suppress " ) ;
2020-02-23 19:49:53 +01:00
const std : : string & comment = tok - > str ( ) ;
2020-09-10 21:46:15 +02:00
if ( comment . size ( ) < cppchecksuppress . size ( ) )
2020-02-23 19:49:53 +01:00
return false ;
const std : : string : : size_type pos1 = comment . find_first_not_of ( " /* \t " ) ;
2020-02-23 18:29:36 +01:00
if ( pos1 = = std : : string : : npos )
2020-02-23 19:49:53 +01:00
return false ;
2020-09-10 21:46:15 +02:00
if ( pos1 + cppchecksuppress . size ( ) > = comment . size ( ) )
2020-02-23 19:49:53 +01:00
return false ;
2020-09-10 21:46:15 +02:00
if ( comment . substr ( pos1 , cppchecksuppress . size ( ) ) ! = cppchecksuppress )
2020-02-23 19:49:53 +01:00
return false ;
2020-02-23 18:29:36 +01:00
// skip spaces after "cppcheck-suppress"
2021-04-06 16:57:27 +02:00
const std : : string : : size_type pos2 = comment . find_first_not_of ( " " , pos1 + cppchecksuppress . size ( ) ) ;
2020-02-23 18:29:36 +01:00
if ( pos2 = = std : : string : : npos )
2020-02-23 19:49:53 +01:00
return false ;
2020-02-23 18:29:36 +01:00
2020-02-23 19:49:53 +01:00
if ( comment [ pos2 ] = = ' [ ' ) {
2020-02-23 18:29:36 +01:00
// multi suppress format
std : : string errmsg ;
2020-02-23 19:49:53 +01:00
std : : vector < Suppressions : : Suppression > suppressions = Suppressions : : parseMultiSuppressComment ( comment , & errmsg ) ;
2020-02-23 18:29:36 +01:00
if ( ! errmsg . empty ( ) )
2022-07-28 22:53:59 +02:00
bad - > emplace_back ( tok - > location , errmsg ) ;
2020-02-23 18:29:36 +01:00
2020-02-23 19:49:53 +01:00
for ( const Suppressions : : Suppression & s : suppressions ) {
if ( ! s . errorId . empty ( ) )
inlineSuppressions . push_back ( s ) ;
2020-02-23 18:04:24 +01:00
}
2020-02-23 18:29:36 +01:00
} else {
//single suppress format
std : : string errmsg ;
Suppressions : : Suppression s ;
2020-02-23 19:49:53 +01:00
if ( ! s . parseComment ( comment , & errmsg ) )
return false ;
2020-02-23 18:29:36 +01:00
if ( ! s . errorId . empty ( ) )
inlineSuppressions . push_back ( s ) ;
2020-02-23 18:04:24 +01:00
2020-02-23 18:29:36 +01:00
if ( ! errmsg . empty ( ) )
2022-07-28 22:53:59 +02:00
bad - > emplace_back ( tok - > location , errmsg ) ;
2020-02-23 18:29:36 +01:00
}
2020-02-23 19:49:53 +01:00
return true ;
2020-02-23 18:04:24 +01:00
}
2021-09-15 20:28:58 +02:00
static void addinlineSuppressions ( const simplecpp : : TokenList & tokens , Settings & mSettings , std : : list < BadInlineSuppression > * bad )
2020-02-23 18:04:24 +01:00
{
2020-05-20 18:03:03 +02:00
for ( const simplecpp : : Token * tok = tokens . cfront ( ) ; tok ; tok = tok - > next ) {
2020-02-23 19:49:53 +01:00
if ( ! tok - > comment )
2016-07-20 12:21:00 +02:00
continue ;
2013-11-15 19:21:21 +01:00
2020-02-23 19:49:53 +01:00
std : : list < Suppressions : : Suppression > inlineSuppressions ;
if ( ! parseInlineSuppressionCommentToken ( tok , inlineSuppressions , bad ) )
continue ;
2020-02-23 18:04:24 +01:00
2020-02-23 19:49:53 +01:00
if ( ! sameline ( tok - > previous , tok ) ) {
// find code after comment..
tok = tok - > next ;
while ( tok & & tok - > comment ) {
parseInlineSuppressionCommentToken ( tok , inlineSuppressions , bad ) ;
tok = tok - > next ;
}
if ( ! tok )
2020-02-23 18:04:24 +01:00
break ;
}
2020-02-23 19:49:53 +01:00
if ( inlineSuppressions . empty ( ) )
2016-07-20 12:21:00 +02:00
continue ;
2013-06-19 17:42:55 +02:00
2016-07-20 12:21:00 +02:00
// Relative filename
2020-02-23 19:49:53 +01:00
std : : string relativeFilename ( tok - > location . file ( ) ) ;
2018-06-16 16:10:28 +02:00
if ( mSettings . relativePaths ) {
2019-09-19 20:29:33 +02:00
for ( const std : : string & basePath : mSettings . basePaths ) {
const std : : string bp = basePath + " / " ;
2016-07-20 12:21:00 +02:00
if ( relativeFilename . compare ( 0 , bp . size ( ) , bp ) = = 0 ) {
relativeFilename = relativeFilename . substr ( bp . size ( ) ) ;
2013-06-19 17:42:55 +02:00
}
}
}
2018-04-09 11:50:59 +02:00
relativeFilename = Path : : simplifyPath ( relativeFilename ) ;
2013-06-19 17:42:55 +02:00
2020-10-02 18:56:26 +02:00
// special handling when suppressing { warnings for backwards compatibility
const bool thisAndNextLine = tok - > previous & &
tok - > previous - > previous & &
tok - > next & &
! sameline ( tok - > previous - > previous , tok - > previous ) & &
tok - > location . line + 1 = = tok - > next - > location . line & &
tok - > location . fileIndex = = tok - > next - > location . fileIndex & &
tok - > previous - > str ( ) = = " { " ;
2016-07-20 12:21:00 +02:00
// Add the suppressions.
2018-04-09 11:50:59 +02:00
for ( Suppressions : : Suppression & suppr : inlineSuppressions ) {
suppr . fileName = relativeFilename ;
2020-02-23 19:49:53 +01:00
suppr . lineNumber = tok - > location . line ;
2020-10-02 18:56:26 +02:00
suppr . thisAndNextLine = thisAndNextLine ;
2018-06-16 16:10:28 +02:00
mSettings . nomsg . addSuppression ( suppr ) ;
2016-07-20 12:21:00 +02:00
}
}
2013-06-19 17:42:55 +02:00
}
2016-07-21 07:57:23 +02:00
void Preprocessor : : inlineSuppressions ( const simplecpp : : TokenList & tokens )
{
2018-06-16 16:10:28 +02:00
if ( ! mSettings . inlineSuppressions )
2016-07-21 07:57:23 +02:00
return ;
2018-04-11 08:18:00 +02:00
std : : list < BadInlineSuppression > err ;
2021-09-15 20:28:58 +02:00
: : addinlineSuppressions ( tokens , mSettings , & err ) ;
2018-06-17 08:58:56 +02:00
for ( std : : map < std : : string , simplecpp : : TokenList * > : : const_iterator it = mTokenLists . begin ( ) ; it ! = mTokenLists . end ( ) ; + + it ) {
2016-07-21 07:57:23 +02:00
if ( it - > second )
2021-09-15 20:28:58 +02:00
: : addinlineSuppressions ( * it - > second , mSettings , & err ) ;
2018-04-11 08:18:00 +02:00
}
for ( const BadInlineSuppression & bad : err ) {
error ( bad . location . file ( ) , bad . location . line , bad . errmsg ) ;
2016-07-21 07:57:23 +02:00
}
}
lib: fix a bunch of warnings about differing function arguments in definition and declaration.
[lib/token.h:72] -> [lib/token.cpp:36]: (style, inconclusive) Function 'Token' argument 1 names different: declaration 'tokensBack' definition 't'.
[lib/token.h:445] -> [lib/token.cpp:497]: (style, inconclusive) Function 'multiCompare' argument 1 names different: declaration 'needle' definition 'tok'.
[lib/checkio.h:73] -> [lib/checkio.cpp:1385]: (style, inconclusive) Function 'ArgumentInfo' argument 3 names different: declaration 'isCPP' definition '_isCPP'.
[lib/checkother.h:216] -> [lib/checkother.cpp:2136]: (style, inconclusive) Function 'checkComparisonFunctionIsAlwaysTrueOrFalseError' argument 2 names different: declaration 'strFunctionName' definition 'functionName'.
[lib/errorlogger.h:214] -> [lib/errorlogger.cpp:51]: (style, inconclusive) Function 'ErrorMessage' argument 2 names different: declaration 'file0' definition 'file0_'.
[lib/errorlogger.h:215] -> [lib/errorlogger.cpp:65]: (style, inconclusive) Function 'ErrorMessage' argument 2 names different: declaration 'file0' definition 'file0_'.
[lib/library.h:327] -> [lib/library.cpp:1043]: (style, inconclusive) Function 'ignorefunction' argument 1 names different: declaration 'function' definition 'functionName'.
[lib/mathlib.h:112] -> [lib/mathlib.cpp:1275]: (style, inconclusive) Function 'isNullValue' argument 1 names different: declaration 'tok' definition 'str'.
[lib/preprocessor.h:91] -> [lib/preprocessor.cpp:122]: (style, inconclusive) Function 'setDirectives' argument 1 names different: declaration 'tokens' definition 'tokens1'.
[lib/symboldatabase.h:860] -> [lib/symboldatabase.cpp:1801]: (style, inconclusive) Function 'argsMatch' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1171] -> [lib/symboldatabase.cpp:2048]: (style, inconclusive) Function 'addClassFunction' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1174] -> [lib/symboldatabase.cpp:2208]: (style, inconclusive) Function 'addNewFunction' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1090] -> [lib/symboldatabase.cpp:3648]: (style, inconclusive) Function 'findVariableType' argument 2 names different: declaration 'type' definition 'typeTok'.
[lib/symboldatabase.h:1101] -> [lib/symboldatabase.cpp:4308]: (style, inconclusive) Function 'findType' argument 1 names different: declaration 'tok' definition 'startTok'.
[lib/symboldatabase.h:1176] -> [lib/symboldatabase.cpp:4349]: (style, inconclusive) Function 'findTypeInNested' argument 1 names different: declaration 'tok' definition 'startTok'.
[lib/symboldatabase.h:1193] -> [lib/symboldatabase.cpp:4501]: (style, inconclusive) Function 'setValueType' argument 2 names different: declaration 'enumerators' definition 'enumerator'.
[lib/path.h:159] -> [lib/path.cpp:247]: (style, inconclusive) Function 'isCPP' argument 1 names different: declaration 'extensionInLowerCase' definition 'path'.
[lib/path.h:145] -> [lib/path.cpp:266]: (style, inconclusive) Function 'acceptFile' argument 1 names different: declaration 'filename' definition 'path'.
2017-04-03 00:06:46 +02:00
void Preprocessor : : setDirectives ( const simplecpp : : TokenList & tokens )
2016-07-24 14:02:21 +02:00
{
// directive list..
2018-06-17 08:45:45 +02:00
mDirectives . clear ( ) ;
2016-07-24 14:02:21 +02:00
2016-12-05 17:30:06 +01:00
std : : vector < const simplecpp : : TokenList * > list ;
2018-06-17 08:58:56 +02:00
list . reserve ( 1U + mTokenLists . size ( ) ) ;
lib: fix a bunch of warnings about differing function arguments in definition and declaration.
[lib/token.h:72] -> [lib/token.cpp:36]: (style, inconclusive) Function 'Token' argument 1 names different: declaration 'tokensBack' definition 't'.
[lib/token.h:445] -> [lib/token.cpp:497]: (style, inconclusive) Function 'multiCompare' argument 1 names different: declaration 'needle' definition 'tok'.
[lib/checkio.h:73] -> [lib/checkio.cpp:1385]: (style, inconclusive) Function 'ArgumentInfo' argument 3 names different: declaration 'isCPP' definition '_isCPP'.
[lib/checkother.h:216] -> [lib/checkother.cpp:2136]: (style, inconclusive) Function 'checkComparisonFunctionIsAlwaysTrueOrFalseError' argument 2 names different: declaration 'strFunctionName' definition 'functionName'.
[lib/errorlogger.h:214] -> [lib/errorlogger.cpp:51]: (style, inconclusive) Function 'ErrorMessage' argument 2 names different: declaration 'file0' definition 'file0_'.
[lib/errorlogger.h:215] -> [lib/errorlogger.cpp:65]: (style, inconclusive) Function 'ErrorMessage' argument 2 names different: declaration 'file0' definition 'file0_'.
[lib/library.h:327] -> [lib/library.cpp:1043]: (style, inconclusive) Function 'ignorefunction' argument 1 names different: declaration 'function' definition 'functionName'.
[lib/mathlib.h:112] -> [lib/mathlib.cpp:1275]: (style, inconclusive) Function 'isNullValue' argument 1 names different: declaration 'tok' definition 'str'.
[lib/preprocessor.h:91] -> [lib/preprocessor.cpp:122]: (style, inconclusive) Function 'setDirectives' argument 1 names different: declaration 'tokens' definition 'tokens1'.
[lib/symboldatabase.h:860] -> [lib/symboldatabase.cpp:1801]: (style, inconclusive) Function 'argsMatch' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1171] -> [lib/symboldatabase.cpp:2048]: (style, inconclusive) Function 'addClassFunction' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1174] -> [lib/symboldatabase.cpp:2208]: (style, inconclusive) Function 'addNewFunction' argument 1 names different: declaration 'info' definition 'scope'.
[lib/symboldatabase.h:1090] -> [lib/symboldatabase.cpp:3648]: (style, inconclusive) Function 'findVariableType' argument 2 names different: declaration 'type' definition 'typeTok'.
[lib/symboldatabase.h:1101] -> [lib/symboldatabase.cpp:4308]: (style, inconclusive) Function 'findType' argument 1 names different: declaration 'tok' definition 'startTok'.
[lib/symboldatabase.h:1176] -> [lib/symboldatabase.cpp:4349]: (style, inconclusive) Function 'findTypeInNested' argument 1 names different: declaration 'tok' definition 'startTok'.
[lib/symboldatabase.h:1193] -> [lib/symboldatabase.cpp:4501]: (style, inconclusive) Function 'setValueType' argument 2 names different: declaration 'enumerators' definition 'enumerator'.
[lib/path.h:159] -> [lib/path.cpp:247]: (style, inconclusive) Function 'isCPP' argument 1 names different: declaration 'extensionInLowerCase' definition 'path'.
[lib/path.h:145] -> [lib/path.cpp:266]: (style, inconclusive) Function 'acceptFile' argument 1 names different: declaration 'filename' definition 'path'.
2017-04-03 00:06:46 +02:00
list . push_back ( & tokens ) ;
2018-06-17 08:58:56 +02:00
for ( std : : map < std : : string , simplecpp : : TokenList * > : : const_iterator it = mTokenLists . begin ( ) ; it ! = mTokenLists . end ( ) ; + + it ) {
2016-07-24 14:02:21 +02:00
list . push_back ( it - > second ) ;
}
2018-04-09 08:00:11 +02:00
for ( const simplecpp : : TokenList * tokenList : list ) {
for ( const simplecpp : : Token * tok = tokenList - > cfront ( ) ; tok ; tok = tok - > next ) {
2016-07-24 14:02:21 +02:00
if ( ( tok - > op ! = ' # ' ) | | ( tok - > previous & & tok - > previous - > location . line = = tok - > location . line ) )
continue ;
2018-05-14 13:00:22 +02:00
if ( tok - > next & & tok - > next - > str ( ) = = " endfile " )
2016-07-24 14:02:21 +02:00
continue ;
2017-03-01 10:50:50 +01:00
Directive directive ( tok - > location . file ( ) , tok - > location . line , emptyString ) ;
2016-07-24 14:02:21 +02:00
for ( const simplecpp : : Token * tok2 = tok ; tok2 & & tok2 - > location . line = = directive . linenr ; tok2 = tok2 - > next ) {
if ( tok2 - > comment )
continue ;
2018-05-14 13:00:22 +02:00
if ( ! directive . str . empty ( ) & & ( tok2 - > location . col > tok2 - > previous - > location . col + tok2 - > previous - > str ( ) . size ( ) ) )
2016-07-24 14:02:21 +02:00
directive . str + = ' ' ;
2018-05-14 13:00:22 +02:00
if ( directive . str = = " # " & & tok2 - > str ( ) = = " file " )
2016-07-24 14:02:21 +02:00
directive . str + = " include " ;
else
2018-05-14 13:00:22 +02:00
directive . str + = tok2 - > str ( ) ;
2016-07-24 14:02:21 +02:00
}
2018-06-17 08:45:45 +02:00
mDirectives . push_back ( directive ) ;
2016-07-24 14:02:21 +02:00
}
}
}
2016-08-21 15:01:04 +02:00
static std : : string readcondition ( const simplecpp : : Token * iftok , const std : : set < std : : string > & defined , const std : : set < std : : string > & undefined )
2009-01-24 20:28:30 +01:00
{
2016-07-20 12:21:00 +02:00
const simplecpp : : Token * cond = iftok - > next ;
2016-07-21 19:11:49 +02:00
if ( ! sameline ( iftok , cond ) )
2013-07-24 13:06:59 +02:00
return " " ;
2016-07-21 19:11:49 +02:00
const simplecpp : : Token * next1 = cond - > next ;
const simplecpp : : Token * next2 = next1 ? next1 - > next : nullptr ;
const simplecpp : : Token * next3 = next2 ? next2 - > next : nullptr ;
unsigned int len = 1 ;
if ( sameline ( iftok , next1 ) )
len = 2 ;
if ( sameline ( iftok , next2 ) )
len = 3 ;
if ( sameline ( iftok , next3 ) )
len = 4 ;
2018-05-14 13:00:22 +02:00
if ( len = = 1 & & cond - > str ( ) = = " 0 " )
2016-07-20 12:21:00 +02:00
return " 0 " ;
2009-05-13 21:18:02 +02:00
2016-07-21 19:11:49 +02:00
if ( len = = 1 & & cond - > name ) {
2018-05-14 13:00:22 +02:00
if ( defined . find ( cond - > str ( ) ) = = defined . end ( ) )
return cond - > str ( ) ;
2009-05-13 21:18:02 +02:00
}
2011-02-11 06:30:42 +01:00
2017-04-22 12:44:57 +02:00
if ( len = = 2 & & cond - > op = = ' ! ' & & next1 - > name ) {
2018-05-14 13:00:22 +02:00
if ( defined . find ( next1 - > str ( ) ) = = defined . end ( ) )
return next1 - > str ( ) + " =0 " ;
2017-04-22 12:44:57 +02:00
}
2016-07-21 19:11:49 +02:00
if ( len = = 3 & & cond - > op = = ' ( ' & & next1 - > name & & next2 - > op = = ' ) ' ) {
2018-05-14 13:00:22 +02:00
if ( defined . find ( next1 - > str ( ) ) = = defined . end ( ) & & undefined . find ( next1 - > str ( ) ) = = undefined . end ( ) )
return next1 - > str ( ) ;
2016-07-20 12:21:00 +02:00
}
2011-02-11 06:30:42 +01:00
2018-05-14 13:00:22 +02:00
if ( len = = 3 & & cond - > name & & next1 - > str ( ) = = " == " & & next2 - > number ) {
if ( defined . find ( cond - > str ( ) ) = = defined . end ( ) )
return cond - > str ( ) + ' = ' + cond - > next - > next - > str ( ) ;
2016-07-20 12:21:00 +02:00
}
2011-03-01 07:50:17 +01:00
2016-07-20 12:21:00 +02:00
std : : set < std : : string > configset ;
2016-07-21 19:11:49 +02:00
for ( ; sameline ( iftok , cond ) ; cond = cond - > next ) {
2017-04-02 09:03:43 +02:00
if ( cond - > op = = ' ! ' ) {
if ( ! sameline ( iftok , cond - > next ) | | ! cond - > next - > name )
break ;
2018-05-14 13:00:22 +02:00
if ( cond - > next - > str ( ) = = " defined " )
2017-04-02 09:03:43 +02:00
continue ;
2018-05-14 13:00:22 +02:00
configset . insert ( cond - > next - > str ( ) + " =0 " ) ;
2017-04-02 09:03:43 +02:00
continue ;
}
2018-05-14 13:00:22 +02:00
if ( cond - > str ( ) ! = " defined " )
2016-07-21 19:11:49 +02:00
continue ;
const simplecpp : : Token * dtok = cond - > next ;
if ( ! dtok )
break ;
if ( dtok - > op = = ' ( ' )
dtok = dtok - > next ;
2018-05-14 13:00:22 +02:00
if ( sameline ( iftok , dtok ) & & dtok - > name & & defined . find ( dtok - > str ( ) ) = = defined . end ( ) & & undefined . find ( dtok - > str ( ) ) = = undefined . end ( ) )
configset . insert ( dtok - > str ( ) ) ;
2016-07-20 12:21:00 +02:00
}
2021-09-15 20:28:58 +02:00
std : : string cfgStr ;
2018-04-09 08:00:11 +02:00
for ( const std : : string & s : configset ) {
2021-09-15 20:28:58 +02:00
if ( ! cfgStr . empty ( ) )
cfgStr + = ' ; ' ;
cfgStr + = s ;
2016-07-20 12:21:00 +02:00
}
2021-09-15 20:28:58 +02:00
return cfgStr ;
2011-02-11 06:30:42 +01:00
}
2016-08-21 13:53:44 +02:00
static bool hasDefine ( const std : : string & userDefines , const std : : string & cfg )
{
2016-10-11 18:46:46 +02:00
if ( cfg . empty ( ) ) {
return false ;
}
2016-08-21 13:53:44 +02:00
std : : string : : size_type pos = 0 ;
while ( pos < userDefines . size ( ) ) {
pos = userDefines . find ( cfg , pos ) ;
if ( pos = = std : : string : : npos )
break ;
const std : : string : : size_type pos2 = pos + cfg . size ( ) ;
if ( ( pos = = 0 | | userDefines [ pos - 1U ] = = ' ; ' ) & & ( pos2 = = userDefines . size ( ) | | userDefines [ pos2 ] = = ' = ' ) )
return true ;
pos = pos2 ;
}
return false ;
}
static std : : string cfg ( const std : : vector < std : : string > & configs , const std : : string & userDefines )
2016-07-20 12:21:00 +02:00
{
std : : set < std : : string > configs2 ( configs . begin ( ) , configs . end ( ) ) ;
std : : string ret ;
2021-09-15 20:28:58 +02:00
for ( const std : : string & c : configs2 ) {
if ( c . empty ( ) )
2016-07-20 12:21:00 +02:00
continue ;
2021-09-15 20:28:58 +02:00
if ( c = = " 0 " )
2016-07-20 12:21:00 +02:00
return " " ;
2021-09-15 20:28:58 +02:00
if ( hasDefine ( userDefines , c ) )
2016-08-21 13:53:44 +02:00
continue ;
2016-07-20 12:21:00 +02:00
if ( ! ret . empty ( ) )
ret + = ' ; ' ;
2021-09-15 20:28:58 +02:00
ret + = c ;
2016-07-20 12:21:00 +02:00
}
return ret ;
}
2013-09-01 07:13:48 +02:00
2016-08-21 07:45:15 +02:00
static bool isUndefined ( const std : : string & cfg , const std : : set < std : : string > & undefined )
{
for ( std : : string : : size_type pos1 = 0U ; pos1 < cfg . size ( ) ; ) {
2016-11-30 12:01:22 +01:00
const std : : string : : size_type pos2 = cfg . find ( ' ; ' , pos1 ) ;
2016-08-21 07:45:15 +02:00
const std : : string def = ( pos2 = = std : : string : : npos ) ? cfg . substr ( pos1 ) : cfg . substr ( pos1 , pos2 - pos1 ) ;
2018-04-04 21:51:31 +02:00
const std : : string : : size_type eq = def . find ( ' = ' ) ;
2016-08-21 07:45:15 +02:00
if ( eq = = std : : string : : npos & & undefined . find ( def ) ! = undefined . end ( ) )
return true ;
if ( eq ! = std : : string : : npos & & undefined . find ( def . substr ( 0 , eq ) ) ! = undefined . end ( ) & & def . substr ( eq ) ! = " =0 " )
return true ;
pos1 = ( pos2 = = std : : string : : npos ) ? pos2 : pos2 + 1U ;
}
return false ;
}
2016-08-21 13:53:44 +02:00
static bool getConfigsElseIsFalse ( const std : : vector < std : : string > & configs_if , const std : : string & userDefines )
{
2019-05-08 20:23:32 +02:00
return std : : any_of ( configs_if . cbegin ( ) , configs_if . cend ( ) ,
2021-08-07 20:51:18 +02:00
[ = ] ( const std : : string & cfg ) {
2019-05-08 20:23:32 +02:00
return hasDefine ( userDefines , cfg ) ;
} ) ;
2016-08-21 13:53:44 +02:00
}
static const simplecpp : : Token * gotoEndIf ( const simplecpp : : Token * cmdtok )
{
int level = 0 ;
while ( nullptr ! = ( cmdtok = cmdtok - > next ) ) {
if ( cmdtok - > op = = ' # ' & & ! sameline ( cmdtok - > previous , cmdtok ) & & sameline ( cmdtok , cmdtok - > next ) ) {
2018-05-14 13:00:22 +02:00
if ( cmdtok - > next - > str ( ) . compare ( 0 , 2 , " if " ) = = 0 )
2016-08-21 13:53:44 +02:00
+ + level ;
2018-05-14 13:00:22 +02:00
else if ( cmdtok - > next - > str ( ) = = " endif " ) {
2016-08-21 13:53:44 +02:00
- - level ;
if ( level < 0 )
return cmdtok ;
}
}
}
return nullptr ;
}
static void getConfigs ( const simplecpp : : TokenList & tokens , std : : set < std : : string > & defined , const std : : string & userDefines , const std : : set < std : : string > & undefined , std : : set < std : : string > & ret )
2013-09-01 07:13:48 +02:00
{
2016-07-20 12:21:00 +02:00
std : : vector < std : : string > configs_if ;
std : : vector < std : : string > configs_ifndef ;
2017-03-22 10:53:21 +01:00
std : : string elseError ;
2016-07-20 12:21:00 +02:00
2016-07-29 08:51:57 +02:00
for ( const simplecpp : : Token * tok = tokens . cfront ( ) ; tok ; tok = tok - > next ) {
2016-07-21 19:11:49 +02:00
if ( tok - > op ! = ' # ' | | sameline ( tok - > previous , tok ) )
2013-09-01 07:13:48 +02:00
continue ;
2016-07-21 19:11:49 +02:00
const simplecpp : : Token * cmdtok = tok - > next ;
if ( ! sameline ( tok , cmdtok ) )
2016-07-20 12:21:00 +02:00
continue ;
2018-05-14 13:00:22 +02:00
if ( cmdtok - > str ( ) = = " ifdef " | | cmdtok - > str ( ) = = " ifndef " | | cmdtok - > str ( ) = = " if " ) {
2016-07-20 12:21:00 +02:00
std : : string config ;
2018-05-14 13:00:22 +02:00
if ( cmdtok - > str ( ) = = " ifdef " | | cmdtok - > str ( ) = = " ifndef " ) {
2016-07-21 19:11:49 +02:00
const simplecpp : : Token * expr1 = cmdtok - > next ;
if ( sameline ( tok , expr1 ) & & expr1 - > name & & ! sameline ( tok , expr1 - > next ) )
2018-05-14 13:00:22 +02:00
config = expr1 - > str ( ) ;
2016-07-20 12:21:00 +02:00
if ( defined . find ( config ) ! = defined . end ( ) )
config . clear ( ) ;
2018-05-14 13:00:22 +02:00
} else if ( cmdtok - > str ( ) = = " if " ) {
2016-08-21 15:01:04 +02:00
config = readcondition ( cmdtok , defined , undefined ) ;
2016-07-20 12:21:00 +02:00
}
2016-08-21 07:45:15 +02:00
// skip undefined configurations..
if ( isUndefined ( config , undefined ) )
2016-07-28 19:22:59 +02:00
config . clear ( ) ;
2016-08-21 07:45:15 +02:00
2021-03-12 18:16:09 +01:00
bool ifndef = false ;
if ( cmdtok - > str ( ) = = " ifndef " )
ifndef = true ;
else {
const std : : vector < std : : string > match { " if " , " ! " , " defined " , " ( " , config , " ) " } ;
int i = 0 ;
ifndef = true ;
for ( const simplecpp : : Token * t = cmdtok ; i < match . size ( ) ; t = t - > next ) {
if ( ! t | | t - > str ( ) ! = match [ i + + ] ) {
ifndef = false ;
break ;
}
}
}
// include guard..
if ( ifndef & & tok - > location . fileIndex > 0 ) {
bool includeGuard = true ;
for ( const simplecpp : : Token * t = tok - > previous ; t ; t = t - > previous ) {
if ( t - > location . fileIndex = = tok - > location . fileIndex ) {
includeGuard = false ;
break ;
}
}
if ( includeGuard ) {
2022-07-26 15:30:53 +02:00
configs_if . emplace_back ( /*std::string()*/ ) ;
configs_ifndef . emplace_back ( /*std::string()*/ ) ;
2021-03-12 18:16:09 +01:00
continue ;
}
}
2018-05-14 13:00:22 +02:00
configs_if . push_back ( ( cmdtok - > str ( ) = = " ifndef " ) ? std : : string ( ) : config ) ;
configs_ifndef . push_back ( ( cmdtok - > str ( ) = = " ifndef " ) ? config : std : : string ( ) ) ;
2016-08-21 13:53:44 +02:00
ret . insert ( cfg ( configs_if , userDefines ) ) ;
2018-05-14 13:00:22 +02:00
} else if ( cmdtok - > str ( ) = = " elif " | | cmdtok - > str ( ) = = " else " ) {
2016-08-21 13:53:44 +02:00
if ( getConfigsElseIsFalse ( configs_if , userDefines ) ) {
tok = gotoEndIf ( tok ) ;
if ( ! tok )
break ;
tok = tok - > previous ;
continue ;
}
2018-05-14 13:00:22 +02:00
if ( cmdtok - > str ( ) = = " else " & &
2017-03-22 10:53:21 +01:00
cmdtok - > next & &
! sameline ( cmdtok , cmdtok - > next ) & &
sameline ( cmdtok - > next , cmdtok - > next - > next ) & &
cmdtok - > next - > op = = ' # ' & &
2018-05-14 13:00:22 +02:00
cmdtok - > next - > next - > str ( ) = = " error " ) {
2017-05-24 11:16:41 +02:00
const std : : string & ifcfg = cfg ( configs_if , userDefines ) ;
if ( ! ifcfg . empty ( ) ) {
if ( ! elseError . empty ( ) )
elseError + = ' ; ' ;
elseError + = ifcfg ;
}
2017-03-22 10:53:21 +01:00
}
2016-07-20 20:39:03 +02:00
if ( ! configs_if . empty ( ) )
configs_if . pop_back ( ) ;
2018-05-14 13:00:22 +02:00
if ( cmdtok - > str ( ) = = " elif " ) {
2016-08-21 15:01:04 +02:00
std : : string config = readcondition ( cmdtok , defined , undefined ) ;
2016-08-21 13:53:44 +02:00
if ( isUndefined ( config , undefined ) )
config . clear ( ) ;
configs_if . push_back ( config ) ;
ret . insert ( cfg ( configs_if , userDefines ) ) ;
} else if ( ! configs_ifndef . empty ( ) ) {
2016-07-23 14:40:01 +02:00
configs_if . push_back ( configs_ifndef . back ( ) ) ;
2016-08-21 13:53:44 +02:00
ret . insert ( cfg ( configs_if , userDefines ) ) ;
2016-07-23 14:40:01 +02:00
}
2018-05-14 13:00:22 +02:00
} else if ( cmdtok - > str ( ) = = " endif " & & ! sameline ( tok , cmdtok - > next ) ) {
2016-07-20 12:21:00 +02:00
if ( ! configs_if . empty ( ) )
configs_if . pop_back ( ) ;
if ( ! configs_ifndef . empty ( ) )
configs_ifndef . pop_back ( ) ;
2018-05-14 13:00:22 +02:00
} else if ( cmdtok - > str ( ) = = " error " ) {
2016-12-03 11:59:48 +01:00
if ( ! configs_ifndef . empty ( ) & & ! configs_ifndef . back ( ) . empty ( ) ) {
2017-04-02 12:15:53 +02:00
if ( configs_ifndef . size ( ) = = 1U )
2022-07-10 10:57:29 +02:00
ret . erase ( emptyString ) ;
2016-12-03 11:59:48 +01:00
std : : vector < std : : string > configs ( configs_if ) ;
configs . push_back ( configs_ifndef . back ( ) ) ;
2017-04-22 12:44:57 +02:00
ret . erase ( cfg ( configs , userDefines ) ) ;
2021-02-06 12:48:52 +01:00
std : : set < std : : string > temp ;
temp . swap ( ret ) ;
for ( const std : : string & c : temp ) {
if ( c . find ( configs_ifndef . back ( ) ) ! = std : : string : : npos )
ret . insert ( c ) ;
else if ( c . empty ( ) )
ret . insert ( configs . empty ( ) ? configs_ifndef . back ( ) : " " ) ;
else
ret . insert ( c + " ; " + configs_ifndef . back ( ) ) ;
}
2017-04-22 12:44:57 +02:00
if ( ! elseError . empty ( ) )
elseError + = ' ; ' ;
elseError + = cfg ( configs_ifndef , userDefines ) ;
2016-12-03 11:59:48 +01:00
}
2017-04-02 10:06:39 +02:00
if ( ! configs_if . empty ( ) & & ! configs_if . back ( ) . empty ( ) ) {
const std : : string & last = configs_if . back ( ) ;
if ( last . size ( ) > 2U & & last . compare ( last . size ( ) - 2U , 2 , " =0 " ) = = 0 ) {
std : : vector < std : : string > configs ( configs_if ) ;
2017-04-02 12:15:53 +02:00
ret . erase ( cfg ( configs , userDefines ) ) ;
2017-04-02 10:06:39 +02:00
configs [ configs . size ( ) - 1U ] = last . substr ( 0 , last . size ( ) - 2U ) ;
2017-04-02 12:15:53 +02:00
if ( configs . size ( ) = = 1U )
ret . erase ( " " ) ;
2017-04-22 12:44:57 +02:00
if ( ! elseError . empty ( ) )
elseError + = ' ; ' ;
elseError + = cfg ( configs , userDefines ) ;
2017-04-02 10:06:39 +02:00
}
}
2018-05-14 13:00:22 +02:00
} else if ( cmdtok - > str ( ) = = " define " & & sameline ( tok , cmdtok - > next ) & & cmdtok - > next - > name ) {
defined . insert ( cmdtok - > next - > str ( ) ) ;
2016-07-20 12:21:00 +02:00
}
}
2017-03-22 10:53:21 +01:00
if ( ! elseError . empty ( ) )
2022-08-07 19:31:16 +02:00
ret . insert ( std : : move ( elseError ) ) ;
2016-07-20 12:21:00 +02:00
}
std : : set < std : : string > Preprocessor : : getConfigs ( const simplecpp : : TokenList & tokens ) const
{
2018-04-11 09:44:35 +02:00
std : : set < std : : string > ret = { " " } ;
2016-07-29 08:51:57 +02:00
if ( ! tokens . cfront ( ) )
2016-07-20 12:21:00 +02:00
return ret ;
2018-04-11 09:44:35 +02:00
std : : set < std : : string > defined = { " __cplusplus " } ;
2016-07-20 12:21:00 +02:00
2018-06-16 16:10:28 +02:00
: : getConfigs ( tokens , defined , mSettings . userDefines , mSettings . userUndefs , ret ) ;
2016-07-20 12:21:00 +02:00
2018-06-17 08:58:56 +02:00
for ( std : : map < std : : string , simplecpp : : TokenList * > : : const_iterator it = mTokenLists . begin ( ) ; it ! = mTokenLists . end ( ) ; + + it ) {
2018-06-16 16:10:28 +02:00
if ( ! mSettings . configurationExcluded ( it - > first ) )
: : getConfigs ( * ( it - > second ) , defined , mSettings . userDefines , mSettings . userUndefs , ret ) ;
2016-09-30 08:00:06 +02:00
}
2013-09-01 07:13:48 +02:00
2016-07-20 12:21:00 +02:00
return ret ;
2013-09-01 07:13:48 +02:00
}
2009-05-13 21:18:02 +02:00
2016-07-20 12:21:00 +02:00
void Preprocessor : : preprocess ( std : : istream & istr , std : : map < std : : string , std : : string > & result , const std : : string & filename , const std : : list < std : : string > & includePaths )
2009-10-04 07:25:30 +02:00
{
2016-07-20 12:21:00 +02:00
( void ) includePaths ;
2009-10-04 07:25:30 +02:00
2016-07-20 12:21:00 +02:00
simplecpp : : OutputList outputList ;
std : : vector < std : : string > files ;
const simplecpp : : TokenList tokens1 ( istr , files , filename , & outputList ) ;
2009-10-04 07:25:30 +02:00
2016-07-20 12:21:00 +02:00
const std : : set < std : : string > configs = getConfigs ( tokens1 ) ;
2009-09-11 21:22:41 +02:00
2021-09-15 20:28:58 +02:00
for ( const std : : string & c : configs ) {
if ( mSettings . userUndefs . find ( c ) = = mSettings . userUndefs . end ( ) ) {
result [ c ] = getcode ( tokens1 , c , files , false ) ;
2013-06-08 16:46:54 +02:00
}
2011-11-30 20:24:01 +01:00
}
2009-01-24 20:28:30 +01:00
}
2010-04-15 22:45:38 +02:00
void Preprocessor : : preprocess ( std : : istream & srcCodeStream , std : : string & processedFile , std : : list < std : : string > & resultConfigurations , const std : : string & filename , const std : : list < std : : string > & includePaths )
{
2016-07-20 12:21:00 +02:00
( void ) includePaths ;
2012-12-27 16:52:31 +01:00
2018-06-17 09:06:16 +02:00
if ( mFile0 . empty ( ) )
mFile0 = filename ;
2010-09-03 13:30:49 +02:00
2016-07-20 12:21:00 +02:00
simplecpp : : OutputList outputList ;
std : : vector < std : : string > files ;
const simplecpp : : TokenList tokens1 ( srcCodeStream , files , filename , & outputList ) ;
2012-12-27 16:52:31 +01:00
2016-07-20 12:21:00 +02:00
const std : : set < std : : string > configs = getConfigs ( tokens1 ) ;
2019-05-08 20:23:32 +02:00
std : : copy ( configs . cbegin ( ) , configs . cend ( ) , std : : back_inserter ( resultConfigurations ) ) ;
2012-12-27 16:52:31 +01:00
2016-07-20 12:21:00 +02:00
processedFile = tokens1 . stringify ( ) ;
}
2015-07-24 13:30:41 +02:00
2016-07-20 12:21:00 +02:00
static void splitcfg ( const std : : string & cfg , std : : list < std : : string > & defines , const std : : string & defaultValue )
{
2016-08-23 17:27:07 +02:00
for ( std : : string : : size_type defineStartPos = 0U ; defineStartPos < cfg . size ( ) ; ) {
2016-11-30 12:01:22 +01:00
const std : : string : : size_type defineEndPos = cfg . find ( ' ; ' , defineStartPos ) ;
2016-08-23 17:27:07 +02:00
std : : string def = ( defineEndPos = = std : : string : : npos ) ? cfg . substr ( defineStartPos ) : cfg . substr ( defineStartPos , defineEndPos - defineStartPos ) ;
2016-11-30 12:01:22 +01:00
if ( ! defaultValue . empty ( ) & & def . find ( ' = ' ) = = std : : string : : npos )
2016-07-20 12:21:00 +02:00
def + = ' = ' + defaultValue ;
defines . push_back ( def ) ;
2016-08-23 17:27:07 +02:00
if ( defineEndPos = = std : : string : : npos )
break ;
defineStartPos = defineEndPos + 1U ;
2015-07-24 13:30:41 +02:00
}
2016-07-20 12:21:00 +02:00
}
2015-07-24 13:30:41 +02:00
2018-06-16 16:10:28 +02:00
static simplecpp : : DUI createDUI ( const Settings & mSettings , const std : : string & cfg , const std : : string & filename )
2016-07-20 12:21:00 +02:00
{
simplecpp : : DUI dui ;
2012-12-27 16:52:31 +01:00
2018-06-16 16:10:28 +02:00
splitcfg ( mSettings . userDefines , dui . defines , " 1 " ) ;
2016-08-06 09:15:09 +02:00
if ( ! cfg . empty ( ) )
2017-03-01 10:50:50 +01:00
splitcfg ( cfg , dui . defines , emptyString ) ;
2016-07-20 12:21:00 +02:00
2018-07-15 15:03:08 +02:00
for ( const std : : string & def : mSettings . library . defines ) {
2019-02-28 22:34:08 +01:00
const std : : string : : size_type pos = def . find_first_of ( " ( " ) ;
2016-07-20 12:21:00 +02:00
if ( pos = = std : : string : : npos ) {
2019-02-28 22:34:08 +01:00
dui . defines . push_back ( def ) ;
2016-07-20 12:21:00 +02:00
continue ;
}
2019-02-28 22:34:08 +01:00
std : : string s = def ;
2016-07-20 12:21:00 +02:00
if ( s [ pos ] = = ' ' ) {
s [ pos ] = ' = ' ;
} else {
2016-11-30 12:01:22 +01:00
s [ s . find ( ' ) ' ) + 1 ] = ' = ' ;
2009-07-22 20:11:27 +02:00
}
2016-07-20 12:21:00 +02:00
dui . defines . push_back ( s ) ;
2009-07-22 20:11:27 +02:00
}
2018-06-16 16:10:28 +02:00
dui . undefined = mSettings . userUndefs ; // -U
dui . includePaths = mSettings . includePaths ; // -I
dui . includes = mSettings . userIncludes ; // --include
2022-04-15 16:17:36 +02:00
// TODO: use mSettings.standards.stdValue instead
2021-04-26 16:32:44 +02:00
if ( Path : : isCPP ( filename ) )
dui . std = mSettings . standards . getCPP ( ) ;
2022-04-15 16:17:36 +02:00
else
dui . std = mSettings . standards . getC ( ) ;
2016-08-06 09:15:09 +02:00
return dui ;
}
2016-08-06 10:22:58 +02:00
static bool hasErrors ( const simplecpp : : OutputList & outputList )
2016-08-06 09:15:09 +02:00
{
for ( simplecpp : : OutputList : : const_iterator it = outputList . begin ( ) ; it ! = outputList . end ( ) ; + + it ) {
switch ( it - > type ) {
case simplecpp : : Output : : ERROR :
case simplecpp : : Output : : INCLUDE_NESTED_TOO_DEEPLY :
case simplecpp : : Output : : SYNTAX_ERROR :
2017-09-12 22:42:10 +02:00
case simplecpp : : Output : : UNHANDLED_CHAR_ERROR :
2019-12-09 19:16:55 +01:00
case simplecpp : : Output : : EXPLICIT_INCLUDE_NOT_FOUND :
2016-08-06 09:15:09 +02:00
return true ;
case simplecpp : : Output : : WARNING :
case simplecpp : : Output : : MISSING_HEADER :
2016-09-03 12:29:45 +02:00
case simplecpp : : Output : : PORTABILITY_BACKSLASH :
2016-08-06 09:15:09 +02:00
break ;
2020-04-21 17:27:51 +02:00
}
2016-08-06 09:15:09 +02:00
}
return false ;
}
2019-12-09 19:16:55 +01:00
void Preprocessor : : handleErrors ( const simplecpp : : OutputList & outputList , bool throwError )
{
const bool showerror = ( ! mSettings . userDefines . empty ( ) & & ! mSettings . force ) ;
reportOutput ( outputList , showerror ) ;
if ( throwError ) {
for ( const simplecpp : : Output & output : outputList ) {
switch ( output . type ) {
case simplecpp : : Output : : ERROR :
case simplecpp : : Output : : INCLUDE_NESTED_TOO_DEEPLY :
case simplecpp : : Output : : SYNTAX_ERROR :
case simplecpp : : Output : : UNHANDLED_CHAR_ERROR :
case simplecpp : : Output : : EXPLICIT_INCLUDE_NOT_FOUND :
throw output ;
case simplecpp : : Output : : WARNING :
case simplecpp : : Output : : MISSING_HEADER :
case simplecpp : : Output : : PORTABILITY_BACKSLASH :
break ;
2020-04-21 17:27:51 +02:00
}
2019-12-09 19:16:55 +01:00
}
}
}
2009-01-24 20:28:30 +01:00
2019-12-09 19:16:55 +01:00
bool Preprocessor : : loadFiles ( const simplecpp : : TokenList & rawtokens , std : : vector < std : : string > & files )
2016-08-06 09:15:09 +02:00
{
2018-06-16 16:10:28 +02:00
const simplecpp : : DUI dui = createDUI ( mSettings , emptyString , files [ 0 ] ) ;
2009-01-24 20:28:30 +01:00
2019-12-09 19:16:55 +01:00
simplecpp : : OutputList outputList ;
mTokenLists = simplecpp : : load ( rawtokens , files , dui , & outputList ) ;
handleErrors ( outputList , false ) ;
return ! hasErrors ( outputList ) ;
2009-01-24 20:28:30 +01:00
}
2016-07-21 07:48:17 +02:00
void Preprocessor : : removeComments ( )
{
2020-09-21 19:30:47 +02:00
for ( std : : pair < const std : : string , simplecpp : : TokenList * > & tokenList : mTokenLists ) {
if ( tokenList . second )
2020-09-21 19:48:04 +02:00
tokenList . second - > removeComments ( ) ;
2016-07-21 07:48:17 +02:00
}
}
2016-07-25 14:52:23 +02:00
void Preprocessor : : setPlatformInfo ( simplecpp : : TokenList * tokens ) const
{
2018-06-16 16:10:28 +02:00
tokens - > sizeOfType [ " bool " ] = mSettings . sizeof_bool ;
tokens - > sizeOfType [ " short " ] = mSettings . sizeof_short ;
tokens - > sizeOfType [ " int " ] = mSettings . sizeof_int ;
tokens - > sizeOfType [ " long " ] = mSettings . sizeof_long ;
tokens - > sizeOfType [ " long long " ] = mSettings . sizeof_long_long ;
tokens - > sizeOfType [ " float " ] = mSettings . sizeof_float ;
tokens - > sizeOfType [ " double " ] = mSettings . sizeof_double ;
tokens - > sizeOfType [ " long double " ] = mSettings . sizeof_long_double ;
tokens - > sizeOfType [ " bool * " ] = mSettings . sizeof_pointer ;
tokens - > sizeOfType [ " short * " ] = mSettings . sizeof_pointer ;
tokens - > sizeOfType [ " int * " ] = mSettings . sizeof_pointer ;
tokens - > sizeOfType [ " long * " ] = mSettings . sizeof_pointer ;
tokens - > sizeOfType [ " long long * " ] = mSettings . sizeof_pointer ;
tokens - > sizeOfType [ " float * " ] = mSettings . sizeof_pointer ;
tokens - > sizeOfType [ " double * " ] = mSettings . sizeof_pointer ;
tokens - > sizeOfType [ " long double * " ] = mSettings . sizeof_pointer ;
2016-07-25 14:52:23 +02:00
}
2018-05-28 14:11:59 +02:00
simplecpp : : TokenList Preprocessor : : preprocess ( const simplecpp : : TokenList & tokens1 , const std : : string & cfg , std : : vector < std : : string > & files , bool throwError )
2012-07-18 20:57:00 +02:00
{
2018-06-16 16:10:28 +02:00
const simplecpp : : DUI dui = createDUI ( mSettings , cfg , files [ 0 ] ) ;
2009-01-24 20:28:30 +01:00
2016-07-20 12:21:00 +02:00
simplecpp : : OutputList outputList ;
std : : list < simplecpp : : MacroUsage > macroUsage ;
2021-07-22 08:46:28 +02:00
std : : list < simplecpp : : IfCond > ifCond ;
2016-07-21 19:42:26 +02:00
simplecpp : : TokenList tokens2 ( files ) ;
2021-07-22 08:46:28 +02:00
simplecpp : : preprocess ( tokens2 , tokens1 , files , mTokenLists , dui , & outputList , & macroUsage , & ifCond ) ;
2021-07-08 14:36:28 +02:00
mMacroUsage = macroUsage ;
2021-07-22 08:46:28 +02:00
mIfCond = ifCond ;
2009-01-24 20:28:30 +01:00
2019-12-09 19:16:55 +01:00
handleErrors ( outputList , throwError ) ;
2009-06-26 13:19:55 +02:00
2017-05-02 22:18:24 +02:00
tokens2 . removeComments ( ) ;
2016-07-20 12:21:00 +02:00
// ensure that guessed define macros without value are not used in the code
2016-08-01 20:09:41 +02:00
if ( ! validateCfg ( cfg , macroUsage ) )
2017-05-17 10:25:37 +02:00
return simplecpp : : TokenList ( files ) ;
2011-10-17 20:12:46 +02:00
2017-05-17 10:25:37 +02:00
return tokens2 ;
}
2011-11-03 19:05:48 +01:00
2017-05-17 10:25:37 +02:00
std : : string Preprocessor : : getcode ( const simplecpp : : TokenList & tokens1 , const std : : string & cfg , std : : vector < std : : string > & files , const bool writeLocations )
{
2018-05-28 14:11:59 +02:00
simplecpp : : TokenList tokens2 = preprocess ( tokens1 , cfg , files , false ) ;
2016-07-20 12:21:00 +02:00
unsigned int prevfile = 0 ;
unsigned int line = 1 ;
std : : ostringstream ret ;
2016-07-29 08:51:57 +02:00
for ( const simplecpp : : Token * tok = tokens2 . cfront ( ) ; tok ; tok = tok - > next ) {
2016-07-20 12:21:00 +02:00
if ( writeLocations & & tok - > location . fileIndex ! = prevfile ) {
ret < < " \n #line " < < tok - > location . line < < " \" " < < tok - > location . file ( ) < < " \" \n " ;
prevfile = tok - > location . fileIndex ;
line = tok - > location . line ;
}
2011-11-03 19:05:48 +01:00
2017-03-05 16:46:43 +01:00
if ( tok - > previous & & line > = tok - > location . line ) // #7912
2016-07-20 12:21:00 +02:00
ret < < ' ' ;
while ( tok - > location . line > line ) {
ret < < ' \n ' ;
line + + ;
}
if ( ! tok - > macro . empty ( ) )
ret < < Preprocessor : : macroChar ;
2018-05-14 13:00:22 +02:00
ret < < tok - > str ( ) ;
2016-07-20 12:21:00 +02:00
}
2011-11-03 19:05:48 +01:00
2016-07-20 12:21:00 +02:00
return ret . str ( ) ;
}
2011-11-03 19:05:48 +01:00
2016-07-20 12:21:00 +02:00
std : : string Preprocessor : : getcode ( const std : : string & filedata , const std : : string & cfg , const std : : string & filename )
{
simplecpp : : OutputList outputList ;
std : : vector < std : : string > files ;
2013-08-18 18:04:06 +02:00
2016-07-20 12:21:00 +02:00
std : : istringstream istr ( filedata ) ;
2016-07-24 14:02:21 +02:00
simplecpp : : TokenList tokens1 ( istr , files , Path : : simplifyPath ( filename ) , & outputList ) ;
2016-07-20 12:21:00 +02:00
inlineSuppressions ( tokens1 ) ;
2016-07-24 14:02:21 +02:00
tokens1 . removeComments ( ) ;
removeComments ( ) ;
setDirectives ( tokens1 ) ;
2011-11-03 19:05:48 +01:00
2016-08-06 09:15:09 +02:00
reportOutput ( outputList , true ) ;
2016-08-06 13:28:24 +02:00
2016-08-06 09:15:09 +02:00
if ( hasErrors ( outputList ) )
return " " ;
2018-05-15 15:42:54 +02:00
std : : string ret ;
try {
ret = getcode ( tokens1 , cfg , files , filedata . find ( " #file " ) ! = std : : string : : npos ) ;
2021-07-22 08:46:28 +02:00
// Since "files" is a local variable the tracking info must be cleared..
mMacroUsage . clear ( ) ;
mIfCond . clear ( ) ;
2018-05-29 13:18:07 +02:00
} catch ( const simplecpp : : Output & ) {
2018-05-15 15:42:54 +02:00
ret . clear ( ) ;
}
return ret ;
2016-08-06 09:15:09 +02:00
}
void Preprocessor : : reportOutput ( const simplecpp : : OutputList & outputList , bool showerror )
{
2018-07-15 15:03:08 +02:00
for ( const simplecpp : : Output & out : outputList ) {
switch ( out . type ) {
2016-07-21 12:47:00 +02:00
case simplecpp : : Output : : ERROR :
2018-07-15 15:03:08 +02:00
if ( out . msg . compare ( 0 , 6 , " #error " ) ! = 0 | | showerror )
error ( out . location . file ( ) , out . location . line , out . msg ) ;
2016-08-06 09:15:09 +02:00
break ;
2016-07-21 12:47:00 +02:00
case simplecpp : : Output : : WARNING :
2016-09-03 12:29:45 +02:00
case simplecpp : : Output : : PORTABILITY_BACKSLASH :
2016-07-21 12:47:00 +02:00
break ;
2016-07-31 12:10:30 +02:00
case simplecpp : : Output : : MISSING_HEADER : {
2018-07-15 15:03:08 +02:00
const std : : string : : size_type pos1 = out . msg . find_first_of ( " < \" " ) ;
const std : : string : : size_type pos2 = out . msg . find_first_of ( " > \" " , pos1 + 1U ) ;
2016-07-21 12:47:00 +02:00
if ( pos1 < pos2 & & pos2 ! = std : : string : : npos )
2018-07-15 15:03:08 +02:00
missingInclude ( out . location . file ( ) , out . location . line , out . msg . substr ( pos1 + 1 , pos2 - pos1 - 1 ) , out . msg [ pos1 ] = = ' \" ' ? UserHeader : SystemHeader ) ;
2011-10-17 20:12:46 +02:00
}
2016-07-21 12:47:00 +02:00
break ;
2016-08-06 09:15:09 +02:00
case simplecpp : : Output : : INCLUDE_NESTED_TOO_DEEPLY :
case simplecpp : : Output : : SYNTAX_ERROR :
2017-09-12 22:42:10 +02:00
case simplecpp : : Output : : UNHANDLED_CHAR_ERROR :
2018-07-15 15:03:08 +02:00
error ( out . location . file ( ) , out . location . line , out . msg ) ;
2016-08-06 09:15:09 +02:00
break ;
2019-12-09 19:16:55 +01:00
case simplecpp : : Output : : EXPLICIT_INCLUDE_NOT_FOUND :
error ( emptyString , 0 , out . msg ) ;
break ;
2020-04-21 17:27:51 +02:00
}
2011-10-17 20:12:46 +02:00
}
}
2016-07-20 12:21:00 +02:00
void Preprocessor : : error ( const std : : string & filename , unsigned int linenr , const std : : string & msg )
2009-01-24 20:28:30 +01:00
{
2020-05-23 07:16:49 +02:00
std : : list < ErrorMessage : : FileLocation > locationList ;
2016-07-20 12:21:00 +02:00
if ( ! filename . empty ( ) ) {
2021-02-18 22:35:55 +01:00
std : : string file = Path : : fromNativeSeparators ( filename ) ;
if ( mSettings . relativePaths )
file = Path : : getRelativePath ( file , mSettings . basePaths ) ;
const ErrorMessage : : FileLocation loc ( file , linenr , 0 ) ;
2016-07-20 12:21:00 +02:00
locationList . push_back ( loc ) ;
2015-01-03 18:22:52 +01:00
}
2020-05-23 07:16:49 +02:00
mErrorLogger - > reportErr ( ErrorMessage ( locationList ,
mFile0 ,
Severity : : error ,
msg ,
" preprocessorErrorDirective " ,
2021-02-24 22:00:06 +01:00
Certainty : : normal ) ) ;
2016-07-20 12:21:00 +02:00
}
2011-01-06 20:01:09 +01:00
2010-12-29 12:43:29 +01:00
// Report that include is missing
2013-03-13 06:48:33 +01:00
void Preprocessor : : missingInclude ( const std : : string & filename , unsigned int linenr , const std : : string & header , HeaderTypes headerType )
2010-12-29 12:43:29 +01:00
{
2022-07-09 23:21:11 +02:00
if ( ! mSettings . checks . isEnabled ( Checks : : missingInclude ) & & ! mSettings . checkConfiguration )
return ;
2014-05-03 19:31:15 +02:00
const std : : string fname = Path : : fromNativeSeparators ( filename ) ;
2018-04-09 06:43:48 +02:00
Suppressions : : ErrorMessage errorMessage ;
errorMessage . errorId = " missingInclude " ;
errorMessage . setFileName ( fname ) ;
errorMessage . lineNumber = linenr ;
2018-06-16 16:10:28 +02:00
if ( mSettings . nomsg . isSuppressed ( errorMessage ) )
2014-05-03 19:31:15 +02:00
return ;
2018-04-09 06:43:48 +02:00
errorMessage . errorId = " missingIncludeSystem " ;
2018-06-16 16:10:28 +02:00
if ( headerType = = SystemHeader & & mSettings . nomsg . isSuppressed ( errorMessage ) )
2014-05-03 19:31:15 +02:00
return ;
2013-03-13 06:48:33 +01:00
2014-05-03 19:31:15 +02:00
if ( headerType = = SystemHeader )
missingSystemIncludeFlag = true ;
else
missingIncludeFlag = true ;
2022-07-09 23:21:11 +02:00
2018-06-16 16:10:28 +02:00
if ( mErrorLogger & & mSettings . checkConfiguration ) {
2014-05-03 19:31:15 +02:00
2020-05-23 07:16:49 +02:00
std : : list < ErrorMessage : : FileLocation > locationList ;
2014-05-03 19:31:15 +02:00
if ( ! filename . empty ( ) ) {
2020-05-23 07:16:49 +02:00
ErrorMessage : : FileLocation loc ;
2014-05-03 19:31:15 +02:00
loc . line = linenr ;
loc . setfile ( Path : : toNativeSeparators ( filename ) ) ;
locationList . push_back ( loc ) ;
}
2020-05-23 07:16:49 +02:00
ErrorMessage errmsg ( locationList , mFile0 , Severity : : information ,
( headerType = = SystemHeader ) ?
" Include file: < " + header + " > not found. Please note: Cppcheck does not need standard library headers to get proper results. " :
" Include file: \" " + header + " \" not found. " ,
( headerType = = SystemHeader ) ? " missingIncludeSystem " : " missingInclude " ,
2021-02-24 22:00:06 +01:00
Certainty : : normal ) ;
2018-06-16 16:10:28 +02:00
mErrorLogger - > reportInfo ( errmsg ) ;
2010-12-29 12:43:29 +01:00
}
}
2016-08-01 20:09:41 +02:00
bool Preprocessor : : validateCfg ( const std : : string & cfg , const std : : list < simplecpp : : MacroUsage > & macroUsageList )
2012-07-10 20:29:04 +02:00
{
2016-08-01 20:09:41 +02:00
bool ret = true ;
std : : list < std : : string > defines ;
2016-12-05 17:30:06 +01:00
splitcfg ( cfg , defines , emptyString ) ;
2018-07-15 15:03:08 +02:00
for ( const std : : string & define : defines ) {
if ( define . find ( ' = ' ) ! = std : : string : : npos )
2016-08-01 20:09:41 +02:00
continue ;
2018-07-15 15:03:08 +02:00
const std : : string macroName ( define . substr ( 0 , define . find ( ' ( ' ) ) ) ;
2018-06-17 08:40:25 +02:00
for ( const simplecpp : : MacroUsage & mu : macroUsageList ) {
2018-09-26 12:17:14 +02:00
if ( mu . macroValueKnown )
continue ;
2016-08-01 20:09:41 +02:00
if ( mu . macroName ! = macroName )
continue ;
2019-05-08 20:23:32 +02:00
bool directiveLocation = std : : any_of ( mDirectives . cbegin ( ) , mDirectives . cend ( ) ,
2021-08-07 20:51:18 +02:00
[ = ] ( const Directive & dir ) {
2019-05-08 20:23:32 +02:00
return mu . useLocation . file ( ) = = dir . file & & mu . useLocation . line = = dir . linenr ;
} ) ;
2016-08-01 20:09:41 +02:00
if ( ! directiveLocation ) {
2021-02-24 22:00:06 +01:00
if ( mSettings . severity . isEnabled ( Severity : : information ) )
2016-08-01 20:09:41 +02:00
validateCfgError ( mu . useLocation . file ( ) , mu . useLocation . line , cfg , macroName ) ;
ret = false ;
2012-07-11 18:29:33 +02:00
}
2012-07-10 20:29:04 +02:00
}
}
2016-08-01 20:09:41 +02:00
return ret ;
2012-07-10 20:29:04 +02:00
}
2016-08-01 20:09:41 +02:00
void Preprocessor : : validateCfgError ( const std : : string & file , const unsigned int line , const std : : string & cfg , const std : : string & macro )
2012-07-10 20:29:04 +02:00
{
const std : : string id = " ConfigurationNotChecked " ;
2020-05-23 07:16:49 +02:00
std : : list < ErrorMessage : : FileLocation > locationList ;
const ErrorMessage : : FileLocation loc ( file , line , 0 ) ;
2012-11-03 11:25:40 +01:00
locationList . push_back ( loc ) ;
2021-02-24 22:00:06 +01:00
const ErrorMessage errmsg ( locationList , mFile0 , Severity : : information , " Skipping configuration ' " + cfg + " ' since the value of ' " + macro + " ' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly. " , id , Certainty : : normal ) ;
2018-06-16 16:10:28 +02:00
mErrorLogger - > reportInfo ( errmsg ) ;
2012-07-10 20:29:04 +02:00
}
2010-12-29 12:43:29 +01:00
void Preprocessor : : getErrorMessages ( ErrorLogger * errorLogger , const Settings * settings )
2010-09-03 13:30:49 +02:00
{
2010-12-29 12:43:29 +01:00
Settings settings2 ( * settings ) ;
2015-07-24 13:30:41 +02:00
Preprocessor preprocessor ( settings2 , errorLogger ) ;
2019-01-12 19:11:44 +01:00
settings2 . checkConfiguration = true ;
2017-03-01 10:50:50 +01:00
preprocessor . missingInclude ( emptyString , 1 , emptyString , UserHeader ) ;
preprocessor . missingInclude ( emptyString , 1 , emptyString , SystemHeader ) ;
preprocessor . validateCfgError ( emptyString , 1 , " X " , " X " ) ;
preprocessor . error ( emptyString , 1 , " #error message " ) ; // #error ..
2010-09-03 13:30:49 +02:00
}
2015-12-07 19:54:41 +01:00
void Preprocessor : : dump ( std : : ostream & out ) const
{
2021-07-08 14:36:28 +02:00
// Create a xml dump.
2015-12-07 19:54:41 +01:00
2021-07-08 14:36:28 +02:00
out < < " <directivelist> " < < std : : endl ;
2018-06-17 08:45:45 +02:00
for ( const Directive & dir : mDirectives ) {
2015-12-07 19:54:41 +01:00
out < < " <directive "
2018-06-17 08:45:45 +02:00
< < " file= \" " < < ErrorLogger : : toxml ( dir . file ) < < " \" "
< < " linenr= \" " < < dir . linenr < < " \" "
2015-12-07 19:54:41 +01:00
// str might contain characters such as '"', '<' or '>' which
// could result in invalid XML, so run it through toxml().
2018-06-17 08:45:45 +02:00
< < " str= \" " < < ErrorLogger : : toxml ( dir . str ) < < " \" /> " < < std : : endl ;
2015-12-07 19:54:41 +01:00
}
out < < " </directivelist> " < < std : : endl ;
2021-07-08 14:36:28 +02:00
2021-07-08 16:53:25 +02:00
if ( ! mMacroUsage . empty ( ) ) {
out < < " <macro-usage> " < < std : : endl ;
for ( const simplecpp : : MacroUsage & macroUsage : mMacroUsage ) {
2021-07-22 08:46:28 +02:00
out < < " <macro "
2021-07-08 16:53:25 +02:00
< < " name= \" " < < macroUsage . macroName < < " \" "
< < " file= \" " < < macroUsage . macroLocation . file ( ) < < " \" "
< < " line= \" " < < macroUsage . macroLocation . line < < " \" "
< < " column= \" " < < macroUsage . macroLocation . col < < " \" "
< < " usefile= \" " < < macroUsage . useLocation . file ( ) < < " \" "
< < " useline= \" " < < macroUsage . useLocation . line < < " \" "
< < " usecolumn= \" " < < macroUsage . useLocation . col < < " \" "
2021-07-22 08:46:28 +02:00
< < " is-known-value= \" " < < ( macroUsage . macroValueKnown ? " true " : " false " ) < < " \" "
< < " /> " < < std : : endl ;
2021-07-08 16:53:25 +02:00
}
out < < " </macro-usage> " < < std : : endl ;
}
2021-07-22 08:46:28 +02:00
if ( ! mIfCond . empty ( ) ) {
out < < " <simplecpp-if-cond> " < < std : : endl ;
for ( const simplecpp : : IfCond & ifCond : mIfCond ) {
out < < " <if-cond "
< < " file= \" " < < ErrorLogger : : toxml ( ifCond . location . file ( ) ) < < " \" "
< < " line= \" " < < ifCond . location . line < < " \" "
< < " column= \" " < < ifCond . location . col < < " \" "
< < " E= \" " < < ErrorLogger : : toxml ( ifCond . E ) < < " \" "
< < " result= \" " < < ifCond . result < < " \" "
< < " /> " < < std : : endl ;
}
out < < " </simplecpp-if-cond> " < < std : : endl ;
}
2015-12-07 19:54:41 +01:00
}
2016-10-29 12:18:11 +02:00
2022-07-07 12:16:01 +02:00
std : : size_t Preprocessor : : calculateHash ( const simplecpp : : TokenList & tokens1 , const std : : string & toolinfo ) const
2016-10-29 15:35:31 +02:00
{
2022-07-07 12:16:01 +02:00
std : : string hashData = toolinfo ;
2016-10-29 12:18:11 +02:00
for ( const simplecpp : : Token * tok = tokens1 . cfront ( ) ; tok ; tok = tok - > next ) {
if ( ! tok - > comment )
2022-07-07 12:16:01 +02:00
hashData + = tok - > str ( ) ;
2016-10-29 12:18:11 +02:00
}
2018-06-17 08:58:56 +02:00
for ( std : : map < std : : string , simplecpp : : TokenList * > : : const_iterator it = mTokenLists . begin ( ) ; it ! = mTokenLists . end ( ) ; + + it ) {
2016-10-29 12:18:11 +02:00
for ( const simplecpp : : Token * tok = it - > second - > cfront ( ) ; tok ; tok = tok - > next ) {
if ( ! tok - > comment )
2022-07-07 12:16:01 +02:00
hashData + = tok - > str ( ) ;
2016-10-29 12:18:11 +02:00
}
}
2022-07-07 12:16:01 +02:00
return ( std : : hash < std : : string > { } ) ( hashData ) ;
2016-10-29 12:18:11 +02:00
}
2017-05-17 10:25:37 +02:00
2022-05-29 17:06:33 +02:00
void Preprocessor : : simplifyPragmaAsm ( simplecpp : : TokenList * tokenList ) const
2017-05-17 21:58:46 +02:00
{
Preprocessor : : simplifyPragmaAsmPrivate ( tokenList ) ;
2022-05-29 17:06:33 +02:00
for ( const std : : pair < const std : : string , simplecpp : : TokenList * > & list : mTokenLists ) {
2020-09-21 19:30:47 +02:00
Preprocessor : : simplifyPragmaAsmPrivate ( list . second ) ;
2017-05-17 21:58:46 +02:00
}
}
void Preprocessor : : simplifyPragmaAsmPrivate ( simplecpp : : TokenList * tokenList )
2017-05-17 10:25:37 +02:00
{
// assembler code..
for ( simplecpp : : Token * tok = tokenList - > front ( ) ; tok ; tok = tok - > next ) {
if ( tok - > op ! = ' # ' )
continue ;
if ( sameline ( tok , tok - > previousSkipComments ( ) ) )
continue ;
const simplecpp : : Token * const tok2 = tok - > nextSkipComments ( ) ;
2018-05-14 13:00:22 +02:00
if ( ! tok2 | | ! sameline ( tok , tok2 ) | | tok2 - > str ( ) ! = " pragma " )
2017-05-17 10:25:37 +02:00
continue ;
const simplecpp : : Token * const tok3 = tok2 - > nextSkipComments ( ) ;
2018-05-14 13:00:22 +02:00
if ( ! tok3 | | ! sameline ( tok , tok3 ) | | tok3 - > str ( ) ! = " asm " )
2017-05-17 10:25:37 +02:00
continue ;
const simplecpp : : Token * endasm = tok3 ;
2017-08-09 20:00:26 +02:00
while ( ( endasm = endasm - > next ) ! = nullptr ) {
2017-05-17 10:25:37 +02:00
if ( endasm - > op ! = ' # ' | | sameline ( endasm , endasm - > previousSkipComments ( ) ) )
continue ;
const simplecpp : : Token * const endasm2 = endasm - > nextSkipComments ( ) ;
2018-05-14 13:00:22 +02:00
if ( ! endasm2 | | ! sameline ( endasm , endasm2 ) | | endasm2 - > str ( ) ! = " pragma " )
2017-05-17 10:25:37 +02:00
continue ;
const simplecpp : : Token * const endasm3 = endasm2 - > nextSkipComments ( ) ;
2018-05-14 13:00:22 +02:00
if ( ! endasm3 | | ! sameline ( endasm2 , endasm3 ) | | endasm3 - > str ( ) ! = " endasm " )
2017-05-17 10:25:37 +02:00
continue ;
while ( sameline ( endasm , endasm3 ) )
endasm = endasm - > next ;
break ;
}
const simplecpp : : Token * const tok4 = tok3 - > next ;
tok - > setstr ( " asm " ) ;
const_cast < simplecpp : : Token * > ( tok2 ) - > setstr ( " ( " ) ;
const_cast < simplecpp : : Token * > ( tok3 ) - > setstr ( " ) " ) ;
const_cast < simplecpp : : Token * > ( tok4 ) - > setstr ( " ; " ) ;
while ( tok4 - > next ! = endasm )
tokenList - > deleteToken ( tok4 - > next ) ;
}
}