source: CMT/v1r21/source/cmt_symbol.cxx

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

See C.L. 418

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