
#ifndef hocdec_h
#define hocdec_h
#define	INCLUDEHOCH	1
#define OOP 1

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

#include	"nrnapi.h"
#include	"hocassrt.h"
#include	<string.h>

#define gargstr hoc_gargstr
#define getarg hoc_getarg

/* the dec alpha cxx doesn't understand struct foo* inside a struct */

#if defined(__cplusplus)
#define HocStruct /**/
#define HocTypedef /**/
#define HocUnion /**/
union Inst;
struct Symbol;
struct Arrayinfo;
struct Proc;
struct Symlist;
union Datum;
struct cTemplate;
union Objectdata;
struct Object;
struct hoc_Item;
#else
#define HocStruct struct
#define HocUnion union
#define HocTypedef typedef
#endif

typedef int	(*Pfri)(void);
typedef void	(*Pfrv)(void);
typedef double	(*Pfrd)(void);
typedef struct Object** (*Pfro)(void);
typedef const char** (*Pfrs)(void);

typedef int	(*Pfri_vp)(void*);
typedef void	(*Pfrv_vp)(void*);
typedef double	(*Pfrd_vp)(void*);
typedef struct Object** (*Pfro_vp)(void*);
typedef const char** (*Pfrs_vp)(void*);

typedef union Inst { /* machine instruction list type */
	Pfrv	pf;
	Pfrd	pfd;
	Pfro	pfo;
	Pfrs	pfs;
	Pfrv_vp	pfv_vp;
	Pfrd_vp	pfd_vp;
	Pfro_vp	pfo_vp;
	Pfrs_vp	pfs_vp;
	HocUnion Inst	*in;
	HocStruct Symbol	*sym;
	void*	ptr;
	int	i;
} Inst;

#define STOP	(Inst *)0

typedef struct Arrayinfo  { /* subscript info for arrays */
	unsigned *a_varn;	/* dependent variable number for array elms */
	int	nsub;		/* number of subscripts */
	int	refcount;	/* because one object always uses symbol's */
	int	sub[1];		/* subscript range */
} Arrayinfo;

typedef struct Proc {
	Inst	defn;	/* FUNCTION, PROCEDURE, FUN_BLTIN */
	unsigned long size;	/* length of instruction list */
	HocStruct Symlist	*list;	/* For constants and strings */
				/* not used by FUN_BLTIN */
	int	nauto;		/* total # local variables */
	int	nobjauto;	/* the last of these are pointers to objects */
} Proc;

typedef struct Symlist {
	HocStruct Symbol *first;
	HocStruct Symbol *last;
}Symlist;

typedef char	*Upoint;

# define	NOTUSER		0
# define	USERINT		1	/* For subtype */
# define	USERDOUBLE	2
#define		USERPROPERTY	3	/* for newcable non-range variables */
#define		USERFLOAT	4	/* John Miller's NEMO uses floats */
#if NEMO
#define		NEMONODE	5	/* looks syntactically like vector */
#define		NEMOAREA	6	/* looks like vector */
#endif
#define		SYMBOL		7	/* for stack type */
#define		OBJECTTMP	8	/* temporary object on stack */
#define		CPLUSOBJECT	16	/* c++ registered class */
#define		JAVAOBJECT	32	/* c++ registered class */
/* above two are bits, next must start at 64 */
#define OBJECTALIAS 1
#define VARALIAS 2

typedef struct HocSymExtension {
	float *parmlimits;	/* some variables have suggested bounds */
	char* units;
	float tolerance;	/* some states have cvode absolute tolerance */
}HocSymExtension;

