/* $Id: mecha.h,v 1.134 2004/05/14 18:33:19 aleigh Exp $ */

/* Copyright (c) 2001, 2004 Alex Leigh, All Rights Reserved 
 *
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH
 * The copyright notice above does not evidence any
 * actual or intended publication of such source code.
 *
 * Use, disclosure, copying, distribution, or transmission of
 * this code without express permission is prohibited.
 */

#ifndef MECHA_H
#define MECHA_H

#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <pwd.h>
#include <uuid/uuid.h>

#ifdef __GNUC__
#define MECHA_UNUSED_ARGUMENT       __attribute__((unused))
#else
#define MECHA_UNUSED_ARGUMENT
#endif

#ifdef __GNUC__
#define MECHA_UNUSED       __attribute__((unused))
#else
#define MECHA_UNUSED
#endif

#if !defined(TRUE)
#define TRUE 1
#endif

#if !defined(FALSE)
#define FALSE 0
#endif

typedef unsigned char BOOL;

typedef void(*mecha_handler)(void *);

void mecha_init(void);

/* ast.c - Astronomical Functions */
struct astSsunriset
{
   double length;          /* 0-degree length of the day in hours */
   double rise;            /* 0-degree rise time UT */
   double set;             /* 0-degree set time UT */
   double zenith;          /* Zenith time UT*/
   double status;          /* Sun status */
   double civil_length;    /* 6-degree length of day in hours*/
   double civil_start;     /* 6-degree rise time UT */
   double civil_end;       /* 6-degree set time UT */
   double civil_status;    /* 6-degree sun status */
   double nautical_length; /* 12-degree length of day in hours */ 
   double nautical_start;  /* 12-degree rise time UT */ 
   double nautical_end;    /* 12-degree set time UT */
   double nautical_status; /* 12-degree sun status */
   double astro_length;    /* 18-degree length of day in hours */
   double astro_start;     /* 18-degree rise time UT */
   double astro_end;       /* 18-degree set time UT */
   double astro_status;    /* 18-degree sun status */
};
typedef struct astSsunriset astTsunriset;
void astFsunriset (astTsunriset * srs, int month, int day, int year, double lon, double lat);

/* b64.c - Base64 Coder */
int b64Fencode (unsigned char *bufin, unsigned int nbytes, char *bufcoded);
int b64Fdecode (const char *bufcoded, unsigned char *bufplain, int outbufsize);

/* bsp.c - BSP Tree */
typedef struct bspSnode bspTnode;

int bspFadd (bspTnode * list, void *p, int high_key, int low_key);
void *bspFsearch (bspTnode * node, unsigned int x);
void bspFdestroy (bspTnode * node, void (*destructor) (void *));
bspTnode *bspFinit (void);
void bspFbalance (bspTnode * node, unsigned int depth);

/* undoc */
unsigned int bspFcount (bspTnode * node);
void bspFsplit (bspTnode * node);
/* end undoc */

/* crc.c - Cyclical Redundancy Check */
uint32_t crcFcrc32 (const unsigned char *buf, unsigned len);

/* dyn.c - Dynamic String BUffers */
typedef struct dynSstring dynTstring;
dynTstring *dynFinit (void);
void dynFfree (dynTstring * ds);
size_t dynFappend (dynTstring * ds, const char *str, size_t len);
size_t dynFappend_string (dynTstring * ds, const dynTstring * src);
size_t dynFsappend (dynTstring * ds, const char *str);
size_t dynFappend_print (dynTstring * ds, const char *fmt, ...);
const char *dynFgetstr (const dynTstring * ds);
size_t dynFgetlen(const dynTstring *ds);
void dynFreset(dynTstring *ds);

/* fle.c - File Operations */
char *fleFload_file(const char *filename, size_t *len);
size_t fleFget_size(const char *filename);
int fleFset_close_exec (int fd);
void fleFpath_clean (char *pathname);
int fleFlock (const char *filename);
int fleFunlock (const char *filename);
int fleFsync_mem_to_file (char *filename, const char *memory, size_t len);
int fleFpath_simplify (const char *path, char *outpath, int len);
int fleFpath_combine (const char *path, int path_len, const char *relative, char *output, int output_len);
void fleFrotate(int count, const char *fn);
int fleFexist(const char *filename);



