1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-14 10:13:05 +02:00
pgbackrest/libc/LibC.h
2017-11-06 22:55:34 -05:00

145 lines
15 KiB
C

/***********************************************************************************************************************************
Helper macros for LibC.xs
***********************************************************************************************************************************/
/***********************************************************************************************************************************
Package Names
***********************************************************************************************************************************/
#define PACKAGE_NAME "pgBackRest"
#define PACKAGE_NAME_LIBC PACKAGE_NAME "::LibC"
/***********************************************************************************************************************************
Load C error into ERROR_SV_error
#define FUNCTION_NAME_ERROR "libcExceptionNew"
#define ERROR_SV() \
SV *ERROR_SV_error; \
\
{ \
// Push parameters onto the Perl stack \
ENTER; \
SAVETMPS; \
PUSHMARK(SP); \
EXTEND(SP, 2); \
PUSHs(sv_2mortal(newSViv(errorCode()))); \
PUSHs(sv_2mortal(newSVpv(errorMessage(), 0))); \
PUTBACK; \
\
// Call error function \
int count = call_pv(PACKAGE_NAME_LIBC "::" FUNCTION_NAME_ERROR, G_SCALAR); \
SPAGAIN; \
\
// Check that correct number of parameters was returned \
if (count != 1) \
croak("expected 1 return value from " FUNCTION_NAME_ERROR "()"); \
\
// Make a copy of the error that can be returned \
ERROR_SV_error = newSVsv(POPs); \
\
// Clean up the stack \
PUTBACK; \
FREETMPS; \
LEAVE; \
}
This turned out to be a dead end because Perl 5.10 does not support croak_sv(), but this code has been kept for example purposes.
***********************************************************************************************************************************/
/***********************************************************************************************************************************
Error handling macros that throw a Perl error when a C error is caught
***********************************************************************************************************************************/
#define ERROR_XS_BEGIN() \
ERROR_TRY()
#define ERROR_XS() \
croak("PGBRCLIB:%d:%s:%d:%s", errorCode(), errorFileName(), errorFileLine(), errorMessage());
#define ERROR_XS_END() \
ERROR_CATCH_ANY() \
{ \
ERROR_XS(); \
}
/***********************************************************************************************************************************
Core context handling macros, only intended to be called from other macros
***********************************************************************************************************************************/
#define MEM_CONTEXT_XS_CORE_BEGIN(memContext) \
/* Switch to the new memory context */ \
MemContext *MEM_CONTEXT_XS_memContextOld = memContextSwitch(memContext); \
\
/* Store any errors to be croaked to Perl at the end */ \
volatile bool MEM_CONTEXT_XS_croak = false; \
\
/* Try the statement block */ \
ERROR_TRY()
#define MEM_CONTEXT_XS_CORE_END() \
/* Set error to be croak to Perl later */ \
ERROR_CATCH_ANY() \
{ \
MEM_CONTEXT_XS_croak = true; \
} \
/* Free the context on error */ \
ERROR_FINALLY() \
{ \
memContextSwitch(MEM_CONTEXT_XS_memContextOld); \
}
/***********************************************************************************************************************************
Simplifies creation of the memory context in contructors and includes error handling
***********************************************************************************************************************************/
#define MEM_CONTEXT_XS_NEW_BEGIN(contextName) \
{ \
/* Attempt to create the memory context */ \
MemContext *MEM_CONTEXT_XS_memContext = NULL; \
\
ERROR_TRY() \
{ \
MEM_CONTEXT_XS_memContext = memContextNew(contextName); \
} \
ERROR_CATCH_ANY() \
{ \
ERROR_XS() \
} \
\
MEM_CONTEXT_XS_CORE_BEGIN(MEM_CONTEXT_XS_memContext)
#define MEM_CONTEXT_XS_NEW_END() \
MEM_CONTEXT_XS_CORE_END(); \
\
/* Free context and croak on error */ \
if (MEM_CONTEXT_XS_croak) \
{ \
memContextFree(MEM_CONTEXT_XS_memContext); \
\
ERROR_XS() \
} \
}
#define MEM_COMTEXT_XS() \
MEM_CONTEXT_XS_memContext
/***********************************************************************************************************************************
Simplifies switching the memory context in functions and includes error handling
***********************************************************************************************************************************/
#define MEM_CONTEXT_XS_BEGIN(memContext) \
{ \
MEM_CONTEXT_XS_CORE_BEGIN(memContext)
#define MEM_CONTEXT_XS_END() \
MEM_CONTEXT_XS_CORE_END(); \
\
/* Croak on error */ \
if (MEM_CONTEXT_XS_croak) \
{ \
ERROR_XS() \
} \
}
/***********************************************************************************************************************************
Free memory context in destructors
***********************************************************************************************************************************/
#define MEM_CONTEXT_XS_DESTROY(memContext) \
memContextFree(memContext)