📄 interp.cxx
字号:
voidCdlInterpreterBody::set_transaction(CdlTransaction new_transaction){ CYG_REPORT_FUNCNAME("CdlInterpreter::set_transaction"); CYG_REPORT_FUNCARG2XV(this, new_transaction); CYG_PRECONDITION_THISC(); CYG_PRECONDITION_ZERO_OR_CLASSC(new_transaction); transaction = new_transaction; CYG_REPORT_RETURN();}CdlContainerCdlInterpreterBody::push_container(CdlContainer new_container){ CYG_REPORT_FUNCNAMETYPE("CdlInterpreter::push_container", "result %p"); CYG_REPORT_FUNCARG2XV(this, new_container); CYG_PRECONDITION_THISC(); CYG_PRECONDITION_CLASSC(new_container); CdlContainer result = container; container = new_container; CYG_REPORT_RETVAL(result); return result;}voidCdlInterpreterBody::pop_container(CdlContainer old_container){ CYG_REPORT_FUNCNAME("CdlInterpreter::pop_container"); CYG_REPORT_FUNCARG2XV(this, old_container); CYG_PRECONDITION_THISC(); CYG_PRECONDITION_ZERO_OR_CLASSC(old_container); CYG_PRECONDITIONC(0 != container); container = old_container; CYG_REPORT_RETURN();}CdlNodeCdlInterpreterBody::push_node(CdlNode new_node){ CYG_REPORT_FUNCNAMETYPE("CdlInterpreter::push_node", "result %p"); CYG_REPORT_FUNCARG2XV(this, new_node); CYG_PRECONDITION_THISC(); CYG_PRECONDITION_CLASSC(new_node); CdlNode result = node; node = new_node; CYG_REPORT_RETVAL(result); return result;}voidCdlInterpreterBody::pop_node(CdlNode old_node){ CYG_REPORT_FUNCNAME("CdlInterpreter::pop_node"); CYG_REPORT_FUNCARG2XV(this, old_node); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC(0 != node); CYG_PRECONDITION_ZERO_OR_CLASSC(old_node); node = old_node; CYG_REPORT_RETURN();}std::stringCdlInterpreterBody::push_filename(std::string new_filename){ CYG_REPORT_FUNCNAME("CdlInterpreter::push_filename"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC("" != new_filename); std::string result = filename; filename = new_filename; return result;}voidCdlInterpreterBody::pop_filename(std::string old_filename){ CYG_REPORT_FUNCNAME("CdlInterpreter::pop_filename"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC("" != filename); filename = old_filename; CYG_REPORT_RETURN();}CdlDiagnosticFnPtrCdlInterpreterBody::push_error_fn_ptr(CdlDiagnosticFnPtr new_fn_ptr){ CYG_REPORT_FUNCNAMETYPE("CdlInterpreter::push_error_fn_ptr", "result %p"); CYG_REPORT_FUNCARG2XV(this, new_fn_ptr); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC(0 != new_fn_ptr); CdlDiagnosticFnPtr result = error_fn_ptr; error_fn_ptr = new_fn_ptr; CYG_REPORT_RETVAL(result); return result;}voidCdlInterpreterBody::pop_error_fn_ptr(CdlDiagnosticFnPtr old_fn_ptr){ CYG_REPORT_FUNCNAME("CdlInterpreter::pop_error_fn_ptr"); CYG_REPORT_FUNCARG2XV(this, old_fn_ptr); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC(0 != error_fn_ptr); error_fn_ptr = old_fn_ptr; CYG_REPORT_RETURN();}CdlDiagnosticFnPtrCdlInterpreterBody::push_warning_fn_ptr(CdlDiagnosticFnPtr new_fn_ptr){ CYG_REPORT_FUNCNAMETYPE("CdlInterpreter::push_warning_fn_ptr", "result %p"); CYG_REPORT_FUNCARG2XV(this, new_fn_ptr); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC(0 != new_fn_ptr); CdlDiagnosticFnPtr result = warning_fn_ptr; warning_fn_ptr = new_fn_ptr; CYG_REPORT_RETVAL(result); return result;}voidCdlInterpreterBody::pop_warning_fn_ptr(CdlDiagnosticFnPtr old_fn_ptr){ CYG_REPORT_FUNCNAME("CdlInterpreter::pop_warning_fn_ptr"); CYG_REPORT_FUNCARG2XV(this, old_fn_ptr); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC(0 != warning_fn_ptr); warning_fn_ptr = old_fn_ptr; CYG_REPORT_RETURN();}//}}}//{{{ CdlInterpreter:: get information // ----------------------------------------------------------------------------// Get hold of the underlying Tcl interpreter. This makes it easier to// use miscellaneous Tcl library facilities such as Tcl_SplitList()Tcl_Interp*CdlInterpreterBody::get_tcl_interpreter(void) const{ CYG_REPORT_FUNCNAMETYPE("CdlInterpreter::get_tcl_interpreter", "interpreter %p"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); Tcl_Interp* result = tcl_interp; CYG_REPORT_RETVAL(result); return result;}//}}}//{{{ CdlInterpreter:: eval() // ----------------------------------------------------------------------------// Evaluate a Cdl script held in a string. The result of this evaluation, // e.g. TCL_OK, is returned directly. The string result is made available// in an in-out parameter.//// According to the spec the underlying Tcl_Eval() routine needs to be able// to make temporary changes to the script, so the latter must be held in// writable memory. This requires a copy operation.intCdlInterpreterBody::eval(std::string script, std::string& str_result){ CYG_REPORT_FUNCNAMETYPE("CdInterpreter::eval", "result %d"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); int result = TCL_OK; int size = script.size(); if (size < 2048) { char buf[2048]; script.copy(buf, size, 0); buf[size] = '\0'; result = Tcl_Eval(tcl_interp, buf); } else { char* buf = static_cast<char*>(malloc(script.size() + 1)); if (0 == buf) { // Stay within Tcl's error handling mechanism rather than // throw an exception. char *msg = "Out of memory"; Tcl_SetResult(tcl_interp, msg, TCL_STATIC); str_result = msg; CYG_REPORT_RETVAL(TCL_ERROR); return TCL_ERROR; } script.copy(buf, size, 0); buf[size] = '\0'; result = Tcl_Eval(tcl_interp, buf); free(buf); } str_result = Tcl_GetStringResult(tcl_interp); // The distinction between TCL_OK and TCL_RETURN is probably not worth // worrying about. if (TCL_RETURN == result) { result = TCL_OK; } CYG_REPORT_RETVAL(result); return result;}// Ditto for Tcl Code that comes from a CDL file. Currently this is held// as a string. In future it may be appropriate to store a byte-compiled// version as well.intCdlInterpreterBody::eval_cdl_code(const cdl_tcl_code script, std::string& str_result){ CYG_REPORT_FUNCNAMETYPE("CdInterpreter::eval_cdl_code", "result %d"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); int result = TCL_OK; int size = script.size(); if (size < 2048) { char buf[2048]; script.copy(buf, size, 0); buf[size] = '\0'; result = Tcl_Eval(tcl_interp, buf); } else { char* buf = static_cast<char*>(malloc(script.size() + 1)); if (0 == buf) { // Stay within Tcl's error handling mechanism rather than // throw an exception. char *msg = "Out of memory"; Tcl_SetResult(tcl_interp, msg, TCL_STATIC); str_result = msg; CYG_REPORT_RETVAL(TCL_ERROR); return TCL_ERROR; } script.copy(buf, size, 0); buf[size] = '\0'; result = Tcl_Eval(tcl_interp, buf); free(buf); } str_result = Tcl_GetStringResult(tcl_interp); // The distinction between TCL_OK and TCL_RETURN is probably not worth // worrying about. if (TCL_RETURN == result) { result = TCL_OK; } 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); int result = Tcl_EvalFile(tcl_interp, const_cast<char*>(script.c_str())); str_result = Tcl_GetStringResult(tcl_interp); // The distinction between TCL_OK and TCL_RETURN is probably not worth // worrying about. if (TCL_RETURN == result) { result = TCL_OK; } CYG_REPORT_RETVAL(result); return result;}//}}}//{{{ 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); CYG_REPORT_RETURN();}// ----------------------------------------------------------------------------// 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::get_diagnostic_prefix(interp) + "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::get_diagnostic_prefix(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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -