/*
 * © Copyright 1996-2012 ECMWF.
 *
 * This software is licensed under the terms of the Apache Licence Version 2.0
 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
 * In applying this licence, ECMWF does not waive the privileges and immunities
 * granted to it by virtue of its status as an intergovernmental organisation nor
 * does it submit to any jurisdiction.
 */

#include "mars_client_config.h"

#ifndef _H_MARS

/* For empress <c.h>  header file */
#define SYSTEM_BOOLEAN
#define _H_MARS

/* This is for name clashes with struct queue in sys/stream.h,
   included from netinet/in.h, and use of stl with mars. The
   define is reverted after mars has included the files.
   There is probably a safer way of doing this
*/

#ifdef sun
#define queue system_queue
#endif

#ifdef __linux__
#ifndef __USE_LARGEFILE64
#define __USE_LARGEFILE64
#endif
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
/* Contains definitions like stat64 */
#include <glob.h>
#endif

#define readany(a)  /*ERROR DONT CALL READANY*/
#define readprod(a) /*ERROR DONT CALL READPROD*/
#define readgrib(a) /*ERROR DONT CALL READPROD*/
#define readbufr(a) /*ERROR DONT CALL READPROD*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
//#include <malloc.h>
#include <unistd.h>
#include <limits.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>

#if mars_client_HAVE_RPC
#include <rpc/rpc.h>
#include <rpc/xdr.h>
#endif /* mars_client_HAVE_RPC */

#include <time.h>  /* for clock_t */
#ifdef __GNUC__
#include <float.h> /* for FLT_MAX */
#endif


#include <errno.h>
#if !defined(__linux__) && !defined(CYGWIN)
#ifdef VMS
#include <sys/perror.h>
#else
//extern char *sys_errlist[];
//extern int sys_nerr;
#endif
#endif

#ifdef sun
#define system_queue queue
#endif

/* when the ibm goes down, undef this variable. Even better, grep it
  and remove the code in it */
#define OBSOLETE

#ifdef sun
#define boolean mars_bool
#endif

#ifdef __uxp__
#define fujitsu
#endif

#define C2FORT(x) (x)

#ifdef CRAY
#include <fortran.h>
#define FORTRAN_UPPERCASE
#undef  C2FORT
#define C2FORT(x)  _cptofcd(x,strlen(x))
#endif

#ifdef _AIX
#if !defined(FORTRAN_NO_UNDERSCORE) && !defined(METVIEW)
#define FORTRAN_NO_UNDERSCORE
#endif
#define LARGE_FILES_SUPPORT
#endif

#ifdef p690
#undef FORTRAN_NO_UNDERSCORE
#endif

#ifdef __hpux
#ifndef hpux
#define hpux
#endif
#endif

#ifdef __ia64
#ifndef ia64
#define ia64
#endif
#endif


#ifdef hpux
#if !defined(FORTRAN_NO_UNDERSCORE) && !defined(METVIEW)
#ifndef ia64
#define FORTRAN_NO_UNDERSCORE
#endif
#endif
#endif

#if defined(fujitsu) || defined(hpux) || defined(AIX) || defined(__alpha)
#define NO_ATOLL_SUPPORT
#endif

#ifdef ia64
/* man htonl on hpia64 */
#ifdef _XOPEN_SOURCE_EXTENDED
#include <arpa/inet.h>
#endif
#endif

#ifdef __linux__
#define LARGE_FILES_SUPPORT
# if !defined __off64_t_defined
typedef __off64_t off64_t;
#define __off64_t_defined
#endif
#endif


/*=======================================================================*/
/* Fortran types                                                         */

#if !defined(I32) && !defined(I64) && !defined(I128)
#define I32
#endif

#if !defined(R32) && !defined(R64) && !defined(R128)
#define R32
#endif

#define INT_MISSING_VALUE INT_MAX
#ifdef hpux
#define FLOAT_MISSING_VALUE 3.40282346638528859812E+38F
#else
#define FLOAT_MISSING_VALUE FLT_MAX
#endif


