Affix
view release on metacpan or search on metacpan
infix/src/core/error.c view on Meta::CPAN
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;
g_infix_last_error.system_error_code = 0;
// Check if we can generate a rich parser error message.
if (category == INFIX_CATEGORY_PARSER && g_infix_last_signature_context != nullptr) {
// Generate a rich, GCC-style error message for parser failures.
const char * signature = g_infix_last_signature_context;
size_t sig_len = strlen(signature);
const size_t radius = 20; // Number of characters to show around the error position.
// Calculate the start and end of the snippet to display.
size_t start = (position > radius) ? (position - radius) : 0;
size_t end = (position + radius < sig_len) ? (position + radius) : sig_len;
// Add indicators if the snippet is truncated.
const char * start_indicator = (start > 0) ? "... " : "";
const char * end_indicator = (end < sig_len) ? " ..." : "";
size_t start_indicator_len = (start > 0) ? 4 : 0;
// Create the code snippet line.
char snippet[128];
snprintf(snippet,
sizeof(snippet),
"%s%.*s%s",
start_indicator,
(int)(end - start),
signature + start,
end_indicator);
// Create the pointer line with a caret '^' under the error.
char pointer[128];
size_t caret_pos = position - start + start_indicator_len;
snprintf(pointer, sizeof(pointer), "%*s^", (int)caret_pos, "");
// Build the final multi-line message piece by piece to avoid buffer overflows.
char * p = g_infix_last_error.message;
size_t remaining = sizeof(g_infix_last_error.message);
int written;
// Write the snippet and pointer lines.
written = snprintf(p, remaining, "\n\n %s\n %s", snippet, pointer);
if (written < 0 || (size_t)written >= remaining) {
// Fallback to a simple message on snprintf failure or buffer overflow.
const char * msg = _get_error_message_for_code(code);
_INFIX_SAFE_STRNCPY(g_infix_last_error.message, msg, sizeof(g_infix_last_error.message) - 1);
return;
}
p += written;
remaining -= written;
// Append the standard error description.
snprintf(p, remaining, "\n\nError: %s", _get_error_message_for_code(code));
}
else {
// For non-parser errors, just copy the standard message.
const char * msg = _get_error_message_for_code(code);
_INFIX_SAFE_STRNCPY(g_infix_last_error.message, msg, sizeof(g_infix_last_error.message) - 1);
}
}
/**
* @internal
* @brief Sets a detailed system error with a platform-specific error code and message.
*
* @details This is used for errors originating from OS-level functions like `dlopen`,
* `mmap`, or `VirtualAlloc`. It records both the `infix` error code and the
* underlying system error code (`errno` or `GetLastError`).
*
* @param category The category of the error.
* @param code The `infix` error code that corresponds to the failure.
* @param system_code The OS-specific error code (e.g., from `errno` or `GetLastError`).
* @param msg An optional custom message from the OS (e.g., from `dlerror`). If `nullptr`, the default message for
* `code` is used.
*/
void _infix_set_system_error(infix_error_category_t category,
infix_error_code_t code,
long system_code,
const char * msg) {
g_infix_last_error.category = category;
g_infix_last_error.code = code;
g_infix_last_error.position = 0;
g_infix_last_error.system_error_code = system_code;
if (msg)
_INFIX_SAFE_STRNCPY(g_infix_last_error.message, msg, sizeof(g_infix_last_error.message) - 1);
else {
const char * default_msg = _get_error_message_for_code(code);
_INFIX_SAFE_STRNCPY(g_infix_last_error.message, default_msg, sizeof(g_infix_last_error.message) - 1);
}
}
/**
* @internal
* @brief Resets the error state for the current thread to "no error".
*
* This should be called at the beginning of every public API function to ensure
( run in 0.506 second using v1.01-cache-2.11-cpan-f56aa216473 )