aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2021-09-09 18:57:07 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2021-09-09 18:58:39 +0200
commit8a0adba9f67a661e0f2428bf43ae8da15f641ec0 (patch)
tree2d214ee2df094ae785b5575ffa2b650f11a01d36
parent305a30d80b63e06d312c9d98ae73934ae143e564 (diff)
downloadbusybox-w32-8a0adba9f67a661e0f2428bf43ae8da15f641ec0.tar.gz
busybox-w32-8a0adba9f67a661e0f2428bf43ae8da15f641ec0.tar.bz2
busybox-w32-8a0adba9f67a661e0f2428bf43ae8da15f641ec0.zip
awk: code shrink: avoid duplicate NUL checks and strlen()
function old new delta awk_printf 665 652 -13 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--editors/awk.c54
1 files changed, 33 insertions, 21 deletions
diff --git a/editors/awk.c b/editors/awk.c
index 3594717b1..46bda93b2 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -2345,38 +2345,49 @@ static char *awk_printf(node *n, size_t *len)
2345 var *arg; 2345 var *arg;
2346 size_t slen; 2346 size_t slen;
2347 2347
2348 /* Find end of the next format spec, or end of line */
2348 s = f; 2349 s = f;
2349 while (*f && *f != '%') 2350 while (1) {
2351 c = *f;
2352 if (!c) /* no percent chars found at all */
2353 goto nul;
2354 if (c == '%') {
2355 c = *++f;
2356 if (!c) /* we are past % in "....%" */
2357 goto nul;
2358 break;
2359 }
2360 f++;
2361 }
2362 /* we are past % in "....%...", c == char after % */
2363 if (c == '%') { /* double % */
2364 slen = f - s;
2365 s = xstrndup(s, slen);
2350 f++; 2366 f++;
2351 if (*f) { 2367 goto tail; /* print "....%" part verbatim */
2368 }
2369 while (1) {
2370 if (isalpha(c))
2371 break;
2372 if (c == '*')
2373 syntax_error("%*x formats are not supported");
2352 c = *++f; 2374 c = *++f;
2353 if (c == '%') { /* double % */ 2375 if (!c) { /* "....%...." and no letter found after % */
2376 /* Example: awk 'BEGIN { printf "^^^%^^^\n"; }' */
2377 nul:
2354 slen = f - s; 2378 slen = f - s;
2355 s = xstrndup(s, slen); 2379 goto tail; /* print remaining string, exit loop */
2356 f++;
2357 goto tail;
2358 }
2359 while (*f && !isalpha(*f)) {
2360 if (*f == '*')
2361 syntax_error("%*x formats are not supported");
2362 f++;
2363 } 2380 }
2364 } 2381 }
2365 c = *f; 2382 /* we are at A in "....%...A..." */
2366 if (!c) { 2383
2367 /* Tail of fmt with no percent chars,
2368 * or "....%" (percent seen, but no format specifier char found)
2369 */
2370 slen = strlen(s);
2371 goto tail;
2372 }
2373 sv = *++f;
2374 *f = '\0';
2375 arg = evaluate(nextarg(&n), TMPVAR); 2384 arg = evaluate(nextarg(&n), TMPVAR);
2376 2385
2377 /* Result can be arbitrarily long. Example: 2386 /* Result can be arbitrarily long. Example:
2378 * printf "%99999s", "BOOM" 2387 * printf "%99999s", "BOOM"
2379 */ 2388 */
2389 sv = *++f;
2390 *f = '\0';
2380 if (c == 'c') { 2391 if (c == 'c') {
2381 char cc = is_numeric(arg) ? getvar_i(arg) : *getvar_s(arg); 2392 char cc = is_numeric(arg) ? getvar_i(arg) : *getvar_s(arg);
2382 char *r = xasprintf(s, cc ? cc : '^' /* else strlen will be wrong */); 2393 char *r = xasprintf(s, cc ? cc : '^' /* else strlen will be wrong */);
@@ -2395,6 +2406,7 @@ static char *awk_printf(node *n, size_t *len)
2395 } else if (strchr("eEfFgGaA", c)) { 2406 } else if (strchr("eEfFgGaA", c)) {
2396 s = xasprintf(s, d); 2407 s = xasprintf(s, d);
2397 } else { 2408 } else {
2409//TODO: GNU Awk 5.0.1: printf "%W" prints "%W", does not error out
2398 syntax_error(EMSG_INV_FMT); 2410 syntax_error(EMSG_INV_FMT);
2399 } 2411 }
2400 } 2412 }