#ifdef I32
typedef int  fortint;    /* fortran integer */
#endif

#ifdef I64
typedef long long fortint;
#endif

#ifdef R32
typedef float fortfloat; /* fortran single precision float */
#define PFLOAT "f"
#endif

#ifdef R64
typedef double fortfloat;
#define FLOAT "lf"
#endif

/*===========================================================================*/
/* Common mars types                                                         */

#if !defined(__cplusplus) && !defined(c_plusplus)
#ifndef false
#define true 1
#define false 0
#endif
#endif

typedef int                 err;
typedef double				real;
typedef long long           long64;
typedef unsigned long long  ulong64;
typedef int                 boolean;

#include "hash.h" /* must be here for rpcmars.h" */

#if mars_client_HAVE_RPC
#include "rpcmars.h"
#else
typedef char *cache_t;
typedef void *voidp_t;
struct value {
        /*  request part */
        struct value *next;
        cache_t         name;
        /* language part */
        struct value     *other_names;
        struct value     *ref;
        struct value     *expand;
};
typedef struct value value;

struct request {
    struct request   *next;
    struct parameter *params;
    cache_t         name;
    cache_t         info;
    cache_t         kind;
    voidp_t          data; /* user data */
    long             order;
};
typedef struct request request;

struct parameter {
    /*  request part */
    struct parameter *next;
    struct value     *values;
    cache_t         name;
    int              count;
    struct request   *subrequest;
    /* language part */
    struct value     *default_values;
    struct value     *current_values;
    struct value     *ibm_values;
    struct request   *interface;
};
typedef struct parameter parameter;

struct cache_index {
    struct request *index;
};
#endif

/*===========================================================================*/
/* Mars logging routines                                                     */
/*===========================================================================*/


#define LOG_DBUG		0	/* debugging message    */
#define LOG_INFO		1	/* informative message  */
#define LOG_WARN 		2	/* warning message      */
#define LOG_EROR		3	/* error   message      */
#define LOG_EXIT		4	/* fatal error message  */
#define LOG_SMS		    5	/* sms message  */
#define LOG_NONE	    6   /* no prefix */
#define LOG_PERR    	256	/* print errno          */
#define LOG_NOCR    	512	/* no carriage-return   */
#define LOG_ONCE	    1024 /* print messages only once */

typedef void (*loopproc)(const request*,int,char**,char**,void*);
typedef void (*exitproc)(int,void*);
typedef void (*cbackproc)(void*); /* simple call back */

/*===========================================================================*/
/* Usefull macros                                                            */
/*===========================================================================*/


#ifndef NUMBER
#define NUMBER(a)    (sizeof(a)/sizeof(a[0])) /* number of elem. of an array */
#endif
#ifndef MAX
#define MAX(a,b) (((a)>(b))?(a):(b))
#endif
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#define ABS(a)       ((a)<0?-(a):(a))
#define ROUND(a)     ((long)((a)+0.5))
#define EQ(a,b)      ((*(a) == *(b)) && (strcmp(a,b) == 0))
#define LT(a,b)      ((*(a) <  *(b)) || (strcmp(a,b) < 0))


/*===========================================================================*/
/* Memory mamagement                                                         */
/*===========================================================================*/

/* Use the macros ... */

#define NEW(type)       (type*)get_mem(sizeof(type))
#define NEW_CLEAR(type) (type*)get_mem_clear(sizeof(type))
#define MALLOC(size)    get_mem(size)
#define NEW_ARRAY(type,cnt) (type*)get_mem((cnt)*(sizeof(type)))
#define NEW_ARRAY_CLEAR(type,cnt) (type*)get_mem_clear((cnt)*(sizeof(type)))
#define FREE(x)          free_mem(x)
#define NEW_STRING(s)    new_string(s)
#define REALLOC(x,n)     re_alloc(x,n)
#define CLEAR(a)         memset(&a,0,sizeof(a))

