
/*

Some pretty macros for the maintainace of singly linked lists and stacks.
The first parameter is always the list anchor that must be initialized
to zero. The anchor shouldn't have side effects. If there's not enough memory
for the malloc's, 'list_error_handler' is called. You can redefine it to meet
your personal needs.

*/


#define list_error_handler() do { \
  fprintf( stderr, "Out of memory!\n" ); \
  exit( 1 ); \
} while(0)

/* alloc fresh memory for a string and copy it */

#define mcpy(a,b) ({ \
  if (!((a) = malloc(strlen(b)+1))) \
    list_error_handler(); \
  strcpy( a, b ); \
  a; \
})

/* substitute for standard strdup, that calls list_error_handler() if
   there's no memory left.
*/

#define strdup(b) ({ \
  char	*__a; \
  if (!((__a) = malloc(strlen(b)+1))) \
    list_error_handler(); \
  strcpy( __a, b ); \
  __a; \
})



/* single linked lists */
/* ------------------- */

/* new element at front */

#define list_new(a) ({ \
  typeof(a) __tmp; \
  if (!(__tmp = malloc(sizeof(typeof(*(a)))))) \
    list_error_handler(); \
  __tmp->next = (a); \
  (a) = __tmp; \
  __tmp; \
})

/* new element at back end */

#define list_append(a) ({ \
  typeof(a) __tmp; \
  if (!(__tmp = malloc(sizeof(typeof(*(a)))))) \
    list_error_handler(); \
  if (!(a)) \
    (a) = __tmp; \
  else { \
    typeof(a) __tmp2; \
    for( __tmp2 = (a); __tmp2->next; __tmp2 = __tmp2->next ) ; \
    __tmp2->next = __tmp; \
  } \
  __tmp->next = 0; \
  __tmp; \
})

/* new element behind element pointed to by 'p' */

#define list_insert(a,p) ({ \
  typeof(a) __tmp; \
  if (!(__tmp = malloc(sizeof(typeof(*(a)))))) \
    list_error_handler(); \
  if (!(a)) { \
    (a) = __tmp; \
    __tmp->next = 0; \
  } \
  else { \
    __tmp->next = (p)->next; \
    (p)->next = __tmp; \
  } \
  __tmp; \
})

/* walk through the list with pointer 'p' */

#define list_for(a,p) for( (p) = (a); (p); (p) = (p)->next )

/* find an element that equals 's' in component 'elt' */
/* must be comparable with == */

#define list_find(a,elt,s) ({ \
  typeof(a) __tmp; \
  for( __tmp = (a); __tmp; __tmp = __tmp->next ) \
    if (__tmp->elt == s) break; \
  __tmp; \
})

/* dito, but stop when function 'func' returns true */

#define list_ffind(a,elt,func,s) ({ \
  typeof(a) __tmp; \
  for( __tmp = (a); __tmp; __tmp = __tmp->next ) \
    if (func(__tmp->elt,s)) break; \
  __tmp; \
})

/* return the number of elements */

#define list_len(a) ({ \
  typeof(a) __tmp; \
  int       __len = 0; \
  for( __tmp = (a); __tmp; __tmp = __tmp->next ) \
    ++__len; \
  __len; \
})
  

/* free the list */

#define list_free(a) do { \
  typeof(a) __tmp, __tmp2; \
  for( __tmp = (a); __tmp; __tmp = __tmp2 ) { \
    __tmp2 = __tmp->next; \
    free( __tmp ); \
  } \
  (a) = 0; \
} while(0)

/* free list, but also free memory pointed to by an element */

#define list_a1free(a,el) do { \
  typeof(a) __tmp, __tmp2; \
  for( __tmp = (a); __tmp; __tmp = __tmp2 ) { \
    __tmp2 = __tmp->next; \
    free( __tmp->el ); \
    free( __tmp ); \
  } \
  (a) = 0; \
} while(0)

#define list_a2free(a,el1,el2) do { \
  typeof(a) __tmp, __tmp2; \
  for( __tmp = (a); __tmp; __tmp = __tmp2 ) { \
    __tmp2 = __tmp->next; \
    free( __tmp->el1 ); \
    free( __tmp->el2 ); \
    free( __tmp ); \
  } \
  (a) = 0; \
} while(0)

#define list_a3free(a,el1,el2,el3) do { \
  typeof(a) __tmp, __tmp2; \
  for( __tmp = (a); __tmp; __tmp = __tmp2 ) { \
    __tmp2 = __tmp->next; \
    free( __tmp->el1 ); \
    free( __tmp->el2 ); \
    free( __tmp->el3 ); \
    free( __tmp ); \
  } \
  (a) = 0; \
} while(0)


/* delete node pointed to by 'p' */

#define list_del(a,p) do { \
  if ((p) == (a)) \
    (a) = (a)->next; \
  else { \
    typeof(a) __tmp; \
    for( __tmp = (a); __tmp && __tmp->next != (p); __tmp = __tmp->next ) ; \
    if (__tmp) __tmp->next = (p)->next; \
  } \
  free( p ); \
} while(0)

/* delete first node */

#define list_fdel(a) do { \
  if (a) { \
    typeof(a) __tmp = (a); \
    (a) = (a)->next; \
    free( __tmp ); \
  } \
} while(0)

/* delete last node */

#define list_bdel(a) do { \
  if (a) { \
    if (!((a)->next)) { \
      free( a ); \
      (a) = 0; \
    } \
    else { \
      typeof(a) __tmp; \
      for( __tmp = (a); __tmp->next->next; __tmp = __tmp->next ) ; \
      free( __tmp->next ); \
      __tmp->next = 0; \
    } \
  } \
} while(0)
    



/*   stack   */
/* --------- */


#define stack_push(a) ({ \
  typeof(a) __tmp; \
  if (!(__tmp = malloc(sizeof(typeof(*(a)))))) \
    list_error_handler(); \
  __tmp->next = (a); \
  (a) = __tmp; \
  __tmp; \
})

#define stack_pop(a) do { \
  typeof(a) __tmp = (a); \
  (a) = (a)->next; \
  free( __tmp ); \
} while(0)

#define stack_top(a) (a)

#define stack_empty(a) (!(a))


  
    