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

Last change on this file since 607 was 607, checked in by rybkin, 12 years ago

See C.L. 482

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