summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko2021-09-09 18:57:07 +0200
committerDenys Vlasenko2021-09-09 18:58:39 +0200
commit8a0adba9f67a661e0f2428bf43ae8da15f641ec0 (patch)
tree2d214ee2df094ae785b5575ffa2b650f11a01d36
parent305a30d80b63e06d312c9d98ae73934ae143e564 (diff)
downloadbusybox-8a0adba9f67a661e0f2428bf43ae8da15f641ec0.zip
busybox-8a0adba9f67a661e0f2428bf43ae8da15f641ec0.tar.gz
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 3594717..46bda93 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -2345,38 +2345,49 @@ static char *awk_printf(node *n, size_t *len)
var *arg;
size_t slen;
+ /* Find end of the next format spec, or end of line */
s = f;
- while (*f && *f != '%')
+ while (1) {
+ c = *f;
+ if (!c) /* no percent chars found at all */
+ goto nul;
+ if (c == '%') {
+ c = *++f;
+ if (!c) /* we are past % in "....%" */
+ goto nul;
+ break;
+ }
+ f++;
+ }
+ /* we are past % in "....%...", c == char after % */
+ if (c == '%') { /* double % */
+ slen = f - s;
+ s = xstrndup(s, slen);
f++;
- if (*f) {
+ goto tail; /* print "....%" part verbatim */
+ }
+ while (1) {
+ if (isalpha(c))
+ break;
+ if (c == '*')
+ syntax_error("%*x formats are not supported");
c = *++f;
- if (c == '%') { /* double % */
+ if (!c) { /* "....%...." and no letter found after % */
+ /* Example: awk 'BEGIN { printf "^^^%^^^\n"; }' */
+ nul:
slen = f - s;
- s = xstrndup(s, slen);
- f++;
- goto tail;
- }
- while (*f && !isalpha(*f)) {
- if (*f == '*')
- syntax_error("%*x formats are not supported");
- f++;
+ goto tail; /* print remaining string, exit loop */
}
}
- c = *f;
- if (!c) {
- /* Tail of fmt with no percent chars,
- * or "....%" (percent seen, but no format specifier char found)
- */
- slen = strlen(s);
- goto tail;
- }
- sv = *++f;
- *f = '\0';
+ /* we are at A in "....%...A..." */
+
arg = evaluate(nextarg(&n), TMPVAR);
/* Result can be arbitrarily long. Example:
* printf "%99999s", "BOOM"
*/
+ sv = *++f;
+ *f = '\0';
if (c == 'c') {
char cc = is_numeric(arg) ? getvar_i(arg) : *getvar_s(arg);
char *r = xasprintf(s, cc ? cc : '^' /* else strlen will be wrong */);
@@ -2395,6 +2406,7 @@ static char *awk_printf(node *n, size_t *len)
} else if (strchr("eEfFgGaA", c)) {
s = xasprintf(s, d);
} else {
+//TODO: GNU Awk 5.0.1: printf "%W" prints "%W", does not error out
syntax_error(EMSG_INV_FMT);
}
}