00001 /** @file tcl/command.h binds a wrapped c++ function to a 00002 tcl::arg_spec and a tcl::dispatcher */ 00003 00004 /////////////////////////////////////////////////////////////////////// 00005 // 00006 // Copyright (c) 1999-2004 California Institute of Technology 00007 // Copyright (c) 2004-2007 University of Southern California 00008 // Rob Peters <rjpeters at usc dot edu> 00009 // 00010 // created: Fri Jun 11 14:50:43 1999 00011 // commit: $Id: command.h 11876 2009-10-22 15:53:06Z icore $ 00012 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/tcl/command.h $ 00013 // 00014 // -------------------------------------------------------------------- 00015 // 00016 // This file is part of GroovX 00017 // [http://ilab.usc.edu/rjpeters/groovx/] 00018 // 00019 // GroovX is free software; you can redistribute it and/or modify it 00020 // under the terms of the GNU General Public License as published by 00021 // the Free Software Foundation; either version 2 of the License, or 00022 // (at your option) any later version. 00023 // 00024 // GroovX is distributed in the hope that it will be useful, but 00025 // WITHOUT ANY WARRANTY; without even the implied warranty of 00026 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00027 // General Public License for more details. 00028 // 00029 // You should have received a copy of the GNU General Public License 00030 // along with GroovX; if not, write to the Free Software Foundation, 00031 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00032 // 00033 /////////////////////////////////////////////////////////////////////// 00034 00035 #ifndef GROOVX_TCL_COMMAND_H_UTC20050628162421_DEFINED 00036 #define GROOVX_TCL_COMMAND_H_UTC20050628162421_DEFINED 00037 00038 #include "tcl/argspec.h" 00039 #include "tcl/conversions.h" 00040 #include "tcl/obj.h" 00041 00042 #include "rutz/shared_ptr.h" 00043 00044 typedef struct Tcl_Obj Tcl_Obj; 00045 00046 namespace rutz 00047 { 00048 class file_pos; 00049 class fstring; 00050 template <class T> class shared_ptr; 00051 } 00052 00053 namespace tcl 00054 { 00055 class arg_spec; 00056 class function; 00057 class command; 00058 class call_context; 00059 class arg_dispatcher; 00060 class interpreter; 00061 } 00062 00063 /// Abstract interface for the core function to be embedded in a tcl::command. 00064 class tcl::function 00065 { 00066 public: 00067 virtual ~function() throw(); 00068 00069 /// Abstract function performs this command's specific functionality. 00070 /** The \c tcl::call_context& argument allows Tcl command arguments 00071 to be retrieved, and allows the interpreter's result to be 00072 set.*/ 00073 virtual void invoke(tcl::call_context& ctx) = 0; 00074 }; 00075 00076 /////////////////////////////////////////////////////////////////////// 00077 /** 00078 * 00079 * \c tcl::command provides a way to wrap Tcl commands in C++ 00080 * classes. The \c tcl::command class itself takes care of such things 00081 * as checking the argument count, and issuing an error message if the 00082 * argument count is incorrect. 00083 * 00084 * \c tcl::command uses class \c tcl::call_context to represent the 00085 * set of Tcl command arguments and the interpreter's result. 00086 * 00087 * If more than one tcl::command is created with the same name, an 00088 * overloading sequence is created. Overloading is done by argument 00089 * counts. The first tcl::command in an overload sequence to match the 00090 * argument count of the context will be used. 00091 * 00092 * Most clients of tcl::command will be able to simply use 00093 * tcl::make_command() or tcl::make_vec_command(), which detect the 00094 * types of C++ functions and build generic tcl::command's that call 00095 * the functions appropriately, or use tcl::pkg::def() and related 00096 * functions, which call tcl::make_command() but in addition help to 00097 * relate the commands to a particular package. 00098 * 00099 **/ 00100 /////////////////////////////////////////////////////////////////////// 00101 00102 class tcl::command 00103 { 00104 public: 00105 /// Build a tcl::command object. 00106 /** BUT, you almost certainly don't want to use this function 00107 directly, but should instead call tcl::command_group::make(). If 00108 you just create a tcl::command on its own, it won't do anything 00109 (it won't be registered with the tcl interpreter). The 00110 tcl::command needs to be hooked into a tcl::command_group, and 00111 the way to do that is by creating it through 00112 tcl::command_group::make(). */ 00113 command(rutz::shared_ptr<tcl::function> callback, 00114 const char* usage, const arg_spec& spec); 00115 00116 /// Non-virtual destructor since this class is not for use as a base class. 00117 ~command() throw(); 00118 00119 /// Returns a string describing the arguments expected by this command. 00120 rutz::fstring usage_string() const; 00121 00122 /// Check if the given argument count is acceptable. 00123 bool allows_argc(unsigned int objc) const; 00124 00125 /// Check if the given argument count is unacceptable. 00126 bool rejects_argc(unsigned int objc) const; 00127 00128 /// Send arguments to its tcl::function via its tcl::arg_dispatcher. 00129 void call(tcl::interpreter& interp, 00130 unsigned int objc, Tcl_Obj* const objv[]); 00131 00132 /// Get the current tcl::arg_dispatcher for this command. 00133 rutz::shared_ptr<arg_dispatcher> get_dispatcher() const; 00134 00135 /// Change the tcl::arg_dispatcher for this command. 00136 void set_dispatcher(rutz::shared_ptr<arg_dispatcher> dpx); 00137 00138 private: 00139 command(const command&); // not implemented 00140 command& operator=(const command&); // not implemented 00141 00142 class impl; 00143 impl* const rep; 00144 }; 00145 00146 /////////////////////////////////////////////////////////////////////// 00147 /** 00148 * 00149 * \c tcl::arg_dispatcher. This may be subclassed in order to provide 00150 * a different interface to the raw Tcl arguments (such as for 00151 * vectorizing a function over a set of arguments). The default 00152 * dispatcher used by tcl::command's implementation just sets up a \c 00153 * tcl::call_context and calls \a invoke(). Errors should be signaled 00154 * by throwing appropriate exceptions, which will be caught and 00155 * returned back to the Tcl interpreter as normal Tcl error messages. 00156 * 00157 **/ 00158 /////////////////////////////////////////////////////////////////////// 00159 00160 class tcl::arg_dispatcher 00161 { 00162 public: 00163 /// Virtual destructor. 00164 virtual ~arg_dispatcher() throw(); 00165 00166 /** Interprets the Tcl_Obj* arguments, sets up an appropriate 00167 tcl::call_context, and calls invoke() on the \a cmd with that 00168 context. */ 00169 virtual void dispatch(tcl::interpreter& interp, 00170 unsigned int objc, Tcl_Obj* const objv[], 00171 tcl::function& callback) = 0; 00172 }; 00173 00174 /////////////////////////////////////////////////////////////////////// 00175 /** 00176 * 00177 * \c tcl::call_context, which is passed to \a tcl::command::invoke(), 00178 * provides a get_arg() for getting values from command arguments, and 00179 * provides set_result() for returning values to the Tcl interpreter. 00180 * 00181 **/ 00182 /////////////////////////////////////////////////////////////////////// 00183 00184 class tcl::call_context 00185 { 00186 public: 00187 friend class tcl::command; 00188 00189 /// Construct with a Tcl interpreter and an argument list. 00190 call_context(tcl::interpreter& interp, 00191 unsigned int objc, Tcl_Obj* const* objv); 00192 00193 /// Virtual destructor. 00194 virtual ~call_context() throw(); 00195 00196 /// Get the Tcl interpreter of the current invocation. 00197 tcl::interpreter& interp() const throw() { return m_interp; } 00198 00199 /// Return the number of arguments in the current invocation. 00200 unsigned int objc() const throw() { return m_objc; } 00201 00202 00203 /** Attempt to convert argument number \a argn to type \c T, and 00204 return the result of the conversion. */ 00205 template <class T> 00206 typename returnable<T>::type get_arg(unsigned int argn) 00207 { 00208 return tcl::convert_to<T>(get_objv(argn)); 00209 } 00210 00211 00212 /// Return satisfactorily with the result \a t of type \c T. 00213 template <class T> 00214 void set_result(T t) 00215 { 00216 set_obj_result(tcl::convert_from<T>(t)); 00217 } 00218 00219 /// Get the raw objv array. 00220 Tcl_Obj* const* get_raw_args() const throw() 00221 { 00222 return m_objv; 00223 } 00224 00225 protected: 00226 /// Get the n'th argument. 00227 virtual Tcl_Obj* get_objv(unsigned int n) throw() { return m_objv[n]; } 00228 00229 /// Return a Tcl_Obj*. 00230 virtual void set_obj_result(const tcl::obj& obj); 00231 00232 private: 00233 call_context(const call_context&); 00234 call_context& operator=(const call_context&); 00235 00236 tcl::interpreter& m_interp; 00237 unsigned int const m_objc; 00238 Tcl_Obj* const* const m_objv; 00239 }; 00240 00241 static const char __attribute__((used)) vcid_groovx_tcl_command_h_utc20050628162421[] = "$Id: command.h 11876 2009-10-22 15:53:06Z icore $ $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/tcl/command.h $"; 00242 #endif // !GROOVX_TCL_COMMAND_H_UTC20050628162421_DEFINED