diff options
| author | Ron Yorston <rmy@pobox.com> | 2021-01-27 11:19:14 +0000 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-02-02 13:51:14 +0100 |
| commit | e8fe9f96356a6b19ec907ea30cffc829c539a7ff (patch) | |
| tree | 1c9450cbdc4c32266241652303852acde28c14a0 | |
| parent | f3a55b306ed3803133ab028b72b255c65d94197f (diff) | |
| download | busybox-w32-e8fe9f96356a6b19ec907ea30cffc829c539a7ff.tar.gz busybox-w32-e8fe9f96356a6b19ec907ea30cffc829c539a7ff.tar.bz2 busybox-w32-e8fe9f96356a6b19ec907ea30cffc829c539a7ff.zip | |
awk: allow printf('%c') to output NUL, closes 13486
Treat the output of printf as binary rather than a null-terminated
string so that NUL characters can be output.
This is considered to be a GNU extension, though it's also available
in mawk and FreeBSD's awk.
function old new delta
evaluate 3487 3504 +17
awk_printf 504 519 +15
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 32/0) Total: 32 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | editors/awk.c | 18 | ||||
| -rwxr-xr-x | testsuite/awk.tests | 5 |
2 files changed, 20 insertions, 3 deletions
diff --git a/editors/awk.c b/editors/awk.c index 2c15f9e4e..b4f6a3741 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
| @@ -2155,7 +2155,10 @@ static int fmt_num(char *b, int size, const char *format, double n, int int_as_i | |||
| 2155 | } | 2155 | } |
| 2156 | 2156 | ||
| 2157 | /* formatted output into an allocated buffer, return ptr to buffer */ | 2157 | /* formatted output into an allocated buffer, return ptr to buffer */ |
| 2158 | static char *awk_printf(node *n) | 2158 | #if !ENABLE_FEATURE_AWK_GNU_EXTENSIONS |
| 2159 | # define awk_printf(a, b) awk_printf(a) | ||
| 2160 | #endif | ||
| 2161 | static char *awk_printf(node *n, int *len) | ||
| 2159 | { | 2162 | { |
| 2160 | char *b = NULL; | 2163 | char *b = NULL; |
| 2161 | char *fmt, *s, *f; | 2164 | char *fmt, *s, *f; |
| @@ -2209,6 +2212,10 @@ static char *awk_printf(node *n) | |||
| 2209 | nvfree(v); | 2212 | nvfree(v); |
| 2210 | b = xrealloc(b, i + 1); | 2213 | b = xrealloc(b, i + 1); |
| 2211 | b[i] = '\0'; | 2214 | b[i] = '\0'; |
| 2215 | #if ENABLE_FEATURE_AWK_GNU_EXTENSIONS | ||
| 2216 | if (len) | ||
| 2217 | *len = i; | ||
| 2218 | #endif | ||
| 2212 | return b; | 2219 | return b; |
| 2213 | } | 2220 | } |
| 2214 | 2221 | ||
| @@ -2666,6 +2673,7 @@ static var *evaluate(node *op, var *res) | |||
| 2666 | case XC( OC_PRINT ): | 2673 | case XC( OC_PRINT ): |
| 2667 | case XC( OC_PRINTF ): { | 2674 | case XC( OC_PRINTF ): { |
| 2668 | FILE *F = stdout; | 2675 | FILE *F = stdout; |
| 2676 | IF_FEATURE_AWK_GNU_EXTENSIONS(int len;) | ||
| 2669 | 2677 | ||
| 2670 | if (op->r.n) { | 2678 | if (op->r.n) { |
| 2671 | rstream *rsm = newfile(R.s); | 2679 | rstream *rsm = newfile(R.s); |
| @@ -2703,8 +2711,12 @@ static var *evaluate(node *op, var *res) | |||
| 2703 | fputs(getvar_s(intvar[ORS]), F); | 2711 | fputs(getvar_s(intvar[ORS]), F); |
| 2704 | 2712 | ||
| 2705 | } else { /* OC_PRINTF */ | 2713 | } else { /* OC_PRINTF */ |
| 2706 | char *s = awk_printf(op1); | 2714 | char *s = awk_printf(op1, &len); |
| 2715 | #if ENABLE_FEATURE_AWK_GNU_EXTENSIONS | ||
| 2716 | fwrite(s, len, 1, F); | ||
| 2717 | #else | ||
| 2707 | fputs(s, F); | 2718 | fputs(s, F); |
| 2719 | #endif | ||
| 2708 | free(s); | 2720 | free(s); |
| 2709 | } | 2721 | } |
| 2710 | fflush(F); | 2722 | fflush(F); |
| @@ -2978,7 +2990,7 @@ static var *evaluate(node *op, var *res) | |||
| 2978 | break; | 2990 | break; |
| 2979 | 2991 | ||
| 2980 | case XC( OC_SPRINTF ): | 2992 | case XC( OC_SPRINTF ): |
| 2981 | setvar_p(res, awk_printf(op1)); | 2993 | setvar_p(res, awk_printf(op1, NULL)); |
| 2982 | break; | 2994 | break; |
| 2983 | 2995 | ||
| 2984 | case XC( OC_UNARY ): { | 2996 | case XC( OC_UNARY ): { |
diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 92c83d719..cf9b722dc 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests | |||
| @@ -383,6 +383,11 @@ testing "awk errors on missing delete arg" \ | |||
| 383 | "awk -e '{delete}' 2>&1" "awk: cmd. line:1: Too few arguments\n" "" "" | 383 | "awk -e '{delete}' 2>&1" "awk: cmd. line:1: Too few arguments\n" "" "" |
| 384 | SKIP= | 384 | SKIP= |
| 385 | 385 | ||
| 386 | optional FEATURE_AWK_GNU_EXTENSIONS | ||
| 387 | testing "awk printf('%c') can output NUL" \ | ||
| 388 | "awk '{printf(\"hello%c null\n\", 0)}'" "hello\0 null\n" "" "\n" | ||
| 389 | SKIP= | ||
| 390 | |||
| 386 | # testing "description" "command" "result" "infile" "stdin" | 391 | # testing "description" "command" "result" "infile" "stdin" |
| 387 | testing 'awk negative field access' \ | 392 | testing 'awk negative field access' \ |
| 388 | 'awk 2>&1 -- '\''{ $(-1) }'\' \ | 393 | 'awk 2>&1 -- '\''{ $(-1) }'\' \ |
