📄 base.cxx
字号:
CdlLoadableBody::get_directory() const{ CYG_REPORT_FUNCNAME("CdlLoadable::get_directory"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CYG_REPORT_RETURN(); return directory;}//}}}//{{{ Bind/unbind support // ----------------------------------------------------------------------------// Binding a loadable. This involves checking every property of every node// in the loadable, which the properties do themselves by a suitable// update() virtual function. Next, there may be properties in the// existing configuration which could not previously be bound: there// will be structural conflicts for all of these. Once all the pointers// go to the right places it is possible to calculate the default values// and generally process the properties. Finally each node's active// state is checked - the default inactive state will be inappropriate// in many cases.//// FIXME: error recovery?voidCdlLoadableBody::bind(CdlTransaction transaction){ CYG_REPORT_FUNCNAME("CdlLoadable::bind"); CYG_REPORT_FUNCARG2XV(this, transaction); CYG_INVARIANT_THISC(CdlLoadableBody); CYG_INVARIANT_CLASSC(CdlTransactionBody, transaction); // The loadable must already be part of the hierarchy. CdlToplevel toplevel = this->get_toplevel(); CYG_ASSERT_CLASSC(toplevel); // As a first step, bind all references in this loadable. // This is achieved via a Loaded update. const std::vector<CdlNode>& nodes = this->get_owned(); std::vector<CdlNode>::const_iterator node_i; for (node_i = nodes.begin(); node_i != nodes.end(); node_i++) { const std::vector<CdlProperty>& properties = (*node_i)->get_properties(); std::vector<CdlProperty>::const_iterator prop_i; for (prop_i = properties.begin(); prop_i != properties.end(); prop_i++) { (*prop_i)->update(transaction, *node_i, 0, CdlUpdate_Loaded); } } // Next, look for all structural conflicts which are unresolved // references and which can now be resolved. It is necessary // to check per-transaction structural conflicts, plus those // in any parent transactions, plus the global ones. std::list<CdlConflict>::const_iterator conf_i; CdlTransaction current_transaction = transaction; do { CYG_ASSERT_CLASSC(current_transaction); const std::list<CdlConflict>& new_structural_conflicts = current_transaction->get_new_structural_conflicts(); for (conf_i = new_structural_conflicts.begin(); conf_i != new_structural_conflicts.end(); ) { CdlConflict conflict = *conf_i++; CYG_LOOP_INVARIANT_CLASSC(conflict); CdlConflict_Unresolved unresolved_conflict = dynamic_cast<CdlConflict_Unresolved>(conflict); if ((0 != unresolved_conflict) && !transaction->has_conflict_been_cleared(conflict)) { CdlNode dest = toplevel->lookup(unresolved_conflict->get_target_name()); if (0 != dest) { CdlNode node = unresolved_conflict->get_node(); CdlProperty prop = unresolved_conflict->get_property(); prop->update(transaction, node, dest, CdlUpdate_Created); } } } current_transaction = current_transaction->get_parent(); } while (0 != current_transaction); const std::list<CdlConflict>& structural_conflicts = toplevel->get_all_structural_conflicts(); for (conf_i = structural_conflicts.begin(); conf_i != structural_conflicts.end(); ) { CdlConflict conflict = *conf_i++; CYG_LOOP_INVARIANT_CLASSC(conflict); CdlConflict_Unresolved this_conflict = dynamic_cast<CdlConflict_Unresolved>(conflict); if ((0 != this_conflict) && !transaction->has_conflict_been_cleared(conflict)) { CdlNode dest = toplevel->lookup(this_conflict->get_target_name()); if (0 != dest) { CdlNode node = this_conflict->get_node(); CdlProperty prop = this_conflict->get_property(); prop->update(transaction, node, dest, CdlUpdate_Created); } } } // Conflict resolution has happened. Next it is time // to evaluate default_value expressions and the like // in the new loadable. for (node_i = nodes.begin(); node_i != nodes.end(); node_i++) { const std::vector<CdlProperty>& properties = (*node_i)->get_properties(); std::vector<CdlProperty>::const_iterator prop_i; for (prop_i = properties.begin(); prop_i != properties.end(); prop_i++) { (*prop_i)->update(transaction, *node_i, 0, CdlUpdate_Init); } } // Nodes start of inactive. Check each one whether or not it // should be active. // NOTE: possibly this should be done via a per-node init // update instead. for (node_i = nodes.begin(); node_i != nodes.end(); node_i++) { bool current_state = transaction->is_active(*node_i); bool new_state = (*node_i)->test_active(transaction); if (current_state != new_state) { transaction->set_active(*node_i, new_state); } } CYG_REPORT_RETURN();}// ----------------------------------------------------------------------------voidCdlLoadableBody::unbind(CdlTransaction transaction){ CYG_REPORT_FUNCNAME("CdlLoadable::unbind"); CYG_REPORT_FUNCARG2XV(this, transaction); CYG_PRECONDITION_THISC(); CYG_PRECONDITION_CLASSC(transaction); // First take care of all references to nodes in the loadable // that is disappearing. This involves a Destroyed update. const std::vector<CdlNode>& nodes = this->get_owned(); std::vector<CdlNode>::const_iterator node_i; for (node_i = nodes.begin(); node_i != nodes.end(); node_i++) { // The update will remove referrer objects, so it is best // to work from the back. std::vector<CdlReferrer>& referrers = (*node_i)->referrers; std::vector<CdlReferrer>::reverse_iterator ref_i; for (ref_i = referrers.rbegin(); ref_i != referrers.rend(); ref_i = referrers.rbegin()) { ref_i->update(transaction, *node_i, CdlUpdate_Destroyed); CYG_LOOP_INVARIANT(ref_i != referrers.rbegin(), "the vector should have shrunk"); } } // Now repeat the loop, but unbind references from the unloaded objects // to ones which are going to stay loaded. This will not cause // the properties to disappear. for (node_i = nodes.begin(); node_i != nodes.end(); node_i++) { const std::vector<CdlProperty>& properties = (*node_i)->get_properties(); std::vector<CdlProperty>::const_iterator prop_i; for (prop_i = properties.begin(); prop_i != properties.end(); prop_i++) { (*prop_i)->update(transaction, *node_i, 0, CdlUpdate_Unloading); } } // Eliminate any conflicts that belong to this loadable. // FIXME: why is his necessary? Should these conflicts not get // eliminated by the above property iterations? std::list<CdlConflict>::const_iterator conf_i; const std::list<CdlConflict>& global_conflicts = toplevel->get_all_conflicts(); for (conf_i = global_conflicts.begin(); conf_i != global_conflicts.end(); ) { CdlConflict conflict = *conf_i++; CYG_LOOP_INVARIANT_CLASSC(conflict); CdlNode node = conflict->get_node(); if ((node->get_owner() == this) && !transaction->has_conflict_been_cleared(conflict)) { transaction->clear_conflict(conflict); } } const std::list<CdlConflict>& global_structural_conflicts = toplevel->get_all_structural_conflicts(); for (conf_i = global_structural_conflicts.begin(); conf_i != global_structural_conflicts.end(); ) { CdlConflict conflict = *conf_i++; CYG_LOOP_INVARIANT_CLASSC(conflict); CdlNode node = conflict->get_node(); if ((node->get_owner() == this) && !transaction->has_conflict_been_cleared(conflict)) { transaction->clear_conflict(conflict); } } const std::list<CdlConflict>& transaction_conflicts = transaction->get_new_conflicts(); for (conf_i = transaction_conflicts.begin(); conf_i != transaction_conflicts.end(); ) { CdlConflict conflict = *conf_i++; CYG_LOOP_INVARIANT_CLASSC(conflict); CdlNode node = conflict->get_node(); if (node->get_owner() == this) { transaction->clear_conflict(conflict); } } const std::list<CdlConflict>& transaction_structural_conflicts = transaction->get_new_structural_conflicts(); for (conf_i = transaction_structural_conflicts.begin(); conf_i != transaction_structural_conflicts.end(); ) { CdlConflict conflict = *conf_i++; CYG_LOOP_INVARIANT_CLASSC(conflict); CdlNode node = conflict->get_node(); if (node->get_owner() == this) { transaction->clear_conflict(conflict); } } // FIXME: how about cleanup_orphans() CYG_REPORT_RETURN();}// ----------------------------------------------------------------------------// These members are invoked for load and unload operations.//// Committing a load does not require anything, the loadable has// already been fully bound and all propagation has happened.voidCdlLoadableBody::transaction_commit_load(CdlTransaction transaction, CdlLoadable loadable){ CYG_REPORT_FUNCNAME("CdlLoadable::transaction_commit_load"); CYG_REPORT_FUNCARG2XV(transaction, loadable); CYG_PRECONDITION_CLASSC(transaction); CYG_PRECONDITION_CLASSC(loadable); CYG_UNUSED_PARAM(CdlTransaction, transaction); CYG_UNUSED_PARAM(CdlLoadable, loadable); CYG_REPORT_RETURN();}// Cancelling a load is more difficult. The loadable has to be// unbound, removed from the toplevel, and deleted. If any of// this fails then we are in trouble, there is no easy way to// recover.voidCdlLoadableBody::transaction_cancel_load(CdlTransaction transaction, CdlLoadable loadable){ CYG_REPORT_FUNCNAME("CdlLoadable::transaction_cancel_load"); CYG_REPORT_FUNCARG2XV(transaction, loadable); CYG_PRECONDITION_CLASSC(transaction); CYG_PRECONDITION_CLASSC(loadable); CdlToplevel toplevel = transaction->get_toplevel(); CYG_PRECONDITION_CLASSC(toplevel); CYG_ASSERTC(toplevel == loadable->get_toplevel()); loadable->unbind(transaction); toplevel->remove_loadable_from_toplevel(loadable); delete loadable; CYG_REPORT_RETURN();}// Committing an unload means that the loadable can now be deleted.// It should already be unbound and removed from the toplevel.voidCdlLoadableBody::transaction_commit_unload(CdlTransaction transaction, CdlLoadable loadable){ CYG_REPORT_FUNCNAME("CdlLoadable::transaction_commit_unload"); CYG_REPORT_FUNCARG2XV(transaction, loadable); CYG_PRECONDITION_CLASSC(transaction); CYG_PRECONDITION_CLASSC(loadable); CYG_UNUSED_PARAM(CdlTransaction, transaction); delete loadable; CYG_REPORT_RETURN();}// Cancelling an unload means that the loadable has to be re-added// to the hierarchy and then rebound. This implies that value// propagation needs to happen. However, since all value changes// since the very start of the transaction are held inside the// transaction and will be eliminated, the original state will// be restored anyway so the propagation is not actually required.voidCdlLoadableBody::transaction_cancel_unload(CdlTransaction transaction, CdlLoadable loadable){ CYG_REPORT_FUNCNAME("CdlLoadable::transaction_cancel_unload"); CYG_REPORT_FUNCARG2XV(transaction, loadable); CYG_PRECONDITION_CLASSC(transaction); CYG_PRECONDITION_CLASSC(loadable); CdlToplevel toplevel = transaction->get_toplevel(); CYG_PRECONDITION_CLASSC(toplevel); toplevel->add_loadable_to_toplevel(loadable); CYG_ASSERT_CLASSC(loadable); loadable->bind(transaction); CYG_REPORT_RETURN();}//}}}//{{{ File search facilities // ----------------------------------------------------------------------------// File search facilities. Given a file name such as hello.cxx from a compile// property, or doc.html from a doc property, find the corresponding filename,// for example /usr/local/eCos/kernel/v1_3/doc/threads.html#create//// The second argument (default value "") indicates a preferred directory// where searching should begin. This would be src for a source file,// doc for a URL, etc.//// For some properties the data may refer to a URL rather than to a local// filename. This is controlled by the third argument, allow_urls.// If false then only local filenames will be considered. allow_urls// also controls whether or not anchor processing is performed.//// RFC1807: a URL consists of <scheme>:<rest>, where <scheme> can be// any sequence of lower-case letters, digits, plus, dot or hyphen. It// is recommended that upper-case letters should be accepted as well.//// RFC1807: an anchor is everything after the first # in the URL.static char find_absolute_file_script[] = " \n\set cdl_anchor \"\" \n\if {$::cdl_allow_urls} { \n\ if { [regexp -- {^[a-zA-Z+.-]*:.*$} $::cdl_target] } { \n\ return $::cdl_target \n\ } \n\ set tmp \"\" \n\ set non_anchor \"\" \n\ if { [regexp -- {^([^#])(#.*$)} $::cdl_target tmp non_anchor cdl_anchor] } { \n\ set ::cdl_target $non_anchor \n\ } \n\} \n\if {$::cdl_prefdir != \"\"} { \n\ set filename [file join $::cdl_topdir $::cdl_pkgdir $::cdl_prefdir $::cdl_target] \n\ if {[file exists $filename]} { \n\ return \"[set filename][set cdl_anchor]\" \n\ } \n\} \n\set filename [file join $::cdl_topdir $::cdl_pkgdir $::cdl_target] \n\if {[file exists $filename]} { \n\ return \"[set filename][set cdl_anchor]\" \n\} \n\return -error \"\" \n\";std::stringCdlLoadableBody::find_absolute_file(std::string filename, std::string dirname, bool allow_urls) const{ CYG_REPORT_FUNCNAME("CdlLoadable::find_absolute_file"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC("" != filename); // These variable names should be kept in step with CdlBuildable::update_all_build_info() interp->set_variable("::cdl_topdir", get_toplevel()->get_directory()); interp->set_variable("::cdl_pkgdir", directory); interp->set_variable("::cdl_prefdir", dirname); interp->set_variable("::cdl_target", filename); interp->set_variable("::cdl_allow_urls", allow_urls ? "1" : "0"); std::string result; int tmp = interp->eval(find_absolute_file_script, result); if (tmp != TCL_OK) { result = ""; } // Replace any backslashes in the repository with forward slashes. // The latter are used throughout the library // NOTE: this is not i18n-friendly. for (unsigned int i = 0; i < result.size(); i++) { if ('\\' == result[i]) { result[i] = '/'; } } CYG_REPORT_RETURN(); return result;}static char find_relative_file_script[] = " \n\if {$::cdl_prefdir != \"\"} { \n\ set filename [file join $::cdl_prefdir $::cdl_target] \n\ if {[file exists [file join $::cdl_topdir $::cdl_pkgdir $filename]]} { \n\ return $filename \n\ } \n\} \n\set filename $::cdl_target \n\if {[file exists [file join $::cdl_topdir $::cdl_pkgdir $filename]]} { \n\ return \"[set filename][set cdl_anchor]\" \n\} \n\return -error \"\" \n\";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -