mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 12:30:06 +00:00
128 lines
4.4 KiB
Awk
128 lines
4.4 KiB
Awk
|
# Testing of printf conversions.
|
||
|
# Copyright (C) 2024 Free Software Foundation, Inc.
|
||
|
# This file is part of the GNU C Library.
|
||
|
|
||
|
# The GNU C Library is free software; you can redistribute it and/or
|
||
|
# modify it under the terms of the GNU Lesser General Public
|
||
|
# License as published by the Free Software Foundation; either
|
||
|
# version 2.1 of the License, or (at your option) any later version.
|
||
|
|
||
|
# The GNU C Library is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
# Lesser General Public License for more details.
|
||
|
|
||
|
# You should have received a copy of the GNU Lesser General Public
|
||
|
# License along with the GNU C Library; if not, see
|
||
|
# <https://www.gnu.org/licenses/>.
|
||
|
|
||
|
BEGIN {
|
||
|
FS = ":"
|
||
|
}
|
||
|
|
||
|
/^prec:/ {
|
||
|
PREC = $2
|
||
|
next
|
||
|
}
|
||
|
|
||
|
/^val:/ {
|
||
|
val = $2
|
||
|
# Prepend "+" for +Inf or +NaN value lacking a sign, because gawk
|
||
|
# interpretes them as strings rather than numeric values in the
|
||
|
# non-bignum mode unless a sign has been explicitly given. Keep
|
||
|
# original 'val' for reporting.
|
||
|
value = gensub(/^(INF|NAN|inf|nan)/, "+\\1", 1, val)
|
||
|
next
|
||
|
}
|
||
|
|
||
|
/^%/ {
|
||
|
# Discard the trailing empty field, used to improve legibility of data.
|
||
|
input = $--NF
|
||
|
format = $1
|
||
|
width = $2
|
||
|
precision = "." $(NF - 1)
|
||
|
# Discard any negative precision, which is to be taken as if omitted.
|
||
|
sub(/\.-.*/, "", precision)
|
||
|
# Simplify handling and paste the precision and width specified as
|
||
|
# arguments to '*' directly into the format.
|
||
|
sub(/\.\*/, precision, format)
|
||
|
sub(/\*/, width, format)
|
||
|
# Discard length modifiers. They are only relevant to C data types.
|
||
|
sub(/([DHLjhltz]|wf?[1-9][0-9]*)/, "", format)
|
||
|
# 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/)
|
||
|
{
|
||
|
tmpfmt = gensub(/#/, "", "g", format)
|
||
|
tmpout = sprintf(tmpfmt, value)
|
||
|
if (tmpout ~ /^ *0/)
|
||
|
format = tmpfmt
|
||
|
}
|
||
|
# 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]/)
|
||
|
{
|
||
|
tmpfmt = gensub(/#/, "", "g", format)
|
||
|
tmpout = sprintf(tmpfmt, value)
|
||
|
if (tmpout ~ /^ *$/)
|
||
|
format = tmpfmt
|
||
|
}
|
||
|
# AWK interpretes input opportunistically as a number, which interferes
|
||
|
# with how the 'c' conversion works: "a" input will result in "a" output
|
||
|
# however "0" input will result in "^@" output rather than "0". Force
|
||
|
# the value to be interpreted as a string then, by appending "".
|
||
|
output = sprintf(format, value "")
|
||
|
# Make up for various anomalies with the handling of +/-Inf and +/-NaN
|
||
|
# 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)/)
|
||
|
{
|
||
|
minus = format ~ /-/ ? "-" : ""
|
||
|
sign = value ~ /-/ ? "-" : format ~ /\+/ ? "+" : format ~ / / ? " " : ""
|
||
|
if (format ~ /^%[^\.1-9]*[1-9][0-9]*/)
|
||
|
width = gensub(/^%[^\.1-9]*([1-9][0-9]*).*$/, "\\1", 1, format)
|
||
|
else
|
||
|
width = ""
|
||
|
output = gensub(/[-+ ]/, "", "g", output)
|
||
|
output = sprintf("%" minus width "s", sign output)
|
||
|
}
|
||
|
# Produce "+" where the '+' flag has been used with a signed integer
|
||
|
# conversion for zero value, observing any field width in effect.
|
||
|
# 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)
|
||
|
{
|
||
|
output = gensub(/^( *) $/, format ~ /-/ ? "+\\1" : "\\1+", 1, output)
|
||
|
output = gensub(/^$/, "+", 1, output)
|
||
|
}
|
||
|
# Produce " " where the space flag has been used with a signed integer
|
||
|
# 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)
|
||
|
{
|
||
|
output = gensub(/^$/, " ", 1, output)
|
||
|
}
|
||
|
if (output != input)
|
||
|
{
|
||
|
printf "(\"%s\"%s%s, %s) => \"%s\", expected \"%s\"\n", \
|
||
|
$1, (NF > 2 ? ", " $2 : ""), (NF > 3 ? ", " $3 : ""), val, \
|
||
|
input, output > "/dev/stderr"
|
||
|
status = 1
|
||
|
}
|
||
|
next
|
||
|
}
|
||
|
|
||
|
{
|
||
|
printf "unrecognized input: \"%s\"\n", $0 > "/dev/stderr"
|
||
|
status = 1
|
||
|
}
|
||
|
|
||
|
END {
|
||
|
exit status
|
||
|
}
|