typedef struct Symbol {	/* symbol table entry */
	char	*name;
	short	type;
	short	subtype;	/* Flag for user integers */
#if defined(__cplusplus)
	short	cpublic;		/* flag set public variable */
#else
	short	public;		/* flag set public variable */
#endif
	short	defined_on_the_fly;/* moved here because otherwize gcc and borland do not align the same way */
	union {
		int	oboff;	/* offset into object data pointer space */
#if 0 /* these are now found via oboff. */
		char	*str;		/* STRING */
		HocStruct Object **objvar; /* possibly an array of object variables */
#endif
		double	*pval;		/* User defined doubles - also for alias to scalar */
		HocStruct Object* object_;	/* alias to an object */
		char	*cstr;		/* constant string */
		double	*pnum;		/* Numbers */
		int	*pvalint;	/* User defined integers */
		float	*pvalfloat;	/* User defined floats */
		int	u_auto;		/* stack offset # for AUTO variable */
		double	(*ptr)();	/* if BLTIN */
		Proc	*u_proc;
		struct {
			short type;	/* Membrane type to find Prop */
			int index;	/* prop->param[index] */
		}rng;
		HocStruct Symbol **ppsym;	/* Pointer to symbol pointer array */
#if defined(__cplusplus)
		HocStruct cTemplate *ctemplate;
#else
		HocStruct Template *template;
#endif
		HocStruct Symbol* sym;	/* for external */
	} u;
	unsigned   s_varn;	/* dependent variable number - 0 means indep */
	Arrayinfo *arayinfo;	/* ARRAY information if null then scalar */
	HocSymExtension* extra; /* additions to symbol allow compatibility
					with old nmodl dll's */
	HocStruct Symbol	*next;	/* to link to another */
} Symbol;
#define	ISARRAY(arg)	(arg->arayinfo != (Arrayinfo *)0)


#ifndef hoc_list_h
#if defined(__cplusplus)
#define hoc_List struct hoc_Item
#else
typedef struct hoc_Item	hoc_List;
#define List hoc_List
#define Item hoc_Item
#endif
#endif

typedef union Datum {	/* interpreter stack type */
	double	val;
	Symbol	*sym;
	int i;
	double	*pval;	/* first used with Eion in NEURON */
	HocStruct Object **pobj;
	HocStruct Object *obj;	/* sections keep this to construct a name */
	char	**pstr;
	HocStruct hoc_Item* itm;
	hoc_List* lst;
	void* _pvoid;	/* not used on stack, see nrnoc/point.c */
} Datum;

#if OOP
#if defined(__cplusplus)
typedef struct cTemplate {
#else
typedef struct Template {
#endif
	Symbol *sym;
	Symlist *symtable;
	int dataspace_size;
	int is_point_; /* actually the pointtype > 0 if a point process */
	Symbol *init;	/* null if there is no initialization function */
	Symbol *unref;  /* null if there is no function to call when refcount is decremented */
	int index;	/* next  unique integer used for name for section */
	int count;	/* how many of this kind of object */
	hoc_List* olist;	/* list of all instances */
	int id;
	void* observers;	/* hook to c++ ClassObservable */
	void* (*constructor)(struct Object*);
	void (*destructor)(void*);
	void (*steer)(void*);	/* normally nil */
	int (*checkpoint)(void**);
#if defined(__cplusplus)
} cTemplate;
#else
} Template;
#endif

typedef union Objectdata{
	double *pval;	/* pointer to array of doubles, usually just 1 */
	char **ppstr;	/* pointer to pointer to string ,allows vectors someday*/
	HocStruct Object **pobj;	/* pointer to array of object pointers, usually just 1*/
	HocStruct hoc_Item** psecitm;   /* array of pointers to section items, usually just 1 */
	hoc_List** plist;	/* array of pointers to linked lists */
	Arrayinfo* arayinfo;
	void* _pvoid;		/* Point_process */
}Objectdata;

typedef struct Object {
	int refcount;		/* how many object variables point to this */
	int index;		/* unique integer used for names of sections */
	union {
	Objectdata *dataspace;	/* Points to beginning of object's data */
	void* this_pointer;	/* the c++ object */
	}u;
#if defined(__cplusplus)
	cTemplate *ctemplate;
#else
	Template *template;
#endif
	void* aliases;	/* more convenient names for e.g. Vector or List elements dynamically created by this object*/
	HocStruct hoc_Item* itm_me;/* this object in the template list */
	HocStruct hoc_Item* secelm_; /* last of a set of contiguous section_list items used by forall */
	void* observers;	/* hook to c++ ObjObservable */
	short recurse;		/* to stop infinite recursions */
	short unref_recurse_cnt; /* free only after last return from unref callback */
} Object;
#endif

