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

Last change on this file since 615 was 11, checked in by arnault, 19 years ago

Changing eol-style property

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