00001 // -*- C++ -*- 00002 /*************************************************************************** 00003 * 00004 * The IPPL Framework 00005 * 00006 * This program was prepared by PSI. 00007 * All rights in the program are reserved by PSI. 00008 * Neither PSI nor the author(s) 00009 * makes any warranty, express or implied, or assumes any liability or 00010 * responsibility for the use of this software 00011 * 00012 * Visit http://www.acl.lanl.gov/POOMS for more details 00013 * 00014 ***************************************************************************/ 00015 00016 // -*- C++ -*- 00017 /*************************************************************************** 00018 * 00019 * The IPPL Framework 00020 * 00021 * 00022 * Visit http://people.web.psi.ch/adelmann/ for more details 00023 * 00024 ***************************************************************************/ 00025 00026 #include "aclvis/InterpTcl.h" 00027 #ifdef IPPL_USE_STANDARD_HEADERS 00028 #include <iostream> 00029 #include <fstream> 00030 using namespace std; 00031 #else 00032 #include <iostream.h> 00033 #include <fstream.h> 00034 #endif 00035 #include <stdio.h> 00036 #include <stdlib.h> 00037 #include <unistd.h> 00038 #include <string.h> 00039 #include <tcl.h> 00040 00041 00043 // the callback function used by all tcl commands, which will call the 00044 // the virtual function "process" in the proper InterpCmd object 00045 int TclCallback(ClientData data, Tcl_Interp *interp, int argc, char *argv[]) { 00046 // recast the clientdata back to an InterpCmd, which it must be 00047 InterpCmd *cmd = static_cast<InterpCmd *>(data); 00048 00049 // invoke the virtual function 'process' in this InterpCmd, which will 00050 // then do the actual work for this command. Give it the argc, argv, and 00051 // an integer status variable. It should return a pointer to a string 00052 // with the return value for the command. 00053 bool status; 00054 char *infobuf = cmd->process(argc, argv, status); 00055 00056 // since this is Tcl, put this return information in Tcl structures. 00057 if (infobuf != 0 && *infobuf != 0) { 00058 cout << infobuf << endl; 00059 Tcl_SetResult(interp, infobuf, TCL_STATIC); 00060 } 00061 00062 // and then return the proper error code 00063 return (status ? TCL_OK : TCL_ERROR); 00064 } 00065 00066 00068 // constructor 00069 InterpTcl::InterpTcl(const char *nm) : Interp(nm) { 00070 // create a new TCL interpreter context 00071 interp = Tcl_CreateInterp(); 00072 } 00073 00074 00076 // destructor 00077 InterpTcl::~InterpTcl() { 00078 // shut down the interpreter 00079 Tcl_DeleteInterp(interp); 00080 } 00081 00082 00084 // Add a new command callback to the interpreter, by providing a InterpCmd. 00085 void InterpTcl::addCommand(InterpCmd &cmd) { 00086 // create a new command - set the callback to TclCallback, and the 00087 // clientdata to the given cmd, so that when the callback is called, 00088 // it can find the context for this new command 00089 Tcl_CreateCommand(interp, cmd.name(), TclCallback, 00090 static_cast<ClientData>(&cmd), 0); 00091 } 00092 00093 00095 // Take the given string and have the interpreter evaluate it as a command. 00096 // Return true if OK, false if an error occurred. 00097 bool InterpTcl::evalCommand(const char *cmdstr) { 00098 // make sure we have something to do 00099 if (cmdstr == 0 || *cmdstr == 0) 00100 return true; 00101 00102 // evaluate the command string using TCL 00103 char *buf = new char[strlen(cmdstr) + 1]; 00104 strcpy(buf, cmdstr); 00105 int code = Tcl_Eval(interp, buf); 00106 00107 // print out the result, if possible 00108 if (*(interp->result) != 0) 00109 cout << interp->result << endl; 00110 00111 // and return if there was an error 00112 delete [] buf; 00113 return (code == TCL_OK); 00114 } 00115 00116 00118 // Bind a given variable to the given string variable name ... modifying 00119 // the interpreter variable should then modify the bound variable. 00120 // This is available for integer and double variables. 00121 void InterpTcl::bindVar(const char *cmdstr, int &myvar) { 00122 Tcl_LinkVar(interp, const_cast<char *>(cmdstr) , 00123 reinterpret_cast<char *>(&myvar), TCL_LINK_INT); 00124 } 00125 00126 00128 // Bind a given variable to the given string variable name ... modifying 00129 // the interpreter variable should then modify the bound variable. 00130 // This is available for integer and double variables. 00131 void InterpTcl::bindVar(const char *cmdstr, double &myvar) { 00132 Tcl_LinkVar(interp, const_cast<char *>(cmdstr) , 00133 reinterpret_cast<char *>(&myvar), TCL_LINK_DOUBLE); 00134 } 00135 00136 00137 /*************************************************************************** 00138 * $RCSfile: InterpTcl.cpp,v $ $Author: adelmann $ 00139 * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:34 $ 00140 * IPPL_VERSION_ID: $Id: InterpTcl.cpp,v 1.1.1.1 2003/01/23 07:40:34 adelmann Exp $ 00141 ***************************************************************************/