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

Last change on this file since 656 was 656, checked in by rybkin, 11 years ago

See C.L. 515

  • Property svn:eol-style set to native
File size: 136.6 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_project = 0;
1829  m_index = -1;
1830
1831  set (new_package, new_version, new_path);
1832}
1833
1834//----------------------------------------------------------
1835Use::~Use ()
1836{
1837  clear ();
1838}
1839
1840//----------------------------------------------------------
1841void Use::clear ()
1842{
1843  specified_path = "";
1844  path      = "";
1845
1846  if (m_package != 0)
1847    {
1848      m_package->remove_use (this);
1849      m_package = 0;
1850    }
1851  m_project = 0;
1852
1853  version   = "";
1854  author    = "";
1855  manager   = "";
1856  real_path = "";
1857  m_realpath = "";
1858
1859  prefix    = "";
1860  style     = mgr_style;
1861  initial_scope = ScopePublic;
1862  done      = false;
1863  discarded = false;
1864  selected  = false;
1865  m_hidden  = false;
1866  auto_imports = Unspecified;
1867
1868  includes.clear ();
1869  include_path = "";
1870  scripts.clear ();
1871  apply_patterns.clear ();
1872  ignore_patterns.clear ();
1873
1874  sub_uses.clear ();
1875  sub_use_scopes.clear ();
1876  sub_use_auto_imports.clear ();
1877
1878  requests.clear ();
1879
1880  alternate_versions.clear ();
1881  alternate_paths.clear ();
1882  alternate_is_head_versions.clear ();
1883
1884  m_head_version.clear (); 
1885
1886  version_alias = "";
1887  path_alias    = "";
1888
1889  m_located = false;
1890  m_has_native_version = false;
1891  m_index = -1;
1892}
1893
1894//----------------------------------------------------------
1895void Use::set (const cmt_string& new_package,
1896               const cmt_string& new_version,
1897               const cmt_string& new_path,
1898               const cmt_string& new_version_alias,
1899               const cmt_string& new_path_alias)
1900{
1901  clear ();
1902
1903  Package* p = Package::add (new_package);
1904
1905  m_package = p;
1906  p->add_use (this);
1907
1908  specified_path    = new_path;
1909  // specified_path.replace_all ("\\", "/");
1910
1911  specified_version = new_version;
1912  version           = new_version;
1913  path              = specified_path;
1914  Symbol::expand (path);
1915  real_path         = "";
1916  style             = mgr_style;
1917  initial_scope     = ScopePublic;
1918  done              = false;
1919  discarded         = false;
1920  Cmt::build_prefix (new_package, prefix);
1921
1922  version_alias = new_version_alias;
1923  path_alias    = new_path_alias;
1924}
1925
1926//----------------------------------------------------------
1927void Use::change_path (const cmt_string& new_path, const Project* project)
1928{
1929  //
1930  // This methods changes real_path after an actual location
1931  // where this package/version has been found.
1932  //
1933  if (Cmt::get_debug ())
1934    {
1935      cout << "|Use::change_path> path: " << new_path
1936           << " project: " << (project ? project->get_cmtpath () : "0")
1937           << " use: " << get_info () << endl;
1938    }
1939
1940  real_path = "";
1941  m_realpath = "";
1942
1943  m_project = 0;
1944
1945  if (new_path.size () != 0)
1946    //  if (new_path != "")
1947    {
1948      if ((path.size () > 0) &&
1949          (!CmtSystem::absolute_path (path)))
1950        {
1951          real_path = new_path;
1952          real_path += CmtSystem::file_separator ();
1953          real_path += path;
1954        }
1955      else
1956        {
1957          real_path = new_path;
1958        }
1959      // real_path.replace_all ("\\", "/");
1960
1961      CmtSystem::compress_path (real_path);
1962      if (!CmtSystem::realpath_ (real_path, m_realpath))
1963        {
1964          CmtError::set (CmtError::file_access_error,
1965                         "Cannot compute real path `" + real_path + "': " +
1966                         get_info ());
1967          CmtError::print ();
1968          return;
1969        }
1970    }
1971 
1972  if (project)
1973    m_project = project;
1974
1975  m_located = true;
1976
1977  if (Cmt::get_debug ())
1978    {
1979      cout << "<Use::change_path| real_path: " << real_path
1980           << " m_project: " << (m_project ? m_project->get_cmtpath () : "0")
1981           << " use: " << get_info () << endl;
1982    }
1983}
1984
1985//----------------------------------------------------------
1986int Use::reach_package (const cmt_string& from_path, const cmt_string& n_version)
1987{
1988  if (Cmt::get_debug ())
1989    {
1990      cout << "Use::reach_package> " << get_package_name ()
1991           << "(" << version << ") from " << from_path << endl;
1992      cout << "Use::reach_package> native_version required "<<n_version<<endl;
1993    }
1994   
1995  //
1996  // We try to reach a package/version starting from from_path
1997  //
1998
1999  // check if from_path is at least real
2000  if ((from_path != "") && !CmtSystem::cd (from_path)) return (0);
2001
2002  if (Cmt::get_debug ())
2003    {
2004      cout << "Use::reach_package-2>" << endl;
2005    }
2006
2007  // check in case from_path is a new search path
2008  if (from_path != real_path)
2009    {
2010      // Move to that prefix only if it is a relative path.
2011      if ((path.size () > 0) && (!CmtSystem::absolute_path (path)))
2012        {
2013          if (!CmtSystem::cd (path))
2014            {
2015              return (0);
2016            }
2017        }
2018    }
2019
2020  if (Cmt::get_debug ())
2021    {
2022      cout << "Use::reach_package-3>" << endl;
2023    }
2024
2025  // Special treatment for CMTHOME package...
2026  if (get_package_name () == CmtSystem::get_home_package ())
2027    {
2028      discarded = 1;
2029      if (!CmtSystem::test_file ("requirements"))
2030        {
2031          return (0);
2032        }
2033      else
2034        {
2035          return (1);
2036        }
2037    }
2038
2039  if (Cmt::get_debug ())
2040    {
2041      cout << "Use::reach_package-4>" << endl;
2042    }
2043
2044  // Special treatment for CMTUSERCONTEXT package...
2045  if (get_package_name () == CmtSystem::get_user_context_package ())
2046    {
2047      discarded = 1;
2048      if (!CmtSystem::test_file ("requirements"))
2049        {
2050          return (0);
2051        }
2052      else
2053        {
2054          return (1);
2055        }
2056    }
2057
2058  // Special treatment for PROJECT package...
2059  if (get_package_name () == CmtSystem::get_project_package ())
2060    {
2061      discarded = 1;
2062      if (!CmtSystem::test_file ("project"))
2063        {
2064          return (0);
2065        }
2066      else
2067        {
2068          return (1);
2069        }
2070    }
2071
2072  if (Cmt::get_debug ())
2073    {
2074      cout << "Use::reach_package-5>" << endl;
2075    }
2076
2077  // Now from_path exists, try if the package exists there
2078  if (!CmtSystem::cd (get_package_name ()))
2079    {
2080      return (0);
2081    }
2082
2083  if (Cmt::get_debug ())
2084    {
2085      cout << "Use::reach_package-6>" << endl;
2086    }
2087
2088  if (CmtSystem::test_file ("cmt/requirements"))
2089    {
2090      //      CmtSystem::cd ("cmt");
2091
2092      //      style = no_version_style;
2093      if (n_version != "")
2094        {
2095          cmt_string path ("cmt");
2096          path += CmtSystem::file_separator ();
2097          path += "native_version.cmt";       
2098          if (!CmtSystem::test_file (path)) return (0);
2099
2100          cmt_string nv;
2101          if (!nv.read (path))
2102            {
2103              CmtError::set (CmtError::file_access_error,
2104                             CmtSystem::pwd () + CmtSystem::file_separator () + path);
2105              return (0);
2106            }
2107          int pos = nv.find ('\n');
2108          if (pos != cmt_string::npos) nv.erase (pos);
2109          pos = nv.find ('\r');
2110          if (pos != cmt_string::npos) nv.erase (pos);
2111          if (Cmt::get_debug ())
2112            {
2113              cout << "Use::reach_package-6.0> native_version found " << nv << " (required " << n_version << ")" << endl;
2114            }
2115          if (nv != n_version) return (0);
2116          this->native_version   = n_version;
2117        }
2118
2119      cmt_string v;
2120      //      if (Package::get_version (v))
2121      if (Package::get_version (v, "cmt"))
2122        {
2123          CompareStatus s = compare_versions (version, v, true);
2124          if (Cmt::get_debug ())
2125            {
2126              cout << "Use::reach_package-6.1> version=" << version << " v=" << v << " s=" << s << endl;
2127            }
2128
2129          switch (s)
2130            {
2131            case IdenticalIds:
2132            case ExplicitOldMajorIdWinsAgainstWildarded:
2133            case ExplicitOldMinorIdWinsAgainstWildarded:
2134            case ExplicitOldPatchIdWinsAgainstWildarded:
2135              break;
2136            case ExplicitNewMajorIdWinsAgainstWildarded:
2137            case ExplicitNewMinorIdWinsAgainstWildarded:
2138            case NewMinorIdGreaterThanOld:
2139            case ExplicitNewPatchIdWinsAgainstWildarded:
2140            case NewPatchIdGreaterThanOld:
2141              break;
2142            case OldMajorIdGreaterThanNew:
2143            case NewMajorIdGreaterThanOld:
2144              break;
2145            case IncompatibleMajorIds:
2146              if (!is_head_version (v))
2147                return (0);
2148              break;
2149            }
2150          version = v;
2151        }
2152      else if (version == "")
2153        {
2154          version = "v0";
2155        }
2156      CmtSystem::cd ("cmt");
2157      style = cmt_style;
2158      structuring_style = without_version_directory;
2159      return (1);
2160    }
2161  else if (!CmtSystem::cd (version) || (version == ""))
2162    //  else if (!CmtSystem::cd (version))
2163    {
2164      //
2165      // The specified version cannot be found per-se
2166      // There are alternate possibilities when it contains wild cards
2167      //
2168      if ((version.find ("*") != cmt_string::npos) || (version == ""))
2169      //      if ((version == "") || (version.find ("*") != cmt_string::npos))
2170      //      if (version.find ("*") != cmt_string::npos)
2171        {
2172          static CmtSystem::cmt_string_vector versions;
2173          static cmt_string name;
2174
2175          name = ".";
2176          name += CmtSystem::file_separator ();
2177          if (version != "") name += version;
2178          else name += "*";
2179          /*
2180          if (version == "") name += "*";
2181          else name += version;
2182          */
2183          //          name += version;
2184          CmtSystem::scan_dir (name, versions);
2185          if (n_version != "")
2186            {
2187              CmtSystem::cmt_string_vector native_versions;           
2188              for (int i = 0; i < versions.size (); i++)
2189                {
2190                  cmt_string path;
2191                  if (CmtSystem::test_directory (versions[i]))
2192                    {
2193                      path  = versions[i];
2194                      path += CmtSystem::file_separator ();
2195                      path += "cmt";
2196                    }
2197                  else
2198                    {
2199                      path = "cmt";
2200                    }
2201                  path += CmtSystem::file_separator ();
2202                  path += "native_version.cmt";       
2203                                 
2204                  if (CmtSystem::test_file (path))
2205                    {
2206                      cmt_string nv;
2207
2208                      nv.read (path);
2209                      int pos = nv.find ('\n');
2210                      if (pos != cmt_string::npos) nv.erase (pos);
2211
2212                      pos = nv.find ('\r');
2213                      if (pos != cmt_string::npos) nv.erase (pos);
2214
2215                      if (nv == n_version)
2216                        {
2217                          cmt_string& name_entry = native_versions.add ();
2218
2219                          // We have found at least one
2220                          // cout << "native_version :" << n_version << " ,version: " << versions[i] << endl;
2221                          this->native_version   = n_version;
2222                          name_entry            += versions[i];
2223                        }
2224                    }                   
2225                }
2226              versions = native_versions;
2227            }
2228         
2229          int i;
2230          bool found = false;
2231         
2232          for (i = 0; i < versions.size (); i++)
2233            {
2234              const cmt_string& vers = versions[i];
2235             
2236              if (Cmt::get_debug ())
2237                {
2238                  cout << "     ... version " << vers << " exists" << endl;
2239                }
2240
2241              CmtSystem::basename (vers, name);
2242             
2243              int v;
2244              int r;
2245              int p;
2246             
2247              if (CmtSystem::is_version_directory (name, v, r, p))
2248                {
2249                  /*
2250                    This check is not sufficient !! We need to check in addition
2251                    that the selected directory is really the start of a true CMT
2252                    package (ie with either cmt/requirements or mgr/requirements below)
2253                  */
2254
2255                  cmt_string req;
2256
2257                  req = name;
2258                  req += CmtSystem::file_separator ();
2259                  req += "cmt";
2260                  req += CmtSystem::file_separator ();
2261                  req += "requirements";
2262
2263                  if (!CmtSystem::test_file (req))
2264                    {
2265                      req = name;
2266                      req += CmtSystem::file_separator ();
2267                      req += "mgr";
2268                      req += CmtSystem::file_separator ();
2269                      req += "requirements";
2270
2271                      if (!CmtSystem::test_file (req)) continue;
2272                    }
2273
2274                  cmt_string& new_v = alternate_versions.add ();
2275                  new_v = name;
2276                  cmt_string& new_p = alternate_paths.add ();
2277                  new_p = from_path;
2278                  bool& new_i = alternate_is_head_versions.add ();
2279                  new_i = is_head_version (name);
2280
2281                  found = true;
2282                }
2283            }
2284
2285              /*
2286          if (!found)
2287            {
2288              if (CmtSystem::test_file ("cmt/requirements"))
2289                {
2290                  CmtSystem::cd ("cmt");
2291                  style = no_version_style;
2292                  return (1);
2293                }
2294            }
2295              */
2296        }
2297
2298      if (Cmt::get_debug ())
2299        {
2300          cout << "  ... end of version scan" << endl;
2301        }
2302
2303      //
2304      //  We have now the list of possible alternate versions. However
2305      // we return that the expected package/version was not found (yet).
2306      //
2307
2308      return (0);
2309    }
2310
2311  if (Cmt::get_debug ())
2312    {
2313      cout << "Use::reach_package-7>" << endl;
2314    }
2315
2316  //cerr << "  ... version " << version << " exists" << endl;
2317
2318  // Now we have met the exact specified version!
2319  if (CmtSystem::test_file ("cmt/requirements"))
2320    {
2321      CmtSystem::cd ("cmt");
2322      style = cmt_style;
2323      structuring_style = with_version_directory;
2324    }
2325  else if (CmtSystem::test_file ("mgr/requirements"))
2326    {
2327      CmtSystem::cd ("mgr");
2328      style = mgr_style;
2329      structuring_style = with_version_directory;
2330    }
2331  else
2332    {
2333      return (0);
2334    }
2335
2336  if (Cmt::get_debug ())
2337    {
2338      cout << "Use::reach_package-8>" << endl;
2339    }
2340
2341  return (1);
2342}
2343
2344class UseProjectAction : public IProjectAction
2345{
2346public:
2347  UseProjectAction (Use* use, cmt_string n_version="") : m_use (use), m_found (false), native_version(n_version)
2348  {
2349  }
2350
2351  bool found () const
2352  {
2353    return (m_found);
2354  }
2355
2356  bool run (const Project& project)
2357  {
2358    const cmt_string& path = project.get_cmtpath ();
2359     
2360    m_use->alternate_versions.clear ();
2361    m_use->alternate_paths.clear ();
2362    m_use->alternate_is_head_versions.clear ();
2363
2364    if (m_use->reach_package (path, this->native_version))
2365      {
2366        if (Cmt::get_debug ())
2367          {
2368            cout << "move_to4> " << path << endl;
2369          }
2370       
2371        m_use->change_path (path, &project);
2372
2373        m_found = true;
2374
2375        return (false);
2376      }
2377    else if (m_use->alternate_versions.size () > 0)
2378      {
2379        if (m_use->select_alternate (&project)) 
2380          {
2381            if (Cmt::get_debug ())
2382              {
2383                cout << "move_to5> " << m_use->real_path << endl;
2384              }
2385
2386            m_found = true;
2387
2388            return (false);
2389          }
2390      }
2391   
2392    return (true);
2393  }
2394
2395private:
2396  Use* m_use;
2397  bool m_found;
2398  cmt_string native_version;
2399};
2400
2401//----------------------------------------------------------
2402bool Use::move_to (const cmt_string& native_version, bool curdir)
2403//bool Use::move_to (const cmt_string& native_version)
2404{
2405  if (m_located)
2406    {
2407      //
2408      // The real path where this version/package can be found
2409      // has already been resolved. We thus first go there.
2410      //
2411
2412      if (Cmt::get_debug ())
2413        {
2414          cout << "move_to1> " << real_path << endl;
2415        }
2416
2417      reach_package (real_path, native_version);
2418
2419      return (true);
2420    }
2421
2422  cmt_string expanded_path = path;
2423
2424  //
2425  // If the path specified in this use is a true absolute path,
2426  // then we search the package from there first.
2427  //
2428  if (CmtSystem::absolute_path (expanded_path))
2429    {
2430      if (reach_package (expanded_path,  native_version))
2431        {
2432          if (Cmt::get_debug ())
2433            {
2434              cout << "move_to3> " << expanded_path << endl;
2435            }
2436
2437          change_path (expanded_path);
2438
2439          return (true);
2440        }
2441      else if (alternate_versions.size () > 0)
2442        {
2443          if (select_alternate ()) 
2444            {
2445              if (Cmt::get_debug ())
2446                {
2447                  cout << "move_to5> " << real_path << endl;
2448                }             
2449
2450              return (true);
2451            }
2452        }
2453    }
2454
2455  //
2456  // Try here.
2457  //
2458  if (curdir)
2459    {
2460//   if (expanded_path == "")
2461//     {
2462//       if (reach_package ("", native_version))
2463
2464      cmt_string here = CmtSystem::pwd ();
2465
2466      if (reach_package (here,  native_version))
2467        {
2468          if (Cmt::get_debug ())
2469            {
2470              cout << "move_to2> " << expanded_path << endl;
2471            }
2472          change_path (here);
2473          return (true);
2474        }
2475      else if (alternate_versions.size () > 0)
2476        {
2477          if (select_alternate ()) 
2478            {
2479              if (Cmt::get_debug ())
2480                {
2481                  cout << "move_to5> " << real_path << endl;
2482                }
2483              return (true);
2484            }
2485        }
2486
2487      if (!CmtSystem::cd (here))
2488        {
2489          CmtError::set (CmtError::file_access_error, here);
2490        }
2491      return (false);
2492//     }
2493    } // end of curdir     
2494     
2495  //
2496  // Second try is among the CMTPATHs
2497  //
2498  UseProjectAction pa (this, native_version);
2499
2500  Project::broadcast (pa);
2501
2502  if (pa.found ()) return (true);
2503
2504  return (false);
2505}
2506
2507//----------------------------------------------------------
2508bool Use::select_alternate (const Project* project)
2509{
2510  int i;
2511
2512  int v0 = 0;
2513  int r0 = 0;
2514  int p0 = 0;
2515
2516  int v = 0;
2517  int r = 0;
2518  int p = 0;
2519
2520  int selected_index = -1;
2521
2522  for (i = 0; i < alternate_versions.size (); i++)
2523    {
2524      cmt_string& name = alternate_versions[i];
2525
2526      if (i == 0)
2527        {
2528          CmtSystem::is_version_directory (name, v0, r0, p0);
2529          selected_index = 0;
2530        }
2531      else
2532        {
2533          if (alternate_is_head_versions[selected_index] &&
2534              alternate_is_head_versions[i])
2535            {
2536              if (strcmp(name.c_str (), alternate_versions[selected_index].c_str ()) > 0)
2537                {
2538                  selected_index = i;
2539                }
2540              continue;
2541            }
2542          else if (alternate_is_head_versions[selected_index])
2543            {
2544              continue;
2545            }
2546          else if (alternate_is_head_versions[i])
2547            {
2548              selected_index = i;
2549              continue;
2550            }
2551
2552          CmtSystem::is_version_directory (name, v, r, p);
2553
2554          if (v > v0)
2555            {
2556              selected_index = i;
2557              v0 = v;
2558              r0 = r;
2559              p0 = p;
2560            }
2561          else if (v == v0)
2562            {
2563              if (r > r0)
2564                {
2565                  selected_index = i;
2566                  r0 = r;
2567                  p0 = p;
2568                }
2569              else if (r == r0)
2570                {
2571                  if (p > p0)
2572                    {
2573                      selected_index = i;
2574                      p0 = p;
2575                    }
2576                }
2577            }
2578        }
2579    }
2580
2581  if (selected_index >= 0)
2582    {
2583      if (CmtSystem::cd (alternate_paths[selected_index]))
2584        {
2585          version = alternate_versions[selected_index];
2586          if (reach_package (alternate_paths[selected_index]))
2587            {
2588              if (Cmt::get_debug ())
2589                {
2590                  cout << "select_alternate> " << alternate_paths[selected_index] << endl;
2591                }
2592
2593              change_path (alternate_paths[selected_index], project);
2594              return (true);
2595            }
2596        }
2597    }
2598
2599  return (false);
2600}
2601
2602//----------------------------------------------------------
2603bool Use::need_new (const cmt_string& path,
2604                    const cmt_string& package,
2605                    const cmt_string& version,
2606                    const cmt_string& n_version,
2607                    Use** old_use,
2608                    Use* context_use)
2609{
2610  bool new_request = add_request (path, package, version);
2611   
2612  Use& current_use = Use::current ();
2613
2614  if (package == current_use.get_package_name ())
2615    {
2616      if (Cmt::get_debug ())
2617        {
2618          cout << "  ... recursive use to current package" << endl;
2619        }
2620
2621      if (old_use != 0) *old_use = &current_use;
2622      return (false);
2623    }
2624
2625  Package* p = Package::add (package);
2626
2627  UsePtrVector& uses = p->get_uses ();
2628
2629  bool do_need_new = true;
2630  Use* found = 0;
2631  Use* registered = 0;
2632
2633  int req_v = -1;
2634  int req_r = -1;
2635  int req_p = -1;
2636
2637  CmtSystem::is_version_directory (version, req_v, req_r, req_p);
2638
2639  if (Cmt::get_debug ())
2640    {
2641      cout << "need_new> p=" << package << " v=" << version << " v=" << req_v << " r=" << req_r << " p=" << req_p << endl;
2642    }
2643
2644  bool has_wild_card = (req_v == -1) || (req_r == -1) || (req_p == -1);
2645
2646  int new_v = -1;
2647  int new_r = -1;
2648  int new_p = -1;
2649
2650  int use_index;
2651
2652  if (old_use != 0) *old_use = 0;
2653
2654  // Acquire the registered use.
2655  for (use_index = 0; use_index < uses.size (); use_index++)
2656    {
2657      Use& use = (*uses[use_index]);
2658
2659      if (use.m_index < 0) continue;
2660
2661      registered = &use;
2662
2663      break;
2664    }
2665
2666  // Make a first try with the registered use if it exists.
2667
2668  cmt_string decision;
2669
2670  if (registered != 0)
2671    {
2672      Use& use = (*registered);
2673
2674      found = &use;
2675
2676      CmtSystem::is_version_directory (use.specified_version, new_v, new_r, new_p);
2677
2678      bool use_has_wild_card = (new_v == -1) || (new_r == -1) || (new_p == -1);
2679
2680      if (has_wild_card && !use_has_wild_card)
2681        {
2682          if (Cmt::get_debug ())
2683            {
2684              cout << "  ... wildcarded request loses against existing explicit" << endl;
2685            }
2686         
2687          do_need_new = false; // We don't need a new one
2688        }
2689      else
2690        {
2691          // here either !has_wild_card or use_has_wild_card
2692
2693          if ((version == use.specified_version) &&
2694              (path == use.specified_path))
2695            {
2696             
2697              if (Cmt::get_debug ())
2698                {
2699                  cout << " ... exactly same version and path!" << endl;
2700                }             
2701              do_need_new = false; // We don't need a new one
2702              if (n_version != use.native_version)
2703                {
2704                  if (Cmt::get_debug ())
2705                    {
2706                      cout << " ... but native_version differs (" << n_version << "!=" << use.native_version << ") !" << endl; 
2707                    }
2708
2709                  do_need_new = true;   
2710                }             
2711            }
2712          else if (version != use.specified_version)
2713            {
2714              if (Cmt::get_debug ())
2715                {
2716                  cout << "requested explicit wins against existing wildcarded"
2717                       << endl;
2718                }
2719
2720              // The registered use loses against the request
2721            }
2722          else
2723            {
2724              if (Cmt::get_debug ())
2725                {
2726                  cout << "only paths differ, consider the new one."
2727                       << endl;
2728                }
2729
2730              // The registered use loses against the request
2731            }
2732        }
2733
2734
2735      //if (new_request && !Cmt::get_quiet () && (Cmt::get_action () == action_show_uses))
2736      if (new_request && !Cmt::get_quiet ())
2737        {
2738          if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
2739            {
2740              cerr << "# Required version " << version
2741                   << " of package " << package;
2742
2743              if (context_use != 0)
2744                {
2745                  cerr << " [from " << context_use->get_package_name () << "]";
2746                }
2747
2748              cerr << " incompatible with selected version " << use.version;
2749
2750              if (use.version != use.specified_version)
2751                {
2752                  cerr << " (" << use.specified_version << ")" ;
2753                }
2754
2755              cerr << endl;
2756            }
2757        }
2758
2759      if (Cmt::get_debug ())
2760        {
2761          cout << "# " << package << " " << version;
2762
2763          if (context_use != 0)
2764            {
2765              cout << " [from " << context_use->get_package_name () << "]";
2766            }
2767
2768          if (do_need_new)
2769            {
2770              cout << " > ";
2771            }
2772          else
2773            {
2774              cout << " < ";
2775            }
2776
2777          cout << use.version;
2778          if (use.version != use.specified_version)
2779            {
2780              cout << " (" << use.specified_version << ")" ;
2781            }
2782
2783          cout << " (r) ";
2784
2785          cout << endl;
2786        }
2787    }
2788
2789  if (do_need_new)
2790    {
2791      // Now try unregistered uses, since the registered one is not appropriate.
2792      // to see is any other existing use could match
2793
2794      for (use_index = 0; use_index < uses.size (); use_index++)
2795        {
2796          Use& use = (*uses[use_index]);
2797         
2798          if (use.m_index >= 0) continue;
2799         
2800          // Always save the latest found.
2801         
2802          found = &use;
2803
2804          CmtSystem::is_version_directory (use.specified_version, new_v, new_r, new_p);
2805
2806          bool use_has_wild_card = (new_v == -1) || (new_r == -1) || (new_p == -1);
2807
2808          if (has_wild_card && !use_has_wild_card)
2809            {
2810              if (Cmt::get_debug ())
2811                {
2812                  cout << "  ... requested wildcarded loses against existing explicit" << endl;
2813                }
2814             
2815              do_need_new = false; // We don't need a new one
2816            }
2817          else
2818            {
2819              // here either !has_wild_card or use_has_wild_card
2820         
2821              if ((version == use.specified_version) &&
2822                  (path == use.specified_path))
2823                {
2824                  if (Cmt::get_debug ())
2825                    {
2826                      cout << " ... exactly same version and path!" << endl;
2827                    }
2828             
2829                  do_need_new = false; // We don't need a new one
2830                  if (n_version != use.native_version)
2831                    {
2832                      if (Cmt::get_debug ())
2833                        {
2834                          cout << " ... but native_version differs (" << n_version << "!=" << use.native_version << ") !" << endl;
2835                        }
2836
2837                      do_need_new = true;   
2838                    }
2839                 
2840                }
2841              else if (version != use.specified_version)
2842                {
2843                  if (Cmt::get_debug ())
2844                    {
2845                      cout << "requested explicit wins against existing wildcarded"
2846                           << endl;
2847                    }
2848
2849                  // This use loses against the request
2850                }
2851              else
2852                {
2853                  if (Cmt::get_debug ())
2854                    {
2855                      cout << "only paths differ, consider the new one."
2856                           << endl;
2857                    }
2858
2859                  // This use loses against the request
2860                }
2861            }
2862
2863          //if (new_request && !Cmt::get_quiet () && (Cmt::get_action () == action_show_uses))
2864          if (new_request && !Cmt::get_quiet ())
2865            {
2866              if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
2867                {
2868                  cerr << "# Required version " << version
2869                       << " of package " << package;
2870
2871                  if (context_use != 0)
2872                    {
2873                      cerr << " [from " << context_use->get_package_name () << "]";
2874                    }
2875             
2876                  cerr << " incompatible with selected version " << use.version;
2877
2878                  if (use.version != use.specified_version)
2879                    {
2880                      cerr << " (" << use.specified_version << ")" ;
2881                    }
2882
2883                  cerr << endl;
2884                }
2885            }
2886
2887          if (Cmt::get_debug ())
2888            {
2889              cout << "# " << package << " " << version;
2890             
2891              if (context_use != 0)
2892                {
2893                  cout << " [from " << context_use->get_package_name () << "]";
2894                }
2895             
2896              if (do_need_new)
2897                {
2898                  cout << " > ";
2899                }
2900              else
2901                {
2902                  cout << " < ";
2903                }
2904             
2905              if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
2906                {
2907                  cout << "(incompatible) ";
2908                }
2909
2910              cout << use.version;
2911              if (use.version != use.specified_version)
2912                {
2913                  cout << " (" << use.specified_version << ")" ;
2914                }
2915              cout << endl;
2916            }
2917        }
2918    }
2919
2920  if (old_use != 0)
2921    {
2922      if (registered != 0) *old_use = registered;
2923      else *old_use = found;
2924    }
2925
2926  return (do_need_new);
2927}
2928
2929//----------------------------------------------------------
2930//
2931//  Here the version which is provided here is the specified version.
2932// It may contain wild cards or it may be simply empty.
2933//
2934//----------------------------------------------------------
2935Use* Use::create (const cmt_string& path,
2936                  const cmt_string& package,
2937                  const cmt_string& version,
2938                  const cmt_string& version_alias,
2939                  const cmt_string& path_alias,
2940                  const cmt_string& n_version)
2941{
2942  Package* p = 0;
2943
2944  p = Package::add (package);
2945
2946  UsePtrVector& vector = p->get_uses ();
2947
2948  // We first look in the database.
2949  for (int use_index = 0; use_index < vector.size (); use_index++)
2950    {
2951      Use* use = vector[use_index];
2952
2953      if ((use->specified_version == version) && 
2954          (use->specified_path == path) && use->native_version==n_version) return (use);
2955    }
2956
2957  // We now really create a new Use entry.
2958
2959  static UseVector& instances = get_instances ();
2960
2961  Use& use_object = instances.add ();
2962
2963  use_object.set (package, version, path, version_alias, path_alias);
2964
2965  return (&use_object);
2966}
2967
2968//----------------------------------------------------------
2969//  Add a use request into the database.
2970//
2971//  o If a use request already exist in the database,
2972//    check the version compatibility
2973//
2974//----------------------------------------------------------
2975Use* Use::add (const cmt_string& path,
2976               const cmt_string& package_name,
2977               const cmt_string& version,
2978               const cmt_string& version_alias,
2979               const cmt_string& path_alias,
2980               const cmt_string& native_version,
2981               Use* context_use,
2982               const State specified_auto_imports)
2983{
2984  bool do_need_new = false;
2985
2986  Use* old_use = 0;
2987  Use* use = 0;
2988
2989  do_need_new = need_new (path, package_name, version, native_version, &old_use, context_use);
2990
2991  if (Cmt::get_debug ())
2992    {
2993      if (old_use != 0 && !do_need_new)
2994        {
2995          cout << "add> old_use " << old_use->get_package_name () <<
2996            " " << old_use->version <<
2997            " " << old_use->path <<
2998            endl;
2999        }
3000    }
3001
3002  if (do_need_new)
3003    {
3004      use = create (path, package_name, version, version_alias, path_alias, native_version);
3005    }
3006  else
3007    {
3008      // Since we don't need a new Use, it means that old_use exists !
3009
3010      use = old_use;
3011      old_use = 0;
3012    }
3013
3014  if (package_name == CmtSystem::get_home_package ())
3015    {
3016      return (use);
3017    }
3018
3019  if (package_name == CmtSystem::get_user_context_package ())
3020    {
3021      return (use);
3022    }
3023
3024  if (package_name == CmtSystem::get_project_package ())
3025    {
3026      return (use);
3027    }
3028
3029  cmt_string here = CmtSystem::pwd ();
3030
3031  //
3032  // Store the specified sub_uses. Some of them may become discarded
3033  // later on.
3034  //
3035  if (context_use != 0)
3036    {
3037      context_use->sub_uses.push_back (use);
3038
3039      context_use->sub_use_scopes.push_back (context_use->get_current_scope ());
3040
3041      context_use->sub_use_auto_imports.push_back (specified_auto_imports);
3042
3043      cmt_string& request = context_use->requests.add ();
3044
3045      request = package_name;
3046      request += " ";
3047      request += version;
3048      request += " ";
3049      request += path;
3050
3051
3052      if (Cmt::get_debug ())
3053        {
3054          cout << "Use::add context(" << context_use->get_package_name () << ") "
3055               << "[u:" << package_name
3056               << " s:" << context_use->get_current_scope ()
3057               << " ai:" << specified_auto_imports
3058               << "]" << endl;
3059        }
3060    }
3061
3062  if (use == &(Use::current ())) 
3063    {
3064      return (use);
3065    }
3066
3067  /*
3068   *   Now we have a Use object. If it is a new one, we have to
3069   *    1) understand if it exists physically
3070   *    2) it is better than the old ones.
3071   *
3072   *   Here, we may have :
3073   *    1) old_use = 0
3074   *         there was no Use object before for this package
3075   *         the existing one is fine
3076   *
3077   *    2) old_use != 0
3078   *         we have created a new Use (which has to be validated)
3079   */
3080  bool found = use->move_to (native_version);
3081
3082  if (Cmt::get_debug ())
3083    {
3084      cout << "add> use [" << use << "] " << use->get_package_name () 
3085           << " " << use->version
3086           << " " << use->path
3087           << " found=" << found
3088           << " done=" << use->done
3089           << endl;
3090
3091      show_packages ();
3092    }
3093     
3094  if (!found)
3095    {
3096      CmtMessage::warning (CmtError::get_error_name (CmtError::package_not_found)
3097                           + ": " + use->get_info ()
3098                           + (native_version != "" ?
3099                              " -native_version=" + native_version : "")
3100                           + ( (context_use != 0) ?
3101                               " (requested by " + context_use->get_package_name () + ")" : "" )
3102                           );
3103      /*
3104      CmtMessage::warning ("package " + use->get_package_name ()
3105                           + " " + use->version + " " + use->path
3106                           + " not found"
3107                           + ( (context_use != 0) ?
3108                               " (requested by " + context_use->get_package_name () + ")" :
3109                               "" )
3110                           );
3111      */
3112      /*
3113      if (!Cmt::get_quiet ())
3114        {
3115          cerr << "#CMT> Warning: package " << use->get_package_name () <<
3116            " " << use->version << " " << use->path <<
3117            " not found";
3118
3119          if (context_use != 0)
3120            {
3121              cerr << " (requested by " << context_use->get_package_name () << ")";
3122            }
3123
3124          cerr << endl;
3125        }
3126      */
3127
3128      //CmtError::set (CmtError::package_not_found, use->get_package_name ());
3129      use->m_located = false;
3130      //use = 0;
3131    }
3132
3133  if ((old_use != 0) && (use != old_use))
3134    {
3135      if (Cmt::get_debug ())
3136        {
3137          cout << "There was another version of this Use. \n"
3138               << "But a new one was created due to some criteria. \n"
3139               << "Now we are going to apply the version strategy to make the final selection"
3140               << endl;
3141        }
3142
3143      /*
3144       *    There was another version of this Use.
3145       *    But a new one was created due to some criteria.
3146       *    Now we are going to apply the version strategy to make the final selection.
3147       */
3148
3149      if (Cmt::get_debug ())
3150        {
3151          cout << "select? [" << use << "] "<< use->version <<" vs old_use[" << old_use << "] "
3152               << old_use->get_package_name ()
3153               << " " << old_use->version
3154               << " " << old_use->path
3155               << endl;
3156        }
3157
3158      if (!found)
3159        {
3160          /*
3161           *  This new Use does not correspond to any physical package.
3162           *  let's simply discard it (and go back to old_use)
3163           */
3164
3165          //if (use != 0) use->discard ();
3166          use->discard ();
3167          use = old_use;
3168          if (context_use != 0)
3169            {
3170              context_use->sub_uses[context_use->sub_uses.size () - 1] = use;
3171            }
3172          found = use->move_to (native_version);
3173        }
3174      else
3175        {
3176          //
3177          //  This new version is different from the old one
3178          // thus we have to choose
3179          //
3180          bool old_use_is_head_version (use->is_head_version (old_use->version));
3181          bool use_is_head_version (use->is_head_version (use->version));
3182          Use* selected_use (old_use);
3183          if (old_use_is_head_version && use_is_head_version)
3184            {
3185              if (strcmp(use->version.c_str (), old_use->version.c_str ()) > 0)
3186                {
3187                  selected_use = use;
3188                  if (Cmt::get_debug ())
3189                    {
3190                      cout << "add> new head version " << use->version
3191                           << " wins old head version " << old_use->version
3192                           << endl;
3193                    }
3194                }
3195            }
3196          else if (old_use_is_head_version)
3197            {
3198            }
3199          else if (use_is_head_version)
3200            {
3201              selected_use = use;
3202              if (Cmt::get_debug ())
3203                {
3204                  cout << "add> new head version " << use->version
3205                       << " wins old version " << old_use->version
3206                       << endl;
3207                }
3208            }
3209          else
3210            {
3211              static BestFitSelector selector;
3212              selected_use = selector.operate (old_use, use);
3213              if (Cmt::get_debug ())
3214                {
3215                  cout << "add> operate on old version " << old_use->version
3216                       << " and new version " << use->version
3217                       << endl;
3218                }
3219            }
3220
3221          if (Cmt::get_debug ())
3222            {
3223              cout << "add> old=" << old_use << "i=" << old_use->m_index
3224                   << " new=" << use << "i=" << use->m_index
3225                   << " => selected=" << selected_use
3226                   << endl;
3227            }
3228
3229          //
3230          // Some situations managed by selector.operate happen
3231          // to fail discarding the rejected Use.
3232          //
3233          if (use != selected_use) 
3234            {
3235              use = use->set_selected_version (selected_use);
3236              if (context_use != 0)
3237                {
3238                  context_use->sub_uses[context_use->sub_uses.size () - 1] = use;
3239                }
3240            }
3241         
3242
3243          /*
3244           *   current directory is moved to the selected one
3245           */
3246          found = use->move_to (native_version);
3247        }
3248    }
3249
3250  //
3251  // The following statement is no longer considered as useful.
3252  // It is commented. But we should clarify why it was really needed!
3253  //
3254  //use->undiscard ();
3255
3256  if (found)
3257    {
3258      static UsePtrVector& uses = get_ordered_uses ();
3259
3260      bool registered = false;
3261      const Use& cu = Use::current ();
3262
3263      Package* package = Package::find (package_name);
3264
3265      //
3266      // A pointer to this new object is also added or replaced.
3267      //
3268      if ((use != &cu) && (package == cu.get_package ()))
3269        {
3270          // This is a recursive call to the current package!!
3271          registered = true;
3272          use->done = true;
3273          use->m_index = -1;
3274        }
3275      else
3276        {
3277          //
3278          // Now sort out the registration in ordered uses
3279          //
3280          //  cases:
3281          //
3282          //   use is not yet registered (m_index < 0)
3283          //     o if another use of the same package is registered,
3284          //       it must be substituted with the new one
3285          //     o otherwise create a new entry at the end (it will be sorted
3286          //       afterwards)
3287          //
3288          //   use is already registered (m_index >= 0)
3289          //     o if another use of the same package is registered,
3290          //       it must be discarded, but this may mean that
3291          //       two versions are simultaneously registered (bug?)
3292          //     o otherwise we keep it in place
3293          //
3294
3295          UsePtrVector& puses = package->get_uses ();
3296
3297          if (use->m_index >= 0) registered = true;
3298
3299          /*
3300            We look for all existing uses in that package.
3301          */
3302          for (int i = 0; i < puses.size(); i++)
3303            {
3304              Use* u = puses[i];
3305             
3306              if (Cmt::get_debug ())
3307                {
3308                  cout << "add> check registering between " << use
3309                       << ":" << use->get_package_name ()
3310                       << "(" << use->m_index << ")"
3311                       << " and " << u
3312                       << ":" << u->get_package_name () 
3313                       << "(" << u->m_index << ")"
3314                       << endl;
3315                }
3316
3317              if ((u != use) && (u->m_index >= 0))
3318                {
3319                  // Another use of that package is already registered
3320
3321                  if (Cmt::get_debug ())
3322                    {
3323                      cout << "add> Another use of that package is already registered " 
3324                           << " use(" << use->m_index << ")";
3325                      if (use->m_index >= 0)
3326                        {
3327                          cout << "[" << (uses[use->m_index])->get_package_name () << "]";
3328                        }
3329                      cout << " u(" << u->m_index << ")";
3330                      if (u->m_index >= 0)
3331                        {
3332                          cout << "[" << (uses[u->m_index])->get_package_name () << "]";
3333                        }
3334                      cout << endl;
3335                    }
3336
3337                  if (use->m_index < 0)
3338                    {
3339                      /*
3340                        the newly selected use (use) should replace the one which was registered (u)
3341                      */
3342
3343                      u->set_selected_version (use);
3344
3345                      registered = true;
3346                    }
3347                  else
3348                    {
3349                      // bug??
3350                      if (Cmt::get_debug ())
3351                        {
3352                          cout << "Duplicate entry in ordered uses" << endl;
3353                        }
3354                    }
3355                }
3356            }
3357
3358          if (Cmt::get_debug ())
3359            {
3360              cout << "add> registering completed" << endl;
3361              //show_packages ();
3362            }
3363        }
3364     
3365      if (!registered) 
3366        {
3367          if (Cmt::get_debug ())
3368            {
3369              cout << "add> We install use at the end the ordered list of uses" << endl;
3370            }
3371
3372          uses.push_back (use);
3373          use->m_index = uses.size () - 1;
3374        }
3375
3376      if (Cmt::get_debug ())
3377        {
3378          for (int use_index = 0; use_index < uses.size (); use_index++)
3379            {
3380              Use* u = (Use*) uses[use_index];
3381              cout << "  use[" << use_index << "] p=(" << u << ")" << u->get_package_name () 
3382                   << " v=" << u->version
3383                   << " discarded=" << u->discarded
3384                   << " selected=" << u->selected
3385                   << " done=" << u->done
3386                   << " index=" << u->m_index
3387                   << endl;
3388            }
3389         
3390        }
3391         
3392      if (!use->done && Cmt::get_recursive ())
3393        {
3394          use->done = true;
3395
3396          if (Cmt::get_debug ())
3397            {
3398              cout << "Parsing requirements file at " << CmtSystem::pwd () << endl;
3399            }
3400
3401          SyntaxParser::parse_requirements ("requirements", use);
3402        }
3403      else
3404        {
3405          if (Cmt::get_debug ())
3406            {
3407              cout << "Requirements file at " << CmtSystem::pwd () << " already parsed" << endl;
3408            }
3409        }
3410    }
3411
3412  CmtSystem::cd (here);
3413
3414  return (use);
3415}
3416
3417//----------------------------------------------------------
3418void Use::discard ()
3419{
3420  discarded = true;
3421}
3422
3423//----------------------------------------------------------
3424void Use::undiscard ()
3425{
3426  discarded = false;
3427}
3428
3429//----------------------------------------------------------
3430void Use::select ()
3431{
3432  selected = true;
3433}
3434
3435//----------------------------------------------------------
3436void Use::unselect ()
3437{
3438  selected = false;
3439}
3440
3441//----------------------------------------------------------
3442bool Use::is_selected ()
3443{
3444  return (selected);
3445}
3446
3447/**
3448 *    Check if the package makes use of the specified package/version
3449 *
3450 *    The seach only considers the first level of uses (thus it is
3451 *   NOT recursive)
3452 */
3453bool Use::is_client (const cmt_string& used_package,
3454                     const cmt_string& used_version)
3455{
3456  // A package is client of itself
3457
3458  Package* package = Package::find (used_package);
3459
3460  if ((get_package () == package) &&
3461      (version == used_version)) return (true);
3462
3463  if (discarded) return (false);
3464
3465  int i;
3466
3467  for (i = 0; i < sub_uses.size (); i++)
3468    {
3469      Use* use = sub_uses[i];
3470      if (use == 0) continue;
3471
3472      if ((use->get_package () == package) &&
3473          (use->version == used_version)) return (true);
3474
3475      /*
3476        if (use->is_client (used_package, used_version))
3477        {
3478        return (true);
3479        }
3480      */
3481    }
3482
3483  return (false);
3484}
3485
3486//----------------------------------------------------------
3487void Use::apply_global_patterns ()
3488{
3489  int i;
3490
3491  Pattern::PatternVector& vector = Pattern::patterns ();
3492
3493  for (i = 0; i < vector.size (); i++)
3494    {
3495      Pattern& p = vector[i];
3496
3497      if (p.global)
3498        {
3499          p.apply (this);
3500        }
3501    }
3502}
3503
3504//----------------------------------------------------------
3505void Use::set_include_path (const cmt_string& new_path)
3506{
3507  include_path = new_path;
3508}
3509
3510/**
3511 *   Compute the full real path of a found package.
3512 *   Takes the structuring style into account
3513 *
3514 *    Result is used to fill in the referenced string
3515 *    Result does NOT include the trailing file_separator
3516 */
3517void Use::get_full_path (cmt_string& s) const
3518{
3519  if (real_path == "") s = CmtSystem::pwd ();
3520  else s = real_path;
3521
3522  if (style != none_style)
3523    {
3524      s += CmtSystem::file_separator ();
3525      s += get_package_name ();
3526    }
3527 
3528  //  if (style != no_version_style)
3529  if (structuring_style == with_version_directory)
3530    {
3531      s += CmtSystem::file_separator ();
3532      s += version;
3533    }
3534}
3535
3536/**
3537 *   Compute the full real path of a found package.
3538 *   Takes the structuring style into account
3539 */
3540cmt_string Use::get_full_path () const
3541{
3542  cmt_string result;
3543
3544  get_full_path (result);
3545
3546  return (result);
3547}
3548
3549/**
3550 *   Considering a given path, try and reduce the part of it
3551 *  that corresponds to the full path of this package into its
3552 *  normal form ${<PACKAGE>ROOT}
3553 *   The argument is modified if the pattern is exactly found.
3554 */
3555void Use::reduce_path (cmt_string& s) const
3556{
3557  cmt_string pattern;
3558  get_full_path (pattern);
3559  pattern += CmtSystem::file_separator ();
3560 
3561  cmt_string replacement = "${";
3562  replacement += prefix;
3563  replacement += "ROOT}";
3564  replacement += CmtSystem::file_separator ();
3565
3566  s.replace (pattern, replacement);
3567}
3568
3569//----------------------------------------------------------
3570void Use::get_cmtpath_and_offset (cmt_string& cmtpath, cmt_string& offset) const
3571{
3572  if (get_package_name () == CmtSystem::get_project_package ())
3573    {
3574      offset = "";
3575      CmtSystem::dirname (path, cmtpath);
3576      return;
3577    }
3578  else if (get_package_name () == CmtSystem::get_home_package ())
3579    {
3580      offset = "";
3581      cmtpath = path;
3582      return;
3583    }
3584  else if (get_package_name () == CmtSystem::get_user_context_package ())
3585    {
3586      offset = "";
3587      cmtpath = path;
3588      return;
3589    }
3590
3591  cmtpath = "";
3592  offset = "";
3593
3594  const Project* p (0);
3595  if (m_project)
3596    {
3597      p = m_project;
3598      cmtpath = p->get_cmtpath ();
3599    }
3600  else
3601    {
3602      cmtpath = m_realpath.size ()
3603        ? Project::find_in_cmt_paths (m_realpath, true)
3604        : Project::find_in_cmt_paths (real_path)
3605        ;
3606      p = Project::find_by_cmtpath (cmtpath);
3607  //  const Project* p = Project::find_by_cmtpath (cmtpath);
3608    }
3609  //  if (cmtpath != "")
3610  if (p != 0)
3611    {
3612      CmtSystem::compress_path (cmtpath);
3613
3614      static const cmt_string empty_string;
3615      static const cmt_string fs = CmtSystem::file_separator ();
3616     
3617      // In case there are symlinks
3618      //      offset = real_path;
3619      //      offset.replace (cmtpath, empty_string);
3620      //cerr << "realpath_: get_cmtpath_and_offset" << endl;
3621      if (0 != m_realpath.size ())
3622        offset = m_realpath;
3623      else if (!CmtSystem::realpath_ (real_path, offset))
3624        {
3625          CmtError::set (CmtError::file_access_error,
3626                         "Cannot compute real path `" + real_path + "': " +
3627                         get_info ());
3628          CmtError::print ();
3629          return;
3630        }
3631      offset.replace (p->get_cmtpath_real (), empty_string);
3632
3633      /**
3634         try to remove this current CMTPATH entry from path.  This
3635         has a meaning when the specified path already contains an
3636         absolute path.
3637      */
3638     
3639      if (offset[0] == CmtSystem::file_separator ())
3640        {
3641          // Just in case there is a part left after removing the cmtpath entry
3642               
3643          offset.replace (fs, empty_string);
3644        }
3645    }
3646  else
3647    {
3648      offset = real_path;
3649    }
3650}
3651
3652//------------------------------------------------------------
3653bool Use::get_strategy (const cmt_string& name) const
3654{
3655  const Project* p = get_project ();
3656    /*
3657    Project::find_by_cmtpath (m_realpath.size ()
3658                              ? Project::find_in_cmt_paths (m_realpath, true)
3659                              : Project::find_in_cmt_paths (real_path)
3660                              );
3661    */
3662
3663  bool strategy;
3664
3665  if (p == 0)
3666    {
3667      static const Project::ProjectPtrVector Ordered = Project::ordered_projects ();
3668      //static const Project::ProjectVector& projects = Project::projects ();
3669
3670      if (Ordered.size () == 0) strategy = StrategyMgr::get_default_strategy (name);
3671      //if (projects.size () == 0) strategy = StrategyMgr::get_default_strategy (name);
3672      else
3673        {
3674          p = Ordered[0];
3675          //p = &(projects[0]);
3676          strategy = p->get_strategy (name);
3677        }
3678    }
3679  else
3680    {
3681      strategy = p->get_strategy (name);
3682    }
3683
3684  return (strategy);
3685}
3686
3687//----------------------------------------------------------
3688void Use::fill_includes_macro (cmt_string& buffer) const
3689{
3690  if (include_path == "")
3691    {
3692      buffer += "$(ppcmd)\"$(";
3693      buffer += get_package_name ();
3694      buffer += "_root)";
3695      buffer += CmtSystem::file_separator ();
3696      buffer += "src\" ";
3697    }
3698  else if (include_path != "none")
3699    {
3700      buffer += "$(ppcmd)\"";
3701      buffer += include_path;
3702      buffer += "\" ";
3703    }
3704 
3705  for (int i = 0; i < includes.size (); i++)
3706    {
3707      Include& incl = includes[i];
3708
3709      if (incl.name == "") continue;
3710     
3711      buffer += "$(ppcmd)\"";
3712      buffer += incl.name;
3713      buffer += "\" ";
3714    }
3715}
3716
3717//----------------------------------------------------------
3718void Use::fill_macro (cmt_string& buffer, const cmt_string& suffix) const
3719{
3720  buffer += " $(";
3721  buffer += get_package_name ();
3722  buffer += "_";
3723  buffer += suffix;
3724  buffer += ") ";
3725}
3726
3727//----------------------------------------------------------
3728void Use::fill_standard_macros (cmt_string& buffer) const
3729{
3730  static cmt_string fs = CmtSystem::file_separator ();
3731
3732  buffer = "";
3733
3734  cmt_string package_name = get_package_name ();
3735
3736  buffer += "macro ";
3737  buffer += package_name;
3738  buffer += "_tag";
3739  buffer += " \"$(tag)\"";
3740  buffer += "\n";
3741
3742  if (m_located)
3743    //  if (located ())
3744    {
3745      buffer += "macro ";
3746      buffer += prefix;
3747      buffer += "ROOT";
3748      buffer += " \"";
3749      buffer += get_full_path ();
3750      buffer += "\"";
3751      buffer += "\n";
3752
3753      buffer += "macro ";
3754      buffer += package_name;
3755      buffer += "_root";
3756      buffer += " \"";
3757      buffer += real_path;
3758      if (style != none_style)
3759        {
3760          buffer += fs;
3761          buffer += package_name;
3762        }
3763      if (structuring_style == with_version_directory)
3764        {
3765          buffer += fs;
3766          buffer += version;
3767        }
3768      buffer += "\"";
3769      buffer += "\n";
3770    }
3771
3772  if (action_setup == Cmt::get_action () &&
3773      Requirements == Cmt::get_print_mode ())
3774    {
3775      //cerr << "|Use::fill_standard_macros> Checking for " << prefix << "CONFIG" << endl;
3776      if (!discarded &&
3777          get_package_name () != "cmt_standalone" &&
3778          get_strategy ("SetupConfig"))
3779        {
3780          buffer += "macro ";
3781          buffer += prefix;
3782          buffer += "CONFIG";
3783          buffer += " \"";
3784          buffer += CmtSystem::get_cmt_config ();
3785          buffer += "\"";
3786          buffer += "\n";
3787        }
3788    }
3789
3790  buffer += "macro ";
3791  buffer += prefix;
3792  buffer += "VERSION";
3793  buffer += " \"";
3794  buffer += version;
3795  buffer += "\"";
3796  buffer += "\n";
3797
3798  cmt_string cmtpath = "";
3799  cmt_string offset = "";
3800
3801  get_cmtpath_and_offset (cmtpath, offset);
3802
3803  buffer += "macro ";
3804  buffer += package_name;
3805  buffer += "_cmtpath";
3806  buffer += " \"";
3807  buffer += cmtpath;
3808  buffer += "\"";
3809  buffer += "\n";
3810
3811  buffer += "macro ";
3812  buffer += package_name;
3813  buffer += "_offset";
3814  buffer += " \"";
3815  buffer += offset;
3816  buffer += "\"";
3817  buffer += "\n";
3818 
3819  const Project* p = m_project
3820    ? m_project
3821    : Project::find_by_cmtpath (cmtpath)
3822    ;
3823  /*
3824  const Project* p (m_project);
3825  if (!p)
3826    p = Project::find_by_cmtpath (cmtpath);
3827  */
3828
3829  buffer += "macro ";
3830  buffer += package_name;
3831  buffer += "_project";
3832  buffer += " \"";
3833  if (p != 0)
3834    {
3835      buffer += p->get_name ();
3836    }
3837  buffer += "\"";
3838  buffer += "\n";
3839
3840  buffer += "macro ";
3841  buffer += package_name;
3842  buffer += "_project_release";
3843  buffer += " \"";
3844  if (p != 0)
3845    {
3846      buffer += p->get_release ();
3847    }
3848  buffer += "\"";
3849}
3850
3851
3852//----------------------------------------------------------
3853static bool same_dirs (const cmt_string& d1, const cmt_string& d2)
3854{
3855  bool result = false;
3856
3857  cmt_string here = CmtSystem::pwd ();
3858
3859  cmt_string h1;
3860  if (CmtSystem::cd (d1)) h1 = CmtSystem::pwd ();
3861
3862  CmtSystem::cd (here);
3863
3864  cmt_string h2;
3865  if (CmtSystem::cd (d2)) h2 = CmtSystem::pwd ();
3866
3867  result = (h1 == h2);
3868
3869  CmtSystem::cd (here);
3870
3871  return (result);
3872}
3873
3874//----------------------------------------------------------
3875static bool install_library (const cmt_string& source_library_name, 
3876                             const cmt_string& dest_library_name, 
3877                             const cmt_string& cmtinstallarea, 
3878                             const cmt_string& tag, 
3879                             const cmt_string& symlinkcmd)
3880{
3881  cmt_string libname = source_library_name;
3882  cmt_string name = dest_library_name;
3883  cmt_string s;
3884  Use& current_use = Use::current ();
3885
3886  Symbol::expand (name);
3887  Symbol::expand (libname);
3888
3889  if (cmtinstallarea != "")
3890    {
3891      s = cmtinstallarea;
3892      s += CmtSystem::file_separator ();
3893      s += tag;
3894      s += CmtSystem::file_separator ();
3895      s += "lib";
3896      s += CmtSystem::file_separator ();
3897      s += name;
3898     
3899      // Now creating the reference file
3900
3901      cmt_string ref_file = s;
3902      ref_file += ".cmtref";
3903
3904      cmt_string text = libname;
3905      text += "\n";
3906
3907      Symbol::expand (ref_file);
3908      Symbol::expand (text);
3909
3910      if (CmtMessage::active (Info))
3911        cerr << "   Creating reference file " << ref_file << endl;
3912          //      if (!Cmt::get_quiet ()) cerr << "   Creating the reference file " << ref_file << endl;
3913      if (!text.write (ref_file))
3914        {
3915          CmtError::set (CmtError::file_access_error, ref_file);
3916          return false;
3917        }
3918    }
3919  else
3920    {
3921      if (current_use.style != none_style)
3922        {
3923          s = "../$(";
3924          s += current_use.get_package_name ();
3925          s += "_tag)/";
3926        }
3927      else
3928        {
3929          s = "./";
3930        }
3931      s += name;
3932    }
3933
3934  Symbol::expand (s);
3935
3936  cmt_string source;
3937  cmt_string dest;
3938
3939  CmtSystem::dirname (libname, source);
3940  CmtSystem::dirname (s, dest);
3941
3942  if (same_dirs (source, dest))
3943    {
3944      cmt_string lname;
3945      CmtSystem::basename (libname, lname);
3946      if (lname == name)
3947        return true;
3948    }
3949
3950  //if (!Cmt::get_quiet ())
3951  if (CmtMessage::active (Info))
3952    cerr << "   Symlinking " << libname << " to " << s << endl;
3953
3954  if (symlinkcmd == "")
3955    {
3956      if (!CmtSystem::create_symlink (libname, s))
3957        {
3958          CmtError::set (CmtError::file_access_error, "Cannot create symbolic link to " + libname);
3959          //CmtMessage::error ("Cannot create a symbolic link to " + libname);
3960          //      cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
3961          return (false);
3962        }
3963    }
3964  else
3965    {
3966      cmt_string cmd = symlinkcmd;
3967      cmd += " ";
3968      cmd += libname;
3969      cmd += " ";
3970      cmd += s;
3971      int status = CmtSystem::execute (cmd);
3972      if (status != 0)
3973        {
3974          CmtError::set (CmtError::execution_error, "Cannot create symbolic link to " + libname);
3975          //CmtMessage::error ("Cannot create a symbolic link to " + libname);
3976          //      cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
3977          return (false);
3978        }
3979    }
3980
3981  return (true);
3982}
3983
3984//----------------------------------------------------------
3985static bool uninstall_library (const cmt_string& source_library_name, 
3986                               const cmt_string& dest_library_name, 
3987                               const cmt_string& cmtinstallarea, 
3988                               const cmt_string& tag, 
3989                               const cmt_string& symunlinkcmd)
3990{
3991  cmt_string libname = source_library_name;
3992  cmt_string name = dest_library_name;
3993  cmt_string s;
3994  Use& current_use = Use::current ();
3995
3996  Symbol::expand (name);
3997  Symbol::expand (libname);
3998
3999  if (cmtinstallarea != "")
4000    {
4001      s = cmtinstallarea;
4002      s += CmtSystem::file_separator ();
4003      s += tag;
4004      s += CmtSystem::file_separator ();
4005      s += "lib";
4006      s += CmtSystem::file_separator ();
4007      s += name;
4008     
4009      // Now removing the reference file
4010
4011      cmt_string r = s;
4012      r += ".cmtref";
4013
4014      if (CmtMessage::active (Info))
4015        cerr << "   Removing reference file " << r << endl;
4016      if (!CmtSystem::remove_file (r))
4017        {
4018          CmtError::set (CmtError::file_access_error, r);
4019          return false;
4020        }
4021      /*
4022      if (symunlinkcmd == "")
4023        {
4024          //if (!CmtSystem::remove_file (r) && CmtSystem::test_file(r))
4025          if (!CmtSystem::remove_file (r))
4026            {
4027              CmtError::set (CmtError::file_access_error, r);
4028              return false;
4029            }
4030        }
4031      else
4032        {
4033          cmt_string cmd (symunlinkcmd);
4034          cmd += " ";
4035          cmd += r;
4036          int status = CmtSystem::execute (cmd);
4037          if (status != 0)
4038            {
4039              //                  if (status != 2) CmtError::set (CmtError::execution_error, s);
4040              CmtError::set (CmtError::execution_error, cmd);
4041            }
4042        }
4043      */
4044    }
4045  else
4046    {
4047      if (current_use.style != none_style)
4048        {
4049          s = "../$(";
4050          s += current_use.get_package_name ();
4051          s += "_tag)/";
4052        }
4053      else
4054        {
4055          s = "./";
4056        }
4057      s += name;
4058    }
4059
4060  Symbol::expand (s);
4061
4062  cmt_string source;
4063  cmt_string dest;
4064
4065  CmtSystem::dirname (libname, source);
4066  CmtSystem::dirname (s, dest);
4067
4068  if (same_dirs (source, dest))
4069    {
4070      cmt_string lname;
4071      CmtSystem::basename (libname, lname);
4072      if (lname == name)
4073        return true;
4074    }
4075
4076  //if (!Cmt::get_quiet ())
4077  if (CmtMessage::active (Info))
4078    cerr << "   Removing symlink " << s << " to " << libname << endl;
4079
4080  if (symunlinkcmd == "")
4081    {
4082      //if (!CmtSystem::remove_file (s) && CmtSystem::test_file(s))
4083      if (!CmtSystem::remove_file (s))
4084        {
4085          CmtError::set (CmtError::file_access_error, "Cannot remove symbolic link to " + libname);
4086          return (false);
4087        }
4088    }
4089  else
4090    {
4091      cmt_string cmd = symunlinkcmd;
4092      cmd += " ";
4093      cmd += s;
4094      int status = CmtSystem::execute (cmd);
4095      if (status != 0)
4096        {
4097          CmtError::set (CmtError::execution_error, "Cannot remove symbolic link to " + libname);
4098          //CmtMessage::error ("Cannot create a symbolic link to " + libname);
4099          //      cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
4100          return (false);
4101        }
4102    }
4103 
4104  return (true);
4105}
4106
4107//----------------------------------------------------------
4108/**
4109 *  This function construct absolute library path
4110 *  for libraries specified via <package>_libraries macros
4111 *  to be used by build[remove]_library_links functions,
4112 *  and class Generator build_library_links_infile function, in particular.
4113 */
4114void Use::absolute_library_path (const cmt_string& libname,
4115                                 const cmt_string& shlibsuffix, 
4116                                 CmtSystem::cmt_string_vector& paths) const
4117{
4118  if (CmtSystem::absolute_path (libname))
4119    {
4120      paths.push_back (libname);
4121      return;
4122    }
4123
4124  /**
4125   *   Here we expect that only the base name of the library
4126   *   is given : ie it should not contain the "lib" prefix,
4127   *   nor the suffix .so, nor any path prefix.
4128   *   This of course should generally correspond to a constituent name.
4129   */
4130  cmt_string libpath;
4131  if (style != none_style)
4132    {
4133      libpath = "${";
4134      libpath += prefix;
4135      libpath += "ROOT}/${";
4136      libpath += get_package_name ();
4137      libpath += "_tag}/";
4138    }
4139  else
4140    {
4141      libpath = "${";
4142      libpath += prefix;
4143      libpath += "ROOT}/";
4144    }
4145  libpath += "$(library_prefix)";
4146  libpath += libname;
4147  libpath += "$(library_suffix)";
4148  libpath += ".";
4149  libpath += shlibsuffix;
4150  paths.push_back (libpath);
4151
4152#ifdef __APPLE__
4153  if (style != none_style)
4154    {
4155      libpath = "${";
4156      libpath += prefix;
4157      libpath += "ROOT}/${";
4158      libpath += get_package_name ();
4159      libpath += "_tag}/";
4160    }
4161  else
4162    {
4163      libpath = "${";
4164      libpath += prefix;
4165      libpath += "ROOT}/";
4166    }
4167  libpath += libname;
4168  libpath += ".bundle";
4169  paths.push_back (libpath);
4170#endif
4171}
4172
4173//----------------------------------------------------------
4174/**
4175 *   Centralize the construction of library links for this Use.
4176 */
4177void Use::build_library_links (const cmt_string& cmtinstallarea, 
4178                               const cmt_string& tag, 
4179                               const cmt_string& shlibsuffix, 
4180                               const cmt_string& symlinkcmd) const
4181{
4182  if (!located ())
4183    {
4184      CmtMessage::warning ("package " + get_package_name ()
4185                           + " " + version + " " + path
4186                           + " not found");
4187      /*
4188      if (!Cmt::get_quiet ())
4189        {
4190          cerr << "# package " << get_package_name () <<
4191            " " << version << " " << path <<
4192            " not found" <<
4193            endl;
4194        }
4195      */
4196      return;
4197    }
4198
4199  cmt_string s;
4200
4201  s = get_package_name ();
4202  s += "_libraries";
4203
4204  Symbol* libraries_macro = Symbol::find (s);
4205
4206  if (libraries_macro == 0) return;
4207
4208  cmt_string libraries = libraries_macro->build_macro_value ();
4209  Symbol::expand (libraries);
4210  static CmtSystem::cmt_string_vector values;
4211
4212  CmtSystem::split (libraries, " \t", values);
4213
4214  for (int j = 0; j < values.size (); j++)
4215    {
4216      const cmt_string& library = values[j];
4217
4218      static cmt_string libname;
4219      static cmt_string name;
4220
4221      // Is it a simple name or a complete path?
4222
4223      libname = library;
4224      Symbol::expand (libname);
4225      if (0 == libname.size ()) continue;
4226
4227      CmtSystem::cmt_string_vector paths;
4228      absolute_library_path (libname,
4229                             shlibsuffix, 
4230                             paths);
4231
4232      for (int k = 0; k < paths.size (); k++)
4233        {
4234          CmtSystem::basename (paths[k], name);
4235          if (!install_library (paths[k], name, cmtinstallarea, tag, symlinkcmd))
4236            {
4237              CmtError::print ();
4238            }
4239        }
4240    }
4241}
4242//----------------------------------------------------------
4243/**
4244 *   Centralize the removal of library links for this Use.
4245 */
4246void Use::remove_library_links (const cmt_string& cmtinstallarea, 
4247                                const cmt_string& tag, 
4248                                const cmt_string& shlibsuffix, 
4249                                const cmt_string& symunlinkcmd) const
4250{
4251  if (!located ())
4252    {
4253      CmtMessage::warning ("package " + get_package_name ()
4254                           + " " + version + " " + path
4255                           + " not found");
4256      return;
4257    }
4258
4259  cmt_string s;
4260
4261  s = get_package_name ();
4262  s += "_libraries";
4263
4264  Symbol* libraries_macro = Symbol::find (s);
4265
4266  if (libraries_macro == 0) return;
4267
4268  cmt_string libraries = libraries_macro->build_macro_value ();
4269  Symbol::expand (libraries);
4270  static CmtSystem::cmt_string_vector values;
4271
4272  CmtSystem::split (libraries, " \t", values);
4273
4274  for (int j = 0; j < values.size (); j++)
4275    {
4276      const cmt_string& library = values[j];
4277
4278      static cmt_string libname;
4279      static cmt_string name;
4280
4281      // Is it a simple name or a complete path?
4282
4283      libname = library;
4284      Symbol::expand (libname);
4285      if (0 == libname.size ()) continue;
4286
4287      CmtSystem::cmt_string_vector paths;
4288      absolute_library_path (libname,
4289                             shlibsuffix, 
4290                             paths);
4291     
4292      for (int k = 0; k < paths.size (); k++)
4293        {
4294          CmtSystem::basename (paths[k], name);
4295          if (!uninstall_library (paths[k], name, cmtinstallarea, tag, symunlinkcmd))
4296            {
4297              CmtError::print ();
4298            }
4299        }
4300    }
4301}
4302
4303/**
4304 *   This function tries to get the replacement of a Use when it has
4305 *  been discarded by a better match to version constraints.
4306 */
4307Use* Use::get_selected_version ()
4308{
4309  if (!discarded) return (this);
4310
4311  Package* p = m_package;
4312
4313  Use::UsePtrVector& uses = p->get_uses ();
4314
4315  bool dbg = Cmt::get_debug ();
4316
4317  int size = uses.size ();
4318
4319  for (int i = 0; i < size; i++)
4320    {
4321      Use* u = uses[i];
4322      if (u == 0) continue;
4323      if (u->discarded) continue;
4324      if (dbg)
4325        {
4326          cout << "Use::get_selected_version> for package " << get_package_name ()
4327               << "  got a version " << u << endl;
4328        }
4329      return (u);
4330    }
4331
4332  return (0);
4333}
4334
4335/**
4336   Switching from one use to another one, (better wrt
4337   various criteria).
4338
4339   When switching, m_index and auto_imports are
4340   transfered from the un-selected to the newly selected.
4341*/
4342Use* Use::set_selected_version (Use* selected_use)
4343{
4344  if (this == selected_use) return (this);
4345
4346  static UsePtrVector& uses = get_ordered_uses ();
4347
4348  if (m_index >= 0)
4349    {
4350      // This discarded package was registered. We have to substitute
4351      // it with the new one.
4352
4353      if (Cmt::get_debug ())
4354        {
4355          cout << "set_selected_version> Replace "
4356               << get_package_name () << "(" << m_index << ")[" << this << "] with "
4357               << selected_use->get_package_name () << "(" << selected_use->m_index << ")[" << selected_use << "]" << endl;
4358        }
4359
4360      selected_use->m_index = m_index;
4361      selected_use->auto_imports = auto_imports;
4362
4363      selected_use->undiscard ();
4364
4365      m_index = -1;
4366
4367      uses[selected_use->m_index] = selected_use;
4368    }
4369
4370  discard ();
4371
4372  return (selected_use);
4373}
4374
4375//----------------------------------------------------------
4376void Use::set_auto_imports (State context_state, State specified_state,
4377                            cmt_map <Use*, bool>& visited)
4378{
4379  static int level (0);
4380  /*
4381  if (level == 0)
4382    {
4383      unselect_all ();
4384      selected = true;
4385    }
4386  */
4387  switch (context_state)
4388    {
4389    case Unspecified:
4390    case On:
4391      if (!visited.has (this) ||
4392          // revisit uses that may be turned into Off != auto_imports
4393          // via some other use(s)
4394          // policy being use has Off != auto_imports,
4395          // if it is (direct) sub-use without -no_auto_imports of
4396          // either current use or sub-use with Off != auto_imports
4397          (Off == auto_imports && Off != specified_state)
4398          )
4399        {
4400          auto_imports = specified_state;
4401          context_state = UseContext::mask_auto_imports (context_state, auto_imports);
4402        }
4403      else
4404        {
4405          return;
4406        }
4407      break;
4408    case Off:
4409      if (visited.has (this))
4410        {
4411          return;
4412        }
4413      auto_imports = context_state;
4414      break;
4415    }
4416
4417  if (Cmt::get_debug ())
4418    {
4419      cout << "Use::set_auto_imports>|";
4420      for (int i = level; i > 0; i--) cout << "-";
4421      cout << get_package_name () << "> " 
4422           << auto_imports << " -> " 
4423           << "(" << context_state << ")" << specified_state << endl;
4424    }
4425
4426  static bool yes (true);
4427  visited.add (this, yes);
4428
4429  cmt_string s;
4430  static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
4431 
4432  if (Cmt::get_debug ())
4433    {
4434      s = "Use::set_auto_imports><";
4435      for (int i = level; i > 0; i--) s += "-";
4436      s += get_package_name ();
4437      s += "|";
4438      //cout << s << endl;
4439    }
4440 
4441  level++;
4442  for (int i = 0; i < sub_uses.size (); i++)
4443  //for (int i = sub_uses.size () - 1; i >= 0; i--)
4444    {
4445      State state = sub_use_auto_imports[i];
4446      if (Cmt::get_debug ())
4447        {
4448          s += " ";
4449          s += sub_uses[i]->get_package_name ();
4450          s += "(";
4451          s += state_text[state + 1];
4452          s += ")";
4453        }
4454      if (sub_uses[i]->m_index >= 0 && !sub_uses[i]->discarded)
4455        {
4456          sub_uses[i]->set_auto_imports (context_state, state, visited);
4457        }
4458      else
4459        {
4460          if (Cmt::get_debug ())
4461            {
4462              char num[32]; sprintf (num, "%p", sub_uses[i]);
4463              char index[32]; sprintf (index, "%d", sub_uses[i]->m_index);
4464              s += "[";
4465              s += num;
4466              s += ", discarded=";
4467              s += (sub_uses[i]->discarded ? "1" : "0");
4468              s += ", m_index=";
4469              s += index;
4470              s += " : invalid]";
4471            }
4472          Use* au (find_valid (sub_uses[i]->get_package_name ()));
4473          if (au)
4474            {
4475              if (Cmt::get_debug ())
4476                {
4477                  char num[32]; sprintf (num, "%p", au);
4478                  char index[32]; sprintf (index, "%d", au->m_index);
4479                  s += "[";
4480                  s += num;
4481                  s += ", discarded=";
4482                  s += (au->discarded ? "1" : "0");
4483                  s += ", m_index=";
4484                  s += index;
4485                  s += " : valid]";
4486                }
4487              au->set_auto_imports (context_state, state, visited);
4488            }
4489          else
4490            {
4491              visited.add (sub_uses[i], yes);
4492            }
4493        }
4494    }
4495  level--;
4496
4497  if (Cmt::get_debug ())
4498    {
4499      cout << s << endl;
4500    }
4501
4502  return;
4503}
4504/*
4505void Use::set_auto_imports (State new_state)
4506{
4507  if (Cmt::get_debug ())
4508    {
4509      cout << "Use::set_auto_imports>(" << get_package_name () << ") "
4510           << auto_imports << " -> " << new_state << endl;
4511    }
4512
4513  if (auto_imports == new_state) return;
4514 
4515  State old_state = auto_imports;
4516 
4517  auto_imports = new_state;
4518
4519  // We propagate only when we switch from Off to On
4520
4521  if ((old_state == Off) && (new_state == On))
4522    {
4523      cmt_string s;
4524      static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
4525
4526      if (Cmt::get_debug ())
4527        {
4528          s = "Use::set_auto_imports>(";
4529          s += get_package_name ();
4530          s += ") ";
4531
4532          cout << s << endl;
4533        }
4534
4535      for (int i = 0; i < sub_uses.size (); i++)
4536        {
4537          Use* u = sub_uses[i];
4538          State state = sub_use_auto_imports[i];
4539         
4540          if (Cmt::get_debug ())
4541            {
4542              s += " ";
4543              s += u->get_package_name ();
4544              s += "(";
4545              s += state_text[state + 1];
4546              s += ")";
4547            }
4548
4549          if (state == Unspecified)
4550            {
4551              u->set_auto_imports (On);
4552            }
4553        }
4554         
4555      if (Cmt::get_debug ())
4556        {
4557          cout << s << endl;
4558        }
4559    }
4560}
4561*/
4562
4563//----------------------------------------------------------
4564void Use::set_native_version (bool state)
4565{
4566  m_has_native_version = state;
4567}
4568
4569bool Use::has_native_version () const
4570{
4571  return (m_has_native_version);
4572}
4573
4574Package* Use::get_package () const
4575{
4576  return (m_package);
4577}
4578
4579const cmt_string& Use::get_package_name () const
4580{
4581  static const cmt_string null = "";
4582
4583  return m_package ? m_package->get_name () : null ;
4584  /*
4585  Package* p = m_package;
4586  if (p == 0) return (null);
4587
4588  return (p->get_name ());
4589  */
4590}
4591
4592void Use::set_package_name (const cmt_string& name)
4593{
4594  Package* p = Package::add (name);
4595
4596  m_package = p;
4597  p->add_use (this);
4598}
4599
4600int Use::get_index () const
4601{
4602  return (m_index);
4603}
4604
4605//----------------------------------------------------------
4606bool Use::get_all_clients (const cmt_string& to_name)
4607{
4608  Use::UsePtrVector& uses = Use::get_ordered_uses ();
4609
4610  Use* use = Use::find (to_name);
4611
4612  if (use == 0)
4613    {
4614      //      CmtMessage::warning ("No access to " + to_name);
4615      return (false);
4616    }
4617
4618  cmt_map <cmt_string, Use*> all_clients;
4619  cmt_map <cmt_string, Use*> all_clients_ok;
4620
4621  const cmt_string& name = get_package_name ();
4622
4623  Use* me = this;
4624
4625  all_clients.add (name, me);
4626  all_clients_ok.add (name, me);
4627
4628  bool status = get_all_clients (use, to_name, all_clients, all_clients_ok); 
4629
4630  return (status);
4631}
4632
4633//----------------------------------------------------------
4634bool Use::get_all_clients (Use* to, 
4635                           const cmt_string& result, 
4636                           cmt_map <cmt_string, Use*>& all_clients, 
4637                           cmt_map <cmt_string, Use*>& all_clients_ok)
4638{
4639  if (this == to)
4640    {
4641      cout << result << endl;
4642      return (true);
4643    }
4644
4645  const cmt_string& to_name = to->get_package_name ();
4646  const cmt_string& to_version = to->version;
4647
4648  //cout << "gac> from " << get_package_name () << " to " << to_name << " -> " << result << endl;
4649
4650  if (all_clients.has (to_name))
4651    {
4652      if (all_clients_ok.has (to_name))
4653        {
4654          cout << "   ..." << result << endl;
4655          return (true);
4656        }
4657      else
4658        {
4659          return (false);
4660        }
4661    }
4662
4663  all_clients.add (to_name, to);
4664
4665  bool status = false;
4666
4667  Use::UsePtrVector& uses = Use::get_ordered_uses ();
4668  Use* use = 0;
4669
4670  for (int n = 0; n < uses.size (); ++n)
4671    {
4672      use = uses[n];
4673
4674      if (use->discarded) continue;
4675      if (use->m_hidden) continue;
4676
4677      if (!use->located ()) continue;
4678
4679      if (use == to) continue;
4680
4681      if (use->is_client (to_name, to_version))
4682        {
4683          const cmt_string& n = use->get_package_name ();
4684
4685          cmt_string r;
4686
4687          if ((use->initial_scope != ScopeUnspecified) &&
4688              (use->initial_scope != ScopePublic)) 
4689            {
4690              r += "(private)";
4691            }
4692         
4693          if (use->auto_imports == Off) r += "(no_auto_imports)";
4694
4695          r += n;
4696          r += ".";
4697          r += result;
4698
4699          //cout << "gac> " << n << " is client of " << to_name << endl;
4700
4701          if (get_all_clients (use, r, all_clients, all_clients_ok))
4702            {
4703              all_clients_ok.add (n, use);
4704              status = true;
4705            }
4706        }
4707    }
4708
4709  use = this;
4710
4711  if (use->is_client (to_name, to_version))
4712    {
4713      const cmt_string& n = use->get_package_name ();
4714     
4715      cmt_string r;
4716
4717      if ((use->initial_scope != ScopeUnspecified) &&
4718          (use->initial_scope != ScopePublic)) 
4719        {
4720          r += "(private)";
4721        }
4722     
4723      if (use->auto_imports == Off) r += "(no_auto_imports)";
4724
4725      r += n;
4726      r += ".";
4727      r += result;
4728     
4729      //cout << "gac> " << n << " is client of " << to_name << endl;
4730     
4731      if (get_all_clients (use, r, all_clients, all_clients_ok))
4732        {
4733          all_clients_ok.add (n, use);
4734          status = true;
4735        }
4736    }
4737
4738  return (status);
4739}
4740
4741/**
4742   Let's consider two packages in the use graph "this" and "to"
4743   This function finds all packages that are reached in between
4744   following all possible paths between "this" and "to"
4745
4746   Result s accumulated into "list"
4747*/
4748bool Use::get_paths (Use* to, UsePtrVector& list)
4749{
4750  bool is_in_path = false;
4751  bool cycle = false;
4752  bool already_in_path = false;
4753  bool dbg = Cmt::get_debug ();
4754
4755  static int level = 0;
4756
4757  int size = 0;
4758
4759  if (level == 0)
4760    {
4761      unselect_all ();
4762      selected = false;
4763    }
4764
4765  if (selected) 
4766    {
4767      /**
4768         If this use is already in the list, we don't duplicate the entry.
4769         (protection duplicate paths in the graph)
4770      */
4771
4772      size = list.size ();
4773
4774      for (int m = 0; m < size; m++)
4775        {
4776          Use* u = list[m];
4777          if (u == this)
4778            {
4779              if (dbg)
4780                {
4781                  for (int lll = 0; lll < level; lll++) cout << "  ";
4782                  cout << "  Use::get_paths." << level << "> try1.2 sub="
4783                       << get_package_name () << " already_in_path " << endl;
4784                }
4785             
4786              return (true);
4787            }
4788        }
4789
4790      return (false);
4791    }
4792
4793  selected = true;
4794
4795  if (dbg)
4796    {
4797      for (int lll = 0; lll < level; lll++) cout << "  ";
4798      cout << "Use::get_paths." << level << ">" << get_package_name ()
4799           << " to=" << to->get_package_name () 
4800           << " list=[";
4801
4802      for (int m = 0; m < list.size (); m++)
4803        {
4804          Use* u = list[m];
4805          cout << u->get_package_name () << " ";
4806        }
4807
4808      cout << "]" << endl;
4809    }
4810
4811  /**
4812     Now "this" is a candidate new entry in the list
4813  */
4814
4815  // First figure out whether 'to' is used by 'this'.
4816
4817  if (this->get_package_name () == to->get_package_name ())
4818    {
4819      // We've reached the goal (for the first time)
4820      is_in_path = true;
4821    }
4822  else
4823    {
4824      /**
4825         Let's scan sub_uses now
4826      */
4827      size = sub_uses.size ();
4828
4829      if (dbg)
4830        {
4831          for (int lll = 0; lll < level; lll++) cout << "  ";
4832          cout << "  Use::get_paths." << level << "> size=" << size << endl;
4833        }
4834
4835      for (int n = 0; n < size; n++)
4836        {
4837          Use* use = sub_uses[n];
4838
4839          if (use == 0) continue;
4840
4841          if (dbg)
4842            {
4843              for (int lll = 0; lll < level; lll++) cout << "  ";
4844              cout << "  Use::get_paths." << level << "> try1 sub="
4845                   << use->get_package_name () << "(" << use << ") " << use->discarded << endl;
4846            }
4847
4848          if (use->discarded)
4849            {
4850              Use* u;
4851
4852              u = use->get_selected_version ();
4853              if (u == 0) 
4854                {
4855                  /**
4856                     No way to find a valid use for this used package.
4857                     Is that a bug?
4858                     Anyway we don't pursue on that branch.
4859                  */
4860                  continue;
4861                }
4862
4863              use = u;
4864            }
4865
4866          if (dbg)
4867            {
4868              for (int lll = 0; lll < level; lll++) cout << "  ";
4869              cout << "  Use::get_paths." << level << "> try2 sub="
4870                   << use->get_package_name () << " " << use->discarded << endl;
4871            }
4872
4873          level++;
4874          bool r = use->get_paths (to, list);
4875          level--;
4876
4877          if (r)
4878            {
4879              is_in_path = true;
4880            }
4881        }
4882    }
4883
4884  if (is_in_path)
4885    {
4886      if (dbg)
4887        {
4888          for (int lll = 0; lll < level; lll++) cout << "  ";
4889          cout << "Use::get_paths." << level << "> push " << get_package_name () << endl;
4890        }
4891      list.push_back (this);
4892    }
4893
4894  return (is_in_path);
4895}
4896
4897//----------------------------------------------------------
4898void Use::show_sub_uses (cmt_map <Use*, bool>& visited,
4899                         const cmt_string& request, State specified_state,
4900                         bool skip_discarded, ostream& out)
4901//void Use::show_sub_uses (const cmt_string& request, bool skip_discarded, ostream& out)
4902{
4903  if (skip_discarded && discarded) return;
4904  if (m_hidden) return;
4905
4906  Use* current = &(Use::current ());
4907  static State context_state (auto_imports);
4908  static int level (0);
4909
4910  if (level == 0)
4911    {
4912      unselect_all ();
4913      selected = false;
4914    }
4915
4916  if (level > 0)
4917    {
4918      out << "# ";
4919      for (int n = 0; n < (level-1); n++) out << "  ";
4920
4921      if (request == "")
4922        {
4923          out << "use " << get_package_name () << " " << specified_version;
4924
4925          if (this == current) 
4926            {
4927              out << " (current)";
4928            }
4929          else
4930            {
4931              if (specified_path != "") out << " " << specified_path;
4932            }
4933        }
4934      else
4935        {
4936          out << "use " << request;
4937        }
4938
4939      if (version_alias != "")
4940        {
4941          out << " | " << version_alias << " " << path_alias;
4942        }
4943
4944      if (initial_scope == ScopeUnspecified) out << " (unspecified)";
4945      else if (initial_scope != ScopePublic) out << " (private)";
4946
4947      if (specified_state == Off) out << " (no_auto_imports)";
4948      //      if (auto_imports == Off) out << " (no_auto_imports)";
4949
4950      if (structuring_style == without_version_directory) out << " (no_version_directory)";
4951
4952      if (m_has_native_version)
4953        {
4954          cmt_string n = get_package_name ();
4955          n += "_native_version";
4956
4957          Symbol* s = Symbol::find (n);
4958          if (s != 0)
4959            {
4960              cmt_string value = s->resolve_macro_value ();
4961              out << " (native_version=" << value << ")";
4962            }
4963        }
4964
4965      out << endl;
4966    }
4967
4968  //  if (selected) return;
4969  //  selected = true;
4970
4971  State saved_context_state (context_state);
4972
4973  switch (context_state)
4974    {
4975    case Unspecified:
4976    case On:
4977      if (!visited.has (this) ||
4978          !selected)
4979        // selected == true means that
4980        // this use has been shown with its actual auto_imports
4981        // either Off != auto_imports or Off == auto_imports,
4982        // mark selected not to consider use again and thus avoid looping this way
4983        {
4984          switch (specified_state)
4985            {
4986            case Unspecified:
4987            case On:
4988              if (Off != auto_imports)
4989                {
4990                  // this path to use is informative
4991                  // want to revisit sub-uses
4992                  // to possibly find Off != auto_imports paths to them
4993                  selected = true;
4994                }
4995              break;
4996            case Off:
4997              if (Off == auto_imports)
4998                {
4999                  // this path to use is informative
5000                  // no point in revisiting sub-uses
5001                  selected = true;
5002                  if (visited.has (this)) return;
5003                }
5004              else
5005                {
5006                  // this path to use is not informative
5007                  // no point in (re)visiting sub-uses
5008                  return;
5009                }
5010              break;
5011            }
5012          context_state = UseContext::mask_auto_imports (context_state, specified_state);
5013        }
5014      else
5015        {
5016          return;
5017        }
5018      break;
5019    case Off:
5020      if (!visited.has (this) ||
5021          !selected)
5022        {
5023          if (Off == auto_imports)
5024            {
5025              // this path to use is informative
5026              // no point in revisiting sub-uses
5027              selected = true;
5028              if (visited.has (this)) return;
5029            }
5030          else
5031            {
5032              // this path to use is not informative
5033              // no point in (re)visiting sub-uses
5034              return;
5035            }
5036        }
5037      else
5038        {
5039          return;
5040        }
5041      break;
5042    }
5043
5044  static bool yes (true);
5045  visited.add (this, yes);
5046
5047  level++;
5048  for (int i = 0; i < sub_uses.size (); i++)
5049    {
5050      //if (use == 0) continue;
5051      Use* use;
5052      if (sub_uses[i]->m_index >= 0 && !sub_uses[i]->discarded)
5053        {
5054          use = sub_uses[i];
5055        }
5056      else
5057        {
5058          Use* au (find_valid (sub_uses[i]->get_package_name ()));
5059          if (au)
5060            {
5061              use = au;
5062            }
5063          else
5064            {
5065              sub_uses[i]->select ();
5066              visited.add (sub_uses[i], yes);
5067              continue;
5068            }
5069        }
5070
5071      const cmt_string& request = requests[i];
5072
5073      ScopeType saved_scope = use->initial_scope;
5074      //      State saved_state = use->auto_imports;
5075
5076      use->initial_scope = sub_use_scopes[i];
5077      //      use->auto_imports = sub_use_auto_imports[i];
5078
5079      use->show_sub_uses (visited, request, sub_use_auto_imports[i], skip_discarded, out);
5080      //use->show_sub_uses (request, skip_discarded, out);
5081
5082      use->initial_scope = saved_scope;
5083      //      use->auto_imports = saved_state;
5084    }
5085  level--;
5086
5087  context_state = saved_context_state;
5088}
5089
5090//----------------------------------------------------------
5091Use& Use::current ()
5092{
5093  static UseVector& instances = get_instances ();
5094  static Use* current_use = 0;
5095
5096  if ((current_use == 0) || (instances.size () == 0))
5097    {
5098      Use& use_object = instances.add ();
5099      current_use = &use_object;
5100    }
5101
5102  return (*current_use);
5103}
5104
5105//----------------------------------------------------------
5106const Use& Use::const_current ()
5107{
5108  const Use& use = Use::current ();
5109
5110  return (use);
5111}
5112
5113//----------------------------------------------------------
5114Use::UseVector& Use::get_instances ()
5115{
5116  static Database& db = Database::instance ();
5117  static UseVector& instances = db.all_uses ();
5118
5119  return (instances);
5120}
5121
5122//----------------------------------------------------------
5123Use::UsePtrVector& Use::get_ordered_uses ()
5124{
5125  static Database& db = Database::instance ();
5126  static UsePtrVector& uses = db.uses ();
5127
5128  return (uses);
5129}
5130
5131//----------------------------------------------------------
5132
5133//----------------------------------------------------------
5134//
5135//  Check if the specified version is better than the
5136//  current one.
5137//
5138//----------------------------------------------------------
5139Use* BestFitSelector::operate (Use* ref_use, Use* new_use)
5140{
5141  Use* selected = ref_use;
5142
5143  int ref_v = -1;
5144  int ref_r = -1;
5145  int ref_p = -1;
5146  cmt_string ref_pp;
5147
5148  int new_v = -1;
5149  int new_r = -1;
5150  int new_p = -1;
5151  cmt_string new_pp;
5152
5153  int alias_v = -1;
5154  int alias_r = -1;
5155  int alias_p = -1;
5156  cmt_string alias_pp;
5157
5158  enum { no_alias, new_has_alias, ref_has_alias } has_alias = no_alias;
5159
5160  // First analyze specified versions
5161  cmt_string ref_version = ref_use->specified_version;
5162  cmt_string new_version = new_use->specified_version;
5163
5164  CmtSystem::is_version_directory (ref_version, ref_v, ref_r, ref_p);
5165  ref_pp = ref_use->path;
5166
5167  CmtSystem::is_version_directory (new_version, new_v, new_r, new_p);
5168  new_pp = new_use->path;
5169
5170  if (new_use->version_alias != "")
5171    {
5172      has_alias = new_has_alias;
5173      CmtSystem::is_version_directory (new_use->version_alias, 
5174                                       alias_v, alias_r, alias_p);
5175      alias_pp = new_use->path_alias;
5176    }
5177  else if (ref_use->version_alias != "")
5178    {
5179      has_alias = ref_has_alias;
5180      CmtSystem::is_version_directory (ref_use->version_alias, 
5181                                       alias_v, alias_r, alias_p);
5182      alias_pp = ref_use->path_alias;
5183    }
5184
5185  ref_use->undiscard ();
5186  new_use->undiscard ();
5187
5188  if (new_v != ref_v)
5189    {
5190      if (has_alias != no_alias)
5191        {
5192          if (has_alias == new_has_alias)
5193            {
5194              new_v = alias_v;
5195              new_r = alias_r;
5196              new_p = alias_p;
5197              new_pp = alias_pp;
5198            }
5199          else if (has_alias == ref_has_alias)
5200            {
5201              ref_v = alias_v;
5202              ref_r = alias_r;
5203              ref_p = alias_p;
5204              ref_pp = alias_pp;
5205            }
5206        }
5207    }
5208
5209  bool ref_v_wildcarded = ((ref_v) == -1);
5210  bool ref_r_wildcarded = ((ref_r) == -1);
5211  bool ref_p_wildcarded = ((ref_p) == -1);
5212
5213  bool ref_v_explicit = !ref_v_wildcarded;
5214  bool ref_r_explicit = !ref_r_wildcarded;
5215  bool ref_p_explicit = !ref_p_wildcarded;
5216
5217  bool new_v_wildcarded = ((new_v) == -1);
5218  bool new_r_wildcarded = ((new_r) == -1);
5219  bool new_p_wildcarded = ((new_p) == -1);
5220
5221  bool new_v_explicit = !new_v_wildcarded;
5222  bool new_r_explicit = !new_r_wildcarded;
5223  bool new_p_explicit = !new_p_wildcarded;
5224
5225  bool verbose = (CmtSystem::getenv ("CMTVERBOSE") != "");
5226
5227  cmt_string ref_vc = ref_v_wildcarded ? "wildcarded" : "explicit";
5228  cmt_string ref_rc = ref_r_wildcarded ? "wildcarded" : "explicit";
5229  cmt_string ref_pc = ref_p_wildcarded ? "wildcarded" : "explicit";
5230 
5231  cmt_string new_vc = new_v_wildcarded ? "wildcarded" : "explicit";
5232  cmt_string new_rc = new_r_wildcarded ? "wildcarded" : "explicit";
5233  cmt_string new_pc = new_p_wildcarded ? "wildcarded" : "explicit";
5234
5235  // Now compute effective version identifiers
5236  CmtSystem::is_version_directory (ref_use->version, ref_v, ref_r, ref_p);
5237  CmtSystem::is_version_directory (new_use->version, new_v, new_r, new_p);
5238
5239  cmt_string new_selected_version = new_use->version;
5240
5241  if (new_v_explicit && ref_v_explicit && (new_v != ref_v))
5242    {
5243      /*
5244        if (verbose && !Cmt::get_quiet ())
5245        {
5246        cerr << "# Required explicit version " << new_version
5247        << " of package " << ref_use->get_package_name ()
5248        << " incompatible with selected explicit version " << ref_version
5249        << endl;
5250        }
5251
5252        CmtError::set (CmtError::version_conflict, "BestFitSelector::operate> ");
5253
5254        if (ref_use != new_use) new_use->discard ();
5255      */
5256
5257      if (new_v > ref_v)
5258        {
5259          if (verbose && !Cmt::get_quiet ())
5260            {
5261              cerr << "# Select " << new_vc << " version " << new_version
5262                   << " of package " << ref_use->get_package_name () 
5263                   << " instead of existing " << ref_vc << " " << ref_version
5264                   << endl;
5265            } 
5266         
5267          if (ref_use != new_use) ref_use->discard ();
5268          selected = new_use;
5269          selected->done = false; // Will read the new requirements
5270        }
5271    }
5272  else if (new_v_wildcarded || ref_v_wildcarded)
5273    {
5274      // at least one of ref or new is wildcarded
5275
5276      //
5277      // we plan to discard new_use, but if it was specified as explicit
5278      // and ref_use was wildcarded then new_use will win !!
5279      //
5280      // So then we'll have to understand where are the wild
5281      // cards... If they are on v or r, then we consider them.
5282      //
5283      //
5284
5285      if (ref_v_wildcarded && new_v_explicit)
5286        {
5287          if ((ref_use->real_path != new_use->real_path) ||
5288              (ref_use->version != new_use->version))
5289            {
5290              if (ref_use != new_use) ref_use->discard ();
5291              selected = new_use;
5292              selected->done = false; // Will read the new requirements
5293
5294              if (verbose && !Cmt::get_quiet ())
5295                {
5296                  cerr << "# Select explicit version " << new_version
5297                       << "(" << new_use->version << ")" 
5298                       << " of package " << ref_use->get_package_name () 
5299                       << " instead of existing wildcarded " << ref_version
5300                       << "(" << ref_use->version << ")" 
5301                       << endl;
5302                }
5303            }
5304          else
5305            {
5306              if (ref_use != new_use) new_use->discard ();
5307              //ref_use->version = new_selected_version;
5308            }
5309        }
5310      else
5311        {
5312          // ref is explicit or new is wildcarded
5313
5314          /*
5315            if (verbose && !Cmt::get_quiet ())
5316            {
5317            cerr << "# keep " << ref_vc << " version " << ref_version
5318            << " of package " << ref_use->get_package_name ()
5319            << " (ignore " << new_vc << " version " << new_version << ")"
5320            << endl;
5321            }
5322          */
5323
5324          if (ref_use != new_use) new_use->discard ();
5325        }
5326    }
5327  else if (new_r_wildcarded || ref_r_wildcarded || (new_r < ref_r))
5328    {
5329      //
5330      // we plan to discard new_use, but if it was specified as explicit
5331      // and ref_use was wildcarded then new_use will win !!
5332      //
5333      // So then we'll have to understand where are the wild
5334      // cards... If they are on v or r, then we consider them.
5335      //
5336      //
5337
5338      if (ref_r_wildcarded && new_r_explicit)
5339        {
5340          // ref has wild card and new has not => new wins
5341
5342          if ((ref_use->real_path != new_use->real_path) ||
5343              (ref_use->version != new_use->version))
5344            {
5345              if (ref_use != new_use) ref_use->discard ();
5346              selected = new_use;
5347              selected->done = false; // Will read the new requirements
5348
5349              if (verbose && !Cmt::get_quiet ())
5350                {
5351                  cerr << "# Select explicit release " << new_version
5352                       << " of package " << ref_use->get_package_name ()
5353                       << " instead of existing wildcarded " << ref_version
5354                       << endl;
5355                } 
5356            }
5357          else
5358            {
5359              // Just adapt version with new one.
5360
5361              if (ref_use != new_use) new_use->discard ();
5362              //ref_use->version = new_selected_version;
5363            }
5364        }
5365      else
5366        {
5367          /*
5368            if (verbose &&!Cmt::get_quiet ())
5369            {
5370            cerr << "# keep " << ref_rc << " release " << ref_version
5371            << " of package " << ref_use->get_package_name ()
5372            << " (ignore " << new_rc << " release " << new_version << ")"
5373            << endl;
5374            }
5375          */
5376
5377          if (ref_use != new_use) new_use->discard ();
5378        }
5379    }
5380  else if (new_r > ref_r)
5381    {
5382      if (verbose && !Cmt::get_quiet ())
5383        {
5384          cerr << "# Select " << new_rc << " release " << new_version
5385               << " of package " << ref_use->get_package_name () 
5386               << " instead of existing " << ref_rc << " " << ref_version
5387               << endl;
5388        } 
5389
5390      if (ref_use != new_use) ref_use->discard ();
5391      selected = new_use;
5392      selected->done = false; // Will read the new requirements
5393    }
5394  else if (new_p_wildcarded || ref_p_wildcarded || (new_p < ref_p))
5395    {
5396      //
5397      // we plan to discard new_use, but if it was specified as explicit
5398      // and ref_use was wildcarded then new_use will win !!
5399      //
5400
5401      if (ref_p_wildcarded && new_p_explicit)
5402        {
5403          if ((ref_use->real_path != new_use->real_path) ||
5404              (ref_use->version != new_use->version))
5405            {
5406              if (ref_use != new_use) ref_use->discard ();
5407              selected = new_use;
5408              selected->done = false; // Will read the new requirements
5409
5410              if (verbose && !Cmt::get_quiet ())
5411                {
5412                  cerr << "# Select explicit patch " << new_version
5413                       << " of package " << ref_use->get_package_name () 
5414                       << " instead of existing wildcarded " << ref_version
5415                       << endl;
5416                }
5417            }
5418          else
5419            {
5420              if (ref_use != new_use) new_use->discard ();
5421              ref_use->version = new_selected_version;
5422            }
5423        }
5424      else
5425        {
5426          /*
5427            if (verbose && !Cmt::get_quiet ())
5428            {
5429            cerr << "# keep " << ref_pc << " patch " << ref_version
5430            << " [" << ref_use->specified_version << "]"
5431            << " of package " << ref_use->get_package_name ()
5432            << " (ignore " << new_pc << " version " << new_version << ")"
5433            << " [" << new_use->specified_version << "]"
5434            << endl;
5435            }
5436          */
5437
5438          if (ref_use != new_use) new_use->discard ();
5439        }
5440    }
5441  else if (new_p > ref_p)
5442    {
5443      if (verbose && !Cmt::get_quiet ())
5444        {
5445          cerr << "# Select " << new_pc << " patch " << new_version
5446               << " of package " << ref_use->get_package_name () 
5447               << " instead of existing " << ref_pc << " " << ref_version
5448               << endl;
5449        }
5450
5451      if (ref_use != new_use) ref_use->discard ();
5452      selected = new_use;
5453      selected->done = false; // Will read the new requirements
5454    }
5455  else if (new_pp != ref_pp) // same version-r-p but from different path
5456    {
5457      if (ref_use != new_use) ref_use->discard ();
5458      selected = new_use;
5459      selected->done = false; // Will read the new requirements
5460    }
5461
5462  return (selected);
5463}
5464
5465
5466//----------------------------------------------------------
5467class VersionReader : public Awk
5468{
5469public:
5470
5471  VersionReader ()
5472  {
5473  }
5474 
5475  const cmt_string& get_version () const
5476  {
5477    return (m_version);
5478  }
5479 
5480  void filter (const cmt_string& line)
5481  {
5482    if (0 == line.size () ||
5483        line[0] == '#') return;
5484    CmtSystem::cmt_string_vector words;
5485    CmtSystem::split (line, " \t", words);
5486    if (words[0] == "version")
5487      {
5488        m_version = words[1];
5489      }
5490  }
5491 
5492private:
5493  cmt_string m_version;
5494};
5495
5496//----------------------------------------------------------
5497class PackageReader : public Awk
5498{
5499public:
5500
5501  PackageReader ()
5502  {
5503  }
5504 
5505  const cmt_string& get_package () const
5506  {
5507    return (m_package);
5508  }
5509 
5510  void filter (const cmt_string& line)
5511  {
5512    if (0 == line.size () ||
5513        line[0] == '#') return;
5514    CmtSystem::cmt_string_vector words;
5515    CmtSystem::split (line, " \t", words);
5516    if (words[0] == "package")
5517      {
5518        m_package = words[1];
5519      }
5520  }
5521 
5522private:
5523  cmt_string m_package;
5524};
5525
5526//----------------------------------------------------------
5527Package* Package::find (const cmt_string& name)
5528{
5529  static PackageMap& PackageMap = package_map ();
5530
5531  Package* result = 0;
5532
5533  result = PackageMap.find (name);
5534
5535  return (result);
5536}
5537
5538//----------------------------------------------------------
5539Package* Package::add (const cmt_string& name)
5540{
5541  static PackageVector& Packages = packages ();
5542  static PackageMap& PackageMap = package_map ();
5543
5544  {
5545    Package* package;
5546
5547    package = find (name);
5548    if (package != 0) return (package);
5549  }
5550
5551  Package& package = Packages.add ();
5552  PackageMap.add (name, package);
5553
5554  package.m_name = name;
5555
5556  if (name == "CMT")
5557    {
5558      package.m_is_cmt = true;
5559    }
5560  else if (name == "methods")
5561    {
5562      package.m_is_cmt = true;
5563    }
5564
5565  if (Cmt::get_debug ())
5566    {
5567      cout << "Package::add (" << name << ")" << endl;
5568    }
5569
5570  return (&package);
5571}
5572
5573//----------------------------------------------------------
5574Package::PackageVector& Package::packages ()
5575{
5576  static Database& db = Database::instance ();
5577  static PackageVector& Packages = db.packages ();
5578
5579  return (Packages);
5580}
5581
5582//----------------------------------------------------------
5583Package::PackageMap& Package::package_map ()
5584{
5585  static Database& db = Database::instance ();
5586  static PackageMap& PackageMap = db.package_map ();
5587
5588  return (PackageMap);
5589}
5590
5591//----------------------------------------------------------
5592void Package::clear_all ()
5593{
5594  static PackageVector& Packages = packages ();
5595  static PackageMap& PackageMap = package_map ();
5596
5597  PackageMap.clear ();
5598  Packages.clear ();
5599}
5600
5601//----------------------------------------------------------
5602bool Package::get_version (cmt_string& version, const cmt_string& path)
5603{
5604  cmt_string version_file = path;
5605  version_file += CmtSystem::file_separator ();
5606  version_file += get_version_file_name ();
5607  if (CmtSystem::test_file (version_file))
5608    {
5609      cmt_string v;
5610      if (v.read (version_file))
5611        {
5612          int pos;
5613          pos = v.find ('\n');
5614          if (pos != cmt_string::npos) v.erase (pos);
5615          pos = v.find ('\r');
5616          if (pos != cmt_string::npos) v.erase (pos);
5617          if (v != "")
5618            {
5619              version = v;
5620              return true;
5621            }
5622        }
5623      else
5624        {
5625          CmtMessage::warning ("Could not read `" + version_file + "'.");
5626        }
5627    }
5628
5629  version_file = path;
5630  version_file += CmtSystem::file_separator ();
5631  version_file += "requirements";
5632  cmt_string text;
5633  if (text.read (version_file))
5634    {
5635      VersionReader reader;
5636      reader.run (text);
5637      cmt_string v = reader.get_version ();
5638      if (v != "")
5639        {
5640          version = v;
5641          return true;
5642        }
5643    }
5644  else
5645    {
5646      CmtMessage::warning ("Could not read `" + version_file + "'.");
5647    }
5648
5649  return false;
5650}
5651
5652//----------------------------------------------------------
5653const cmt_string& Package::get_version_file_name ()
5654{
5655  static const cmt_string name = "version.cmt";
5656
5657  return (name);
5658}
5659
5660//----------------------------------------------------------
5661bool Package::get_name (cmt_string& name, const cmt_string& path)
5662{
5663  cmt_string name_file = path;
5664  name_file += CmtSystem::file_separator ();
5665  name_file += "requirements";
5666  cmt_string text;
5667  if (text.read (name_file))
5668    {
5669      PackageReader reader;
5670      reader.run (text);
5671      cmt_string v = reader.get_package ();
5672      if (v != "")
5673        {
5674          name = v;
5675          return true;
5676        }
5677    }
5678  else
5679    {
5680      CmtMessage::warning ("Could not read `" + name_file + "'.");
5681    }
5682
5683  return false;
5684}
5685
5686//----------------------------------------------------------
5687Package::Package () : m_is_cmt (false)
5688{
5689  if (Cmt::get_debug ())
5690    {
5691      cout << "Package::Package" << endl;
5692    }
5693}
5694
5695//----------------------------------------------------------
5696Package::~Package ()
5697{
5698  m_name = "";
5699}
5700
5701//----------------------------------------------------------
5702const cmt_string& Package::get_name () const
5703{
5704  return (m_name);
5705}
5706
5707//----------------------------------------------------------
5708void Package::add_use (Use* use)
5709{
5710  for (int i = 0; i < m_uses.size (); i++)
5711    {
5712      Use* u = m_uses[i];
5713      if (u == use) return;
5714    }
5715
5716  m_uses.push_back (use);
5717}
5718
5719//----------------------------------------------------------
5720void Package::remove_use (Use* use)
5721{
5722  if (Cmt::get_debug ())
5723    {
5724      cout << "Package::remove_use (" << use->get_package_name () << ")" << endl;
5725      cout << "  name=" << m_name
5726           << " uses=" << m_uses.size () << endl;
5727    }
5728
5729  Use::UsePtrVector temp;
5730
5731  temp = m_uses;
5732
5733  m_uses.clear ();
5734
5735  for (int i = 0; i < temp.size (); i++)
5736    {
5737      Use* u = temp[i];
5738      if (u != use)
5739        {
5740          m_uses.push_back (u);
5741        }
5742    }
5743}
5744
5745//----------------------------------------------------------
5746Use::UsePtrVector& Package::get_uses ()
5747{
5748  return (m_uses);
5749}
5750
5751//----------------------------------------------------------
5752bool Package::is_cmt ()
5753{
5754  return (m_is_cmt);
5755}
5756
5757//----------------------------------------------------------
5758static void show_packages ()
5759{
5760  Package::PackageVector& vector = Package::packages ();
5761
5762  int i;
5763  int j;
5764
5765  cout << "### Packages: ";
5766  for (i = 0; i < vector.size (); i++)
5767    {
5768      Package& p = vector[i];
5769      cout << p.get_name () << "[";
5770      Use::UsePtrVector& uses = p.get_uses ();
5771      for (j = 0; j < uses.size (); j++)
5772        {
5773          Use* u = uses[j];
5774          cout << u << ",";
5775        }
5776
5777      cout << "] ";
5778    }
5779  cout << endl;
5780
5781  {
5782    static Use::UsePtrVector& uses = Use::get_ordered_uses ();
5783
5784    cout << "### Uses: ";
5785    for (i = 0; i < uses.size (); i++)
5786      {
5787        Use* u = uses[i];
5788        cout << "[" << u << "]" << u->get_package_name () << " ";
5789      }
5790  }
5791
5792  cout << endl;
5793}
5794
5795//----------------------------------------------------------
5796const Project* Use::get_project () const
5797{   
5798  if (m_project)
5799    return m_project;
5800
5801  return Project::find_by_cmtpath (m_realpath.size ()
5802                                   ? Project::find_in_cmt_paths (m_realpath, true)
5803                                   : Project::find_in_cmt_paths (real_path)
5804                                   );
5805  /*
5806  cmt_string cmtpath = m_realpath.size ()
5807    ? Project::find_in_cmt_paths (m_realpath, true)
5808    : Project::find_in_cmt_paths (real_path)
5809    ;
5810  return Project::find_by_cmtpath (cmtpath);
5811  */
5812  /*
5813  Project* p;
5814  cmt_string cmtpath = "";
5815  cmt_string offset  = "";   
5816  get_cmtpath_and_offset (cmtpath, offset);
5817  p = Project::find_by_cmtpath (cmtpath);
5818  return p;   
5819  */
5820}
5821
5822//----------------------------------------------------------
5823cmt_string Use::get_info () const
5824{   
5825  return get_package_name () + " " + (version != "" ? version : "*") +
5826    (path != "" ? " " + path : "") ;
5827  //  return get_package_name () + " " + version + (path != "" ? " " + path : "") ;
5828}
5829
5830//----------------------------------------------------------
5831/**
5832 *    Check whether @version@
5833 *    is head version as specified by CMTHEADVERSION symbol/environment variable
5834 *    or equals HEAD|head
5835 */
5836//----------------------------------------------------------
5837bool Use::is_head_version (const cmt_string& version)
5838{
5839  if (!m_head_version.is_valid ())
5840    {
5841      cmt_string s (Symbol::get_env_value ("CMTHEADVERSION"));
5842      static const cmt_string package_template = "<package>";
5843      s.replace_all (package_template, get_package_name ());
5844      static const cmt_string PACKAGE_template = "<PACKAGE>";
5845      s.replace_all (PACKAGE_template, prefix);
5846      static const cmt_string revision_template = "<revision>";
5847      s.replace_all (revision_template.c_str (), "[0-9]*");
5848      if (0 != s.size ())
5849        {
5850          if ('^' != s[0]) s = "^" + s;
5851          if ('$' != s[s.size () - 1]) s = s + "$";
5852        }
5853      else
5854        {
5855          s = "^(HEAD|head)$";
5856        }
5857      m_head_version.set (s);
5858      if (!m_head_version.is_valid ())
5859        {
5860          CmtMessage::warning
5861            (CmtError::get_error_name (CmtError::configuration_error)
5862             + ": CMTHEADVERSION regular expression invalid `" + s + "'");
5863        }
5864    }
5865
5866  return m_head_version.match (version);
5867}
Note: See TracBrowser for help on using the repository browser.