Well, I also tried adding support for bash's ${var@Q} (which I think is the
 most readable way to solve quoting) but it seems I really don't understand
how ash's subevalvar() works after all :)


./busybox ash -xvc 'v="ab cd"; echo "(${v@Q})"'
+ v='ab cd'
ash: vstransform:str='Q'
ash: vstransform:startp='ab cd'
+ echo ''"'"'a'"'"'ab cd'"'"')'
'a'ab cd')





diff --git a/shell/ash.c b/shell/ash.c
index ae1b79f37..8d5d6146d 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -222,6 +222,8 @@
 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
+#define    BASH_PARAM_TRANSFORM ENABLE_ASH_BASH_COMPAT
+#define IF_BASH_PARAM_TRANSFORM     IF_ASH_BASH_COMPAT
 /* BASH_TEST2: [[ EXPR ]]
  * Status of [[ support:
  *   && and || work as they should
@@ -574,6 +576,7 @@ var_end(const char *var)
        return var;
 }

+static int hasmeta(const char *);

 /* ============ Parser data */

@@ -868,6 +871,9 @@ out2str(const char *p)
 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
 #endif
+#if BASH_PARAM_TRANSFORM
+#define VSTRANSFORM     0xf     /* ${var@operator} */
+#endif

 static const char dolatstr[] ALIGN1 = {
        CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
@@ -7262,6 +7268,20 @@ subevalvar(char *start, char *str, int strloc,
                repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
        );

+#if BASH_PARAM_TRANSFORM
+       if (subtype == VSTRANSFORM) {
+               bb_error_msg("vstransform:str='%s'", str);
+               if (strcmp(str, "Q") != 0)
+                       goto out1;
+               bb_error_msg("vstransform:startp='%s'", startp);
+               char *quoted = single_quote(startp);
+               int len = strlen(quoted);
+               memmove(startp, quoted, len);
+               loc = startp + len;
+               goto out;
+       }
+#endif /* BASH_PARAM_TRANSFORM */
+
 #if BASH_PATTERN_SUBST
        workloc = expdest - (char *)stackblock();
        if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
@@ -7432,7 +7452,7 @@ subevalvar(char *start, char *str, int strloc,
  out:
        amount = loc - expdest;
        STADJUST(amount, expdest);
-#if BASH_PATTERN_SUBST
+#if BASH_PATTERN_SUBST || BASH_PARAM_TRANSFORM
  out1:
 #endif
        /* Remove any recorded regions beyond start of variable */
@@ -7671,6 +7691,9 @@ evalvar(char *p, int flag)
 #if BASH_PATTERN_SUBST
        case VSREPLACE:
        case VSREPLACEALL:
+#endif
+#if BASH_PARAM_TRANSFORM
+       case VSTRANSFORM:
 #endif
                break;
        default:
@@ -12989,6 +13012,13 @@ parsesub: {
                                        goto badsub;
                                subtype++; /* VSREPLACEALL */
                                break;
+#endif
+#if BASH_PARAM_TRANSFORM
+                       case '@':
+                               /* ${v@operator} */
+                               subtype = VSTRANSFORM;
+                               newsyn = BASESYNTAX;
+                               break;
 #endif
                        }
                } else {


On Thu, 15 Feb 2024, David Laight wrote:

From: David Leonard
Sent: 15 February 2024 08:46
To: Harvey <h...@gmx.de>
Cc: busybox@busybox.net
Subject: Re: Failing shell code under busybox 1.36.1 that worked with 1.31.1


        _result="$_result '${_p//'/'\"'\"'}'"

Busybox ash has a CONFIG_ASH_BASH_COMPAT config to get this ${var//...}
replacement behaviour.  And, in bash, the ' in the pattern section is treated
as a quote start. To give the ' a literal meaning, use \'
eg ${_p//\'/..repl..}
...

It is probably safer to the quotes into variables.
Then the syntax analysis won't get messed up.

So something like:
sq="'"
qsq='"'"'"'"'

then
        "${_p/$sg/$qsq}"

is probably ok and maybe more readable.

        David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, 
UK
Registration No: 1397386 (Wales)

_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to