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

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

See C.L. 522

  • Property svn:eol-style set to native
File size: 104.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            else if (temp == "")
2373              {
2374                if (Cmt::get_env_access () ||
2375                    Symbol::std_env_vars ().has (symbol.name))
2376                  {
2377                    temp = CmtSystem::getenv (symbol.name);
2378                    if (Cmt::get_debug ())
2379                      {
2380                        cerr << "SetBuilder::build> getenv (" << symbol.name
2381                             << ") => " << temp << endl;
2382                      }
2383                  }
2384                else
2385                  {
2386                    if (Cmt::get_debug ())
2387                      {
2388                        cerr << "SetBuilder::build> getenv (" << symbol.name
2389                             << ") denied" << endl;
2390                      }
2391                    CmtError::set (CmtError::warning,
2392                                   "getenv (" + symbol.name + ") denied");
2393                    return "";
2394                  }
2395              }
2396
2397            break;
2398          case CommandSetAppend :
2399           
2400            if (new_value != "")
2401              {
2402                temp += new_value;
2403              }
2404           
2405            break;
2406          case CommandSetPrepend :
2407           
2408            if (new_value != "")
2409              {
2410                previous_temp = temp;
2411                temp = new_value;
2412                temp += previous_temp;
2413              }
2414           
2415            break;
2416          case CommandSetRemove :
2417           
2418            if (new_value != "")
2419              {
2420                temp.replace_all (new_value, empty);
2421              }
2422           
2423            break;
2424          case CommandSetRemoveRegexp :
2425           
2426            if (new_value != "")
2427              {
2428                cmt_regexp e (new_value);
2429                cmt_regexp::iterator it;
2430
2431                for (;;)
2432                  {
2433                    it = e.begin (temp);
2434                    if (it == e.end ()) break;
2435
2436                    temp.erase (it._pos, it._length);
2437                  }
2438              }
2439           
2440            break;
2441          case CommandAlias :
2442           
2443            resolve_value (new_value, symbol.name, temp);
2444            temp = new_value;
2445           
2446            break;
2447        }
2448    }
2449
2450  level--;
2451
2452  return (temp);
2453}
2454
2455namespace
2456{
2457int find_path_entry (const CmtSystem::cmt_string_vector& items, const cmt_string& value)
2458{
2459  //  if (value.size () == 0) return true;
2460 
2461  static cmt_vmap <cmt_string, cmt_string> realpaths;
2462
2463  cmt_string rvalue;
2464  const cmt_string * prvalue;
2465
2466  if (!(prvalue = realpaths.find (value)))
2467    {
2468      // if (!CmtSystem::realpath_ (value, rvalue))
2469      //{
2470          rvalue = value;
2471          CmtSystem::compress_path (rvalue);
2472      //}
2473      prvalue = &rvalue;
2474      realpaths.add (value, rvalue);
2475      //      cerr << "realpaths.add: " << value << " , " << rvalue << endl;
2476    }
2477
2478  for (int i = 0; i < items.size (); i++)
2479    {
2480      const cmt_string& item = items[i];
2481      if (item.size () == 0) continue;
2482      cmt_string ritem;
2483      const cmt_string * pritem;
2484
2485      if (!(pritem = realpaths.find (item)))
2486        {
2487          //if (!CmtSystem::realpath_ (item, ritem))
2488          //{
2489              ritem = item;
2490              CmtSystem::compress_path (ritem);
2491          //}
2492          pritem = &ritem;
2493          realpaths.add (item, ritem);
2494          //  cerr << "realpaths.add: " << item << " , " << ritem << endl;
2495        }
2496      if (*pritem == *prvalue)
2497        {
2498          return i;
2499        }
2500    }
2501
2502  return -1;
2503}
2504
2505}
2506/*
2507static bool find_path_entry (const CmtSystem::cmt_string_vector& items, const cmt_string& value)
2508{
2509  if (value.size () == 0) return true;
2510
2511  static cmt_vmap <cmt_string, cmt_string> realpaths;
2512
2513  cmt_string rvalue;
2514  const cmt_string * prvalue;
2515
2516  if (!(prvalue = realpaths.find (value)))
2517    {
2518      // if (!CmtSystem::realpath_ (value, rvalue))
2519      //{
2520          rvalue = value;
2521          CmtSystem::compress_path (rvalue);
2522      //}
2523      prvalue = &rvalue;
2524      realpaths.add (value, rvalue);
2525      //      cerr << "realpaths.add: " << value << " , " << rvalue << endl;
2526    }
2527
2528  for (int i = 0; i < items.size (); i++)
2529    {
2530      const cmt_string& item = items[i];
2531      if (item.size () == 0) continue;
2532      cmt_string ritem;
2533      const cmt_string * pritem;
2534
2535      if (!(pritem = realpaths.find (item)))
2536        {
2537          //if (!CmtSystem::realpath_ (item, ritem))
2538          //{
2539              ritem = item;
2540              CmtSystem::compress_path (ritem);
2541          //}
2542          pritem = &ritem;
2543          realpaths.add (item, ritem);
2544          //  cerr << "realpaths.add: " << item << " , " << ritem << endl;
2545        }
2546      if (*pritem == *prvalue)
2547        {
2548          return true;
2549        }
2550    }
2551
2552  return false;
2553}
2554*/
2555/*
2556static bool find_path_entry (const cmt_string& paths, const cmt_string& value)
2557{
2558  static const cmt_string path_separator = CmtSystem::path_separator ();
2559  static cmt_vmap <cmt_string, cmt_string> realpaths;
2560
2561  cmt_string rvalue;
2562  const cmt_string * prvalue;
2563
2564  if (!(prvalue = realpaths.find (value)))
2565    {
2566      if (!CmtSystem::realpath_ (value, rvalue))
2567        {
2568          rvalue = value;
2569          CmtSystem::compress_path (rvalue);
2570        }
2571      prvalue = &rvalue;
2572      realpaths.add (value, rvalue);
2573      //      cerr << "realpaths.add: " << value << " , " << rvalue << endl;
2574    }
2575
2576  CmtSystem::cmt_string_vector items;
2577  CmtSystem::split (paths, path_separator, items);
2578
2579  bool found = false;
2580
2581  for (int i = 0; i < items.size (); i++)
2582    {
2583      const cmt_string& item = items[i];
2584      cmt_string ritem;
2585      const cmt_string * pritem;
2586
2587      if (!(pritem = realpaths.find (item)))
2588        {
2589          if (!CmtSystem::realpath_ (item, ritem))
2590            {
2591              ritem = item;
2592              CmtSystem::compress_path (ritem);
2593            }
2594          pritem = &ritem;
2595          realpaths.add (item, ritem);
2596          //  cerr << "realpaths.add: " << item << " , " << ritem << endl;
2597        }
2598      if (*pritem == *prvalue)
2599        {
2600          found = true;
2601          break;
2602        }
2603    }
2604
2605  return (found);
2606}
2607*/
2608//-------------------------------------------------------------
2609PathBuilder* PathBuilder::get_path_builder ()
2610{
2611  static PathBuilder Path (Cmt::get_strip_path ());
2612  return &Path;
2613}
2614
2615//-------------------------------------------------------------
2616PathBuilder::PathBuilder ()
2617  : m_strip_path (false)
2618{
2619}
2620
2621//-------------------------------------------------------------
2622PathBuilder::PathBuilder (bool strip_path)
2623{
2624  PathBuilder ();
2625  m_strip_path = strip_path;
2626}
2627
2628//-------------------------------------------------------------
2629const cmt_string PathBuilder::build (const Symbol& symbol,
2630                                     const cmt_string& /*tag_name*/)
2631{
2632    // Control of recursivity
2633  static int level = 0;
2634
2635  bool show_it = false;
2636
2637  cmt_string temp;
2638  CmtSystem::cmt_string_vector temp_vector;
2639  //  cmt_string previous_temp;
2640  CmtSystem::cmt_string_vector new_value_vector;
2641  cmt_string new_value;
2642  static const cmt_string empty;
2643
2644  static cmt_string path_separator = CmtSystem::path_separator ();
2645
2646  ActionType action = Cmt::get_action ();
2647
2648  if (action == action_show_set)
2649    {
2650      if (symbol.name == Cmt::get_current_target ())
2651        {
2652            // Should not display on recursive calls
2653          if (level == 0) show_it = m_display_it;
2654        }
2655    }
2656
2657  level++;
2658
2659                if (Cmt::get_env_access () ||
2660                    Symbol::std_env_vars ().has (symbol.name))
2661                  {
2662  //temp = CmtSystem::getenv (symbol.name);
2663  CmtSystem::split (CmtSystem::getenv (symbol.name), path_separator, temp_vector);
2664  filter_path_value (symbol, temp_vector);
2665                    if (Cmt::get_debug ())
2666                      {
2667                        cmt_string temp_txt;
2668                        Cmt::vector_to_string (temp_vector, path_separator, temp_txt);
2669                        cerr << "PathBuilder::build> getenv (" << symbol.name
2670                             << ") => " << temp_txt << endl;
2671                      }
2672                  }
2673                else
2674                  {
2675                    if (Cmt::get_debug ())
2676                      {
2677                        cerr << "PathBuilder::build> getenv (" << symbol.name
2678                             << ") denied" << endl;
2679                      }
2680                    CmtError::set (CmtError::warning,
2681                                   "getenv (" + symbol.name + ") denied");
2682                    return "";
2683                  }
2684
2685  bool first_definition = true;
2686
2687  for (int i = 0; i < symbol.value_lists.size (); i++)
2688    {
2689      const SymbolValueList& value_list = symbol.value_lists[i];
2690
2691      if ((value_list.use != 0) &&
2692          (value_list.use->discarded)) continue;
2693
2694      const int selected = value_list.select_first ();
2695     
2696      if (selected < 0) continue;
2697 
2698      SymbolValue& value = value_list.values[selected];
2699         
2700      if (show_it && !Symbol::get_inhibit_display())
2701        {
2702          value_list.show (symbol, value, first_definition);
2703        }
2704         
2705      if (value_list.discarded) continue;
2706
2707      new_value = value.text;
2708         
2709          //resolve_value (new_value);
2710      resolve_value_for_macros (new_value);
2711         
2712      switch (value_list.command_type)
2713        {
2714          case CommandPath :
2715           
2716            if (!value_list.is_reflexive || 
2717                !symbol.value_is_reflexive (value.text))
2718              {
2719                Cmt::vector_to_string (temp_vector, path_separator, temp);
2720                resolve_value (new_value, symbol.name, temp);
2721                CmtSystem::split (new_value, path_separator, temp_vector);
2722                //temp = new_value;
2723                filter_path_value (symbol, temp_vector);
2724              }
2725
2726            break;
2727          case CommandPathAppend :
2728             
2729            if (new_value != "")
2730              {
2731                CmtSystem::split (new_value, path_separator, new_value_vector);
2732                for (int i = 0; i < new_value_vector.size (); i++)
2733                  {
2734                    if (new_value_vector[i].size () == 0) continue;
2735                    int j = find_path_entry (temp_vector, new_value_vector[i]);
2736                    if (j < 0)
2737                      {
2738                        temp_vector.push_back (new_value_vector[i]);
2739                      }
2740                    else if (j < temp_vector.size () - 1)
2741                      {
2742                        temp_vector [j] = "";
2743                        temp_vector.push_back (new_value_vector[i]);
2744                      }
2745                  }
2746              }
2747                 
2748            break;
2749          case CommandPathPrepend :
2750             
2751            if (new_value != "")
2752              {
2753                CmtSystem::split (new_value, path_separator, new_value_vector);
2754                int n (new_value_vector.size ());
2755                temp_vector.resize (temp_vector.size () + n);
2756                for (int i = temp_vector.size () - 1; i > n - 1; i--)
2757                  temp_vector [i] = temp_vector [i - n];
2758                for (int i = 0; i < n; i++)
2759                  temp_vector [i] = "";
2760                for (int i = 0; i < new_value_vector.size (); i++)
2761                  {
2762                    if (new_value_vector[i].size () == 0) continue;
2763                    int j = find_path_entry (temp_vector, new_value_vector[i]);
2764                    if (j < 0)
2765                      {
2766                        temp_vector [i] = new_value_vector[i];
2767                      }
2768                    else if (j >= n)
2769                      {
2770                        temp_vector [i] = new_value_vector[i];
2771                        temp_vector [j] = "";
2772                      }
2773                  }
2774              }
2775           
2776            break;
2777          case CommandPathRemove :
2778             
2779            if (new_value != "")
2780              {
2781                for (int j = 0; j < temp_vector.size (); ++j)
2782                  {
2783                    cmt_string& s = temp_vector[j];
2784                   
2785                    if (s.find (new_value) != cmt_string::npos)
2786                      {
2787                        s = "";
2788                      }
2789                  }
2790                /*
2791                CmtSystem::cmt_string_vector paths;
2792                 
2793                CmtSystem::split (temp, path_separator, paths);
2794                 
2795                for (int j = 0; j < paths.size (); ++j)
2796                  {
2797                    cmt_string& s = paths[j];
2798                     
2799                    if (s.find (new_value) != cmt_string::npos)
2800                      {
2801                        s = "";
2802                      }
2803                  }
2804
2805                Cmt::vector_to_string (paths, path_separator, temp);
2806                */
2807              }
2808             
2809            break;
2810          case CommandPathRemoveRegexp :
2811
2812            if (new_value != "")
2813              {
2814                cmt_regexp e (new_value);
2815
2816                for (int j = 0; j < temp_vector.size (); ++j)
2817                  {
2818                    cmt_string& s = temp_vector[j];
2819
2820                    if (Cmt::get_debug () &&
2821                        CmtSystem::getenv ("TESTPRR") != "")
2822                      {
2823                        cerr << "PRR> s=[" << s << "]";
2824                      }
2825
2826                    if (e.match (s))
2827                      {
2828                        s = "";
2829
2830                        if (Cmt::get_debug () &&
2831                            CmtSystem::getenv ("TESTPRR") != "")
2832                          {
2833                            cerr << " match ";
2834                          }
2835                      }
2836                    else
2837                      {
2838                        if (Cmt::get_debug () &&
2839                            CmtSystem::getenv ("TESTPRR") != "")
2840                          {
2841                            cerr << " no match ";
2842                          }
2843                      }
2844
2845                    if (Cmt::get_debug () &&
2846                        CmtSystem::getenv ("TESTPRR") != "")
2847                      {
2848                        cerr << endl;
2849                      }
2850                  }
2851
2852                /*
2853                CmtSystem::cmt_string_vector paths;
2854                 
2855                CmtSystem::split (temp, path_separator, paths);
2856                 
2857                for (int j = 0; j < paths.size (); ++j)
2858                  {
2859                    cmt_string& s = paths[j];
2860
2861                    if (CmtSystem::getenv ("TESTPRR") != "")
2862                      {
2863                        cerr << "PRR> s=[" << s << "]";
2864                      }
2865
2866                    if (e.match (s))
2867                      {
2868                        s = "";
2869
2870                        if (CmtSystem::getenv ("TESTPRR") != "")
2871                          {
2872                            cerr << " match ";
2873                          }
2874                      }
2875                    else
2876                      {
2877                        if (CmtSystem::getenv ("TESTPRR") != "")
2878                          {
2879                            cerr << " no match ";
2880                          }
2881                      }
2882
2883                    if (CmtSystem::getenv ("TESTPRR") != "")
2884                      {
2885                        cerr << endl;
2886                      }
2887                  }
2888
2889                Cmt::vector_to_string (paths, path_separator, temp);
2890                */
2891              }
2892             
2893            break;
2894        }
2895
2896    }
2897
2898  Cmt::vector_to_string (temp_vector, path_separator, temp);
2899
2900  level--;
2901  /*
2902  for (;;)
2903    {
2904      int sz = temp.size ();
2905
2906      if (sz == 0) break;
2907
2908      if ((temp[0] == ';') || (temp[0] == ':'))
2909        {
2910          temp.erase (0, 1);
2911        }
2912      else if ((temp[sz-1] == ';') || (temp[sz-1] == ':'))
2913        {
2914          temp.erase (sz-1, 1);
2915        }
2916      else
2917        {
2918          break;
2919        }
2920    }
2921
2922  temp.replace_all ("::", ":");
2923  temp.replace_all (";;", ";");
2924  */
2925  return (temp);
2926}
2927
2928//-------------------------------------------------------------
2929const cmt_string PathBuilder::clean (const Symbol& symbol,
2930                                     const cmt_string& /*tag_name*/)
2931{
2932    // Control of recursivity
2933  static int level = 0;
2934
2935  cmt_string temp;
2936  cmt_string new_value;
2937  static const cmt_string empty;
2938
2939  static cmt_string path_separator = CmtSystem::path_separator ();
2940
2941  temp = CmtSystem::getenv (symbol.name);
2942
2943    //cerr << "#####1 temp=" << temp << endl;
2944
2945  for (int i = 0; i < symbol.value_lists.size (); i++)
2946    {
2947      const SymbolValueList& value_list = symbol.value_lists[i];
2948
2949      if (value_list.discarded) continue;
2950
2951      if ((value_list.use != 0) &&
2952          (value_list.use->discarded)) continue;
2953
2954      const int selected = value_list.select_first ();
2955     
2956      if (selected < 0) continue;
2957 
2958      SymbolValue& value = value_list.values[selected];
2959         
2960      new_value = value.text;
2961         
2962          //resolve_value (new_value);
2963
2964        //cerr << "#####1 new_value=" << new_value << endl;
2965
2966      resolve_value_for_macros (new_value);
2967      resolve_value (new_value);
2968         
2969        //cerr << "#####2 new_value=" << new_value << endl;
2970
2971      switch (value_list.command_type)
2972        {
2973          case CommandPath :
2974           
2975            temp = "";
2976           
2977            break;
2978          case CommandPathAppend :
2979          case CommandPathPrepend :
2980          case CommandPathRemove :
2981
2982            if (new_value != "")
2983              {
2984                CmtSystem::cmt_string_vector paths;
2985                 
2986                CmtSystem::split (temp, path_separator, paths);
2987                 
2988                for (int j = 0; j < paths.size (); ++j)
2989                  {
2990                    cmt_string& s = paths[j];
2991                     
2992                    if (s.find (new_value) != cmt_string::npos)
2993                      {
2994                        s = "";
2995                      }
2996
2997                    if (j > 0)
2998                      {
2999                        cmt_string& s2 = paths[j-1];
3000                        if (s2 == s)
3001                          {
3002                            s2 = "";
3003                          }
3004                      }
3005                  }
3006
3007                Cmt::vector_to_string (paths, path_separator, temp);
3008                temp.replace_all ("::", ":");
3009                temp.replace_all (";;", ";");
3010              }
3011             
3012            break;
3013          case CommandPathRemoveRegexp :
3014
3015            if (new_value != "")
3016              {
3017                cmt_regexp e (new_value);
3018
3019                CmtSystem::cmt_string_vector paths;
3020                 
3021                CmtSystem::split (temp, path_separator, paths);
3022                 
3023                for (int j = 0; j < paths.size (); ++j)
3024                  {
3025                    cmt_string& s = paths[j];
3026                     
3027                    if (e.match (s))
3028                      {
3029                        s = "";
3030                      }
3031
3032                    if (j > 0)
3033                      {
3034                        cmt_string& s2 = paths[j-1];
3035                        if (s2 == s)
3036                          {
3037                            s2 = "";
3038                          }
3039                      }
3040                  }
3041
3042                Cmt::vector_to_string (paths, path_separator, temp);
3043                temp.replace_all ("::", ":");
3044                temp.replace_all (";;", ";");
3045              }
3046             
3047            break;
3048        }
3049    }
3050
3051    //cerr << "#####2 temp=" << temp << endl;
3052 
3053  return (temp);
3054}
3055
3056//-------------------------------------------------------------
3057void PathBuilder::filter_path_value (const Symbol& symbol,
3058                                     CmtSystem::cmt_string_vector& value,
3059                                     const cmt_string& /* tag_name */) const
3060{
3061  static cmt_regexp reg ("[$%`]");
3062
3063  cmt_vector<int> path (value.size ());
3064  int n (0);
3065
3066  for (int j = 0; j < value.size (); j++)
3067    {
3068      const cmt_string& v = value[j];
3069      bool exists (false); 
3070      for (int i = 0; i < j; i++)
3071        {
3072          if (value[i] == v)
3073            {
3074              exists = true;
3075              break;
3076            }
3077        }                 
3078      if (!exists)
3079        {
3080          if (m_strip_path)
3081            {
3082              if (!reg.match (v))
3083                {
3084                  if (!CmtSystem::test_directory (v))
3085                    {
3086                      CmtMessage::verbose ("Non-existent directory " + v + " in " + symbol.name + " skipped");
3087                      continue;
3088                    }
3089                }
3090              else
3091                {
3092                  if (CmtMessage::active (Verbose))
3093                    {
3094                      CmtMessage::warning ("Unresolved directory name " + v + " in " + symbol.name);
3095                    }
3096                }
3097            }
3098          else
3099            {
3100              if (CmtMessage::active (Verbose))
3101                if (!reg.match (v) &&
3102                    !CmtSystem::test_directory (v))
3103                  {
3104                    CmtMessage::warning ("Non-existent directory " + v + " in " + symbol.name);
3105                  }
3106            }
3107          path[n++] = j;
3108        }
3109    }
3110
3111  for (int i = 0; i < n; i++)
3112    if (i != path[i]) value[i] = value[path[i]];
3113 
3114  value.resize (n);
3115}
3116
3117//-------------------------------------------------------------
3118void PathBuilder::filter_path_value (const Symbol& symbol,
3119                                     cmt_string& value,
3120                                     const cmt_string& tag_name) const
3121{
3122  static cmt_string ps (CmtSystem::path_separator ());
3123  CmtSystem::cmt_string_vector paths;
3124
3125  CmtSystem::split (value, ps, paths);
3126  filter_path_value (symbol, paths, tag_name);
3127  Cmt::vector_to_string (paths, ps, value);
3128}
3129
3130//-------------------------------------------------------------
3131inline const bool& PathBuilder::get_strip_path () const
3132{
3133  return m_strip_path;
3134}
3135
3136//-------------------------------------------------------------
3137inline void PathBuilder::set_strip_path (const bool& strip_path)
3138{
3139  m_strip_path = strip_path;
3140}
3141
3142//-------------------------------------------------------------
3143const cmt_string MacroBuilder::build (const Symbol& symbol,
3144                                      const cmt_string& tag_name)
3145{
3146    // Control of recursivity
3147  static int level = 0;
3148
3149  cmt_string temp;
3150  cmt_string previous_temp;
3151  static const cmt_string empty;
3152  bool show_it = false;
3153
3154  ActionType action = Cmt::get_action ();
3155
3156  if (action == action_show_macro)
3157    {
3158      if (symbol.name == Cmt::get_current_target ())
3159        {
3160             // Should not display on recursive calls
3161          if (level == 0) show_it = m_display_it;
3162        }
3163    }
3164
3165  level++;
3166
3167  temp = "";
3168
3169  int i;
3170
3171  bool first_definition = true;
3172
3173  for (i = 0; i < symbol.value_lists.size (); i++)
3174    {
3175      const SymbolValueList& value_list = symbol.value_lists[i];
3176
3177      if ((value_list.use != 0) &&
3178          (value_list.use->discarded)) continue;
3179
3180      if (value_list.command_type != CommandMacroPrepend) continue;
3181
3182      const int selected = value_list.select_first (tag_name);
3183
3184      if (selected < 0) continue;
3185
3186      SymbolValue& value = value_list.values[selected];
3187
3188      if (show_it && !Symbol::get_inhibit_display())
3189        {
3190          value_list.show (symbol, value, first_definition);
3191        }
3192
3193      if (value_list.discarded) continue;
3194
3195      previous_temp = temp;
3196      temp = value.text;
3197      temp += previous_temp;
3198    }
3199
3200  previous_temp = temp;
3201  temp = "";
3202
3203  first_definition = true;
3204
3205  for (i = 0; i < symbol.value_lists.size (); i++)
3206    {
3207      const SymbolValueList& value_list = symbol.value_lists[i];
3208
3209      if ((value_list.use != 0) &&
3210          (value_list.use->discarded)) continue;
3211
3212      if (value_list.command_type != CommandMacro) continue;
3213
3214      const int selected = value_list.select_first (tag_name);
3215
3216      if (selected < 0) continue;
3217
3218      SymbolValue& value = value_list.values[selected];
3219
3220      if (show_it && !Symbol::get_inhibit_display())
3221        {
3222          value_list.show (symbol, value, first_definition);
3223        }
3224
3225      // WARNING:
3226      // Commented just for a test : should be uncommented after the test
3227      if (value_list.discarded) continue;
3228     
3229      if (!value_list.is_reflexive || 
3230          !symbol.value_is_reflexive (value.text))
3231        {
3232          temp = value.text;
3233        }
3234    }
3235
3236  previous_temp += temp;
3237  temp = previous_temp;
3238
3239  for (i = 0; i < symbol.value_lists.size (); i++)
3240    {
3241      const SymbolValueList& value_list = symbol.value_lists[i];
3242
3243      if ((value_list.use != 0) &&
3244          (value_list.use->discarded)) continue;
3245
3246      if (value_list.command_type != CommandMacroAppend) continue;
3247
3248      const int selected = value_list.select_first (tag_name);
3249
3250      if (selected < 0) continue;
3251
3252      SymbolValue& value = value_list.values[selected];
3253
3254      if (show_it && !Symbol::get_inhibit_display())
3255        {
3256          value_list.show (symbol, value, first_definition);
3257        }
3258
3259      if (value_list.discarded) continue;
3260
3261      temp += value.text;
3262    }
3263
3264  for (i = 0; i < symbol.value_lists.size (); i++)
3265    {
3266      const SymbolValueList& value_list = symbol.value_lists[i];
3267
3268      if ((value_list.use != 0) &&
3269          (value_list.use->discarded)) continue;
3270
3271      if ((value_list.command_type != CommandMacroRemove) &&
3272          (value_list.command_type != CommandMacroRemoveRegexp) &&
3273          (value_list.command_type != CommandMacroRemoveAll) &&
3274          (value_list.command_type != CommandMacroRemoveAllRegexp)) continue;
3275
3276      const int selected = value_list.select_first (tag_name);
3277
3278      if (selected < 0) continue;
3279
3280      SymbolValue& value = value_list.values[selected];
3281
3282      if (show_it && !Symbol::get_inhibit_display())
3283        {
3284          value_list.show (symbol, value, first_definition);
3285        }
3286
3287      if (value_list.discarded) continue;
3288
3289      switch (value_list.command_type)
3290        {
3291          case CommandMacroRemove :
3292            temp.replace (value.text, empty);
3293            break;
3294          case CommandMacroRemoveRegexp :
3295            if (value.text != "")
3296              {
3297                cmt_regexp e (value.text);
3298                cmt_regexp::iterator it;
3299
3300                it = e.begin (temp);
3301                if (it != e.end ())
3302                  {
3303                    temp.erase (it._pos, it._length);
3304                  }
3305              }
3306            break;
3307          case CommandMacroRemoveAll :
3308            temp.replace_all (value.text, empty);
3309            break;
3310          case CommandMacroRemoveAllRegexp :
3311            if (value.text != "")
3312              {
3313                cmt_regexp e (value.text);
3314                cmt_regexp::iterator it;
3315
3316                for (;;)
3317                  {
3318                    it = e.begin (temp);
3319                    if (it != e.end ())
3320                      {
3321                        temp.erase (it._pos, it._length);
3322                      }
3323                    else
3324                      {
3325                        break;
3326                      }
3327                  }
3328              }
3329            break;
3330        }
3331    }
3332
3333  level--;
3334
3335  return (temp);
3336}
3337
3338//-------------------------------------------------------------
3339const cmt_string ScriptBuilder::build (const Symbol& symbol,
3340                                       const cmt_string& tag_name)
3341{
3342    // Control of recursivity
3343  static int level = 0;
3344
3345  static const cmt_string empty = "";
3346
3347  if (symbol.value_lists.size () > 0)
3348    {
3349      const SymbolValueList& value_list = symbol.value_lists[0];
3350
3351      if (value_list.discarded) return (empty);
3352
3353      if ((value_list.use != 0) &&
3354          (value_list.use->discarded)) return (empty);
3355    }
3356
3357  return (symbol.name);
3358}
3359
3360//-------------------------------------------------------------
3361const cmt_string ActionBuilder::build (const Symbol& symbol,
3362                                       const cmt_string& tag_name)
3363{
3364    // Control of recursivity
3365  static int level = 0;
3366
3367  cmt_string temp;
3368  cmt_string previous_temp;
3369  static const cmt_string empty;
3370  bool show_it = false;
3371
3372  ActionType action = Cmt::get_action ();
3373
3374  if (action == action_show_action)
3375    {
3376      if (symbol.name == Cmt::get_current_target ())
3377        {
3378             // Should not display on recursive calls
3379          if (level == 0) show_it = m_display_it;
3380        }
3381    }
3382
3383  level++;
3384
3385  int i;
3386
3387  bool first_definition = true;
3388
3389  temp = "";
3390
3391  for (i = 0; i < symbol.value_lists.size (); i++)
3392    {
3393      const SymbolValueList& value_list = symbol.value_lists[i];
3394
3395      if ((value_list.use != 0) &&
3396          (value_list.use->discarded)) continue;
3397
3398      if (value_list.command_type != CommandAction) continue;
3399
3400      const int selected = value_list.select_first (tag_name);
3401
3402      if (selected < 0) continue;
3403
3404      SymbolValue& value = value_list.values[selected];
3405
3406      if (show_it && !Symbol::get_inhibit_display())
3407        {
3408          value_list.show (symbol, value, first_definition);
3409        }
3410
3411      // WARNING:
3412      // Commented just for a test : should be uncommented after the test
3413      if (value_list.discarded) continue;
3414     
3415      if (!value_list.is_reflexive || 
3416          !symbol.value_is_reflexive (value.text))
3417        {
3418          temp = value.text;
3419        }
3420    }
3421
3422  level--;
3423
3424  return (temp);
3425}
3426
3427//-------------------------------------------------------------
3428int SymbolValueList::select_first (const cmt_string& tag_name) const
3429{
3430  int priority = 0;
3431  int value_number;
3432  int selected = -1;
3433
3434  Tag* the_tag = 0;
3435
3436  if (tag_name != "") the_tag = Tag::find (tag_name);
3437
3438  for (value_number = 0;
3439       value_number < values.size ();
3440       value_number++)
3441    {
3442      const SymbolValue& value = values[value_number];
3443
3444      const Tag* tag = value.tag;
3445
3446      if (the_tag == 0)
3447        {
3448          if (!tag->is_selected ()) continue;
3449          selected = value_number;
3450          if (tag == Tag::get_default ())
3451            continue;
3452        }
3453      else
3454        {
3455          if (tag != the_tag) continue;
3456          selected = value_number;
3457        }
3458
3459      //
3460      // Only the value for the first alternative (i.e. non-default)
3461      // matching tag expression is
3462      // selected (which means the selection stops here)
3463      //
3464      break;
3465
3466      //
3467      // Only the first value at a given priority is
3468      // selected (which implies the '>' test instead
3469      // of '>=')
3470      //
3471      /*
3472      if (tag->get_priority () > priority)
3473        {
3474          priority = tag->get_priority ();
3475          selected = value_number;
3476        }
3477      */
3478    }
3479
3480  return (selected);
3481}
3482
3483//-------------------------------------------------------------
3484int SymbolValueList::select_last () const
3485{
3486  int priority = 0;
3487  int value_number;
3488  int selected = -1;
3489
3490  for (value_number = 0;
3491       value_number < values.size ();
3492       value_number++)
3493    {
3494      SymbolValue& value = values[value_number];
3495
3496      const Tag* tag = value.tag;
3497
3498      if (tag->is_selected ())
3499        {
3500          //
3501          // The last value at a given priority is
3502          // selected (which implies the '>=' test instead
3503          // of '>')
3504          //
3505
3506          if (tag->get_priority () >= priority)
3507            {
3508              priority = tag->get_priority ();
3509              selected = value_number;
3510            }
3511        }
3512    }
3513
3514  return (selected);
3515}
3516
3517//-------------------------------------------------------------
3518void SymbolValueList::show (const Symbol& symbol, 
3519                            const SymbolValue& value, 
3520                            bool& first_definition) const
3521{
3522  cmt_string discarded_text;
3523  cmt_string define_text;
3524  ActionType action = Cmt::get_action ();
3525
3526  switch (command_type)
3527    {
3528      //case CommandSet :
3529      case CommandSetAppend :
3530      case CommandSetPrepend :
3531      case CommandSetRemove :
3532      case CommandSetRemoveRegexp :
3533        //case CommandAlias :
3534        //case CommandPath :
3535      case CommandPathAppend :
3536      case CommandPathPrepend :
3537      case CommandPathRemove :
3538      case CommandPathRemoveRegexp :
3539      case CommandMacroPrepend :
3540        //case CommandMacro :
3541      case CommandMacroAppend :
3542      case CommandMacroRemove :
3543      case CommandMacroRemoveRegexp :
3544      case CommandMacroRemoveAll :
3545      case CommandMacroRemoveAllRegexp :
3546        //case CommandAction :
3547        if (value.text == "") return;
3548        break;
3549    }
3550
3551  if (discarded) discarded_text = " (discarded by override)";
3552  else discarded_text = "";
3553
3554  if (first_definition) define_text = "defines";
3555  else define_text = "overrides";
3556
3557  cout << "# Package ";
3558  if (use != 0)
3559    {
3560      cout << use->get_package_name () << " " << use->version;
3561    }
3562
3563  switch (command_type)
3564    {
3565      case CommandSet :
3566        cout << " " << define_text << " set " << symbol.name << " as ";
3567        first_definition = false;
3568        break;
3569      case CommandSetAppend :
3570        cout << " appends to set " << symbol.name << " : ";
3571        break;
3572      case CommandSetPrepend :
3573        cout << " prepends to set " << symbol.name << " : ";
3574        break;
3575      case CommandSetRemove :
3576        cout << " removes from set " << symbol.name << " : ";
3577        break;
3578      case CommandSetRemoveRegexp :
3579        cout << " removes RE from set " << symbol.name << " : ";
3580        break;
3581      case CommandAlias :
3582        cout << " " << define_text << " alias " << symbol.name << " as ";
3583        first_definition = false;
3584        break;
3585      case CommandPath :
3586        cout << " " << define_text << " path " << symbol.name << " as ";
3587        first_definition = false;
3588        break;
3589      case CommandPathAppend :
3590        cout << " appends to path " << symbol.name << " : ";
3591        break;
3592      case CommandPathPrepend :
3593        cout << " prepends to path " << symbol.name << " : ";
3594        break;
3595      case CommandPathRemove :
3596        cout << " removes from path " << symbol.name << " : ";
3597        break;
3598      case CommandPathRemoveRegexp :
3599        cout << " removes RE from path " << symbol.name << " : ";
3600        break;
3601      case CommandMacroPrepend :
3602        cout << " prepends to macro " << symbol.name << " : ";
3603        break;
3604      case CommandMacro :
3605        cout << " " << define_text << " macro " << symbol.name << " as ";
3606        break;
3607      case CommandMacroAppend :
3608        cout << " appends to macro " << symbol.name << " : ";
3609        break;
3610      case CommandMacroRemove :
3611        cout << " remove from macro " << symbol.name << " : ";
3612        break;
3613      case CommandMacroRemoveRegexp :
3614        cout << " remove RE from macro " << symbol.name << " : ";
3615        break;
3616      case CommandMacroRemoveAll :
3617        cout << " remove all from macro " << symbol.name << " : ";
3618        break;
3619      case CommandMacroRemoveAllRegexp :
3620        cout << " remove all RE from macro " << symbol.name << " : ";
3621        break;
3622      case CommandAction :
3623        cout << " " << define_text << " action " << symbol.name << " as ";
3624        first_definition = false;
3625        break;
3626    }
3627
3628  cout << "'" << value.text << "'";
3629         
3630  Tag* selected_tag = value.tag;
3631         
3632  if ((selected_tag == 0) ||
3633      (selected_tag == Tag::get_default ()))
3634    {
3635      cout << " for default tag";
3636    }
3637  else
3638    {
3639      cout << " for tag '" << selected_tag->get_name () << "'";
3640    }
3641 
3642  cout << discarded_text << endl;
3643}
3644
3645//-------------------------------------------------------------
3646int SymbolValueList::print (const Symbol& symbol, 
3647                            const SymbolValue& value, 
3648                            bool& first_definition,
3649                            ostream& out) const
3650{
3651  int result (0);
3652
3653  cmt_string discarded_text;
3654  cmt_string define_text;
3655  ActionType action = Cmt::get_action ();
3656
3657  static PathBuilder* pb (0);
3658  cmt_string rvalue (value.text);
3659
3660  switch (command_type)
3661    {
3662      //case CommandSet :
3663      case CommandSetAppend :
3664      case CommandSetPrepend :
3665      case CommandSetRemove :
3666      case CommandSetRemoveRegexp :
3667        //case CommandAlias :
3668        //case CommandPath :
3669      case CommandPathAppend :
3670      case CommandPathPrepend :
3671      case CommandPathRemove :
3672      case CommandPathRemoveRegexp :
3673      case CommandMacroPrepend :
3674        //case CommandMacro :
3675      case CommandMacroAppend :
3676      case CommandMacroRemove :
3677      case CommandMacroRemoveRegexp :
3678      case CommandMacroRemoveAll :
3679      case CommandMacroRemoveAllRegexp :
3680        //case CommandAction :
3681        if (value.text.size () == 0) return result;
3682        break;
3683    }
3684
3685  CmtError::code code (CmtError::ok);
3686  cmt_string msg, n;
3687  int exec_err (0);
3688
3689  switch (command_type)
3690    {
3691      case CommandSet :
3692      case CommandSetAppend :
3693      case CommandSetPrepend :
3694      case CommandSetRemove :
3695      case CommandSetRemoveRegexp :
3696
3697        if (CmtError::has_pending_error ())
3698          {
3699            code = CmtError::get_last_error_code ();
3700            msg = CmtError::get_last_error ();
3701            exec_err = CmtError::get_last_execution_error ();
3702            n = CmtError::get_error_name (code);
3703            CmtError::clear ();
3704          }
3705        resolve_value_for_macros (rvalue);
3706        if (CmtError::get_last_error_code () != CmtError::warning)
3707          {
3708            if (CmtError::has_pending_error ())
3709              {
3710                CmtError::print ();
3711                CmtError::clear ();
3712              }
3713            if (CmtError::ok != code)
3714              {
3715                // restore error occurred before value expansion
3716                CmtError::set (code,
3717                               (msg.replace (n + ": ", cmt_string ("")), msg),
3718                               exec_err);
3719              }
3720            if (CommandSet != command_type &&
3721                rvalue.size () == 0)
3722              return result;
3723          }
3724        else
3725          {
3726            if (CmtMessage::active (Verbose))
3727              CmtError::print ();
3728            CmtError::clear ();
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            // Ignore the error, keep the value unresolved
3737            rvalue = value.text;
3738          }
3739
3740        break;
3741
3742        //case CommandAlias :
3743      case CommandPath :
3744      case CommandPathAppend :
3745      case CommandPathPrepend :
3746      case CommandPathRemove :
3747      case CommandPathRemoveRegexp :
3748        //case CommandMacroPrepend :
3749        //case CommandMacro :
3750        //case CommandMacroAppend :
3751        //case CommandMacroRemove :
3752        //case CommandMacroRemoveRegexp :
3753        //case CommandMacroRemoveAll :
3754        //case CommandMacroRemoveAllRegexp :
3755        //case CommandAction :
3756
3757        if (!pb)
3758          pb = static_cast<PathBuilder*> (symbol.builder);
3759        if (pb->get_strip_path ())
3760          {
3761            /*
3762            CmtError::code code (CmtError::ok);
3763            cmt_string msg, n;
3764            int exec_err (0);
3765            */
3766            if (CmtError::has_pending_error ())
3767              {
3768                code = CmtError::get_last_error_code ();
3769                msg = CmtError::get_last_error ();
3770                exec_err = CmtError::get_last_execution_error ();
3771                n = CmtError::get_error_name (code);
3772                CmtError::clear ();
3773              }
3774            resolve_value (rvalue);
3775            if (CmtError::get_last_error_code () != CmtError::warning)
3776              {
3777                if (CmtError::has_pending_error ())
3778                  {
3779                    CmtError::print ();
3780                    CmtError::clear ();
3781                  }
3782                if (CmtError::ok != code)
3783                  {
3784                    // restore error occurred before value expansion
3785                    CmtError::set (code,
3786                                   (msg.replace (n + ": ", cmt_string ("")), msg),
3787                                   exec_err);
3788                  }
3789                if (CommandPath != command_type &&
3790                    rvalue.size () == 0)
3791                  return result;
3792              }
3793            else
3794              {
3795                if (CommandPathRemove == command_type ||
3796                    CommandPathRemoveRegexp == command_type)
3797                  {
3798                    // This means that the value is not resolved via symbols
3799                    // and, possibly, standard environment variables and
3800                    //   * either has no effect on the path at all,
3801                    //     or
3802                    //   * there should be similar contribution from
3803                    //     and, hence, we should get the same error with
3804                    //     CommandPath, CommandPathAppend, or CommandPathPrepend
3805                    //  Either way, we can ignore this error.
3806
3807                    if (CmtMessage::active (Verbose))
3808                      CmtError::print ();
3809                    CmtError::clear ();
3810                    if (CmtError::ok != code)
3811                      {
3812                        // restore error occurred before value expansion
3813                        CmtError::set (code,
3814                                       (msg.replace (n + ": ", cmt_string ("")), msg),
3815                                       exec_err);
3816                      }
3817                  }
3818                else if (CmtError::ok != code)
3819                  {
3820                    // print error occurred before value expansion
3821                    CmtMessage::error (msg);
3822                  }
3823                // We keep CmtError::warning to indicate that
3824                // we could not resolve path
3825                // (without referencing the environment)
3826                // and strip path of non-existent directories
3827                //
3828                rvalue = value.text;
3829              }
3830          }
3831        else // (!pb->get_strip_path ())
3832          {
3833            if (CmtError::has_pending_error ())
3834              {
3835                code = CmtError::get_last_error_code ();
3836                msg = CmtError::get_last_error ();
3837                exec_err = CmtError::get_last_execution_error ();
3838                n = CmtError::get_error_name (code);
3839                CmtError::clear ();
3840              }
3841            resolve_value_for_macros (rvalue);
3842            if (CmtError::get_last_error_code () != CmtError::warning)
3843              {
3844                if (CmtError::has_pending_error ())
3845                  {
3846                    CmtError::print ();
3847                    CmtError::clear ();
3848                  }
3849                if (CmtError::ok != code)
3850                  {
3851                    // restore error occurred before value expansion
3852                    CmtError::set (code,
3853                                   (msg.replace (n + ": ", cmt_string ("")), msg),
3854                                   exec_err);
3855                  }
3856                if (CommandPath != command_type &&
3857                    rvalue.size () == 0)
3858                  return result;
3859              }
3860            else
3861              {
3862                if (CmtMessage::active (Verbose))
3863                  CmtError::print ();
3864                CmtError::clear ();
3865                if (CmtError::ok != code)
3866                  {
3867                    // restore error occurred before value expansion
3868                    CmtError::set (code,
3869                                   (msg.replace (n + ": ", cmt_string ("")), msg),
3870                                   exec_err);
3871                  }
3872                // Ignore the error, keep the value unresolved
3873                rvalue = value.text;
3874              }
3875          }
3876
3877        break;
3878    }
3879
3880  if (discarded) discarded_text = " (discarded by override)";
3881  else discarded_text = "";
3882
3883  if (first_definition) define_text = "defines";
3884  else define_text = "overrides";
3885
3886  if (CmtMessage::active (Verbose))
3887    out << "# Package " << (use ? use->get_package_name () + " " + use->version : "");
3888
3889  switch (command_type)
3890    {
3891      case CommandSet :
3892        if (CmtMessage::active (Verbose))
3893          out << " " << define_text << " set " << symbol.name << " as " << endl;
3894        //        out << " " << define_text << " set " << symbol.name << " as ";
3895        out << "set " << symbol.name;
3896        first_definition = false;
3897        result = 1;
3898        break;
3899      case CommandSetAppend :
3900        if (CmtMessage::active (Verbose))
3901          out << " appends to set " << symbol.name << " : " << endl;
3902        //        out << " appends to set " << symbol.name << " : ";
3903        out << "set_append " << symbol.name;
3904        result = 1;
3905        break;
3906      case CommandSetPrepend :
3907        if (CmtMessage::active (Verbose))
3908          out << " prepends to set " << symbol.name << " : " << endl;
3909        //        out << " prepends to set " << symbol.name << " : ";
3910        out << "set_prepend " << symbol.name;
3911        result = 1;
3912        break;
3913      case CommandSetRemove :
3914        if (CmtMessage::active (Verbose))
3915          out << " removes from set " << symbol.name << " : " << endl;
3916        //        out << " removes from set " << symbol.name << " : ";
3917        out << "set_remove " << symbol.name;
3918        result = 1;
3919        break;
3920      case CommandSetRemoveRegexp :
3921        if (CmtMessage::active (Verbose))
3922          out << " removes RE from set " << symbol.name << " : " << endl;
3923        //        out << " removes RE from set " << symbol.name << " : ";
3924        out << "set_remove_regexp " << symbol.name;
3925        result = 1;
3926        break;
3927      case CommandAlias :
3928        if (CmtMessage::active (Verbose))
3929          out << " " << define_text << " alias " << symbol.name << endl;
3930        //        out << " " << define_text << " alias " << symbol.name << " as ";
3931        out << "alias " << symbol.name;
3932        first_definition = false;
3933        result = 1;
3934        break;
3935    case CommandPath :
3936        if (CmtMessage::active (Verbose))
3937          out << " " << define_text << " path " << symbol.name << endl;
3938        //        out << " " << define_text << " path " << symbol.name << " as ";
3939        pb->filter_path_value (symbol, rvalue);
3940
3941        if (Cmt::get_debug ())
3942          {
3943            cerr << "|SymbolValueList::print> path " << symbol.name
3944                 << " " << value.text << " => " << rvalue << endl;
3945          }
3946
3947        out << "path " << symbol.name;
3948        first_definition = false;
3949        result = 1;
3950        break;
3951      case CommandPathAppend :
3952        if (CmtMessage::active (Verbose))
3953          out << " appends to path " << symbol.name << endl;
3954        //        out << " appends to path " << symbol.name << " : ";
3955        pb->filter_path_value (symbol, rvalue);
3956
3957        if (Cmt::get_debug ())
3958          {
3959            cerr << "|SymbolValueList::print> path_append " << symbol.name
3960                 << " " << value.text << " => " << rvalue << endl;
3961          }
3962
3963        if (rvalue.size () == 0) return result;
3964        out << "path_append " << symbol.name;
3965        result = 1;
3966        break;
3967      case CommandPathPrepend :
3968        if (CmtMessage::active (Verbose))
3969          out << " prepends to path " << symbol.name << " : " << endl;
3970        //        out << " prepends to path " << symbol.name << " : ";
3971        pb->filter_path_value (symbol, rvalue);
3972
3973        if (Cmt::get_debug ())
3974          {
3975            cerr << "|SymbolValueList::print> path_prepend " << symbol.name
3976                 << " " << value.text << " => " << rvalue << endl;
3977          }
3978
3979        if (rvalue.size () == 0) return result;
3980        out << "path_prepend " << symbol.name;
3981        result = 1;
3982        break;
3983      case CommandPathRemove :
3984        if (CmtMessage::active (Verbose))
3985          out << " removes from path " << symbol.name << " : " << endl;
3986        //        out << " removes from path " << symbol.name << " : ";
3987
3988        if (Cmt::get_debug ())
3989          {
3990            cerr << "|SymbolValueList::print> path_remove " << symbol.name
3991                 << " " << value.text << " => " << rvalue << endl;
3992          }
3993
3994        out << "path_remove " << symbol.name;
3995        result = 1;
3996        break;
3997      case CommandPathRemoveRegexp :
3998        if (CmtMessage::active (Verbose))
3999          out << " removes RE from path " << symbol.name << " : " << endl;
4000        //        out << " removes RE from path " << symbol.name << " : ";
4001
4002        if (Cmt::get_debug ())
4003          {
4004            cerr << "|SymbolValueList::print> path_remove_regexp " << symbol.name
4005                 << " " << value.text << " => " << rvalue << endl;
4006          }
4007
4008        out << "path_remove_regexp " << symbol.name;
4009        result = 1;
4010        break;
4011      case CommandMacro :
4012        if (CmtMessage::active (Verbose))
4013          out << " " << define_text << " macro " << symbol.name << " as " << endl;
4014        //        out << " " << define_text << " macro " << symbol.name << " as ";
4015        out << "macro " << symbol.name;
4016        result = 1;
4017        break;
4018      case CommandMacroPrepend :
4019        if (CmtMessage::active (Verbose))
4020          out << " prepends to macro " << symbol.name << " : " << endl;
4021        //        out << " prepends to macro " << symbol.name << " : ";
4022        out << "macro_prepend " << symbol.name;
4023        result = 1;
4024        break;
4025      case CommandMacroAppend :
4026        if (CmtMessage::active (Verbose))
4027          out << " appends to macro " << symbol.name << " : " << endl;
4028        //        out << " appends to macro " << symbol.name << " : ";
4029        out << "macro_append " << symbol.name;
4030        result = 1;
4031        break;
4032      case CommandMacroRemove :
4033        if (CmtMessage::active (Verbose))
4034          out << " remove from macro " << symbol.name << " : " << endl;
4035        //        out << " remove from macro " << symbol.name << " : ";
4036        out << "macro_remove " << symbol.name;
4037        result = 1;
4038        break;
4039      case CommandMacroRemoveRegexp :
4040        if (CmtMessage::active (Verbose))
4041          out << " remove RE from macro " << symbol.name << " : " << endl;
4042        //        out << " remove RE from macro " << symbol.name << " : ";
4043        out << "macro_remove_regexp " << symbol.name;
4044        result = 1;
4045        break;
4046      case CommandMacroRemoveAll :
4047        if (CmtMessage::active (Verbose))
4048          out << " remove all from macro " << symbol.name << " : " << endl;
4049        //        out << " remove all from macro " << symbol.name << " : ";
4050        out << "macro_remove_all " << symbol.name;
4051        result = 1;
4052        break;
4053      case CommandMacroRemoveAllRegexp :
4054        if (CmtMessage::active (Verbose))
4055          out << " remove all RE from macro " << symbol.name << " : " << endl;
4056        //        out << " remove all RE from macro " << symbol.name << " : ";
4057        out << "macro_remove_all_regexp " << symbol.name;
4058        result = 1;
4059        break;
4060      case CommandSetupScript :
4061        if (CmtMessage::active (Verbose))
4062          out << " " << define_text << " setup script " << symbol.name << endl;
4063        //       out << " " << define_text << " action " << symbol.name << " as ";
4064        out << "setup_script" /* << symbol.name */;
4065        first_definition = false;
4066        result = 1;
4067        break;
4068        /*
4069      case CommandAction :
4070        out << " " << define_text << " action " << symbol.name << " as ";
4071        first_definition = false;
4072        break;
4073        */
4074    }
4075
4076  out << " " << CmtSystem::quote (rvalue, " \t");
4077  //  out << " " << CmtSystem::quote (value.text, " \t");
4078  //  out << "'" << value.text << "'";
4079         
4080  /*
4081  Tag* selected_tag = value.tag;
4082         
4083  if ((selected_tag == 0) ||
4084      (selected_tag == Tag::get_default ()))
4085    {
4086      out << " for default tag";
4087    }
4088  else
4089    {
4090      out << " for tag '" << selected_tag->get_name () << "'";
4091    }
4092  */
4093
4094  out << endl;
4095  //  out << discarded_text << endl;
4096  return result;
4097}
4098
4099//-------------------------------------------------------------
4100bool Symbol::check_tag_used (const Tag* tag)
4101{
4102  if (tag == 0) return (false);
4103
4104  static SymbolVector& Symbols = symbols ();
4105
4106  if (Symbols.size () == 0) 
4107    {
4108      return (false);
4109    }
4110
4111  for (int number = 0; number < Symbol::symbol_number (); number++)
4112    {
4113      Symbol& symbol = Symbol::symbol (number);
4114
4115      for (int i = 0; i < symbol.value_lists.size (); i++)
4116        {
4117          const SymbolValueList& value_list = symbol.value_lists[i];
4118
4119          for (int j = 0; j < value_list.values.size (); j++)
4120            {
4121              const SymbolValue& value = value_list.values[j];
4122              Tag* t = value.tag;
4123
4124              if (t != 0)
4125                {
4126                  if (t->use_operand (tag)) return (true);
4127                }
4128            }
4129        }
4130    }
4131
4132  return (false);
4133}
4134
4135//-------------------------------------------------------------
4136cmt_string Symbol::get_env_value (const cmt_string& name)
4137{
4138  cmt_string s;
4139
4140  Symbol* symbol = Symbol::find (name);
4141  if (symbol != 0)
4142    {
4143      m_inhibit_display = true;
4144
4145      s = symbol->build_macro_value ();
4146      Symbol::expand (s);
4147
4148      m_inhibit_display = false;
4149    }
4150  else
4151    {
4152                if (Cmt::get_env_access () ||
4153                    Symbol::std_env_vars ().has (name))
4154                  {
4155      s = CmtSystem::getenv (name);
4156                    if (Cmt::get_debug ())
4157                      {
4158                        cerr << "Symbol::get_env_value> getenv (" << name
4159                             << ") => " << s << endl;
4160                      }
4161                  }
4162                else
4163                  {
4164                    if (Cmt::get_debug ())
4165                      {
4166                        cerr << "Symbol::get_env_value> getenv (" << name
4167                             << ") denied" << endl;
4168                      }
4169                    CmtError::set (CmtError::warning,
4170                                   "getenv (" + name + ") denied");
4171                    return (s);
4172                  }
4173    }
4174
4175  return (s);
4176}
4177
4178bool Symbol::get_inhibit_display ()
4179{
4180  return (m_inhibit_display);
4181}
4182
Note: See TracBrowser for help on using the repository browser.