source: CMT/v1r21/source/cmt_use.cxx

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

See C.L. 425

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