📄 config.cxx
字号:
//}}}//{{{ CdlConfiguration::save() - internal // ----------------------------------------------------------------------------// The exported interface is CdlConfiguration::save(). This takes a single// argument, a filename. It opens the file, and then invokes various// functions that output the relevants bits of the file.//// This member function is responsible for outputting a cdl_configuration// command.voidCdlConfigurationBody::save(CdlInterpreter interp, Tcl_Channel chan, int indentation, bool minimal){ CYG_REPORT_FUNCNAME("CdlConfiguration::save"); CYG_REPORT_FUNCARG5XV(this, interp, chan, indentation, minimal); CYG_PRECONDITION_THISC(); CYG_PRECONDITION_CLASSC(interp); CYG_PRECONDITIONC(0 == indentation); std::string text = ""; if (!minimal) { text = "# This section defines the toplevel configuration object. The only\n\# values that can be changed are the name of the configuration and\n\# the description field. It is not possible to modify the target,\n\# the template or the set of packages simply by editing the lines\n\# below because these changes have wide-ranging effects. Instead\n\# the appropriate tools should be used to make such modifications.\n\\n"; } text += "cdl_configuration " + CdlInterpreterBody::quote(this->get_name()) + " {\n"; std::string config_data = this->get_description(); if (!minimal || ("" != text)) { text += " description " + CdlInterpreterBody::quote(config_data) + " ;\n"; } // Repeat the warning. if (!minimal) { text += "\n # These fields should not be modified.\n"; } config_data = this->get_hardware(); if ("" != config_data) { text += " hardware " + CdlInterpreterBody::quote(config_data) + " ;\n"; } config_data = this->get_template(); if ("" != config_data) { 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){ 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){ 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){ 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. CdlParse::clear_error_count(interp); CdlInterpreterBody::DiagSupport diag_support(interp, error_fn, warn_fn); CdlInterpreterBody::ContextSupport context_support(interp, filename); try { interp->set_transaction(transaction); std::vector<CdlInterpreterCommandEntry> commands; this->get_savefile_commands(commands); CdlInterpreterBody::CommandSupport interp_cmds(interp, commands); interp->eval_file(filename); // 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(...) { interp->set_transaction(0); throw; } 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>(t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -