source: CMT/v1r19p20061114/source/cmt_symbol.cxx

Last change on this file was 257, checked in by garonne, 18 years ago

see CL 312

  • 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                  cout << "#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              //cout << "...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 << "; ";
1480                  cout << endl;
1481                }
1482            }
1483        }
1484    }
1485}
1486
1487//-------------------------------------------------------------
1488void Symbol::check_all_paths ()
1489{
1490  static SymbolVector& Symbols = symbols ();
1491
1492  int number;
1493
1494  if (Symbols.size () == 0) return;
1495
1496  for (number = 0; number < Symbol::symbol_number (); number++)
1497    {
1498      Symbol& symbol = Symbol::symbol (number);
1499
1500      if (symbol.type == SymbolPath)
1501        {
1502          cmt_string temp;
1503
1504          temp = symbol.build_macro_value ();
1505          expand (temp);
1506
1507          Symbol::filter_path_value (symbol.name, temp);
1508        }
1509    }
1510}
1511
1512//-------------------------------------------------------------
1513void Symbol::all_print_clean (PrintMode mode)
1514{
1515  static SymbolVector& Symbols = symbols ();
1516
1517  int number;
1518
1519  if (Symbols.size () == 0) return;
1520
1521  for (number = Symbols.size () - 1; number >= 0; number--)
1522    {
1523      Symbol& symbol = Symbols[number];
1524
1525      if ((symbol.type == SymbolSet) ||
1526          (symbol.type == SymbolAlias) ||
1527          (symbol.type == SymbolCleanupScript))
1528        {
1529          if (symbol.print_clean (mode))
1530            {
1531              cout << endl;
1532            }
1533        }
1534    }
1535
1536  for (number = Symbols.size () - 1; number >= 0; number--)
1537    {
1538      Symbol& symbol = Symbols[number];
1539
1540      if ((symbol.type != SymbolPath)) continue;
1541
1542      if (symbol.print_clean (mode))
1543        {
1544          cout << endl;
1545        }
1546    }
1547}
1548
1549//-------------------------------------------------------------
1550int Symbol::print_clean (PrintMode mode)
1551{
1552  int result = 0;
1553  static cmt_string temp;
1554
1555  if (name == "CMTCONFIG") return (0);
1556
1557  switch (type)
1558    {
1559    case SymbolSet :
1560      switch (mode)
1561        {
1562        case Csh :
1563          cout << "unsetenv " << name;
1564          result = 1;
1565          break;
1566        case Sh :
1567          cout << "unset " << name;
1568          result = 1;
1569          break;
1570        case Bat :
1571          cout << "set " << name << "=";
1572          result = 1;
1573          break;
1574        }
1575      break;
1576    case SymbolAlias :
1577      switch (mode)
1578        {
1579          case Csh :
1580            cout << "unalias " << name;
1581            result = 1;
1582            break;
1583          case Sh :
1584            cout << "unset " << name;
1585            result = 1;
1586            break;
1587        }
1588      break;
1589    case SymbolPath :
1590      temp = clean_macro_value ();
1591      switch (mode)
1592        {
1593        case Csh :
1594          if (temp == "")
1595            {
1596              cout << "unsetenv " << name;
1597            }
1598          else
1599            {
1600              cout << "setenv " << name << " " << temp;
1601            }
1602          result = 1;
1603          break;
1604        case Sh :
1605          cout << name << "=" << temp << "; export " << name;
1606          result = 1;
1607          break;
1608        case Bat :
1609          cout << "set " << name << "=" << temp;
1610          result = 1;
1611          break;
1612        }
1613      break;
1614    case SymbolCleanupScript :
1615      switch (mode)
1616        {
1617        case Csh :
1618          cout << "if ( -f " << name << ".csh ) then" << endl;
1619          cout << "  source " << name << ".csh" << endl;
1620          cout << "endif" << endl;
1621          result = 1;
1622          break;
1623        case Sh :
1624          cout << "if test -f " << name << ".sh; then" << endl;
1625          cout << "  . " << name << ".sh" << endl;
1626          cout << "fi" << endl;
1627          result = 1;
1628          break;
1629        case Bat :
1630          cout << "call " << name;
1631          result = 1;
1632          break;
1633        }
1634      break;
1635    }
1636
1637  return (result);
1638}
1639
1640//-------------------------------------------------------------
1641int Symbol::print (PrintMode mode)
1642{
1643  int result = 0;
1644  cmt_string temp;
1645
1646  temp = build_macro_value ();
1647
1648  bool empty = (temp.size () == 0) ? true : false;
1649
1650  if (type == SymbolPath)
1651    {
1652      expand (temp);
1653      Symbol::filter_path_value (name, temp);
1654    }
1655
1656  switch (type)
1657    {
1658      case SymbolSet :
1659      case SymbolPath :
1660        switch (mode)
1661          {
1662            case Csh :
1663              if (empty) cout << "unsetenv " << name;
1664              else cout << "setenv " << name << " \"" << temp << "\"";
1665
1666              result = 1;
1667              break;
1668            case Sh :
1669              if (empty) cout << "unset " << name;
1670              else cout << name << "=\"" << temp << "\"; export " << name;
1671
1672              result = 1;
1673              break;
1674            case Bat :
1675              temp.replace_all ("/", "\\");
1676              cout << "set " << name << "=" << temp;
1677              result = 1;
1678              break;
1679          }
1680        break;
1681      case SymbolAlias :
1682        switch (mode)
1683          {
1684            case Csh :
1685              cout << "alias " << name <<
1686                  " \"" << temp << "\"";
1687              result = 1;
1688              break;
1689            case Sh :
1690              cout << "alias " << name <<
1691                  "=\"" << temp << "\"";
1692              result = 1;
1693              break;
1694            case Bat :
1695              cout << "set " << name <<
1696                  "=" << temp;
1697              result = 1;
1698              break;
1699          }
1700        break;
1701      default :
1702        break;
1703    }
1704
1705  if (temp != "")
1706    {
1707      switch (type)
1708        {
1709          case SymbolSetupScript :
1710            switch (mode)
1711              {
1712                case Csh :
1713                  cout << "if ( -f " << name << ".csh ) then" << endl;
1714                  cout << "  source " << name << ".csh" << endl;
1715                  cout << "endif" << endl;
1716                  result = 1;
1717                  break;
1718                case Sh :
1719                  cout << "if test -f " << name << ".sh; then" << endl;
1720                  cout << "  . " << name << ".sh" << endl;
1721                  cout << "fi" << endl;
1722                  result = 1;
1723                  break;
1724                case Bat :
1725                  cout << "call " << name;
1726                  result = 1;
1727                  break;
1728              }
1729            break;
1730          default:
1731            break;
1732        }
1733    }
1734
1735  return (result);
1736}
1737
1738//-------------------------------------------------------------
1739cmt_string Symbol::build_macro_value (bool display_it) const
1740{
1741  cmt_string temp;
1742
1743  if (display_it)
1744    {
1745      temp = builder->build_and_display (*this);
1746    }
1747  else
1748    {
1749      temp = builder->build (*this);
1750    }
1751
1752  return (temp);
1753}
1754
1755//-------------------------------------------------------------
1756cmt_string Symbol::clean_macro_value () const
1757{
1758  cmt_string temp;
1759
1760  temp = builder->clean (*this);
1761
1762  return (temp);
1763}
1764
1765/**
1766
1767   Attempt to substitute into the symbol value all occurrences of
1768
1769      ${xxx}
1770      $(xxx)
1771      `xxx`
1772      %xxx%    [on Windows only]
1773
1774      by the appropriate value:
1775
1776        for `xxx` :
1777
1778            xxx is considered as a shell command. Value is the result of its execution
1779
1780        for other patterns:
1781
1782            if xxx is a symbol name, its value is substituted to the pattern
1783            otherwise, xxx is tried as an environment variable
1784
1785
1786     ===> In all cases, the pattern is filtered away.
1787
1788  */
1789cmt_string Symbol::resolve_macro_value (const cmt_string& tag_name)
1790{
1791  cmt_string temp = builder->build (*this, tag_name);
1792
1793  resolve_value (temp);
1794
1795  return (temp);
1796}
1797
1798//-------------------------------------------------------------
1799void Symbol::show_macro (PrintMode mode)
1800{
1801  if (Cmt::get_debug ())
1802    {
1803      cout << "Symbol::show_macro> " << name << endl;
1804    }
1805
1806  ActionType action = Cmt::get_action ();
1807
1808  cmt_string value = build_macro_value (true);
1809
1810  if ((!Cmt::get_quiet ()) &&
1811      (action != action_build_tag_makefile) &&
1812      (action != action_show_macros) &&
1813      (action != action_show_actions) &&
1814      (action != action_show_sets))
1815    {
1816      cout << "#" << endl;
1817      cout << "# Selection : " << endl;
1818    }
1819
1820  if (value.size () > 0)
1821    {
1822      if ((action == action_show_macro) ||
1823          (action == action_show_macros) ||
1824          (action == action_show_sets) ||
1825          (action == action_show_set) ||
1826          (action == action_show_actions) ||
1827          (action == action_show_action) ||
1828          (action == action_build_tag_makefile) ||
1829          (action == action_load) ||
1830          (!Cmt::get_quiet ()))
1831        {
1832          if (mode == Make)
1833            {
1834              cout << name << "=";
1835            }
1836          else
1837            {
1838              cout << name << "='";
1839            }
1840        }
1841
1842      if ((action == action_show_macro_value) ||
1843          (action == action_show_set_value) ||
1844          (action == action_show_action_value))
1845        {
1846          expand (value);
1847        }
1848      else if (action == action_build_tag_makefile)
1849        {
1850            /*
1851               Unfortunately, the %xxx% pattern has to be kept on Unix. Therefore
1852               we cannot force all patterns to become $(xxx)
1853
1854               This was useful on Windows so as to only keep $(xxx)
1855             */
1856#ifdef WIN32
1857          suppress_OS_delimiters (value);
1858#endif
1859        }
1860
1861      cout << value;
1862
1863      if ((action == action_show_macro) ||
1864          (action == action_show_macros) ||
1865          (action == action_show_sets) ||
1866          (action == action_show_set) ||
1867          (action == action_show_actions) ||
1868          (action == action_show_action) ||
1869          (action == action_build_tag_makefile) ||
1870          (action == action_load) ||
1871          (!Cmt::get_quiet ()))
1872        {
1873          if (mode != Make)
1874            {
1875              cout << "'";
1876            }
1877#ifdef WIN32
1878          else
1879            {
1880              cout << " ";
1881            }
1882#endif
1883        }
1884
1885      cout << endl;
1886    }
1887}
1888
1889//-------------------------------------------------------------
1890void Symbol::clear_all ()
1891{
1892  static SymbolVector& Symbols = symbols ();
1893  static SymbolMap& SymbolMap = symbol_map ();
1894
1895  SymbolMap.clear ();
1896  Symbols.clear ();
1897}
1898
1899//-------------------------------------------------------------
1900void Symbol::expand (cmt_string& text)
1901{
1902  static cmt_regexp reg ("[$%`]");
1903
1904  if (!reg.match (text)) return;
1905
1906  resolve_value (text);
1907}
1908
1909//-------------------------------------------------------------
1910ValueBuilder::ValueBuilder ()
1911{
1912  m_display_it = false;
1913}
1914
1915//-------------------------------------------------------------
1916const cmt_string ValueBuilder::build_and_display (const Symbol& symbol)
1917{
1918  cmt_string temp;
1919
1920  m_display_it = true;
1921  temp = build (symbol);
1922  m_display_it = false;
1923
1924  return (temp);
1925}
1926
1927//-------------------------------------------------------------
1928const cmt_string SetBuilder::build (const Symbol& symbol,
1929                                    const cmt_string& /*tag_name*/)
1930{
1931    // Control of recursivity
1932  static int level = 0;
1933
1934  bool show_it = false;
1935
1936  cmt_string temp;
1937  cmt_string previous_temp;
1938  cmt_string new_value;
1939  static const cmt_string empty;
1940
1941  ActionType action = Cmt::get_action ();
1942
1943  if (action == action_show_set)
1944    {
1945      if (symbol.name == Cmt::get_current_target ())
1946        {
1947             // Should not display on recursive calls
1948          if (level == 0) show_it = m_display_it;
1949        }
1950    }
1951
1952  level++;
1953
1954  temp = "";
1955
1956  bool first_definition = true;
1957
1958  for (int i = 0; i < symbol.value_lists.size (); i++)
1959    {
1960      const SymbolValueList& value_list = symbol.value_lists[i];
1961
1962      if ((value_list.use != 0) &&
1963          (value_list.use->discarded)) continue;
1964
1965      const int selected = value_list.select_first ();
1966
1967      if (selected < 0) continue;
1968
1969      SymbolValue& value = value_list.values[selected];
1970
1971      if (show_it && !Symbol::get_inhibit_display())
1972        {
1973          value_list.show (symbol, value, first_definition);
1974        }
1975     
1976      if (value_list.discarded) continue;
1977
1978        //
1979        // One should accumulate values if it refers to
1980        // itself.
1981        //
1982     
1983      new_value = value.text;
1984     
1985      resolve_value_for_macros (new_value);
1986     
1987      switch (value_list.command_type)
1988        {
1989          case CommandSet :
1990
1991            if (!value_list.is_reflexive || 
1992                !symbol.value_is_reflexive (value.text))
1993              {
1994                resolve_value (new_value, symbol.name, temp);
1995                temp = new_value;
1996              }
1997            else if (temp == "")
1998              {
1999                temp = CmtSystem::getenv (symbol.name);
2000              }
2001
2002            break;
2003          case CommandSetAppend :
2004           
2005            if (new_value != "")
2006              {
2007                temp += new_value;
2008              }
2009           
2010            break;
2011          case CommandSetPrepend :
2012           
2013            if (new_value != "")
2014              {
2015                previous_temp = temp;
2016                temp = new_value;
2017                temp += previous_temp;
2018              }
2019           
2020            break;
2021          case CommandSetRemove :
2022           
2023            if (new_value != "")
2024              {
2025                temp.replace_all (new_value, empty);
2026              }
2027           
2028            break;
2029          case CommandSetRemoveRegexp :
2030           
2031            if (new_value != "")
2032              {
2033                cmt_regexp e (new_value);
2034                cmt_regexp::iterator it;
2035
2036                for (;;)
2037                  {
2038                    it = e.begin (temp);
2039                    if (it == e.end ()) break;
2040
2041                    temp.erase (it._pos, it._length);
2042                  }
2043              }
2044           
2045            break;
2046          case CommandAlias :
2047           
2048            resolve_value (new_value, symbol.name, temp);
2049            temp = new_value;
2050           
2051            break;
2052        }
2053    }
2054
2055  level--;
2056
2057  return (temp);
2058}
2059
2060static bool find_path_entry (const cmt_string& paths, const cmt_string& value)
2061{
2062  static const cmt_string path_separator = CmtSystem::path_separator ();
2063
2064  cmt_string here = CmtSystem::pwd ();
2065  cmt_string rvalue = value;
2066
2067  if (CmtSystem::cd (value))
2068    {
2069      rvalue = CmtSystem::pwd ();
2070    }
2071  else
2072    {
2073      CmtSystem::compress_path (rvalue);
2074    }
2075
2076  CmtSystem::cmt_string_vector items;
2077  CmtSystem::split (paths, path_separator, items);
2078
2079  bool found = false;
2080
2081  for (int i = 0; i < items.size (); i++)
2082    {
2083      const cmt_string& item = items[i];
2084      cmt_string ritem = item;
2085      if (CmtSystem::cd (item))
2086        {
2087          ritem = CmtSystem::pwd ();
2088        }
2089      else
2090        {
2091          CmtSystem::compress_path (ritem);
2092        }
2093
2094      if (ritem == rvalue)
2095        {
2096          found = true;
2097          break;
2098        }
2099    }
2100
2101  CmtSystem::cd (here);
2102  return (found);
2103}
2104
2105//-------------------------------------------------------------
2106const cmt_string PathBuilder::build (const Symbol& symbol,
2107                                     const cmt_string& /*tag_name*/)
2108{
2109    // Control of recursivity
2110  static int level = 0;
2111
2112  bool show_it = false;
2113
2114  cmt_string temp;
2115  cmt_string previous_temp;
2116  cmt_string new_value;
2117  static const cmt_string empty;
2118
2119  static cmt_string path_separator = CmtSystem::path_separator ();
2120
2121  ActionType action = Cmt::get_action ();
2122
2123  if (action == action_show_set)
2124    {
2125      if (symbol.name == Cmt::get_current_target ())
2126        {
2127            // Should not display on recursive calls
2128          if (level == 0) show_it = m_display_it;
2129        }
2130    }
2131
2132  level++;
2133
2134  temp = CmtSystem::getenv (symbol.name);
2135
2136  bool first_definition = true;
2137
2138  for (int i = 0; i < symbol.value_lists.size (); i++)
2139    {
2140      const SymbolValueList& value_list = symbol.value_lists[i];
2141
2142      if ((value_list.use != 0) &&
2143          (value_list.use->discarded)) continue;
2144
2145      const int selected = value_list.select_first ();
2146     
2147      if (selected < 0) continue;
2148 
2149      SymbolValue& value = value_list.values[selected];
2150         
2151      if (show_it && !Symbol::get_inhibit_display())
2152        {
2153          value_list.show (symbol, value, first_definition);
2154        }
2155         
2156      if (value_list.discarded) continue;
2157
2158      new_value = value.text;
2159         
2160          //resolve_value (new_value);
2161      resolve_value_for_macros (new_value);
2162         
2163      switch (value_list.command_type)
2164        {
2165          case CommandPath :
2166           
2167            if (!value_list.is_reflexive || 
2168                !symbol.value_is_reflexive (value.text))
2169              {
2170                resolve_value (new_value, symbol.name, temp);
2171                temp = new_value;
2172              }
2173
2174            break;
2175          case CommandPathAppend :
2176             
2177            if (new_value != "")
2178              {
2179                if (!find_path_entry (temp, new_value))
2180                  {
2181                    if (temp != "") temp += path_separator;
2182                     
2183                    temp += new_value;
2184                  }
2185              }
2186                 
2187            break;
2188          case CommandPathPrepend :
2189             
2190            if (new_value != "")
2191              {
2192                if (!find_path_entry (temp, new_value))
2193                  {
2194                    previous_temp = temp;
2195                    temp = new_value;
2196                    if (previous_temp != "") temp += path_separator;
2197                    temp += previous_temp;
2198                  }
2199              }
2200                 
2201            break;
2202          case CommandPathRemove :
2203             
2204            if (new_value != "")
2205              {
2206                CmtSystem::cmt_string_vector paths;
2207                 
2208                CmtSystem::split (temp, path_separator, paths);
2209                 
2210                for (int j = 0; j < paths.size (); ++j)
2211                  {
2212                    cmt_string& s = paths[j];
2213                     
2214                    if (s.find (new_value) != cmt_string::npos)
2215                      {
2216                        s = "";
2217                      }
2218                  }
2219
2220                Cmt::vector_to_string (paths, path_separator, temp);
2221              }
2222             
2223            break;
2224          case CommandPathRemoveRegexp :
2225
2226            if (new_value != "")
2227              {
2228                cmt_regexp e (new_value);
2229
2230                CmtSystem::cmt_string_vector paths;
2231                 
2232                CmtSystem::split (temp, path_separator, paths);
2233                 
2234                for (int j = 0; j < paths.size (); ++j)
2235                  {
2236                    cmt_string& s = paths[j];
2237
2238                    if (CmtSystem::getenv ("TESTPRR") != "")
2239                      {
2240                        cout << "PRR> s=[" << s << "]";
2241                      }
2242
2243                    if (e.match (s))
2244                      {
2245                        s = "";
2246
2247                        if (CmtSystem::getenv ("TESTPRR") != "")
2248                          {
2249                            cout << " match ";
2250                          }
2251                      }
2252                    else
2253                      {
2254                        if (CmtSystem::getenv ("TESTPRR") != "")
2255                          {
2256                            cout << " no match ";
2257                          }
2258                      }
2259
2260                    if (CmtSystem::getenv ("TESTPRR") != "")
2261                      {
2262                        cout << endl;
2263                      }
2264                  }
2265
2266                Cmt::vector_to_string (paths, path_separator, temp);
2267              }
2268             
2269            break;
2270        }
2271
2272    }
2273
2274  level--;
2275
2276  for (;;)
2277    {
2278      int sz = temp.size ();
2279
2280      if (sz == 0) break;
2281
2282      if ((temp[0] == ';') || (temp[0] == ':'))
2283        {
2284          temp.erase (0, 1);
2285        }
2286      else if ((temp[sz-1] == ';') || (temp[sz-1] == ':'))
2287        {
2288          temp.erase (sz-1, 1);
2289        }
2290      else
2291        {
2292          break;
2293        }
2294    }
2295
2296  temp.replace_all ("::", ":");
2297  temp.replace_all (";;", ";");
2298 
2299  return (temp);
2300}
2301
2302//-------------------------------------------------------------
2303const cmt_string PathBuilder::clean (const Symbol& symbol,
2304                                     const cmt_string& /*tag_name*/)
2305{
2306    // Control of recursivity
2307  static int level = 0;
2308
2309  cmt_string temp;
2310  cmt_string new_value;
2311  static const cmt_string empty;
2312
2313  static cmt_string path_separator = CmtSystem::path_separator ();
2314
2315  temp = CmtSystem::getenv (symbol.name);
2316
2317    //cerr << "#####1 temp=" << temp << endl;
2318
2319  for (int i = 0; i < symbol.value_lists.size (); i++)
2320    {
2321      const SymbolValueList& value_list = symbol.value_lists[i];
2322
2323      if (value_list.discarded) continue;
2324
2325      if ((value_list.use != 0) &&
2326          (value_list.use->discarded)) continue;
2327
2328      const int selected = value_list.select_first ();
2329     
2330      if (selected < 0) continue;
2331 
2332      SymbolValue& value = value_list.values[selected];
2333         
2334      new_value = value.text;
2335         
2336          //resolve_value (new_value);
2337
2338        //cerr << "#####1 new_value=" << new_value << endl;
2339
2340      resolve_value_for_macros (new_value);
2341      resolve_value (new_value);
2342         
2343        //cerr << "#####2 new_value=" << new_value << endl;
2344
2345      switch (value_list.command_type)
2346        {
2347          case CommandPath :
2348           
2349            temp = "";
2350           
2351            break;
2352          case CommandPathAppend :
2353          case CommandPathPrepend :
2354          case CommandPathRemove :
2355
2356            if (new_value != "")
2357              {
2358                CmtSystem::cmt_string_vector paths;
2359                 
2360                CmtSystem::split (temp, path_separator, paths);
2361                 
2362                for (int j = 0; j < paths.size (); ++j)
2363                  {
2364                    cmt_string& s = paths[j];
2365                     
2366                    if (s.find (new_value) != cmt_string::npos)
2367                      {
2368                        s = "";
2369                      }
2370
2371                    if (j > 0)
2372                      {
2373                        cmt_string& s2 = paths[j-1];
2374                        if (s2 == s)
2375                          {
2376                            s2 = "";
2377                          }
2378                      }
2379                  }
2380
2381                Cmt::vector_to_string (paths, path_separator, temp);
2382                temp.replace_all ("::", ":");
2383                temp.replace_all (";;", ";");
2384              }
2385             
2386            break;
2387          case CommandPathRemoveRegexp :
2388
2389            if (new_value != "")
2390              {
2391                cmt_regexp e (new_value);
2392
2393                CmtSystem::cmt_string_vector paths;
2394                 
2395                CmtSystem::split (temp, path_separator, paths);
2396                 
2397                for (int j = 0; j < paths.size (); ++j)
2398                  {
2399                    cmt_string& s = paths[j];
2400                     
2401                    if (e.match (s))
2402                      {
2403                        s = "";
2404                      }
2405
2406                    if (j > 0)
2407                      {
2408                        cmt_string& s2 = paths[j-1];
2409                        if (s2 == s)
2410                          {
2411                            s2 = "";
2412                          }
2413                      }
2414                  }
2415
2416                Cmt::vector_to_string (paths, path_separator, temp);
2417                temp.replace_all ("::", ":");
2418                temp.replace_all (";;", ";");
2419              }
2420             
2421            break;
2422        }
2423    }
2424
2425    //cerr << "#####2 temp=" << temp << endl;
2426 
2427  return (temp);
2428}
2429
2430//-------------------------------------------------------------
2431const cmt_string MacroBuilder::build (const Symbol& symbol,
2432                                      const cmt_string& tag_name)
2433{
2434    // Control of recursivity
2435  static int level = 0;
2436
2437  cmt_string temp;
2438  cmt_string previous_temp;
2439  static const cmt_string empty;
2440  bool show_it = false;
2441
2442  ActionType action = Cmt::get_action ();
2443
2444  if (action == action_show_macro)
2445    {
2446      if (symbol.name == Cmt::get_current_target ())
2447        {
2448             // Should not display on recursive calls
2449          if (level == 0) show_it = m_display_it;
2450        }
2451    }
2452
2453  level++;
2454
2455  temp = "";
2456
2457  int i;
2458
2459  bool first_definition = true;
2460
2461  for (i = 0; i < symbol.value_lists.size (); i++)
2462    {
2463      const SymbolValueList& value_list = symbol.value_lists[i];
2464
2465      if ((value_list.use != 0) &&
2466          (value_list.use->discarded)) continue;
2467
2468      if (value_list.command_type != CommandMacroPrepend) continue;
2469
2470      const int selected = value_list.select_first (tag_name);
2471
2472      if (selected < 0) continue;
2473
2474      SymbolValue& value = value_list.values[selected];
2475
2476      if (show_it && !Symbol::get_inhibit_display())
2477        {
2478          value_list.show (symbol, value, first_definition);
2479        }
2480
2481      if (value_list.discarded) continue;
2482
2483      previous_temp = temp;
2484      temp = value.text;
2485      temp += previous_temp;
2486    }
2487
2488  previous_temp = temp;
2489  temp = "";
2490
2491  first_definition = true;
2492
2493  for (i = 0; i < symbol.value_lists.size (); i++)
2494    {
2495      const SymbolValueList& value_list = symbol.value_lists[i];
2496
2497      if ((value_list.use != 0) &&
2498          (value_list.use->discarded)) continue;
2499
2500      if (value_list.command_type != CommandMacro) continue;
2501
2502      const int selected = value_list.select_first (tag_name);
2503
2504      if (selected < 0) continue;
2505
2506      SymbolValue& value = value_list.values[selected];
2507
2508      if (show_it && !Symbol::get_inhibit_display())
2509        {
2510          value_list.show (symbol, value, first_definition);
2511        }
2512
2513      // WARNING:
2514      // Commented just for a test : should be uncommented after the test
2515      if (value_list.discarded) continue;
2516     
2517      if (!value_list.is_reflexive || 
2518          !symbol.value_is_reflexive (value.text))
2519        {
2520          temp = value.text;
2521        }
2522    }
2523
2524  previous_temp += temp;
2525  temp = previous_temp;
2526
2527  for (i = 0; i < symbol.value_lists.size (); i++)
2528    {
2529      const SymbolValueList& value_list = symbol.value_lists[i];
2530
2531      if ((value_list.use != 0) &&
2532          (value_list.use->discarded)) continue;
2533
2534      if (value_list.command_type != CommandMacroAppend) continue;
2535
2536      const int selected = value_list.select_first (tag_name);
2537
2538      if (selected < 0) continue;
2539
2540      SymbolValue& value = value_list.values[selected];
2541
2542      if (show_it && !Symbol::get_inhibit_display())
2543        {
2544          value_list.show (symbol, value, first_definition);
2545        }
2546
2547      if (value_list.discarded) continue;
2548
2549      temp += value.text;
2550    }
2551
2552  for (i = 0; i < symbol.value_lists.size (); i++)
2553    {
2554      const SymbolValueList& value_list = symbol.value_lists[i];
2555
2556      if ((value_list.use != 0) &&
2557          (value_list.use->discarded)) continue;
2558
2559      if ((value_list.command_type != CommandMacroRemove) &&
2560          (value_list.command_type != CommandMacroRemoveRegexp) &&
2561          (value_list.command_type != CommandMacroRemoveAll) &&
2562          (value_list.command_type != CommandMacroRemoveAllRegexp)) continue;
2563
2564      const int selected = value_list.select_first (tag_name);
2565
2566      if (selected < 0) continue;
2567
2568      SymbolValue& value = value_list.values[selected];
2569
2570      if (show_it && !Symbol::get_inhibit_display())
2571        {
2572          value_list.show (symbol, value, first_definition);
2573        }
2574
2575      if (value_list.discarded) continue;
2576
2577      switch (value_list.command_type)
2578        {
2579          case CommandMacroRemove :
2580            temp.replace (value.text, empty);
2581            break;
2582          case CommandMacroRemoveRegexp :
2583            if (value.text != "")
2584              {
2585                cmt_regexp e (value.text);
2586                cmt_regexp::iterator it;
2587
2588                it = e.begin (temp);
2589                if (it != e.end ())
2590                  {
2591                    temp.erase (it._pos, it._length);
2592                  }
2593              }
2594            break;
2595          case CommandMacroRemoveAll :
2596            temp.replace_all (value.text, empty);
2597            break;
2598          case CommandMacroRemoveAllRegexp :
2599            if (value.text != "")
2600              {
2601                cmt_regexp e (value.text);
2602                cmt_regexp::iterator it;
2603
2604                for (;;)
2605                  {
2606                    it = e.begin (temp);
2607                    if (it != e.end ())
2608                      {
2609                        temp.erase (it._pos, it._length);
2610                      }
2611                    else
2612                      {
2613                        break;
2614                      }
2615                  }
2616              }
2617            break;
2618        }
2619    }
2620
2621  level--;
2622
2623  return (temp);
2624}
2625
2626//-------------------------------------------------------------
2627const cmt_string ScriptBuilder::build (const Symbol& symbol,
2628                                       const cmt_string& tag_name)
2629{
2630    // Control of recursivity
2631  static int level = 0;
2632
2633  static const cmt_string empty = "";
2634
2635  if (symbol.value_lists.size () > 0)
2636    {
2637      const SymbolValueList& value_list = symbol.value_lists[0];
2638
2639      if (value_list.discarded) return (empty);
2640
2641      if ((value_list.use != 0) &&
2642          (value_list.use->discarded)) return (empty);
2643    }
2644
2645  return (symbol.name);
2646}
2647
2648//-------------------------------------------------------------
2649const cmt_string ActionBuilder::build (const Symbol& symbol,
2650                                       const cmt_string& tag_name)
2651{
2652    // Control of recursivity
2653  static int level = 0;
2654
2655  cmt_string temp;
2656  cmt_string previous_temp;
2657  static const cmt_string empty;
2658  bool show_it = false;
2659
2660  ActionType action = Cmt::get_action ();
2661
2662  if (action == action_show_action)
2663    {
2664      if (symbol.name == Cmt::get_current_target ())
2665        {
2666             // Should not display on recursive calls
2667          if (level == 0) show_it = m_display_it;
2668        }
2669    }
2670
2671  level++;
2672
2673  int i;
2674
2675  bool first_definition = true;
2676
2677  temp = "";
2678
2679  for (i = 0; i < symbol.value_lists.size (); i++)
2680    {
2681      const SymbolValueList& value_list = symbol.value_lists[i];
2682
2683      if ((value_list.use != 0) &&
2684          (value_list.use->discarded)) continue;
2685
2686      if (value_list.command_type != CommandAction) continue;
2687
2688      const int selected = value_list.select_first (tag_name);
2689
2690      if (selected < 0) continue;
2691
2692      SymbolValue& value = value_list.values[selected];
2693
2694      if (show_it && !Symbol::get_inhibit_display())
2695        {
2696          value_list.show (symbol, value, first_definition);
2697        }
2698
2699      // WARNING:
2700      // Commented just for a test : should be uncommented after the test
2701      if (value_list.discarded) continue;
2702     
2703      if (!value_list.is_reflexive || 
2704          !symbol.value_is_reflexive (value.text))
2705        {
2706          temp = value.text;
2707        }
2708    }
2709
2710  level--;
2711
2712  return (temp);
2713}
2714
2715//-------------------------------------------------------------
2716int SymbolValueList::select_first (const cmt_string& tag_name) const
2717{
2718  int priority = 0;
2719  int value_number;
2720  int selected = -1;
2721
2722  Tag* the_tag = 0;
2723
2724  if (tag_name != "") the_tag = Tag::find (tag_name);
2725
2726  for (value_number = 0;
2727       value_number < values.size ();
2728       value_number++)
2729    {
2730      const SymbolValue& value = values[value_number];
2731
2732      const Tag* tag = value.tag;
2733
2734      if (the_tag == 0)
2735        {
2736          if (!tag->is_selected ()) continue;
2737        }
2738      else
2739        {
2740          if (tag != the_tag) continue;
2741          selected = value_number;
2742        }
2743
2744      //
2745      // Only the first value at a given priority is
2746      // selected (which implies the '>' test instead
2747      // of '>=')
2748      //
2749
2750      if (tag->get_priority () > priority)
2751        {
2752          priority = tag->get_priority ();
2753          selected = value_number;
2754        }
2755    }
2756
2757  return (selected);
2758}
2759
2760//-------------------------------------------------------------
2761int SymbolValueList::select_last () const
2762{
2763  int priority = 0;
2764  int value_number;
2765  int selected = -1;
2766
2767  for (value_number = 0;
2768       value_number < values.size ();
2769       value_number++)
2770    {
2771      SymbolValue& value = values[value_number];
2772
2773      const Tag* tag = value.tag;
2774
2775      if (tag->is_selected ())
2776        {
2777          //
2778          // The last value at a given priority is
2779          // selected (which implies the '>=' test instead
2780          // of '>')
2781          //
2782
2783          if (tag->get_priority () >= priority)
2784            {
2785              priority = tag->get_priority ();
2786              selected = value_number;
2787            }
2788        }
2789    }
2790
2791  return (selected);
2792}
2793
2794//-------------------------------------------------------------
2795void SymbolValueList::show (const Symbol& symbol, 
2796                            const SymbolValue& value, 
2797                            bool& first_definition) const
2798{
2799  cmt_string discarded_text;
2800  cmt_string define_text;
2801  ActionType action = Cmt::get_action ();
2802
2803  switch (command_type)
2804    {
2805      //case CommandSet :
2806      case CommandSetAppend :
2807      case CommandSetPrepend :
2808      case CommandSetRemove :
2809      case CommandSetRemoveRegexp :
2810        //case CommandAlias :
2811        //case CommandPath :
2812      case CommandPathAppend :
2813      case CommandPathPrepend :
2814      case CommandPathRemove :
2815      case CommandPathRemoveRegexp :
2816      case CommandMacroPrepend :
2817        //case CommandMacro :
2818      case CommandMacroAppend :
2819      case CommandMacroRemove :
2820      case CommandMacroRemoveRegexp :
2821      case CommandMacroRemoveAll :
2822      case CommandMacroRemoveAllRegexp :
2823        //case CommandAction :
2824        if (value.text == "") return;
2825        break;
2826    }
2827
2828  if (discarded) discarded_text = " (discarded by override)";
2829  else discarded_text = "";
2830
2831  if (first_definition) define_text = "defines";
2832  else define_text = "overrides";
2833
2834  cout << "# Package ";
2835  if (use != 0)
2836    {
2837      cout << use->get_package_name () << " " << use->version;
2838    }
2839
2840  switch (command_type)
2841    {
2842      case CommandSet :
2843        cout << " " << define_text << " set " << symbol.name << " as ";
2844        first_definition = false;
2845        break;
2846      case CommandSetAppend :
2847        cout << " appends to set " << symbol.name << " : ";
2848        break;
2849      case CommandSetPrepend :
2850        cout << " prepends to set " << symbol.name << " : ";
2851        break;
2852      case CommandSetRemove :
2853        cout << " removes from set " << symbol.name << " : ";
2854        break;
2855      case CommandSetRemoveRegexp :
2856        cout << " removes RE from set " << symbol.name << " : ";
2857        break;
2858      case CommandAlias :
2859        cout << " " << define_text << " alias " << symbol.name << " as ";
2860        first_definition = false;
2861        break;
2862      case CommandPath :
2863        cout << " " << define_text << " path " << symbol.name << " as ";
2864        first_definition = false;
2865        break;
2866      case CommandPathAppend :
2867        cout << " appends to path " << symbol.name << " : ";
2868        break;
2869      case CommandPathPrepend :
2870        cout << " prepends to path " << symbol.name << " : ";
2871        break;
2872      case CommandPathRemove :
2873        cout << " removes from path " << symbol.name << " : ";
2874        break;
2875      case CommandPathRemoveRegexp :
2876        cout << " removes RE from path " << symbol.name << " : ";
2877        break;
2878      case CommandMacroPrepend :
2879        cout << " prepends to macro " << symbol.name << " : ";
2880        break;
2881      case CommandMacro :
2882        cout << " " << define_text << " macro " << symbol.name << " as ";
2883        break;
2884      case CommandMacroAppend :
2885        cout << " appends to macro " << symbol.name << " : ";
2886        break;
2887      case CommandMacroRemove :
2888        cout << " remove from macro " << symbol.name << " : ";
2889        break;
2890      case CommandMacroRemoveRegexp :
2891        cout << " remove RE from macro " << symbol.name << " : ";
2892        break;
2893      case CommandMacroRemoveAll :
2894        cout << " remove all from macro " << symbol.name << " : ";
2895        break;
2896      case CommandMacroRemoveAllRegexp :
2897        cout << " remove all RE from macro " << symbol.name << " : ";
2898        break;
2899      case CommandAction :
2900        cout << " " << define_text << " action " << symbol.name << " as ";
2901        first_definition = false;
2902        break;
2903    }
2904
2905  cout << "'" << value.text << "'";
2906         
2907  Tag* selected_tag = value.tag;
2908         
2909  if ((selected_tag == 0) ||
2910      (selected_tag == Tag::get_default ()))
2911    {
2912      cout << " for default tag";
2913    }
2914  else
2915    {
2916      cout << " for tag '" << selected_tag->get_name () << "'";
2917    }
2918 
2919  cout << discarded_text << endl;
2920}
2921
2922//-------------------------------------------------------------
2923bool Symbol::check_tag_used (Tag* tag)
2924{
2925  if (tag == 0) return (false);
2926
2927  static SymbolVector& Symbols = symbols ();
2928
2929  if (Symbols.size () == 0) 
2930    {
2931      return (false);
2932    }
2933
2934  for (int number = 0; number < Symbol::symbol_number (); number++)
2935    {
2936      Symbol& symbol = Symbol::symbol (number);
2937
2938      for (int i = 0; i < symbol.value_lists.size (); i++)
2939        {
2940          const SymbolValueList& value_list = symbol.value_lists[i];
2941
2942          for (int j = 0; j < value_list.values.size (); j++)
2943            {
2944              const SymbolValue& value = value_list.values[j];
2945              Tag* t = value.tag;
2946
2947              if (t != 0)
2948                {
2949                  if (t->use_operand (tag)) return (true);
2950                }
2951            }
2952        }
2953    }
2954
2955  return (false);
2956}
2957
2958//-------------------------------------------------------------
2959cmt_string Symbol::get_env_value (const cmt_string& name)
2960{
2961  cmt_string s;
2962
2963  Symbol* symbol = Symbol::find (name);
2964  if (symbol != 0)
2965    {
2966      m_inhibit_display = true;
2967
2968      s = symbol->build_macro_value ();
2969      Symbol::expand (s);
2970
2971      m_inhibit_display = false;
2972    }
2973  else
2974    {
2975      s = CmtSystem::getenv (name);
2976    }
2977
2978  return (s);
2979}
2980
2981bool Symbol::get_inhibit_display ()
2982{
2983  return (m_inhibit_display);
2984}
2985
Note: See TracBrowser for help on using the repository browser.