aboutsummaryrefslogtreecommitdiff
path: root/win32/process.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-04-27 07:31:23 +0100
committerRon Yorston <rmy@pobox.com>2023-04-27 07:31:23 +0100
commitd0deef23fa6b228aea60b5599b5ba291ed0ad304 (patch)
treea722955c91cf1eff44d229d1a750188c8a875827 /win32/process.c
parentcbbb73da90bac5029cbd58f4a8f148312768bc0f (diff)
downloadbusybox-w32-d0deef23fa6b228aea60b5599b5ba291ed0ad304.tar.gz
busybox-w32-d0deef23fa6b228aea60b5599b5ba291ed0ad304.tar.bz2
busybox-w32-d0deef23fa6b228aea60b5599b5ba291ed0ad304.zip
win32: code shrink quote_args()
Replace parts of quote_args() with code from avih's GitHub PR #317. This overestimates the size of the buffer to avoid having to calculate the exact size. Retain the code to determine whether the argument needs to be quoted. Quoting arguments unconditionally wastes space on the command line and causes the test "xargs argument line too long" to fail. Saves 144-176 bytes.
Diffstat (limited to '')
-rw-r--r--win32/process.c78
1 files changed, 20 insertions, 58 deletions
diff --git a/win32/process.c b/win32/process.c
index 62be6e0cc..5dc0f7080 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -116,9 +116,10 @@ parse_interpreter(const char *cmd, interp_t *interp)
116char * 116char *
117quote_arg(const char *arg) 117quote_arg(const char *arg)
118{ 118{
119 int len = 0, n = 0;
120 int force_quotes = 0; 119 int force_quotes = 0;
121 char *q, *d; 120 char *r = xmalloc(2 * strlen(arg) + 3); // max-esc, enclosing DQ, \0
121 char *d = r;
122 int nbs = 0; // n consecutive BS right before current char
122 const char *p = arg; 123 const char *p = arg;
123 124
124 /* empty arguments must be quoted */ 125 /* empty arguments must be quoted */
@@ -130,78 +131,39 @@ quote_arg(const char *arg)
130 if (isspace(*p)) { 131 if (isspace(*p)) {
131 /* arguments containing whitespace must be quoted */ 132 /* arguments containing whitespace must be quoted */
132 force_quotes = 1; 133 force_quotes = 1;
134 break;
133 } 135 }
134 else if (*p == '"') {
135 /* double quotes in arguments need to be escaped */
136 n++;
137 }
138 else if (*p == '\\') {
139 /* count contiguous backslashes */
140 int count = 0;
141 while (*p == '\\') {
142 count++;
143 p++;
144 len++;
145 }
146
147 /*
148 * Only escape backslashes before explicit double quotes or
149 * or where the backslashes are at the end of an argument
150 * that is scheduled to be quoted.
151 */
152 if (*p == '"' || (force_quotes && *p == '\0')) {
153 n += count*2 + 1;
154 }
155
156 if (*p == '\0') {
157 break;
158 }
159 continue;
160 }
161 len++;
162 p++; 136 p++;
163 } 137 }
164 138
165 if (!force_quotes && n == 0) {
166 return xstrdup(arg);
167 }
168
169 /* insert double quotes and backslashes where necessary */ 139 /* insert double quotes and backslashes where necessary */
170 d = q = xmalloc(len+n+3);
171 if (force_quotes) { 140 if (force_quotes) {
172 *d++ = '"'; 141 *d++ = '"';
173 } 142 }
174 143
175 while (*arg) { 144 while (*arg) {
176 if (*arg == '"') { 145 switch (*arg) {
177 *d++ = '\\'; 146 case '\\':
178 } 147 ++nbs;
179 else if (*arg == '\\') { 148 break;
180 int count = 0; 149 case '"': // double consecutive-BS, plus one to escape the DQ
181 while (*arg == '\\') { 150 for (++nbs; nbs; --nbs)
182 count++; 151 *d++ = '\\';
183 *d++ = *arg++; 152 break;
184 } 153 default: // reset count if followed by not-DQ
185 154 nbs = 0;
186 if (*arg == '"' || (force_quotes && *arg == '\0')) {
187 while (count-- > 0) {
188 *d++ = '\\';
189 }
190 if (*arg == '"') {
191 *d++ = '\\';
192 }
193 }
194 }
195 if (*arg != '\0') {
196 *d++ = *arg++;
197 } 155 }
156 *d++ = *arg++;
198 } 157 }
158
199 if (force_quotes) { 159 if (force_quotes) {
160 while (nbs--) // double consecutive-BS before the closing DQ
161 *d++ = '\\';
200 *d++ = '"'; 162 *d++ = '"';
201 } 163 }
202 *d = '\0'; 164 *d++ = '\0';
203 165
204 return q; 166 return xrealloc(r, d - r);
205} 167}
206 168
207char * 169char *