source: CMT/v1r20p20090520/source/cmt_symbol.cxx @ 597

Last change on this file since 597 was 467, checked in by rybkin, 16 years ago

See C.L. 368

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