/* hsh.c - Hashing & Hash Lists */
typedef struct hshSiterator hshTiterator;
typedef struct hshSvoid_list hshTvoid_list;

void hshFvoid_int_update(hshTvoid_list * list, const int key, void *data);
void hshFvoid_update(hshTvoid_list * list, const char *name, void *data);

unsigned short int hshFraw_hash (const char *str, size_t len,
				 unsigned int buckets);
unsigned short int hshFraw_hashcode (const char *str, size_t len);
unsigned short int hshFhash (const char *str);
hshTvoid_list *hshFvoid_init (void (*destructor) (void *));
hshTvoid_list *hshFvoid_int_init (void (*destructor) (void *));
hshTvoid_list *hshFvoid_raw_init (void (*destructor) (void *),
				  void (*name_destructor) (void *),
				  int (name_comparator) (const void *s1,
							 const void *s2,
							 size_t len),
				  unsigned int buckets);
void hshFvoid_int_replace (hshTvoid_list * list, int key, void *data);
int hshFvoid_int_add (hshTvoid_list * list, int key, void *data);
void hshFvoid_replace (hshTvoid_list * list, const char *name, void *data);
int hshFvoid_add (hshTvoid_list * list, const char *name, void *data);
int hshFvoid_raw_add (hshTvoid_list * list, char *name, size_t name_len,
		      void *data, int replace);
void *hshFvoid_raw_find (hshTvoid_list * list, const char *name,
			 size_t name_len);
void *hshFvoid_find (hshTvoid_list * list, const char *name);
void *hshFvoid_int_find (hshTvoid_list * list, int key);

int hshFvoid_contains (hshTvoid_list *list, const char *key);
int hshFvoid_int_contains (hshTvoid_list *list, int key);

void hshFvoid_del (hshTvoid_list * list, const char *name);
void hshFvoid_int_del (hshTvoid_list * list, int key);
void hshFvoid_raw_del (hshTvoid_list * list, const char *name,
		       size_t name_len);
void *hshFvoid_remove (hshTvoid_list * list, const char *name);
void *hshFvoid_int_remove (hshTvoid_list * list, int key);
void * hshFvoid_raw_remove (hshTvoid_list * list, const char *name, size_t name_len);
void hshFvoid_destroy (hshTvoid_list *list);
void hshFvoid_free(hshTvoid_list *list);
hshTiterator *hshFiterator_init (hshTvoid_list * list);
int hshFiterator_next (hshTiterator * iterator);
void *hshFiterator_current_key (hshTiterator * iterator);
void *hshFiterator_current_value (hshTiterator * iterator);
void hshFiterator_free (hshTiterator * iterator);
void hshFiterator_reset (hshTiterator * iterator);
int hshFvoid_size (hshTvoid_list *list);
uint32_t hshFraw_hash32(const void *buf, size_t len, uint32_t buckets);
uint32_t hshFhash32(const char *str);
uint32_t hshFraw_hashcode32(const void *buf, size_t len);
void hshFvalue_destructor_set(hshTvoid_list *list, void (*destructor)(void *));
/* nodoc */
dynTstring *hshFdiag_output (hshTvoid_list *list);
/* end nodoc */

/* log.c - Message Logging */
#define CONT_LOG_OK 0
#define CONT_LOG_WARN 1
#define CONT_LOG_ERROR 2
#define CONT_LOG_DEBUG 3

#define logFmsg(...) logF_msg(__func__,__VA_ARGS__)

void logF_msg (const char *func, int level, const char *m, ...);
void logFmsgid (int level, const char *module, int msg_id, ...);
void logFoutputfh_set(FILE *fh, int close_flag);
FILE *logFoutputfh_get(void);
int logFset_outputfile(const char *filename);
void logFset_rotatesize(size_t size);
void logFinit(void);


/* lst.c - Linear Lists */
struct lstSarray {
    size_t size;
    size_t maxsize;
    size_t element_sz;
    char *elements;
};
void lstFarray_init(struct lstSarray *array, size_t element_sz);
int lstFarray_add(struct lstSarray *array, void *data, size_t *index);
void lstFarray_free(struct lstSarray *array, void(* freefunc)(char *elements, size_t size));
int lstFarray_get(void **p, struct lstSarray *array, size_t idx);
int lstFarray_remove(struct lstSarray *array, size_t idx);
int lstFarray_set(struct lstSarray *array, size_t idx, const char *data);

