The #include directive

J

jacob navia

I have just noticed that I forgot to include an explanation of that in my tutorial.
I added the following. I hope I got the essentials corect. Note that this is a
tutorial, i.e. should be easy on the user...

Note that the standard says nothing about directories, so it is of no
help here.

1.34.1.6 The include directive
This directive instructs the preprocessor to read a file from disk and include its
text into the current position. All the text of the file is inserted into the compiler
input stream and preprocessed just as if you would have written exactly all that text
in the current position.

This directive has two variants:
The first uses angle brackets to enclose the name of the file to include.
#include <stdio.h>
The second uses quotes to enclose the file name:
#include "myfile.h"

The first one means that the preprocessor should look for the file in the system
include directory, where the files furnished by the implementation are stored.
The second means that the preprocessor looks first in the current directory for
the mentioned file. Note that the current directory starts as the one where the
first source file is stored, the one that the compiler receives as a parameter
when invoked. Of course, this can change later if you include a file in another
directory.

For instance:
You have a file in the current directory that has an include directive like:
#include "myincludes/decls.h"
And within decls.h you have an include directive like
#include "stddecls.h"
The preprocessor starts looking for stddecls.h in "myincludes", not in the
original directory.
 
M

Michael Tsang

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

jacob said:
I have just noticed that I forgot to include an explanation of that in my
tutorial. I added the following. I hope I got the essentials corect. Note
that this is a tutorial, i.e. should be easy on the user...

Note that the standard says nothing about directories, so it is of no
help here.

1.34.1.6 The include directive
This directive instructs the preprocessor to read a file from disk and
include its text into the current position. All the text of the file is
inserted into the compiler input stream and preprocessed just as if you
would have written exactly all that text in the current position.

This directive has two variants:
The first uses angle brackets to enclose the name of the file to include.
#include <stdio.h>
The second uses quotes to enclose the file name:
#include "myfile.h"

The first one means that the preprocessor should look for the file in the
system include directory, where the files furnished by the implementation
are stored. The second means that the preprocessor looks first in the
current directory for the mentioned file. Note that the current directory
starts as the one where the first source file is stored, the one that the
compiler receives as a parameter when invoked. Of course, this can change
later if you include a file in another directory.

For instance:
You have a file in the current directory that has an include directive
like:
#include "myincludes/decls.h"
And within decls.h you have an include directive like
#include "stddecls.h"
The preprocessor starts looking for stddecls.h in "myincludes", not in the
original directory.

The standard just says that the search method is "implementation-defined",
i.e. not mandated by the standard. By convention. <> files are found in the
system include directories and "" files are found in the directory the same
as the including file.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAktcLboACgkQm4klUUKw07BuxQCfRq9HdGk3zup9ru+OIOJWRQH7
IGkAniZCnkyPFWoI9npjgNQRHCySo9kh
=X4rF
-----END PGP SIGNATURE-----
 
F

Flash Gordon

jacob said:
I have just noticed that I forgot to include an explanation of that in
my tutorial.
I added the following. I hope I got the essentials corect. Note that
this is a
tutorial, i.e. should be easy on the user...

Note that the standard says nothing about directories, so it is of no
help here.

I think you've gone slightly too much in to the way the compiler works
rather than the way it seems to the users...
1.34.1.6 The include directive
This directive instructs the preprocessor to read a file from disk and
include its
text into the current position. All the text of the file is inserted
into the compiler
input stream and preprocessed just as if you would have written exactly
all that text
in the current position.

The user does not need to be told it is "from disk" or about input
streams etc...

This directive instructs the compiler to include the contents of the
specified file[1] as if you had simply typed the contents at that point
in the source file.

Footnote 1: System includes need not actually be files, but the effect
is always the same.
This directive has two variants:
The first uses angle brackets to enclose the name of the file to include.
#include <stdio.h>
The second uses quotes to enclose the file name:
#include "myfile.h"

The first one means that the preprocessor should look for the file in
the system
include directory, where the files furnished by the implementation are
stored.

That should probably be more like, "furnished by the implementation and
system libraries", since on *nix it certainly often includes other
optional library headers.
The second means that the preprocessor looks first in the current
directory for
the mentioned file. Note that the current directory starts as the one
where the
first source file is stored, the one that the compiler receives as a
parameter
when invoked. Of course, this can change later if you include a file in
another
directory.

