Replace all ctype.h functions with locale-independent ones

This commit is contained in:
Rangi
2025-10-03 12:52:24 -04:00
parent 268b586c9d
commit 13e85b5151
4 changed files with 22 additions and 12 deletions

View File

@@ -4,7 +4,6 @@
#define RGBDS_UTIL_HPP #define RGBDS_UTIL_HPP
#include <algorithm> #include <algorithm>
#include <ctype.h> // toupper
#include <numeric> #include <numeric>
#include <optional> #include <optional>
#include <stddef.h> #include <stddef.h>
@@ -22,6 +21,7 @@ enum NumberBase {
BASE_16 = 16, BASE_16 = 16,
}; };
// Locale-independent character class functions
bool isNewline(int c); bool isNewline(int c);
bool isBlankSpace(int c); bool isBlankSpace(int c);
bool isWhitespace(int c); bool isWhitespace(int c);
@@ -35,6 +35,10 @@ bool isOctDigit(int c);
bool isHexDigit(int c); bool isHexDigit(int c);
bool isAlphanumeric(int c); bool isAlphanumeric(int c);
// Locale-independent character transform functions
char toLower(char c);
char toUpper(char c);
bool startsIdentifier(int c); bool startsIdentifier(int c);
bool continuesIdentifier(int c); bool continuesIdentifier(int c);
@@ -48,14 +52,14 @@ struct Uppercase {
// FNV-1a hash of an uppercased string // FNV-1a hash of an uppercased string
constexpr size_t operator()(std::string const &str) const { constexpr size_t operator()(std::string const &str) const {
return std::accumulate(RANGE(str), 0x811C9DC5, [](size_t hash, char c) { 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) // Compare two strings without case-sensitivity (by converting to uppercase)
constexpr bool operator()(std::string const &str1, std::string const &str2) const { constexpr bool operator()(std::string const &str1, std::string const &str2) const {
return std::equal(RANGE(str1), RANGE(str2), [](char c1, char c2) { return std::equal(RANGE(str1), RANGE(str2), [](char c1, char c2) {
return toupper(c1) == toupper(c2); return toUpper(c1) == toUpper(c2);
}); });
} }
}; };

View File

@@ -32,7 +32,6 @@
%code { %code {
#include <algorithm> #include <algorithm>
#include <ctype.h>
#include <inttypes.h> #include <inttypes.h>
#include <optional> #include <optional>
#include <stdio.h> #include <stdio.h>
@@ -42,6 +41,7 @@
#include "extern/utf8decoder.hpp" #include "extern/utf8decoder.hpp"
#include "helpers.hpp" #include "helpers.hpp"
#include "util.hpp" // toLower, toUpper
#include "asm/charmap.hpp" #include "asm/charmap.hpp"
#include "asm/fixpoint.hpp" #include "asm/fixpoint.hpp"
@@ -1599,11 +1599,11 @@ string_literal:
} }
| OP_STRUPR LPAREN string RPAREN { | OP_STRUPR LPAREN string RPAREN {
$$ = std::move($3); $$ = std::move($3);
std::transform(RANGE($$), $$.begin(), [](char c) { return toupper(c); }); std::transform(RANGE($$), $$.begin(), toUpper);
} }
| OP_STRLWR LPAREN string RPAREN { | OP_STRLWR LPAREN string RPAREN {
$$ = std::move($3); $$ = 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 { | OP_STRRPL LPAREN string COMMA string COMMA string RPAREN {
$$ = act_StringReplace($3, $5, $7); $$ = act_StringReplace($3, $5, $7);

View File

@@ -12,7 +12,7 @@
#include "helpers.hpp" // unreachable_ #include "helpers.hpp" // unreachable_
#include "platform.hpp" // strcasecmp #include "platform.hpp" // strcasecmp
#include "util.hpp" // isBlankSpace, isLower, isDigit #include "util.hpp"
#include "fix/warning.hpp" #include "fix/warning.hpp"
@@ -103,12 +103,10 @@ static void skipMBCSpace(char const *&ptr) {
} }
static char normalizeMBCChar(char c) { static char normalizeMBCChar(char c) {
if (isLower(c)) { if (c == '_') {
c = c - 'a' + 'A'; // Uppercase for comparison with `mbc_Name`s return ' '; // Treat underscores as spaces
} else if (c == '_') {
c = ' '; // Treat underscores as spaces
} }
return c; return toUpper(c); // Uppercase for comparison with `mbc_Name`s
} }
[[noreturn]] [[noreturn]]

View File

@@ -58,6 +58,14 @@ bool isAlphanumeric(int c) {
return isLetter(c) || isDigit(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) { bool startsIdentifier(int c) {
// This returns false for anonymous labels, which internally start with a '!', // This returns false for anonymous labels, which internally start with a '!',
// and for section fragment literal labels, which internally start with a '$'. // and for section fragment literal labels, which internally start with a '$'.