← Commit list

1b4f8e2a8

Denys Vlasenko
Denys Vlasenko
2026-09-14
SUCCESS Duration: 310s

Subject

awk: allow OFMT='prefix:%SPEC suffix with %%'

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

editors/awk.c+10 -3
@@ -982,6 +982,7 @@ static const char *fmt_num(const char *format, double n)
snprintf(g_buf, MAXVARFMT, "%.0f", n);
} else {
const char *s = format;
+ const char *p2;
char c;
/* Find %SPEC in format string */
@@ -993,9 +994,15 @@ static const char *fmt_num(const char *format, double n)
break;
s += 2; /* skip "%%" */
}
- if (strchr(s + 1, '%') != NULL)
-//TODO: allow "%%"s in the suffix too?
- goto INV_FMT; /* more than one %SPEC */
+ /* We are at %SPEC. Is there a second %SPEC? (%% and trailing % aren't %SPEC) */
+ p2 = s;
+ for (;;) {
+ p2 = strchr(p2 + 1, '%');
+ if (!p2) break; /* no more %SPEC: ok */
+ if (*++p2 == '\0') break; /* trailing lone %: ok */
+ if (*p2 != '%') goto INV_FMT; /* more than one %SPEC: error */
+ /* else: %% - ok, look for %SPEC past it by iterating once more */
+ }
//TODO: factor out awk_printf machinery to make %d print large numbers too. Example:
// awk -v OFMT='R:%d!' 'BEGIN { print 184467440737095.1 }'
testsuite/awk.tests+8 -1
@@ -88,11 +88,18 @@ testing "awk %o -1.9" \
# OFMT can contain literals before and after %SPEC:
testing "awk OFMT='R%%:%f!' -1.9" \
"awk -v OFMT='R%%:%f!' 'BEGIN { print -1.9; }'" "R%:-1.900000!\n" "" ""
+testing "awk OFMT='R%%:%f!%%!!' -1.9" \
+"awk -v OFMT='R%%:%f!%%!!' 'BEGIN { print -1.9; }'" "R%:-1.900000!%!!\n" "" ""
+# In our code, whether trailing lone % prints "%" or "" depends on what libc's sprintf does.
+# GNU Awk 5.3.0 prints "%", I do not know whether it is libc-dependent in their code.
+# Let's not test this:
+#testing "awk OFMT='R%%:%f!%' -1.9" \
+#"awk -v OFMT='R%%:%f!%' 'BEGIN { print -1.9; }'" "R%:-1.900000!%\n" "" ""
# OFMT is ignored if the value has no fractionals (even if it does not fit into uint64)
testing "awk OFMT='R%%:%f!' 2**128" \
"awk -v OFMT='R%%:%f!' 'BEGIN { print 2**128; }'" "340282366920938463463374607431768211456\n" "" ""
-testing "awk OFMT='R%%:%f!' 2**128" \
+testing "awk OFMT='R%%:%f!' -2**129" \
"awk -v OFMT='R%%:%f!' 'BEGIN { print -2**129; }'" "-680564733841876926926749214863536422912\n" "" ""
# OFMT can contain no %SPEC (be a literal):