# include <stdio.h>
# include <fcntl.h>
# include <math.h>
# include <float.h>
# include <errno.h>
# include <time.h>
# include <stdlib.h>
# include <stdint.h>
# include <string.h>
# include <sys/socket.h>
# include <sys/time.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <sys/uio.h>
# include <sys/un.h>
# include <unistd.h>
# include <stdarg.h> 
# include <readline/history.h>
# include <readline/readline.h>

// XXX I was including these before, but RHL claims they are not needed
// # include <malloc.h>
// # include <memory.h>

/* OHANA included stuff */
# ifndef OHANA_H
# define OHANA_H

# ifndef TRUE
# define TRUE (1)
# endif

# ifndef FALSE
# define FALSE (0)
# endif 

// XXX these should probably use safe name-spaces (eg, OHANA_MIN)
# ifndef SIGN
# define SIGN(X) (((X) == 0) ? 0 : ((fabs((double)(X))) / (X)))
# endif

# ifndef ROUND
# define ROUND(X) ((int) ((X) + 0.5*SIGN(X)))
# endif

# ifndef SQR
# define SQR(X)   (double) (((double)(X))*((double)(X)))
# endif

# ifndef SQ
# define SQ(X)    (double) (((double)(X))*((double)(X)))
# endif

# ifndef MIN
# define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
# endif

# ifndef MAX
# define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
# endif

# ifndef SWAP
# define SWAP(X,Y) {double tmp=(X); (X) = (Y); (Y) = tmp;}
# endif

# ifndef DTIME
# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
# endif

enum {
 LCK_UNLOCK,        /* file is unlocked */
 LCK_INVALID,       /* invalid locktype requested */
 LCK_MISSING,       /* soft requested and file missing (error) */
 LCK_ACCESS,        /* can't get access to file */
 LCK_TIMEOUT,       /* timeout setting lock */
 LCK_HARDOPEN,      /* cannot open hard lockfile */
 LCK_HARDLOCK,      /* cannot lock hard lockfile */
 LCK_HARDLOCKHARD,  /* hard lockfile is locked */
 LCK_HARDCLOSE,     /* cannot write to hardlock */

 LCK_EMPTY,         /* file is locked and empty */
 LCK_FULL,          /* file is locked and not empty */
 LCK_UNKNOWN,       /* file is locked, but can't get size */

 LCK_SOFT,          /* soft lock */
 LCK_HARD,          /* hard lock */
 LCK_XCLD,          /* exclusive soft lock */
};

# ifndef M_PI
# define M_PI 3.14159265358979323846264
# endif

# define DEG_RAD 57.295779513082322
# define RAD_DEG  0.017453292519943

# ifndef PROTO
#   define PROTO(A) A
# endif

/* 
# else
#   ifndef PROTO
#   define PROTO(A) ()
#   endif
# include <varargs.h>
# endif
*/

/* ohana_allocate.h provides ohana memory tools.  to use them
   you must # define OHANA_MEMORY before including ohana.h */
# include <ohana_allocate.h>

# ifndef FOPEN 
# define FOPEN(F,NAME) \
  F = fopen (NAME, "r"); \
  if (F == NULL) { \
    fprintf (stderr, "failed to open %s\n", NAME); \
    exit (0); \
  }
# endif /* FOPEN */

/*
  isspace is c99 : do we require c99 now? 
  isspace()
   checks  for white-space characters.  In the "C" and "POSIX" locales, these are: space, form-feed ('\f'), newline ('\n'),
   carriage return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
   horiz. tab: 0x09, vert. tab: 0x0b, newline: 0x0a, form-feed: 0x0c, return: 0x0d, space: 0x20, 
*/
# define OHANA_WHITESPACE(c)(((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0b) || ((c) == 0x0b) || ((c) == 0x0c) || ((c) == 0x0d) || ((c) == 0x20))

// sorting is now defined as a macro call
# include <ohana_sort.h>

/* socket / pipe communication buffer */
typedef struct {
  char *buffer;
  int   Nalloc;
  int   Nreset;
  int   Nblock;
  int   Nbuffer;
} IOBuffer;

extern double hypot(double,double);

/* in string.c */
int     stripwhite             PROTO((char *string));
int     strnumcmp              PROTO((char *str1, char *str2));
char   *strcreate              PROTO((char *string));
char   *strncreate             PROTO((char *string, int n));
int     scan_line              PROTO((FILE *f, char *line)); 
int     dparse                 PROTO((double *X, int NX, char *line));
int     fparse                 PROTO((float *X, int NX, char *line));
int     get_argument           PROTO((int argc, char **argv, char *arg));
int     remove_argument        PROTO((int N, int *argc, char **argv));
void    uppercase              PROTO((char *string));
char   *strip_version          PROTO((char *input));
char   *strsubs                PROTO((char *string, char *match, char *with));

