Skip to content

Commit 6d53bc4

Browse files
committed
Simplify toggling of enabling/disabling expansions
1 parent 32b5ef5 commit 6d53bc4

File tree

2 files changed

+28
-36
lines changed

2 files changed

+28
-36
lines changed

include/asm/lexer.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,8 @@ struct LexerState {
9292
size_t captureSize; // Amount of text captured
9393
std::shared_ptr<std::vector<char>> captureBuf; // Buffer to send the captured text to if set
9494

95-
bool disableMacroArgs;
96-
bool disableInterpolation;
97-
size_t macroArgScanDistance; // Max distance already scanned for macro args
95+
bool disableExpansions;
96+
size_t expansionScanDistance; // Max distance already scanned for expansions
9897
bool expandStrings;
9998
std::deque<Expansion> expansions; // Front is the innermost current expansion
10099

src/asm/lexer.cpp

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -272,9 +272,8 @@ void LexerState::clear(uint32_t lineNo_) {
272272
capturing = false;
273273
captureBuf = nullptr;
274274

275-
disableMacroArgs = false;
276-
disableInterpolation = false;
277-
macroArgScanDistance = 0;
275+
disableExpansions = false;
276+
expansionScanDistance = 0;
278277
expandStrings = true;
279278

280279
expansions.clear();
@@ -517,13 +516,10 @@ static int nextChar();
517516
static uint32_t readDecimalNumber(int initial);
518517

519518
static uint32_t readBracketedMacroArgNum() {
520-
bool disableMacroArgs = lexerState->disableMacroArgs;
521-
bool disableInterpolation = lexerState->disableInterpolation;
522-
lexerState->disableMacroArgs = false;
523-
lexerState->disableInterpolation = false;
519+
bool disableExpansions = lexerState->disableExpansions;
520+
lexerState->disableExpansions = false;
524521
Defer restoreExpansions{[&] {
525-
lexerState->disableMacroArgs = disableMacroArgs;
526-
lexerState->disableInterpolation = disableInterpolation;
522+
lexerState->disableExpansions = disableExpansions;
527523
}};
528524

529525
int32_t num = 0;
@@ -713,15 +709,17 @@ static std::shared_ptr<std::string> readInterpolation(size_t depth);
713709
static int peek() {
714710
int c = lexerState->peekChar();
715711

716-
if (lexerState->macroArgScanDistance > 0) {
712+
if (lexerState->expansionScanDistance > 0) {
717713
return c;
718714
}
719715

720-
++lexerState->macroArgScanDistance; // Do not consider again
716+
++lexerState->expansionScanDistance; // Do not consider again
721717

722-
if (c == '\\' && !lexerState->disableMacroArgs) {
718+
if (lexerState->disableExpansions) {
719+
return c;
720+
} else if (c == '\\') {
723721
// If character is a backslash, check for a macro arg
724-
++lexerState->macroArgScanDistance;
722+
++lexerState->expansionScanDistance;
725723
if (!isMacroChar(lexerState->peekCharAhead())) {
726724
return c;
727725
}
@@ -734,11 +732,11 @@ static int peek() {
734732
// Mark the entire macro arg expansion as "painted blue"
735733
// so that macro args can't be recursive
736734
// https://en.wikipedia.org/wiki/Painted_blue
737-
lexerState->macroArgScanDistance += str->length();
735+
lexerState->expansionScanDistance += str->length();
738736
}
739737

740738
return peek(); // Tail recursion
741-
} else if (c == '{' && !lexerState->disableInterpolation) {
739+
} else if (c == '{') {
742740
// If character is an open brace, do symbol interpolation
743741
shiftChar();
744742
if (std::shared_ptr<std::string> str = readInterpolation(0); str) {
@@ -759,7 +757,7 @@ static void shiftChar() {
759757
++lexerState->captureSize;
760758
}
761759

762-
--lexerState->macroArgScanDistance;
760+
--lexerState->expansionScanDistance;
763761

764762
for (;;) {
765763
if (!lexerState->expansions.empty()) {
@@ -811,11 +809,9 @@ static void handleCRLF(int c) {
811809
}
812810

813811
static auto scopedDisableExpansions() {
814-
lexerState->disableMacroArgs = true;
815-
lexerState->disableInterpolation = true;
812+
lexerState->disableExpansions = true;
816813
return Defer{[&] {
817-
lexerState->disableMacroArgs = false;
818-
lexerState->disableInterpolation = false;
814+
lexerState->disableExpansions = false;
819815
}};
820816
}
821817

@@ -1217,21 +1213,19 @@ static std::shared_ptr<std::string> readInterpolation(size_t depth) {
12171213
std::string fmtBuf;
12181214
FormatSpec fmt{};
12191215

1220-
// In a context where `lexerState->disableInterpolation` is true, `peek` will expand
1221-
// nested interpolations itself, which can lead to stack overflow. This lets
1222-
// `readInterpolation` handle its own nested expansions, increasing `depth` each time.
1223-
bool disableInterpolation = lexerState->disableInterpolation;
1224-
lexerState->disableInterpolation = true;
1225-
1226-
// Reset `lexerState->disableInterpolation` when exiting this loop
1227-
for (Defer reset{[&] { lexerState->disableInterpolation = disableInterpolation; }};;) {
1228-
if (int c = peek(); c == '{') { // Nested interpolation
1216+
for (;;) {
1217+
// If `lexerState->disableExpansions` is false, `peek()` will expand nested interpolations
1218+
// and recursively call `readInterpolation()`, which can cause stack overflow.
1219+
// `lexerState->peekChar()` lets `readInterpolation()` handle its own nested expansions,
1220+
// increasing `depth` each time.
1221+
if (lexerState->peekChar() == '{') {
1222+
++lexerState->expansionScanDistance; // Prevent `shiftChar()` from calling `peek()`
12291223
shiftChar();
12301224
if (std::shared_ptr<std::string> str = readInterpolation(depth + 1); str) {
12311225
beginExpansion(str, *str);
12321226
}
12331227
continue; // Restart, reading from the new buffer
1234-
} else if (c == EOF || c == '\r' || c == '\n' || c == '"') {
1228+
} else if (int c = peek(); c == EOF || c == '\r' || c == '\n' || c == '"') {
12351229
error("Missing }");
12361230
break;
12371231
} else if (c == '}') {
@@ -1329,12 +1323,11 @@ static void appendCharInLiteral(std::string &str, int c) {
13291323
// Symbol interpolation
13301324
if (c == '{') {
13311325
// We'll be exiting the string/character scope, so re-enable expansions
1332-
// (Not interpolations, since they're handled by the function itself...)
1333-
lexerState->disableMacroArgs = false;
1326+
lexerState->disableExpansions = false;
13341327
if (std::shared_ptr<std::string> interpolation = readInterpolation(0); interpolation) {
13351328
appendExpandedString(str, *interpolation);
13361329
}
1337-
lexerState->disableMacroArgs = true;
1330+
lexerState->disableExpansions = true;
13381331
return;
13391332
}
13401333

0 commit comments

Comments
 (0)