#ifndef GENERICSTACK_H
#define GENERICSTACK_H

#include <stdlib.h>       /* For malloc, free */
#include <stddef.h>       /* For size_t */
#include <string.h>       /* For memcpy */
#include <errno.h>        /* For errno */

/* =============== */
/* C generic stack */
/* =============== */

/* ---------------------------------------------------------------------- */
/* Most of the generic stack implementations either assume that every     */
/* element is of the same size, or bypass type checking going through     */
/* a C layer. This version does not have these two constraints.           */
/* By default it is restricted to ANSI-C data type, nevertheless          */
/* adding others is as trivial as looking into e.g. long long below.      */
/* Please note that, IF the data typecast to the stack, no warning.       */
/*                                                                        */
/* Purists will notice this is an array-based implementation. This        */
/* choice was made because it is fits all my applications.                */
/*                                                                        */
/* Define GENERICSTACK_C99           to have C99 data type                */
/* Define GENERICSTACK_CUSTOM to XXX to have a custom type XXX            */
/*                                                                        */
/* Stack size increases automatically if needed until user disposes it.   */
/* ---------------------------------------------------------------------- */
/* About the implementation we do use flexible arrays, because we do not  */
/* want to access out of what the compiler did on memory alignment,       */
/* internal padding etc...                                                */
/* Instead the rule is the following: as long as the generic stack usage  */
/* do not goes beyond the default size, internal default pool is used.    */
/* As soon as the usage goes beyond, the full data moved to the heap.     */
/* So, from access point of view, all data will always be aligned in a    */
/* single internal array, but there is a cost when:                       */
/* - usage goes beyond default length (once with a malloc + memcpy)       */

/* We count on any decent compiler to automatically inline our functions. */
/* In doubt, set the GENERICSTACK_INLINE keyword, that will tell we WISH  */
/* inlining.                                                              */
#ifdef __cplusplus
#  undef GENERICSTACK_INLINE /* With C++ inline is well defined */
#  define GENERICSTACK_INLINE inline
#else
#  ifndef GENERICSTACK_INLINE
#    define GENERICSTACK_INLINE /* Define it to nothing */
#  endif
#endif

/* ====================================================================== */
/* gcc family has the __builtin_expect that optimizes branch prediction.  */
/* This is off by default, but you can set the macros                     */
/* GENERICSTACK_LIKELY and GENERICSTACK_UNLIKELY to handle that.          */
/* ====================================================================== */
#ifndef GENERICSTACK_LIKELY
#  define GENERICSTACK_LIKELY(x) x
#endif
#ifndef GENERICSTACK_UNLIKELY
#  define GENERICSTACK_UNLIKELY(x) x
#endif

/* ====================================================================== */
/* In theory we should check for int turnaround. In practice this is      */
/* instructions for nothing, this is a so improbable case. Nevertheless   */
/* if you insist, set the variable GENERICSTACK_PARANOID.                 */
/* ====================================================================== */
/* #define GENERICSTACK_PARANOID */

/* ====================================================================== */
/* Stack default length.                                                  */
/* ====================================================================== */
#ifndef GENERICSTACK_DEFAULT_LENGTH
#  define GENERICSTACK_DEFAULT_LENGTH 128 /* Subjective number */
#endif
#if GENERICSTACK_DEFAULT_LENGTH < 0
/* We rely on GENERICSTACK_DEFAULT_LENGTH >= 0 to managed extension */
#  error "GENERICSTACK_DEFAULT_LENGTH < 0 is not allowed"
#endif

/* ====================================================================== */
/* C99 support.                                                           */
/* ====================================================================== */
#ifdef GENERICSTACK_C99
#  undef GENERICSTACK_HAVE_LONG_LONG
#  define GENERICSTACK_HAVE_LONG_LONG 1
#  undef GENERICSTACK_HAVE__BOOL
#  define GENERICSTACK_HAVE__BOOL     1
#  undef GENERICSTACK_HAVE__COMPLEX
#  define GENERICSTACK_HAVE__COMPLEX  1
#else
#  ifndef GENERICSTACK_HAVE_LONG_LONG
#    define GENERICSTACK_HAVE_LONG_LONG 0
#  endif
#  ifndef GENERICSTACK_HAVE__BOOL
#    define GENERICSTACK_HAVE__BOOL     0
#  endif
#  ifndef GENERICSTACK_HAVE__COMPLEX
#    define GENERICSTACK_HAVE__COMPLEX  0
#  endif
#endif

/* ====================================================================== */
/* Custom type support.                                                   */
/* ====================================================================== */
#ifdef GENERICSTACK_CUSTOM
#  undef GENERICSTACK_HAVE_CUSTOM
#  define GENERICSTACK_HAVE_CUSTOM 1
#else
#  ifndef GENERICSTACK_HAVE_CUSTOM
#    define GENERICSTACK_HAVE_CUSTOM 0
#  endif
#endif

/* ====================================================================== */
/* Items definition.                                                      */
/* ====================================================================== */
typedef enum genericStackItemType {
  GENERICSTACKITEMTYPE_NA = 0,    /* Not a hasard it is explicitely 0 */
  GENERICSTACKITEMTYPE_CHAR,
  GENERICSTACKITEMTYPE_SHORT,
  GENERICSTACKITEMTYPE_INT,
  GENERICSTACKITEMTYPE_LONG,
  GENERICSTACKITEMTYPE_FLOAT,
  GENERICSTACKITEMTYPE_DOUBLE,
  GENERICSTACKITEMTYPE_PTR,
  GENERICSTACKITEMTYPE_ARRAY,
#if GENERICSTACK_HAVE_LONG_LONG
  GENERICSTACKITEMTYPE_LONG_LONG,
#endif
#if GENERICSTACK_HAVE__BOOL
  GENERICSTACKITEMTYPE__BOOL,
#endif
#if GENERICSTACK_HAVE__COMPLEX
  GENERICSTACKITEMTYPE_FLOAT__COMPLEX,
  GENERICSTACKITEMTYPE_DOUBLE__COMPLEX,
  GENERICSTACKITEMTYPE_LONG_DOUBLE__COMPLEX,
#endif
#if GENERICSTACK_HAVE_CUSTOM
  GENERICSTACKITEMTYPE_CUSTOM,
#endif
  GENERICSTACKITEMTYPE_LONG_DOUBLE,
  _GENERICSTACKITEMTYPE_MAX
} genericStackItemType_t;

