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

Last change on this file since 530 was 530, checked in by rybkin, 15 years ago

See C.L. 417

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