⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 config.cxx

📁 eCos1.31版
💻 CXX
📖 第 1 页 / 共 5 页
字号:
////  3) create the package object, and add it to the toplevel of the current//     configuration. It may get reparented later on. Part of the creation//     process is to allocate a new slave interpreter, which can be updated//     with various bits of information.////  4) evaluate the toplevel script. Subsidiary component scripts will//     get evaluated as a side effect. The various nodes will be added//     to the hierarchy as they are created, but no property binding//     happens yet.////     Any failure up to this point should result in the entire package//     being removed from the hierarchy and then destroyed, thus leaving//     the configuration in its original state.////  5) now property binding needs to take place. This can have lots//     of side effects, e.g. default values may get calculated, the//     hierarchy may change because of parent properties, etc.//     The work is done inside CdlLoadable::bind() which will undo//     everything on failure - although bad_alloc is the only//     failure that should occur.////  6) load operations can get cancelled, so a suitable commit/cancel//     operation needs to allocated and added to the transaction.////  7) if limbo is enabled, previous values should be extracted from//     limbo if at all possible. In addition the package's value can//     be set to its version.voidCdlConfigurationBody::load_package(CdlTransaction transaction, std::string name, std::string version,                                   CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn, bool limbo)    throw(CdlInputOutputException, CdlParseException, std::bad_alloc){    CYG_REPORT_FUNCNAME("CdlConfiguration::load_package");    CYG_REPORT_FUNCARG1XV(this);    CYG_PRECONDITION_THISC();    CYG_PRECONDITION_CLASSC(transaction);    CYG_PRECONDITIONC("" != name);    // Locate the database entry. Also check the version (filling it in if necessary).    // Get hold of the package directory and the initial script.    if (!database->is_known_package(name)) {        throw CdlInputOutputException("Unknown package " + name);    }    const std::vector<std::string>& versions = database->get_package_versions(name);    if ("" == version) {        version = *(versions.begin());    } else {        if (std::find(versions.begin(), versions.end(), version) == versions.end()) {            throw CdlInputOutputException("Package " + name + " does not have an installed version " + version);        }    }    std::string directory       = database->get_package_directory(name);    std::string script          = database->get_package_script(name);    CYG_ASSERTC(("" != directory) && ("" != script));    // Check that the directory actually exists. For this the configuration's own    // interpreter can be used.    CdlInterpreter interp = get_interpreter();    CYG_ASSERT_CLASSC(interp);    std::string tcl_cmd = "regsub -all -- {\\\\} [file join " + directory + " " + version + "] / result; return $result";    std::string tcl_result;    if (TCL_OK != interp->eval(tcl_cmd, tcl_result)) {        throw CdlInputOutputException("Cannot load package " + name + ", internal error constructing pathname");    }    directory = tcl_result;        tcl_cmd   = "file isdirectory [file join \"" + database->get_component_repository() + "\" " + directory + "]";    if ((TCL_OK != interp->eval(tcl_cmd, tcl_result)) || ("1" != tcl_result)) {        throw CdlInputOutputException("Cannot load package " + name + ", there is no directory " + directory);    }        // Make sure that there is no name conflict. No resources have been allocated    // yet, so this is a good time.    CdlNode node = lookup(name);    if (0 != node) {        if (0 != dynamic_cast<CdlPackage>(node)) {            throw CdlInputOutputException("Package " + name + " is already loaded");        } else {            std::string msg = "Name clash for package " + name + ",there is a " +                node->get_class_name() + " " + name + " already loaded";            CdlLoadable owner_pkg = node->get_owner();            if (0 != owner_pkg) {                msg += " in package " + owner_pkg->get_name();            }            throw CdlInputOutputException(msg);        }    }        // Now create the package object itself.    CdlPackage package  = 0;    bool       bound    = false;    CdlConfiguration_CommitCancelLoad* load_op  = 0;        try {        package = new CdlPackageBody(name, this, directory);        // The package should be added to the hierarchy immediately.        // All nodes will get added to the hierarchy as they are        // created, an operation that has to be undone during        // failure.         this->add_node(package, this, package);                // Load the package data. The various nodes will all end up        // in a hierarchy below the package, but without any checks        // for name conflicts etc and ignoring any re-parenting.        CdlInterpreter interp = package->get_interpreter();        CYG_ASSERT_CLASSC(interp);        interp->add_command("unknown", &CdlParse::unknown_command);                // Next figure out the script name, and make sure that it exists.        std::string actual_script = package->find_absolute_file(script, "cdl");        if ("" == actual_script) {            throw CdlInputOutputException("Package " + name + ", unable to find initial script " + script);        }        tcl_cmd = "file isfile \"" + actual_script + "\"";        if ((TCL_OK != interp->eval(tcl_cmd, tcl_result)) || ("1" != tcl_result)) {            throw CdlInputOutputException("Package " + name + ", " + actual_script + " is not a CDL script");        }        // The script is valid. Set up the interpreter appropriately.        CdlContainer old_container      = interp->push_container(package);        std::string old_filename        = interp->push_filename(actual_script);        CdlDiagnosticFnPtr old_error_fn = interp->push_error_fn_ptr(error_fn);        CdlDiagnosticFnPtr old_warn_fn  = interp->push_warning_fn_ptr(warn_fn);        CdlParse::clear_error_count(interp);        static CdlInterpreterCommandEntry commands[] =        {            CdlInterpreterCommandEntry("cdl_package",    &CdlPackageBody::parse_package     ),            CdlInterpreterCommandEntry("cdl_component",  &CdlComponentBody::parse_component ),            CdlInterpreterCommandEntry("cdl_option",     &CdlOptionBody::parse_option       ),            CdlInterpreterCommandEntry("cdl_interface",  &CdlInterfaceBody::parse_interface ),            CdlInterpreterCommandEntry("cdl_dialog",     &CdlDialogBody::parse_dialog       ),            CdlInterpreterCommandEntry("cdl_wizard",     &CdlWizardBody::parse_wizard       ),            CdlInterpreterCommandEntry("",               0                                  )        };        std::vector<CdlInterpreterCommandEntry> new_commands;        for (int i = 0; 0 != commands[i].command; i++) {            new_commands.push_back(commands[i]);        }        std::vector<CdlInterpreterCommandEntry>* old_commands = interp->push_commands(new_commands);                // The interpreter is now ready.        if (TCL_OK != interp->eval_file(actual_script, tcl_result)) {            throw CdlInputOutputException("Package " + name + ", error executing CDL script.\n" + tcl_result);        }        // Clean out the commands etc. This interpreter may get used again        // in future, and it should not be possible to define new options        // etc. in that invocation.        interp->remove_command("unknown");        interp->pop_commands(old_commands);        interp->pop_container(old_container);        interp->pop_filename(old_filename);        interp->pop_error_fn_ptr(old_error_fn);        interp->pop_warning_fn_ptr(old_warn_fn);                // All the data has been read in without generating an        // exception. However there may have been errors reported via        // the parse_error_fn, 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 CdlParseException("Package " + name + ", " + tmp + " error" +                                    ((error_count > 1) ? "s" : "") +                                    " occurred while reading in the CDL data.");        }        // All the data has been read in, implying that there are no        // fatal problems with the data. Now try to bind all        // references to and from this loadable.        package->bind(transaction);        bound = true;        // Finally, create a suitable transaction commit/cancel object        // and add it to the transaction.        load_op = new CdlConfiguration_CommitCancelLoad(package);        transaction->add_commit_cancel_op(load_op);            } catch (...) {        // Something went wrong during the create or load. It is necessary        // to delete the package. Undo all the operations above, in        // reverse order. The add_commit_cancel_op() was the last step,        // so need not be undone here.        if (0 != load_op) {            delete load_op;        }                if (0 != package) {            // Note: no attempt is made to recover from errors here            if (bound) {                package->unbind(transaction);            }            this->remove_loadable_from_toplevel(package);            delete package;        }         throw;    }    // FIXME: implement limbo support        // We also have a sensible value for the package as a whole.    // Use this value for both default and user - after all the    // user has selected the package.    package->enable_and_set_value(transaction, version, CdlValueSource_Default);    package->enable_and_set_value(transaction, version, CdlValueSource_User);    CYG_REPORT_RETURN();}//}}}//{{{  CdlConfiguration::unload_package()               // ----------------------------------------------------------------------------// Unloading a package is very simple. If requested, save all current// values to limbo: there is no point in saving default values, these// will get recalculated from the default_value property anyway;// inferred values should be saved, there is no guarantee that the exact// same value will be calculated again, and if the inferred value is no// longer correct then the inference engine can freely update it.//// Next, unbind the package and remove it from the hierarchy. These// operations are reversible if the transaction gets cancelled.// A suitable transaction commit/cancel object is created and// added to the transaction.voidCdlConfigurationBody::unload_package(CdlTransaction transaction, CdlPackage package, bool limbo){    CYG_REPORT_FUNCNAME("CdlConfiguration::unload_package");    CYG_REPORT_FUNCARG4XV(this, transaction, package, limbo);    CYG_INVARIANT_THISC(CdlConfigurationBody);    CYG_INVARIANT_CLASSC(CdlTransactionBody, transaction);    CYG_PRECONDITION_CLASSC(package);    if (limbo) {        const std::vector<CdlNode>& pkg_contents = package->get_owned();        std::vector<CdlNode>::const_iterator node_i;        for (node_i = pkg_contents.begin(); node_i != pkg_contents.end(); node_i++) {            CdlValuable valuable = dynamic_cast<CdlValuable>(*node_i);            if (0 != valuable) {                if (valuable->has_source(CdlValueSource_Inferred) ||                    valuable->has_source(CdlValueSource_Wizard)   ||                    valuable->has_source(CdlValueSource_User)) {                                        set_limbo_value(valuable);                }            }        }    }    bool unbound = false;    bool removed = false;    CdlConfiguration_CommitCancelUnload* unload_op = 0;    try {                package->unbind(transaction);        unbound = true;        this->remove_loadable_from_toplevel(package);        removed = true;        unload_op = new CdlConfiguration_CommitCancelUnload(package);        transaction->add_commit_cancel_op(unload_op);            } catch(...) {        if (0 != unload_op) {            delete unload_op;        }        if (removed) {            this->add_loadable_to_toplevel(package);        }        if (unbound) {            package->bind(transaction);        }        throw;    }        CYG_REPORT_RETURN();}//}}}//{{{  CdlConfiguration::change_package_version()       // ----------------------------------------------------------------------------// Changing a package version is just a case of unloading the old version// and then loading in the new version. Because this all happens in the// context of a transaction it is possible to undo the unload on// failure, and the whole transaction can be cancelled at a higher level.voidCdlConfigurationBody::change_package_version(CdlTransaction transaction, CdlPackage package, std::string new_version,                                             CdlDiagnosticFnPtr error_fn, CdlDiagnosticFnPtr warn_fn, bool limbo)    throw(CdlInputOutputException, CdlParseException, std::bad_alloc){    CYG_REPORT_FUNCNAME("CdlConfiguration::change_package_version");    CYG_REPORT_FUNCARG3XV(this, transaction, package);    CYG_PRECONDITION_THISC();    CYG_INVARIANT_CLASSC(CdlTransactionBody, transaction);    CYG_PRECONDITION_CLASSC(package);    // "" is valid for the version, it indicates the default    // Since the package is already loaded it must be in the database,    // but it is possible that the desired version does not exist.    std::string name = package->get_name();    const std::vector<std::string>& pkg_versions = database->get_package_versions(name);    if ("" == new_version) {        new_version = *(pkg_versions.begin());    } else if (std::find(pkg_versions.begin(), pkg_versions.end(), new_version) == pkg_versions.end()) {        throw CdlInputOutputException("Version " + new_version + " of package " + name + " is not installed.");    }    bool unloaded = false;    try {        this->unload_package(transaction, package, limbo);        unloaded = true;        this->load_package(transaction, name, new_version, error_fn, warn_fn, limbo);    } catch(...) {        if (unloaded) {            // There should be a commit/cancel op for the unload package step.            // This can be undone.            CdlTransactionCommitCancelOp* unload_op = transaction->get_last_commit_cancel_op();            CYG_ASSERTC(0 != unload_op);            CYG_ASSERTC(0 != dynamic_cast<CdlConfiguration_CommitCancelUnload*>(unload_op));            transaction->cancel_last_commit_cancel_op();            CYG_UNUSED_PARAM(CdlTransactionCommitCancelOp*, unload_op);        }        throw;    }    CYG_REPORT_RETURN();}//}}}//{{{  CdlConfiguration::set_hardware() etc.            // ----------------------------------------------------------------------------// Setting the hardware involves unloading the old hardware, if any, and// then loading in the new one. Obviously this should only happen if// the new hardware name is valid. It would be possible to optimise for// the case where the old and new hardware are the same, subject// to dynamic database reload support.voidCdlConfigurationBody::set_hardware(CdlTransaction transaction, std::string target_name,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -