# ifndef OHANA_ALLOCATE
# define OHANA_ALLOCATE

/* default is to use basic system memory functions */
# ifdef OHANA_MEMORY

void *ohana_malloc (char *file, int line, int Nelem, size_t esize);
void *ohana_realloc (char *file, int line, void *in, int Nelem, size_t esize);
void  ohana_free (char *file, int line, void *in);
void  ohana_memregister_func (char *file, int line, void *ptr);
void  ohana_memdump_func (int mode);
void  ohana_memcheck_func (int mode);

# define ohana_memregister(X) ohana_memregister_func (__FILE__, __LINE__, (X));
# define ohana_memcheck(X) ohana_memcheck_func (X);
# define ohana_memdump(X) ohana_memdump_func (X);

# define ALLOCATE(X,T,S) \
  X = (T *) ohana_malloc (__FILE__, __LINE__, (S), sizeof(T))
# define REALLOCATE(X,T,S) \
  X = (T *) ohana_realloc(__FILE__, __LINE__, X, (S), sizeof(T));
# define CHECK_REALLOCATE(X,T,S,N,D) \
  if ((N) >= (S)) { S += D; \
  X = (T *) ohana_realloc(__FILE__, __LINE__, X, (S), sizeof(T)); }
# define FREE(X) if (X != NULL) { ohana_free (__FILE__, __LINE__, X); }
# define free(X) ohana_free(__FILE__, __LINE__, X)

# else 
# define ohana_memregister(X) /* NOP */
# define ohana_memcheck(X) /* NOP */
# define ohana_memdump(X) /* NOP */
# endif /* OHANA_MEMORY */

# ifndef ALLOCATE
# define ALLOCATE(X,T,S)  \
  X = (T *) malloc ((unsigned)(MAX(((S)*((int)sizeof(T))),1))); \
  if (X == NULL) { \
    fprintf(stderr,"failed malloc at %d in %s\n", __LINE__, __FILE__);\
    exit (10); } 
# define REALLOCATE(X,T,S) \
  X = (T *) realloc(X,(unsigned)(MAX(((S)*((int)sizeof(T))),1))); \
  if (X == NULL) { \
    fprintf(stderr,"failed realloc at %d in %s\n", __LINE__, __FILE__);\
    exit (10); }
# define CHECK_REALLOCATE(X,T,S,N,D) \
  if ((N) >= (S)) { \
    S += D; \
    X = (T *) realloc(X,(unsigned)(MAX(((S)*((int)sizeof(T))),1))); \
    if (X == NULL) { \
      fprintf(stderr,"failed realloc increment at %d in %s\n", __LINE__, __FILE__);\
      exit (10); } }
# define FREE(X) if (X != NULL) { free (X); }
# endif /* ALLOCATE */

# endif /* OHANA_ALLOCATE */
