cmt_use.cxx Source File

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 }