typedef struct genericStackItemTypeArray {
  void   *p;
  size_t  lengthl;
} genericStackItemTypeArray_t;

typedef struct genericStackItem {
  genericStackItemType_t type;
  union {
    char c;
    short s;
    int i;
    long l;
    float f;
    double d;
    void *p;
    genericStackItemTypeArray_t a;
#if GENERICSTACK_HAVE_LONG_LONG > 0
    long long ll;
#endif
#if GENERICSTACK_HAVE__BOOL > 0
    _Bool b;
#endif
#if GENERICSTACK_HAVE__COMPLEX > 0
    float _Complex fc;
    double _Complex dc;
    long double _Complex ldc;
#endif
#if GENERICSTACK_HAVE_CUSTOM > 0
    GENERICSTACK_CUSTOM custom;
#endif
    long double ld;
  } u;
} genericStackItem_t;

/* ====================================================================== */
/* Stack definition.                                                      */
/* ====================================================================== */
typedef struct genericStack {
  genericStackItem_t *items;   /* Point to defaultItems or heapItems      */
#if GENERICSTACK_DEFAULT_LENGTH > 0
  genericStackItem_t  defaultItems[GENERICSTACK_DEFAULT_LENGTH];
#endif
  genericStackItem_t *heapItems;
  int                 initialLengthi; /* Initial length                   */
  int                 heapi;   /* Heap length                             */
  int                 lengthi; /* Available length                        */
  int                 usedi;   /* Used length                             */
  int                 errori;  /* True if the stack had an error          */
} genericStack_t;

/* ====================================================================== */
/* "Inline"d functions                                                    */
/*                                                                        */
/* Not that we never assert: we assume that a SIGSEGV will be enough -;   */
/* ====================================================================== */

#ifdef GENERICSTACK_ZERO_INT_IS_NOT_ZERO_BYTES
/* we want to memset items[starti...endi] - no protection on indices because we call it only when we know we need it */
static GENERICSTACK_INLINE void _GENERICSTACK_NA_MEMSET(genericStack_t *stackp, int starti, int endi) {
  int indicei;

  for (indicei = starti; indicei <= endi; indicei++) {
    stackp->items[indicei].type = GENERICSTACKITEMTYPE_NA;
  }
}

#  if GENERICSTACK_DEFAULT_LENGTH > 0
static GENERICSTACK_INLINE short _GENERICSTACK_CREATE_HEAP(genericStack_t *stackp, int heapi) {
  short rcb;

  stackp->heapItems = (genericStackItem_t *) malloc(heapi * sizeof(genericStackItem_t));
  if (GENERICSTACK_UNLIKELY(stackp->heapItems == NULL)) {
    stackp->errori = 1;
    rcb = 0;
  } else {
    stackp->items = stackp->heapItems;
    if (stackp->usedi > 0) {
      memcpy(stackp->items, stackp->defaultItems, stackp->usedi * sizeof(genericStackItem_t));
    }
    stackp->lengthi = stackp->heapi = heapi;
    rcb = 1;
  }

  return rcb;
}
#  else /* GENERICSTACK_DEFAULT_LENGTH > 0 */
static GENERICSTACK_INLINE short _GENERICSTACK_CREATE_HEAP(genericStack_t *stackp, int heapi) {
  short rcb;

  stackp->heapItems = (genericStackItem_t *) malloc(heapi * sizeof(genericStackItem_t));
  if (GENERICSTACK_UNLIKELY(stackp->heapItems == NULL)) {
    stackp->errori = 1;
    rcb = 0;
  } else {
    stackp->items = stackp->heapItems;
    stackp->lengthi = stackp->heapi = heapi;
    rcb = 1;
  }

  return rcb;
}
#  endif /* GENERICSTACK_DEFAULT_LENGTH > 0 */
#else /* GENERICSTACK_ZERO_INT_IS_NOT_ZERO_BYTES */
static GENERICSTACK_INLINE void _GENERICSTACK_NA_MEMSET(genericStack_t *stackp, int starti, int endi) {
  memset(&(stackp->items[starti]), '\0', (endi - starti + 1) * sizeof(genericStackItem_t));
}
#  if GENERICSTACK_DEFAULT_LENGTH > 0
static GENERICSTACK_INLINE short _GENERICSTACK_CREATE_HEAP(genericStack_t *stackp, int heapi) {
  short rcb;

  /* No need to calloc: GENERICSTACK_NA_MEMSET() does the job when needed, and in practice this almost never happens */
  stackp->heapItems = (genericStackItem_t *) malloc(heapi * sizeof(genericStackItem_t));
  if (GENERICSTACK_UNLIKELY(stackp->heapItems == NULL)) {
    stackp->errori = 1;
    rcb = 0;
  } else {
    stackp->items = stackp->heapItems;
    if (stackp->usedi > 0) {
      memcpy(stackp->items, stackp->defaultItems, stackp->usedi * sizeof(genericStackItem_t));
    }
    /* No need to memset */
    stackp->lengthi = stackp->heapi = heapi;
    rcb = 1;
  }

  return rcb;
}
#  else /* GENERICSTACK_DEFAULT_LENGTH > 0 */
static GENERICSTACK_INLINE short _GENERICSTACK_CREATE_HEAP(genericStack_t *stackp, int heapi) {
  short rcb;

  stackp->heapItems = (genericStackItem_t *) malloc(heapi * sizeof(genericStackItem_t));
  if (GENERICSTACK_UNLIKELY(stackp->heapItems == NULL)) {
    stackp->errori = 1;
    rcb = 0;
  } else {
    stackp->items = stackp->heapItems;
    stackp->lengthi = stackp->heapi = heapi;
    rcb = 1;
  }

  return rcb;
}
#  endif /* GENERICSTACK_DEFAULT_LENGTH > 0 */
#endif /* GENERICSTACK_ZERO_INT_IS_NOT_ZERO_BYTES */

