/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* This file is distributed subject to a Software License Agreement found
* in the file LICENSE that is included with this distribution. 
\*************************************************************************/

/* 
 * $Log: not supported by cvs2svn $
 * Revision 1.7  2005/06/03 21:10:54  soliday
 * Fixed bug when connecting to waveform PVs. The INFOBUF was not a pointer
 * and could not be enlarged by allocating more space.
 *
 * Revision 1.6  2003/09/09 19:22:13  soliday
 * Added the "pv toggleErrorMode" command to work with Tcl catch statements.
 *
 * Revision 1.5  2003/08/08 20:43:58  soliday
 * Updated code so that this is a dynamically loadable extension.
 *
 * Revision 1.4  2002/08/14 20:44:34  soliday
 * Added Open License
 *
 * Revision 1.3  2001/01/16 22:33:25  soliday
 * BLT is no longer required to build this extension.
 *
 * Revision 1.2  2001/01/15 22:16:58  soliday
 * Merged some of the changes from caTCL.
 *
 * Revision 1.1  1999/06/10 19:35:26  soliday
 * Moved to oag tree.
 *
 * Revision 1.4  1999/06/08 20:00:16  soliday
 * Removed compiler warnings under Linux.
 *
 * Revision 1.3  1999/03/18 19:47:38  soliday
 * fixed some bugs with -blunderAhead
 *
 * Revision 1.2  1999/03/17 22:34:44  soliday
 * Added blunderAhead option to tclCaLink.
 *
 * Revision 1.1.1.1  1996/05/07 19:08:38  saunders
 * Imported Files
 *
 *
 *-------------------------------------------------------------------
 * The following is the revision history while in OAG CVS Repository
 *-------------------------------------------------------------------
 * Revision 1.6  1996/04/19 20:09:57  saunders
 * 1. Added "pv unlink" command.
 * 2. Repaired a number of bugs in existing link command. Now permits
 *    multiple linkw on same pv, and behaves better if IOC goes down/up.
 * 3. Changed link command so that ca flushes are done in groups, not
 *    on a channel by channel basis. The only loss is in the specificity
 *    of the error messages when a connect fails.
 * 4. Tcl var is now initialized with pv value upon completion of the link.
 * 5. Removed length limitation on tcl var names supplied to pv commands.
 * 6. Removed repeated free/malloc's when DBR_STRING and DBR_ENUM gets
 *    are performed.
 *
 * Revision 1.5  1996/04/18 20:32:12  saunders
 * 1. Add drvh/drvl options to "pv info" command.
 * 2. Change tclCaHash.c to use Tcl supplied hash table library.
 * 3. Removed more unneeded indirection and variables in structs.
 *
 * Revision 1.4  1996/04/17 15:38:43  saunders
 * 1. Completely modified internal tcl<-->ca type handling. This cleans
 *    up large amounts of code, fixes handling of enum types, and permits
 *    proper use of integers and doubles.
 * 2. Changed "fd activity" callback so it uses MAGIC_POLL value for
 *    pend_event, instead of 1ms wait.
 *
 * Revision 1.3  1996/04/16 14:53:59  saunders
 * 1. Removed unneeded indirection in pv_exists() function.
 * 2. Removed unused vars in chandata struct.
 * 3. Removed doubleValue() function, replacing with copyCaTypeToTclType().
 *    Collapsed redundant code around doubleValue() function.
 * 4. Renamed eventCount to secondMonEvent, and fixed usage of it.
 * 5. Changed updateInterpVar technique, yielding 25% performance improvement,
 *    and less memory fragmentation.
 *
 * Revision 1.2  1996/04/11 19:18:31  saunders
 * 1. Periodic pend_io time from .001 to 1e-9, resulting in poll.
 * 2. Use search_and_connect, not build_and_connect ca call.
 * 3. Removed ca_pend_io calls at end of async functions.
 * 4. Remove redundant call to ca_change_connection_event in updateChCtrl.
 * 5. Removed switch statement from howManyBytes (should be macro).
 * 6. Changed byte-by-byte copies to use memcpy instead.
 * 7. Removed some mixed use of ca_field_type() and iType.
 * 8. Removed redundant clause in if-then-else.
 * 9. Removed hardcoded pend_io timeouts. Use #define now.
 * 10. Removed unused calls to system time().
 * 11. Uppercased and lowercased stuff to follow conventions.
 *
 * Revision 1.1  1996/04/04 23:16:21  saunders
 * Renamed library files, ANSI-fied and reformatted code. Renamed external
 * function names to begin with tclCa library name.
 * */