typedef struct {
	int   pages;     /* Number of pages to allocate */
	int   clear;     /* clear newly allocated memory */
	void *priv;
} mempool;

extern mempool *permanent_mem;
extern mempool *transient_mem;


/*===========================================================================*/
/* Expand flags                                                              */
/*===========================================================================*/

#define EXPAND_DATE				1   /* expand dates           */
#define EXPAND_TIME				2   /* expand times           */
#define EXPAND_NO_OFF			4   /* remove off values      */
#define EXPAND_LAST_NAME		8   /* name is last           */
#define EXPAND_2ND_NAME		    16  /* name is second         */
#define EXPAND_FIRST_NAME		32  /* name is first          */
#define EXPAND_LISTS			64  /* expand lists (not imp) */
#define EXPAND_NO_DEFAULT	   128  /* expand, no default val */
#define EXPAND_DEFAULTS	   	   512  /* expand, default as well*/
#define EXPAND_DONT_FAIL	  1024  /* expand, don't fail     */
#define EXPAND_SUB_LISTS	  2048  /* expand values into lists*/
#define EXPAND_STEP			  4096   /* expand steps           */

#define EXPAND_MARS           (EXPAND_DATE|EXPAND_TIME|EXPAND_STEP|EXPAND_NO_OFF|\
							   EXPAND_LAST_NAME|EXPAND_LISTS|EXPAND_SUB_LISTS)


/*===========================================================================*/
/* Schedule flags                                                            */
/*===========================================================================*/

#define SCHEDULE_FAIL   0x01
#define SCHEDULE_INFORM 0x02
#define SCHEDULE_LOG    0x04
#define SCHEDULE_INFORM_FUTURE_CHANGE    0x08
#define SCHEDULE_MAIL   0x10

/* compare two values */
typedef boolean (*namecmp)(const char *, const char *);
/*===========================================================================*/
/*                                                                           */
/*===========================================================================*/

/*===========================================================================*/
/* Lex & Yacc                                                                */
/*===========================================================================*/
#define YYMAXDEPTH 300

/*===========================================================================*/
/* Language                                                                  */
/*===========================================================================*/

typedef void (*lookupproc)(char*,void*);

/*===========================================================================*/
/* Networking                                                                */
/*===========================================================================*/

typedef void (*taskproc)(int,int,void*);
typedef void (*udpproc)(char*,int*,int,void*);

typedef struct udpinfo {
	int soc;
	struct sockaddr_in sin;
	struct timeval     timeout;
} udpinfo;

typedef struct firewall_info firewall_info;

#if defined(AIX) || (defined(ia64) && defined(_XOPEN_SOURCE_EXTENDED))
#ifdef __64BIT__
	typedef socklen_t marssocklen_t;
#else
	typedef size_t marssocklen_t;
#endif
#elif (defined(__APPLE__) && defined(__MACH__))
	typedef socklen_t marssocklen_t;
#else
#ifdef __APPLE__
	typedef socklen_t marssocklen_t;
#else
	typedef int marssocklen_t;
#endif
#endif

/*===========================================================================*/
/* Post-processing                                                           */
/*===========================================================================*/

/* Vector Post-processing */
typedef struct ppbuffer_t {
	char *buffer;
	long buflen;
	long inlen;
	long outlen;
} ppbuffer_t;

typedef err (*postproc)(ppbuffer_t *,long *);

/*===========================================================================*/
/* Handler                                                                   */
/*===========================================================================*/

typedef err  (*handlerproc) (request*,void*);

typedef struct handler {
	char        *name;
	handlerproc proc;
	long        flags;
} handler;

/*===========================================================================*/
/* Service                                                                   */
/*===========================================================================*/

typedef struct svc svc;


typedef struct svcid {
	struct svcid *next;
	request      *r;
	svc          *s;
	void         *data;
} svcid;

