/** * @file error.h * @brief Declares the public error API. */ #ifndef _AKGL_ERROR_H_ #define _AKGL_ERROR_H_ #include /* * libakerror 1.0.0 is the floor. That release moved the status-name table into a * private registry -- AKERR_MAX_ERR_VALUE and __AKERR_ERROR_NAMES are gone, the * registry entry points raise akerr_ErrorContext * instead of returning int, and * the library gained an soname -- so a translation unit that pairs this header * with a pre-1.0.0 akerror.h is an ABI mismatch, not just a compile problem. * * libakerror publishes no version macro, so this feature-tests on * AKERR_FIRST_CONSUMER_STATUS, which that release introduced, rather than on a * version number that does not exist. Without the guard an embedded build is * fine but a stale installed header fails much further in, on the AKGL_ERR_* * codes below and again inside src/heap.c. * * See deps/libakerror/UPGRADING.md. */ #ifndef AKERR_FIRST_CONSUMER_STATUS #error "libakgl requires libakerror >= 1.0.0: the akerror.h on the include path predates the status registry. Rebuild and reinstall libakerror." #endif // Silences -Wformat-truncation on a string concatenation that genuinely may not // fit -- e.g. joining two PATH_MAX strings into one AKGL_MAX_STRING_LENGTH // buffer. The line has to be drawn somewhere or the buffers grow forever to // keep the compiler happy. // // **Nothing in libakgl uses these any more.** Both sites -- the path join in // akgl_path_relative and the tileset image join in // akgl_tilemap_load_layer_image -- now go through aksl_snprintf, which raises // AKERR_OUTOFBOUNDS on truncation instead. That is the better answer: the // compiler was right both times, and silencing it left the truncation // happening and unreported. Kept because they are public and a consumer may // have them; see TODO.md. #define DISABLE_GCC_WARNING_FORMAT_TRUNCATION \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wformat-truncation\"") #define RESTORE_GCC_WARNINGS \ _Pragma("GCC diagnostic pop") // libakerror reserves statuses 0-255 for the host's errno values and its own // AKERR_* codes; consumers allocate from AKERR_FIRST_CONSUMER_STATUS upward. // These are fixed offsets from that base rather than from AKERR_LAST_ERRNO_VALUE // so that a libc which grows an errno cannot move them out from under us. // // akgl_error_init() reserves this whole band in one call and registers a name // for every code below. Add a code here and you must name it there, or it // prints as "Unknown Error" in every stack trace that carries it. #define AKGL_ERR_OWNER "libakgl" #define AKGL_ERR_BASE AKERR_FIRST_CONSUMER_STATUS #define AKGL_ERR_SDL (AKGL_ERR_BASE + 0) /**< An SDL call failed; the message carries SDL_GetError() */ #define AKGL_ERR_REGISTRY (AKGL_ERR_BASE + 1) /**< A registry property or lookup operation failed */ #define AKGL_ERR_HEAP (AKGL_ERR_BASE + 2) /**< A heap pool has no free object left to hand out */ #define AKGL_ERR_BEHAVIOR (AKGL_ERR_BASE + 3) /**< A component did not behave the way its contract requires */ #define AKGL_ERR_LOGICINTERRUPT (AKGL_ERR_BASE + 4) /**< Actor logic is telling the physics simulator to skip it */ // One past the last libakgl status. The reservation is all-or-nothing -- a // subset or superset of an existing one is refused -- so this must stay one // past the highest code above. #define AKGL_ERR_LIMIT (AKGL_ERR_BASE + 5) #define AKGL_ERR_COUNT (AKGL_ERR_LIMIT - AKGL_ERR_BASE) /** * @brief Claim the libakgl status band and register a name for every code in it. * * Call this before anything else in libakgl. Every other subsystem raises * AKGL_ERR_* codes, and a code raised before this runs carries no name into its * stack trace. Repeating the call is a no-op, so a program that cannot order its * initialization precisely may call it more than once. * * @throws AKERR_STATUS_RANGE_OVERLAP When another component already owns part of the band. * @throws AKERR_STATUS_RANGE_FULL When libakerror has no reservation slots left. * @throws AKERR_STATUS_NAME_FULL When libakerror's name registry is full. */ akerr_ErrorContext AKERR_NOIGNORE *akgl_error_init(void); #endif // _AKGL_ERROR_H_