#ifndef EXTERN_TOOLS_H
#define EXTERN_TOOLS_H

#ifndef NDEBUG
# define DEBUG_PRINT(x, y) do { \
  if (x) fprintf(stderr, "%s:%d -- %s\n", __FILE__, __LINE__, y); \
 } while (FALSE)
# ifdef __GNUC__
#  define VDEBUG_PRINT(x, y, args...) do { \
   if (x) fprintf(stderr, "%s:%d -- " y "\n", __FILE__, __LINE__ , ## args); \
   } while (FALSE)
# else
#  define VDEBUG_PRINT(x, y, z) while (FALSE) {\
  IGNORE_PARAMETER((x) && (y)); IGNORE_PARAMETER(z) } break
# endif
#else
# define DEBUG_PRINT(x, y) while (FALSE) break
# define VDEBUG_PRINT(x, y, z...) while (FALSE) break
#endif

#ifdef NWARNS
# define IGNORE_PARAMETER(x)
#else
# define IGNORE_PARAMETER(x) while (x && FALSE) break
#endif

#define DO_CRAZY_TIMER(obj, timer, secs) do { \
 (obj)-> timer ## _timestamp = now; (obj)-> timer ## _in_seconds = secs; \
 } while (FALSE)
#define STOP_CRAZY_TIMER(obj, timer) (obj)-> timer ## _in_seconds = 0
#define IS_ACTIVE_CRAZY_TIMER(obj, timer) ((obj)-> timer ## _in_seconds)
#define TOGO_CRAZY_TIMER(obj, timer) ((int) \
 ((obj)-> timer ## _in_seconds - difftime(now, (obj)-> timer ## _timestamp)))
#define DONE_CRAZY_TIMER(obj, timer) (IS_ACTIVE_CRAZY_TIMER(obj, timer) && \
 (difftime(now, (obj)-> timer ## _timestamp) >= (obj)-> timer ## _in_seconds))

#define DO_ORDER_TEST(type_after, t, func_true, func_false, params) \
 (((t) ? (do_ ## func_true ## order_ ## type_after) : \
   (do_ ## func_false ## order_ ## type_after))  params)

/* time defines */
#define MINUTE (60)
#define HOUR (MINUTE * 60)
#define DAY (HOUR * 60)
#define WEEK (DAY * 7)
     
/* useful time macros */
#define MK_MINUTES(n) (MINUTE * (n))
#define MK_HOURS(n) (HOUR * (n))
#define MK_DAYS(n) (DAY * (n))
#define MK_WEEKS(n) (WEEK * (n))

/* useful string constants */
#define ALPHABET_LOWER "abcdefghijklmnopqrstuvwxyz"
#define ALPHABET_UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

#ifdef NOT_USING_ASCII
# define ALPHA_LOWER_OFFSET(x) (strchr(ALPHABET_LOWER, \
                                       tolower((unsigned char) (x))) - \
                                ALPHABET_LOWER)
# define ALPHA_UPPER_OFFSET(x) (strchr(ALPHABET_UPPER, \
                                       toupper((unsigned char) (x))) - \
                                ALPHABET_UPPER)
#else /* using ascii */
# define ALPHA_LOWER_OFFSET(x) (tolower(((unsigned char) (x)) - 'a'))
   
# define ALPHA_UPPER_OFFSET(x) (toupper(((unsigned char) (x)) - 'A'))
#endif

#define CONST_STR_LENGTH(x) (sizeof(x) - 1)


/* given a char cnovert it to an int, number */
#define TONUMB(x) ((int)((x) - '0'))

/* if x then add ", " onto the front of the CONSTANT string */
#define ADD_COMMA_FRONT(x, y) ((x) ? ( ", " y) : (y))

/* does a range check, y = min, z = max, x = integer checked */
#define RANGE(x, y, z) (((x) >= (y)) && ((x) <= (z)))

extern int skip_atoi(const char **);
extern long int skip_atol(const char **);


#endif
