Translating C macros to D

Jacob Carlborg via Digitalmars-d digitalmars-d at puremagic.com
Mon Jul 10 12:42:28 PDT 2017


I'm trying to come up with a generic way to translate function like C 
macros to D to be used in DStep.

One problem with macros is that it's not possible, by just looking at 
the macro, to understand how it's used, what can be passed to it. For 
example, it's possible to pass values, variables and types to a C macro. 
But I cannot come up with a signature for a template or function in D 
that would work for all cases.

Currently DStep translates the macros to templated functions where each 
parameter has its own template type and are declared as "auto ref". Example:

#define _IOR(type,nr,size) 
_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))

Is translated to:

extern (D) auto _IOR(T0, T1, T2)(auto ref T0 type, auto ref T1 nr, auto 
ref T2 size)
{
     return _IOC(_IOC_READ, type, nr, (_IOC_TYPECHECK(size)));
}

Use as follows:

enum FE_READ_BER = _IOR('o', 70, uint);

The problem with this translation is that it's not possible to pass only 
a type to this function.

Second try: use alias parameters and only template parameters:

extern (D) auto _IOR(alias type, alias nr, alias size)();

Use as a template:

enum FE_READ_BER = _IOR!('o', 70, uint);

This won't compile either because it's not possible to pass a type to an 
alias parameter. This is probably a bug that should be fixed.

Third try:

Use the template variadic parameter trick:

extern (D) auto _IOR(Args... /* type, nr, size */)() if (Args.length == 3);

Now the above usage example actually works:

enum FE_READ_BER = _IOR!('o', 70, uint);

Unfortunately it's not possible to take the address of a variable and 
pass to template variadic parameter:

void foo(Args...)() {}

void main()
{
     int b;
     foo!(b); // passing the variable directly works fine
     foo!(&b); // Error: variable b cannot be read at compile time
}

The strange thing is, if I add another function and pass to the variadic 
parameter it does work:

void foo(Args...)(Args args)
{
     bar!(args);
}

void bar(Args...)() {}

void main()
{
     int a;
     foo(&a);
}

Does anyone have any other ideas that would work for everything that can 
be passed to a C macro?

-- 
/Jacob Carlborg


More information about the Digitalmars-d mailing list