diff options
| author | Ron Yorston <rmy@pobox.com> | 2024-12-30 08:27:31 +0000 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2024-12-30 08:27:31 +0000 |
| commit | becedd5bd29dd1ea3c21426568e6412d6b9a404e (patch) | |
| tree | 81cf0a4ad070afd1ff2fbe6a55a51a5da99777f0 | |
| parent | c5e5da5eb1e0f6acee26bc22d2f567406a2840bc (diff) | |
| download | busybox-w32-becedd5bd29dd1ea3c21426568e6412d6b9a404e.tar.gz busybox-w32-becedd5bd29dd1ea3c21426568e6412d6b9a404e.tar.bz2 busybox-w32-becedd5bd29dd1ea3c21426568e6412d6b9a404e.zip | |
win32: code shrink quote_arg()
Alter quote_arg() to perform a single pass over the string in the
case where no change is required. Based on a proposal by @avih in
GitHub PR #317.
Saves 16 bytes.
| -rw-r--r-- | win32/process.c | 44 |
1 files changed, 20 insertions, 24 deletions
diff --git a/win32/process.c b/win32/process.c index a70b9484e..e7c9ca187 100644 --- a/win32/process.c +++ b/win32/process.c | |||
| @@ -109,38 +109,34 @@ parse_interpreter(const char *cmd, interp_t *interp) | |||
| 109 | char * FAST_FUNC | 109 | char * FAST_FUNC |
| 110 | quote_arg(const char *arg) | 110 | quote_arg(const char *arg) |
| 111 | { | 111 | { |
| 112 | char *r = xmalloc(2 * strlen(arg) + 3); // max-esc, enclosing DQ, \0 | 112 | char *d, *r = xmalloc(2 * strlen(arg) + 3); // max-esc, quotes, \0 |
| 113 | char *d = r; | 113 | size_t nbs = 0; // consecutive backslashes before current char |
| 114 | int nbs = 0; // n consecutive BS right before current char | 114 | int quoted = !*arg; |
| 115 | 115 | ||
| 116 | /* empty arguments and those containing tab/space must be quoted */ | 116 | for (d = r; *arg; *d++ = *arg++) { |
| 117 | if (!*arg || strpbrk(arg, " \t")) { | 117 | if (*arg == ' ' || *arg == '\t') |
| 118 | *d++ = '"'; | 118 | quoted = 1; |
| 119 | } | 119 | |
| 120 | if (*arg == '\\' || *arg == '"') | ||
| 121 | *d++ = '\\'; | ||
| 122 | else | ||
| 123 | d -= nbs; // undo nbs escapes, if any (not followed by DQ) | ||
| 120 | 124 | ||
| 121 | while (*arg) { | 125 | if (*arg == '\\') |
| 122 | switch (*arg) { | ||
| 123 | case '\\': | ||
| 124 | ++nbs; | 126 | ++nbs; |
| 125 | break; | 127 | else |
| 126 | case '"': // double consecutive-BS, plus one to escape the DQ | ||
| 127 | for (++nbs; nbs; --nbs) | ||
| 128 | *d++ = '\\'; | ||
| 129 | break; | ||
| 130 | default: // reset count if followed by not-DQ | ||
| 131 | nbs = 0; | 128 | nbs = 0; |
| 132 | } | ||
| 133 | *d++ = *arg++; | ||
| 134 | } | 129 | } |
| 135 | 130 | ||
| 136 | if (*r == '"') { | 131 | if (quoted) { |
| 137 | while (nbs--) // double consecutive-BS before the closing DQ | 132 | memmove(r + 1, r, d++ - r); |
| 138 | *d++ = '\\'; | 133 | *r = *d++ = '"'; |
| 139 | *d++ = '"'; | 134 | } else { |
| 135 | d -= nbs; | ||
| 140 | } | 136 | } |
| 141 | *d++ = '\0'; | ||
| 142 | 137 | ||
| 143 | return xrealloc(r, d - r); | 138 | *d = 0; |
| 139 | return r; | ||
| 144 | } | 140 | } |
| 145 | 141 | ||
| 146 | char * FAST_FUNC | 142 | char * FAST_FUNC |
