From 2191b0d32a59c5f73cadfb30ca473f64e4dfa285 Mon Sep 17 00:00:00 2001 From: firewave Date: Wed, 5 Nov 2025 15:48:20 +0100 Subject: [PATCH] fixed #504 / refs #507 - cleaned up and improved parsing of line preprocessor directive --- simplecpp.cpp | 70 ++++++++++++++++++++++++++------------------------- test.cpp | 15 ++++++++++- 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index dcc534ba..0152a375 100644 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -696,42 +696,44 @@ void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename, if (oldLastToken != cback()) { oldLastToken = cback(); - const Token * const llTok = isLastLinePreprocessor(); - if (!llTok) + + // #line 3 + // #line 3 "file.c" + // #3 + // #3 "file.c" + const Token * ppTok = isLastLinePreprocessor(); + if (!ppTok) continue; - const Token * const llNextToken = llTok->next; - if (!llTok->next) + + const auto advanceAndSkipComments = [](const Token* tok) { + do { + tok = tok->next; + } while (tok && tok->comment); + return tok; + }; + + // skip # + ppTok = advanceAndSkipComments(ppTok); + if (!ppTok) continue; - if (llNextToken->next) { - // TODO: add support for "# 3" - // #3 "file.c" - // #line 3 "file.c" - if ((llNextToken->number && - llNextToken->next->str()[0] == '\"') || - (llNextToken->str() == "line" && - llNextToken->next->number && - llNextToken->next->next && - llNextToken->next->next->str()[0] == '\"')) - { - const Token *strtok = cback(); - while (strtok->comment) - strtok = strtok->previous; - const Token *numtok = strtok->previous; - while (numtok->comment) - numtok = numtok->previous; - lineDirective(fileIndex(replaceAll(strtok->str().substr(1U, strtok->str().size() - 2U),"\\\\","\\")), - std::atol(numtok->str().c_str()), location); - } - // #line 3 - else if (llNextToken->str() == "line" && - llNextToken->next->number) - { - const Token *numtok = cback(); - while (numtok->comment) - numtok = numtok->previous; - lineDirective(location.fileIndex, std::atol(numtok->str().c_str()), location); - } - } + + if (ppTok->str() == "line") + ppTok = advanceAndSkipComments(ppTok); + + if (!ppTok || !ppTok->number) + continue; + + const unsigned int line = std::atol(ppTok->str().c_str()); + ppTok = advanceAndSkipComments(ppTok); + + unsigned int fileindex; + + if (ppTok && ppTok->str()[0] == '\"') + fileindex = fileIndex(replaceAll(ppTok->str().substr(1U, ppTok->str().size() - 2U),"\\\\","\\")); + else + fileindex = location.fileIndex; + + lineDirective(fileindex, line, location); } continue; diff --git a/test.cpp b/test.cpp index bebc535d..603d596d 100644 --- a/test.cpp +++ b/test.cpp @@ -2413,7 +2413,8 @@ static void location8() "# 3\n" "__LINE__ __FILE__\n"; ASSERT_EQUALS("\n" - "2 \"\"", // TODO: should say 3 + "\n" + "3 \"\"", preprocess(code)); } @@ -2454,6 +2455,17 @@ static void location11() preprocess(code)); } +static void location12() +{ + const char code[] = + "/**//**/#/**//**/line/**//**/3/**//**/\"file.c\"/**/\n" + "__LINE__ __FILE__\n"; + ASSERT_EQUALS("\n" + "#line 3 \"file.c\"\n" + "3 \"file.c\"", + preprocess(code)); +} + static void missingHeader1() { const char code[] = "#include \"notexist.h\"\n"; @@ -4060,6 +4072,7 @@ static void runTests(int argc, char **argv, Input input) TEST_CASE(location9); TEST_CASE(location10); TEST_CASE(location11); + TEST_CASE(location12); TEST_CASE(missingHeader1); TEST_CASE(missingHeader2);