Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

cmt_use.cxx

Go to the documentation of this file.
00001 //-----------------------------------------------------------
00002 // Copyright Christian Arnault LAL-Orsay CNRS
00003 // arnault@lal.in2p3.fr
00004 // See the complete license in cmt_license.txt "http://www.cecill.info". 
00005 //-----------------------------------------------------------
00006 
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <string.h>
00010 
00011 #include "cmt_use.h"
00012 #include "cmt_system.h"
00013 #include "cmt_symbol.h"
00014 #include "cmt_error.h"
00015 #include "cmt_database.h"
00016 #include "cmt_syntax.h"
00017 
00018 static void show_packages ();
00019 
00020 /*
00021  *   Design.
00022  *
00023  *   There is one central database of all Use objects. This in the Database using:
00024  *       Database::instance().get_instances ();
00025  *
00026  *   There is also a list of selected Use pointers available from
00027  *       Database::instance().get_ordered_uses ();
00028  *
00029  *   A new Use object is created when a new use statement requires it:
00030  *     o if the specified version is specified for the first time
00031  *     o if the specified path is specified for the first time
00032  *
00033  */
00034 
00035 static bool add_request (const cmt_string& path,
00036                          const cmt_string& package_name,
00037                          const cmt_string& version)
00038 {
00039   static cmt_map <cmt_string, bool> requests;
00040 
00041   cmt_string request = package_name;
00042   request += " ";
00043   request += version;
00044   request += " ";
00045   request += path;
00046   static bool b = true;
00047 
00048   bool new_request = false;
00049 
00050   if (!requests.has ((const cmt_string&) request))
00051     {
00052       new_request = true;
00053       requests.add ((const cmt_string&) request, b);
00054     }
00055 
00056   return (new_request);
00057 }
00058 
00059 class UseContext
00060 {
00061 public:
00062 
00063   static UseContext& current ()
00064   {
00065     static UseContext me;
00066 
00067     return (me);
00068   }
00069 
00070   UseContext ()
00071   {
00072     m_auto_imports = On;
00073   }
00074 
00075   UseContext (const UseContext& other)
00076   {
00077     m_auto_imports = other.m_auto_imports;
00078   }
00079 
00080   UseContext& operator = (const UseContext& other)
00081   {
00082     m_auto_imports = other.m_auto_imports;
00083 
00084     return (*this);
00085   }
00086 
00087   static void set_current (State auto_imports)
00088   {
00089     UseContext& c = current ();
00090 
00091     c.m_auto_imports = auto_imports;
00092   }
00093 
00094   static State get_current_auto_imports ()
00095   {
00096     UseContext& c = current ();
00097 
00098     return (c.m_auto_imports);
00099   }
00100 
00101 private:
00102   State m_auto_imports;
00103 };
00104 
00105 
00106 class BestFitSelector
00107 {
00108 public:
00109   Use* operate (Use* ref_use, Use* new_use);
00110 };
00111 
00112 //----------------------------------------------------------
00113 
00114 typedef enum
00115 {
00116   IdenticalIds,
00117 
00118   IncompatibleMajorIds,
00119   NewMajorIdGreaterThanOld,
00120   OldMajorIdGreaterThanNew,
00121   ExplicitOldMajorIdWinsAgainstWildarded,
00122   ExplicitNewMajorIdWinsAgainstWildarded,
00123 
00124   ExplicitOldMinorIdWinsAgainstWildarded,
00125   ExplicitNewMinorIdWinsAgainstWildarded,
00126   NewMinorIdGreaterThanOld,
00127 
00128   ExplicitOldPatchIdWinsAgainstWildarded,
00129   ExplicitNewPatchIdWinsAgainstWildarded,
00130   NewPatchIdGreaterThanOld
00131 } CompareStatus;
00132 
00133 static CompareStatus compare_versions (const cmt_string& ref_version, const cmt_string& new_version)
00134 {
00135   CompareStatus result = IdenticalIds;
00136 
00137   int old_v = -1;
00138   int old_r = -1;
00139   int old_p = -1;
00140 
00141   int new_v = -1;
00142   int new_r = -1;
00143   int new_p = -1;
00144 
00145   CmtSystem::is_version_directory (ref_version, old_v, old_r, old_p);
00146 
00147   CmtSystem::is_version_directory (new_version, new_v, new_r, new_p);
00148 
00149   if ((new_v != -1) && (old_v != -1) && (new_v != old_v))
00150     {
00151       /*
00152       if (!Cmt::get_quiet ())
00153         {
00154           cout << "#1 Required version " << new_version <<
00155             " incompatible with selected version " << ref_version <<
00156             endl;
00157         }
00158       */
00159 
00160       if (new_v > old_v)
00161         {
00162           result = NewMajorIdGreaterThanOld;
00163         }
00164       else
00165         {
00166           result = OldMajorIdGreaterThanNew;
00167         }
00168       //result = IncompatibleMajorIds;
00169     }
00170   else if ((new_v == -1) || (old_v == -1))
00171     {
00172       //
00173       // we plan to discard new_use, but if it was specified as explicit 
00174       // and ref_use was wildcarded then new_use will win !!
00175       //
00176       // So then we'll have to understand where are the wild
00177       // cards... If they are on v or r, then we consider them.
00178       // 
00179       //
00180 
00181 
00182       if ((old_v == -1) && (new_v != -1))
00183         {
00184           /*
00185           if (!Cmt::get_quiet ())
00186             {
00187               cout << "#2 Select version " << new_version <<
00188                 " instead of existing " << ref_version <<
00189                 endl;
00190             }
00191           */
00192 
00193           result = ExplicitNewMajorIdWinsAgainstWildarded;
00194         }
00195       else
00196         {
00197           /*
00198           if (!Cmt::get_quiet ())
00199             cout << "#3 keep version " << ref_version <<
00200               " (ignore version " << new_version << ")" <<
00201               endl;
00202           */
00203 
00204           result = ExplicitOldMajorIdWinsAgainstWildarded;
00205         }
00206     }
00207   else if ((new_r == -1) || (old_r == -1) || (new_r < old_r))
00208     {
00209       //
00210       // we plan to discard new_use, but if it was specified as explicit 
00211       // and ref_use was wildcarded then new_use will win !!
00212       //
00213       // So then we'll have to understand where are the wild
00214       // cards... If they are on v or r, then we consider them.
00215       // 
00216       //
00217 
00218 
00219       if ((old_r == -1) && (new_r != -1))
00220         {
00221           // old has wild card and new has not => new wins
00222 
00223           /*
00224           if (!Cmt::get_quiet ())
00225             {
00226               cout << "#4 Select release " << new_version
00227                    << " instead of existing " << ref_version
00228                    << endl;
00229             }
00230           */
00231 
00232           result = ExplicitNewMinorIdWinsAgainstWildarded;
00233         }
00234       else
00235         {
00236           /*
00237           if (!Cmt::get_quiet ())
00238             cout << "#5 keep release " << ref_version <<
00239               " (ignore release " << new_version << ")" <<
00240               endl;
00241           */
00242 
00243           result = ExplicitOldMinorIdWinsAgainstWildarded;
00244         }
00245     }
00246   else if (new_r > old_r)
00247     {
00248       /*
00249       if (!Cmt::get_quiet ())
00250         {
00251           cout << "#6 Select release " << new_version <<
00252             " instead of existing " << ref_version <<
00253             endl;
00254         }
00255       */
00256  
00257       result = NewMinorIdGreaterThanOld;
00258    }
00259   else if ((new_p == -1) || (old_p == -1) || (new_p < old_p))
00260     {
00261       //
00262       // we plan to discard new_use, but if it was specified as explicit 
00263       // and ref_use was wildcarded then new_use will win !!
00264       //
00265 
00266 
00267       if ((old_p == -1) && (new_p != -1))
00268         {
00269           /*
00270           if (!Cmt::get_quiet ())
00271             {
00272               cout << "#7 Select patch " << new_version <<
00273                 " instead of existing " << ref_version <<
00274                 endl;
00275             }
00276           */
00277 
00278           result = ExplicitNewPatchIdWinsAgainstWildarded;
00279         }
00280       else
00281         {
00282           /*
00283           if (!Cmt::get_quiet ())
00284             cout << "#8 keep patch " << ref_version <<
00285               " (ignore version " << new_version << ")" <<
00286               endl;
00287           */
00288 
00289           result = ExplicitOldPatchIdWinsAgainstWildarded;
00290         }
00291     }
00292   else if (new_p > old_p)
00293     {
00294       /*
00295       if (!Cmt::get_quiet ())
00296         {
00297           cout << "#9 Select patch " << new_version <<
00298             " instead of existing " << ref_version <<
00299             endl;
00300         }
00301       */
00302 
00303       result = NewPatchIdGreaterThanOld;
00304     }
00305 
00306   return (result);
00307 }
00308 
00309 //----------------------------------------------------------
00310 //
00311 //  Operations on Use
00312 //
00313 //----------------------------------------------------------
00314 
00318 void Use::select_clients (const cmt_string& package,
00319                           const cmt_string& version)
00320 {
00321   static UsePtrVector& uses = get_ordered_uses ();
00322 
00323   int number;
00324   Use* use = 0;
00325 
00326   unselect_all ();
00327   undiscard_all ();
00328 
00329   for (number = uses.size () - 1; number >= 0; number--)
00330     {
00331       use = uses[number];
00332       if (use == 0) continue;
00333       if (use->is_selected ()) continue;
00334       use->select ();
00335       if (!use->is_client (package, version)) use->discard ();
00336     }
00337 }
00338 
00339 //----------------------------------------------------------
00340 void Use::show_all (bool skip_discarded)
00341 {
00342   show_all ("use ", skip_discarded);
00343 }
00344 
00345 //----------------------------------------------------------
00346 void Use::show_cycles ()
00347 {
00348   static int level = 0;
00349   static UsePtrVector stack;
00350   int size = 0;
00351 
00352   if (level == 0)
00353     {
00354       unselect_all ();
00355       unselect ();
00356       stack.clear ();
00357     }
00358 
00359   //for (int i = 0; i < level; i++) cout << "  ";
00360   //cout << "Use::show_cycles> " << level << " " << get_package_name () << endl;
00361   
00362   // Detect cycles.
00363   for (int k = 0; k < level; k++)
00364     {
00365       Use* u = stack[k];
00366       if (u == this) 
00367         {
00368           for (;k < level; k++)
00369             {
00370               u = stack[k];
00371               cout << u->get_package_name () << " ";
00372             }
00373 
00374           cout << endl;
00375 
00376           return;
00377         }
00378     }
00379 
00380   // Save this to the stack.
00381   if (stack.size () <= level)
00382     {
00383       stack.push_back (this);
00384     }
00385   else
00386     {
00387       stack[level] = this;
00388     }
00389 
00390   if (selected) return;
00391   selected = true;
00392 
00393   size = sub_uses.size ();
00394   for (int n = 0; n < size; n++)
00395     {
00396       Use* use = sub_uses[n];
00397       
00398       if (use == 0) continue;
00399       
00400       //for (int i = 0; i < level; i++) cout << "  ";
00401       //cout << "Use::show_cycles> " << get_package_name () << " uses " << use->get_package_name () << endl;
00402 
00403       if (use->discarded)
00404         {
00405           Use* u;
00406           
00407           u = use->get_selected_version ();
00408           if (u == 0) continue;
00409           
00410           use = u;
00411         }
00412       
00413       level++;
00414       use->show_cycles ();
00415       level--;
00416     }
00417 }
00418 
00419 //----------------------------------------------------------
00420 void Use::push_scope_section (ScopeType type)
00421 {
00422   scope_sections.push_back (type);
00423 }
00424 
00425 //----------------------------------------------------------
00426 void Use::pop_scope_section ()
00427 {
00428   scope_sections.pop_back ();
00429 }
00430 
00431 //----------------------------------------------------------
00432 void Use::close_scope_sections ()
00433 {
00434   scope_sections.clear ();
00435 }
00436 
00437 //----------------------------------------------------------
00438 ScopeType Use::get_current_scope () const
00439 {
00440   if (scope_sections.size () == 0) return (initial_scope);
00441   const ScopeSection& s = scope_sections.back ();
00442   return (s.get_scope ());
00443 }
00444 
00445 //----------------------------------------------------------
00446 void Use::show_all (const cmt_string& prefix, bool skip_discarded)
00447 {
00448   static UsePtrVector& uses = get_ordered_uses ();
00449 
00450   Use* use;
00451   int number;
00452 
00453   if (Cmt::get_debug ())
00454     {
00455       cout << "use::show_all-1> ";
00456       
00457       int i;
00458       
00459       for (i = 0; i < uses.size (); i++)
00460         {
00461           Use* u = uses[i];
00462           cout << u->get_package_name () << "[" << u->get_index () << "]" << " ";
00463         }
00464       
00465       cout << endl;
00466     }
00467 
00468   unselect_all ();
00469 
00470   use = &(current ());
00471   use->unselect ();
00472   if (!Cmt::get_quiet ()) use->show_sub_uses ("", skip_discarded);
00473 
00474   if (uses.size () > 0)
00475     {
00476       if (!Cmt::get_quiet ())
00477         {
00478           cout << "#\n";
00479           cout << "# Selection :\n";
00480         }
00481 
00482       //
00483       //  First move the CMT package to the end of the use set.
00484       //  (ie. used by everybody)
00485       //
00486       use = Use::find ("CMT");
00487       Use::move (use);
00488 
00489       for (number = uses.size () - 1; number >= 0; number--)
00490         {
00491           use = uses[number];
00492 
00493           if (use->discarded) continue;
00494 
00495           if (!use->located ())
00496             {
00497               if (!Cmt::get_quiet ())
00498                 {
00499                   cout << "# package " << use->get_package_name () <<
00500                       " " << use->version << " " << use->path << 
00501                       " not found" <<
00502                       endl;
00503                 }
00504               CmtError::set (CmtError::package_not_found, use->get_package_name ());
00505             }
00506           else
00507             {
00508               static const cmt_string empty;
00509               cmt_string p = use->real_path;
00510               if (use->path != "")
00511                 {
00512                   int pos = p.find_last_of (use->path);
00513                   if (pos != cmt_string::npos)
00514                     {
00515                       p.erase (pos);
00516                     }
00517                 }
00518               
00519               cout << prefix << use->get_package_name ()
00520                    << " " << use->version;
00521 
00522               if (CmtSystem::absolute_path (use->path))
00523                 {
00524                   if (!Cmt::get_quiet ()) 
00525                     {
00526                       cout << " (" << use->path << ")";
00527                     }
00528                 }
00529               else
00530                 {
00531                   cout << " " << use->path;
00532                 }
00533 
00534               if (!Cmt::get_quiet ()) 
00535                 {
00536                   if (p != "") cout << " (" << p << ")";
00537                   if (use->auto_imports == Off) cout << " (no_auto_imports)";
00538                 }
00539 
00540               cout << endl;
00541             }
00542         }
00543 
00544       if (Cmt::get_cmt_home () != "")
00545         {
00546           cout << prefix << CmtSystem::get_home_package () << " v0";
00547           if (!Cmt::get_quiet ()) 
00548             {
00549               cout << " (" << Cmt::get_cmt_home () << ")";
00550             }
00551           cout << endl;
00552         }
00553 
00554       if (Cmt::get_cmt_user_context () != "")
00555         {
00556           cout << prefix << CmtSystem::get_user_context_package () << " v0";
00557           if (!Cmt::get_quiet ()) 
00558             {
00559               cout << " (" << Cmt::get_cmt_user_context () << ")";
00560             }
00561           cout << endl;
00562         }
00563     }
00564 }
00565 
00572 class use_action_iterator
00573 {
00574 public:
00575 
00576   use_action_iterator ()
00577       {
00578         state = need_package;
00579         auto_imports = Unspecified;
00580       }
00581 
00582   void set (const cmt_string& w)
00583       {
00584         if (w == "-auto_imports")
00585           {
00586             auto_imports = On;
00587           }
00588         else if (w == "-no_auto_imports")
00589           {
00590             auto_imports = Off;
00591           }
00592         else if (w == "|")
00593           {
00594             state = need_version_alias;
00595           }
00596         else
00597           {
00598             switch (state)
00599               {
00600                 case need_package:
00601                   package = w;
00602                   state = need_version;
00603                   break;
00604                 case need_version:
00605                   version = w;
00606                   state = need_path;
00607                   break;
00608                 case need_path:
00609                   path = w;
00610                   while (path[path.size() - 1] == '/') path.erase (path.size() - 1);
00611                   while (path[path.size() - 1] == '\\') path.erase (path.size() - 1);
00612                   state = finished;
00613                   break;
00614                 case need_version_alias:
00615                   version_alias = w;
00616                   state = need_path_alias;
00617                   break;
00618                 case need_path_alias:
00619                   path_alias = w;
00620                   while (path_alias[path_alias.size() - 1] == '/') path_alias.erase (path_alias.size() - 1);
00621                   while (path_alias[path_alias.size() - 1] == '\\') path_alias.erase (path_alias.size() - 1);
00622                   state = finished;
00623                   break;
00624               }
00625           }
00626       }
00627 
00628   bool ok ()
00629       {
00630         if (package == "") return (false);
00631         if (CmtSystem::is_home_package (package, version)) return (false);
00632         if (CmtSystem::is_user_context_package (package, version)) return (false);
00633         if (CmtSystem::is_project_package (package, version)) return (false);
00634 
00635         return (true);
00636       }
00637 
00643   Use* get_use (Use* parent)
00644       {
00645         static Use::UsePtrVector& uses = Use::get_ordered_uses ();
00646 
00647         if (version == "") version = "*";
00648 
00649         if (Cmt::get_debug ())
00650           {
00651             int i;
00652 
00653             cout << "use::action1> current=" << parent->get_package_name () <<
00654                 " package=" << package << " ";
00655 
00656             for (i = 0; i < uses.size (); i++)
00657               {
00658                 Use* u = uses[i];
00659                 cout << u->get_package_name () << " ";
00660               }
00661             cout << endl;
00662           }
00663 
00664         const Use& cu = Use::current ();
00665 
00675         ActionType action = Cmt::get_action ();
00676 
00677         if (Cmt::get_debug ())
00678           {
00679             cout << "before adding " << package <<"> auto_imports=" << auto_imports
00680                  << " (current AI was " << UseContext::get_current_auto_imports () << ")" 
00681                  << " (Use::scope=" << parent->get_current_scope () << ")"
00682                  << " (parent=" << parent->get_package_name () << ")"
00683                  << endl;
00684           }
00685 
00686         bool hidden_by_scope = false;
00687 
00688         if (parent->get_current_scope () == ScopePrivate)
00689           {
00690             hidden_by_scope = true;
00691 
00692             // Do not hide immediate children of the current package.
00693             if ((parent == 0) || 
00694                 (parent->get_package () == cu.get_package ())) hidden_by_scope = false;
00695 
00696             // Override default rule according to the scope filtering mode.
00697 
00698             if (Cmt::get_scope_filtering_mode () == reach_private_uses) hidden_by_scope = false;
00699           }
00700 
00701         if (hidden_by_scope)
00702           {
00703             return (0);
00704           }
00705 
00706         // Here the version may contain wild cards
00707 
00708         UseContext save = UseContext::current ();
00709 
00714         switch (auto_imports)
00715           {
00716             case Unspecified:
00717 
00718                 // unspecified => we forward the state saved in the current use context
00719 
00720               UseContext::set_current (UseContext::get_current_auto_imports ());
00721               break;
00722             case Off:
00723 
00724                 // off => the context becomes constrained to be off
00725 
00726               UseContext::set_current (Off);
00727               break;
00728             case On:
00729 
00730                 // on => if current context is off it is kept off
00731                 //       otherwise it is forced to on
00732 
00733               if (UseContext::get_current_auto_imports () != Off)
00734                 {
00735                   UseContext::set_current (On);
00736                 }
00737               break;
00738           }
00739 
00740         if (Cmt::get_debug ())
00741           {
00742             cout << "about to add " << package << endl;
00743             show_packages ();
00744           }
00745 
00747         Use* new_use = Use::add (path, package, version, 
00748                                  version_alias, path_alias, parent,
00749                                  auto_imports);
00750 
00751         if (new_use != 0)
00752           {
00753             if (Cmt::get_debug ())
00754               {
00755                 cout << "after adding1 " << package
00756                      << "> auto_imports=" << new_use->auto_imports << endl;
00757 
00758                 show_packages ();
00759               }
00760 
00761             switch (new_use->auto_imports)
00762               {
00763                 case Unspecified:
00764                   new_use->auto_imports = UseContext::get_current_auto_imports ();
00765                   if (new_use->auto_imports == Unspecified)
00766                     {
00767                       new_use->auto_imports = On;
00768                     }
00769                   break;
00770                 case On:
00771                   break;
00772                 case Off:
00773                   if (UseContext::get_current_auto_imports () == On)
00774                     {
00786                       new_use->set_auto_imports (On);
00787                     }
00788                   break;
00789               }
00790 
00791 
00792             if (Cmt::get_debug ())
00793               {
00794                 cout << "after adding2 " << package 
00795                      << "> auto_imports=" << new_use->auto_imports << " ";
00796                 cout << endl;
00797               }
00798 
00799             UseContext& c = UseContext::current ();
00800             c = save;
00801 
00802             Use::reorder (new_use, parent);
00803             
00804             if (Cmt::get_debug ())
00805               {
00806                 cout << "use::action2> current=" << parent->get_package_name ()
00807                      << " package=" << package << " ";
00808 
00809                 int i;
00810                 
00811                 for (i = 0; i < uses.size (); i++)
00812                   {
00813                     Use* u = uses[i];
00814                     cout << u->get_package_name () << "[" << u->get_index () << "]" << " ";
00815                   }
00816 
00817                 cout << endl;
00818               }
00819           }
00820 
00821         return (new_use);
00822       }
00823 
00824 private:
00825 
00826   enum
00827   {
00828     need_package,
00829     need_version,
00830     need_path,
00831     need_version_alias,
00832     need_path_alias,
00833     finished
00834   } state;
00835   
00836   State auto_imports;
00837 
00838   cmt_string package;
00839   cmt_string version;
00840   cmt_string path;
00841   cmt_string version_alias;
00842   cmt_string path_alias;
00843 };
00844 
00845 //----------------------------------------------------------
00846 Use* Use::action (const CmtSystem::cmt_string_vector& words, Use* parent)
00847 {
00848   Use* new_use;
00849 
00850   //
00851   // complete syntax : "use <package> <version> <path>"
00852   // minimal syntax  : "use <package>"
00853   //
00854   //  o if <version> is omitted then take any version available
00855   //  o <version> can be specified using "v*" or "v<n>r*" or "v<n>r<m>p*"
00856   //
00857   //  o the notation "v*" is preferred to omission (particularly since
00858   //    omission does not permit <path>)
00859   //
00860   if (words.size () < 2) return (0);
00861 
00862   use_action_iterator it;
00863 
00864   for (int i = 1; i < words.size (); i++)
00865     {
00866       const cmt_string& w = words[i];
00867       cmt_string ew = w;
00868 
00869       Symbol::expand (ew);
00870       if (ew != w)
00871         {
00872           CmtSystem::cmt_string_vector ws;
00873 
00874           CmtSystem::split (ew, " ", ws);
00875 
00876           for (int j = 0; j < ws.size (); ++j)
00877             {
00878               const cmt_string& ww = ws[j];
00879               it.set (ww);
00880             }
00881         }
00882       else
00883         {
00884           it.set (ew);
00885         }
00886     }
00887 
00888   if (!it.ok ()) return (0);
00889 
00890   static int level = 0;
00891 
00892   level++;
00893   new_use = it.get_use (parent);
00894   level--;
00895 
00896   return (new_use);
00897 }
00898 
00899 //----------------------------------------------------------
00900 void Use::author_action (const CmtSystem::cmt_string_vector& words)
00901 {
00902   if (author != "") author += "\n";
00903   for (int i = 1; i < words.size (); i++)
00904     {
00905       const cmt_string& w = words[i];
00906       
00907       if (i > 1) author += " ";
00908       author += w;
00909     }
00910 }
00911 
00912 //----------------------------------------------------------
00913 void Use::manager_action (const CmtSystem::cmt_string_vector& words)
00914 {
00915   if (manager != "") manager += "\n";
00916   for (int i = 1; i < words.size (); i++)
00917     {
00918       const cmt_string& w = words[i];
00919       
00920       if (i > 1) manager += " ";
00921       manager += w;
00922     }
00923 }
00924 
00925 //----------------------------------------------------------
00926 Use* Use::find (const cmt_string& package, 
00927                 const cmt_string& version, 
00928                 const cmt_string& path)
00929 {
00930   Package* p = Package::find (package);
00931   if (p == 0) return (0);
00932 
00933   UsePtrVector& uses = p->get_uses ();
00934 
00935   int use_index;
00936   int size = uses.size ();
00937 
00938   for (use_index = 0; use_index < size; use_index++)
00939     {
00940       Use& use = (*uses[use_index]);
00941 
00942       // If the version argument is omitted then
00943       // take the first registered version
00944       if (version == "") return (&use);
00945           
00946       // Otherwise compare against specified_version and path
00947       //if ((use.specified_version == version) && 
00948       //  (use.specified_path == path)) return (&use);
00949       
00950       // what about comparing wild cards?
00951 
00952       if (use.specified_version == version) return (&use);
00953     }
00954 
00955   return (0);
00956 }
00957 
00958 //----------------------------------------------------------
00959 int Use::find_index (const cmt_string& package_name, 
00960                      const cmt_string& version, 
00961                      const cmt_string& path)
00962 {
00963   Package* package = Package::find (package_name);
00964   if (package == 0) return (-1);
00965 
00966   UsePtrVector& uses = package->get_uses ();
00967 
00968   int use_index;
00969   int size = uses.size ();
00970   for (use_index = 0; use_index < size; use_index++)
00971     {
00972       Use* use = uses[use_index];
00973 
00974       if (Cmt::get_debug ())
00975         {
00976           cout << "Use::find_index> " << package_name
00977                << " " << use
00978                << " " << use->m_index
00979                << endl;
00980         }
00981 
00982       // If the version argument is omitted then
00983       // take the first registered version
00984       if (version == "") return (use->m_index);
00985       
00986       // Otherwise compare against specified_version and path
00987       //if ((use.specified_version == version) && 
00988       //  (use.specified_path == path)) return (&use);
00989       
00990       // what about comparing wild cards?
00991       
00992       if (use->specified_version == version) return (use->m_index);
00993     }
00994 
00995   return (-1);
00996 }
00997 
01006 void Use::set_auto_imports_state (int use_index,
01007                                   cmt_vector<bool>& auto_imports_states)
01008 {
01009   // check boundaries (this should be an error when out bondaries)
01010   if ((use_index < 0) || (use_index >= auto_imports_states.size ())) return;
01011 
01012   Use::UsePtrVector& uses = Use::get_ordered_uses ();
01013 
01014   if (Cmt::get_debug ())
01015     {
01016       int i;
01017       
01018       cout << "Use::set_auto_imports_state> use_index=" << use_index << " ";
01019       
01020       for (i = 0; i < auto_imports_states.size (); i++)
01021         {
01022           cout << (auto_imports_states[i] ? "|" : "o");
01023         }
01024 
01025       for (i = 0; i < auto_imports_states.size (); i++)
01026         {
01027           cout << " " << (uses[i])->get_package_name ();
01028         }
01029 
01030       cout << endl;
01031     }
01032 
01033   // check if this is already done (recursivity ending)
01034   if (auto_imports_states[use_index]) return;
01035 
01036   Use* use = uses[use_index];
01037 
01038   // We only have to deal with Use objects that were
01039   // actually turned Off
01040   if (use->auto_imports != Off) return;
01041 
01052   auto_imports_states[use_index] = true;
01053 
01054   int size = 0;
01055 
01056   size = use->sub_uses.size ();
01057   for (int i = 0; i < size; i++)
01058     {
01059       Use* u = use->sub_uses[i];
01060 
01061       // first find the index of this use.
01062 
01063       int j = u->m_index;
01064 
01065       if (j >= 0)
01066         {
01067           if (u->sub_use_auto_imports[i] == Off)
01068             {
01069               set_auto_imports_state (j, auto_imports_states);
01070             }
01071           else
01072             {
01073               auto_imports_states[j] = true;
01074             }
01075         }
01076     }
01077 }
01078 
01079 //----------------------------------------------------------
01080 //
01081 //  Move use to the end
01082 //
01083 //----------------------------------------------------------
01084 void Use::move (Use* use)
01085 {
01086   if (use == 0) return;
01087 
01088   static UsePtrVector& uses = get_ordered_uses ();
01089 
01090   int size = uses.size ();
01091 
01092   if (size == 0) return;
01093 
01094   //
01095   // On se positionne sur le pointeur.
01096   //
01097 
01098   int use_index = use->m_index;
01099 
01100   if (use_index < 0) return;
01101 
01102   //
01103   // On deplace tous les pointeurs d'une case en arriere
01104   //
01105   for (use_index++; use_index < size; use_index++)
01106     {
01107       Use* u = uses[use_index];
01108       u->m_index--;
01109 
01110       uses[use_index - 1] = uses[use_index];
01111     }
01112 
01113   //
01114   // use est donc replace en derniere position
01115   //
01116 
01117   use->m_index = size - 1;
01118   uses[size - 1] = use;
01119 }
01120 
01126 void Use::reorder (Use* provider, Use* client)
01127 {
01128   static UsePtrVector& uses = get_ordered_uses ();
01129 
01130   int use_index;
01131 
01132   int size = uses.size ();
01133 
01134   if (size == 0) return;
01135   if (provider == client) return;
01136 
01137   //
01138   // First locate the two use objects into the uses vector.
01139   //   -> provider_index and client_index
01140   //
01141 
01142   int provider_index = -1;
01143   int client_index = -1;
01144 
01145   provider_index = provider->m_index;
01146   client_index = client->m_index;
01147 
01148   if (Cmt::get_debug ())
01149     {
01150       cout << "Use::reorder> provider=" << provider_index << " client=" << client_index << endl;
01151     }
01152 
01153   //
01154   // Both objects must be installed in uses before acting.
01155   //
01156   if (provider_index == -1) return;
01157   if (client_index == -1) return;
01158 
01159   if (client_index < provider_index)
01160     {
01161       //
01162       // client is already before provider so job is finished
01163       //
01164       return;
01165     }
01166 
01167   //
01168   // before : <a a a P b b b C c c c>
01169   //                 ^       ^
01170   //                 ip      ic
01171   //
01172   //  1) move "P b b b" by one place to the right
01173   // thus :   <a a a P P b b b c c c>
01174   //
01175   //  2) move "C" to [ip]
01176   //
01177   // after  : <a a a C P b b b c c c>
01178   //
01179   
01180   for (use_index = client_index - 1; use_index >= provider_index; use_index--)
01181     {
01182       Use* use = uses[use_index];
01183       use->m_index++;
01184 
01185       uses[use_index + 1] = uses[use_index];
01186     }
01187   
01188   uses[provider_index] = client;
01189   client->m_index = provider_index;
01190 }
01191 
01192 //----------------------------------------------------------
01193 void Use::clear_all ()
01194 {
01195   static UsePtrVector& uses = get_ordered_uses ();
01196   static UseVector& instances = get_instances ();
01197 
01198   int use_index;
01199 
01200   for (use_index = 0; use_index < instances.size (); use_index++)
01201     {
01202       Use& use = instances[use_index];
01203       use.clear ();
01204     }
01205 
01206   uses.clear ();
01207   instances.clear ();
01208 }
01209 
01210 //----------------------------------------------------------
01211 void Use::unselect_all ()
01212 {
01213   static UsePtrVector& uses = get_ordered_uses ();
01214 
01215   int use_index;
01216 
01217   int size = uses.size ();
01218 
01219   if (size == 0) return;
01220 
01221   for (use_index = 0; use_index < size; use_index++)
01222     {
01223       Use* use = uses[use_index];
01224 
01225       if (use != 0)
01226         {
01227           use->unselect ();
01228         }
01229     }
01230 }
01231 
01232 //----------------------------------------------------------
01233 void Use::undiscard_all ()
01234 {
01235   static UsePtrVector& uses = get_ordered_uses ();
01236 
01237   int use_index;
01238 
01239   if (uses.size () == 0) return;
01240 
01241   for (use_index = 0; use_index < uses.size (); use_index++)
01242     {
01243       Use* use = uses[use_index];
01244 
01245       if (use != 0)
01246         {
01247           use->undiscard ();
01248         }
01249     }
01250 }
01251 
01252 //----------------------------------------------------------
01253 void Use::fill_macro_all (cmt_string& buffer, const cmt_string& suffix)
01254 {
01255   UsePtrVector& uses = get_ordered_uses ();
01256 
01257   buffer = "macro_append use_";
01258   buffer += suffix;
01259   buffer += " \" ";
01260   (Use::current()).fill_macro (buffer, suffix);
01261 
01262   for (int number = 0; number < uses.size (); number++)
01263     {
01264       Use* use = uses[number];
01265       
01266       Package* p = use->get_package ();
01267       if (p->is_cmt ()) continue;
01268 
01269       if (use->discarded) continue;
01270       if (use->auto_imports == Off) continue;
01271 
01272       use->fill_macro (buffer, suffix);
01273     }
01274   
01275   buffer += "\"";
01276 }
01277 
01278 //----------------------------------------------------------
01279 Use::Use ()
01280 {
01281   done = false;
01282   discarded = false;
01283   auto_imports = Unspecified;
01284   m_package = 0;
01285   m_index = -1;
01286 
01287   clear ();
01288 }
01289 
01290 //----------------------------------------------------------
01291 Use::Use (const cmt_string& new_package,
01292           const cmt_string& new_version,
01293           const cmt_string& new_path)
01294 {
01295   auto_imports = Unspecified;
01296   m_located = false;
01297   m_package = 0;
01298   m_index = -1;
01299 
01300   set (new_package, new_version, new_path);
01301 }
01302 
01303 //----------------------------------------------------------
01304 Use::~Use ()
01305 {
01306   clear ();
01307 }
01308 
01309 //----------------------------------------------------------
01310 void Use::clear ()
01311 {
01312   specified_path = "";
01313   path      = "";
01314 
01315   if (m_package != 0)
01316     {
01317       m_package->remove_use (this);
01318       m_package = 0;
01319     }
01320 
01321   version   = "";
01322   author    = "";
01323   manager   = "";
01324   real_path = "";
01325 
01326   prefix    = "";
01327   style     = mgr_style;
01328   initial_scope = ScopePublic;
01329   done      = false;
01330   discarded = false;
01331   selected  = false;
01332   auto_imports = Unspecified;
01333 
01334   includes.clear ();
01335   include_path = "";
01336   scripts.clear ();
01337   apply_patterns.clear ();
01338   ignore_patterns.clear ();
01339 
01340   sub_uses.clear ();
01341   sub_use_scopes.clear ();
01342   sub_use_auto_imports.clear ();
01343 
01344   requests.clear ();
01345 
01346   alternate_versions.clear ();
01347   alternate_paths.clear ();
01348 
01349   version_alias = "";
01350   path_alias    = "";
01351 
01352   m_located = false;
01353   m_has_native_version = false;
01354   m_index = -1;
01355 }
01356 
01357 //----------------------------------------------------------
01358 void Use::set (const cmt_string& new_package,
01359                const cmt_string& new_version,
01360                const cmt_string& new_path,
01361                const cmt_string& new_version_alias,
01362                const cmt_string& new_path_alias)
01363 {
01364   clear ();
01365 
01366   Package* p = Package::add (new_package);
01367 
01368   m_package = p;
01369   p->add_use (this);
01370 
01371   specified_path    = new_path;
01372   // specified_path.replace_all ("\\", "/");
01373 
01374   specified_version = new_version;
01375   version           = new_version;
01376   path              = specified_path;
01377   Symbol::expand (path);
01378   real_path         = "";
01379   style             = mgr_style;
01380   initial_scope     = ScopePublic;
01381   done              = false;
01382   discarded         = false;
01383   Cmt::build_prefix (new_package, prefix);
01384 
01385   version_alias = new_version_alias;
01386   path_alias    = new_path_alias;
01387 }
01388 
01389 //----------------------------------------------------------
01390 void Use::change_path (const cmt_string& new_path)
01391 {
01392   // 
01393   // This methods changes real_path after an actual location
01394   // where this package/version has been found.
01395   //
01396 
01397   real_path = "";
01398 
01399   if (new_path != "")
01400     {
01401       if ((path.size () > 0) &&
01402           (!CmtSystem::absolute_path (path)))
01403         {
01404           real_path = new_path;
01405           real_path += CmtSystem::file_separator ();
01406           real_path += path;
01407         }
01408       else
01409         {
01410           real_path = new_path;
01411         }
01412       // real_path.replace_all ("\\", "/");
01413 
01414       CmtSystem::compress_path (real_path);
01415     }
01416   
01417   m_located = true;
01418 }
01419 
01420 //----------------------------------------------------------
01421 int Use::reach_package (const cmt_string& from_path)
01422 {
01423   if (Cmt::get_debug ())
01424     {
01425       cout << "Use::reach_package> (" << get_package_name () << " " 
01426            << version << ")from " << from_path << endl;
01427     }
01428 
01429   //
01430   // We try to reach a package/version starting from from_path
01431   //
01432 
01433   // check if from_path is at least real
01434   if ((from_path != "") && !CmtSystem::cd (from_path)) return (0);
01435 
01436   if (Cmt::get_debug ())
01437     {
01438       cout << "Use::reach_package-2>" << endl;
01439     }
01440 
01441   // check in case from_path is a new search path 
01442   if (from_path != real_path)
01443     {
01444       // Move to that prefix only if it is a relative path.
01445       if ((path.size () > 0) && (!CmtSystem::absolute_path (path)))
01446         {
01447           if (!CmtSystem::cd (path))
01448             {
01449               return (0);
01450             }
01451         }
01452     }
01453 
01454   if (Cmt::get_debug ())
01455     {
01456       cout << "Use::reach_package-3>" << endl;
01457     }
01458 
01459   // Special treatment for CMTHOME package...
01460   if (get_package_name () == CmtSystem::get_home_package ())
01461     {
01462       discarded = 1;
01463       if (!CmtSystem::test_file ("requirements"))
01464         {
01465           return (0);
01466         }
01467       else
01468         {
01469           return (1);
01470         }
01471     }
01472 
01473   if (Cmt::get_debug ())
01474     {
01475       cout << "Use::reach_package-4>" << endl;
01476     }
01477 
01478   // Special treatment for CMTUSERCONTEXT package...
01479   if (get_package_name () == CmtSystem::get_user_context_package ())
01480     {
01481       discarded = 1;
01482       if (!CmtSystem::test_file ("requirements"))
01483         {
01484           return (0);
01485         }
01486       else
01487         {
01488           return (1);
01489         }
01490     }
01491 
01492   // Special treatment for PROJECT package...
01493   if (get_package_name () == CmtSystem::get_project_package ())
01494     {
01495       discarded = 1;
01496       if (!CmtSystem::test_file ("project"))
01497         {
01498           return (0);
01499         }
01500       else
01501         {
01502           return (1);
01503         }
01504     }
01505 
01506   if (Cmt::get_debug ())
01507     {
01508       cout << "Use::reach_package-5>" << endl;
01509     }
01510 
01511   // Now from_path exists, try if the package exists there
01512   if (!CmtSystem::cd (get_package_name ()))
01513     {
01514       return (0);
01515     }
01516 
01517   if (Cmt::get_debug ())
01518     {
01519       cout << "Use::reach_package-6>" << endl;
01520     }
01521 
01522   if (CmtSystem::test_file ("cmt/requirements"))
01523     {
01524       CmtSystem::cd ("cmt");
01525 
01526       style = no_version_style;
01527 
01528       if (CmtSystem::test_file ("version.cmt"))
01529         {
01530           cmt_string v;
01531 
01532           v.read ("version.cmt");
01533           int pos;
01534           pos = v.find ('\n');
01535           if (pos != cmt_string::npos) v.erase (pos);
01536           pos = v.find ('\r');
01537           if (pos != cmt_string::npos) v.erase (pos);
01538 
01539           CompareStatus s = compare_versions (version, v);
01540 
01541           if (Cmt::get_debug ())
01542             {
01543               cout << "Use::reach_package-6.1> version=" << version << " v=" << v << " s=" << s << endl;
01544             }
01545 
01546           switch (s)
01547             {
01548             case IdenticalIds:
01549             case ExplicitOldMajorIdWinsAgainstWildarded:
01550             case ExplicitOldMinorIdWinsAgainstWildarded:
01551             case ExplicitOldPatchIdWinsAgainstWildarded:
01552               break;
01553             case ExplicitNewMajorIdWinsAgainstWildarded:
01554             case ExplicitNewMinorIdWinsAgainstWildarded:
01555             case NewMinorIdGreaterThanOld:
01556             case ExplicitNewPatchIdWinsAgainstWildarded:
01557             case NewPatchIdGreaterThanOld:
01558               break;
01559             case OldMajorIdGreaterThanNew:
01560             case NewMajorIdGreaterThanOld:
01561               break;
01562             case IncompatibleMajorIds:
01563               return (0);
01564             }
01565           version = v;
01566         }
01567       else if (version == "")
01568         {
01569           version = "v0";
01570         }
01571 
01572       return (1);
01573     }
01574   else if (!CmtSystem::cd (version))
01575     {
01576       //
01577       // The specified version cannot be found per-se
01578       // There are alternate possibilities when it contains wild cards
01579       //
01580       if ((version == "") ||
01581           (version.find ("*") != cmt_string::npos))
01582         {
01583           static CmtSystem::cmt_string_vector versions;
01584           static cmt_string name;
01585 
01586           name = ".";
01587           name += CmtSystem::file_separator ();
01588           if (version == "") name += "*";
01589           else name += version;
01590 
01591           CmtSystem::scan_dir (name, versions);
01592           
01593           int i;
01594           bool found = false;
01595           
01596           for (i = 0; i < versions.size (); i++)
01597             {
01598               const cmt_string& vers = versions[i];
01599               
01600               if (Cmt::get_debug ())
01601                 {
01602                   cout << "     ... version " << vers << " exists" << endl;
01603                 }
01604 
01605               CmtSystem::basename (vers, name);
01606               
01607               int v;
01608               int r;
01609               int p;
01610               
01611               if (CmtSystem::is_version_directory (name, v, r, p))
01612                 {
01613                   /*
01614                     This check is not sufficient !! We need to check in addition
01615                     that the selected directory is really the start of a true CMT
01616                     package (ie with either /mgr/requirements or /cmt/requirements below)
01617                   */
01618 
01619                   cmt_string req;
01620 
01621                   req = name;
01622                   req += CmtSystem::file_separator ();
01623                   req += "mgr";
01624                   req += CmtSystem::file_separator ();
01625                   req += "requirements";
01626 
01627                   if (!CmtSystem::test_file (req))
01628                     {
01629                       req = name;
01630                       req += CmtSystem::file_separator ();
01631                       req += "cmt";
01632                       req += CmtSystem::file_separator ();
01633                       req += "requirements";
01634 
01635                       if (!CmtSystem::test_file (req)) continue;
01636                     }
01637 
01638                   cmt_string& new_v = alternate_versions.add ();
01639                   new_v = name;
01640                   cmt_string& new_p = alternate_paths.add ();
01641                   new_p = from_path;
01642 
01643                   found = true;
01644                 }
01645             }
01646 
01647           if (!found)
01648             {
01649               if (CmtSystem::test_file ("cmt/requirements"))
01650                 {
01651                   CmtSystem::cd ("cmt");
01652                   style = no_version_style;
01653                   return (1);
01654                 }
01655             }
01656         }
01657 
01658       if (Cmt::get_debug ())
01659         {
01660           cout << "  ... end of version scan" << endl;
01661         }
01662 
01663         //
01664         //  We have now the list of possible alternate versions. However
01665         // we return that the expected package/version was not found (yet).
01666         //
01667 
01668       return (0);
01669     }
01670 
01671   if (Cmt::get_debug ())
01672     {
01673       cout << "Use::reach_package-7>" << endl;
01674     }
01675 
01676   //cerr << "  ... version " << version << " exists" << endl;
01677 
01678   // Now we have met the exact specified version!
01679   if (!CmtSystem::test_file ("cmt/requirements"))
01680     {
01681       if (!CmtSystem::test_file ("mgr/requirements"))
01682         {
01683           return (0);
01684         }
01685       else
01686         {
01687           CmtSystem::cd ("mgr");
01688           style = mgr_style;
01689         }
01690     }
01691   else
01692     {
01693       CmtSystem::cd ("cmt");
01694       style = cmt_style;
01695     }
01696 
01697   if (Cmt::get_debug ())
01698     {
01699       cout << "Use::reach_package-8>" << endl;
01700     }
01701 
01702   return (1);
01703 }
01704 
01705 class UseProjectAction : public IProjectAction
01706 {
01707 public:
01708   UseProjectAction (Use* use) : m_use (use), m_found (false)
01709   {
01710   }
01711 
01712   bool found () const
01713   {
01714     return (m_found);
01715   }
01716 
01717   bool run (const Project& project)
01718   {
01719     const cmt_string& path = project.get_cmtpath ();
01720       
01721     m_use->alternate_versions.clear ();
01722     m_use->alternate_paths.clear ();
01723 
01724     if (m_use->reach_package (path))
01725       {
01726         if (Cmt::get_debug ())
01727           {
01728             cout << "move_to4> " << path << endl;
01729           }
01730         
01731         m_use->change_path (path);
01732 
01733         m_found = true;
01734 
01735         return (false);
01736       }
01737     else if (m_use->alternate_versions.size () > 0)
01738       {
01739         if (m_use->select_alternate ()) 
01740           {
01741             if (Cmt::get_debug ())
01742               {
01743                 cout << "move_to5> " << m_use->real_path << endl;
01744               }
01745 
01746             m_found = true;
01747 
01748             return (false);
01749           }
01750       }
01751     
01752     return (true);
01753   }
01754 
01755 private:
01756   Use* m_use;
01757   bool m_found;
01758 };
01759 
01760 //----------------------------------------------------------
01761 bool Use::move_to ()
01762 {
01763   if (m_located)
01764     {
01765       //
01766       // The real path where this version/package can be found 
01767       // has already been resolved. We thus first go there.
01768       //
01769 
01770       if (Cmt::get_debug ())
01771         {
01772           cout << "move_to1> " << real_path << endl;
01773         }
01774 
01775       reach_package (real_path);
01776 
01777       return (true);
01778     }
01779 
01780   cmt_string expanded_path = path;
01781 
01782   //
01783   // Try here.
01784   //
01785   if (expanded_path == "")
01786     {
01787       if (reach_package (""))
01788         {
01789           if (Cmt::get_debug ())
01790             {
01791               cout << "move_to2> " << expanded_path << endl;
01792             }
01793 
01794           change_path (expanded_path);
01795 
01796           return (true);
01797         }
01798       else if (alternate_versions.size () > 0)
01799         {
01800           if (select_alternate ()) 
01801             {
01802               if (Cmt::get_debug ())
01803                 {
01804                   cout << "move_to5> " << real_path << endl;
01805                 }
01806               
01807               return (true);
01808             }
01809         }
01810     }
01811       
01812   //
01813   // If the path specified in this use is a true absolute path,
01814   // then we search the package from there first.
01815   //
01816   if (CmtSystem::absolute_path (expanded_path))
01817     {
01818       if (reach_package (expanded_path))
01819         {
01820           if (Cmt::get_debug ())
01821             {
01822               cout << "move_to3> " << expanded_path << endl;
01823             }
01824 
01825           change_path (expanded_path);
01826 
01827           return (true);
01828         }
01829       else if (alternate_versions.size () > 0)
01830         {
01831           if (select_alternate ()) 
01832             {
01833               if (Cmt::get_debug ())
01834                 {
01835                   cout << "move_to5> " << real_path << endl;
01836                 }
01837               
01838               return (true);
01839             }
01840         }
01841     }
01842       
01843   //
01844   // Second try is among the CMTPATHs
01845   //
01846       
01847   UseProjectAction pa (this);
01848 
01849   Project::broadcast (pa);
01850 
01851   if (pa.found ()) return (true);
01852 
01853   return (false);
01854 }
01855 
01856 //----------------------------------------------------------
01857 bool Use::select_alternate ()
01858 {
01859   int i;
01860 
01861   int v0 = 0;
01862   int r0 = 0;
01863   int p0 = 0;
01864 
01865   int v = 0;
01866   int r = 0;
01867   int p = 0;
01868 
01869   int selected_index = -1;
01870 
01871   for (i = 0; i < alternate_versions.size (); i++)
01872     {
01873       cmt_string& name = alternate_versions[i];
01874 
01875         /*
01876       if (CmtSystem::getenv ("CMTTESTUSEWILDCARDS") != "")
01877         {
01878           cout << "select_alternate[" << this << "]> package " << get_package_name () << 
01879               " sv=" << specified_version << 
01880               " v=" << version << 
01881               " av[" << i << "]=" << name << endl;
01882         }
01883         */
01884 
01885       if (i == 0)
01886         {
01887           CmtSystem::is_version_directory (name, v0, r0, p0);
01888           selected_index = 0;
01889         }
01890       else
01891         {
01892           CmtSystem::is_version_directory (name, v, r, p);
01893 
01894           if (v > v0)
01895             {
01896               selected_index = i;
01897               v0 = v;
01898               r0 = r;
01899               p0 = p;
01900             }
01901           else if (v == v0)
01902             {
01903               if (r > r0)
01904                 {
01905                   selected_index = i;
01906                   r0 = r;
01907                   p0 = p;
01908                 }
01909               else if (r == r0)
01910                 {
01911                   if (p > p0)
01912                     {
01913                       selected_index = i;
01914                       p0 = p;
01915                     }
01916                 }
01917             }
01918         }
01919     }
01920 
01921   if (selected_index >= 0)
01922     {
01923       if (CmtSystem::cd (alternate_paths[selected_index]))
01924         {
01925           version = alternate_versions[selected_index];
01926           if (reach_package (alternate_paths[selected_index]))
01927             {
01928                 /*
01929               if (CmtSystem::getenv ("CMTTESTUSEWILDCARDS") != "")
01930                 {
01931                   cout << "select_alternate2> package " << get_package_name () << 
01932                       " sv=" << specified_version << 
01933                       " v=" << version << endl;
01934                 }
01935                 */
01936 
01937               if (Cmt::get_debug ())
01938                 {
01939                   cout << "select_alternate> " << alternate_paths[selected_index] << endl;
01940                 }
01941 
01942               change_path (alternate_paths[selected_index]);
01943               return (true);
01944             }
01945         }
01946     }
01947 
01948   return (false);
01949 }
01950 
01951 //----------------------------------------------------------
01952 bool Use::need_new (const cmt_string& path,
01953                     const cmt_string& package,
01954                     const cmt_string& version,
01955                     Use** old_use,
01956                     Use* context_use)
01957 {
01958   bool new_request = add_request (path, package, version);
01959 
01960   Use& current_use = Use::current ();
01961 
01962   if (package == current_use.get_package_name ())
01963     {
01964       if (Cmt::get_debug ())
01965         {
01966           cout << "  ... recursive use to current package" << endl;
01967         }
01968 
01969       if (old_use != 0) *old_use = &current_use;
01970       return (false);
01971     }
01972 
01973   Package* p = Package::add (package);
01974 
01975   UsePtrVector& uses = p->get_uses ();
01976 
01977   bool do_need_new = true;
01978   Use* found = 0;
01979   Use* registered = 0;
01980 
01981   int req_v = -1;
01982   int req_r = -1;
01983   int req_p = -1;
01984 
01985   CmtSystem::is_version_directory (version, req_v, req_r, req_p);
01986 
01987   if (Cmt::get_debug ())
01988     {
01989       cout << "need_new> p=" << package << " v=" << version << " v=" << req_v << " r=" << req_r << " p=" << req_p << endl;
01990     }
01991 
01992   bool has_wild_card = (req_v == -1) || (req_r == -1) || (req_p == -1);
01993 
01994   int new_v = -1;
01995   int new_r = -1;
01996   int new_p = -1;
01997 
01998   int use_index;
01999 
02000   if (old_use != 0) *old_use = 0;
02001 
02002   // Acquire the registered use.
02003   for (use_index = 0; use_index < uses.size (); use_index++)
02004     {
02005       Use& use = (*uses[use_index]);
02006 
02007       if (use.m_index < 0) continue;
02008 
02009       registered = &use;
02010 
02011       break;
02012     }
02013 
02014   // Make a first try with the registered use if it exists.
02015 
02016   cmt_string decision;
02017 
02018   if (registered != 0)
02019     {
02020       Use& use = (*registered);
02021 
02022       found = &use;
02023 
02024       CmtSystem::is_version_directory (use.specified_version, new_v, new_r, new_p);
02025 
02026       bool use_has_wild_card = (new_v == -1) || (new_r == -1) || (new_p == -1);
02027 
02028       if (has_wild_card && !use_has_wild_card)
02029         {
02030           if (Cmt::get_debug ())
02031             {
02032               cout << "  ... wildcarded request loses against existing explicit" << endl;
02033             }
02034           
02035           do_need_new = false; // We don't need a new one
02036         }
02037       else
02038         {
02039           // here either !has_wild_card or use_has_wild_card
02040 
02041           if ((version == use.specified_version) &&
02042               (path == use.specified_path))
02043             {
02044               if (Cmt::get_debug ())
02045                 {
02046                   cout << " ... exactly same version and path!" << endl;
02047                 }
02048               
02049               do_need_new = false; // We don't need a new one
02050             }
02051           else if (version != use.specified_version)
02052             {
02053               if (Cmt::get_debug ())
02054                 {
02055                   cout << "requested explicit wins against existing wildcarded"
02056                        << endl;
02057                 }
02058 
02059               // The registered use loses against the request
02060             }
02061           else
02062             {
02063               if (Cmt::get_debug ())
02064                 {
02065                   cout << "only paths differ, consider the new one."
02066                        << endl;
02067                 }
02068 
02069               // The registered use loses against the request
02070             }
02071         }
02072 
02073 
02074       //if (new_request && !Cmt::get_quiet () && (Cmt::get_action () == action_show_uses))
02075       if (new_request && !Cmt::get_quiet ())
02076         {
02077           if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
02078             {
02079               cout << "# Required version " << version
02080                    << " of package " << package;
02081 
02082               if (context_use != 0)
02083                 {
02084                   cout << " [from " << context_use->get_package_name () << "]";
02085                 }
02086 
02087               cout << " incompatible with selected version " << use.version;
02088 
02089               if (use.version != use.specified_version)
02090                 {
02091                   cout << " (" << use.specified_version << ")" ;
02092                 }
02093 
02094               cout << endl;
02095             }
02096         }
02097 
02098       if (Cmt::get_debug ())
02099         {
02100           cout << "# " << package << " " << version;
02101 
02102           if (context_use != 0)
02103             {
02104               cout << " [from " << context_use->get_package_name () << "]";
02105             }
02106 
02107           if (do_need_new)
02108             {
02109               cout << " > ";
02110             }
02111           else
02112             {
02113               cout << " < ";
02114             }
02115 
02116           cout << use.version;
02117           if (use.version != use.specified_version)
02118             {
02119               cout << " (" << use.specified_version << ")" ;
02120             }
02121 
02122           cout << " (r) ";
02123 
02124           cout << endl;
02125         }
02126     }
02127 
02128   if (do_need_new)
02129     {
02130       // Now try unregistered uses, since the registered one is not appropriate.
02131       // to see is any other existing use could match
02132 
02133       for (use_index = 0; use_index < uses.size (); use_index++)
02134         {
02135           Use& use = (*uses[use_index]);
02136           
02137           if (use.m_index >= 0) continue;
02138           
02139           // Always save the latest found.
02140           
02141           found = &use;
02142 
02143           CmtSystem::is_version_directory (use.specified_version, new_v, new_r, new_p);
02144 
02145           bool use_has_wild_card = (new_v == -1) || (new_r == -1) || (new_p == -1);
02146 
02147           if (has_wild_card && !use_has_wild_card)
02148             {
02149               if (Cmt::get_debug ())
02150                 {
02151                   cout << "  ... requested wildcarded loses against existing explicit" << endl;
02152                 }
02153               
02154               do_need_new = false; // We don't need a new one
02155             }
02156           else
02157             {
02158               // here either !has_wild_card or use_has_wild_card
02159           
02160               if ((version == use.specified_version) &&
02161                   (path == use.specified_path))
02162                 {
02163                   if (Cmt::get_debug ())
02164                     {
02165                       cout << " ... exactly same version and path!" << endl;
02166                     }
02167               
02168                   do_need_new = false; // We don't need a new one
02169                 }
02170               else if (version != use.specified_version)
02171                 {
02172                   if (Cmt::get_debug ())
02173                     {
02174                       cout << "requested explicit wins against existing wildcarded"
02175                            << endl;
02176                     }
02177 
02178                   // This use loses against the request
02179                 }
02180               else
02181                 {
02182                   if (Cmt::get_debug ())
02183                     {
02184                       cout << "only paths differ, consider the new one."
02185                            << endl;
02186                     }
02187 
02188                   // This use loses against the request
02189                 }
02190             }
02191 
02192           //if (new_request && !Cmt::get_quiet () && (Cmt::get_action () == action_show_uses))
02193           if (new_request && !Cmt::get_quiet ())
02194             {
02195               if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
02196                 {
02197                   cout << "# Required version " << version
02198                        << " of package " << package;
02199 
02200                   if (context_use != 0)
02201                     {
02202                       cout << " [from " << context_use->get_package_name () << "]";
02203                     }
02204               
02205                   cout << " incompatible with selected version " << use.version;
02206 
02207                   if (use.version != use.specified_version)
02208                     {
02209                       cout << " (" << use.specified_version << ")" ;
02210                     }
02211 
02212                   cout << endl;
02213                 }
02214             }
02215 
02216           if (Cmt::get_debug ())
02217             {
02218               cout << "# " << package << " " << version;
02219               
02220               if (context_use != 0)
02221                 {
02222                   cout << " [from " << context_use->get_package_name () << "]";
02223                 }
02224               
02225               if (do_need_new)
02226                 {
02227                   cout << " > ";
02228                 }
02229               else
02230                 {
02231                   cout << " < ";
02232                 }
02233               
02234               if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
02235                 {
02236                   cout << "(incompatible) ";
02237                 }
02238 
02239               cout << use.version;
02240               if (use.version != use.specified_version)
02241                 {
02242                   cout << " (" << use.specified_version << ")" ;
02243                 }
02244               cout << endl;
02245             }
02246         }
02247     }
02248 
02249   if (old_use != 0)
02250     {
02251       if (registered != 0) *old_use = registered;
02252       else *old_use = found;
02253     }
02254 
02255   return (do_need_new);
02256 }
02257 
02258 //----------------------------------------------------------
02259 //
02260 //  Here the version which is provided here is the specified version.
02261 // It may contain wild cards or it may be simply empty.
02262 //
02263 //----------------------------------------------------------
02264 Use* Use::create (const cmt_string& path,
02265                   const cmt_string& package,
02266                   const cmt_string& version,
02267                   const cmt_string& version_alias,
02268                   const cmt_string& path_alias)
02269 {
02270   Package* p = 0;
02271 
02272   p = Package::add (package);
02273 
02274   UsePtrVector& vector = p->get_uses ();
02275 
02276   // We first look in the database.
02277   for (int use_index = 0; use_index < vector.size (); use_index++)
02278     {
02279       Use* use = vector[use_index];
02280 
02281       if ((use->specified_version == version) && 
02282           (use->specified_path == path)) return (use);
02283     }
02284 
02285   // We now really create a new Use entry.
02286 
02287   static UseVector& instances = get_instances ();
02288 
02289   Use& use_object = instances.add ();
02290 
02291   use_object.set (package, version, path, version_alias, path_alias);
02292 
02293   return (&use_object);
02294 }
02295 
02296 //----------------------------------------------------------
02297 //  Add a use request into the database.
02298 //
02299 //  o If a use request already exist in the database,
02300 //    check the version compatibility
02301 //
02302 //----------------------------------------------------------
02303 Use* Use::add (const cmt_string& path,
02304                const cmt_string& package_name,
02305                const cmt_string& version,
02306                const cmt_string& version_alias,
02307                const cmt_string& path_alias,
02308                Use* context_use,
02309                State specified_auto_imports)
02310 {
02311   bool do_need_new = false;
02312 
02313   Use* old_use = 0;
02314   Use* use = 0;
02315 
02316   do_need_new = need_new (path, package_name, version, &old_use, context_use);
02317 
02318   if (Cmt::get_debug ())
02319     {
02320       if (old_use != 0)
02321         {
02322           cout << "add> old_use " << old_use->get_package_name () <<
02323             " " << old_use->version <<
02324             " " << old_use->path <<
02325             endl;
02326         }
02327     }
02328 
02329   if (do_need_new)
02330     {
02331       use = create (path, package_name, version, version_alias, path_alias);
02332     }
02333   else
02334     {
02335       // Since we don't need a new Use, it means that old_use exists !
02336       use = old_use;
02337       old_use = 0;
02338     }
02339 
02340   if (package_name == CmtSystem::get_home_package ())
02341     {
02342       return (use);
02343     }
02344 
02345   if (package_name == CmtSystem::get_user_context_package ())
02346     {
02347       return (use);
02348     }
02349 
02350   if (package_name == CmtSystem::get_project_package ())
02351     {
02352       return (use);
02353     }
02354 
02355   cmt_string here = CmtSystem::pwd ();
02356 
02357     //
02358     // Store the specified sub_uses. Some of them may become discarded
02359     // later on.
02360     //
02361   if (context_use != 0)
02362     {
02363       context_use->sub_uses.push_back (use);
02364 
02365       context_use->sub_use_scopes.push_back (context_use->get_current_scope ());
02366 
02367       context_use->sub_use_auto_imports.push_back (specified_auto_imports);
02368 
02369       cmt_string& request = context_use->requests.add ();
02370 
02371       request = package_name;
02372       request += " ";
02373       request += version;
02374       request += " ";
02375       request += path;
02376 
02377 
02378       if (Cmt::get_debug ())
02379         {
02380           cout << "Use::add context(" << context_use->get_package_name () << ") "
02381                << "[u:" << package_name
02382                << " s:" << context_use->get_current_scope ()
02383                << " ai:" << specified_auto_imports
02384                << "]" << endl;
02385         }
02386     }
02387 
02388   if (use == &(Use::current ())) 
02389     {
02390       return (use);
02391     }
02392 
02393   /*
02394    *   Now we have a Use object. If it is a new one, we have to
02395    *    1) understand if it exists physically
02396    *    2) it is better than the old ones.
02397    *
02398    *   Here, we may have :
02399    *    1) old_use = 0 
02400    *         there was no Use object before for this package
02401    *         the existing one is fine
02402    *
02403    *    2) old_use != 0 
02404    *         we have created a new Use (which has to be validated)
02405    */
02406 
02407   bool found = use->move_to ();
02408 
02409   if (Cmt::get_debug ())
02410     {
02411       cout << "add> use [" << use << "] " << use->get_package_name () 
02412            << " " << use->version
02413            << " " << use->path
02414            << " found=" << found
02415            << " done=" << use->done
02416            << endl;
02417 
02418       show_packages ();
02419     }
02420       
02421   if (!found)
02422     {
02423       if (!Cmt::get_quiet ())
02424         {
02425           cerr << "#CMT> Warning: package " << use->get_package_name () <<
02426             " " << use->version << " " << use->path << 
02427             " not found";
02428 
02429           if (context_use != 0)
02430             {
02431               cerr << " (requested by " << context_use->get_package_name () << ")";
02432             }
02433 
02434           cerr << endl;
02435         }
02436 
02437       //CmtError::set (CmtError::package_not_found, use->get_package_name ());
02438       use = 0;
02439     }
02440 
02441   if ((old_use != 0) && (use != old_use))
02442     {
02443       if (Cmt::get_debug ())
02444         {
02445           cout << "There was another version of this Use. \n"
02446                << "But a new one was created due to some criteria. \n"
02447                << "Now we are going to apply the version strategy to make the final selection"
02448                << endl;
02449         }
02450 
02451       /*
02452        *    There was another version of this Use. 
02453        *    But a new one was created due to some criteria.
02454        *    Now we are going to apply the version strategy to make the final selection.
02455        */
02456 
02457       if (Cmt::get_debug ())
02458         {
02459           cout << "select? [" << use << "] vs old_use[" << old_use << "] "
02460                << old_use->get_package_name ()
02461                << " " << old_use->version
02462                << " " << old_use->path
02463                << endl;
02464         }
02465 
02466       if (!found)
02467         {
02468           /*
02469            *  This new Use does not correspond to any physical package.
02470            *  let's simply discard it (and go back to old_use)
02471            */
02472 
02473           if (use != 0) use->discard ();
02474           use = old_use;
02475           found = use->move_to ();
02476         }
02477       else
02478         {
02479             //
02480             //  This new version is different from the old one
02481             // thus we have to choose
02482             //
02483           static BestFitSelector selector;
02484           Use* selected_use = selector.operate (old_use, use);
02485 
02486           if (Cmt::get_debug ())
02487             {
02488               cout << "after operate old=" << old_use << "(" << old_use->m_index << ")"
02489                    << " use=" << use << "(" << use->m_index << ")"
02490                    << " => selected=" << selected_use
02491                    << endl;
02492             }
02493 
02494             //
02495             // Some situations managed by selector.operate happen
02496             // to fail discarding the rejected Use.
02497             //
02498           if (use != selected_use) 
02499             {
02500               use = use->set_selected_version (selected_use);
02501             }
02502           
02503 
02504           /*
02505            *   current directory is moved to the selected one
02506            */
02507           found = use->move_to ();
02508         }
02509     }
02510 
02511     //
02512     // The following statement is no longer considered as useful.
02513     // It is commented. But we should clarify why it was really needed!
02514     //
02515     //use->undiscard ();
02516 
02517   if (found)
02518     {
02519       static UsePtrVector& uses = get_ordered_uses ();
02520 
02521       bool registered = false;
02522       const Use& cu = Use::current ();
02523 
02524       Package* package = Package::find (package_name);
02525 
02526       //
02527       // A pointer to this new object is also added or replaced.
02528       //
02529       if ((use != &cu) && (package == cu.get_package ()))
02530         {
02531             // This is a recursive call to the current package!!
02532           registered = true;
02533           use->done = true;
02534           use->m_index = -1;
02535         }
02536       else
02537         {
02538           //
02539           // Now sort out the registration in ordered uses
02540           //
02541           //  cases:
02542           //
02543           //   use is not yet registered (m_index < 0)
02544           //     o if another use of the same package is registered,
02545           //       it must be substituted with the new one
02546           //     o otherwise create a new entry at the end (it will be sorted
02547           //       afterwards)
02548           //
02549           //   use is already registered (m_index >= 0)
02550           //     o if another use of the same package is registered,
02551           //       it must be discarded, but this may mean that
02552           //       two versions are simultaneously registered (bug?)
02553           //     o otherwise we keep it in place
02554           //
02555 
02556           UsePtrVector& puses = package->get_uses ();
02557 
02558           if (use->m_index >= 0) registered = true;
02559 
02560           /*
02561             We look for all existing uses in that package.
02562            */
02563           for (int i = 0; i < puses.size(); i++)
02564             {
02565               Use* u = puses[i];
02566               
02567               if (Cmt::get_debug ())
02568                 {
02569                   cout << "add> check registering between " << use
02570                        << ":" << use->get_package_name ()
02571                        << "(" << use->m_index << ")"
02572                        << " and " << u
02573                        << ":" << u->get_package_name () 
02574                        << "(" << u->m_index << ")"
02575                        << endl;
02576                 }
02577 
02578               if ((u != use) && (u->m_index >= 0))
02579                 {
02580                   // Another use of that package is already registered
02581 
02582                   if (Cmt::get_debug ())
02583                     {
02584                       cout << "add> Another use of that package is already registered " 
02585                            << " use(" << use->m_index << ")";
02586                       if (use->m_index >= 0)
02587                         {
02588                           cout << "[" << (uses[use->m_index])->get_package_name () << "]";
02589                         }
02590                       cout << " u(" << u->m_index << ")";
02591                       if (u->m_index >= 0)
02592                         {
02593                           cout << "[" << (uses[u->m_index])->get_package_name () << "]";
02594                         }
02595                       cout << endl;
02596                     }
02597 
02598                   if (use->m_index < 0)
02599                     {
02600                       /*
02601                         the newly selected use (use) should replace the one which was registered (u)
02602                       */
02603 
02604                       u->set_selected_version (use);
02605 
02606                       registered = true;
02607                     }
02608                   else
02609                     {
02610                       // bug??
02611                       if (Cmt::get_debug ())
02612                         {
02613                           cout << "Duplicate entry in ordered uses" << endl;
02614                         }
02615                     }
02616                 }
02617             }
02618 
02619           if (Cmt::get_debug ())
02620             {
02621               cout << "add> registering completed" << endl;
02622               show_packages ();
02623             }
02624         }
02625       
02626       if (!registered) 
02627         {
02628           if (Cmt::get_debug ())
02629             {
02630               cout << "add> We install use at the end the ordered list of uses" << endl;
02631             }
02632 
02633           uses.push_back (use);
02634           use->m_index = uses.size () - 1;
02635         }
02636 
02637       if (Cmt::get_debug ())
02638         {
02639           for (int use_index = 0; use_index < uses.size (); use_index++)
02640             {
02641               Use* u = (Use*) uses[use_index];
02642               cout << "  use[" << use_index << "] p=(" << u << ")" << u->get_package_name () 
02643                    << " v=" << u->version
02644                    << " discarded=" << u->discarded
02645                    << " selected=" << u->selected 
02646                    << " done=" << u->done
02647                    << " index=" << u->m_index
02648                    << endl;
02649             }
02650           
02651         }
02652           
02653       if (!use->done && Cmt::get_recursive ())
02654         {
02655           use->done = true;
02656 
02657           if (Cmt::get_debug ())
02658             {
02659               cout << "Parsing requirements file at " << CmtSystem::pwd () << endl;
02660             }
02661 
02662           SyntaxParser::parse_requirements ("requirements", use);
02663         }
02664       else
02665         {
02666           if (Cmt::get_debug ())
02667             {
02668               cout << "Requirements file at " << CmtSystem::pwd () << " already parsed" << endl;
02669             }
02670         }
02671     }
02672 
02673   CmtSystem::cd (here);
02674 
02675   return (use);
02676 }
02677 
02678 //----------------------------------------------------------
02679 void Use::discard ()
02680 {
02681   discarded = true;
02682 }
02683 
02684 //----------------------------------------------------------
02685 void Use::undiscard ()
02686 {
02687   discarded = false;
02688 }
02689 
02690 //----------------------------------------------------------
02691 void Use::select ()
02692 {
02693   selected = true;
02694 }
02695 
02696 //----------------------------------------------------------
02697 void Use::unselect ()
02698 {
02699   selected = false;
02700 }
02701 
02702 //----------------------------------------------------------
02703 bool Use::is_selected ()
02704 {
02705   return (selected);
02706 }
02707 
02714 bool Use::is_client (const cmt_string& used_package,
02715                      const cmt_string& used_version)
02716 {
02717   // A package is client of itself
02718 
02719   Package* package = Package::find (used_package);
02720 
02721   if ((get_package () == package) &&
02722       (version == used_version)) return (true);
02723 
02724   if (discarded) return (false);
02725 
02726   int i;
02727 
02728   for (i = 0; i < sub_uses.size (); i++)
02729     {
02730       Use* use = sub_uses[i];
02731       if (use == 0) continue;
02732 
02733       if ((use->get_package () == package) &&
02734           (use->version == used_version)) return (true);
02735 
02736       /*
02737         if (use->is_client (used_package, used_version))
02738         {
02739         return (true);
02740         }
02741       */
02742     }
02743 
02744   return (false);
02745 }
02746 
02747 //----------------------------------------------------------
02748 void Use::apply_global_patterns ()
02749 {
02750   int i;
02751 
02752   Pattern::PatternVector& vector = Pattern::patterns ();
02753 
02754   for (i = 0; i < vector.size (); i++)
02755     {
02756       Pattern& p = vector[i];
02757 
02758       if (p.global)
02759         {
02760           p.apply (this);
02761         }
02762     }
02763 }
02764 
02765 //----------------------------------------------------------
02766 void Use::set_include_path (const cmt_string& new_path)
02767 {
02768   include_path = new_path;
02769 }
02770 
02778 void Use::get_full_path (cmt_string& s) const
02779 {
02780   if (real_path == "") s = CmtSystem::pwd ();
02781   else s = real_path;
02782 
02783   s += CmtSystem::file_separator ();
02784   s += get_package_name ();
02785   
02786   if (style != no_version_style)
02787     {
02788       s += CmtSystem::file_separator ();
02789       s += version;
02790     }
02791 }
02792 
02797 cmt_string Use::get_full_path () const
02798 {
02799   cmt_string result;
02800 
02801   get_full_path (result);
02802 
02803   return (result);
02804 }
02805 
02812 void Use::reduce_path (cmt_string& s) const
02813 {
02814   cmt_string pattern;
02815   get_full_path (pattern);
02816   pattern += CmtSystem::file_separator ();
02817   
02818   cmt_string replacement = "${";
02819   replacement += prefix;
02820   replacement += "ROOT}";
02821   replacement += CmtSystem::file_separator ();
02822 
02823   s.replace (pattern, replacement);
02824 }
02825 
02826 //----------------------------------------------------------
02827 void Use::get_cmtpath_and_offset (cmt_string& cmtpath, cmt_string& offset) const
02828 {
02829   if (get_package_name () == CmtSystem::get_project_package ())
02830     {
02831       offset = "";
02832       CmtSystem::dirname (path, cmtpath);
02833       return;
02834     }
02835   else if (get_package_name () == CmtSystem::get_home_package ())
02836     {
02837       offset = "";
02838       cmtpath = path;
02839       return;
02840     }
02841   else if (get_package_name () == CmtSystem::get_user_context_package ())
02842     {
02843       offset = "";
02844       cmtpath = path;
02845       return;
02846     }
02847 
02848   cmtpath = "";
02849   offset = "";
02850 
02851   cmtpath = Project::find_in_cmt_paths (real_path);
02852 
02853   if (cmtpath != "")
02854     {
02855       CmtSystem::compress_path (cmtpath);
02856 
02857       static const cmt_string empty_string;
02858       static const cmt_string fs = CmtSystem::file_separator ();
02859       
02860       offset = real_path;
02861       offset.replace (cmtpath, empty_string);
02862 
02869       if (offset[0] == CmtSystem::file_separator ())
02870         {
02871           // Just in case there is a part left after removing the cmtpath entry
02872                 
02873           offset.replace (fs, empty_string);
02874         }
02875     }
02876 }
02877 
02878 //----------------------------------------------------------
02879 void Use::fill_includes_macro (cmt_string& buffer) const
02880 {
02881   if (include_path == "")
02882     {
02883       buffer += "$(ppcmd)\"$(";
02884       buffer += get_package_name ();
02885       buffer += "_root)";
02886       buffer += CmtSystem::file_separator ();
02887       buffer += "src\" ";
02888     }
02889   else if (include_path != "none")
02890     {
02891       buffer += "$(ppcmd)\"";
02892       buffer += include_path;
02893       buffer += "\" ";
02894     }
02895   
02896   for (int i = 0; i < includes.size (); i++)
02897     {
02898       Include& incl = includes[i];
02899       
02900       buffer += "$(ppcmd)\"";
02901       buffer += incl.name;
02902       buffer += "\" ";
02903     }
02904 }
02905 
02906 //----------------------------------------------------------
02907 void Use::fill_macro (cmt_string& buffer, const cmt_string& suffix) const
02908 {
02909   buffer += " $(";
02910   buffer += get_package_name ();
02911   buffer += "_";
02912   buffer += suffix;
02913   buffer += ") ";
02914 }
02915 
02916 //----------------------------------------------------------
02917 void Use::fill_standard_macros (cmt_string& buffer) const
02918 {
02919   static cmt_string fs = CmtSystem::file_separator ();
02920 
02921   buffer = "";
02922 
02923   cmt_string package_name = get_package_name ();
02924 
02925   buffer += "macro ";
02926   buffer += package_name;
02927   buffer += "_tag";
02928   buffer += " \"$(tag)\"";
02929   buffer += "\n";
02930 
02931   if (located ())
02932     {
02933       buffer += "macro ";
02934       buffer += prefix;
02935       buffer += "ROOT";
02936       buffer += " \"";
02937       buffer += get_full_path ();
02938       buffer += "\"";
02939       buffer += "\n";
02940 
02941       buffer += "macro ";
02942       buffer += package_name;
02943       buffer += "_root";
02944       buffer += " \"";
02945       buffer += real_path;
02946       buffer += fs;
02947       buffer += package_name;
02948       if (style != no_version_style)
02949         {
02950           buffer += fs;
02951           buffer += version;
02952         }
02953       buffer += "\"";
02954       buffer += "\n";
02955     }
02956 
02957   buffer += "macro ";
02958   buffer += prefix;
02959   buffer += "VERSION";
02960   buffer += " \"";
02961   buffer += version;
02962   buffer += "\"";
02963   buffer += "\n";
02964 
02965   cmt_string cmtpath = "";
02966   cmt_string offset = "";
02967 
02968   get_cmtpath_and_offset (cmtpath, offset);
02969 
02970   buffer += "macro ";
02971   buffer += package_name;
02972   buffer += "_cmtpath";
02973   buffer += " \"";
02974   buffer += cmtpath;
02975   buffer += "\"";
02976   buffer += "\n";
02977 
02978   buffer += "macro ";
02979   buffer += package_name;
02980   buffer += "_offset";
02981   buffer += " \"";
02982   buffer += offset;
02983   buffer += "\"";
02984   buffer += "\n";
02985   
02986   Project* p = Project::find_by_cmtpath (cmtpath);
02987 
02988   buffer += "macro ";
02989   buffer += package_name;
02990   buffer += "_project";
02991   buffer += " \"";
02992   if (p != 0)
02993     {
02994       buffer += p->get_name ();
02995     }
02996   buffer += "\"";
02997 
02998   buffer += "macro ";
02999   buffer += package_name;
03000   buffer += "_project_release";
03001   buffer += " \"";
03002   if (p != 0)
03003     {
03004       buffer += p->get_release ();
03005     }
03006   buffer += "\"";
03007 }
03008 
03009 
03010 //----------------------------------------------------------
03011 static bool same_dirs (const cmt_string& d1, const cmt_string& d2)
03012 {
03013   bool result = false;
03014 
03015   cmt_string here = CmtSystem::pwd ();
03016 
03017   cmt_string h1;
03018   if (CmtSystem::cd (d1)) h1 = CmtSystem::pwd ();
03019 
03020   CmtSystem::cd (here);
03021 
03022   cmt_string h2;
03023   if (CmtSystem::cd (d2)) h2 = CmtSystem::pwd ();
03024 
03025   result = (h1 == h2);
03026 
03027   CmtSystem::cd (here);
03028 
03029   return (result);
03030 }
03031 
03032 //----------------------------------------------------------
03033 static bool install_library (const cmt_string& source_library_name, 
03034                              const cmt_string& dest_library_name, 
03035                              const cmt_string& cmtinstallarea, 
03036                              const cmt_string& tag, 
03037                              const cmt_string& symlinkcmd)
03038 {
03039   cmt_string libname = source_library_name;
03040   cmt_string name = dest_library_name;
03041   cmt_string s;
03042   Use& current_use = Use::current ();
03043 
03044   Symbol::expand (name);
03045   Symbol::expand (libname);
03046 
03047   if (cmtinstallarea != "")
03048     {
03049       s = cmtinstallarea;
03050       s += CmtSystem::file_separator ();
03051       s += tag;
03052       s += CmtSystem::file_separator ();
03053       s += "lib";
03054       s += CmtSystem::file_separator ();
03055       s += name;
03056       
03057       // Now creating the reference file
03058 
03059       cmt_string ref_file = s;
03060       ref_file += ".cmtref";
03061 
03062       cmt_string text = libname;
03063       text += "\n";
03064 
03065       Symbol::expand (ref_file);
03066       Symbol::expand (text);
03067 
03068       if (!Cmt::get_quiet ()) cout << "   Creating the reference file " << ref_file << endl;
03069       text.write (ref_file);
03070     }
03071   else
03072     {
03073       s = "../$(";
03074       s += current_use.get_package_name ();
03075       s += "_tag)/";
03076       s += name;
03077     }
03078 
03079   Symbol::expand (s);
03080 
03081   cmt_string source;
03082   cmt_string dest;
03083 
03084   CmtSystem::dirname (libname, source);
03085   CmtSystem::dirname (s, dest);
03086 
03087   if (same_dirs (source, dest))
03088     {
03089       return (false);
03090     }
03091 
03092   //if (!Cmt::get_quiet ()) 
03093   cout << "   Symlinking " << libname << " to " << s << endl;
03094 
03095   if (symlinkcmd == "")
03096     {
03097       if (!CmtSystem::create_symlink (libname, s))
03098         {
03099           cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
03100           return (false);
03101         }
03102     }
03103   else
03104     {
03105       cmt_string cmd = symlinkcmd;
03106       cmd += " ";
03107       cmd += libname;
03108       cmd += " ";
03109       cmd += s;
03110       
03111       int status = CmtSystem::execute (cmd);
03112       
03113       if (status != 0)
03114         {
03115           cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
03116           return (false);
03117         }
03118     }
03119 
03120   return (true);
03121 }
03122 
03123 
03127 void Use::build_library_links (const cmt_string& cmtinstallarea, 
03128                                const cmt_string& tag, 
03129                                const cmt_string& shlibsuffix, 
03130                                const cmt_string& symlinkcmd) const
03131 {
03132   if (!located ())
03133     {
03134       if (!Cmt::get_quiet ())
03135         {
03136           cout << "# package " << get_package_name () <<
03137             " " << version << " " << path << 
03138             " not found" <<
03139             endl;
03140         }
03141       return;
03142     }
03143 
03144   cmt_string s;
03145 
03146   s = get_package_name ();
03147   s += "_libraries";
03148 
03149   Symbol* libraries_macro = Symbol::find (s);
03150 
03151   if (libraries_macro == 0) return;
03152 
03153   cmt_string libraries = libraries_macro->build_macro_value ();
03154   Symbol::expand (libraries);
03155   static CmtSystem::cmt_string_vector values;
03156 
03157   CmtSystem::split (libraries, " \t", values);
03158 
03159   for (int j = 0; j < values.size (); j++)
03160     {
03161       const cmt_string& library = values[j];
03162 
03163       static cmt_string libname;
03164       static cmt_string name;
03165 
03166       // Is it a simple name or a complete path?
03167 
03168       libname = library;
03169       Symbol::expand (libname);
03170 
03171       bool is_absolute = false;
03172 
03173       is_absolute = CmtSystem::absolute_path (libname);
03174 
03175       if (is_absolute)
03176         {
03182           cmt_string suffix;
03183           CmtSystem::basename (library, name);
03184         }
03185       else
03186         {
03194           libname = "${";
03195           libname += prefix;
03196           libname += "ROOT}/${";
03197           libname += get_package_name ();
03198           libname += "_tag}/";
03199           libname += "$(library_prefix)";
03200           libname += library;
03201           libname += "$(library_suffix)";
03202           libname += ".";
03203           libname += shlibsuffix;
03204 
03205           name = "$(library_prefix)";
03206           name += library;
03207           name += "$(library_suffix)";
03208           name += ".";
03209           name += shlibsuffix;
03210         }
03211 
03212       if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
03213         {
03214           continue;
03215         }
03216 
03217 #ifdef __APPLE__
03218       if (!is_absolute)
03219         {
03220           libname = "${";
03221           libname += prefix;
03222           libname += "ROOT}/${";
03223           libname += get_package_name ();
03224           libname += "_tag}/";
03225           libname += library;
03226           libname += ".bundle";
03227 
03228           name = library;
03229           name += ".bundle";
03230           
03231           if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
03232             {
03233               continue;
03234             }
03235         }
03236 #endif
03237     }
03238 }
03239 
03244 Use* Use::get_selected_version ()
03245 {
03246     //cout << "get_selected_version for package " << get_package_name () << endl;
03247 
03248   if (!discarded) return (this);
03249 
03250   Package* p = m_package;
03251 
03252   Use::UsePtrVector& uses = p->get_uses ();
03253 
03254   bool dbg = Cmt::get_debug ();
03255 
03256   int size = uses.size ();
03257 
03258   for (int i = 0; i < size; i++)
03259     {
03260       Use* u = uses[i];
03261       if (u == 0) continue;
03262       if (u->discarded) continue;
03263       if (dbg)
03264         {
03265           cout << "Use::get_selected_version> for package " << get_package_name ()
03266                << "  got a version " << u << endl;
03267         }
03268       return (u);
03269     }
03270 
03271   return (0);
03272 }
03273 
03281 Use* Use::set_selected_version (Use* selected_use)
03282 {
03283   if (this == selected_use) return (this);
03284 
03285   static UsePtrVector& uses = get_ordered_uses ();
03286 
03287   if (m_index >= 0)
03288     {
03289       // This discarded package was registered. We have to substitute
03290       // it with the new one.
03291 
03292       selected_use->m_index = m_index;
03293       selected_use->auto_imports = auto_imports;
03294 
03295       selected_use->undiscard ();
03296 
03297       m_index = -1;
03298 
03299       uses[selected_use->m_index] = selected_use;
03300     }
03301 
03302   discard ();
03303 
03304   return (selected_use);
03305 }
03306 
03307 void Use::set_auto_imports (State new_state)
03308 {
03309   if (Cmt::get_debug ())
03310     {
03311       cout << "Use::set_auto_imports>(" << get_package_name () << ") " 
03312            << auto_imports << " -> " << new_state << endl;
03313     }
03314 
03315   if (auto_imports == new_state) return;
03316   
03317   State old_state = auto_imports;
03318   
03319   auto_imports = new_state;
03320 
03321     // We propagate only when we switch from Off to On
03322 
03323   if ((old_state == Off) && (new_state == On))
03324     {
03325       cmt_string s;
03326       static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
03327 
03328       if (Cmt::get_debug ())
03329         {
03330           s = "Use::set_auto_imports>(";
03331           s += get_package_name ();
03332           s += ") ";
03333 
03334           cout << s << endl;
03335         }
03336 
03337       for (int i = 0; i < sub_uses.size (); i++)
03338         {
03339           Use* u = sub_uses[i];
03340           State state = sub_use_auto_imports[i];
03341           
03342           if (Cmt::get_debug ())
03343             {
03344               s += " ";
03345               s += u->get_package_name ();
03346               s += "(";
03347               s += state_text[state];
03348               s += ")";
03349             }
03350 
03351           if (state == Unspecified)
03352             {
03353               u->set_auto_imports (On);
03354             }
03355         }
03356           
03357       if (Cmt::get_debug ())
03358         {
03359           cout << s << endl;
03360         }
03361     }
03362 }
03363 
03364 void Use::set_native_version (bool state)
03365 {
03366   m_has_native_version = state;
03367 }
03368 
03369 bool Use::has_native_version () const
03370 {
03371   return (m_has_native_version);
03372 }
03373 
03374 Package* Use::get_package () const
03375 {
03376   return (m_package);
03377 }
03378 
03379 const cmt_string& Use::get_package_name () const
03380 {
03381   static const cmt_string null = "";
03382 
03383   Package* p = m_package;
03384   if (p == 0) return (null);
03385 
03386   return (p->get_name ());
03387 }
03388 
03389 void Use::set_package_name (const cmt_string& name)
03390 {
03391   Package* p = Package::add (name);
03392 
03393   m_package = p;
03394   p->add_use (this);
03395 }
03396 
03397 int Use::get_index () const
03398 {
03399   return (m_index);
03400 }
03401 
03402 //----------------------------------------------------------
03403 bool Use::get_all_clients (const cmt_string& to_name)
03404 {
03405   Use::UsePtrVector& uses = Use::get_ordered_uses ();
03406 
03407   Use* use = Use::find (to_name);
03408 
03409   if (use == 0)
03410     {
03411       cerr << "#CMT> No access to " << to_name << endl;
03412       return (false);
03413     }
03414 
03415   cmt_map <cmt_string, Use*> all_clients;
03416   cmt_map <cmt_string, Use*> all_clients_ok;
03417 
03418   const cmt_string& name = get_package_name ();
03419 
03420   Use* me = this;
03421 
03422   all_clients.add (name, me);
03423   all_clients_ok.add (name, me);
03424 
03425   bool status = get_all_clients (use, to_name, all_clients, all_clients_ok); 
03426 
03427   return (status);
03428 }
03429 
03430 //----------------------------------------------------------
03431 bool Use::get_all_clients (Use* to, 
03432                            const cmt_string& result, 
03433                            cmt_map <cmt_string, Use*>& all_clients, 
03434                            cmt_map <cmt_string, Use*>& all_clients_ok)
03435 {
03436   if (this == to)
03437     {
03438       cout << result << endl;
03439       return (true);
03440     }
03441 
03442   const cmt_string& to_name = to->get_package_name ();
03443   const cmt_string& to_version = to->version;
03444 
03445   //cout << "gac> from " << get_package_name () << " to " << to_name << " -> " << result << endl;
03446 
03447   if (all_clients.has (to_name))
03448     {
03449       if (all_clients_ok.has (to_name))
03450         {
03451           cout << "   ..." << result << endl;
03452           return (true);
03453         }
03454       else
03455         {
03456           return (false);
03457         }
03458     }
03459 
03460   all_clients.add (to_name, to);
03461 
03462   bool status = false;
03463 
03464   Use::UsePtrVector& uses = Use::get_ordered_uses ();
03465   Use* use = 0;
03466 
03467   for (int n = 0; n < uses.size (); ++n)
03468     {
03469       use = uses[n];
03470 
03471       if (use->discarded) continue;
03472 
03473       if (!use->located ()) continue;
03474 
03475       if (use == to) continue;
03476 
03477       if (use->is_client (to_name, to_version))
03478         {
03479           const cmt_string& n = use->get_package_name ();
03480 
03481           cmt_string r;
03482 
03483           if ((use->initial_scope != ScopeUnspecified) &&
03484               (use->initial_scope != ScopePublic)) 
03485             {
03486               r += "(private)";
03487             }
03488           
03489           if (use->auto_imports == Off) r += "(no_auto_imports)";
03490 
03491           r += n;
03492           r += ".";
03493           r += result;
03494 
03495           //cout << "gac> " << n << " is client of " << to_name << endl;
03496 
03497           if (get_all_clients (use, r, all_clients, all_clients_ok))
03498             {
03499               all_clients_ok.add (n, use);
03500               status = true;
03501             }
03502         }
03503     }
03504 
03505   use = this;
03506 
03507   if (use->is_client (to_name, to_version))
03508     {
03509       const cmt_string& n = use->get_package_name ();
03510       
03511       cmt_string r;
03512 
03513       if ((use->initial_scope != ScopeUnspecified) &&
03514           (use->initial_scope != ScopePublic)) 
03515         {
03516           r += "(private)";
03517         }
03518       
03519       if (use->auto_imports == Off) r += "(no_auto_imports)";
03520 
03521       r += n;
03522       r += ".";
03523       r += result;
03524       
03525       //cout << "gac> " << n << " is client of " << to_name << endl;
03526       
03527       if (get_all_clients (use, r, all_clients, all_clients_ok))
03528         {
03529           all_clients_ok.add (n, use);
03530           status = true;
03531         }
03532     }
03533 
03534   return (status);
03535 }
03536 
03544 bool Use::get_paths (Use* to, UsePtrVector& list)
03545 {
03546   bool is_in_path = false;
03547   bool cycle = false;
03548   bool already_in_path = false;
03549   bool dbg = Cmt::get_debug ();
03550 
03551   static int level = 0;
03552 
03553   int size = 0;
03554 
03555   if (level == 0)
03556     {
03557       unselect_all ();
03558       selected = false;
03559     }
03560 
03561   if (selected) 
03562     {
03568       size = list.size ();
03569 
03570       for (int m = 0; m < size; m++)
03571         {
03572           Use* u = list[m];
03573           if (u == this)
03574             {
03575               if (dbg)
03576                 {
03577                   for (int lll = 0; lll < level; lll++) cout << "  ";
03578                   cout << "  Use::get_paths." << level << "> try1.2 sub="
03579                        << get_package_name () << " already_in_path " << endl;
03580                 }
03581               
03582               return (true);
03583             }
03584         }
03585 
03586       return (false);
03587     }
03588 
03589   selected = true;
03590 
03591   if (dbg)
03592     {
03593       for (int lll = 0; lll < level; lll++) cout << "  ";
03594       cout << "Use::get_paths." << level << ">" << get_package_name ()
03595            << " to=" << to->get_package_name () 
03596            << " list=[";
03597 
03598       for (int m = 0; m < list.size (); m++)
03599         {
03600           Use* u = list[m];
03601           cout << u->get_package_name () << " ";
03602         }
03603 
03604       cout << "]" << endl;
03605     }
03606 
03611   // First figure out whether 'to' is used by 'this'.
03612 
03613   if (this->get_package_name () == to->get_package_name ())
03614     {
03615       // We've reached the goal (for the first time)
03616       is_in_path = true;
03617     }
03618   else
03619     {
03623       size = sub_uses.size ();
03624 
03625       if (dbg)
03626         {
03627           for (int lll = 0; lll < level; lll++) cout << "  ";
03628           cout << "  Use::get_paths." << level << "> size=" << size << endl;
03629         }
03630 
03631       for (int n = 0; n < size; n++)
03632         {
03633           Use* use = sub_uses[n];
03634 
03635           if (use == 0) continue;
03636 
03637           if (dbg)
03638             {
03639               for (int lll = 0; lll < level; lll++) cout << "  ";
03640               cout << "  Use::get_paths." << level << "> try1 sub="
03641                    << use->get_package_name () << "(" << use << ") " << use->discarded << endl;
03642             }
03643 
03644           if (use->discarded)
03645             {
03646               Use* u;
03647 
03648               u = use->get_selected_version ();
03649               if (u == 0) 
03650                 {
03656                   continue;
03657                 }
03658 
03659               use = u;
03660             }
03661 
03662           if (dbg)
03663             {
03664               for (int lll = 0; lll < level; lll++) cout << "  ";
03665               cout << "  Use::get_paths." << level << "> try2 sub="
03666                    << use->get_package_name () << " " << use->discarded << endl;
03667             }
03668 
03669           level++;
03670           bool r = use->get_paths (to, list);
03671           level--;
03672 
03673           if (r)
03674             {
03675               is_in_path = true;
03676             }
03677         }
03678     }
03679 
03680   if (is_in_path)
03681     {
03682       if (dbg)
03683         {
03684           for (int lll = 0; lll < level; lll++) cout << "  ";
03685           cout << "Use::get_paths." << level << "> push " << get_package_name () << endl;
03686         }
03687       list.push_back (this);
03688     }
03689 
03690   return (is_in_path);
03691 }
03692 
03693 //----------------------------------------------------------
03694 bool Use::located () const
03695 {
03696   return (m_located);
03697 }
03698 
03699 //----------------------------------------------------------
03700 void Use::show_sub_uses (const cmt_string& request, bool skip_discarded)
03701 {
03702   Use* current = &(Use::current ());
03703   int n;
03704   Use* use;
03705   static int level = 0;
03706 
03707   if (skip_discarded && discarded) return;
03708 
03709   if (level > 0)
03710     {
03711       cout << "# ";
03712       for (n = 0; n < (level-1); n++) cout << "  ";
03713 
03714       if (request == "")
03715         {
03716           cout << "use " << get_package_name () << " " << specified_version;
03717 
03718           if (this == current) 
03719             {
03720               cout << " (current)";
03721             }
03722           else
03723             {
03724               if (specified_path != "") cout << " " << specified_path;
03725             }
03726         }
03727       else
03728         {
03729           cout << "use " << request;
03730         }
03731 
03732       if (version_alias != "")
03733         {
03734           cout << " | " << version_alias << " " << path_alias;
03735         }
03736 
03737       if (initial_scope == ScopeUnspecified) cout << " (unspecified)";
03738       else if (initial_scope != ScopePublic) cout << " (private)";
03739 
03740       if (auto_imports == Off) cout << " (no_auto_imports)";
03741 
03742       if (style == no_version_style) cout << " (no_version_directory)";
03743 
03744       if (m_has_native_version)
03745         {
03746           cmt_string n = get_package_name ();
03747           n += "_native_version";
03748 
03749           Symbol* s = Symbol::find (n);
03750           if (s != 0)
03751             {
03752               cmt_string value = s->resolve_macro_value ();
03753               cout << " (native_version=" << value << ")";
03754             }
03755         }
03756 
03757       cout << endl;
03758     }
03759 
03760   if (selected) return;
03761   selected = true;
03762 
03763   level++;
03764   for (n = 0; n < sub_uses.size (); n++)
03765     {
03766       use = sub_uses[n];
03767       if (use == 0) continue;
03768 
03769       const cmt_string& request = requests[n];
03770 
03771       ScopeType saved_scope = use->initial_scope;
03772       State saved_state = use->auto_imports;
03773 
03774       use->initial_scope = sub_use_scopes[n];
03775       use->auto_imports = sub_use_auto_imports[n];
03776 
03777       use->show_sub_uses (request, skip_discarded);
03778 
03779       use->initial_scope = saved_scope;
03780       use->auto_imports = saved_state;
03781     }
03782   level--;
03783 }
03784 
03785 //----------------------------------------------------------
03786 Use& Use::current ()
03787 {
03788   static UseVector& instances = get_instances ();
03789   static Use* current_use = 0;
03790 
03791   if ((current_use == 0) || (instances.size () == 0))
03792     {
03793       Use& use_object = instances.add ();
03794       current_use = &use_object;
03795     }
03796 
03797   return (*current_use);
03798 }
03799 
03800 //----------------------------------------------------------
03801 const Use& Use::const_current ()
03802 {
03803   const Use& use = Use::current ();
03804 
03805   return (use);
03806 }
03807 
03808 //----------------------------------------------------------
03809 Use::UseVector& Use::get_instances ()
03810 {
03811   static Database& db = Database::instance ();
03812   static UseVector& instances = db.all_uses ();
03813 
03814   return (instances);
03815 }
03816 
03817 //----------------------------------------------------------
03818 Use::UsePtrVector& Use::get_ordered_uses ()
03819 {
03820   static Database& db = Database::instance ();
03821   static UsePtrVector& uses = db.uses ();
03822 
03823   return (uses);
03824 }
03825 
03826 //----------------------------------------------------------
03827 
03828 //----------------------------------------------------------
03829 //
03830 //  Check if the specified version is better than the
03831 //  current one.
03832 //
03833 //----------------------------------------------------------
03834 Use* BestFitSelector::operate (Use* ref_use, Use* new_use)
03835 {
03836   Use* selected = ref_use;
03837 
03838   int ref_v = -1;
03839   int ref_r = -1;
03840   int ref_p = -1;
03841   cmt_string ref_pp;
03842 
03843   int new_v = -1;
03844   int new_r = -1;
03845   int new_p = -1;
03846   cmt_string new_pp;
03847 
03848   int alias_v = -1;
03849   int alias_r = -1;
03850   int alias_p = -1;
03851   cmt_string alias_pp;
03852 
03853   enum { no_alias, new_has_alias, ref_has_alias } has_alias = no_alias;
03854 
03855   // First analyze specified versions
03856   cmt_string ref_version = ref_use->specified_version;
03857   cmt_string new_version = new_use->specified_version;
03858 
03859   CmtSystem::is_version_directory (ref_version, ref_v, ref_r, ref_p);
03860   ref_pp = ref_use->path;
03861 
03862   CmtSystem::is_version_directory (new_version, new_v, new_r, new_p);
03863   new_pp = new_use->path;
03864 
03865   if (new_use->version_alias != "")
03866     {
03867       has_alias = new_has_alias;
03868       CmtSystem::is_version_directory (new_use->version_alias, 
03869                                        alias_v, alias_r, alias_p);
03870       alias_pp = new_use->path_alias;
03871     }
03872   else if (ref_use->version_alias != "")
03873     {
03874       has_alias = ref_has_alias;
03875       CmtSystem::is_version_directory (ref_use->version_alias, 
03876                                        alias_v, alias_r, alias_p);
03877       alias_pp = ref_use->path_alias;
03878     }
03879 
03880   ref_use->undiscard ();
03881   new_use->undiscard ();
03882 
03883   if (new_v != ref_v)
03884     {
03885       if (has_alias != no_alias)
03886         {
03887           if (has_alias == new_has_alias)
03888             {
03889               new_v = alias_v;
03890               new_r = alias_r;
03891               new_p = alias_p;
03892               new_pp = alias_pp;
03893             }
03894           else if (has_alias == ref_has_alias)
03895             {
03896               ref_v = alias_v;
03897               ref_r = alias_r;
03898               ref_p = alias_p;
03899               ref_pp = alias_pp;
03900             }
03901         }
03902     }
03903 
03904   bool ref_v_wildcarded = ((ref_v) == -1);
03905   bool ref_r_wildcarded = ((ref_r) == -1);
03906   bool ref_p_wildcarded = ((ref_p) == -1);
03907 
03908   bool ref_v_explicit = !ref_v_wildcarded;
03909   bool ref_r_explicit = !ref_r_wildcarded;
03910   bool ref_p_explicit = !ref_p_wildcarded;
03911 
03912   bool new_v_wildcarded = ((new_v) == -1);
03913   bool new_r_wildcarded = ((new_r) == -1);
03914   bool new_p_wildcarded = ((new_p) == -1);
03915 
03916   bool new_v_explicit = !new_v_wildcarded;
03917   bool new_r_explicit = !new_r_wildcarded;
03918   bool new_p_explicit = !new_p_wildcarded;
03919 
03920   bool verbose = (CmtSystem::getenv ("CMTVERBOSE") != "");
03921 
03922   cmt_string ref_vc = ref_v_wildcarded ? "wildcarded" : "explicit";
03923   cmt_string ref_rc = ref_r_wildcarded ? "wildcarded" : "explicit";
03924   cmt_string ref_pc = ref_p_wildcarded ? "wildcarded" : "explicit";
03925   
03926   cmt_string new_vc = new_v_wildcarded ? "wildcarded" : "explicit";
03927   cmt_string new_rc = new_r_wildcarded ? "wildcarded" : "explicit";
03928   cmt_string new_pc = new_p_wildcarded ? "wildcarded" : "explicit";
03929 
03930   // Now compute effective version identifiers
03931   CmtSystem::is_version_directory (ref_use->version, ref_v, ref_r, ref_p);
03932   CmtSystem::is_version_directory (new_use->version, new_v, new_r, new_p);
03933 
03934   cmt_string new_selected_version = new_use->version;
03935 
03936   if (new_v_explicit && ref_v_explicit && (new_v != ref_v))
03937     {
03938       /*
03939       if (verbose && !Cmt::get_quiet ())
03940         {
03941           cerr << "# Required explicit version " << new_version
03942                << " of package " << ref_use->get_package_name () 
03943                << " incompatible with selected explicit version " << ref_version
03944                << endl;
03945         }
03946 
03947       CmtError::set (CmtError::version_conflict, "BestFitSelector::operate> ");
03948 
03949       if (ref_use != new_use) new_use->discard ();
03950       */
03951 
03952       if (new_v > ref_v)
03953         {
03954           if (verbose && !Cmt::get_quiet ())
03955             {
03956               cerr << "# Select " << new_vc << " version " << new_version 
03957                    << " of package " << ref_use->get_package_name () 
03958                    << " instead of existing " << ref_vc << " " << ref_version 
03959                    << endl;
03960             } 
03961           
03962           if (ref_use != new_use) ref_use->discard ();
03963           selected = new_use;
03964           selected->done = false; // Will read the new requirements
03965         }
03966     }
03967   else if (new_v_wildcarded || ref_v_wildcarded)
03968     {
03969       // at least one of ref or new is wildcarded
03970 
03971       //
03972       // we plan to discard new_use, but if it was specified as explicit 
03973       // and ref_use was wildcarded then new_use will win !!
03974       //
03975       // So then we'll have to understand where are the wild
03976       // cards... If they are on v or r, then we consider them.
03977       // 
03978       //
03979 
03980       if (ref_v_wildcarded && new_v_explicit)
03981         {
03982           if ((ref_use->real_path != new_use->real_path) ||
03983               (ref_use->version != new_use->version))
03984             {
03985               if (ref_use != new_use) ref_use->discard ();
03986               selected = new_use;
03987               selected->done = false; // Will read the new requirements
03988 
03989               if (verbose && !Cmt::get_quiet ())
03990                 {
03991                   cerr << "# Select explicit version " << new_version 
03992                        << "(" << new_use->version << ")" 
03993                        << " of package " << ref_use->get_package_name () 
03994                        << " instead of existing wildcarded " << ref_version 
03995                        << "(" << ref_use->version << ")" 
03996                        << endl;
03997                 }
03998             }
03999           else
04000             {
04001               if (ref_use != new_use) new_use->discard ();
04002               //ref_use->version = new_selected_version;
04003             }
04004         }
04005       else
04006         {
04007           // ref is explicit or new is wildcarded
04008 
04009           /*
04010           if (verbose && !Cmt::get_quiet ())
04011             {
04012               cerr << "# keep " << ref_vc << " version " << ref_version
04013                    << " of package " << ref_use->get_package_name () 
04014                    << " (ignore " << new_vc << " version " << new_version << ")" 
04015                    << endl;
04016             }
04017           */
04018 
04019           if (ref_use != new_use) new_use->discard ();
04020         }
04021     }
04022   else if (new_r_wildcarded || ref_r_wildcarded || (new_r < ref_r))
04023     {
04024       //
04025       // we plan to discard new_use, but if it was specified as explicit 
04026       // and ref_use was wildcarded then new_use will win !!
04027       //
04028       // So then we'll have to understand where are the wild
04029       // cards... If they are on v or r, then we consider them.
04030       // 
04031       //
04032 
04033       if (ref_r_wildcarded && new_r_explicit)
04034         {
04035           // ref has wild card and new has not => new wins
04036 
04037           if ((ref_use->real_path != new_use->real_path) ||
04038               (ref_use->version != new_use->version))
04039             {
04040               if (ref_use != new_use) ref_use->discard ();
04041               selected = new_use;
04042               selected->done = false; // Will read the new requirements
04043 
04044               if (verbose && !Cmt::get_quiet ())
04045                 {
04046                   cerr << "# Select explicit release " << new_version
04047                        << " of package " << ref_use->get_package_name ()
04048                        << " instead of existing wildcarded " << ref_version
04049                        << endl;
04050                 } 
04051             }
04052           else
04053             {
04054               // Just adapt version with new one.
04055 
04056               if (ref_use != new_use) new_use->discard ();
04057               //ref_use->version = new_selected_version;
04058             }
04059         }
04060       else
04061         {
04062           /*
04063           if (verbose &&!Cmt::get_quiet ())
04064             {
04065               cerr << "# keep " << ref_rc << " release " << ref_version 
04066                    << " of package " << ref_use->get_package_name () 
04067                    << " (ignore " << new_rc << " release " << new_version << ")" 
04068                    << endl;
04069             }
04070           */
04071 
04072           if (ref_use != new_use) new_use->discard ();
04073         }
04074     }
04075   else if (new_r > ref_r)
04076     {
04077       if (verbose && !Cmt::get_quiet ())
04078         {
04079           cerr << "# Select " << new_rc << " release " << new_version 
04080                << " of package " << ref_use->get_package_name () 
04081                << " instead of existing " << ref_rc << " " << ref_version 
04082                << endl;
04083         } 
04084 
04085       if (ref_use != new_use) ref_use->discard ();
04086       selected = new_use;
04087       selected->done = false; // Will read the new requirements
04088     }
04089   else if (new_p_wildcarded || ref_p_wildcarded || (new_p < ref_p))
04090     {
04091       //
04092       // we plan to discard new_use, but if it was specified as explicit 
04093       // and ref_use was wildcarded then new_use will win !!
04094       //
04095 
04096       if (ref_p_wildcarded && new_p_explicit)
04097         {
04098           if ((ref_use->real_path != new_use->real_path) ||
04099               (ref_use->version != new_use->version))
04100             {
04101               if (ref_use != new_use) ref_use->discard ();
04102               selected = new_use;
04103               selected->done = false; // Will read the new requirements
04104 
04105               if (verbose && !Cmt::get_quiet ())
04106                 {
04107                   cerr << "# Select explicit patch " << new_version 
04108                        << " of package " << ref_use->get_package_name () 
04109                        << " instead of existing wildcarded " << ref_version 
04110                        << endl;
04111                 }
04112             }
04113           else
04114             {
04115               if (ref_use != new_use) new_use->discard ();
04116               ref_use->version = new_selected_version;
04117             }
04118         }
04119       else
04120         {
04121           /*
04122           if (verbose && !Cmt::get_quiet ())
04123             {
04124               cerr << "# keep " << ref_pc << " patch " << ref_version 
04125                    << " [" << ref_use->specified_version << "]" 
04126                    << " of package " << ref_use->get_package_name () 
04127                    << " (ignore " << new_pc << " version " << new_version << ")" 
04128                    << " [" << new_use->specified_version << "]" 
04129                    << endl;
04130             }
04131           */
04132 
04133           if (ref_use != new_use) new_use->discard ();
04134         }
04135     }
04136   else if (new_p > ref_p)
04137     {
04138       if (verbose && !Cmt::get_quiet ())
04139         {
04140           cerr << "# Select " << new_pc << " patch " << new_version 
04141                << " of package " << ref_use->get_package_name () 
04142                << " instead of existing " << ref_pc << " " << ref_version 
04143                << endl;
04144         }
04145 
04146       if (ref_use != new_use) ref_use->discard ();
04147       selected = new_use;
04148       selected->done = false; // Will read the new requirements
04149     }
04150   else if (new_pp != ref_pp) // same version-r-p but from different path
04151     {
04152       if (ref_use != new_use) ref_use->discard ();
04153       selected = new_use;
04154       selected->done = false; // Will read the new requirements
04155     }
04156 
04157   return (selected);
04158 }
04159 
04160 
04161 
04162 
04163 
04164 
04165 Package* Package::find (const cmt_string& name)
04166 {
04167   static PackageMap& PackageMap = package_map ();
04168 
04169   Package* result = 0;
04170 
04171   result = PackageMap.find (name);
04172 
04173   return (result);
04174 }
04175 
04176 Package* Package::add (const cmt_string& name)
04177 {
04178   static PackageVector& Packages = packages ();
04179   static PackageMap& PackageMap = package_map ();
04180 
04181   {
04182     Package* package;
04183 
04184     package = find (name);
04185     if (package != 0) return (package);
04186   }
04187 
04188   Package& package = Packages.add ();
04189   PackageMap.add (name, package);
04190 
04191   package.m_name = name;
04192 
04193   if (name == "CMT")
04194     {
04195       package.m_is_cmt = true;
04196     }
04197   else if (name == "methods")
04198     {
04199       package.m_is_cmt = true;
04200     }
04201 
04202   if (Cmt::get_debug ())
04203     {
04204       cout << "Package::add (" << name << ")" << endl;
04205     }
04206 
04207   return (&package);
04208 }
04209 
04210 Package::PackageVector& Package::packages ()
04211 {
04212   static Database& db = Database::instance ();
04213   static PackageVector& Packages = db.packages ();
04214 
04215   return (Packages);
04216 }
04217 
04218 Package::PackageMap& Package::package_map ()
04219 {
04220   static Database& db = Database::instance ();
04221   static PackageMap& PackageMap = db.package_map ();
04222 
04223   return (PackageMap);
04224 }
04225 
04226 void Package::clear_all ()
04227 {
04228   static PackageVector& Packages = packages ();
04229   static PackageMap& PackageMap = package_map ();
04230 
04231   PackageMap.clear ();
04232   Packages.clear ();
04233 }
04234 
04235 Package::Package () : m_is_cmt (false)
04236 {
04237   if (Cmt::get_debug ())
04238     {
04239       cout << "Package::Package" << endl;
04240     }
04241 }
04242 
04243 Package::~Package ()
04244 {
04245   m_name = "";
04246 }
04247 
04248 const cmt_string& Package::get_name () const
04249 {
04250   return (m_name);
04251 }
04252 
04253 void Package::add_use (Use* use)
04254 {
04255   for (int i = 0; i < m_uses.size (); i++)
04256     {
04257       Use* u = m_uses[i];
04258       if (u == use) return;
04259     }
04260 
04261   m_uses.push_back (use);
04262 }
04263 
04264 void Package::remove_use (Use* use)
04265 {
04266   if (Cmt::get_debug ())
04267     {
04268       cout << "Package::remove_use (" << use->get_package_name () << ")" << endl;
04269       cout << "  name=" << m_name
04270            << " uses=" << m_uses.size () << endl;
04271     }
04272 
04273   Use::UsePtrVector temp;
04274 
04275   temp = m_uses;
04276 
04277   m_uses.clear ();
04278 
04279   for (int i = 0; i < temp.size (); i++)
04280     {
04281       Use* u = temp[i];
04282       if (u != use)
04283         {
04284           m_uses.push_back (u);
04285         }
04286     }
04287 }
04288 
04289 Use::UsePtrVector& Package::get_uses ()
04290 {
04291   return (m_uses);
04292 }
04293 
04294 bool Package::is_cmt ()
04295 {
04296   return (m_is_cmt);
04297 }
04298 
04299 static void show_packages ()
04300 {
04301   Package::PackageVector& vector = Package::packages ();
04302 
04303   int i;
04304   int j;
04305 
04306   cout << "### Packages: ";
04307   for (i = 0; i < vector.size (); i++)
04308     {
04309       Package& p = vector[i];
04310       cout << p.get_name () << "[";
04311       Use::UsePtrVector& uses = p.get_uses ();
04312       for (j = 0; j < uses.size (); j++)
04313         {
04314           Use* u = uses[j];
04315           cout << u << ",";
04316         }
04317 
04318       cout << "] ";
04319     }
04320   cout << endl;
04321 
04322   {
04323     static Use::UsePtrVector& uses = Use::get_ordered_uses ();
04324 
04325     cout << "### Uses: ";
04326     for (i = 0; i < uses.size (); i++)
04327       {
04328         Use* u = uses[i];
04329         cout << "[" << u << "]" << u->get_package_name () << " ";
04330       }
04331   }
04332 
04333   cout << endl;
04334 }
04335 

Generated on Mon May 2 10:25:06 2005 for CMT by doxygen 1.3.5