static GENERICSTACK_INLINE short _GENERICSTACK_EXTEND_HEAP(genericStack_t *stackp, int heapi) {
  short rcb;

  /* We are already on the heap, so previous value is in items */
  stackp->heapItems = (genericStackItem_t *) realloc(stackp->items, heapi * sizeof(genericStackItem_t));
  if (GENERICSTACK_UNLIKELY(stackp->heapItems == NULL)) {
    stackp->errori = 1;
    stackp->heapItems = stackp->items;
    rcb = 0;
  } else {
    /* Initialize new items to type GENERICSTACK_NA */
    /* Previous length was stackp->heapi: [0..stackp->heapi-1] */
    /* New length is heapi: [0..stackp->heapi.. heapi] */
    stackp->items = stackp->heapItems;
    stackp->lengthi = stackp->heapi = heapi;
    rcb = 1;
  }

  return rcb;
}

static GENERICSTACK_INLINE short _GENERICSTACK_EXTEND(genericStack_t *stackp, int wantedi, int targetIndicei) {
  short rcb;
  
  /* Do we need to go the heap ? */
  if (wantedi <= GENERICSTACK_DEFAULT_LENGTH) {
    rcb = 1;
  } else {
    /* Is heap already large enough ? */
    if (wantedi <= stackp->heapi) {
      rcb = 1;
    } else {
      /* Get the multiple of 2 that is >= wantedi */
      int heapi;
#ifdef GENERICSTACK_PARANOID
      int previousHeapi;
#endif

      /* https://www.geeksforgeeks.org/smallest-power-of-2-greater-than-or-equal-to-n/ */
      if (!(wantedi & (wantedi - 1))) {
        heapi = wantedi;
      } else {
#ifdef GENERICSTACK_PARANOID
        previousHeapi =
#endif
          heapi = 1;
        while (heapi < wantedi) {
          /* We count on compiler to optimize (<<= 1, + twice etc.) */
          heapi *= 2;
#ifdef GENERICSTACK_PARANOID
          if (heapi < previousHeapi) {
            /* Turnaround */
            heapi = 0;
            break;
          }
          previousHeapi = heapi;
#endif
        }
      }

      if (GENERICSTACK_UNLIKELY(heapi == 0)) {
        stackp->errori = 1;
        errno = EINVAL;
        rcb = 0;
      } else {
        rcb = (stackp->heapItems == NULL) ? _GENERICSTACK_CREATE_HEAP(stackp, heapi) : _GENERICSTACK_EXTEND_HEAP(stackp, heapi);
      }
    }
  }

  /* Are we targetting something that is bigger than the next unused indice ? */
  if (targetIndicei > stackp->usedi) {
    /* Current usage is: [0..stackp>usedi-1], user targets [0..stackp->usedi-1..targetIndicei where targetIndicei is bigger than stackp->usedi */
    _GENERICSTACK_NA_MEMSET(stackp, stackp->usedi, targetIndicei - 1);
  }

  return rcb;
}

#if GENERICSTACK_DEFAULT_LENGTH > 0
static GENERICSTACK_INLINE void _GENERICSTACK_INIT(genericStack_t *stackp) {
  stackp->items                                  = stackp->defaultItems;
  stackp->heapItems                              = NULL;
  stackp->lengthi = stackp->initialLengthi       = GENERICSTACK_DEFAULT_LENGTH;
  stackp->errori = stackp->usedi = stackp->heapi = 0;
}
#else /* GENERICSTACK_DEFAULT_LENGTH > 0 */
static GENERICSTACK_INLINE void _GENERICSTACK_INIT(genericStack_t *stackp) {
  stackp->heapItems = stackp->items                                                         = NULL;
  stackp->errori = stackp->usedi = stackp->heapi = stackp->lengthi = stackp->initialLengthi = 0;
}
#endif /* GENERICSTACK_DEFAULT_LENGTH > 0 */

static GENERICSTACK_INLINE short _GENERICSTACK_INIT_SIZED(genericStack_t *stackp, int lengthi) {
  short rcb;

  /* Note that _GENERICSTACK_INIT() never alters stackp->errori */
  _GENERICSTACK_INIT(stackp);
  rcb = _GENERICSTACK_EXTEND(stackp, lengthi, 0);
  if (GENERICSTACK_LIKELY(rcb)) {
    stackp->initialLengthi = lengthi;
  }

  return rcb;
}

static GENERICSTACK_INLINE void _GENERICSTACK_RESET(genericStack_t *stackp) {
  if (stackp != NULL) {
    if (stackp->heapItems != NULL) {
      free(stackp->heapItems);
      stackp->heapItems = NULL;
    }
    stackp->usedi = stackp->heapi = stackp->lengthi = 0;
  }
}

static GENERICSTACK_INLINE void _GENERICSTACK_FREE(genericStack_t *stackp) {
  if (stackp != NULL) {
    if (stackp->heapItems != NULL) {
      free(stackp->heapItems);
    }
    free(stackp);
  }
}

static GENERICSTACK_INLINE genericStack_t *_GENERICSTACK_NEW() {
    genericStack_t *stackp = (genericStack_t *) malloc(sizeof(genericStack_t));

    if (GENERICSTACK_LIKELY(stackp != NULL)) {
      _GENERICSTACK_INIT(stackp);
    }

    return stackp;
}

static GENERICSTACK_INLINE genericStack_t *_GENERICSTACK_NEW_SIZED(int lengthi) {
  genericStack_t *stackp = (genericStack_t *) malloc(sizeof(genericStack_t));

  if (GENERICSTACK_LIKELY(stackp != NULL)) {
    /* Note that _GENERICSTACK_INIT() never alters stackp->errori */
    _GENERICSTACK_INIT(stackp);
    if (GENERICSTACK_UNLIKELY(! _GENERICSTACK_EXTEND(stackp, lengthi, 0))) {
      _GENERICSTACK_FREE(stackp);
      stackp = NULL;
    }
  }
    
  return stackp;
}

static GENERICSTACK_INLINE void _GENERICSTACK_RELAX(genericStack_t *stackp) {
  if (stackp != NULL) {
    stackp->usedi = 0;
  }
}

#ifdef GENERICSTACK_PARANOID
#  define __GENERICSTACK_SET_BY_TYPE(varType, itemType, dst) \
  static GENERICSTACK_INLINE short _GENERICSTACK_SET_##itemType(genericStack_t *stackp, varType var, int indexi) { \
    short rcb;                                                          \
    int lengthi = indexi + 1;                                           \
                                                                        \
    /* Turnaround */                                                    \
    if (GENERICSTACK_UNLIKELY(lengthi < indexi)) {                      \
      stackp->errori = 1;                                               \
      rcb = 0;                                                          \
    } else {                                                            \
      if (GENERICSTACK_UNLIKELY(! _GENERICSTACK_EXTEND(stackp, lengthi, indexi))) { \
        rcb = 0;                                                        \
      } else {                                                          \
        if (stackp->usedi < lengthi) {                                  \
          stackp->usedi = lengthi;                                      \
        }                                                               \
        stackp->items[indexi].type = GENERICSTACKITEMTYPE_##itemType;   \
        stackp->items[indexi].u.dst = var;                              \
        rcb = 1;                                                        \
      }                                                                 \
    }                                                                   \
                                                                        \
    return rcb;                                                         \
}
#else /* GENERICSTACK_PARANOID */
#  define __GENERICSTACK_SET_BY_TYPE(varType, itemType, dst) \
  static GENERICSTACK_INLINE short _GENERICSTACK_SET_##itemType(genericStack_t *stackp, varType var, int indexi) { \
    short rcb;                                                          \
    int lengthi = indexi + 1;                                           \
                                                                        \
    if (GENERICSTACK_UNLIKELY(! _GENERICSTACK_EXTEND(stackp, lengthi, indexi))) { \
      rcb = 0;                                                          \
    } else {                                                            \
      if (stackp->usedi < lengthi) {                                    \
        stackp->usedi = lengthi;                                        \
      }                                                                 \
      stackp->items[indexi].type = GENERICSTACKITEMTYPE_##itemType;     \
      stackp->items[indexi].u.dst = var;                                \
      rcb = 1;                                                          \
    }                                                                   \
                                                                        \
    return rcb;                                                         \
}
#endif /* GENERICSTACK_PARANOID */

#ifdef GENERICSTACK_PARANOID
#  define __GENERICSTACK_SET_BY_TYPEP(varType, itemType, dst) \
  static GENERICSTACK_INLINE short _GENERICSTACK_SET_##itemType##P(genericStack_t *stackp, varType *var, int indexi) { \
    short rcb;                                                          \
    int lengthi = indexi + 1;                                           \
                                                                        \
    /* Turnaround */                                                    \
    if (GENERICSTACK_UNLIKELY(lengthi < indexi)) {                      \
      stackp->errori = 1;                                               \
      rcb = 0;                                                          \
    } else {                                                            \
      if (GENERICSTACK_UNLIKELY(! _GENERICSTACK_EXTEND(stackp, lengthi, indexi))) { \
        rcb = 0;                                                        \
      } else {                                                          \
        if (stackp->usedi < lengthi) {                                  \
          stackp->usedi = lengthi;                                      \
        }                                                               \
        stackp->items[indexi].type = GENERICSTACKITEMTYPE_##itemType;   \
        stackp->items[indexi].u.dst = *var;                             \
        rcb = 1;                                                        \
      }                                                                 \
    }                                                                   \
                                                                        \
    return rcb;                                                         \
}
#else /* GENERICSTACK_PARANOID */
#  define __GENERICSTACK_SET_BY_TYPEP(varType, itemType, dst) \
  static GENERICSTACK_INLINE short _GENERICSTACK_SET_##itemType##P(genericStack_t *stackp, varType *var, int indexi) { \
    short rcb;                                                          \
    int lengthi = indexi + 1;                                           \
                                                                        \
    if (GENERICSTACK_UNLIKELY(! _GENERICSTACK_EXTEND(stackp, lengthi, indexi))) { \
      rcb = 0;                                                          \
    } else {                                                            \
      if (stackp->usedi < lengthi) {                                    \
        stackp->usedi = lengthi;                                        \
      }                                                                 \
      stackp->items[indexi].type = GENERICSTACKITEMTYPE_##itemType;     \
      stackp->items[indexi].u.dst = *var;                               \
      rcb = 1;                                                          \
    }                                                                   \
                                                                        \
    return rcb;                                                         \
}
#endif /* GENERICSTACK_PARANOID */

__GENERICSTACK_SET_BY_TYPE(char, CHAR, c)
__GENERICSTACK_SET_BY_TYPE(short, SHORT, s)
__GENERICSTACK_SET_BY_TYPE(int, INT, i)
__GENERICSTACK_SET_BY_TYPE(long, LONG, l)
__GENERICSTACK_SET_BY_TYPE(long double, LONG_DOUBLE, ld)
__GENERICSTACK_SET_BY_TYPE(float, FLOAT, f)
__GENERICSTACK_SET_BY_TYPE(double, DOUBLE, d)
__GENERICSTACK_SET_BY_TYPE(void *, PTR, p)
__GENERICSTACK_SET_BY_TYPE(genericStackItemTypeArray_t, ARRAY, a)
__GENERICSTACK_SET_BY_TYPEP(genericStackItemTypeArray_t, ARRAY, a)
#if GENERICSTACK_HAVE_LONG_LONG > 0
  __GENERICSTACK_SET_BY_TYPE(long long, LONG_LONG, ll)
#endif
#if GENERICSTACK_HAVE__BOOL > 0
  __GENERICSTACK_SET_BY_TYPE(_Bool, _BOOL, b)
#endif
#if GENERICSTACK_HAVE__COMPLEX > 0
  __GENERICSTACK_SET_BY_TYPE(float _Complex, FLOAT__COMPLEX, fc)
  __GENERICSTACK_SET_BY_TYPE(double _Complex, DOUBLE__COMPLEX, dc)
  __GENERICSTACK_SET_BY_TYPE(long double _Complex, LONG_DOUBLE__COMPLEX, ldc)
#endif
#if GENERICSTACK_HAVE_CUSTOM > 0
  __GENERICSTACK_SET_BY_TYPE(GENERICSTACK_CUSTOM, CUSTOM, custom)
  __GENERICSTACK_SET_BY_TYPEP(GENERICSTACK_CUSTOM, CUSTOM, custom)
#endif
/* Special case for N/A: there is no associated data */
static GENERICSTACK_INLINE short _GENERICSTACK_SET_NA(genericStack_t *stackp, int indexi) {
  short rcb;
  int lengthi = indexi + 1;

#ifdef GENERICSTACK_PARANOID
  /* Turnaround */
  if (GENERICSTACK_UNLIKELY(lengthi < indexi)) {
    stackp->errori = 1;
    rcb = 0;
  } else {
#endif
    if (GENERICSTACK_UNLIKELY(! _GENERICSTACK_EXTEND(stackp, lengthi, indexi))) {
      rcb = 0;
    } else {
      if (stackp->usedi < lengthi) {
        stackp->usedi = lengthi;
      }
      stackp->items[indexi].type = GENERICSTACKITEMTYPE_NA;
      rcb = 1;
    }
#ifdef GENERICSTACK_PARANOID
  }
#endif

  return rcb;
}

/* ====================================================================== */
/* Interface.                                                             */
/* ====================================================================== */
#define GENERICSTACK_ERROR(stackp)               (stackp)->errori
#define GENERICSTACK_ERROR_RESET(stackp)         (stackp)->errori = 0
#define GENERICSTACK_INITIAL_LENGTH(stackp)      (stackp)->initialLengthi
#define GENERICSTACK_HEAP_LENGTH(stackp)         (stackp)->heapi
#define GENERICSTACK_LENGTH(stackp)              (stackp)->lengthi
#define GENERICSTACK_USED(stackp)                (stackp)->usedi
#define GENERICSTACK_INIT(stackp)                _GENERICSTACK_INIT(stackp)
#define GENERICSTACK_NEW(stackp)                 (stackp) = _GENERICSTACK_NEW()
#define GENERICSTACK_NEW_SIZED(stackp, lengthi)  (stackp) = _GENERICSTACK_NEW_SIZED(lengthi)
#define GENERICSTACK_INIT_SIZED(stackp, lengthi) _GENERICSTACK_INIT_SIZED(stackp, lengthi)

/* ====================================================================== */
/* GET interface                                                          */
/* ====================================================================== */
#define GENERICSTACK_GET_CHAR(stackp, indexi)                   ((stackp)->items[indexi].u.c)
#define GENERICSTACK_GET_SHORT(stackp, indexi)                  ((stackp)->items[indexi].u.s)
#define GENERICSTACK_GET_INT(stackp, indexi)                    ((stackp)->items[indexi].u.i)
#define GENERICSTACK_GET_LONG(stackp, indexi)                   ((stackp)->items[indexi].u.l)
#define GENERICSTACK_GET_LONG_DOUBLE(stackp, indexi)            ((stackp)->items[indexi].u.ld)
#define GENERICSTACK_GET_FLOAT(stackp, indexi)                  ((stackp)->items[indexi].u.f)
#define GENERICSTACK_GET_DOUBLE(stackp, indexi)                 ((stackp)->items[indexi].u.d)
#define GENERICSTACK_GET_PTR(stackp, indexi)                    ((stackp)->items[indexi].u.p)
#define GENERICSTACK_GET_ARRAY(stackp, indexi)                  ((stackp)->items[indexi].u.a)
#define GENERICSTACK_GET_ARRAYP(stackp, indexi)                 (&((stackp)->items[indexi].u.a))
#if GENERICSTACK_HAVE_LONG_LONG > 0
#  define GENERICSTACK_GET_LONG_LONG(stackp, indexi)            ((stackp)->items[indexi].u.ll)
#endif
#if GENERICSTACK_HAVE__BOOL > 0
#  define GENERICSTACK_GET__BOOL(stackp, indexi)                ((stackp)->items[indexi].u.b)
#endif
#if GENERICSTACK_HAVE__COMPLEX > 0
#  define GENERICSTACK_GET_FLOAT__COMPLEX(stackp, indexi)       ((stackp)->items[indexi].u.fc)
#  define GENERICSTACK_GET_DOUBLE__COMPLEX(stackp, indexi)      ((stackp)->items[indexi].u.dc)
#  define GENERICSTACK_GET_LONG_DOUBLE__COMPLEX(stackp, indexi) ((stackp)->items[indexi].u.ldc)
#endif
#if GENERICSTACK_HAVE_CUSTOM > 0
#  define GENERICSTACK_GET_CUSTOM(stackp, indexi)               ((stackp)->items[indexi].u.custom)
#  define GENERICSTACK_GET_CUSTOMP(stackp, indexi)              (&((stackp)->items[indexi].u.custom))
#endif
/* Per def N/A value is undefined - we just have to make sure indexi is processed */
#define GENERICSTACK_GET_NA(stackp, indexi)                     (indexi)

/* ====================================================================== */
/* SET interface                                                          */
/* ====================================================================== */
#define GENERICSTACK_SET_CHAR(stackp, var, index)                   _GENERICSTACK_SET_CHAR(stackp, var, index)
#define GENERICSTACK_SET_SHORT(stackp, var, index)                  _GENERICSTACK_SET_SHORT(stackp, var, index)
#define GENERICSTACK_SET_INT(stackp, var, index)                    _GENERICSTACK_SET_INT(stackp, var, index)
#define GENERICSTACK_SET_LONG(stackp, var, index)                   _GENERICSTACK_SET_LONG(stackp, var, index)
#define GENERICSTACK_SET_LONG_DOUBLE(stackp, var, index)            _GENERICSTACK_SET_LONG_DOUBLE(stackp, var, index)
#define GENERICSTACK_SET_FLOAT(stackp, var, index)                  _GENERICSTACK_SET_FLOAT(stackp, var, index)
#define GENERICSTACK_SET_DOUBLE(stackp, var, index)                 _GENERICSTACK_SET_DOUBLE(stackp, var, index)
#define GENERICSTACK_SET_PTR(stackp, var, index)                    _GENERICSTACK_SET_PTR(stackp, var, index)
#define GENERICSTACK_SET_ARRAY(stackp, var, index)                  _GENERICSTACK_SET_ARRAY(stackp, var, index)
#define GENERICSTACK_SET_ARRAYP(stackp, var, index)                 _GENERICSTACK_SET_ARRAYP(stackp, var, index)
#if GENERICSTACK_HAVE_LONG_LONG > 0
#  define GENERICSTACK_SET_LONG_LONG(stackp, var, index)            _GENERICSTACK_SET_LONG_LONG(stackp, var, index)
#endif
#if GENERICSTACK_HAVE__BOOL > 0
#  define GENERICSTACK_SET__BOOL(stackp, var, index)                _GENERICSTACK_SET_BOOL(stackp, var, index)
#endif
#if GENERICSTACK_HAVE__COMPLEX > 0
#  define GENERICSTACK_SET_FLOAT__COMPLEX(stackp, var, index)       _GENERICSTACK_SET_FLOAT__COMPLEX(stackp, var, index)
#  define GENERICSTACK_SET_DOUBLE__COMPLEX(stackp, var, index)      _GENERICSTACK_SET_DOUBLE__COMPLEX(stackp, var, index)
#  define GENERICSTACK_SET_LONG_DOUBLE__COMPLEX(stackp, var, index) _GENERICSTACK_SET_LONG_DOUBLE__COMPLEX(stackp, var, index)
#endif
#if GENERICSTACK_HAVE_CUSTOM > 0
#  define GENERICSTACK_SET_CUSTOM(stackp, var, index)               _GENERICSTACK_SET_CUSTOM(stackp, var, index)
#  define GENERICSTACK_SET_CUSTOMP(stackp, var, index)              _GENERICSTACK_SET_CUSTOMP(stackp, var, index)
#endif
#define GENERICSTACK_SET_NA(stackp, index)                          _GENERICSTACK_SET_NA(stackp, index)

/* ====================================================================== */
/* PUSH interface: built on top of SET                                    */
/* ====================================================================== */
#define GENERICSTACK_PUSH_CHAR(stackp, var)                   GENERICSTACK_SET_CHAR(stackp, var, (stackp)->usedi)
#define GENERICSTACK_PUSH_SHORT(stackp, var)                  GENERICSTACK_SET_SHORT(stackp, var, (stackp)->usedi)
#define GENERICSTACK_PUSH_INT(stackp, var)                    GENERICSTACK_SET_INT(stackp, var, (stackp)->usedi)
#define GENERICSTACK_PUSH_LONG(stackp, var)                   GENERICSTACK_SET_LONG(stackp, var, (stackp)->usedi)
#define GENERICSTACK_PUSH_LONG_DOUBLE(stackp, var)            GENERICSTACK_SET_LONG_DOUBLE(stackp, var, (stackp)->usedi)
#define GENERICSTACK_PUSH_FLOAT(stackp, var)                  GENERICSTACK_SET_FLOAT(stackp, var, (stackp)->usedi)
#define GENERICSTACK_PUSH_DOUBLE(stackp, var)                 GENERICSTACK_SET_DOUBLE(stackp, var, (stackp)->usedi)
#define GENERICSTACK_PUSH_PTR(stackp, var)                    GENERICSTACK_SET_PTR(stackp, var, (stackp)->usedi)
#define GENERICSTACK_PUSH_ARRAY(stackp, var)                  GENERICSTACK_SET_ARRAY(stackp, var, (stackp)->usedi)
#define GENERICSTACK_PUSH_ARRAYP(stackp, var)                 GENERICSTACK_SET_ARRAYP(stackp, var, (stackp)->usedi)
#if GENERICSTACK_HAVE_LONG_LONG > 0
#  define GENERICSTACK_PUSH_LONG_LONG(stackp, var)            GENERICSTACK_SET_LONG_LONG(stackp, var, (stackp)->usedi)
#endif
#if GENERICSTACK_HAVE__BOOL > 0
#  define GENERICSTACK_PUSH__BOOL(stackp, var)                GENERICSTACK_SET__BOOL(stackp, var, (stackp)->usedi)
#endif
#if GENERICSTACK_HAVE__COMPLEX > 0
#  define GENERICSTACK_PUSH_FLOAT__COMPLEX(stackp, var)       GENERICSTACK_SET_FLOAT__COMPLEX(stackp, var, (stackp)->usedi)
#  define GENERICSTACK_PUSH_DOUBLE__COMPLEX(stackp, var)      GENERICSTACK_SET_DOUBLE__COMPLEX(stackp, var, (stackp)->usedi)
#  define GENERICSTACK_PUSH_LONG_DOUBLE__COMPLEX(stackp, var) GENERICSTACK_SET_LONG_DOUBLE__COMPLEX(stackp, var, (stackp)->usedi)
#endif
#if GENERICSTACK_HAVE_CUSTOM > 0
#  define GENERICSTACK_PUSH_CUSTOM(stackp, var)               GENERICSTACK_SET_CUSTOM(stackp, var, (stackp)->usedi)
#  define GENERICSTACK_PUSH_CUSTOMP(stackp, var)              GENERICSTACK_SET_CUSTOMP(stackp, var, (stackp)->usedi)
#endif
#define GENERICSTACK_PUSH_NA(stackp)                          GENERICSTACK_SET_NA(stackp, (stackp)->usedi)

/* ====================================================================== */
/* POP interface: built on top GET                                        */
/* ====================================================================== */
#define GENERICSTACK_POP_CHAR(stackp)                         GENERICSTACK_GET_CHAR(stackp, --(stackp)->usedi)
#define GENERICSTACK_POP_SHORT(stackp)                        GENERICSTACK_GET_SHORT(stackp, --(stackp)->usedi)
#define GENERICSTACK_POP_INT(stackp)                          GENERICSTACK_GET_INT(stackp, --(stackp)->usedi)
#define GENERICSTACK_POP_LONG(stackp)                         GENERICSTACK_GET_LONG(stackp, --(stackp)->usedi)
#define GENERICSTACK_POP_LONG_DOUBLE(stackp)                  GENERICSTACK_GET_LONG_DOUBLE(stackp, --(stackp)->usedi)
#define GENERICSTACK_POP_FLOAT(stackp)                        GENERICSTACK_GET_FLOAT(stackp, --(stackp)->usedi)
#define GENERICSTACK_POP_DOUBLE(stackp)                       GENERICSTACK_GET_DOUBLE(stackp, --(stackp)->usedi)
#define GENERICSTACK_POP_PTR(stackp)                          GENERICSTACK_GET_PTR(stackp, --(stackp)->usedi)
#define GENERICSTACK_POP_ARRAY(stackp)                        GENERICSTACK_GET_ARRAY(stackp,--(stackp)->usedi)
#if GENERICSTACK_HAVE_LONG_LONG > 0
#  define GENERICSTACK_POP_LONG_LONG(stackp)                  GENERICSTACK_GET_LONG_LONG(stackp, --(stackp)->usedi)
#endif
#if GENERICSTACK_HAVE__BOOL > 0
#  define GENERICSTACK_POP__BOOL(stackp)                      GENERICSTACK_GET__BOOL(stackp, --(stackp)->usedi)
#endif
#if GENERICSTACK_HAVE__COMPLEX > 0
#  define GENERICSTACK_POP_FLOAT__COMPLEX(stackp)             GENERICSTACK_GET_FLOAT__COMPLEX(stackp, --(stackp)->usedi)
#  define GENERICSTACK_POP_DOUBLE__COMPLEX(stackp)            GENERICSTACK_GET_DOUBLE__COMPLEX(stackp, --(stackp)->usedi)
#  define GENERICSTACK_POP_LONG_DOUBLE__COMPLEX(stackp)       GENERICSTACK_GET_LONG_DOUBLE__COMPLEX(stackp, --(stackp)->usedi)
#endif
#if GENERICSTACK_HAVE_CUSTOM > 0
#  define GENERICSTACK_POP_CUSTOM(stackp)                     GENERICSTACK_GET_CUSTOM(stackp, --(stackp)->usedi)
#endif
#define GENERICSTACK_POP_NA(stackp)                           GENERICSTACK_GET_NA(stackp, --(stackp)->usedi)

