I'd like to wrap a function-like C macro in a C function (and in turn wrap it in Haskell with a {#fun ... #}
block), but the c2hs
preprocessor chokes on the do.. while(0)
syntax;
here's the code:
module TestMacro where
#c
#define TestF1(n) do{if n==0 return 0;else return 1; } while(0)
int c_testF1(int x)
{ return ( TestF1(x) ); }
#endc
and here's the error:
c2hs TestMacro.chs
c2hs: C header contains errors:
TestMacro.chs.h:6: (column 12) [ERROR] >>> Syntax error !
The symbol `do' does not fit here.
make: *** [main] Error 1
What am I doing wrong?
My goal is wrapping the CHKERRQ
macro of the PETSc library, defined as follows in petscerror.h
(split onto multiple lines for readability):
#define CHKERRQ(n)
do {if (PetscUnlikely(n))
return PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_REPEAT," ");}
while (0)
Remember that #define
is text replacement. So
{ return ( TestF1(c) ); }
becomes
{ return ( do{if c==0 return 0;else return 1; } while(0) ); }
and you can neither use do { .. } while()
nor other return
statements as return parameters (and the brackets around the ìf
- condition are missing). For your macro to work at that place it could be simply defined as
#define TestF1(n) ((n)==0 ? 0 : 1)
Edit
A function that uses CHKERRQ
could look like this
int my_chkerrq( int n )
{
CHKERRQ(n);
return( whatever_you_want_to_return_here );
}
but I would suggest to directly call what CHKERRQ()
calls:
int my_chkerrq( int n )
{
if (PetscUnlikely(n))
return( PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_REPEAT," ") );
else
return( whatever_you_want_to_return_here );
}
Of course, in both cases __LINE__
and __FILE__
are replaced by those of the C code and may not be very useful in the Haskell environment