/* in findexec.c */
char   *pathname               PROTO((char *name));
char   *filebasename           PROTO((char *name));
char   *filerootname           PROTO((char *name));
char   *fileextname            PROTO((char *file));
char   *findexec               PROTO((int argc, char **argv));
int     mkdirhier              PROTO((char *path, int mode));
void    make_backup            PROTO((char *filename));
int     check_file_access      PROTO((char *basefile, int backup, int verbose));
int     check_dir_access       PROTO((char *path, int verbose));
int     check_file_exec        PROTO((char *filename));

/* in glockfile.c */
FILE   *fsetlockfile           PROTO((char *filename, double timeout, int type, int *state));
int     fclearlockfile         PROTO((char *filename, FILE *f, int type, int *state));

/* in config.c */
char   *SelectConfigFile       PROTO((int *argc, char **argv, char *progname));
char   *LoadConfigFile         PROTO((char *filename));
char   *ScanConfig             PROTO((char *config, char *field, char *mode, int N,...));
char   *expandline             PROTO((char *line, char *config));
char   *fileextname            PROTO((char *file));
char   *LoadRawConfigFile      PROTO((char *, int));

/* others */
int     Fseek                  PROTO((FILE *f, long offset, int whence));
char   *ohana_version          PROTO((void));

int     dgaussjordan           PROTO((double **A, double **B, int N, int M));
int     fgaussjordan           PROTO((float **A, float **B, int n, int m));

/* in time.c */
enum {TIME_NONE, TIME_DATE, TIME_DAYS, TIME_HOURS, TIME_MINUTES, TIME_SECONDS, TIME_JD, TIME_MJD};

int     ohana_chk_time         PROTO((char *line));
time_t  ohana_date_to_sec      PROTO((char *date));
int     ohana_dms_to_ddd       PROTO((double *Value, char *string));
time_t  ohana_jd_to_sec        PROTO((double jd));
time_t  ohana_mjd_to_sec       PROTO((double mjd));
char   *ohana_sec_to_date      PROTO((time_t second));
double  ohana_sec_to_jd        PROTO((time_t second));
int     ohana_str_to_dtime     PROTO((char *line, double *second));
int     ohana_str_to_time      PROTO((char *line, time_t *second));
double  ohana_sec_to_mjd       PROTO((time_t second));
double  ohana_lst              PROTO((double jd, double longitude));
int     ohana_str_to_radec     PROTO((double *ra, double *dec, char *str1, char *str2));
double  ohana_normalize_angle  PROTO((double angle));

int     hstgsc_hms_to_deg      PROTO((double *h0, double *h1, double *d0, double *d1, char *string));

/* IO Buffer functions */
int     InitIOBuffer   	       PROTO((IOBuffer *buffer, int Nalloc));
int 	FlushIOBuffer  	       PROTO((IOBuffer *buffer));
int 	ReadtoIOBuffer 	       PROTO((IOBuffer *buffer, int fd));
int 	EmptyIOBuffer  	       PROTO((IOBuffer *buffer, int Nmax, int fd));
void    FreeIOBuffer   	       PROTO((IOBuffer *buffer));
int 	PrintIOBuffer  	       PROTO((IOBuffer *buffer, char *format, ...));
int 	vPrintIOBuffer 	       PROTO((IOBuffer *buffer, char *format, va_list argp));

/* communication functions */
int 	ExpectMessage 	       PROTO((int device, double timeout, IOBuffer *message));
int 	ExpectCommand 	       PROTO((int device, int length, double timeout, IOBuffer *buffer));
int 	SendMessage   	       PROTO((int device, char *format, ...));
int 	SendMessageFixed       PROTO((int device, int length, char *messge));
int 	SendCommand   	       PROTO((int device, int length, char *format, ...));
int 	SendCommandV  	       PROTO((int device, int length, char *format, va_list argp));

char   *CheckForMessage        PROTO((IOBuffer *buffer));

/*
#   define F_SETFL         4   
#   define O_NONBLOCK      0200000  
#   define AF_UNIX         1          
#   define SOCK_STREAM     1
*/

/*
# ifndef ANSI
# include <varargs.h>
# else
# include <stdarg.h> 
# include <cfuncs.h> 
# endif
*/

# endif
