[comp.std.c] #include "filename.h" does not mean "include user file"

ned@pebbles.cad.mcc.com (Ned Nowotny) (03/16/90)

[ Note:  Followups are directed to comp.std.c.  GNU mailing list readers ]
[        should probably just take note.                                 ]

From K&R2, section A12.4, page 231:

        A control line of the form
	    #include <filename>
    causes the replacement of that line by the entire contents of the file
    _filename_.  The characters in the name _filename_ must not include >
    or newline, and the effect is undefined if it contains any of ", ', \,
    or /*.  The named file is searched for in a sequence of implementation-
    dependent places.
	Similarly, a control line of the form 
	    #include "filename"
    searches first in association with the original source file (a deliberately
    implementation dependent phrase), and if that search fails, then as in the
    first form.  The effect of using ', \, or /* in the filename remains
    undefined, but > is permitted.
	Finally, a directive of the form
	    #include token-sequence
    not matching one of the previous forms is interpreted by expanding the
    token sequence as for normal text; one of the two forms with <...> or
    "..." must result, and it is then treated as previously described.
	#include files may be nested.

I believe that this description is essentially equivalent to the version in
the current (as yet still unpublished) ANSI C standard.  Moreover, it is
essentially the same as (though more precise than) the description given in
K&R1.

In all cases, #include "filename" has never meant:

       If the file name is enclosed by a pair of quotation marks, the file
    is presumed to be a user-supplied header file.  The search to find it
    begins in the current directory.  If it is not found, then the predefined
    set of locations is examined.  The -I option also works with user-supplied
    header files.
                -- _C++ Primer_, Stanley B. Lippman, Copyright 1989, page 13

Nor does it have the meaning implied in the following passage from the _User's
Guide to GNU C++_, page 22, wherein the '-I-' flag to G++ is described:

    In addition, the '-I-' option inhibits the use of the current directory
    as the first search directory for '#include "file"'.  Therefore, the
    current directory is searched only if it is requested explicitly with
    '-I.'.  Specifying both '-I-' and '-I.' allows you to control precisely
    which directories are searched before the current one and which are
    searched after."

Neither of the previous two quotes should be construed as a complaint directed
specifically at either Mr. Lippman or Mr. Tiemann.  I have heard and read
similar descriptions of the behavior expected of the #include "filename"
construct many times before.  In fact, I myself once believed essentially the
same thing having failed to carefully read the appropriate passage in the
appendix of K&R1.  (Of course, if both Mr. Lippman and Mr. Tiemann meant that
the current directory referenced in their descriptions was the directory in
which the current file resides which contains the particular #include statement
to be processed, then their descriptions are correct, though confusing.
Generally, I find it more natural to think of the current directory as being
the one current when the compiler was invoked.)

For an example of the kind of problems which the above intuitive usage will
cause, consider the following:

    1)  A source file in the current directory which is being compiled to test
	the header file described next.
    2)  A copy in the current directory of a header file located in a project
        defined include directory.  This file contains some value which is to
	be varied for the purposes of testing; therefore, the copy is a
	temporary necessity.
    3)  The source file in 1 above includes a file from the project defined
	include directory which actually contains the include statement for
	the header file which has been copied and modified.

Given that '-I.' is one of the options passed to the compiler:

    If the include statement in the header file included by the source file in
    1 above is of the form #include <filename>, all is well.  The header file
    with the local changes will be picked up as expected.  However, if the form
    of the include statement is #include "filename", the compiler will ignore
    the copy of the header file in the current directory and silently pick up
    the original header file located in the project defined include directory.

As a result of problems similar to the one described above, it seems that
programmers should always use the #include <filename> form unless they
have a specific, well defined situation in which the behavior of the
#include "filename" form is clearly desired.  The #include "filename" form
seems most appropriate for associated source and header files which are
generated by code generating programs like YACC and LEX.  (Of course, if .
is not one of the implementation defined directories searched when the
#include <filename> form is used, '-I.' must be passed on the compiler
command line.  If fact, . will almost certainly not be one of the standard
search directories for the #include "filename" form either.  If it seems to
have behaved that way, it is most likely because the header files included
were in the same directory as the source files which happened to be in the
current directory during compilation.)

Ned Nowotny, MCC CAD Program, Box 200195, Austin, TX  78720  Ph: (512) 338-3715
ARPA: ned@mcc.com                   UUCP: ...!cs.utexas.edu!milano!cadillac!ned
-------------------------------------------------------------------------------
"We have ways to make you scream." - Intel advertisement in the June 1989 DDJ.

sullivan@aqdata.uucp (Michael T. Sullivan) (03/16/90)

:From article <6928@cadillac.CAD.MCC.COM>, by ned@pebbles.cad.mcc.com (Ned Nowotny):
> 
> As a result of problems similar to the one described above, it seems that
> programmers should always use the #include <filename> form unless they
> have a specific, well defined situation in which the behavior of the
> #include "filename" form is clearly desired.  The #include "filename" form

I have never thought of "filename" as meaning "an include file in the
current directory".  My usage has been to use <file> when the file is
a Unix supplied header file and to use "file" otherwise.  This gives
future programmers a clue as to where to look for the header file.  Now,
you may have package supplied header files in /usr/include on your system--
that's fine and "file" will still find it but not all systems will have
package-defined header files in /usr/include.  Also, if a future programmer
is porting some code and cpp can't find <file>, then the programmer knows
that the system is lacking a certain header file and that he/she better
get his/her hands on one, instead of wondering why the code came incomplete.
-- 
Michael Sullivan          uunet!jarthur!aqdata!sullivan
aQdata, Inc.              sullivan@aqdata.uucp
San Dimas, CA             +1 714 599 9992

ekrell@ulysses.att.com (Eduardo Krell) (03/16/90)

I'm the one who originally implemented the '-I-' flag for gcc-cpp. The
wording I gave FSF is different from the one that appears in the manual
(which is wrong, as you point out).

>    In addition, the '-I-' option inhibits the use of the current directory
>    as the first search directory for '#include "file"'.  Therefore, the
>    current directory is searched only if it is requested explicitly with
>    '-I.'.  Specifying both '-I-' and '-I.' allows you to control precisely
>    which directories are searched before the current one and which are
>    searched after."

What '-I-' does is supress the search in the directory where the including
file is (the file with the #include statement), NOT the current directory.

This is needed because there's no way to override the search in that
directory, which comes first for header files included with "". For
instance, you #include <foo.h>. Inside foo.h there's a #include "bar.h"
which is in the same directory foo.h is.
If you want to use your own bar.h so that it's included by foo.h, there's no
way of doing that since -I. would NOT take precedence over searching
in the same directory where foo.h is. That's the reason why -I-
is needed.
    
Eduardo Krell                   AT&T Bell Laboratories, Murray Hill, NJ

UUCP: {att,decvax,ucbvax}!ulysses!ekrell  Internet: ekrell@ulysses.att.com

shap@delrey.sgi.com (Jonathan Shapiro) (03/17/90)

In article <6928@cadillac.CAD.MCC.COM> ned@MCC.COM (Ned Nowotny) writes:
>[ Note:  Followups are directed to comp.std.c.  GNU mailing list readers ]
>[        should probably just take note.                                 ]
>
[ Discussion of meaning of #include "file" ellided... ]

To preclude the rash of corrections, the issue is well known.  Early
cpp specs didn't specify whether the "file" syntax meant relative to
the file that did the include or relative to the source file.  The cpp
by Jon Reiser (sp?) implemented the former, when the latter was the
intended meaning.

Reiser's preprocessor has spread and a few very strange folks have
come to depend on the behavior.

In any case, it is well understood.

Jon

ned@pebbles.cad.mcc.com (Ned Nowotny) (03/23/90)

In article <1990Mar16.003404.29369@aqdata.uucp> sullivan@aqdata.uucp (Michael T. Sullivan) writes:
=>:From article <6928@cadillac.CAD.MCC.COM>, by ned@pebbles.cad.mcc.com (Ned Nowotny):
=>> 
=>> As a result of problems similar to the one described above, it seems that
=>> programmers should always use the #include <filename> form unless they
=>> have a specific, well defined situation in which the behavior of the
=>> #include "filename" form is clearly desired.  The #include "filename" form
=>
=>I have never thought of "filename" as meaning "an include file in the
=>current directory".  My usage has been to use <file> when the file is
=>a Unix supplied header file and to use "file" otherwise.  This gives
=>future programmers a clue as to where to look for the header file.  Now,
=>you may have package supplied header files in /usr/include on your system--
=>that's fine and "file" will still find it but not all systems will have
=>package-defined header files in /usr/include.  Also, if a future programmer
=>is porting some code and cpp can't find <file>, then the programmer knows
=>that the system is lacking a certain header file and that he/she better
=>get his/her hands on one, instead of wondering why the code came incomplete.

However, given that #include "filename" does behave differently from
#include <filename> and that this behavior can produce undesirable results
in some circumstances, you should be using comments to indicate which include
files are system header files, which are package supplied header files and
which are local application header files.  After all, #include "filename"
does not mean "not a system header file" in any sense.

Aside from code produced by code generators like YACC, LEX, BISON, and FLEX
where all files produced are generally written to and kept in a single
directory, is there any compelling reason to ever use #include "filename"?
My opinion is that there is not and that programmers should not be using the
form unless there is a very special circumstance in which the behavior of
#include "filename" is exactly the behavior desired.  The wish to not
specify a particular directory with the -I flag on a compiler command line
is not a sufficiently compelling reason.

Ned Nowotny, MCC CAD Program, Box 200195, Austin, TX  78720  Ph: (512) 338-3715
ARPA: ned@mcc.com                   UUCP: ...!cs.utexas.edu!milano!cadillac!ned
-------------------------------------------------------------------------------
"We have ways to make you scream." - Intel advertisement in the June 1989 DDJ.