diff --git a/simplecpp.cpp b/simplecpp.cpp index babf611..928e123 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -886,7 +886,7 @@ void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename, } if (prefix.empty()) - push_back(new Token(s, location)); // push string without newlines + push_back(new Token(s, location, isspace(stream.peekChar()))); // push string without newlines else back()->setstr(prefix + s); @@ -916,7 +916,7 @@ void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename, } } - push_back(new Token(currentToken, location)); + push_back(new Token(currentToken, location, isspace(stream.peekChar()))); if (multiline) location.col += currentToken.size(); @@ -1546,9 +1546,9 @@ namespace simplecpp { // Copy macro call to a new tokenlist with no linebreaks const Token * const rawtok1 = rawtok; TokenList rawtokens2(inputFiles); - rawtokens2.push_back(new Token(rawtok->str(), rawtok1->location)); + rawtokens2.push_back(new Token(rawtok->str(), rawtok1->location, rawtok->whitespaceahead)); rawtok = rawtok->next; - rawtokens2.push_back(new Token(rawtok->str(), rawtok1->location)); + rawtokens2.push_back(new Token(rawtok->str(), rawtok1->location, rawtok->whitespaceahead)); rawtok = rawtok->next; int par = 1; while (rawtok && par > 0) { @@ -1558,7 +1558,7 @@ namespace simplecpp { --par; else if (rawtok->op == '#' && !sameline(rawtok->previous, rawtok)) throw Error(rawtok->location, "it is invalid to use a preprocessor directive as macro parameter"); - rawtokens2.push_back(new Token(rawtok->str(), rawtok1->location)); + rawtokens2.push_back(new Token(rawtok->str(), rawtok1->location, rawtok->whitespaceahead)); rawtok = rawtok->next; } if (expand(&output2, rawtok1->location, rawtokens2.cfront(), macros, expandedmacros)) @@ -2128,6 +2128,8 @@ namespace simplecpp { partok = partok->next; } } + if (tok->whitespaceahead && output->back()) + output->back()->whitespaceahead = true; return true; } @@ -2146,8 +2148,12 @@ namespace simplecpp { tok = expandToken(&tokenListHash, loc, tok->next, macros2, expandedmacros, parametertokens); std::ostringstream ostr; ostr << '\"'; - for (const Token *hashtok = tokenListHash.cfront(); hashtok; hashtok = hashtok->next) + for (const Token *hashtok = tokenListHash.cfront(), *next; hashtok; hashtok = next) { + next = hashtok->next; ostr << hashtok->str(); + if (next && hashtok->whitespaceahead) + ostr << ' '; + } ostr << '\"'; output->push_back(newMacroToken(escapeString(ostr.str()), loc, isReplaced(expandedmacros))); return tok; diff --git a/simplecpp.h b/simplecpp.h index 88a1401..672f29a 100755 --- a/simplecpp.h +++ b/simplecpp.h @@ -94,13 +94,13 @@ namespace simplecpp { */ class SIMPLECPP_LIB Token { public: - Token(const TokenString &s, const Location &loc) : - location(loc), previous(nullptr), next(nullptr), string(s) { + Token(const TokenString &s, const Location &loc, bool wsahead = false) : + whitespaceahead(wsahead), location(loc), previous(nullptr), next(nullptr), string(s) { flags(); } Token(const Token &tok) : - macro(tok.macro), op(tok.op), comment(tok.comment), name(tok.name), number(tok.number), location(tok.location), previous(nullptr), next(nullptr), string(tok.string), mExpandedFrom(tok.mExpandedFrom) { + macro(tok.macro), op(tok.op), comment(tok.comment), name(tok.name), number(tok.number), whitespaceahead(tok.whitespaceahead), location(tok.location), previous(nullptr), next(nullptr), string(tok.string), mExpandedFrom(tok.mExpandedFrom) { } void flags() { @@ -132,6 +132,7 @@ namespace simplecpp { bool comment; bool name; bool number; + bool whitespaceahead; Location location; Token *previous; Token *next; @@ -153,6 +154,8 @@ namespace simplecpp { void setExpandedFrom(const Token *tok, const Macro* m) { mExpandedFrom = tok->mExpandedFrom; mExpandedFrom.insert(m); + if (tok->whitespaceahead) + whitespaceahead = true; } bool isExpandedFrom(const Macro* m) const { return mExpandedFrom.find(m) != mExpandedFrom.end(); diff --git a/test.cpp b/test.cpp index e6210ec..1e42fad 100644 --- a/test.cpp +++ b/test.cpp @@ -47,7 +47,7 @@ static int assertEquals(const std::string &expected, const std::string &actual, return (expected == actual); } -static int assertEquals(const unsigned int &expected, const unsigned int &actual, int line) +static int assertEquals(const long long &expected, const long long &actual, int line) { return assertEquals(std::to_string(expected), std::to_string(actual), line); } @@ -1038,6 +1038,12 @@ static void hash() preprocess("#define bar(x) x % 2\n" "#define foo(x) printf(#x \"\\n\")\n" "foo(bar(3));")); + + ASSERT_EQUALS("\n\n\n\"Y Y\"", + preprocess("#define X(x,y) x y\n" + "#define STR_(x) #x\n" + "#define STR(x) STR_(x)\n" + "STR(X(Y,Y))")); } static void hashhash1() // #4703