--- Begin Message ---
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 ---