/* LEGACY */

typedef struct lstSset lstTset;
typedef struct lstSfield lstTfield;
lstTset *lstFset_init(void);
void lstFset_update (lstTset * set, const char *key, const char *value);
void lstFset_bupdate (lstTset * set, const char *key, size_t key_len, const char *value, size_t value_len);
/* undoc */
lstTset *lstFset_create (const char *name);
size_t lstFset_get_vsize_cmp (lstTset * set, const char *key,
                              int (*cmp) (const char *s1, const char *s2));
size_t lstFset_get_nsize_cmp (lstTset * set, const char *key,
                              int (*cmp) (const char *s1, const char *s2));
/* end undoc */
void lstFset_free (lstTset * set);
int lstFset_add (lstTset * set, const char *key, const char *value);
int lstFset_badd (lstTset * set, const char *key, size_t key_len, const char *value, size_t value_len);
int lstFset_nadd (lstTset * set, const char *key, int value);
/* return based on physical location */
const char *lstFset_get_index (lstTset * set, int idx);
int lstFset_unique (lstTset * set, const char *key);
int lstFset_inique (lstTset * set, const char *key);
int lstFset_find (lstTset * set, const char *key);
int lstFset_ifind (lstTset * set, const char *key);	
const char *lstFset_get (const lstTset * set, const char *key);
ssize_t lstFset_get_vsize (lstTset * set, const char *key);
ssize_t lstFset_get_nsize (lstTset * set, const char *key);
const char *lstFset_iget (lstTset * set, const char *key);
void lstFset_trunc (lstTset * set, int size);
void lstFset_delete (lstTset * set, int idx);
void lstFset_add_value (lstTset * set, int idx, const char *value);
void lstFset_delete_key (lstTset * set, const char *key);
void lstFset_idelete_key (lstTset * set, const char *key);
int lstFset_size (const lstTset * set);	
void lstFset_merge (lstTset * high, const lstTset * low);
int lstFnth_find (const lstTset * list, int nth);
char *lstFset_pack (const lstTset * set, size_t * len);

lstTset *lstFset_unpack (const char *pack);

const char *lstFfield_value (const lstTfield *field);
int lstFfield_value_len (const lstTfield *field);

const lstTfield *lstFset_get_field (lstTset *set, const char *key, int key_len);

/* begin undoc */
void lstFset_dump (char *pack);
int lstFpack (char *dest, char *src, int len, int class);
const char *lstFset_get_key_index (lstTset * set, int idx);
void lstFset_list_free (lstTset * sets);
lstTset *lstFset_list_find (lstTset ** sets, const char *name);
int lstFset_unique_cmp (lstTset * set, const char *key,
			int (*cmp) (const char *s1, const char *s2));
int lstFset_find_cmp (const lstTset * set, const char *key,
		      int (*cmp) (const char *s1, const char *s2));
const char *lstFset_get_cmp (const lstTset * set, const char *key,
		       int (*cmp) (const char *s1, const char *s2));
/* end undoc */

/* lst_void.c - Void Linear List */
/* begin undoc */
/* DEPRECATED INTERFACE DO NOT USE */
typedef struct lstSlist lstTlist;
typedef struct lstSlist_elem lstTlist_elem;
void lstFlist_init(lstTlist * list, void (*destroy) (void *));
void lstFlist_destroy(lstTlist * list);
lstTlist * lstFlist_create (void (*destroy) (void *));
void lstFlist_free (lstTlist *list);
int lstFlist_add_next(lstTlist * list, lstTlist_elem * elem, void *data);
int lstFlist_add_prev(lstTlist * list, lstTlist_elem * elem, void *data);
int lstFlist_remove(lstTlist * list, lstTlist_elem * elem, void **data);
lstTlist_elem * lstFlist_next (lstTlist_elem *elem);
lstTlist_elem * lstFlist_prev (lstTlist_elem *elem);
void * lstFlist_data (lstTlist_elem *elem);
int lstFlist_is_head (lstTlist *list, lstTlist_elem *elem);
int lstFlist_is_head (lstTlist *list, lstTlist_elem *elem);
lstTlist_elem * lstFlist_head (lstTlist *list);
lstTlist_elem * lstFlist_tail (lstTlist *list);
int lstFlist_size (lstTlist *list);
int lstFlist_is_tail (lstTlist *list, lstTlist_elem *elem) ;
/* end undoc */

