www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - X header like functionality

reply "Mattias" <holm liacs.nl> writes:
Hi, I spent some time recently learning D. I am curious about the 
best way to implement something like X-includes in C. I.e. where 
one use macros that you redefine at the include point.

This is indispensable sometimes for keeping code in sync.

For example, if we in an include header writes:

---
#ifndef X
#define X(a, b)
#endif

X(int, foo)

#undef X
---

We can then include it as follows (this probably won't compile, 
but should serve as an illustration):

// Define the globals
#define X(a, b) a b;
#include "blah.inc"

struct {char *, void *} myarray[] = {
#define X(a, b) {#b, &b} , // C99 allows for comma at the end
#include "blah.inc"
};

The point here is that we can make a single point definition of 
something which is then later used in multiple locations in order 
to keep things in sync.

So my question is, whether there is some clever way to use mixins 
and templates that accomplish roughly the same thing of defining 
a table at one location and then reusing the table at multiple 
locations for different purposes?
Jul 08 2012
parent reply "Lukasz" <wrzoski gmail.com> writes:
On Sunday, 8 July 2012 at 08:05:58 UTC, Mattias wrote:
 Hi, I spent some time recently learning D. I am curious about 
 the best way to implement something like X-includes in C. I.e. 
 where one use macros that you redefine at the include point.

 This is indispensable sometimes for keeping code in sync.

 For example, if we in an include header writes:

 ---
 #ifndef X
 #define X(a, b)
 #endif

 X(int, foo)

 #undef X
 ---

 We can then include it as follows (this probably won't compile, 
 but should serve as an illustration):

 // Define the globals
 #define X(a, b) a b;
 #include "blah.inc"

 struct {char *, void *} myarray[] = {
 #define X(a, b) {#b, &b} , // C99 allows for comma at the end
 #include "blah.inc"
 };

 The point here is that we can make a single point definition of 
 something which is then later used in multiple locations in 
 order to keep things in sync.

 So my question is, whether there is some clever way to use 
 mixins and templates that accomplish roughly the same thing of 
 defining a table at one location and then reusing the table at 
 multiple locations for different purposes?
This should do the trick: alias tuple!("MBlaze", "CppBackend", "MSIL", "CBackend", "Blackfin", "SystemZ", "MSP430", "XCore", "PIC16", "CellSPU", "Mips", "ARM", "Alpha", "PowerPC", "Sparc", "X86") Targets; string TARGETS(string prefix, string postfix) { string ret = ""; foreach(target; Targets) { ret = ret ~ prefix ~ target ~ postfix; } return ret; } mixin(TARGETS("void LLVMInitialize", "TargetInfo();\n")); mixin(TARGETS("void LLVMInitialize", "Target();\n")); mixin(TARGETS("void LLVMInitialize", "TargetMC();\n"));
Jul 08 2012
parent Matt Soucy <msoucy csh.rit.edu> writes:
On 07/08/2012 05:39 AM, Lukasz wrote:
 On Sunday, 8 July 2012 at 08:05:58 UTC, Mattias wrote:
 Hi, I spent some time recently learning D. I am curious about the best
 way to implement something like X-includes in C. I.e. where one use
 macros that you redefine at the include point.

 This is indispensable sometimes for keeping code in sync.

 For example, if we in an include header writes:

 ---
 #ifndef X
 #define X(a, b)
 #endif

 X(int, foo)

 #undef X
 ---

 We can then include it as follows (this probably won't compile, but
 should serve as an illustration):

 // Define the globals
 #define X(a, b) a b;
 #include "blah.inc"

 struct {char *, void *} myarray[] = {
 #define X(a, b) {#b, &b} , // C99 allows for comma at the end
 #include "blah.inc"
 };

 The point here is that we can make a single point definition of
 something which is then later used in multiple locations in order to
 keep things in sync.

 So my question is, whether there is some clever way to use mixins and
 templates that accomplish roughly the same thing of defining a table
 at one location and then reusing the table at multiple locations for
 different purposes?
This should do the trick: alias tuple!("MBlaze", "CppBackend", "MSIL", "CBackend", "Blackfin", "SystemZ", "MSP430", "XCore", "PIC16", "CellSPU", "Mips", "ARM", "Alpha", "PowerPC", "Sparc", "X86") Targets; string TARGETS(string prefix, string postfix) { string ret = ""; foreach(target; Targets) { ret = ret ~ prefix ~ target ~ postfix; } return ret; } mixin(TARGETS("void LLVMInitialize", "TargetInfo();\n")); mixin(TARGETS("void LLVMInitialize", "Target();\n")); mixin(TARGETS("void LLVMInitialize", "TargetMC();\n"));
Another thing that is closer to the original idea is to use string imports. By using -J instead of -I as an argument to dmd, you can tell it to look for string imports within a certain folder. After that, you simply:
import("stuff.inc");
and it gets treated as a string literal. So, how is this helpful? At this point, you can use mixin, as in
mixin(import("stuff.inc"));
Or, you could use a CTFE function to mess with the string first, it's up to you. I'm attaching a quick test I whipped up, hopefully it sends... -Matt Soucy
Jul 08 2012