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

Last change on this file since 669 was 669, checked in by rybkin, 10 years ago

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