00001 #ifndef VTCL_H 00002 #define VTCL_H 00003 00004 //#include <sty.h> 00005 #include "common/suif_list.h" 00006 #include "vcommands.h" 00007 #include <tcl.h> 00008 #include <tk.h> 00009 #include <stdlib.h> 00010 #include <string.h> 00011 #include "suifkernel/suifkernel_messages.h" 00012 00013 /* globals */ 00014 00015 extern Tcl_Interp *v_interp; // Visual interpreter 00016 00017 /* 00018 * tcl command interface class 00019 * 00020 */ 00021 #define COMMAND_INCREMENT_SIZE 500 00022 00023 class tcl_terminator { 00024 }; 00025 00026 extern tcl_terminator *tcl_end; // end of tcl command, will call tcl to 00027 // interpret the command 00028 extern char *tcl_0; 00029 00030 class tcl_command { 00031 private: 00032 char *command; // points to current tcl_command (or 0) 00033 int end_command; // offset of the last valid element of string (the 0) 00034 int end_reserved_space; // the first offset past the allocation area 00035 // (all usable offsets have to be smaller) 00036 00037 Tcl_Interp *interp; 00038 00039 protected: 00040 00041 char* reserve_space( int size_to_reserve ) { 00042 // space_remaining can be negative! (in the beginning) 00043 int space_remaining = end_reserved_space - end_command - 1; 00044 if ( size_to_reserve > space_remaining ) { 00045 int increment_size = size_to_reserve < COMMAND_INCREMENT_SIZE ? 00046 COMMAND_INCREMENT_SIZE : size_to_reserve; 00047 end_reserved_space = end_reserved_space + increment_size; 00048 if ( !command ) end_reserved_space++; // space for extra 0 00049 char* new_space = new char[ end_reserved_space ]; 00050 // initialize the new string 00051 if ( command ) { 00052 strcpy( new_space, command ); 00053 } else { 00054 assert( end_command == 0 ); 00055 new_space[0]=0; 00056 } 00057 delete [] command; 00058 command = new_space; 00059 } 00060 suif_assert_message( ( command[end_command]==0 ), ("End of string must be 0" )); 00061 return command+end_command; 00062 } 00063 00064 void reset_string() { 00065 delete [] command; 00066 command = 0; 00067 end_command = 0; 00068 end_reserved_space = 0; 00069 } 00070 00071 public: 00072 tcl_command() { 00073 command = 0; 00074 00075 reset_string(); 00076 00077 interp = 0; 00078 } 00079 00080 ~tcl_command() { 00081 reset_string(); 00082 } 00083 00084 void set_interp(Tcl_Interp *tcl_interp) { 00085 interp = tcl_interp; 00086 } 00087 00088 Tcl_Interp *get_interp(void) { 00089 return interp; 00090 } 00091 00092 /* 00093 * create command 00094 */ 00095 void create_command(char *cmdName, Tcl_CmdProc *proc, 00096 ClientData clientData, 00097 Tcl_CmdDeleteProc *deleteProc) { 00098 Tcl_CreateCommand(interp, cmdName, proc, clientData, deleteProc); 00099 } 00100 00101 int link_var(char *varName, char *addr, int type) { 00102 return (Tcl_LinkVar(interp, varName, addr, type)); 00103 } 00104 void unlink_var(char *varName) { 00105 Tcl_UnlinkVar(interp, varName); 00106 } 00107 00108 /* 00109 * Evaluating tcl command 00110 * 00111 */ 00112 00113 int operator << (const tcl_terminator *) { 00114 assert( command ); 00115 00116 // ATTENTION: This might be invoked recursively!! 00117 // => reinitialize this object before invoking eval 00118 char* current_command = command; 00119 command = 0; 00120 reset_string(); 00121 00122 int result = eval( current_command ); 00123 00124 delete [] current_command; 00125 00126 return result; 00127 } 00128 00129 tcl_command &operator << (const char *string) { 00130 int length = strlen( string ); 00131 char* start = reserve_space( length ); 00132 sprintf( start, "{%s} ", string); 00133 end_command += length + 3; 00134 return *this; 00135 } 00136 tcl_command &operator << (const void *data) { 00137 const int buffer_size = 20; 00138 char buffer[ buffer_size ]; 00139 sprintf( buffer, "%p ", data ); 00140 int len = strlen( buffer ); 00141 suif_assert_message( (len<=buffer_size), ("Pointer to string conversion has unexpected size (too large).\n") ); 00142 strcat( reserve_space( len ), buffer ); 00143 end_command += len; 00144 return *this; 00145 } 00146 tcl_command &operator << (int data) { 00147 const int buffer_size = 40; 00148 char buffer[ buffer_size ]; 00149 sprintf( buffer, "%d ", data ); 00150 int len = strlen( buffer ); 00151 suif_assert_message(( len<=buffer_size), ("Int to string conversion has unexpected size (too large).\n" )); 00152 strcat( reserve_space( len ), buffer ); 00153 end_command += len; 00154 return *this; 00155 } 00156 tcl_command &operator << ( double data ) { 00157 const int buffer_size = 40; 00158 char buffer[ buffer_size ]; 00159 sprintf( buffer, "%f ", data ); 00160 int len = strlen( buffer ); 00161 suif_assert_message( (len<=buffer_size), ("Double to string conversion has unexpected size (too large).\n") ); 00162 strcat( reserve_space( len ), buffer ); 00163 end_command += len; 00164 return *this; 00165 } 00166 int eval(char *string) { 00167 int result = Tcl_Eval(interp, string); 00168 if (result != TCL_OK) { 00169 v_warning("Tcl command `%s': (%d) %s", 00170 string, result, interp->result); 00171 } 00172 return result; 00173 } 00174 int eval_file(char *filename) { 00175 return (Tcl_EvalFile(interp, filename)); 00176 } 00177 00178 /* 00179 * Get results from tcl 00180 */ 00181 00182 int operator >> (int &data) { 00183 data = atoi(interp->result); 00184 return TCL_OK; 00185 } 00186 int operator >> (char *&data) { 00187 strcpy(data, interp->result); 00188 return TCL_OK; 00189 } 00190 int operator >> (void *&data) { 00191 if (sscanf(interp->result, "%p", &data) != 1) { 00192 return TCL_ERROR; 00193 } else { 00194 return TCL_OK; 00195 } 00196 } 00197 char *result() { 00198 return interp->result; 00199 } 00200 00201 /* 00202 * Misc 00203 */ 00204 void print(FILE *fd = stdout) { 00205 fprintf(fd, "%s\n", command ? command : "<NO COMMAND>"); 00206 } 00207 }; 00208 00209 extern tcl_command tcl; 00210 00211 #endif