/* mem.c - Memory Operations */
#ifndef WIN32
#define memFclear bzero
#define memFcopy bcopy
#else
#define memFclear(a,b) memset(a,0,b)
#define memFcopy memcpy
#endif
#define memFfree free
#define memFalloc malloc
#define memFrealloc realloc
void *memFdup(const void *p, size_t len);

/* rnd.c - Random Number Generator */
void rndFinit (void);
void rndFrandom_bytes (unsigned char *buf, int len);
unsigned int rndFnumber (void);

/* str.c - String Functions */
lstTset *strFattrib_parser(const char *str);
void strFstrip_crlf (char *s, const size_t len);
void strFtoupper (char *s);
void strFtolower (char *s);
char *strFdup_size (const char *s, size_t * len);
char *strFcopy_size (const char *s, size_t * len);
char *strFcopy (const char *s);
void strFrealloc (char **strP, int *maxsizeP, int size);
const char *strFcasestr (const char *haystack, const char *needle);
int strFis_whitespace(char c);
int strFis_blank(char *s);
dynTstring *strFcollapse_whitespace (char *str);
unsigned int strFsplit (char *str, char **list, unsigned int list_size,const char delim, const char quotechar);
char *strFncopy(const char *s, size_t len);
const char *strFskip_whitespace(const char *p);
const char *strFskip_token(const char *p);

/* tls.c - Thread Local Storage */
int tlsFregister (void *(*clean_fn) (void *));
char *tlsFadd_makeid (void *data, int class);
void *tlsFget (const char *name, int class);
void tlsFdel (char *name, int class);
void tlsFclean (void);
/* undoc */
void tlsFdestroy (void *p);
void tlsFinit (void);
void tlsFadd (void *data, char *name, int class);
/* end undoc */

/* utl.c - Utility Functions */
typedef struct utlSswatch utlTswatch;
int utlFfd_printf (int fd, const char *fmt, ...);
unsigned int utlFtime (void);
volatile const struct tm *utlFlocaltime (void);
volatile const char *utlFcommonlog_time (void);
volatile const char *utlFlocal_time (void);
utlTswatch *utlFstart_swatch (void);
unsigned int utlFstop_swatch (utlTswatch * sw);
int utlFtv_sub (struct timeval *r, const struct timeval *x, const struct timeval *y);
int utlFip_to_str (unsigned int ip, char *buf, size_t buflen);
unsigned int utlFstr_to_ip (const char *ip);
int utlFisnum (const char c);
int utlFstr_has_alphas (const char *p);
void utlFtv_add (struct timeval *res, struct timeval *t1, struct timeval *t2);
long utlFtv_to_ms (struct timeval *tv);
int utlFurl_encode (dynTstring * dyn, const char *string);
int utlFurl_decode (dynTstring * dyn, const char *string);
int utlFhexdigit (char c);
uint32_t utlFgethostid (void);
size_t utlFhttp_time_print (time_t when, char *buf, size_t buflen);
time_t utlFhttp_time_parse (char *str);
int utlFgetuid (const char *username);
int utlFgetgid (const char *username);
int utlFget_pwname(const char *username, struct passwd *pw);
int utlFget_homedir(const char *username,char *dir,size_t dir_len);
void utlFhours_to_hourmin(double in_time, int *hours, int *mins);
double utlFhourmin_to_hours(int hours, int mins);
int utlFip_match(unsigned int ipa, unsigned int ipb, unsigned int netmask);
const char *utlFshort_to_str(unsigned short n);
int utlFip_validate(const char *addr);
unsigned int utlFatoui(const char *s);
void utlFhexdump(void *data, size_t size);

/* undoc */
int utlFclock_get (uint32_t * clock_high, uint32_t * clock_low,
		   uint16_t * ret_clock_seq);
/* end undoc */

/* uid.c - Unique ID Generator */
int uidFgenerate_str (char *id, size_t len);

