[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: supporting strings > 2 GB
From: |
Paul Eggert |
Subject: |
Re: supporting strings > 2 GB |
Date: |
Sun, 13 Oct 2019 11:32:49 -0700 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.9.0 |
On 10/13/19 10:38 AM, Bruno Haible wrote:
The type printf_len_t is meant to allow the user to write code that works with
and without _PRINTF_LARGE.
By "the user" do you mean a user of an improved POSIX API for printf-like
functions, or a user of a Gnulib wrapper around the improved POSIX API? If the
former, I'm not quite following. If the latter, then I do follow; but we need to
make it clear which part of the change is the former and which is for the
latter, if we ever want to change POSIX and/or ISO C.
1) It would be wrong to write
int ret = printf (...);
because without _PRINTF_LARGE this code will truncate the printf result.
For this particular case, portable code could use 'ptrdiff_t' instead of 'int';
this would be portable enough as it would work regardless of whether printf is
old-style or new-style (except on weird platforms where PTRDIFF_MAX < INT_MAX,
which I don't think we need to worry about).
The type and macro allow to write these as
printf_len_t ret = printf (...);
printf_len_t len;
if (len > PRINTF_LEN_MAX)
fail ();
Sorry, I don't follow this. I thought PRINTF_LEN_MAX was intended to be the
maximum value that can be stored into printf_len_t, in which case 'len >
PRINTF_LEN_MAX' must yield 0. If the intent is something else, then these types
and/or macros probably need different names, to avoid confusion with
longstanding naming practice elsewhere.
There is no need to reserve a new length modifier and/or macros like PRIdPRINTF
and SCNdPRINTF, because the type and macro are only a convenience.
So if I want to print a printf_len_t I must first convert it to intmax_t and
print that? I don't see the convenience here, but perhaps that's because I don't
understand the intent of printf_len_t and PRINTF_LEN_MAX.
Would %ln work only for the new *l functions, or would it also work for the
already-standard printf functions?
The existing printf functions are left unchanged: Since the entire result
may not be longer than INT_MAX bytes, it makes no sense to add provisions
for returning an index > INT_MAX or using a format directive with width
or precision > INT_MAX.
printf already has provisions for width or precision > INT_MAX; one can do
'printf ("%2147483648d", 0)', for example. These calls are a corner case that
fail, but that's OK. Attempting to use '**' with old printf could fail in a
similar way.
Perhaps it would be simpler if the new *l functions use ptrdiff_t everywhere
that the old functions use 'int' for sizes and widths. Then we wouldn't have to
worry about '**' vs '*', or about '%ln' versus '%n'. The Gnulib layer could
resolve whether the functions are about int or ptrdiff_t.
But then the valid format strings for the *l functions would not be
a superset of the valid format strings for the existing *printf functions.
Why a superset? Shouldn't the sets of format strings be the same, so that
programmers can easily switch back and forth between the two sets of functions?
For example, if you have code that generates a format string, it would be nicer
if you could use that same format string regardless of whether you pass it to
printf or to lprintf.
One of the goals is that programmers can use the new facility just be
importing the respective gnulib modules and doing
#define _PRINTF_LARGE 1
without reviewing every format string.
Yes, and that goal is furthered by having the two sets of functions accept the
same format strings.
Regarding the naming: I'm now tending towards 'lprintf' and 'flprintf',
to make it look like 'wprintf' and 'fwprintf'.
Yes, that sounds better than the first proposal.