tcpdump mailing list archives

Re: [tcpdump] About HAVE_NO_PRINTF_Z


From: Guy Harris via tcpdump-workers <tcpdump-workers () lists tcpdump org>
Date: Thu, 12 Jan 2023 00:10:22 -0800

--- Begin Message --- From: Guy Harris <gharris () sonic net>
Date: Thu, 12 Jan 2023 00:10:22 -0800
On Jan 11, 2023, at 11:06 PM, Guy Harris via tcpdump-workers <tcpdump-workers () lists tcpdump org> wrote:

On UN*Xes, the C library is typically the system API library, so it's bundled with the OS rather than the compiler, 
so I don't know whether this is an issue of Sun C 5.9 or SunOS 5.9 (the core OS part of Solaris 9).

Solaris 9 printf() man page:

        https://docs.oracle.com/cd/E19683-01/816-0213/6m6ne387j/index.html

"An optional h specifies that a following d, i, o, u, x, or X conversion character applies to a type short int or type 
unsigned short int argument (the argument will be promoted according to the integral promotions, and its value 
converted to type short int or unsigned short int before printing); an optional h specifying that a following n 
conversion character applies to a pointer to a type short int argument; an optional l (ell) specifying that a following 
d, i, o, u, x, or X conversion character applies to a type long int or unsigned long int argument; an optional l (ell) 
specifying that a following n conversion character applies to a pointer to a type long int argument; an optional ll 
(ell ell) specifying that a following  d, i, o, u, x, or X conversion character applies to a type long long or unsigned 
long long argument; an optional ll (ell ell) specifying that a following n conversion character applies to a pointer to 
a long long argument; or an optional L specifying that a following e, E, f, g, or G conversion character applies to a 
type long double argument. If an h, l, ll, or L appears with any other conversion character, the behavior is undefined."

No mention of z.

Solaris 10 printf() man page:

        https://docs.oracle.com/cd/E19253-01/816-5168/6mbb3hrj1/index.html

"Length Modifiers

        The length modifiers and their meanings are:

                ...

        z

                Specifies that a following d, i, o, u, x, or X conversion specifier applies to a size_t or the 
corresponding signed integer type argument; or that a following n conversion specifier applies to a pointer to a signed 
integer type corresponding to size_t argument."

So I suspect it's more like "C on Solaris 9 only supports %z if the compiler includes a library with a printf family 
that supports it and the compiler driver causes programs to be linked with that library before -lc; C on Solaris 10 and 
later supports %z even if the compiler relies on the system library for printf-family functions".

I don't know whether any C99-supporting versions of GCC, when built on Solaris 9 for Solaris 9, provides their own 
printf-family functions with %z support.  The GCC 4.6.4 manual says, in section 2 "Language Standards Supported by GCC":

        https://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/Standards.html#Standards

in subsection 2.1 "C language":

        The ISO C standard defines (in clause 4) two classes of conforming implementation. A conforming hosted 
implementation supports the whole standard including all the library facilities; a conforming freestanding 
implementation is only required to provide certain library facilities: those in <float.h>, <limits.h>, <stdarg.h>, and 
<stddef.h>; since AMD1, also those in<iso646.h>; and in C99, also those in <stdbool.h> and <stdint.h>. In addition, 
complex types, added in C99, are not required for freestanding implementations. The standard also defines two 
environments for programs, a freestanding environment, required of all implementations and which may not have library 
facilities beyond those required of freestanding implementations, where the handling of program startup and termination 
are implementation-defined, and a hosted environment, which is not required, in which all the library facilities are 
provided and startup is through a function int main (void) or int main (int, char *[]). An OS kernel would be a 
freestanding environment; a program using the facilities of an operating system would normally be in a hosted 
implementation.

        GCC aims towards being usable as a conforming freestanding implementation, or as the compiler for a conforming 
hosted implementation. By default, it will act as the compiler for a hosted implementation, defining __STDC_HOSTED__ as 
1 and presuming that when the names of ISO C functions are used, they have the semantics defined in the standard. To 
make it act as a conforming freestanding implementation for a freestanding environment, use the option -ffreestanding; 
it will then define __STDC_HOSTED__ to 0 and not make assumptions about the meanings of function names from the 
standard library, with exceptions noted below. To build an OS kernel, you may well still need to make your own 
arrangements for linking and startup. See Options Controlling C Dialect.

        GCC does not provide the library facilities required only of hosted implementations, nor yet all the facilities 
required by C99 of freestanding implementations; to use the facilities of a hosted environment, you will need to find 
them elsewhere (for example, in the GNU C library). See Standard Libraries.

So a conforming freestanding implementation does *not* have to support any of the printf-family routines (something 
else can provide them, e.g. at least some UN*X kernels provide their own version of sprintf()), and GCC does not 
provide printf-family routines, as they're required only of hosted implementations.  "Standard Libraries" links to 
section 11.6 "Standard Libraries":

        https://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/Standard-Libraries.html#Standard-Libraries

which says:

        GCC by itself attempts to be a conforming freestanding implementation. See Language Standards Supported by GCC, 
for details of what this means. Beyond the library facilities required of such an implementation, the rest of the C 
library is supplied by the vendor of the operating system. If that C library doesn't conform to the C standards, then 
your programs might get warnings (especially when using -Wall) that you don't expect.

        For example, the sprintf function on SunOS 4.1.3 returns char * while the C standard says that sprintf returns 
an int. The fixincludes program could make the prototype for this function match the Standard, but that would be wrong, 
since the function will still return char *.

        If you need a Standard compliant library, then you need to find one, as GCC does not provide one. The GNU C 
library (called glibc) provides ISO C, POSIX, BSD, SystemV and X/Open compatibility for GNU/Linux and HURD-based GNU 
systems; no recent version of it supports other systems, though some very old versions did. Version 2.2 of the GNU C 
library includes nearly complete C99 support. You could also ask your operating system vendor if newer libraries are 
available.

So merely having GCC 4.6.4 as your compiler doesn't affect whether %z is supported; %z will not work on Solaris 9 and 
will work on Solaris 10.

So, if we care about %z support:

        on UN*Xes, we'd have to drop support for OSes that don't provide a C library that supports it;

        on Windows with MSVC, we'd have to require a version of MSVC whose library supports it (which I think we do);

        on Windows with other compilers, it depends on whether they provide their own library providing printf-family 
functions, in which case we'd have to require a compiler version with a library that supports %z, or they use the MSVC 
library, in which case we'd have to require that a version of the library be the one used.

(The C library was not part of Windows until the Universal C Runtime.  Prior to that, a lot of programs were either 
statically linked with the C runtime or had an installer that ran Microsoft's installer for the appropriate Visual C 
runtime.  The Universal C Runtime:

        https://devblogs.microsoft.com/cppblog/introducing-the-universal-crt/

is distributed with Windows; it includes "all of the purely library parts of the CRT", with the remainder, the 
VCRuntime, which is, I think, still distributed with Visual Studio and which is not, I think, guaranteed to be 
compiler-independent, "[contains] the compiler support functionality required for things like process startup and 
exception handling".  I suspect the idea is that you link statically with the VCRuntime, just as you link with crt0.o 
or whatever the equivalent is called with your compiler/OS on UN*X, and can link dynamically with the Universal C 
Runtime.)

--- End Message ---
_______________________________________________
tcpdump-workers mailing list
tcpdump-workers () lists tcpdump org
https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers

Current thread: