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

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

See C.L. 483

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