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

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

See C.L. 524

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