source: CMT/v1r20p20070524/source/cmt_symbol.cxx

Last change on this file was 400, checked in by arnault, 17 years ago

Text formatting
Sending warnings & errors to stderr
Using internally PWD for every cd/pwd
CL 327

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