I would slightly re-word the above...

The second means that the compiler first looks include files provided by
you. With lcc-win32 this means first looking in the current directory...
For instance:
You have a file in the current directory that has an include directive
like:
#include "myincludes/decls.h"

I assume somewhere you have already mentioned that / can be used as a
directory seperator, since as you know on DOS/Windows people tend to use \
And within decls.h you have an include directive like
#include "stddecls.h"
The preprocessor starts looking for stddecls.h in "myincludes", not in the
original directory.

It's important to state up front the handling of directories is specific
to lcc-win32, since I don't think all compilers do this. Hence my
earlier suggestion of saying, "With lcc-win32 this means...". I.e. don't
belabor the point, just mention it when you start on the bits which are
implementation defined.

I've also changed to saying compiler rather than preprocessor, since
generally the user does not care, but you can obviously say preprocessor
if that is more consistent with the rest of your tutorial.
 
E

Eric Sosman

[...]
This directive has two variants:
The first uses angle brackets to enclose the name of the file to include.
#include <stdio.h>
The second uses quotes to enclose the file name:
#include "myfile.h"

... and the third of the two is described in 6.10.2p4.
After macro substitution it must resolve to one of the other
two forms, so the third form might be considered "transitory"
or "evanescent" or something, but it deserves at least a
footnote.
 
J

jacob navia

Eric Sosman a écrit :
[...]
This directive has two variants:
The first uses angle brackets to enclose the name of the file to include.
#include <stdio.h>
The second uses quotes to enclose the file name:
#include "myfile.h"

... and the third of the two is described in 6.10.2p4.
After macro substitution it must resolve to one of the other
two forms, so the third form might be considered "transitory"
or "evanescent" or something, but it deserves at least a
footnote.

True I forgot that one.
Thanks
 
J

jacob navia

Flash Gordon a écrit :
The user does not need to be told it is "from disk" or about input
streams etc...

This directive instructs the compiler to include the contents of the
specified file[1] as if you had simply typed the contents at that point
in the source file.

Footnote 1: System includes need not actually be files, but the effect
is always the same.

True, you are right. I changed that.
[snip]
It's important to state up front the handling of directories is specific
to lcc-win32, since I don't think all compilers do this. Hence my
earlier suggestion of saying, "With lcc-win32 this means...". I.e. don't
belabor the point, just mention it when you start on the bits which are
implementation defined.

I thought all compilers do this, even if it is not defined in the standard.
I've also changed to saying compiler rather than preprocessor, since
generally the user does not care, but you can obviously say preprocessor
if that is more consistent with the rest of your tutorial.

Well, the chapter is called "Inside the preprocessor", so it is OK.
 
F

Flash Gordon

jacob said:
Flash Gordon a écrit :
The user does not need to be told it is "from disk" or about input
streams etc...

This directive instructs the compiler to include the contents of the
specified file[1] as if you had simply typed the contents at that
point in the source file.

Footnote 1: System includes need not actually be files, but the effect
is always the same.

True, you are right. I changed that.
[snip]

That's good. Note I was suggesting as a footnote, rather than in the
main body, for explaining the system headers.
I thought all compilers do this, even if it is not defined in the standard.

I think there are subtleties in the way the subdirectories are sometimes
handled, certainly enough that I would completely trust it. You could
say "With lcc-win32 and most other compilers...", or "With most
compilers including lcc-win32..."

In any case, I've seen headers which do not assume quite the same method
of handling directories. I.e. headers in a directory named foo which
include each other as foo/bar.h rather than assuming the directory foo
will be searched.
Well, the chapter is called "Inside the preprocessor", so it is OK.

Yes, I agree, in context that makes sense.
 
N

Nick

Flash Gordon said:
I think there are subtleties in the way the subdirectories are
sometimes handled, certainly enough that I would completely trust
it. You could say "With lcc-win32 and most other compilers...", or
"With most compilers including lcc-win32..."

In any case, I've seen headers which do not assume quite the same
method of handling directories. I.e. headers in a directory named foo
which include each other as foo/bar.h rather than assuming the
directory foo will be searched.

I've used C compilers on systems where there aren't even directories as
people commonly think of them. Partioned Data Sets for example.
 
J

jacob navia

