source: CMT/v1r25-branch/source/cmt_symbol.cxx @ 636

Last change on this file since 636 was 612, checked in by rybkin, 12 years ago

See C.L. 487

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