The problem: How to get a C preprocessor to #include different .h files based on a user-#defined symbol, whose all possible values are generally unknown at the time the code is written. In other words, how to get the preprocessor to substitute Foo for Bar inside #include "Foo.h" Note, the preprocessor does not normally substitute #defined symbols inside C strings (let alone parts of C strings, let alone #include strings) This is not an abstract problem: it came up during implementation of "link-time plug-ins". I was working on a communication application, and was trying to make higher-level functions (segment fragmentation/assembly, etc) as independent of the actual transport mechanism as possible. To this end, all interface with the transport was done via a pair of abstract classes LAPIn/LAPOut, which define necessary methods to send/receive a byte, and wait for a packet to arrive. Classes derived from LAPIn/LAPOut are then responsible for implementing these abstract methods according to a particular transport layer protocol. For example, if the application is to communicate through a UNIX file (pipe, character-device), a receiver module source code does #include "LAPFile.h" and instantiates an object LAPFileIn in_link; (of a class LAPFileIn derived from LAPIn). If the receiver works with a UDP TCP/IP link, the receiver code performs #include "LAPNet.h" and instantiates an object LAPNetIn in_link; In either case, only LAPIn methods of the in_link object are actually used in the receiver, regardless which particular LAPIn-derived class the object actually belongs to. As far as my application is concerned, the only difference between a File and a Network transport is in the names, LAPFile vs. LAPNet. Later on I developed a link using Win95/WinNT COM port, and compiled the receiver with LAPFile substituted by LAPSWin. Again, only the names differed. In either case, the object code implementing a particular transport is plugged-in at the link time. One can easily accomplish these substitutions with a text editor. But what if I don't want to modify the applications' source code at all? If a primitive character substitution is one and the only one thing needs to be done to tune in the application to a different transport, why not to use a C preprocessor, and define the name of a transport layer at the compile time, with -D compiler directive (or with a corresponding Project option in Borland/Metrowerk's IDEs) Thus gcc -DDEFLAP=DEFFile receiver.cc -lplug-ins -lother-libs -o receiver would make the receiver's executable that uses a file transport. If I compile exactly the same source code as gcc -DDEFLAP=DEFNet receiver.cc -lplug-ins -lother-libs -o receiver the resulting application would use the UDP transport. Although the C preprocessor was designed to perform substitutions, the particular substitutions I need in this project are tough: for one thing, only a part of class' name -- LAPFileIn, LAPNetIn, etc -- needs to be substituted, suffix 'In' must stay. But the toughest part is to get the preprocessor to substitute inside an #include "string", that is, to _compute_ an .h file name on the fly, and then to include that file - all at the compile time. There is an obvious naive solution that immediately springs to mind: #if defined(LAPFile) #include "LAPFile.h" #define LAPClass LAPFileIn #elif defined(LAPNet) #include "LAPNet.h" #define LAPClass LAPNetIn #endif and compile this source code pre-defining either LAPNet or LAPFile: gcc -DLAPNet receiver.cc However, this assumes that the user knows in advance the names of all transport protocols the application could possibly use. But what if this is not the case? What if later on I come up with a new transport, which I'd like to "plug-in" without modifying the source code? Thus the true substitution inside #include becomes necessary (a true computable #include) A solution: (a snippet from an actual working code, which compiles, takes plug-ins, and works _exactly_ as described above) // Select the LAPFile transport link by default // (can be overridden by -D compiler option) #ifndef DEFLAP #define DEFLAP LAPFile #endif // Some preprocessor black magic to form an #include // string and names involving DEFLAP #define _XqYq(x,y) x ## y #define _XY(x,y) _XqYq(x,y) #define QMAKESTR(x) #x #define MAKESTR(x) QMAKESTR(x) #define MAKEINC(x) x ## .h #define DEFLAPINC MAKEINC(DEFLAP) #define DEFLAPINCSTR MAKESTR(DEFLAPINC) #include "util.h" #include "Segment.h" #include DEFLAPINCSTR #include main(const int argc, const char * argv[]) { _XY(DEFLAP,In) in_stream; Sessions sessions(argv+1); // Pass the words of the sh-command while(!done) { try{ SegmentInStream new_packet(in_stream); sessions.remove_dead_sessions(session_ttl); sessions.digest(new_packet); } .... } } Note: a careful distinction between strings, symbols and their values. A preprocessor variable (#defined token) is a symbol, which can have a value - a token, an integer, or a string. The preprocessor is capable of performing some conversions among them: from a symbol to a string, from a token to an integer. The solution above takes an advantage of these conversions. Another example: including a file depending on compiler's version: for example, if the code is compiled with version 2.7 of gcc, then a file "ver7.h" would be included. Version 2.8 of the compiler would then include a file "ver8.h" - transparently and automatically, without requiring the user to modify a bit of the source code. (another application: a platform-specific #include). // Even more advanced example // Some preprocessor black magic to form an #include // string and names involving some predefined variables #define _XqYq(x,y) x ## y #define _XY(x,y) _XqYq(x,y) #define QMAKESTR(x) #x #define MAKESTR(x) QMAKESTR(x) #define MAKEINC(x) ver ## x ## .h #define DEFLAPINCU(X) MAKEINC(X) #define DEFLAPINC DEFLAPINCU(__GNUC_MINOR__) #define DEFLAPINCSTR MAKESTR(DEFLAPINC) #include DEFLAPINCSTR Indeed, when I compiled the above snippet using gcc 2.7.2, a file ver7.h _was_ included. All the snippets above have been tested with gcc 2.7.2 (on Sun/Solaris 2.4) and CodeWarrior9 on a PowerMac. Why did I call it "Scheming": relation to Scheme symbol->string and string->symbol primitive in Scheme That's why Scheme can do tricks like ; Writing, reading back and checking reference patterns (define VEIO:patterns `(1 ,#xffffffff 0 ,#xffff0000 ,#x0000ffff ,#x5a5a5a5a ,#xa5a5a5a5)) (define-macro (VEIO:stream-op name op) (define (op-symb suffix) (string->symbol (string-append (if (null? op) "write-" "read-") suffix))) `(define (,name stream) (for-each (lambda (x) (,@op stream ',(op-symb "int4") x)) VEIO:patterns) (for-each (lambda (x) (,@op stream ',(op-symb "int3") (modulo x #x1000000))) VEIO:patterns) (for-each (lambda (x) (,@op stream ',(op-symb "int2") (quotient x #x10000)) (,@op stream ',(op-symb "int2") (modulo x #x10000))) VEIO:patterns) (for-each (lambda (x) (,@op stream ',(op-symb "byte") (modulo (quotient x #x10000) #x100)) (,@op stream ',(op-symb "byte") (modulo (quotient x #x100) #x100)) (,@op stream ',(op-symb "byte") (modulo x #x100))) VEIO:patterns))) (VEIO:stream-op VEIO:write_patterns ()) (VEIO:stream-op VEIO:read_and_check_patterns (VEIO:read_and_check_value)) which I can later use as (VEIO:write_patterns stream))) So, the C preprocessor is much closer to Scheme than to C.... Alas, as far as C is concerned, the macro-language and the base language are actually different. In Scheme, they're the same.