#ifndef __mem__H
#define __mem__H

#include <stdarg.h>
#include <stdbool.h>
#include "kernel.h"

#ifdef __cplusplus
extern "C" {
#endif

#define EMem_Pack       0x01
#define EMem_Init       0x02
#define EMem_Dump       0x04
#define EMem_Check      0x08
#define EMem_CPP        0x10
#define EMem_Log        0x20
#define EMem_InitMask   0x3C
#define EMem_UseBlock   0x80

extern const char nil;
extern const char mem_NoMem[];

#define nvl(x) ( x ? x : &nil)

void* __mem_alloc(const char* f, int l, int);
void* __mem_realloc(const char* f, int l, void*, int);
void* __mem_calloc(const char* f, int l, int, int);
char* __mem_allocstring(const char* f, int l, const char*);
#ifdef __CC_NORCROFT
#pragma -v1 // hint to the compiler to check f/s/printf format
#endif
char* __mem_allocprint(const char* f, int l, const char*, ...);
#ifdef __CC_NORCROFT
#pragma -v0 // return to default
#endif
char* __mem_allocvprint(const char* f, int l, const char*, va_list);
bool __mem_setstring(const char* f, int l, const char**, const char*);
void __mem_free(const char* f, int l, const void*);
void* __throw_mem_alloc(const char* f, int l, int);
void* __throw_mem_calloc(const char* f, int l, int, int);
char* __throw_mem_allocstring(const char* f, int l, const char*);
#ifdef __CC_NORCROFT
#pragma -v1 // hint to the compiler to check f/s/printf format
#endif
char* __throw_mem_allocprint(const char* f, int l, const char*, ...);
#ifdef __CC_NORCROFT
#pragma -v0 // return to default
#endif
char* __throw_mem_allocvprint(const char* f, int l, const char*, va_list);
bool __throw_mem_setstring(const char* f, int l, const char**, const char*);

#define mem_alloc(x) __mem_alloc(__FILE__, __LINE__, x)
#define mem_realloc(x, y) __mem_realloc(__FILE__, __LINE__, x, y)
#define mem_calloc(x, y) __mem_calloc(__FILE__, __LINE__, x, y)
#define mem_allocstring(x) __mem_allocstring(__FILE__, __LINE__, x)
#define mem_allocprint(x, ...) __mem_allocprint(__FILE__, __LINE__, x, __VA_ARGS__)
#define mem_allocvprint(x, y) __mem_allocprint(__FILE__, __LINE__, x, y)
#define mem_setstring(x, y) __mem_setstring(__FILE__, __LINE__, x, y)
#define mem_free(x) __mem_free(__FILE__, __LINE__, x)
#define throw_mem_alloc(x) __throw_mem_alloc(__FILE__, __LINE__, x)
#define throw_mem_calloc(x, y) __throw_mem_calloc(__FILE__, __LINE__, x, y)
#define throw_mem_allocstring(x) __throw_mem_allocstring(__FILE__, __LINE__, x)
#define throw_mem_allocprint(x, ...) __throw_mem_allocprint(__FILE__, __LINE__, x, __VA_ARGS__)
#define throw_mem_allocvprint(x, y) __throw_mem_allocprint(__FILE__, __LINE__, x, y)
#define throw_mem_setstring(x, y) __throw_mem_setstring(__FILE__, __LINE__, x, y)

#define  throw_mem_nomem() throw_string(mem_NoMem)
void mem_init(int flags);
void mem_pack(void);
void mem_dump(void);
bool mem_check(void);
void throw_memcheck(void*);
void mem_removechecks(void);

#ifdef __cplusplus
}
#endif

#endif
