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

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

See C.L. 432

  • Property svn:eol-style set to native
File size: 73.2 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
777                CmtMessage::warning ("Symbol " + name
778                                     + " inconsistently redeclared from " + s1
779                                     + " to " + s2
780                                     + ( (use != 0) ?
781                                         " in package " + use->get_package_name () :
782                                         "" )
783                                     );
784                /*
785                cerr << "#CMT> Warning: Symbol " << name
786                     << " inconsistently redeclared from " << s1 << " to " << s2;
787                if (use != 0) cerr << " in package " << use->get_package_name ();
788                cerr << endl;
789                */
790              }
791          }
792
793        return (symbol);
794      }
795  }
796
797  Symbol& symbol = Symbols.add ();
798  SymbolMap.add (name, symbol);
799
800  symbol.name  = name;
801  symbol.scope = use->get_current_scope ();
802  symbol.type  = type;
803
804  symbol.value_lists.clear ();
805
806  switch (type)
807    {
808    case SymbolSet:
809      symbol.builder = &Set;
810      break;
811    case SymbolPath:
812      symbol.builder = &Path;
813      break;
814    case SymbolAlias:
815      symbol.builder = &Set;
816      break;
817    case SymbolMacro:
818      symbol.builder = &Macro;
819      break;
820    case SymbolSetupScript:
821    case SymbolCleanupScript:
822      symbol.builder = &Script;
823      break;
824    case SymbolAction:
825      symbol.builder = &Action;
826      break;
827    }
828
829  symbol.selected_value = -1;
830
831  return (&symbol);
832}
833
834//-------------------------------------------------------------
835Symbol* Symbol::find (const cmt_string& name)
836{
837  static SymbolMap& SymbolMap = symbol_map ();
838
839  Symbol* result = 0;
840
841  result = SymbolMap.find (name);
842
843  return (result);
844}
845
846//-------------------------------------------------------------
847int Symbol::symbol_number ()
848{
849  static SymbolVector& Symbols = symbols ();
850
851  return (Symbols.size ());
852}
853
854//-------------------------------------------------------------
855Symbol::SymbolVector& Symbol::symbols ()
856{
857  static Database& db = Database::instance ();
858  static SymbolVector& Symbols = db.symbols ();
859
860  return (Symbols);
861}
862
863//-------------------------------------------------------------
864Symbol::SymbolMap& Symbol::symbol_map ()
865{
866  static Database& db = Database::instance ();
867  static SymbolMap& SymbolMap = db.symbol_map ();
868
869  return (SymbolMap);
870}
871
872/**
873   Filter out faulty items of a path-like symbol value
874 */
875void Symbol::filter_path_value (const cmt_string& name, cmt_string& text)
876{
877
878  CmtSystem::cmt_string_vector paths;
879  CmtSystem::cmt_string_vector normalyzed_paths;   
880                 
881  CmtSystem::split (text, CmtSystem::path_separator (), paths);
882                 
883  for (int j = 0; j < paths.size (); ++j)
884    {
885      cmt_string& t = paths[j];
886
887      if (!CmtSystem::test_directory (t))
888          {
889            if (CmtMessage::active (Verbose))
890              CmtMessage::warning ("Non-existent directory " + t + " in " + name);
891            /*
892              if (Cmt::get_warnings ())
893              {
894                  cerr << "#CMT> Warning: Wrong path item " << t << " in " << name << endl;
895              }
896            */
897          }
898           
899      int exist = 0; 
900      for (int i = 0; i < j; ++i)
901      {
902          cmt_string& u = paths[i];
903          if (u == t)
904             exist = 1;
905      }           
906      if (exist==0)
907      {
908          cmt_string& s = normalyzed_paths.add ();
909          s = t;
910      }             
911    }
912   
913  Cmt::vector_to_string (normalyzed_paths, CmtSystem::path_separator (), text);
914
915  for (;;)
916    {
917      int sz = text.size ();
918
919      if (sz == 0) break;
920
921      if ((text[0] == ';') || (text[0] == ':'))
922        {
923          text.erase (0, 1);
924        }
925      else if ((text[sz-1] == ';') || (text[sz-1] == ':'))
926        {
927          text.erase (sz-1, 1);
928        }
929      else
930        {
931          break;
932        }
933    }
934
935  text.replace_all ("::", ":");
936  text.replace_all (";;", ";");
937}
938
939
940//-------------------------------------------------------------
941Symbol& Symbol::symbol (int index)
942{
943  static SymbolVector& Symbols = symbols ();
944
945  return (Symbols[index]);
946}
947
948//-------------------------------------------------------------
949void Symbol::action (const CmtSystem::cmt_string_vector& words,
950                     CommandType command_type,
951                     Use* use)
952{
953  int number;
954  Symbol* symbol;
955  Tag* tag;
956
957  if (words.size () < 1) return;
958  cmt_string name = words[1];
959
960  if ((command_type == CommandSetupScript) ||
961      (command_type == CommandCleanupScript))
962    {
963      cmt_string full_name;
964
965      Symbol::expand (name);
966
967      if (name != "")
968        {
969          if (CmtSystem::absolute_path (name)) 
970            {
971              full_name = name;
972            }
973          else
974            {
975              if (use->get_strategy ("SetupRoot") &&
976                  use->get_package_name () != "cmt_standalone")
977                {
978#ifdef WIN32
979              full_name = "%";
980#else
981              full_name = "${";
982#endif
983              full_name += use->prefix;
984              full_name += "ROOT";
985#ifdef WIN32
986              full_name += "%";
987#else
988              full_name += "}";
989#endif
990                }
991              else
992                {
993              full_name = use->get_full_path ();
994                }
995              if (use->style == cmt_style)
996                {
997                  full_name += CmtSystem::file_separator ();
998                  full_name += "cmt";
999                }
1000              else if (use->style == mgr_style)
1001                {
1002                  full_name += CmtSystem::file_separator ();
1003                  full_name += "mgr";
1004                }
1005              //              else if (use->style == no_version_style) full_name += "cmt";
1006              //              else full_name += "mgr";
1007              full_name += CmtSystem::file_separator ();
1008              full_name += name;
1009            }
1010
1011          symbol = create (full_name, command_type, use);
1012          symbol->add_value_to_list (command_type, use,
1013                                     Tag::get_default (), full_name);
1014        }
1015    }
1016  else
1017    {
1018      if (words.size () < 2) return;
1019      const cmt_string& default_value = words[2];
1020
1021      Cmt::reset_all_sets_done ();
1022
1023      if (Cmt::get_debug ())
1024        {
1025          cout << "Symbol::action> name:" << name
1026               << " access:" << Cmt::get_current_access () 
1027               << " scope:" << use->get_current_scope () << endl;
1028        }
1029
1030      if (Cmt::get_current_access () == UserMode)
1031        {
1032          /*
1033            The following statements mean that some symbols are
1034            always private.
1035            This list is hardcoded. This should be replaced by a
1036            database of "private" symbols.
1037           */
1038          if (name == "constituents") return;
1039          if (name == "constituentscclean") return;
1040
1041          if (use->get_current_scope () == ScopePrivate) return;
1042        }
1043
1044      symbol = create (name, command_type, use);
1045
1046      /*
1047        Parse the default value.
1048      */
1049     
1050      symbol->add_value_to_list (command_type, use,
1051                                 Tag::get_default (), default_value);
1052     
1053      /*
1054        Then parse all specific values
1055       
1056        <tag> <value>
1057        ...
1058      */
1059     
1060      number = 3;
1061      while (number < (words.size () - 1))
1062        {
1063          cmt_string tag_name = words[number];
1064          const cmt_string& value = words[number + 1];
1065
1066          expand (tag_name);
1067
1068          if (Cmt::get_debug ())
1069            {
1070              cout << "Symbol::action> tag_name=" << tag_name << endl;
1071            }
1072
1073          tag = Tag::find (tag_name);
1074          if (tag == 0)
1075            {
1076              tag = Tag::add (tag_name, PriorityUserTag, "use", use);
1077            }
1078
1079          symbol->add_value_to_list (command_type, use, tag, value);
1080         
1081          number += 2;
1082        }
1083
1084      if (name == "CMTPATH")
1085        {
1086          Cmt::configure_cmt_path (use);
1087        }
1088      else if (name == "CMTPROJECTPATH")
1089        {
1090          Cmt::configure_cmt_path (use);
1091        }
1092      else if (name == "CMTSITE")
1093        {
1094          Cmt::configure_site_tag (use);
1095        }
1096      else if (name == "CMTCONFIG")
1097        {
1098            //cerr << "redefining CMTCONFIG" << endl;
1099          Cmt::configure_tags (use);
1100        }
1101      else if (name == "CMTHOME")
1102        {
1103          Cmt::configure_home (use);
1104        }
1105      else if (name == "CMTUSERCONTEXT")
1106        {
1107          Cmt::configure_user_context (use);
1108        }
1109      else if (name.find ("_native_version") != cmt_string::npos)
1110        {
1111          cmt_string n = use->get_package_name ();
1112          n += "_native_version";
1113
1114          if (name == n)
1115            {
1116              use->set_native_version (true);
1117            }
1118        }
1119    }
1120}
1121
1122//-------------------------------------------------------------
1123int Symbol::is_selected (const cmt_string& name)
1124{
1125  Symbol* symbol;
1126  int number;
1127  int value_number;
1128
1129  symbol = find (name);
1130  if (symbol == 0) return (0);
1131
1132  if (symbol->value_lists.size () == 0) return (0);
1133
1134  for (number = 0;
1135       number < symbol->value_lists.size ();
1136       number++)
1137    {
1138      const SymbolValueList& value_list = symbol->value_lists[number];
1139
1140      if (value_list.discarded) continue;
1141
1142      if ((value_list.command_type == CommandMacro) ||
1143          (value_list.command_type == CommandSet) ||
1144          (value_list.command_type == CommandSetAppend) ||
1145          (value_list.command_type == CommandSetPrepend) ||
1146          (value_list.command_type == CommandSetRemove) ||
1147          (value_list.command_type == CommandSetRemoveRegexp) ||
1148          (value_list.command_type == CommandAlias) ||
1149          (value_list.command_type == CommandAction))
1150        {
1151          for (value_number = 0;
1152               value_number < value_list.values.size ();
1153               value_number++)
1154            {
1155              Tag* tag;
1156
1157              SymbolValue& value = value_list.values[value_number];
1158
1159              tag = value.tag;
1160              if ((tag == 0) ||
1161                  (tag == Tag::get_default ()) ||
1162                  (tag->is_selected () != 0))
1163                {
1164                  return (1);
1165                }
1166            }
1167        }
1168    }
1169
1170  return (0);
1171}
1172
1173//-------------------------------------------------------------
1174Symbol::Symbol ()
1175{
1176  name = "";
1177}
1178
1179//-------------------------------------------------------------
1180Symbol::~Symbol ()
1181{
1182}
1183
1184/**
1185 *  Characterizes if a value is provided as the reference to itself.
1186 */
1187bool Symbol::value_is_reflexive (const cmt_string& text) const
1188{
1189  bool result = false;
1190  int text_length = text.size ();
1191
1192  if (text_length == (name.size () + 3))
1193    {
1194      static cmt_string temp;
1195             
1196      if (text[0] == '$')
1197        {
1198          if (text[1] == '(')
1199            {
1200              temp = "$(";
1201              temp += name;
1202              temp += ")";
1203             
1204              if (text == temp)
1205                {
1206                  result = true;
1207                }
1208            }
1209          else if (text[1] == '{')
1210            {
1211              temp = "${";
1212              temp += name;
1213              temp += "}";
1214             
1215              if (text == temp)
1216                {
1217                  result = true;
1218                }
1219            }
1220        }
1221    }
1222  else if (text_length == (name.size () + 2))
1223    {
1224      static cmt_string temp;
1225
1226      temp = "%";
1227      temp += name;
1228      temp += "%";
1229
1230      if (text == temp)
1231        {
1232          result = true;
1233        }
1234    }
1235
1236  return (result);
1237}
1238
1239//-------------------------------------------------------------
1240void Symbol::add_value_to_list (CommandType command_type,
1241                                Use* use,
1242                                Tag* tag,
1243                                const cmt_string& text)
1244{
1245  SymbolValueList* value_list = 0;
1246  bool is_reflexive = false;
1247
1248    //
1249    // First pickup the most recent value_list
1250    //
1251  if (value_lists.size () > 0) value_list = &(value_lists.back ());
1252
1253    //
1254    //  Create a new value list is we switch to another use or
1255    //  if we switch to a new command_type (eg. switching from
1256    //  macro to macro_append).
1257    //
1258  if ((value_list == 0) ||
1259      (use != value_list->use) ||
1260      (command_type != value_list->command_type) ||
1261      (tag == Tag::get_default ()))
1262    {
1263      value_list = &(value_lists.add ());
1264      value_list->use = use;
1265      value_list->command_type = command_type;
1266      value_list->values.clear ();
1267      value_list->discarded = false;
1268      value_list->is_reflexive = false;
1269    }
1270
1271/*
1272  else
1273    {
1274        value_list = &(value_lists[value_lists.size () - 1]);
1275    }
1276*/
1277
1278  is_reflexive = value_list->is_reflexive;
1279
1280    //
1281    //  If the command_type is command_macro or command_set,
1282    // this is considered as a full re-set of this symbol
1283    //   In this case, we have to discard all previous values
1284    //
1285    //  However, we'd like to exclude from this logic the cases where
1286    //  the value is **exactly*
1287    //
1288    //     $(<symbol>)
1289    //     ${<symbol>}
1290    //     %<symbol>%
1291    //
1292    //   which would then mean that we do not reset the value but rather
1293    //  override it.
1294    //
1295
1296    //
1297    // Inside this value_list, we add this new tag-value pair.
1298    //
1299
1300  if ((command_type == CommandMacro) ||
1301      (command_type == CommandSet) ||
1302      (command_type == CommandPath) ||
1303      (command_type == CommandAction))
1304    {
1305        //
1306        // Check whether we have to hide previous settings by this new definition
1307        //  (of course this is only useful if there WERE previous settings)
1308        //
1309      if ((value_lists.size () >= 1) && (!is_reflexive))
1310        {
1311          if (value_is_reflexive (text))
1312            {
1313              value_list->is_reflexive = true;
1314              is_reflexive = true;
1315            }
1316          else
1317            {
1318              //cerr << "...discarding old values for symbol " << name << " text=[" << text << "]" << endl;
1319                 
1320              for (int i = 0; i < (value_lists.size () - 1); i++)
1321                {
1322                  SymbolValueList& vl = value_lists[i];
1323                 
1324                  if ((vl.use != 0) &&
1325                      (vl.use->discarded))
1326                    {
1327                      //vl.discarded = true;
1328                    }
1329                }
1330            }
1331        }
1332    }
1333
1334  SymbolValue& value = value_list->values.add ();
1335
1336  value.tag = tag;
1337  value.text = text;
1338  value.selected = 0;
1339}
1340
1341/**
1342   Compute the current value of all environment variables and set them to the
1343   shell
1344 */
1345void Symbol::all_set ()
1346{
1347  //cerr << "all_set" << endl;
1348
1349  static bool running = false;
1350
1351
1352  if (Cmt::get_debug ())
1353    {
1354      cout << "\nSymbol::all_set> done=" << running << endl;
1355    }
1356
1357  if (Cmt::get_all_sets_done ()) return;
1358
1359  if (running) return;
1360
1361  running = true;
1362  Cmt::set_all_sets_done ();
1363
1364  static SymbolVector& Symbols = symbols ();
1365  Use::UsePtrVector& Uses = Use::get_ordered_uses ();
1366
1367  int number;
1368
1369  if (Symbols.size () == 0) 
1370    {
1371      running = false;
1372      return;
1373    }
1374
1375  cmt_string value;
1376
1377  for (number = 0; number < Symbol::symbol_number (); number++)
1378    {
1379      Symbol& symbol = Symbol::symbol (number);
1380
1381      if (symbol.type != SymbolSet) continue;
1382
1383      value = symbol.build_macro_value ();
1384      if (value != "")
1385        {
1386          Symbol::expand (value);
1387
1388          CmtSystem::putenv (symbol.name, value);
1389        }
1390    }
1391
1392  cmt_string cmtconfig = CmtSystem::get_cmt_config ();
1393
1394  if (Uses.size () > 0)
1395    {
1396      int number;
1397
1398      for (number = 0; number < Uses.size (); number++)
1399        {
1400          Use& use = *(Uses[number]);
1401
1402          if (use.discarded) continue;
1403
1404          if (use.get_package_name () == "cmt_standalone") continue;
1405
1406          if (use.get_strategy ("SetupConfig"))
1407            {
1408              cmt_string temp;
1409
1410              temp = use.prefix;
1411              temp += "CONFIG";
1412
1413              CmtSystem::putenv (temp, cmtconfig);
1414            }
1415
1416          if (use.get_strategy ("SetupRoot"))
1417            {
1418              cmt_string temp;
1419
1420              temp = use.prefix;
1421              temp += "ROOT";
1422
1423              CmtSystem::putenv (temp, use.get_full_path ());
1424            }
1425        }
1426    }
1427
1428  {
1429    Use& use = Use::current ();
1430
1431    if (use.get_package_name () != "cmt_standalone")
1432      {
1433        if (use.get_strategy ("SetupConfig"))
1434          {
1435            cmt_string temp;
1436
1437            temp = use.prefix;
1438            temp += "CONFIG";
1439
1440            CmtSystem::putenv (temp, cmtconfig);
1441          }
1442       
1443        if (use.get_strategy ("SetupRoot"))
1444          {
1445            cmt_string temp;
1446
1447            temp = use.prefix;
1448            temp += "ROOT";
1449
1450            CmtSystem::putenv (temp, use.get_full_path ());
1451          }
1452      }
1453  }
1454
1455  for (number = 0; number < Symbol::symbol_number (); number++)
1456    {
1457      Symbol& symbol = Symbol::symbol (number);
1458
1459      if ((symbol.type != SymbolPath)) continue;
1460
1461      value = symbol.build_macro_value ();
1462      if (value != "")
1463        {
1464          Symbol::expand (value);
1465          filter_path_value (symbol.name, value);
1466
1467#ifdef WIN32
1468          value.replace_all ("/", "\\");
1469#endif
1470
1471          if (Cmt::get_debug ())
1472            {
1473              cerr << "Symbol::all_set-2> " << symbol.name << " = " << value << endl;
1474            }
1475
1476          CmtSystem::putenv (symbol.name, value);
1477        }
1478    }
1479
1480  running = false;
1481}
1482
1483//-------------------------------------------------------------
1484void Symbol::all_print (PrintMode mode)
1485{
1486  static SymbolVector& Symbols = symbols ();
1487
1488  int number;
1489
1490  if (Symbols.size () == 0) return;
1491
1492  for (number = 0; number < Symbol::symbol_number (); number++)
1493    {
1494      Symbol& symbol = Symbol::symbol (number);
1495
1496      if ((symbol.type == SymbolSet) ||
1497          (symbol.type == SymbolAlias) ||
1498          (symbol.type == SymbolSetupScript) ||
1499          (symbol.type == SymbolPath))
1500        {
1501          if (symbol.print (mode))
1502            {
1503              if (mode == Bat)
1504                {
1505                  cout << endl;
1506                }
1507              else
1508                {
1509                  cout << endl;
1510                }
1511            }
1512        }
1513    }
1514}
1515
1516//-------------------------------------------------------------
1517void Symbol::check_all_paths ()
1518{
1519  static SymbolVector& Symbols = symbols ();
1520
1521  int number;
1522
1523  if (Symbols.size () == 0) return;
1524
1525  for (number = 0; number < Symbol::symbol_number (); number++)
1526    {
1527      Symbol& symbol = Symbol::symbol (number);
1528
1529      if (symbol.type == SymbolPath)
1530        {
1531          cmt_string temp;
1532
1533          temp = symbol.build_macro_value ();
1534          expand (temp);
1535
1536          Symbol::filter_path_value (symbol.name, temp);
1537        }
1538    }
1539}
1540
1541//-------------------------------------------------------------
1542void Symbol::all_print_clean (PrintMode mode)
1543{
1544  static SymbolVector& Symbols = symbols ();
1545
1546  int number;
1547
1548  if (Symbols.size () == 0) return;
1549
1550  for (number = Symbols.size () - 1; number >= 0; number--)
1551    {
1552      Symbol& symbol = Symbols[number];
1553
1554      if ((symbol.type == SymbolSet) ||
1555          (symbol.type == SymbolAlias) ||
1556          (symbol.type == SymbolCleanupScript))
1557        {
1558          if (symbol.print_clean (mode))
1559            {
1560              cout << endl;
1561            }
1562        }
1563    }
1564
1565  for (number = Symbols.size () - 1; number >= 0; number--)
1566    {
1567      Symbol& symbol = Symbols[number];
1568
1569      if ((symbol.type != SymbolPath)) continue;
1570
1571      if (symbol.print_clean (mode))
1572        {
1573          cout << endl;
1574        }
1575    }
1576}
1577
1578//-------------------------------------------------------------
1579int Symbol::print_clean (PrintMode mode)
1580{
1581  int result = 0;
1582  static cmt_string temp;
1583
1584  if (name == "CMTCONFIG") return (0);
1585
1586  switch (type)
1587    {
1588    case SymbolSet :
1589      switch (mode)
1590        {
1591        case Csh :
1592          cout << "unsetenv " << name;
1593          result = 1;
1594          break;
1595        case Sh :
1596          cout << "unset " << name;
1597          result = 1;
1598          break;
1599        case Bat :
1600          cout << "set " << name << "=";
1601          result = 1;
1602          break;
1603        }
1604      break;
1605    case SymbolAlias :
1606      switch (mode)
1607        {
1608          case Csh :
1609            cout << "unalias " << name;
1610            result = 1;
1611            break;
1612          case Sh :
1613            cout << "unset " << name;
1614            result = 1;
1615            break;
1616        }
1617      break;
1618    case SymbolPath :
1619      temp = clean_macro_value ();
1620      switch (mode)
1621        {
1622        case Csh :
1623          if (temp == "")
1624            {
1625              cout << "unsetenv " << name;
1626            }
1627          else
1628            {
1629              cout << "setenv " << name << " " << temp;
1630            }
1631          result = 1;
1632          break;
1633        case Sh :
1634          cout << name << "=" << temp << "; export " << name;
1635          result = 1;
1636          break;
1637        case Bat :
1638          cout << "set " << name << "=" << temp;
1639          result = 1;
1640          break;
1641        }
1642      break;
1643    case SymbolCleanupScript :
1644      switch (mode)
1645        {
1646        case Csh :
1647          cout << "if ( -f " << name << ".csh ) then" << endl;
1648          cout << "  source " << name << ".csh" << endl;
1649          cout <<
1650            "if ( $status != 0 ) then\n"
1651            "    set cmtcleanupstatus=1\n"
1652            "endif\n";
1653          cout << "endif" << endl;
1654          result = 1;
1655          break;
1656        case Sh :
1657          cout << "if test -f " << name << ".sh; then" << endl;
1658          cout << "  . " << name << ".sh" << endl;
1659          cout <<
1660            "if test $? != 0; then\n"
1661            "    cmtcleanupstatus=1\n"
1662            "fi\n";
1663          cout << "fi" << endl;
1664          result = 1;
1665          break;
1666        case Bat :
1667          cout << "call " << name;
1668          result = 1;
1669          break;
1670        }
1671      break;
1672    }
1673
1674  return (result);
1675}
1676
1677//-------------------------------------------------------------
1678int Symbol::print (PrintMode mode)
1679{
1680  int result = 0;
1681  cmt_string temp;
1682
1683  temp = build_macro_value ();
1684
1685  bool empty = (temp.size () == 0) ? true : false;
1686
1687  if (type == SymbolPath)
1688    {
1689      expand (temp);
1690      Symbol::filter_path_value (name, temp);
1691    }
1692
1693  switch (type)
1694    {
1695      case SymbolSet :
1696      case SymbolPath :
1697        switch (mode)
1698          {
1699            case Csh :
1700              if (empty) cout << "unsetenv " << name;
1701              else cout << "setenv " << name << " \"" << temp << "\"";
1702
1703              result = 1;
1704              break;
1705            case Sh :
1706              if (empty) cout << "unset " << name;
1707              else cout << name << "=\"" << temp << "\"; export " << name;
1708
1709              result = 1;
1710              break;
1711            case Bat :
1712              temp.replace_all ("/", "\\");
1713              cout << "set " << name << "=" << temp;
1714              result = 1;
1715              break;
1716          }
1717        break;
1718      case SymbolAlias :
1719        switch (mode)
1720          {
1721            case Csh :
1722              cout << "alias " << name <<
1723                  " \"" << temp << "\"";
1724              result = 1;
1725              break;
1726            case Sh :
1727              cout << "alias " << name <<
1728                  "=\"" << temp << "\"";
1729              result = 1;
1730              break;
1731            case Bat :
1732              cout << "set " << name <<
1733                  "=" << temp;
1734              result = 1;
1735              break;
1736          }
1737        break;
1738      default :
1739        break;
1740    }
1741
1742  if (temp != "")
1743    {
1744      switch (type)
1745        {
1746          case SymbolSetupScript :
1747            switch (mode)
1748              {
1749                case Csh :
1750                  cout << "if ( -f " << name << ".csh ) then" << endl;
1751                  cout << "  source " << name << ".csh" << endl;
1752                  cout <<
1753                    "if ( $status != 0 ) then\n"
1754                    "    set cmtsetupstatus=1\n"
1755                    "endif\n";
1756                  cout << "endif" << endl;
1757                  result = 1;
1758                  break;
1759                case Sh :
1760                  cout << "if test -f " << name << ".sh; then" << endl;
1761                  cout << "  . " << name << ".sh" << endl;
1762                  cout <<
1763                    "if test $? != 0; then\n"
1764                    "    cmtsetupstatus=1\n"
1765                    "fi\n";
1766                  cout << "fi" << endl;
1767                  result = 1;
1768                  break;
1769                case Bat :
1770                  cout << "call " << name;
1771                  result = 1;
1772                  break;
1773              }
1774            break;
1775          default:
1776            break;
1777        }
1778    }
1779
1780  return (result);
1781}
1782
1783//-------------------------------------------------------------
1784cmt_string Symbol::build_macro_value (bool display_it) const
1785{
1786  cmt_string temp;
1787
1788  if (display_it)
1789    {
1790      temp = builder->build_and_display (*this);
1791    }
1792  else
1793    {
1794      temp = builder->build (*this);
1795    }
1796
1797  return (temp);
1798}
1799
1800//-------------------------------------------------------------
1801cmt_string Symbol::clean_macro_value () const
1802{
1803  cmt_string temp;
1804
1805  temp = builder->clean (*this);
1806
1807  return (temp);
1808}
1809
1810/**
1811
1812   Attempt to substitute into the symbol value all occurrences of
1813
1814      ${xxx}
1815      $(xxx)
1816      `xxx`
1817      %xxx%    [on Windows only]
1818
1819      by the appropriate value:
1820
1821        for `xxx` :
1822
1823            xxx is considered as a shell command. Value is the result of its execution
1824
1825        for other patterns:
1826
1827            if xxx is a symbol name, its value is substituted to the pattern
1828            otherwise, xxx is tried as an environment variable
1829
1830
1831     ===> In all cases, the pattern is filtered away.
1832
1833  */
1834cmt_string Symbol::resolve_macro_value (const cmt_string& tag_name)
1835{
1836  cmt_string temp = builder->build (*this, tag_name);
1837
1838  resolve_value (temp);
1839
1840  return (temp);
1841}
1842
1843//-------------------------------------------------------------
1844void Symbol::show_macro (PrintMode mode, ostream& out)
1845//void Symbol::show_macro (PrintMode mode)
1846{
1847  if (Cmt::get_debug ())
1848    {
1849      cout << "Symbol::show_macro> " << name << endl;
1850    }
1851
1852  ActionType action = Cmt::get_action ();
1853
1854  cmt_string value = build_macro_value (true);
1855
1856  if ((!Cmt::get_quiet ()) &&
1857      (action != action_build_tag_makefile) &&
1858      (action != action_build_constituents_config) &&
1859      (action != action_build_constituent_config) &&
1860      (action != action_show_macros) &&
1861      (action != action_show_actions) &&
1862      (action != action_show_sets))
1863    {
1864      out << "#" << endl;
1865      out << "# Selection : " << endl;
1866    }
1867
1868  if (value.size () > 0)
1869    {
1870      if ((action == action_show_macro) ||
1871          (action == action_show_macros) ||
1872          (action == action_show_sets) ||
1873          (action == action_show_set) ||
1874          (action == action_show_actions) ||
1875          (action == action_show_action) ||
1876          (action == action_build_tag_makefile) ||
1877          (action == action_build_constituents_config) ||
1878          (action == action_build_constituent_config) ||
1879          (action == action_load) ||
1880          (!Cmt::get_quiet ()))
1881        {
1882          if (mode == Make)
1883            {
1884              out << name << "=";
1885            }
1886          else
1887            {
1888              out << name << "='";
1889            }
1890        }
1891
1892      if ((action == action_show_macro_value) ||
1893          (action == action_show_set_value) ||
1894          (action == action_show_action_value))
1895        {
1896          expand (value);
1897        }
1898      else if (action == action_build_tag_makefile ||
1899               action == action_build_constituents_config ||
1900               action == action_build_constituent_config)
1901        {
1902            /*
1903               Unfortunately, the %xxx% pattern has to be kept on Unix. Therefore
1904               we cannot force all patterns to become $(xxx)
1905
1906               This was useful on Windows so as to only keep $(xxx)
1907             */
1908#ifdef WIN32
1909          suppress_OS_delimiters (value);
1910#endif
1911        }
1912
1913      out << value;
1914
1915      if ((action == action_show_macro) ||
1916          (action == action_show_macros) ||
1917          (action == action_show_sets) ||
1918          (action == action_show_set) ||
1919          (action == action_show_actions) ||
1920          (action == action_show_action) ||
1921          (action == action_build_tag_makefile) ||
1922          (action == action_build_constituents_config) ||
1923          (action == action_build_constituent_config) ||
1924          (action == action_load) ||
1925          (!Cmt::get_quiet ()))
1926        {
1927          if (mode != Make)
1928            {
1929              out << "'";
1930            }
1931#ifdef WIN32
1932          else
1933            {
1934              out << " ";
1935            }
1936#endif
1937        }
1938
1939      out << endl;
1940    }
1941}
1942
1943//-------------------------------------------------------------
1944void Symbol::clear_all ()
1945{
1946  static SymbolVector& Symbols = symbols ();
1947  static SymbolMap& SymbolMap = symbol_map ();
1948
1949  SymbolMap.clear ();
1950  Symbols.clear ();
1951}
1952
1953//-------------------------------------------------------------
1954void Symbol::expand (cmt_string& text)
1955{
1956  static cmt_regexp reg ("[$%`]");
1957
1958  if (!reg.match (text)) return;
1959
1960  resolve_value (text);
1961}
1962
1963//-------------------------------------------------------------
1964ValueBuilder::ValueBuilder ()
1965{
1966  m_display_it = false;
1967}
1968
1969//-------------------------------------------------------------
1970const cmt_string ValueBuilder::build_and_display (const Symbol& symbol)
1971{
1972  cmt_string temp;
1973
1974  m_display_it = true;
1975  temp = build (symbol);
1976  m_display_it = false;
1977
1978  return (temp);
1979}
1980
1981//-------------------------------------------------------------
1982const cmt_string SetBuilder::build (const Symbol& symbol,
1983                                    const cmt_string& /*tag_name*/)
1984{
1985    // Control of recursivity
1986  static int level = 0;
1987
1988  bool show_it = false;
1989
1990  cmt_string temp;
1991  cmt_string previous_temp;
1992  cmt_string new_value;
1993  static const cmt_string empty;
1994
1995  ActionType action = Cmt::get_action ();
1996
1997  if (action == action_show_set)
1998    {
1999      if (symbol.name == Cmt::get_current_target ())
2000        {
2001             // Should not display on recursive calls
2002          if (level == 0) show_it = m_display_it;
2003        }
2004    }
2005
2006  level++;
2007
2008  temp = "";
2009
2010  bool first_definition = true;
2011
2012  for (int i = 0; i < symbol.value_lists.size (); i++)
2013    {
2014      const SymbolValueList& value_list = symbol.value_lists[i];
2015
2016      if ((value_list.use != 0) &&
2017          (value_list.use->discarded)) continue;
2018
2019      const int selected = value_list.select_first ();
2020
2021      if (selected < 0) continue;
2022
2023      SymbolValue& value = value_list.values[selected];
2024
2025      if (show_it && !Symbol::get_inhibit_display())
2026        {
2027          value_list.show (symbol, value, first_definition);
2028        }
2029     
2030      if (value_list.discarded) continue;
2031
2032        //
2033        // One should accumulate values if it refers to
2034        // itself.
2035        //
2036     
2037      new_value = value.text;
2038     
2039      resolve_value_for_macros (new_value);
2040     
2041      switch (value_list.command_type)
2042        {
2043          case CommandSet :
2044
2045            if (!value_list.is_reflexive || 
2046                !symbol.value_is_reflexive (value.text))
2047              {
2048                resolve_value (new_value, symbol.name, temp);
2049                temp = new_value;
2050              }
2051            else if (temp == "")
2052              {
2053                temp = CmtSystem::getenv (symbol.name);
2054              }
2055
2056            break;
2057          case CommandSetAppend :
2058           
2059            if (new_value != "")
2060              {
2061                temp += new_value;
2062              }
2063           
2064            break;
2065          case CommandSetPrepend :
2066           
2067            if (new_value != "")
2068              {
2069                previous_temp = temp;
2070                temp = new_value;
2071                temp += previous_temp;
2072              }
2073           
2074            break;
2075          case CommandSetRemove :
2076           
2077            if (new_value != "")
2078              {
2079                temp.replace_all (new_value, empty);
2080              }
2081           
2082            break;
2083          case CommandSetRemoveRegexp :
2084           
2085            if (new_value != "")
2086              {
2087                cmt_regexp e (new_value);
2088                cmt_regexp::iterator it;
2089
2090                for (;;)
2091                  {
2092                    it = e.begin (temp);
2093                    if (it == e.end ()) break;
2094
2095                    temp.erase (it._pos, it._length);
2096                  }
2097              }
2098           
2099            break;
2100          case CommandAlias :
2101           
2102            resolve_value (new_value, symbol.name, temp);
2103            temp = new_value;
2104           
2105            break;
2106        }
2107    }
2108
2109  level--;
2110
2111  return (temp);
2112}
2113
2114static bool find_path_entry (const cmt_string& paths, const cmt_string& value)
2115{
2116  static const cmt_string path_separator = CmtSystem::path_separator ();
2117
2118  cmt_string here = CmtSystem::pwd ();
2119  cmt_string rvalue = value;
2120
2121  if (CmtSystem::cd (value))
2122    {
2123      rvalue = CmtSystem::pwd ();
2124    }
2125  else
2126    {
2127      CmtSystem::compress_path (rvalue);
2128    }
2129
2130  CmtSystem::cmt_string_vector items;
2131  CmtSystem::split (paths, path_separator, items);
2132
2133  bool found = false;
2134
2135  for (int i = 0; i < items.size (); i++)
2136    {
2137      const cmt_string& item = items[i];
2138      cmt_string ritem = item;
2139      if (CmtSystem::cd (item))
2140        {
2141          ritem = CmtSystem::pwd ();
2142        }
2143      else
2144        {
2145          CmtSystem::compress_path (ritem);
2146        }
2147
2148      if (ritem == rvalue)
2149        {
2150          found = true;
2151          break;
2152        }
2153    }
2154
2155  CmtSystem::cd (here);
2156  return (found);
2157}
2158
2159//-------------------------------------------------------------
2160const cmt_string PathBuilder::build (const Symbol& symbol,
2161                                     const cmt_string& /*tag_name*/)
2162{
2163    // Control of recursivity
2164  static int level = 0;
2165
2166  bool show_it = false;
2167
2168  cmt_string temp;
2169  cmt_string previous_temp;
2170  cmt_string new_value;
2171  static const cmt_string empty;
2172
2173  static cmt_string path_separator = CmtSystem::path_separator ();
2174
2175  ActionType action = Cmt::get_action ();
2176
2177  if (action == action_show_set)
2178    {
2179      if (symbol.name == Cmt::get_current_target ())
2180        {
2181            // Should not display on recursive calls
2182          if (level == 0) show_it = m_display_it;
2183        }
2184    }
2185
2186  level++;
2187
2188  temp = CmtSystem::getenv (symbol.name);
2189
2190  bool first_definition = true;
2191
2192  for (int i = 0; i < symbol.value_lists.size (); i++)
2193    {
2194      const SymbolValueList& value_list = symbol.value_lists[i];
2195
2196      if ((value_list.use != 0) &&
2197          (value_list.use->discarded)) continue;
2198
2199      const int selected = value_list.select_first ();
2200     
2201      if (selected < 0) continue;
2202 
2203      SymbolValue& value = value_list.values[selected];
2204         
2205      if (show_it && !Symbol::get_inhibit_display())
2206        {
2207          value_list.show (symbol, value, first_definition);
2208        }
2209         
2210      if (value_list.discarded) continue;
2211
2212      new_value = value.text;
2213         
2214          //resolve_value (new_value);
2215      resolve_value_for_macros (new_value);
2216         
2217      switch (value_list.command_type)
2218        {
2219          case CommandPath :
2220           
2221            if (!value_list.is_reflexive || 
2222                !symbol.value_is_reflexive (value.text))
2223              {
2224                resolve_value (new_value, symbol.name, temp);
2225                temp = new_value;
2226              }
2227
2228            break;
2229          case CommandPathAppend :
2230             
2231            if (new_value != "")
2232              {
2233                if (!find_path_entry (temp, new_value))
2234                  {
2235                    if (temp != "") temp += path_separator;
2236                     
2237                    temp += new_value;
2238                  }
2239              }
2240                 
2241            break;
2242          case CommandPathPrepend :
2243             
2244            if (new_value != "")
2245              {
2246                if (!find_path_entry (temp, new_value))
2247                  {
2248                    previous_temp = temp;
2249                    temp = new_value;
2250                    if (previous_temp != "") temp += path_separator;
2251                    temp += previous_temp;
2252                  }
2253              }
2254                 
2255            break;
2256          case CommandPathRemove :
2257             
2258            if (new_value != "")
2259              {
2260                CmtSystem::cmt_string_vector paths;
2261                 
2262                CmtSystem::split (temp, path_separator, paths);
2263                 
2264                for (int j = 0; j < paths.size (); ++j)
2265                  {
2266                    cmt_string& s = paths[j];
2267                     
2268                    if (s.find (new_value) != cmt_string::npos)
2269                      {
2270                        s = "";
2271                      }
2272                  }
2273
2274                Cmt::vector_to_string (paths, path_separator, temp);
2275              }
2276             
2277            break;
2278          case CommandPathRemoveRegexp :
2279
2280            if (new_value != "")
2281              {
2282                cmt_regexp e (new_value);
2283
2284                CmtSystem::cmt_string_vector paths;
2285                 
2286                CmtSystem::split (temp, path_separator, paths);
2287                 
2288                for (int j = 0; j < paths.size (); ++j)
2289                  {
2290                    cmt_string& s = paths[j];
2291
2292                    if (CmtSystem::getenv ("TESTPRR") != "")
2293                      {
2294                        cerr << "PRR> s=[" << s << "]";
2295                      }
2296
2297                    if (e.match (s))
2298                      {
2299                        s = "";
2300
2301                        if (CmtSystem::getenv ("TESTPRR") != "")
2302                          {
2303                            cerr << " match ";
2304                          }
2305                      }
2306                    else
2307                      {
2308                        if (CmtSystem::getenv ("TESTPRR") != "")
2309                          {
2310                            cerr << " no match ";
2311                          }
2312                      }
2313
2314                    if (CmtSystem::getenv ("TESTPRR") != "")
2315                      {
2316                        cerr << endl;
2317                      }
2318                  }
2319
2320                Cmt::vector_to_string (paths, path_separator, temp);
2321              }
2322             
2323            break;
2324        }
2325
2326    }
2327
2328  level--;
2329
2330  for (;;)
2331    {
2332      int sz = temp.size ();
2333
2334      if (sz == 0) break;
2335
2336      if ((temp[0] == ';') || (temp[0] == ':'))
2337        {
2338          temp.erase (0, 1);
2339        }
2340      else if ((temp[sz-1] == ';') || (temp[sz-1] == ':'))
2341        {
2342          temp.erase (sz-1, 1);
2343        }
2344      else
2345        {
2346          break;
2347        }
2348    }
2349
2350  temp.replace_all ("::", ":");
2351  temp.replace_all (";;", ";");
2352 
2353  return (temp);
2354}
2355
2356//-------------------------------------------------------------
2357const cmt_string PathBuilder::clean (const Symbol& symbol,
2358                                     const cmt_string& /*tag_name*/)
2359{
2360    // Control of recursivity
2361  static int level = 0;
2362
2363  cmt_string temp;
2364  cmt_string new_value;
2365  static const cmt_string empty;
2366
2367  static cmt_string path_separator = CmtSystem::path_separator ();
2368
2369  temp = CmtSystem::getenv (symbol.name);
2370
2371    //cerr << "#####1 temp=" << temp << endl;
2372
2373  for (int i = 0; i < symbol.value_lists.size (); i++)
2374    {
2375      const SymbolValueList& value_list = symbol.value_lists[i];
2376
2377      if (value_list.discarded) continue;
2378
2379      if ((value_list.use != 0) &&
2380          (value_list.use->discarded)) continue;
2381
2382      const int selected = value_list.select_first ();
2383     
2384      if (selected < 0) continue;
2385 
2386      SymbolValue& value = value_list.values[selected];
2387         
2388      new_value = value.text;
2389         
2390          //resolve_value (new_value);
2391
2392        //cerr << "#####1 new_value=" << new_value << endl;
2393
2394      resolve_value_for_macros (new_value);
2395      resolve_value (new_value);
2396         
2397        //cerr << "#####2 new_value=" << new_value << endl;
2398
2399      switch (value_list.command_type)
2400        {
2401          case CommandPath :
2402           
2403            temp = "";
2404           
2405            break;
2406          case CommandPathAppend :
2407          case CommandPathPrepend :
2408          case CommandPathRemove :
2409
2410            if (new_value != "")
2411              {
2412                CmtSystem::cmt_string_vector paths;
2413                 
2414                CmtSystem::split (temp, path_separator, paths);
2415                 
2416                for (int j = 0; j < paths.size (); ++j)
2417                  {
2418                    cmt_string& s = paths[j];
2419                     
2420                    if (s.find (new_value) != cmt_string::npos)
2421                      {
2422                        s = "";
2423                      }
2424
2425                    if (j > 0)
2426                      {
2427                        cmt_string& s2 = paths[j-1];
2428                        if (s2 == s)
2429                          {
2430                            s2 = "";
2431                          }
2432                      }
2433                  }
2434
2435                Cmt::vector_to_string (paths, path_separator, temp);
2436                temp.replace_all ("::", ":");
2437                temp.replace_all (";;", ";");
2438              }
2439             
2440            break;
2441          case CommandPathRemoveRegexp :
2442
2443            if (new_value != "")
2444              {
2445                cmt_regexp e (new_value);
2446
2447                CmtSystem::cmt_string_vector paths;
2448                 
2449                CmtSystem::split (temp, path_separator, paths);
2450                 
2451                for (int j = 0; j < paths.size (); ++j)
2452                  {
2453                    cmt_string& s = paths[j];
2454                     
2455                    if (e.match (s))
2456                      {
2457                        s = "";
2458                      }
2459
2460                    if (j > 0)
2461                      {
2462                        cmt_string& s2 = paths[j-1];
2463                        if (s2 == s)
2464                          {
2465                            s2 = "";
2466                          }
2467                      }
2468                  }
2469
2470                Cmt::vector_to_string (paths, path_separator, temp);
2471                temp.replace_all ("::", ":");
2472                temp.replace_all (";;", ";");
2473              }
2474             
2475            break;
2476        }
2477    }
2478
2479    //cerr << "#####2 temp=" << temp << endl;
2480 
2481  return (temp);
2482}
2483
2484//-------------------------------------------------------------
2485const cmt_string MacroBuilder::build (const Symbol& symbol,
2486                                      const cmt_string& tag_name)
2487{
2488    // Control of recursivity
2489  static int level = 0;
2490
2491  cmt_string temp;
2492  cmt_string previous_temp;
2493  static const cmt_string empty;
2494  bool show_it = false;
2495
2496  ActionType action = Cmt::get_action ();
2497
2498  if (action == action_show_macro)
2499    {
2500      if (symbol.name == Cmt::get_current_target ())
2501        {
2502             // Should not display on recursive calls
2503          if (level == 0) show_it = m_display_it;
2504        }
2505    }
2506
2507  level++;
2508
2509  temp = "";
2510
2511  int i;
2512
2513  bool first_definition = true;
2514
2515  for (i = 0; i < symbol.value_lists.size (); i++)
2516    {
2517      const SymbolValueList& value_list = symbol.value_lists[i];
2518
2519      if ((value_list.use != 0) &&
2520          (value_list.use->discarded)) continue;
2521
2522      if (value_list.command_type != CommandMacroPrepend) continue;
2523
2524      const int selected = value_list.select_first (tag_name);
2525
2526      if (selected < 0) continue;
2527
2528      SymbolValue& value = value_list.values[selected];
2529
2530      if (show_it && !Symbol::get_inhibit_display())
2531        {
2532          value_list.show (symbol, value, first_definition);
2533        }
2534
2535      if (value_list.discarded) continue;
2536
2537      previous_temp = temp;
2538      temp = value.text;
2539      temp += previous_temp;
2540    }
2541
2542  previous_temp = temp;
2543  temp = "";
2544
2545  first_definition = true;
2546
2547  for (i = 0; i < symbol.value_lists.size (); i++)
2548    {
2549      const SymbolValueList& value_list = symbol.value_lists[i];
2550
2551      if ((value_list.use != 0) &&
2552          (value_list.use->discarded)) continue;
2553
2554      if (value_list.command_type != CommandMacro) continue;
2555
2556      const int selected = value_list.select_first (tag_name);
2557
2558      if (selected < 0) continue;
2559
2560      SymbolValue& value = value_list.values[selected];
2561
2562      if (show_it && !Symbol::get_inhibit_display())
2563        {
2564          value_list.show (symbol, value, first_definition);
2565        }
2566
2567      // WARNING:
2568      // Commented just for a test : should be uncommented after the test
2569      if (value_list.discarded) continue;
2570     
2571      if (!value_list.is_reflexive || 
2572          !symbol.value_is_reflexive (value.text))
2573        {
2574          temp = value.text;
2575        }
2576    }
2577
2578  previous_temp += temp;
2579  temp = previous_temp;
2580
2581  for (i = 0; i < symbol.value_lists.size (); i++)
2582    {
2583      const SymbolValueList& value_list = symbol.value_lists[i];
2584
2585      if ((value_list.use != 0) &&
2586          (value_list.use->discarded)) continue;
2587
2588      if (value_list.command_type != CommandMacroAppend) continue;
2589
2590      const int selected = value_list.select_first (tag_name);
2591
2592      if (selected < 0) continue;
2593
2594      SymbolValue& value = value_list.values[selected];
2595
2596      if (show_it && !Symbol::get_inhibit_display())
2597        {
2598          value_list.show (symbol, value, first_definition);
2599        }
2600
2601      if (value_list.discarded) continue;
2602
2603      temp += value.text;
2604    }
2605
2606  for (i = 0; i < symbol.value_lists.size (); i++)
2607    {
2608      const SymbolValueList& value_list = symbol.value_lists[i];
2609
2610      if ((value_list.use != 0) &&
2611          (value_list.use->discarded)) continue;
2612
2613      if ((value_list.command_type != CommandMacroRemove) &&
2614          (value_list.command_type != CommandMacroRemoveRegexp) &&
2615          (value_list.command_type != CommandMacroRemoveAll) &&
2616          (value_list.command_type != CommandMacroRemoveAllRegexp)) continue;
2617
2618      const int selected = value_list.select_first (tag_name);
2619
2620      if (selected < 0) continue;
2621
2622      SymbolValue& value = value_list.values[selected];
2623
2624      if (show_it && !Symbol::get_inhibit_display())
2625        {
2626          value_list.show (symbol, value, first_definition);
2627        }
2628
2629      if (value_list.discarded) continue;
2630
2631      switch (value_list.command_type)
2632        {
2633          case CommandMacroRemove :
2634            temp.replace (value.text, empty);
2635            break;
2636          case CommandMacroRemoveRegexp :
2637            if (value.text != "")
2638              {
2639                cmt_regexp e (value.text);
2640                cmt_regexp::iterator it;
2641
2642                it = e.begin (temp);
2643                if (it != e.end ())
2644                  {
2645                    temp.erase (it._pos, it._length);
2646                  }
2647              }
2648            break;
2649          case CommandMacroRemoveAll :
2650            temp.replace_all (value.text, empty);
2651            break;
2652          case CommandMacroRemoveAllRegexp :
2653            if (value.text != "")
2654              {
2655                cmt_regexp e (value.text);
2656                cmt_regexp::iterator it;
2657
2658                for (;;)
2659                  {
2660                    it = e.begin (temp);
2661                    if (it != e.end ())
2662                      {
2663                        temp.erase (it._pos, it._length);
2664                      }
2665                    else
2666                      {
2667                        break;
2668                      }
2669                  }
2670              }
2671            break;
2672        }
2673    }
2674
2675  level--;
2676
2677  return (temp);
2678}
2679
2680//-------------------------------------------------------------
2681const cmt_string ScriptBuilder::build (const Symbol& symbol,
2682                                       const cmt_string& tag_name)
2683{
2684    // Control of recursivity
2685  static int level = 0;
2686
2687  static const cmt_string empty = "";
2688
2689  if (symbol.value_lists.size () > 0)
2690    {
2691      const SymbolValueList& value_list = symbol.value_lists[0];
2692
2693      if (value_list.discarded) return (empty);
2694
2695      if ((value_list.use != 0) &&
2696          (value_list.use->discarded)) return (empty);
2697    }
2698
2699  return (symbol.name);
2700}
2701
2702//-------------------------------------------------------------
2703const cmt_string ActionBuilder::build (const Symbol& symbol,
2704                                       const cmt_string& tag_name)
2705{
2706    // Control of recursivity
2707  static int level = 0;
2708
2709  cmt_string temp;
2710  cmt_string previous_temp;
2711  static const cmt_string empty;
2712  bool show_it = false;
2713
2714  ActionType action = Cmt::get_action ();
2715
2716  if (action == action_show_action)
2717    {
2718      if (symbol.name == Cmt::get_current_target ())
2719        {
2720             // Should not display on recursive calls
2721          if (level == 0) show_it = m_display_it;
2722        }
2723    }
2724
2725  level++;
2726
2727  int i;
2728
2729  bool first_definition = true;
2730
2731  temp = "";
2732
2733  for (i = 0; i < symbol.value_lists.size (); i++)
2734    {
2735      const SymbolValueList& value_list = symbol.value_lists[i];
2736
2737      if ((value_list.use != 0) &&
2738          (value_list.use->discarded)) continue;
2739
2740      if (value_list.command_type != CommandAction) continue;
2741
2742      const int selected = value_list.select_first (tag_name);
2743
2744      if (selected < 0) continue;
2745
2746      SymbolValue& value = value_list.values[selected];
2747
2748      if (show_it && !Symbol::get_inhibit_display())
2749        {
2750          value_list.show (symbol, value, first_definition);
2751        }
2752
2753      // WARNING:
2754      // Commented just for a test : should be uncommented after the test
2755      if (value_list.discarded) continue;
2756     
2757      if (!value_list.is_reflexive || 
2758          !symbol.value_is_reflexive (value.text))
2759        {
2760          temp = value.text;
2761        }
2762    }
2763
2764  level--;
2765
2766  return (temp);
2767}
2768
2769//-------------------------------------------------------------
2770int SymbolValueList::select_first (const cmt_string& tag_name) const
2771{
2772  int priority = 0;
2773  int value_number;
2774  int selected = -1;
2775
2776  Tag* the_tag = 0;
2777
2778  if (tag_name != "") the_tag = Tag::find (tag_name);
2779
2780  for (value_number = 0;
2781       value_number < values.size ();
2782       value_number++)
2783    {
2784      const SymbolValue& value = values[value_number];
2785
2786      const Tag* tag = value.tag;
2787
2788      if (the_tag == 0)
2789        {
2790          if (!tag->is_selected ()) continue;
2791          selected = value_number;
2792          if (tag == Tag::get_default ())
2793            continue;
2794        }
2795      else
2796        {
2797          if (tag != the_tag) continue;
2798          selected = value_number;
2799        }
2800
2801      //
2802      // Only the value for the first alternative (i.e. non-default)
2803      // matching tag expression is
2804      // selected (which means the selection stops here)
2805      //
2806      break;
2807
2808      //
2809      // Only the first value at a given priority is
2810      // selected (which implies the '>' test instead
2811      // of '>=')
2812      //
2813      /*
2814      if (tag->get_priority () > priority)
2815        {
2816          priority = tag->get_priority ();
2817          selected = value_number;
2818        }
2819      */
2820    }
2821
2822  return (selected);
2823}
2824
2825//-------------------------------------------------------------
2826int SymbolValueList::select_last () const
2827{
2828  int priority = 0;
2829  int value_number;
2830  int selected = -1;
2831
2832  for (value_number = 0;
2833       value_number < values.size ();
2834       value_number++)
2835    {
2836      SymbolValue& value = values[value_number];
2837
2838      const Tag* tag = value.tag;
2839
2840      if (tag->is_selected ())
2841        {
2842          //
2843          // The last value at a given priority is
2844          // selected (which implies the '>=' test instead
2845          // of '>')
2846          //
2847
2848          if (tag->get_priority () >= priority)
2849            {
2850              priority = tag->get_priority ();
2851              selected = value_number;
2852            }
2853        }
2854    }
2855
2856  return (selected);
2857}
2858
2859//-------------------------------------------------------------
2860void SymbolValueList::show (const Symbol& symbol, 
2861                            const SymbolValue& value, 
2862                            bool& first_definition) const
2863{
2864  cmt_string discarded_text;
2865  cmt_string define_text;
2866  ActionType action = Cmt::get_action ();
2867
2868  switch (command_type)
2869    {
2870      //case CommandSet :
2871      case CommandSetAppend :
2872      case CommandSetPrepend :
2873      case CommandSetRemove :
2874      case CommandSetRemoveRegexp :
2875        //case CommandAlias :
2876        //case CommandPath :
2877      case CommandPathAppend :
2878      case CommandPathPrepend :
2879      case CommandPathRemove :
2880      case CommandPathRemoveRegexp :
2881      case CommandMacroPrepend :
2882        //case CommandMacro :
2883      case CommandMacroAppend :
2884      case CommandMacroRemove :
2885      case CommandMacroRemoveRegexp :
2886      case CommandMacroRemoveAll :
2887      case CommandMacroRemoveAllRegexp :
2888        //case CommandAction :
2889        if (value.text == "") return;
2890        break;
2891    }
2892
2893  if (discarded) discarded_text = " (discarded by override)";
2894  else discarded_text = "";
2895
2896  if (first_definition) define_text = "defines";
2897  else define_text = "overrides";
2898
2899  cout << "# Package ";
2900  if (use != 0)
2901    {
2902      cout << use->get_package_name () << " " << use->version;
2903    }
2904
2905  switch (command_type)
2906    {
2907      case CommandSet :
2908        cout << " " << define_text << " set " << symbol.name << " as ";
2909        first_definition = false;
2910        break;
2911      case CommandSetAppend :
2912        cout << " appends to set " << symbol.name << " : ";
2913        break;
2914      case CommandSetPrepend :
2915        cout << " prepends to set " << symbol.name << " : ";
2916        break;
2917      case CommandSetRemove :
2918        cout << " removes from set " << symbol.name << " : ";
2919        break;
2920      case CommandSetRemoveRegexp :
2921        cout << " removes RE from set " << symbol.name << " : ";
2922        break;
2923      case CommandAlias :
2924        cout << " " << define_text << " alias " << symbol.name << " as ";
2925        first_definition = false;
2926        break;
2927      case CommandPath :
2928        cout << " " << define_text << " path " << symbol.name << " as ";
2929        first_definition = false;
2930        break;
2931      case CommandPathAppend :
2932        cout << " appends to path " << symbol.name << " : ";
2933        break;
2934      case CommandPathPrepend :
2935        cout << " prepends to path " << symbol.name << " : ";
2936        break;
2937      case CommandPathRemove :
2938        cout << " removes from path " << symbol.name << " : ";
2939        break;
2940      case CommandPathRemoveRegexp :
2941        cout << " removes RE from path " << symbol.name << " : ";
2942        break;
2943      case CommandMacroPrepend :
2944        cout << " prepends to macro " << symbol.name << " : ";
2945        break;
2946      case CommandMacro :
2947        cout << " " << define_text << " macro " << symbol.name << " as ";
2948        break;
2949      case CommandMacroAppend :
2950        cout << " appends to macro " << symbol.name << " : ";
2951        break;
2952      case CommandMacroRemove :
2953        cout << " remove from macro " << symbol.name << " : ";
2954        break;
2955      case CommandMacroRemoveRegexp :
2956        cout << " remove RE from macro " << symbol.name << " : ";
2957        break;
2958      case CommandMacroRemoveAll :
2959        cout << " remove all from macro " << symbol.name << " : ";
2960        break;
2961      case CommandMacroRemoveAllRegexp :
2962        cout << " remove all RE from macro " << symbol.name << " : ";
2963        break;
2964      case CommandAction :
2965        cout << " " << define_text << " action " << symbol.name << " as ";
2966        first_definition = false;
2967        break;
2968    }
2969
2970  cout << "'" << value.text << "'";
2971         
2972  Tag* selected_tag = value.tag;
2973         
2974  if ((selected_tag == 0) ||
2975      (selected_tag == Tag::get_default ()))
2976    {
2977      cout << " for default tag";
2978    }
2979  else
2980    {
2981      cout << " for tag '" << selected_tag->get_name () << "'";
2982    }
2983 
2984  cout << discarded_text << endl;
2985}
2986
2987//-------------------------------------------------------------
2988bool Symbol::check_tag_used (Tag* tag)
2989{
2990  if (tag == 0) return (false);
2991
2992  static SymbolVector& Symbols = symbols ();
2993
2994  if (Symbols.size () == 0) 
2995    {
2996      return (false);
2997    }
2998
2999  for (int number = 0; number < Symbol::symbol_number (); number++)
3000    {
3001      Symbol& symbol = Symbol::symbol (number);
3002
3003      for (int i = 0; i < symbol.value_lists.size (); i++)
3004        {
3005          const SymbolValueList& value_list = symbol.value_lists[i];
3006
3007          for (int j = 0; j < value_list.values.size (); j++)
3008            {
3009              const SymbolValue& value = value_list.values[j];
3010              Tag* t = value.tag;
3011
3012              if (t != 0)
3013                {
3014                  if (t->use_operand (tag)) return (true);
3015                }
3016            }
3017        }
3018    }
3019
3020  return (false);
3021}
3022
3023//-------------------------------------------------------------
3024cmt_string Symbol::get_env_value (const cmt_string& name)
3025{
3026  cmt_string s;
3027
3028  Symbol* symbol = Symbol::find (name);
3029  if (symbol != 0)
3030    {
3031      m_inhibit_display = true;
3032
3033      s = symbol->build_macro_value ();
3034      Symbol::expand (s);
3035
3036      m_inhibit_display = false;
3037    }
3038  else
3039    {
3040      s = CmtSystem::getenv (name);
3041    }
3042
3043  return (s);
3044}
3045
3046bool Symbol::get_inhibit_display ()
3047{
3048  return (m_inhibit_display);
3049}
3050
Note: See TracBrowser for help on using the repository browser.