Date: Sat, 24 Oct 2020 21:40:44 +0900 From: Rin Okuyama <rokuyama...@gmail.com> Message-ID: <e1dae284-3666-c343-ef93-be463a6ee...@gmail.com>
| However, this result apparently depends on width of intmax_t. Is this | behavior acceptable by POSIX? Two things: This from POSIX (actually from a draft that will, perhaps modified, become the next revision of the standard): If an argument operand cannot be completely converted into an internal value appropriate to the corresponding conversion specification, a diagnostic message shall be written to standard error and the utility shall not exit with a zero exit status, but shall continue processing any remaining operands and shall write the value accumulated at the time the error was detected to standard output. and, on the same point, somewhat later: If an argument cannot be parsed correctly for the corresponding conversion specification, the printf utility is required to report an error. Thus, overflow and extraneous characters at the end of an argument being used for a numeric conversion shall be reported as errors. 0xffffc00000000000 is too big for an intmax_t data type, it overflows. It is a large positive number, not a negative one. You can print it using %u or %x (even %o if you want), but not, without an error message, using %d. Second, I can find nothing in POSIX (which doesn't mean it isn't there, it is a large doc) which even hints at what range of integers need to be supported by printf(1). It may even be that strictly we're only supposed to be able to print an "int" (not a long int, not a long long int, or any other variety) as the formats for printf(1) don't include any of the length modifiers that printf(3) supports, all it can print are (signed or unsigned) integers. Perhaps anything bigger than 2^31-1 should report an error. | I think intmax_t is 64bit-width for all platforms that we currently | support. But, test cases (included in the patch above) can assume this? You shouldn't, we'll get something with 128 bit intmax_t's one day. | If not, how can we obtain sizeof(intmax_t) from portable shell scripts? No way I'm aware of, I'm not even sure that giving a huge integer to printf, ignoring the error, and looking at what is printed works to discover what printf can handle. Current implementations seem to do that, set the value to the max possible on overflow, but that might actually be violating the standard, if we use printf '%d\n' 0xffffc0000000000 we get 1152917106560335872 when one more 0 is added, we get overflow - a plausible reading of the standard could be that when that overflow happens, the "value accumulated at the time the error was detected' could be regarded as that one (115....) and not 2^63-1 which is what we actually report. (The 115... value is what zsh produces, everything else I tested gives the same as us, but for many of the shells that's not surprising, as they don't all have printf built in. and are simply executing our /usr/bin/printf). kre ps: I will see if I can elicit any answers to the missing parts. And if you really want: $ printf '%d\n' 0xffffc00000000000 -70368744177664 use ksh93, that's what it does, but it is unquestionably broken.