typedef struct {		/* User Functions */
	const char 	*name;
	void	(*func)(void);
} VoidFunc;

typedef struct {		/* User Double Scalars */
	const char 	*name;
	double	*pdoub;
} DoubScal;

typedef struct {		/* User Vectors */
	const char 	*name;
	double	*pdoub;
	int	index1;
} DoubVec;

typedef struct {		/* recommended limits for symbol values */
	const char	*name;
	float	bnd[2];
} HocParmLimits;

typedef struct {		/* recommended tolerance for CVODE */
	const char	*name;
	float tolerance;
} HocStateTolerance;

typedef struct {		/* units for symbol values */
	const char	*name;
	char	*units;
} HocParmUnits;

#include "oc_ansi.h"

extern void* emalloc(size_t n);
extern void* ecalloc(size_t n, size_t size);
extern void* erealloc(void* ptr, size_t n);

extern	Inst *hoc_progp, *hoc_progbase, *hoc_prog, *hoc_prog_parse_recover;
extern Inst *hoc_pc;

extern Objectdata *hoc_objectdata;
extern Objectdata *hoc_top_level_data;
extern Object* hoc_thisobject;
extern Symlist* hoc_symlist;
extern Symlist* hoc_top_level_symlist;
extern Symlist* hoc_built_in_symlist;
extern Objectdata *hoc_objectdata_save(void);
extern Objectdata* hoc_objectdata_restore(Objectdata*);
#define OPVAL(sym) hoc_objectdata[sym->u.oboff].pval
#define OPSTR(sym) hoc_objectdata[sym->u.oboff].ppstr
#define OPOBJ(sym) hoc_objectdata[sym->u.oboff].pobj
#define OPSECITM(sym) hoc_objectdata[sym->u.oboff].psecitm
#define OPLIST(sym) hoc_objectdata[sym->u.oboff].plist
#define OPARINFO(sym) hoc_objectdata[sym->u.oboff + 1].arayinfo

#if LINT
#undef assert
#define assert(arg)	{if (arg) ;}	/* so fprintf doesn't give lint */
#undef IGNORE
#define	IGNORE(arg)	{if(arg);}
#define LINTUSE(arg)	{if(arg);}
char	*cplint;
int	ilint;
#define Strcat          cplint = strcat
#define Strncat         cplint = strncat
#define Strcpy          cplint = strcpy
#define Strncpy         cplint = strncpy
#define Sprintf         cplint = sprintf
#define Printf		ilint = printf
#define Fprintf		ilint = fprintf
#else
#if defined(__TURBOC__)
#undef IGNORE
#define IGNORE
#else
#undef IGNORE
#define IGNORE(arg)	arg
#endif
#define LINTUSE(arg)
#define Strcat          strcat
#define Strncat         strncat
#define Strcpy          strcpy
#define Strncpy         strncpy
#define Sprintf         sprintf
#define Printf		nrnpy_pr
#define Fprintf		fprintf
#endif

/* EINTR handling for LINDA */
#if LINDA
#include <errno.h>
#define ERRCHK(c1) {errno=EINTR;while(errno==EINTR){errno=0;c1}}

#else
#define ERRCHK(c1) c1
#endif

#define IFGUI if (hoc_usegui){
#define ENDGUI }

extern int hoc_usegui; /* when 0 does not make interviews calls */
extern int nrn_istty_;
extern int parallel_sub; /* for use with parallel neuron (see parallel.cl) */

#define NOT_PARALLEL_SUB(c1)  {if (!parallel_sub) c1}

/* Enter handling for PVM  NJP 11/21/94 */
#ifdef PVM
extern int init_parallel( );
int num_procs;
int *tids;
int node_num;
int mytid;
#endif

#if defined(__cplusplus)
}
#endif

#endif
