From cf897aa06538c10d3edb839d53b37d4a8a671445 Mon Sep 17 00:00:00 2001 From: Rangi <35663410+Rangi42@users.noreply.github.com> Date: Sat, 26 Sep 2026 18:19:10 -0400 Subject: [PATCH] Add `STRICMP` case-insensitive string compare function (#2164) --- man/rgbasm.5 | 1 + src/asm/lexer.cpp | 1 + src/asm/parser.y | 10 +++++++++- test/asm/string-compare.asm | 8 ++++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/man/rgbasm.5 b/man/rgbasm.5 index 58568cc2..06de1bf5 100644 --- a/man/rgbasm.5 +++ b/man/rgbasm.5 @@ -659,6 +659,7 @@ The following functions operate on string expressions, but return integers: .It Sy Name Ta Sy Operation .It Fn STRLEN str Ta Returns the number of characters in Ar str . .It Fn STRCMP str1 str2 Ta Compares Ar str1 No and Ar str2 No according to ASCII ordering of their characters. Returns -1 if Ar str1 No is lower than Ar str2 Ns , 1 if Ar str1 No is greater than Ar str2 Ns , or 0 if they match. +.It Fn STRICMP str1 str2 Ta Compares Ar str1 No and Ar str2 No according to case-insensitive ASCII ordering of their characters. Returns -1 if Ar str1 No is lower than Ar str2 Ns , 1 if Ar str1 No is greater than Ar str2 Ns , or 0 if they match. .It Fn STRFIND str sub Ta Returns the first index of Ar sub No in Ar str Ns , or -1 if it's not present. .It Fn STRRFIND str sub Ta Returns the last index of Ar sub No in Ar str Ns , or -1 if it's not present. .It Fn STRSTARTS str prefix Ta Returns 1 if Ar str No starts with Ar prefix Ns , or 0 otherwise. diff --git a/src/asm/lexer.cpp b/src/asm/lexer.cpp index 286e4790..5da27d2c 100644 --- a/src/asm/lexer.cpp +++ b/src/asm/lexer.cpp @@ -185,6 +185,7 @@ static UpperMap const keywords{ {"STRENDS", T_(OP_STRENDS) }, {"STRFIND", T_(OP_STRFIND) }, {"STRFMT", T_(OP_STRFMT) }, + {"STRICMP", T_(OP_STRICMP) }, {"STRIN", T_(OP_STRIN) }, {"STRLEN", T_(OP_STRLEN) }, {"STRLWR", T_(OP_STRLWR) }, diff --git a/src/asm/parser.y b/src/asm/parser.y index aa808647..a14a59c1 100644 --- a/src/asm/parser.y +++ b/src/asm/parser.y @@ -5,6 +5,8 @@ %define api.token.constructor %code requires { + #include "platform.hpp" + #include #include #include @@ -301,6 +303,7 @@ %token OP_STRENDS "STRENDS" %token OP_STRFIND "STRFIND" %token OP_STRFMT "STRFMT" +%token OP_STRICMP "STRICMP" %token OP_STRIN "STRIN" %token OP_STRLEN "STRLEN" %token OP_STRLWR "STRLWR" @@ -1483,7 +1486,12 @@ relocexpr_no_str: $$.makeNumber(fix_ATan2($3, $5, $6)); } | OP_STRCMP LPAREN string COMMA string RPAREN { - $$.makeNumber($3.compare($5)); + int result = $3.compare($5); + $$.makeNumber(result < 0 ? -1 : result > 0 ? 1 : 0); + } + | OP_STRICMP LPAREN string COMMA string RPAREN { + int result = strcasecmp($3.c_str(), $5.c_str()); + $$.makeNumber(result < 0 ? -1 : result > 0 ? 1 : 0); } | OP_STRFIND LPAREN string COMMA string RPAREN { size_t pos = $3.find($5); diff --git a/test/asm/string-compare.asm b/test/asm/string-compare.asm index 930bda81..812d9a01 100644 --- a/test/asm/string-compare.asm +++ b/test/asm/string-compare.asm @@ -5,3 +5,11 @@ assert "fire flower" === "fire" ++ " " ++ "flower" assert "a" === "b" == 0 assert 1 == "a" !== "b" assert 1 + 2 * 3 ** "x" !== "y" == 7 + +assert !STRICMP("hello", "hello") +assert !STRICMP("hello", "HELLO") +assert !STRICMP("HeLlO", "hElLo") +assert STRICMP("HELLO", "goodBYE") > 0 +assert STRICMP("hello", "GOODbye") > 0 +assert STRICMP("", "hello") < 0 +assert STRICMP("hello", "") > 0