Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Must implementations support #include "foo.h"?

6 views
Skip to first unread message

Keith Thompson

unread,
Sep 10, 2009, 4:08:05 PM9/10/09
to
This came up during a discussion on comp.lang.c.

According to C99 6.19.2, this:

#include <foo.h>

searches for the specified header (not necessarily a file) in a
sequence of implementation-defined places. A conforming
implementation could restrict this search to places controlled by the
implementation, allowing it only for predefined headers.

Whereas this:

#include "foo.h"

does an implementation-defined search for the specified *file*, and if
that search fails it then acts like #include <foo.h>.

But here's the strange part:

The named source file is searched for in an implementation-defined
manner. If *this search is not supported*, or if the search fails,
the directive is reprocessed as if [...]

This seems to imply that an implementation needn't support a search
for user-defined header files, and that it could allow only predefine
headers for *either* form of #include, <> or "".

Of course an implementation with such a restriction would not be very
useful, but it seems to be permitted.

Am I reading this correctly? And is this really the intent?

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

David R Tribble

unread,
Sep 10, 2009, 6:50:09 PM9/10/09
to
Keith Thompson wrote:
> According to C99 6.19.2, this:
> #include "foo.h"
> does an implementation-defined search for the specified *file*, and if
> that search fails it then acts like #include <foo.h>.
> But here's the strange part:
> The named source file is searched for in an implementation-defined
> manner. If *this search is not supported*, or if the search fails,
> the directive is reprocessed as if [...]
> This seems to imply that an implementation needn't support a search
> for user-defined header files, and that it could allow only predefine
> headers for *either* form of #include, <> or "".

Is the requirement meant to cover implementations (I forget
the term, "freestanding"?) such as compilers for embedded
systems that don't provide a file system as such?

Or perhaps it was meant to cover systems such as OS/390,
which require a //dataset card to define all of the input files
within a batch compile job, and, technically, don't "search"
for any files.

Or, conceivably, an implementation could allow only #includes
of the standard headers.

-drt

Eric Sosman

unread,
Sep 10, 2009, 8:19:16 PM9/10/09
to
Keith Thompson wrote:
> This came up during a discussion on comp.lang.c.
>
> According to C99 6.19.2, this:
>
> #include <foo.h>
>
> searches for the specified header (not necessarily a file) in a
> sequence of implementation-defined places. A conforming
> implementation could restrict this search to places controlled by the
> implementation, allowing it only for predefined headers.
>
> Whereas this:
>
> #include "foo.h"
>
> does an implementation-defined search for the specified *file*, and if
> that search fails it then acts like #include <foo.h>.
>
> But here's the strange part:
>
> The named source file is searched for in an implementation-defined
> manner. If *this search is not supported*, or if the search fails,
> the directive is reprocessed as if [...]
>
> This seems to imply that an implementation needn't support a search
> for user-defined header files, and that it could allow only predefine
> headers for *either* form of #include, <> or "".
>
> Of course an implementation with such a restriction would not be very
> useful, but it seems to be permitted.
>
> Am I reading this correctly? And is this really the intent?

I believe your reading is correct: An implementation must
support #include for the Standard-mandated headers, but can
(in theory) get away with supporting no others.

It's a QoI issue ...

(In the Standard's defense, trying to define the nature of
the various searches would have opened a system-dependent can of
worms best left wriggling in confinement.)

--
Eric Sosman
eso...@ieee-dot-org.invalid

Keith Thompson

unread,
Sep 10, 2009, 10:37:07 PM9/10/09
to
David R Tribble <da...@tribble.com> writes:
> Keith Thompson wrote:
>> According to C99 6.19.2, this:
>> #include "foo.h"
>> does an implementation-defined search for the specified *file*, and if
>> that search fails it then acts like #include <foo.h>.
>> But here's the strange part:
>> The named source file is searched for in an implementation-defined
>> manner. If *this search is not supported*, or if the search fails,
>> the directive is reprocessed as if [...]
>> This seems to imply that an implementation needn't support a search
>> for user-defined header files, and that it could allow only predefine
>> headers for *either* form of #include, <> or "".
>
> Is the requirement meant to cover implementations (I forget
> the term, "freestanding"?) such as compilers for embedded
> systems that don't provide a file system as such?

I don't think so (and yes, "freestanding" is the right term). Header
files exist in the compilation environment, not in the execution
environment. Freestanding compilers are typically cross-compilers;
presumably the host system has a sufficiently capable file system.

> Or perhaps it was meant to cover systems such as OS/390,
> which require a //dataset card to define all of the input files
> within a batch compile job, and, technically, don't "search"
> for any files.

Hmm. I'd describe that as a trivial search that looks in only one
place.

> Or, conceivably, an implementation could allow only #includes
> of the standard headers.

See my next response.

Keith Thompson

unread,
Sep 10, 2009, 10:43:08 PM9/10/09
to
Eric Sosman <eso...@ieee-dot-org.invalid> writes:
> Keith Thompson wrote:
[snip]

>> But here's the strange part:
>>
>> The named source file is searched for in an implementation-defined
>> manner. If *this search is not supported*, or if the search fails,
>> the directive is reprocessed as if [...]
>>
>> This seems to imply that an implementation needn't support a search
>> for user-defined header files, and that it could allow only predefine
>> headers for *either* form of #include, <> or "".
>>
>> Of course an implementation with such a restriction would not be very
>> useful, but it seems to be permitted.
>>
>> Am I reading this correctly? And is this really the intent?
>
> I believe your reading is correct: An implementation must
> support #include for the Standard-mandated headers, but can
> (in theory) get away with supporting no others.
>
> It's a QoI issue ...

I don't think so. I realized after posting the original article that
this interpretation would contradict C99 5.2.4.1, which requires an
implementation to support (one program with) "15 nesting levels for
#included files". An implementation that only supported #include
for the standard headers could not meet that requirement.

> (In the Standard's defense, trying to define the nature of
> the various searches would have opened a system-dependent can of
> worms best left wriggling in confinement.)

There would be no need to define the nature of the search, just a
requirement that some kind of search is possible.

And here's something else I missed: C99 6.10.2p5 (it has a change bar;
I'm quoting n1256):

The implementation shall provide unique mappings for sequences
consisting of one or 5 more nondigits or digits (6.4.2.1)
followed by a period (.) and a single nondigit. The first
character shall not be a digit. The implementation may ignore
distinctions of alphabetical case and restrict the mapping to
eight significant characters before the period.

Again, this requirement would make no sense if #include were
permitted only for the standard-defined headers.

So what exactly is "If this search is not supported" supposed
to mean? What would be the characteristics of an implementation
that took advantage of that permission?

James Kuyper

unread,
Sep 10, 2009, 11:22:59 PM9/10/09
to

There are two ordered sets of places to be searched, call them A and B.
#include "header.h" searches the set A, in order, and searches area B
only if it doesn't find header.h in any of the places in set A. #include
<header.h> searches only the places in set B. The wording about "if
this search is not supported" merely means that A can be the empty set.

This does not preclude user-defined header files; it merely means that
they an implementation can search for them in the same sequence of
places, regardless of whether you use #include "" or #include <>.

Keith Thompson

unread,
Sep 11, 2009, 1:11:15 AM9/11/09
to

And a conforming implementation may *either* restrict set B so it
includes only standard headers, *or* it may make set A the empty set,
but not both.

Dag-Erling Smørgrav

unread,
Sep 11, 2009, 6:57:53 AM9/11/09
to
David R Tribble <da...@tribble.com> writes:
> Is the requirement meant to cover implementations (I forget the term,
> "freestanding"?) such as compilers for embedded systems that don't
> provide a file system as such?

The standard does speak of freestanding implementations, but they have
absolutely nothing to do with having a file system. A freestanding
implementation is quite simply is an implementation where:

- complex types are not available.

- only those parts of the library defined in <float.h>, <iso646.h>,
<limits.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, and <stdint.h> are
available.

- the entry point (i.e. the name, type and arguments of the function
called when the program starts) is implementation-defined.

- the effect of program termination is implementation-defined.

BTW, "embedded systems that don't provide a file system as such" rarely
provide a compiler; programs for these systems are usually compiled with
a cross-compiler that runs on a more capable system.

DES
--
Dag-Erling Smørgrav - d...@des.no

James Kuyper

unread,
Sep 11, 2009, 7:18:04 AM9/11/09
to
Dag-Erling Smørgrav wrote:
> David R Tribble <da...@tribble.com> writes:
>> Is the requirement meant to cover implementations (I forget the term,
>> "freestanding"?) such as compilers for embedded systems that don't
>> provide a file system as such?
>
> The standard does speak of freestanding implementations, but they have
> absolutely nothing to do with having a file system. A freestanding
> implementation is quite simply is an implementation where:
>
> - complex types are not available.
>
> - only those parts of the library defined in <float.h>, <iso646.h>,
> <limits.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, and <stdint.h> are
> available.

In both cases, "available" should be replaced with "required to be
available. The standard does not prohibit a freestanding implementation
from supporting complex types, or from providing the other headers.
However, because such an implementation is not required to do so, if it
does choose to do so, it might be in a way incompatible with the way the
standard requires those things to be done by a hosted implementation.

Tim Rentsch

unread,
Sep 29, 2009, 4:59:43 PM9/29/09
to
Keith Thompson <ks...@mib.org> writes:

> This came up during a discussion on comp.lang.c.
>
> According to C99 6.19.2, this:
>
> #include <foo.h>
>
> searches for the specified header (not necessarily a file) in a
> sequence of implementation-defined places. A conforming
> implementation could restrict this search to places controlled by the
> implementation, allowing it only for predefined headers.
>
> Whereas this:
>
> #include "foo.h"
>
> does an implementation-defined search for the specified *file*, and if
> that search fails it then acts like #include <foo.h>.
>
> But here's the strange part:
>
> The named source file is searched for in an implementation-defined
> manner. If *this search is not supported*, or if the search fails,
> the directive is reprocessed as if [...]
>
> This seems to imply that an implementation needn't support a search
> for user-defined header files, and that it could allow only predefine
> headers for *either* form of #include, <> or "".
>
> Of course an implementation with such a restriction would not be very
> useful, but it seems to be permitted.
>
> Am I reading this correctly? And is this really the intent?

[Of course the reference given is meant to be for 6.10.2.]

I believe the point of doing a search is that there may not
be a one-to-one correspondence between file names and files.
However, I think access to /some/ files, including "foo.h",
must be provided, because of 6.10.2p5:

The implementation shall provide unique mappings for sequences

consisting of one or more nondigits or digits (6.4.2.1) followed by a


period (.) and a single nondigit. The first character shall not be a
digit. The implementation may ignore distinctions of alphabetical
case and restrict the mapping to eight significant characters before
the period.

The "unique mapping" means a search for names meeting the
given requirements must have well-defined mechanism for
locating such names, and any files that correspond to
those names must be distinct.

Tim Rentsch

unread,
Sep 29, 2009, 5:07:10 PM9/29/09
to
Keith Thompson <ks...@mib.org> writes:

Suppose we saw a #include line like this:

#include "http:/ /somewhere.who-knows/brilliant-header.h"

The implementation might take that to mean, get a file off a
server somewhere using http:. However, if run on a machine
without a network stack, that search would not be supported.
The implementation defines the search, but the environment
running the implementation doesn't provide (ie, "support")
it.

Incidentally, it's reasonable to call it a search, because
a single domain name can map to multiple IP addresses.

Keith Thompson

unread,
Sep 29, 2009, 5:50:54 PM9/29/09
to
Tim Rentsch <t...@alumni.caltech.edu> writes:
> Keith Thompson <ks...@mib.org> writes:
[...]

