#include ("/" "include/foo.h")
#include ("/" "include/bar.h")
I.e., I have gotten things like..
char* a = "/" "include/foo.h";
to work. So I'm wondering, why not add this as a feature for the preprocessor to?
Or maybe.. are there any preprocessors that support this syntax?
My thinking is that you could do something like..
// config.h
#define LIB1_PATH "/include"
and then..
// main.c
#include "config.h"
#include (LIB1_PATH "foo.h")
#include (LIB1_PATH "bar.h")
If you then were to move "lib1" elsewhere in your project, you would only need to adjust config.h.
Why isn't this valid syntax?
Because the syntax for #include preprocessing directive is cpp.include for example:
# include " q-char-sequence " new-line
The ( ) characters are not allowed there. Multiple " are also not allowed, and q-char is any member of the source character set **except** new-line and ".
why not add this as a feature for the preprocessor to?
Because it would require work. To implement it.
are there any preprocessors that support this syntax?
I very much doubt. No.
My thinking is that you could do something like..
And for limited cases you kind-of can, the form of preprocessing directive takes:
# include pp-tokens new-line
For the usages, see this question. However not everything is possible, see this answer.
If you then were to move "lib1" elsewhere in your project, you would only need to adjust config.h.
No, the typical solution is to add include paths to your compiler. Then if you were to move lib1, you would change your build and compiler options, without any modification to the source code.
Keep your #include very simple - they are a very crude way to raw include other files. There is no reason to generate #include paths.
Concatenation is defined for string literals, as you've illustrated. From cppreference on string literals :
String literals placed side-by-side are concatenated at translation phase 6 (after the preprocessor). That is, "Hello," " world!" yields the (single) string "Hello, world!"
But the "string" in an #include directive is not a technically a string literal. Looking at how #include is defined on cppreference : #include "filename" we can see that the filename is some token delimited by " characters. This looks a lot like a string literal, but this is a coincidence. A string literal defines an object. It has an address and a size and every other property an object can have. An #include does not define an object, it is a preprocessor directive.
Related
I would like to have include file paths dynamically created by a macro for a target-configuration-dependent part of my program.
for example, I would like to construct a macro that would be invoked like this:
#include TARGET_PATH_OF(header.h)
Which will expand to a something like this:
#include "corefoundation/header.h"
when the source is configured (in this case) for OSX
So far all attempts have failed. I'm hoping someone out there has done this before?
example of what does not work:
#include <iostream>
#include <boost/preprocessor.hpp>
#define Dir directory/
#define File filename.h
#define MakePath(f) BOOST_PP_STRINGIZE(BOOST_PP_CAT(Dir,f))
#define MyPath MakePath(File)
using namespace std;
int main() {
// this is a test - yes I know I could just concatenate strings here
// but that is not the case for #include
cout << MyPath << endl;
}
errors:
./enableif.cpp:31:13: error: pasting formed '/filename', an invalid preprocessing token
cout << MyPath << endl;
^
./enableif.cpp:26:16: note: expanded from macro 'MyPath'
#define MyPath MakePath(File)
^
./enableif.cpp:25:40: note: expanded from macro 'MakePath'
#define MakePath(f) BOOST_PP_STRINGIZE(BOOST_PP_CAT(Dir,f))
^
/usr/local/include/boost/preprocessor/cat.hpp:22:32: note: expanded from macro 'BOOST_PP_CAT'
# define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b)
^
/usr/local/include/boost/preprocessor/cat.hpp:29:36: note: expanded from macro 'BOOST_PP_CAT_I'
# define BOOST_PP_CAT_I(a, b) a ## b
^
1 error generated.
I tend to agree with the comment in utnapistim's answer that you shouldn't do this even though you can. But, in fact, you can, with standard-conformant C compilers. [Note 1]
There are two issues to overcome. The first one is that you cannot use the ## operator to create something which is not a valid preprocessor token, and pathnames do not qualify as valid preprocessor tokens because they include / and . characters. (The . would be ok if the token started with a digit, but the / will never work.)
You don't actually need to concatenate tokens in order to stringify them with the # operator, since that operator will stringify an entire macro argument, and the argument may consist of multiple tokens. However, stringify respects whitespace [Note 2], so STRINGIFY(Dir File) won't work; it will result in "directory/ filename.h" and the extraneous space in the filename will cause the #include to fail. So you need to concate Dir and File without any whitespace.
The following solves the second problem by using a function-like macro which just returns its argument:
#define IDENT(x) x
#define XSTR(x) #x
#define STR(x) XSTR(x)
#define PATH(x,y) STR(IDENT(x)IDENT(y))
#define Dir sys/
#define File socket.h
#include PATH(Dir,File)
Warning: (Thanks to #jed for passing on this issue.) If the strings being concatenated contain identifiers which are defined elsewhere as macros, then unexpected macro substitution will occur here. Caution should be taken to avoid this scenario, particularly if Dir and/or File are not controlled (for example, by being defined as a command-line parameter in the compiler invocation).
You need to also be aware than some implementations may define words which are likely to show up in a token-like fashion in a file path. For example, GCC may define macros with names like unix and linux unless it is invoked with an explicit C standard (which is not the default). That could be triggered by paths like platform/linux/my-header.h or even linux-specific/my-header.h.
To avoid these issues, I'd recommend that if you use this hack:
you use a C (or C11) standards-conformant compiler setting, and
you place the sequence very early in your source file, ideally before including any other header, or at least any header outside of the standard library.
Also, you wouldn't need the complication of the IDENT macro if you could write the concatenation without spaces. For example:
#define XSTR(x) #x
#define STR(x) XSTR(x)
#define Dir sys
#define File socket.h
#include STR(Dir/File)
Notes
I tried it with clang, gcc and icc, as available on godbolt. I don't know if it works with Visual Studio.
More accurately, it semi-respects whitespace: whitespace is converted to a single space character.
I would like to have include file paths dynamically created by a macro for a target-configuration-dependent part of my program.
You should be unable to (and if you are able to do so, you probably shouldn't do this).
You are effectively trying to do the compiler's job in a source file, which does not make much sense. If you want to change include paths based on the machine you compile on, this is a solved problem (but not solved in a header file).
Canonical solution:
Use an IF in your Makefile or CMakeLists.txt, use custom property pages depending on the build configuration in Visual Studio (or simply set the particular settings for your build in the OS environment for your user).
Then, write the include directive as:
#include <filename.h> // no path here
and rely on the environment/build system to make the path available when the compiler is invoked.
This works for VS2013. (It can be done easier, ofcourse.)
#define myIDENT(x) x
#define myXSTR(x) #x
#define mySTR(x) myXSTR(x)
#define myPATH(x,y) mySTR(myIDENT(x)myIDENT(y))
#define myLIBAEdir D:\\Georgy\\myprojects\\LibraryAE\\build\\native\\include\\ //here whitespace!
#define myFile libae.h
#include myPATH(myLIBAEdir,myFile)
From your description, it sound like you discovered that not every "" is a string. In particular, #include "corefoundation/header.h" looks like an ordinary string but it isn't. Grammatically, quoted text outside preprocessor directives are intended for the compiler, and compile to null terminated string literals. Quoted text in preprocessor directives is interpreted by the preprocessor in an implementation-defined way.
That said, the error in your example is because Boost pasted the second and third token : / and filename. The first, fourth and fifth token (directory, . and h) are left unchanged. This is not what you wanted, obviously.
It's a lot easier to rely on automatic string concatenation. "directory/" "filename" is the same string literal as "directory/filename" Note that there is no + between the two fragments.
I've just noticed that an answer I have given for this question actually doesn't work:
Regardless of using CMake or not, the following should work with the current standard:
std::string resource = R"(
#include "text.txt"
)";
I thought that the pre-processor would recognize the #include "text.txt" statement in first place and expand the text.
But that's obviously not the case, the result for
std::cout << resource << std::endl;
is
#include "text.txt"
I tried to use some macro to let the #include statement be expanded within, but it doesn't work either:
#include <string>
#include <iostream>
#define RESOURCE_DEFINIION(resource_var,resource_name) \
const std::string resource_var = R"xxx( \
#include resource_name \
)xxx";
RESOURCE_DEFINIION(resource,"text.txt")
int main()
{
std::cout << resource << std::endl;
return 0;
}
The output is
\
#include resource_name \
Here's the demo to play with
Is there any trickery available to pull in the text.txt resource into a c++-11 raw-string literal, using the pre-processor or any other regular c++ language feature?
Disclaimer:
I well know what's wrong with the above samples and why these fail this way. It's a problem that the pre-processor ignores the stuff appearing within " pairs.
So is there a way to escape these to be seen by the pre-processor?
It seems like not possible in standard C++
Problem 0: Only standard way of textual inclusion is #include directive.
Problem 1: String literal is a preprocessing token, which are recognised in phase 3, so when preprocessing directives are executed in phase 4, it is already determined that #include is a part of string literal and not a preprocessing directive.
preprocessing-token:
header-name
identifier
pp-number
character-literal
user-defined-character-literal
string-literal
user-defined-string-literal
preprocessing-op-or-punc
each non-white-space character that cannot be one of the above
Problem 2: It is impossible to bring preprocessing directive in source and execute it by macro substitution:
16.3.4/3
The resulting completely macro-replaced preprocessing token sequence is not processed as a preprocessing directive even if it resembles one
So you cannot have working #include inside macro.
Problem 3: macro replacement list should be a valid preprocessing token:
control-line:
# define identifier replacement-list new-line
replacement-list:
pp-tokens opt
pp-tokens:
preprocessing-token
pp-tokens preprocessing-token
And string literal is a preprocessing token itself, you cannot build string literal from several macro.
I have a header file that I am trying to include from another source file using include pre-processor directory. I have tried to use both quoted form as well as angle-braket form, but neither seem to do the job.
The file name is .>"hello.h and a directory where it is searched by the compiler. I have tried to include it like this:
#include <.>"hello.h>
#include <.\>"hello.h>
#include <.\>\"hello.h>
#include ".>"hello.h"
#include ".>\"hello.h"
I also tried different C and C++ compilers — clang, gcc, clang++ and g++.
Obviously, none of the above worked or otherwise there would have been no question.
I thought that maybe the name is not legal according to the standard. Unfortunately, I have neither C nor C++ standard specifications on hand. The only authoritative source of information I could find was this MSDN page about #include directive, and GNU C preprocessor documentation, here. GNU's documentation does not say much, MSDN has the following clause, however:
The path-spec is a file name optionally preceded by a directory
specification. The file name must name an existing file. The syntax of
the path-spec depends on the operating system on which the program is
compiled.
I am curious as to what C and C++ standards say about this?
Where do I find those OS-specific rules for C and C++ header file naming requirements? I am particularly interested in OS X, Linux and FreeBSD.
Why escaping < and/or " characters does not work?
How do I include my file?
I think you are out of luck with that file name from the draft C99 standard section 6.4.7 Header names the grammar is as follows:
header-name:
< h-char-sequence >
" q-char-sequence "
h-char-sequence:
h-char
h-char-sequence h-char
h-char:
any member of the source character set except
the new-line character and >
q-char-sequence:
q-char
q-char-sequence q-char
q-char:
any member of the source character set except
the new-line character and "
You have both a " and > in the file name which excludes you from both the q-char and h-char specification. I don't think you have much choice but to change the file name.
The grammar is the same in the draft C++ standard, section 2.9 Header names.
In both C and C++, that's not a valid header name since it contains both > and ".
The syntax for header names allows those delimited by <> to contain "any member of the source character set except new-line and >", and those delimited by "" to contain "any member of the source character set except new-line and "". There is no concept of an escape sequence.
" and > are not valid characters for a filename in Windows. Your filename should be hello.h, or .\hello.h, or ..\hello.h, but not .>"hello.h.
#include "hello.h"
#include ".\hello.h"
#include "..\hello.h"
#include "c:/temp/hello.h"
Which is why you will not find anything in MSDN about it.
ext3 allows most characters (several have to be escaped when used), but it is HIGHLY recommended that you do not use them when naming your header and source files (if for no other reason than readability). For more information: http://pic.dhe.ibm.com/infocenter/compbg/v121v141/index.jsp?topic=%2Fcom.ibm.xlcpp121.bg.doc%2Flanguage_ref%2Fc99preprocessor.html
What is an acceptable filename is implementation defined.
I would have expected #include ".>\"hello.h" to work, at least
on systems where'>'and'"'` are legal in filenames, but
there's no requirement that it work, and there are clearly
systems where it won't, because such names are not legal in the
system.
You might try forcing the issue:
#define NAME ".>\"hello.h"
#include NAME
But for practical purposes, you should limit your filenames to
alphanumerics, underscores, and maybe hyphens (but I'd be
leary of those as well). And with only one dot, before the
extension. If you go looking for trouble, don't be surprised if
you find it.
Which, of course, answers your last question: how do I include
the file. You rename it to something sensible.
Observe the following program:
#include __FILE__
main(){}
The preprocessor gets stuck in infinite recursion including a copy of itself inside itself and complaining about main() already being defined.
If I can use macros to include files,
can I derive a file name based on __FILE__ and include it?
For example, I'd like to include "foo.h" whilst inside "foo.cpp", but derive it from __FILE__.
## will concatenate macros.
It is also possible to Stringify macros.
Can it be done with the preprocessor?
The C standard specifies three forms of #include:
#include <file>
#include "file"
#include ANYTHING ELSE
In the former two cases, no macro expansion takes place, so there's no way to vary the behavior. In the third case, C99 says (§6.10.2p4):
The preprocessing tokens after #include in the directive are [macro-expanded]. The directive resulting after all replacements shall match one of the two previous forms [footnote: Note that adjacent string literals are not concatenated into a single string literal]. 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.
Slightly different, but effectively equivalent, wording appears in C++98 §16.2p4.
Any sentence with "shall" in it imposes a hard requirement: in this case, the program is ill-formed if ANYTHING ELSE expands to anything but a sequence of tokens beginning with < and ending with >, or beginning and ending with ". The exact interpretation of that sequence of tokens is implementation defined, but note that the footnote specifically forbids string-literal concatenation.
So, as the expansion of __FILE__ is a string constant, the only ways to use it in an #include are
#include __FILE__
which, as you discovered, leads to infinite recursion, and
#define LT <
#define GT >
#include LT __FILE__ etc GT
which has amusing, but useless, effects on all the compilers I can conveniently test. Assuming that the above is in a file named test.c:
GCC attempts to open a file named "test.c" etc, with the quotation marks and space included verbatim.
clang is even more literal, and looks for that same filename but with leading and trailing spaces.
MSVC macro-expands only the LT (it is my considered opinion that this is a conformance violation), complains that there is no matching >, and then attempts to open a file named __FILE__ etc GT.
(GCC's behavior is documented here; you are on your own for anything else.)
tl;dr: There is no way to do what you want from inside the preprocessor. I recommend working out the name of the file-to-be-included from your build system and notifying the compiler of it with a -D switch (on a Unixy system you will need double quotation, -DINCLUDEME='"includeme.h"'; I don't speak CMD)
The best I've come up with is this:
#define foo(x) #x
#include foo(x)
prog.cpp:2:16: error: x: No such file or directory
I'm trying to create a string from multiple macros/values for use in a #include. I'm doing this to clean up some code for an initial state in a simple state system.
I have 2 default, redefinable macros (if not defined there's a default value)
#define DEFAULT_STATE StateName // name of class
#define DEFAULT_STATE_LOCATION states/ // location of header file from root
The include directive is being used from a file 4 folders in from the root, so the include should look like this
#include "../../../../states/StateName.h"
based on the example above.
So I want to define a macro from the 4 values.
../../../../
DEFAULT_STATE_LOCATION
DEFAULT_STATE
.h
into some macro, say DEFAULT_STATE_INCLUDE
so I can say
#include #DEFAULT_STATE_INCLUDE
(to stringize the value for quotes)
That way I can change the default state and the path from the root of the header file for the default state in a prefix header, and the source using the #include will not have to be updated, and I can omit the constants from redefinition every time.
I'm not including the .h in the DEFAULT_STATE macro because I use the same macro to create and instance of the default state.
I've tried using the concatenation ##, and the stringize operator, and some tricks I've found online, but nothing worked.
I can define ../../../../ and .h in their own macros if needed.
But simply
#define DEFAULT_STATE_INCLUDE ../../../../ ## DEFAULT_STATE_LOCATION ## DEFAULT_STATE ## .h
#include #DEFAULT_STATE_INCLUDE
gives tons of errors.
Any help is appreciated.
Thanks
Note that footnote 143 in section §6.10.2 "Source file inclusion" of the C99 standard says:
143) Note that adjacent string literals are not concatenated into a single string literal (see the translation
phases in 5.1.1.2); thus, an expansion that results in two string literals is an invalid directive.
Thus, any string concatenation must be done outside the source code. Token concatenation with ## is not an option; that is used to build identifiers, and the bits of the header name you are joining are not identifiers.
I think you should simply use something like:
#ifndef STATE_HEADER
#define STATE_HEADER "states/StateName.h"
#endif
#include STATE_HEADER
and leave it to the build system, not the source code, to determine that -I../../../.. is required as an option to the compiler.
You'd better pass the include directory to gcc with -I option
-I../../../..
From gcc man page:
-I dir
Add the directory dir to the list of directories to be searched for header files.
This seems relevant: Computed Includes
My reading of that is that the #define macro has to include the " (quote) characters and that you can't rely on the stringize or concatenation operators to do it for you.