source: CMT/HEAD/source/cmt_symbol.cxx @ 610

Last change on this file since 610 was 610, checked in by rybkin, 12 years ago

See C.L. 485

  • Property svn:eol-style set to native
File size: 88.0 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_use.h"
13#include "cmt_symbol.h"
14#include "cmt_system.h"
15#include "cmt_database.h"
16#include "cmt_log.h"
17
18// Global inhibitor of any display
19bool Symbol::m_inhibit_display = false;
20
21//-------------------------------------------------------------
22class SetBuilder : public ValueBuilder
23{
24public:
25  const cmt_string build (const Symbol& symbol,
26                          const cmt_string& tag_name = "");
27  const cmt_string clean (const Symbol& symbol,
28                          const cmt_string& tag_name = "")
29      {
30        static const cmt_string empty = "";
31        return (empty);
32      }
33};
34//-------------------------------------------------------------
35
36//-------------------------------------------------------------
37class PathBuilder : public ValueBuilder
38{
39public:
40  const cmt_string build (const Symbol& symbol,
41                          const cmt_string& tag_name = "");
42  const cmt_string clean (const Symbol& symbol,
43                          const cmt_string& tag_name = "");
44};
45//-------------------------------------------------------------
46
47//-------------------------------------------------------------
48class MacroBuilder : public ValueBuilder
49{
50public:
51  const cmt_string build (const Symbol& symbol,
52                          const cmt_string& tag_name = "");
53  const cmt_string clean (const Symbol& symbol,
54                          const cmt_string& tag_name = "")
55      {
56        static const cmt_string empty = "";
57        return (empty);
58      }
59};
60//-------------------------------------------------------------
61
62//-------------------------------------------------------------
63class ScriptBuilder : public ValueBuilder
64{
65public:
66  const cmt_string build (const Symbol& symbol,
67                          const cmt_string& tag_name = "");
68  const cmt_string clean (const Symbol& symbol,
69                          const cmt_string& tag_name = "")
70      {
71        static const cmt_string empty = "";
72        return (empty);
73      }
74};
75//-------------------------------------------------------------
76
77//-------------------------------------------------------------
78class ActionBuilder : public ValueBuilder
79{
80public:
81  const cmt_string build (const Symbol& symbol,
82                          const cmt_string& tag_name = "");
83  const cmt_string clean (const Symbol& symbol,
84                          const cmt_string& tag_name = "")
85      {
86        static const cmt_string empty = "";
87        return (empty);
88      }
89};
90//-------------------------------------------------------------
91
92//-------------------------------------------------------------
93class symbol_marker
94{
95public:
96  symbol_marker ()
97  {
98    ptr = cmt_string::npos;
99    pattern = 0;
100    intro = 0;
101  }
102
103  symbol_marker (int a_ptr, char a_pattern, int a_intro)
104  {
105    ptr = a_ptr;
106    pattern = a_pattern;
107    intro = a_intro;
108  }
109
110  symbol_marker (const symbol_marker& other)
111  {
112    ptr = other.ptr;
113    pattern = other.pattern;
114    intro = other.intro;
115  }
116
117  void set (int a_ptr, char a_pattern, int a_intro)
118  {
119    ptr = a_ptr;
120    pattern = a_pattern;
121    intro = a_intro;
122  }
123
124  static symbol_marker& get_lowest (symbol_marker markers[], int count)
125  {
126    static symbol_marker result;
127    int real_count = 0;
128    int i;
129
130      // Check that at least one marker has result
131
132    for (i = 0; i < count; i++)
133      {
134        if (markers[i].ptr != cmt_string::npos) real_count++;
135      }
136
137    if (real_count == 0) return (result);
138
139    // since we've passed the previous test,
140    // at least one entry is not npos.
141    // Now discards other npos by moving them to the end
142   
143    for (i = 0; i < count;)
144      {
145        if (markers[i].ptr == cmt_string::npos)
146          {
147            markers[i] = markers[count-1];
148            count--;
149            if (count == 0) break;
150          }
151        else
152          {
153            i++;
154          }
155      }
156   
157    if (count == 0) return (result);
158   
159    // now all entries in [0, count-1] are not npos
160    // let's sort the lowest one in [0]
161   
162    for (i = 1; i < count;)
163      {
164        if (markers[0].ptr > markers[i].ptr)
165          {
166            symbol_marker temp = markers[0];
167            markers[0] = markers[i];
168            markers[i] = temp;
169            i = 1;
170          }
171        else
172          {
173            i++;
174          }
175      }
176   
177    return (markers[0]);
178  }
179
180  int ptr;
181  char pattern;
182  int intro;
183};
184//-------------------------------------------------------------
185
186/**
187
188   Attempt to substitute all occurrences of
189
190      ${<symbol_name>}
191      $(<symbol_name>)
192      %<symbol_name>%    [on Windows only]
193
194      by the specified value in the given text.
195
196    This is for one symbol only
197
198 */
199static void resolve_value (cmt_string& text,
200                           const cmt_string& symbol_name,
201                           const cmt_string& value)
202{
203  static cmt_string pattern;
204
205  pattern = "${";
206  pattern += symbol_name;
207  pattern += "}";
208
209  text.replace_all (pattern, value);
210
211  pattern = "$(";
212  pattern += symbol_name;
213  pattern += ")";
214
215  text.replace_all (pattern, value);
216
217#ifdef WIN32
218  pattern = "%";
219  pattern += symbol_name;
220  pattern += "%";
221
222  text.replace_all (pattern, value);
223#endif
224}
225
226/**
227
228   Attempt to substitute into the specified text all occurrences of
229
230      ${xxx}
231      $(xxx)
232      `xxx`
233      %xxx%    [on Windows only]
234
235      by the appropriate value:
236
237        for `xxx` :
238
239            xxx is considered as a shell command. Value is the result of its execution
240
241        for other patterns:
242
243            if xxx is a symbol name, its value is substituted to the pattern
244            otherwise, xxx is tried as an environment variable
245
246
247     ===> In all cases, the pattern is filtered away.
248
249
250 */
251static void resolve_value (cmt_string& text)
252{
253  //static cmt_regexp reg ("[$%`]");
254
255  //if (!reg.match (text)) return;
256
257  cmt_string pattern;
258  cmt_string symbol_name;
259  char end_pattern;
260
261  int start = 0;
262
263  for (;;)
264    {
265      int begin;
266      int end;
267
268      symbol_marker markers[4];
269      int num = 0;
270
271      markers[num].set (text.find (start, "$("), ')', 2); num++;
272      markers[num].set (text.find (start, "${"), '}', 2); num++;
273      markers[num].set (text.find (start, "`"), '`', 1); num++;
274
275#ifdef WIN32
276      markers[num].set (text.find (start, "%"), '%', 1); num++;
277#endif
278
279      // Find the first matching pattern
280
281      symbol_marker& marker = symbol_marker::get_lowest (markers, num);
282
283      begin = marker.ptr;
284
285      if (begin == cmt_string::npos) break;
286
287      end_pattern = marker.pattern;
288      start = begin + marker.intro;
289
290      end = text.find (start, end_pattern);
291      if (end == cmt_string::npos)
292        {
293          // The pattern is a fake one (no ending!)
294          start++;
295          continue;
296        }
297
298      // This should never happen...
299      if (end < begin) break;
300
301      // Extract the complete pattern
302      text.substr (begin, end - begin + 1, pattern);
303
304      // Then only the symbol name
305      text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name);
306
307      if (text[begin] == '`')
308        {
309          cmt_string command = symbol_name;
310          resolve_value (command);
311
312            // The value is a shell command that first needs
313            // to be applied. The output of the command is then substituted
314
315          cmt_string result;
316
317          Symbol::all_set ();
318          CmtSystem::execute (command, result);
319         
320          int pos;
321          pos = result.find ('\n');
322          if (pos != cmt_string::npos) result.erase (pos);
323          pos = result.find ('\r');
324          if (pos != cmt_string::npos) result.erase (pos);
325         
326          if (Cmt::get_debug ())
327            {
328              cout << "   Executing [" << command << "] to expand a symbol value =>[" 
329                   << result << "]" << endl;
330            }
331         
332          text.replace_all (pattern, result);
333
334          // The substitution will restart from the same place
335          // allowing for recursive replacements
336          start = begin;
337        }
338      else
339        {
340          Symbol* symbol = Symbol::find (symbol_name);
341          if (symbol != 0)
342            {
343                // Symbol found
344              cmt_string value = symbol->resolve_macro_value ();
345              text.replace_all (pattern, value);
346             
347                // The substitution will restart from the same place
348                // allowing for recursive replacements
349              start = begin;
350            }
351          else
352            {
353                // Symbol not found. Look for env. variable
354              cmt_string value = CmtSystem::getenv (symbol_name);
355             
356                // When the env. variable is not defined, the replacement is empty
357                // thus all $(xxx) ${xxx} %xxx% patterns are always filtered away.
358              text.replace_all (pattern, value);
359             
360                // The substitution will restart from the same place
361                // allowing for recursive replacements
362              start = begin;
363            }
364        }
365    }
366}
367
368/**
369
370   Attempt to substitute all occurrences of
371
372      ${xxx}
373      $(xxx)
374      `xxx`
375      %xxx%    [on Windows only]
376
377      by the appropriate value:
378
379        for `xxx` :
380
381            xxx is considered as a shell command. Value is the result of its execution
382
383        for other patterns:
384
385            if xxx is a macro name, its value is substituted to the pattern
386
387            if xxx is a set or a path, it is kept in place (after fixing the pattern
388            according to the OS style)
389
390            otherwise it is simply kept in place
391
392 */
393static void resolve_value_for_macros (cmt_string& text)
394{
395  cmt_string pattern;
396  cmt_string symbol_name;
397  char end_pattern;
398
399  int start = 0;
400
401  for (;;)
402    {
403      //
404      // Try and substitute all ${xxx} $(xxx) or %xxx% patterns
405      // using symbol values, only when the symbol is a macro.
406      //
407
408      int begin;
409      int end;
410
411      symbol_marker markers[4];
412      int num = 0;
413
414      markers[num].set (text.find (start, "$("), ')', 2); num++;
415      markers[num].set (text.find (start, "${"), '}', 2); num++;
416
417#ifdef WIN32
418      markers[num].set (text.find (start, "%"), '%', 1); num++;
419#endif
420
421      markers[num].set (text.find (start, "`"), '`', 1); num++;
422
423      // Find the first of three patterns
424
425      symbol_marker& marker = symbol_marker::get_lowest (markers, num);
426
427      begin = marker.ptr;
428
429      if (begin == cmt_string::npos) break;
430
431      end_pattern = marker.pattern;
432      start = begin + marker.intro;
433
434      end = text.find (start, end_pattern);
435      if (end == cmt_string::npos)
436        {
437          // The pattern is a fake one (no ending!)
438          start++;
439          continue;
440        }
441
442      // This should never happen...
443      if (end < begin) break;
444
445      // Extract the complete pattern
446      text.substr (begin, end - begin + 1, pattern);
447
448      // Then only the macro name
449      text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name);
450
451      if (text[begin] == '`')
452        {
453          cmt_string command = symbol_name;
454          resolve_value (command);
455
456            // The macro value is a shell command that first needs
457            // to be applied. The output of the command is substituted
458
459          cmt_string result;
460
461          Symbol::all_set ();
462          CmtSystem::execute (command, result);
463         
464          int pos;
465          pos = result.find ('\n');
466          if (pos != cmt_string::npos) result.erase (pos);
467          pos = result.find ('\r');
468          if (pos != cmt_string::npos) result.erase (pos);
469         
470          if (Cmt::get_debug ())
471            {
472              cout << "   Executing [" << command << "] to expand a macro value =>[" 
473                   << result << "]" << endl;
474            }
475         
476          text.replace_all (pattern, result);
477
478          // The substitution will restart from the same place
479          // allowing for recursive replacements
480          start = begin;
481        }
482      else
483        {
484          Symbol* macro = Symbol::find (symbol_name);
485          if ((macro != 0) && 
486              (macro->type == Symbol::SymbolMacro))
487            {
488                // Macro found
489              cmt_string value = macro->resolve_macro_value ();
490              text.replace_all (pattern, value);
491
492                // The substitution will restart from the same place
493                // allowing for recursive replacements
494              start = begin;
495            }
496          else if ((macro == 0) || 
497                   ((macro->type == Symbol::SymbolSet) || (macro->type == Symbol::SymbolPath)))
498            {
499                // Set found
500                // ensure that the delimiters will match the OS dependent
501                // delimiters.
502             
503              cmt_string pattern_close = marker.pattern;
504             
505              if (pattern_close != CmtSystem::ev_close ())
506                {
507                  cmt_string new_pattern;
508                 
509                  new_pattern = CmtSystem::ev_open ();
510                  new_pattern += symbol_name;
511                  new_pattern += CmtSystem::ev_close ();
512                 
513                  text.replace (pattern, new_pattern);
514                }
515             
516              start = end + 1;
517            }
518          else
519            {
520              start = end + 1;
521            }
522        }
523    }
524}
525
526/**
527
528   This function suppress all OS delimiters ie ${ } or % % and replaces them
529   by the pure macro delimiters $( )
530
531   `xxx` pattern is replaced by the result of the execution of the command
532
533 */
534static void suppress_OS_delimiters (cmt_string& text)
535{
536  cmt_string pattern;
537  cmt_string symbol_name;
538  char end_pattern;
539
540  int start = 0;
541
542  for (;;)
543    {
544      int begin;
545      int end;
546
547      symbol_marker markers[3];
548      int num = 0;
549
550      markers[num].set (text.find (start, "${"), '}', 2); num++;
551      markers[num].set (text.find (start, "`"), '`', 1); num++;
552
553#ifdef WIN32
554      markers[num].set (text.find (start, "%"), '%', 1); num++;
555#endif
556
557      // Find the first of three patterns
558
559      symbol_marker& marker = symbol_marker::get_lowest (markers, num);
560
561      begin = marker.ptr;
562
563      if (begin == cmt_string::npos) break;
564
565      end_pattern = marker.pattern;
566      start = begin + marker.intro;
567
568      end = text.find (start, end_pattern);
569      if (end == cmt_string::npos)
570        {
571          // The pattern is a fake one (no ending!)
572          start++;
573          continue;
574        }
575
576      // This should never happen...
577      if (end < begin) break;
578
579      // Extract the complete pattern
580      text.substr (begin, end - begin + 1, pattern);
581
582      // Then only the macro name
583      text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name);
584
585      if (text[begin] == '`')
586        {
587          cmt_string command = symbol_name;
588          resolve_value (command);
589
590            // The macro value is a shell command that first needs
591            // to be applied. The output of the command is substituted
592
593          cmt_string result;
594
595          Symbol::all_set ();
596          CmtSystem::execute (command, result);
597         
598          int pos;
599          pos = result.find ('\n');
600          if (pos != cmt_string::npos) result.erase (pos);
601          pos = result.find ('\r');
602          if (pos != cmt_string::npos) result.erase (pos);
603         
604          if (Cmt::get_debug ())
605            {
606              cout << "   Executing [" << command << "] to expand a macro value =>[" 
607                   << result << "]" << endl;
608            }
609         
610          text.replace_all (pattern, result);
611
612          // The substitution will restart from the same place
613          // allowing for recursive replacements
614          start = begin;
615        }
616      else
617        {
618          cmt_string new_pattern;
619
620          new_pattern = "$(";
621          new_pattern += symbol_name;
622          new_pattern += ")";
623
624          text.replace (pattern, new_pattern);
625
626          start = begin;
627        }
628    }
629}
630
631//-------------------------------------------------------------
632/*                                                          */
633/*  Operations on SymbolValues                              */
634/*                                                          */
635//-------------------------------------------------------------
636
637//-------------------------------------------------------------
638SymbolValue::SymbolValue ()
639{
640  tag = 0;
641}
642
643//-------------------------------------------------------------
644SymbolValue::~SymbolValue ()
645{
646  tag = 0;
647}
648
649//-------------------------------------------------------------
650/*                                                          */
651/*  Operations on Symbols                                   */
652/*                                                          */
653//-------------------------------------------------------------
654
655//-------------------------------------------------------------
656Symbol* Symbol::create (const cmt_string& name,
657                        CommandType command,
658                        Use* use)
659{
660  static SetBuilder Set;
661  static PathBuilder Path;
662  static MacroBuilder Macro;
663  static ScriptBuilder Script;
664  static ActionBuilder Action;
665
666  static SymbolVector& Symbols = symbols ();
667  static SymbolMap& SymbolMap = symbol_map ();
668
669  SymbolType type = SymbolUndefined;
670
671  switch (command)
672    {
673    case CommandSet:
674    case CommandSetAppend:
675    case CommandSetPrepend:
676    case CommandSetRemove:
677    case CommandSetRemoveRegexp:
678      type = SymbolSet;
679      break;
680    case CommandPath:
681    case CommandPathAppend:
682    case CommandPathPrepend:
683    case CommandPathRemove:
684    case CommandPathRemoveRegexp:
685      type = SymbolPath;
686      break;
687    case CommandMacro:
688    case CommandMacroAppend:
689    case CommandMacroPrepend:
690    case CommandMacroRemove:
691    case CommandMacroRemoveRegexp:
692    case CommandMacroRemoveAll:
693    case CommandMacroRemoveAllRegexp:
694      type = SymbolMacro;
695      break;
696    case CommandAction:
697      type = SymbolAction;
698      break;
699    case CommandAlias:
700      type = SymbolAlias;
701      break;
702    case CommandSetupScript:
703      type = SymbolSetupScript;
704      break;
705    case CommandCleanupScript:
706      type = SymbolCleanupScript;
707      break;
708    }
709
710  {
711    Symbol* symbol;
712
713    symbol = find (name);
714    if (symbol != 0) 
715      {
716        if (symbol->type != type)
717          {
718            ActionType action = Cmt::get_action ();
719
720            if ((!Cmt::get_quiet ()) &&
721                (action != action_build_constituents_config) &&
722                (action != action_build_constituent_config))
723              {
724                cmt_string s1;
725                cmt_string s2;
726
727                switch (symbol->type)
728                  {
729                  case SymbolSet:
730                    s1 = "set";
731                    break;
732                  case SymbolPath:
733                    s1 = "path";
734                    break;
735                  case SymbolMacro:
736                    s1 = "macro";
737                    break;
738                  case SymbolSetupScript:
739                    s1 = "setup_script";
740                    break;
741                  case SymbolCleanupScript:
742                    s1 = "cleanup_script";
743                    break;
744                  case SymbolAction:
745                    s1 = "action";
746                    break;
747                  case SymbolAlias:
748                    s1 = "alias";
749                    break;
750                  } 
751
752                switch (type)
753                  {
754                  case SymbolSet:
755                    s2 = "set";   
756                    break;
757                  case SymbolPath:
758                    s2 = "path";   
759                    break;
760                  case SymbolMacro:
761                    s2 = "macro";   
762                    break;
763                  case SymbolSetupScript:
764                    s2 = "setup_script"; 
765                    break;
766                  case SymbolCleanupScript:
767                    s2 = "cleanup_script"; 
768                    break;
769                  case SymbolAction:
770                    s2 = "action";
771                    break;
772                  case SymbolAlias:
773                    s2 = "alias";
774                    break;
775                  } 
776                // <PACKAGE>ROOT macro is defined in
777                // Use::fill_standard_macros <- SyntaxParser::parse_requirements
778                // "cmt -requirements setup" may generate <PACKAGE>ROOT set
779                // hence, warning
780                // Symbol <PACKAGE>ROOT inconsistently redeclared from macro to set in package <package>
781                // below, we suppress the warning for current package
782                if (use != &(Use::current()) ||
783                    (Use::current().prefix + "ROOT") != name ||
784                    symbol->type != SymbolMacro ||
785                    type != SymbolSet)
786                  CmtMessage::warning ("Symbol " + name
787                                       + " inconsistently redeclared from " + s1
788                                       + " to " + s2
789                                       + ( (use != 0) ?
790                                           " in package " + use->get_package_name () :
791                                           "" )
792                                       );
793                /*
794                cerr << "#CMT> Warning: Symbol " << name
795                     << " inconsistently redeclared from " << s1 << " to " << s2;
796                if (use != 0) cerr << " in package " << use->get_package_name ();
797                cerr << endl;
798                */
799              }
800          }
801
802        return (symbol);
803      }
804  }
805
806  Symbol& symbol = Symbols.add ();
807  SymbolMap.add (name, symbol);
808
809  symbol.name  = name;
810  symbol.scope = use->get_current_scope ();
811  symbol.type  = type;
812
813  symbol.value_lists.clear ();
814
815  switch (type)
816    {
817    case SymbolSet:
818      symbol.builder = &Set;
819      break;
820    case SymbolPath:
821      symbol.builder = &Path;
822      break;
823    case SymbolAlias:
824      symbol.builder = &Set;
825      break;
826    case SymbolMacro:
827      symbol.builder = &Macro;
828      break;
829    case SymbolSetupScript:
830    case SymbolCleanupScript:
831      symbol.builder = &Script;
832      break;
833    case SymbolAction:
834      symbol.builder = &Action;
835      break;
836    }
837
838  symbol.selected_value = -1;
839  symbol.printed = false;
840
841  return (&symbol);
842}
843
844//-------------------------------------------------------------
845Symbol* Symbol::find (const cmt_string& name)
846{
847  static SymbolMap& SymbolMap = symbol_map ();
848
849  Symbol* result = 0;
850
851  result = SymbolMap.find (name);
852
853  return (result);
854}
855
856//-------------------------------------------------------------
857int Symbol::symbol_number ()
858{
859  static SymbolVector& Symbols = symbols ();
860
861  return (Symbols.size ());
862}
863
864//-------------------------------------------------------------
865Symbol::SymbolVector& Symbol::symbols ()
866{
867  static Database& db = Database::instance ();
868  static SymbolVector& Symbols = db.symbols ();
869
870  return (Symbols);
871}
872
873//-------------------------------------------------------------
874Symbol::SymbolMap& Symbol::symbol_map ()
875{
876  static Database& db = Database::instance ();
877  static SymbolMap& SymbolMap = db.symbol_map ();
878
879  return (SymbolMap);
880}
881
882/**
883   Filter out faulty items of a path-like symbol value
884 */
885void Symbol::filter_path_value (const cmt_string& name, cmt_string& text)
886{
887
888  CmtSystem::cmt_string_vector paths;
889  CmtSystem::cmt_string_vector normalyzed_paths;   
890                 
891  CmtSystem::split (text, CmtSystem::path_separator (), paths);
892                 
893  for (int j = 0; j < paths.size (); ++j)
894    {
895      cmt_string& t = paths[j];
896
897      if (!CmtSystem::test_directory (t))
898          {
899            if (CmtMessage::active (Verbose))
900              CmtMessage::warning ("Non-existent directory " + t + " in " + name);
901            /*
902              if (Cmt::get_warnings ())
903              {
904                  cerr << "#CMT> Warning: Wrong path item " << t << " in " << name << endl;
905              }
906            */
907          }
908           
909      int exist = 0; 
910      for (int i = 0; i < j; ++i)
911      {
912          cmt_string& u = paths[i];
913          if (u == t)
914             exist = 1;
915      }           
916      if (exist==0)
917      {
918          cmt_string& s = normalyzed_paths.add ();
919          s = t;
920      }             
921    }
922   
923  Cmt::vector_to_string (normalyzed_paths, CmtSystem::path_separator (), text);
924
925  for (;;)
926    {
927      int sz = text.size ();
928
929      if (sz == 0) break;
930
931      if ((text[0] == ';') || (text[0] == ':'))
932        {
933          text.erase (0, 1);
934        }
935      else if ((text[sz-1] == ';') || (text[sz-1] == ':'))
936        {
937          text.erase (sz-1, 1);
938        }
939      else
940        {
941          break;
942        }
943    }
944
945  text.replace_all ("::", ":");
946  text.replace_all (";;", ";");
947}
948
949
950//-------------------------------------------------------------
951Symbol& Symbol::symbol (int index)
952{
953  static SymbolVector& Symbols = symbols ();
954
955  return (Symbols[index]);
956}
957
958//-------------------------------------------------------------
959void Symbol::action (const CmtSystem::cmt_string_vector& words,
960                     CommandType command_type,
961                     Use* use)
962{
963  int number;
964  Symbol* symbol;
965  Tag* tag;
966
967  if (words.size () < 1) return;
968  cmt_string name = words[1];
969
970  if ((command_type == CommandSetupScript) ||
971      (command_type == CommandCleanupScript))
972    {
973      cmt_string full_name;
974
975      Symbol::expand (name);
976
977      if (name != "")
978        {
979          if (CmtSystem::absolute_path (name)) 
980            {
981              full_name = name;
982            }
983          else
984            {
985              if (use->get_strategy ("SetupRoot") &&
986                  use->get_package_name () != "cmt_standalone")
987                {
988#ifdef WIN32
989              full_name = "%";
990#else
991              full_name = "${";
992#endif
993              full_name += CmtSystem::mangle (use->prefix);
994              full_name += "ROOT";
995#ifdef WIN32
996              full_name += "%";
997#else
998              full_name += "}";
999#endif
1000                }
1001              else
1002                {
1003              full_name = use->get_full_path ();
1004                }
1005              if (use->style == cmt_style)
1006                {
1007                  full_name += CmtSystem::file_separator ();
1008                  full_name += "cmt";
1009                }
1010              else if (use->style == mgr_style)
1011                {
1012                  full_name += CmtSystem::file_separator ();
1013                  full_name += "mgr";
1014                }
1015              //              else if (use->style == no_version_style) full_name += "cmt";
1016              //              else full_name += "mgr";
1017              full_name += CmtSystem::file_separator ();
1018              full_name += name;
1019            }
1020
1021          symbol = create (full_name, command_type, use);
1022          symbol->add_value_to_list (command_type, use,
1023                                     Tag::get_default (), full_name);
1024        }
1025    }
1026  else
1027    {
1028      if (words.size () < 2) return;
1029      const cmt_string& default_value = words[2];
1030
1031      Cmt::reset_all_sets_done ();
1032
1033      if (Cmt::get_debug ())
1034        {
1035          cout << "Symbol::action> name:" << name
1036               << " access:" << Cmt::get_current_access () 
1037               << " scope:" << use->get_current_scope () << endl;
1038        }
1039
1040      if (Cmt::get_current_access () == UserMode)
1041        {
1042          /*
1043            The following statements mean that some symbols are
1044            always private.
1045            This list is hardcoded. This should be replaced by a
1046            database of "private" symbols.
1047           */
1048          if (name == "constituents") return;
1049          if (name == "constituentscclean") return;
1050
1051          if (use->get_current_scope () == ScopePrivate) return;
1052        }
1053
1054      symbol = create (name, command_type, use);
1055
1056      /*
1057        Parse the default value.
1058      */
1059     
1060      symbol->add_value_to_list (command_type, use,
1061                                 Tag::get_default (), default_value);
1062     
1063      /*
1064        Then parse all specific values
1065       
1066        <tag> <value>
1067        ...
1068      */
1069     
1070      number = 3;
1071      while (number < (words.size () - 1))
1072        {
1073          cmt_string tag_name = words[number];
1074          const cmt_string& value = words[number + 1];
1075
1076          expand (tag_name);
1077
1078          if (Cmt::get_debug ())
1079            {
1080              cout << "Symbol::action> tag_name=" << tag_name << endl;
1081            }
1082
1083          tag = Tag::find (tag_name);
1084          if (tag == 0)
1085            {
1086              tag = Tag::add (tag_name, PriorityUserTag, "use", use);
1087            }
1088
1089          symbol->add_value_to_list (command_type, use, tag, value);
1090         
1091          number += 2;
1092        }
1093
1094      if (name == "CMTPATH")
1095        {
1096          Cmt::configure_cmt_path (use);
1097        }
1098      else if (name == "CMTPROJECTPATH")
1099        {
1100          Cmt::configure_cmt_path (use);
1101        }
1102      else if (name == "CMTSITE")
1103        {
1104          Cmt::configure_site_tag (use);
1105        }
1106      else if (name == "CMTCONFIG")
1107        {
1108            //cerr << "redefining CMTCONFIG" << endl;
1109          Cmt::configure_tags (use);
1110        }
1111      else if (name == "CMTHOME")
1112        {
1113          Cmt::configure_home (use);
1114        }
1115      else if (name == "CMTUSERCONTEXT")
1116        {
1117          Cmt::configure_user_context (use);
1118        }
1119      else if (name.find ("_native_version") != cmt_string::npos)
1120        {
1121          cmt_string n = use->get_package_name ();
1122          n += "_native_version";
1123
1124          if (name == n)
1125            {
1126              use->set_native_version (true);
1127            }
1128        }
1129    }
1130}
1131
1132//-------------------------------------------------------------
1133int Symbol::is_selected (const cmt_string& name)
1134{
1135  Symbol* symbol;
1136  int number;
1137  int value_number;
1138
1139  symbol = find (name);
1140  if (symbol == 0) return (0);
1141
1142  if (symbol->value_lists.size () == 0) return (0);
1143
1144  for (number = 0;
1145       number < symbol->value_lists.size ();
1146       number++)
1147    {
1148      const SymbolValueList& value_list = symbol->value_lists[number];
1149
1150      if (value_list.discarded) continue;
1151
1152      if ((value_list.command_type == CommandMacro) ||
1153          (value_list.command_type == CommandSet) ||
1154          (value_list.command_type == CommandSetAppend) ||
1155          (value_list.command_type == CommandSetPrepend) ||
1156          (value_list.command_type == CommandSetRemove) ||
1157          (value_list.command_type == CommandSetRemoveRegexp) ||
1158          (value_list.command_type == CommandAlias) ||
1159          (value_list.command_type == CommandAction))
1160        {
1161          for (value_number = 0;
1162               value_number < value_list.values.size ();
1163               value_number++)
1164            {
1165              Tag* tag;
1166
1167              SymbolValue& value = value_list.values[value_number];
1168
1169              tag = value.tag;
1170              if ((tag == 0) ||
1171                  (tag == Tag::get_default ()) ||
1172                  (tag->is_selected () != 0))
1173                {
1174                  return (1);
1175                }
1176            }
1177        }
1178    }
1179
1180  return (0);
1181}
1182
1183//-------------------------------------------------------------
1184Symbol::Symbol ()
1185{
1186  name = "";
1187}
1188
1189//-------------------------------------------------------------
1190Symbol::~Symbol ()
1191{
1192}
1193
1194/**
1195 *  Characterizes if a value is provided as the reference to itself.
1196 */
1197bool Symbol::value_is_reflexive (const cmt_string& text) const
1198{
1199  bool result = false;
1200  int text_length = text.size ();
1201
1202  if (text_length == (name.size () + 3))
1203    {
1204      static cmt_string temp;
1205             
1206      if (text[0] == '$')
1207        {
1208          if (text[1] == '(')
1209            {
1210              temp = "$(";
1211              temp += name;
1212              temp += ")";
1213             
1214              if (text == temp)
1215                {
1216                  result = true;
1217                }
1218            }
1219          else if (text[1] == '{')
1220            {
1221              temp = "${";
1222              temp += name;
1223              temp += "}";
1224             
1225              if (text == temp)
1226                {
1227                  result = true;
1228                }
1229            }
1230        }
1231    }
1232  else if (text_length == (name.size () + 2))
1233    {
1234      static cmt_string temp;
1235
1236      temp = "%";
1237      temp += name;
1238      temp += "%";
1239
1240      if (text == temp)
1241        {
1242          result = true;
1243        }
1244    }
1245
1246  return (result);
1247}
1248
1249//-------------------------------------------------------------
1250void Symbol::add_value_to_list (CommandType command_type,
1251                                Use* use,
1252                                Tag* tag,
1253                                const cmt_string& text)
1254{
1255  SymbolValueList* value_list = 0;
1256  bool is_reflexive = false;
1257
1258    //
1259    // First pickup the most recent value_list
1260    //
1261  if (value_lists.size () > 0) value_list = &(value_lists.back ());
1262
1263    //
1264    //  Create a new value list is we switch to another use or
1265    //  if we switch to a new command_type (eg. switching from
1266    //  macro to macro_append).
1267    //
1268  if ((value_list == 0) ||
1269      (use != value_list->use) ||
1270      (command_type != value_list->command_type) ||
1271      (tag == Tag::get_default ()))
1272    {
1273      value_list = &(value_lists.add ());
1274      value_list->use = use;
1275      value_list->command_type = command_type;
1276      value_list->values.clear ();
1277      value_list->discarded = false;
1278      value_list->is_reflexive = false;
1279    }
1280
1281/*
1282  else
1283    {
1284        value_list = &(value_lists[value_lists.size () - 1]);
1285    }
1286*/
1287
1288  is_reflexive = value_list->is_reflexive;
1289
1290    //
1291    //  If the command_type is command_macro or command_set,
1292    // this is considered as a full re-set of this symbol
1293    //   In this case, we have to discard all previous values
1294    //
1295    //  However, we'd like to exclude from this logic the cases where
1296    //  the value is **exactly*
1297    //
1298    //     $(<symbol>)
1299    //     ${<symbol>}
1300    //     %<symbol>%
1301    //
1302    //   which would then mean that we do not reset the value but rather
1303    //  override it.
1304    //
1305
1306    //
1307    // Inside this value_list, we add this new tag-value pair.
1308    //
1309
1310  if ((command_type == CommandMacro) ||
1311      (command_type == CommandSet) ||
1312      (command_type == CommandPath) ||
1313      (command_type == CommandAction))
1314    {
1315        //
1316        // Check whether we have to hide previous settings by this new definition
1317        //  (of course this is only useful if there WERE previous settings)
1318        //
1319      if ((value_lists.size () >= 1) && (!is_reflexive))
1320        {
1321          if (value_is_reflexive (text))
1322            {
1323              value_list->is_reflexive = true;
1324              is_reflexive = true;
1325            }
1326          else
1327            {
1328              //cerr << "...discarding old values for symbol " << name << " text=[" << text << "]" << endl;
1329                 
1330              for (int i = 0; i < (value_lists.size () - 1); i++)
1331                {
1332                  SymbolValueList& vl = value_lists[i];
1333                 
1334                  if ((vl.use != 0) &&
1335                      (vl.use->discarded))
1336                    {
1337                      //vl.discarded = true;
1338                    }
1339                }
1340            }
1341        }
1342    }
1343
1344  SymbolValue& value = value_list->values.add ();
1345
1346  value.tag = tag;
1347  value.text = text;
1348  value.selected = 0;
1349}
1350
1351/**
1352   Compute the current value of all environment variables and set them to the
1353   shell
1354 */
1355void Symbol::all_set ()
1356{
1357  //cerr << "all_set" << endl;
1358
1359  static bool running = false;
1360
1361
1362  if (Cmt::get_debug ())
1363    {
1364      cout << "\nSymbol::all_set> done=" << running << endl;
1365    }
1366
1367  if (Cmt::get_all_sets_done ()) return;
1368
1369  if (running) return;
1370
1371  running = true;
1372  Cmt::set_all_sets_done ();
1373
1374  static SymbolVector& Symbols = symbols ();
1375  Use::UsePtrVector& Uses = Use::get_ordered_uses ();
1376
1377  int number;
1378
1379  if (Symbols.size () == 0) 
1380    {
1381      running = false;
1382      return;
1383    }
1384
1385  cmt_string value;
1386
1387  for (number = 0; number < Symbol::symbol_number (); number++)
1388    {
1389      Symbol& symbol = Symbol::symbol (number);
1390
1391      if (symbol.type != SymbolSet) continue;
1392
1393      value = symbol.build_macro_value ();
1394      if (value != "")
1395        {
1396          Symbol::expand (value);
1397
1398          CmtSystem::putenv (symbol.name, value);
1399        }
1400    }
1401
1402  cmt_string cmtconfig = CmtSystem::get_cmt_config ();
1403
1404  if (Uses.size () > 0)
1405    {
1406      int number;
1407
1408      for (number = 0; number < Uses.size (); number++)
1409        {
1410          Use& use = *(Uses[number]);
1411
1412          if (use.discarded) continue;
1413
1414          if (use.get_package_name () == "cmt_standalone") continue;
1415
1416          if (use.get_strategy ("SetupConfig"))
1417            {
1418              cmt_string temp;
1419
1420              temp = use.prefix;
1421              temp += "CONFIG";
1422
1423              CmtSystem::putenv (temp, cmtconfig);
1424            }
1425
1426          if (use.get_strategy ("SetupRoot"))
1427            {
1428              cmt_string temp;
1429
1430              temp = use.prefix;
1431              temp += "ROOT";
1432
1433              CmtSystem::putenv (temp, use.get_full_path ());
1434            }
1435        }
1436    }
1437
1438  {
1439    Use& use = Use::current ();
1440
1441    if (use.get_package_name () != "cmt_standalone")
1442      {
1443        if (use.get_strategy ("SetupConfig"))
1444          {
1445            cmt_string temp;
1446
1447            temp = use.prefix;
1448            temp += "CONFIG";
1449
1450            CmtSystem::putenv (temp, cmtconfig);
1451          }
1452       
1453        if (use.get_strategy ("SetupRoot"))
1454          {
1455            cmt_string temp;
1456
1457            temp = use.prefix;
1458            temp += "ROOT";
1459
1460            CmtSystem::putenv (temp, use.get_full_path ());
1461          }
1462      }
1463  }
1464
1465  for (number = 0; number < Symbol::symbol_number (); number++)
1466    {
1467      Symbol& symbol = Symbol::symbol (number);
1468
1469      if ((symbol.type != SymbolPath)) continue;
1470
1471      value = symbol.build_macro_value ();
1472      if (value != "")
1473        {
1474          Symbol::expand (value);
1475          filter_path_value (symbol.name, value);
1476
1477#ifdef WIN32
1478          value.replace_all ("/", "\\");
1479#endif
1480
1481          if (Cmt::get_debug ())
1482            {
1483              cerr << "Symbol::all_set-2> " << symbol.name << " = " << value << endl;
1484            }
1485
1486          CmtSystem::putenv (symbol.name, value);
1487        }
1488    }
1489
1490  running = false;
1491}
1492
1493//-------------------------------------------------------------
1494void Symbol::all_print (PrintMode mode)
1495{
1496  static SymbolVector& Symbols = symbols ();
1497
1498  int number;
1499
1500  if (Symbols.size () == 0) return;
1501
1502  switch (mode)
1503    {
1504    case Requirements :
1505      for (number = 0; number < Symbol::symbol_number (); number++)
1506        {
1507          Symbol& symbol = Symbol::symbol (number);
1508
1509          if ((symbol.type == SymbolSet) ||
1510              (symbol.type == SymbolAlias) ||
1511              (symbol.type == SymbolSetupScript) ||
1512              (symbol.type == SymbolPath) ||
1513              (symbol.type == SymbolMacro))
1514            {
1515              if (symbol.print_macro (mode))
1516                {
1517                  //              cout << endl;
1518                }
1519            }
1520        }
1521      break;
1522    default :
1523      for (number = 0; number < Symbol::symbol_number (); number++)
1524        {
1525          Symbol& symbol = Symbol::symbol (number);
1526         
1527          if ((symbol.type == SymbolSet) ||
1528              (symbol.type == SymbolAlias) ||
1529              (symbol.type == SymbolSetupScript) ||
1530              (symbol.type == SymbolPath))
1531            {
1532              if (symbol.print (mode))
1533                {
1534                  if (mode == Bat)
1535                    {
1536                      cout << endl;
1537                    }
1538                  else if (mode == Xml)
1539                    {
1540                      //                      cout << endl;
1541                    }
1542                  else
1543                    {
1544                      cout << endl;
1545                    }
1546                }
1547            }
1548        }
1549      break;
1550    }
1551}
1552
1553//-------------------------------------------------------------
1554void Symbol::check_all_paths ()
1555{
1556  static SymbolVector& Symbols = symbols ();
1557
1558  int number;
1559
1560  if (Symbols.size () == 0) return;
1561
1562  for (number = 0; number < Symbol::symbol_number (); number++)
1563    {
1564      Symbol& symbol = Symbol::symbol (number);
1565
1566      if (symbol.type == SymbolPath)
1567        {
1568          cmt_string temp;
1569
1570          temp = symbol.build_macro_value ();
1571          expand (temp);
1572
1573          Symbol::filter_path_value (symbol.name, temp);
1574        }
1575    }
1576}
1577
1578//-------------------------------------------------------------
1579void Symbol::all_print_clean (PrintMode mode)
1580{
1581  static SymbolVector& Symbols = symbols ();
1582
1583  int number;
1584
1585  if (Symbols.size () == 0) return;
1586
1587  for (number = Symbols.size () - 1; number >= 0; number--)
1588    {
1589      Symbol& symbol = Symbols[number];
1590
1591      if ((symbol.type == SymbolSet) ||
1592          (symbol.type == SymbolAlias) ||
1593          (symbol.type == SymbolCleanupScript))
1594        {
1595          if (symbol.print_clean (mode))
1596            {
1597              cout << endl;
1598            }
1599        }
1600    }
1601
1602  for (number = Symbols.size () - 1; number >= 0; number--)
1603    {
1604      Symbol& symbol = Symbols[number];
1605
1606      if ((symbol.type != SymbolPath)) continue;
1607
1608      if (symbol.print_clean (mode))
1609        {
1610          cout << endl;
1611        }
1612    }
1613}
1614
1615//-------------------------------------------------------------
1616int Symbol::print_clean (PrintMode mode)
1617{
1618  int result = 0;
1619  static cmt_string temp;
1620
1621  if (name == "CMTCONFIG") return (0);
1622
1623  cmt_string _name;
1624  switch (type)
1625    {
1626    case SymbolSet :
1627    case SymbolPath :
1628      if (0 != CmtSystem::mangle (name, _name))
1629        CmtMessage::info ("Replace " + name + " with " + _name);
1630      break;
1631    }
1632
1633  switch (type)
1634    {
1635    case SymbolSet :
1636      switch (mode)
1637        {
1638        case Csh :
1639          cout << "unsetenv " << _name;
1640          result = 1;
1641          break;
1642        case Sh :
1643          cout << "[ -z ${" << _name << "+CMT} ] || unset " << _name;
1644          //          cout << "unset " << _name;
1645          result = 1;
1646          break;
1647        case Bat :
1648          cout << "set " << _name << "=";
1649          result = 1;
1650          break;
1651        }
1652      break;
1653    case SymbolAlias :
1654      switch (mode)
1655        {
1656          case Csh :
1657            cout << "unalias " << name;
1658            result = 1;
1659            break;
1660          case Sh :
1661            cout << "[ -z ${" << name << "+CMT} ] || unset " << name;
1662          //            cout << "unset " << name;
1663            result = 1;
1664            break;
1665        }
1666      break;
1667    case SymbolPath :
1668      temp = clean_macro_value ();
1669      switch (mode)
1670        {
1671        case Csh :
1672          if (temp == "")
1673            {
1674              cout << "unsetenv " << _name;
1675            }
1676          else
1677            {
1678              cout << "setenv " << _name << " " << CmtSystem::quote (temp, " \t");
1679            }
1680          result = 1;
1681          break;
1682        case Sh :
1683          cout << _name << "=" << CmtSystem::quote (temp, " \t") << "; export " << _name;
1684          result = 1;
1685          break;
1686        case Bat :
1687          cout << "set " << _name << "=" << CmtSystem::quote (temp, " \t");
1688          result = 1;
1689          break;
1690        }
1691      break;
1692    case SymbolCleanupScript :
1693      switch (mode)
1694        {
1695        case Csh :
1696          cout << "if ( -f " << CmtSystem::quote (name, " \t") << ".csh ) then" << endl;
1697          cout << "  source " << CmtSystem::quote (name, " \t") << ".csh" << endl;
1698          cout <<
1699            "if ( $status != 0 ) then\n"
1700            "    set cmtcleanupstatus=1\n"
1701            "endif\n";
1702          cout << "endif" << endl;
1703          result = 1;
1704          break;
1705        case Sh :
1706          cout << "if test -f " << CmtSystem::quote (name, " \t") << ".sh; then" << endl;
1707          cout << "  . " << CmtSystem::quote (name, " \t") << ".sh" << endl;
1708          cout <<
1709            "if test $? != 0; then\n"
1710            "    cmtcleanupstatus=1\n"
1711            "fi\n";
1712          cout << "fi" << endl;
1713          result = 1;
1714          break;
1715        case Bat :
1716          cout << "call " << CmtSystem::quote (name, " \t");
1717          result = 1;
1718          break;
1719        }
1720      break;
1721    }
1722
1723  return (result);
1724}
1725
1726//-------------------------------------------------------------
1727int Symbol::print (PrintMode mode)
1728{
1729  int result = 0;
1730
1731  cmt_string temp = build_macro_value ();
1732  bool empty = (temp.size () == 0) ? true : false;
1733
1734  if (type == SymbolPath)
1735    {
1736      expand (temp);
1737      Symbol::filter_path_value (name, temp);
1738    }
1739
1740  cmt_string _name;
1741  switch (type)
1742    {
1743      case SymbolSet :
1744      case SymbolPath :
1745        if (0 != CmtSystem::mangle (name, _name))
1746          CmtMessage::info ("Replace " + name + " with " + _name);
1747        switch (mode)
1748          {
1749            case Csh :
1750              if (empty) cout << "unsetenv " << _name;
1751              else cout << "setenv " << _name << " \"" << temp << "\"";
1752              //else cout << "setenv " << name << " " << CmtSystem::quote (temp, " \t");
1753
1754              result = 1;
1755              break;
1756            case Sh :
1757              if (empty) cout << "[ -z ${" << _name << "+CMT} ] || unset " << _name;
1758              //              if (empty) cout << "unset " << _name;
1759              else cout << _name << "=\"" << temp << "\"; export " << _name;
1760              //else cout << name << "=" << CmtSystem::quote (temp, " \t") << "; export " << name;
1761
1762              result = 1;
1763              break;
1764            case Bat :
1765              temp.replace_all ("/", "\\");
1766              cout << "set " << _name << "=" << CmtSystem::quote (temp, " \t");
1767              //cout << "set " << name << "=" << temp;
1768              result = 1;
1769              break;
1770            case Xml :
1771              cout << "<variable><name>" << _name << "</name>"
1772                   << "<value>" << temp << "</value></variable>";
1773              result = 1;
1774              break;
1775          }
1776        break;
1777      case SymbolAlias :
1778        switch (mode)
1779          {
1780            case Csh :
1781              cout << "alias " << name <<
1782                " \"" << temp << "\"";
1783              //CmtSystem::quote (temp, " \t");
1784              result = 1;
1785              break;
1786            case Sh :
1787              cout << "alias " << name <<
1788                "=\"" << temp << "\"";
1789              //"=" << CmtSystem::quote (temp, " \t");
1790              result = 1;
1791              break;
1792            case Bat :
1793              cout << "set " << name <<
1794                "=" << CmtSystem::quote (temp, " \t");
1795              //"=" << temp;
1796              result = 1;
1797              break;
1798            case Xml :
1799              cout << "<alias><name>" << name << "</name>"
1800                   << "<value>" << temp << "</value></alias>";
1801              result = 1;
1802              break;
1803          }
1804        break;
1805      default :
1806        break;
1807    }
1808
1809  if (temp != "")
1810    {
1811      switch (type)
1812        {
1813          case SymbolSetupScript :
1814            switch (mode)
1815              {
1816                case Csh :
1817                  cout << "if ( -f " << CmtSystem::quote (name, " \t") << ".csh ) then" << endl;
1818                  cout << "  source " << CmtSystem::quote (name, " \t") << ".csh" << endl;
1819                  cout <<
1820                    "if ( $status != 0 ) then\n"
1821                    "    set cmtsetupstatus=1\n"
1822                    "endif\n";
1823                  cout << "endif" << endl;
1824                  result = 1;
1825                  break;
1826                case Sh :
1827                  cout << "if test -f " << CmtSystem::quote (name, " \t") << ".sh; then" << endl;
1828                  cout << "  . " << CmtSystem::quote (name, " \t") << ".sh" << endl;
1829                  cout <<
1830                    "if test $? != 0; then\n"
1831                    "    cmtsetupstatus=1\n"
1832                    "fi\n";
1833                  cout << "fi" << endl;
1834                  result = 1;
1835                  break;
1836                case Bat :
1837                  cout << "call " << CmtSystem::quote (name, " \t");
1838                  result = 1;
1839                  break;
1840                case Xml :
1841                  cout << "<script>" << name << "</script>";
1842                  result = 1;
1843                  break;
1844              }
1845            break;
1846          default:
1847            break;
1848        }
1849    }
1850
1851  return (result);
1852}
1853
1854//-------------------------------------------------------------
1855cmt_string Symbol::build_macro_value (bool display_it) const
1856{
1857  cmt_string temp;
1858
1859  if (display_it)
1860    {
1861      temp = builder->build_and_display (*this);
1862    }
1863  else
1864    {
1865      temp = builder->build (*this);
1866    }
1867
1868  return (temp);
1869}
1870
1871//-------------------------------------------------------------
1872int Symbol::print_macro (PrintMode mode, ostream& out) const
1873{
1874  if (mode != Requirements || printed) return 0;
1875  return builder->print (*this, out);
1876}
1877
1878//-------------------------------------------------------------
1879cmt_string Symbol::clean_macro_value () const
1880{
1881  cmt_string temp;
1882
1883  temp = builder->clean (*this);
1884
1885  return (temp);
1886}
1887
1888/**
1889
1890   Attempt to substitute into the symbol value all occurrences of
1891
1892      ${xxx}
1893      $(xxx)
1894      `xxx`
1895      %xxx%    [on Windows only]
1896
1897      by the appropriate value:
1898
1899        for `xxx` :
1900
1901            xxx is considered as a shell command. Value is the result of its execution
1902
1903        for other patterns:
1904
1905            if xxx is a symbol name, its value is substituted to the pattern
1906            otherwise, xxx is tried as an environment variable
1907
1908
1909     ===> In all cases, the pattern is filtered away.
1910
1911  */
1912cmt_string Symbol::resolve_macro_value (const cmt_string& tag_name) const
1913{
1914  cmt_string temp = builder->build (*this, tag_name);
1915
1916  resolve_value (temp);
1917
1918  return (temp);
1919}
1920
1921//-------------------------------------------------------------
1922void Symbol::show_macro (PrintMode mode, ostream& out)
1923//void Symbol::show_macro (PrintMode mode)
1924{
1925  if (Cmt::get_debug ())
1926    {
1927      cout << "Symbol::show_macro> " << name << endl;
1928    }
1929
1930  ActionType action = Cmt::get_action ();
1931
1932  cmt_string value = build_macro_value (true);
1933
1934  if ((!Cmt::get_quiet ()) &&
1935      (action != action_build_tag_makefile) &&
1936      (action != action_build_constituents_config) &&
1937      (action != action_build_constituent_config) &&
1938      (action != action_build_broadcast_config) &&
1939      (action != action_show_macros) &&
1940      (action != action_show_actions) &&
1941      (action != action_show_sets))
1942    {
1943      out << "#" << endl;
1944      out << "# Selection : " << endl;
1945    }
1946
1947  if (value.size () > 0)
1948    {
1949      if ((action == action_show_macro) ||
1950          (action == action_show_macros) ||
1951          (action == action_show_sets) ||
1952          (action == action_show_set) ||
1953          (action == action_show_actions) ||
1954          (action == action_show_action) ||
1955          (action == action_build_tag_makefile) ||
1956          (action == action_build_constituents_config) ||
1957          (action == action_build_constituent_config) ||
1958          (action == action_build_broadcast_config) ||
1959          (action == action_load) ||
1960          (!Cmt::get_quiet ()))
1961        {
1962          if (mode == Make)
1963            {
1964              out << name << "=";
1965            }
1966          else
1967            {
1968              out << name << "='";
1969            }
1970        }
1971
1972      if ((action == action_show_macro_value) ||
1973          (action == action_show_set_value) ||
1974          (action == action_show_action_value))
1975        {
1976          expand (value);
1977        }
1978      else if (action == action_build_tag_makefile ||
1979               action == action_build_constituents_config ||
1980               action == action_build_constituent_config ||
1981               action == action_build_broadcast_config)
1982        {
1983            /*
1984               Unfortunately, the %xxx% pattern has to be kept on Unix. Therefore
1985               we cannot force all patterns to become $(xxx)
1986
1987               This was useful on Windows so as to only keep $(xxx)
1988             */
1989#ifdef WIN32
1990          suppress_OS_delimiters (value);
1991#endif
1992        }
1993
1994      out << value;
1995
1996      if ((action == action_show_macro) ||
1997          (action == action_show_macros) ||
1998          (action == action_show_sets) ||
1999          (action == action_show_set) ||
2000          (action == action_show_actions) ||
2001          (action == action_show_action) ||
2002          (action == action_build_tag_makefile) ||
2003          (action == action_build_constituents_config) ||
2004          (action == action_build_constituent_config) ||
2005          (action == action_build_broadcast_config) ||
2006          (action == action_load) ||
2007          (!Cmt::get_quiet ()))
2008        {
2009          if (mode != Make)
2010            {
2011              out << "'";
2012            }
2013#ifdef WIN32
2014          else
2015            {
2016              out << " ";
2017            }
2018#endif
2019        }
2020
2021      out << endl;
2022    }
2023}
2024
2025//-------------------------------------------------------------
2026void Symbol::clear_all ()
2027{
2028  static SymbolVector& Symbols = symbols ();
2029  static SymbolMap& SymbolMap = symbol_map ();
2030
2031  SymbolMap.clear ();
2032  Symbols.clear ();
2033}
2034
2035//-------------------------------------------------------------
2036void Symbol::expand (cmt_string& text)
2037{
2038  static cmt_regexp reg ("[$%`]");
2039
2040  if (!reg.match (text)) return;
2041
2042  resolve_value (text);
2043}
2044
2045//-------------------------------------------------------------
2046ValueBuilder::ValueBuilder ()
2047{
2048  m_display_it = false;
2049}
2050
2051//-------------------------------------------------------------
2052const cmt_string ValueBuilder::build_and_display (const Symbol& symbol)
2053{
2054  cmt_string temp;
2055
2056  m_display_it = true;
2057  temp = build (symbol);
2058  m_display_it = false;
2059
2060  return (temp);
2061}
2062
2063//-------------------------------------------------------------
2064int ValueBuilder::print (const Symbol& symbol, ostream& out)
2065{
2066  int result (0);
2067
2068  bool first_definition = true;
2069 
2070  for (int i = 0; i < symbol.value_lists.size (); i++)
2071    {
2072      const SymbolValueList& value_list = symbol.value_lists[i];
2073
2074      if ((value_list.use != 0) &&
2075          (value_list.use->discarded)) continue;
2076
2077      const int selected = value_list.select_first ();
2078
2079      if (selected < 0) continue;
2080
2081      SymbolValue& value = value_list.values[selected];
2082
2083      result += value_list.print (symbol, value, first_definition);
2084    }
2085
2086  return result;
2087}
2088
2089//-------------------------------------------------------------
2090const cmt_string SetBuilder::build (const Symbol& symbol,
2091                                    const cmt_string& /*tag_name*/)
2092{
2093    // Control of recursivity
2094  static int level = 0;
2095
2096  bool show_it = false;
2097
2098  cmt_string temp;
2099  cmt_string previous_temp;
2100  cmt_string new_value;
2101  static const cmt_string empty;
2102
2103  ActionType action = Cmt::get_action ();
2104
2105  if (action == action_show_set)
2106    {
2107      if (symbol.name == Cmt::get_current_target ())
2108        {
2109             // Should not display on recursive calls
2110          if (level == 0) show_it = m_display_it;
2111        }
2112    }
2113
2114  level++;
2115
2116  temp = "";
2117
2118  bool first_definition = true;
2119
2120  for (int i = 0; i < symbol.value_lists.size (); i++)
2121    {
2122      const SymbolValueList& value_list = symbol.value_lists[i];
2123
2124      if ((value_list.use != 0) &&
2125          (value_list.use->discarded)) continue;
2126
2127      const int selected = value_list.select_first ();
2128
2129      if (selected < 0) continue;
2130
2131      SymbolValue& value = value_list.values[selected];
2132
2133      if (show_it && !Symbol::get_inhibit_display())
2134        {
2135          value_list.show (symbol, value, first_definition);
2136        }
2137     
2138      if (value_list.discarded) continue;
2139
2140        //
2141        // One should accumulate values if it refers to
2142        // itself.
2143        //
2144     
2145      new_value = value.text;
2146     
2147      resolve_value_for_macros (new_value);
2148     
2149      switch (value_list.command_type)
2150        {
2151          case CommandSet :
2152
2153            if (!value_list.is_reflexive || 
2154                !symbol.value_is_reflexive (value.text))
2155              {
2156                resolve_value (new_value, symbol.name, temp);
2157                temp = new_value;
2158              }
2159            else if (temp == "")
2160              {
2161                temp = CmtSystem::getenv (symbol.name);
2162              }
2163
2164            break;
2165          case CommandSetAppend :
2166           
2167            if (new_value != "")
2168              {
2169                temp += new_value;
2170              }
2171           
2172            break;
2173          case CommandSetPrepend :
2174           
2175            if (new_value != "")
2176              {
2177                previous_temp = temp;
2178                temp = new_value;
2179                temp += previous_temp;
2180              }
2181           
2182            break;
2183          case CommandSetRemove :
2184           
2185            if (new_value != "")
2186              {
2187                temp.replace_all (new_value, empty);
2188              }
2189           
2190            break;
2191          case CommandSetRemoveRegexp :
2192           
2193            if (new_value != "")
2194              {
2195                cmt_regexp e (new_value);
2196                cmt_regexp::iterator it;
2197
2198                for (;;)
2199                  {
2200                    it = e.begin (temp);
2201                    if (it == e.end ()) break;
2202
2203                    temp.erase (it._pos, it._length);
2204                  }
2205              }
2206           
2207            break;
2208          case CommandAlias :
2209           
2210            resolve_value (new_value, symbol.name, temp);
2211            temp = new_value;
2212           
2213            break;
2214        }
2215    }
2216
2217  level--;
2218
2219  return (temp);
2220}
2221
2222static bool find_path_entry (const CmtSystem::cmt_string_vector& items, const cmt_string& value)
2223{
2224  static const cmt_string path_separator = CmtSystem::path_separator ();
2225  static cmt_vmap <cmt_string, cmt_string> realpaths;
2226
2227  if (value.size () == 0) return true;
2228
2229  cmt_string rvalue;
2230  const cmt_string * prvalue;
2231
2232  if (!(prvalue = realpaths.find (value)))
2233    {
2234      if (!CmtSystem::realpath_ (value, rvalue))
2235        {
2236          rvalue = value;
2237          CmtSystem::compress_path (rvalue);
2238        }
2239      prvalue = &rvalue;
2240      realpaths.add (value, rvalue);
2241      //      cerr << "realpaths.add: " << value << " , " << rvalue << endl;
2242    }
2243
2244  //  CmtSystem::cmt_string_vector items;
2245  //  CmtSystem::split (paths, path_separator, items);
2246
2247  bool found = false;
2248
2249  for (int i = 0; i < items.size (); i++)
2250    {
2251      const cmt_string& item = items[i];
2252      if (item.size () == 0) continue;
2253      cmt_string ritem;
2254      const cmt_string * pritem;
2255
2256      if (!(pritem = realpaths.find (item)))
2257        {
2258          if (!CmtSystem::realpath_ (item, ritem))
2259            {
2260              ritem = item;
2261              CmtSystem::compress_path (ritem);
2262            }
2263          pritem = &ritem;
2264          realpaths.add (item, ritem);
2265          //  cerr << "realpaths.add: " << item << " , " << ritem << endl;
2266        }
2267      if (*pritem == *prvalue)
2268        {
2269          found = true;
2270          break;
2271        }
2272    }
2273
2274  return (found);
2275}
2276
2277static bool find_path_entry (const cmt_string& paths, const cmt_string& value)
2278{
2279  static const cmt_string path_separator = CmtSystem::path_separator ();
2280  static cmt_vmap <cmt_string, cmt_string> realpaths;
2281
2282  cmt_string rvalue;
2283  const cmt_string * prvalue;
2284
2285  if (!(prvalue = realpaths.find (value)))
2286    {
2287      if (!CmtSystem::realpath_ (value, rvalue))
2288        {
2289          rvalue = value;
2290          CmtSystem::compress_path (rvalue);
2291        }
2292      prvalue = &rvalue;
2293      realpaths.add (value, rvalue);
2294      //      cerr << "realpaths.add: " << value << " , " << rvalue << endl;
2295    }
2296
2297  CmtSystem::cmt_string_vector items;
2298  CmtSystem::split (paths, path_separator, items);
2299
2300  bool found = false;
2301
2302  for (int i = 0; i < items.size (); i++)
2303    {
2304      const cmt_string& item = items[i];
2305      cmt_string ritem;
2306      const cmt_string * pritem;
2307
2308      if (!(pritem = realpaths.find (item)))
2309        {
2310          if (!CmtSystem::realpath_ (item, ritem))
2311            {
2312              ritem = item;
2313              CmtSystem::compress_path (ritem);
2314            }
2315          pritem = &ritem;
2316          realpaths.add (item, ritem);
2317          //  cerr << "realpaths.add: " << item << " , " << ritem << endl;
2318        }
2319      if (*pritem == *prvalue)
2320        {
2321          found = true;
2322          break;
2323        }
2324    }
2325
2326  return (found);
2327}
2328
2329//-------------------------------------------------------------
2330const cmt_string PathBuilder::build (const Symbol& symbol,
2331                                     const cmt_string& /*tag_name*/)
2332{
2333    // Control of recursivity
2334  static int level = 0;
2335
2336  bool show_it = false;
2337
2338  cmt_string temp;
2339  CmtSystem::cmt_string_vector temp_vector;
2340  //  cmt_string previous_temp;
2341  CmtSystem::cmt_string_vector new_value_vector;
2342  cmt_string new_value;
2343  static const cmt_string empty;
2344
2345  static cmt_string path_separator = CmtSystem::path_separator ();
2346
2347  ActionType action = Cmt::get_action ();
2348
2349  if (action == action_show_set)
2350    {
2351      if (symbol.name == Cmt::get_current_target ())
2352        {
2353            // Should not display on recursive calls
2354          if (level == 0) show_it = m_display_it;
2355        }
2356    }
2357
2358  level++;
2359
2360  CmtSystem::split (CmtSystem::getenv (symbol.name), path_separator, temp_vector);
2361  //temp = CmtSystem::getenv (symbol.name);
2362
2363  bool first_definition = true;
2364
2365  for (int i = 0; i < symbol.value_lists.size (); i++)
2366    {
2367      const SymbolValueList& value_list = symbol.value_lists[i];
2368
2369      if ((value_list.use != 0) &&
2370          (value_list.use->discarded)) continue;
2371
2372      const int selected = value_list.select_first ();
2373     
2374      if (selected < 0) continue;
2375 
2376      SymbolValue& value = value_list.values[selected];
2377         
2378      if (show_it && !Symbol::get_inhibit_display())
2379        {
2380          value_list.show (symbol, value, first_definition);
2381        }
2382         
2383      if (value_list.discarded) continue;
2384
2385      new_value = value.text;
2386         
2387          //resolve_value (new_value);
2388      resolve_value_for_macros (new_value);
2389         
2390      switch (value_list.command_type)
2391        {
2392          case CommandPath :
2393           
2394            if (!value_list.is_reflexive || 
2395                !symbol.value_is_reflexive (value.text))
2396              {
2397                Cmt::vector_to_string (temp_vector, path_separator, temp);
2398                resolve_value (new_value, symbol.name, temp);
2399                CmtSystem::split (new_value, path_separator, temp_vector);
2400                //temp = new_value;
2401              }
2402
2403            break;
2404          case CommandPathAppend :
2405             
2406            if (new_value != "")
2407              {
2408                CmtSystem::split (new_value, path_separator, new_value_vector);
2409                for (int i = 0; i < new_value_vector.size (); i++)
2410                  if (!find_path_entry (temp_vector, new_value_vector[i]))
2411                    //if (!find_path_entry (temp, new_value))
2412                    {
2413                      temp_vector.push_back (new_value_vector[i]);
2414                      /*
2415                        if (temp != "") temp += path_separator;
2416                       
2417                        temp += new_value;
2418                      */
2419                    }
2420              }
2421                 
2422            break;
2423          case CommandPathPrepend :
2424             
2425            if (new_value != "")
2426              {
2427                CmtSystem::split (new_value, path_separator, new_value_vector);
2428                int n (new_value_vector.size ());
2429                temp_vector.resize (temp_vector.size () + n);
2430                for (int i = temp_vector.size () - 1; i > n - 1; i--)
2431                  temp_vector [i] = temp_vector [i - n];
2432                for (int i = 0; i < new_value_vector.size (); i++)
2433                  if (!find_path_entry (temp_vector, new_value_vector[i]))
2434                    //if (!find_path_entry (temp, new_value))
2435                    {
2436                      temp_vector [i] = new_value_vector[i];
2437                      /*
2438                        previous_temp = temp;
2439                        temp = new_value;
2440                        if (previous_temp != "") temp += path_separator;
2441                        temp += previous_temp;
2442                      */
2443                    }
2444                  else
2445                    temp_vector [i] = "";
2446              }
2447           
2448            break;
2449          case CommandPathRemove :
2450             
2451            if (new_value != "")
2452              {
2453                for (int j = 0; j < temp_vector.size (); ++j)
2454                  {
2455                    cmt_string& s = temp_vector[j];
2456                   
2457                    if (s.find (new_value) != cmt_string::npos)
2458                      {
2459                        s = "";
2460                      }
2461                  }
2462                /*
2463                CmtSystem::cmt_string_vector paths;
2464                 
2465                CmtSystem::split (temp, path_separator, paths);
2466                 
2467                for (int j = 0; j < paths.size (); ++j)
2468                  {
2469                    cmt_string& s = paths[j];
2470                     
2471                    if (s.find (new_value) != cmt_string::npos)
2472                      {
2473                        s = "";
2474                      }
2475                  }
2476
2477                Cmt::vector_to_string (paths, path_separator, temp);
2478                */
2479              }
2480             
2481            break;
2482          case CommandPathRemoveRegexp :
2483
2484            if (new_value != "")
2485              {
2486                cmt_regexp e (new_value);
2487
2488                for (int j = 0; j < temp_vector.size (); ++j)
2489                  {
2490                    cmt_string& s = temp_vector[j];
2491
2492                    if (Cmt::get_debug () &&
2493                        CmtSystem::getenv ("TESTPRR") != "")
2494                      {
2495                        cerr << "PRR> s=[" << s << "]";
2496                      }
2497
2498                    if (e.match (s))
2499                      {
2500                        s = "";
2501
2502                        if (Cmt::get_debug () &&
2503                            CmtSystem::getenv ("TESTPRR") != "")
2504                          {
2505                            cerr << " match ";
2506                          }
2507                      }
2508                    else
2509                      {
2510                        if (Cmt::get_debug () &&
2511                            CmtSystem::getenv ("TESTPRR") != "")
2512                          {
2513                            cerr << " no match ";
2514                          }
2515                      }
2516
2517                    if (Cmt::get_debug () &&
2518                        CmtSystem::getenv ("TESTPRR") != "")
2519                      {
2520                        cerr << endl;
2521                      }
2522                  }
2523
2524                /*
2525                CmtSystem::cmt_string_vector paths;
2526                 
2527                CmtSystem::split (temp, path_separator, paths);
2528                 
2529                for (int j = 0; j < paths.size (); ++j)
2530                  {
2531                    cmt_string& s = paths[j];
2532
2533                    if (CmtSystem::getenv ("TESTPRR") != "")
2534                      {
2535                        cerr << "PRR> s=[" << s << "]";
2536                      }
2537
2538                    if (e.match (s))
2539                      {
2540                        s = "";
2541
2542                        if (CmtSystem::getenv ("TESTPRR") != "")
2543                          {
2544                            cerr << " match ";
2545                          }
2546                      }
2547                    else
2548                      {
2549                        if (CmtSystem::getenv ("TESTPRR") != "")
2550                          {
2551                            cerr << " no match ";
2552                          }
2553                      }
2554
2555                    if (CmtSystem::getenv ("TESTPRR") != "")
2556                      {
2557                        cerr << endl;
2558                      }
2559                  }
2560
2561                Cmt::vector_to_string (paths, path_separator, temp);
2562                */
2563              }
2564             
2565            break;
2566        }
2567
2568    }
2569
2570  Cmt::vector_to_string (temp_vector, path_separator, temp);
2571
2572  level--;
2573
2574  for (;;)
2575    {
2576      int sz = temp.size ();
2577
2578      if (sz == 0) break;
2579
2580      if ((temp[0] == ';') || (temp[0] == ':'))
2581        {
2582          temp.erase (0, 1);
2583        }
2584      else if ((temp[sz-1] == ';') || (temp[sz-1] == ':'))
2585        {
2586          temp.erase (sz-1, 1);
2587        }
2588      else
2589        {
2590          break;
2591        }
2592    }
2593
2594  temp.replace_all ("::", ":");
2595  temp.replace_all (";;", ";");
2596 
2597  return (temp);
2598}
2599
2600//-------------------------------------------------------------
2601const cmt_string PathBuilder::clean (const Symbol& symbol,
2602                                     const cmt_string& /*tag_name*/)
2603{
2604    // Control of recursivity
2605  static int level = 0;
2606
2607  cmt_string temp;
2608  cmt_string new_value;
2609  static const cmt_string empty;
2610
2611  static cmt_string path_separator = CmtSystem::path_separator ();
2612
2613  temp = CmtSystem::getenv (symbol.name);
2614
2615    //cerr << "#####1 temp=" << temp << endl;
2616
2617  for (int i = 0; i < symbol.value_lists.size (); i++)
2618    {
2619      const SymbolValueList& value_list = symbol.value_lists[i];
2620
2621      if (value_list.discarded) continue;
2622
2623      if ((value_list.use != 0) &&
2624          (value_list.use->discarded)) continue;
2625
2626      const int selected = value_list.select_first ();
2627     
2628      if (selected < 0) continue;
2629 
2630      SymbolValue& value = value_list.values[selected];
2631         
2632      new_value = value.text;
2633         
2634          //resolve_value (new_value);
2635
2636        //cerr << "#####1 new_value=" << new_value << endl;
2637
2638      resolve_value_for_macros (new_value);
2639      resolve_value (new_value);
2640         
2641        //cerr << "#####2 new_value=" << new_value << endl;
2642
2643      switch (value_list.command_type)
2644        {
2645          case CommandPath :
2646           
2647            temp = "";
2648           
2649            break;
2650          case CommandPathAppend :
2651          case CommandPathPrepend :
2652          case CommandPathRemove :
2653
2654            if (new_value != "")
2655              {
2656                CmtSystem::cmt_string_vector paths;
2657                 
2658                CmtSystem::split (temp, path_separator, paths);
2659                 
2660                for (int j = 0; j < paths.size (); ++j)
2661                  {
2662                    cmt_string& s = paths[j];
2663                     
2664                    if (s.find (new_value) != cmt_string::npos)
2665                      {
2666                        s = "";
2667                      }
2668
2669                    if (j > 0)
2670                      {
2671                        cmt_string& s2 = paths[j-1];
2672                        if (s2 == s)
2673                          {
2674                            s2 = "";
2675                          }
2676                      }
2677                  }
2678
2679                Cmt::vector_to_string (paths, path_separator, temp);
2680                temp.replace_all ("::", ":");
2681                temp.replace_all (";;", ";");
2682              }
2683             
2684            break;
2685          case CommandPathRemoveRegexp :
2686
2687            if (new_value != "")
2688              {
2689                cmt_regexp e (new_value);
2690
2691                CmtSystem::cmt_string_vector paths;
2692                 
2693                CmtSystem::split (temp, path_separator, paths);
2694                 
2695                for (int j = 0; j < paths.size (); ++j)
2696                  {
2697                    cmt_string& s = paths[j];
2698                     
2699                    if (e.match (s))
2700                      {
2701                        s = "";
2702                      }
2703
2704                    if (j > 0)
2705                      {
2706                        cmt_string& s2 = paths[j-1];
2707                        if (s2 == s)
2708                          {
2709                            s2 = "";
2710                          }
2711                      }
2712                  }
2713
2714                Cmt::vector_to_string (paths, path_separator, temp);
2715                temp.replace_all ("::", ":");
2716                temp.replace_all (";;", ";");
2717              }
2718             
2719            break;
2720        }
2721    }
2722
2723    //cerr << "#####2 temp=" << temp << endl;
2724 
2725  return (temp);
2726}
2727
2728//-------------------------------------------------------------
2729const cmt_string MacroBuilder::build (const Symbol& symbol,
2730                                      const cmt_string& tag_name)
2731{
2732    // Control of recursivity
2733  static int level = 0;
2734
2735  cmt_string temp;
2736  cmt_string previous_temp;
2737  static const cmt_string empty;
2738  bool show_it = false;
2739
2740  ActionType action = Cmt::get_action ();
2741
2742  if (action == action_show_macro)
2743    {
2744      if (symbol.name == Cmt::get_current_target ())
2745        {
2746             // Should not display on recursive calls
2747          if (level == 0) show_it = m_display_it;
2748        }
2749    }
2750
2751  level++;
2752
2753  temp = "";
2754
2755  int i;
2756
2757  bool first_definition = true;
2758
2759  for (i = 0; i < symbol.value_lists.size (); i++)
2760    {
2761      const SymbolValueList& value_list = symbol.value_lists[i];
2762
2763      if ((value_list.use != 0) &&
2764          (value_list.use->discarded)) continue;
2765
2766      if (value_list.command_type != CommandMacroPrepend) continue;
2767
2768      const int selected = value_list.select_first (tag_name);
2769
2770      if (selected < 0) continue;
2771
2772      SymbolValue& value = value_list.values[selected];
2773
2774      if (show_it && !Symbol::get_inhibit_display())
2775        {
2776          value_list.show (symbol, value, first_definition);
2777        }
2778
2779      if (value_list.discarded) continue;
2780
2781      previous_temp = temp;
2782      temp = value.text;
2783      temp += previous_temp;
2784    }
2785
2786  previous_temp = temp;
2787  temp = "";
2788
2789  first_definition = true;
2790
2791  for (i = 0; i < symbol.value_lists.size (); i++)
2792    {
2793      const SymbolValueList& value_list = symbol.value_lists[i];
2794
2795      if ((value_list.use != 0) &&
2796          (value_list.use->discarded)) continue;
2797
2798      if (value_list.command_type != CommandMacro) continue;
2799
2800      const int selected = value_list.select_first (tag_name);
2801
2802      if (selected < 0) continue;
2803
2804      SymbolValue& value = value_list.values[selected];
2805
2806      if (show_it && !Symbol::get_inhibit_display())
2807        {
2808          value_list.show (symbol, value, first_definition);
2809        }
2810
2811      // WARNING:
2812      // Commented just for a test : should be uncommented after the test
2813      if (value_list.discarded) continue;
2814     
2815      if (!value_list.is_reflexive || 
2816          !symbol.value_is_reflexive (value.text))
2817        {
2818          temp = value.text;
2819        }
2820    }
2821
2822  previous_temp += temp;
2823  temp = previous_temp;
2824
2825  for (i = 0; i < symbol.value_lists.size (); i++)
2826    {
2827      const SymbolValueList& value_list = symbol.value_lists[i];
2828
2829      if ((value_list.use != 0) &&
2830          (value_list.use->discarded)) continue;
2831
2832      if (value_list.command_type != CommandMacroAppend) continue;
2833
2834      const int selected = value_list.select_first (tag_name);
2835
2836      if (selected < 0) continue;
2837
2838      SymbolValue& value = value_list.values[selected];
2839
2840      if (show_it && !Symbol::get_inhibit_display())
2841        {
2842          value_list.show (symbol, value, first_definition);
2843        }
2844
2845      if (value_list.discarded) continue;
2846
2847      temp += value.text;
2848    }
2849
2850  for (i = 0; i < symbol.value_lists.size (); i++)
2851    {
2852      const SymbolValueList& value_list = symbol.value_lists[i];
2853
2854      if ((value_list.use != 0) &&
2855          (value_list.use->discarded)) continue;
2856
2857      if ((value_list.command_type != CommandMacroRemove) &&
2858          (value_list.command_type != CommandMacroRemoveRegexp) &&
2859          (value_list.command_type != CommandMacroRemoveAll) &&
2860          (value_list.command_type != CommandMacroRemoveAllRegexp)) continue;
2861
2862      const int selected = value_list.select_first (tag_name);
2863
2864      if (selected < 0) continue;
2865
2866      SymbolValue& value = value_list.values[selected];
2867
2868      if (show_it && !Symbol::get_inhibit_display())
2869        {
2870          value_list.show (symbol, value, first_definition);
2871        }
2872
2873      if (value_list.discarded) continue;
2874
2875      switch (value_list.command_type)
2876        {
2877          case CommandMacroRemove :
2878            temp.replace (value.text, empty);
2879            break;
2880          case CommandMacroRemoveRegexp :
2881            if (value.text != "")
2882              {
2883                cmt_regexp e (value.text);
2884                cmt_regexp::iterator it;
2885
2886                it = e.begin (temp);
2887                if (it != e.end ())
2888                  {
2889                    temp.erase (it._pos, it._length);
2890                  }
2891              }
2892            break;
2893          case CommandMacroRemoveAll :
2894            temp.replace_all (value.text, empty);
2895            break;
2896          case CommandMacroRemoveAllRegexp :
2897            if (value.text != "")
2898              {
2899                cmt_regexp e (value.text);
2900                cmt_regexp::iterator it;
2901
2902                for (;;)
2903                  {
2904                    it = e.begin (temp);
2905                    if (it != e.end ())
2906                      {
2907                        temp.erase (it._pos, it._length);
2908                      }
2909                    else
2910                      {
2911                        break;
2912                      }
2913                  }
2914              }
2915            break;
2916        }
2917    }
2918
2919  level--;
2920
2921  return (temp);
2922}
2923
2924//-------------------------------------------------------------
2925const cmt_string ScriptBuilder::build (const Symbol& symbol,
2926                                       const cmt_string& tag_name)
2927{
2928    // Control of recursivity
2929  static int level = 0;
2930
2931  static const cmt_string empty = "";
2932
2933  if (symbol.value_lists.size () > 0)
2934    {
2935      const SymbolValueList& value_list = symbol.value_lists[0];
2936
2937      if (value_list.discarded) return (empty);
2938
2939      if ((value_list.use != 0) &&
2940          (value_list.use->discarded)) return (empty);
2941    }
2942
2943  return (symbol.name);
2944}
2945
2946//-------------------------------------------------------------
2947const cmt_string ActionBuilder::build (const Symbol& symbol,
2948                                       const cmt_string& tag_name)
2949{
2950    // Control of recursivity
2951  static int level = 0;
2952
2953  cmt_string temp;
2954  cmt_string previous_temp;
2955  static const cmt_string empty;
2956  bool show_it = false;
2957
2958  ActionType action = Cmt::get_action ();
2959
2960  if (action == action_show_action)
2961    {
2962      if (symbol.name == Cmt::get_current_target ())
2963        {
2964             // Should not display on recursive calls
2965          if (level == 0) show_it = m_display_it;
2966        }
2967    }
2968
2969  level++;
2970
2971  int i;
2972
2973  bool first_definition = true;
2974
2975  temp = "";
2976
2977  for (i = 0; i < symbol.value_lists.size (); i++)
2978    {
2979      const SymbolValueList& value_list = symbol.value_lists[i];
2980
2981      if ((value_list.use != 0) &&
2982          (value_list.use->discarded)) continue;
2983
2984      if (value_list.command_type != CommandAction) continue;
2985
2986      const int selected = value_list.select_first (tag_name);
2987
2988      if (selected < 0) continue;
2989
2990      SymbolValue& value = value_list.values[selected];
2991
2992      if (show_it && !Symbol::get_inhibit_display())
2993        {
2994          value_list.show (symbol, value, first_definition);
2995        }
2996
2997      // WARNING:
2998      // Commented just for a test : should be uncommented after the test
2999      if (value_list.discarded) continue;
3000     
3001      if (!value_list.is_reflexive || 
3002          !symbol.value_is_reflexive (value.text))
3003        {
3004          temp = value.text;
3005        }
3006    }
3007
3008  level--;
3009
3010  return (temp);
3011}
3012
3013//-------------------------------------------------------------
3014int SymbolValueList::select_first (const cmt_string& tag_name) const
3015{
3016  int priority = 0;
3017  int value_number;
3018  int selected = -1;
3019
3020  Tag* the_tag = 0;
3021
3022  if (tag_name != "") the_tag = Tag::find (tag_name);
3023
3024  for (value_number = 0;
3025       value_number < values.size ();
3026       value_number++)
3027    {
3028      const SymbolValue& value = values[value_number];
3029
3030      const Tag* tag = value.tag;
3031
3032      if (the_tag == 0)
3033        {
3034          if (!tag->is_selected ()) continue;
3035          selected = value_number;
3036          if (tag == Tag::get_default ())
3037            continue;
3038        }
3039      else
3040        {
3041          if (tag != the_tag) continue;
3042          selected = value_number;
3043        }
3044
3045      //
3046      // Only the value for the first alternative (i.e. non-default)
3047      // matching tag expression is
3048      // selected (which means the selection stops here)
3049      //
3050      break;
3051
3052      //
3053      // Only the first value at a given priority is
3054      // selected (which implies the '>' test instead
3055      // of '>=')
3056      //
3057      /*
3058      if (tag->get_priority () > priority)
3059        {
3060          priority = tag->get_priority ();
3061          selected = value_number;
3062        }
3063      */
3064    }
3065
3066  return (selected);
3067}
3068
3069//-------------------------------------------------------------
3070int SymbolValueList::select_last () const
3071{
3072  int priority = 0;
3073  int value_number;
3074  int selected = -1;
3075
3076  for (value_number = 0;
3077       value_number < values.size ();
3078       value_number++)
3079    {
3080      SymbolValue& value = values[value_number];
3081
3082      const Tag* tag = value.tag;
3083
3084      if (tag->is_selected ())
3085        {
3086          //
3087          // The last value at a given priority is
3088          // selected (which implies the '>=' test instead
3089          // of '>')
3090          //
3091
3092          if (tag->get_priority () >= priority)
3093            {
3094              priority = tag->get_priority ();
3095              selected = value_number;
3096            }
3097        }
3098    }
3099
3100  return (selected);
3101}
3102
3103//-------------------------------------------------------------
3104void SymbolValueList::show (const Symbol& symbol, 
3105                            const SymbolValue& value, 
3106                            bool& first_definition) const
3107{
3108  cmt_string discarded_text;
3109  cmt_string define_text;
3110  ActionType action = Cmt::get_action ();
3111
3112  switch (command_type)
3113    {
3114      //case CommandSet :
3115      case CommandSetAppend :
3116      case CommandSetPrepend :
3117      case CommandSetRemove :
3118      case CommandSetRemoveRegexp :
3119        //case CommandAlias :
3120        //case CommandPath :
3121      case CommandPathAppend :
3122      case CommandPathPrepend :
3123      case CommandPathRemove :
3124      case CommandPathRemoveRegexp :
3125      case CommandMacroPrepend :
3126        //case CommandMacro :
3127      case CommandMacroAppend :
3128      case CommandMacroRemove :
3129      case CommandMacroRemoveRegexp :
3130      case CommandMacroRemoveAll :
3131      case CommandMacroRemoveAllRegexp :
3132        //case CommandAction :
3133        if (value.text == "") return;
3134        break;
3135    }
3136
3137  if (discarded) discarded_text = " (discarded by override)";
3138  else discarded_text = "";
3139
3140  if (first_definition) define_text = "defines";
3141  else define_text = "overrides";
3142
3143  cout << "# Package ";
3144  if (use != 0)
3145    {
3146      cout << use->get_package_name () << " " << use->version;
3147    }
3148
3149  switch (command_type)
3150    {
3151      case CommandSet :
3152        cout << " " << define_text << " set " << symbol.name << " as ";
3153        first_definition = false;
3154        break;
3155      case CommandSetAppend :
3156        cout << " appends to set " << symbol.name << " : ";
3157        break;
3158      case CommandSetPrepend :
3159        cout << " prepends to set " << symbol.name << " : ";
3160        break;
3161      case CommandSetRemove :
3162        cout << " removes from set " << symbol.name << " : ";
3163        break;
3164      case CommandSetRemoveRegexp :
3165        cout << " removes RE from set " << symbol.name << " : ";
3166        break;
3167      case CommandAlias :
3168        cout << " " << define_text << " alias " << symbol.name << " as ";
3169        first_definition = false;
3170        break;
3171      case CommandPath :
3172        cout << " " << define_text << " path " << symbol.name << " as ";
3173        first_definition = false;
3174        break;
3175      case CommandPathAppend :
3176        cout << " appends to path " << symbol.name << " : ";
3177        break;
3178      case CommandPathPrepend :
3179        cout << " prepends to path " << symbol.name << " : ";
3180        break;
3181      case CommandPathRemove :
3182        cout << " removes from path " << symbol.name << " : ";
3183        break;
3184      case CommandPathRemoveRegexp :
3185        cout << " removes RE from path " << symbol.name << " : ";
3186        break;
3187      case CommandMacroPrepend :
3188        cout << " prepends to macro " << symbol.name << " : ";
3189        break;
3190      case CommandMacro :
3191        cout << " " << define_text << " macro " << symbol.name << " as ";
3192        break;
3193      case CommandMacroAppend :
3194        cout << " appends to macro " << symbol.name << " : ";
3195        break;
3196      case CommandMacroRemove :
3197        cout << " remove from macro " << symbol.name << " : ";
3198        break;
3199      case CommandMacroRemoveRegexp :
3200        cout << " remove RE from macro " << symbol.name << " : ";
3201        break;
3202      case CommandMacroRemoveAll :
3203        cout << " remove all from macro " << symbol.name << " : ";
3204        break;
3205      case CommandMacroRemoveAllRegexp :
3206        cout << " remove all RE from macro " << symbol.name << " : ";
3207        break;
3208      case CommandAction :
3209        cout << " " << define_text << " action " << symbol.name << " as ";
3210        first_definition = false;
3211        break;
3212    }
3213
3214  cout << "'" << value.text << "'";
3215         
3216  Tag* selected_tag = value.tag;
3217         
3218  if ((selected_tag == 0) ||
3219      (selected_tag == Tag::get_default ()))
3220    {
3221      cout << " for default tag";
3222    }
3223  else
3224    {
3225      cout << " for tag '" << selected_tag->get_name () << "'";
3226    }
3227 
3228  cout << discarded_text << endl;
3229}
3230
3231//-------------------------------------------------------------
3232int SymbolValueList::print (const Symbol& symbol, 
3233                            const SymbolValue& value, 
3234                            bool& first_definition) const
3235{
3236  int result (0);
3237
3238  //if (use->get_package_name () == "CMT") return result;
3239
3240  cmt_string discarded_text;
3241  cmt_string define_text;
3242  ActionType action = Cmt::get_action ();
3243
3244  switch (command_type)
3245    {
3246      //case CommandSet :
3247      case CommandSetAppend :
3248      case CommandSetPrepend :
3249      case CommandSetRemove :
3250      case CommandSetRemoveRegexp :
3251        //case CommandAlias :
3252        //case CommandPath :
3253      case CommandPathAppend :
3254      case CommandPathPrepend :
3255      case CommandPathRemove :
3256      case CommandPathRemoveRegexp :
3257      case CommandMacroPrepend :
3258        //case CommandMacro :
3259      case CommandMacroAppend :
3260      case CommandMacroRemove :
3261      case CommandMacroRemoveRegexp :
3262      case CommandMacroRemoveAll :
3263      case CommandMacroRemoveAllRegexp :
3264        //case CommandAction :
3265        if (value.text == "") return result;
3266        break;
3267    }
3268
3269  if (discarded) discarded_text = " (discarded by override)";
3270  else discarded_text = "";
3271
3272  if (first_definition) define_text = "defines";
3273  else define_text = "overrides";
3274
3275  if (CmtMessage::active (Verbose))
3276    cout << "# Package " << (use != 0 ? use->get_package_name () + " " + use->version : "");
3277  /*
3278  if (use != 0)
3279    {
3280      cout << use->get_package_name () << " " << use->version;
3281    }
3282  */
3283
3284  switch (command_type)
3285    {
3286      case CommandSet :
3287        if (CmtMessage::active (Verbose))
3288          cout << " " << define_text << " set " << symbol.name << " as " << endl;
3289        //        cout << " " << define_text << " set " << symbol.name << " as ";
3290        cout << "set " << symbol.name;
3291        first_definition = false;
3292        result = 1;
3293        break;
3294      case CommandSetAppend :
3295        if (CmtMessage::active (Verbose))
3296          cout << " appends to set " << symbol.name << " : " << endl;
3297        //        cout << " appends to set " << symbol.name << " : ";
3298        cout << "set_append " << symbol.name;
3299        result = 1;
3300        break;
3301      case CommandSetPrepend :
3302        if (CmtMessage::active (Verbose))
3303          cout << " prepends to set " << symbol.name << " : " << endl;
3304        //        cout << " prepends to set " << symbol.name << " : ";
3305        cout << "set_prepend " << symbol.name;
3306        result = 1;
3307        break;
3308      case CommandSetRemove :
3309        if (CmtMessage::active (Verbose))
3310          cout << " removes from set " << symbol.name << " : " << endl;
3311        //        cout << " removes from set " << symbol.name << " : ";
3312        cout << "set_remove " << symbol.name;
3313        result = 1;
3314        break;
3315      case CommandSetRemoveRegexp :
3316        if (CmtMessage::active (Verbose))
3317          cout << " removes RE from set " << symbol.name << " : " << endl;
3318        //        cout << " removes RE from set " << symbol.name << " : ";
3319        cout << "set_remove_regexp " << symbol.name;
3320        result = 1;
3321        break;
3322      case CommandAlias :
3323        if (CmtMessage::active (Verbose))
3324          cout << " " << define_text << " alias " << symbol.name << endl;
3325        //        cout << " " << define_text << " alias " << symbol.name << " as ";
3326        cout << "alias " << symbol.name;
3327        first_definition = false;
3328        result = 1;
3329        break;
3330      case CommandPath :
3331        if (CmtMessage::active (Verbose))
3332          cout << " " << define_text << " path " << symbol.name << endl;
3333        //        cout << " " << define_text << " path " << symbol.name << " as ";
3334        cout << "path " << symbol.name;
3335        first_definition = false;
3336        result = 1;
3337        break;
3338      case CommandPathAppend :
3339        if (CmtMessage::active (Verbose))
3340          cout << " appends to path " << symbol.name << endl;
3341        //        cout << " appends to path " << symbol.name << " : ";
3342        cout << "path_append " << symbol.name;
3343        result = 1;
3344        break;
3345      case CommandPathPrepend :
3346        if (CmtMessage::active (Verbose))
3347          cout << " prepends to path " << symbol.name << " : " << endl;
3348        //        cout << " prepends to path " << symbol.name << " : ";
3349        cout << "path_prepend " << symbol.name;
3350        result = 1;
3351        break;
3352      case CommandPathRemove :
3353        if (CmtMessage::active (Verbose))
3354          cout << " removes from path " << symbol.name << " : " << endl;
3355        //        cout << " removes from path " << symbol.name << " : ";
3356        cout << "path_remove " << symbol.name;
3357        result = 1;
3358        break;
3359      case CommandPathRemoveRegexp :
3360        if (CmtMessage::active (Verbose))
3361          cout << " removes RE from path " << symbol.name << " : " << endl;
3362        //        cout << " removes RE from path " << symbol.name << " : ";
3363        cout << "path_remove_regexp " << symbol.name;
3364        result = 1;
3365        break;
3366      case CommandMacro :
3367        if (CmtMessage::active (Verbose))
3368          cout << " " << define_text << " macro " << symbol.name << " as " << endl;
3369        //        cout << " " << define_text << " macro " << symbol.name << " as ";
3370        cout << "macro " << symbol.name;
3371        result = 1;
3372        break;
3373      case CommandMacroPrepend :
3374        if (CmtMessage::active (Verbose))
3375          cout << " prepends to macro " << symbol.name << " : " << endl;
3376        //        cout << " prepends to macro " << symbol.name << " : ";
3377        cout << "macro_prepend " << symbol.name;
3378        result = 1;
3379        break;
3380      case CommandMacroAppend :
3381        if (CmtMessage::active (Verbose))
3382          cout << " appends to macro " << symbol.name << " : " << endl;
3383        //        cout << " appends to macro " << symbol.name << " : ";
3384        cout << "macro_append " << symbol.name;
3385        result = 1;
3386        break;
3387      case CommandMacroRemove :
3388        if (CmtMessage::active (Verbose))
3389          cout << " remove from macro " << symbol.name << " : " << endl;
3390        //        cout << " remove from macro " << symbol.name << " : ";
3391        cout << "macro_remove " << symbol.name;
3392        result = 1;
3393        break;
3394      case CommandMacroRemoveRegexp :
3395        if (CmtMessage::active (Verbose))
3396          cout << " remove RE from macro " << symbol.name << " : " << endl;
3397        //        cout << " remove RE from macro " << symbol.name << " : ";
3398        cout << "macro_remove_regexp " << symbol.name;
3399        result = 1;
3400        break;
3401      case CommandMacroRemoveAll :
3402        if (CmtMessage::active (Verbose))
3403          cout << " remove all from macro " << symbol.name << " : " << endl;
3404        //        cout << " remove all from macro " << symbol.name << " : ";
3405        cout << "macro_remove_all " << symbol.name;
3406        result = 1;
3407        break;
3408      case CommandMacroRemoveAllRegexp :
3409        if (CmtMessage::active (Verbose))
3410          cout << " remove all RE from macro " << symbol.name << " : " << endl;
3411        //        cout << " remove all RE from macro " << symbol.name << " : ";
3412        cout << "macro_remove_all_regexp " << symbol.name;
3413        result = 1;
3414        break;
3415      case CommandSetupScript :
3416        if (CmtMessage::active (Verbose))
3417          cout << " " << define_text << " setup script " << symbol.name << endl;
3418        //       cout << " " << define_text << " action " << symbol.name << " as ";
3419        cout << "setup_script" /* << symbol.name */;
3420        first_definition = false;
3421        result = 1;
3422        break;
3423        /*
3424      case CommandAction :
3425        cout << " " << define_text << " action " << symbol.name << " as ";
3426        first_definition = false;
3427        break;
3428        */
3429    }
3430
3431  cout << " " << CmtSystem::quote (value.text, " \t");
3432  //  cout << "'" << value.text << "'";
3433         
3434  /*
3435  Tag* selected_tag = value.tag;
3436         
3437  if ((selected_tag == 0) ||
3438      (selected_tag == Tag::get_default ()))
3439    {
3440      cout << " for default tag";
3441    }
3442  else
3443    {
3444      cout << " for tag '" << selected_tag->get_name () << "'";
3445    }
3446  */
3447
3448  cout << endl;
3449  //  cout << discarded_text << endl;
3450  return result;
3451}
3452
3453//-------------------------------------------------------------
3454bool Symbol::check_tag_used (const Tag* tag)
3455{
3456  if (tag == 0) return (false);
3457
3458  static SymbolVector& Symbols = symbols ();
3459
3460  if (Symbols.size () == 0) 
3461    {
3462      return (false);
3463    }
3464
3465  for (int number = 0; number < Symbol::symbol_number (); number++)
3466    {
3467      Symbol& symbol = Symbol::symbol (number);
3468
3469      for (int i = 0; i < symbol.value_lists.size (); i++)
3470        {
3471          const SymbolValueList& value_list = symbol.value_lists[i];
3472
3473          for (int j = 0; j < value_list.values.size (); j++)
3474            {
3475              const SymbolValue& value = value_list.values[j];
3476              Tag* t = value.tag;
3477
3478              if (t != 0)
3479                {
3480                  if (t->use_operand (tag)) return (true);
3481                }
3482            }
3483        }
3484    }
3485
3486  return (false);
3487}
3488
3489//-------------------------------------------------------------
3490cmt_string Symbol::get_env_value (const cmt_string& name)
3491{
3492  cmt_string s;
3493
3494  Symbol* symbol = Symbol::find (name);
3495  if (symbol != 0)
3496    {
3497      m_inhibit_display = true;
3498
3499      s = symbol->build_macro_value ();
3500      Symbol::expand (s);
3501
3502      m_inhibit_display = false;
3503    }
3504  else
3505    {
3506      s = CmtSystem::getenv (name);
3507    }
3508
3509  return (s);
3510}
3511
3512bool Symbol::get_inhibit_display ()
3513{
3514  return (m_inhibit_display);
3515}
3516
Note: See TracBrowser for help on using the repository browser.