source: CMT/v1r18p20061003/source/cmt_project.cxx

Last change on this file was 151, checked in by arnault, 18 years ago

Suppress some warnings see CL 298

  • Property svn:eol-style set to native
File size: 48.4 KB
Line 
1//-----------------------------------------------------------
2// Copyright Christian Arnault LAL-Orsay CNRS
3// arnault@lal.in2p3.fr
4// See the complete license in cmt_license.txt "http://www.cecill.info".
5//-----------------------------------------------------------
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <ctype.h>
11
12#include "cmt_project.h"
13#include "cmt_database.h"
14#include "cmt_system.h"
15#include "cmt_awk.h"
16#include "cmt_syntax.h"
17#include "cmt_tag.h"
18#include "cmt_error.h"
19
20class ProjectReader : public Awk
21{
22public:
23
24  ProjectReader ()
25  {
26  }
27 
28  const cmt_string& get_project_name () const
29  {
30    return (m_project);
31  }
32 
33  void filter (const cmt_string& line)
34  {
35    CmtSystem::cmt_string_vector words;
36    CmtSystem::split (line, " \t", words);
37    if (words[0] == "project")
38      {
39        m_project = words[1];
40      }
41  }
42 
43private:
44  cmt_string m_project;
45};
46
47class ProjectPatcher : public Awk
48{
49public:
50
51  ProjectPatcher (const cmt_string& p) : m_project (p)
52  {
53  }
54
55  void commit ()
56  {
57    m_output.write (Project::get_project_file_name ());
58  }
59
60  void filter (const cmt_string& line)
61  {
62    CmtSystem::cmt_string_vector words;
63    CmtSystem::split (line, " \t", words);
64    if (words[0] == "project")
65      {
66        m_output += "project ";
67        m_output += m_project;
68      }
69    else
70      {
71        m_output += line;
72      }
73
74    m_output += "\n";
75  }
76 
77private:
78  cmt_string m_output;
79  const cmt_string& m_project;
80};
81
82IProjectFactory& ProjectFactory::instance ()
83{
84  static ProjectFactory me;
85 
86  return (me);
87}
88
89void ProjectFactory::reset ()
90{
91  Project::clear_all ();
92}
93
94static bool get_release_from_path (const CmtSystem::cmt_string_vector& items, 
95                                   const cmt_string& path, 
96                                   const cmt_string& name, 
97                                   cmt_string& real_name, 
98                                   cmt_string& release)
99{
100  bool result = false;
101
102  release = "";
103  real_name = "";
104
105  cmt_string p = path;
106
107  if ((items.size () == 0) && (name == ""))
108    {
109      // There is no CMTPROJECTPATH and no expected project name.
110      // We have no way to find a project structure
111      // So we only expect a 2-level structure.
112
113      CmtSystem::basename (p, release);
114      CmtSystem::dirname (p, p);
115      CmtSystem::basename (p, real_name);
116     
117      return (false);
118    }
119
120  for (;;)
121    {
122      if (p == "")
123        {
124          // Protection: we found no matching project name
125          // and path was outside any CMTPROJECTPATH
126
127          p = path;
128
129          CmtSystem::basename (p, release);
130          CmtSystem::dirname (p, p);
131          CmtSystem::basename (p, real_name);
132
133          return (false);
134        }
135
136      cmt_string n;
137
138      CmtSystem::basename (p, n);
139      CmtSystem::dirname (p, p);
140
141      if (n == name)
142        {
143          real_name = name;
144          result = true;
145          break;
146        }
147
148      CmtSystem::basename (p, real_name);
149
150      for (int i = 0; i < items.size (); i++)
151        {
152          const cmt_string& item = items[i];
153          if (p == item)
154            {
155              // We have reached an item of CMTPROJECTPATH, no need to continue
156              return (false);
157            }
158        }
159
160      if (release == "")
161        {
162          release = n;
163        }
164      else
165        {
166          cmt_string r;
167
168          r = n;
169          r += CmtSystem::file_separator ();
170          r += release;
171          release = r;
172        }
173    }
174
175  //cerr << "$CMT> GRFP> path=" << path << " name=" << name << " rel=" << release << endl;
176
177  return (result);
178}
179 
180
181/*
182  Every new CMTPATH entry becomes associated with a dedicated PROJECT
183  This function will understand this new entry to CMTPATH and understand it:
184  - it can correspond to an existing project (ie already declared)
185  - it's a new project
186     - then it tries to read and parse its project file
187 */
188Project* ProjectFactory::create_project (const cmt_string& specified_name,
189                                         const cmt_string& path,
190                                         const cmt_string& source,
191                                         Project* parent)
192{
193  cmt_string compressed_path = path;
194  CmtSystem::compress_path (compressed_path);
195  bool specify_name = (specified_name != "");
196
197  if (Cmt::get_debug ())
198    {
199      cout << "Creating project " << path << " with parent " << ((parent==0)? "0" : parent->get_name ()) << endl;
200      Project::show_all ();
201    }
202
203  cmt_string sep;
204  sep = CmtSystem::path_separator ();
205
206  cmt_string cmtprojectpath = Symbol::get_env_value ("CMTPROJECTPATH"); 
207  CmtSystem::cmt_string_vector items;
208  CmtSystem::split (cmtprojectpath, sep, items);
209
210  cmt_string here = CmtSystem::pwd ();
211  if (!CmtSystem::cd (compressed_path)) return (0);
212  cmt_string pwd = CmtSystem::pwd ();
213
214  static Project::ProjectVector& Projects = Project::projects ();
215
216  int i;
217 
218  for (i = 0; i < Projects.size (); i++)
219    {
220      Project& p = Projects[i];
221     
222      if ((p.get_cmtpath () == compressed_path) ||
223          (p.get_cmtpath_pwd () == pwd) ||
224          (specify_name && (p.get_name () == specified_name)))
225        {
226          cmt_string r;
227          cmt_string n;
228
229          get_release_from_path (items, compressed_path, p.get_name (), n, r);
230
231          if (r != p.get_release ())
232            {
233              cerr << "#CMT> Project " << p.get_name ()
234                   << " requested with conflicting releases " << p.get_release () << " and " << r << endl;
235              CmtError::set (CmtError::project_release_conflict, p.get_name ());
236            }
237 
238          if (parent != 0)
239            {
240              p.add_parent (parent);
241              parent->add_child (&p);
242
243              // Since p is a new parent, we should propagate the settings UP.
244
245              parent->update_strategies_from_children ();
246            }
247
248          CmtSystem::cd (here);
249          return (&p);
250        }
251    }
252
253
254  Project* project = 0;
255  Project* cmt = 0;
256 
257  bool is_current = false;
258 
259  cmt_string name = specified_name;
260  cmt_string project_name;
261  cmt_string release;
262
263  //
264  // Figure out if this is the current project
265  //
266  if (here.find (pwd) == 0) is_current = true;
267
268  cmt_string text;
269
270  /*
271    Now Figure out the project name from the project file
272       or does not specify the project name
273   */
274  bool has_project_file = false;
275
276  if (CmtSystem::cd ("cmt") && CmtSystem::test_file (Project::get_project_file_name ()))
277    {
278      has_project_file = true;
279      text.read (Project::get_project_file_name ());
280
281      ProjectReader reader;
282
283      reader.run (text);
284
285      project_name = reader.get_project_name ();
286    }
287
288  enum
289    {
290      without_project_file   = 0x01,
291      with_project_file      = 0x02,
292      without_project_name   = 0x04,
293      with_project_name      = 0x08,
294      without_specified_name = 0x10,
295      with_specified_name    = 0x20,
296      names_mismatch         = 0x40,
297      names_match            = 0x80
298    };
299
300  int status = ((has_project_file) ? with_project_file : without_project_file) |
301    ((has_project_file && (project_name != "")) ? with_project_name : without_project_name) |
302    ((specify_name) ? with_specified_name : without_specified_name) |
303    ((specify_name && has_project_file && (project_name == specified_name)) ? names_match : names_mismatch);
304
305  if (source == "default path")
306    {
307      name = "CMT";
308    }
309  else
310    {
311      cmt_string n;
312         
313      switch (status)
314        {
315        case with_project_file | without_project_name | without_specified_name | names_mismatch:
316
317          // The project is neither specified from the caller nor from the project file
318
319          /*
320            if (!Cmt::get_quiet ())
321            {
322            cerr << "#CMT> Warning: project name unspecified in project file." << endl;
323            }
324          */
325     
326          get_release_from_path (items, compressed_path, "", name, release);
327
328          break;
329         
330        case with_project_file | without_project_name | with_specified_name | names_mismatch:
331         
332          // The name is only specified from the caller
333          // find this specified name in the path
334         
335          if (get_release_from_path (items, compressed_path, specified_name, name, release))
336            {
337              // The specified name has been found from the path.
338              // We believe in the release spec.
339            }
340          else
341            {
342              // The specified name is not in the path.
343              /*
344              if (!Cmt::get_quiet ())
345                {
346                  cerr << "#CMT> Warning: specified project name "
347                       << specified_name
348                       << " from the caller does not match path." << endl;
349                }
350              */
351              name = specified_name;
352            }
353         
354          break;
355         
356        case with_project_file | with_project_name | with_specified_name | names_match:
357         
358          // We have a double specification: from the caller and from the project file.
359          // And both specifications are consistent. 
360         
361          if (get_release_from_path (items, compressed_path, specified_name, name, release))
362            {
363              // The specified name has been found from the path.
364              // We believe in the release spec.
365            }
366          else
367            {
368              // The specified name is not in the path.
369              /*
370              if (!Cmt::get_quiet ())
371                {
372                  cerr << "#CMT> Warning: specified project name "
373                       << specified_name
374                       << " from project file and from caller does not match path." << endl;
375                }
376              */
377              name = specified_name;
378            }
379         
380          break;
381         
382        case with_project_file | with_project_name | with_specified_name | names_mismatch:
383         
384          // We have a double specification: from the caller and from the project file.
385          // Specifications are inconsistent!!
386         
387          /*
388          if (!Cmt::get_quiet ())
389            {
390              cerr << "#CMT> Warning: specified project name "
391                   << specified_name
392                   << " inconsistent with name "
393                   << project_name
394                   << " from project file." << endl;
395            }
396          */
397         
398          if (get_release_from_path (items, compressed_path, specified_name, n, release))
399            {
400              // name from caller wins.
401            }
402          else if (get_release_from_path (items, compressed_path, project_name, name, release))
403            {
404              // name from project file wins.
405            }
406          else
407            {
408              // The specified name is not in the path.
409             
410              if (!Cmt::get_quiet ())
411                {
412                  cerr << "#CMT> Warning: none of specified project names "
413                       << specified_name
414                       << " from graph and "
415                       << project_name
416                       << " from project file match path." << endl;
417                }
418
419              name = specified_name;
420            }
421         
422          break;
423         
424        case with_project_file | with_project_name | without_specified_name | names_mismatch:
425         
426          // Project name is specified in the project file but not from the caller.
427         
428          if (get_release_from_path (items, compressed_path, project_name, name, release))
429            {
430              // The specified name has been found from the path.
431              // We believe in the release spec.
432
433            }
434          else
435            {
436              // The specified name is not in the path.
437
438              /*
439              if (!Cmt::get_quiet ())
440                {
441                  cerr << "#CMT> Warning: specified project name "
442                       << project_name
443                       << " from project file does not match path." << endl;
444                }
445              */
446
447              name = project_name;
448            }
449         
450          break;
451         
452        case without_project_file | without_project_name | without_specified_name | names_mismatch:
453         
454          // The project is not specified from the caller and there is no project file
455          // This corresponds to the backward compatibility
456          // For the moment, assume /name/release/ structure where release is one level only
457         
458          /*
459            if (!Cmt::get_quiet ())
460            {
461            cerr << "#CMT> Warning: project name is not specified "
462            << " (no project file)." << endl;
463            }
464          */
465         
466          CmtSystem::basename (compressed_path, release);
467          CmtSystem::dirname (compressed_path, name);
468          CmtSystem::basename (name, name);
469
470          if (name == "")
471            {
472              name = release;
473              release = "";
474            }
475         
476          break;
477         
478        case without_project_file | without_project_name | with_specified_name | names_mismatch:
479         
480          // The name is only specified from the caller
481          // find this specified name in the path
482         
483          if (get_release_from_path (items, compressed_path, specified_name, name, release))
484            {
485              // The specified name has been found from the path.
486              // We believe in the release spec.
487            }
488          else
489            {
490              // The specified name is not in the path.
491              /*
492              if (!Cmt::get_quiet ())
493                {
494                  cerr << "#CMT> Warning: specified project name "
495                       << specified_name
496                       << " from project graph does not match path." << endl;
497                }
498              */
499              name = specified_name;
500            }
501         
502          break;
503        }
504    }
505
506  if (name == "")
507    {
508      name = "Project";
509    }
510
511  project = Project::add (name, release);
512     
513  if (parent != 0)
514    {
515      project->add_parent (parent);
516      parent->add_child (project);
517
518      // Since project is a new child, we should propagate the settings UP.
519
520      parent->update_strategies_from_children ();
521    }
522  else
523    {
524      // this project has no parent thus it should become the top project.
525      // Let's look for all projects without parent.
526      // they will become children of this project.
527
528      for (i = 0; i < Projects.size (); i++)
529        {
530          Project* p = &(Projects[i]);
531          if (p->get_name () == name) continue;
532          if (!p->has_parents ())
533            {
534              project->add_child (p);
535              p->add_parent (project);
536            }
537        }
538
539      // Since project is a new parent, we should upgrade its settings
540
541      project->update_strategies_from_children ();
542    }
543
544  if (source == "default path")
545    {
546      cmt = project;
547      is_current = false;
548    }
549
550  project->set_cmtpath (compressed_path);
551  project->set_cmtpath_pwd (pwd);
552  project->set_cmtpath_source (source);
553
554  if (is_current)
555    {
556      //
557      // The current project defines a tag with its name
558      //
559
560      Tag* tag;
561     
562      tag = Tag::add (project->get_name (), PriorityConfig, "PROJECT", 0);
563      tag->mark ();
564    }
565
566  if (text != "")
567    {
568      // Last step is to parse the project file
569
570      if (Cmt::get_debug ())
571        {
572          cout << "About to parse project file [" << text << "]" << endl;
573        }
574
575      SyntaxParser::parse_project_file_text (text, 
576                                             Project::get_project_file_name (),
577                                             project);
578    }
579
580  CmtSystem::cd (here);
581
582  return (project);
583}
584
585/*----------------------------------------------------------*/
586/*                                                          */
587/*  Operations on Projects                                  */
588/*                                                          */
589/*----------------------------------------------------------*/
590
591//----------------------------------------------------------
592bool Project::create (const cmt_string& name, 
593                      const cmt_string& release, 
594                      const cmt_string& path)
595{
596  cout << "------------------------------------------" << endl;
597  cout << "Configuring environment for project " << name << " " << release;
598
599  if (path != "")
600    {
601      cout << " in " << path;
602    }
603
604  cout << endl;
605  cout << "CMT version " << Cmt::get_cmt_version () << "." << endl;
606  cout << "------------------------------------------" << endl;
607
608  if (path != "")
609    {
610      if (!CmtSystem::mkdir (path))
611        {
612          cout << "Cannot create the " << path << " directory" << endl;
613          return (false);
614        }
615
616      if (!CmtSystem::cd (path))
617        {
618          cout << "Cannot access the " << path << " directory" << endl;
619          return (false);
620        }
621    }
622
623  if (!CmtSystem::mkdir (name))
624    {
625      cout << "Cannot create the " << name << " directory" << endl;
626      return (false);
627    }
628
629  if (!CmtSystem::cd (name))
630    {
631      cout << "Cannot access the " << name << " directory" << endl;
632      return (false);
633    }
634
635  if (release != "")
636    {
637      if (!CmtSystem::mkdir (release))
638        {
639          cout << "Cannot create the " << release << " directory" << endl;
640          return (false);
641        }
642     
643      if (!CmtSystem::cd (release))
644        {
645          cout << "Cannot access the " << release << " directory" << endl;
646          return (false);
647        }
648    }
649
650  if (!CmtSystem::test_directory ("cmt"))
651    {
652      if (!CmtSystem::mkdir ("cmt"))
653        {
654          cout << "Cannot create the cmt directory" << endl;
655          return (false);
656        }
657      else
658        {
659          cout << "Installing the cmt directory" << endl;
660        }
661    }
662
663  CmtSystem::cd ("cmt");
664
665  if (!CmtSystem::test_file (get_project_file_name ()))
666    {
667      cout << "Creating a new project file" << endl;
668
669      ofstream f (get_project_file_name ());
670      if (f)
671        {
672          f << "project " << name << endl;
673          f << endl;
674          f.close ();
675        }
676      else
677        {
678          cout << "Cannot create the project file" << endl;
679          return (false);
680        }
681    }
682  else
683    {
684      cmt_string text;
685      text.read (get_project_file_name ());
686
687      ProjectPatcher p (name);
688
689      p.run (text);
690      p.commit ();
691
692      cout << "project file already there" << endl;
693    }
694
695  return (true);
696}
697
698//----------------------------------------------------------
699Project* Project::find_by_name (const cmt_string& name)
700{
701  static ProjectVector& Projects = projects ();
702
703  for (int i = 0; i < Projects.size (); i++)
704    {
705      Project& p = Projects[i];
706
707      if (p.m_name == name) return (&p);
708    }
709
710  return (0);
711}
712
713//----------------------------------------------------------
714Project* Project::find_by_cmtpath (const cmt_string& cmtpath)
715{
716  cmt_string compressed_path = cmtpath;
717  CmtSystem::compress_path (compressed_path);
718
719  static ProjectVector& Projects = projects ();
720
721  for (int i = 0; i < Projects.size (); i++)
722    {
723      Project& p = Projects[i];
724
725      if (p.m_cmtpath == compressed_path) return (&p);
726      if (p.m_cmtpath_pwd == compressed_path) return (&p);
727    }
728
729  return (0);
730}
731
732//----------------------------------------------------------
733Project* Project::get_current ()
734{
735  cmt_string here = CmtSystem::pwd ();
736
737  static ProjectVector& Projects = projects ();
738
739  Project* result = 0;
740
741  for (int i = (Projects.size () - 1); i >= 0; i--)
742    {
743      Project& p = Projects[i];
744
745      if (here.find (p.m_cmtpath_pwd) == 0) 
746        {
747          result = &p;
748        }
749
750      if (here.find (p.m_cmtpath) == 0) 
751        {
752          result = &p;
753        }
754    }
755
756  return (result);
757}
758
759//----------------------------------------------------------
760Project* Project::add (const cmt_string& name,
761                       const cmt_string& release)
762{
763  static ProjectVector& Projects = projects ();
764
765  //cout << "Project::add> name=" << name << endl;
766
767  {
768    Project* project;
769
770    project = find_by_name (name);
771    if (project != 0) 
772      {
773        if (!Cmt::get_quiet ())
774          {
775            if (release != project->get_release ())
776              {
777                cerr << "#CMT> Project " << name << " requested with conflicting releases " << project->get_release () << " and " << release << endl;
778                CmtError::set (CmtError::project_release_conflict, name);
779              }
780          }
781
782        // Project objects are recreated here to follow the hierarchy
783        // This duplication is needed for properly applying the strategies
784        Project& p = Projects.add ();
785
786        p.set_name (name);
787        p.set_release (release);
788        p.configure ();
789
790        return (&p);
791
792        //return (project);
793      }
794  }
795
796  Project& project = Projects.add ();
797  project.clear ();
798  project.set_name (name);
799  project.set_release (release);
800  project.configure ();
801
802  return (&project);
803}
804
805//----------------------------------------------------------
806Project::ProjectVector& Project::projects ()
807{
808  static Database& db = Database::instance ();
809  static ProjectVector& Projects = db.projects ();
810
811  return (Projects);
812}
813
814/*----------------------------------------------------------*/
815void Project::clear_all ()
816{
817  static ProjectVector& Projects = projects ();
818
819  for (int i = 0; i < Projects.size (); i++)
820    {
821      Project& project = Projects[i];
822      project.clear ();
823    }
824
825  Projects.clear ();
826}
827
828/*----------------------------------------------------------*/
829void Project::show_all ()
830{
831  static Project::ProjectVector& Projects = Project::projects ();
832 
833  for (int i = 0; i < Projects.size (); i++)
834    {
835      Project& p = Projects[i];
836      p.m_visited = false;
837    }
838
839  Project* p = get_current ();
840
841  if (p == 0)
842    {
843      if (Projects.size () == 0) return;
844
845      p = &(Projects[0]);
846    }
847
848  p->show ();
849}
850
851/*----------------------------------------------------------*/
852void Project::show_specified_strategies_for_all ()
853{
854  static ProjectVector& Projects = projects ();
855
856  for (int i = 0; i < Projects.size (); i++)
857    {
858      const Project& project = Projects[i];
859      project.show_specified_strategies ();
860    }
861}
862
863/*----------------------------------------------------------*/
864class VisitorForShowPaths : public IProjectVisitor
865{
866public:
867  VisitorForShowPaths ()
868  {
869  }
870
871  void pre (Project* p)
872  {
873    const cmt_string& w = p->get_cmtpath_pwd ();
874    const cmt_string& s = p->get_cmtpath_source ();
875
876    if (s == "default path") return;
877
878    if (CmtSystem::test_directory (w))
879      {
880        cout << "# Add path " << w << " from " << s << endl;
881      }
882  }
883
884  void in (Project* p)
885  {
886    const cmt_string& w = p->get_cmtpath_pwd ();
887    const cmt_string& s = p->get_cmtpath_source ();
888
889    if (s == "default path") return;
890
891    if (CmtSystem::test_directory (w))
892      {
893        cout << "# Add path " << w << " from " << s << endl;
894      }
895  }
896
897  void post (Project* p)
898  {
899  }
900};
901
902/*----------------------------------------------------------*/
903void Project::show_paths ()
904{
905  VisitorForShowPaths visitor;
906
907  start_visit (visitor);
908}
909
910//----------------------------------------------------------
911const cmt_string& Project::get_project_file_name ()
912{
913  static const cmt_string name = "project.cmt";
914
915  return (name);
916}
917
918//----------------------------------------------------------
919void Project::fill_selection (int depth, CmtSystem::cmt_string_vector& path_selections)
920{
921  static ProjectVector& Projects = projects ();
922
923  for (int i = 0; i < Projects.size (); i++)
924    {
925      Project& project = Projects[i];
926
927      const cmt_string& p = project.get_cmtpath ();
928      const cmt_string& pwd = project.get_cmtpath_pwd ();
929      const cmt_string& src = project.get_cmtpath_source ();
930
931      if (src != "default path")
932        {
933          if (depth > 0)
934            {
935              cmt_string& s1 = path_selections.add ();
936              s1 = p;
937              cmt_string& s2 = path_selections.add ();
938              s2 = pwd;
939              depth--;
940
941              if (depth == 0) break;
942            }
943        }
944    }
945}
946
947//----------------------------------------------------------
948void Project::broadcast (IProjectAction& action)
949{
950  static ProjectVector& Projects = projects ();
951
952  for (int i = 0; i < Projects.size (); i++)
953    {
954      const Project& project = Projects[i];
955
956      if (!action.run (project)) break;
957    }
958}
959
960//----------------------------------------------------------
961void Project::reverse_broadcast (IProjectAction& action)
962{
963  static ProjectVector& Projects = projects ();
964
965  for (int i = (Projects.size () - 1); i >= 0; i--)
966    {
967      const Project& project = Projects[i];
968
969      if (!action.run (project)) break;
970    }
971}
972
973//----------------------------------------------------------
974void Project::scan_paths (PathScanner& scanner, PathScanner::actor& a)
975{
976  static ProjectVector& Projects = projects ();
977
978  int i;
979
980  for (i = 0; i < Projects.size (); i++)
981    {
982      Project& p  = Projects[i];
983      p.m_visited = false;
984    }
985
986  for (i = 0; i < Projects.size (); i++)
987    {
988      const Project& project = Projects[i];
989       
990      const cmt_string& p = project.m_cmtpath;
991      scanner.scan_path (p, a);
992    }
993}
994
995//----------------------------------------------------------
996void Project::scan_paths_for_package (PathScanner& scanner, const cmt_string& name)
997{
998  static ProjectVector& Projects = projects ();
999
1000  for (int i = 0; i < Projects.size (); i++)
1001    {
1002      const Project& project = Projects[i];
1003
1004      const cmt_string& p = project.m_cmtpath;
1005      scanner.scan_package (p, name);
1006    }
1007}
1008
1009//----------------------------------------------------------
1010cmt_string Project::find_in_cmt_paths (const cmt_string& path)
1011{
1012  const cmt_string pwd = CmtSystem::pwd ();
1013
1014  static ProjectVector& Projects = projects ();
1015
1016  for (int i = 0; i < Projects.size (); i++)
1017    {
1018      const Project& project = Projects[i];
1019
1020      const cmt_string& p = project.m_cmtpath;
1021      const cmt_string& w = project.m_cmtpath_pwd;
1022      const cmt_string& s = project.m_cmtpath_source;
1023
1024      if (s == "default path") continue;
1025
1026      if (CmtSystem::test_directory (p))
1027        {
1028          if (path.find (p) != cmt_string::npos)
1029            {
1030              return (p);
1031            }
1032
1033          // To become the current area, a path must correspond to the current package
1034          if (path.find (w) != cmt_string::npos)
1035            {
1036              return (p);
1037            }
1038        }
1039
1040      if (p == w) continue;
1041
1042      if (CmtSystem::test_directory (w))
1043        {
1044          if (path.find (w) != cmt_string::npos)
1045            {
1046              return (w);
1047            }
1048        }
1049    }
1050
1051  return ("");
1052}
1053
1054//----------------------------------------------------------
1055void Project::visit (IProjectVisitor& visitor)
1056{
1057  if (m_visited) return;
1058  m_visited = true;
1059
1060  int i;
1061
1062  for (i = 0; i < get_children_size (); i++)
1063    {
1064      Project* child = get_child (i);
1065
1066      if (child->visited ()) continue;
1067
1068      visitor.in (child);
1069    }
1070
1071  for (i = 0; i < m_children.size (); i++)
1072    {
1073      Project* child = m_children[i];
1074      child->visit (visitor);
1075    }
1076}
1077
1078//----------------------------------------------------------
1079void Project::start_visit (IProjectVisitor& visitor)
1080{
1081  static Project::ProjectVector& Projects = Project::projects ();
1082 
1083  for (int i = 0; i < Projects.size (); i++)
1084    {
1085      Project& p = Projects[i];
1086      p.m_visited = false;
1087    }
1088
1089  Project* p = get_current ();
1090
1091  if (p == 0)
1092    {
1093      if (Projects.size () == 0) return;
1094
1095      p = &(Projects[0]);
1096    }
1097
1098  visitor.pre (p);
1099  p->visit (visitor);
1100  visitor.post (p);
1101}
1102
1103//----------------------------------------------------------
1104class VisitorForFillCMTPATH : public IProjectVisitor
1105{
1106public:
1107  VisitorForFillCMTPATH (cmt_string& buffer) : m_buffer (buffer)
1108  {
1109    buffer = "path CMTPATH \"\" \n";
1110  }
1111
1112  void pre (Project* p)
1113  {
1114    const cmt_string& w = p->get_cmtpath_pwd ();
1115    const cmt_string& s = p->get_cmtpath_source ();
1116
1117    if (s == "default path") return;
1118
1119    if (CmtSystem::test_directory (w))
1120      {
1121        m_buffer += "path_append CMTPATH \"";
1122        m_buffer += w;
1123        m_buffer += "\" \n";
1124      }
1125  }
1126
1127  void in (Project* p)
1128  {
1129    const cmt_string& w = p->get_cmtpath_pwd ();
1130    const cmt_string& s = p->get_cmtpath_source ();
1131
1132    if (s == "default path") return;
1133
1134    if (CmtSystem::test_directory (w))
1135      {
1136        m_buffer += "path_append CMTPATH \"";
1137        m_buffer += w;
1138        m_buffer += "\" \n";
1139      }
1140  }
1141
1142  void post (Project* p)
1143  {
1144    //cerr << "Buffer = " << m_buffer << endl;
1145  }
1146
1147private:
1148  cmt_string& m_buffer;
1149
1150};
1151
1152//----------------------------------------------------------
1153void Project::fill_cmtpaths (cmt_string& buffer)
1154{
1155  /*
1156    Try to re-create all CMTPATH items from project definitions.
1157    The goal is to generate CMTPATH even if this EV was not pre-set
1158    which is the case when CMTPROJECTPATH is only used
1159   */
1160
1161  VisitorForFillCMTPATH visitor (buffer);
1162
1163  start_visit (visitor);
1164}
1165
1166//----------------------------------------------------------
1167Project::Project () : m_name ("")
1168{
1169  clear ();
1170}
1171
1172//----------------------------------------------------------
1173const cmt_string& Project::get_name () const
1174{
1175  return (m_name);
1176}
1177
1178//----------------------------------------------------------
1179const cmt_string& Project::get_release () const
1180{
1181  return (m_release);
1182}
1183
1184//----------------------------------------------------------
1185const cmt_string& Project::get_container () const
1186{
1187  return (m_container);
1188}
1189
1190//----------------------------------------------------------
1191const cmt_string& Project::get_container_version () const
1192{
1193  return (m_container_version);
1194}
1195
1196//----------------------------------------------------------
1197const cmt_string& Project::get_cmtpath () const
1198{
1199  return (m_cmtpath);
1200}
1201
1202//----------------------------------------------------------
1203const cmt_string& Project::get_cmtpath_pwd () const
1204{
1205  return (m_cmtpath_pwd);
1206}
1207
1208//----------------------------------------------------------
1209const cmt_string& Project::get_cmtpath_source () const
1210{
1211  return (m_cmtpath_source);
1212}
1213
1214//----------------------------------------------------------
1215int Project::get_children_size () const
1216{
1217  return (m_children.size ());
1218}
1219
1220//----------------------------------------------------------
1221Project* Project::get_child (int index) const
1222{
1223  if (index < 0) return (0);
1224  if (index >= m_children.size ()) return (0);
1225  return (m_children[index]);
1226}
1227
1228//----------------------------------------------------------
1229bool Project::visited () const
1230{
1231  return (m_visited);
1232}
1233
1234//----------------------------------------------------------
1235void Project::set_name (const cmt_string& name)
1236{
1237  m_name = name;
1238}
1239
1240//----------------------------------------------------------
1241void Project::set_release (const cmt_string& release)
1242{
1243  m_release = release;
1244}
1245
1246//----------------------------------------------------------
1247void Project::set_container (const cmt_string& container)
1248{
1249  m_container = container;
1250}
1251
1252//----------------------------------------------------------
1253void Project::set_container_version (const cmt_string& container_version)
1254{
1255  m_container_version = container_version;
1256}
1257
1258//----------------------------------------------------------
1259void Project::set_cmtpath (const cmt_string& path)
1260{
1261  m_cmtpath = path;
1262}
1263
1264//----------------------------------------------------------
1265void Project::set_cmtpath_pwd (const cmt_string& path)
1266{
1267  m_cmtpath_pwd = path;
1268}
1269
1270//----------------------------------------------------------
1271void Project::set_cmtpath_source (const cmt_string& source)
1272{
1273  m_cmtpath_source = source;
1274}
1275
1276//----------------------------------------------------------
1277void Project::clear ()
1278{
1279  m_name = "";
1280  m_release = "";
1281  m_cmtpath = "";
1282  m_cmtpath_pwd = "";
1283  m_cmtpath_source = "";
1284
1285  m_parents.clear ();
1286  m_children.clear ();
1287
1288  m_configured = false;
1289
1290  m_strategies.clear ();
1291}
1292
1293//----------------------------------------------------------
1294bool Project::has_parents () const
1295{
1296  return ((m_parents.size () > 0));
1297}
1298
1299//----------------------------------------------------------
1300bool Project::has_parent (Project* p) const
1301{
1302  if (p == 0) return (false);
1303  if (p == this) return (false);
1304
1305  const cmt_string& name = p->get_name ();
1306
1307  int i;
1308
1309  for (i = 0; i < m_parents.size (); i++)
1310    {
1311      const Project* parent = m_parents[i];
1312      if (parent == 0) continue;
1313
1314      if (parent->get_name () == name)
1315        {
1316          // registered as a parent
1317          return (true);
1318        }
1319
1320      if (parent->has_parent (p))
1321        {
1322          // recurse
1323          return (true);
1324        }
1325    }
1326
1327  return (false);
1328}
1329
1330//----------------------------------------------------------
1331bool Project::has_child (Project* p) const
1332{
1333  if (p == 0) return (false);
1334  if (p == this) return (false);
1335
1336  const cmt_string& name = p->get_name ();
1337
1338  int i;
1339
1340  for (i = 0; i < m_children.size (); i++)
1341    {
1342      const Project* child = m_children[i];
1343      if (child == 0) continue;
1344
1345      if (child->get_name () == name)
1346        {
1347          // registered as a child
1348          return (true);
1349        }
1350
1351      if (child->has_child (p))
1352        {
1353          // recurse
1354          return (true);
1355        }
1356    }
1357
1358  return (false);
1359}
1360
1361//----------------------------------------------------------
1362void Project::add_parent (Project* p)
1363{
1364  if (p == 0) return;
1365  if (p == this) return;
1366
1367  //cerr << "Adding parent " << p->get_name () << " to " << m_name << endl;
1368
1369  if (has_child (p)) return;
1370  if (has_parent (p)) return;
1371
1372  m_parents.push_back (p);
1373}
1374
1375//----------------------------------------------------------
1376void Project::add_child (Project* p)
1377{
1378  if (p == 0) return;
1379  if (p == this) return;
1380
1381  if (has_child (p)) return;
1382  if (has_parent (p)) return;
1383
1384  m_children.push_back (p);
1385}
1386
1387//----------------------------------------------------------
1388void Project::configure ()
1389{
1390  if (m_configured) return;
1391  m_configured = true;
1392
1393  set_default_strategy ("SetupConfig");
1394  set_default_strategy ("SetupRoot");
1395  set_default_strategy ("SetupCleanup");
1396  set_default_strategy ("BuildPrototypes");
1397  set_default_strategy ("InstallArea");
1398  set_default_strategy ("VersionDirectory");
1399}
1400
1401/**---------------------------------------------------------
1402 A container statement is met in the project file
1403*/
1404void Project::container_action (const cmt_string& name, const cmt_string& version)
1405{
1406  //cerr << "Container action " << name << " " << version << endl;
1407
1408  set_container (name);
1409  set_container_version (version);
1410}
1411
1412/**---------------------------------------------------------
1413 A use statement is met in the project file
1414*/
1415void Project::use_action (const cmt_string& name, const cmt_string& release)
1416{
1417  if (Cmt::get_debug ())
1418    {
1419      cout << "Use action " << name << " " << release << endl;
1420    }
1421
1422  // A project with its release is specified
1423  //
1424  // Is this project already visible?
1425  // If not: look for it
1426  //   + get CMTPROJECTPATH
1427  //   + search from all entries of CMTPROJECTPATH : p(i)/<name>/<release>
1428  //   + when found, this should become a new CMTPATH entry
1429  //   +             the new project is then parsed ... etc...
1430
1431  cmt_string cmtprojectpath = Symbol::get_env_value ("CMTPROJECTPATH");
1432
1433  cmt_string sep;
1434  sep = CmtSystem::path_separator ();
1435
1436  //cerr << "cmtprojectpath = " << cmtprojectpath << endl;
1437  CmtSystem::cmt_string_vector items;
1438  CmtSystem::split (cmtprojectpath, sep, items);
1439
1440  bool found = false;
1441
1442  for (int i = 0; i < items.size (); i++)
1443    {
1444      const cmt_string& item = items[i];
1445      cmt_string p = item;
1446      p += CmtSystem::file_separator ();
1447      p += name;
1448      if (release != "")
1449        {
1450          p += CmtSystem::file_separator ();
1451          p += release;
1452        }
1453
1454      if (CmtSystem::test_directory (p))
1455        {
1456          //cerr << "Project directory " << p << " exists " << endl;
1457
1458          found = true;
1459
1460          IProjectFactory& factory = ProjectFactory::instance ();
1461
1462          factory.create_project (name, p, "ProjectPath", this);
1463
1464          break;
1465        }
1466    }
1467
1468  if (!found)
1469    {
1470      Project* p = Project::find_by_name (name);
1471
1472      if (p != 0)
1473        {
1474          found = true;
1475
1476          p->add_parent (this);
1477          add_child (p);
1478
1479          update_strategies_from_children ();
1480        }
1481    }
1482
1483  if (!found && (cmtprojectpath != ""))
1484    {
1485      cerr << "#CMT> Project " << name << " " << release << " requested by " << m_name << " not found in CMTPROJECTPATH" << endl;
1486    }
1487}
1488
1489
1490//----------------------------------------------------------
1491Project& Project::operator = (const Project& other)
1492{
1493  m_name = other.m_name;
1494  m_cmtpath = other.m_cmtpath;
1495  m_cmtpath_pwd = other.m_cmtpath_pwd;
1496  m_cmtpath_source = other.m_cmtpath_source;
1497
1498  return (*this);
1499}
1500
1501//----------------------------------------------------------
1502bool Project::operator == (const cmt_string& name) const
1503{
1504  return ((m_name == name));
1505}
1506
1507//----------------------------------------------------------
1508bool Project::operator != (const cmt_string& name) const
1509{
1510  return ((m_name != name));
1511}
1512
1513//----------------------------------------------------------
1514void Project::show ()
1515{
1516  static int level = 0;
1517
1518  bool is_current = false;
1519
1520  cmt_string here = CmtSystem::pwd ();
1521
1522  if (here.find (m_cmtpath) == 0) 
1523    {
1524      if (m_cmtpath_source != "default path")
1525        {
1526          is_current = true;
1527        }
1528    }
1529
1530  for (int tab = 0; tab < level; tab++) cout << "  ";
1531  cout << m_name << " " << m_release << " (in " << m_cmtpath << ")";
1532
1533  if (is_current) cout << " (current)";
1534
1535  int i;
1536
1537  for (i = 0; i < m_parents.size (); i++)
1538    {
1539      Project* p = m_parents[i];
1540      if (p == 0) continue;
1541      cout << " P=" << p->get_name ();
1542    }
1543
1544  for (i = 0; i < m_children.size (); i++)
1545    {
1546      Project* p = m_children[i];
1547      if (p == 0) continue;
1548      cout << " C=" << p->get_name ();
1549    }
1550
1551  cout << endl;
1552
1553  if (m_visited) return;
1554
1555  m_visited = true;
1556
1557  for (i = 0; i < m_children.size (); i++)
1558    {
1559      Project* p = m_children[i];
1560      if (p == 0) continue;
1561      level++;
1562      p->show ();
1563      level--;
1564    }
1565}
1566
1567
1568//----------------------------------------------------------
1569void Project::show_specified_strategies () const
1570{
1571  int i;
1572
1573  for (i = 0; i < m_strategies.size (); i++)
1574    {
1575      const Strategy& s = m_strategies[i];
1576      if (s.m_specified)
1577        {
1578          const StrategyDef* def = s.m_definition;
1579 
1580          cout << "# Project " << m_name
1581               << " sets " << def->m_keyword
1582               << " strategy to " << ((s.m_value) ? def->m_on_value : def->m_off_value);
1583
1584          if (s.m_context != "")
1585            {
1586              cout << " (from package " << s.m_context << ")";
1587            }
1588
1589          cout << endl;
1590        }
1591    }
1592}
1593
1594//----------------------------------------------------------
1595bool Project::has_strategy (const StrategyDef* definition) const
1596{
1597  int i;
1598
1599  for (i = 0; i < m_strategies.size (); i++)
1600    {
1601      const Strategy& s = m_strategies[i];
1602      if (s.m_definition == definition)
1603        {
1604          return (true);
1605        }
1606    }
1607
1608  return (false);
1609}
1610
1611//----------------------------------------------------------
1612bool Project::get_strategy (const cmt_string& name) const
1613{
1614  static StrategyMgr& mgr = StrategyMgr::instance ();
1615
1616  StrategyDef* def = mgr.find_strategy (name);
1617  if (def == 0)
1618    {
1619      cerr << "#CMT> strategy " << name << " undefined" << endl;
1620      return (false);
1621    }
1622
1623  return (get_strategy (def));
1624}
1625
1626//----------------------------------------------------------
1627bool Project::is_specified (const StrategyDef* definition) const
1628{
1629  int i;
1630
1631  for (i = 0; i < m_strategies.size (); i++)
1632    {
1633      Strategy& s = m_strategies[i];
1634      if (s.m_definition == definition)
1635        {
1636          // This strategy is applied in this project
1637          return (s.m_specified);
1638        }
1639    }
1640
1641  // This strategy is not applied in this project
1642  return (false);
1643}
1644
1645//----------------------------------------------------------
1646bool Project::get_strategy (const StrategyDef* def) const
1647{
1648  int i;
1649
1650  for (i = 0; i < m_strategies.size (); i++)
1651    {
1652      Strategy& s = m_strategies[i];
1653      if (s.m_definition == def)
1654        {
1655          // This strategy is applied in this project
1656          if (s.m_specified)
1657            {
1658              return (s.m_specified_value);
1659            }
1660          return (s.m_value);
1661        }
1662    }
1663
1664  // This strategy is not applied in this project
1665  return (def->m_default_value);
1666}
1667
1668//----------------------------------------------------------
1669void Project::set_default_strategy (const cmt_string& name)
1670{
1671  static StrategyMgr& mgr = StrategyMgr::instance ();
1672
1673  StrategyDef* def = mgr.find_strategy (name);
1674  if (def == 0)
1675    {
1676      cerr << "#CMT> strategy " << name << " undefined" << endl;
1677      return;
1678    }
1679
1680  update_strategy (def, def->m_default_value);
1681}
1682
1683
1684//----------------------------------------------------------
1685void Project::set_strategy (const cmt_string& name, const cmt_string& value, const cmt_string& context)
1686{
1687  static StrategyMgr& mgr = StrategyMgr::instance ();
1688
1689  StrategyDef* def = mgr.find_strategy (name);
1690  if (def == 0)
1691    {
1692      cerr << "#CMT> strategy " << name << " undefined" << endl;
1693      return;
1694    }
1695
1696  bool b_value = false;
1697
1698  if (value == def->m_on_value)
1699    {
1700      b_value = true;
1701    }
1702  else if (value == def->m_off_value)
1703    {
1704      b_value = false;
1705    }
1706  else
1707    {
1708      cerr << "#CMT> requested strategy value " << value << " undefined in strategy " << name << endl;
1709      return;
1710    }
1711
1712  set_strategy (def, b_value, context);
1713}
1714
1715//----------------------------------------------------------
1716void Project::set_strategy (StrategyDef* definition, bool b_value, const cmt_string& context)
1717{
1718  bool need_strategy = true;
1719
1720  int i;
1721
1722  for (i = 0; i < m_strategies.size (); i++)
1723    {
1724      Strategy& s = m_strategies[i];
1725      if (s.m_definition == definition)
1726        {
1727          // This strategy is already applied in this project. Let's change it's value
1728          s.set (definition, b_value, get_name ());
1729          if (context != "")
1730            {
1731              if (s.m_context != "") s.m_context += " ";
1732              s.m_context += context;
1733            }
1734          need_strategy = false;
1735          break;
1736        }
1737    }
1738
1739  if (need_strategy)
1740    {
1741      // This strategy is not yet applied in this project.
1742
1743      Strategy& s = m_strategies.add ();
1744      s.clear ();
1745      s.set (definition, b_value, get_name ());
1746      s.m_context = context;
1747    }
1748 
1749  for (i = 0; i < m_parents.size (); i++)
1750    {
1751      Project* project = m_parents[i];
1752
1753      project->update_strategy (definition, b_value);
1754    }
1755}
1756
1757/**----------------------------------------------------------
1758   The strategy value is changed because of indirect influences
1759   - default strategy at initialization time
1760   - change in the children
1761   - change in the children list
1762
1763   (This is not a specification : see the set_strategy method)
1764 */
1765void Project::update_strategy (StrategyDef* definition, bool b_value)
1766{
1767  bool need_strategy = true;
1768  bool specified = false;
1769
1770  int i;
1771
1772  for (i = 0; i < m_strategies.size (); i++)
1773    {
1774      Strategy& s = m_strategies[i];
1775      if (s.m_definition == definition)
1776        {
1777          need_strategy = false;
1778
1779          if (!s.m_specified)
1780            {
1781              // This strategy is already applied in this project. Let's change it's value
1782              s.update (definition, b_value, get_name ());
1783            }
1784          else
1785            {
1786              specified = true;
1787            }
1788          break;
1789        }
1790    }
1791
1792  if (need_strategy)
1793    {
1794      // This strategy is not yet applied in this project.
1795
1796      Strategy& s = m_strategies.add ();
1797      s.clear ();
1798      s.update (definition, b_value, get_name ());
1799    }
1800
1801  if (!specified)
1802    {
1803      for (i = 0; i < m_parents.size (); i++)
1804        {
1805          Project* project = m_parents[i];
1806
1807          project->update_strategy (definition, b_value);
1808        }
1809    }
1810}
1811
1812/**----------------------------------------------------------
1813   At least one of the children has changed this strategy
1814   Or the list of children has changed.
1815   We need to update the strategy value accordingly
1816   This will not change the specified value for this strategy
1817 */
1818void Project::update_strategy_from_children (StrategyDef* definition)
1819{
1820  // If this strategy is specified we don't care what happens from the children
1821
1822  //cerr << "Updating strategy " << definition->m_name << " from children for project " << m_name << endl;
1823
1824  int i;
1825
1826  for (i = 0; i < m_strategies.size (); i++)
1827    {
1828      Strategy& s = m_strategies[i];
1829      if (s.m_definition == definition)
1830        {
1831          // This strategy is applied in this project.
1832
1833          if (s.m_specified)
1834            {
1835              // There will be no impact since the strategy is specified
1836
1837              //cerr << "This strategy is specified in this project" << endl;
1838              return;
1839            }
1840
1841          break;
1842        }
1843    }
1844
1845  // The strategy is not specified locally so we will now figure out
1846  // which strategy has to be considered from the mixture of specifications
1847  // from all children.
1848
1849  // Algorithm:
1850  // - We consider children by pairs
1851  // - a child that specifies its strategy wins over a child that does not
1852  // - when the two children have the same level of priority we consider the priority value
1853
1854  Project* selected = 0;
1855  bool selected_is_specified = false;
1856  bool selected_value = definition->m_default_value;
1857
1858  for (i = 0; i < m_children.size (); i++)
1859    {
1860      Project* p = m_children[i];
1861
1862      //cerr << "Checking strategy for child " << p->get_name () << endl;
1863
1864      bool is_specified = p->is_specified (definition);
1865      bool value = p->get_strategy (definition);
1866
1867      if (selected == 0)
1868        {
1869          selected = p;
1870          selected_is_specified = is_specified;
1871          selected_value = value;
1872          continue;
1873        }
1874
1875      if (is_specified == selected_is_specified)
1876        {
1877          if (selected_value != value)
1878            {
1879              // same level of priority but different values -> we must decide
1880              bool priority_value = definition->m_priority_value;
1881              if (value == priority_value)
1882                {
1883                  selected = p;
1884                  selected_is_specified = is_specified;
1885                  selected_value = value;
1886                }
1887            }
1888        }
1889      else
1890        {
1891          if (is_specified)
1892            {
1893              selected = p;
1894              selected_is_specified = is_specified;
1895              selected_value = value;
1896            }
1897        }
1898    }
1899
1900  update_strategy (definition, selected_value); 
1901}
1902
1903/**----------------------------------------------------------
1904   At least one of the children has changed its strategies
1905   Or the list of children has changed.
1906   We need to update the strategy values accordingly
1907   This will not change the specified values
1908 */
1909void Project::update_strategies_from_children ()
1910{
1911  StrategyDef::StrategyDefs& defs = StrategyMgr::get_definitions ();
1912
1913  //cerr << "Updating strategies from children for project " << m_name << endl;
1914
1915  int i;
1916
1917  for (i = 0; i < defs.size (); i++)
1918    {
1919      StrategyDef* def = defs[i];
1920     
1921      update_strategy_from_children (def);
1922    }
1923
1924  for (i = 0; i < m_parents.size (); i++)
1925    {
1926      Project* p = m_parents[i];
1927      p->update_strategies_from_children ();
1928    }
1929}
1930
1931/**----------------------------------------------------------
1932   The StrategyMgr singleton
1933 */
1934StrategyMgr& StrategyMgr::instance ()
1935{
1936  static StrategyMgr me;
1937  return (me);
1938}
1939
1940/**----------------------------------------------------------
1941   The StrategyMgr constructor
1942   Here are primarily constructed all strategy definitions
1943 */
1944StrategyMgr::StrategyMgr ()
1945{
1946  m_defs.clear ();
1947
1948  StrategyDef* s;
1949
1950  s = new StrategyDef;
1951  s->m_keyword = "build";
1952  s->m_name = "BuildPrototypes";
1953  s->m_on_value = "prototypes";
1954  s->m_off_value = "no_prototypes";
1955  s->m_default_value = true;
1956  s->m_priority_value = false;
1957
1958  m_defs.push_back (s);
1959
1960  s = new StrategyDef;
1961  s->m_keyword = "build";
1962  s->m_name = "InstallArea";
1963  s->m_on_value = "with_installarea";
1964  s->m_off_value = "without_installarea";
1965  s->m_default_value = false;
1966  s->m_priority_value = true;
1967
1968  m_defs.push_back (s);
1969
1970  s = new StrategyDef;
1971  s->m_keyword = "setup";
1972  s->m_name = "SetupConfig";
1973  s->m_on_value = "config";
1974  s->m_off_value = "no_config";
1975  s->m_default_value = true;
1976  s->m_priority_value = false;
1977
1978  m_defs.push_back (s);
1979
1980  s = new StrategyDef;
1981  s->m_keyword = "setup";
1982  s->m_name = "SetupRoot";
1983  s->m_on_value = "root";
1984  s->m_off_value = "no_root";
1985  s->m_default_value = true;
1986  s->m_priority_value = false;
1987
1988  m_defs.push_back (s);
1989
1990  s = new StrategyDef;
1991  s->m_keyword = "setup";
1992  s->m_name = "SetupCleanup";
1993  s->m_on_value = "cleanup";
1994  s->m_off_value = "no_cleanup";
1995  s->m_default_value = true;
1996  s->m_priority_value = false;
1997
1998  m_defs.push_back (s);
1999
2000  s = new StrategyDef;
2001  s->m_keyword = "structure";
2002  s->m_name = "VersionDirectory";
2003  s->m_on_value = "with_version_directory";
2004  s->m_off_value = "without_version_directory";
2005  if (Cmt::get_current_structuring_style () != without_version_directory)
2006    {
2007      s->m_default_value = true;
2008      s->m_priority_value = false;
2009    }
2010  else
2011    {
2012      s->m_default_value = false;
2013      s->m_priority_value = true;
2014    }
2015
2016  m_defs.push_back (s);
2017}
2018
2019/**----------------------------------------------------------
2020   Find a strategy definition by its name
2021 */
2022StrategyDef* StrategyMgr::find_strategy (const cmt_string& name)
2023{
2024  static StrategyMgr& me = instance ();
2025
2026  int i;
2027
2028  for (i = 0; i < me.m_defs.size (); i++)
2029    {
2030      StrategyDef* def = me.m_defs[i];
2031      if (def->m_name == name)
2032        {
2033          return (def);
2034        }
2035    }
2036
2037  return (0);
2038}
2039
2040/**----------------------------------------------------------
2041   Retreive the default value defined for a given strategy
2042 */
2043bool StrategyMgr::get_default_strategy (const cmt_string& name)
2044{
2045  StrategyDef* def = find_strategy (name);
2046  if (def == 0) return (false);
2047  return (def->m_default_value);
2048}
2049
2050/**----------------------------------------------------------
2051   Retreive the priority value defined for a given strategy
2052   This value is used when two children of a project request two conflicting strategy values
2053 */
2054bool StrategyMgr::get_priority_strategy (const cmt_string& name)
2055{
2056  StrategyDef* def = find_strategy (name);
2057  if (def == 0) return (false);
2058  return (def->m_priority_value);
2059}
2060
2061/**----------------------------------------------------------
2062   Return the vector of all existing strategy definitions
2063 */
2064StrategyDef::StrategyDefs& StrategyMgr::get_definitions ()
2065{
2066  static StrategyMgr& me = instance ();
2067
2068  return (me.m_defs);
2069}
2070
2071//-----------------------------------------------------------
2072Strategy::Strategy ()
2073{
2074  clear ();
2075}
2076
2077//-----------------------------------------------------------
2078void Strategy::clear ()
2079{
2080  m_definition = 0;
2081  m_specified = false;
2082  m_specified_value = false;
2083  m_value = false;
2084  m_on_tag = 0;
2085  m_off_tag = 0;
2086}
2087
2088/**----------------------------------------------------------
2089   Specify a new value for this strategy.
2090   This only happens when a strategy statement is met in a project file or in a requirements file.
2091 */
2092void Strategy::set (StrategyDef* definition, bool value, const cmt_string& project_name)
2093{
2094  //cerr << "Setting strategy " << definition->m_name << " for project " << project_name << " to " << value << endl;
2095
2096  m_definition = definition;
2097  m_specified = true;
2098  m_specified_value = value;
2099
2100  update (definition, value, project_name);
2101}
2102
2103/**----------------------------------------------------------
2104   Change the effective value for this strategy.
2105   This has no impact on to the specified value.
2106   This will adapt the tag settings
2107 */
2108void Strategy::update (StrategyDef* definition, bool value, const cmt_string& project_name)
2109{
2110  //cerr << "Updating strategy " << definition->m_name << " for project " << project_name << " to " << value << endl;
2111
2112  m_value = value;
2113  m_definition = definition;
2114
2115  cmt_string to_tag_name = project_name;
2116  cmt_string to_untag_name = project_name;
2117
2118  to_tag_name += "_";
2119  to_untag_name += "_";
2120
2121  if (m_value)
2122    {
2123      to_tag_name += m_definition->m_on_value;
2124      to_untag_name += m_definition->m_off_value;
2125    }
2126  else
2127    {
2128      to_tag_name += m_definition->m_off_value;
2129      to_untag_name += m_definition->m_on_value;
2130    }
2131
2132  m_on_tag = Tag::find (to_tag_name);
2133  m_off_tag = Tag::find (to_untag_name);
2134
2135  if (m_on_tag == 0) 
2136    {
2137      m_on_tag = Tag::add (to_tag_name, PriorityConfig, "PROJECT", 0);
2138      m_off_tag = Tag::add (to_untag_name, PriorityConfig, "PROJECT", 0);
2139
2140      m_on_tag->add_tag_exclude (m_off_tag);
2141      m_off_tag->add_tag_exclude (m_on_tag);
2142    }
2143
2144  m_off_tag->unmark ();
2145  m_on_tag->mark ();
2146}
2147
2148const cmt_string& StrategyDef::get_default_value () const
2149{
2150  if (m_default_value)
2151    {
2152      return (m_on_value);
2153    }
2154  else
2155    {
2156      return (m_off_value);
2157    }
2158}
2159
Note: See TracBrowser for help on using the repository browser.