typedef void (*svcproc)(svcid *,request *,void *);
typedef boolean (*inputproc)(FILE *,void *); /* return false on eof */

typedef struct svcprocs {
	struct svcprocs *next;
	char            *name;
	svcproc          proc;
	void            *data;
	request         *args;
} svcprocs;

typedef struct inputprocs {
	struct inputprocs *next;
	inputproc          proc;
	void              *data;
	FILE 			  *f;
} inputprocs;

#if mars_client_HAVE_RPC
struct svc {
  int soc;
  XDR x;

  svcid *id;

  svcproc waitp; /* wait for      */
  err waite;     /* wait error    */

  svcprocs *serv; /* services   cb */
  svcprocs *repl; /* replies    cb */
  svcprocs *mess; /* messages   cb */
  svcprocs *prog; /* progession cb */
  svcprocs *fncs; /* functions  cb */
  svcprocs *drop; /* drag-drop  cb */

  inputprocs *input; /* input procs */

  boolean recording;

  int port; /* pid on server side */
  char *host;
  char *name;
  char *user; /* server only */

  long context;
  long flags;
  long timeout;

  long replies; /* number of outstanding replies */

  request *r;
};
#endif /* mars_client_HAVE_RPC */

/*===========================================================================*/
/* Service functions                                                         */
/*===========================================================================*/

enum argtype {

	tnumber  = 1L, /* warning : for recording, it's a double ... */
	tstring  = 2L,
	tdate    = 4L,
	tmatrix  = 8L,
	tgrib    = 16L,
	tbufr    = 32L,
	tlist    = 64L,
	trequest = 128L,
	tfile    = 256L,
	tdefered = 512L,
	terror   = 1024L,
	timage   = 2048L,
	tvector  = 4096L,
	tgeopts  = 32768L,
	tvis5d   = 65536L,
	tnil     = 131072L,
	tnetcdf  = 262144L,
	tobject  = 524288L,
	todb     = 1048576L,
	ttable   = 2097152L,
	tgptset  = 4194304L,

	/* used only for recording .. */

	tinteger = 8192L,
	tboolean = 16384L,


	tany    = ~0L,
	tnone   = 0L
};

typedef enum argtype argtype;

typedef struct {
	char    *name;
	char    *def;
	argtype kind;
} argdef;

/*===========================================================================*/
/* Stream                                                                    */
/*===========================================================================*/

typedef struct mstream {
	long64 in;
	long64 out;
	err  error;
	void *data;
	int (*read) (void*,void*,unsigned int);
	int (*write)(void*,void*,unsigned int);
} mstream;

/*===========================================================================*/
/* Options                                                                   */
/*===========================================================================*/

typedef enum {t_char,t_int,t_long,t_long64,t_str,t_ptr,t_double,t_boolean,t_fortfloat} type;

typedef struct option {

	char *name;            /* Option name          */
	char *env;             /* Environment variable */
	char *opt;             /* command line option  */
	char *def;             /* default value        */
	type  kind;            /* type of variable     */
	int   size;            /* field size           */
	long  offset;          /* field offset         */

}option;

#define OFFSET(type,field) (((char*)(&(((type*)NULL)->field)))-((char*)NULL))

typedef struct _wind wind;

/*===========================================================================*/
/* Time                                                                      */
/*===========================================================================*/
#define SECS_IN_DAY	86400

typedef long64 datetime;

typedef struct time_interval {

	datetime begin;
	datetime end;

} time_interval;

/*===========================================================================*/
/* Timer                                                                     */
/*===========================================================================*/

typedef struct timer {

	struct timeval start_;
	double timer_;
	boolean   active_;
	char   *name_;
	int    count_;
	long64 total_;

	boolean elapsed_;
	double  cpu_;
	double  total_cpu_;

	char   *statname_;

	struct timer *next_;
} timer;

/*===========================================================================*/
/* Errors                                                                    */
/*===========================================================================*/


