[2/2] stdio-common: avoid repeated regexp matches in tst-printf-format.awk
Checks
| Context |
Check |
Description |
| redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
| linaro-tcwg-bot/tcwg_glibc_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_glibc_check--master-arm |
fail
|
Test failed
|
| linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 |
fail
|
Test failed
|
Commit Message
Whether the value is an infinity, a NaN or zero does not change between
the conversions applied to it, but was determined again for each one.
Determine it where the value is read.
Also look for the '#' flag with index() before matching the expressions
that need it, and test the value first where both have to hold.
For the %f conversion for double, in the C locale, as the median of five
runs:
x86_64, gawk 5.4.1 1.248s -> 1.184s
x86_64, gawk 5.3.2 0.703s -> 0.708s
alpha, gawk 5.4.60 26.6s -> 25.8s
So this only helps with the regular expression engine that gawk 5.4
brought in; under 5.3.2 it is lost in the noise. Output and exit status
are unchanged for the e, f and g conversions for double under both
gawk versions and both locales.
---
stdio-common/tst-printf-format.awk | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
Comments
On 03/08/26 22:59, Matt Turner wrote:
> Whether the value is an infinity, a NaN or zero does not change between
> the conversions applied to it, but was determined again for each one.
> Determine it where the value is read.
>
> Also look for the '#' flag with index() before matching the expressions
> that need it, and test the value first where both have to hold.
>
> For the %f conversion for double, in the C locale, as the median of five
> runs:
>
> x86_64, gawk 5.4.1 1.248s -> 1.184s
> x86_64, gawk 5.3.2 0.703s -> 0.708s
> alpha, gawk 5.4.60 26.6s -> 25.8s
>
> So this only helps with the regular expression engine that gawk 5.4
> brought in; under 5.3.2 it is lost in the noise. Output and exit status
> are unchanged for the e, f and g conversions for double under both
> gawk versions and both locales.
LGTM, thanks.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> ---
> stdio-common/tst-printf-format.awk | 13 ++++++++-----
> 1 file changed, 8 insertions(+), 5 deletions(-)
>
> diff --git ./stdio-common/tst-printf-format.awk ./stdio-common/tst-printf-format.awk
> index 5d0324c551..57bea12621 100644
> --- ./stdio-common/tst-printf-format.awk
> +++ ./stdio-common/tst-printf-format.awk
> @@ -32,6 +32,9 @@ BEGIN {
> # non-bignum mode unless a sign has been explicitly given. Keep
> # original 'val' for reporting.
> value = gensub(/^(INF|NAN|inf|nan)/, "+\\1", 1, val)
> + # Neither changes between the conversions applied to this value.
> + value_infnan = value ~ /(INF|NAN|inf|nan)/
> + value_zero = value == 0
> next
> }
>
> @@ -52,7 +55,7 @@ BEGIN {
> # Discard the '#' flag with the octal conversion if output starts with
> # 0 in the absence of this flag. In that case no extra 0 is supposed
> # to be produced, but gawk prepends it anyway.
> - if (format ~ /#.*o/)
> + if (index(format, "#") && format ~ /#.*o/)
> {
> tmpfmt = gensub(/#/, "", "g", format)
> tmpout = sprintf(tmpfmt, value)
> @@ -62,7 +65,7 @@ BEGIN {
> # Likewise with the hexadecimal conversion where zero value with the
> # precision of zero is supposed to produce no characters, but gawk
> # outputs 0 instead.
> - else if (format ~ /#.*[Xx]/)
> + else if (index(format, "#") && format ~ /#.*[Xx]/)
> {
> tmpfmt = gensub(/#/, "", "g", format)
> tmpout = sprintf(tmpfmt, value)
> @@ -78,7 +81,7 @@ BEGIN {
> # values and reprint the output produced using the string conversion,
> # with the field width carried over and the relevant flags handled by
> # hand.
> - if (format ~ /[EFGefg]/ && value ~ /(INF|NAN|inf|nan)/)
> + if (value_infnan && format ~ /[EFGefg]/)
> {
> minus = format ~ /-/ ? "-" : ""
> sign = value ~ /-/ ? "-" : format ~ /\+/ ? "+" : format ~ / / ? " " : ""
> @@ -94,7 +97,7 @@ BEGIN {
> # In that case "+" is always supposed to be produced, but with the
> # precision of zero gawk in the non-bignum mode produces any padding
> # requested only.
> - else if (format ~ /\+.*[di]/ && value == 0)
> + else if (value_zero && format ~ /\+.*[di]/)
> {
> output = gensub(/^( *) $/, format ~ /-/ ? "+\\1" : "\\1+", 1, output)
> output = gensub(/^$/, "+", 1, output)
> @@ -103,7 +106,7 @@ BEGIN {
> # conversion for zero value. In that case at least one " " is
> # supposed to be produced, but with the precision of zero gawk in the
> # non-bignum mode produces nothing.
> - else if (format ~ / .*[di]/ && value == 0)
> + else if (value_zero && format ~ / .*[di]/)
> {
> output = gensub(/^$/, " ", 1, output)
> }
@@ -32,6 +32,9 @@ BEGIN {
# non-bignum mode unless a sign has been explicitly given. Keep
# original 'val' for reporting.
value = gensub(/^(INF|NAN|inf|nan)/, "+\\1", 1, val)
+ # Neither changes between the conversions applied to this value.
+ value_infnan = value ~ /(INF|NAN|inf|nan)/
+ value_zero = value == 0
next
}
@@ -52,7 +55,7 @@ BEGIN {
# Discard the '#' flag with the octal conversion if output starts with
# 0 in the absence of this flag. In that case no extra 0 is supposed
# to be produced, but gawk prepends it anyway.
- if (format ~ /#.*o/)
+ if (index(format, "#") && format ~ /#.*o/)
{
tmpfmt = gensub(/#/, "", "g", format)
tmpout = sprintf(tmpfmt, value)
@@ -62,7 +65,7 @@ BEGIN {
# Likewise with the hexadecimal conversion where zero value with the
# precision of zero is supposed to produce no characters, but gawk
# outputs 0 instead.
- else if (format ~ /#.*[Xx]/)
+ else if (index(format, "#") && format ~ /#.*[Xx]/)
{
tmpfmt = gensub(/#/, "", "g", format)
tmpout = sprintf(tmpfmt, value)
@@ -78,7 +81,7 @@ BEGIN {
# values and reprint the output produced using the string conversion,
# with the field width carried over and the relevant flags handled by
# hand.
- if (format ~ /[EFGefg]/ && value ~ /(INF|NAN|inf|nan)/)
+ if (value_infnan && format ~ /[EFGefg]/)
{
minus = format ~ /-/ ? "-" : ""
sign = value ~ /-/ ? "-" : format ~ /\+/ ? "+" : format ~ / / ? " " : ""
@@ -94,7 +97,7 @@ BEGIN {
# In that case "+" is always supposed to be produced, but with the
# precision of zero gawk in the non-bignum mode produces any padding
# requested only.
- else if (format ~ /\+.*[di]/ && value == 0)
+ else if (value_zero && format ~ /\+.*[di]/)
{
output = gensub(/^( *) $/, format ~ /-/ ? "+\\1" : "\\1+", 1, output)
output = gensub(/^$/, "+", 1, output)
@@ -103,7 +106,7 @@ BEGIN {
# conversion for zero value. In that case at least one " " is
# supposed to be produced, but with the precision of zero gawk in the
# non-bignum mode produces nothing.
- else if (format ~ / .*[di]/ && value == 0)
+ else if (value_zero && format ~ / .*[di]/)
{
output = gensub(/^$/, " ", 1, output)
}