mirror of
https://github.com/gbdev/rgbds.git
synced 2026-06-14 12:42:11 +00:00
Handle more numeric literal syntax errors in linker scripts
This commit is contained in:
+37
-30
@@ -97,27 +97,39 @@ static std::string readKeyword(int initial) {
|
|||||||
|
|
||||||
template<uint32_t Base>
|
template<uint32_t Base>
|
||||||
requires ValidBaseV<Base>
|
requires ValidBaseV<Base>
|
||||||
static yy::parser::symbol_type readNumber(int initial, char const *prefix, char const *name) {
|
static yy::parser::symbol_type readNumber(int initial, char const *prefix) {
|
||||||
LexerStackEntry &context = lexerStack.back();
|
LexerStackEntry &context = lexerStack.back();
|
||||||
|
|
||||||
uint32_t number;
|
uint32_t number;
|
||||||
|
bool empty;
|
||||||
if constexpr (Base == 10) {
|
if constexpr (Base == 10) {
|
||||||
assume(prefix == nullptr && name == nullptr);
|
assume(prefix == nullptr);
|
||||||
number = parseDigit<Base>(initial);
|
number = parseDigit<Base>(initial);
|
||||||
|
empty = false;
|
||||||
} else {
|
} else {
|
||||||
assume(initial == 0 && prefix != nullptr && name != nullptr);
|
assume(initial == 0 && prefix != nullptr);
|
||||||
int c = context.file.sgetc();
|
number = 0;
|
||||||
if (!isDigit<Base>(c)) {
|
empty = true;
|
||||||
scriptError("No %s digits found after %s", name, prefix);
|
|
||||||
return yy::parser::make_number(0);
|
|
||||||
}
|
|
||||||
number = parseDigit<Base>(c);
|
|
||||||
context.file.sbumpc();
|
|
||||||
}
|
}
|
||||||
for (int c = context.file.sgetc(); isDigit<Base>(c) || c == '_'; c = context.file.snextc()) {
|
|
||||||
|
bool prevWasSeparator = false;
|
||||||
|
|
||||||
|
for (int c = context.file.sgetc();; c = context.file.snextc()) {
|
||||||
if (c == '_') {
|
if (c == '_') {
|
||||||
|
if (prevWasSeparator) {
|
||||||
|
scriptError("Invalid integer constant, '_' after another '_'");
|
||||||
|
}
|
||||||
|
prevWasSeparator = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isDigit<Base>(c)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
uint32_t digit = parseDigit<Base>(c);
|
uint32_t digit = parseDigit<Base>(c);
|
||||||
|
empty = false;
|
||||||
|
prevWasSeparator = false;
|
||||||
|
|
||||||
if (number > (UINT32_MAX - digit) / Base) {
|
if (number > (UINT32_MAX - digit) / Base) {
|
||||||
scriptWarning(WARNING_LARGE_CONSTANT, "Integer constant is too large");
|
scriptWarning(WARNING_LARGE_CONSTANT, "Integer constant is too large");
|
||||||
// Discard any additional digits
|
// Discard any additional digits
|
||||||
@@ -127,21 +139,16 @@ static yy::parser::symbol_type readNumber(int initial, char const *prefix, char
|
|||||||
}
|
}
|
||||||
number = number * Base + digit;
|
number = number * Base + digit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (empty) {
|
||||||
|
scriptError("Invalid integer constant, no digits after %s", prefix);
|
||||||
|
}
|
||||||
|
if (prevWasSeparator) {
|
||||||
|
scriptError("Invalid integer constant, trailing '_'");
|
||||||
|
}
|
||||||
return yy::parser::make_number(number);
|
return yy::parser::make_number(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
static yy::parser::symbol_type parseBinNumber(char const *prefix) {
|
|
||||||
return readNumber<2>(0, prefix, "binary");
|
|
||||||
}
|
|
||||||
|
|
||||||
static yy::parser::symbol_type parseOctNumber(char const *prefix) {
|
|
||||||
return readNumber<8>(0, prefix, "octal");
|
|
||||||
}
|
|
||||||
|
|
||||||
static yy::parser::symbol_type parseHexNumber(char const *prefix) {
|
|
||||||
return readNumber<16>(0, prefix, "hexadecimal");
|
|
||||||
}
|
|
||||||
|
|
||||||
static yy::parser::symbol_type parseAnyNumber(int initial) {
|
static yy::parser::symbol_type parseAnyNumber(int initial) {
|
||||||
LexerStackEntry &context = lexerStack.back();
|
LexerStackEntry &context = lexerStack.back();
|
||||||
if (initial == '0') {
|
if (initial == '0') {
|
||||||
@@ -149,18 +156,18 @@ static yy::parser::symbol_type parseAnyNumber(int initial) {
|
|||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
context.file.sbumpc();
|
context.file.sbumpc();
|
||||||
return parseHexNumber("\"0x\"");
|
return readNumber<16>(0, "\"0x\"");
|
||||||
case 'o':
|
case 'o':
|
||||||
case 'O':
|
case 'O':
|
||||||
context.file.sbumpc();
|
context.file.sbumpc();
|
||||||
return parseOctNumber("\"0o\"");
|
return readNumber<8>(0, "\"0o\"");
|
||||||
case 'b':
|
case 'b':
|
||||||
case 'B':
|
case 'B':
|
||||||
context.file.sbumpc();
|
context.file.sbumpc();
|
||||||
return parseBinNumber("\"0b\"");
|
return readNumber<2>(0, "\"0b\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return readNumber<10>(initial, nullptr, nullptr);
|
return readNumber<10>(initial, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static yy::parser::symbol_type parseString() {
|
static yy::parser::symbol_type parseString() {
|
||||||
@@ -226,11 +233,11 @@ yy::parser::symbol_type yylex() {
|
|||||||
} else if (c == '"') {
|
} else if (c == '"') {
|
||||||
return parseString();
|
return parseString();
|
||||||
} else if (c == '$') {
|
} else if (c == '$') {
|
||||||
return parseHexNumber("'$'");
|
return readNumber<16>(0, "'$'");
|
||||||
} else if (c == '%') {
|
} else if (c == '%') {
|
||||||
return parseBinNumber("'%'");
|
return readNumber<2>(0, "'%'");
|
||||||
} else if (c == '&') {
|
} else if (c == '&') {
|
||||||
return parseOctNumber("'&'");
|
return readNumber<8>(0, "'&'");
|
||||||
} else if (isDigit<10>(c)) {
|
} else if (isDigit<10>(c)) {
|
||||||
return parseAnyNumber(c);
|
return parseAnyNumber(c);
|
||||||
} else if (isLetter(c)) {
|
} else if (isLetter(c)) {
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
error: No hexadecimal digits found after '$'
|
error: Invalid integer constant, no digits after '$'
|
||||||
at script-lone-dollar.link(1)
|
at script-lone-dollar.link(1)
|
||||||
Linking failed with 1 error
|
Linking failed with 1 error
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
error: No binary digits found after '%'
|
error: Invalid integer constant, no digits after '%'
|
||||||
at script-lone-percent.link(1)
|
at script-lone-percent.link(1)
|
||||||
Linking failed with 1 error
|
Linking failed with 1 error
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
ROM0
|
ROM0
|
||||||
org 4_2
|
org 4_2
|
||||||
org %10_10_10
|
org %10_10_10
|
||||||
org &52_
|
org &52_ ; trailing '_'
|
||||||
org $2A_
|
org $2A_ ; trailing '_'
|
||||||
org 0b101_010
|
org 0b101__010 ; '_' after another '_'
|
||||||
org 0o5_2
|
org 0o__5_2 ; '_' after another '_'
|
||||||
org 0x2_A
|
org 0x2_A
|
||||||
org 41 ; Error!
|
org 41 ; different value
|
||||||
|
org %_ ; no digits
|
||||||
|
org 0x__ ; no digits
|
||||||
|
|||||||
@@ -1,3 +1,25 @@
|
|||||||
|
error: Invalid integer constant, trailing '_'
|
||||||
|
at script-num-fmt.link(4)
|
||||||
|
error: Invalid integer constant, trailing '_'
|
||||||
|
at script-num-fmt.link(5)
|
||||||
|
error: Invalid integer constant, '_' after another '_'
|
||||||
|
at script-num-fmt.link(6)
|
||||||
|
error: Invalid integer constant, '_' after another '_'
|
||||||
|
at script-num-fmt.link(7)
|
||||||
error: Cannot decrease the current address (from $002a to $0029)
|
error: Cannot decrease the current address (from $002a to $0029)
|
||||||
at script-num-fmt.link(9)
|
at script-num-fmt.link(9)
|
||||||
Linking failed with 1 error
|
error: Invalid integer constant, no digits after '%'
|
||||||
|
at script-num-fmt.link(10)
|
||||||
|
error: Invalid integer constant, trailing '_'
|
||||||
|
at script-num-fmt.link(10)
|
||||||
|
error: Cannot decrease the current address (from $002a to $0000)
|
||||||
|
at script-num-fmt.link(10)
|
||||||
|
error: Invalid integer constant, '_' after another '_'
|
||||||
|
at script-num-fmt.link(11)
|
||||||
|
error: Invalid integer constant, no digits after "0x"
|
||||||
|
at script-num-fmt.link(11)
|
||||||
|
error: Invalid integer constant, trailing '_'
|
||||||
|
at script-num-fmt.link(11)
|
||||||
|
error: Cannot decrease the current address (from $002a to $0000)
|
||||||
|
at script-num-fmt.link(11)
|
||||||
|
Linking failed with 12 errors
|
||||||
|
|||||||
Reference in New Issue
Block a user