source: CMT/v1r18p20051108/source/cmt_symbol.cxx

Last change on this file was 113, checked in by arnault, 19 years ago

Fix: must expand PATH values before filtering and setting them see CL290

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