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

Last change on this file since 550 was 550, checked in by rybkin, 14 years ago

See C.L. 435

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