diff --git a/include/util.hpp b/include/util.hpp index 46ab672c..5abd7d57 100644 --- a/include/util.hpp +++ b/include/util.hpp @@ -4,7 +4,6 @@ #define RGBDS_UTIL_HPP #include -#include // toupper #include #include #include @@ -22,6 +21,7 @@ enum NumberBase { BASE_16 = 16, }; +// Locale-independent character class functions bool isNewline(int c); bool isBlankSpace(int c); bool isWhitespace(int c); @@ -35,6 +35,10 @@ bool isOctDigit(int c); bool isHexDigit(int c); bool isAlphanumeric(int c); +// Locale-independent character transform functions +char toLower(char c); +char toUpper(char c); + bool startsIdentifier(int c); bool continuesIdentifier(int c); @@ -48,14 +52,14 @@ struct Uppercase { // FNV-1a hash of an uppercased string constexpr size_t operator()(std::string const &str) const { return std::accumulate(RANGE(str), 0x811C9DC5, [](size_t hash, char c) { - return (hash ^ toupper(c)) * 16777619; + return (hash ^ toUpper(c)) * 16777619; }); } // Compare two strings without case-sensitivity (by converting to uppercase) constexpr bool operator()(std::string const &str1, std::string const &str2) const { return std::equal(RANGE(str1), RANGE(str2), [](char c1, char c2) { - return toupper(c1) == toupper(c2); + return toUpper(c1) == toUpper(c2); }); } }; diff --git a/src/asm/parser.y b/src/asm/parser.y index 8bf7ceef..1e3f509c 100644 --- a/src/asm/parser.y +++ b/src/asm/parser.y @@ -32,7 +32,6 @@ %code { #include - #include #include #include #include @@ -42,6 +41,7 @@ #include "extern/utf8decoder.hpp" #include "helpers.hpp" + #include "util.hpp" // toLower, toUpper #include "asm/charmap.hpp" #include "asm/fixpoint.hpp" @@ -1599,11 +1599,11 @@ string_literal: } | OP_STRUPR LPAREN string RPAREN { $$ = std::move($3); - std::transform(RANGE($$), $$.begin(), [](char c) { return toupper(c); }); + std::transform(RANGE($$), $$.begin(), toUpper); } | OP_STRLWR LPAREN string RPAREN { $$ = std::move($3); - std::transform(RANGE($$), $$.begin(), [](char c) { return tolower(c); }); + std::transform(RANGE($$), $$.begin(), toLower); } | OP_STRRPL LPAREN string COMMA string COMMA string RPAREN { $$ = act_StringReplace($3, $5, $7); diff --git a/src/fix/mbc.cpp b/src/fix/mbc.cpp index b21ec94f..219be9c2 100644 --- a/src/fix/mbc.cpp +++ b/src/fix/mbc.cpp @@ -12,7 +12,7 @@ #include "helpers.hpp" // unreachable_ #include "platform.hpp" // strcasecmp -#include "util.hpp" // isBlankSpace, isLower, isDigit +#include "util.hpp" #include "fix/warning.hpp" @@ -103,12 +103,10 @@ static void skipMBCSpace(char const *&ptr) { } static char normalizeMBCChar(char c) { - if (isLower(c)) { - c = c - 'a' + 'A'; // Uppercase for comparison with `mbc_Name`s - } else if (c == '_') { - c = ' '; // Treat underscores as spaces + if (c == '_') { + return ' '; // Treat underscores as spaces } - return c; + return toUpper(c); // Uppercase for comparison with `mbc_Name`s } [[noreturn]] diff --git a/src/util.cpp b/src/util.cpp index 24bf6f5a..514c172f 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -58,6 +58,14 @@ bool isAlphanumeric(int c) { return isLetter(c) || isDigit(c); } +char toLower(char c) { + return isUpper(c) ? c - 'A' + 'a' : c; +} + +char toUpper(char c) { + return isLower(c) ? c - 'a' + 'A' : c; +} + bool startsIdentifier(int c) { // This returns false for anonymous labels, which internally start with a '!', // and for section fragment literal labels, which internally start with a '$'.