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

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

See C.L. 511

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