source: CMT/v1r18p20060301/source/cmt_symbol.cxx @ 615

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

Various fixes and message cleanups see CL 294 and 295

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