/* thr.c - Threads (Pooling, Triggers) */
typedef struct thrStpool thrTtpool;
typedef struct thrStrigger thrTtrigger;
thrTtpool *thrFinit (int num_threads,
                     int max_queue_size, int blocking_mode);
int thrFadd_work (thrTtpool * tpool, void (*routine) (void *), void *arg);
int thrFdestroy (thrTtpool * tpool, int finish);
int thrFsleep (int ms);
thrTtrigger *thrFgettrigger (void);
void thrFcheck_triggers (thrTtpool * tp);
int thrFtrigger_set (unsigned int delta, int fd);
int thrFtrigger_clear (void);
void thrFmod_init (void);
void thrFstat_thr (void *tp);

/* qry.c - HTTP query parser */
lstTset *qryFlst_parse(const char *query);
int qryFqualify(void);

/* cfg.c - "XML"ish configuration parser */
typedef struct xmlSiterator xmlTiterator;
typedef struct xmlSconfig xmlTconfig;
typedef struct xmlStag xmlTtag;

xmlTtag *xmlFbase_tag(const xmlTconfig *config);
xmlTconfig *xmlFparse(const char *str);
xmlTconfig *xmlFload_file(const char *filename);
const xmlTtag *xmlFfind_first_tag(const xmlTtag *tag, const char *name);
const xmlTtag *xmlFfind_first_tag_children(const xmlTtag *tag, const char *name);
const xmlTtag *xmlFfind_first_child(const xmlTtag *tag, const char *name);
xmlTiterator *xmlFiterator_init(const xmlTtag *tag);
void xmlFiterator_free(xmlTiterator *iterator);
const xmlTtag *xmlFiterator_next(xmlTiterator *iterator);
const xmlTtag *xmlFiterator_next_name(xmlTiterator *iterator, const char *name);
xmlTiterator *xmlFiterate_children(const xmlTtag *tag);
void xmlFiterator_reset(xmlTiterator *iterator);
const xmlTtag *xmlFiterator_tag(xmlTiterator *it);
const char *xmlFtag_get_name(const xmlTtag *tag, size_t *name_len);
const char *xmlFtag_get_value(const xmlTtag *tag, size_t *value_len);
const lstTset *xmlFtag_get_attribs(const xmlTtag *tag);
const char *xmlFtag_get_attrib_value(const xmlTtag *tag, const char *name);
const xmlTtag *xmlFtag_get_children(const xmlTtag *tag);
const char *xmlFtag_get_value_str(const xmlTtag *tag);
const char *xmlFtag_get_name_str(const xmlTtag *tag);
lstTset *xmlFcreate_list(const xmlTtag *tag, const char *tagname, const char *attribname);
const char *xmlFfirst_child_value(const xmlTtag *tag, const char *name, size_t *value_len);
const char *xmlFfirst_child_value_str (const xmlTtag *tag, const char *name);

/* net.c */
struct netSconn {
   int sd;                      /* OS socket descriptor*/
   uint32_t cli_ipv4_addr;      /* ipv4 address of the remote endpoint*/
   int (*io_close)(struct netSconn *conn);
   ssize_t (*io_writev)(struct netSconn *conn, const struct iovec *iov, int iovcnt);
   ssize_t (*io_read)(struct netSconn *conn, void *buf, size_t len);
   ssize_t (*io_write)(struct netSconn *conn, const void *buf, size_t len);
   void (*data_free)(void *data);
   void *data;
};   
typedef struct netSconn netTconn;
typedef struct netSreader netTreader;

