#ifndef __VXGG_REWRITE___SHARED_H___3880294315821___ #define __VXGG_REWRITE___SHARED_H___3880294315821___ #include #define STATIC_ARRAY_LEN(arr) (sizeof((arr))/sizeof((arr)[0])) #define FALSE 0 #define TRUE 1 #define RETURNWERR(errval, retval) do {\ errno = (errval);\ return (retval);\ } while (0) // Defines how `x___alloc()` functions should exit. `___VXGG___XALLOC_EXIT_ON_ERROR___ > 0` calls `error()`, and thus functions // registered with `atexit()` and `on_exit()`. `___VXGG___XALLOC_EXIT_ON_ERROR___ <= 0` calls `abort()` on error. `x___alloc()` // type functions will ALWAYS 'abort', doing otherwise defeats the purpose of the function type #define ___VXGG___XALLOC_EXIT_ON_ERROR___ 1 // Defines whether vxgg functions that can error print out a short warning of the error when one is encountered. // `___VXGG___VERBOSE_ERRORS___ > 0` will print diagnostic error messages, and will do nothing otherwise #define ___VXGG___VERBOSE_ERRORS___ 1 // Macro to exit on an alloc error instead of doing the terrible nested if statement that was being used previously #define XALLOC_EXIT(msg, ...) do {\ if(!___VXGG___XALLOC_EXIT_ON_ERROR___)\ abort();\ if(!___VXGG___VERBOSE_ERRORS___)\ exit(EXIT_FAILURE);\ error(EXIT_FAILURE, errno, (msg)__VA_ARGS__);\ exit(EXIT_FAILURE); /* Makes gcc happy */\ } while (0) // Whether to use `XALLOC` or normal `malloc` functions for acquiring new memory via the `VALLOC()` macro. `> 0` // enables XALLOC functionality #define ___VXGG___USE_XALLOC_FOR_VALLOC___ 0 #define VALLOC(nmemb, size) ((___VXGG___USE_XALLOC_FOR_VALLOC___ > 0) ? xmalloc((nmemb) * (size)) : malloc((nmemb) * (size))) // Error macro that gcc will not complain about #define ERROR(status, errnum, format, ...) do {error((status), (errnum), (format)__VA_ARGS__); exit((status));} while (0) // `malloc()` with error checking. Calls `exit()` or `abort()` on error, depending on the value of `___VXGG___XALLOC_EXIT_ON_ERROR___` void * xmalloc(size_t size); // `calloc()` with error checking. Calls `exit()` or `abort()` on error, depending on the value of `___VXGG___XALLOC_EXIT_ON_ERROR___` void * xcalloc(size_t nmemb, size_t size); // `reallocarray()` with error checking. Calls `exit()` or `abort()` on error, depending on the value of `___VXGG___XALLOC_EXIT_ON_ERROR___` void * xreallocarray(void *ptr, size_t nmemb, size_t size); // Read the entire contents of a file descriptor into a malloc()'ed buffer int rwbuf(char **str, unsigned long int initsize, int fd); // Write the entire contents of a buffer into a file descriptor int wwbuf(int fd, const unsigned char *buf, int len); // `dirname()` reimplementation that returns a malloc()'ed string. According to the `x___` naming scheme, exits/aborts on alloc error. char * xdirname(const char * const path); // Cleanup callback. Should act like `free()`, in that it doesn't crash if the pointer it's given is null typedef void (*cleanup_callback)(void*); // Cleanup struct. Stores a STATICALLY defined array of callbacks and void* arguments typedef struct cl { cleanup_callback *funcs; void **args; int size; int used; } cleanup; // Initialize a local cleanup stack. `loc`, `funcs` and `args` need to be locally defined, non allocated arrays, and must be at least `size` elements large int cleanup_init(cleanup * const loc, int size, cleanup_callback funcs[], void *args[]); // Register a cleanup callback for a given cleanup object int cleanup_register(cleanup * const loc, cleanup_callback cb, void *arg); // Register a cleanup callback, if and only if `flag == 0` int cleanup_cndregister(cleanup * const loc, unsigned char flag, cleanup_callback cb, void *arg); // Clear the contents of a cleanup stack int cleanup_clear(cleanup * const loc); // Get the top callback without removing it from the cleanup stack cleanup_callback cleanup_peekf(cleanup * const loc); // Get and remove the top callback from the cleanup stack. Does not return the argument for the given callback cleanup_callback cleanup_popf(cleanup * const loc); // Get the top argument without removing it from the cleanup stack void * cleanup_peeka(cleanup * const loc); // Get and remove the top argument from the cleanup stack. Does not return the callback it was to be fed into void * cleanup_popa(cleanup * const loc); // Fire all the callbacks in the cleanup stack int cleanup_fire(cleanup * const loc); /* Cleanup environment creator. Automatically defines the variables `__CLEANUP`, `__CLEANUP_FUNCS`, and `__CLEANUP_ARGS` and initializes // via `cleanup_init()` using these variables. */ #define cleanup_CREATE(size) \ cleanup __CLEANUP; \ cleanup_callback __CLEANUP_FUNCS[(size)]; \ void *__CLEANUP_ARGS[(size)]; \ unsigned char __FLAG = 0; \ cleanup_init(&__CLEANUP, (size), __CLEANUP_FUNCS, __CLEANUP_ARGS) #define cleanup_REGISTER(cb, arg) cleanup_register(&__CLEANUP, (cb), (arg)) #define cleanup_CNDREGISTER(cb, arg) cleanup_cndregister(&__CLEANUP, __FLAG, (cb), (arg)) #define cleanup_CLEAR() cleanup_clear(&__CLEANUP) #define cleanup_PEEKF() cleanup_peekf(&__CLEANUP) #define cleanup_POPF() cleanup_popf(&__CLEANUP) #define cleanup_PEEKA() cleanup_peeka(&__CLEANUP) #define cleanup_POPA() cleanup_popa(&__CLEANUP) #define cleanup_FIRE() cleanup_fire(&__CLEANUP) #define cleanup_MARK() (__FLAG = 1) #define cleanup_UNMARK() (__FLAG = 0) #define cleanup_ERRORFLAGGED (__FLAG != 0) #endif