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

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

See C.L. 522

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