mirror of
https://github.com/fish-shell/fish-shell
synced 2024-11-10 15:14:44 +00:00
printf: Don't die on incomplete conversions
POSIX dictates here that incomplete conversions, like in printf %d\n 15.2 or printf %d 14g are still printed along with any error. This seems alright, as it allows users to silence stderr to accept incomplete conversions. This commit implements it, but what's a bit weird is the ordering between stdout and stderr, causing the error to be printed _after_, like 15 14 15.1: value not completely converted 14,2: value not completely converted but that seems like a general issue with how we buffer the streams. (I know that nonfatal_error is a copy of most of fatal_error - I tried differently, and va_* is weird) Fixes #5532.
This commit is contained in:
parent
aea4062906
commit
0bde698f81
5 changed files with 32 additions and 4 deletions
|
@ -18,6 +18,7 @@
|
|||
- `math` now accepts `--scale=max` for the maximum scale (#5579).
|
||||
- `complete --do-complete` now also does fuzzy matches (#5467).
|
||||
- `count` now also counts lines fed on stdin (#5744).
|
||||
- `printf` prints what it can when input hasn't been fully converted to a number, but still prints an error (#5532).
|
||||
|
||||
### Interactive improvements
|
||||
- Major improvements in performance and functionality to the 'sorin' sample prompt (#5411).
|
||||
|
|
|
@ -90,8 +90,10 @@ struct builtin_printf_state_t {
|
|||
|
||||
int print_formatted(const wchar_t *format, int argc, wchar_t **argv);
|
||||
|
||||
void nonfatal_error(const wchar_t *fmt, ...);
|
||||
void fatal_error(const wchar_t *format, ...);
|
||||
|
||||
|
||||
long print_esc(const wchar_t *escstart, bool octal_0);
|
||||
void print_esc_string(const wchar_t *str);
|
||||
void print_esc_char(wchar_t c);
|
||||
|
@ -193,6 +195,22 @@ static int octal_to_bin(wchar_t c) {
|
|||
}
|
||||
}
|
||||
|
||||
void builtin_printf_state_t::nonfatal_error(const wchar_t *fmt, ...) {
|
||||
// Don't error twice.
|
||||
if (early_exit) return;
|
||||
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
wcstring errstr = vformat_string(fmt, va);
|
||||
va_end(va);
|
||||
streams.err.append(errstr);
|
||||
if (!string_suffixes_string(L"\n", errstr)) streams.err.push_back(L'\n');
|
||||
|
||||
// We set the exit code to error, because one occured,
|
||||
// but we don't do an early exit so we still print what we can.
|
||||
this->exit_code = STATUS_CMD_ERROR;
|
||||
}
|
||||
|
||||
void builtin_printf_state_t::fatal_error(const wchar_t *fmt, ...) {
|
||||
// Don't error twice.
|
||||
if (early_exit) return;
|
||||
|
@ -207,7 +225,6 @@ void builtin_printf_state_t::fatal_error(const wchar_t *fmt, ...) {
|
|||
this->exit_code = STATUS_CMD_ERROR;
|
||||
this->early_exit = true;
|
||||
}
|
||||
|
||||
void builtin_printf_state_t::append_output(wchar_t c) {
|
||||
// Don't output if we're done.
|
||||
if (early_exit) return;
|
||||
|
@ -241,10 +258,12 @@ void builtin_printf_state_t::verify_numeric(const wchar_t *s, const wchar_t *end
|
|||
this->fatal_error(L"%ls: %s", s, std::strerror(errcode));
|
||||
}
|
||||
} else if (*end) {
|
||||
if (s == end)
|
||||
if (s == end) {
|
||||
this->fatal_error(_(L"%ls: expected a numeric value"), s);
|
||||
else
|
||||
this->fatal_error(_(L"%ls: value not completely converted"), s);
|
||||
} else {
|
||||
// This isn't entirely fatal - the value should still be printed.
|
||||
this->nonfatal_error(_(L"%ls: value not completely converted"), s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
2,34: value not completely converted
|
||||
0xABCDEF12345678901: Number out of range
|
||||
15.1: value not completely converted
|
||||
|
|
|
@ -72,3 +72,7 @@ printf 'long hex4 %X\n' 0xABCDEF12345678901
|
|||
printf 'long decimal %d\n' 498216206594
|
||||
printf 'long signed %d\n' -498216206595
|
||||
printf 'long signed to unsigned %u\n' -498216206596
|
||||
|
||||
# Verify numeric conversion still happens even if it couldn't be fully converted
|
||||
printf '%d\n' 15.1
|
||||
echo $status
|
||||
|
|
|
@ -16,6 +16,7 @@ a
|
|||
0000000 376
|
||||
0000001
|
||||
1.230000e+00
|
||||
2.000000e+00
|
||||
3,450000e+00
|
||||
4,560000e+00
|
||||
long hex1 73ffffff9a
|
||||
|
@ -24,3 +25,5 @@ long hex3 ABCDEF1234567890
|
|||
long hex4 long decimal 498216206594
|
||||
long signed -498216206595
|
||||
long signed to unsigned 18446743575493345020
|
||||
15
|
||||
1
|
||||
|
|
Loading…
Reference in a new issue