source: CMT/v1r18p20050501/source/cmt_project.cxx

Last change on this file was 41, checked in by arnault, 19 years ago

Implement the container statement in project file - See CL269 and #4

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