builtins/printf: use wcsto[i,u]max, check EINVAL, add test

This fixes #9321

IEEE Std 1003.1-2017 Issue 6 added optional error condition
[EINVAL] for if no conversion could be performed.

Switch back to wcstoimax/wcstoumax: do not work around the old FreeBSD
8 issue.

Add a test for printf '%d %d' 1 2 3
This commit is contained in:
Aaron Gyes 2022-10-31 19:50:17 -07:00
parent 8168ed7bf6
commit 1a0d6ebe59
2 changed files with 8 additions and 5 deletions

View file

@ -53,6 +53,7 @@
#include "printf.h"
#include <cerrno>
#include <cinttypes>
#include <climits>
#include <cstdarg>
#include <cstdint>
@ -174,7 +175,7 @@ void builtin_printf_state_t::append_format_output(const wchar_t *fmt, ...) {
}
void builtin_printf_state_t::verify_numeric(const wchar_t *s, const wchar_t *end, int errcode) {
if (errcode != 0) {
if (errcode != 0 && errcode != EINVAL) {
if (errcode == ERANGE) {
this->fatal_error(L"%ls: %ls", s, _(L"Number out of range"));
} else {
@ -201,16 +202,14 @@ void builtin_printf_state_t::verify_numeric(const wchar_t *s, const wchar_t *end
template <typename T>
static T raw_string_to_scalar_type(const wchar_t *s, wchar_t **end);
// we use wcstoll instead of wcstoimax because FreeBSD 8 has busted wcstoumax and wcstoimax - see
// #626
template <>
intmax_t raw_string_to_scalar_type(const wchar_t *s, wchar_t **end) {
return std::wcstoll(s, end, 0);
return std::wcstoimax(s, end, 0);
}
template <>
uintmax_t raw_string_to_scalar_type(const wchar_t *s, wchar_t **end) {
return std::wcstoull(s, end, 0);
return std::wcstoumax(s, end, 0);
}
template <>

View file

@ -1,5 +1,9 @@
# RUN: %fish %s
printf "%d %d\n" 1 2 3
# CHECK: 1 2
# CHECK: 3 0
printf "Hello %d %i %f %F %g %G\n" 1 2 3 4 5 6
# CHECK: Hello 1 2 3.000000 4.000000 5 6