Affix
view release on metacpan or search on metacpan
infix/src/core/error.c view on Meta::CPAN
#elif defined(INFIX_COMPILER_GCC)
// MinGW (GCC on Windows) and standard GCC/Clang on *nix.
// MinGW prefers __thread or _Thread_local over __declspec(thread).
#define INFIX_TLS __thread
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
// Fallback to C11 standard
#define INFIX_TLS _Thread_local
#else
// Fallback for compilers that do not support TLS. This is not thread-safe.
#warning "Compiler does not support thread-local storage; error handling will not be thread-safe."
#define INFIX_TLS
#endif
// A portable macro for safe string copying to prevent buffer overflows.
#if defined(INFIX_COMPILER_MSVC)
#define _INFIX_SAFE_STRNCPY(dest, src, count) strncpy_s(dest, sizeof(dest), src, count)
#else
#define _INFIX_SAFE_STRNCPY(dest, src, count) \
do { \
strncpy(dest, src, (count)); \
(dest)[(sizeof(dest)) - 1] = '\0'; \
} while (0)
#endif
/**
* @var g_infix_last_error
* @brief The thread-local variable that stores the details of the last error.
*
* @details Each thread gets its own independent instance of this variable. It is
* initialized to a "no error" state.
*/
static INFIX_TLS infix_error_details_t g_infix_last_error = {INFIX_CATEGORY_NONE, INFIX_CODE_SUCCESS, 0, 0, {0}};
/**
* @var g_infix_last_signature_context
* @brief A thread-local pointer to the full signature string being parsed.
*
* @details This is set by the high-level API functions (`infix_type_from_signature`, etc.)
* before parsing begins. If a parser error occurs, `_infix_set_error` uses this
* context to generate a rich, contextual error message.
*/
INFIX_TLS const char * g_infix_last_signature_context = nullptr;
/**
* @internal
* @brief Maps an `infix_error_code_t` to its human-readable string representation.
* @param code The error code to map.
* @return A constant string describing the error.
*/
static const char * _get_error_message_for_code(infix_error_code_t code) {
switch (code) {
case INFIX_CODE_SUCCESS:
return "Success";
case INFIX_CODE_UNKNOWN:
return "An unknown error occurred";
case INFIX_CODE_NULL_POINTER:
return "A required pointer argument was NULL";
case INFIX_CODE_MISSING_REGISTRY:
return "A type registry was required but not provided";
case INFIX_CODE_NATIVE_EXCEPTION:
return "A native exception was thrown across the FFI boundary";
case INFIX_CODE_OUT_OF_MEMORY:
return "Out of memory";
case INFIX_CODE_EXECUTABLE_MEMORY_FAILURE:
return "Failed to allocate executable memory";
case INFIX_CODE_PROTECTION_FAILURE:
return "Failed to change memory protection flags";
case INFIX_CODE_INVALID_ALIGNMENT:
return "Invalid alignment requested (must be power of two > 0)";
case INFIX_CODE_UNEXPECTED_TOKEN:
return "Unexpected token or character";
case INFIX_CODE_UNTERMINATED_AGGREGATE:
return "Unterminated aggregate (missing '}', '>', ']', or ')')'";
case INFIX_CODE_INVALID_KEYWORD:
return "Invalid type keyword";
case INFIX_CODE_MISSING_RETURN_TYPE:
return "Function signature missing '->' or return type";
case INFIX_CODE_INTEGER_OVERFLOW:
return "Integer overflow detected during layout calculation";
case INFIX_CODE_RECURSION_DEPTH_EXCEEDED:
return "Type definition is too deeply nested";
case INFIX_CODE_EMPTY_MEMBER_NAME:
return "Named type was declared with empty angle brackets";
case INFIX_CODE_EMPTY_SIGNATURE:
return "The provided signature string was empty";
case INFIX_CODE_UNSUPPORTED_ABI:
return "The current platform ABI is not supported";
case INFIX_CODE_TYPE_TOO_LARGE:
return "A data type was too large to be handled by the ABI";
case INFIX_CODE_UNRESOLVED_NAMED_TYPE:
return "Named type not found in registry or is an undefined forward declaration";
case INFIX_CODE_INVALID_MEMBER_TYPE:
return "Aggregate contains an illegal member type (e.g., a struct with a void member)";
case INFIX_CODE_LIBRARY_NOT_FOUND:
return "The requested dynamic library could not be found";
case INFIX_CODE_SYMBOL_NOT_FOUND:
return "The requested symbol was not found in the library";
case INFIX_CODE_LIBRARY_LOAD_FAILED:
return "Loading the dynamic library failed";
default:
return "An unknown or unspecified error occurred";
}
}
/**
* @internal
* @brief Sets the last error details for the current thread.
*
* If the error is from the parser and a signature context is available, this
* function generates a rich, multi-line diagnostic message with a code snippet
* and a caret pointing to the error location. Otherwise, it uses the standard,
* single-line message for the given error code.
*
* @param category The category of the error.
* @param code The specific error code.
* @param position For parser errors, the byte offset into the signature string where the error occurred.
*/
void _infix_set_error(infix_error_category_t category, infix_error_code_t code, size_t position) {
g_infix_last_error.category = category;
g_infix_last_error.code = code;
g_infix_last_error.position = position;
( run in 2.299 seconds using v1.01-cache-2.11-cpan-437f7b0c052 )