[Top][All Lists]

[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.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]