#define NOERR           0
#ifndef EOF
#define EOF             -1
#endif
#define BUF_TO_SMALL    -3
#define COMPRESS_ERR	-4
#define NOT_FOUND_7777  -5
#define END_REQUEST     -6
#define HYPERCUBE_ERROR -7
#define POSTPROC_ERROR -8
#define FAILED_EXPAND   -9
#define ODB_ERROR       -10
#define QUOTA_ERROR       -11

#define NOT_READY_ERR	-42
#define TOO_SHORT_ERR	-43

#define RETRY_FOREVER_ERR   -7776
#define RETRY_ERR           -7777


#define EMPRESS_ERR     -1000

#define QUALBUILD_ERR	(-1  + EMPRESS_ERR)
#define LOCK_ERR		(-2  + EMPRESS_ERR)
#define ADD_ERR			(-3  + EMPRESS_ERR)
#define CONVERT_ERR		(-4  + EMPRESS_ERR)
#define DUPLICATE_ERR	(-5  + EMPRESS_ERR)
#define REQUEST_ERR		(-6  + EMPRESS_ERR)
#define WRITEBLOB_ERR	(-7  + EMPRESS_ERR)
#define OPENTABLE_ERR	(-8  + EMPRESS_ERR)
#define UPDATE_ERR		(-9  + EMPRESS_ERR)
#define ATTRLIST_ERR	(-10 + EMPRESS_ERR)

typedef struct math{
	struct math *left;
	struct math *right;
	char        *name;
	int         arity;
}math;

typedef double (*mathproc)();
typedef err    (*funcproc)(math*,mathproc);

typedef struct func {
	char    *name;
	funcproc addr;
	mathproc proc;
	int      arity;
	char     *info;
}func;

#include "grib.h"
#include "bufr.h"
#include "field.h"
#include "variable.h"
#include "tools.h"
#include "globals.h"
#include "lang.h"
#include "base.h"
#include "control.h"
#include "hypercube.h"
#include "index.h"
#include "nctarget.h"

typedef struct marslist {
	struct marslist  *next;
	char             *name;
	void             *data;
} marslist;


#ifdef __alpha
/* Alpha has its own basename(), but not with 'const' */
/* rename ours to mbasename. Beware not to include
string.h after mars.h
*/
#define basename mbasename
#endif

#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

/* used to certify requests */
typedef struct ECMarsCertReply eCMarsCertReply;

#include "api.h"
#include "json.h"
#include "cos.h"
#include "proto.h"
extern err parser(const char*,boolean);
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

/* xdr routines */

#if (defined(CRAY) || defined(__alpha))
typedef void* mxdrparam;
typedef int (*mxdrproc)();
typedef void* msockopt;
#elif defined(sgi)
typedef void* mxdrparam;
typedef int (*mxdrproc)(void*,void*,u_int);
typedef void* msockopt;
#elif defined(fujitsu)
typedef caddr_t mxdrparam;
typedef int (*mxdrproc)(void*,caddr_t,int);
typedef char* msockopt;
#elif (defined(__APPLE__) && defined(__MACH__))  /* To allow Metview to compile on Mac OS X */
typedef caddr_t mxdrparam;
typedef int (*mxdrproc)(void*,void*,int);
typedef void* msockopt;
#elif defined(__linux__)
typedef caddr_t mxdrparam;
typedef int (*mxdrproc)(void*,void*,int);
typedef __ptr_t msockopt;
#else
typedef caddr_t mxdrparam;
typedef int (*mxdrproc)(void*,caddr_t,int);
typedef void* msockopt;
#endif




#ifndef SEEK_SET
#define SEEK_SET 0 /* stupid codecenter */
#endif

#ifdef _AIX
/* stupid ibm got it wrong ... */
#define strcasecmp casecompare

#endif

#endif

#ifdef METVIEW_MOTIF
#ifdef XtSpecificationRelease
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
svc *RegisterService(XtAppContext app_context,const char *name);
void ListenToService(XtAppContext app_context,svc *s);
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
#endif
#endif
