From 13b7b29157c47442e9443c8b914b3eddd95477e5 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Fri, 8 May 2015 21:50:22 -0500 Subject: [PATCH] Replace OOM checks with light wrappers around allocation functions. --- src/assembler.c | 5 +---- src/assembler/errors.c | 22 ++++++---------------- src/assembler/hash_table.c | 11 +++-------- src/assembler/instructions.c | 11 ++++------- src/assembler/io.c | 15 ++++----------- src/assembler/parse_util.c | 9 ++------- src/assembler/preprocessor.c | 38 ++++++++------------------------------ src/assembler/tokenizer.c | 42 +++++++++--------------------------------- src/config.c | 28 +++++++--------------------- src/gamegear.c | 10 ++-------- src/logging.h | 24 +++++++++++++----------- src/mmu.c | 12 +++--------- src/mmu.h | 2 +- src/rom.c | 9 +++------ src/util.h | 2 ++ src/util_alloc.h | 40 ++++++++++++++++++++++++++++++++++++++++ 16 files changed, 108 insertions(+), 172 deletions(-) create mode 100644 src/util_alloc.h diff --git a/src/assembler.c b/src/assembler.c index ea292eb..67750a1 100644 --- a/src/assembler.c +++ b/src/assembler.c @@ -201,10 +201,7 @@ size_t assemble(const LineBuffer *source, uint8_t **binary_ptr, ErrorInfo **ei_p if ((error_info = resolve_symbols(&state))) goto error; - uint8_t *binary = malloc(sizeof(uint8_t) * state.rom_size); - if (!binary) - OUT_OF_MEMORY() - + uint8_t *binary = cr_malloc(sizeof(uint8_t) * state.rom_size); serialize_binary(&state, binary); *binary_ptr = binary; retval = state.rom_size; diff --git a/src/assembler/errors.c b/src/assembler/errors.c index 5bc412f..4a30f10 100644 --- a/src/assembler/errors.c +++ b/src/assembler/errors.c @@ -6,7 +6,7 @@ #include "errors.h" #include "state.h" #include "../assembler.h" -#include "../logging.h" +#include "../util.h" /* Error strings */ @@ -82,27 +82,20 @@ struct ErrorInfo { */ static ASMErrorLine* create_error_line(const ASMLine *line) { - ASMErrorLine *el = malloc(sizeof(ASMErrorLine)); - if (!el) - OUT_OF_MEMORY() - + ASMErrorLine *el = cr_malloc(sizeof(ASMErrorLine)); const char *source = line->original->data; size_t length = line->original->length; - if (!(el->data = malloc(sizeof(char) * length))) - OUT_OF_MEMORY() // Ignore spaces at beginning: while (length > 0 && (*source == ' ' || *source == '\t')) source++, length--; + + el->data = cr_malloc(sizeof(char) * length); memcpy(el->data, source, length); el->length = length; el->lineno = line->original->lineno; - - el->filename = strdup(line->filename); - if (!el->filename) - OUT_OF_MEMORY() - + el->filename = cr_strdup(line->filename); el->next = NULL; return el; } @@ -119,10 +112,7 @@ static ASMErrorLine* create_error_line(const ASMLine *line) ErrorInfo* error_info_create( const ASMLine *line, ASMErrorType err_type, ASMErrorDesc err_desc) { - ErrorInfo *einfo = malloc(sizeof(ErrorInfo)); - if (!einfo) - OUT_OF_MEMORY() - + ErrorInfo *einfo = cr_malloc(sizeof(ErrorInfo)); einfo->type = err_type; einfo->desc = err_desc; einfo->line = line ? create_error_line(line) : NULL; diff --git a/src/assembler/hash_table.c b/src/assembler/hash_table.c index 566cece..7fec740 100644 --- a/src/assembler/hash_table.c +++ b/src/assembler/hash_table.c @@ -5,7 +5,7 @@ #include #include "hash_table.h" -#include "../logging.h" +#include "../util.h" #define INITIAL_BUCKETS 127 @@ -61,13 +61,8 @@ static inline bool keyeq(const char *s1, const char *s2, ssize_t size) HashTable* hash_table_new( size_t key_offset, size_t next_offset, HashFreeCallback callback) { - HashTable *table; - if (!(table = malloc(sizeof(HashTable)))) - OUT_OF_MEMORY() - - if (!(table->nodes = calloc(INITIAL_BUCKETS, sizeof(HashNode*)))) - OUT_OF_MEMORY() - + HashTable *table = cr_malloc(sizeof(HashTable)); + table->nodes = cr_calloc(INITIAL_BUCKETS, sizeof(HashNode*)); table->buckets = INITIAL_BUCKETS; table->key_offset = key_offset; table->next_offset = next_offset; diff --git a/src/assembler/instructions.c b/src/assembler/instructions.c index 3d11602..3481a00 100644 --- a/src/assembler/instructions.c +++ b/src/assembler/instructions.c @@ -7,7 +7,7 @@ #include "instructions.h" #include "inst_args.h" #include "parse_util.h" -#include "../logging.h" +#include "../util.h" /* Helper macros for get_inst_parser() */ @@ -26,8 +26,7 @@ #define INST_ALLOC_(len) \ *length = len; \ - if (!(*bytes = malloc(sizeof(uint8_t) * (len)))) \ - OUT_OF_MEMORY() + *bytes = cr_malloc(sizeof(uint8_t) * (len)); #define INST_SET_(b, val) ((*bytes)[b] = val) #define INST_SET1_(b1) INST_SET_(0, b1) @@ -55,7 +54,7 @@ static ASMErrorDesc parse_inst_##mnemonic( \ #define INST_TAKES_NO_ARGS \ if (ap_info.arg) \ - INST_ERROR(TOO_MANY_ARGS) \ + INST_ERROR(TOO_MANY_ARGS) #define INST_TAKES_ARGS(lo, hi) \ if (!ap_info.arg) \ @@ -104,9 +103,7 @@ static ASMErrorDesc parse_inst_##mnemonic( \ } #define INST_RETURN_WITH_SYMBOL(len, label, ...) { \ - *symbol = strdup(label); \ - if (!(*symbol)) \ - OUT_OF_MEMORY() \ + *symbol = cr_strdup(label); \ INST_ALLOC_(len) \ INST_FILL_BYTES_(len - 2, __VA_ARGS__) \ return ED_NONE; \ diff --git a/src/assembler/io.c b/src/assembler/io.c index f5b42b6..ab02333 100644 --- a/src/assembler/io.c +++ b/src/assembler/io.c @@ -9,6 +9,7 @@ #include "io.h" #include "../logging.h" +#include "../util.h" /* Deallocate a LineBuffer previously created with read_source_file(). @@ -59,14 +60,9 @@ LineBuffer* read_source_file(const char *path, bool print_errors) return NULL; } - LineBuffer *source = malloc(sizeof(LineBuffer)); - if (!source) - OUT_OF_MEMORY() - + LineBuffer *source = cr_malloc(sizeof(LineBuffer)); source->lines = NULL; - source->filename = strdup(path); - if (!source->filename) - OUT_OF_MEMORY() + source->filename = cr_strdup(path); Line dummy = {.next = NULL}; Line *line, *prev = &dummy; @@ -90,10 +86,7 @@ LineBuffer* read_source_file(const char *path, bool print_errors) return NULL; } - line = malloc(sizeof(Line)); - if (!line) - OUT_OF_MEMORY() - + line = cr_malloc(sizeof(Line)); line->data = data; line->length = feof(fp) ? len : (len - 1); line->lineno = lineno++; diff --git a/src/assembler/parse_util.c b/src/assembler/parse_util.c index 974a1ad..b060cac 100644 --- a/src/assembler/parse_util.c +++ b/src/assembler/parse_util.c @@ -7,7 +7,6 @@ #include "parse_util.h" #include "directives.h" -#include "../logging.h" #include "../util.h" #define MAX_REGION_SIZE 32 @@ -183,9 +182,7 @@ bool parse_string(char **result, size_t *length, const char *arg, ssize_t size) return false; *length = size - 2; - *result = malloc(sizeof(char) * (*length)); - if (!*result) - OUT_OF_MEMORY() + *result = cr_malloc(sizeof(char) * (*length)); memcpy(*result, arg + 1, *length); return true; } @@ -217,9 +214,7 @@ bool parse_bytes(uint8_t **result, size_t *length, const char *arg, ssize_t size } nbytes++; - bytes = realloc(bytes, sizeof(uint8_t) * nbytes); - if (!bytes) - OUT_OF_MEMORY() + bytes = cr_realloc(bytes, sizeof(uint8_t) * nbytes); bytes[nbytes - 1] = temp; if (arg < end - 1 && *arg == ',' && *(arg + 1) == ' ') diff --git a/src/assembler/preprocessor.c b/src/assembler/preprocessor.c index 8a38314..884f017 100644 --- a/src/assembler/preprocessor.c +++ b/src/assembler/preprocessor.c @@ -121,14 +121,8 @@ static size_t read_labels( return 0; } - ASMLine *line = malloc(sizeof(ASMLine)); - if (!line) - OUT_OF_MEMORY() - - line->data = malloc(sizeof(char) * (i - start + 1)); - if (!line->data) - OUT_OF_MEMORY() - + ASMLine *line = cr_malloc(sizeof(ASMLine)); + line->data = cr_malloc(sizeof(char) * (i - start + 1)); memcpy_lc(line->data, source + start, i - start + 1); line->length = i - start + 1; line->is_label = true; @@ -160,10 +154,7 @@ static ASMLine* normalize_line(const char *source, size_t length) source += offset; length -= offset; - char *data = malloc(sizeof(char) * length); - if (!data) - OUT_OF_MEMORY() - + char *data = cr_malloc(sizeof(char) * length); size_t si, di, slashes = 0; bool has_content = false, space_pending = false, in_string = false; for (si = di = 0; si < length; si++) { @@ -206,14 +197,8 @@ static ASMLine* normalize_line(const char *source, size_t length) return head; } - ASMLine *line = malloc(sizeof(ASMLine)); - if (!line) - OUT_OF_MEMORY() - - data = realloc(data, sizeof(char) * di); - if (!data) - OUT_OF_MEMORY() - + ASMLine *line = cr_malloc(sizeof(ASMLine)); + data = cr_realloc(data, sizeof(char) * di); line->data = data; line->length = di; line->is_label = false; @@ -239,10 +224,7 @@ static char* read_include_path(const ASMLine *line) if (maxlen >= INT_MAX) // Allows us to safely downcast to int later return NULL; - char *path = malloc(sizeof(char) * maxlen), *base, *dup; - if (!path) - OUT_OF_MEMORY() - + char *path = cr_malloc(sizeof(char) * maxlen), *base, *dup; if (!(i = DIRECTIVE_OFFSET(line, DIR_INCLUDE))) goto error; if (line->length - i <= 3) // Not long enough to hold a non-zero argument @@ -252,8 +234,7 @@ static char* read_include_path(const ASMLine *line) if (!parse_string(&base, &baselen, line->data + i, line->length - i)) goto error; - if (!(dup = strdup(line->filename))) - OUT_OF_MEMORY() + dup = cr_strdup(line->filename); // TODO: should normalize filenames in some way to prevent accidental dupes snprintf(path, maxlen, "%s/%.*s", dirname(dup), (int) baselen, base); @@ -330,10 +311,7 @@ static ErrorInfo* build_asm_lines( goto error; } - ASMInclude *include = malloc(sizeof(ASMInclude)); - if (!include) - OUT_OF_MEMORY() - + ASMInclude *include = cr_malloc(sizeof(ASMInclude)); include->lines = incbuffer; include->next = *includes; *includes = include; diff --git a/src/assembler/tokenizer.c b/src/assembler/tokenizer.c index 81bbde2..beb9808 100644 --- a/src/assembler/tokenizer.c +++ b/src/assembler/tokenizer.c @@ -9,7 +9,6 @@ #include "instructions.h" #include "inst_args.h" #include "parse_util.h" -#include "../logging.h" #include "../mmu.h" #include "../rom.h" #include "../util.h" @@ -63,12 +62,8 @@ static void init_layout_info(ASMLayoutInfo *li, AssemblerState *state) li->origin = NULL; li->bank = 0; li->cross_blocks = state->cross_blocks; - - if (!(li->overlap_table = calloc(li->size, sizeof(const ASMLine*)))) - OUT_OF_MEMORY() - - if (!(li->overlap_origins = calloc(li->size, sizeof(const ASMLine*)))) - OUT_OF_MEMORY() + li->overlap_table = cr_calloc(li->size, sizeof(const ASMLine*)); + li->overlap_origins = cr_calloc(li->size, sizeof(const ASMLine*)); for (size_t i = 0; i < HEADER_SIZE; i++) li->overlap_table[state->header.offset + i] = &header_sentinel; @@ -104,10 +99,7 @@ static ErrorInfo* add_label_to_table( if (argparse_condition(&cond, info)) return error_info_create(line, ET_SYMBOL, ED_SYM_IS_CONDITION); - char *symbol = strndup(line->data, line->length - 1); - if (!symbol) - OUT_OF_MEMORY() - + char *symbol = cr_strndup(line->data, line->length - 1); const ASMSymbol *current = asm_symtable_find(symtable, symbol); if (current) { ErrorInfo *ei = error_info_create(line, ET_SYMBOL, ED_SYM_DUPE_LABELS); @@ -116,10 +108,7 @@ static ErrorInfo* add_label_to_table( return ei; } - ASMSymbol *label = malloc(sizeof(ASMSymbol)); - if (!label) - OUT_OF_MEMORY() - + ASMSymbol *label = cr_malloc(sizeof(ASMSymbol)); label->offset = map_into_slot(offset, (slot >= 0) ? slot : default_bank_slot(offset / MMU_ROM_BANK_SIZE)); label->symbol = symbol; @@ -169,13 +158,8 @@ static ErrorInfo* handle_define_directive( if (!argparse_immediate(&imm, info)) return error_info_create(line, ET_PREPROC, ED_PP_BAD_ARG); - ASMDefine *define = malloc(sizeof(ASMDefine)); - if (!define) - OUT_OF_MEMORY() - - if (!(define->name = strndup(key, keylen))) - OUT_OF_MEMORY() - + ASMDefine *define = cr_malloc(sizeof(ASMDefine)); + define->name = cr_strndup(key, keylen); define->value = imm; define->line = line; asm_deftable_insert(deftab, define); @@ -285,9 +269,7 @@ static bool parse_space( } *length = bytes[0]; - if (!(*result = malloc(sizeof(uint8_t) * (*length)))) - OUT_OF_MEMORY() - + *result = cr_malloc(sizeof(uint8_t) * (*length)); memset(*result, nbytes == 2 ? bytes[1] : 0, *length); free(bytes); return true; @@ -328,10 +310,7 @@ static ErrorInfo* parse_data( const char *arg = line->data + dir_offset; size_t arglen = line->length - dir_offset; - ASMData *data = malloc(sizeof(ASMData)); - if (!data) - OUT_OF_MEMORY() - + ASMData *data = cr_malloc(sizeof(ASMData)); data->loc.offset = offset; data->next = NULL; @@ -386,10 +365,7 @@ static ErrorInfo* parse_instruction( if (edesc != ED_NONE) return error_info_create(line, ET_PARSER, edesc); - ASMInstruction *inst = malloc(sizeof(ASMInstruction)); - if (!inst) - OUT_OF_MEMORY() - + ASMInstruction *inst = cr_malloc(sizeof(ASMInstruction)); inst->loc.offset = offset; inst->loc.length = length; inst->bytes = bytes; diff --git a/src/config.c b/src/config.c index 0aeae5b..1777772 100644 --- a/src/config.c +++ b/src/config.c @@ -10,6 +10,7 @@ #include "config.h" #include "logging.h" +#include "util.h" #include "version.h" /* @@ -73,21 +74,15 @@ static int get_rom_paths(char ***path_ptr) dirp = opendir(ROMS_DIR); if (dirp) { - paths = malloc(sizeof(char*) * psize); - if (!paths) - OUT_OF_MEMORY() + paths = cr_malloc(sizeof(char*) * psize); while ((entry = readdir(dirp))) { path = entry->d_name; if (ends_with(path, ".gg") || ends_with(path, ".bin")) { if (npaths >= psize) { - paths = realloc(paths, sizeof(char*) * (psize *= 2)); - if (!paths) - OUT_OF_MEMORY() + paths = cr_realloc(paths, sizeof(char*) * (psize *= 2)); } - paths[npaths] = malloc(sizeof(char*) * + paths[npaths] = cr_malloc(sizeof(char*) * (strlen(path) + strlen(ROMS_DIR) + 1)); - if (!paths[npaths]) - OUT_OF_MEMORY() strcpy(paths[npaths], ROMS_DIR "/"); strcat(paths[npaths], path); npaths++; @@ -159,9 +154,7 @@ static int parse_args(Config *config, int argc, char *argv[]) return CONFIG_EXIT_FAILURE; } - path = malloc(sizeof(char) * (strlen(arg) + 1)); - if (!path) - OUT_OF_MEMORY() + path = cr_malloc(sizeof(char) * (strlen(arg) + 1)); strcpy(path, arg); if (paths_read == 1) { @@ -264,9 +257,7 @@ static void guess_assembler_output_file(Config* config) } } while (ptr-- >= src); - config->dst_path = malloc(sizeof(char) * (until_ext + 5)); - if (!config->dst_path) - OUT_OF_MEMORY() + config->dst_path = cr_malloc(sizeof(char) * (until_ext + 5)); strcpy(stpncpy(config->dst_path, src, until_ext), ext); } @@ -315,14 +306,9 @@ static bool sanity_check(Config* config) */ int config_create(Config** config_ptr, int argc, char* argv[]) { - Config *config; + Config *config = cr_malloc(sizeof(Config)); int retval; - if (!(config = malloc(sizeof(Config)))) { - OUT_OF_MEMORY() - return CONFIG_EXIT_FAILURE; - } - config->debug = false; config->assemble = false; config->disassemble = false; diff --git a/src/gamegear.c b/src/gamegear.c index 3ecc0dd..4d6742e 100644 --- a/src/gamegear.c +++ b/src/gamegear.c @@ -12,17 +12,11 @@ /* Create and return a pointer to a new GameGear object. - - If memory could not be allocated, OUT_OF_MEMORY() is triggered. */ GameGear* gamegear_create() { - GameGear *gg = malloc(sizeof(GameGear)); - if (!gg) - OUT_OF_MEMORY() - - if (!mmu_init(&gg->mmu)) - OUT_OF_MEMORY() + GameGear *gg = cr_malloc(sizeof(GameGear)); + mmu_init(&gg->mmu); z80_init(&gg->cpu, &gg->mmu); gg->powered = false; gg->exc_buffer[0] = '\0'; diff --git a/src/logging.h b/src/logging.h index b0cd09e..a40e3cd 100644 --- a/src/logging.h +++ b/src/logging.h @@ -10,27 +10,29 @@ /* Internal usage only */ -#define LOG_MSG(dest, level, extra, after, ...) { \ +#define LOG_MSG_(dest, level, extra, after, ...) { \ fprintf(dest, level ": " __VA_ARGS__); \ extra; \ fprintf(dest, "\n"); \ after; \ } -#define PRINT_ERRNO() fprintf(stderr, ": %s", strerror(errno)) + +#define LOG_ERR_(...) LOG_MSG_(stderr, __VA_ARGS__) +#define LOG_OUT_(...) LOG_MSG_(stdout, __VA_ARGS__) + +#define PRINT_ERRNO_() fprintf(stderr, ": %s", strerror(errno)) /* Public logging macros */ -#define FATAL(...) LOG_MSG(stderr, "fatal", {}, exit(EXIT_FAILURE), __VA_ARGS__) -#define FATAL_ERRNO(...) LOG_MSG(stderr, "fatal", PRINT_ERRNO(), exit(EXIT_FAILURE), __VA_ARGS__) -#define ERROR(...) LOG_MSG(stderr, "error", {}, {}, __VA_ARGS__) -#define ERROR_ERRNO(...) LOG_MSG(stderr, "error", PRINT_ERRNO(), {}, __VA_ARGS__) -#define WARN(...) LOG_MSG(stderr, "warning", {}, {}, __VA_ARGS__) -#define WARN_ERRNO(...) LOG_MSG(stderr, "warning", PRINT_ERRNO(), {}, __VA_ARGS__) +#define FATAL(...) LOG_ERR_("fatal", {}, exit(EXIT_FAILURE), __VA_ARGS__) +#define FATAL_ERRNO(...) LOG_ERR_("fatal", PRINT_ERRNO_(), exit(EXIT_FAILURE), __VA_ARGS__) +#define ERROR(...) LOG_ERR_("error", {}, {}, __VA_ARGS__) +#define ERROR_ERRNO(...) LOG_ERR_("error", PRINT_ERRNO_(), {}, __VA_ARGS__) +#define WARN(...) LOG_ERR_("warning", {}, {}, __VA_ARGS__) +#define WARN_ERRNO(...) LOG_ERR_("warning", PRINT_ERRNO_(), {}, __VA_ARGS__) #ifdef DEBUG_MODE -#define DEBUG(...) LOG_MSG(stdout, "[DEBUG]", {}, {}, __VA_ARGS__) +#define DEBUG(...) LOG_OUT_("[DEBUG]", {}, {}, __VA_ARGS__) #else #define DEBUG(...) {} #endif - -#define OUT_OF_MEMORY() FATAL("couldn't allocate enough memory") diff --git a/src/mmu.c b/src/mmu.c index 64f83a5..f6b2879 100644 --- a/src/mmu.c +++ b/src/mmu.c @@ -5,27 +5,21 @@ #include #include "logging.h" +#include "util.h" #include "z80.h" /* Initialize a MMU object. This must be called before using the MMU. - - Return true if initialization was successful, or false if the required - amount of memory could not be allocated. */ -bool mmu_init(MMU *mmu) +void mmu_init(MMU *mmu) { - mmu->system_ram = malloc(sizeof(uint8_t) * MMU_SYSTEM_RAM_SIZE); - if (!mmu->system_ram) - return false; + mmu->system_ram = cr_malloc(sizeof(uint8_t) * MMU_SYSTEM_RAM_SIZE); for (size_t slot = 0; slot < MMU_NUM_SLOTS; slot++) mmu->map_slots[slot] = NULL; for (size_t bank = 0; bank < MMU_NUM_ROM_BANKS; bank++) mmu->rom_banks[bank] = NULL; - - return true; } /* diff --git a/src/mmu.h b/src/mmu.h index a76d4c5..3ee4088 100644 --- a/src/mmu.h +++ b/src/mmu.h @@ -22,7 +22,7 @@ typedef struct { /* Functions */ -bool mmu_init(MMU*); +void mmu_init(MMU*); void mmu_free(MMU*); void mmu_load_rom(MMU*, const uint8_t*, size_t); void mmu_power(MMU*); diff --git a/src/rom.c b/src/rom.c index 90a2b30..2083dd6 100644 --- a/src/rom.c +++ b/src/rom.c @@ -169,8 +169,7 @@ const char* rom_open(ROM **rom_ptr, const char *path) return (st.st_mode & S_IFDIR) ? rom_err_isdir : rom_err_notfile; } - if (!(rom = malloc(sizeof(ROM)))) - OUT_OF_MEMORY() + rom = cr_malloc(sizeof(ROM)); // Set defaults: rom->name = NULL; @@ -183,8 +182,7 @@ const char* rom_open(ROM **rom_ptr, const char *path) rom->region_code = 0; // Set rom->name: - if (!(rom->name = malloc(sizeof(char) * (strlen(path) + 1)))) - OUT_OF_MEMORY() + rom->name = cr_malloc(sizeof(char) * (strlen(path) + 1)); strcpy(rom->name, path); DEBUG("Loading ROM %s:", rom->name) @@ -198,8 +196,7 @@ const char* rom_open(ROM **rom_ptr, const char *path) rom->size = st.st_size; // Set rom->data: - if (!(rom->data = malloc(sizeof(uint8_t) * st.st_size))) - OUT_OF_MEMORY() + rom->data = cr_malloc(sizeof(uint8_t) * st.st_size); if (!(fread(rom->data, st.st_size, 1, fp))) { rom_close(rom); fclose(fp); diff --git a/src/util.h b/src/util.h index 64f21c9..2dbd81b 100644 --- a/src/util.h +++ b/src/util.h @@ -6,6 +6,8 @@ #include #include +#include "util_alloc.h" + #define INVALID_SIZE_CODE 0x8 /* Functions */ diff --git a/src/util_alloc.h b/src/util_alloc.h new file mode 100644 index 0000000..babbd16 --- /dev/null +++ b/src/util_alloc.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2014-2015 Ben Kurtovic + Released under the terms of the MIT License. See LICENSE for details. */ + +#pragma once + +#include +#include +#include + +#include "logging.h" + +#define OUT_OF_MEMORY() FATAL("couldn't allocate enough memory") + +#define OOM_GUARD_(type, call) \ + type ptr = call; \ + if (!ptr) \ + OUT_OF_MEMORY() \ + return ptr; + +#define OOM_GUARD_FUNC_1_(ret_type, func, arg_type) \ + static inline ret_type cr_##func(arg_type arg1) { \ + OOM_GUARD_(ret_type, func(arg1)) \ + } + +#define OOM_GUARD_FUNC_2_(ret_type, func, arg1_type, arg2_type) \ + static inline ret_type cr_##func(arg1_type arg1, arg2_type arg2) { \ + OOM_GUARD_(ret_type, func(arg1, arg2)) \ + } + +/* Functions */ + +OOM_GUARD_FUNC_1_(void*, malloc, size_t) // cr_malloc +OOM_GUARD_FUNC_2_(void*, calloc, size_t, size_t) // cr_calloc +OOM_GUARD_FUNC_2_(void*, realloc, void*, size_t) // cr_realloc +OOM_GUARD_FUNC_1_(char*, strdup, const char*) // cr_strdup +OOM_GUARD_FUNC_2_(char*, strndup, const char*, size_t) // cr_strndup + +#undef OOM_GUARD_FUNC2_ +#undef OOM_GUARD_FUNC1_ +#undef OOM_GUARD_