#include <stdio.h>
#include <string.h>
#include <cadef.h>
#include <db_access.h>
#include <tcl.h>
#if defined(USE_BLT)
#include <tk.h>
#include <blt.h>
#else
#define True 1
#define False 0
#endif

/* Default Channel Access timeout, and magic pend event time for a poll */
#define CA_PEND_IO_TIME 10.0
#define MAGIC_POLL .000000001

typedef union {
  struct dbr_time_string s;
  struct dbr_time_enum   e;
  struct dbr_time_char   c;
  struct dbr_time_short  i;
  struct dbr_time_long   l;
  struct dbr_time_float  f;
  struct dbr_time_double d;
} DATABUF;

typedef union {
  struct dbr_sts_string  s;
  struct dbr_ctrl_enum   e;
  struct dbr_ctrl_char   c;
  struct dbr_ctrl_short  i;
  struct dbr_ctrl_long   l;
  struct dbr_ctrl_float  f;
  struct dbr_ctrl_double d;
} INFOBUF;

typedef union {
  long tclLong;
  double tclDouble;
  char *tclStr;
} TCLDATABUF;

typedef enum {NewConnection,NeverConnected, LostConnection,
	      ReadAccess,WriteAccess, PendIO, ConnectionOK } 
caState;

typedef struct MonScript {
  Tcl_DString script;
  int  number;
} MONSCRIPT;

typedef struct ViewPort {
  int    base;
  int    size;
  int    precision;
} VIEWPORT;
	
typedef struct Item {
  struct Chandata *pchandata;
  char *tclname;
#if defined(USE_BLT)
  char *vecname;
#endif
} ITEM;
	
typedef struct Chandata{
  chid 		chid;
  evid 		evid;
  DATABUF 	*pdata;
  INFOBUF  	*info;
  VIEWPORT	view;
  caState  	castate;
  int	 	countPendIO;
  int     	initSize; 
  int     	dataSize;
  int	 	iType;       /* native ca type of pv               */
  int           tclType;     /* closest tcl type to native ca type */
  int	 	precision; 
  TCLDATABUF    tclValue;
  ITEM		*pitem;
  MONSCRIPT	*pscript;
  int           secondMonEvent;
  int		updateVar;
  Tcl_Interp	*interp;
  int           skip;
  Tcl_ThreadId  parent; /* Thread id of parent thread */
#if defined(USE_BLT)
  double	*pvec;
  Blt_Vector	*vecPtr;
#endif
} CHANDATA;

/***********************/
/* Function Prototypes */
/***********************/
int tclCaStat(Tcl_Interp *interp, char *tclNameList, char *arrayList, int UseCatch);
int tclCaGet(Tcl_Interp *interp, char *tclNameList, 
	     int waitFlag, float pendioTime, int UseCatch);
int tclCaPut(Tcl_Interp *interp, char *tclNameList, int waitFlag,
	     int quickFlag, float pendioTime, int UseCatch);
int tclCaLink(Tcl_Interp *interp, char *tclNameList, char *pvNameList,
	      int waitFlag, float pendioTime, int blunderAhead, int UseCatch);
int tclCaUnLink(Tcl_Interp *interp, char *tclNameList, int UseCatch);
int tclCaExit(Tcl_Interp *interp, int UseCatch);
int tclCaMon(Tcl_Interp *interp, char *tclNameList, 
	     char *pcommand, int updateVar, int UseCatch);
int tclCaCmon(Tcl_Interp *interp, char *tclNameList, int UseCatch);
int tclCaVviewport(Tcl_Interp *interp, char *tclNameList, char *portParmList, int UseCatch);
int tclCaVviewput(Tcl_Interp *interp, char *tclNameList, char *valueList, int UseCatch);
int tclCaVviewget(Tcl_Interp *interp, char *tclNameList, int UseCatch);
int tclCaVdis(Tcl_Interp *interp, char *tclName,
	      char *pathName, char *elemName);
int tclCaInfostate(Tcl_Interp *interp, char *tclNameList, char *pvParmList, int UseCatch);
#if defined(USE_BLT)
int tclCaVmapToVector(Tcl_Interp *interp, char *tclNameList, char *bltNameList, int UseCatch);
#endif

/***********************/
/* tclCaHash functions */
/***********************/
void pv_hash_init();
ITEM *pv_search(char *s);
ITEM *pv_exists(char *s);
void pv_delete(char *s);

