source: CMT/HEAD/source/cmt_use.cxx @ 570

Last change on this file since 570 was 570, checked in by rybkin, 13 years ago

See C.L. 453

  • Property svn:eol-style set to native
File size: 123.0 KB
Line 
1//-----------------------------------------------------------
2// Copyright Christian Arnault LAL-Orsay CNRS
3// arnault@lal.in2p3.fr
4// Modified by garonne@lal.in2p3.fr
5// See the complete license in cmt_license.txt "http://www.cecill.info".
6//-----------------------------------------------------------
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12#include "cmt_use.h"
13#include "cmt_system.h"
14#include "cmt_symbol.h"
15#include "cmt_error.h"
16#include "cmt_database.h"
17#include "cmt_syntax.h"
18#include "cmt_log.h"
19
20static void show_packages ();
21
22/*
23 *   Design.
24 *
25 *   There is one central database of all Use objects. This in the Database using:
26 *       Database::instance().get_instances ();
27 *
28 *   There is also a list of selected Use pointers available from
29 *       Database::instance().get_ordered_uses ();
30 *
31 *   A new Use object is created when a new use statement requires it:
32 *     o if the specified version is specified for the first time
33 *     o if the specified path is specified for the first time
34 *
35 */
36
37static bool add_request (const cmt_string& path,
38                         const cmt_string& package_name,
39                         const cmt_string& version)
40{
41  static cmt_map <cmt_string, bool> requests;
42
43  cmt_string request = package_name;
44  request += " ";
45  request += version;
46  request += " ";
47  request += path;
48  static bool b = true;
49
50  bool new_request = false;
51
52  if (!requests.has ((const cmt_string&) request))
53    {
54      new_request = true;
55      requests.add ((const cmt_string&) request, b);
56    }
57
58  return (new_request);
59}
60
61class UseContext
62{
63public:
64
65  static UseContext& current ()
66  {
67    static UseContext me;
68
69    return (me);
70  }
71
72  UseContext ()
73  {
74    m_auto_imports = Unspecified;
75    //m_auto_imports = On;
76  }
77
78  UseContext (const UseContext& other)
79  {
80    m_auto_imports = other.m_auto_imports;
81  }
82
83  UseContext& operator = (const UseContext& other)
84  {
85    m_auto_imports = other.m_auto_imports;
86
87    return (*this);
88  }
89
90  static void set_current (State auto_imports)
91  {
92    UseContext& c = current ();
93
94    c.m_auto_imports = auto_imports;
95  }
96
97  static State get_current_auto_imports ()
98  {
99    UseContext& c = current ();
100
101    return (c.m_auto_imports);
102  }
103
104  static State mask_auto_imports (State context_state, State auto_imports)
105  {
106    switch (auto_imports)
107      {
108      case Unspecified:
109        return context_state;
110        break;
111      case Off:
112        return Off;
113        break;
114      case On:
115        if (context_state != Off)
116          return On;
117        else
118          return context_state;
119        break;
120      }
121  }
122
123private:
124  State m_auto_imports;
125};
126
127
128class BestFitSelector
129{
130public:
131  Use* operate (Use* ref_use, Use* new_use);
132};
133
134//----------------------------------------------------------
135
136typedef enum
137  {
138    IdenticalIds,
139
140    IncompatibleMajorIds,
141    NewMajorIdGreaterThanOld,
142    OldMajorIdGreaterThanNew,
143    ExplicitOldMajorIdWinsAgainstWildarded,
144    ExplicitNewMajorIdWinsAgainstWildarded,
145
146    ExplicitOldMinorIdWinsAgainstWildarded,
147    ExplicitNewMinorIdWinsAgainstWildarded,
148    NewMinorIdGreaterThanOld,
149
150    ExplicitOldPatchIdWinsAgainstWildarded,
151    ExplicitNewPatchIdWinsAgainstWildarded,
152    NewPatchIdGreaterThanOld
153  } CompareStatus;
154
155static CompareStatus compare_versions (const cmt_string& ref_version, const cmt_string& new_version, bool match = false)
156{
157  CompareStatus result = IdenticalIds;
158
159  if (match)
160    {
161      if (ref_version == "" ||
162          ref_version == "*" ||
163          ref_version == "v*")
164        return IdenticalIds;
165
166      int wild_card = ref_version.find ('*');
167      if (wild_card != cmt_string::npos)
168        {
169          cmt_string ref_ver (ref_version.substr (0, wild_card));
170          if (ref_ver.size () > new_version.size ())
171            return IncompatibleMajorIds;
172          else if (strncmp (ref_ver.c_str (), new_version.c_str (), wild_card) == 0)
173            return IdenticalIds;
174          else
175            return IncompatibleMajorIds;
176        }
177      else if (ref_version == new_version)
178            return IdenticalIds;
179      else
180            return IncompatibleMajorIds;
181    }
182
183  int old_v = -1;
184  int old_r = -1;
185  int old_p = -1;
186
187  int new_v = -1;
188  int new_r = -1;
189  int new_p = -1;
190
191  CmtSystem::is_version_directory (ref_version, old_v, old_r, old_p);
192
193  CmtSystem::is_version_directory (new_version, new_v, new_r, new_p);
194
195  if ((new_v != -1) && (old_v != -1) && (new_v != old_v))
196    {
197      /*
198        if (!Cmt::get_quiet ())
199        {
200        cerr << "#1 Required version " << new_version <<
201        " incompatible with selected version " << ref_version <<
202        endl;
203        }
204      */
205
206      if (new_v > old_v)
207        {
208          result = NewMajorIdGreaterThanOld;
209        }
210      else
211        {
212          result = OldMajorIdGreaterThanNew;
213        }
214      //result = IncompatibleMajorIds;
215    }
216  else if ((new_v == -1) || (old_v == -1))
217    {
218      //
219      // we plan to discard new_use, but if it was specified as explicit
220      // and ref_use was wildcarded then new_use will win !!
221      //
222      // So then we'll have to understand where are the wild
223      // cards... If they are on v or r, then we consider them.
224      //
225      //
226
227
228      if ((old_v == -1) && (new_v != -1))
229        {
230          /*
231            if (!Cmt::get_quiet ())
232            {
233            cerr << "#2 Select version " << new_version <<
234            " instead of existing " << ref_version <<
235            endl;
236            }
237          */
238
239          result = ExplicitNewMajorIdWinsAgainstWildarded;
240        }
241      else
242        {
243          /*
244            if (!Cmt::get_quiet ())
245            cerr << "#3 keep version " << ref_version <<
246            " (ignore version " << new_version << ")" <<
247            endl;
248          */
249
250          result = ExplicitOldMajorIdWinsAgainstWildarded;
251        }
252    }
253  else if ((new_r == -1) || (old_r == -1) || (new_r < old_r))
254    {
255      //
256      // we plan to discard new_use, but if it was specified as explicit
257      // and ref_use was wildcarded then new_use will win !!
258      //
259      // So then we'll have to understand where are the wild
260      // cards... If they are on v or r, then we consider them.
261      //
262      //
263
264
265      if ((old_r == -1) && (new_r != -1))
266        {
267          // old has wild card and new has not => new wins
268
269          /*
270            if (!Cmt::get_quiet ())
271            {
272            cerr << "#4 Select release " << new_version
273            << " instead of existing " << ref_version
274            << endl;
275            }
276          */
277
278          result = ExplicitNewMinorIdWinsAgainstWildarded;
279        }
280      else
281        {
282          /*
283            if (!Cmt::get_quiet ())
284            cerr << "#5 keep release " << ref_version <<
285            " (ignore release " << new_version << ")" <<
286            endl;
287          */
288
289          result = ExplicitOldMinorIdWinsAgainstWildarded;
290        }
291    }
292  else if (new_r > old_r)
293    {
294      /*
295        if (!Cmt::get_quiet ())
296        {
297        cerr << "#6 Select release " << new_version <<
298        " instead of existing " << ref_version <<
299        endl;
300        }
301      */
302 
303      result = NewMinorIdGreaterThanOld;
304    }
305  else if ((new_p == -1) || (old_p == -1) || (new_p < old_p))
306    {
307      //
308      // we plan to discard new_use, but if it was specified as explicit
309      // and ref_use was wildcarded then new_use will win !!
310      //
311
312
313      if ((old_p == -1) && (new_p != -1))
314        {
315          /*
316            if (!Cmt::get_quiet ())
317            {
318            cerr << "#7 Select patch " << new_version <<
319            " instead of existing " << ref_version <<
320            endl;
321            }
322          */
323
324          result = ExplicitNewPatchIdWinsAgainstWildarded;
325        }
326      else
327        {
328          /*
329            if (!Cmt::get_quiet ())
330            cerr << "#8 keep patch " << ref_version <<
331            " (ignore version " << new_version << ")" <<
332            endl;
333          */
334
335          result = ExplicitOldPatchIdWinsAgainstWildarded;
336        }
337    }
338  else if (new_p > old_p)
339    {
340      /*
341        if (!Cmt::get_quiet ())
342        {
343        cerr << "#9 Select patch " << new_version <<
344        " instead of existing " << ref_version <<
345        endl;
346        }
347      */
348
349      result = NewPatchIdGreaterThanOld;
350    }
351
352  return (result);
353}
354
355//----------------------------------------------------------
356//
357//  Operations on Use
358//
359//----------------------------------------------------------
360
361/**
362 *  Mark all clients of the current package.
363 */
364void Use::select_clients (const cmt_string& package,
365                          const cmt_string& version)
366{
367  static UsePtrVector& uses = get_ordered_uses ();
368
369  int number;
370  Use* use = 0;
371
372  unselect_all ();
373  undiscard_all ();
374
375  for (number = uses.size () - 1; number >= 0; number--)
376    {
377      use = uses[number];
378      if (use == 0) continue;
379      if (use->is_selected ()) continue;
380      use->select ();
381      if (!use->is_client (package, version)) use->discard ();
382    }
383}
384
385//----------------------------------------------------------
386void Use::show_all (bool skip_discarded, ostream& out, PrintMode mode)
387//void Use::show_all (bool skip_discarded, ostream& out)
388//void Use::show_all (bool skip_discarded)
389{
390  show_all ("use ", skip_discarded, out, mode);
391  //  show_all ("use ", skip_discarded, out);
392}
393
394//----------------------------------------------------------
395void Use::show_cycles ()
396{
397  static int level = 0;
398  static UsePtrVector stack;
399  int size = 0;
400
401  if (level == 0)
402    {
403      unselect_all ();
404      unselect ();
405      stack.clear ();
406    }
407
408  //for (int i = 0; i < level; i++) cout << "  ";
409  //cout << "Use::show_cycles> " << level << " " << get_package_name () << endl;
410 
411  // Detect cycles.
412  for (int k = 0; k < level; k++)
413    {
414      Use* u = stack[k];
415      if (u == this) 
416        {
417          for (;k < level; k++)
418            {
419              u = stack[k];
420              cout << u->get_package_name () << " ";
421            }
422
423          cout << endl;
424
425          return;
426        }
427    }
428
429  // Save this to the stack.
430  if (stack.size () <= level)
431    {
432      stack.push_back (this);
433    }
434  else
435    {
436      stack[level] = this;
437    }
438
439  if (selected) return;
440  selected = true;
441
442  size = sub_uses.size ();
443  for (int n = 0; n < size; n++)
444    {
445      Use* use = sub_uses[n];
446     
447      if (use == 0) continue;
448     
449      //for (int i = 0; i < level; i++) cout << "  ";
450      //cout << "Use::show_cycles> " << get_package_name () << " uses " << use->get_package_name () << endl;
451
452      if (use->discarded)
453        {
454          Use* u;
455         
456          u = use->get_selected_version ();
457          if (u == 0) continue;
458         
459          use = u;
460        }
461     
462      level++;
463      use->show_cycles ();
464      level--;
465    }
466}
467
468//----------------------------------------------------------
469void Use::push_scope_section (ScopeType type)
470{
471  scope_sections.push_back (type);
472}
473
474//----------------------------------------------------------
475void Use::pop_scope_section ()
476{
477  scope_sections.pop_back ();
478}
479
480//----------------------------------------------------------
481void Use::close_scope_sections ()
482{
483  scope_sections.clear ();
484}
485
486//----------------------------------------------------------
487ScopeType Use::get_current_scope () const
488{
489  if (scope_sections.size () == 0) return (initial_scope);
490  const ScopeSection& s = scope_sections.back ();
491  return (s.get_scope ());
492}
493
494//----------------------------------------------------------
495void Use::show_all (const cmt_string& prefix, bool skip_discarded, ostream& out, PrintMode mode)
496//void Use::show_all (const cmt_string& prefix, bool skip_discarded, ostream& out)
497//void Use::show_all (const cmt_string& prefix, bool skip_discarded)
498{
499  static UsePtrVector& uses = get_ordered_uses ();
500
501  Use* use;
502  int number;
503
504  if (Cmt::get_debug ())
505    {
506      cout << "use::show_all-1> ";
507     
508      int i;
509     
510      for (i = 0; i < uses.size (); i++)
511        {
512          Use* u = uses[i];
513          cout << u->get_package_name () << "[" << u->get_index () << "]" << " ";
514        }
515     
516      cout << endl;
517    }
518
519  unselect_all ();
520
521  use = &(current ());
522  use->unselect ();
523  if (!Cmt::get_quiet () && mode != Xml) use->show_sub_uses ("", skip_discarded, out);
524
525  if (uses.size () > 0)
526    {
527      if (!Cmt::get_quiet () && mode != Xml)
528        {
529          out << "#\n";
530          out << "# Selection :\n";
531        }
532
533      //
534      //  First move the CMT package to the end of the use set.
535      //  (ie. used by everybody)
536      //
537      use = Use::find ("CMT");
538      Use::move (use);
539
540      switch (mode)
541        {
542        case Xml :
543          Cmt::print_xml_prolog ("uses", out);
544          out << "<uses>";
545          break;
546        }
547     
548      for (number = uses.size () - 1; number >= 0; number--)
549        {
550          use = uses[number];
551
552          if (use->discarded) continue;
553          if (use->m_hidden) continue;
554
555          if (!use->located ())
556            {
557              CmtMessage::warning ("package " + use->get_package_name ()
558                                   + " " + use->version + " " + use->path
559                                   + " not found");
560              /*
561              if (!Cmt::get_quiet ())
562                {
563                  out << "# package " << use->get_package_name () <<
564                    " " << use->version << " " << use->path <<
565                    " not found" <<
566                    endl;
567                }
568              */
569              CmtError::set (CmtError::package_not_found, use->get_package_name ());
570            }
571          else
572            {
573              switch (mode)
574                {
575                case Xml :
576                  Symbol* s;
577                  out << "<package"
578                      << (use->auto_imports == Off ? " auto_imports=\"no\"" : "")
579                      << ">";
580                  // out << "<order>" << use->get_index () << "</order>";
581                  out << "<name>" << use->get_package_name ()
582                      << "</name><version>" << use->version << "</version>";
583                  out << "<offset>" <<
584                    ( (s = Symbol::find (use->get_package_name () + "_offset"))
585                      ? s->build_macro_value ()
586                      : (CmtMessage::warning
587                         (CmtError::get_error_name (CmtError::symbol_not_found)
588                          + ": macro " + use->get_package_name () + "_offset")
589                         , "") )
590                      << "</offset>";
591                  out << "<cmtpath>" <<
592                    ( (s = Symbol::find (use->get_package_name () + "_cmtpath"))
593                      ? s->build_macro_value ()
594                      : (CmtMessage::warning
595                         (CmtError::get_error_name (CmtError::symbol_not_found)
596                          + ": macro " + use->get_package_name () + "_cmtpath")
597                         , "") )
598                      << "</cmtpath>";
599                  //out << "<offset>" << use->path << "</offset>";
600                  //out << "<cmtpath>" << p << "</cmtpath>";
601                  out << "<root>" << use->get_full_path () << "</root>";
602                  //if (use->auto_imports == Off)
603                  //out << "<no_auto_imports/>";
604                  out << "</package>";
605                  break;
606                default :
607              static const cmt_string empty;
608              cmt_string p = use->real_path;
609              if (use->path != "")
610                {
611                  int pos = p.find_last_of (use->path);
612                  if (pos != cmt_string::npos)
613                    {
614                      if (pos > 0 &&
615                          p[pos - 1] == CmtSystem::file_separator ())
616                        {
617                          // strip trailing file separator
618                          p.erase (pos - 1);
619                        }
620                      else
621                        p.erase (pos);
622                    }
623                }
624
625              out << prefix << use->get_package_name ()
626                   << " " << use->version;
627
628              if (CmtSystem::absolute_path (use->path))
629                {
630                  if (!Cmt::get_quiet ()) 
631                    {
632                      out << " (" << use->path << ")";
633                    }
634                }
635              else
636                {
637                  out << " " << use->path;
638                }
639
640              if (!Cmt::get_quiet ()) 
641                {
642                  if (p != "") out << " (" << p << ")";
643                  if (use->auto_imports == Off) out << " (no_auto_imports)";
644                }
645
646              out << endl;
647                  break;
648                }
649            }
650        }
651
652      Use* suse = Use::find (CmtSystem::get_home_package ());
653      if (suse != 0 && !suse->discarded && !suse->m_hidden && suse->located ())
654        {
655          switch (mode)
656            {
657            case Xml :
658              out << "<package>";
659              out << "<name>" << suse->get_package_name ()
660                  << "</name><version>" << suse->version << "</version>";
661              out << "<offset></offset>";
662              out << "<cmtpath>" << suse->path << "</cmtpath>";
663              out << "<root>" << suse->path << "</root>";
664              out << "</package>";
665              break;
666            default :
667          out << prefix << suse->get_package_name ()
668               << " " << suse->version;
669          if (!Cmt::get_quiet ()) 
670            {
671              out << " (" << suse->path << ")";
672            }
673          out << endl;
674              break;
675            }
676        }
677      suse = Use::find (CmtSystem::get_user_context_package ());
678      if (suse != 0 && !suse->discarded && !suse->m_hidden && suse->located ())
679        {
680          switch (mode)
681            {
682            case Xml :
683              out << "<package>";
684              out << "<name>" << suse->get_package_name ()
685                  << "</name><version>" << suse->version << "</version>";
686              out << "<offset></offset>";
687              out << "<cmtpath>" << suse->path << "</cmtpath>";
688              out << "<root>" << suse->path << "</root>";
689              out << "</package>";
690              break;
691            default :
692          out << prefix << suse->get_package_name ()
693               << " " << suse->version;
694          if (!Cmt::get_quiet ()) 
695            {
696              out << " (" << suse->path << ")";
697            }
698          out << endl;
699              break;
700            }
701        }
702
703      switch (mode)
704        {
705        case Xml :
706          out << "</uses>" << endl;
707          break;
708        }
709      /*
710      if (Cmt::get_cmt_home () != "")
711        {
712          out << prefix << CmtSystem::get_home_package () << " v0";
713          if (!Cmt::get_quiet ())
714            {
715              out << " (" << Cmt::get_cmt_home () << ")";
716            }
717          out << endl;
718        }
719
720      if (Cmt::get_cmt_user_context () != "")
721        {
722          out << prefix << CmtSystem::get_user_context_package () << " v0";
723          if (!Cmt::get_quiet ())
724            {
725              out << " (" << Cmt::get_cmt_user_context () << ")";
726            }
727          out << endl;
728        }
729      */
730    }
731 
732  const UseVector& instances = get_instances ();
733  for (int use_index = 0; use_index < instances.size (); use_index++)
734    {
735      Use* use = &(instances[use_index]);
736      //Use* use = uses[j];
737     
738      if (use->discarded) continue;
739      if (use->m_hidden) continue;
740     
741      if (!use->located ())
742        {
743          CmtError::set (CmtError::package_not_found, use->get_info ());
744        }
745      else
746        {
747          /*
748            CmtMessage::info ("package " +
749            use->get_package_name () +
750            " " + use->version +
751            (use->path != "" ? " " + use->path : "") +
752            " found");
753          */
754        }
755    }
756}
757
758/**
759 *   This private class parses the use statement after macro expansion
760 *   This is a finite state machine.
761 *    It maintains the results of the parsing in terms of a package name,
762 *   a version, a path, and state variables (no_auto_imports)
763 */
764class use_action_iterator
765{
766public:
767
768  use_action_iterator ()
769  {
770    state = need_package;
771    auto_imports = Unspecified;
772  }
773
774  void set (const cmt_string& w)
775  {
776    if (w.find (0, "-native_version=") != -1)
777      {
778        native_version = w.substr (16);
779      }
780    else if (w == "-auto_imports")
781      {
782        auto_imports = On;
783      }
784    else if (w == "-no_auto_imports")
785      {
786        auto_imports = Off;
787      }
788    else if (w == "|")
789      {
790        state = need_version_alias;
791      }
792    else
793      {
794        switch (state)
795          {
796          case need_package:
797            package = w;
798            state = need_version;
799            break;
800          case need_version:
801            version = w;
802            state = need_path;
803            break;
804          case need_path:
805            path = w;
806            while (path[path.size() - 1] == '/') path.erase (path.size() - 1);
807            while (path[path.size() - 1] == '\\') path.erase (path.size() - 1);
808            state = finished;
809            break;
810          case need_version_alias:
811            version_alias = w;
812            state = need_path_alias;
813            break;
814          case need_path_alias:
815            path_alias = w;
816            while (path_alias[path_alias.size() - 1] == '/') path_alias.erase (path_alias.size() - 1);
817            while (path_alias[path_alias.size() - 1] == '\\') path_alias.erase (path_alias.size() - 1);
818            state = finished;
819            break;
820          }
821      }
822  }
823
824  bool ok ()
825  {
826    if (package == "") return (false);
827    if (CmtSystem::is_home_package (package, version)) return (false);
828    if (CmtSystem::is_user_context_package (package, version)) return (false);
829    if (CmtSystem::is_project_package (package, version)) return (false);
830
831    return (true);
832  }
833
834  /**
835   *
836   *  Build or retreive the Use object corresponding to the parsed specification.
837   *
838   */
839  Use* get_use (Use* parent)
840  {
841    static Use::UsePtrVector& uses = Use::get_ordered_uses ();
842
843    if (version == "") version = "*";
844
845    if (Cmt::get_debug ())
846      {
847        int i;
848
849        cout << "use::action1> current=" << parent->get_package_name () <<
850          " package=" << package << "(" << version << ")" << " ";
851
852        for (i = 0; i < uses.size (); i++)
853          {
854            Use* u = uses[i];
855            cout << u->get_package_name () << " ";
856          }
857        cout << endl;
858      }
859
860    const Use& cu = Use::current ();
861
862    /**
863     *   Do not continue the operations for private uses
864     *  accessed from an external context.
865     *
866     *   Exceptions should be considered for
867     *     - cmt broadcast
868     *     - cmt show uses
869     */
870
871    ActionType action = Cmt::get_action ();
872
873    if (Cmt::get_debug ())
874      {
875        cout << "before adding " << package <<"> auto_imports=" << auto_imports
876             << " (current AI was " << UseContext::get_current_auto_imports () << ")" 
877             << " (Use::scope=" << parent->get_current_scope () << ")"
878             << " (parent=" << parent->get_package_name () << ")"
879             << endl;
880      }
881
882    bool hidden_by_scope = false;
883
884    if (parent->get_current_scope () == ScopePrivate)
885      {
886        hidden_by_scope = true;
887
888        // Do not hide immediate children of the current package.
889        if ((parent == 0) || 
890            (parent->get_package () == cu.get_package ())) hidden_by_scope = false;
891
892        // Override default rule according to the scope filtering mode.
893
894        if (Cmt::get_scope_filtering_mode () == reach_private_uses) hidden_by_scope = false;
895      }
896
897    if (hidden_by_scope)
898      {
899        return (0);
900      }
901
902    // Here the version may contain wild cards
903
904    //UseContext save = UseContext::current ();
905
906    /**
907     *  "auto_imports" is the state which is specified on the use statement
908     *  currently being parsed.
909     */
910    //UseContext::set_current (UseContext::mask_auto_imports (UseContext::get_current_auto_imports (), auto_imports));
911    /*
912    switch (auto_imports)
913      {
914      case Unspecified:
915
916        // unspecified => we forward the state saved in the current use context
917
918        //UseContext::set_current (UseContext::get_current_auto_imports ());
919        break;
920      case Off:
921
922        // off => the context becomes constrained to be off
923
924        UseContext::set_current (Off);
925        break;
926      case On:
927
928        // on => if current context is off it is kept off
929        //       otherwise it is forced to on
930
931        if (UseContext::get_current_auto_imports () != Off)
932          {
933            UseContext::set_current (On);
934          }
935        break;
936      }
937*/
938    if (Cmt::get_debug ())
939      {
940        cout << "about to add " << package << endl;
941        //show_packages ();
942      }
943
944    /// Now do create or retreive the Use object.
945        Use* new_use = Use::add (path, package, version, 
946                                 version_alias, path_alias, native_version,
947                                 parent, auto_imports);
948
949        if (new_use != 0)
950          {
951            if (Cmt::get_debug ())
952              {
953                cout << "after adding1 " << package
954                     << "> auto_imports=" << new_use->auto_imports << endl;
955
956                //show_packages ();
957              }
958            /*
959            if (&(Use::current()) == parent)
960              {
961                cmt_map <Use*, bool> visited;
962                static bool yes (true);
963                visited.add (&(Use::current()), yes);
964                new_use->set_auto_imports
965                  (UseContext::mask_auto_imports (Use::current().auto_imports,
966                                                  auto_imports),
967                   auto_imports, visited);
968              }
969            */
970            //new_use->set_auto_imports (UseContext::get_current_auto_imports (),
971            //                 auto_imports);
972            /*
973            switch (new_use->auto_imports)
974              {
975              case Unspecified:
976                new_use->auto_imports = UseContext::get_current_auto_imports ();
977                if (new_use->auto_imports == Unspecified)
978                  {
979                    new_use->auto_imports = On;
980                  }
981                break;
982              case On:
983                break;
984              case Off:
985                if (UseContext::get_current_auto_imports () != Off)
986                  //if (UseContext::get_current_auto_imports () == On)
987                  {
988            */
989                    /**
990                     *  Warning : this Use had been previously specified as -no_auto_imports
991                     *  Now this new specification tries to turn it to auto_imports.
992                     *  It will be required to propagate the change, according to the
993                     *  specifications:
994                     *
995                     *    for all sub_uses:
996                     *       if it is unspecified OR specified as auto_imports:
997                     *          turn it to auto_imports
998                     *
999                     */
1000            /*
1001                    new_use->set_auto_imports (UseContext::get_current_auto_imports ());
1002                    //new_use->set_auto_imports (On);
1003                  }
1004                break;
1005              }
1006            */
1007
1008            if (Cmt::get_debug ())
1009              {
1010                cout << "after adding2 " << package
1011                     << "> auto_imports=" << new_use->auto_imports << " ";
1012                cout << endl;
1013              }
1014
1015            //UseContext& c = UseContext::current ();
1016            //c = save;
1017
1018            Use::reorder (new_use, parent);
1019           
1020            if (Cmt::get_debug ())
1021              {
1022                cout << "use::action2> current=" << parent->get_package_name ()
1023                     << " package=" << package << " ";
1024
1025                int i;
1026               
1027                for (i = 0; i < uses.size (); i++)
1028                  {
1029                    Use* u = uses[i];
1030                    cout << u->get_package_name () << "[" << u->get_index () << "]" << " ";
1031                  }
1032
1033                cout << endl;
1034              }
1035          }
1036        /*
1037        else // new_use == 0
1038          {
1039            cerr << "action: " << action << " new_use: " <<  new_use
1040                 << " package: " <<  package << endl;
1041
1042            CmtError::set (CmtError::package_not_found, package);
1043          }
1044        */
1045
1046        return (new_use);
1047  }
1048
1049private:
1050
1051  enum
1052    {
1053      need_package,
1054      need_version,
1055      need_path,
1056      need_version_alias,
1057      need_path_alias,
1058      finished
1059    } state;
1060 
1061  State auto_imports;
1062  cmt_string native_version;
1063  cmt_string package;
1064  cmt_string version;
1065  cmt_string path;
1066  cmt_string version_alias;
1067  cmt_string path_alias;
1068};
1069
1070//----------------------------------------------------------
1071Use* Use::action (const CmtSystem::cmt_string_vector& words, Use* parent)
1072{
1073  Use* new_use;
1074
1075  //
1076  // complete syntax : "use <package> <version> <path> <-native_version=<version>>" 
1077  // minimal syntax  : "use <package>"
1078  //
1079  //  o if <version> is omitted then take any version available
1080  //  o <version> can be specified using "v*" or "v<n>r*" or "v<n>r<m>p*"
1081  //
1082  //  o the notation "v*" is preferred to omission (particularly since
1083  //    omission does not permit <path>)
1084  //
1085  if (words.size () < 2) return (0);
1086
1087  use_action_iterator it;
1088
1089  for (int i = 1; i < words.size (); i++)
1090    {
1091      const cmt_string& w = words[i];
1092      cmt_string ew = w;
1093
1094      Symbol::expand (ew);
1095      if (ew != w)
1096        {
1097          CmtSystem::cmt_string_vector ws;
1098
1099          CmtSystem::split (ew, " ", ws);
1100
1101          for (int j = 0; j < ws.size (); ++j)
1102            {
1103              const cmt_string& ww = ws[j];
1104              it.set (ww);
1105            }
1106        }
1107      else
1108        {
1109          it.set (ew);
1110        }
1111    }
1112
1113  if (!it.ok ()) return (0);
1114
1115  static int level = 0;
1116
1117  level++;
1118  new_use = it.get_use (parent);
1119  level--;
1120
1121  return (new_use);
1122}
1123
1124//----------------------------------------------------------
1125void Use::author_action (const CmtSystem::cmt_string_vector& words)
1126{
1127  if (author != "") author += "\n";
1128  for (int i = 1; i < words.size (); i++)
1129    {
1130      const cmt_string& w = words[i];
1131     
1132      if (i > 1) author += " ";
1133      author += w;
1134    }
1135}
1136//----------------------------------------------------------
1137void Use::manager_action (const CmtSystem::cmt_string_vector& words)
1138{
1139  if (manager != "") manager += "\n";
1140  for (int i = 1; i < words.size (); i++)
1141    {
1142      const cmt_string& w = words[i];
1143     
1144      if (i > 1) manager += " ";
1145      manager += w;
1146    }
1147}
1148
1149//----------------------------------------------------------
1150Use* Use::find (const cmt_string& package, 
1151                const cmt_string& version, 
1152                const cmt_string& path)
1153{
1154  Package* p = Package::find (package);
1155  if (p == 0) return (0);
1156
1157  UsePtrVector& uses = p->get_uses ();
1158
1159  int use_index;
1160  int size = uses.size ();
1161
1162  for (use_index = 0; use_index < size; use_index++)
1163    {
1164      Use& use = (*uses[use_index]);
1165
1166      // If the version argument is omitted then
1167      // take the first registered version
1168      if (version == "") return (&use);
1169         
1170      // Otherwise compare against specified_version and path
1171      //if ((use.specified_version == version) &&
1172      //  (use.specified_path == path)) return (&use);
1173     
1174      // what about comparing wild cards?
1175
1176      if (use.specified_version == version) return (&use);
1177    }
1178
1179  return (0);
1180}
1181
1182//----------------------------------------------------------
1183int Use::find_index (const cmt_string& package_name, 
1184                     const cmt_string& version, 
1185                     const cmt_string& path)
1186{
1187  Package* package = Package::find (package_name);
1188  if (package == 0) return (-1);
1189
1190  UsePtrVector& uses = package->get_uses ();
1191
1192  int use_index;
1193  int size = uses.size ();
1194  for (use_index = 0; use_index < size; use_index++)
1195    {
1196      Use* use = uses[use_index];
1197
1198      if (Cmt::get_debug ())
1199        {
1200          cout << "Use::find_index> " << package_name
1201               << " " << use
1202               << " " << use->m_index
1203               << endl;
1204        }
1205
1206      // If the version argument is omitted then
1207      // take the first registered version
1208      if (version == "") return (use->m_index);
1209     
1210      // Otherwise compare against specified_version and path
1211      //if ((use.specified_version == version) &&
1212      //  (use.specified_path == path)) return (&use);
1213     
1214      // what about comparing wild cards?
1215     
1216      if (use->specified_version == version) return (use->m_index);
1217    }
1218
1219  return (-1);
1220}
1221
1222//----------------------------------------------------------
1223/**
1224 *    Find by @package@ Use-object that is
1225 *    o not discarded
1226 *    o in ordereded Uses list (i.e., has non-negative m_index)
1227 */
1228//----------------------------------------------------------
1229Use* Use::find_valid (const cmt_string& package)
1230{
1231  Package* p = Package::find (package);
1232  if (p == 0) return (0);
1233
1234  UsePtrVector& uses = p->get_uses ();
1235
1236  for (int use_index = 0; use_index < uses.size (); use_index++)
1237    {
1238      Use* use = uses[use_index];
1239
1240      if (use->discarded) continue;
1241      if (use->m_index < 0) continue;
1242      // take the first not discarded and ordered
1243      // there should not be more than one
1244      return use;
1245    }
1246
1247  return (0);
1248}
1249
1250//----------------------------------------------------------
1251void Use::set_auto_imports_state (const Use::UsePtrVector& uses,
1252                                  cmt_vector<bool>& auto_imports_states,
1253                                  cmt_map <Use*, bool>& visited)
1254{
1255  if (0 == uses.size ()) return;
1256  static bool yes (true);
1257
1258  static int level (-1);
1259  level++;
1260  if (level == 0)
1261    {
1262      unselect_all ();
1263    }
1264
1265  if (Cmt::get_debug ())
1266    {
1267      cout << "Use::set_auto_imports_state>|";
1268      for (int i = level; i > 0; i--) cout << "-";
1269      for (int i = 0; i < uses.size (); i++)
1270      //for (int i = uses.size () - 1; i >= 0; i--)
1271        {
1272          cout << " " << uses[i]->get_package_name ()
1273               << "(" << uses[i]->auto_imports << ")";
1274        }
1275      cout << ">" << endl;
1276    }
1277
1278  for (int i = 0; i < uses.size (); i++)
1279  //for (int i = uses.size () - 1; i >= 0; i--)
1280    {
1281      Use* use = uses[i];
1282      if (visited.has (use) &&
1283          (0 != level || use->is_selected ()))
1284        // revisit uses specified explicitly with -import=<package> (level == 0)
1285        // encountered in constituent specification for the first time (selected == false)
1286        // to ensure <package> is imported
1287        {
1288          continue;
1289        }
1290
1291      visited.add (use, yes);
1292      if (0 == level) use->select ();
1293
1294      if (!auto_imports_states[use->m_index])
1295        auto_imports_states[use->m_index] = true;
1296      //if (0 == level && use->is_selected ()) continue;
1297
1298      Use::UsePtrVector subuses;
1299      for (int i = 0; i < use->sub_uses.size (); i++)
1300        {
1301          if (use->sub_uses[i]->m_index >= 0 && !use->sub_uses[i]->discarded)
1302            {
1303              if (use->sub_use_auto_imports[i] != Off)
1304                {
1305                  subuses.push_back (use->sub_uses[i]);
1306                }
1307              else
1308                {
1309                  visited.add (use->sub_uses[i], yes);
1310                }
1311            }
1312          else
1313            {
1314              if (Cmt::get_debug ())
1315                {
1316                  cout << "Use::set_auto_imports_state> " << use->get_package_name ()
1317                       << " -> sub_use " << use->sub_uses[i]->get_package_name ()
1318                       << "[" << use->sub_uses[i] << ", discarded="
1319                       << use->sub_uses[i]->discarded << ", m_index="
1320                       << use->sub_uses[i]->m_index << " : invalid]" << endl;
1321                }
1322              Use* au (find_valid (use->sub_uses[i]->get_package_name ()));
1323              if (au)
1324                {
1325                  if (Cmt::get_debug ())
1326                    {
1327                      cout << "Use::set_auto_imports_state> " << use->get_package_name ()
1328                           << " -> sub_use " << au->get_package_name ()
1329                           << "[" << au << ", discarded="
1330                           << au->discarded << ", m_index="
1331                           << au->m_index << " : valid]" << endl;
1332                    }
1333                  if (use->sub_use_auto_imports[i] != Off)
1334                    {
1335                      subuses.push_back (au);
1336                    }
1337                  else
1338                    {
1339                      visited.add (au, yes);
1340                    }
1341                }
1342              else
1343                {
1344                  visited.add (use->sub_uses[i], yes);
1345                }
1346            }
1347        }
1348      Use::set_auto_imports_state (subuses, auto_imports_states, visited);
1349    }
1350
1351  if (Cmt::get_debug ())
1352    {
1353      cout << "Use::set_auto_imports_state><";
1354      for (int i = level; i > 0; i--) cout << "-";
1355      for (int i = 0; i < uses.size (); i++)
1356      //for (int i = uses.size () - 1; i >= 0; i--)
1357        {
1358          cout << " " << uses[i]->get_package_name ()
1359               << "(" << (auto_imports_states[uses[i]->m_index] ? "+" : "-") << ")";
1360        }
1361      cout << "|" << endl;
1362    }
1363
1364  level--;
1365  return;
1366}
1367
1368/**
1369 *   1) Given a Use object identified by its index in the ordered_uses() array,
1370 *   2) Given a vector of states containing the auto_imports states of all uses,
1371 *
1372 *     we want to switch to 'On' the auto_imports states of all
1373 *     sub_uses of the argument that were Off.
1374 *
1375 */
1376 /*
1377void Use::set_auto_imports_state (int use_index,
1378                                  cmt_vector<bool>& auto_imports_states)
1379{
1380  // check boundaries (this should be an error when out bondaries)
1381  if ((use_index < 0) || (use_index >= auto_imports_states.size ())) return;
1382
1383  Use::UsePtrVector& uses = Use::get_ordered_uses ();
1384
1385  if (Cmt::get_debug ())
1386    {
1387      int i;
1388     
1389      cout << "Use::set_auto_imports_state> use_index=" << use_index << " ";
1390     
1391      for (i = 0; i < auto_imports_states.size (); i++)
1392        {
1393          cout << (auto_imports_states[i] ? "|" : "o");
1394        }
1395
1396      for (i = 0; i < auto_imports_states.size (); i++)
1397        {
1398          cout << " " << (uses[i])->get_package_name ();
1399        }
1400
1401      cout << endl;
1402    }
1403
1404  // check if this is already done (recursivity ending)
1405  if (auto_imports_states[use_index]) return;
1406  auto_imports_states[use_index] = true;
1407
1408  Use* use = uses[use_index];
1409
1410  // We only have to deal with Use objects that were
1411  // actually turned Off
1412  //  if (use->auto_imports != Off) return;
1413  */
1414  /**
1415   *  Here, use points to a Use object which had been declared as
1416   *  no_auto_imports. But we need to switch it On. Therefore,
1417   *
1418   *    1) the state in auto_imports_states has to be set On
1419   *    2) the operation has to be recursively propagated to all
1420   *         sub_uses which also had no_auto_imports. (only to those)
1421   * 
1422   */
1423 
1424  //  auto_imports_states[use_index] = true;
1425  /*
1426  cmt_string s;
1427  static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
1428 
1429  if (Cmt::get_debug ())
1430    {
1431      s = "Use::set_auto_imports_state>(";
1432      s += use->get_package_name ();
1433      s += ")";
1434      //cout << s << endl;
1435    }
1436
1437  int size = use->sub_uses.size ();
1438  for (int i = 0; i < size; i++)
1439    {
1440      Use* u = use->sub_uses[i];
1441
1442      // first find the index of this use.
1443     
1444      int j = u->m_index;
1445
1446      if (Cmt::get_debug ())
1447        {
1448          char num[32]; sprintf (num, "%#x", u);
1449          s += " ";
1450          s += use->sub_uses[i]->get_package_name ();
1451          s += "(";
1452          s += state_text[use->sub_use_auto_imports[i] + 1];
1453          s += ")[p=";
1454          s += num;
1455          s += "]";
1456        }
1457     
1458      if (j >= 0)
1459        {
1460          if (use->sub_use_auto_imports[i] != Off)
1461            {
1462              set_auto_imports_state (j, auto_imports_states);
1463            }
1464  */
1465          /*
1466          if (u->sub_use_auto_imports[i] == Off)
1467            {
1468              set_auto_imports_state (j, auto_imports_states);
1469            }
1470          else
1471            {
1472              auto_imports_states[j] = true;
1473            }
1474            */
1475  /*
1476        }
1477      else
1478        {
1479          if (Cmt::get_debug ())
1480            {
1481              cout << "Use::set_auto_imports_state> " << use->get_package_name ()
1482                   << ": sub_use " << u->get_package_name () << "[" << u
1483                   << "] invalid" << endl;
1484            }
1485        }
1486    }
1487  if (Cmt::get_debug ())
1488    {
1489      cout << s << endl;
1490    }
1491}
1492  */
1493//----------------------------------------------------------
1494//
1495//  Move use to the end
1496//
1497//----------------------------------------------------------
1498void Use::move (Use* use)
1499{
1500  if (use == 0) return;
1501
1502  static UsePtrVector& uses = get_ordered_uses ();
1503
1504  int size = uses.size ();
1505
1506  if (size == 0) return;
1507
1508  //
1509  // On se positionne sur le pointeur.
1510  //
1511
1512  int use_index = use->m_index;
1513
1514  if (use_index < 0) return;
1515
1516  //
1517  // On deplace tous les pointeurs d'une case en arriere
1518  //
1519  for (use_index++; use_index < size; use_index++)
1520    {
1521      Use* u = uses[use_index];
1522      u->m_index--;
1523
1524      uses[use_index - 1] = uses[use_index];
1525    }
1526
1527  //
1528  // use est donc replace en derniere position
1529  //
1530
1531  use->m_index = size - 1;
1532  uses[size - 1] = use;
1533}
1534
1535/**
1536 *   Reorder provider versus client in the UsePtrVector list,
1537 *  so that the order reflects the fact that client makes use of provider.
1538 *   The result should be that provider appears before client in the list.
1539 */
1540void Use::reorder (Use* provider, Use* client)
1541{
1542  static UsePtrVector& uses = get_ordered_uses ();
1543
1544  int use_index;
1545
1546  int size = uses.size ();
1547
1548  if (size == 0) return;
1549  if (provider == client) return;
1550
1551  //
1552  // First locate the two use objects into the uses vector.
1553  //   -> provider_index and client_index
1554  //
1555
1556  int provider_index = -1;
1557  int client_index = -1;
1558
1559  provider_index = provider->m_index;
1560  client_index = client->m_index;
1561
1562  if (Cmt::get_debug ())
1563    {
1564      cout << "Use::reorder> provider=" << provider_index << " client=" << client_index << endl;
1565    }
1566
1567  //
1568  // Both objects must be installed in uses before acting.
1569  //
1570  if (provider_index == -1) return;
1571  if (client_index == -1) return;
1572
1573  if (client_index < provider_index)
1574    {
1575      //
1576      // client is already before provider so job is finished
1577      //
1578      return;
1579    }
1580
1581  //
1582  // before : <a a a P b b b C c c c>
1583  //                 ^       ^
1584  //                 ip      ic
1585  //
1586  //  1) move "P b b b" by one place to the right
1587  // thus :   <a a a P P b b b c c c>
1588  //
1589  //  2) move "C" to [ip]
1590  //
1591  // after  : <a a a C P b b b c c c>
1592  //
1593 
1594  for (use_index = client_index - 1; use_index >= provider_index; use_index--)
1595    {
1596      Use* use = uses[use_index];
1597      use->m_index++;
1598
1599      uses[use_index + 1] = uses[use_index];
1600    }
1601 
1602  uses[provider_index] = client;
1603  client->m_index = provider_index;
1604}
1605
1606//----------------------------------------------------------
1607void Use::clear_all ()
1608{
1609  static UsePtrVector& uses = get_ordered_uses ();
1610  static UseVector& instances = get_instances ();
1611
1612  int use_index;
1613
1614  for (use_index = 0; use_index < instances.size (); use_index++)
1615    {
1616      Use& use = instances[use_index];
1617      use.clear ();
1618    }
1619
1620  uses.clear ();
1621  instances.clear ();
1622}
1623
1624//----------------------------------------------------------
1625void Use::unselect_all ()
1626{
1627  static UsePtrVector& uses = get_ordered_uses ();
1628
1629  int use_index;
1630
1631  int size = uses.size ();
1632
1633  if (size == 0) return;
1634
1635  for (use_index = 0; use_index < size; use_index++)
1636    {
1637      Use* use = uses[use_index];
1638
1639      if (use != 0)
1640        {
1641          use->unselect ();
1642        }
1643    }
1644}
1645
1646//----------------------------------------------------------
1647void Use::undiscard_all ()
1648{
1649  static UsePtrVector& uses = get_ordered_uses ();
1650
1651  int use_index;
1652
1653  if (uses.size () == 0) return;
1654
1655  for (use_index = 0; use_index < uses.size (); use_index++)
1656    {
1657      Use* use = uses[use_index];
1658
1659      if (use != 0)
1660        {
1661          use->undiscard ();
1662        }
1663    }
1664}
1665
1666//----------------------------------------------------------
1667void Use::fill_macro_all (cmt_string& buffer, const cmt_string& suffix)
1668{
1669  UsePtrVector& uses = get_ordered_uses ();
1670
1671  buffer = "macro_append use_";
1672  buffer += suffix;
1673  buffer += " \" ";
1674  (Use::current()).fill_macro (buffer, suffix);
1675
1676  for (int number = 0; number < uses.size (); number++)
1677    {
1678      Use* use = uses[number];
1679     
1680      Package* p = use->get_package ();
1681      if (p->is_cmt ()) continue;
1682
1683      if (use->discarded) continue;
1684      if (use->auto_imports == Off) continue;
1685
1686      use->fill_macro (buffer, suffix);
1687    }
1688 
1689  buffer += "\"";
1690}
1691
1692//----------------------------------------------------------
1693Use::Use ()
1694{
1695  done = false;
1696  discarded = false;
1697  auto_imports = Unspecified;
1698  m_package = 0;
1699  m_index = -1;
1700  native_version = "";
1701
1702  clear ();
1703}
1704
1705//----------------------------------------------------------
1706Use::Use (const cmt_string& new_package,
1707          const cmt_string& new_version,
1708          const cmt_string& new_path)
1709{
1710  auto_imports = Unspecified;
1711  m_located = false;
1712  m_package = 0;
1713  m_index = -1;
1714
1715  set (new_package, new_version, new_path);
1716}
1717
1718//----------------------------------------------------------
1719Use::~Use ()
1720{
1721  clear ();
1722}
1723
1724//----------------------------------------------------------
1725void Use::clear ()
1726{
1727  specified_path = "";
1728  path      = "";
1729
1730  if (m_package != 0)
1731    {
1732      m_package->remove_use (this);
1733      m_package = 0;
1734    }
1735
1736  version   = "";
1737  author    = "";
1738  manager   = "";
1739  real_path = "";
1740
1741  prefix    = "";
1742  style     = mgr_style;
1743  initial_scope = ScopePublic;
1744  done      = false;
1745  discarded = false;
1746  selected  = false;
1747  m_hidden  = false;
1748  auto_imports = Unspecified;
1749
1750  includes.clear ();
1751  include_path = "";
1752  scripts.clear ();
1753  apply_patterns.clear ();
1754  ignore_patterns.clear ();
1755
1756  sub_uses.clear ();
1757  sub_use_scopes.clear ();
1758  sub_use_auto_imports.clear ();
1759
1760  requests.clear ();
1761
1762  alternate_versions.clear ();
1763  alternate_paths.clear ();
1764
1765  version_alias = "";
1766  path_alias    = "";
1767
1768  m_located = false;
1769  m_has_native_version = false;
1770  m_index = -1;
1771}
1772
1773//----------------------------------------------------------
1774void Use::set (const cmt_string& new_package,
1775               const cmt_string& new_version,
1776               const cmt_string& new_path,
1777               const cmt_string& new_version_alias,
1778               const cmt_string& new_path_alias)
1779{
1780  clear ();
1781
1782  Package* p = Package::add (new_package);
1783
1784  m_package = p;
1785  p->add_use (this);
1786
1787  specified_path    = new_path;
1788  // specified_path.replace_all ("\\", "/");
1789
1790  specified_version = new_version;
1791  version           = new_version;
1792  path              = specified_path;
1793  Symbol::expand (path);
1794  real_path         = "";
1795  style             = mgr_style;
1796  initial_scope     = ScopePublic;
1797  done              = false;
1798  discarded         = false;
1799  Cmt::build_prefix (new_package, prefix);
1800
1801  version_alias = new_version_alias;
1802  path_alias    = new_path_alias;
1803}
1804
1805//----------------------------------------------------------
1806void Use::change_path (const cmt_string& new_path)
1807{
1808  //
1809  // This methods changes real_path after an actual location
1810  // where this package/version has been found.
1811  //
1812
1813  real_path = "";
1814
1815  if (new_path != "")
1816    {
1817      if ((path.size () > 0) &&
1818          (!CmtSystem::absolute_path (path)))
1819        {
1820          real_path = new_path;
1821          real_path += CmtSystem::file_separator ();
1822          real_path += path;
1823        }
1824      else
1825        {
1826          real_path = new_path;
1827        }
1828      // real_path.replace_all ("\\", "/");
1829
1830      CmtSystem::compress_path (real_path);
1831    }
1832 
1833  m_located = true;
1834}
1835
1836//----------------------------------------------------------
1837int Use::reach_package (const cmt_string& from_path, const cmt_string& n_version)
1838{
1839  if (Cmt::get_debug ())
1840    {
1841      cout << "Use::reach_package> " << get_package_name ()
1842           << "(" << version << ") from " << from_path << endl;
1843      cout << "Use::reach_package> native_version required "<<n_version<<endl;
1844    }
1845   
1846  //
1847  // We try to reach a package/version starting from from_path
1848  //
1849
1850  // check if from_path is at least real
1851  if ((from_path != "") && !CmtSystem::cd (from_path)) return (0);
1852
1853  if (Cmt::get_debug ())
1854    {
1855      cout << "Use::reach_package-2>" << endl;
1856    }
1857
1858  // check in case from_path is a new search path
1859  if (from_path != real_path)
1860    {
1861      // Move to that prefix only if it is a relative path.
1862      if ((path.size () > 0) && (!CmtSystem::absolute_path (path)))
1863        {
1864          if (!CmtSystem::cd (path))
1865            {
1866              return (0);
1867            }
1868        }
1869    }
1870
1871  if (Cmt::get_debug ())
1872    {
1873      cout << "Use::reach_package-3>" << endl;
1874    }
1875
1876  // Special treatment for CMTHOME package...
1877  if (get_package_name () == CmtSystem::get_home_package ())
1878    {
1879      discarded = 1;
1880      if (!CmtSystem::test_file ("requirements"))
1881        {
1882          return (0);
1883        }
1884      else
1885        {
1886          return (1);
1887        }
1888    }
1889
1890  if (Cmt::get_debug ())
1891    {
1892      cout << "Use::reach_package-4>" << endl;
1893    }
1894
1895  // Special treatment for CMTUSERCONTEXT package...
1896  if (get_package_name () == CmtSystem::get_user_context_package ())
1897    {
1898      discarded = 1;
1899      if (!CmtSystem::test_file ("requirements"))
1900        {
1901          return (0);
1902        }
1903      else
1904        {
1905          return (1);
1906        }
1907    }
1908
1909  // Special treatment for PROJECT package...
1910  if (get_package_name () == CmtSystem::get_project_package ())
1911    {
1912      discarded = 1;
1913      if (!CmtSystem::test_file ("project"))
1914        {
1915          return (0);
1916        }
1917      else
1918        {
1919          return (1);
1920        }
1921    }
1922
1923  if (Cmt::get_debug ())
1924    {
1925      cout << "Use::reach_package-5>" << endl;
1926    }
1927
1928  // Now from_path exists, try if the package exists there
1929  if (!CmtSystem::cd (get_package_name ()))
1930    {
1931      return (0);
1932    }
1933
1934  if (Cmt::get_debug ())
1935    {
1936      cout << "Use::reach_package-6>" << endl;
1937    }
1938
1939  if (CmtSystem::test_file ("cmt/requirements"))
1940    {
1941      //      CmtSystem::cd ("cmt");
1942
1943      //      style = no_version_style;
1944
1945      cmt_string v;
1946      //      if (Package::get_version (v))
1947      if (Package::get_version (v, "cmt"))
1948        {
1949          CompareStatus s = compare_versions (version, v, true);
1950          if (Cmt::get_debug ())
1951            {
1952              cout << "Use::reach_package-6.1> version=" << version << " v=" << v << " s=" << s << endl;
1953            }
1954
1955          switch (s)
1956            {
1957            case IdenticalIds:
1958            case ExplicitOldMajorIdWinsAgainstWildarded:
1959            case ExplicitOldMinorIdWinsAgainstWildarded:
1960            case ExplicitOldPatchIdWinsAgainstWildarded:
1961              break;
1962            case ExplicitNewMajorIdWinsAgainstWildarded:
1963            case ExplicitNewMinorIdWinsAgainstWildarded:
1964            case NewMinorIdGreaterThanOld:
1965            case ExplicitNewPatchIdWinsAgainstWildarded:
1966            case NewPatchIdGreaterThanOld:
1967              break;
1968            case OldMajorIdGreaterThanNew:
1969            case NewMajorIdGreaterThanOld:
1970              break;
1971            case IncompatibleMajorIds:
1972              if (!is_head_version (v))
1973                return (0);
1974              break;
1975            }
1976          version = v;
1977        }
1978      else if (version == "")
1979        {
1980          version = "v0";
1981        }
1982      CmtSystem::cd ("cmt");
1983      style = cmt_style;
1984      structuring_style = without_version_directory;
1985      return (1);
1986    }
1987  else if (!CmtSystem::cd (version) || (version == ""))
1988    //  else if (!CmtSystem::cd (version))
1989    {
1990      //
1991      // The specified version cannot be found per-se
1992      // There are alternate possibilities when it contains wild cards
1993      //
1994      if ((version.find ("*") != cmt_string::npos) || (version == ""))
1995      //      if ((version == "") || (version.find ("*") != cmt_string::npos))
1996      //      if (version.find ("*") != cmt_string::npos)
1997        {
1998          static CmtSystem::cmt_string_vector versions;
1999          static cmt_string name;
2000
2001          name = ".";
2002          name += CmtSystem::file_separator ();
2003          if (version != "") name += version;
2004          else name += "*";
2005          /*
2006          if (version == "") name += "*";
2007          else name += version;
2008          */
2009          //          name += version;
2010          CmtSystem::scan_dir (name, versions);
2011          if (n_version != "")
2012            {
2013              CmtSystem::cmt_string_vector native_versions;           
2014              for (int i = 0; i < versions.size (); i++)
2015                {
2016                  cmt_string path;
2017                  if (CmtSystem::test_directory (versions[i]))
2018                    {
2019                      path  = versions[i];
2020                      path += CmtSystem::file_separator ();
2021                      path += "cmt";
2022                    }
2023                  else
2024                    {
2025                      path = "cmt";
2026                    }
2027                  path += CmtSystem::file_separator ();
2028                  path += "native_version.cmt";       
2029                                 
2030                  if (CmtSystem::test_file (path))
2031                    {
2032                      cmt_string nv;
2033
2034                      nv.read (path);
2035                      int pos = nv.find ('\n');
2036                      if (pos != cmt_string::npos) nv.erase (pos);
2037
2038                      pos = nv.find ('\r');
2039                      if (pos != cmt_string::npos) nv.erase (pos);
2040
2041                      if (nv == n_version)
2042                        {
2043                          cmt_string& name_entry = native_versions.add ();
2044
2045                          // We have found at least one
2046                          // cout << "native_version :" << n_version << " ,version: " << versions[i] << endl;
2047                          this->native_version   = n_version;
2048                          name_entry            += versions[i];
2049                        }
2050                    }                   
2051                }
2052              versions = native_versions;
2053            }
2054         
2055          int i;
2056          bool found = false;
2057         
2058          for (i = 0; i < versions.size (); i++)
2059            {
2060              const cmt_string& vers = versions[i];
2061             
2062              if (Cmt::get_debug ())
2063                {
2064                  cout << "     ... version " << vers << " exists" << endl;
2065                }
2066
2067              CmtSystem::basename (vers, name);
2068             
2069              int v;
2070              int r;
2071              int p;
2072             
2073              if (CmtSystem::is_version_directory (name, v, r, p))
2074                {
2075                  /*
2076                    This check is not sufficient !! We need to check in addition
2077                    that the selected directory is really the start of a true CMT
2078                    package (ie with either cmt/requirements or mgr/requirements below)
2079                  */
2080
2081                  cmt_string req;
2082
2083                  req = name;
2084                  req += CmtSystem::file_separator ();
2085                  req += "cmt";
2086                  req += CmtSystem::file_separator ();
2087                  req += "requirements";
2088
2089                  if (!CmtSystem::test_file (req))
2090                    {
2091                      req = name;
2092                      req += CmtSystem::file_separator ();
2093                      req += "mgr";
2094                      req += CmtSystem::file_separator ();
2095                      req += "requirements";
2096
2097                      if (!CmtSystem::test_file (req)) continue;
2098                    }
2099
2100                  cmt_string& new_v = alternate_versions.add ();
2101                  new_v = name;
2102                  cmt_string& new_p = alternate_paths.add ();
2103                  new_p = from_path;
2104                  bool& new_i = alternate_is_head_versions.add ();
2105                  new_i = is_head_version (name);
2106
2107                  found = true;
2108                }
2109            }
2110
2111              /*
2112          if (!found)
2113            {
2114              if (CmtSystem::test_file ("cmt/requirements"))
2115                {
2116                  CmtSystem::cd ("cmt");
2117                  style = no_version_style;
2118                  return (1);
2119                }
2120            }
2121              */
2122        }
2123
2124      if (Cmt::get_debug ())
2125        {
2126          cout << "  ... end of version scan" << endl;
2127        }
2128
2129      //
2130      //  We have now the list of possible alternate versions. However
2131      // we return that the expected package/version was not found (yet).
2132      //
2133
2134      return (0);
2135    }
2136
2137  if (Cmt::get_debug ())
2138    {
2139      cout << "Use::reach_package-7>" << endl;
2140    }
2141
2142  //cerr << "  ... version " << version << " exists" << endl;
2143
2144  // Now we have met the exact specified version!
2145  if (CmtSystem::test_file ("cmt/requirements"))
2146    {
2147      CmtSystem::cd ("cmt");
2148      style = cmt_style;
2149      structuring_style = with_version_directory;
2150    }
2151  else if (CmtSystem::test_file ("mgr/requirements"))
2152    {
2153      CmtSystem::cd ("mgr");
2154      style = mgr_style;
2155      structuring_style = with_version_directory;
2156    }
2157  else
2158    {
2159      return (0);
2160    }
2161
2162  if (Cmt::get_debug ())
2163    {
2164      cout << "Use::reach_package-8>" << endl;
2165    }
2166
2167  return (1);
2168}
2169
2170class UseProjectAction : public IProjectAction
2171{
2172public:
2173  UseProjectAction (Use* use, cmt_string n_version="") : m_use (use), m_found (false), native_version(n_version)
2174  {
2175  }
2176
2177  bool found () const
2178  {
2179    return (m_found);
2180  }
2181
2182  bool run (const Project& project)
2183  {
2184    const cmt_string& path = project.get_cmtpath ();
2185     
2186    m_use->alternate_versions.clear ();
2187    m_use->alternate_paths.clear ();
2188
2189    if (m_use->reach_package (path, this->native_version))
2190      {
2191        if (Cmt::get_debug ())
2192          {
2193            cout << "move_to4> " << path << endl;
2194          }
2195       
2196        m_use->change_path (path);
2197
2198        m_found = true;
2199
2200        return (false);
2201      }
2202    else if (m_use->alternate_versions.size () > 0)
2203      {
2204        if (m_use->select_alternate ()) 
2205          {
2206            if (Cmt::get_debug ())
2207              {
2208                cout << "move_to5> " << m_use->real_path << endl;
2209              }
2210
2211            m_found = true;
2212
2213            return (false);
2214          }
2215      }
2216   
2217    return (true);
2218  }
2219
2220private:
2221  Use* m_use;
2222  bool m_found;
2223  cmt_string native_version;
2224};
2225
2226//----------------------------------------------------------
2227bool Use::move_to (const cmt_string& native_version, bool curdir)
2228//bool Use::move_to (const cmt_string& native_version)
2229{
2230  if (m_located)
2231    {
2232      //
2233      // The real path where this version/package can be found
2234      // has already been resolved. We thus first go there.
2235      //
2236
2237      if (Cmt::get_debug ())
2238        {
2239          cout << "move_to1> " << real_path << endl;
2240        }
2241
2242      reach_package (real_path, native_version);
2243
2244      return (true);
2245    }
2246
2247  cmt_string expanded_path = path;
2248
2249  //
2250  // If the path specified in this use is a true absolute path,
2251  // then we search the package from there first.
2252  //
2253  if (CmtSystem::absolute_path (expanded_path))
2254    {
2255      if (reach_package (expanded_path,  native_version))
2256        {
2257          if (Cmt::get_debug ())
2258            {
2259              cout << "move_to3> " << expanded_path << endl;
2260            }
2261
2262          change_path (expanded_path);
2263
2264          return (true);
2265        }
2266      else if (alternate_versions.size () > 0)
2267        {
2268          if (select_alternate ()) 
2269            {
2270              if (Cmt::get_debug ())
2271                {
2272                  cout << "move_to5> " << real_path << endl;
2273                }             
2274
2275              return (true);
2276            }
2277        }
2278    }
2279
2280  //
2281  // Try here.
2282  //
2283  if (curdir)
2284    {
2285//   if (expanded_path == "")
2286//     {
2287//       if (reach_package ("", native_version))
2288
2289      cmt_string here = CmtSystem::pwd ();
2290
2291      if (reach_package (here,  native_version))
2292        {
2293          if (Cmt::get_debug ())
2294            {
2295              cout << "move_to2> " << expanded_path << endl;
2296            }
2297
2298          change_path (here);
2299
2300          return (true);
2301        }
2302      else if (alternate_versions.size () > 0)
2303        {
2304          if (select_alternate ()) 
2305            {
2306              if (Cmt::get_debug ())
2307                {
2308                  cout << "move_to5> " << real_path << endl;
2309                }
2310             
2311              return (true);
2312            }
2313        }
2314      return (false);
2315//     }
2316    } // end of curdir     
2317     
2318  //
2319  // Second try is among the CMTPATHs
2320  //
2321  UseProjectAction pa (this, native_version);
2322
2323  Project::broadcast (pa);
2324
2325  if (pa.found ()) return (true);
2326
2327  return (false);
2328}
2329
2330//----------------------------------------------------------
2331bool Use::select_alternate ()
2332{
2333  int i;
2334
2335  int v0 = 0;
2336  int r0 = 0;
2337  int p0 = 0;
2338
2339  int v = 0;
2340  int r = 0;
2341  int p = 0;
2342
2343  int selected_index = -1;
2344
2345  for (i = 0; i < alternate_versions.size (); i++)
2346    {
2347      cmt_string& name = alternate_versions[i];
2348
2349      if (i == 0)
2350        {
2351          CmtSystem::is_version_directory (name, v0, r0, p0);
2352          selected_index = 0;
2353        }
2354      else
2355        {
2356          if (alternate_is_head_versions[selected_index] &&
2357              alternate_is_head_versions[i])
2358            {
2359              if (strcmp(name.c_str (), alternate_versions[selected_index].c_str ()) > 0)
2360                {
2361                  selected_index = i;
2362                }
2363              continue;
2364            }
2365          else if (alternate_is_head_versions[selected_index])
2366            {
2367              continue;
2368            }
2369          else if (alternate_is_head_versions[i])
2370            {
2371              selected_index = i;
2372              continue;
2373            }
2374
2375          CmtSystem::is_version_directory (name, v, r, p);
2376
2377          if (v > v0)
2378            {
2379              selected_index = i;
2380              v0 = v;
2381              r0 = r;
2382              p0 = p;
2383            }
2384          else if (v == v0)
2385            {
2386              if (r > r0)
2387                {
2388                  selected_index = i;
2389                  r0 = r;
2390                  p0 = p;
2391                }
2392              else if (r == r0)
2393                {
2394                  if (p > p0)
2395                    {
2396                      selected_index = i;
2397                      p0 = p;
2398                    }
2399                }
2400            }
2401        }
2402    }
2403
2404  if (selected_index >= 0)
2405    {
2406      if (CmtSystem::cd (alternate_paths[selected_index]))
2407        {
2408          version = alternate_versions[selected_index];
2409          if (reach_package (alternate_paths[selected_index]))
2410            {
2411              if (Cmt::get_debug ())
2412                {
2413                  cout << "select_alternate> " << alternate_paths[selected_index] << endl;
2414                }
2415
2416              change_path (alternate_paths[selected_index]);
2417              return (true);
2418            }
2419        }
2420    }
2421
2422  return (false);
2423}
2424
2425//----------------------------------------------------------
2426bool Use::need_new (const cmt_string& path,
2427                    const cmt_string& package,
2428                    const cmt_string& version,
2429                    const cmt_string& n_version,
2430                    Use** old_use,
2431                    Use* context_use)
2432{
2433  bool new_request = add_request (path, package, version);
2434   
2435  Use& current_use = Use::current ();
2436
2437  if (package == current_use.get_package_name ())
2438    {
2439      if (Cmt::get_debug ())
2440        {
2441          cout << "  ... recursive use to current package" << endl;
2442        }
2443
2444      if (old_use != 0) *old_use = &current_use;
2445      return (false);
2446    }
2447
2448  Package* p = Package::add (package);
2449
2450  UsePtrVector& uses = p->get_uses ();
2451
2452  bool do_need_new = true;
2453  Use* found = 0;
2454  Use* registered = 0;
2455
2456  int req_v = -1;
2457  int req_r = -1;
2458  int req_p = -1;
2459
2460  CmtSystem::is_version_directory (version, req_v, req_r, req_p);
2461
2462  if (Cmt::get_debug ())
2463    {
2464      cout << "need_new> p=" << package << " v=" << version << " v=" << req_v << " r=" << req_r << " p=" << req_p << endl;
2465    }
2466
2467  bool has_wild_card = (req_v == -1) || (req_r == -1) || (req_p == -1);
2468
2469  int new_v = -1;
2470  int new_r = -1;
2471  int new_p = -1;
2472
2473  int use_index;
2474
2475  if (old_use != 0) *old_use = 0;
2476
2477  // Acquire the registered use.
2478  for (use_index = 0; use_index < uses.size (); use_index++)
2479    {
2480      Use& use = (*uses[use_index]);
2481
2482      if (use.m_index < 0) continue;
2483
2484      registered = &use;
2485
2486      break;
2487    }
2488
2489  // Make a first try with the registered use if it exists.
2490
2491  cmt_string decision;
2492
2493  if (registered != 0)
2494    {
2495      Use& use = (*registered);
2496
2497      found = &use;
2498
2499      CmtSystem::is_version_directory (use.specified_version, new_v, new_r, new_p);
2500
2501      bool use_has_wild_card = (new_v == -1) || (new_r == -1) || (new_p == -1);
2502
2503      if (has_wild_card && !use_has_wild_card)
2504        {
2505          if (Cmt::get_debug ())
2506            {
2507              cout << "  ... wildcarded request loses against existing explicit" << endl;
2508            }
2509         
2510          do_need_new = false; // We don't need a new one
2511        }
2512      else
2513        {
2514          // here either !has_wild_card or use_has_wild_card
2515
2516          if ((version == use.specified_version) &&
2517              (path == use.specified_path))
2518            {
2519             
2520              if (Cmt::get_debug ())
2521                {
2522                  cout << " ... exactly same version and path!" << endl;
2523                }             
2524              do_need_new = false; // We don't need a new one
2525              if (n_version != use.native_version)
2526                {
2527                  if (Cmt::get_debug ())
2528                    {
2529                      cout << " ... but native_version differs (" << n_version << "!=" << use.native_version << ") !" << endl; 
2530                    }
2531
2532                  do_need_new = true;   
2533                }             
2534            }
2535          else if (version != use.specified_version)
2536            {
2537              if (Cmt::get_debug ())
2538                {
2539                  cout << "requested explicit wins against existing wildcarded"
2540                       << endl;
2541                }
2542
2543              // The registered use loses against the request
2544            }
2545          else
2546            {
2547              if (Cmt::get_debug ())
2548                {
2549                  cout << "only paths differ, consider the new one."
2550                       << endl;
2551                }
2552
2553              // The registered use loses against the request
2554            }
2555        }
2556
2557
2558      //if (new_request && !Cmt::get_quiet () && (Cmt::get_action () == action_show_uses))
2559      if (new_request && !Cmt::get_quiet ())
2560        {
2561          if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
2562            {
2563              cerr << "# Required version " << version
2564                   << " of package " << package;
2565
2566              if (context_use != 0)
2567                {
2568                  cerr << " [from " << context_use->get_package_name () << "]";
2569                }
2570
2571              cerr << " incompatible with selected version " << use.version;
2572
2573              if (use.version != use.specified_version)
2574                {
2575                  cerr << " (" << use.specified_version << ")" ;
2576                }
2577
2578              cerr << endl;
2579            }
2580        }
2581
2582      if (Cmt::get_debug ())
2583        {
2584          cout << "# " << package << " " << version;
2585
2586          if (context_use != 0)
2587            {
2588              cout << " [from " << context_use->get_package_name () << "]";
2589            }
2590
2591          if (do_need_new)
2592            {
2593              cout << " > ";
2594            }
2595          else
2596            {
2597              cout << " < ";
2598            }
2599
2600          cout << use.version;
2601          if (use.version != use.specified_version)
2602            {
2603              cout << " (" << use.specified_version << ")" ;
2604            }
2605
2606          cout << " (r) ";
2607
2608          cout << endl;
2609        }
2610    }
2611
2612  if (do_need_new)
2613    {
2614      // Now try unregistered uses, since the registered one is not appropriate.
2615      // to see is any other existing use could match
2616
2617      for (use_index = 0; use_index < uses.size (); use_index++)
2618        {
2619          Use& use = (*uses[use_index]);
2620         
2621          if (use.m_index >= 0) continue;
2622         
2623          // Always save the latest found.
2624         
2625          found = &use;
2626
2627          CmtSystem::is_version_directory (use.specified_version, new_v, new_r, new_p);
2628
2629          bool use_has_wild_card = (new_v == -1) || (new_r == -1) || (new_p == -1);
2630
2631          if (has_wild_card && !use_has_wild_card)
2632            {
2633              if (Cmt::get_debug ())
2634                {
2635                  cout << "  ... requested wildcarded loses against existing explicit" << endl;
2636                }
2637             
2638              do_need_new = false; // We don't need a new one
2639            }
2640          else
2641            {
2642              // here either !has_wild_card or use_has_wild_card
2643         
2644              if ((version == use.specified_version) &&
2645                  (path == use.specified_path))
2646                {
2647                  if (Cmt::get_debug ())
2648                    {
2649                      cout << " ... exactly same version and path!" << endl;
2650                    }
2651             
2652                  do_need_new = false; // We don't need a new one
2653                  if (n_version != use.native_version)
2654                    {
2655                      if (Cmt::get_debug ())
2656                        {
2657                          cout << " ... but native_version differs (" << n_version << "!=" << use.native_version << ") !" << endl;
2658                        }
2659
2660                      do_need_new = true;   
2661                    }
2662                 
2663                }
2664              else if (version != use.specified_version)
2665                {
2666                  if (Cmt::get_debug ())
2667                    {
2668                      cout << "requested explicit wins against existing wildcarded"
2669                           << endl;
2670                    }
2671
2672                  // This use loses against the request
2673                }
2674              else
2675                {
2676                  if (Cmt::get_debug ())
2677                    {
2678                      cout << "only paths differ, consider the new one."
2679                           << endl;
2680                    }
2681
2682                  // This use loses against the request
2683                }
2684            }
2685
2686          //if (new_request && !Cmt::get_quiet () && (Cmt::get_action () == action_show_uses))
2687          if (new_request && !Cmt::get_quiet ())
2688            {
2689              if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
2690                {
2691                  cerr << "# Required version " << version
2692                       << " of package " << package;
2693
2694                  if (context_use != 0)
2695                    {
2696                      cerr << " [from " << context_use->get_package_name () << "]";
2697                    }
2698             
2699                  cerr << " incompatible with selected version " << use.version;
2700
2701                  if (use.version != use.specified_version)
2702                    {
2703                      cerr << " (" << use.specified_version << ")" ;
2704                    }
2705
2706                  cerr << endl;
2707                }
2708            }
2709
2710          if (Cmt::get_debug ())
2711            {
2712              cout << "# " << package << " " << version;
2713             
2714              if (context_use != 0)
2715                {
2716                  cout << " [from " << context_use->get_package_name () << "]";
2717                }
2718             
2719              if (do_need_new)
2720                {
2721                  cout << " > ";
2722                }
2723              else
2724                {
2725                  cout << " < ";
2726                }
2727             
2728              if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
2729                {
2730                  cout << "(incompatible) ";
2731                }
2732
2733              cout << use.version;
2734              if (use.version != use.specified_version)
2735                {
2736                  cout << " (" << use.specified_version << ")" ;
2737                }
2738              cout << endl;
2739            }
2740        }
2741    }
2742
2743  if (old_use != 0)
2744    {
2745      if (registered != 0) *old_use = registered;
2746      else *old_use = found;
2747    }
2748
2749  return (do_need_new);
2750}
2751
2752//----------------------------------------------------------
2753//
2754//  Here the version which is provided here is the specified version.
2755// It may contain wild cards or it may be simply empty.
2756//
2757//----------------------------------------------------------
2758Use* Use::create (const cmt_string& path,
2759                  const cmt_string& package,
2760                  const cmt_string& version,
2761                  const cmt_string& version_alias,
2762                  const cmt_string& path_alias,
2763                  const cmt_string& n_version)
2764{
2765  Package* p = 0;
2766
2767  p = Package::add (package);
2768
2769  UsePtrVector& vector = p->get_uses ();
2770
2771  // We first look in the database.
2772  for (int use_index = 0; use_index < vector.size (); use_index++)
2773    {
2774      Use* use = vector[use_index];
2775
2776      if ((use->specified_version == version) && 
2777          (use->specified_path == path) && use->native_version==n_version) return (use);
2778    }
2779
2780  // We now really create a new Use entry.
2781
2782  static UseVector& instances = get_instances ();
2783
2784  Use& use_object = instances.add ();
2785
2786  use_object.set (package, version, path, version_alias, path_alias);
2787
2788  return (&use_object);
2789}
2790
2791//----------------------------------------------------------
2792//  Add a use request into the database.
2793//
2794//  o If a use request already exist in the database,
2795//    check the version compatibility
2796//
2797//----------------------------------------------------------
2798Use* Use::add (const cmt_string& path,
2799               const cmt_string& package_name,
2800               const cmt_string& version,
2801               const cmt_string& version_alias,
2802               const cmt_string& path_alias,
2803               const cmt_string& native_version,
2804               Use* context_use,
2805               const State specified_auto_imports)
2806{
2807  bool do_need_new = false;
2808
2809  Use* old_use = 0;
2810  Use* use = 0;
2811
2812  do_need_new = need_new (path, package_name, version, native_version, &old_use, context_use);
2813
2814  if (Cmt::get_debug ())
2815    {
2816      if (old_use != 0 && !do_need_new)
2817        {
2818          cout << "add> old_use " << old_use->get_package_name () <<
2819            " " << old_use->version <<
2820            " " << old_use->path <<
2821            endl;
2822        }
2823    }
2824
2825  if (do_need_new)
2826    {
2827      use = create (path, package_name, version, version_alias, path_alias, native_version);
2828    }
2829  else
2830    {
2831      // Since we don't need a new Use, it means that old_use exists !
2832
2833      use = old_use;
2834      old_use = 0;
2835    }
2836
2837  if (package_name == CmtSystem::get_home_package ())
2838    {
2839      return (use);
2840    }
2841
2842  if (package_name == CmtSystem::get_user_context_package ())
2843    {
2844      return (use);
2845    }
2846
2847  if (package_name == CmtSystem::get_project_package ())
2848    {
2849      return (use);
2850    }
2851
2852  cmt_string here = CmtSystem::pwd ();
2853
2854  //
2855  // Store the specified sub_uses. Some of them may become discarded
2856  // later on.
2857  //
2858  if (context_use != 0)
2859    {
2860      context_use->sub_uses.push_back (use);
2861
2862      context_use->sub_use_scopes.push_back (context_use->get_current_scope ());
2863
2864      context_use->sub_use_auto_imports.push_back (specified_auto_imports);
2865
2866      cmt_string& request = context_use->requests.add ();
2867
2868      request = package_name;
2869      request += " ";
2870      request += version;
2871      request += " ";
2872      request += path;
2873
2874
2875      if (Cmt::get_debug ())
2876        {
2877          cout << "Use::add context(" << context_use->get_package_name () << ") "
2878               << "[u:" << package_name
2879               << " s:" << context_use->get_current_scope ()
2880               << " ai:" << specified_auto_imports
2881               << "]" << endl;
2882        }
2883    }
2884
2885  if (use == &(Use::current ())) 
2886    {
2887      return (use);
2888    }
2889
2890  /*
2891   *   Now we have a Use object. If it is a new one, we have to
2892   *    1) understand if it exists physically
2893   *    2) it is better than the old ones.
2894   *
2895   *   Here, we may have :
2896   *    1) old_use = 0
2897   *         there was no Use object before for this package
2898   *         the existing one is fine
2899   *
2900   *    2) old_use != 0
2901   *         we have created a new Use (which has to be validated)
2902   */
2903  bool found = use->move_to (native_version);
2904
2905  if (Cmt::get_debug ())
2906    {
2907      cout << "add> use [" << use << "] " << use->get_package_name () 
2908           << " " << use->version
2909           << " " << use->path
2910           << " found=" << found
2911           << " done=" << use->done
2912           << endl;
2913
2914      show_packages ();
2915    }
2916     
2917  if (!found)
2918    {
2919      CmtMessage::warning (CmtError::get_error_name (CmtError::package_not_found)
2920                           + ": " + use->get_info ()
2921                           + ( (context_use != 0) ?
2922                               " (requested by " + context_use->get_package_name () + ")" :
2923                               "" )
2924                           );
2925      /*
2926      CmtMessage::warning ("package " + use->get_package_name ()
2927                           + " " + use->version + " " + use->path
2928                           + " not found"
2929                           + ( (context_use != 0) ?
2930                               " (requested by " + context_use->get_package_name () + ")" :
2931                               "" )
2932                           );
2933      */
2934      /*
2935      if (!Cmt::get_quiet ())
2936        {
2937          cerr << "#CMT> Warning: package " << use->get_package_name () <<
2938            " " << use->version << " " << use->path <<
2939            " not found";
2940
2941          if (context_use != 0)
2942            {
2943              cerr << " (requested by " << context_use->get_package_name () << ")";
2944            }
2945
2946          cerr << endl;
2947        }
2948      */
2949
2950      //CmtError::set (CmtError::package_not_found, use->get_package_name ());
2951      use->m_located = false;
2952      //use = 0;
2953    }
2954
2955  if ((old_use != 0) && (use != old_use))
2956    {
2957      if (Cmt::get_debug ())
2958        {
2959          cout << "There was another version of this Use. \n"
2960               << "But a new one was created due to some criteria. \n"
2961               << "Now we are going to apply the version strategy to make the final selection"
2962               << endl;
2963        }
2964
2965      /*
2966       *    There was another version of this Use.
2967       *    But a new one was created due to some criteria.
2968       *    Now we are going to apply the version strategy to make the final selection.
2969       */
2970
2971      if (Cmt::get_debug ())
2972        {
2973          cout << "select? [" << use << "] "<< use->version <<" vs old_use[" << old_use << "] "
2974               << old_use->get_package_name ()
2975               << " " << old_use->version
2976               << " " << old_use->path
2977               << endl;
2978        }
2979
2980      if (!found)
2981        {
2982          /*
2983           *  This new Use does not correspond to any physical package.
2984           *  let's simply discard it (and go back to old_use)
2985           */
2986
2987          //if (use != 0) use->discard ();
2988          use->discard ();
2989          use = old_use;
2990          if (context_use != 0)
2991            {
2992              context_use->sub_uses[context_use->sub_uses.size () - 1] = use;
2993            }
2994          found = use->move_to (native_version);
2995        }
2996      else
2997        {
2998          //
2999          //  This new version is different from the old one
3000          // thus we have to choose
3001          //
3002          bool old_use_is_head_version (use->is_head_version (old_use->version));
3003          bool use_is_head_version (use->is_head_version (use->version));
3004          Use* selected_use (old_use);
3005          if (old_use_is_head_version && use_is_head_version)
3006            {
3007              if (strcmp(use->version.c_str (), old_use->version.c_str ()) > 0)
3008                {
3009                  selected_use = use;
3010                  if (Cmt::get_debug ())
3011                    {
3012                      cout << "add> new head version " << use->version
3013                           << " wins old head version " << old_use->version
3014                           << endl;
3015                    }
3016                }
3017            }
3018          else if (old_use_is_head_version)
3019            {
3020            }
3021          else if (use_is_head_version)
3022            {
3023              selected_use = use;
3024              if (Cmt::get_debug ())
3025                {
3026                  cout << "add> new head version " << use->version
3027                       << " wins old version " << old_use->version
3028                       << endl;
3029                }
3030            }
3031          else
3032            {
3033              static BestFitSelector selector;
3034              selected_use = selector.operate (old_use, use);
3035              if (Cmt::get_debug ())
3036                {
3037                  cout << "add> operate on old version " << old_use->version
3038                       << " and new version " << use->version
3039                       << endl;
3040                }
3041            }
3042
3043          if (Cmt::get_debug ())
3044            {
3045              cout << "add> old=" << old_use << "i=" << old_use->m_index
3046                   << " new=" << use << "i=" << use->m_index
3047                   << " => selected=" << selected_use
3048                   << endl;
3049            }
3050
3051          //
3052          // Some situations managed by selector.operate happen
3053          // to fail discarding the rejected Use.
3054          //
3055          if (use != selected_use) 
3056            {
3057              use = use->set_selected_version (selected_use);
3058              if (context_use != 0)
3059                {
3060                  context_use->sub_uses[context_use->sub_uses.size () - 1] = use;
3061                }
3062            }
3063         
3064
3065          /*
3066           *   current directory is moved to the selected one
3067           */
3068          found = use->move_to (native_version);
3069        }
3070    }
3071
3072  //
3073  // The following statement is no longer considered as useful.
3074  // It is commented. But we should clarify why it was really needed!
3075  //
3076  //use->undiscard ();
3077
3078  if (found)
3079    {
3080      static UsePtrVector& uses = get_ordered_uses ();
3081
3082      bool registered = false;
3083      const Use& cu = Use::current ();
3084
3085      Package* package = Package::find (package_name);
3086
3087      //
3088      // A pointer to this new object is also added or replaced.
3089      //
3090      if ((use != &cu) && (package == cu.get_package ()))
3091        {
3092          // This is a recursive call to the current package!!
3093          registered = true;
3094          use->done = true;
3095          use->m_index = -1;
3096        }
3097      else
3098        {
3099          //
3100          // Now sort out the registration in ordered uses
3101          //
3102          //  cases:
3103          //
3104          //   use is not yet registered (m_index < 0)
3105          //     o if another use of the same package is registered,
3106          //       it must be substituted with the new one
3107          //     o otherwise create a new entry at the end (it will be sorted
3108          //       afterwards)
3109          //
3110          //   use is already registered (m_index >= 0)
3111          //     o if another use of the same package is registered,
3112          //       it must be discarded, but this may mean that
3113          //       two versions are simultaneously registered (bug?)
3114          //     o otherwise we keep it in place
3115          //
3116
3117          UsePtrVector& puses = package->get_uses ();
3118
3119          if (use->m_index >= 0) registered = true;
3120
3121          /*
3122            We look for all existing uses in that package.
3123          */
3124          for (int i = 0; i < puses.size(); i++)
3125            {
3126              Use* u = puses[i];
3127             
3128              if (Cmt::get_debug ())
3129                {
3130                  cout << "add> check registering between " << use
3131                       << ":" << use->get_package_name ()
3132                       << "(" << use->m_index << ")"
3133                       << " and " << u
3134                       << ":" << u->get_package_name () 
3135                       << "(" << u->m_index << ")"
3136                       << endl;
3137                }
3138
3139              if ((u != use) && (u->m_index >= 0))
3140                {
3141                  // Another use of that package is already registered
3142
3143                  if (Cmt::get_debug ())
3144                    {
3145                      cout << "add> Another use of that package is already registered " 
3146                           << " use(" << use->m_index << ")";
3147                      if (use->m_index >= 0)
3148                        {
3149                          cout << "[" << (uses[use->m_index])->get_package_name () << "]";
3150                        }
3151                      cout << " u(" << u->m_index << ")";
3152                      if (u->m_index >= 0)
3153                        {
3154                          cout << "[" << (uses[u->m_index])->get_package_name () << "]";
3155                        }
3156                      cout << endl;
3157                    }
3158
3159                  if (use->m_index < 0)
3160                    {
3161                      /*
3162                        the newly selected use (use) should replace the one which was registered (u)
3163                      */
3164
3165                      u->set_selected_version (use);
3166
3167                      registered = true;
3168                    }
3169                  else
3170                    {
3171                      // bug??
3172                      if (Cmt::get_debug ())
3173                        {
3174                          cout << "Duplicate entry in ordered uses" << endl;
3175                        }
3176                    }
3177                }
3178            }
3179
3180          if (Cmt::get_debug ())
3181            {
3182              cout << "add> registering completed" << endl;
3183              //show_packages ();
3184            }
3185        }
3186     
3187      if (!registered) 
3188        {
3189          if (Cmt::get_debug ())
3190            {
3191              cout << "add> We install use at the end the ordered list of uses" << endl;
3192            }
3193
3194          uses.push_back (use);
3195          use->m_index = uses.size () - 1;
3196        }
3197
3198      if (Cmt::get_debug ())
3199        {
3200          for (int use_index = 0; use_index < uses.size (); use_index++)
3201            {
3202              Use* u = (Use*) uses[use_index];
3203              cout << "  use[" << use_index << "] p=(" << u << ")" << u->get_package_name () 
3204                   << " v=" << u->version
3205                   << " discarded=" << u->discarded
3206                   << " selected=" << u->selected
3207                   << " done=" << u->done
3208                   << " index=" << u->m_index
3209                   << endl;
3210            }
3211         
3212        }
3213         
3214      if (!use->done && Cmt::get_recursive ())
3215        {
3216          use->done = true;
3217
3218          if (Cmt::get_debug ())
3219            {
3220              cout << "Parsing requirements file at " << CmtSystem::pwd () << endl;
3221            }
3222
3223          SyntaxParser::parse_requirements ("requirements", use);
3224        }
3225      else
3226        {
3227          if (Cmt::get_debug ())
3228            {
3229              cout << "Requirements file at " << CmtSystem::pwd () << " already parsed" << endl;
3230            }
3231        }
3232    }
3233
3234  CmtSystem::cd (here);
3235
3236  return (use);
3237}
3238
3239//----------------------------------------------------------
3240void Use::discard ()
3241{
3242  discarded = true;
3243}
3244
3245//----------------------------------------------------------
3246void Use::undiscard ()
3247{
3248  discarded = false;
3249}
3250
3251//----------------------------------------------------------
3252void Use::select ()
3253{
3254  selected = true;
3255}
3256
3257//----------------------------------------------------------
3258void Use::unselect ()
3259{
3260  selected = false;
3261}
3262
3263//----------------------------------------------------------
3264bool Use::is_selected ()
3265{
3266  return (selected);
3267}
3268
3269/**
3270 *    Check if the package makes use of the specified package/version
3271 *
3272 *    The seach only considers the first level of uses (thus it is
3273 *   NOT recursive)
3274 */
3275bool Use::is_client (const cmt_string& used_package,
3276                     const cmt_string& used_version)
3277{
3278  // A package is client of itself
3279
3280  Package* package = Package::find (used_package);
3281
3282  if ((get_package () == package) &&
3283      (version == used_version)) return (true);
3284
3285  if (discarded) return (false);
3286
3287  int i;
3288
3289  for (i = 0; i < sub_uses.size (); i++)
3290    {
3291      Use* use = sub_uses[i];
3292      if (use == 0) continue;
3293
3294      if ((use->get_package () == package) &&
3295          (use->version == used_version)) return (true);
3296
3297      /*
3298        if (use->is_client (used_package, used_version))
3299        {
3300        return (true);
3301        }
3302      */
3303    }
3304
3305  return (false);
3306}
3307
3308//----------------------------------------------------------
3309void Use::apply_global_patterns ()
3310{
3311  int i;
3312
3313  Pattern::PatternVector& vector = Pattern::patterns ();
3314
3315  for (i = 0; i < vector.size (); i++)
3316    {
3317      Pattern& p = vector[i];
3318
3319      if (p.global)
3320        {
3321          p.apply (this);
3322        }
3323    }
3324}
3325
3326//----------------------------------------------------------
3327void Use::set_include_path (const cmt_string& new_path)
3328{
3329  include_path = new_path;
3330}
3331
3332/**
3333 *   Compute the full real path of a found package.
3334 *   Takes the structuring style into account
3335 *
3336 *    Result is used to fill in the referenced string
3337 *    Result does NOT include the trailing file_separator
3338 */
3339void Use::get_full_path (cmt_string& s) const
3340{
3341  if (real_path == "") s = CmtSystem::pwd ();
3342  else s = real_path;
3343
3344  if (style != none_style)
3345    {
3346      s += CmtSystem::file_separator ();
3347      s += get_package_name ();
3348    }
3349 
3350  //  if (style != no_version_style)
3351  if (structuring_style == with_version_directory)
3352    {
3353      s += CmtSystem::file_separator ();
3354      s += version;
3355    }
3356}
3357
3358/**
3359 *   Compute the full real path of a found package.
3360 *   Takes the structuring style into account
3361 */
3362cmt_string Use::get_full_path () const
3363{
3364  cmt_string result;
3365
3366  get_full_path (result);
3367
3368  return (result);
3369}
3370
3371/**
3372 *   Considering a given path, try and reduce the part of it
3373 *  that corresponds to the full path of this package into its
3374 *  normal form ${<PACKAGE>ROOT}
3375 *   The argument is modified if the pattern is exactly found.
3376 */
3377void Use::reduce_path (cmt_string& s) const
3378{
3379  cmt_string pattern;
3380  get_full_path (pattern);
3381  pattern += CmtSystem::file_separator ();
3382 
3383  cmt_string replacement = "${";
3384  replacement += prefix;
3385  replacement += "ROOT}";
3386  replacement += CmtSystem::file_separator ();
3387
3388  s.replace (pattern, replacement);
3389}
3390
3391//----------------------------------------------------------
3392void Use::get_cmtpath_and_offset (cmt_string& cmtpath, cmt_string& offset) const
3393{
3394  if (get_package_name () == CmtSystem::get_project_package ())
3395    {
3396      offset = "";
3397      CmtSystem::dirname (path, cmtpath);
3398      return;
3399    }
3400  else if (get_package_name () == CmtSystem::get_home_package ())
3401    {
3402      offset = "";
3403      cmtpath = path;
3404      return;
3405    }
3406  else if (get_package_name () == CmtSystem::get_user_context_package ())
3407    {
3408      offset = "";
3409      cmtpath = path;
3410      return;
3411    }
3412
3413  cmtpath = "";
3414  offset = "";
3415
3416  cmtpath = Project::find_in_cmt_paths (real_path);
3417  Project* p = Project::find_by_cmtpath (cmtpath);
3418
3419  //  if (cmtpath != "")
3420  if (p != 0)
3421    {
3422      CmtSystem::compress_path (cmtpath);
3423
3424      static const cmt_string empty_string;
3425      static const cmt_string fs = CmtSystem::file_separator ();
3426     
3427      // In case there are symlinks
3428      //      offset = real_path;
3429      //      offset.replace (cmtpath, empty_string);
3430      //cerr << "realpath_: get_cmtpath_and_offset" << endl;
3431      CmtSystem::realpath_ (real_path, offset);
3432      offset.replace (p->get_cmtpath_real (), empty_string);
3433
3434      /**
3435         try to remove this current CMTPATH entry from path.  This
3436         has a meaning when the specified path already contains an
3437         absolute path.
3438      */
3439     
3440      if (offset[0] == CmtSystem::file_separator ())
3441        {
3442          // Just in case there is a part left after removing the cmtpath entry
3443               
3444          offset.replace (fs, empty_string);
3445        }
3446    }
3447  else
3448    {
3449      offset = real_path;
3450    }
3451}
3452
3453//------------------------------------------------------------
3454bool Use::get_strategy (const cmt_string& name) const
3455{
3456  const Project* p = Project::find_by_cmtpath (Project::find_in_cmt_paths (real_path));
3457
3458  bool strategy;
3459
3460  if (p == 0)
3461    {
3462      static const Project::ProjectPtrVector Ordered = Project::ordered_projects ();
3463      //static const Project::ProjectVector& projects = Project::projects ();
3464
3465      if (Ordered.size () == 0) strategy = StrategyMgr::get_default_strategy (name);
3466      //if (projects.size () == 0) strategy = StrategyMgr::get_default_strategy (name);
3467      else
3468        {
3469          p = Ordered[0];
3470          //p = &(projects[0]);
3471          strategy = p->get_strategy (name);
3472        }
3473    }
3474  else
3475    {
3476      strategy = p->get_strategy (name);
3477    }
3478
3479  return (strategy);
3480}
3481
3482//----------------------------------------------------------
3483void Use::fill_includes_macro (cmt_string& buffer) const
3484{
3485  if (include_path == "")
3486    {
3487      buffer += "$(ppcmd)\"$(";
3488      buffer += get_package_name ();
3489      buffer += "_root)";
3490      buffer += CmtSystem::file_separator ();
3491      buffer += "src\" ";
3492    }
3493  else if (include_path != "none")
3494    {
3495      buffer += "$(ppcmd)\"";
3496      buffer += include_path;
3497      buffer += "\" ";
3498    }
3499 
3500  for (int i = 0; i < includes.size (); i++)
3501    {
3502      Include& incl = includes[i];
3503
3504      if (incl.name == "") continue;
3505     
3506      buffer += "$(ppcmd)\"";
3507      buffer += incl.name;
3508      buffer += "\" ";
3509    }
3510}
3511
3512//----------------------------------------------------------
3513void Use::fill_macro (cmt_string& buffer, const cmt_string& suffix) const
3514{
3515  buffer += " $(";
3516  buffer += get_package_name ();
3517  buffer += "_";
3518  buffer += suffix;
3519  buffer += ") ";
3520}
3521
3522//----------------------------------------------------------
3523void Use::fill_standard_macros (cmt_string& buffer) const
3524{
3525  static cmt_string fs = CmtSystem::file_separator ();
3526
3527  buffer = "";
3528
3529  cmt_string package_name = get_package_name ();
3530
3531  buffer += "macro ";
3532  buffer += package_name;
3533  buffer += "_tag";
3534  buffer += " \"$(tag)\"";
3535  buffer += "\n";
3536
3537  if (located ())
3538    {
3539      buffer += "macro ";
3540      buffer += prefix;
3541      buffer += "ROOT";
3542      buffer += " \"";
3543      buffer += get_full_path ();
3544      buffer += "\"";
3545      buffer += "\n";
3546
3547      buffer += "macro ";
3548      buffer += package_name;
3549      buffer += "_root";
3550      buffer += " \"";
3551      buffer += real_path;
3552      if (style != none_style)
3553        {
3554          buffer += fs;
3555          buffer += package_name;
3556        }
3557      //      if (style != no_version_style)
3558      if (structuring_style == with_version_directory)
3559        {
3560          buffer += fs;
3561          buffer += version;
3562        }
3563      buffer += "\"";
3564      buffer += "\n";
3565    }
3566
3567  buffer += "macro ";
3568  buffer += prefix;
3569  buffer += "VERSION";
3570  buffer += " \"";
3571  buffer += version;
3572  buffer += "\"";
3573  buffer += "\n";
3574
3575  cmt_string cmtpath = "";
3576  cmt_string offset = "";
3577
3578  get_cmtpath_and_offset (cmtpath, offset);
3579
3580  buffer += "macro ";
3581  buffer += package_name;
3582  buffer += "_cmtpath";
3583  buffer += " \"";
3584  buffer += cmtpath;
3585  buffer += "\"";
3586  buffer += "\n";
3587
3588  buffer += "macro ";
3589  buffer += package_name;
3590  buffer += "_offset";
3591  buffer += " \"";
3592  buffer += offset;
3593  buffer += "\"";
3594  buffer += "\n";
3595 
3596  Project* p = Project::find_by_cmtpath (cmtpath);
3597
3598  buffer += "macro ";
3599  buffer += package_name;
3600  buffer += "_project";
3601  buffer += " \"";
3602  if (p != 0)
3603    {
3604      buffer += p->get_name ();
3605    }
3606  buffer += "\"";
3607  buffer += "\n";
3608
3609  buffer += "macro ";
3610  buffer += package_name;
3611  buffer += "_project_release";
3612  buffer += " \"";
3613  if (p != 0)
3614    {
3615      buffer += p->get_release ();
3616    }
3617  buffer += "\"";
3618}
3619
3620
3621//----------------------------------------------------------
3622static bool same_dirs (const cmt_string& d1, const cmt_string& d2)
3623{
3624  bool result = false;
3625
3626  cmt_string here = CmtSystem::pwd ();
3627
3628  cmt_string h1;
3629  if (CmtSystem::cd (d1)) h1 = CmtSystem::pwd ();
3630
3631  CmtSystem::cd (here);
3632
3633  cmt_string h2;
3634  if (CmtSystem::cd (d2)) h2 = CmtSystem::pwd ();
3635
3636  result = (h1 == h2);
3637
3638  CmtSystem::cd (here);
3639
3640  return (result);
3641}
3642
3643//----------------------------------------------------------
3644static bool install_library (const cmt_string& source_library_name, 
3645                             const cmt_string& dest_library_name, 
3646                             const cmt_string& cmtinstallarea, 
3647                             const cmt_string& tag, 
3648                             const cmt_string& symlinkcmd)
3649{
3650  cmt_string libname = source_library_name;
3651  cmt_string name = dest_library_name;
3652  cmt_string s;
3653  Use& current_use = Use::current ();
3654
3655  Symbol::expand (name);
3656  Symbol::expand (libname);
3657
3658  if (cmtinstallarea != "")
3659    {
3660      s = cmtinstallarea;
3661      s += CmtSystem::file_separator ();
3662      s += tag;
3663      s += CmtSystem::file_separator ();
3664      s += "lib";
3665      s += CmtSystem::file_separator ();
3666      s += name;
3667     
3668      // Now creating the reference file
3669
3670      cmt_string ref_file = s;
3671      ref_file += ".cmtref";
3672
3673      cmt_string text = libname;
3674      text += "\n";
3675
3676      Symbol::expand (ref_file);
3677      Symbol::expand (text);
3678
3679      if (CmtMessage::active (Info))
3680        cerr << "   Creating the reference file " << ref_file << endl;
3681          //      if (!Cmt::get_quiet ()) cerr << "   Creating the reference file " << ref_file << endl;
3682      text.write (ref_file);
3683    }
3684  else
3685    {
3686      if (current_use.style != none_style)
3687        {
3688          s = "../$(";
3689          s += current_use.get_package_name ();
3690          s += "_tag)/";
3691        }
3692      else
3693        {
3694          s = "./";
3695        }
3696      s += name;
3697    }
3698
3699  Symbol::expand (s);
3700
3701  cmt_string source;
3702  cmt_string dest;
3703
3704  CmtSystem::dirname (libname, source);
3705  CmtSystem::dirname (s, dest);
3706
3707  if (same_dirs (source, dest))
3708    {
3709      return (false);
3710    }
3711
3712  //if (!Cmt::get_quiet ())
3713  if (CmtMessage::active (Info))
3714    cerr << "   Symlinking " << libname << " to " << s << endl;
3715
3716  if (symlinkcmd == "")
3717    {
3718      if (!CmtSystem::create_symlink (libname, s))
3719        {
3720          CmtMessage::error ("Cannot create a symbolic link to " + libname);
3721          //      cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
3722          return (false);
3723        }
3724    }
3725  else
3726    {
3727      cmt_string cmd = symlinkcmd;
3728      cmd += " ";
3729      cmd += libname;
3730      cmd += " ";
3731      cmd += s;
3732     
3733      int status = CmtSystem::execute (cmd);
3734     
3735      if (status != 0)
3736        {
3737          CmtMessage::error ("Cannot create a symbolic link to " + libname);
3738          //      cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
3739          return (false);
3740        }
3741    }
3742
3743  return (true);
3744}
3745
3746
3747/**
3748   Centralize the construction of library links for this Use.
3749*/
3750void Use::build_library_links (const cmt_string& cmtinstallarea, 
3751                               const cmt_string& tag, 
3752                               const cmt_string& shlibsuffix, 
3753                               const cmt_string& symlinkcmd) const
3754{
3755  if (!located ())
3756    {
3757      CmtMessage::warning ("package " + get_package_name ()
3758                           + " " + version + " " + path
3759                           + " not found");
3760      /*
3761      if (!Cmt::get_quiet ())
3762        {
3763          cerr << "# package " << get_package_name () <<
3764            " " << version << " " << path <<
3765            " not found" <<
3766            endl;
3767        }
3768      */
3769      return;
3770    }
3771
3772  cmt_string s;
3773
3774  s = get_package_name ();
3775  s += "_libraries";
3776
3777  Symbol* libraries_macro = Symbol::find (s);
3778
3779  if (libraries_macro == 0) return;
3780
3781  cmt_string libraries = libraries_macro->build_macro_value ();
3782  Symbol::expand (libraries);
3783  static CmtSystem::cmt_string_vector values;
3784
3785  CmtSystem::split (libraries, " \t", values);
3786
3787  for (int j = 0; j < values.size (); j++)
3788    {
3789      const cmt_string& library = values[j];
3790
3791      static cmt_string libname;
3792      static cmt_string name;
3793
3794      // Is it a simple name or a complete path?
3795
3796      libname = library;
3797      Symbol::expand (libname);
3798
3799      bool is_absolute = false;
3800
3801      is_absolute = CmtSystem::absolute_path (libname);
3802
3803      if (is_absolute)
3804        {
3805          /**
3806           *   We assume here that "library" contains a complete path.
3807           *   (including the complete syntax libxxx.so)
3808           */
3809
3810          cmt_string suffix;
3811          CmtSystem::basename (library, name);
3812        }
3813      else
3814        {
3815          /**
3816           *   Here we expect that only the base name of the library
3817           *   is given : ie it should not contain the "lib" prefix,
3818           *   nor the suffix .so, nor any path prefix.
3819           *    This of course should generally correspond to a constituent name.
3820           */
3821         
3822          if (style != none_style)
3823            {
3824          libname = "${";
3825          libname += prefix;
3826          libname += "ROOT}/${";
3827          libname += get_package_name ();
3828          libname += "_tag}/";
3829            }
3830          else
3831            {
3832          libname = "${";
3833          libname += prefix;
3834          libname += "ROOT}/";
3835            }
3836          libname += "$(library_prefix)";
3837          libname += library;
3838          libname += "$(library_suffix)";
3839          libname += ".";
3840          libname += shlibsuffix;
3841
3842          name = "$(library_prefix)";
3843          name += library;
3844          name += "$(library_suffix)";
3845          name += ".";
3846          name += shlibsuffix;
3847        }
3848
3849      if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
3850        {
3851          continue;
3852        }
3853
3854#ifdef __APPLE__
3855      if (!is_absolute)
3856        {
3857          if (style != none_style)
3858            {
3859          libname = "${";
3860          libname += prefix;
3861          libname += "ROOT}/${";
3862          libname += get_package_name ();
3863          libname += "_tag}/";
3864            }
3865          else
3866            {
3867          libname = "${";
3868          libname += prefix;
3869          libname += "ROOT}/";
3870            }
3871          libname += library;
3872          libname += ".bundle";
3873
3874          name = library;
3875          name += ".bundle";
3876         
3877          if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
3878            {
3879              continue;
3880            }
3881        }
3882#endif
3883    }
3884}
3885
3886/**
3887 *   This function tries to get the replacement of a Use when it has
3888 *  been discarded by a better match to version constraints.
3889 */
3890Use* Use::get_selected_version ()
3891{
3892  if (!discarded) return (this);
3893
3894  Package* p = m_package;
3895
3896  Use::UsePtrVector& uses = p->get_uses ();
3897
3898  bool dbg = Cmt::get_debug ();
3899
3900  int size = uses.size ();
3901
3902  for (int i = 0; i < size; i++)
3903    {
3904      Use* u = uses[i];
3905      if (u == 0) continue;
3906      if (u->discarded) continue;
3907      if (dbg)
3908        {
3909          cout << "Use::get_selected_version> for package " << get_package_name ()
3910               << "  got a version " << u << endl;
3911        }
3912      return (u);
3913    }
3914
3915  return (0);
3916}
3917
3918/**
3919   Switching from one use to another one, (better wrt
3920   various criteria).
3921
3922   When switching, m_index and auto_imports are
3923   transfered from the un-selected to the newly selected.
3924*/
3925Use* Use::set_selected_version (Use* selected_use)
3926{
3927  if (this == selected_use) return (this);
3928
3929  static UsePtrVector& uses = get_ordered_uses ();
3930
3931  if (m_index >= 0)
3932    {
3933      // This discarded package was registered. We have to substitute
3934      // it with the new one.
3935
3936      if (Cmt::get_debug ())
3937        {
3938          cout << "set_selected_version> Replace "
3939               << get_package_name () << "(" << m_index << ")[" << this << "] with "
3940               << selected_use->get_package_name () << "(" << selected_use->m_index << ")[" << selected_use << "]" << endl;
3941        }
3942
3943      selected_use->m_index = m_index;
3944      selected_use->auto_imports = auto_imports;
3945
3946      selected_use->undiscard ();
3947
3948      m_index = -1;
3949
3950      uses[selected_use->m_index] = selected_use;
3951    }
3952
3953  discard ();
3954
3955  return (selected_use);
3956}
3957
3958//----------------------------------------------------------
3959void Use::set_auto_imports (State context_state, State specified_state,
3960                            cmt_map <Use*, bool>& visited)
3961{
3962  static int level (-1);
3963  level++;
3964  if (level == 0)
3965    {
3966      unselect_all ();
3967      selected = true;
3968    }
3969
3970  if (visited.has (this) &&
3971      (1 != level || selected))
3972    // revisit sub-uses of current (level == 0) use
3973    // encountered in its requirements file for the first time (selected == false)
3974    // to ensure their auto_imports state takes precedence
3975    {
3976      level--;
3977      return;
3978    }
3979
3980  if (Cmt::get_debug ())
3981    {
3982      cout << "Use::set_auto_imports>|";
3983      for (int i = level; i > 0; i--) cout << "-";
3984      cout << get_package_name () << "> " 
3985           << auto_imports << " -> " 
3986           << "(" << context_state << ")" << specified_state << endl;
3987    }
3988
3989  static bool yes (true);
3990  visited.add (this, yes);
3991  if (1 == level) selected = true;
3992  //  if (auto_imports == context_state) return;
3993 
3994  //State old_state = auto_imports;
3995 
3996  //auto_imports = context_state;
3997
3998  switch (context_state)
3999    {
4000    case Unspecified:
4001    case On:
4002      //if (auto_imports == specified_state) return;
4003      auto_imports = specified_state;
4004      /*
4005      switch (auto_imports)
4006        {
4007        case Unspecified:
4008          break;
4009        case Off:
4010          context_state = Off;
4011          break;
4012        case On:
4013          context_state = On;
4014          break;
4015        }
4016      */
4017      context_state = UseContext::mask_auto_imports (context_state, auto_imports);
4018      break;
4019    case Off:
4020      //if (auto_imports == context_state) return;
4021      auto_imports = context_state;
4022      break;
4023    }
4024  cmt_string s;
4025  static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
4026 
4027  if (Cmt::get_debug ())
4028    {
4029      s = "Use::set_auto_imports><";
4030      for (int i = level; i > 0; i--) s += "-";
4031      s += get_package_name ();
4032      s += "|";
4033      //cout << s << endl;
4034    }
4035 
4036  for (int i = 0; i < sub_uses.size (); i++)
4037  //for (int i = sub_uses.size () - 1; i >= 0; i--)
4038    {
4039      State state = sub_use_auto_imports[i];
4040      if (Cmt::get_debug ())
4041        {
4042          s += " ";
4043          s += sub_uses[i]->get_package_name ();
4044          s += "(";
4045          s += state_text[state + 1];
4046          s += ")";
4047        }
4048      if (sub_uses[i]->m_index >= 0 && !sub_uses[i]->discarded)
4049        {
4050          sub_uses[i]->set_auto_imports (context_state, state, visited);
4051        }
4052      else
4053        {
4054          if (Cmt::get_debug ())
4055            {
4056              char num[32]; sprintf (num, "%#x", sub_uses[i]);
4057              char index[32]; sprintf (index, "%d", sub_uses[i]->m_index);
4058              s += "[";
4059              s += num;
4060              s += ", discarded=";
4061              s += (sub_uses[i]->discarded ? "1" : "0");
4062              s += ", m_index=";
4063              s += index;
4064              s += " : invalid]";
4065            }
4066          Use* au (find_valid (sub_uses[i]->get_package_name ()));
4067          if (au)
4068            {
4069              if (Cmt::get_debug ())
4070                {
4071                  char num[32]; sprintf (num, "%#x", au);
4072                  char index[32]; sprintf (index, "%d", au->m_index);
4073                  s += "[";
4074                  s += num;
4075                  s += ", discarded=";
4076                  s += (au->discarded ? "1" : "0");
4077                  s += ", m_index=";
4078                  s += index;
4079                  s += " : valid]";
4080                }
4081              au->set_auto_imports (context_state, state, visited);
4082            }
4083          else
4084            {
4085              visited.add (sub_uses[i], yes);
4086              sub_uses[i]->select ();
4087            }
4088        }
4089    }
4090
4091  if (Cmt::get_debug ())
4092    {
4093      cout << s << endl;
4094    }
4095
4096  level--;
4097  return;
4098}
4099/*
4100void Use::set_auto_imports (State new_state)
4101{
4102  if (Cmt::get_debug ())
4103    {
4104      cout << "Use::set_auto_imports>(" << get_package_name () << ") "
4105           << auto_imports << " -> " << new_state << endl;
4106    }
4107
4108  if (auto_imports == new_state) return;
4109 
4110  State old_state = auto_imports;
4111 
4112  auto_imports = new_state;
4113
4114  // We propagate only when we switch from Off to On
4115
4116  if ((old_state == Off) && (new_state == On))
4117    {
4118      cmt_string s;
4119      static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
4120
4121      if (Cmt::get_debug ())
4122        {
4123          s = "Use::set_auto_imports>(";
4124          s += get_package_name ();
4125          s += ") ";
4126
4127          cout << s << endl;
4128        }
4129
4130      for (int i = 0; i < sub_uses.size (); i++)
4131        {
4132          Use* u = sub_uses[i];
4133          State state = sub_use_auto_imports[i];
4134         
4135          if (Cmt::get_debug ())
4136            {
4137              s += " ";
4138              s += u->get_package_name ();
4139              s += "(";
4140              s += state_text[state + 1];
4141              s += ")";
4142            }
4143
4144          if (state == Unspecified)
4145            {
4146              u->set_auto_imports (On);
4147            }
4148        }
4149         
4150      if (Cmt::get_debug ())
4151        {
4152          cout << s << endl;
4153        }
4154    }
4155}
4156*/
4157
4158//----------------------------------------------------------
4159void Use::set_native_version (bool state)
4160{
4161  m_has_native_version = state;
4162}
4163
4164bool Use::has_native_version () const
4165{
4166  return (m_has_native_version);
4167}
4168
4169Package* Use::get_package () const
4170{
4171  return (m_package);
4172}
4173
4174const cmt_string& Use::get_package_name () const
4175{
4176  static const cmt_string null = "";
4177
4178  Package* p = m_package;
4179  if (p == 0) return (null);
4180
4181  return (p->get_name ());
4182}
4183
4184void Use::set_package_name (const cmt_string& name)
4185{
4186  Package* p = Package::add (name);
4187
4188  m_package = p;
4189  p->add_use (this);
4190}
4191
4192int Use::get_index () const
4193{
4194  return (m_index);
4195}
4196
4197//----------------------------------------------------------
4198bool Use::get_all_clients (const cmt_string& to_name)
4199{
4200  Use::UsePtrVector& uses = Use::get_ordered_uses ();
4201
4202  Use* use = Use::find (to_name);
4203
4204  if (use == 0)
4205    {
4206      //      CmtMessage::warning ("No access to " + to_name);
4207      return (false);
4208    }
4209
4210  cmt_map <cmt_string, Use*> all_clients;
4211  cmt_map <cmt_string, Use*> all_clients_ok;
4212
4213  const cmt_string& name = get_package_name ();
4214
4215  Use* me = this;
4216
4217  all_clients.add (name, me);
4218  all_clients_ok.add (name, me);
4219
4220  bool status = get_all_clients (use, to_name, all_clients, all_clients_ok); 
4221
4222  return (status);
4223}
4224
4225//----------------------------------------------------------
4226bool Use::get_all_clients (Use* to, 
4227                           const cmt_string& result, 
4228                           cmt_map <cmt_string, Use*>& all_clients, 
4229                           cmt_map <cmt_string, Use*>& all_clients_ok)
4230{
4231  if (this == to)
4232    {
4233      cout << result << endl;
4234      return (true);
4235    }
4236
4237  const cmt_string& to_name = to->get_package_name ();
4238  const cmt_string& to_version = to->version;
4239
4240  //cout << "gac> from " << get_package_name () << " to " << to_name << " -> " << result << endl;
4241
4242  if (all_clients.has (to_name))
4243    {
4244      if (all_clients_ok.has (to_name))
4245        {
4246          cout << "   ..." << result << endl;
4247          return (true);
4248        }
4249      else
4250        {
4251          return (false);
4252        }
4253    }
4254
4255  all_clients.add (to_name, to);
4256
4257  bool status = false;
4258
4259  Use::UsePtrVector& uses = Use::get_ordered_uses ();
4260  Use* use = 0;
4261
4262  for (int n = 0; n < uses.size (); ++n)
4263    {
4264      use = uses[n];
4265
4266      if (use->discarded) continue;
4267      if (use->m_hidden) continue;
4268
4269      if (!use->located ()) continue;
4270
4271      if (use == to) continue;
4272
4273      if (use->is_client (to_name, to_version))
4274        {
4275          const cmt_string& n = use->get_package_name ();
4276
4277          cmt_string r;
4278
4279          if ((use->initial_scope != ScopeUnspecified) &&
4280              (use->initial_scope != ScopePublic)) 
4281            {
4282              r += "(private)";
4283            }
4284         
4285          if (use->auto_imports == Off) r += "(no_auto_imports)";
4286
4287          r += n;
4288          r += ".";
4289          r += result;
4290
4291          //cout << "gac> " << n << " is client of " << to_name << endl;
4292
4293          if (get_all_clients (use, r, all_clients, all_clients_ok))
4294            {
4295              all_clients_ok.add (n, use);
4296              status = true;
4297            }
4298        }
4299    }
4300
4301  use = this;
4302
4303  if (use->is_client (to_name, to_version))
4304    {
4305      const cmt_string& n = use->get_package_name ();
4306     
4307      cmt_string r;
4308
4309      if ((use->initial_scope != ScopeUnspecified) &&
4310          (use->initial_scope != ScopePublic)) 
4311        {
4312          r += "(private)";
4313        }
4314     
4315      if (use->auto_imports == Off) r += "(no_auto_imports)";
4316
4317      r += n;
4318      r += ".";
4319      r += result;
4320     
4321      //cout << "gac> " << n << " is client of " << to_name << endl;
4322     
4323      if (get_all_clients (use, r, all_clients, all_clients_ok))
4324        {
4325          all_clients_ok.add (n, use);
4326          status = true;
4327        }
4328    }
4329
4330  return (status);
4331}
4332
4333/**
4334   Let's consider two packages in the use graph "this" and "to"
4335   This function finds all packages that are reached in between
4336   following all possible paths between "this" and "to"
4337
4338   Result s accumulated into "list"
4339*/
4340bool Use::get_paths (Use* to, UsePtrVector& list)
4341{
4342  bool is_in_path = false;
4343  bool cycle = false;
4344  bool already_in_path = false;
4345  bool dbg = Cmt::get_debug ();
4346
4347  static int level = 0;
4348
4349  int size = 0;
4350
4351  if (level == 0)
4352    {
4353      unselect_all ();
4354      selected = false;
4355    }
4356
4357  if (selected) 
4358    {
4359      /**
4360         If this use is already in the list, we don't duplicate the entry.
4361         (protection duplicate paths in the graph)
4362      */
4363
4364      size = list.size ();
4365
4366      for (int m = 0; m < size; m++)
4367        {
4368          Use* u = list[m];
4369          if (u == this)
4370            {
4371              if (dbg)
4372                {
4373                  for (int lll = 0; lll < level; lll++) cout << "  ";
4374                  cout << "  Use::get_paths." << level << "> try1.2 sub="
4375                       << get_package_name () << " already_in_path " << endl;
4376                }
4377             
4378              return (true);
4379            }
4380        }
4381
4382      return (false);
4383    }
4384
4385  selected = true;
4386
4387  if (dbg)
4388    {
4389      for (int lll = 0; lll < level; lll++) cout << "  ";
4390      cout << "Use::get_paths." << level << ">" << get_package_name ()
4391           << " to=" << to->get_package_name () 
4392           << " list=[";
4393
4394      for (int m = 0; m < list.size (); m++)
4395        {
4396          Use* u = list[m];
4397          cout << u->get_package_name () << " ";
4398        }
4399
4400      cout << "]" << endl;
4401    }
4402
4403  /**
4404     Now "this" is a candidate new entry in the list
4405  */
4406
4407  // First figure out whether 'to' is used by 'this'.
4408
4409  if (this->get_package_name () == to->get_package_name ())
4410    {
4411      // We've reached the goal (for the first time)
4412      is_in_path = true;
4413    }
4414  else
4415    {
4416      /**
4417         Let's scan sub_uses now
4418      */
4419      size = sub_uses.size ();
4420
4421      if (dbg)
4422        {
4423          for (int lll = 0; lll < level; lll++) cout << "  ";
4424          cout << "  Use::get_paths." << level << "> size=" << size << endl;
4425        }
4426
4427      for (int n = 0; n < size; n++)
4428        {
4429          Use* use = sub_uses[n];
4430
4431          if (use == 0) continue;
4432
4433          if (dbg)
4434            {
4435              for (int lll = 0; lll < level; lll++) cout << "  ";
4436              cout << "  Use::get_paths." << level << "> try1 sub="
4437                   << use->get_package_name () << "(" << use << ") " << use->discarded << endl;
4438            }
4439
4440          if (use->discarded)
4441            {
4442              Use* u;
4443
4444              u = use->get_selected_version ();
4445              if (u == 0) 
4446                {
4447                  /**
4448                     No way to find a valid use for this used package.
4449                     Is that a bug?
4450                     Anyway we don't pursue on that branch.
4451                  */
4452                  continue;
4453                }
4454
4455              use = u;
4456            }
4457
4458          if (dbg)
4459            {
4460              for (int lll = 0; lll < level; lll++) cout << "  ";
4461              cout << "  Use::get_paths." << level << "> try2 sub="
4462                   << use->get_package_name () << " " << use->discarded << endl;
4463            }
4464
4465          level++;
4466          bool r = use->get_paths (to, list);
4467          level--;
4468
4469          if (r)
4470            {
4471              is_in_path = true;
4472            }
4473        }
4474    }
4475
4476  if (is_in_path)
4477    {
4478      if (dbg)
4479        {
4480          for (int lll = 0; lll < level; lll++) cout << "  ";
4481          cout << "Use::get_paths." << level << "> push " << get_package_name () << endl;
4482        }
4483      list.push_back (this);
4484    }
4485
4486  return (is_in_path);
4487}
4488
4489//----------------------------------------------------------
4490bool Use::located () const
4491{
4492  return (m_located);
4493}
4494
4495//----------------------------------------------------------
4496void Use::show_sub_uses (const cmt_string& request, bool skip_discarded, ostream& out)
4497//void Use::show_sub_uses (const cmt_string& request, bool skip_discarded)
4498{
4499  Use* current = &(Use::current ());
4500  int n;
4501  Use* use;
4502  static int level = 0;
4503
4504  if (skip_discarded && discarded) return;
4505  if (m_hidden) return;
4506
4507  if (level > 0)
4508    {
4509      out << "# ";
4510      for (n = 0; n < (level-1); n++) out << "  ";
4511
4512      if (request == "")
4513        {
4514          out << "use " << get_package_name () << " " << specified_version;
4515
4516          if (this == current) 
4517            {
4518              out << " (current)";
4519            }
4520          else
4521            {
4522              if (specified_path != "") out << " " << specified_path;
4523            }
4524        }
4525      else
4526        {
4527          out << "use " << request;
4528        }
4529
4530      if (version_alias != "")
4531        {
4532          out << " | " << version_alias << " " << path_alias;
4533        }
4534
4535      if (initial_scope == ScopeUnspecified) out << " (unspecified)";
4536      else if (initial_scope != ScopePublic) out << " (private)";
4537
4538      if (auto_imports == Off) out << " (no_auto_imports)";
4539
4540      if (structuring_style == without_version_directory) out << " (no_version_directory)";
4541      //      if (style == no_version_style) out << " (no_version_directory)";
4542
4543      if (m_has_native_version)
4544        {
4545          cmt_string n = get_package_name ();
4546          n += "_native_version";
4547
4548          Symbol* s = Symbol::find (n);
4549          if (s != 0)
4550            {
4551              cmt_string value = s->resolve_macro_value ();
4552              out << " (native_version=" << value << ")";
4553            }
4554        }
4555
4556      out << endl;
4557    }
4558
4559  if (selected) return;
4560  selected = true;
4561
4562  level++;
4563  for (n = 0; n < sub_uses.size (); n++)
4564    {
4565      use = sub_uses[n];
4566      if (use == 0) continue;
4567
4568      const cmt_string& request = requests[n];
4569
4570      ScopeType saved_scope = use->initial_scope;
4571      State saved_state = use->auto_imports;
4572
4573      use->initial_scope = sub_use_scopes[n];
4574      use->auto_imports = sub_use_auto_imports[n];
4575
4576      use->show_sub_uses (request, skip_discarded, out);
4577
4578      use->initial_scope = saved_scope;
4579      use->auto_imports = saved_state;
4580    }
4581  level--;
4582}
4583
4584//----------------------------------------------------------
4585Use& Use::current ()
4586{
4587  static UseVector& instances = get_instances ();
4588  static Use* current_use = 0;
4589
4590  if ((current_use == 0) || (instances.size () == 0))
4591    {
4592      Use& use_object = instances.add ();
4593      current_use = &use_object;
4594    }
4595
4596  return (*current_use);
4597}
4598
4599//----------------------------------------------------------
4600const Use& Use::const_current ()
4601{
4602  const Use& use = Use::current ();
4603
4604  return (use);
4605}
4606
4607//----------------------------------------------------------
4608Use::UseVector& Use::get_instances ()
4609{
4610  static Database& db = Database::instance ();
4611  static UseVector& instances = db.all_uses ();
4612
4613  return (instances);
4614}
4615
4616//----------------------------------------------------------
4617Use::UsePtrVector& Use::get_ordered_uses ()
4618{
4619  static Database& db = Database::instance ();
4620  static UsePtrVector& uses = db.uses ();
4621
4622  return (uses);
4623}
4624
4625//----------------------------------------------------------
4626
4627//----------------------------------------------------------
4628//
4629//  Check if the specified version is better than the
4630//  current one.
4631//
4632//----------------------------------------------------------
4633Use* BestFitSelector::operate (Use* ref_use, Use* new_use)
4634{
4635  Use* selected = ref_use;
4636
4637  int ref_v = -1;
4638  int ref_r = -1;
4639  int ref_p = -1;
4640  cmt_string ref_pp;
4641
4642  int new_v = -1;
4643  int new_r = -1;
4644  int new_p = -1;
4645  cmt_string new_pp;
4646
4647  int alias_v = -1;
4648  int alias_r = -1;
4649  int alias_p = -1;
4650  cmt_string alias_pp;
4651
4652  enum { no_alias, new_has_alias, ref_has_alias } has_alias = no_alias;
4653
4654  // First analyze specified versions
4655  cmt_string ref_version = ref_use->specified_version;
4656  cmt_string new_version = new_use->specified_version;
4657
4658  CmtSystem::is_version_directory (ref_version, ref_v, ref_r, ref_p);
4659  ref_pp = ref_use->path;
4660
4661  CmtSystem::is_version_directory (new_version, new_v, new_r, new_p);
4662  new_pp = new_use->path;
4663
4664  if (new_use->version_alias != "")
4665    {
4666      has_alias = new_has_alias;
4667      CmtSystem::is_version_directory (new_use->version_alias, 
4668                                       alias_v, alias_r, alias_p);
4669      alias_pp = new_use->path_alias;
4670    }
4671  else if (ref_use->version_alias != "")
4672    {
4673      has_alias = ref_has_alias;
4674      CmtSystem::is_version_directory (ref_use->version_alias, 
4675                                       alias_v, alias_r, alias_p);
4676      alias_pp = ref_use->path_alias;
4677    }
4678
4679  ref_use->undiscard ();
4680  new_use->undiscard ();
4681
4682  if (new_v != ref_v)
4683    {
4684      if (has_alias != no_alias)
4685        {
4686          if (has_alias == new_has_alias)
4687            {
4688              new_v = alias_v;
4689              new_r = alias_r;
4690              new_p = alias_p;
4691              new_pp = alias_pp;
4692            }
4693          else if (has_alias == ref_has_alias)
4694            {
4695              ref_v = alias_v;
4696              ref_r = alias_r;
4697              ref_p = alias_p;
4698              ref_pp = alias_pp;
4699            }
4700        }
4701    }
4702
4703  bool ref_v_wildcarded = ((ref_v) == -1);
4704  bool ref_r_wildcarded = ((ref_r) == -1);
4705  bool ref_p_wildcarded = ((ref_p) == -1);
4706
4707  bool ref_v_explicit = !ref_v_wildcarded;
4708  bool ref_r_explicit = !ref_r_wildcarded;
4709  bool ref_p_explicit = !ref_p_wildcarded;
4710
4711  bool new_v_wildcarded = ((new_v) == -1);
4712  bool new_r_wildcarded = ((new_r) == -1);
4713  bool new_p_wildcarded = ((new_p) == -1);
4714
4715  bool new_v_explicit = !new_v_wildcarded;
4716  bool new_r_explicit = !new_r_wildcarded;
4717  bool new_p_explicit = !new_p_wildcarded;
4718
4719  bool verbose = (CmtSystem::getenv ("CMTVERBOSE") != "");
4720
4721  cmt_string ref_vc = ref_v_wildcarded ? "wildcarded" : "explicit";
4722  cmt_string ref_rc = ref_r_wildcarded ? "wildcarded" : "explicit";
4723  cmt_string ref_pc = ref_p_wildcarded ? "wildcarded" : "explicit";
4724 
4725  cmt_string new_vc = new_v_wildcarded ? "wildcarded" : "explicit";
4726  cmt_string new_rc = new_r_wildcarded ? "wildcarded" : "explicit";
4727  cmt_string new_pc = new_p_wildcarded ? "wildcarded" : "explicit";
4728
4729  // Now compute effective version identifiers
4730  CmtSystem::is_version_directory (ref_use->version, ref_v, ref_r, ref_p);
4731  CmtSystem::is_version_directory (new_use->version, new_v, new_r, new_p);
4732
4733  cmt_string new_selected_version = new_use->version;
4734
4735  if (new_v_explicit && ref_v_explicit && (new_v != ref_v))
4736    {
4737      /*
4738        if (verbose && !Cmt::get_quiet ())
4739        {
4740        cerr << "# Required explicit version " << new_version
4741        << " of package " << ref_use->get_package_name ()
4742        << " incompatible with selected explicit version " << ref_version
4743        << endl;
4744        }
4745
4746        CmtError::set (CmtError::version_conflict, "BestFitSelector::operate> ");
4747
4748        if (ref_use != new_use) new_use->discard ();
4749      */
4750
4751      if (new_v > ref_v)
4752        {
4753          if (verbose && !Cmt::get_quiet ())
4754            {
4755              cerr << "# Select " << new_vc << " version " << new_version
4756                   << " of package " << ref_use->get_package_name () 
4757                   << " instead of existing " << ref_vc << " " << ref_version
4758                   << endl;
4759            } 
4760         
4761          if (ref_use != new_use) ref_use->discard ();
4762          selected = new_use;
4763          selected->done = false; // Will read the new requirements
4764        }
4765    }
4766  else if (new_v_wildcarded || ref_v_wildcarded)
4767    {
4768      // at least one of ref or new is wildcarded
4769
4770      //
4771      // we plan to discard new_use, but if it was specified as explicit
4772      // and ref_use was wildcarded then new_use will win !!
4773      //
4774      // So then we'll have to understand where are the wild
4775      // cards... If they are on v or r, then we consider them.
4776      //
4777      //
4778
4779      if (ref_v_wildcarded && new_v_explicit)
4780        {
4781          if ((ref_use->real_path != new_use->real_path) ||
4782              (ref_use->version != new_use->version))
4783            {
4784              if (ref_use != new_use) ref_use->discard ();
4785              selected = new_use;
4786              selected->done = false; // Will read the new requirements
4787
4788              if (verbose && !Cmt::get_quiet ())
4789                {
4790                  cerr << "# Select explicit version " << new_version
4791                       << "(" << new_use->version << ")" 
4792                       << " of package " << ref_use->get_package_name () 
4793                       << " instead of existing wildcarded " << ref_version
4794                       << "(" << ref_use->version << ")" 
4795                       << endl;
4796                }
4797            }
4798          else
4799            {
4800              if (ref_use != new_use) new_use->discard ();
4801              //ref_use->version = new_selected_version;
4802            }
4803        }
4804      else
4805        {
4806          // ref is explicit or new is wildcarded
4807
4808          /*
4809            if (verbose && !Cmt::get_quiet ())
4810            {
4811            cerr << "# keep " << ref_vc << " version " << ref_version
4812            << " of package " << ref_use->get_package_name ()
4813            << " (ignore " << new_vc << " version " << new_version << ")"
4814            << endl;
4815            }
4816          */
4817
4818          if (ref_use != new_use) new_use->discard ();
4819        }
4820    }
4821  else if (new_r_wildcarded || ref_r_wildcarded || (new_r < ref_r))
4822    {
4823      //
4824      // we plan to discard new_use, but if it was specified as explicit
4825      // and ref_use was wildcarded then new_use will win !!
4826      //
4827      // So then we'll have to understand where are the wild
4828      // cards... If they are on v or r, then we consider them.
4829      //
4830      //
4831
4832      if (ref_r_wildcarded && new_r_explicit)
4833        {
4834          // ref has wild card and new has not => new wins
4835
4836          if ((ref_use->real_path != new_use->real_path) ||
4837              (ref_use->version != new_use->version))
4838            {
4839              if (ref_use != new_use) ref_use->discard ();
4840              selected = new_use;
4841              selected->done = false; // Will read the new requirements
4842
4843              if (verbose && !Cmt::get_quiet ())
4844                {
4845                  cerr << "# Select explicit release " << new_version
4846                       << " of package " << ref_use->get_package_name ()
4847                       << " instead of existing wildcarded " << ref_version
4848                       << endl;
4849                } 
4850            }
4851          else
4852            {
4853              // Just adapt version with new one.
4854
4855              if (ref_use != new_use) new_use->discard ();
4856              //ref_use->version = new_selected_version;
4857            }
4858        }
4859      else
4860        {
4861          /*
4862            if (verbose &&!Cmt::get_quiet ())
4863            {
4864            cerr << "# keep " << ref_rc << " release " << ref_version
4865            << " of package " << ref_use->get_package_name ()
4866            << " (ignore " << new_rc << " release " << new_version << ")"
4867            << endl;
4868            }
4869          */
4870
4871          if (ref_use != new_use) new_use->discard ();
4872        }
4873    }
4874  else if (new_r > ref_r)
4875    {
4876      if (verbose && !Cmt::get_quiet ())
4877        {
4878          cerr << "# Select " << new_rc << " release " << new_version
4879               << " of package " << ref_use->get_package_name () 
4880               << " instead of existing " << ref_rc << " " << ref_version
4881               << endl;
4882        } 
4883
4884      if (ref_use != new_use) ref_use->discard ();
4885      selected = new_use;
4886      selected->done = false; // Will read the new requirements
4887    }
4888  else if (new_p_wildcarded || ref_p_wildcarded || (new_p < ref_p))
4889    {
4890      //
4891      // we plan to discard new_use, but if it was specified as explicit
4892      // and ref_use was wildcarded then new_use will win !!
4893      //
4894
4895      if (ref_p_wildcarded && new_p_explicit)
4896        {
4897          if ((ref_use->real_path != new_use->real_path) ||
4898              (ref_use->version != new_use->version))
4899            {
4900              if (ref_use != new_use) ref_use->discard ();
4901              selected = new_use;
4902              selected->done = false; // Will read the new requirements
4903
4904              if (verbose && !Cmt::get_quiet ())
4905                {
4906                  cerr << "# Select explicit patch " << new_version
4907                       << " of package " << ref_use->get_package_name () 
4908                       << " instead of existing wildcarded " << ref_version
4909                       << endl;
4910                }
4911            }
4912          else
4913            {
4914              if (ref_use != new_use) new_use->discard ();
4915              ref_use->version = new_selected_version;
4916            }
4917        }
4918      else
4919        {
4920          /*
4921            if (verbose && !Cmt::get_quiet ())
4922            {
4923            cerr << "# keep " << ref_pc << " patch " << ref_version
4924            << " [" << ref_use->specified_version << "]"
4925            << " of package " << ref_use->get_package_name ()
4926            << " (ignore " << new_pc << " version " << new_version << ")"
4927            << " [" << new_use->specified_version << "]"
4928            << endl;
4929            }
4930          */
4931
4932          if (ref_use != new_use) new_use->discard ();
4933        }
4934    }
4935  else if (new_p > ref_p)
4936    {
4937      if (verbose && !Cmt::get_quiet ())
4938        {
4939          cerr << "# Select " << new_pc << " patch " << new_version
4940               << " of package " << ref_use->get_package_name () 
4941               << " instead of existing " << ref_pc << " " << ref_version
4942               << endl;
4943        }
4944
4945      if (ref_use != new_use) ref_use->discard ();
4946      selected = new_use;
4947      selected->done = false; // Will read the new requirements
4948    }
4949  else if (new_pp != ref_pp) // same version-r-p but from different path
4950    {
4951      if (ref_use != new_use) ref_use->discard ();
4952      selected = new_use;
4953      selected->done = false; // Will read the new requirements
4954    }
4955
4956  return (selected);
4957}
4958
4959
4960//----------------------------------------------------------
4961class VersionReader : public Awk
4962{
4963public:
4964
4965  VersionReader ()
4966  {
4967  }
4968 
4969  const cmt_string& get_version () const
4970  {
4971    return (m_version);
4972  }
4973 
4974  void filter (const cmt_string& line)
4975  {
4976    CmtSystem::cmt_string_vector words;
4977    CmtSystem::split (line, " \t", words);
4978    if (words[0] == "version")
4979      {
4980        m_version = words[1];
4981      }
4982  }
4983 
4984private:
4985  cmt_string m_version;
4986};
4987
4988//----------------------------------------------------------
4989class PackageReader : public Awk
4990{
4991public:
4992
4993  PackageReader ()
4994  {
4995  }
4996 
4997  const cmt_string& get_package () const
4998  {
4999    return (m_package);
5000  }
5001 
5002  void filter (const cmt_string& line)
5003  {
5004    CmtSystem::cmt_string_vector words;
5005    CmtSystem::split (line, " \t", words);
5006    if (words[0] == "package")
5007      {
5008        m_package = words[1];
5009      }
5010  }
5011 
5012private:
5013  cmt_string m_package;
5014};
5015
5016//----------------------------------------------------------
5017Package* Package::find (const cmt_string& name)
5018{
5019  static PackageMap& PackageMap = package_map ();
5020
5021  Package* result = 0;
5022
5023  result = PackageMap.find (name);
5024
5025  return (result);
5026}
5027
5028//----------------------------------------------------------
5029Package* Package::add (const cmt_string& name)
5030{
5031  static PackageVector& Packages = packages ();
5032  static PackageMap& PackageMap = package_map ();
5033
5034  {
5035    Package* package;
5036
5037    package = find (name);
5038    if (package != 0) return (package);
5039  }
5040
5041  Package& package = Packages.add ();
5042  PackageMap.add (name, package);
5043
5044  package.m_name = name;
5045
5046  if (name == "CMT")
5047    {
5048      package.m_is_cmt = true;
5049    }
5050  else if (name == "methods")
5051    {
5052      package.m_is_cmt = true;
5053    }
5054
5055  if (Cmt::get_debug ())
5056    {
5057      cout << "Package::add (" << name << ")" << endl;
5058    }
5059
5060  return (&package);
5061}
5062
5063//----------------------------------------------------------
5064Package::PackageVector& Package::packages ()
5065{
5066  static Database& db = Database::instance ();
5067  static PackageVector& Packages = db.packages ();
5068
5069  return (Packages);
5070}
5071
5072//----------------------------------------------------------
5073Package::PackageMap& Package::package_map ()
5074{
5075  static Database& db = Database::instance ();
5076  static PackageMap& PackageMap = db.package_map ();
5077
5078  return (PackageMap);
5079}
5080
5081//----------------------------------------------------------
5082void Package::clear_all ()
5083{
5084  static PackageVector& Packages = packages ();
5085  static PackageMap& PackageMap = package_map ();
5086
5087  PackageMap.clear ();
5088  Packages.clear ();
5089}
5090
5091//----------------------------------------------------------
5092bool Package::get_version (cmt_string& version, const cmt_string& path)
5093{
5094  cmt_string version_file = path;
5095  version_file += CmtSystem::file_separator ();
5096  version_file += get_version_file_name ();
5097  if (CmtSystem::test_file (version_file))
5098    {
5099      cmt_string v;
5100      if (v.read (version_file))
5101        {
5102          int pos;
5103          pos = v.find ('\n');
5104          if (pos != cmt_string::npos) v.erase (pos);
5105          pos = v.find ('\r');
5106          if (pos != cmt_string::npos) v.erase (pos);
5107          if (v != "")
5108            {
5109              version = v;
5110              return true;
5111            }
5112        }
5113      else
5114        {
5115          CmtMessage::warning ("Could not read `" + version_file + "'.");
5116        }
5117    }
5118
5119  version_file = path;
5120  version_file += CmtSystem::file_separator ();
5121  version_file += "requirements";
5122  cmt_string text;
5123  if (text.read (version_file))
5124    {
5125      VersionReader reader;
5126      reader.run (text);
5127      cmt_string v = reader.get_version ();
5128      if (v != "")
5129        {
5130          version = v;
5131          return true;
5132        }
5133    }
5134  else
5135    {
5136      CmtMessage::warning ("Could not read `" + version_file + "'.");
5137    }
5138
5139  return false;
5140}
5141
5142//----------------------------------------------------------
5143const cmt_string& Package::get_version_file_name ()
5144{
5145  static const cmt_string name = "version.cmt";
5146
5147  return (name);
5148}
5149
5150//----------------------------------------------------------
5151bool Package::get_name (cmt_string& name, const cmt_string& path)
5152{
5153  cmt_string name_file = path;
5154  name_file += CmtSystem::file_separator ();
5155  name_file += "requirements";
5156  cmt_string text;
5157  if (text.read (name_file))
5158    {
5159      PackageReader reader;
5160      reader.run (text);
5161      cmt_string v = reader.get_package ();
5162      if (v != "")
5163        {
5164          name = v;
5165          return true;
5166        }
5167    }
5168  else
5169    {
5170      CmtMessage::warning ("Could not read `" + name_file + "'.");
5171    }
5172
5173  return false;
5174}
5175
5176//----------------------------------------------------------
5177Package::Package () : m_is_cmt (false)
5178{
5179  if (Cmt::get_debug ())
5180    {
5181      cout << "Package::Package" << endl;
5182    }
5183}
5184
5185//----------------------------------------------------------
5186Package::~Package ()
5187{
5188  m_name = "";
5189}
5190
5191//----------------------------------------------------------
5192const cmt_string& Package::get_name () const
5193{
5194  return (m_name);
5195}
5196
5197//----------------------------------------------------------
5198void Package::add_use (Use* use)
5199{
5200  for (int i = 0; i < m_uses.size (); i++)
5201    {
5202      Use* u = m_uses[i];
5203      if (u == use) return;
5204    }
5205
5206  m_uses.push_back (use);
5207}
5208
5209//----------------------------------------------------------
5210void Package::remove_use (Use* use)
5211{
5212  if (Cmt::get_debug ())
5213    {
5214      cout << "Package::remove_use (" << use->get_package_name () << ")" << endl;
5215      cout << "  name=" << m_name
5216           << " uses=" << m_uses.size () << endl;
5217    }
5218
5219  Use::UsePtrVector temp;
5220
5221  temp = m_uses;
5222
5223  m_uses.clear ();
5224
5225  for (int i = 0; i < temp.size (); i++)
5226    {
5227      Use* u = temp[i];
5228      if (u != use)
5229        {
5230          m_uses.push_back (u);
5231        }
5232    }
5233}
5234
5235//----------------------------------------------------------
5236Use::UsePtrVector& Package::get_uses ()
5237{
5238  return (m_uses);
5239}
5240
5241//----------------------------------------------------------
5242bool Package::is_cmt ()
5243{
5244  return (m_is_cmt);
5245}
5246
5247//----------------------------------------------------------
5248static void show_packages ()
5249{
5250  Package::PackageVector& vector = Package::packages ();
5251
5252  int i;
5253  int j;
5254
5255  cout << "### Packages: ";
5256  for (i = 0; i < vector.size (); i++)
5257    {
5258      Package& p = vector[i];
5259      cout << p.get_name () << "[";
5260      Use::UsePtrVector& uses = p.get_uses ();
5261      for (j = 0; j < uses.size (); j++)
5262        {
5263          Use* u = uses[j];
5264          cout << u << ",";
5265        }
5266
5267      cout << "] ";
5268    }
5269  cout << endl;
5270
5271  {
5272    static Use::UsePtrVector& uses = Use::get_ordered_uses ();
5273
5274    cout << "### Uses: ";
5275    for (i = 0; i < uses.size (); i++)
5276      {
5277        Use* u = uses[i];
5278        cout << "[" << u << "]" << u->get_package_name () << " ";
5279      }
5280  }
5281
5282  cout << endl;
5283}
5284
5285//----------------------------------------------------------
5286Project* Use::get_project ()
5287{   
5288  Project* p;
5289  cmt_string cmtpath = "";
5290  cmt_string offset  = "";   
5291  get_cmtpath_and_offset (cmtpath, offset);
5292  p = Project::find_by_cmtpath (cmtpath);
5293  return p;   
5294}
5295
5296//----------------------------------------------------------
5297cmt_string Use::get_info () const
5298{   
5299  return get_package_name () + " " + (version != "" ? version : "*") +
5300    (path != "" ? " " + path : "") ;
5301  //  return get_package_name () + " " + version + (path != "" ? " " + path : "") ;
5302}
5303
5304//----------------------------------------------------------
5305/**
5306 *    Check whether @version@
5307 *    is head version as specified by CMTHEADVERSION symbol/environment variable
5308 *    or equals HEAD|head
5309 */
5310//----------------------------------------------------------
5311bool Use::is_head_version (const cmt_string& version)
5312{
5313  if (!m_head_version.is_valid ())
5314    {
5315      cmt_string s (Symbol::get_env_value ("CMTHEADVERSION"));
5316      static const cmt_string package_template = "<package>";
5317      s.replace_all (package_template, get_package_name ());
5318      static const cmt_string PACKAGE_template = "<PACKAGE>";
5319      s.replace_all (PACKAGE_template, prefix);
5320      static const cmt_string revision_template = "<revision>";
5321      s.replace_all (revision_template.c_str (), "[0-9]*");
5322      if (0 != s.size ())
5323        {
5324          if ('^' != s[0]) s = "^" + s;
5325          if ('$' != s[s.size () - 1]) s = s + "$";
5326        }
5327      else
5328        {
5329          s = "^(HEAD|head)$";
5330        }
5331      m_head_version.set (s);
5332      if (!m_head_version.is_valid ())
5333        {
5334          CmtMessage::warning
5335            (CmtError::get_error_name (CmtError::configuration_error)
5336             + ": CMTHEADVERSION regular expression invalid `" + s + "'");
5337        }
5338    }
5339
5340  return m_head_version.match (version);
5341}
Note: See TracBrowser for help on using the repository browser.