Nick a écrit :
I've used C compilers on systems where there aren't even directories as
people commonly think of them. Partioned Data Sets for example.

OK. Either

(1) You have separate name spaces for files (i.e. "directories")

(2) You don't. In that case there is only ONE namespace and it
doesn't make any sense to write
#include "subdir/foo.h"
and the problem doesn't even appear.

What it would be interesting is to see if some compiler in a
system where there are name spaces does NOT implement the schema
I mentioned.
 
K

Keith Thompson

jacob navia said:
This directive has two variants:
The first uses angle brackets to enclose the name of the file to include.
#include <stdio.h>
The second uses quotes to enclose the file name:
#include "myfile.h"

The first one means that the preprocessor should look for the file
in the system include directory, where the files furnished by the
implementation are stored. The second means that the preprocessor
looks first in the current directory for the mentioned file. Note
that the current directory starts as the one where the first source
file is stored, the one that the compiler receives as a parameter
when invoked. Of course, this can change later if you include a file
in another directory.
[...]

#include "myfile.h" typically looks in the current directory (though
this isn't required), but it can also search in other places.
Many (most?) compilers have a "-I" option, or something similar,
that lets you specify which directories to search. gcc, for example,
can also use any of several environment variables to control this.
So "myfile.h" might be found in a project-specific directory, not
necessarily the current directory. This lets you, for example,
store ".h" and ".c" files in separate directories.

Your tutorial doesn't necessary need to repeat everything the standard
says, but you should definitely refer to the standard while writing
it.
 
E

Eric Sosman

Flash Gordon said:
[...]
In any case, I've seen headers which do not assume quite the same
method of handling directories. I.e. headers in a directory named foo
which include each other as foo/bar.h rather than assuming the
directory foo will be searched.

I've used C compilers on systems where there aren't even directories as
people commonly think of them. Partioned Data Sets for example.

An oddity I once encountered had to do with what "the
same directory" meant. On this system (VMS), it was possible
to construct a file name that incorporated a kind of search
path: You'd instruct the compiler to look for included files
in PATH, where PATH was defined (externally to the compiler)
as A, B, C, ... When processing #include "foo.h", the compiler
would look for A:foo.h, B:foo.h, C:foo.h, ... and use the first
foo.h that it found. Syntactically and conceptually, this PATH
construct was just part of the name of "the" directory.

The oddity came up when foo.h contained #include bar.h.
One compiler would look for PATH:bar.h, that is, for A:bar.h
then B:bar.h then C:bar.h. Another, having found B:foo.h (say),
would search only for B:bar.h. Both strategies were defensible
as searching in "the same" directory (indeed, both compilers
described their searches that way), yet the outcomes differed.
If you had the files A:bar.h and B:bar.h, and B:foo.h included
"bar.h", on compiler got A:bar.h and the other got B:bar.h.
Both compilers claimed that they searched "the same" directory,
and both were arguably right.

(Why were we using these PATH things, anyhow? The idea
was that B: was the read-only "committed" version of all the
source files, and A: contained just the sources you'd checked
out and modified. When compiling in the PATH directory, you'd
get the A: versions of the files you were actively working with
and the "reference" B: versions of whatever you hadn't touched.
Disks were smaller and more expensive in those days; the prospect
of copying twelve thousand or so source files onto a local disk
just so you could change two of them and recompile was not
attractive.)
 
E

Ersek, Laszlo

On 1/24/2010 12:05 PM, Nick wrote:

I've immediately thought of OpenVMS when reading this. I remember
An oddity I once encountered had to do with what "the
same directory" meant. On this system (VMS), it was possible
to construct a file name that incorporated a kind of search
path: You'd instruct the compiler to look for included files
in PATH, where PATH was defined (externally to the compiler)
as A, B, C, ... When processing #include "foo.h", the compiler
would look for A:foo.h, B:foo.h, C:foo.h, ... and use the first
foo.h that it found. Syntactically and conceptually, this PATH
construct was just part of the name of "the" directory.

The oddity came up when foo.h contained #include bar.h.
One compiler would look for PATH:bar.h, that is, for A:bar.h
then B:bar.h then C:bar.h. Another, having found B:foo.h (say),
would search only for B:bar.h.

This is funny because my usenet client is "ANU News - V6.2.0
(23-Jun-1997)", running on ludens.elte.hu:

ludens$ show sys/noproc
OpenVMS V8.3 on node LUDENS 24-JAN-2010 22:17:16.74 Uptime 242 16:37:08

I might have found what you describe (very long citation, sorry):

ludens$ help cc /incl


----v----
CC

/INCLUDE_DIRECTORY

/INCLUDE_DIRECTORY=(place[,...])

[...]

For the quoted form, the search order is:

1. One of the following:

o If /NESTED_INCLUDE_DIRECTORY=INCLUDE_FILE (the default) is
in effect, search the directory containing the file in
which the #include directive itself occurred. The meaning
of "directory containing" is: the RMS "resultant string"
obtained when the file in which the #include occurred was
opened, except that the filename and subsequent components
are replaced by the default file type for headers (".H", or
just "." if /ASSUME=NOHEADER_TYPE_DEFAULT is in effect).
The "resultant string" will not have translated any
concealed device logical.

o If /NESTED_INCLUDE_DIRECTORY=PRIMARY_FILE is in effect,
search the default file type for headers using the context
of the primary source file. This means that just the file
type (".H" or ".") is used for the default file-spec but,
in addition, the chain of "related file-specs" used to
maintain the sticky defaults for processing the next
top-level source file is applied when searching for the
include file.

o If /NESTED_INCLUDE_DIRECTORY=NONE is in effect, this entire
step (Step 1) is bypassed.

2. Search the places specified in the /INCLUDE_DIRECTORY
qualifier, if any. A place that can be parsed successfuly as
an OpenVMS file-spec and that does not contain an explicit file
type or version specification is edited to append the default
header file type specification (".H" or ".").

A place containing a "/" character is considered to be a
UNIX-style name. If the name in the #include directive also
contains a "/" character that is not the first character and is
not preceded by a "!" character (that is, it is not an absolute
UNIX-style pathname), then the name in the #include directive
is appended to the named place, separated by a "/" character,
before applying the decc$to_vms pathname translation function.

3. If "DECC$USER_INCLUDE" is defined as a logical name, search
"DECC$USER_INCLUDE:.H", or just "DECC$USER_INCLUDE:." if
/ASSUME=NOHEADER_TYPE_DEFAULT is in effect.


4. If the file is not found, follow the steps for the
angle-bracketed form of inclusion.
----^----


Furthermore,

ludens$ help define examples


----v----
DEFINE

Examples

[...]

7.$ DEFINE MYDISK XXX0:[MYDIR], YYY0:[TESTDIR]

In this example, the DEFINE command places the logical name
MYDISK in the process logical name table with two equivalence
names: XXX0:[MYDIR] and YYY0:[TESTDIR].
----^----


A plausible reconstruction of your old setup might be:

1. Define the DECC$USER_INCLUDE logical to a list of include
directories, all different from the directory where the .C files
resided.

2. Specify no /INCLUDE_DIRECTORY option.

3. When the .C file includes "foo.h", the compiler looks for it under
all directories specified in DECC$USER_INCLUDE.

4a. When "foo.h" includes "bar.h", the compiler looks for such a "bar.h"
per default (/NESTED_INCLUDE_DIRECTORY=INCLUDE_FILE) that is a "sibling"
of "foo.h".

4b. However, if /NESTED_INCLUDE_DIRECTORY=PRIMARY_FILE is in effect, the
compiler searches for "bar.h" as described for "foo.h" in step 3.


(Off topic again, sorry.)

Cheers,
lacos
 
J

jacob navia

Ersek, Laszlo a écrit :
[snip]

Thanks for this contribution. This means that that compiler could be
configured to acept the options for searching include files, what
is better than forcing one, as now lcc-win does.

There are still Vaxes around as it seems...
What are the characteristics of that server? (Ram/disk etc) ?

Just curious

jacob
 
E

Eric Sosman

