Hi Hrvoje :))

 * Hrvoje Niksic <[EMAIL PROTECTED]> dixit:
> There have been several attempts to fix this:
[...]
> * In its own patches, Debian introduced the use of large file APIs and
>   `long long'.  While that's perfectly fine for Debian, it is not
>   portable.  Neither the large file API nor `long long' are
>   universally available, and both need thorough configure checking.

    Yes, you're true, but... How about using C99 large integer types
(intmax_t and family)? I know, is not universally available, but if
you support obsolete systems IMHO you should do in a last resort way.
I mean, use large file API or intmax_t on every system that supports
it (all systems with a not-so-recent GNU C compiler), long long on
the rest and long as the last resort. It's not very complicated to do
so in autoshi^H^H^Hconf, and wget will support really huge files in
most of systems (those with a GNU C compiler and those with long long
support), and normal files on the rest.

> Of those two issues, choosing and using the numeric type is the hard
> one.  Autoconf helps only to an extent -- even if you define your own
> `large_number_t' typedef, which is either `long' or `long long', the
> question remains how to print that number.

    If you use intmax_t, the problem is solved because C99 has a
%-format for them. If you use long long and gcc, the same happens
AFAIK. The problem is that you don't have an universal format for all
those types... You should write a printf wrapper or a special
function for printing those numbers.

> 1. Concatenation of adjacent string literals is an ANSI feature and
>    would break pre-ANSI compilers.

    You're true again, but you can wrap it in a macro and use '##'.
Or you can stop supporting pre-ANSI compilers. How many users will
this affect (more or less).

> 2. It breaks gettext.  With translation support, the above code would
>    look like this:

    Yes, gettext is far from perfect :(((( The solution is to do the
conditional preprocessing above directly on the code, so you have
three (or more, as needed) printf lines with legal-gettext code in
them:

#ifdef CRAP_SYSTEM
printf(_("Whatever %d\n"), num);
#elif defined A_BIT_BETTER_SYSTEM
printf(_("Whatever %lld\n", num);
#else
/* We have a good system */
printf(_("Whatever %j\n", num);
#endif

    Yes, looks ugly, is crap, but... 

> The bottom line is, I really don't know how to solve this portably.

    IMHO, the best solution is to use a big unsigned type for sums,
totals, sizes to print, etc... and use a large file API for reading
and write large files. If the large file API doesn't exist, use off_t
anyway. Provide a function for printing off_t's and just make sure
that the type for sums is larger than off_t if possible, otherwise
use off_t too (I suppose that autoconf can help you in this).

    Normally I use 'size_t' or 'uintmax_t' for sizes to print, sums,
totals, etc... and off_t for files, because an off_t, being signed,
will be shorter than the uintmax type for sure, although you can
always use bignum libraries. The bignum libraries (well, pick up just
the code for additions, for example) will help you with half of the
problem. The other half, reading/writing large files, must be
provided by the system. Just define _LARGEFILE64 (or whatever is the
macro called in SuSv3 or POSIX) and use off_t and an small function
for printing them (although off_t is opaque and if you want full
portability you should not use it directly...).

    That's the better I can get, because when I wrote portable code,
by portable I understand 'according to standards'. For me that means,
in that order: SuSv3, POSIX, C99, C89, stop. No pre-ANSI and no brain
damaged compilers.

> Does anyone know how widely ported software deals with large files?

    No idea, sorry :((( And thanks for the work you're doing with
wget, we all benefit from.

    Raúl Núñez de Arenas Coronado

-- 
Linux Registered User 88736
http://www.pleyades.net & http://raul.pleyades.net/

Reply via email to