Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 22 Mar 2015 08:46:01 -0700
From:      Mark Millard <markmi@dsl-only.net>
To:        Dimitry Andric <dim@FreeBSD.org>
Cc:        freebsd-current@freebsd.org, FreeBSD PowerPC ML <freebsd-ppc@freebsd.org>
Subject:   Re: 11.0-CURRENT -r276514: lib/libpjdlog/pjdlog.c has <stdarg.h> after <printf.h>
Message-ID:  <CBF924DC-A144-42A0-8141-C51C8C90211B@dsl-only.net>
In-Reply-To: <DDD27E04-BA1A-49AF-A5DC-6490E0C10EED@FreeBSD.org>
References:  <17E1F4C9-EB45-4A14-B3A6-97B016A8AD4D@dsl-only.net> <DDD27E04-BA1A-49AF-A5DC-6490E0C10EED@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Dimitry Adnric wrote:

> You should be able to include standard headers (or at least, headers =
in
> /usr/include) in any order, and <printf.h> includes <stdio.h>, which
> then defines the correct types.


Another of the ANSI/ISO-C rules is: You must include a standard header =
before you refer to anything that it officially defines or declares. =
(The Standard C Library by P. J. Plauger, Copyright 1992, page 7, 3rd =
bullet under "using headers".)

Part of that status is tied to the following: In a correct ANSI/ISO-C =
implementation <stdio.h> defines one or more synonyms for va_list using =
names from the class of reserved-to-implementation names in order to =
declare vprintf, vfprintf, and vsprintf. But <stdio.h> does not declare =
va_list itself. No ANSI/ISO-C header is allowed to declare/define extra =
official-public-name items that are only officially from other headers. =
(Page 12.)

[There are also 2 more major principles for standard headers: mutual =
independence (so order-independence) and idempotent status =
(repeatability).]


Only <stdargs.h> is allowed to declare that exact name (va_list) --the =
synonym with the official, public name. va_list is one of many things =
with this private-name vs public-name synonym structure in ANSI/ISO-C.



<printf.h> is not one of the 24 (C99) or so ANSI/ISO-C standard headers =
(by name). Nor is __xvprintf from the C standard.

So the #include <printf> that I referenced is violating the standard by =
referring to something from <stdargs.h> before that header has been =
included.

The existing source code is in error relative to ANSI/ISO-C.


Also: Using the order

#include <stdarg.h>
#include <printf.h>

in pjdlog.c does get rid of the problem. (As it should, per the above.)


But I do not know that there is any official claim that the environment =
is to strictly follow ANSI/ISO-C for such points. There may be other =
principles instead.



How comprehensive/complete is /usr/include header analogy to the =
ANSI/ISO-C rules? Does FreeBSD bother with having the private-named =
synonyms for headers that do not official declare/define something? Is =
FreeBSD as explicit as ANSI/ISO-C about where official definitions are =
and are not in headers? (Idempotent headers are the easier part to set =
up. Mutual-independence gets into private-named synonym techniques in =
order to deal with public names being only in the official places.)

(ANSI/ISO-C does have examples of some specific things explicitly being =
declared/defined (public names) in more than one header: more examples =
where using reserved-name guard macros to gain idempotent status and =
order independence can be done.)


Note: Much of my background information for this and the terminology =
that I use is from The Standard C Library by P. J. Plauger, Copyright =
1992. But I've not noticed any later ANSI/ISO material indicating the =
the above has changed status in more recent vintages of the standard. I =
could be wrong since I've not tried to be comprehensive about analyzing =
changes.

=3D=3D=3D
Mark Millard
markmi at dsl-only.net

On 2015-Mar-22, at 05:14 AM, Dimitry Andric <dim at FreeBSD.org> wrote:

On 22 Mar 2015, at 03:45, Mark Millard <markmi at dsl-only.net> wrote:
...
> Looking at the sources suggests that <stdarg.h> is explicitly in the =
#include sequence too late to guarantee va_args a definition at the =
point of its use in #include <printf.h> : <stdarg.h> is #include'd in =
pjdlog.c in the line after #include <printf.h> and printf.h itself does =
not (directly) include stdarg.h .
>=20
> /usr/include/printf.h (the LOOK HERE is my message editing) :
>> ...
>> #include <stdio.h>
>> #include <wchar.h>  /// <<<<< LOOK HERE for lack of <stdarg.h>
>> ...
>> int __xvprintf(FILE *fp, const char *fmt0, va_list ap);
>> ...
>=20
> /usr/srcC/lib/libpjdlog/pjdlog.c (the LOOK HERE's are my message =
editing) :
>> ...
>> #include <sys/cdefs.h>
>> __FBSDID("$FreeBSD: head/lib/libpjdlog/pjdlog.c 258791 2013-12-01 =
09:41:06Z pjd $");
>>=20
>> #include <sys/types.h>
>> #include <sys/socket.h>
>> #include <sys/un.h>
>> #include <netinet/in.h>
>> #include <arpa/inet.h>
>>=20
>> #include <assert.h>
>> #include <errno.h>
>> #include <libutil.h>
>> #include <limits.h>
>> #include <printf.h>  /// <<<<< LOOK HERE
>> #include <stdarg.h>  /// <<<<< LOOK HERE for stdarg.h vs. printf.h =
order

You should be able to include standard headers (or at least, headers in
/usr/include) in any order, and <printf.h> includes <stdio.h>, which
then defines the correct types.

However, there is a problem in the gcc ports.  What happens, is that the
gcc port uses its *own* munged versions of stdio.h and stdarg.h, and
includes them instead of the system versions.  For example, the gcc 4.7
port has this "fixed" version of stdio.h:

=
/usr/local/lib/gcc47/gcc/i386-portbld-freebsd11.0/4.7.4/include-fixed/stdi=
o.h

which explicitly *disables* our declaration of __va_list (the type which
va_list is based on):

 typedef __va_list __not_va_list__;

For functions like vprintf(), it replaces __va_list by a GNU builtin
variant, for example:

 int      vprintf(const char * __restrict, __gnuc_va_list);

However, it does not properly declare the regular va_list type, and then
things break in interesting ways.

I think the ports should not attempt to "fix" our include files.

-Dimitry





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CBF924DC-A144-42A0-8141-C51C8C90211B>