source: CMT/v1r18p20050901/source/cmt_symbol.cxx @ 693

Last change on this file since 693 was 81, checked in by arnault, 19 years ago

moving get_strategy to cmt_use - see CL#276

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