📄 config.cxx
字号:
text += " template " + CdlInterpreterBody::quote(config_data) + " ;\n"; } std::vector<CdlLoadable>::const_iterator load_i; const std::vector<CdlLoadable>& packages = get_loadables(); for (load_i = packages.begin(); load_i != packages.end(); load_i++) { CdlPackage pkg = dynamic_cast<CdlPackage>(*load_i); CYG_ASSERT_CLASSC(pkg); text += " package "; if (pkg->belongs_to_template()) { text += "-template "; } if (pkg->belongs_to_hardware()) { text += "-hardware "; } text += CdlInterpreterBody::quote(pkg->get_name()) + " " + CdlInterpreterBody::quote(pkg->get_value()) + " ;\n"; } interp->write_data(chan, text); // If the package was loaded from a file then there may be additional // data associated with the configuration that is not currently // recognised. This call preserves that data. this->CdlNodeBody::save(interp, chan, indentation + 4, minimal); interp->write_data(chan, "};\n\n"); CYG_REPORT_RETURN();}//}}}//{{{ CdlConfiguration::save() - exported interface // ----------------------------------------------------------------------------// This is the exported interface for saving a configuration. The specified// file is opened via the appropriate Tcl library routines, and then the// relevant member functions are invoked to output the actual configuration// date.voidCdlConfigurationBody::save(std::string filename, bool minimal) throw(CdlInputOutputException, std::bad_alloc){ CYG_REPORT_FUNCNAME("CdlConfiguration::save"); CYG_REPORT_FUNCARG2XV(this, minimal); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC("" != filename); // Make sure that the savefile support is properly initialized. // This happens during the first save or load operation, or when // the application starts to register its own savefile extensions. if (!CdlToplevelBody::savefile_support_initialized()) { this->initialize_savefile_support(); } // A Tcl interpreter is needed for the call to OpenFileChannel(), // and will also be passed to the individual save functions. CdlInterpreter interp = this->get_interpreter(); CYG_ASSERT_CLASSC(interp); // Do not worry about forward vs. backward slashes, since the filename // is not manipulated in any way. Instead just pass it to Tcl. Tcl_Channel chan = Tcl_OpenFileChannel(interp->get_tcl_interpreter(), const_cast<char*>(filename.c_str()), "w", 0666); if (0 == chan) { throw CdlInputOutputException("Unable to open file " + filename + "\n" + interp->get_result()); } // The channel may end up being registered in various different // interpreters, so Tcl_Close() is not the right way to close down // the channel. Instead Tcl_RegisterChannel() should be used here // to provide reference counting semantics. Tcl_RegisterChannel(0, chan); // A try/catch body is needed here to make sure that the file gets // properly cleaned up. std::string tmp; try { if (!minimal) { interp->write_data(chan, "# eCos saved configuration\n\n"); } CdlToplevelBody::save_separator(interp, chan, "commands", minimal); this->CdlToplevelBody::save_command_details(interp, chan, 0, minimal); CdlToplevelBody::save_separator(interp, chan, "toplevel", minimal); this->save(interp, chan, 0, minimal); CdlToplevelBody::save_separator(interp, chan, "conflicts", minimal); this->CdlToplevelBody::save_conflicts(interp, chan, 0, minimal); CdlToplevelBody::save_separator(interp, chan, "contents", minimal); this->CdlContainerBody::save(interp, chan, 0, minimal); this->save_unsupported_commands(interp, chan, 0, minimal); } catch(...) { Tcl_UnregisterChannel(0, chan); // NOTE: deleting the file is necessary, it is a bad idea to // end up with incomplete save files. It would be even better // to write to a temporary file and only overwrite the old // savefile on success. // // Tcl does not provide direct access to the file delete // facility, so it is necessary to evaluate a script. This // introduces quoting and security problems, since the // filename might contain spaces, square brackets, braces... // To avoid these problems a variable is used. interp->set_variable("__cdlconfig_filename", filename); interp->eval("file delete $__cdlconfig_filename", tmp); interp->unset_variable("__cdlconfig_filename"); throw; } // This call will perform the appropriate close. Tcl_UnregisterChannel(0, chan);}//}}}//{{{ CdlConfiguration::load() and add() // ----------------------------------------------------------------------------// Most of the work is done in add(). load() simply creates a new configuration// and then invokes add().CdlConfigurationCdlConfigurationBody::load(std::string filename, CdlPackagesDatabase db, CdlInterpreter interp, CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn) throw(CdlInputOutputException, CdlParseException, std::bad_alloc){ CYG_REPORT_FUNCNAMETYPE("CdlConfiguration::load", "result %p"); CYG_REPORT_FUNCARG4XV(db, interp, error_fn, warn_fn); CYG_PRECONDITION_CLASSC(db); CYG_PRECONDITION_CLASSC(interp); CdlConfiguration result = CdlConfigurationBody::make("eCos", db, interp); if (0 == result) { CYG_REPORT_RETVAL(result); return result; } try { result->add(filename, error_fn, warn_fn); result->save_file = filename; } catch(...) { delete result; throw; } CYG_REPORT_RETVAL(result); return result;}// ----------------------------------------------------------------------------voidCdlConfigurationBody::add(CdlTransaction transaction, std::string filename, CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn) throw(CdlInputOutputException, CdlParseException, std::bad_alloc){ CYG_REPORT_FUNCNAME("CdlConfiguration::add"); CYG_REPORT_FUNCARG3XV(this, error_fn, warn_fn); CYG_PRECONDITION_THISC(); // Initialize the savefile support, so that it is known what // commands can occur in a savefile. if (!CdlToplevelBody::savefile_support_initialized()) { this->initialize_savefile_support(); } // The interpreter should not have any left-over junk. CdlInterpreter interp = this->get_interpreter(); CYG_PRECONDITION_CLASSC(interp); CYG_ASSERTC(0 == interp->get_loadable()); CYG_ASSERTC(0 == interp->get_container()); CYG_ASSERTC(0 == interp->get_node()); CYG_ASSERTC(0 == interp->get_transaction()); // Keep track of enough information to undo all the changes. std::string old_filename = interp->get_filename(); CdlDiagnosticFnPtr old_error_fn = interp->get_error_fn_ptr(); CdlDiagnosticFnPtr old_warn_fn = interp->get_warning_fn_ptr(); std::vector<CdlInterpreterCommandEntry>* old_commands = 0; std::vector<CdlInterpreterCommandEntry> commands; try { // Associate the right information with the interpreter old_filename = interp->push_filename(filename); old_error_fn = interp->push_error_fn_ptr(error_fn); old_warn_fn = interp->push_warning_fn_ptr(warn_fn); CdlParse::clear_error_count(interp); interp->set_transaction(transaction); this->get_savefile_commands(commands); old_commands = interp->push_commands(commands); std::string tcl_result = ""; if (TCL_OK != interp->eval_file(filename, tcl_result)) { throw CdlInputOutputException("Invalid savefile \"" + filename + "\".\n" + tcl_result); } // All the data has been read in without generating an // exception. However there may have been errors reported via // the error_fn handling, and any errors at all should result // in an exception. int error_count = CdlParse::get_error_count(interp); if (error_count > 0) { std::string tmp; Cdl::integer_to_string(error_count, tmp); throw CdlInputOutputException("Invalid savefile \"" + filename + "\".\n" + tmp + " error" + ((error_count > 1) ? "s" : "") + " occurred while reading in the savefile data."); } } catch(...) { if (0 != old_commands) { interp->pop_commands(old_commands); } interp->pop_filename(old_filename); interp->pop_error_fn_ptr(old_error_fn); interp->pop_warning_fn_ptr(old_warn_fn); interp->set_transaction(0); throw; } interp->pop_filename(old_filename); interp->pop_error_fn_ptr(old_error_fn); interp->pop_warning_fn_ptr(old_warn_fn); interp->pop_commands(old_commands); interp->set_transaction(0); CYG_REPORT_RETURN();}//}}}//{{{ savefile commands // ----------------------------------------------------------------------------// A cdl_configuration command does not actually do very much. It acts as// a container for subcommands, and it can be used to change the name.//// The command could also check that the current configuration is empty.// This is not done, to allow multiple savefiles to be loaded into// a single configuration in future.intCdlConfigurationBody::savefile_configuration_command(CdlInterpreter interp, int argc, char** argv){ CYG_REPORT_FUNCNAMETYPE("CdlConfiguration::savefile_configuration_command", "result %d"); CYG_PRECONDITION_CLASSC(interp); int result = TCL_OK; CdlToplevel toplevel = interp->get_toplevel(); CYG_ASSERT_CLASSC(toplevel); CdlConfiguration config = dynamic_cast<CdlConfiguration>(toplevel); CYG_ASSERT_CLASSC(config); std::vector<CdlInterpreterCommandEntry> subcommands; std::vector<CdlInterpreterCommandEntry>* toplevel_commands = 0; try { std::vector<std::pair<std::string,std::string> > options; int data_index = CdlParse::parse_options(interp, "cdl_configuration command", 0, argc, argv, 1, options); // A broken cdl_configuration command is pretty fatal, chances are // that the entire load is going to fail. if (data_index != (argc - 2)) { CdlParse::report_error(interp, "Invalid cdl_configuration command in savefile, expecting two arguments."); } else { config->set_name(argv[1]); config->get_savefile_subcommands("cdl_configuration", subcommands); toplevel_commands = interp->push_commands(subcommands); std::string tcl_result; result = interp->eval(argv[2], tcl_result); interp->pop_commands(toplevel_commands); toplevel_commands = 0; } } catch(...) { if (0 != toplevel_commands) { interp->pop_commands(toplevel_commands); } throw; } CYG_REPORT_RETVAL(result); return result;}// ----------------------------------------------------------------------------intCdlConfigurationBody::savefile_description_command(CdlInterpreter interp, int argc, char** argv){ CYG_REPORT_FUNCNAME("CdlConfiguration::savefile_description_command"); CYG_PRECONDITION_CLASSC(interp); CdlToplevel toplevel = interp->get_toplevel(); CYG_ASSERT_CLASSC(toplevel); CdlConfiguration config = dynamic_cast<CdlConfiguration>(toplevel); CYG_ASSERT_CLASSC(config); std::vector<std::pair<std::string,std::string> > options; int data_index = CdlParse::parse_options(interp, "cdl_configuration/description command", 0, argc, argv, 1, options); if (data_index != (argc - 1)) { CdlParse::report_warning(interp, "Ignoring invalid configuration description command, expecting a single argument."); } else { config->description = argv[1]; } return TCL_OK;}// ----------------------------------------------------------------------------intCdlConfigurationBody::savefile_hardware_command(CdlInterpreter interp, int argc, char** argv){ CYG_REPORT_FUNCNAME("CdlConfiguration::savefile_hardware_command"); CYG_PRECONDITION_CLASSC(interp); CdlToplevel toplevel = interp->get_toplevel(); CYG_ASSERT_CLASSC(toplevel); CdlConfiguration config = dynamic_cast<CdlConfiguration>(toplevel); CYG_ASSERT_CLASSC(config); std::vector<std::pair<std::string,std::string> > options; int data_index = CdlParse::parse_options(interp, "cdl_configuration/hardware command", 0, argc, argv, 1, options); if (data_index != (argc - 1)) { CdlParse::report_warning(interp, "Ignoring invalid configuration hardware command, expecting a single argument."); } else { config->current_hardware = argv[1]; } return TCL_OK;}// ----------------------------------------------------------------------------intCdlConfigurationBody::savefile_template_command(CdlInterpreter interp, int argc, char** argv){ CYG_REPORT_FUNCNAME("CdlConfiguration::savefile_template_command"); CYG_PRECONDITION_CLASSC(interp); CdlToplevel toplevel = interp->get_toplevel(); CYG_ASSERT_CLASSC(toplevel); CdlConfiguration config = dynamic_cast<CdlConfiguration>(toplevel); CYG_ASSERT_CLASSC(config); std::vector<std::pair<std::string,std::string> > options; int data_index = CdlParse::parse_op
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -