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

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

See C.L. 519

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