source: CMT/v1r23/source/cmt_use.cxx

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

See C.L. 458

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