📄 interp.cxx
字号:
} // If we have an error condition that was raised by the Tcl // interpreter rather than by the library, it needs to be // raised up to the library level. That way the error count // etc. are kept accurate. if ((TCL_OK != result) && !cdl_result) { char* tcl_result = Tcl_GetStringResult(tcl_interp); if ((0 == tcl_result) || ('\0' == tcl_result[0])) { tcl_result = "Internal error, no additional information available."; } CdlParse::report_error(this, "", tcl_result); } str_result = Tcl_GetStringResult(tcl_interp); CYG_REPORT_RETVAL(result); return result;}// Ditto for evaluating an entire file.intCdlInterpreterBody::eval_file(std::string script, std::string& str_result){ CYG_REPORT_FUNCNAMETYPE("CdlInterpreter::eval_file", "result %d"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC("" != script); // Distinguish between results set by the Tcl interpreter and results // set by CDL-related commands running in that interpreter. cdl_result = false; int result = Tcl_EvalFile(tcl_interp, const_cast<char*>(script.c_str())); // The distinction between TCL_OK and TCL_RETURN is probably not worth // worrying about. if (TCL_RETURN == result) { result = TCL_OK; } // If we have an error condition that was raised by the Tcl // interpreter rather than by the library, it needs to be // raised up to the library level. That way the error count // etc. are kept accurate. if ((TCL_OK != result) && !cdl_result) { char* tcl_result = Tcl_GetStringResult(tcl_interp); if ((0 == tcl_result) || ('\0' == tcl_result[0])) { tcl_result = "Internal error, no additional information available."; } CdlParse::report_error(this, "", tcl_result); } str_result = Tcl_GetStringResult(tcl_interp); CYG_REPORT_RETVAL(result); return result;}// Variants for when the result string is of no interestintCdlInterpreterBody::eval(std::string script){ std::string result_string; return this->eval(script, result_string);}intCdlInterpreterBody::eval_cdl_code(const cdl_tcl_code script){ std::string result_string; return this->eval_cdl_code(script, result_string);}intCdlInterpreterBody::eval_file(std::string filename){ std::string result_string; return this->eval_file(filename, result_string);}//}}}//{{{ CdlInterpreter:: set_result() // ----------------------------------------------------------------------------// Provide a way of setting an interpreter's result from a command implemented// in C++.voidCdlInterpreterBody::set_result(std::string result){ CYG_REPORT_FUNCNAME("CdlInterpreter::set_result"); CYG_PRECONDITION_THISC(); Tcl_SetResult(tcl_interp, const_cast<char*>(result.c_str()), TCL_VOLATILE); this->cdl_result = true; CYG_REPORT_RETURN();}boolCdlInterpreterBody::result_set_by_cdl(){ CYG_REPORT_FUNCNAMETYPE("CdlInterpreter::result_set_by_cdl", "result %d"); CYG_PRECONDITION_THISC(); bool result = this->cdl_result; CYG_REPORT_RETVAL(result); return result;}// ----------------------------------------------------------------------------// Also allow the result to be extracted again.std::stringCdlInterpreterBody::get_result(){ CYG_REPORT_FUNCNAME("CdlInterpreter::get_result"); CYG_PRECONDITION_THISC(); std::string result = Tcl_GetStringResult(tcl_interp); CYG_REPORT_RETURN(); return result;}//}}}//{{{ CdlInterpreter:: add and remove commands // ----------------------------------------------------------------------------// This is the Tcl command proc that gets used for all CdlInterpreter// commands. The ClientData field will be a CdlInterpreterCommand,// i.e. a function pointer. That function needs a pointer to the// CdlInterpreter object, which can be accessed via AssocData.intCdlInterpreterBody::tcl_command_proc(ClientData data, Tcl_Interp* tcl_interp, int argc, char* argv[]){ CYG_REPORT_FUNCNAMETYPE("CdlInterpreter::tcl_command_proc", "result %d"); CYG_REPORT_FUNCARG3XV(data, tcl_interp, argc); CYG_PRECONDITIONC(0 != data); int result = TCL_OK; union { ClientData data; CdlInterpreterCommand command; } x; x.data = data; CdlInterpreterCommand command = x.command; data = Tcl_GetAssocData(tcl_interp, cdlinterpreter_assoc_data_key, 0); CdlInterpreter interp = static_cast<CdlInterpreter>(data); CYG_ASSERT_CLASSC(interp); try { result = (*command)(interp, argc, argv); } catch(std::bad_alloc e) { interp->set_result(CdlParse::construct_diagnostic(interp, "internal error", "", "Out of memory.")); result = TCL_ERROR; } catch(CdlStringException e) { interp->set_result(e.get_message()); result = TCL_ERROR; } catch(...) { CYG_FAIL("Unexpected C++ exception"); interp->set_result(CdlParse::construct_diagnostic(interp, "internal error", "", "Unexpected C++ exception.")); result = TCL_ERROR; } CYG_REPORT_RETVAL(result); return result;}voidCdlInterpreterBody::add_command(std::string name, CdlInterpreterCommand command){ CYG_REPORT_FUNCNAME("CdlInterpreter::add_command"); CYG_REPORT_FUNCARG2XV(this, command); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC("" != name); CYG_CHECK_FUNC_PTRC(command); union { CdlInterpreterCommand command; ClientData data; } x; x.command = command; if (0 == Tcl_CreateCommand(tcl_interp, const_cast<char*>(name.c_str()), &tcl_command_proc, x.data, 0)) { throw std::bad_alloc(); } CYG_REPORT_RETURN();}// ----------------------------------------------------------------------------// Remove a command from an interpreter. This is just a wrapper for the// Tcl_DeleteCommand() routine.voidCdlInterpreterBody::remove_command(std::string name){ CYG_REPORT_FUNCNAME("CdlInterpreter::remove_command"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC("" != name); if (0 != Tcl_DeleteCommand(tcl_interp, const_cast<char*>(name.c_str()))) { CYG_FAIL("attempt to delete non-existant command"); } CYG_REPORT_RETURN();}// ----------------------------------------------------------------------------// It is also possible to add and remove whole sets of commands in one go,// keeping track of the current set.std::vector<CdlInterpreterCommandEntry>*CdlInterpreterBody::push_commands(std::vector<CdlInterpreterCommandEntry>& new_commands){ CYG_REPORT_FUNCNAMETYPE("CdlInterpreter::push_commands", "result %p"); CYG_REPORT_FUNCARG2XV(this, &new_commands); CYG_PRECONDITION_THISC(); std::vector<CdlInterpreterCommandEntry>* result = current_commands; std::vector<CdlInterpreterCommandEntry>::iterator i; // First uninstall all the old commands, if any if (0 != current_commands) { for (i = current_commands->begin(); i != current_commands->end(); i++) { remove_command(i->name); } } // Now install the new commands for (i = new_commands.begin(); i != new_commands.end(); i++) { add_command(i->name, i->command); } // Remember the current set in case of a subsequent push operation current_commands = &new_commands; CYG_REPORT_RETVAL(result); return result;}voidCdlInterpreterBody::pop_commands(std::vector<CdlInterpreterCommandEntry>* original_commands){ CYG_REPORT_FUNCNAME("CdlInterpreter::pop_commands"); CYG_REPORT_FUNCARG2XV(this, &original_commands); CYG_PRECONDITION_THISC(); CYG_PRECONDITION(0 != current_commands, "no pop without a previous push please"); std::vector<CdlInterpreterCommandEntry>::iterator i; // Uninstall the most recent set of commands for (i = current_commands->begin(); i != current_commands->end(); i++) { remove_command(i->name); } // Reinstall the previous set, if any if (0 != original_commands) { for (i = original_commands->begin(); i != original_commands->end(); i++) { add_command(i->name, i->command); } } current_commands = original_commands; CYG_REPORT_RETURN();}std::vector<CdlInterpreterCommandEntry>*CdlInterpreterBody::get_pushed_commands() const{ CYG_REPORT_FUNCNAME("CdlInterpreter::get_pushed_commands"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CYG_REPORT_RETURN(); return current_commands;}//}}}//{{{ CdlInterpreter:: variables // ----------------------------------------------------------------------------// Provide some more stubs, this time for accessing Tcl global variables.voidCdlInterpreterBody::set_variable(std::string name, std::string value){ CYG_REPORT_FUNCNAME("CdlInterpreter::set_variable"); CYG_REPORT_FUNCARG2("this %p, name %s", this, name.c_str()); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC("" != name); if (0 == Tcl_SetVar(tcl_interp, const_cast<char*>(name.c_str()), const_cast<char*>(value.c_str()), TCL_GLOBAL_ONLY)) { throw std::bad_alloc(); } CYG_REPORT_RETURN();}voidCdlInterpreterBody::unset_variable(std::string name){ CYG_REPORT_FUNCNAME("CdlInterpreter::unset_variable"); CYG_REPORT_FUNCARG2("this %p, name %s", this, name.c_str()); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC("" != name); Tcl_UnsetVar(tcl_interp, const_cast<char*>(name.c_str()), TCL_GLOBAL_ONLY); CYG_REPORT_RETURN();}std::stringCdlInterpreterBody::get_variable(std::string name){ CYG_REPORT_FUNCNAME("CdlInterpreter::get_variable"); CYG_REPORT_FUNCARG2("this %p, name %s", this, name.c_str()); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC("" != name); std::string result = ""; char *tmp = Tcl_GetVar(tcl_interp, const_cast<char*>(name.c_str()), TCL_GLOBAL_ONLY); if (0 != tmp) { result = tmp; } CYG_REPORT_RETURN(); return result;}//}}}//{{{ CdlInterpreter:: assoc data // ----------------------------------------------------------------------------// Associated data. It is useful to be able to store some C++ data with// Tcl interpreters, so that the implementations of various commands// can retrieve details of the current state. Tcl provides the necessary// underlying support via routines Tcl_SetAssocData() etc., and the// routines here are just stubs for the underlying Tcl ones.voidCdlInterpreterBody::set_assoc_data(const char* key, ClientData data, Tcl_InterpDeleteProc* del_proc){ CYG_REPORT_FUNCNAME("CdlInterpreter::set_assoc_data"); CYG_REPORT_FUNCARG3("this %p, key %s, data %p", this, key, data); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC((0 != key) && ('\0' != key[0])); Tcl_SetAssocData(tcl_interp, const_cast<char*>(key), del_proc, data); CYG_REPORT_RETURN();}ClientDataCdlInterpreterBody::get_assoc_data(const char* key){ CYG_REPORT_FUNCNAMETYPE("CdlInterpreter::get_assoc_data", "result %p"); CYG_REPORT_FUNCARG2("this %p, key %s", this, key); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC((0 != key) && ('\0' != key[0])); ClientData result = Tcl_GetAssocData(tcl_interp, const_cast<char*>(key), 0); CYG_REPORT_RETVAL(result); return result;}voidCdlInterpreterBody::delete_assoc_data(const char* key){ CYG_REPORT_FUNCNAME("CdlInterpreter::delete_assoc_data"); CYG_REPORT_FUNCARG2("this %p, key %s", this, key); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC((0 != key) && ('\0' != key[0])); Tcl_DeleteAssocData(tcl_interp, const_cast<char*>(key)); CYG_REPORT_RETURN();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -