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

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

See C.L. 474

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