source: CMT/HEAD/source/cmt_symbol.cxx @ 665

Last change on this file since 665 was 665, checked in by rybkin, 10 years ago

See C.L. 523

  • Property svn:eol-style set to native
File size: 105.1 KB
Line 
1//-----------------------------------------------------------
2// Copyright Christian Arnault LAL-Orsay CNRS
3// arnault@lal.in2p3.fr
4// Modified by Grigory Rybkin
5// See the complete license in cmt_license.txt "http://www.cecill.info".
6//-----------------------------------------------------------
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <ctype.h>
12
13#include "cmt_use.h"
14#include "cmt_symbol.h"
15#include "cmt_system.h"
16#include "cmt_database.h"
17#include "cmt_log.h"
18#include "cmt_error.h"
19
20// Global inhibitor of any display
21bool Symbol::m_inhibit_display = false;
22
23//-------------------------------------------------------------
24class SetBuilder : public ValueBuilder
25{
26public:
27  const cmt_string build (const Symbol& symbol,
28                          const cmt_string& tag_name = "");
29  const cmt_string clean (const Symbol& symbol,
30                          const cmt_string& tag_name = "")
31      {
32        static const cmt_string empty = "";
33        return (empty);
34      }
35};
36//-------------------------------------------------------------
37
38//-------------------------------------------------------------
39class PathBuilder : public ValueBuilder
40{
41public:
42  const cmt_string build (const Symbol& symbol,
43                          const cmt_string& tag_name = "");
44  const cmt_string clean (const Symbol& symbol,
45                          const cmt_string& tag_name = "");
46
47  void filter_path_value (const Symbol& symbol,
48                          cmt_string& value,
49                          const cmt_string& tag_name = "") const;
50  void filter_path_value (const Symbol& symbol,
51                          CmtSystem::cmt_string_vector& value,
52                          const cmt_string& tag_name = "") const;
53  inline const bool& get_strip_path () const;
54  inline void set_strip_path (const bool& strip_path);
55
56  static PathBuilder* get_path_builder ();
57
58private:
59  PathBuilder ();
60  PathBuilder (bool strip_path);
61  PathBuilder (const PathBuilder& other);
62  PathBuilder& operator = (const PathBuilder& other);
63
64  bool m_strip_path;
65};
66//-------------------------------------------------------------
67
68//-------------------------------------------------------------
69class MacroBuilder : public ValueBuilder
70{
71public:
72  const cmt_string build (const Symbol& symbol,
73                          const cmt_string& tag_name = "");
74  const cmt_string clean (const Symbol& symbol,
75                          const cmt_string& tag_name = "")
76      {
77        static const cmt_string empty = "";
78        return (empty);
79      }
80};
81//-------------------------------------------------------------
82
83//-------------------------------------------------------------
84class ScriptBuilder : public ValueBuilder
85{
86public:
87  const cmt_string build (const Symbol& symbol,
88                          const cmt_string& tag_name = "");
89  const cmt_string clean (const Symbol& symbol,
90                          const cmt_string& tag_name = "")
91      {
92        static const cmt_string empty = "";
93        return (empty);
94      }
95};
96//-------------------------------------------------------------
97
98//-------------------------------------------------------------
99class ActionBuilder : public ValueBuilder
100{
101public:
102  const cmt_string build (const Symbol& symbol,
103                          const cmt_string& tag_name = "");
104  const cmt_string clean (const Symbol& symbol,
105                          const cmt_string& tag_name = "")
106      {
107        static const cmt_string empty = "";
108        return (empty);
109      }
110};
111//-------------------------------------------------------------
112
113//-------------------------------------------------------------
114class symbol_marker
115{
116public:
117  symbol_marker ()
118  {
119    ptr = cmt_string::npos;
120    pattern = 0;
121    intro = 0;
122  }
123
124  symbol_marker (int a_ptr, char a_pattern, int a_intro)
125  {
126    ptr = a_ptr;
127    pattern = a_pattern;
128    intro = a_intro;
129  }
130
131  symbol_marker (const symbol_marker& other)
132  {
133    ptr = other.ptr;
134    pattern = other.pattern;
135    intro = other.intro;
136  }
137
138  void set (int a_ptr, char a_pattern, int a_intro)
139  {
140    ptr = a_ptr;
141    pattern = a_pattern;
142    intro = a_intro;
143  }
144
145  static symbol_marker& get_lowest (symbol_marker markers[], int count)
146  {
147    static symbol_marker result;
148    int real_count = 0;
149    int i;
150
151      // Check that at least one marker has result
152
153    for (i = 0; i < count; i++)
154      {
155        if (markers[i].ptr != cmt_string::npos) real_count++;
156      }
157
158    if (real_count == 0) return (result);
159
160    // since we've passed the previous test,
161    // at least one entry is not npos.
162    // Now discards other npos by moving them to the end
163   
164    for (i = 0; i < count;)
165      {
166        if (markers[i].ptr == cmt_string::npos)
167          {
168            markers[i] = markers[count-1];
169            count--;
170            if (count == 0) break;
171          }
172        else
173          {
174            i++;
175          }
176      }
177   
178    if (count == 0) return (result);
179   
180    // now all entries in [0, count-1] are not npos
181    // let's sort the lowest one in [0]
182   
183    for (i = 1; i < count;)
184      {
185        if (markers[0].ptr > markers[i].ptr)
186          {
187            symbol_marker temp = markers[0];
188            markers[0] = markers[i];
189            markers[i] = temp;
190            i = 1;
191          }
192        else
193          {
194            i++;
195          }
196      }
197   
198    return (markers[0]);
199  }
200
201  int ptr;
202  char pattern;
203  int intro;
204};
205//-------------------------------------------------------------
206
207/**
208
209   Attempt to substitute all occurrences of
210
211      ${<symbol_name>}
212      $(<symbol_name>)
213      %<symbol_name>%    [on Windows only]
214
215      by the specified value in the given text.
216
217    This is for one symbol only
218
219 */
220static void resolve_value (cmt_string& text,
221                           const cmt_string& symbol_name,
222                           const cmt_string& value)
223{
224  static cmt_string pattern;
225
226  pattern = "${";
227  pattern += symbol_name;
228  pattern += "}";
229
230  text.replace_all (pattern, value);
231
232  pattern = "$(";
233  pattern += symbol_name;
234  pattern += ")";
235
236  text.replace_all (pattern, value);
237
238#ifdef WIN32
239  pattern = "%";
240  pattern += symbol_name;
241  pattern += "%";
242
243  text.replace_all (pattern, value);
244#endif
245}
246/**
247 * similar to processing
248 * `shell' function of GNU Make does
249 *  on command output
250 */
251static void process_cmd_output (cmt_string& text)
252{
253  //cerr << "process_cmd_output (begin): [" << text << "]" << endl;
254  // remove trailing (carriage-return and) newline(s)
255  int nl = text.size ();
256  while (nl > 0 && text[nl - 1] == '\n')
257    {
258      nl--;
259      if (nl > 0 && text[nl - 1] == '\r')
260        nl--;
261    }
262  if (nl != text.size ())
263    text.erase (nl);
264
265  // convert each newline (or carriage-return / newline pair) to a single space
266  text.replace_all ("\r\n", " ");
267  text.replace_all ("\n", " ");
268  //cerr << "process_cmd_output (end): [" << text << "]" << endl;
269}
270
271//
272// Global cache
273//
274namespace
275{
276  cmt_vmap <cmt_string, cmt_string> cmdoutputs;
277}
278/**
279
280   Attempt to substitute into the specified text all occurrences of
281
282      ${xxx}
283      $(xxx)
284      `xxx`
285      %xxx%    [on Windows only]
286
287      by the appropriate value:
288
289        for `xxx` :
290
291            xxx is considered as a shell command. Value is the result of its execution
292
293        for other patterns:
294
295            if xxx is a symbol name, its value is substituted to the pattern
296            otherwise, xxx is tried as an environment variable
297
298
299     ===> In all cases, the pattern is filtered away.
300
301
302 */
303static void resolve_value (cmt_string& text)
304{
305  //static cmt_regexp reg ("[$%`]");
306
307  //if (!reg.match (text)) return;
308
309  cmt_string pattern;
310  cmt_string symbol_name;
311  char end_pattern;
312
313  int start = 0;
314
315  //  static cmt_vmap <cmt_string, cmt_string> cmdoutputs;
316
317  for (;;)
318    {
319      int begin;
320      int end;
321
322      symbol_marker markers[4];
323      int num = 0;
324
325      markers[num].set (text.find (start, "$("), ')', 2); num++;
326      markers[num].set (text.find (start, "${"), '}', 2); num++;
327      markers[num].set (text.find (start, "`"), '`', 1); num++;
328
329#ifdef WIN32
330      markers[num].set (text.find (start, "%"), '%', 1); num++;
331#endif
332
333      // Find the first matching pattern
334
335      symbol_marker& marker = symbol_marker::get_lowest (markers, num);
336
337      begin = marker.ptr;
338
339      if (begin == cmt_string::npos) break;
340
341      end_pattern = marker.pattern;
342      start = begin + marker.intro;
343
344      end = text.find (start, end_pattern);
345      if (end == cmt_string::npos)
346        {
347          // The pattern is a fake one (no ending!)
348          start++;
349          continue;
350        }
351
352      // This should never happen...
353      if (end < begin) break;
354
355      // Extract the complete pattern
356      text.substr (begin, end - begin + 1, pattern);
357
358      // Then only the symbol name
359      text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name);
360
361      if (text[begin] == '`')
362        {
363          cmt_string command = symbol_name;
364          resolve_value (command);
365
366            // The value is a shell command that first needs
367            // to be applied. The output of the command is then substituted
368
369          Symbol::all_set ();
370
371          cmt_string result;
372          const cmt_string * presult;
373          if (!(presult = cmdoutputs.find (command)))
374            {
375              CmtSystem::execute (command, result);
376             
377              process_cmd_output (result);
378              cmdoutputs.add (command, result);
379              if (Cmt::get_debug ())
380                {
381                  cout << "resolve_value: Executing [" << command << "] to expand a symbol value =>[" 
382                       << result << "]" << endl;
383                }
384            }
385          else
386            {
387              result = *presult;
388              if (Cmt::get_debug ())
389                {
390                  cout << "resolve_value: Found in cache [" << command << "] to expand a symbol value =>[" 
391                       << result << "]" << endl;
392                }
393            }
394
395          text.replace_all (pattern, result);
396
397          // The substitution will restart from the same place
398          // allowing for recursive replacements
399          start = begin;
400        }
401      else
402        {
403          Symbol* symbol = Symbol::find (symbol_name);
404          if (symbol != 0)
405            {
406                // Symbol found
407              cmt_string value = symbol->resolve_macro_value ();
408              text.replace_all (pattern, value);
409             
410                // The substitution will restart from the same place
411                // allowing for recursive replacements
412              start = begin;
413            }
414          else
415            {
416              if (Cmt::get_env_access () ||
417                  Symbol::std_env_vars ().has (symbol_name))
418                {
419                // Symbol not found. Look for env. variable
420              cmt_string value = CmtSystem::getenv (symbol_name);
421                // When the env. variable is not defined, the replacement is empty
422                // thus all $(xxx) ${xxx} %xxx% patterns are always filtered away.
423              text.replace_all (pattern, value);
424             
425                  if (Cmt::get_debug ())
426                    {
427                      cerr << "resolve_value: getenv (" << symbol_name
428                           << ") => " << value << endl;
429                    }
430                // The substitution will restart from the same place
431                // allowing for recursive replacements
432              start = begin;
433                }
434              else
435                {
436                  if (Cmt::get_debug ())
437                    {
438                      cerr << "resolve_value: getenv (" << symbol_name
439                           << ") denied" << endl;
440                    }
441                  CmtError::set (CmtError::warning,
442                                 "getenv (" + symbol_name + ") denied");
443                  return;
444                }
445            }
446        }
447    }
448}
449
450/**
451
452   Attempt to substitute all occurrences of
453
454      ${xxx}
455      $(xxx)
456      `xxx`
457      %xxx%    [on Windows only]
458
459      by the appropriate value:
460
461        for `xxx` :
462
463            xxx is considered as a shell command. Value is the result of its execution
464
465        for other patterns:
466
467            if xxx is a macro name, its value is substituted to the pattern
468
469            if xxx is a set or a path, it is kept in place (after fixing the pattern
470            according to the OS style)
471
472            otherwise it is simply kept in place
473
474 */
475static void resolve_value_for_macros (cmt_string& text)
476{
477  cmt_string pattern;
478  cmt_string symbol_name;
479  char end_pattern;
480
481  int start = 0;
482
483  for (;;)
484    {
485      //
486      // Try and substitute all ${xxx} $(xxx) or %xxx% patterns
487      // using symbol values, only when the symbol is a macro.
488      //
489
490      int begin;
491      int end;
492
493      symbol_marker markers[4];
494      int num = 0;
495
496      markers[num].set (text.find (start, "$("), ')', 2); num++;
497      markers[num].set (text.find (start, "${"), '}', 2); num++;
498
499#ifdef WIN32
500      markers[num].set (text.find (start, "%"), '%', 1); num++;
501#endif
502
503      markers[num].set (text.find (start, "`"), '`', 1); num++;
504
505      // Find the first of three patterns
506
507      symbol_marker& marker = symbol_marker::get_lowest (markers, num);
508
509      begin = marker.ptr;
510
511      if (begin == cmt_string::npos) break;
512
513      end_pattern = marker.pattern;
514      start = begin + marker.intro;
515
516      end = text.find (start, end_pattern);
517      if (end == cmt_string::npos)
518        {
519          // The pattern is a fake one (no ending!)
520          start++;
521          continue;
522        }
523
524      // This should never happen...
525      if (end < begin) break;
526
527      // Extract the complete pattern
528      text.substr (begin, end - begin + 1, pattern);
529
530      // Then only the macro name
531      text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name);
532
533      if (text[begin] == '`')
534        {
535          cmt_string command = symbol_name;
536          resolve_value (command);
537
538            // The macro value is a shell command that first needs
539            // to be applied. The output of the command is substituted
540
541          Symbol::all_set ();
542
543          cmt_string result;
544          const cmt_string * presult;
545          if (!(presult = cmdoutputs.find (command)))
546            {
547              CmtSystem::execute (command, result);
548             
549              process_cmd_output (result);
550              cmdoutputs.add (command, result);
551              if (Cmt::get_debug ())
552                {
553                  cout << "resolve_value_for_macros: Executing [" << command << "] to expand a symbol value =>[" 
554                       << result << "]" << endl;
555                }
556            }
557          else
558            {
559              result = *presult;
560              if (Cmt::get_debug ())
561                {
562                  cout << "resolve_value_for_macros: Found in cache [" << command << "] to expand a symbol value =>[" 
563                       << result << "]" << endl;
564                }
565            }
566
567          text.replace_all (pattern, result);
568
569          // The substitution will restart from the same place
570          // allowing for recursive replacements
571          start = begin;
572        }
573      else
574        {
575          Symbol* macro = Symbol::find (symbol_name);
576          if ((macro != 0) && 
577              (macro->type == Symbol::SymbolMacro))
578            {
579                // Macro found
580              cmt_string value = macro->resolve_macro_value ();
581              text.replace_all (pattern, value);
582
583                // The substitution will restart from the same place
584                // allowing for recursive replacements
585              start = begin;
586            }
587          else if ((macro == 0) || 
588                   ((macro->type == Symbol::SymbolSet) || (macro->type == Symbol::SymbolPath)))
589            {
590                // Set found
591                // ensure that the delimiters will match the OS dependent
592                // delimiters.
593             
594              cmt_string pattern_close = marker.pattern;
595             
596              if (pattern_close != CmtSystem::ev_close ())
597                {
598                  cmt_string new_pattern;
599                 
600                  new_pattern = CmtSystem::ev_open ();
601                  new_pattern += symbol_name;
602                  new_pattern += CmtSystem::ev_close ();
603                 
604                  text.replace (pattern, new_pattern);
605                }
606             
607              start = end + 1;
608            }
609          else
610            {
611              start = end + 1;
612            }
613        }
614    }
615}
616
617/**
618
619   This function suppress all OS delimiters ie ${ } or % % and replaces them
620   by the pure macro delimiters $( )
621
622   `xxx` pattern is replaced by the result of the execution of the command
623
624 */
625static void suppress_OS_delimiters (cmt_string& text)
626{
627  cmt_string pattern;
628  cmt_string symbol_name;
629  char end_pattern;
630
631  int start = 0;
632
633  for (;;)
634    {
635      int begin;
636      int end;
637
638      symbol_marker markers[3];
639      int num = 0;
640
641      markers[num].set (text.find (start, "${"), '}', 2); num++;
642      markers[num].set (text.find (start, "`"), '`', 1); num++;
643
644#ifdef WIN32
645      markers[num].set (text.find (start, "%"), '%', 1); num++;
646#endif
647
648      // Find the first of three patterns
649
650      symbol_marker& marker = symbol_marker::get_lowest (markers, num);
651
652      begin = marker.ptr;
653
654      if (begin == cmt_string::npos) break;
655
656      end_pattern = marker.pattern;
657      start = begin + marker.intro;
658
659      end = text.find (start, end_pattern);
660      if (end == cmt_string::npos)
661        {
662          // The pattern is a fake one (no ending!)
663          start++;
664          continue;
665        }
666
667      // This should never happen...
668      if (end < begin) break;
669
670      // Extract the complete pattern
671      text.substr (begin, end - begin + 1, pattern);
672
673      // Then only the macro name
674      text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name);
675
676      if (text[begin] == '`')
677        {
678          cmt_string command = symbol_name;
679          resolve_value (command);
680
681            // The macro value is a shell command that first needs
682            // to be applied. The output of the command is substituted
683
684          Symbol::all_set ();
685
686          cmt_string result;
687          const cmt_string * presult;
688          if (!(presult = cmdoutputs.find (command)))
689            {
690              CmtSystem::execute (command, result);
691             
692              process_cmd_output (result);
693              cmdoutputs.add (command, result);
694              if (Cmt::get_debug ())
695                {
696                  cout << "suppress_OS_delimiters: Executing [" << command << "] to expand a symbol value =>[" 
697                       << result << "]" << endl;
698                }
699            }
700          else
701            {
702              result = *presult;
703              if (Cmt::get_debug ())
704                {
705                  cout << "suppress_OS_delimiters: Found in cache [" << command << "] to expand a symbol value =>[" 
706                       << result << "]" << endl;
707                }
708            }
709
710          text.replace_all (pattern, result);
711
712          // The substitution will restart from the same place
713          // allowing for recursive replacements
714          start = begin;
715        }
716      else
717        {
718          cmt_string new_pattern;
719
720          new_pattern = "$(";
721          new_pattern += symbol_name;
722          new_pattern += ")";
723
724          text.replace (pattern, new_pattern);
725
726          start = begin;
727        }
728    }
729}
730
731//-------------------------------------------------------------
732/*                                                          */
733/*  Operations on SymbolValues                              */
734/*                                                          */
735//-------------------------------------------------------------
736
737//-------------------------------------------------------------
738SymbolValue::SymbolValue ()
739{
740  tag = 0;
741}
742
743//-------------------------------------------------------------
744SymbolValue::~SymbolValue ()
745{
746  tag = 0;
747}
748
749//-------------------------------------------------------------
750/*                                                          */
751/*  Operations on Symbols                                   */
752/*                                                          */
753//-------------------------------------------------------------
754
755//-------------------------------------------------------------
756Symbol* Symbol::create (const cmt_string& name,
757                        CommandType command,
758                        Use* use)
759{
760  static SetBuilder Set;
761  static PathBuilder* PathPtr (PathBuilder::get_path_builder ());
762  //static PathBuilder Path (Cmt::get_strip_path ());
763  //static PathBuilder Path;
764  static MacroBuilder Macro;
765  static ScriptBuilder Script;
766  static ActionBuilder Action;
767
768  static SymbolVector& Symbols = symbols ();
769  static SymbolMap& SymbolMap = symbol_map ();
770
771  SymbolType type = SymbolUndefined;
772
773  switch (command)
774    {
775    case CommandSet:
776    case CommandSetAppend:
777    case CommandSetPrepend:
778    case CommandSetRemove:
779    case CommandSetRemoveRegexp:
780      type = SymbolSet;
781      break;
782    case CommandPath:
783    case CommandPathAppend:
784    case CommandPathPrepend:
785    case CommandPathRemove:
786    case CommandPathRemoveRegexp:
787      type = SymbolPath;
788      break;
789    case CommandMacro:
790    case CommandMacroAppend:
791    case CommandMacroPrepend:
792    case CommandMacroRemove:
793    case CommandMacroRemoveRegexp:
794    case CommandMacroRemoveAll:
795    case CommandMacroRemoveAllRegexp:
796      type = SymbolMacro;
797      break;
798    case CommandAction:
799      type = SymbolAction;
800      break;
801    case CommandAlias:
802      type = SymbolAlias;
803      break;
804    case CommandSetupScript:
805      type = SymbolSetupScript;
806      break;
807    case CommandCleanupScript:
808      type = SymbolCleanupScript;
809      break;
810    }
811
812  {
813    Symbol* symbol;
814
815    symbol = find (name);
816    if (symbol != 0) 
817      {
818        if (symbol->type != type)
819          {
820            ActionType action = Cmt::get_action ();
821
822            if ((!Cmt::get_quiet ()) &&
823                (action != action_build_constituents_config) &&
824                (action != action_build_constituent_config))
825              {
826                cmt_string s1;
827                cmt_string s2;
828
829                switch (symbol->type)
830                  {
831                  case SymbolSet:
832                    s1 = "set";
833                    break;
834                  case SymbolPath:
835                    s1 = "path";
836                    break;
837                  case SymbolMacro:
838                    s1 = "macro";
839                    break;
840                  case SymbolSetupScript:
841                    s1 = "setup_script";
842                    break;
843                  case SymbolCleanupScript:
844                    s1 = "cleanup_script";
845                    break;
846                  case SymbolAction:
847                    s1 = "action";
848                    break;
849                  case SymbolAlias:
850                    s1 = "alias";
851                    break;
852                  } 
853
854                switch (type)
855                  {
856                  case SymbolSet:
857                    s2 = "set";   
858                    break;
859                  case SymbolPath:
860                    s2 = "path";   
861                    break;
862                  case SymbolMacro:
863                    s2 = "macro";   
864                    break;
865                  case SymbolSetupScript:
866                    s2 = "setup_script"; 
867                    break;
868                  case SymbolCleanupScript:
869                    s2 = "cleanup_script"; 
870                    break;
871                  case SymbolAction:
872                    s2 = "action";
873                    break;
874                  case SymbolAlias:
875                    s2 = "alias";
876                    break;
877                  } 
878                // <PACKAGE>ROOT macro is defined in
879                // Use::fill_standard_macros <- SyntaxParser::parse_requirements
880                // "cmt -requirements setup" may generate <PACKAGE>ROOT set
881                // hence, warning
882                // Symbol <PACKAGE>ROOT inconsistently redeclared from macro to set in package <package>
883                // below, we suppress the warning for current package
884                if (use != &(Use::current()) ||
885                    (Use::current().prefix + "ROOT") != name ||
886                    symbol->type != SymbolMacro ||
887                    type != SymbolSet)
888                  CmtMessage::warning ("Symbol " + name
889                                       + " inconsistently redeclared from " + s1
890                                       + " to " + s2
891                                       + ( (use != 0) ?
892                                           " in package " + use->get_package_name () :
893                                           "" )
894                                       );
895                /*
896                cerr << "#CMT> Warning: Symbol " << name
897                     << " inconsistently redeclared from " << s1 << " to " << s2;
898                if (use != 0) cerr << " in package " << use->get_package_name ();
899                cerr << endl;
900                */
901              }
902          }
903
904        return (symbol);
905      }
906  }
907
908  Symbol& symbol = Symbols.add ();
909  SymbolMap.add (name, symbol);
910
911  symbol.name  = name;
912  symbol.scope = use->get_current_scope ();
913  symbol.type  = type;
914
915  symbol.value_lists.clear ();
916
917  switch (type)
918    {
919    case SymbolSet:
920      symbol.builder = &Set;
921      break;
922    case SymbolPath:
923      symbol.builder = PathPtr;
924      //symbol.builder = &Path;
925      break;
926    case SymbolAlias:
927      symbol.builder = &Set;
928      break;
929    case SymbolMacro:
930      symbol.builder = &Macro;
931      break;
932    case SymbolSetupScript:
933    case SymbolCleanupScript:
934      symbol.builder = &Script;
935      break;
936    case SymbolAction:
937      symbol.builder = &Action;
938      break;
939    }
940
941  symbol.selected_value = -1;
942  symbol.printed = false;
943
944  return (&symbol);
945}
946
947//-------------------------------------------------------------
948Symbol* Symbol::find (const cmt_string& name)
949{
950  static SymbolMap& SymbolMap = symbol_map ();
951
952  Symbol* result = 0;
953
954  result = SymbolMap.find (name);
955
956  return (result);
957}
958
959//-------------------------------------------------------------
960int Symbol::symbol_number ()
961{
962  static SymbolVector& Symbols = symbols ();
963
964  return (Symbols.size ());
965}
966
967//-------------------------------------------------------------
968Symbol::SymbolVector& Symbol::symbols ()
969{
970  static Database& db = Database::instance ();
971  static SymbolVector& Symbols = db.symbols ();
972
973  return (Symbols);
974}
975
976//-------------------------------------------------------------
977Symbol::SymbolMap& Symbol::symbol_map ()
978{
979  static Database& db = Database::instance ();
980  static SymbolMap& SymbolMap = db.symbol_map ();
981
982  return (SymbolMap);
983}
984
985//-------------------------------------------------------------
986Symbol::SymbolMap& Symbol::std_env_vars ()
987{
988  static SymbolMap env_vars;
989  static Symbol std_sym;
990  static bool initialized (false);
991  if (!initialized)
992    {
993      env_vars.add ("SITEROOT", std_sym);
994      env_vars.add ("CMTCONFIG", std_sym);
995      env_vars.add ("CMTBIN", std_sym);
996      env_vars.add ("CMTPATH", std_sym);
997      env_vars.add ("CMTHEADVERSION", std_sym);
998      env_vars.add ("CMTPROJECTPATH", std_sym);
999      env_vars.add ("CMTSITE", std_sym);
1000      env_vars.add ("CMTEXTRATAGS", std_sym);
1001      env_vars.add ("CMTSTRUCTURINGSTYLE", std_sym);
1002      env_vars.add ("CMTHOME", std_sym);
1003      env_vars.add ("CMTUSERCONTEXT", std_sym);
1004      initialized = true;
1005    }
1006  return env_vars;
1007}
1008
1009/**
1010   Filter out faulty items of a path-like symbol value
1011 */
1012void Symbol::filter_path_value (const cmt_string& name, cmt_string& text)
1013{
1014
1015  CmtSystem::cmt_string_vector paths;
1016  CmtSystem::cmt_string_vector normalyzed_paths;   
1017                 
1018  CmtSystem::split (text, CmtSystem::path_separator (), paths);
1019                 
1020  for (int j = 0; j < paths.size (); ++j)
1021    {
1022      cmt_string& t = paths[j];
1023
1024            /*
1025        if (!CmtSystem::test_directory (t))
1026              if (Cmt::get_warnings ())
1027              {
1028                  cerr << "#CMT> Warning: Wrong path item " << t << " in " << name << endl;
1029              }
1030            */
1031           
1032      int exist = 0; 
1033      for (int i = 0; i < j; ++i)
1034      {
1035          cmt_string& u = paths[i];
1036          if (u == t)
1037            {
1038              exist = 1;
1039              break;
1040            }
1041      }           
1042      if (exist==0)
1043      {
1044          cmt_string& s = normalyzed_paths.add ();
1045          s = t;
1046          if (CmtMessage::active (Verbose))
1047            if (!CmtSystem::test_directory (t))
1048              {
1049                CmtMessage::warning ("Non-existent directory " + t + " in " + name);
1050              }
1051      }
1052    }
1053   
1054  Cmt::vector_to_string (normalyzed_paths, CmtSystem::path_separator (), text);
1055
1056  for (;;)
1057    {
1058      int sz = text.size ();
1059
1060      if (sz == 0) break;
1061
1062      if ((text[0] == ';') || (text[0] == ':'))
1063        {
1064          text.erase (0, 1);
1065        }
1066      else if ((text[sz-1] == ';') || (text[sz-1] == ':'))
1067        {
1068          text.erase (sz-1, 1);
1069        }
1070      else
1071        {
1072          break;
1073        }
1074    }
1075
1076  text.replace_all ("::", ":");
1077  text.replace_all (";;", ";");
1078}
1079
1080
1081//-------------------------------------------------------------
1082Symbol& Symbol::symbol (int index)
1083{
1084  static SymbolVector& Symbols = symbols ();
1085
1086  return (Symbols[index]);
1087}
1088
1089//-------------------------------------------------------------
1090void Symbol::action (const CmtSystem::cmt_string_vector& words,
1091                     CommandType command_type,
1092                     Use* use)
1093{
1094  int number;
1095  Symbol* symbol;
1096  Tag* tag;
1097
1098  if (words.size () < 1) return;
1099  cmt_string name = words[1];
1100
1101  if ((command_type == CommandSetupScript) ||
1102      (command_type == CommandCleanupScript))
1103    {
1104      cmt_string full_name;
1105
1106      Symbol::expand (name);
1107
1108      if (name != "")
1109        {
1110          if (CmtSystem::absolute_path (name)) 
1111            {
1112              full_name = name;
1113            }
1114          else
1115            {
1116              if (use->get_strategy ("SetupRoot") &&
1117                  use->get_package_name () != "cmt_standalone" &&
1118                  (action_setup == Cmt::get_action () ||
1119                   action_cleanup == Cmt::get_action ()) &&
1120                  Requirements != Cmt::get_print_mode () &&
1121                  Xml != Cmt::get_print_mode ())
1122                {
1123#ifdef WIN32
1124              full_name = "%";
1125#else
1126              full_name = "${";
1127#endif
1128              full_name += CmtSystem::mangle (use->prefix);
1129              full_name += "ROOT";
1130#ifdef WIN32
1131              full_name += "%";
1132#else
1133              full_name += "}";
1134#endif
1135                }
1136              else
1137                {
1138              full_name = use->get_full_path ();
1139                }
1140              if (use->style == cmt_style)
1141                {
1142                  full_name += CmtSystem::file_separator ();
1143                  full_name += "cmt";
1144                }
1145              else if (use->style == mgr_style)
1146                {
1147                  full_name += CmtSystem::file_separator ();
1148                  full_name += "mgr";
1149                }
1150              //              else if (use->style == no_version_style) full_name += "cmt";
1151              //              else full_name += "mgr";
1152              full_name += CmtSystem::file_separator ();
1153              full_name += name;
1154            }
1155
1156          symbol = create (full_name, command_type, use);
1157          symbol->add_value_to_list (command_type, use,
1158                                     Tag::get_default (), full_name);
1159        }
1160    }
1161  else
1162    {
1163      if (words.size () < 2) return;
1164      const cmt_string& default_value = words[2];
1165
1166      Cmt::reset_all_sets_done ();
1167
1168      if (Cmt::get_debug ())
1169        {
1170          cout << "Symbol::action> name:" << name
1171               << " access:" << Cmt::get_current_access () 
1172               << " scope:" << use->get_current_scope () << endl;
1173        }
1174
1175      if (Cmt::get_current_access () == UserMode)
1176        {
1177          /*
1178            The following statements mean that some symbols are
1179            always private.
1180            This list is hardcoded. This should be replaced by a
1181            database of "private" symbols.
1182           */
1183          if (name == "constituents") return;
1184          if (name == "constituentsclean") return;
1185
1186          if (use->get_current_scope () == ScopePrivate) return;
1187        }
1188
1189      symbol = create (name, command_type, use);
1190
1191      /*
1192        Parse the default value.
1193      */
1194     
1195      symbol->add_value_to_list (command_type, use,
1196                                 Tag::get_default (), default_value);
1197     
1198      /*
1199        Then parse all specific values
1200       
1201        <tag> <value>
1202        ...
1203      */
1204     
1205      number = 3;
1206      while (number < (words.size () - 1))
1207        {
1208          cmt_string tag_name = words[number];
1209          const cmt_string& value = words[number + 1];
1210
1211          expand (tag_name);
1212
1213          if (Cmt::get_debug ())
1214            {
1215              cout << "Symbol::action> tag_name=" << tag_name << endl;
1216            }
1217
1218          tag = Tag::find (tag_name);
1219          if (tag == 0)
1220            {
1221              tag = Tag::add (tag_name, PriorityUserTag, "use", use);
1222            }
1223
1224          symbol->add_value_to_list (command_type, use, tag, value);
1225         
1226          number += 2;
1227        }
1228
1229      if (name == "CMTPATH")
1230        {
1231          Cmt::configure_cmt_path (use);
1232        }
1233      else if (name == "CMTPROJECTPATH")
1234        {
1235          Cmt::configure_cmt_path (use);
1236        }
1237      else if (name == "CMTSITE")
1238        {
1239          Cmt::configure_site_tag (use);
1240        }
1241      else if (name == "CMTCONFIG")
1242        {
1243            //cerr << "redefining CMTCONFIG" << endl;
1244          Cmt::configure_tags (use);
1245        }
1246      else if (name == "CMTHOME")
1247        {
1248          Cmt::configure_home (use);
1249        }
1250      else if (name == "CMTUSERCONTEXT")
1251        {
1252          Cmt::configure_user_context (use);
1253        }
1254      else if (name.find ("_native_version") != cmt_string::npos)
1255        {
1256          cmt_string n = use->get_package_name ();
1257          n += "_native_version";
1258
1259          if (name == n)
1260            {
1261              use->set_native_version (true);
1262            }
1263        }
1264    }
1265}
1266
1267//-------------------------------------------------------------
1268bool Symbol::set_strip_path (const bool& strip_path)
1269{
1270  PathBuilder::get_path_builder ()->set_strip_path (strip_path);
1271  return true;
1272  /*
1273  // searching for a path symbol
1274  for (int number = 0; number < Symbol::symbol_number (); number++)
1275    {
1276      Symbol& symbol = Symbol::symbol (number);
1277     
1278      if (symbol.type == Symbol::SymbolPath)
1279        {
1280          static_cast<PathBuilder*> (symbol.builder)->set_strip_path (strip_path);
1281          return true;
1282        }
1283    }
1284
1285  return false;
1286  */
1287}
1288
1289//-------------------------------------------------------------
1290int Symbol::is_selected (const cmt_string& name)
1291{
1292  Symbol* symbol;
1293  int number;
1294  int value_number;
1295
1296  symbol = find (name);
1297  if (symbol == 0) return (0);
1298
1299  if (symbol->value_lists.size () == 0) return (0);
1300
1301  for (number = 0;
1302       number < symbol->value_lists.size ();
1303       number++)
1304    {
1305      const SymbolValueList& value_list = symbol->value_lists[number];
1306
1307      if (value_list.discarded) continue;
1308
1309      if ((value_list.command_type == CommandMacro) ||
1310          (value_list.command_type == CommandSet) ||
1311          (value_list.command_type == CommandSetAppend) ||
1312          (value_list.command_type == CommandSetPrepend) ||
1313          (value_list.command_type == CommandSetRemove) ||
1314          (value_list.command_type == CommandSetRemoveRegexp) ||
1315          (value_list.command_type == CommandAlias) ||
1316          (value_list.command_type == CommandAction))
1317        {
1318          for (value_number = 0;
1319               value_number < value_list.values.size ();
1320               value_number++)
1321            {
1322              Tag* tag;
1323
1324              SymbolValue& value = value_list.values[value_number];
1325
1326              tag = value.tag;
1327              if ((tag == 0) ||
1328                  (tag == Tag::get_default ()) ||
1329                  (tag->is_selected () != 0))
1330                {
1331                  return (1);
1332                }
1333            }
1334        }
1335    }
1336
1337  return (0);
1338}
1339
1340//-------------------------------------------------------------
1341Symbol::Symbol ()
1342{
1343  name = "";
1344}
1345
1346//-------------------------------------------------------------
1347Symbol::~Symbol ()
1348{
1349}
1350
1351/**
1352 *  Characterizes if a value is provided as the reference to itself.
1353 */
1354bool Symbol::value_is_reflexive (const cmt_string& text) const
1355{
1356  bool result = false;
1357  int text_length = text.size ();
1358
1359  if (text_length == (name.size () + 3))
1360    {
1361      static cmt_string temp;
1362             
1363      if (text[0] == '$')
1364        {
1365          if (text[1] == '(')
1366            {
1367              temp = "$(";
1368              temp += name;
1369              temp += ")";
1370             
1371              if (text == temp)
1372                {
1373                  result = true;
1374                }
1375            }
1376          else if (text[1] == '{')
1377            {
1378              temp = "${";
1379              temp += name;
1380              temp += "}";
1381             
1382              if (text == temp)
1383                {
1384                  result = true;
1385                }
1386            }
1387        }
1388    }
1389  else if (text_length == (name.size () + 2))
1390    {
1391      static cmt_string temp;
1392
1393      temp = "%";
1394      temp += name;
1395      temp += "%";
1396
1397      if (text == temp)
1398        {
1399          result = true;
1400        }
1401    }
1402
1403  return (result);
1404}
1405
1406//-------------------------------------------------------------
1407void Symbol::add_value_to_list (CommandType command_type,
1408                                Use* use,
1409                                Tag* tag,
1410                                const cmt_string& text)
1411{
1412  SymbolValueList* value_list = 0;
1413  bool is_reflexive = false;
1414
1415    //
1416    // First pickup the most recent value_list
1417    //
1418  if (value_lists.size () > 0) value_list = &(value_lists.back ());
1419
1420    //
1421    //  Create a new value list is we switch to another use or
1422    //  if we switch to a new command_type (eg. switching from
1423    //  macro to macro_append).
1424    //
1425  if ((value_list == 0) ||
1426      (use != value_list->use) ||
1427      (command_type != value_list->command_type) ||
1428      (tag == Tag::get_default ()))
1429    {
1430      value_list = &(value_lists.add ());
1431      value_list->use = use;
1432      value_list->command_type = command_type;
1433      value_list->values.clear ();
1434      value_list->discarded = false;
1435      value_list->is_reflexive = false;
1436    }
1437
1438/*
1439  else
1440    {
1441        value_list = &(value_lists[value_lists.size () - 1]);
1442    }
1443*/
1444
1445  is_reflexive = value_list->is_reflexive;
1446
1447    //
1448    //  If the command_type is command_macro or command_set,
1449    // this is considered as a full re-set of this symbol
1450    //   In this case, we have to discard all previous values
1451    //
1452    //  However, we'd like to exclude from this logic the cases where
1453    //  the value is **exactly*
1454    //
1455    //     $(<symbol>)
1456    //     ${<symbol>}
1457    //     %<symbol>%
1458    //
1459    //   which would then mean that we do not reset the value but rather
1460    //  override it.
1461    //
1462
1463    //
1464    // Inside this value_list, we add this new tag-value pair.
1465    //
1466
1467  if ((command_type == CommandMacro) ||
1468      (command_type == CommandSet) ||
1469      (command_type == CommandPath) ||
1470      (command_type == CommandAction))
1471    {
1472        //
1473        // Check whether we have to hide previous settings by this new definition
1474        //  (of course this is only useful if there WERE previous settings)
1475        //
1476      if ((value_lists.size () >= 1) && (!is_reflexive))
1477        {
1478          if (value_is_reflexive (text))
1479            {
1480              value_list->is_reflexive = true;
1481              is_reflexive = true;
1482            }
1483          else
1484            {
1485              //cerr << "...discarding old values for symbol " << name << " text=[" << text << "]" << endl;
1486                 
1487              for (int i = 0; i < (value_lists.size () - 1); i++)
1488                {
1489                  SymbolValueList& vl = value_lists[i];
1490                 
1491                  if ((vl.use != 0) &&
1492                      (vl.use->discarded))
1493                    {
1494                      //vl.discarded = true;
1495                    }
1496                }
1497            }
1498        }
1499    }
1500
1501  SymbolValue& value = value_list->values.add ();
1502
1503  value.tag = tag;
1504  value.text = text;
1505  value.selected = 0;
1506}
1507
1508/**
1509   Compute the current value of all environment variables and set them to the
1510   shell
1511 */
1512void Symbol::all_set ()
1513{
1514  //cerr << "all_set" << endl;
1515
1516  static bool running = false;
1517
1518
1519  if (Cmt::get_debug ())
1520    {
1521      cout << "\nSymbol::all_set> done=" << running << endl;
1522    }
1523
1524  if (Cmt::get_all_sets_done ()) return;
1525
1526  if (running) return;
1527
1528  running = true;
1529  Cmt::set_all_sets_done ();
1530
1531  static SymbolVector& Symbols = symbols ();
1532  Use::UsePtrVector& Uses = Use::get_ordered_uses ();
1533
1534  int number;
1535
1536  if (Symbols.size () == 0) 
1537    {
1538      running = false;
1539      return;
1540    }
1541
1542  cmt_string value;
1543
1544  if (Cmt::get_env_access ())
1545    {
1546  for (number = 0; number < Symbol::symbol_number (); number++)
1547    {
1548      Symbol& symbol = Symbol::symbol (number);
1549
1550      if (symbol.type != SymbolSet) continue;
1551
1552      value = symbol.build_macro_value ();
1553      if (value != "")
1554        {
1555          Symbol::expand (value);
1556
1557          if (Cmt::get_debug ())
1558            {
1559              cerr << "Symbol::all_set (set)> " << symbol.name << " = " << value << endl;
1560            }
1561
1562          CmtSystem::putenv (symbol.name, value);
1563        }
1564    }
1565    }
1566
1567  cmt_string cmtconfig = CmtSystem::get_cmt_config ();
1568
1569  if (Uses.size () > 0)
1570    {
1571      int number;
1572
1573      for (number = 0; number < Uses.size (); number++)
1574        {
1575          Use& use = *(Uses[number]);
1576
1577          if (use.discarded) continue;
1578
1579          if (use.get_package_name () == "cmt_standalone") continue;
1580
1581          if (use.get_strategy ("SetupConfig"))
1582            {
1583              cmt_string temp;
1584
1585              temp = use.prefix;
1586              temp += "CONFIG";
1587
1588              CmtSystem::putenv (temp, cmtconfig);
1589            }
1590
1591          if (use.get_strategy ("SetupRoot"))
1592            {
1593              cmt_string temp;
1594
1595              temp = use.prefix;
1596              temp += "ROOT";
1597
1598              CmtSystem::putenv (temp, use.get_full_path ());
1599            }
1600        }
1601    }
1602
1603  {
1604    Use& use = Use::current ();
1605
1606    if (use.get_package_name () != "cmt_standalone")
1607      {
1608        if (use.get_strategy ("SetupConfig"))
1609          {
1610            cmt_string temp;
1611
1612            temp = use.prefix;
1613            temp += "CONFIG";
1614
1615            CmtSystem::putenv (temp, cmtconfig);
1616          }
1617       
1618        if (use.get_strategy ("SetupRoot"))
1619          {
1620            cmt_string temp;
1621
1622            temp = use.prefix;
1623            temp += "ROOT";
1624
1625            CmtSystem::putenv (temp, use.get_full_path ());
1626          }
1627      }
1628  }
1629
1630  static PathBuilder* pb (0);
1631
1632  if (Cmt::get_env_access ())
1633    {
1634  for (number = 0; number < Symbol::symbol_number (); number++)
1635    {
1636      Symbol& symbol = Symbol::symbol (number);
1637
1638      if ((symbol.type != SymbolPath)) continue;
1639
1640      value = symbol.build_macro_value ();
1641      if (value != "")
1642        {
1643          Symbol::expand (value);
1644          if (!pb)
1645            pb = static_cast<PathBuilder*> (symbol.builder);
1646          pb->filter_path_value (symbol, value);
1647          //filter_path_value (symbol.name, value);
1648
1649#ifdef WIN32
1650          value.replace_all ("/", "\\");
1651#endif
1652
1653          if (Cmt::get_debug ())
1654            {
1655              cerr << "Symbol::all_set (path)> " << symbol.name << " = " << value << endl;
1656            }
1657
1658          CmtSystem::putenv (symbol.name, value);
1659        }
1660    }
1661    }
1662
1663  running = false;
1664}
1665
1666//-------------------------------------------------------------
1667void Symbol::all_print (PrintMode mode, ostream& out)
1668//void Symbol::all_print (PrintMode mode)
1669{
1670  static SymbolVector& Symbols = symbols ();
1671
1672  int number;
1673
1674  if (Symbols.size () == 0) return;
1675
1676  switch (mode)
1677    {
1678    case Requirements :
1679      for (number = 0; number < Symbol::symbol_number (); number++)
1680        {
1681          Symbol& symbol = Symbol::symbol (number);
1682
1683          if ((symbol.type == SymbolSet) ||
1684              (symbol.type == SymbolAlias) ||
1685              (symbol.type == SymbolSetupScript) ||
1686              (symbol.type == SymbolPath) ||
1687              (symbol.type == SymbolMacro))
1688            {
1689              if (symbol.print_macro (mode, out))
1690                {
1691                  //              cout << endl;
1692                }
1693            }
1694        }
1695      break;
1696    default :
1697      for (number = 0; number < Symbol::symbol_number (); number++)
1698        {
1699          Symbol& symbol = Symbol::symbol (number);
1700         
1701          if ((symbol.type == SymbolSet) ||
1702              (symbol.type == SymbolAlias) ||
1703              (symbol.type == SymbolSetupScript) ||
1704              (symbol.type == SymbolPath))
1705            {
1706              if (symbol.print (mode, out))
1707                {
1708                  if (mode == Bat)
1709                    {
1710                      out << endl;
1711                    }
1712                  else if (mode == Xml)
1713                    {
1714                      //                      cout << endl;
1715                    }
1716                  else
1717                    {
1718                      out << endl;
1719                    }
1720                }
1721            }
1722        }
1723      break;
1724    }
1725}
1726
1727//-------------------------------------------------------------
1728void Symbol::check_all_paths ()
1729{
1730  static SymbolVector& Symbols = symbols ();
1731
1732  static PathBuilder* pb (0);
1733
1734  int number;
1735
1736  if (Symbols.size () == 0) return;
1737
1738  for (number = 0; number < Symbol::symbol_number (); number++)
1739    {
1740      Symbol& symbol = Symbol::symbol (number);
1741
1742      if (symbol.type == SymbolPath)
1743        {
1744          cmt_string temp;
1745
1746          temp = symbol.build_macro_value ();
1747          expand (temp);
1748
1749          if (!pb)
1750            pb = static_cast<PathBuilder*> (symbol.builder);
1751          pb->filter_path_value (symbol, temp);
1752          //Symbol::filter_path_value (symbol.name, temp);
1753        }
1754    }
1755}
1756
1757//-------------------------------------------------------------
1758void Symbol::all_print_clean (PrintMode mode)
1759{
1760  static SymbolVector& Symbols = symbols ();
1761
1762  int number;
1763
1764  if (Symbols.size () == 0) return;
1765
1766  for (number = Symbols.size () - 1; number >= 0; number--)
1767    {
1768      Symbol& symbol = Symbols[number];
1769
1770      if ((symbol.type == SymbolSet) ||
1771          (symbol.type == SymbolAlias) ||
1772          (symbol.type == SymbolCleanupScript))
1773        {
1774          if (symbol.print_clean (mode))
1775            {
1776              cout << endl;
1777            }
1778        }
1779    }
1780
1781  for (number = Symbols.size () - 1; number >= 0; number--)
1782    {
1783      Symbol& symbol = Symbols[number];
1784
1785      if ((symbol.type != SymbolPath)) continue;
1786
1787      if (symbol.print_clean (mode))
1788        {
1789          cout << endl;
1790        }
1791    }
1792}
1793
1794//-------------------------------------------------------------
1795int Symbol::print_clean (PrintMode mode)
1796{
1797  int result = 0;
1798  static cmt_string temp;
1799
1800  if (name == "CMTCONFIG") return (0);
1801
1802  cmt_string _name;
1803  switch (type)
1804    {
1805    case SymbolSet :
1806    case SymbolPath :
1807      if (0 != CmtSystem::mangle (name, _name))
1808        CmtMessage::info ("Replace " + name + " with " + _name);
1809      break;
1810    }
1811
1812  switch (type)
1813    {
1814    case SymbolSet :
1815      switch (mode)
1816        {
1817        case Csh :
1818          cout << "unsetenv " << _name;
1819          result = 1;
1820          break;
1821        case Sh :
1822          cout << "[ -z ${" << _name << "+CMT} ] || unset " << _name;
1823          //          cout << "unset " << _name;
1824          result = 1;
1825          break;
1826        case Bat :
1827          cout << "set " << _name << "=";
1828          result = 1;
1829          break;
1830        }
1831      break;
1832    case SymbolAlias :
1833      switch (mode)
1834        {
1835          case Csh :
1836            cout << "unalias " << name;
1837            result = 1;
1838            break;
1839          case Sh :
1840            cout << "alias " << name << " >/dev/null 2>&1 && unalias " << name;
1841            result = 1;
1842            break;
1843        }
1844      break;
1845    case SymbolPath :
1846      temp = clean_macro_value ();
1847      switch (mode)
1848        {
1849        case Csh :
1850          if (temp == "")
1851            {
1852              cout << "unsetenv " << _name;
1853            }
1854          else
1855            {
1856              cout << "setenv " << _name << " " << CmtSystem::quote (temp, " \t");
1857            }
1858          result = 1;
1859          break;
1860        case Sh :
1861          cout << _name << "=" << CmtSystem::quote (temp, " \t") << "; export " << _name;
1862          result = 1;
1863          break;
1864        case Bat :
1865          cout << "set " << _name << "=" << CmtSystem::quote (temp, " \t");
1866          result = 1;
1867          break;
1868        }
1869      break;
1870    case SymbolCleanupScript :
1871      switch (mode)
1872        {
1873        case Csh :
1874          cout << "if ( -f " << CmtSystem::quote (name, " \t") << ".csh ) then" << endl;
1875          cout << "  source " << CmtSystem::quote (name, " \t") << ".csh" << endl;
1876          cout <<
1877            "if ( $status != 0 ) then\n"
1878            "    set cmtcleanupstatus=1\n"
1879            "endif\n";
1880          cout << "endif" << endl;
1881          result = 1;
1882          break;
1883        case Sh :
1884          cout << "if test -f " << CmtSystem::quote (name, " \t") << ".sh; then" << endl;
1885          cout << "  . " << CmtSystem::quote (name, " \t") << ".sh" << endl;
1886          cout <<
1887            "if test $? != 0; then\n"
1888            "    cmtcleanupstatus=1\n"
1889            "fi\n";
1890          cout << "fi" << endl;
1891          result = 1;
1892          break;
1893        case Bat :
1894          cout << "call " << CmtSystem::quote (name, " \t");
1895          result = 1;
1896          break;
1897        }
1898      break;
1899    }
1900
1901  return (result);
1902}
1903
1904//-------------------------------------------------------------
1905int Symbol::print (PrintMode mode, ostream& out)
1906{
1907  static PathBuilder* pb (0);
1908
1909  int result = 0;
1910
1911  cmt_string temp = build_macro_value ();
1912  bool empty = (temp.size () == 0) ? true : false;
1913
1914  cmt_string _name (name);
1915  switch (type)
1916    {
1917    case SymbolSet :
1918    case SymbolPath :
1919      expand (temp);
1920      if (type == SymbolPath)
1921        {
1922          if (!pb)
1923            pb = static_cast<PathBuilder*> (builder);
1924          pb->filter_path_value (*this, temp);
1925        }
1926      switch (mode)
1927        {
1928        case Xml :
1929          break;
1930        default:
1931          if (0 != CmtSystem::mangle (name, _name))
1932            CmtMessage::info ("Replace " + name + " with " + _name);
1933          break;
1934        }
1935      break;
1936    default:
1937      break;
1938    }
1939
1940  /*
1941  if (type == SymbolPath)
1942    {
1943      expand (temp);
1944      //Symbol::filter_path_value (name, temp);
1945      if (!pb)
1946        pb = static_cast<PathBuilder*> (builder);
1947      pb->filter_path_value (*this, temp);
1948    }
1949  */
1950  switch (type)
1951    {
1952      case SymbolSet :
1953      case SymbolPath :
1954        switch (mode)
1955          {
1956            case Csh :
1957              if (empty) out << "unsetenv " << _name;
1958              else out << "setenv " << _name << " \"" << temp << "\"";
1959              //else out << "setenv " << name << " " << CmtSystem::quote (temp, " \t");
1960
1961              result = 1;
1962              break;
1963            case Sh :
1964              if (empty) out << "[ -z ${" << _name << "+CMT} ] || unset " << _name;
1965              //              if (empty) out << "unset " << _name;
1966              else out << _name << "=\"" << temp << "\"; export " << _name;
1967              //else out << name << "=" << CmtSystem::quote (temp, " \t") << "; export " << name;
1968
1969              result = 1;
1970              break;
1971            case Bat :
1972              temp.replace_all ("/", "\\");
1973              out << "set " << _name << "=" << CmtSystem::quote (temp, " \t");
1974              //out << "set " << name << "=" << temp;
1975              result = 1;
1976              break;
1977            case Xml :
1978              out << "<variable><name>" << _name << "</name>"
1979                   << "<value>" << temp << "</value></variable>";
1980              result = 1;
1981              break;
1982          }
1983        break;
1984      case SymbolAlias :
1985        switch (mode)
1986          {
1987            case Csh :
1988              out << "alias " << name <<
1989                " \"" << temp << "\"";
1990              //CmtSystem::quote (temp, " \t");
1991              result = 1;
1992              break;
1993            case Sh :
1994              out << "alias " << name <<
1995                "=\"" << temp << "\"";
1996              //"=" << CmtSystem::quote (temp, " \t");
1997              result = 1;
1998              break;
1999            case Bat :
2000              out << "set " << name <<
2001                "=" << CmtSystem::quote (temp, " \t");
2002              //"=" << temp;
2003              result = 1;
2004              break;
2005            case Xml :
2006              out << "<alias><name>" << name << "</name>"
2007                   << "<value>" << temp << "</value></alias>";
2008              result = 1;
2009              break;
2010          }
2011        break;
2012      default :
2013        break;
2014    }
2015
2016  if (temp != "")
2017    {
2018      switch (type)
2019        {
2020          case SymbolSetupScript :
2021            switch (mode)
2022              {
2023                case Csh :
2024                  out << "if ( -f " << CmtSystem::quote (name, " \t") << ".csh ) then" << endl;
2025                  out << "  source " << CmtSystem::quote (name, " \t") << ".csh" << endl;
2026                  out <<
2027                    "if ( $status != 0 ) then\n"
2028                    "    set cmtsetupstatus=1\n"
2029                    "endif\n";
2030                  out << "endif" << endl;
2031                  result = 1;
2032                  break;
2033                case Sh :
2034                  out << "if test -f " << CmtSystem::quote (name, " \t") << ".sh; then" << endl;
2035                  out << "  . " << CmtSystem::quote (name, " \t") << ".sh" << endl;
2036                  out <<
2037                    "if test $? != 0; then\n"
2038                    "    cmtsetupstatus=1\n"
2039                    "fi\n";
2040                  out << "fi" << endl;
2041                  result = 1;
2042                  break;
2043                case Bat :
2044                  out << "call " << CmtSystem::quote (name, " \t");
2045                  result = 1;
2046                  break;
2047                case Xml :
2048                  out << "<script>" << name << "</script>";
2049                  result = 1;
2050                  break;
2051              }
2052            break;
2053          default:
2054            break;
2055        }
2056    }
2057
2058  return (result);
2059}
2060
2061//-------------------------------------------------------------
2062cmt_string Symbol::build_macro_value (bool display_it) const
2063{
2064  cmt_string temp;
2065
2066  if (display_it)
2067    {
2068      temp = builder->build_and_display (*this);
2069    }
2070  else
2071    {
2072      temp = builder->build (*this);
2073    }
2074
2075  return (temp);
2076}
2077
2078//-------------------------------------------------------------
2079int Symbol::print_macro (PrintMode mode, ostream& out) const
2080{
2081  if (mode != Requirements || printed) return 0;
2082  return builder->print (*this, out);
2083}
2084
2085//-------------------------------------------------------------
2086cmt_string Symbol::clean_macro_value () const
2087{
2088  cmt_string temp;
2089
2090  temp = builder->clean (*this);
2091
2092  return (temp);
2093}
2094
2095/**
2096
2097   Attempt to substitute into the symbol value all occurrences of
2098
2099      ${xxx}
2100      $(xxx)
2101      `xxx`
2102      %xxx%    [on Windows only]
2103
2104      by the appropriate value:
2105
2106        for `xxx` :
2107
2108            xxx is considered as a shell command. Value is the result of its execution
2109
2110        for other patterns:
2111
2112            if xxx is a symbol name, its value is substituted to the pattern
2113            otherwise, xxx is tried as an environment variable
2114
2115
2116     ===> In all cases, the pattern is filtered away.
2117
2118  */
2119cmt_string Symbol::resolve_macro_value (const cmt_string& tag_name) const
2120{
2121  cmt_string temp = builder->build (*this, tag_name);
2122
2123  resolve_value (temp);
2124
2125  return (temp);
2126}
2127
2128//-------------------------------------------------------------
2129void Symbol::show_macro (PrintMode mode, ostream& out)
2130//void Symbol::show_macro (PrintMode mode)
2131{
2132  if (Cmt::get_debug ())
2133    {
2134      cout << "Symbol::show_macro> " << name << endl;
2135    }
2136
2137  ActionType action = Cmt::get_action ();
2138
2139  cmt_string value = build_macro_value (true);
2140
2141  if ((!Cmt::get_quiet ()) &&
2142      (action != action_build_tag_makefile) &&
2143      (action != action_build_constituents_config) &&
2144      (action != action_build_constituent_config) &&
2145      (action != action_build_broadcast_config) &&
2146      (action != action_show_macros) &&
2147      (action != action_show_actions) &&
2148      (action != action_show_aliases) &&
2149      (action != action_show_sets))
2150    {
2151      out << "#" << endl;
2152      out << "# Selection : " << endl;
2153    }
2154
2155  if (value.size () > 0)
2156    {
2157      if ((action == action_show_macro) ||
2158          (action == action_show_macros) ||
2159          (action == action_show_sets) ||
2160          (action == action_show_set) ||
2161          (action == action_show_actions) ||
2162          (action == action_show_action) ||
2163          (action == action_show_alias) ||
2164          (action == action_show_aliases) ||
2165          (action == action_build_tag_makefile) ||
2166          (action == action_build_constituents_config) ||
2167          (action == action_build_constituent_config) ||
2168          (action == action_build_broadcast_config) ||
2169          (action == action_load) ||
2170          (!Cmt::get_quiet ()))
2171        {
2172          if (mode == Make)
2173            {
2174              out << name << "=";
2175            }
2176          else
2177            {
2178              out << name << "='";
2179            }
2180        }
2181
2182      if ((action == action_show_macro_value) ||
2183          (action == action_show_set_value) ||
2184          (action == action_show_action_value) ||
2185          (action == action_show_alias_value))
2186        {
2187          expand (value);
2188        }
2189      else if (action == action_build_tag_makefile ||
2190               action == action_build_constituents_config ||
2191               action == action_build_constituent_config ||
2192               action == action_build_broadcast_config)
2193        {
2194            /*
2195               Unfortunately, the %xxx% pattern has to be kept on Unix. Therefore
2196               we cannot force all patterns to become $(xxx)
2197
2198               This was useful on Windows so as to only keep $(xxx)
2199             */
2200#ifdef WIN32
2201          suppress_OS_delimiters (value);
2202#endif
2203        }
2204
2205      out << value;
2206
2207      if ((action == action_show_macro) ||
2208          (action == action_show_macros) ||
2209          (action == action_show_sets) ||
2210          (action == action_show_set) ||
2211          (action == action_show_actions) ||
2212          (action == action_show_action) ||
2213          (action == action_show_alias) ||
2214          (action == action_show_aliases) ||
2215          (action == action_build_tag_makefile) ||
2216          (action == action_build_constituents_config) ||
2217          (action == action_build_constituent_config) ||
2218          (action == action_build_broadcast_config) ||
2219          (action == action_load) ||
2220          (!Cmt::get_quiet ()))
2221        {
2222          if (mode != Make)
2223            {
2224              out << "'";
2225            }
2226#ifdef WIN32
2227          else
2228            {
2229              out << " ";
2230            }
2231#endif
2232        }
2233
2234      out << endl;
2235    }
2236}
2237
2238//-------------------------------------------------------------
2239void Symbol::clear_all ()
2240{
2241  static SymbolVector& Symbols = symbols ();
2242  static SymbolMap& SymbolMap = symbol_map ();
2243
2244  SymbolMap.clear ();
2245  Symbols.clear ();
2246}
2247
2248//-------------------------------------------------------------
2249void Symbol::expand (cmt_string& text)
2250{
2251  static cmt_regexp reg ("[$%`]");
2252
2253  if (!reg.match (text)) return;
2254
2255  resolve_value (text);
2256}
2257
2258//-------------------------------------------------------------
2259ValueBuilder::ValueBuilder ()
2260{
2261  m_display_it = false;
2262}
2263
2264//-------------------------------------------------------------
2265const cmt_string ValueBuilder::build_and_display (const Symbol& symbol)
2266{
2267  cmt_string temp;
2268
2269  m_display_it = true;
2270  temp = build (symbol);
2271  m_display_it = false;
2272
2273  return (temp);
2274}
2275
2276//-------------------------------------------------------------
2277int ValueBuilder::print (const Symbol& symbol, ostream& out)
2278{
2279  int result (0);
2280
2281  bool first_definition = true;
2282 
2283  for (int i = 0; i < symbol.value_lists.size (); i++)
2284    {
2285      const SymbolValueList& value_list = symbol.value_lists[i];
2286
2287      if ((value_list.use != 0) &&
2288          (value_list.use->discarded)) continue;
2289
2290      const int selected = value_list.select_first ();
2291
2292      if (selected < 0) continue;
2293
2294      SymbolValue& value = value_list.values[selected];
2295
2296      result += value_list.print (symbol, value, first_definition, out);
2297    }
2298
2299  return result;
2300}
2301
2302//-------------------------------------------------------------
2303const cmt_string SetBuilder::build (const Symbol& symbol,
2304                                    const cmt_string& /*tag_name*/)
2305{
2306    // Control of recursivity
2307  static int level = 0;
2308
2309  bool show_it = false;
2310
2311  cmt_string temp;
2312  cmt_string previous_temp;
2313  cmt_string new_value;
2314  static const cmt_string empty;
2315
2316  ActionType action = Cmt::get_action ();
2317
2318  if (action == action_show_set)
2319    {
2320      if (symbol.name == Cmt::get_current_target ())
2321        {
2322             // Should not display on recursive calls
2323          if (level == 0) show_it = m_display_it;
2324        }
2325    }
2326
2327  level++;
2328
2329  temp = "";
2330
2331  bool first_definition = true;
2332
2333  for (int i = 0; i < symbol.value_lists.size (); i++)
2334    {
2335      const SymbolValueList& value_list = symbol.value_lists[i];
2336
2337      if ((value_list.use != 0) &&
2338          (value_list.use->discarded)) continue;
2339
2340      const int selected = value_list.select_first ();
2341
2342      if (selected < 0) continue;
2343
2344      SymbolValue& value = value_list.values[selected];
2345
2346      if (show_it && !Symbol::get_inhibit_display())
2347        {
2348          value_list.show (symbol, value, first_definition);
2349        }
2350     
2351      if (value_list.discarded) continue;
2352
2353        //
2354        // One should accumulate values if it refers to
2355        // itself.
2356        //
2357     
2358      new_value = value.text;
2359     
2360      resolve_value_for_macros (new_value);
2361     
2362      switch (value_list.command_type)
2363        {
2364          case CommandSet :
2365
2366            if (!value_list.is_reflexive || 
2367                !symbol.value_is_reflexive (value.text))
2368              {
2369                resolve_value (new_value, symbol.name, temp);
2370                temp = new_value;
2371
2372                // We clear the error since the set is defined in requirements
2373                // and the environment variable ought not to have been used
2374                if (CmtError::get_last_error_code () == CmtError::warning &&
2375                    CmtError::get_last_error () ==
2376                    CmtError::get_error_name (CmtError::warning) + ": " "getenv (" + symbol.name + ") denied")
2377                  CmtError::clear ();
2378              }
2379            else if (temp == "")
2380              {
2381                if (Cmt::get_env_access () ||
2382                    Symbol::std_env_vars ().has (symbol.name))
2383                  {
2384                    temp = CmtSystem::getenv (symbol.name);
2385                    if (Cmt::get_debug ())
2386                      {
2387                        cerr << "SetBuilder::build> getenv (" << symbol.name
2388                             << ") => " << temp << endl;
2389                      }
2390                  }
2391                else
2392                  {
2393                    if (Cmt::get_debug ())
2394                      {
2395                        cerr << "SetBuilder::build> getenv (" << symbol.name
2396                             << ") denied" << endl;
2397                      }
2398                    CmtError::set (CmtError::warning,
2399                                   "getenv (" + symbol.name + ") denied");
2400                    //              return "";
2401                    // We will clear the error if the set is defined in requirements
2402                  }
2403              }
2404
2405            break;
2406          case CommandSetAppend :
2407           
2408            if (new_value != "")
2409              {
2410                temp += new_value;
2411              }
2412           
2413            break;
2414          case CommandSetPrepend :
2415           
2416            if (new_value != "")
2417              {
2418                previous_temp = temp;
2419                temp = new_value;
2420                temp += previous_temp;
2421              }
2422           
2423            break;
2424          case CommandSetRemove :
2425           
2426            if (new_value != "")
2427              {
2428                temp.replace_all (new_value, empty);
2429              }
2430           
2431            break;
2432          case CommandSetRemoveRegexp :
2433           
2434            if (new_value != "")
2435              {
2436                cmt_regexp e (new_value);
2437                cmt_regexp::iterator it;
2438
2439                for (;;)
2440                  {
2441                    it = e.begin (temp);
2442                    if (it == e.end ()) break;
2443
2444                    temp.erase (it._pos, it._length);
2445                  }
2446              }
2447           
2448            break;
2449          case CommandAlias :
2450           
2451            resolve_value (new_value, symbol.name, temp);
2452            temp = new_value;
2453           
2454            break;
2455        }
2456    }
2457
2458  level--;
2459
2460  return (temp);
2461}
2462
2463namespace
2464{
2465int find_path_entry (const CmtSystem::cmt_string_vector& items, const cmt_string& value)
2466{
2467  //  if (value.size () == 0) return true;
2468 
2469  static cmt_vmap <cmt_string, cmt_string> realpaths;
2470
2471  cmt_string rvalue;
2472  const cmt_string * prvalue;
2473
2474  if (!(prvalue = realpaths.find (value)))
2475    {
2476      // if (!CmtSystem::realpath_ (value, rvalue))
2477      //{
2478          rvalue = value;
2479          CmtSystem::compress_path (rvalue);
2480      //}
2481      prvalue = &rvalue;
2482      realpaths.add (value, rvalue);
2483      //      cerr << "realpaths.add: " << value << " , " << rvalue << endl;
2484    }
2485
2486  for (int i = 0; i < items.size (); i++)
2487    {
2488      const cmt_string& item = items[i];
2489      if (item.size () == 0) continue;
2490      cmt_string ritem;
2491      const cmt_string * pritem;
2492
2493      if (!(pritem = realpaths.find (item)))
2494        {
2495          //if (!CmtSystem::realpath_ (item, ritem))
2496          //{
2497              ritem = item;
2498              CmtSystem::compress_path (ritem);
2499          //}
2500          pritem = &ritem;
2501          realpaths.add (item, ritem);
2502          //  cerr << "realpaths.add: " << item << " , " << ritem << endl;
2503        }
2504      if (*pritem == *prvalue)
2505        {
2506          return i;
2507        }
2508    }
2509
2510  return -1;
2511}
2512
2513}
2514/*
2515static bool find_path_entry (const CmtSystem::cmt_string_vector& items, const cmt_string& value)
2516{
2517  if (value.size () == 0) return true;
2518
2519  static cmt_vmap <cmt_string, cmt_string> realpaths;
2520
2521  cmt_string rvalue;
2522  const cmt_string * prvalue;
2523
2524  if (!(prvalue = realpaths.find (value)))
2525    {
2526      // if (!CmtSystem::realpath_ (value, rvalue))
2527      //{
2528          rvalue = value;
2529          CmtSystem::compress_path (rvalue);
2530      //}
2531      prvalue = &rvalue;
2532      realpaths.add (value, rvalue);
2533      //      cerr << "realpaths.add: " << value << " , " << rvalue << endl;
2534    }
2535
2536  for (int i = 0; i < items.size (); i++)
2537    {
2538      const cmt_string& item = items[i];
2539      if (item.size () == 0) continue;
2540      cmt_string ritem;
2541      const cmt_string * pritem;
2542
2543      if (!(pritem = realpaths.find (item)))
2544        {
2545          //if (!CmtSystem::realpath_ (item, ritem))
2546          //{
2547              ritem = item;
2548              CmtSystem::compress_path (ritem);
2549          //}
2550          pritem = &ritem;
2551          realpaths.add (item, ritem);
2552          //  cerr << "realpaths.add: " << item << " , " << ritem << endl;
2553        }
2554      if (*pritem == *prvalue)
2555        {
2556          return true;
2557        }
2558    }
2559
2560  return false;
2561}
2562*/
2563/*
2564static bool find_path_entry (const cmt_string& paths, const cmt_string& value)
2565{
2566  static const cmt_string path_separator = CmtSystem::path_separator ();
2567  static cmt_vmap <cmt_string, cmt_string> realpaths;
2568
2569  cmt_string rvalue;
2570  const cmt_string * prvalue;
2571
2572  if (!(prvalue = realpaths.find (value)))
2573    {
2574      if (!CmtSystem::realpath_ (value, rvalue))
2575        {
2576          rvalue = value;
2577          CmtSystem::compress_path (rvalue);
2578        }
2579      prvalue = &rvalue;
2580      realpaths.add (value, rvalue);
2581      //      cerr << "realpaths.add: " << value << " , " << rvalue << endl;
2582    }
2583
2584  CmtSystem::cmt_string_vector items;
2585  CmtSystem::split (paths, path_separator, items);
2586
2587  bool found = false;
2588
2589  for (int i = 0; i < items.size (); i++)
2590    {
2591      const cmt_string& item = items[i];
2592      cmt_string ritem;
2593      const cmt_string * pritem;
2594
2595      if (!(pritem = realpaths.find (item)))
2596        {
2597          if (!CmtSystem::realpath_ (item, ritem))
2598            {
2599              ritem = item;
2600              CmtSystem::compress_path (ritem);
2601            }
2602          pritem = &ritem;
2603          realpaths.add (item, ritem);
2604          //  cerr << "realpaths.add: " << item << " , " << ritem << endl;
2605        }
2606      if (*pritem == *prvalue)
2607        {
2608          found = true;
2609          break;
2610        }
2611    }
2612
2613  return (found);
2614}
2615*/
2616//-------------------------------------------------------------
2617PathBuilder* PathBuilder::get_path_builder ()
2618{
2619  static PathBuilder Path (Cmt::get_strip_path ());
2620  return &Path;
2621}
2622
2623//-------------------------------------------------------------
2624PathBuilder::PathBuilder ()
2625  : m_strip_path (false)
2626{
2627}
2628
2629//-------------------------------------------------------------
2630PathBuilder::PathBuilder (bool strip_path)
2631{
2632  PathBuilder ();
2633  m_strip_path = strip_path;
2634}
2635
2636//-------------------------------------------------------------
2637const cmt_string PathBuilder::build (const Symbol& symbol,
2638                                     const cmt_string& /*tag_name*/)
2639{
2640    // Control of recursivity
2641  static int level = 0;
2642
2643  bool show_it = false;
2644
2645  cmt_string temp;
2646  CmtSystem::cmt_string_vector temp_vector;
2647  //  cmt_string previous_temp;
2648  CmtSystem::cmt_string_vector new_value_vector;
2649  cmt_string new_value;
2650  static const cmt_string empty;
2651
2652  static cmt_string path_separator = CmtSystem::path_separator ();
2653
2654  ActionType action = Cmt::get_action ();
2655
2656  if (action == action_show_set)
2657    {
2658      if (symbol.name == Cmt::get_current_target ())
2659        {
2660            // Should not display on recursive calls
2661          if (level == 0) show_it = m_display_it;
2662        }
2663    }
2664
2665  level++;
2666
2667                if (Cmt::get_env_access () ||
2668                    Symbol::std_env_vars ().has (symbol.name))
2669                  {
2670  //temp = CmtSystem::getenv (symbol.name);
2671  CmtSystem::split (CmtSystem::getenv (symbol.name), path_separator, temp_vector);
2672  filter_path_value (symbol, temp_vector);
2673                    if (Cmt::get_debug ())
2674                      {
2675                        cmt_string temp_txt;
2676                        Cmt::vector_to_string (temp_vector, path_separator, temp_txt);
2677                        cerr << "PathBuilder::build> getenv (" << symbol.name
2678                             << ") => " << temp_txt << endl;
2679                      }
2680                  }
2681                else
2682                  {
2683                    if (Cmt::get_debug ())
2684                      {
2685                        cerr << "PathBuilder::build> getenv (" << symbol.name
2686                             << ") denied" << endl;
2687                      }
2688                    CmtError::set (CmtError::warning,
2689                                   "getenv (" + symbol.name + ") denied");
2690                    //              return "";
2691                    // We will clear the error if the path is defined in requirements
2692                  }
2693
2694  bool first_definition = true;
2695
2696  for (int i = 0; i < symbol.value_lists.size (); i++)
2697    {
2698      const SymbolValueList& value_list = symbol.value_lists[i];
2699
2700      if ((value_list.use != 0) &&
2701          (value_list.use->discarded)) continue;
2702
2703      const int selected = value_list.select_first ();
2704     
2705      if (selected < 0) continue;
2706 
2707      SymbolValue& value = value_list.values[selected];
2708         
2709      if (show_it && !Symbol::get_inhibit_display())
2710        {
2711          value_list.show (symbol, value, first_definition);
2712        }
2713         
2714      if (value_list.discarded) continue;
2715
2716      new_value = value.text;
2717         
2718          //resolve_value (new_value);
2719      resolve_value_for_macros (new_value);
2720         
2721      switch (value_list.command_type)
2722        {
2723          case CommandPath :
2724           
2725            if (!value_list.is_reflexive || 
2726                !symbol.value_is_reflexive (value.text))
2727              {
2728                Cmt::vector_to_string (temp_vector, path_separator, temp);
2729                resolve_value (new_value, symbol.name, temp);
2730                CmtSystem::split (new_value, path_separator, temp_vector);
2731                //temp = new_value;
2732                filter_path_value (symbol, temp_vector);
2733
2734                // We clear the error since the path is defined in requirements
2735                // and the environment variable ought not to have been used
2736                if (CmtError::get_last_error_code () == CmtError::warning &&
2737                    CmtError::get_last_error () ==
2738                    CmtError::get_error_name (CmtError::warning) + ": " "getenv (" + symbol.name + ") denied")
2739                  CmtError::clear ();
2740              }
2741
2742            break;
2743          case CommandPathAppend :
2744             
2745            if (new_value != "")
2746              {
2747                CmtSystem::split (new_value, path_separator, new_value_vector);
2748                for (int i = 0; i < new_value_vector.size (); i++)
2749                  {
2750                    if (new_value_vector[i].size () == 0) continue;
2751                    int j = find_path_entry (temp_vector, new_value_vector[i]);
2752                    if (j < 0)
2753                      {
2754                        temp_vector.push_back (new_value_vector[i]);
2755                      }
2756                    else if (j < temp_vector.size () - 1)
2757                      {
2758                        temp_vector [j] = "";
2759                        temp_vector.push_back (new_value_vector[i]);
2760                      }
2761                  }
2762              }
2763                 
2764            break;
2765          case CommandPathPrepend :
2766             
2767            if (new_value != "")
2768              {
2769                CmtSystem::split (new_value, path_separator, new_value_vector);
2770                int n (new_value_vector.size ());
2771                temp_vector.resize (temp_vector.size () + n);
2772                for (int i = temp_vector.size () - 1; i > n - 1; i--)
2773                  temp_vector [i] = temp_vector [i - n];
2774                for (int i = 0; i < n; i++)
2775                  temp_vector [i] = "";
2776                for (int i = 0; i < new_value_vector.size (); i++)
2777                  {
2778                    if (new_value_vector[i].size () == 0) continue;
2779                    int j = find_path_entry (temp_vector, new_value_vector[i]);
2780                    if (j < 0)
2781                      {
2782                        temp_vector [i] = new_value_vector[i];
2783                      }
2784                    else if (j >= n)
2785                      {
2786                        temp_vector [i] = new_value_vector[i];
2787                        temp_vector [j] = "";
2788                      }
2789                  }
2790              }
2791           
2792            break;
2793          case CommandPathRemove :
2794             
2795            if (new_value != "")
2796              {
2797                for (int j = 0; j < temp_vector.size (); ++j)
2798                  {
2799                    cmt_string& s = temp_vector[j];
2800                   
2801                    if (s.find (new_value) != cmt_string::npos)
2802                      {
2803                        s = "";
2804                      }
2805                  }
2806                /*
2807                CmtSystem::cmt_string_vector paths;
2808                 
2809                CmtSystem::split (temp, path_separator, paths);
2810                 
2811                for (int j = 0; j < paths.size (); ++j)
2812                  {
2813                    cmt_string& s = paths[j];
2814                     
2815                    if (s.find (new_value) != cmt_string::npos)
2816                      {
2817                        s = "";
2818                      }
2819                  }
2820
2821                Cmt::vector_to_string (paths, path_separator, temp);
2822                */
2823              }
2824             
2825            break;
2826          case CommandPathRemoveRegexp :
2827
2828            if (new_value != "")
2829              {
2830                cmt_regexp e (new_value);
2831
2832                for (int j = 0; j < temp_vector.size (); ++j)
2833                  {
2834                    cmt_string& s = temp_vector[j];
2835
2836                    if (Cmt::get_debug () &&
2837                        CmtSystem::getenv ("TESTPRR") != "")
2838                      {
2839                        cerr << "PRR> s=[" << s << "]";
2840                      }
2841
2842                    if (e.match (s))
2843                      {
2844                        s = "";
2845
2846                        if (Cmt::get_debug () &&
2847                            CmtSystem::getenv ("TESTPRR") != "")
2848                          {
2849                            cerr << " match ";
2850                          }
2851                      }
2852                    else
2853                      {
2854                        if (Cmt::get_debug () &&
2855                            CmtSystem::getenv ("TESTPRR") != "")
2856                          {
2857                            cerr << " no match ";
2858                          }
2859                      }
2860
2861                    if (Cmt::get_debug () &&
2862                        CmtSystem::getenv ("TESTPRR") != "")
2863                      {
2864                        cerr << endl;
2865                      }
2866                  }
2867
2868                /*
2869                CmtSystem::cmt_string_vector paths;
2870                 
2871                CmtSystem::split (temp, path_separator, paths);
2872                 
2873                for (int j = 0; j < paths.size (); ++j)
2874                  {
2875                    cmt_string& s = paths[j];
2876
2877                    if (CmtSystem::getenv ("TESTPRR") != "")
2878                      {
2879                        cerr << "PRR> s=[" << s << "]";
2880                      }
2881
2882                    if (e.match (s))
2883                      {
2884                        s = "";
2885
2886                        if (CmtSystem::getenv ("TESTPRR") != "")
2887                          {
2888                            cerr << " match ";
2889                          }
2890                      }
2891                    else
2892                      {
2893                        if (CmtSystem::getenv ("TESTPRR") != "")
2894                          {
2895                            cerr << " no match ";
2896                          }
2897                      }
2898
2899                    if (CmtSystem::getenv ("TESTPRR") != "")
2900                      {
2901                        cerr << endl;
2902                      }
2903                  }
2904
2905                Cmt::vector_to_string (paths, path_separator, temp);
2906                */
2907              }
2908             
2909            break;
2910        }
2911
2912    }
2913
2914  Cmt::vector_to_string (temp_vector, path_separator, temp);
2915
2916  level--;
2917  /*
2918  for (;;)
2919    {
2920      int sz = temp.size ();
2921
2922      if (sz == 0) break;
2923
2924      if ((temp[0] == ';') || (temp[0] == ':'))
2925        {
2926          temp.erase (0, 1);
2927        }
2928      else if ((temp[sz-1] == ';') || (temp[sz-1] == ':'))
2929        {
2930          temp.erase (sz-1, 1);
2931        }
2932      else
2933        {
2934          break;
2935        }
2936    }
2937
2938  temp.replace_all ("::", ":");
2939  temp.replace_all (";;", ";");
2940  */
2941  return (temp);
2942}
2943
2944//-------------------------------------------------------------
2945const cmt_string PathBuilder::clean (const Symbol& symbol,
2946                                     const cmt_string& /*tag_name*/)
2947{
2948    // Control of recursivity
2949  static int level = 0;
2950
2951  cmt_string temp;
2952  cmt_string new_value;
2953  static const cmt_string empty;
2954
2955  static cmt_string path_separator = CmtSystem::path_separator ();
2956
2957  temp = CmtSystem::getenv (symbol.name);
2958
2959    //cerr << "#####1 temp=" << temp << endl;
2960
2961  for (int i = 0; i < symbol.value_lists.size (); i++)
2962    {
2963      const SymbolValueList& value_list = symbol.value_lists[i];
2964
2965      if (value_list.discarded) continue;
2966
2967      if ((value_list.use != 0) &&
2968          (value_list.use->discarded)) continue;
2969
2970      const int selected = value_list.select_first ();
2971     
2972      if (selected < 0) continue;
2973 
2974      SymbolValue& value = value_list.values[selected];
2975         
2976      new_value = value.text;
2977         
2978          //resolve_value (new_value);
2979
2980        //cerr << "#####1 new_value=" << new_value << endl;
2981
2982      resolve_value_for_macros (new_value);
2983      resolve_value (new_value);
2984         
2985        //cerr << "#####2 new_value=" << new_value << endl;
2986
2987      switch (value_list.command_type)
2988        {
2989          case CommandPath :
2990           
2991            temp = "";
2992           
2993            break;
2994          case CommandPathAppend :
2995          case CommandPathPrepend :
2996          case CommandPathRemove :
2997
2998            if (new_value != "")
2999              {
3000                CmtSystem::cmt_string_vector paths;
3001                 
3002                CmtSystem::split (temp, path_separator, paths);
3003                 
3004                for (int j = 0; j < paths.size (); ++j)
3005                  {
3006                    cmt_string& s = paths[j];
3007                     
3008                    if (s.find (new_value) != cmt_string::npos)
3009                      {
3010                        s = "";
3011                      }
3012
3013                    if (j > 0)
3014                      {
3015                        cmt_string& s2 = paths[j-1];
3016                        if (s2 == s)
3017                          {
3018                            s2 = "";
3019                          }
3020                      }
3021                  }
3022
3023                Cmt::vector_to_string (paths, path_separator, temp);
3024                temp.replace_all ("::", ":");
3025                temp.replace_all (";;", ";");
3026              }
3027             
3028            break;
3029          case CommandPathRemoveRegexp :
3030
3031            if (new_value != "")
3032              {
3033                cmt_regexp e (new_value);
3034
3035                CmtSystem::cmt_string_vector paths;
3036                 
3037                CmtSystem::split (temp, path_separator, paths);
3038                 
3039                for (int j = 0; j < paths.size (); ++j)
3040                  {
3041                    cmt_string& s = paths[j];
3042                     
3043                    if (e.match (s))
3044                      {
3045                        s = "";
3046                      }
3047
3048                    if (j > 0)
3049                      {
3050                        cmt_string& s2 = paths[j-1];
3051                        if (s2 == s)
3052                          {
3053                            s2 = "";
3054                          }
3055                      }
3056                  }
3057
3058                Cmt::vector_to_string (paths, path_separator, temp);
3059                temp.replace_all ("::", ":");
3060                temp.replace_all (";;", ";");
3061              }
3062             
3063            break;
3064        }
3065    }
3066
3067    //cerr << "#####2 temp=" << temp << endl;
3068 
3069  return (temp);
3070}
3071
3072//-------------------------------------------------------------
3073void PathBuilder::filter_path_value (const Symbol& symbol,
3074                                     CmtSystem::cmt_string_vector& value,
3075                                     const cmt_string& /* tag_name */) const
3076{
3077  static cmt_regexp reg ("[$%`]");
3078
3079  cmt_vector<int> path (value.size ());
3080  int n (0);
3081
3082  for (int j = 0; j < value.size (); j++)
3083    {
3084      const cmt_string& v = value[j];
3085      bool exists (false); 
3086      for (int i = 0; i < j; i++)
3087        {
3088          if (value[i] == v)
3089            {
3090              exists = true;
3091              break;
3092            }
3093        }                 
3094      if (!exists)
3095        {
3096          if (m_strip_path)
3097            {
3098              if (!reg.match (v))
3099                {
3100                  if (!CmtSystem::test_directory (v))
3101                    {
3102                      CmtMessage::verbose ("Non-existent directory " + v + " in " + symbol.name + " skipped");
3103                      continue;
3104                    }
3105                }
3106              else
3107                {
3108                  if (CmtMessage::active (Verbose))
3109                    {
3110                      CmtMessage::warning ("Unresolved directory name " + v + " in " + symbol.name);
3111                    }
3112                }
3113            }
3114          else
3115            {
3116              if (CmtMessage::active (Verbose))
3117                if (!reg.match (v) &&
3118                    !CmtSystem::test_directory (v))
3119                  {
3120                    CmtMessage::warning ("Non-existent directory " + v + " in " + symbol.name);
3121                  }
3122            }
3123          path[n++] = j;
3124        }
3125    }
3126
3127  for (int i = 0; i < n; i++)
3128    if (i != path[i]) value[i] = value[path[i]];
3129 
3130  value.resize (n);
3131}
3132
3133//-------------------------------------------------------------
3134void PathBuilder::filter_path_value (const Symbol& symbol,
3135                                     cmt_string& value,
3136                                     const cmt_string& tag_name) const
3137{
3138  static cmt_string ps (CmtSystem::path_separator ());
3139  CmtSystem::cmt_string_vector paths;
3140
3141  CmtSystem::split (value, ps, paths);
3142  filter_path_value (symbol, paths, tag_name);
3143  Cmt::vector_to_string (paths, ps, value);
3144}
3145
3146//-------------------------------------------------------------
3147inline const bool& PathBuilder::get_strip_path () const
3148{
3149  return m_strip_path;
3150}
3151
3152//-------------------------------------------------------------
3153inline void PathBuilder::set_strip_path (const bool& strip_path)
3154{
3155  m_strip_path = strip_path;
3156}
3157
3158//-------------------------------------------------------------
3159const cmt_string MacroBuilder::build (const Symbol& symbol,
3160                                      const cmt_string& tag_name)
3161{
3162    // Control of recursivity
3163  static int level = 0;
3164
3165  cmt_string temp;
3166  cmt_string previous_temp;
3167  static const cmt_string empty;
3168  bool show_it = false;
3169
3170  ActionType action = Cmt::get_action ();
3171
3172  if (action == action_show_macro)
3173    {
3174      if (symbol.name == Cmt::get_current_target ())
3175        {
3176             // Should not display on recursive calls
3177          if (level == 0) show_it = m_display_it;
3178        }
3179    }
3180
3181  level++;
3182
3183  temp = "";
3184
3185  int i;
3186
3187  bool first_definition = true;
3188
3189  for (i = 0; i < symbol.value_lists.size (); i++)
3190    {
3191      const SymbolValueList& value_list = symbol.value_lists[i];
3192
3193      if ((value_list.use != 0) &&
3194          (value_list.use->discarded)) continue;
3195
3196      if (value_list.command_type != CommandMacroPrepend) continue;
3197
3198      const int selected = value_list.select_first (tag_name);
3199
3200      if (selected < 0) continue;
3201
3202      SymbolValue& value = value_list.values[selected];
3203
3204      if (show_it && !Symbol::get_inhibit_display())
3205        {
3206          value_list.show (symbol, value, first_definition);
3207        }
3208
3209      if (value_list.discarded) continue;
3210
3211      previous_temp = temp;
3212      temp = value.text;
3213      temp += previous_temp;
3214    }
3215
3216  previous_temp = temp;
3217  temp = "";
3218
3219  first_definition = true;
3220
3221  for (i = 0; i < symbol.value_lists.size (); i++)
3222    {
3223      const SymbolValueList& value_list = symbol.value_lists[i];
3224
3225      if ((value_list.use != 0) &&
3226          (value_list.use->discarded)) continue;
3227
3228      if (value_list.command_type != CommandMacro) continue;
3229
3230      const int selected = value_list.select_first (tag_name);
3231
3232      if (selected < 0) continue;
3233
3234      SymbolValue& value = value_list.values[selected];
3235
3236      if (show_it && !Symbol::get_inhibit_display())
3237        {
3238          value_list.show (symbol, value, first_definition);
3239        }
3240
3241      // WARNING:
3242      // Commented just for a test : should be uncommented after the test
3243      if (value_list.discarded) continue;
3244     
3245      if (!value_list.is_reflexive || 
3246          !symbol.value_is_reflexive (value.text))
3247        {
3248          temp = value.text;
3249        }
3250    }
3251
3252  previous_temp += temp;
3253  temp = previous_temp;
3254
3255  for (i = 0; i < symbol.value_lists.size (); i++)
3256    {
3257      const SymbolValueList& value_list = symbol.value_lists[i];
3258
3259      if ((value_list.use != 0) &&
3260          (value_list.use->discarded)) continue;
3261
3262      if (value_list.command_type != CommandMacroAppend) continue;
3263
3264      const int selected = value_list.select_first (tag_name);
3265
3266      if (selected < 0) continue;
3267
3268      SymbolValue& value = value_list.values[selected];
3269
3270      if (show_it && !Symbol::get_inhibit_display())
3271        {
3272          value_list.show (symbol, value, first_definition);
3273        }
3274
3275      if (value_list.discarded) continue;
3276
3277      temp += value.text;
3278    }
3279
3280  for (i = 0; i < symbol.value_lists.size (); i++)
3281    {
3282      const SymbolValueList& value_list = symbol.value_lists[i];
3283
3284      if ((value_list.use != 0) &&
3285          (value_list.use->discarded)) continue;
3286
3287      if ((value_list.command_type != CommandMacroRemove) &&
3288          (value_list.command_type != CommandMacroRemoveRegexp) &&
3289          (value_list.command_type != CommandMacroRemoveAll) &&
3290          (value_list.command_type != CommandMacroRemoveAllRegexp)) continue;
3291
3292      const int selected = value_list.select_first (tag_name);
3293
3294      if (selected < 0) continue;
3295
3296      SymbolValue& value = value_list.values[selected];
3297
3298      if (show_it && !Symbol::get_inhibit_display())
3299        {
3300          value_list.show (symbol, value, first_definition);
3301        }
3302
3303      if (value_list.discarded) continue;
3304
3305      switch (value_list.command_type)
3306        {
3307          case CommandMacroRemove :
3308            temp.replace (value.text, empty);
3309            break;
3310          case CommandMacroRemoveRegexp :
3311            if (value.text != "")
3312              {
3313                cmt_regexp e (value.text);
3314                cmt_regexp::iterator it;
3315
3316                it = e.begin (temp);
3317                if (it != e.end ())
3318                  {
3319                    temp.erase (it._pos, it._length);
3320                  }
3321              }
3322            break;
3323          case CommandMacroRemoveAll :
3324            temp.replace_all (value.text, empty);
3325            break;
3326          case CommandMacroRemoveAllRegexp :
3327            if (value.text != "")
3328              {
3329                cmt_regexp e (value.text);
3330                cmt_regexp::iterator it;
3331
3332                for (;;)
3333                  {
3334                    it = e.begin (temp);
3335                    if (it != e.end ())
3336                      {
3337                        temp.erase (it._pos, it._length);
3338                      }
3339                    else
3340                      {
3341                        break;
3342                      }
3343                  }
3344              }
3345            break;
3346        }
3347    }
3348
3349  level--;
3350
3351  return (temp);
3352}
3353
3354//-------------------------------------------------------------
3355const cmt_string ScriptBuilder::build (const Symbol& symbol,
3356                                       const cmt_string& tag_name)
3357{
3358    // Control of recursivity
3359  static int level = 0;
3360
3361  static const cmt_string empty = "";
3362
3363  if (symbol.value_lists.size () > 0)
3364    {
3365      const SymbolValueList& value_list = symbol.value_lists[0];
3366
3367      if (value_list.discarded) return (empty);
3368
3369      if ((value_list.use != 0) &&
3370          (value_list.use->discarded)) return (empty);
3371    }
3372
3373  return (symbol.name);
3374}
3375
3376//-------------------------------------------------------------
3377const cmt_string ActionBuilder::build (const Symbol& symbol,
3378                                       const cmt_string& tag_name)
3379{
3380    // Control of recursivity
3381  static int level = 0;
3382
3383  cmt_string temp;
3384  cmt_string previous_temp;
3385  static const cmt_string empty;
3386  bool show_it = false;
3387
3388  ActionType action = Cmt::get_action ();
3389
3390  if (action == action_show_action)
3391    {
3392      if (symbol.name == Cmt::get_current_target ())
3393        {
3394             // Should not display on recursive calls
3395          if (level == 0) show_it = m_display_it;
3396        }
3397    }
3398
3399  level++;
3400
3401  int i;
3402
3403  bool first_definition = true;
3404
3405  temp = "";
3406
3407  for (i = 0; i < symbol.value_lists.size (); i++)
3408    {
3409      const SymbolValueList& value_list = symbol.value_lists[i];
3410
3411      if ((value_list.use != 0) &&
3412          (value_list.use->discarded)) continue;
3413
3414      if (value_list.command_type != CommandAction) continue;
3415
3416      const int selected = value_list.select_first (tag_name);
3417
3418      if (selected < 0) continue;
3419
3420      SymbolValue& value = value_list.values[selected];
3421
3422      if (show_it && !Symbol::get_inhibit_display())
3423        {
3424          value_list.show (symbol, value, first_definition);
3425        }
3426
3427      // WARNING:
3428      // Commented just for a test : should be uncommented after the test
3429      if (value_list.discarded) continue;
3430     
3431      if (!value_list.is_reflexive || 
3432          !symbol.value_is_reflexive (value.text))
3433        {
3434          temp = value.text;
3435        }
3436    }
3437
3438  level--;
3439
3440  return (temp);
3441}
3442
3443//-------------------------------------------------------------
3444int SymbolValueList::select_first (const cmt_string& tag_name) const
3445{
3446  int priority = 0;
3447  int value_number;
3448  int selected = -1;
3449
3450  Tag* the_tag = 0;
3451
3452  if (tag_name != "") the_tag = Tag::find (tag_name);
3453
3454  for (value_number = 0;
3455       value_number < values.size ();
3456       value_number++)
3457    {
3458      const SymbolValue& value = values[value_number];
3459
3460      const Tag* tag = value.tag;
3461
3462      if (the_tag == 0)
3463        {
3464          if (!tag->is_selected ()) continue;
3465          selected = value_number;
3466          if (tag == Tag::get_default ())
3467            continue;
3468        }
3469      else
3470        {
3471          if (tag != the_tag) continue;
3472          selected = value_number;
3473        }
3474
3475      //
3476      // Only the value for the first alternative (i.e. non-default)
3477      // matching tag expression is
3478      // selected (which means the selection stops here)
3479      //
3480      break;
3481
3482      //
3483      // Only the first value at a given priority is
3484      // selected (which implies the '>' test instead
3485      // of '>=')
3486      //
3487      /*
3488      if (tag->get_priority () > priority)
3489        {
3490          priority = tag->get_priority ();
3491          selected = value_number;
3492        }
3493      */
3494    }
3495
3496  return (selected);
3497}
3498
3499//-------------------------------------------------------------
3500int SymbolValueList::select_last () const
3501{
3502  int priority = 0;
3503  int value_number;
3504  int selected = -1;
3505
3506  for (value_number = 0;
3507       value_number < values.size ();
3508       value_number++)
3509    {
3510      SymbolValue& value = values[value_number];
3511
3512      const Tag* tag = value.tag;
3513
3514      if (tag->is_selected ())
3515        {
3516          //
3517          // The last value at a given priority is
3518          // selected (which implies the '>=' test instead
3519          // of '>')
3520          //
3521
3522          if (tag->get_priority () >= priority)
3523            {
3524              priority = tag->get_priority ();
3525              selected = value_number;
3526            }
3527        }
3528    }
3529
3530  return (selected);
3531}
3532
3533//-------------------------------------------------------------
3534void SymbolValueList::show (const Symbol& symbol, 
3535                            const SymbolValue& value, 
3536                            bool& first_definition) const
3537{
3538  cmt_string discarded_text;
3539  cmt_string define_text;
3540  ActionType action = Cmt::get_action ();
3541
3542  switch (command_type)
3543    {
3544      //case CommandSet :
3545      case CommandSetAppend :
3546      case CommandSetPrepend :
3547      case CommandSetRemove :
3548      case CommandSetRemoveRegexp :
3549        //case CommandAlias :
3550        //case CommandPath :
3551      case CommandPathAppend :
3552      case CommandPathPrepend :
3553      case CommandPathRemove :
3554      case CommandPathRemoveRegexp :
3555      case CommandMacroPrepend :
3556        //case CommandMacro :
3557      case CommandMacroAppend :
3558      case CommandMacroRemove :
3559      case CommandMacroRemoveRegexp :
3560      case CommandMacroRemoveAll :
3561      case CommandMacroRemoveAllRegexp :
3562        //case CommandAction :
3563        if (value.text == "") return;
3564        break;
3565    }
3566
3567  if (discarded) discarded_text = " (discarded by override)";
3568  else discarded_text = "";
3569
3570  if (first_definition) define_text = "defines";
3571  else define_text = "overrides";
3572
3573  cout << "# Package ";
3574  if (use != 0)
3575    {
3576      cout << use->get_package_name () << " " << use->version;
3577    }
3578
3579  switch (command_type)
3580    {
3581      case CommandSet :
3582        cout << " " << define_text << " set " << symbol.name << " as ";
3583        first_definition = false;
3584        break;
3585      case CommandSetAppend :
3586        cout << " appends to set " << symbol.name << " : ";
3587        break;
3588      case CommandSetPrepend :
3589        cout << " prepends to set " << symbol.name << " : ";
3590        break;
3591      case CommandSetRemove :
3592        cout << " removes from set " << symbol.name << " : ";
3593        break;
3594      case CommandSetRemoveRegexp :
3595        cout << " removes RE from set " << symbol.name << " : ";
3596        break;
3597      case CommandAlias :
3598        cout << " " << define_text << " alias " << symbol.name << " as ";
3599        first_definition = false;
3600        break;
3601      case CommandPath :
3602        cout << " " << define_text << " path " << symbol.name << " as ";
3603        first_definition = false;
3604        break;
3605      case CommandPathAppend :
3606        cout << " appends to path " << symbol.name << " : ";
3607        break;
3608      case CommandPathPrepend :
3609        cout << " prepends to path " << symbol.name << " : ";
3610        break;
3611      case CommandPathRemove :
3612        cout << " removes from path " << symbol.name << " : ";
3613        break;
3614      case CommandPathRemoveRegexp :
3615        cout << " removes RE from path " << symbol.name << " : ";
3616        break;
3617      case CommandMacroPrepend :
3618        cout << " prepends to macro " << symbol.name << " : ";
3619        break;
3620      case CommandMacro :
3621        cout << " " << define_text << " macro " << symbol.name << " as ";
3622        break;
3623      case CommandMacroAppend :
3624        cout << " appends to macro " << symbol.name << " : ";
3625        break;
3626      case CommandMacroRemove :
3627        cout << " remove from macro " << symbol.name << " : ";
3628        break;
3629      case CommandMacroRemoveRegexp :
3630        cout << " remove RE from macro " << symbol.name << " : ";
3631        break;
3632      case CommandMacroRemoveAll :
3633        cout << " remove all from macro " << symbol.name << " : ";
3634        break;
3635      case CommandMacroRemoveAllRegexp :
3636        cout << " remove all RE from macro " << symbol.name << " : ";
3637        break;
3638      case CommandAction :
3639        cout << " " << define_text << " action " << symbol.name << " as ";
3640        first_definition = false;
3641        break;
3642    }
3643
3644  cout << "'" << value.text << "'";
3645         
3646  Tag* selected_tag = value.tag;
3647         
3648  if ((selected_tag == 0) ||
3649      (selected_tag == Tag::get_default ()))
3650    {
3651      cout << " for default tag";
3652    }
3653  else
3654    {
3655      cout << " for tag '" << selected_tag->get_name () << "'";
3656    }
3657 
3658  cout << discarded_text << endl;
3659}
3660
3661//-------------------------------------------------------------
3662int SymbolValueList::print (const Symbol& symbol, 
3663                            const SymbolValue& value, 
3664                            bool& first_definition,
3665                            ostream& out) const
3666{
3667  int result (0);
3668
3669  cmt_string discarded_text;
3670  cmt_string define_text;
3671  ActionType action = Cmt::get_action ();
3672
3673  static PathBuilder* pb (0);
3674  cmt_string rvalue (value.text);
3675
3676  switch (command_type)
3677    {
3678      //case CommandSet :
3679      case CommandSetAppend :
3680      case CommandSetPrepend :
3681      case CommandSetRemove :
3682      case CommandSetRemoveRegexp :
3683        //case CommandAlias :
3684        //case CommandPath :
3685      case CommandPathAppend :
3686      case CommandPathPrepend :
3687      case CommandPathRemove :
3688      case CommandPathRemoveRegexp :
3689      case CommandMacroPrepend :
3690        //case CommandMacro :
3691      case CommandMacroAppend :
3692      case CommandMacroRemove :
3693      case CommandMacroRemoveRegexp :
3694      case CommandMacroRemoveAll :
3695      case CommandMacroRemoveAllRegexp :
3696        //case CommandAction :
3697        if (value.text.size () == 0) return result;
3698        break;
3699    }
3700
3701  CmtError::code code (CmtError::ok);
3702  cmt_string msg, n;
3703  int exec_err (0);
3704
3705  switch (command_type)
3706    {
3707      case CommandSet :
3708      case CommandSetAppend :
3709      case CommandSetPrepend :
3710      case CommandSetRemove :
3711      case CommandSetRemoveRegexp :
3712
3713        if (CmtError::has_pending_error ())
3714          {
3715            code = CmtError::get_last_error_code ();
3716            msg = CmtError::get_last_error ();
3717            exec_err = CmtError::get_last_execution_error ();
3718            n = CmtError::get_error_name (code);
3719            CmtError::clear ();
3720          }
3721        resolve_value_for_macros (rvalue);
3722        if (CmtError::get_last_error_code () != CmtError::warning)
3723          {
3724            if (CmtError::has_pending_error ())
3725              {
3726                CmtError::print ();
3727                CmtError::clear ();
3728              }
3729            if (CmtError::ok != code)
3730              {
3731                // restore error occurred before value expansion
3732                CmtError::set (code,
3733                               (msg.replace (n + ": ", cmt_string ("")), msg),
3734                               exec_err);
3735              }
3736            if (CommandSet != command_type &&
3737                rvalue.size () == 0)
3738              return result;
3739          }
3740        else
3741          {
3742            if (CmtMessage::active (Verbose))
3743              CmtError::print ();
3744            CmtError::clear ();
3745            if (CmtError::ok != code)
3746              {
3747                // restore error occurred before value expansion
3748                CmtError::set (code,
3749                               (msg.replace (n + ": ", cmt_string ("")), msg),
3750                               exec_err);
3751              }
3752            // Ignore the error, keep the value unresolved
3753            rvalue = value.text;
3754          }
3755
3756        break;
3757
3758        //case CommandAlias :
3759      case CommandPath :
3760      case CommandPathAppend :
3761      case CommandPathPrepend :
3762      case CommandPathRemove :
3763      case CommandPathRemoveRegexp :
3764        //case CommandMacroPrepend :
3765        //case CommandMacro :
3766        //case CommandMacroAppend :
3767        //case CommandMacroRemove :
3768        //case CommandMacroRemoveRegexp :
3769        //case CommandMacroRemoveAll :
3770        //case CommandMacroRemoveAllRegexp :
3771        //case CommandAction :
3772
3773        if (!pb)
3774          pb = static_cast<PathBuilder*> (symbol.builder);
3775        if (pb->get_strip_path ())
3776          {
3777            /*
3778            CmtError::code code (CmtError::ok);
3779            cmt_string msg, n;
3780            int exec_err (0);
3781            */
3782            if (CmtError::has_pending_error ())
3783              {
3784                code = CmtError::get_last_error_code ();
3785                msg = CmtError::get_last_error ();
3786                exec_err = CmtError::get_last_execution_error ();
3787                n = CmtError::get_error_name (code);
3788                CmtError::clear ();
3789              }
3790            resolve_value (rvalue);
3791            if (CmtError::get_last_error_code () != CmtError::warning)
3792              {
3793                if (CmtError::has_pending_error ())
3794                  {
3795                    CmtError::print ();
3796                    CmtError::clear ();
3797                  }
3798                if (CmtError::ok != code)
3799                  {
3800                    // restore error occurred before value expansion
3801                    CmtError::set (code,
3802                                   (msg.replace (n + ": ", cmt_string ("")), msg),
3803                                   exec_err);
3804                  }
3805                if (CommandPath != command_type &&
3806                    rvalue.size () == 0)
3807                  return result;
3808              }
3809            else
3810              {
3811                if (CommandPathRemove == command_type ||
3812                    CommandPathRemoveRegexp == command_type)
3813                  {
3814                    // This means that the value is not resolved via symbols
3815                    // and, possibly, standard environment variables and
3816                    //   * either has no effect on the path at all,
3817                    //     or
3818                    //   * there should be similar contribution from
3819                    //     and, hence, we should get the same error with
3820                    //     CommandPath, CommandPathAppend, or CommandPathPrepend
3821                    //  Either way, we can ignore this error.
3822
3823                    if (CmtMessage::active (Verbose))
3824                      CmtError::print ();
3825                    CmtError::clear ();
3826                    if (CmtError::ok != code)
3827                      {
3828                        // restore error occurred before value expansion
3829                        CmtError::set (code,
3830                                       (msg.replace (n + ": ", cmt_string ("")), msg),
3831                                       exec_err);
3832                      }
3833                  }
3834                else if (CmtError::ok != code)
3835                  {
3836                    // print error occurred before value expansion
3837                    if (code != CmtError::warning)
3838                      CmtMessage::error (msg);
3839                    else
3840                      CmtMessage::warning (msg);
3841                  }
3842                // We keep CmtError::warning to indicate that
3843                // we could not resolve path
3844                // (without referencing the environment)
3845                // and strip path of non-existent directories
3846                //
3847                rvalue = value.text;
3848              }
3849          }
3850        else // (!pb->get_strip_path ())
3851          {
3852            if (CmtError::has_pending_error ())
3853              {
3854                code = CmtError::get_last_error_code ();
3855                msg = CmtError::get_last_error ();
3856                exec_err = CmtError::get_last_execution_error ();
3857                n = CmtError::get_error_name (code);
3858                CmtError::clear ();
3859              }
3860            resolve_value_for_macros (rvalue);
3861            if (CmtError::get_last_error_code () != CmtError::warning)
3862              {
3863                if (CmtError::has_pending_error ())
3864                  {
3865                    CmtError::print ();
3866                    CmtError::clear ();
3867                  }
3868                if (CmtError::ok != code)
3869                  {
3870                    // restore error occurred before value expansion
3871                    CmtError::set (code,
3872                                   (msg.replace (n + ": ", cmt_string ("")), msg),
3873                                   exec_err);
3874                  }
3875                if (CommandPath != command_type &&
3876                    rvalue.size () == 0)
3877                  return result;
3878              }
3879            else
3880              {
3881                if (CmtMessage::active (Verbose))
3882                  CmtError::print ();
3883                CmtError::clear ();
3884                if (CmtError::ok != code)
3885                  {
3886                    // restore error occurred before value expansion
3887                    CmtError::set (code,
3888                                   (msg.replace (n + ": ", cmt_string ("")), msg),
3889                                   exec_err);
3890                  }
3891                // Ignore the error, keep the value unresolved
3892                rvalue = value.text;
3893              }
3894          }
3895
3896        break;
3897    }
3898
3899  if (discarded) discarded_text = " (discarded by override)";
3900  else discarded_text = "";
3901
3902  if (first_definition) define_text = "defines";
3903  else define_text = "overrides";
3904
3905  if (CmtMessage::active (Verbose))
3906    out << "# Package " << (use ? use->get_package_name () + " " + use->version : "");
3907
3908  switch (command_type)
3909    {
3910      case CommandSet :
3911        if (CmtMessage::active (Verbose))
3912          out << " " << define_text << " set " << symbol.name << " as " << endl;
3913        //        out << " " << define_text << " set " << symbol.name << " as ";
3914        out << "set " << symbol.name;
3915        first_definition = false;
3916        result = 1;
3917        break;
3918      case CommandSetAppend :
3919        if (CmtMessage::active (Verbose))
3920          out << " appends to set " << symbol.name << " : " << endl;
3921        //        out << " appends to set " << symbol.name << " : ";
3922        out << "set_append " << symbol.name;
3923        result = 1;
3924        break;
3925      case CommandSetPrepend :
3926        if (CmtMessage::active (Verbose))
3927          out << " prepends to set " << symbol.name << " : " << endl;
3928        //        out << " prepends to set " << symbol.name << " : ";
3929        out << "set_prepend " << symbol.name;
3930        result = 1;
3931        break;
3932      case CommandSetRemove :
3933        if (CmtMessage::active (Verbose))
3934          out << " removes from set " << symbol.name << " : " << endl;
3935        //        out << " removes from set " << symbol.name << " : ";
3936        out << "set_remove " << symbol.name;
3937        result = 1;
3938        break;
3939      case CommandSetRemoveRegexp :
3940        if (CmtMessage::active (Verbose))
3941          out << " removes RE from set " << symbol.name << " : " << endl;
3942        //        out << " removes RE from set " << symbol.name << " : ";
3943        out << "set_remove_regexp " << symbol.name;
3944        result = 1;
3945        break;
3946      case CommandAlias :
3947        if (CmtMessage::active (Verbose))
3948          out << " " << define_text << " alias " << symbol.name << endl;
3949        //        out << " " << define_text << " alias " << symbol.name << " as ";
3950        out << "alias " << symbol.name;
3951        first_definition = false;
3952        result = 1;
3953        break;
3954    case CommandPath :
3955        if (CmtMessage::active (Verbose))
3956          out << " " << define_text << " path " << symbol.name << endl;
3957        //        out << " " << define_text << " path " << symbol.name << " as ";
3958        pb->filter_path_value (symbol, rvalue);
3959
3960        if (Cmt::get_debug ())
3961          {
3962            cerr << "|SymbolValueList::print> path " << symbol.name
3963                 << " " << value.text << " => " << rvalue << endl;
3964          }
3965
3966        out << "path " << symbol.name;
3967        first_definition = false;
3968        result = 1;
3969        break;
3970      case CommandPathAppend :
3971        if (CmtMessage::active (Verbose))
3972          out << " appends to path " << symbol.name << endl;
3973        //        out << " appends to path " << symbol.name << " : ";
3974        pb->filter_path_value (symbol, rvalue);
3975
3976        if (Cmt::get_debug ())
3977          {
3978            cerr << "|SymbolValueList::print> path_append " << symbol.name
3979                 << " " << value.text << " => " << rvalue << endl;
3980          }
3981
3982        if (rvalue.size () == 0) return result;
3983        out << "path_append " << symbol.name;
3984        result = 1;
3985        break;
3986      case CommandPathPrepend :
3987        if (CmtMessage::active (Verbose))
3988          out << " prepends to path " << symbol.name << " : " << endl;
3989        //        out << " prepends to path " << symbol.name << " : ";
3990        pb->filter_path_value (symbol, rvalue);
3991
3992        if (Cmt::get_debug ())
3993          {
3994            cerr << "|SymbolValueList::print> path_prepend " << symbol.name
3995                 << " " << value.text << " => " << rvalue << endl;
3996          }
3997
3998        if (rvalue.size () == 0) return result;
3999        out << "path_prepend " << symbol.name;
4000        result = 1;
4001        break;
4002      case CommandPathRemove :
4003        if (CmtMessage::active (Verbose))
4004          out << " removes from path " << symbol.name << " : " << endl;
4005        //        out << " removes from path " << symbol.name << " : ";
4006
4007        if (Cmt::get_debug ())
4008          {
4009            cerr << "|SymbolValueList::print> path_remove " << symbol.name
4010                 << " " << value.text << " => " << rvalue << endl;
4011          }
4012
4013        out << "path_remove " << symbol.name;
4014        result = 1;
4015        break;
4016      case CommandPathRemoveRegexp :
4017        if (CmtMessage::active (Verbose))
4018          out << " removes RE from path " << symbol.name << " : " << endl;
4019        //        out << " removes RE from path " << symbol.name << " : ";
4020
4021        if (Cmt::get_debug ())
4022          {
4023            cerr << "|SymbolValueList::print> path_remove_regexp " << symbol.name
4024                 << " " << value.text << " => " << rvalue << endl;
4025          }
4026
4027        out << "path_remove_regexp " << symbol.name;
4028        result = 1;
4029        break;
4030      case CommandMacro :
4031        if (CmtMessage::active (Verbose))
4032          out << " " << define_text << " macro " << symbol.name << " as " << endl;
4033        //        out << " " << define_text << " macro " << symbol.name << " as ";
4034        out << "macro " << symbol.name;
4035        result = 1;
4036        break;
4037      case CommandMacroPrepend :
4038        if (CmtMessage::active (Verbose))
4039          out << " prepends to macro " << symbol.name << " : " << endl;
4040        //        out << " prepends to macro " << symbol.name << " : ";
4041        out << "macro_prepend " << symbol.name;
4042        result = 1;
4043        break;
4044      case CommandMacroAppend :
4045        if (CmtMessage::active (Verbose))
4046          out << " appends to macro " << symbol.name << " : " << endl;
4047        //        out << " appends to macro " << symbol.name << " : ";
4048        out << "macro_append " << symbol.name;
4049        result = 1;
4050        break;
4051      case CommandMacroRemove :
4052        if (CmtMessage::active (Verbose))
4053          out << " remove from macro " << symbol.name << " : " << endl;
4054        //        out << " remove from macro " << symbol.name << " : ";
4055        out << "macro_remove " << symbol.name;
4056        result = 1;
4057        break;
4058      case CommandMacroRemoveRegexp :
4059        if (CmtMessage::active (Verbose))
4060          out << " remove RE from macro " << symbol.name << " : " << endl;
4061        //        out << " remove RE from macro " << symbol.name << " : ";
4062        out << "macro_remove_regexp " << symbol.name;
4063        result = 1;
4064        break;
4065      case CommandMacroRemoveAll :
4066        if (CmtMessage::active (Verbose))
4067          out << " remove all from macro " << symbol.name << " : " << endl;
4068        //        out << " remove all from macro " << symbol.name << " : ";
4069        out << "macro_remove_all " << symbol.name;
4070        result = 1;
4071        break;
4072      case CommandMacroRemoveAllRegexp :
4073        if (CmtMessage::active (Verbose))
4074          out << " remove all RE from macro " << symbol.name << " : " << endl;
4075        //        out << " remove all RE from macro " << symbol.name << " : ";
4076        out << "macro_remove_all_regexp " << symbol.name;
4077        result = 1;
4078        break;
4079      case CommandSetupScript :
4080        if (CmtMessage::active (Verbose))
4081          out << " " << define_text << " setup script " << symbol.name << endl;
4082        //       out << " " << define_text << " action " << symbol.name << " as ";
4083        out << "setup_script" /* << symbol.name */;
4084        first_definition = false;
4085        result = 1;
4086        break;
4087        /*
4088      case CommandAction :
4089        out << " " << define_text << " action " << symbol.name << " as ";
4090        first_definition = false;
4091        break;
4092        */
4093    }
4094
4095  out << " " << CmtSystem::quote (rvalue, " \t");
4096  //  out << " " << CmtSystem::quote (value.text, " \t");
4097  //  out << "'" << value.text << "'";
4098         
4099  /*
4100  Tag* selected_tag = value.tag;
4101         
4102  if ((selected_tag == 0) ||
4103      (selected_tag == Tag::get_default ()))
4104    {
4105      out << " for default tag";
4106    }
4107  else
4108    {
4109      out << " for tag '" << selected_tag->get_name () << "'";
4110    }
4111  */
4112
4113  out << endl;
4114  //  out << discarded_text << endl;
4115  return result;
4116}
4117
4118//-------------------------------------------------------------
4119bool Symbol::check_tag_used (const Tag* tag)
4120{
4121  if (tag == 0) return (false);
4122
4123  static SymbolVector& Symbols = symbols ();
4124
4125  if (Symbols.size () == 0) 
4126    {
4127      return (false);
4128    }
4129
4130  for (int number = 0; number < Symbol::symbol_number (); number++)
4131    {
4132      Symbol& symbol = Symbol::symbol (number);
4133
4134      for (int i = 0; i < symbol.value_lists.size (); i++)
4135        {
4136          const SymbolValueList& value_list = symbol.value_lists[i];
4137
4138          for (int j = 0; j < value_list.values.size (); j++)
4139            {
4140              const SymbolValue& value = value_list.values[j];
4141              Tag* t = value.tag;
4142
4143              if (t != 0)
4144                {
4145                  if (t->use_operand (tag)) return (true);
4146                }
4147            }
4148        }
4149    }
4150
4151  return (false);
4152}
4153
4154//-------------------------------------------------------------
4155cmt_string Symbol::get_env_value (const cmt_string& name)
4156{
4157  cmt_string s;
4158
4159  Symbol* symbol = Symbol::find (name);
4160  if (symbol != 0)
4161    {
4162      m_inhibit_display = true;
4163
4164      s = symbol->build_macro_value ();
4165      Symbol::expand (s);
4166
4167      m_inhibit_display = false;
4168    }
4169  else
4170    {
4171                if (Cmt::get_env_access () ||
4172                    Symbol::std_env_vars ().has (name))
4173                  {
4174      s = CmtSystem::getenv (name);
4175                    if (Cmt::get_debug ())
4176                      {
4177                        cerr << "Symbol::get_env_value> getenv (" << name
4178                             << ") => " << s << endl;
4179                      }
4180                  }
4181                else
4182                  {
4183                    if (Cmt::get_debug ())
4184                      {
4185                        cerr << "Symbol::get_env_value> getenv (" << name
4186                             << ") denied" << endl;
4187                      }
4188                    CmtError::set (CmtError::warning,
4189                                   "getenv (" + name + ") denied");
4190                    return (s);
4191                  }
4192    }
4193
4194  return (s);
4195}
4196
4197bool Symbol::get_inhibit_display ()
4198{
4199  return (m_inhibit_display);
4200}
4201
Note: See TracBrowser for help on using the repository browser.