00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef _OASYS_TCL_COMMAND_H_
00039 #define _OASYS_TCL_COMMAND_H_
00040
00041 #include <list>
00042 #include <map>
00043 #include <string>
00044
00045 #include <stdarg.h>
00046 #include <tcl.h>
00047
00048 #include <netinet/in.h>
00049
00050 #include "../compat/inttypes.h"
00051 #include "../debug/DebugUtils.h"
00052 #include "../util/Singleton.h"
00053 #include "../util/StringBuffer.h"
00054
00055 namespace oasys {
00056
00057
00058 class TclCommandInterp;
00059 class TclCommand;
00060 class Lock;
00061
00065 typedef std::list<TclCommand*> TclCommandList;
00066
00073 class TclCommandInterp : public Logger {
00074 public:
00080 static TclCommandInterp* instance() {
00081 ASSERT(instance_ != NULL);
00082 return instance_;
00083 }
00084
00088 static int init(char* objv0, bool no_default_cmds = false);
00089
00093 static void shutdown();
00094
00099 int exec_file(const char* file);
00100
00106 int exec_command(const char* command);
00107
00111 void command_server(const char* prompt, in_addr_t addr, u_int16_t port);
00112
00116 void command_loop(const char* prompt);
00117
00121 void event_loop();
00122
00127 void exit_event_loop();
00128
00138 static int tcl_cmd(ClientData client_data, Tcl_Interp* interp,
00139 int objc, Tcl_Obj* const* objv);
00140
00144 void reg(TclCommand* module);
00145
00151 bool lookup(const char* command, TclCommand** commandp = NULL);
00152
00158 static void auto_reg(TclCommand* module);
00159
00163 void reg_atexit(void(*fn)(void*), void* data);
00164
00168 void set_result(const char* result);
00169
00173 void set_objresult(Tcl_Obj* obj);
00174
00178 void append_result(const char* result);
00179
00183 void resultf(const char* fmt, ...) PRINTFLIKE(2, 3);
00184
00188 void append_resultf(const char* fmt, ...) PRINTFLIKE(2, 3);
00189
00193 void vresultf(const char* fmt, va_list ap, bool append);
00194
00205 void wrong_num_args(int objc, const char** objv, int parsed,
00206 int min, int max);
00207
00218 void wrong_num_args(int objc, Tcl_Obj** objv, int parsed,
00219 int min, int max);
00220
00224 const char* get_result();
00225
00229 const TclCommandList* commands() { return &commands_; }
00230
00231 protected:
00235 TclCommandInterp();
00236
00240 int do_init(char* objv0, bool no_default_cmds);
00241
00245 ~TclCommandInterp();
00246
00247 Lock* lock_;
00248 Tcl_Interp* interp_;
00249
00250 TclCommandList commands_;
00251 static TclCommandList* auto_reg_;
00252
00253 static TclCommandInterp* instance_;
00254 };
00255
00265 class TclCommand : public Logger {
00266 public:
00273 TclCommand(const char* name, const char* theNamespace = 0);
00274 virtual ~TclCommand();
00275
00285 virtual int exec(int objc, Tcl_Obj** objv, Tcl_Interp* interp);
00286
00296 virtual int exec(int argc, const char** argv, Tcl_Interp* interp);
00297
00304 virtual int cmd_info(Tcl_Interp* interp);
00305
00315 virtual int cmd_set(int objc, Tcl_Obj** objv, Tcl_Interp* interp);
00316
00320 const char* name() const { return name_.c_str(); }
00321
00325 virtual const char* help_string() { return help_.c_str(); }
00326
00330 bool hasBindings() { return ! bindings_.empty(); }
00331
00332 protected:
00333 friend class TclCommandInterp;
00334
00335 std::string name_;
00336 StringBuffer help_;
00337 bool do_builtins_;
00338
00339
00343 enum type_t {
00344 BINDING_INVALID = -1,
00345 BINDING_INT = 1,
00346 BINDING_INT16,
00347 BINDING_DOUBLE,
00348 BINDING_BOOL,
00349 BINDING_STRING,
00350 BINDING_ADDR
00351 };
00352
00356 struct Binding {
00357 Binding(type_t type, void* val)
00358 : type_(type)
00359 {
00360 val_.voidval_ = val;
00361 }
00362
00363 type_t type_;
00364
00365 union {
00366 void* voidval_;
00367 int* intval_;
00368 int16_t* int16val_;
00369 double* doubleval_;
00370 bool* boolval_;
00371 in_addr_t* addrval_;
00372 std::string* stringval_;
00373 } val_;
00374 };
00375
00379 typedef std::map<std::string, Binding*> BindingTable;
00380
00384 BindingTable bindings_;
00385
00389 void bind_i(const char* name, int* val, const char *help = NULL);
00390 void bind_i(const char* name, int* val, int initval,
00391 const char* help = NULL);
00392
00396 void bind_i(const char* name, int16_t* val, const char *help = NULL);
00397 void bind_i(const char* name, int16_t* val, int16_t initval,
00398 const char* help = NULL);
00399
00401
00404 void bind_i(const char* name, unsigned int* val,
00405 const char* help = NULL)
00406 {
00407 bind_i(name, (int*)val, help);
00408 }
00409
00410 void bind_i(const char* name, unsigned int* val, unsigned int initval,
00411 const char* help = NULL)
00412 {
00413 bind_i(name, (int*)val, initval, help);
00414 }
00415
00416 void bind_i(const char* name, u_int16_t* val,
00417 const char* help = NULL)
00418 {
00419 bind_i(name, (int16_t*)val, help);
00420 }
00421
00422 void bind_i(const char* name, u_int16_t* val, u_int16_t initval,
00423 const char* help = NULL)
00424 {
00425 bind_i(name, (int16_t*)val, initval, help);
00426 }
00427
00429
00433 void bind_d(const char* name, double* val, const char* help = NULL);
00434 void bind_d(const char* name, double* val, double initval,
00435 const char* help = NULL);
00436
00440 void bind_b(const char* name, bool* val, const char* help = NULL);
00441 void bind_b(const char* name, bool* val, bool initval,
00442 const char* help = NULL);
00443
00447 void bind_s(const char* name, std::string* str,
00448 const char* initval, const char* help);
00449
00450 void bind_s(const char* name, std::string* str,
00451 const char* help = NULL)
00452 {
00453 return bind_s(name, str, NULL, help);
00454 }
00455
00460 void bind_addr(const char* name, in_addr_t* addrp,
00461 const char* help = NULL);
00462 void bind_addr(const char* name, in_addr_t* addrp,
00463 in_addr_t initval, const char* help = NULL);
00464
00468 void unbind(const char* name);
00469
00473 void set_result(const char* result)
00474 {
00475 TclCommandInterp::instance()->set_result(result);
00476 }
00477
00481 void set_objresult(Tcl_Obj* obj)
00482 {
00483 TclCommandInterp::instance()->set_objresult(obj);
00484 }
00485
00489 void append_result(const char* result)
00490 {
00491 TclCommandInterp::instance()->append_result(result);
00492 }
00493
00497 void resultf(const char* fmt, ...) PRINTFLIKE(2, 3);
00498
00502 void append_resultf(const char* fmt, ...) PRINTFLIKE(2, 3);
00503
00514 void wrong_num_args(int objc, const char** objv, int parsed,
00515 int min, int max)
00516 {
00517 TclCommandInterp::instance()->
00518 wrong_num_args(objc, objv, parsed, min, max);
00519 }
00520
00531 void wrong_num_args(int objc, Tcl_Obj** objv, int parsed,
00532 int min, int max)
00533 {
00534 TclCommandInterp::instance()->
00535 wrong_num_args(objc, objv, parsed, min, max);
00536 }
00537
00542 void add_to_help(const char* subcmd, const char* help_str)
00543 {
00544 help_.appendf("%s %s\n", name(), subcmd);
00545 if (help_str) {
00546 help_.appendf("\t%s\n", help_str);
00547 }
00548 help_.append("\n");
00549 }
00550 };
00551
00555 class AutoTclCommand : public TclCommand {
00556 public:
00557 AutoTclCommand(const char* name, const char* theNamespace = 0)
00558 : TclCommand(name, theNamespace)
00559 {
00560 TclCommandInterp::auto_reg(this);
00561 }
00562 };
00563
00564 }
00565
00566 #endif