Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

cmt_use.cxx

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 
00005 #include "cmt_use.h"
00006 #include "cmt_system.h"
00007 #include "cmt_symbol.h"
00008 #include "cmt_error.h"
00009 #include "cmt_database.h"
00010 
00011 /*
00012  *   Design.
00013  *
00014  *   There is one central database of all Use objects. This in the Database using:
00015  *       Database::instance().all_uses ();
00016  *
00017  *   There is also a list of selected Use pointers available from
00018  *       Database::instance().uses ();
00019  *
00020  *   A new Use object is created when a new use statement requires it:
00021  *     o if the specified version is specified for the first time
00022  *     o if the specified path is specified for the first time
00023  *
00024  */
00025 
00026 class UseContext
00027 {
00028 public:
00029 
00030   static UseContext& current ()
00031   {
00032     static UseContext me;
00033 
00034     return (me);
00035   }
00036 
00037   UseContext ()
00038   {
00039     m_auto_imports = On;
00040     m_scope = ScopePublic;
00041   }
00042 
00043   UseContext (const UseContext& other)
00044   {
00045     m_auto_imports = other.m_auto_imports;
00046     m_scope = other.m_scope;
00047   }
00048 
00049   UseContext& operator = (const UseContext& other)
00050   {
00051     m_auto_imports = other.m_auto_imports;
00052     m_scope = other.m_scope;
00053 
00054     return (*this);
00055   }
00056 
00057   static void set_current (State auto_imports)
00058   {
00059     UseContext& c = current ();
00060 
00061     c.m_auto_imports = auto_imports;
00062   }
00063 
00064   static void set_current (ScopeType scope)
00065   {
00066     UseContext& c = current ();
00067 
00068     c.m_scope = scope;
00069   }
00070 
00071   static State get_current_auto_imports ()
00072   {
00073     UseContext& c = current ();
00074 
00075     return (c.m_auto_imports);
00076   }
00077 
00078   static ScopeType get_current_scope ()
00079   {
00080     UseContext& c = current ();
00081 
00082     return (c.m_scope);
00083   }
00084 
00085 private:
00086   State m_auto_imports;
00087   ScopeType m_scope;
00088 };
00089 
00097 class VersionSelector
00098 {
00099 public:
00100   static VersionSelector& instance ();
00101 
00102   virtual Use* operate (Use* ref_use, Use* new_use)
00103   {
00104     return (ref_use);
00105   }
00106 };
00107 
00108 class BestFitSelector : public VersionSelector
00109 {
00110 public:
00111   Use* operate (Use* ref_use, Use* new_use);
00112 };
00113 
00114 class BestFitNoCheckSelector : public VersionSelector
00115 {
00116 public:
00117   Use* operate (Use* ref_use, Use* new_use);
00118 };
00119 
00120 class FirstChoiceSelector : public VersionSelector
00121 {
00122 public:
00123   Use* operate (Use* ref_use, Use* new_use);
00124 };
00125 
00126 class LastChoiceSelector : public VersionSelector
00127 {
00128 public:
00129   Use* operate (Use* ref_use, Use* new_use);
00130 };
00131 
00132 class KeepAllSelector : public VersionSelector
00133 {
00134 public:
00135   Use* operate (Use* ref_use, Use* new_use);
00136 };
00137 //----------------------------------------------------------
00138 
00139 //----------------------------------------------------------
00140 //
00141 //  Operations on Use
00142 //
00143 //----------------------------------------------------------
00144 
00148 void Use::select_clients (const cmt_string& package,
00149                           const cmt_string& version)
00150 {
00151   static UsePtrVector& Uses = uses ();
00152 
00153   int number;
00154   Use* use = 0;
00155 
00156   unselect_all ();
00157   undiscard_all ();
00158 
00159   for (number = Uses.size () - 1; number >= 0; number--)
00160     {
00161       use = Uses[number];
00162       if (use == 0) continue;
00163       if (use->is_selected ()) continue;
00164       use->select ();
00165       if (!use->is_client (package, version)) use->discard ();
00166     }
00167 }
00168 
00169 //----------------------------------------------------------
00170 void Use::show_all (bool skip_discarded)
00171 {
00172   show_all ("use ", skip_discarded);
00173 }
00174 
00175 //----------------------------------------------------------
00176 void Use::show_all (const cmt_string& prefix, bool skip_discarded)
00177 {
00178   static UsePtrVector& Uses = uses ();
00179 
00180   Use* use;
00181   int number;
00182 
00183   unselect_all ();
00184 
00185   use = &(current ());
00186   use->unselect ();
00187   if (!Cmt::get_quiet ()) use->show_sub_uses (skip_discarded);
00188 
00189   if (Uses.size () > 0)
00190     {
00191       if (!Cmt::get_quiet ())
00192         {
00193           cout << "#\n";
00194           cout << "# Selection :\n";
00195         }
00196 
00197       //
00198       //  First move the CMT package to the end of the use set.
00199       //  (ie. used by everybody)
00200       //
00201       use = Use::find ("CMT");
00202       Use::move (use);
00203 
00204       for (number = Uses.size () - 1; number >= 0; number--)
00205         {
00206           use = Uses[number];
00207 
00208           if (use->discarded) continue;
00209 
00210           if (!use->located ())
00211             {
00212               if (!Cmt::get_quiet ())
00213                 {
00214                   cout << "# package " << use->package <<
00215                       " " << use->version << " " << use->path << 
00216                       " not found" <<
00217                       endl;
00218                 }
00219               CmtError::set (CmtError::package_not_found, use->package);
00220             }
00221           else
00222             {
00223               static const cmt_string empty;
00224               cmt_string p = use->real_path;
00225               if (use->path != "")
00226                 {
00227                   p.replace (use->path, empty);
00228                 }
00229               
00230               cout << prefix << use->package <<
00231                   " " << use->version <<
00232                   " " << use->path;
00233 
00234               if (!Cmt::get_quiet ()) 
00235                 {
00236                   if (p != "") cout << " (" << p << ")";
00237                   if (use->auto_imports == Off) cout << " (no_auto_imports)";
00238                 }
00239 
00240               cout << endl;
00241             }
00242         }
00243 
00244       if (Cmt::get_cmt_home () != "")
00245         {
00246           cout << prefix << CmtSystem::get_home_package () <<
00247               " " << Cmt::get_cmt_home () <<
00248               endl;
00249         }
00250 
00251       if (Cmt::get_cmt_user_context () != "")
00252         {
00253           cout << prefix << CmtSystem::get_user_context_package () <<
00254               " " << Cmt::get_cmt_user_context () <<
00255               endl;
00256         }
00257     }
00258 }
00259 
00266 class use_action_iterator
00267 {
00268 public:
00269 
00270   use_action_iterator ()
00271       {
00272         state = need_package;
00273         auto_imports = Unspecified;
00274       }
00275 
00276   void set (const cmt_string& w)
00277       {
00278         if (w == "-auto_imports")
00279           {
00280             auto_imports = On;
00281           }
00282         else if (w == "-no_auto_imports")
00283           {
00284             auto_imports = Off;
00285           }
00286         else if (w == "|")
00287           {
00288             state = need_version_alias;
00289           }
00290         else
00291           {
00292             switch (state)
00293               {
00294                 case need_package:
00295                   package = w;
00296                   state = need_version;
00297                   break;
00298                 case need_version:
00299                   version = w;
00300                   state = need_path;
00301                   break;
00302                 case need_path:
00303                   path = w;
00304                   state = finished;
00305                   break;
00306                 case need_version_alias:
00307                   version_alias = w;
00308                   state = need_path_alias;
00309                   break;
00310                 case need_path_alias:
00311                   path_alias = w;
00312                   state = finished;
00313                   break;
00314               }
00315           }
00316       }
00317 
00318   bool ok ()
00319       {
00320         if (package == "") return (false);
00321         if (CmtSystem::is_home_package (package, version)) return (false);
00322         if (CmtSystem::is_user_context_package (package, version)) return (false);
00323 
00324         return (true);
00325       }
00326 
00332   Use* get_use (Use* parent)
00333       {
00334         static Use::UsePtrVector& Uses = Use::uses ();
00335 
00336         if (version == "") version = "*";
00337 
00338         if (Cmt::get_debug ())
00339           {
00340             int i;
00341 
00342             cout << "use::action1> current=" << parent->package <<
00343                 " package=" << package << " ";
00344 
00345             for (i = 0; i < Uses.size (); i++)
00346               {
00347                 Use* u = Uses[i];
00348                 cout << u->package << " ";
00349               }
00350             cout << endl;
00351           }
00352 
00353         const Use& cu = Use::current ();
00354 
00364         ActionType action = Cmt::get_action ();
00365 
00366         if ((parent != 0) && 
00367             (parent->package != cu.package) &&
00368             (Cmt::get_scope () == ScopePrivate) &&
00369             (action != action_broadcast) &&
00370             (action != action_show_uses))
00371           {
00372             return (0);
00373           }
00374 
00375         // Here the version may contain wild cards
00376 
00377         UseContext save = UseContext::current ();
00378 
00379         if (Cmt::get_debug ())
00380           {
00381             cout << "before adding " << package <<"> auto_imports=" << auto_imports
00382                  << " (current was " << UseContext::get_current_auto_imports () << ")" 
00383                  << " (Cmt::scope=" << Cmt::get_scope () << ")"
00384                  << endl;
00385           }
00386 
00391         switch (auto_imports)
00392           {
00393             case Unspecified:
00394 
00395                 // unspecified => we forward the state saved in the current use context
00396 
00397               UseContext::set_current (UseContext::get_current_auto_imports ());
00398               break;
00399             case Off:
00400 
00401                 // off => the context becomes constrained to be off
00402 
00403               UseContext::set_current (Off);
00404               break;
00405             case On:
00406 
00407                 // on => if current context is off it is kept off
00408                 //       otherwise it is forced to on
00409 
00410               if (UseContext::get_current_auto_imports () != Off)
00411                 {
00412                   UseContext::set_current (On);
00413                 }
00414               break;
00415           }
00416 
00417           //UseContext::set_current (auto_imports);
00418         UseContext::set_current (Cmt::get_scope ());
00419 
00421         Use* new_use = Use::add (path, package, version, 
00422                                  version_alias, path_alias, parent,
00423                                  auto_imports);
00424 
00425         if (new_use != 0)
00426           {
00427             if (Cmt::get_debug ())
00428               {
00429                 cout << "after adding1 " << package << "> auto_imports=" << new_use->auto_imports << endl;
00430               }
00431 
00432             switch (new_use->auto_imports)
00433               {
00434                 case Unspecified:
00435                   new_use->auto_imports = UseContext::get_current_auto_imports ();
00436                   break;
00437                 case On:
00438                   break;
00439                 case Off:
00440                   if (UseContext::get_current_auto_imports () == On)
00441                     {
00453                         //new_use->auto_imports = On;
00454                       new_use->set_auto_imports (On);
00455                     }
00456                   break;
00457               }
00458 
00459 
00460             if (Cmt::get_debug ())
00461               {
00462                 cout << "after adding2 " << package << "> auto_imports=" << new_use->auto_imports << endl;
00463               }
00464 
00465             UseContext& c = UseContext::current ();
00466             c = save;
00467 
00468             Use::reorder (new_use, parent);
00469             
00470             if (Cmt::get_debug ())
00471               {
00472                 int i;
00473                 
00474                 cout << "use::action2> current=" << parent->package
00475                      << " package=" << package << " ";
00476 
00477                 for (i = 0; i < Uses.size (); i++)
00478                   {
00479                     Use* u = Uses[i];
00480                     cout << u->package << " ";
00481                   }
00482 
00483                 cout << endl;
00484               }
00485           }
00486 
00487         return (new_use);
00488       }
00489 
00490 private:
00491 
00492   enum
00493   {
00494     need_package,
00495     need_version,
00496     need_path,
00497     need_version_alias,
00498     need_path_alias,
00499     finished
00500   } state;
00501   
00502   State auto_imports;
00503 
00504   cmt_string package;
00505   cmt_string version;
00506   cmt_string path;
00507   cmt_string version_alias;
00508   cmt_string path_alias;
00509 };
00510 
00511 //----------------------------------------------------------
00512 Use* Use::action (const CmtSystem::cmt_string_vector& words, Use* parent)
00513 {
00514   Use* new_use;
00515 
00516   //
00517   // complete syntax : "use <package> <version> <path>"
00518   // minimal syntax  : "use <package>"
00519   //
00520   //  o if <version> is omitted then take any version available
00521   //  o <version> can be specified using "v*" or "v<n>r*" or "v<n>r<m>p*"
00522   //
00523   //  o the notation "v*" is preferred to omission (particularly since
00524   //    omission does not permit <path>)
00525   //
00526   if (words.size () < 2) return (0);
00527 
00528   use_action_iterator it;
00529 
00530   for (int i = 1; i < words.size (); i++)
00531     {
00532       const cmt_string& w = words[i];
00533       cmt_string ew = w;
00534 
00535       Symbol::expand (ew);
00536       if (ew != w)
00537         {
00538           CmtSystem::cmt_string_vector ws;
00539 
00540           CmtSystem::split (ew, " ", ws);
00541 
00542           for (int j = 0; j < ws.size (); ++j)
00543             {
00544               const cmt_string& ww = ws[j];
00545               it.set (ww);
00546             }
00547         }
00548       else
00549         {
00550           it.set (ew);
00551         }
00552     }
00553 
00554   if (!it.ok ()) return (0);
00555 
00556   static int level = 0;
00557 
00558   level++;
00559   new_use = it.get_use (parent);
00560   level--;
00561 
00562   return (new_use);
00563 }
00564 
00565 //----------------------------------------------------------
00566 void Use::author_action (const CmtSystem::cmt_string_vector& words)
00567 {
00568   if (author != "") author += "\n";
00569   for (int i = 1; i < words.size (); i++)
00570     {
00571       const cmt_string& w = words[i];
00572       
00573       if (i > 1) author += " ";
00574       author += w;
00575     }
00576 }
00577 
00578 //----------------------------------------------------------
00579 void Use::manager_action (const CmtSystem::cmt_string_vector& words)
00580 {
00581   if (manager != "") manager += "\n";
00582   for (int i = 1; i < words.size (); i++)
00583     {
00584       const cmt_string& w = words[i];
00585       
00586       if (i > 1) manager += " ";
00587       manager += w;
00588     }
00589 }
00590 
00591 //----------------------------------------------------------
00592 Use* Use::find (const cmt_string& package, 
00593                 const cmt_string& version, 
00594                 const cmt_string& path)
00595 {
00596   static UsePtrVector& Uses = uses ();
00597   static UseVector& AllUses = all_uses ();
00598 
00599   int use_index;
00600 
00601   if (AllUses.size () == 0) return (0);
00602 
00603   for (use_index = 0; use_index < Uses.size (); use_index++)
00604     {
00605       Use& use = (*Uses[use_index]);
00606 
00607       if (use.package == package)
00608         {
00609             // If the version argument is omitted then
00610             // take the first registered version
00611           if (version == "") return (&use);
00612           
00613             // Otherwise compare against specified_version and path
00614             //if ((use.specified_version == version) && 
00615             //  (use.specified_path == path)) return (&use);
00616           
00617             // what about comparing wild cards?
00618 
00619           if (use.specified_version == version) return (&use);
00620         }
00621     }
00622 
00623   return (0);
00624 }
00625 
00626 //----------------------------------------------------------
00627 //
00628 //  Move use to the end
00629 //
00630 //----------------------------------------------------------
00631 void Use::move (Use* use1)
00632 {
00633   static UsePtrVector& Uses = uses ();
00634 
00635   int use_index;
00636   Use* use;
00637   int found = 0;
00638 
00639   if (Uses.size () == 0) return;
00640   if (use1 == 0) return;
00641 
00642   //
00643   // On se positionne sur le pointeur.
00644   //
00645   for (use_index = 0; use_index < Uses.size (); use_index++)
00646     {
00647       use = Uses[use_index];
00648 
00649       if (use == use1)
00650         {
00651           found = 1;
00652           break;
00653         }
00654     }
00655 
00656   if (!found) return;
00657 
00658   //
00659   // On deplace tous les pointeurs d'une case en arriere
00660   //
00661   for (use_index++;
00662        use_index < Uses.size ();
00663        use_index++)
00664     {
00665       Uses[use_index - 1] = Uses[use_index];
00666     }
00667 
00668   //
00669   // use1 est donc replace en derniere position
00670   //
00671   {
00672     Uses[Uses.size () - 1] = use1;
00673   }
00674 }
00675 
00681 void Use::reorder (Use* use1, Use* use2)
00682 {
00683   static UsePtrVector& Uses = uses ();
00684 
00685   int use_index;
00686   int index1 = -1;
00687   int index2 = -1;
00688   Use* use;
00689 
00690   if (Uses.size () == 0) return;
00691   if (use1 == use2) return;
00692 
00693   //
00694   // First locate the two use objects into the Uses vector.
00695   //   -> index1 and index 2
00696   //
00697   for (use_index = 0; use_index < Uses.size (); use_index++)
00698     {
00699       use = (Use*) Uses[use_index];
00700 
00701       if (use == use1) index1 = use_index;
00702       if (use == use2) index2 = use_index;
00703     }
00704 
00705   if (Cmt::get_debug ())
00706     {
00707       cout << "Use::reorder> 1=" << index1 << " 2=" << index2 << endl;
00708     }
00709 
00710   //
00711   // Both objects must be installed in Uses before acting.
00712   //
00713   if (index1 == -1) return;
00714   if (index2 == -1) return;
00715 
00716   if (index2 < index1)
00717     {
00718       //
00719       // 2 is already before 1 so job is finished
00720       //
00721       return;
00722     }
00723   else
00724     {
00725       //
00726       // before : <a a a 1 b b b 2 c c c>
00727       //                 ^       ^
00728       //                 i1      i2
00729       //
00730       //  1) move "1 b b b" by one place to the right
00731       // thus :   <a a a 1 1 b b b c c c>
00732       //
00733       //  2) move "2" to [i1]
00734       //
00735       // after  : <a a a 2 1 b b b c c c>
00736       //
00737 
00738       use = use2;
00739 
00740       for (use_index = index2 - 1; use_index >= index1; use_index--)
00741         {
00742           Uses[use_index + 1] = Uses[use_index];
00743         }
00744 
00745       Uses[index1] = use;
00746     }
00747 }
00748 
00749 //----------------------------------------------------------
00750 void Use::clear_all ()
00751 {
00752   static UsePtrVector& Uses = uses ();
00753   static UseVector& AllUses = all_uses ();
00754 
00755   int use_index;
00756 
00757   for (use_index = 0; use_index < AllUses.size (); use_index++)
00758     {
00759       Use& use = AllUses[use_index];
00760       use.clear ();
00761     }
00762 
00763   Uses.clear ();
00764   AllUses.clear ();
00765 }
00766 
00767 //----------------------------------------------------------
00768 void Use::unselect_all ()
00769 {
00770   static UsePtrVector& Uses = uses ();
00771 
00772   int use_index;
00773 
00774   if (Uses.size () == 0) return;
00775 
00776   for (use_index = 0; use_index < Uses.size (); use_index++)
00777     {
00778       Use* use = Uses[use_index];
00779 
00780       if (use != 0)
00781         {
00782           use->unselect ();
00783         }
00784     }
00785 }
00786 
00787 //----------------------------------------------------------
00788 void Use::undiscard_all ()
00789 {
00790   static UsePtrVector& Uses = uses ();
00791 
00792   int use_index;
00793 
00794   if (Uses.size () == 0) return;
00795 
00796   for (use_index = 0; use_index < Uses.size (); use_index++)
00797     {
00798       Use* use = Uses[use_index];
00799 
00800       if (use != 0)
00801         {
00802           use->undiscard ();
00803         }
00804     }
00805 }
00806 
00807 //----------------------------------------------------------
00808 void Use::fill_macro_all (cmt_string& buffer, const cmt_string& suffix)
00809 {
00810   UsePtrVector& Uses = uses ();
00811 
00812   buffer = "macro_append use_";
00813   buffer += suffix;
00814   buffer += " \" ";
00815   (Use::current()).fill_macro (buffer, suffix);
00816 
00817   for (int number = 0; number < Uses.size (); number++)
00818     {
00819       Use* use = Uses[number];
00820       
00821       if (use->package == "CMT") continue;
00822       if (use->package == "methods") continue;
00823       if (use->discarded) continue;
00824       if (use->auto_imports == Off) continue;
00825 
00826       use->fill_macro (buffer, suffix);
00827     }
00828   
00829   buffer += "\"";
00830 }
00831 
00832 //----------------------------------------------------------
00833 Use::Use ()
00834 {
00835   done = false;
00836   discarded = false;
00837   auto_imports = Unspecified;
00838 
00839   clear ();
00840 }
00841 
00842 //----------------------------------------------------------
00843 Use::Use (const cmt_string& new_package,
00844           const cmt_string& new_version,
00845           const cmt_string& new_path)
00846 {
00847   auto_imports = Unspecified;
00848   m_located = false;
00849   set (new_package, new_version, new_path);
00850 }
00851 
00852 //----------------------------------------------------------
00853 Use::~Use ()
00854 {
00855   clear ();
00856 }
00857 
00858 //----------------------------------------------------------
00859 void Use::clear ()
00860 {
00861   specified_path = "";
00862   path      = "";
00863   package   = "";
00864   version   = "";
00865   author    = "";
00866   manager   = "";
00867   real_path = "";
00868 
00869   prefix    = "";
00870   style     = mgr_style;
00871   scope     = Cmt::get_scope ();
00872   done      = false;
00873   discarded = false;
00874   selected  = false;
00875   auto_imports = Unspecified;
00876 
00877   includes.clear ();
00878   include_path = "";
00879   scripts.clear ();
00880   apply_patterns.clear ();
00881   ignore_patterns.clear ();
00882 
00883   sub_uses.clear ();
00884   sub_use_scopes.clear ();
00885   sub_use_auto_imports.clear ();
00886 
00887   alternate_versions.clear ();
00888   alternate_paths.clear ();
00889 
00890   version_alias = "";
00891   path_alias    = "";
00892 
00893   m_located = false;
00894   m_has_native_version = false;
00895 }
00896 
00897 //----------------------------------------------------------
00898 void Use::set (const cmt_string& new_package,
00899                const cmt_string& new_version,
00900                const cmt_string& new_path,
00901                const cmt_string& new_version_alias,
00902                const cmt_string& new_path_alias)
00903 {
00904   clear ();
00905 
00906   package           = new_package;
00907   specified_path    = new_path;
00908   // specified_path.replace_all ("\\", "/");
00909 
00910   specified_version = new_version;
00911   version           = new_version;
00912   path              = specified_path;
00913   Symbol::expand (path);
00914   real_path         = "";
00915   style             = mgr_style;
00916   scope             = Cmt::get_scope ();
00917   done              = false;
00918   discarded         = false;
00919   Cmt::build_prefix (new_package, prefix);
00920 
00921   version_alias = new_version_alias;
00922   path_alias    = new_path_alias;
00923 }
00924 
00925 //----------------------------------------------------------
00926 void Use::change_path (const cmt_string& new_path)
00927 {
00928   // 
00929   // This methods changes real_path after an actual location
00930   // where this package/version has been found.
00931   //
00932 
00933   real_path = "";
00934 
00935   if (new_path != "")
00936     {
00937       if ((path.size () > 0) &&
00938           (!CmtSystem::absolute_path (path)))
00939         {
00940           real_path = new_path;
00941           real_path += CmtSystem::file_separator ();
00942           real_path += path;
00943         }
00944       else
00945         {
00946           real_path = new_path;
00947         }
00948       // real_path.replace_all ("\\", "/");
00949     }
00950   
00951   m_located = true;
00952 }
00953 
00954 //----------------------------------------------------------
00955 int Use::reach_package (const cmt_string& from_path)
00956 {
00957   //cerr << "Use::reach_package> (" << package << " " << version << ")from " << from_path << endl;
00958 
00959   //
00960   // We try to reach a package/version starting from from_path
00961   //
00962 
00963   // check if from_path is at least real
00964   if ((from_path != "") && !CmtSystem::cd (from_path)) return (0);
00965 
00966   // check in case from_path is a new search path 
00967   if (from_path != real_path)
00968     {
00969       // Move to that prefix only if it is a relative path.
00970       if ((path.size () > 0) && (!CmtSystem::absolute_path (path)))
00971         {
00972           if (!CmtSystem::cd (path))
00973             {
00974               return (0);
00975             }
00976         }
00977     }
00978 
00979   // Special treatment for CMTHOME package...
00980   if (package == CmtSystem::get_home_package ())
00981     {
00982       discarded = 1;
00983       if (!CmtSystem::test_file ("requirements"))
00984         {
00985           return (0);
00986         }
00987       else
00988         {
00989           return (1);
00990         }
00991     }
00992 
00993   // Special treatment for CMTUSERCONTEXT package...
00994   if (package == CmtSystem::get_user_context_package ())
00995     {
00996       discarded = 1;
00997       if (!CmtSystem::test_file ("requirements"))
00998         {
00999           return (0);
01000         }
01001       else
01002         {
01003           return (1);
01004         }
01005     }
01006 
01007   // Now from_path exists, try if the package exists there
01008   if (!CmtSystem::cd (package))
01009     {
01010       return (0);
01011     }
01012 
01013   if (!CmtSystem::cd (version))
01014     {
01015       //
01016       // The specified version cannot be found per-se
01017       // There are alternate possibilities when it contains wild cards
01018       //
01019       if ((version == "") ||
01020           (version.find ("*") != cmt_string::npos))
01021         {
01022           static CmtSystem::cmt_string_vector versions;
01023           static cmt_string name;
01024 
01025           name = ".";
01026           name += CmtSystem::file_separator ();
01027           if (version == "") name += "*";
01028           else name += version;
01029 
01030           CmtSystem::scan_dir (name, versions);
01031           
01032           int i;
01033           
01034           for (i = 0; i < versions.size (); i++)
01035             {
01036               const cmt_string& vers = versions[i];
01037               
01038               if (Cmt::get_debug ())
01039                 {
01040                   cout << "     ... version " << vers << " exists" << endl;
01041                 }
01042 
01043               CmtSystem::basename (vers, name);
01044               
01045               int v;
01046               int r;
01047               int p;
01048               
01049               if (CmtSystem::is_version_directory (name, v, r, p))
01050                 {
01051                   /*
01052                     This check is not sufficient !! We need to check in addition
01053                     that the selected directory is really the start of a true CMT
01054                     package (ie with either /mgr/requirements or /cmt/requirements below)
01055                   */
01056 
01057                   cmt_string req;
01058 
01059                   req = name;
01060                   req += CmtSystem::file_separator ();
01061                   req += "mgr";
01062                   req += CmtSystem::file_separator ();
01063                   req += "requirements";
01064 
01065                   if (!CmtSystem::test_file (req))
01066                     {
01067                       req = name;
01068                       req += CmtSystem::file_separator ();
01069                       req += "cmt";
01070                       req += CmtSystem::file_separator ();
01071                       req += "requirements";
01072 
01073                       if (!CmtSystem::test_file (req)) continue;
01074                     }
01075 
01076                   cmt_string& new_v = alternate_versions.add ();
01077                   new_v = name;
01078                   cmt_string& new_p = alternate_paths.add ();
01079                   new_p = from_path;
01080                 }
01081             }
01082         }
01083 
01084       if (Cmt::get_debug ())
01085         {
01086           cout << "  ... end of version scan" << endl;
01087         }
01088 
01089         //
01090         //  We have now the list of possible alternate versions. However
01091         // we return that the expected package/version was not found (yet).
01092         //
01093 
01094       return (0);
01095     }
01096 
01097   //cerr << "  ... version " << version << " exists" << endl;
01098 
01099   // Now we have met the exact specified version!
01100   if (!CmtSystem::test_file ("cmt/requirements"))
01101     {
01102       if (!CmtSystem::test_file ("mgr/requirements"))
01103         {
01104           return (0);
01105         }
01106       else
01107         {
01108           CmtSystem::cd ("mgr");
01109           style = mgr_style;
01110         }
01111     }
01112   else
01113     {
01114       CmtSystem::cd ("cmt");
01115       style = cmt_style;
01116     }
01117 
01118   return (1);
01119 }
01120 
01121 //----------------------------------------------------------
01122 bool Use::move_to ()
01123 {
01124   if (m_located)
01125     {
01126       //
01127       // The real path where this version/package can be found 
01128       // has already been resolved. We thus first go there.
01129       //
01130 
01131       if (Cmt::get_debug ())
01132         {
01133           cout << "move_to1> " << real_path << endl;
01134         }
01135 
01136       reach_package (real_path);
01137 
01138       return (true);
01139     }
01140 
01141   cmt_string expanded_path = path;
01142 
01143   //
01144   // Try here.
01145   //
01146   if (expanded_path == "")
01147     {
01148       if (reach_package (""))
01149         {
01150           if (Cmt::get_debug ())
01151             {
01152               cout << "move_to2> " << expanded_path << endl;
01153             }
01154 
01155           change_path (expanded_path);
01156 
01157           return (true);
01158         }
01159       else if (alternate_versions.size () > 0)
01160         {
01161           if (select_alternate ()) 
01162             {
01163               if (Cmt::get_debug ())
01164                 {
01165                   cout << "move_to5> " << real_path << endl;
01166                 }
01167               
01168               return (true);
01169             }
01170         }
01171     }
01172       
01173   //
01174   // If the path specified in this use is a true absolute path,
01175   // then we search the package from there first.
01176   //
01177   if (CmtSystem::absolute_path (expanded_path))
01178     {
01179       if (reach_package (expanded_path))
01180         {
01181           if (Cmt::get_debug ())
01182             {
01183               cout << "move_to3> " << expanded_path << endl;
01184             }
01185 
01186           change_path (expanded_path);
01187 
01188           return (true);
01189         }
01190       else if (alternate_versions.size () > 0)
01191         {
01192           if (select_alternate ()) 
01193             {
01194               if (Cmt::get_debug ())
01195                 {
01196                   cout << "move_to5> " << real_path << endl;
01197                 }
01198               
01199               return (true);
01200             }
01201         }
01202     }
01203       
01204   //
01205   // Second try is among the CMTPATHs
01206   //
01207       
01208   static const CmtSystem::cmt_string_vector& search_path = Cmt::get_cmt_path ();
01209   int path_index = 0;
01210       
01211   for (path_index = 0; path_index < search_path.size (); path_index++)
01212     {
01213       const cmt_string& next_path = search_path[path_index];
01214       
01215       alternate_versions.clear ();
01216       alternate_paths.clear ();
01217 
01218       if (reach_package (next_path))
01219         {
01220           if (Cmt::get_debug ())
01221             {
01222               cout << "move_to4> " << next_path << endl;
01223             }
01224 
01225           change_path (next_path);
01226 
01227           return (true);
01228         }
01229       else if (alternate_versions.size () > 0)
01230         {
01231           if (select_alternate ()) 
01232             {
01233               if (Cmt::get_debug ())
01234                 {
01235                   cout << "move_to5> " << real_path << endl;
01236                 }
01237               
01238               return (true);
01239             }
01240         }
01241     }
01242   
01243 
01244   return (false);
01245 }
01246 
01247 //----------------------------------------------------------
01248 bool Use::select_alternate ()
01249 {
01250   int i;
01251 
01252   int v0 = 0;
01253   int r0 = 0;
01254   int p0 = 0;
01255 
01256   int v = 0;
01257   int r = 0;
01258   int p = 0;
01259 
01260   int selected_index = -1;
01261 
01262   for (i = 0; i < alternate_versions.size (); i++)
01263     {
01264       cmt_string& name = alternate_versions[i];
01265 
01266         /*
01267       if (CmtSystem::getenv ("CMTTESTUSEWILDCARDS") != "")
01268         {
01269           cout << "select_alternate[" << this << "]> package " << package << 
01270               " sv=" << specified_version << 
01271               " v=" << version << 
01272               " av[" << i << "]=" << name << endl;
01273         }
01274         */
01275 
01276       if (i == 0)
01277         {
01278           CmtSystem::is_version_directory (name, v0, r0, p0);
01279           selected_index = 0;
01280         }
01281       else
01282         {
01283           CmtSystem::is_version_directory (name, v, r, p);
01284 
01285           if (v > v0)
01286             {
01287               selected_index = i;
01288               v0 = v;
01289               r0 = r;
01290               p0 = p;
01291             }
01292           else if (v == v0)
01293             {
01294               if (r > r0)
01295                 {
01296                   selected_index = i;
01297                   r0 = r;
01298                   p0 = p;
01299                 }
01300               else if (r == r0)
01301                 {
01302                   if (p > p0)
01303                     {
01304                       selected_index = i;
01305                       p0 = p;
01306                     }
01307                 }
01308             }
01309         }
01310     }
01311 
01312   if (selected_index >= 0)
01313     {
01314       if (CmtSystem::cd (alternate_paths[selected_index]))
01315         {
01316           version = alternate_versions[selected_index];
01317           if (reach_package (alternate_paths[selected_index]))
01318             {
01319                 /*
01320               if (CmtSystem::getenv ("CMTTESTUSEWILDCARDS") != "")
01321                 {
01322                   cout << "select_alternate2> package " << package << 
01323                       " sv=" << specified_version << 
01324                       " v=" << version << endl;
01325                 }
01326                 */
01327 
01328               if (Cmt::get_debug ())
01329                 {
01330                   cout << "select_alternate> " << alternate_paths[selected_index] << endl;
01331                 }
01332 
01333               change_path (alternate_paths[selected_index]);
01334               return (true);
01335             }
01336         }
01337     }
01338 
01339   return (false);
01340 }
01341 
01342 //----------------------------------------------------------
01343 bool Use::need_new (const cmt_string& path,
01344                     const cmt_string& package,
01345                     const cmt_string& version,
01346                     Use** old_use)
01347 {
01348   bool has_wild_card = (version.find ("*") != cmt_string::npos);
01349 
01350   static UsePtrVector& Uses = uses ();
01351   static UseVector& AllUses = all_uses ();
01352 
01353   bool result = true;
01354   Use* found = 0;
01355 
01356   int use_index;
01357 
01358   if (old_use != 0) *old_use = 0;
01359   if (AllUses.size () == 0) return (true);
01360 
01361   for (use_index = 0; use_index < Uses.size (); use_index++)
01362     {
01363       Use& use = (*Uses[use_index]);
01364 
01365       if (use.package != package) continue;
01366 
01367       found = &use;
01368 
01369       /*
01370         cerr << "Use::need_new> (" << package
01371         << ") requested version=" << version
01372         << " vs existing=" << use->version
01373         << " (specified as " << use->specified_version
01374         << ")" << endl;
01375       */
01376 
01377       bool use_has_wild_card = (use.specified_version.find ("*") != cmt_string::npos);
01378 
01379       if (has_wild_card && !use_has_wild_card)
01380         {
01381           //cerr << "  ... requested wildcarded loses against existing explicit" << endl;
01382           result = false;
01383           break;
01384         }
01385 
01386       if ((version == use.specified_version) &&
01387           (path == use.specified_path))
01388         {
01389           // exactly same version and path!
01390           result = false;
01391           break;
01392         }
01393 
01394       // requested explicit wins against existing wildcarded
01395       // In any case when paths are different, consider the new one.
01396       // Now paths are identical (thus versions are different).
01397     }
01398 
01399   if (old_use != 0) *old_use = found;
01400   return (result);
01401 }
01402 
01403 //----------------------------------------------------------
01404 //
01405 //  Here the version which is provided here is the specified version.
01406 // It may contain wild cards or it may be simply empty.
01407 //
01408 //----------------------------------------------------------
01409 Use* Use::create (const cmt_string& path,
01410                   const cmt_string& package,
01411                   const cmt_string& version,
01412                   const cmt_string& version_alias,
01413                   const cmt_string& path_alias)
01414 {
01415   static UseVector& AllUses = all_uses ();
01416 
01417   // We first look in the database.
01418   for (int use_index = 0; use_index < AllUses.size (); use_index++)
01419     {
01420       Use& use = AllUses[use_index];
01421 
01422       if (use.package == package)
01423         {
01424           if ((use.specified_version == version) && 
01425               (use.specified_path == path)) return (&use);
01426         }
01427     }
01428 
01429   // We now really create a new Use entry.
01430 
01431   Use& use_object = AllUses.add ();
01432   use_object.set (package, version, path, version_alias, path_alias);
01433 
01434   return (&use_object);
01435 }
01436 
01437 //----------------------------------------------------------
01438 //  Add a use request into the database.
01439 //
01440 //  o If a use request already exist in the database,
01441 //    check the version compatibility
01442 //
01443 //----------------------------------------------------------
01444 Use* Use::add (const cmt_string& path,
01445                const cmt_string& package,
01446                const cmt_string& version,
01447                const cmt_string& version_alias,
01448                const cmt_string& path_alias,
01449                Use* context_use,
01450                State specified_auto_imports)
01451 {
01452   static UsePtrVector& Uses = uses ();
01453 
01454   bool do_need_new = false;
01455 
01456   Use* old_use = 0;
01457   Use* use = 0;
01458 
01459   do_need_new = need_new (path, package, version, &old_use);
01460 
01461   /*
01462     if (old_use != 0)
01463     {
01464     cout << "add> old_use " << old_use->package <<
01465     " " << old_use->version <<
01466     " " << old_use->path <<
01467     endl;
01468     }
01469   */
01470 
01471   if (do_need_new)
01472     {
01473       use = create (path, package, version, version_alias, path_alias);
01474     }
01475   else
01476     {
01477       // Since we don't need a new Use, it means that old_use exists !
01478       use = old_use;
01479       old_use = 0;
01480     }
01481 
01482   if (package == CmtSystem::get_home_package ())
01483     {
01484       return (use);
01485     }
01486 
01487   if (package == CmtSystem::get_user_context_package ())
01488     {
01489       return (use);
01490     }
01491 
01492   cmt_string here = CmtSystem::pwd ();
01493 
01494     //
01495     // Store the specified sub_uses. Some of them may become discarded
01496     // later on.
01497     //
01498   if (context_use != 0)
01499     {
01500       context_use->sub_uses.push_back (use);
01501       context_use->sub_use_scopes.push_back (Cmt::get_scope ());
01502       context_use->sub_use_auto_imports.push_back (specified_auto_imports);
01503 
01504       if (Cmt::get_debug ())
01505         {
01506           cout << "Use::add context(" << context_use->package << ") "
01507                << "[u:" << package
01508                << " s:" << Cmt::get_scope ()
01509                << " ai:" << specified_auto_imports
01510                << "]" << endl;
01511         }
01512     }
01513 
01514   /*
01515    *   Now we have a Use object. If it is a new one, we have to
01516    *    1) understand if it exists physically
01517    *    2) it is better than the old ones.
01518    *
01519    *   Here, we may have :
01520    *    1) old_use = 0 
01521    *         there was no Use object before for this package
01522    *         the existing one is fine
01523    *
01524    *    2) old_use != 0 
01525    *         we have created a new Use (which has to be validated)
01526    */
01527 
01528   bool found = use->move_to ();
01529 
01530   if (Cmt::get_debug ())
01531     {
01532       cout << "add> use " << use->package 
01533            << " " << use->version
01534            << " " << use->path
01535            << " found=" << found
01536            << endl;
01537     }
01538       
01539   if (!found)
01540     {
01541       if (!Cmt::get_quiet ())
01542         {
01543           cerr << "#(Warning) package " << use->package <<
01544             " " << use->version << " " << use->path << 
01545             " not found" <<
01546             endl;
01547         }
01548 
01549       CmtError::set (CmtError::package_not_found, use->package);
01550       use = 0;
01551     }
01552 
01553   if ((old_use != 0) && (use != old_use))
01554     {
01555       /*
01556        *    There was another version of this Use. But a new one was created due to 
01557        *   some criteria.
01558        *    New we are going to apply the version strategy to make the final selection.
01559        */
01560 
01561       /*
01562         if (CmtSystem::getenv ("CMTTESTUSEWILDCARDS") != "")
01563         {
01564         cout << "select? [" << use << "] vs old_use[" << old_use << "] " << old_use->package <<
01565         " " << old_use->version <<
01566         " " << old_use->path <<
01567         endl;
01568         }
01569       */
01570 
01571       if (!found)
01572         {
01573           /*
01574            *  This new Use does not correspond to any physical package.
01575            *  let's simply discard it 
01576            */
01577 
01578           use->discard ();
01579           use = old_use;
01580           found = use->move_to ();
01581         }
01582       else
01583         {
01584             //
01585             //  This new version is different from the old one
01586             // thus we have to choose
01587             //
01588           VersionSelector& selector = VersionSelector::instance ();
01589           Use* selected_use = selector.operate (old_use, use);
01590 
01591             //
01592             // Some situations managed by selector.operate happen
01593             // to fail discarding the rejected Use.
01594             //
01595           if (use != selected_use) 
01596             {
01597               use->discard ();
01598             }
01599           
01600           use = selected_use;
01601 
01602           /*
01603            *   current directory is moved to the selected one
01604            */
01605           found = use->move_to ();
01606         }
01607     }
01608 
01609     //
01610     // The following statement is no longer considered as useful.
01611     // It is commented. But we should clarify why it was really needed!
01612     //
01613     //use->undiscard ();
01614 
01615   if (found)
01616     {
01617       bool registered = false;
01618       const Use& cu = Use::current ();
01619 
01620       //
01621       // A pointer to this new object is also added or replaced.
01622       //
01623       if ((use != &cu) && (package == cu.package))
01624         {
01625             // This is a recursive call to the current package!!
01626           registered = true;
01627           use->done = true;
01628         }
01629       else
01630         {
01631           for (int i = 0; i < Uses.size(); i++)
01632             {
01633               Use* u = Uses[i];
01634               
01635               if (u->package == package)
01636                 {
01637                   registered = true;
01638                   Uses[i] = use;
01639                   break;
01640                 }
01641             }
01642         }
01643       
01644       if (!registered) Uses.push_back (use);
01645 
01646       if (!use->done && Cmt::get_recursive ())
01647         {
01648           use->done = true;
01649 
01650           /*
01651             if (CmtSystem::getenv ("CMTTESTUSEWILDCARDS") != "")
01652             {
01653             for (int use_index = 0; use_index < Uses.size (); use_index++)
01654             {
01655             Use* u = (Use*) Uses[use_index];
01656             cout << "  use[" << use_index << "] p=" << u->package <<
01657             " v=" << u->version <<
01658             " discarded=" << u->discarded <<
01659             " selected=" << u->selected <<
01660             endl;
01661             }
01662             
01663             cout << "parsing at " << CmtSystem::pwd () << endl;
01664             }
01665           */
01666           
01673           //Cmt::parse_requirements ("uses.log", use);
01674           
01675           if (Cmt::get_debug ())
01676             {
01677               cout << "Parsing requirements file at " << CmtSystem::pwd () << endl;
01678             }
01679           
01680           Cmt::parse_requirements ("requirements", use);
01681         }
01682     }
01683 
01684   CmtSystem::cd (here);
01685 
01686   return (use);
01687 }
01688 
01689 //----------------------------------------------------------
01690 void Use::discard ()
01691 {
01692   discarded = true;
01693 }
01694 
01695 //----------------------------------------------------------
01696 void Use::undiscard ()
01697 {
01698   discarded = false;
01699 }
01700 
01701 //----------------------------------------------------------
01702 void Use::select ()
01703 {
01704   selected = true;
01705 }
01706 
01707 //----------------------------------------------------------
01708 void Use::unselect ()
01709 {
01710   selected = false;
01711 }
01712 
01713 //----------------------------------------------------------
01714 bool Use::is_selected ()
01715 {
01716   return (selected);
01717 }
01718 
01725 bool Use::is_client (const cmt_string& used_package,
01726                      const cmt_string& used_version)
01727 {
01728   // A package is client of itself
01729   if ((package == used_package) &&
01730       (version == used_version)) return (true);
01731 
01732   if (discarded) return (false);
01733 
01734   int i;
01735 
01736   for (i = 0; i < sub_uses.size (); i++)
01737     {
01738       Use* use = sub_uses[i];
01739       if (use == 0) continue;
01740 
01741       if ((use->package == used_package) &&
01742           (use->version == used_version)) return (true);
01743 
01744       /*
01745         if (use->is_client (used_package, used_version))
01746         {
01747         return (true);
01748         }
01749       */
01750     }
01751 
01752   return (false);
01753 }
01754 
01755 //----------------------------------------------------------
01756 void Use::apply_global_patterns ()
01757 {
01758   int i;
01759 
01760   Pattern::PatternVector& vector = Pattern::patterns ();
01761 
01762   for (i = 0; i < vector.size (); i++)
01763     {
01764       Pattern& p = vector[i];
01765 
01766       if (p.global)
01767         {
01768           p.apply (this);
01769         }
01770     }
01771 }
01772 
01773 //----------------------------------------------------------
01774 void Use::set_include_path (const cmt_string& new_path)
01775 {
01776   include_path = new_path;
01777 }
01778 
01779 //----------------------------------------------------------
01780 void Use::fill_includes_macro (cmt_string& buffer) const
01781 {
01782   if (include_path == "")
01783     {
01784       buffer += "$(ppcmd)\"$(";
01785       buffer += package;
01786       buffer += "_root)";
01787       buffer += CmtSystem::file_separator ();
01788       buffer += "src\" ";
01789     }
01790   else if (include_path != "none")
01791     {
01792       buffer += "$(ppcmd)\"";
01793       buffer += include_path;
01794       buffer += "\" ";
01795     }
01796   
01797   for (int i = 0; i < includes.size (); i++)
01798     {
01799       Include& incl = includes[i];
01800       
01801       buffer += "$(ppcmd)\"";
01802       buffer += incl.name;
01803       buffer += "\" ";
01804     }
01805 }
01806 
01807 //----------------------------------------------------------
01808 void Use::fill_macro (cmt_string& buffer, const cmt_string& suffix) const
01809 {
01810   buffer += " $(";
01811   buffer += package;
01812   buffer += "_";
01813   buffer += suffix;
01814   buffer += ") ";
01815 }
01816 
01821 Use* Use::get_selected_version ()
01822 {
01823   static Use::UsePtrVector& Uses = uses ();
01824 
01825     //cout << "get_selected_version for package " << package << endl;
01826 
01827   if (!discarded) return (this);
01828 
01829   for (int i = 0; i < Uses.size (); i++)
01830     {
01831       Use* u = Uses[i];
01832       if (u == 0) continue;
01833       if (u->discarded) continue;
01834       if (u->package == package) 
01835         {
01836             //cout << "  got a version" << endl;
01837           return (u);
01838         }
01839     }
01840 
01841   return (0);
01842 }
01843 
01844 void Use::set_auto_imports (State new_state)
01845 {
01846   if (Cmt::get_debug ())
01847     {
01848       cout << "Use::set_auto_imports>(" << package << ") " 
01849            << auto_imports << " -> " << new_state << endl;
01850     }
01851 
01852   if (auto_imports == new_state) return;
01853   
01854   State old_state = auto_imports;
01855   
01856   auto_imports = new_state;
01857 
01858     // We propagate only when we switch from Off to On
01859 
01860   if ((old_state == Off) && (new_state == On))
01861     {
01862       cmt_string s;
01863       static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
01864 
01865       if (Cmt::get_debug ())
01866         {
01867           s = "Use::set_auto_imports>(";
01868           s += package;
01869           s += ") ";
01870 
01871           cout << s << endl;
01872         }
01873 
01874       for (int i = 0; i < sub_uses.size (); i++)
01875         {
01876           Use* u = sub_uses[i];
01877           State state = sub_use_auto_imports[i];
01878           
01879           if (Cmt::get_debug ())
01880             {
01881               s += " ";
01882               s += u->package;
01883               s += "(";
01884               s += state_text[state];
01885               s += ")";
01886             }
01887 
01888           if (state == Unspecified)
01889             {
01890               u->set_auto_imports (On);
01891             }
01892         }
01893           
01894       if (Cmt::get_debug ())
01895         {
01896           cout << s << endl;
01897         }
01898     }
01899 }
01900 
01901 void Use::set_native_version (bool state)
01902 {
01903   m_has_native_version = state;
01904 }
01905 
01906 bool Use::has_native_version () const
01907 {
01908   return (m_has_native_version);
01909 }
01910 
01911 //----------------------------------------------------------
01912 bool Use::get_paths (Use* to, UsePtrVector& list)
01913 {
01914   bool found = false;
01915   bool cycle = false;
01916 
01917   static int level = 0;
01918   static UsePtrVector stack;
01919 
01920   if (level == 0)
01921     {
01922       stack.clear ();
01923     }
01924 
01925   for (int k = 0; k < stack.size (); k++)
01926     {
01927       Use* u = stack[k];
01928       if (u == this) return (false);
01929     }
01930 
01931   if (stack.size () <= level)
01932     {
01933       stack.push_back (this);
01934     }
01935   else
01936     {
01937       stack[level] = this;
01938     }
01939 
01940     // First figure out whether 'to' is used by 'this'.
01941 
01942   if (Cmt::get_debug ())
01943     {
01944       cout << "Use::get_paths." << level << ">" << package << " list[" << list.size () << "]" << endl;
01945     }
01946 
01947   if (this == to)
01948     {
01949       found = true;
01950     }
01951   else
01952     {
01953       for (int n = 0; n < sub_uses.size (); n++)
01954         {
01955           Use* use = sub_uses[n];
01956 
01957           if (use == 0) continue;
01958 
01959           if (use->discarded)
01960             {
01961               Use* u;
01962 
01963               u = use->get_selected_version ();
01964               if (u == 0) continue;
01965 
01966               use = u;
01967             }
01968 
01969           cycle = false;
01970       
01971             // This use must not be already in the list (protection against cycles)
01972 
01973           for (int m = 0; m < list.size (); m++)
01974             {
01975               Use* u = list[m];
01976               if (u == use)
01977                 {
01978                   cycle = true;
01979                   break;
01980                 }
01981             }
01982 
01983           if (cycle) 
01984             {
01985               found = true;
01986               continue;
01987             }
01988 
01989           level++;
01990           bool r = use->get_paths (to, list);
01991           level--;
01992 
01993           if (r)
01994             {
01995               found = true;
01996             }
01997         }
01998     }
01999 
02000   if (found)
02001     {
02002       cycle = false;
02003 
02004       for (int m = 0; m < list.size (); m++)
02005         {
02006           Use* u = list[m];
02007           if (u == this)
02008             {
02009               cycle = true;
02010               break;
02011             }
02012         }
02013 
02014       if (!cycle)
02015         {
02016           list.push_back (this);
02017         }
02018     }
02019 
02020   return (found);  
02021 }
02022 
02023 //----------------------------------------------------------
02024 bool Use::located () const
02025 {
02026   return (m_located);
02027 }
02028 
02029 //----------------------------------------------------------
02030 void Use::show_sub_uses (bool skip_discarded)
02031 {
02032   int n;
02033   Use* use;
02034   static int level = 0;
02035 
02036   if (skip_discarded && discarded) return;
02037 
02038   if (level > 0)
02039     {
02040       cout << "# ";
02041       for (n = 0; n < (level-1); n++) cout << "  ";
02042 
02043       cout << "use " << package << " " << specified_version;
02044 
02045       if (specified_path != "") cout << " " << specified_path;
02046 
02047       if (version_alias != "")
02048         {
02049           cout << " | " << version_alias << " " << path_alias;
02050         }
02051 
02052       if (scope == ScopeUnspecified) cout << " unspecified";
02053       else if (scope != ScopePublic) cout << " (private)";
02054       //else cout << " private";
02055 
02056       if (auto_imports == Off) cout << " (no_auto_imports)";
02057 
02058       if (m_has_native_version)
02059         {
02060           cmt_string n = package;
02061           n += "_native_version";
02062 
02063           Symbol* s = Symbol::find (n);
02064           if (s != 0)
02065             {
02066               cmt_string value = s->resolve_macro_value ();
02067               cout << " (native_version=" << value << ")";
02068             }
02069         }
02070 
02071       cout << endl;
02072     }
02073 
02074   if (selected) return;
02075   selected = true;
02076 
02077   level++;
02078   for (n = 0; n < sub_uses.size (); n++)
02079     {
02080       use = sub_uses[n];
02081       if (use == 0) continue;
02082 
02083       ScopeType saved_scope = use->scope;
02084       State saved_state = use->auto_imports;
02085 
02086       use->scope = sub_use_scopes[n];
02087       use->auto_imports = sub_use_auto_imports[n];
02088 
02089       use->show_sub_uses (skip_discarded);
02090 
02091       use->scope = saved_scope;
02092       use->auto_imports = saved_state;
02093     }
02094   level--;
02095 }
02096 
02097 //----------------------------------------------------------
02098 Use& Use::current ()
02099 {
02100   static UseVector& AllUses = all_uses ();
02101   static Use* current_use = 0;
02102 
02103   if ((current_use == 0) || (AllUses.size () == 0))
02104     {
02105       Use& use_object = AllUses.add ();
02106       current_use = &use_object;
02107     }
02108 
02109   return (*current_use);
02110 }
02111 
02112 //----------------------------------------------------------
02113 const Use& Use::const_current ()
02114 {
02115   const Use& use = Use::current ();
02116 
02117   return (use);
02118 }
02119 
02120 //----------------------------------------------------------
02121 Use::UseVector& Use::all_uses ()
02122 {
02123   static Database& db = Database::instance ();
02124   static UseVector& AllUses = db.all_uses ();
02125 
02126   return (AllUses);
02127 }
02128 
02129 //----------------------------------------------------------
02130 Use::UsePtrVector& Use::uses ()
02131 {
02132   static Database& db = Database::instance ();
02133   static UsePtrVector& Uses = db.uses ();
02134 
02135   return (Uses);
02136 }
02137 
02138 //----------------------------------------------------------
02139 VersionSelector& VersionSelector::instance ()
02140 {
02141   static BestFitSelector best_fit;
02142   static BestFitNoCheckSelector best_fit_no_check;
02143   static FirstChoiceSelector first_choice;
02144   static LastChoiceSelector last_choice;
02145   static KeepAllSelector keep_all;
02146 
02147   switch (Cmt::get_current_strategy ())
02148     {
02149     case BestFit:
02150       return (best_fit);
02151     case BestFitNoCheck:
02152       return (best_fit_no_check);
02153     case FirstChoice:
02154       return (first_choice);
02155     case LastChoice:
02156       return (last_choice);
02157     case KeepAll:
02158       return (keep_all);
02159     default:
02160       return (best_fit);
02161     }
02162 }
02163 
02164 //----------------------------------------------------------
02165 //
02166 //  Check if the specified version is better than the
02167 //  current one.
02168 //
02169 //----------------------------------------------------------
02170 Use* BestFitSelector::operate (Use* ref_use, Use* new_use)
02171 {
02172   Use* selected = ref_use;
02173 
02174   int old_v = -1;
02175   int old_r = -1;
02176   int old_p = -1;
02177   cmt_string old_pp;
02178 
02179   int new_v = -1;
02180   int new_r = -1;
02181   int new_p = -1;
02182   cmt_string new_pp;
02183 
02184   int alias_v = -1;
02185   int alias_r = -1;
02186   int alias_p = -1;
02187   cmt_string alias_pp;
02188 
02189   enum { no_alias, new_has_alias, ref_has_alias } has_alias = no_alias;
02190 
02191   CmtSystem::is_version_directory (ref_use->version, old_v, old_r, old_p);
02192   old_pp = ref_use->path;
02193 
02194   CmtSystem::is_version_directory (new_use->version, new_v, new_r, new_p);
02195   new_pp = new_use->path;
02196 
02197   if (new_use->version_alias != "")
02198     {
02199       has_alias = new_has_alias;
02200       CmtSystem::is_version_directory (new_use->version_alias, 
02201                                        alias_v, alias_r, alias_p);
02202       alias_pp = new_use->path_alias;
02203     }
02204   else if (ref_use->version_alias != "")
02205     {
02206       has_alias = ref_has_alias;
02207       CmtSystem::is_version_directory (ref_use->version_alias, 
02208                                        alias_v, alias_r, alias_p);
02209       alias_pp = ref_use->path_alias;
02210     }
02211 
02212   ref_use->undiscard ();
02213   new_use->undiscard ();
02214 
02215   if (new_v != old_v)
02216     {
02217       if (has_alias != no_alias)
02218         {
02219           if (has_alias == new_has_alias)
02220             {
02221               new_v = alias_v;
02222               new_r = alias_r;
02223               new_p = alias_p;
02224               new_pp = alias_pp;
02225             }
02226           else if (has_alias == ref_has_alias)
02227             {
02228               old_v = alias_v;
02229               old_r = alias_r;
02230               old_p = alias_p;
02231               old_pp = alias_pp;
02232             }
02233         }
02234     }
02235 
02236   if (new_v != old_v)
02237     {
02238       if (!Cmt::get_quiet ())
02239         cout << "# Required version " << new_use->version <<
02240           " of package " << ref_use->package <<
02241           " incompatible with selected version " << ref_use->version <<
02242           endl;
02243 
02244       CmtError::set (CmtError::version_conflict, "BestFitSelector::operate> ");
02245 
02246       if (ref_use != new_use) new_use->discard ();
02247     }
02248   else if (new_r < old_r)
02249     {
02250       //
02251       // we plan to discard new_use, but if it was specified as explicit 
02252       // and ref_use was wildcarded then new_use will win !!
02253       //
02254       // So then we'll have to understand where are the wild
02255       // cards... If they are on v or r, then we consider them.
02256       // 
02257       //
02258 
02259 
02260       bool new_is_wildcarded = false;
02261       bool ref_is_wildcarded = false;
02262 
02263       if (new_use->specified_version.find ("*") != cmt_string::npos)
02264         {
02265           int nv = -1;
02266           int nr = -1;
02267           int np = -1;
02268 
02269           CmtSystem::is_version_directory (new_use->specified_version, nv, nr, np);
02270           if ((nv == -1) || (nr == -1)) new_is_wildcarded = true;
02271         }
02272 
02273       if (ref_use->specified_version.find ("*") != cmt_string::npos)
02274         {
02275           int nv = -1;
02276           int nr = -1;
02277           int np = -1;
02278 
02279           CmtSystem::is_version_directory (ref_use->specified_version, nv, nr, np);
02280           if ((nv == -1) || (nr == -1)) new_is_wildcarded = true;
02281         }
02282 
02283       if (!ref_is_wildcarded && new_is_wildcarded)
02284         {
02285           if (ref_use != new_use) ref_use->discard ();
02286           selected = new_use;
02287           selected->done = false; // Will read the new requirements
02288         }
02289       else
02290         {
02291           if (!Cmt::get_quiet ())
02292             cout << "# keep release " << ref_use->version <<
02293               " of package " << ref_use->package <<
02294               " (ignore release " << new_use->version << ")" <<
02295               endl;
02296 
02297           if (ref_use != new_use) new_use->discard ();
02298         }
02299     }
02300   else if (new_r > old_r)
02301     {
02302       if (!Cmt::get_quiet ())
02303         {
02304           cout << "# Select release " << new_use->version <<
02305             " of package " << ref_use->package <<
02306             " instead of existing " << ref_use->version <<
02307             endl;
02308         }
02309 
02310       if (ref_use != new_use) ref_use->discard ();
02311       selected = new_use;
02312       selected->done = false; // Will read the new requirements
02313     }
02314   else if (new_p > old_p)
02315     {
02316       if (!Cmt::get_quiet ())
02317         {
02318           cout << "# Select patch " << new_use->version <<
02319             " of package " << ref_use->package <<
02320             " instead of existing " << ref_use->version <<
02321             endl;
02322         }
02323 
02324       if (ref_use != new_use) ref_use->discard ();
02325       selected = new_use;
02326       selected->done = false; // Will read the new requirements
02327     }
02328   else if (new_pp != old_pp) // same version-r-p but from different path
02329     {
02330       if (ref_use != new_use) ref_use->discard ();
02331       selected = new_use;
02332       selected->done = false; // Will read the new requirements
02333     }
02334 
02335   return (selected);
02336 }
02337 
02338 //----------------------------------------------------------
02339 //
02340 //  Check if the specified version is better than the
02341 //  current one. We don't check major ids incompatibilities
02342 //
02343 //----------------------------------------------------------
02344 Use* BestFitNoCheckSelector::operate (Use* ref_use, Use* new_use)
02345 {
02346   Use* selected = ref_use;
02347 
02348   int old_v = -1;
02349   int old_r = -1;
02350   int old_p = -1;
02351   cmt_string old_pp;
02352 
02353   int new_v = -1;
02354   int new_r = -1;
02355   int new_p = -1;
02356   cmt_string new_pp;
02357 
02358   int alias_v = -1;
02359   int alias_r = -1;
02360   int alias_p = -1;
02361   cmt_string alias_pp;
02362 
02363   enum { no_alias, new_has_alias, ref_has_alias } has_alias = no_alias;
02364 
02365   CmtSystem::is_version_directory (ref_use->version, old_v, old_r, old_p);
02366   old_pp = ref_use->path;
02367 
02368   CmtSystem::is_version_directory (new_use->version, new_v, new_r, new_p);
02369   new_pp = new_use->path;
02370 
02371   if (new_use->version_alias != "")
02372     {
02373       has_alias = new_has_alias;
02374       CmtSystem::is_version_directory (new_use->version_alias, 
02375                                        alias_v, alias_r, alias_p);
02376       alias_pp = new_use->path_alias;
02377     }
02378   else if (ref_use->version_alias != "")
02379     {
02380       has_alias = ref_has_alias;
02381       CmtSystem::is_version_directory (ref_use->version_alias, 
02382                                        alias_v, alias_r, alias_p);
02383       alias_pp = ref_use->path_alias;
02384     }
02385 
02386   ref_use->undiscard ();
02387   new_use->undiscard ();
02388 
02389   if (new_v != old_v)
02390     {
02391       if (has_alias != no_alias)
02392         {
02393           if (has_alias == new_has_alias)
02394             {
02395               new_v = alias_v;
02396               new_r = alias_r;
02397               new_p = alias_p;
02398               new_pp = alias_pp;
02399             }
02400           else if (has_alias == ref_has_alias)
02401             {
02402               old_v = alias_v;
02403               old_r = alias_r;
02404               old_p = alias_p;
02405               old_pp = alias_pp;
02406             }
02407         }
02408     }
02409 
02410   if (new_v < old_v)
02411     {
02412       if (!Cmt::get_quiet ())
02413         {
02414           cout << "# Keep version " << ref_use->version <<
02415             " of package " << ref_use->package <<
02416             " (ignore version " << new_use->version << ")" <<
02417             endl;
02418         }
02419 
02420       if (ref_use != new_use) new_use->discard ();
02421     }
02422   else if (new_v > old_v)
02423     {
02424       if (!Cmt::get_quiet ())
02425         {
02426           cout << "# Select version " << new_use->version <<
02427             " of package " << ref_use->package <<
02428             " instead of existing " << ref_use->version <<
02429             endl;
02430         }
02431 
02432       if (ref_use != new_use) ref_use->discard ();
02433       selected = new_use;
02434       selected->done = false; // Will read the new requirements
02435     }
02436   else if (new_r < old_r)
02437     {
02438       if (!Cmt::get_quiet ())
02439         {
02440           cout << "# keep release " << ref_use->version <<
02441             " of package " << ref_use->package <<
02442             " (ignore release " << new_use->version << ")" <<
02443             endl;
02444         }
02445 
02446       if (ref_use != new_use) new_use->discard ();
02447     }
02448   else if (new_r > old_r)
02449     {
02450       if (!Cmt::get_quiet ())
02451         {
02452           cout << "# Select release " << new_use->version <<
02453             " of package " << ref_use->package <<
02454             " instead of existing " << ref_use->version <<
02455             endl;
02456         }
02457 
02458       if (ref_use != new_use) ref_use->discard ();
02459       selected = new_use;
02460       selected->done = false; // Will read the new requirements
02461     }
02462   else if (new_p > old_p)
02463     {
02464       if (!Cmt::get_quiet ())
02465         {
02466           cout << "# Select patch " << new_use->version <<
02467             " of package " << ref_use->package <<
02468             " instead of existing " << ref_use->version <<
02469             endl;
02470         }
02471 
02472       if (ref_use != new_use) ref_use->discard ();
02473       selected = new_use;
02474       selected->done = false; // Will read the new requirements
02475     }
02476   else if (new_pp != old_pp) // same version-r-p but from different path
02477     {
02478       if (ref_use != new_use) ref_use->discard ();
02479       selected = new_use;
02480       selected->done = false; // Will read the new requirements
02481     }
02482 
02483   return (selected);
02484 }
02485 
02486 //----------------------------------------------------------
02487 Use* FirstChoiceSelector::operate (Use* ref_use, Use* new_use)
02488 {
02489   ref_use->undiscard ();
02490   new_use->undiscard ();
02491 
02492   new_use->done = false; // Will read the new requirements
02493   if (ref_use != new_use) new_use->discard ();
02494   return (ref_use);
02495 }
02496 
02497 //----------------------------------------------------------
02498 Use* LastChoiceSelector::operate (Use* ref_use, Use* new_use)
02499 {
02500   ref_use->undiscard ();
02501   new_use->undiscard ();
02502 
02503   new_use->done = false; // Will read the new requirements
02504   if (ref_use != new_use) ref_use->discard ();
02505   return (new_use);
02506 }
02507 
02508 //----------------------------------------------------------
02509 Use* KeepAllSelector::operate (Use* ref_use, Use* new_use)
02510 {
02511   ref_use->undiscard ();
02512   new_use->undiscard ();
02513 
02514   new_use->done = false; // Will read the new requirements
02515   return (new_use);
02516 }

Generated at Thu Apr 11 16:49:43 2002 for CMT by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000