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

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

See C.L. 416

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