Do..while (0) C function macrogrid in c2hs
I would like to put a macro of type C in a C function (and in turn wrap it in Haskell with a block {#fun ... #}
), but the preprocessor will c2hs
slam into the syntax do.. while(0)
; 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 to wrap a CHKERRQ
PETSc library macro defined in the petscerror.h
following way: (split over 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)
source to share
Remember, this #define
is a text replacement. So,
{ return ( TestF1(c) ); }
becomes
{ return ( do{if c==0 return 0;else return 1; } while(0) ); }
and you cannot use do { .. } while()
other operators return
as return parameters (and there are Γ¬f
no parentheses around the condition ). To make your macro work at this point, it could simply be defined as
#define TestF1(n) ((n)==0 ? 0 : 1)
Edit
The function using CHKERRQ
might look like this:
int my_chkerrq( int n )
{
CHKERRQ(n);
return( whatever_you_want_to_return_here );
}
but I would suggest directly triggering the calls CHKERRQ()
:
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 C code values ββand may not be very useful in the Haskell environment
source to share
{ return ( TestF1(c) ); }
The syntax return
requires an expression (optional): you cannot use an operator instead of an expression. do {} while (0)
- this statement.
(C11, 6.8.6. Jump Operators)
Syntax
return expression_opt;
What you can do is use instead:
int c_testF1(int x)
{ TestF1(c); }
As I added in the comments, it would work, but I don't advise doing it, it's bad coding style. ?:
can be used in an example macro TestF1
(as written in another answer), but it cannot be used for your real use case CHKERRQ
(you can use a macro to call a function PetscError
though).
source to share