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

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

See C.L. 521

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