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. === 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 . > > /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); >> ... > > /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 $"); >> >> #include <sys/types.h> >> #include <sys/socket.h> >> #include <sys/un.h> >> #include <netinet/in.h> >> #include <arpa/inet.h> >> >> #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/stdio.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. -DimitryReceived on Sun Mar 22 2015 - 14:46:06 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:56 UTC