int netFconn_close(netTconn *conn);
ssize_t netFconn_os_read(netTconn *conn, void *buf, size_t len);
ssize_t netFconn_os_write(netTconn *conn, const void *buf, size_t len);
int netFconn_os_close(netTconn *conn);
ssize_t netFconn_os_writev(netTconn *conn, const struct iovec *iov, int iovcnt);
ssize_t netFconn_write(netTconn *conn, const char *buf, ssize_t len);
netTreader *netFreader_init(void);
void netFreader_free(netTreader * reader);
int netFset_reuse(int sd);
int netFset_nodelay(int sd);
int netFipv4_listen_tcp(int port, unsigned int ip, int maxconnect);
ssize_t netFconn_read_line(netTconn * conn, netTreader * reader, char *buf, ssize_t len);
int netFisready(int fd);
int netFtcp_connect(char *addr, unsigned int port);
ssize_t netFconn_read(netTconn * conn, netTreader * reader, char *buf, ssize_t len);
ssize_t netFconn_write_two(netTconn * conn, const char *buf1, size_t buf1_len, const char *buf2, size_t buf2_len);
int netFudp_send(int sd, const void *msg, size_t msg_len, unsigned int port, unsigned int ip);
int netFudp_recv(int sd, char *msg, size_t msg_len, struct sockaddr_in * sa, socklen_t *sa_len);
int netFudp_open(uint16_t * port, int defport, char *service);
int netFudp_bcast_connect(void);
int netFconn_writef(netTconn * conn, const char *fmt,...);
int _netFconn_writef(netTconn * conn, const char *fmt, va_list * ap);
void netFconn_free(netTconn *conn);
netTconn *netFconn_make(int sd);

int netFipv4_mcast_create(unsigned int port, char *group);

    /* pat.c - patterns */
typedef struct patSstack patTstack;

patTstack *patFstack_init(void (*destructor) (void *));
void patFstack_free(patTstack *stack);
size_t patFstack_size(patTstack *stack);
void patFstack_append(patTstack *stack, const char *regexp, void *target);
void *patFstack_search(patTstack *stack, const char *needle) ;

/* exp.c - Expressions */
typedef void expTregexp;
int expFmatch(const char *pattern, const char *subject);
int expFmatch_len(const char *pattern, const char *subject, size_t subject_length);

expTregexp *expFregexp_compile(const char *pattern);
void expFregexp_free(expTregexp *re);
int expFregexp_replace (const expTregexp * regexp, const char *subject, size_t subject_length,
              const char *replace, size_t replace_length, char *output, size_t output_length);

int expFregexp_match(const expTregexp *re, const char *subject);
int expFregexp_match_len(const expTregexp *regexp, const char *subject, size_t subject_length);
int expFapply(const char *pattern, const char *subject, lstTset * output);

/* dic.c - Dictionary */
typedef struct dicSdictionary dicTdictionary;

dicTdictionary *dicFinit(void (*destructor) (void *),
                         int (*comparator) (const void *s1,
                                            const void *s2,
                                            size_t len));
void dicFfree(dicTdictionary *d);
int dicFupdate(dicTdictionary *d, int idx, void *value, size_t value_len);
void *dicFfind(dicTdictionary *d, int idx);
int docFfind_index(dicTdictionary *d, void *value, size_t value_len, int *idx);
char *dicFchar_find(dicTdictionary *d, int idx);
int dicFchar_update(dicTdictionary *d, int idx, char *str, size_t str_len);
dicTdictionary *dicFchar_init(void);
int dicFchar_find_index(dicTdictionary *d, char *value, size_t value_len, int *idx);
void dicFuserdata_destructor_set(dicTdictionary *d, void (*destructor)(void *));
void *dicFuserdata_find(dicTdictionary *d, int idx);
void dicFuserdata_update(dicTdictionary *d, int idx, void *data);

/* sic.c - System functions */
int sysFfs_info(lstTset * set);
int sysFget_load(double *one_min, double *five_min, double *fifteen_min);
unsigned int sysFboot_time(void);
int sysFmem_usage(uint32_t *pages_total, uint32_t *pages_free,
                  uint32_t *phys_mem, uint32_t *availr_mem,
                  uint32_t *free_mem);
int sysFcpu_usage(uint32_t *idle_time, uint32_t *user_time, 
                 uint32_t *kernel_time, uint32_t *wait_time);
int sysFnet_usage(uint32_t *obytes, uint32_t *ibytes, 
                  uint32_t *opkts, uint32_t *ipkts);

struct mapShash {
    hshTvoid_list *legacy;
};
int mapFhash_init(struct mapShash *map, void (*destructor)(void *),
                  void (*name_destructor)(void *),
                  int (name_comparator)(const void *,
                                        const void *,
                                        size_t),
                  unsigned int buckets);
int mapFhash_free(struct mapShash *map);
int mapFhash_set(struct mapShash *map, void *name, size_t name_len, void *data);
int mapFhash_get(void **data, struct mapShash *map, void *name, size_t name_len);

#endif
