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

Last change on this file since 136 was 136, checked in by arnault, 18 years ago

Implement ticket #14 - See CL 292

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