/* ====================================================================== */
/* Memory release                                                         */
/* We intentionnaly loop on size and not used.                            */
/* ====================================================================== */
#define GENERICSTACK_RESET(stackp) _GENERICSTACK_RESET(stackp)
#define GENERICSTACK_FREE(stackp) _GENERICSTACK_FREE(stackp)
#define GENERICSTACK_RELAX(stackp) _GENERICSTACK_RELAX(stackp)

/* ====================================================================== */
/* In some rare occasions user might want to get the basic type           */
/* from an item type.                                                     */
/* ====================================================================== */
#define GENERICSTACKITEMTYPE(stackp, index) (stackp)->items[index].type

#define GENERICSTACKITEMTYPE2TYPE_CHAR                   char
#define GENERICSTACKITEMTYPE2TYPE_SHORT                  short
#define GENERICSTACKITEMTYPE2TYPE_INT                    int
#define GENERICSTACKITEMTYPE2TYPE_LONG                   long
#define GENERICSTACKITEMTYPE2TYPE_LONG_DOUBLE            long double
#define GENERICSTACKITEMTYPE2TYPE_FLOAT                  float
#define GENERICSTACKITEMTYPE2TYPE_DOUBLE                 double
#define GENERICSTACKITEMTYPE2TYPE_PTR                    void *
#define GENERICSTACKITEMTYPE2TYPE_ARRAY                  genericStackItemTypeArray_t
#define GENERICSTACKITEMTYPE2TYPE_ARRAYP                 genericStackItemTypeArray_t *
#define GENERICSTACK_ARRAY_PTR(a)                        (a).p
#define GENERICSTACK_ARRAYP_PTR(a)                       (a)->p
#define GENERICSTACK_ARRAY_LENGTH(a)                     (a).lengthl
#define GENERICSTACK_ARRAYP_LENGTH(a)                    (a)->lengthl
#if GENERICSTACK_HAVE_LONG_LONG
  #define GENERICSTACKITEMTYPE2TYPE_LONG_LONG            long long
#endif
#if GENERICSTACK_HAVE__BOOL
  #define GENERICSTACKITEMTYPE2TYPE__BOOL                _Bool
#endif
#if GENERICSTACK_HAVE__COMPLEX
  #define GENERICSTACKITEMTYPE2TYPE_FLOAT__COMPLEX       float _Complex
  #define GENERICSTACKITEMTYPE2TYPE_DOUBLE__COMPLEX      double _Complex
  #define GENERICSTACKITEMTYPE2TYPE_LONG_DOUBLE__COMPLEX long double _Complex
#endif
#if GENERICSTACK_HAVE_CUSTOM
  #define GENERICSTACKITEMTYPE2TYPE_CUSTOM               GENERICSTACK_CUSTOM
  #define GENERICSTACKITEMTYPE2TYPE_CUSTOMP              GENERICSTACK_CUSTOM *
#endif

/* ====================================================================== */
/* IS interface                                                           */
/* ====================================================================== */
#define GENERICSTACK_EXISTS(stackp, i) (((stackp) != NULL) && ((stackp)->usedi > i))
#define GENERICSTACK_IS_NA(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE_NA))
#define GENERICSTACK_IS_CHAR(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE_CHAR))
#define GENERICSTACK_IS_SHORT(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE_SHORT))
#define GENERICSTACK_IS_INT(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE_INT))
#define GENERICSTACK_IS_LONG(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE_LONG))
#define GENERICSTACK_IS_LONG_DOUBLE(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE_LONG_DOUBLE))
#define GENERICSTACK_IS_FLOAT(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE_FLOAT))
#define GENERICSTACK_IS_DOUBLE(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE_DOUBLE))
#define GENERICSTACK_IS_PTR(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE_PTR))
#define GENERICSTACK_IS_ARRAY(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE_ARRAY))
#if GENERICSTACK_HAVE_LONG_LONG
#define GENERICSTACK_IS_LONG_LONG(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE_LONG_LONG))
#endif
#if GENERICSTACK_HAVE__BOOL
#define GENERICSTACK_IS__BOOL(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE__BOOL))
#endif
#if GENERICSTACK_HAVE__COMPLEX
#define GENERICSTACK_IS_FLOAT__COMPLEX(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE_FLOAT__COMPLEX))
#define GENERICSTACK_IS_DOUBLE__COMPLEX(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE_DOUBLE__COMPLEX))
#define GENERICSTACK_IS_LONG_DOUBLE__COMPLEX(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE_LONG_DOUBLE__COMPLEX))
#endif
#if GENERICSTACK_HAVE_CUSTOM
#define GENERICSTACK_IS_CUSTOM(stackp, i) (GENERICSTACK_EXISTS(stackp, i) && (GENERICSTACKITEMTYPE((stackp), (i)) == GENERICSTACKITEMTYPE_CUSTOM))
#endif

