diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/cbasetypes.h | 4 | ||||
-rw-r--r-- | src/map/script.c | 89 |
2 files changed, 69 insertions, 24 deletions
diff --git a/src/common/cbasetypes.h b/src/common/cbasetypes.h index 0b5613316..3ca0c5f67 100644 --- a/src/common/cbasetypes.h +++ b/src/common/cbasetypes.h @@ -410,13 +410,15 @@ typedef char bool; #define ISALPHA(c) (isalpha((unsigned char)(c))) #define ISCNTRL(c) (iscntrl((unsigned char)(c))) #define ISDIGIT(c) (isdigit((unsigned char)(c))) +#define ISXDIGIT(c) (isxdigit((unsigned char)(c))) +#define ISBDIGIT(c) ((unsigned char)(c) == '0' || (unsigned char)(c) == '1') +#define ISODIGIT(c) ((unsigned char)(c) >= '0' && (unsigned char)(c) <= '7') #define ISGRAPH(c) (isgraph((unsigned char)(c))) #define ISLOWER(c) (islower((unsigned char)(c))) #define ISPRINT(c) (isprint((unsigned char)(c))) #define ISPUNCT(c) (ispunct((unsigned char)(c))) #define ISSPACE(c) (isspace((unsigned char)(c))) #define ISUPPER(c) (isupper((unsigned char)(c))) -#define ISXDIGIT(c) (isxdigit((unsigned char)(c))) #define TOASCII(c) (toascii((unsigned char)(c))) #define TOLOWER(c) (tolower((unsigned char)(c))) #define TOUPPER(c) (toupper((unsigned char)(c))) diff --git a/src/map/script.c b/src/map/script.c index b8a7979a7..d5e73ad65 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -1161,6 +1161,41 @@ static const char *parse_variable(const char *p) return p; } +/** + * converts a number expression literal to an actual integer +*/ +static long long parse_number(const char *p, char **np) { + long long lli = 0; + unsigned char radix = 10; + + nullpo_retr(lli, p); + + if (*p == '0' && p[1] == 'x') { + p += 2; + radix = 16; // hexadecimal + } else if (*p == '0' && p[1] == 'o') { + p += 2; + radix = 8; // octal + } else if (*p == '0' && p[1] == 'b') { + p += 2; + radix = 2; // binary + } + + // actual parsing happens here + lli = strtoll(p, np, radix); + + // make sure we can't underflow/overflow + if (lli < INT_MIN) { + lli = INT_MIN; + script->disp_warning_message("parse_number: underflow detected, capping value to INT_MIN", p); + } else if (lli > INT_MAX) { + lli = INT_MAX; + script->disp_warning_message("parse_number: overflow detected, capping value to INT_MAX", p); + } + + return lli; +} + /* * Checks whether the gives string is a number literal * @@ -1177,24 +1212,44 @@ static const char *parse_variable(const char *p) static bool is_number(const char *p) { const char *np; - if (!p) - return false; - if (*p == '-' || *p == '+') + nullpo_retr(false, p); + + if (*p == '-' || *p == '+') { p++; + } + np = p; + if (*p == '0' && p[1] == 'x') { - p+=2; - np = p; - // Hexadecimal - while (ISXDIGIT(*np)) + // Hexadecimal: 0xFFFF + np = p += 2; + while (ISXDIGIT(*np)) { np++; + } + } else if (*p == '0' && p[1] == 'b') { + // Binary: 0b0001 + np = p += 2; + while (ISBDIGIT(*np)) { + np++; + } + } else if (*p == '0' && p[1] == 'o') { + // Octal: 0o1500 + np = p += 2; + while (ISODIGIT(*np)) { + np++; + } } else { - // Decimal - while (ISDIGIT(*np)) + // Decimal: 1234 + while (ISDIGIT(*np)) { np++; + } } - if (p != np && *np != '_' && !ISALPHA(*np)) // At least one digit, and next isn't a letter or _ + + if (p != np && *np != '_' && !ISALPHA(*np)) { + // At least one digit, and next isn't a letter or _ return true; + } + return false; } @@ -1276,20 +1331,8 @@ static const char *parse_simpleexpr_paren(const char *p) static const char *parse_simpleexpr_number(const char *p) { char *np = NULL; - long long lli; + long long lli = parse_number(p, &np); - nullpo_retr(NULL, p); - while (*p == '0' && ISDIGIT(p[1])) - p++; // Skip leading zeros, we don't support octal literals - - lli = strtoll(p, &np, 0); - if (lli < INT_MIN) { - lli = INT_MIN; - script->disp_warning_message("parse_simpleexpr: underflow detected, capping value to INT_MIN", p); - } else if (lli > INT_MAX) { - lli = INT_MAX; - script->disp_warning_message("parse_simpleexpr: overflow detected, capping value to INT_MAX", p); - } script->addi((int)lli); // Cast is safe, as it's already been checked for overflows return np; |