From cad5affacdaa8094c8850d087bafe4f195b926af Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Mon, 12 Sep 2022 10:53:00 +0300 Subject: [PATCH] Add shorthand macros for some conventient Lua string operations Despite all the Lua magic we already do, it's annoyingly often the case that shelling out is easier (or at least shorter) than doing the same in Lua (substrings, length etc) Add shorthand macros %gsub, %len, %lower, %rep, %reverse, %sub and %upper which simply wrap the corresponding Lua string.* functions for convenience. --- docs/manual/macros.md | 9 +++++++++ rpmio/macro.c | 31 +++++++++++++++++++++++++++++ tests/data/SPECS/configtest.spec | 2 +- tests/data/SPECS/replacetest.spec | 2 +- tests/rpmconfig.at | 6 +++--- tests/rpmconfig2.at | 6 +++--- tests/rpmmacro.at | 33 +++++++++++++++++++++++++++++++ 7 files changed, 81 insertions(+), 8 deletions(-) diff --git a/docs/manual/macros.md b/docs/manual/macros.md index ddc0303fa..551894a09 100644 --- a/docs/manual/macros.md +++ b/docs/manual/macros.md @@ -84,6 +84,15 @@ to perform useful operations. The current list is %{macrobody:...} literal body of a macro + %{gsub:...} replace occurences of pattern in a string + (see Lua `string.gsub()`) + %{len:...} string length + %{lower:...} lowercase a string + %{rep:...} repeat a string (see Lua `string.rep()`) + %{reverse:...} reverse a string + %{sub:...} expand to substring (see Lua `string.sub()`) + %{upper:...} uppercase a string + %{basename:...} basename(1) macro analogue %{dirname:...} dirname(1) macro analogue %{exists:...} test file existence, expands to 1/0 diff --git a/rpmio/macro.c b/rpmio/macro.c index 7aa9f0fd7..2a00c22b3 100644 --- a/rpmio/macro.c +++ b/rpmio/macro.c @@ -1096,6 +1096,30 @@ static void doLua(MacroBuf mb, rpmMacroEntry me, ARGV_t argv, size_t *parsed) } } +/* + * Wrap a call to Lua string functions. + * Note extra parentheses to force only one result returned, multi-value + * returns such as from string.gsub() make no sense in this context. + */ +static void doString(MacroBuf mb, rpmMacroEntry me, ARGV_t argv, size_t *parsed) +{ + rpmlua lua = NULL; /* Global state. */ + char *printbuf = NULL; + char *s = rstrscat(NULL, + "return (string.", argv[0], "(table.unpack(arg)))", NULL); + + rpmluaPushPrintBuffer(lua); + if (rpmluaRunScript(lua, s, argv[0], NULL, argv+1) == -1) + mb->error = 1; + printbuf = rpmluaPopPrintBuffer(lua); + + if (printbuf) { + mbAppendStr(mb, printbuf); + free(printbuf); + } + free(s); +} + static void doSP(MacroBuf mb, rpmMacroEntry me, ARGV_t argv, size_t *parsed) { char *s = NULL; @@ -1245,17 +1269,24 @@ static struct builtins_s { { "getenv", doFoo, 1, 0 }, { "getncpus", doFoo, 0, 0 }, { "global", doGlobal, 1, ME_PARSE }, + { "gsub", doString, 1, 0 }, + { "len", doString, 1, 0 }, { "load", doLoad, 1, 0 }, + { "lower", doString, 1, 0 }, { "lua", doLua, 1, ME_PARSE }, { "macrobody", doBody, 1, 0 }, { "quote", doFoo, 1, 0 }, + { "rep", doString, 1, 0 }, + { "reverse", doString, 1, 0 }, { "shrink", doFoo, 1, 0 }, + { "sub", doString, 1, 0 }, { "suffix", doFoo, 1, 0 }, { "trace", doTrace, 0, 0 }, { "u2p", doFoo, 1, 0 }, { "shescape", doShescape, 1, 0 }, { "uncompress", doUncompress, 1, 0 }, { "undefine", doUndefine, 1, 0 }, + { "upper", doString, 1, 0 }, { "url2path", doFoo, 1, 0 }, { "verbose", doVerbose, -1, ME_PARSE }, { "warn", doOutput, 1, 0 }, diff --git a/tests/data/SPECS/configtest.spec b/tests/data/SPECS/configtest.spec index ea9376442..63a733537 100644 --- a/tests/data/SPECS/configtest.spec +++ b/tests/data/SPECS/configtest.spec @@ -3,7 +3,7 @@ %{!?filetype: %global filetype file} -Name: configtest%{?sub:-%{sub}} +Name: configtest%{?subpkg:-%{subpkg}} Version: %{ver} Release: 1 Summary: Testing config file behavior diff --git a/tests/data/SPECS/replacetest.spec b/tests/data/SPECS/replacetest.spec index b30ad70dd..0f86ea628 100644 --- a/tests/data/SPECS/replacetest.spec +++ b/tests/data/SPECS/replacetest.spec @@ -3,7 +3,7 @@ %{!?user: %global user root} %{!?grp: %global grp root} -Name: replacetest%{?sub:-%{sub}} +Name: replacetest%{?subpkg:-%{subpkg}} Version: %{ver} Release: 1 Summary: Testing file replacement behavior diff --git a/tests/rpmconfig.at b/tests/rpmconfig.at index a836bbfa4..99cfc5055 100644 --- a/tests/rpmconfig.at +++ b/tests/rpmconfig.at @@ -402,7 +402,7 @@ RPMDB_INIT for s in "A" "B"; do for v in "1.0" "2.0"; do runroot rpmbuild --quiet -bb \ - --define "sub $s" \ + --define "subpkg $s" \ --define "ver $v" \ --define "filedata foo" \ /data/SPECS/configtest.spec @@ -462,7 +462,7 @@ RPMDB_INIT for s in "A" "B"; do for v in "1.0" "2.0"; do runroot rpmbuild --quiet -bb \ - --define "sub $s" \ + --define "subpkg $s" \ --define "ver $v" \ --define "filedata foo-$v" \ /data/SPECS/configtest.spec @@ -552,7 +552,7 @@ RPMDB_INIT for s in "A" "B"; do for v in "1.0" "2.0"; do runroot rpmbuild --quiet -bb \ - --define "sub $s" \ + --define "subpkg $s" \ --define "ver $v" \ --define "filedata foo-$v" \ --define "noreplace 1" \ diff --git a/tests/rpmconfig2.at b/tests/rpmconfig2.at index 90530a7a6..3ae30269b 100644 --- a/tests/rpmconfig2.at +++ b/tests/rpmconfig2.at @@ -352,7 +352,7 @@ RPMDB_INIT for s in "A" "B"; do for v in "1.0" "2.0"; do runroot rpmbuild --quiet -bb \ - --define "sub $s" \ + --define "subpkg $s" \ --define "ver $v" \ --define "filedata foo" \ --define "filetype link" \ @@ -414,7 +414,7 @@ RPMDB_INIT for s in "A" "B"; do for v in "1.0" "2.0"; do runroot rpmbuild --quiet -bb \ - --define "sub $s" \ + --define "subpkg $s" \ --define "ver $v" \ --define "filedata foo-$v" \ --define "filetype link" \ @@ -504,7 +504,7 @@ RPMDB_INIT for s in "A" "B"; do for v in "1.0" "2.0"; do runroot rpmbuild --quiet -bb \ - --define "sub $s" \ + --define "subpkg $s" \ --define "ver $v" \ --define "filedata foo-$v" \ --define "filetype link" \ diff --git a/tests/rpmmacro.at b/tests/rpmmacro.at index c4376d49e..a4bcd0e9c 100644 --- a/tests/rpmmacro.at +++ b/tests/rpmmacro.at @@ -387,6 +387,39 @@ runroot rpm \ ]) AT_CLEANUP +AT_SETUP([string functions]) +AT_KEYWORDS([macros]) +AT_CHECK([ +runroot rpm \ + --eval "%sub cd6317ba61e6c27b92d6bbdf2702094ff3c0c732 1 7" \ + --eval "%sub cd6317ba61e6c27b92d6bbdf2702094ff3c0c732 7 -7" \ + --eval "%sub cd6317ba61e6c27b92d6bbdf2702094ff3c0c732 -7" \ + --eval "%len cd6317ba61e6c27b92d6bbdf2702094ff3c0c732" \ + --eval "%upper abba" \ + --eval "%lower Beatles" \ + --eval "%rep ai 2" \ + --eval "%reverse live" \ + --eval "%reverse a'b" \ + --eval "%reverse a\"b" \ + --eval "%gsub aaa a b 2" +], +[0], +[cd6317b +ba61e6c27b92d6bbdf2702094ff3 +3c0c732 +40 +ABBA +beatles +aiai +evil +b'a +b"a +bba +], +[]) +AT_CLEANUP + + AT_SETUP([expr macro 1]) AT_KEYWORDS([macros]) AT_CHECK([