>>> Keith Thompson wrote:
>> [snip]
>>>> But here's the strange part:
>>>>
>>>> The named source file is searched for in an implementation-defined
>>>> manner. If *this search is not supported*, or if the search fails,
>>>> the directive is reprocessed as if [...]
>>>>
>>>> This seems to imply that an implementation needn't support a search
>>>> for user-defined header files, and that it could allow only predefine
>>>> headers for *either* form of #include, <> or "".
[snip]

>> So what exactly is "If this search is not supported" supposed
>> to mean? What would be the characteristics of an implementation
>> that took advantage of that permission?
>
> Suppose we saw a #include line like this:
>
> #include "http:/ /somewhere.who-knows/brilliant-header.h"
>
> The implementation might take that to mean, get a file off a
> server somewhere using http:. However, if run on a machine
> without a network stack, that search would not be supported.
> The implementation defines the search, but the environment
> running the implementation doesn't provide (ie, "support")
> it.
>
> Incidentally, it's reasonable to call it a search, because
> a single domain name can map to multiple IP addresses.

Hmm. I'm not convinced that that's what it means. I assumed, and
still assume, that if "this search is not supported", it means the
implementation doesn't support searching at all. The standard doesn't
go into enough detail (any at all) about what kind of search is done
for it to make sense to say that one kind of search is supported and
another isn't.

I would think that would be covered by "or if the search fails".

My conclusion a while ago, when I thought this discussion had ended
8-)}, was that an implementation must *either* support the search
*or* permit user header files to be placed where <> can find them.
But even that doesn't make a whole lot of sense.

Tim Rentsch

unread,
Oct 2, 2009, 1:16:26 AM10/2/09
to
Tim Rentsch <t...@alumni.caltech.edu> writes:

On further reflection I withdraw my previous comment.
Perhaps it's true that 6.10.2p5 is relevant, but I
can't offer any convincing line of reasoning that
this is the best answer to the question.

I now believe the remark about "if the search is not supported"
is a statement about the environment in which the implementation
is running, not about the implementation itself. For example,
there might be a #include with a file name including a version
number. The implementation might have system calls to do such a
lookup, but suppose it were on a system that didn't support
version numbers as part of file names (eg, a compiler written for
VAX VMS run on a non-VMS emulator). In a case like that the
search would not be supported, not because of the implementation
but only because of what system the implementation is running on.
Overall I think this interpretation about whether a search
is supported makes more sense.

This leaves open the question about whether file names meeting
the criteria of 6.10.2p5 must have a search that is "supported"
(by some mechanism or other in the surrounding environment,
presumably).

Tim Rentsch

unread,
Oct 2, 2009, 1:30:35 AM10/2/09
to
Keith Thompson <ks...@mib.org> writes:

I continue to think that the condition "if the search is
not supported" is talking about the particular platform
on which the implementation is running rather than about the
implementation itself.


> I would think that would be covered by "or if the search fails".

Potayto, potahto. I think of it as the search not being
supported, because no attempt is made to actually locate
the given file. In terms of the standard though there
is no significant difference between the two conditions,
except perhaps in how the implementation refers to them
in its documentation.


> My conclusion a while ago, when I thought this discussion had ended
> 8-)}, was that an implementation must *either* support the search
> *or* permit user header files to be placed where <> can find them.
> But even that doesn't make a whole lot of sense.

I believe in fact the implementation must support the search
in that it must make appropriate system calls to carry out
its specified search mechanism. By talking about the search
not being supported, the Standard is allowing the possibility
that an implementation might be run in an environment where,
even though the implementation has the relevant system calls
in it, the particular instance of the surrounding environment
doesn't implement those system calls. For example, perhaps
loadable modules are needed, and the necessary modules aren't
loaded. The search doesn't fail, because it is never really
initiated; rather, in that particular case the chosen search
mechanism is not supported (again, by the compile-time environment).

0 new messages