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

cmt_use.cxx

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

Generated at Mon Jun 10 17:57:50 2002 for CMT by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000