From 6e2e2f1db7b8bac7c9deb8317ed8ab30c56f545c Mon Sep 17 00:00:00 2001 From: Rangi <35663410+Rangi42@users.noreply.github.com> Date: Sat, 26 Sep 2026 19:30:05 -0400 Subject: [PATCH] Add `%A`/`%a` uppercase/lowercase string format specifiers (#2165) --- man/rgbasm.5 | 4 +++- src/asm/format.cpp | 19 ++++++++++++++----- test/asm/case-conversion.asm | 13 +++++++++++++ test/asm/string-formatting.asm | 5 +++-- test/asm/string-formatting.out | 3 ++- 5 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 test/asm/case-conversion.asm diff --git a/man/rgbasm.5 b/man/rgbasm.5 index 06de1bf5..dfa32684 100644 --- a/man/rgbasm.5 +++ b/man/rgbasm.5 @@ -251,7 +251,9 @@ Valid types are: .It Ql b Ta Binary Ta 101010 .It Ql o Ta Octal Ta 52 .It Ql f Ta Fixed-point Ta 1234.56789 -.It Ql s Ta String Ta string contents +.It Ql s Ta String Ta String contents +.It Ql A Ta Uppercase string Ta UPPERCASED STRING +.It Ql a Ta Lowercase string Ta lowercased string .El .Pp Examples: diff --git a/src/asm/format.cpp b/src/asm/format.cpp index 364d91fc..ad29adf5 100644 --- a/src/asm/format.cpp +++ b/src/asm/format.cpp @@ -11,7 +11,8 @@ #include #include -#include "util.hpp" // parseNumber +#include "helpers.hpp" // RANGE +#include "util.hpp" // parseNumber, toUpper, toLower #include "asm/main.hpp" // options #include "asm/warning.hpp" @@ -72,6 +73,8 @@ size_t FormatSpec::parseSpec(char const *spec) { case 'o': case 'f': case 's': + case 'A': + case 'a': ++i; type = c; break; @@ -130,11 +133,17 @@ void FormatSpec::appendString(std::string &str, std::string const &value) const if (hasPrec) { error("Formatting string with fractional precision"); } - if (useType != 's') { + if (useType != 's' && useType != 'A' && useType != 'a') { error("Formatting string as type '%c'", useType); } - std::string useValue = exact ? escapeString(value) : value; + std::string useValue = value; + if (useType == 'A' || useType == 'a') { + std::transform(RANGE(useValue), useValue.begin(), useType == 'A' ? toUpper : toLower); + } + if (exact) { + useValue = escapeString(useValue); + } size_t valueLen = useValue.length(); size_t totalLen = width > valueLen ? width : valueLen; size_t padLen = totalLen - valueLen; @@ -168,8 +177,8 @@ void FormatSpec::appendNumber(std::string &str, uint32_t value) const { if (useType != 'f' && hasPrec) { error("Formatting type '%c' with fractional precision", useType); } - if (useType == 's') { - error("Formatting number as type 's'"); + if (useType == 's' || useType == 'A' || useType == 'a') { + error("Formatting number as type '%c'", useType); } char signChar = sign; // 0 or ' ' or '+' diff --git a/test/asm/case-conversion.asm b/test/asm/case-conversion.asm new file mode 100644 index 00000000..03e46a9d --- /dev/null +++ b/test/asm/case-conversion.asm @@ -0,0 +1,13 @@ +; ASCII +assert STRUPR("camelCase") === "CAMELCASE" +assert STRLWR("camelCase") === "camelcase" +assert STRFMT("%s", "camelCase") === "camelCase" +assert STRFMT("%A", "camelCase") === "CAMELCASE" +assert STRFMT("%a", "camelCase") === "camelcase" + +; UTF-8 +assert STRUPR("ÇA a été ?") === "ÇA A éTé ?" +assert STRLWR("ÇA a été ?") === "Ça a été ?" +assert STRFMT("%s", "ÇA a été ?") === "ÇA a été ?" +assert STRFMT("%A", "ÇA a été ?") === "ÇA A éTé ?" +assert STRFMT("%a", "ÇA a été ?") === "Ça a été ?" diff --git a/test/asm/string-formatting.asm b/test/asm/string-formatting.asm index cc009ade..691a5b72 100644 --- a/test/asm/string-formatting.asm +++ b/test/asm/string-formatting.asm @@ -2,7 +2,7 @@ def n equ 300 def m equ -42 def f equ -123.0456 def pi equ 3.14159 -def s equs "hello" +def s equs "Hello!" def t equs "\"\\t\" is '\t'" def u equs "\t\r\0\n" @@ -10,7 +10,8 @@ def u equs "\t\r\0\n" println "<{u:m}> <{+3d:m}> <{#016o:m}>" println "<{f:pi}> <{06.f:f}> <{.10f:f}>" println "\"{#-20s:t}\", \"{#20s:t}\", \"{20s:t}\"" - println "{#s:u}" + println "{s:s} {A:s} {a:s}" + println "{#s:u} {#A:u} {#a:u}" macro foo println "\1 <{\1}>" diff --git a/test/asm/string-formatting.out b/test/asm/string-formatting.out index f000a17c..1e7425e6 100644 --- a/test/asm/string-formatting.out +++ b/test/asm/string-formatting.out @@ -2,5 +2,6 @@ <4294967254> <-42> <&000037777777726> <3.14159> <-00123> <-123.0455932617> "\"\\t\" is '\t' ", " \"\\t\" is '\t'", " "\t" is ' '" -\t\r\0\n +Hello! HELLO! hello! +\t\r\0\n \t\r\0\n \t\r\0\n -6d:n <300 >