[... DECC #include search strategies ...]

(Off topic again, sorry.)

Far worse abuses have occurred (and will again, I'm sure).
For this thread, though, I think the point is well made: Compilers
search for #include files in a variety of idiosyncratic ways, which
defy a one- or two-line description.
 
F

frank

Keith said:
jacob navia said:
This directive has two variants:
The first uses angle brackets to enclose the name of the file to include.
#include <stdio.h>
The second uses quotes to enclose the file name:
#include "myfile.h"

The first one means that the preprocessor should look for the file
in the system include directory, where the files furnished by the
implementation are stored. The second means that the preprocessor
looks first in the current directory for the mentioned file. Note
that the current directory starts as the one where the first source
file is stored, the one that the compiler receives as a parameter
when invoked. Of course, this can change later if you include a file
in another directory.
[...]

#include "myfile.h" typically looks in the current directory (though
this isn't required), but it can also search in other places.
Many (most?) compilers have a "-I" option, or something similar,
that lets you specify which directories to search. gcc, for example,
can also use any of several environment variables to control this.
So "myfile.h" might be found in a project-specific directory, not
necessarily the current directory. This lets you, for example,
store ".h" and ".c" files in separate directories.

Your tutorial doesn't necessary need to repeat everything the standard
says, but you should definitely refer to the standard while writing
it.

I would go farther with the -I and include an example. I would guess
that for linux users of gcc, it would look something like
gcc -I "/usr/headers/" ...

, but this can be a harder thing if windows is the platform, if lcc is
installed in say, "Program Files", which turns any path into a serious
bummer.
 
E

Ersek, Laszlo

There are still Vaxes around as it seems...

ludens is an Alpha.

What are the characteristics of that server? (Ram/disk etc) ?

Just curious

I've asked the sysadmin and he was kind enough to tell us.

live server: (working)
Alphaserver DS20E
2x 667 Mhz Alpha EV67 CPU
2 Gbyte RAM (will be upgraded to 4G during the next scheduled maintenance)
no internal disk

cold spare server: (turned off)
Alphaserver ES40
2x 500 MHz Alpha EV67 CPU
4 Gbyte RAM
no internal disk

storage:
HP MSA 1000 (2gbit FC SAN storage subsystem)
2 controllers
2 switches
2 shelfes (4x scsi320 buses)
8 disk (300 Gbyte 10k RPM) 2 in each bus

tape library:
HP StorageWorks MSL6030 Tape Library
1 Ultrium 2 drive
2x 15 slot magazine
ultra3-lvd (scsi160) interface

Console:
original VT520 console with hardcopy printing

Rack: an old |D|I|G|I|T|A|L| branded alphaserver (blue) rack

Web servers were moved a year ago to a dedicated machine (also VMS OS,
WASD http server, Alphaserver ES45 (4x 1000GHz Alpha EV68 cpu, 4 Gbyte
ram)).

Most components are used parts and were donated to the University,
except for the storage and the tape library, which were bought new four
years ago.

He also mentions that under VMS there are "text libraries" (TLBs)
additionally, which provide faster access to headers (and other texts)
than individual files.

If you wish, I can cite the full cc/incl help, which also details how
TLBs are searched. (Though I'm sure it's available on the web as well.)

(I can hear those *PLONK*s :()
lacos
 
F

Flash Gordon

Eric said:
[... DECC #include search strategies ...]

(Off topic again, sorry.)

Far worse abuses have occurred (and will again, I'm sure).
For this thread, though, I think the point is well made: Compilers
search for #include files in a variety of idiosyncratic ways, which
defy a one- or two-line description.

I think that Jacob's original description, with my small modification,
is perfectly reasonable for a tutorial, and that was only about a four
line description.
 
F

frank

On 1/24/2010 5:22 AM, jacob navia wrote:

     ... and the third of the two is described in 6.10.2p4.
After macro substitution it must resolve to one of the other
two forms, so the third form might be considered "transitory"
or "evanescent" or something, but it deserves at least a
footnote.

4 A preprocessing directive of the form
# include pp-tokens new-line
(that does not match one of the two previous forms) is permitted. The
preprocessing
tokens after include in the directive are processed just as in normal
text. (Each
identifier currently defined as a macro name is replaced by its
replacement list of
preprocessing tokens.) The directive resulting after all replacements
shall match one of
the two previous forms.148) The method by which a sequence of
preprocessing tokens
between a < and a > preprocessing token pair or a pair of " characters
is combined into a
single header name preprocessing token is implementation-defined.

Apparently pp-tokens is the output from a preprocessor. I think I've
figured out why #includes don't just include files. Doesn't cpp hand
gcc a bunck of tokens that aren't in any file?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top