source: CMT/v1r25-branch/source/cmt_use.cxx

Last change on this file was 680, checked in by rybkin, 8 years ago

merge -r 670:679 HEAD

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