/* ====================================================================== */
/* Dump macro for development purpose. Fixed to stderr.                   */
/* ====================================================================== */
#if GENERICSTACK_HAVE_CUSTOM
#define _GENERICSTACK_DUMP_CASE_CUSTOM(stackp,indice) case GENERICSTACKITEMTYPE_CUSTOM: fprintf(stderr, "Element[%3ld/%3ld] type     : CUSTOM\n", (unsigned long) indice, (unsigned long) GENERICSTACK_USED(stackp)); break;
#else
#define _GENERICSTACK_DUMP_CASE_CUSTOM(stackp,indice)
#endif
#define GENERICSTACK_DUMP(stackp) do {                                  \
    int _i_for_dump;							\
    fprintf(stderr, "GENERIC STACK DUMP\n");				\
    fprintf(stderr, "------------------\n");				\
    fprintf(stderr, "Items                     : %p\n", stackp->items); \
    fprintf(stderr, "Heap items                : %p\n", stackp->heapItems); \
    fprintf(stderr, "Initial Length            : %d\n", GENERICSTACK_INITIAL_LENGTH(stackp)); \
    fprintf(stderr, "Heap Length               : %d\n", GENERICSTACK_HEAP_LENGTH(stackp)); \
    fprintf(stderr, "Length                    : %d\n", GENERICSTACK_LENGTH(stackp)); \
    fprintf(stderr, "Used:                     : %d\n", GENERICSTACK_USED(stackp)); \
    fprintf(stderr, "Error?                    : %s\n", GENERICSTACK_ERROR(stackp) ? "yes" : "no"); \
    for (_i_for_dump = 0; _i_for_dump < GENERICSTACK_USED(stackp); _i_for_dump++) { \
      switch(GENERICSTACKITEMTYPE(stackp, _i_for_dump)) {		\
      case GENERICSTACKITEMTYPE_NA:					\
	fprintf(stderr, "Element[%3d/%3d] type     : NA\n", _i_for_dump, GENERICSTACK_USED(stackp));	\
	break;								\
      case GENERICSTACKITEMTYPE_CHAR:					\
	fprintf(stderr, "Element[%3d/%3d] type     : CHAR\n", _i_for_dump, GENERICSTACK_USED(stackp)); \
	break;								\
      case GENERICSTACKITEMTYPE_SHORT:					\
	fprintf(stderr, "Element[%3d/%3d] type     : SHORT\n", _i_for_dump, GENERICSTACK_USED(stackp)); \
	break;								\
      case GENERICSTACKITEMTYPE_INT:					\
	fprintf(stderr, "Element[%3d/%3d] type     : INT\n", _i_for_dump, GENERICSTACK_USED(stackp)); \
	break;								\
      case GENERICSTACKITEMTYPE_LONG:					\
	fprintf(stderr, "Element[%3d/%3d] type     : LONG\n", _i_for_dump, GENERICSTACK_USED(stackp)); \
	break;								\
      case GENERICSTACKITEMTYPE_FLOAT:					\
	fprintf(stderr, "Element[%3d/%3d] type     : FLOAT\n", _i_for_dump, GENERICSTACK_USED(stackp)); \
	break;								\
      case GENERICSTACKITEMTYPE_DOUBLE:					\
	fprintf(stderr, "Element[%3d/%3d] type     : DOUBLE\n", _i_for_dump, GENERICSTACK_USED(stackp)); \
	break;								\
      case GENERICSTACKITEMTYPE_PTR:					\
	fprintf(stderr, "Element[%3d/%3d] type     : PTR\n", _i_for_dump, GENERICSTACK_USED(stackp)); \
	break;								\
      case GENERICSTACKITEMTYPE_ARRAY:					\
	fprintf(stderr, "Element[%3d/%3d] type     : ARRAY\n", _i_for_dump, GENERICSTACK_USED(stackp)); \
	break;								\
      case GENERICSTACKITEMTYPE_LONG_DOUBLE:                            \
	fprintf(stderr, "Element[%3d/%3d] type     : LONG DOUBLE\n", _i_for_dump, GENERICSTACK_USED(stackp)); \
	break;								\
      default:								\
	fprintf(stderr, "Element[%3d/%3d] type     : %d\n", _i_for_dump, GENERICSTACK_USED(stackp), GENERICSTACKITEMTYPE(stackp, _i_for_dump)); \
	break;								\
        _GENERICSTACK_DUMP_CASE_CUSTOM(stackp,_i_for_dump)           \
      }									\
    }									\
 } while (0)
     
/* ====================================================================== */
/* Switches two entries                                                   */
/* We support a "negative index", which mean start by far from the end.   */
/* ====================================================================== */
#define GENERICSTACK_SWITCH(stackp, i1, i2) do {                     \
    int _genericStackSwitch_index1 = (int) (i1);                        \
    int _genericStackSwitch_index2 = (int) (i2);                        \
                                                                        \
    if (_genericStackSwitch_index1 < 0) {                               \
      _genericStackSwitch_index1 = (stackp)->usedi + _genericStackSwitch_index1; \
    }                                                                   \
    if (_genericStackSwitch_index2 < 0) {                               \
      _genericStackSwitch_index2 = (stackp)->usedi + _genericStackSwitch_index2; \
    }                                                                   \
                                                                        \
    if (GENERICSTACK_UNLIKELY((_genericStackSwitch_index1 < 0) || ((_genericStackSwitch_index1) >= (stackp)->usedi) || \
                              (_genericStackSwitch_index2 < 0) || ((_genericStackSwitch_index2) >= (stackp)->usedi))) { \
      (stackp)->errori = 1;                                          \
      errno = EINVAL;                                                   \
    } else if (_genericStackSwitch_index1 != _genericStackSwitch_index2) { \
      genericStackItem_t _item = (stackp)->items[_genericStackSwitch_index1]; \
      void *_addr1 = (void *) &((stackp)->items[_genericStackSwitch_index1]); \
      void *_addr2 = (void *) &((stackp)->items[_genericStackSwitch_index2]); \
                                                                        \
      memcpy(_addr1, _addr2,  sizeof(genericStackItem_t));              \
      memcpy(_addr2, &_item,  sizeof(genericStackItem_t));              \
    }                                                                   \
  } while (0)

#endif /* GENERICSTACK_H */
