String concatenation for include path - c++

Is there a way to concatenate 2 strings literals to form an include path?
Code stub:
#define INCLUDE_DIR "/include"
#include INCLUDE_DIR "/dummy.h"
Looking at this question, the answers point in a different direction (compiler command line). It is mentioned here that it is seemingly not possible, but I wonder if the topic has been dug enough.
(I do have an use case in which this is relevant, please focus your answers/comments on this question only.)

It really seems this is not possible. I will report here the relevant section from Eric Postpischil's answer (he doesn't seem to be active anymore).
The compiler will do macro replacement on an #include line (per C
2011 [N1570] 6.10.2 4), but the semantics are not fully defined and
cannot be used to concatenate file path components without additional
assistance from the C implementation. So about all this allows you to
do is some simple substitution that provides a complete path, such as:
#define MyPath "../../path/to/my/file.h"
#include MyPath
Link to documentation. In particular this section doesn't leave much hope for portable solutions:
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.
For completeness, maybe something can be tried using https://stackoverflow.com/a/27830271/2436175. I'll investigate that when I have a moment...

I'm not sure that this is exactly what you want but anyway.
#define DECORATE(x) <x>
#define MAKE_PATH(root, file) DECORATE(root file)
#define SYS_DIR(file) MAKE_PATH(sys/, file)
#define ARPA_DIR(file) MAKE_PATH(arpa/, file)
#include SYS_DIR(types.h)
#include SYS_DIR(socket.h)
#include ARPA_DIR(inet.h)
Note, that generated filenames contain extra space - <sys/ types.h>, so it may not be a cross-compiler solution. But at least for me it works on Linux host on GCC 4.8 / 4.9.
P.S. It would be nice if someone could check this snippet with another compilers, e.g. MSVC.

Simply avoid the space and the concatenation (##) and use the < > it makes all simplier:
#include <QtCore/QtGlobal>
#define QT_VERSION_PREFIX QT_VERSION_MAJOR.QT_VERSION_MINOR.QT_VERSION_PATCH
#define _CONCATE(a, c) <a/QT_VERSION_PREFIX/a/private/c>
#include _CONCATE(QtWidgets, qwidgettextcontrol_p.h)

Related

How can I include a header file that contains `>` in its name?

This is quite a contrived problem, I admit, but here it is.
Suppose you have a file with the > character in its name. This is possible on most Unix systems afaik:
$ touch 'weird>name'
$ ls -l
-rw-r--r-- 1 user user 0 28 Mag 11:05 weird>name
Now, suppose this file contains C/C++ code and you want to include it as an header:
#include <weird>name>
int main() {
return weird_function();
}
Clang gives me the following error:
test.cpp:1:10: fatal error: 'weird' file not found
#include <weird>name>
Of course, since the preprocessor parses the directive up to the first > and looks for the weird file. But, I wonder if some escaping mechanism exists to allow me to include the right file.
So, in C and/or C++, is there a way to include an header file which has the > character in its name?
Edit: Many suggested me why not to use #include "weird>name". I admit that my mind slipped over the quotes syntax while writing the question, but it remains valid because the two syntaxes may ask the compiler to search in different paths (theoretically at least). So is there any escaping mechanism to let me include weird>name using the #include <> syntax?
So, in C and/or C++, is there a way to include an header file which has the > character in its name?
Yes:
#include "weird>name"
So is there any escaping mechanism to let me include weird>name using the #include <> syntax?
No. The characters between the < and > must be "any member of the source character set except new-line and >" ([lex.header]). Any escaped form of > would still be a way to represent the > character, which is not allowed. Edit: Implementations are allowed to support implementation-defined escape sequences there though (see [lex.header] p2 and its footnote).
The #include " q-char-sequence " form does allow the > character to appear, even though it might get reprocessed as #include <...> if searching as "..." fails ([cpp.include] p3).
The preprocessor also allows another form ([cpp.include] p4](http://eel.is/c++draft/cpp.include#4)), but its effect are implementation-defined, and the implementations I tried do not allow joining weird and > and name into a single preprocessor-token that can then be included
Ask the author of your compiler.
The C and C++ standards grant a lot of leeway to implementations over the interpretation of #include directives. There's no requirement that #include <foo.h> causes the inclusion of a file called "foo.h". For instance, a compiler can choose to ROT13 all the source file names if it likes. And for non-alphanumeric characters, the implementation can identify and remap certain character sequences. So if there were a platform where > regularly showed up in filenames, it's likely that a compiler for that platform would specify that, say, \g or something would be remapped to >. But the standard doesn't mandate a particular encoding.
Incidentally, the implementation could also just choose to allow #include <weird>name>. Since that is not well-formed under the language standards, an implementation is free to define a meaning for it as an extension.
Try below syntax:
#include "weird>name"

How to extract headers from source file using clang?

I am using clang ast matcher to extract some information fromt the source file. Now, I would also like to know the list of headers and dependency headers that the source file is using. For example, the source file abc.c has following header:
#include <def.h>
//#include <def_private.h>
During clang matcher, I need to make sure clang knows about the def.h, which is in the same directory. The def.h includes the following headers:
#include <iostream.h>
#include <string.h>
#include <float.h>
#include <math.h>
/*#include <boost>
* #inclde <fstream>*/
I do ast matcher to extract or identify information from abc.c. Now, I would like to extract all the headers or includes. This should include all of them:
#include <def.h>
#include <iostream.h>
#include <string.h>
#include <float.h>
#include <math.h>
I did some online research to do this, unfortunately all of them are involving regex (Regular expression to extract header name from c file) or how to do in visual studio (Displaying the #include hierarchy for a C++ file in Visual Studio).
I wonder if it is possible using clang. Also, please let me know if there is any other way to programmatically extract the headers that is more than just using regular expression.
OP says Any other way to programmatically extract the headers that is more than just using a regular expression. .... without clang is ok.
We both agree that regexes are simply incapable of doing this right. You need the source text parsed as a tree with the #include directives explicitl appearing in the tree.
I'm not a Clang expert. I suspect its internal tree reflects preprocessed source, so the #include constructs have vanished. The problem is then one of insisting on preprocessing the source text to parse it.
Our DMS Software Reengineering Toolkit with its C++17 capable parser can handle such parsing without expanding the directives. It can do this two ways: a) where preprocessor directives are "well structured" with respect to the source code, the C++ front end can be configured to capture a parse tree with the directives also parsed as trees in appropriate places; this works pretty well in practice at the price of sometimes having to hand-patch a particularly ugly conditional or macro call to make it "well structured, or b) parse capturing the preprocessor directives placed in (almost) arbitrary way; this captures the directives sometimes at the price of automatically duplicating small bits of code to in essence cause the good restructuring liked by case a).
In either case, the #include directives now appear explicitly in the AST, with the included file pretty much built as an auxiliary tree representing the included file. Such tree nodes easily found by a tree walk looking for such explicit include nodes.
DMS's ASTInterface provides ScanTree to walk across nodes and taking actions when some provided predicate is true of a node; checking for #include nodes is easy. It is useful to note that becaause the conditional directives are also retained, by walking up the tree from a #include onr can construct the condition under which that include file is actually included.
Of course, the header file itself is also parsed, producing a tree. Any includes it has appear in its tree body. One would have to run ScanTree over each of these trees to collect all the includes.
OP didn't say what he wanted to do with the #includes. DMS provides a lot beyond parsing to help OP achieve her purpose, including symbol table construction, control and dataflow analysis, tree pattern matching, tree-to-tree transformations expressed in terms of source language (C++) syntax, and finally source code (re)generated from a modified syntax tree.

how to concatenate strings in #include statement [duplicate]

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.

How do I use a preprocessor macro inside an include?

I am trying to build freetype2 using my own build system (I do not want to use Jam, and I am prepared to put the time into figuring it out). I found something odd in the headers. Freetype defines macros like this:
#define FT_CID_H <freetype/ftcid.h>
and then uses them later like this:
#include FT_CID_H
I didn't think that this was possible, and indeed Clang 3.9.1 complains:
error: expected "FILENAME" or <FILENAME>
#include FT_CID_H
What is the rationale behind these macros?
Is this valid C/C++?
How can I convince Clang to parse these headers?
This is related to How to use a macro in an #include directive? but different because the question here is about compiling freetype, not writing new code.
I will address your three questions out of order.
Question 2
Is this valid C/C++?
Yes, this is indeed valid. Macro expansion can be used to produce the final version of a #include directive. Quoting C++14 (N4140) [cpp.include] 16.2/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 (i.e., each identifier currently defined as a macro name is
replaced by its replacement list of preprocessing tokens). If the directive resulting after all replacements does
not match one of the two previous forms, the behavior is undefined.
The "previous forms" mentioned are #include "..." and #include <...>. So yes, it is legal to use a macro which expands to the header/file to include.
Question 1
What is the rationale behind these macros?
I have no idea, as I've never used the freetype2 library. That would be a question best answered by its support channels or community.
Question 3
How can I convince Clang to parse these headers?
Since this is legal C++, you shouldn't have to do anything. Indeed, user #Fanael has demonstrated that Clang is capable of parsing such code. There must be some problem other problem in your setup or something else you haven't shown.
Is this valid C/C++?
The usage is valid C, provided that the macro definition is in scope at the point where the #include directive appears. Specifically, paragraph 6.10.2/4 of C11 says
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.
(Emphasis added.) Inasmuch as the preprocessor has the same semantics in C++ as in C, to the best of my knowledge, the usage is also valid in C++.
What is the rationale behind these macros?
I presume it is intended to provide for indirection of the header name or location (by providing alternative definitions of the macro).
How can I convince Clang to parse these headers?
Provided, again, that the macro definition is in scope at the point where the #include directive appears, you shouldn't have to do anything. If indeed it is, then Clang is buggy in this regard. In that case, after filing a bug report (if this issue is not already known), you probably need to expand the troublesome macro references manually.
But before you do that, be sure that the macro definitions really are in scope. In particular, they may be guarded by conditional compilation directives -- in that case, the best course of action would probably be to provide whatever macro definition is needed (via the compiler command line) to satisfy the condition. If you are expected to do this manually, then surely the build documentation discusses it. Read the build instructions.

Concatenate and stringize macro values for #include

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.