\subsection{Tcl Drivable Interface} This is a module which allows to override or specify a drivable interface through Tcl procedures. The corresponding member function of the drivable interface will be replaced by a function which does the following things: \begin{itemize} \item Given the object pointer as key, it will find a data structure which holds the name of the Tcl procedure to invoke and a user specified name (general to this interface) which the Tcl procedure can use in order to locate instance specific data. \item With this data, a Tcl command is constructed. \item This Tcl command is then invoked. \item Suitable Tcl commands return the numeric equivalents of the HW* codes returned by the equivalent ANSII C functions. \end{itemize} Overrriding a drivable interface functions is done by a call like: \begin{verbatim} DrivableTclReplace objectName functionName tclReplaceProcedure tclName \end{verbatim} In order to implement a drivable completely in Tcl, create an empty object with MakeTclInt and assign functions with DrivableTclReplace. Please note that SICS will die if any of the required functions is left out! The first thing needed in order to implement this scheme is a data structure holding the necessary information. This data structure also doubles as an entry into the dictionary for mapping object pointers to the corresponding data structure. This dictionary is implemented on top of the general linked list package used within SICS. The index to this linked list is kept as a module static within the implementation file for this object. This is also where the original for this data structure is placed. \begin{verbatim} struct{ void *objectPointer; char *tclName; char *tclHalt; char *tclCheckLimits; char *tclSetValue; char *tclCheckStatus; char *tclGetValue; }TclDrivable, *pTclDrivable; \end{verbatim} The fields in this data structure: \begin{description} \item[objectPointer] A pointer to the SICS object this overloaded interface belongs to. Also used as key in searches. \item[tclName] The name passed over to the Tcl procedures in order to allow them to find application specific data. \item[tclHalt] A replacement Halt Tcl script. \item[tclCheckLimits] A Tcl script for replacing the CheckLimits function. \item[tclSetvalue] A replacement for the Setvalue function. \item[tclCheckStatus] a replacement for the CheckStatus function. \item[tclGetValue] a replacement for the GetValue function. \end{description} The interface of this module to SICS is mainly its interpreter functions. In order to allow for configuring Tcl functions from C a function is provided. @o tcldrivable.h @{ /*----------------------------------------------------------------------- The code in this file allows to override or define Drivable interfaces through tcl scripts. More more details, see tcldrivable.tex copyright: see file COPYRIGHT Mark Koennecke, September 2003 ----------------------------------------------------------------------*/ #ifndef SICSTCLDRIVABLE #define SICSTCLDRIVABLE /* Function codes for functionIndex */ #define TCLHALT 1 #define TCLCHECK 2 #define TCLSET 3 #define TCLSTATUS 4 #define TCLGET 5 /* This installs a Tcl replacement for a drivable function */ int TclReplaceDrivable(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); /* This allows to invoke a replaced function for debugging purposes */ int TclDrivableInvoke(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); /* This is for use from C */ int replaceDrivableByTcl(void *sicsObject, int functionIndex, char *scriptName, char *tclName); /* map name to a functionIndex for use in replaceDrivableByTcl. Returns 0 on failure, a usefule index > 0 in the case of success */ int mapDrivableFunctionNames(char *name); /* This is called from StopServer/nserver.c in order to remove all memory related to this class */ void killTclDrivable(void); #endif @}