diff mbox series

[1/3] codeparser: support shell substitutions in quotes

Message ID 20240514015234.67318-2-antoningodard@pm.me
State Accepted, archived
Commit f56e1a37b2ba1773ed308043d7eb073cc2e6c06e
Headers show
Series Support codeparser shell expansion between quotes | expand

Commit Message

Antonin Godard May 14, 2024, 1:53 a.m. UTC
The current shell substitution mechanism only works without quotes. For
example:

  var1=$(cmd1 ...)

Will work and add `cmd1` to the correspondind `run.do_*` file.

However, although quite common, this syntax is not supported:

  var1="$(cmd1 ...)"

This commit adds this feature by adding a step to process_words() to
check whether we are dealing with quotes first, and by iterating on
what's between them to detect new shell substitution candidates. These
candidates are tested and parsed like before in the next step. The
original `part` being part of the candidates means the syntax
var1=$(cmd1 ...) is still valid.

Signed-off-by: Antonin Godard <antoningodard@pm.me>
---
 lib/bb/codeparser.py | 29 ++++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/lib/bb/codeparser.py b/lib/bb/codeparser.py
index 2e8b7ced3..c613806c8 100644
--- a/lib/bb/codeparser.py
+++ b/lib/bb/codeparser.py
@@ -490,13 +490,28 @@  class ShellParser():
                 if not isinstance(part, list):
                     continue
 
-                if part[0] in ('`', '$('):
-                    command = pyshlex.wordtree_as_string(part[1:-1])
-                    self._parse_shell(command)
-
-                    if word[0] in ("cmd_name", "cmd_word"):
-                        if word in words:
-                            words.remove(word)
+                candidates = [part]
+
+                # If command is of type:
+                #
+                #   var="... $(cmd [...]) ..."
+                #
+                # Then iterate on what's between the quotes and if we find a
+                # list, make that what we check for below.
+                if len(part) >= 3 and part[0] == '"':
+                    for p in part[1:-1]:
+                        if isinstance(p, list):
+                            candidates.append(p)
+
+                for candidate in candidates:
+                    if len(candidate) >= 2:
+                        if candidate[0] in ('`', '$('):
+                            command = pyshlex.wordtree_as_string(candidate[1:-1])
+                            self._parse_shell(command)
+
+                            if word[0] in ("cmd_name", "cmd_word"):
+                                if word in words:
+                                    words.remove(word)
 
         usetoken = False
         for word in words: