source: CMT/v1r19/source/cmt_symbol.cxx @ 1

Last change on this file since 1 was 1, checked in by arnault, 19 years ago

Import all tags

File size: 71.4 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
17//-------------------------------------------------------------
18class SetBuilder : public ValueBuilder
19{
20public:
21  const cmt_string build (const Symbol& symbol,
22                          const cmt_string& tag_name = "");
23  const cmt_string clean (const Symbol& symbol,
24                          const cmt_string& tag_name = "")
25      {
26        static const cmt_string empty = "";
27        return (empty);
28      }
29};
30//-------------------------------------------------------------
31
32//-------------------------------------------------------------
33class PathBuilder : public ValueBuilder
34{
35public:
36  const cmt_string build (const Symbol& symbol,
37                          const cmt_string& tag_name = "");
38  const cmt_string clean (const Symbol& symbol,
39                          const cmt_string& tag_name = "");
40};
41//-------------------------------------------------------------
42
43//-------------------------------------------------------------
44class MacroBuilder : public ValueBuilder
45{
46public:
47  const cmt_string build (const Symbol& symbol,
48                          const cmt_string& tag_name = "");
49  const cmt_string clean (const Symbol& symbol,
50                          const cmt_string& tag_name = "")
51      {
52        static const cmt_string empty = "";
53        return (empty);
54      }
55};
56//-------------------------------------------------------------
57
58//-------------------------------------------------------------
59class ScriptBuilder : public ValueBuilder
60{
61public:
62  const cmt_string build (const Symbol& symbol,
63                          const cmt_string& tag_name = "");
64  const cmt_string clean (const Symbol& symbol,
65                          const cmt_string& tag_name = "")
66      {
67        static const cmt_string empty = "";
68        return (empty);
69      }
70};
71//-------------------------------------------------------------
72
73//-------------------------------------------------------------
74class ActionBuilder : public ValueBuilder
75{
76public:
77  const cmt_string build (const Symbol& symbol,
78                          const cmt_string& tag_name = "");
79  const cmt_string clean (const Symbol& symbol,
80                          const cmt_string& tag_name = "")
81      {
82        static const cmt_string empty = "";
83        return (empty);
84      }
85};
86//-------------------------------------------------------------
87
88//-------------------------------------------------------------
89class symbol_marker
90{
91public:
92  symbol_marker ()
93  {
94    ptr = cmt_string::npos;
95    pattern = 0;
96    intro = 0;
97  }
98
99  symbol_marker (int a_ptr, char a_pattern, int a_intro)
100  {
101    ptr = a_ptr;
102    pattern = a_pattern;
103    intro = a_intro;
104  }
105
106  symbol_marker (const symbol_marker& other)
107  {
108    ptr = other.ptr;
109    pattern = other.pattern;
110    intro = other.intro;
111  }
112
113  void set (int a_ptr, char a_pattern, int a_intro)
114  {
115    ptr = a_ptr;
116    pattern = a_pattern;
117    intro = a_intro;
118  }
119
120  static symbol_marker& get_lowest (symbol_marker markers[], int count)
121  {
122    static symbol_marker result;
123    int real_count = 0;
124    int i;
125
126      // Check that at least one marker has result
127
128    for (i = 0; i < count; i++)
129      {
130        if (markers[i].ptr != cmt_string::npos) real_count++;
131      }
132
133    if (real_count == 0) return (result);
134
135    // since we've passed the previous test,
136    // at least one entry is not npos.
137    // Now discards other npos by moving them to the end
138   
139    for (i = 0; i < count;)
140      {
141        if (markers[i].ptr == cmt_string::npos)
142          {
143            markers[i] = markers[count-1];
144            count--;
145            if (count == 0) break;
146          }
147        else
148          {
149            i++;
150          }
151      }
152   
153    if (count == 0) return (result);
154   
155    // now all entries in [0, count-1] are not npos
156    // let's sort the lowest one in [0]
157   
158    for (i = 1; i < count;)
159      {
160        if (markers[0].ptr > markers[i].ptr)
161          {
162            symbol_marker temp = markers[0];
163            markers[0] = markers[i];
164            markers[i] = temp;
165            i = 1;
166          }
167        else
168          {
169            i++;
170          }
171      }
172   
173    return (markers[0]);
174  }
175
176  int ptr;
177  char pattern;
178  int intro;
179};
180//-------------------------------------------------------------
181
182/**
183
184   Attempt to substitute all occurrences of
185
186      ${<symbol_name>}
187      $(<symbol_name>)
188      %<symbol_name>%    [on Windows only]
189
190      by the specified value in the given text.
191
192    This is for one symbol only
193
194 */
195static void resolve_value (cmt_string& text,
196                           const cmt_string& symbol_name,
197                           const cmt_string& value)
198{
199  static cmt_string pattern;
200
201  pattern = "${";
202  pattern += symbol_name;
203  pattern += "}";
204
205  text.replace_all (pattern, value);
206
207  pattern = "$(";
208  pattern += symbol_name;
209  pattern += ")";
210
211  text.replace_all (pattern, value);
212
213#ifdef WIN32
214  pattern = "%";
215  pattern += symbol_name;
216  pattern += "%";
217
218  text.replace_all (pattern, value);
219#endif
220}
221
222/**
223
224   Attempt to substitute into the specified text all occurrences of
225
226      ${xxx}
227      $(xxx)
228      `xxx`
229      %xxx%    [on Windows only]
230
231      by the appropriate value:
232
233        for `xxx` :
234
235            xxx is considered as a shell command. Value is the result of its execution
236
237        for other patterns:
238
239            if xxx is a symbol name, its value is substituted to the pattern
240            otherwise, xxx is tried as an environment variable
241
242
243     ===> In all cases, the pattern is filtered away.
244
245
246 */
247static void resolve_value (cmt_string& text)
248{
249  //static cmt_regexp reg ("[$%`]");
250
251  //if (!reg.match (text)) return;
252
253  cmt_string pattern;
254  cmt_string symbol_name;
255  char end_pattern;
256
257  int start = 0;
258
259  for (;;)
260    {
261      int begin;
262      int end;
263
264      symbol_marker markers[4];
265      int num = 0;
266
267      markers[num].set (text.find (start, "$("), ')', 2); num++;
268      markers[num].set (text.find (start, "${"), '}', 2); num++;
269      markers[num].set (text.find (start, "`"), '`', 1); num++;
270
271#ifdef WIN32
272      markers[num].set (text.find (start, "%"), '%', 1); num++;
273#endif
274
275      // Find the first matching pattern
276
277      symbol_marker& marker = symbol_marker::get_lowest (markers, num);
278
279      begin = marker.ptr;
280
281      if (begin == cmt_string::npos) break;
282
283      end_pattern = marker.pattern;
284      start = begin + marker.intro;
285
286      end = text.find (start, end_pattern);
287      if (end == cmt_string::npos)
288        {
289          // The pattern is a fake one (no ending!)
290          start++;
291          continue;
292        }
293
294      // This should never happen...
295      if (end < begin) break;
296
297      // Extract the complete pattern
298      text.substr (begin, end - begin + 1, pattern);
299
300      // Then only the symbol name
301      text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name);
302
303      if (text[begin] == '`')
304        {
305          cmt_string command = symbol_name;
306          resolve_value (command);
307
308            // The value is a shell command that first needs
309            // to be applied. The output of the command is then substituted
310
311          cmt_string result;
312
313          Symbol::all_set ();
314          CmtSystem::execute (command, result);
315         
316          int pos;
317          pos = result.find ('\n');
318          if (pos != cmt_string::npos) result.erase (pos);
319          pos = result.find ('\r');
320          if (pos != cmt_string::npos) result.erase (pos);
321         
322          if (Cmt::get_debug ())
323            {
324              cout << "   Executing [" << command << "] to expand a symbol value =>[" 
325                   << result << "]" << endl;
326            }
327         
328          text.replace_all (pattern, result);
329
330          // The substitution will restart from the same place
331          // allowing for recursive replacements
332          start = begin;
333        }
334      else
335        {
336          Symbol* symbol = Symbol::find (symbol_name);
337          if (symbol != 0)
338            {
339                // Symbol found
340              cmt_string value = symbol->resolve_macro_value ();
341              text.replace_all (pattern, value);
342             
343                // The substitution will restart from the same place
344                // allowing for recursive replacements
345              start = begin;
346            }
347          else
348            {
349                // Symbol not found. Look for env. variable
350              cmt_string value = CmtSystem::getenv (symbol_name);
351             
352                // When the env. variable is not defined, the replacement is empty
353                // thus all $(xxx) ${xxx} %xxx% patterns are always filtered away.
354              text.replace_all (pattern, value);
355             
356                // The substitution will restart from the same place
357                // allowing for recursive replacements
358              start = begin;
359            }
360        }
361    }
362}
363
364/**
365
366   Attempt to substitute all occurrences of
367
368      ${xxx}
369      $(xxx)
370      `xxx`
371      %xxx%    [on Windows only]
372
373      by the appropriate value:
374
375        for `xxx` :
376
377            xxx is considered as a shell command. Value is the result of its execution
378
379        for other patterns:
380
381            if xxx is a macro name, its value is substituted to the pattern
382
383            if xxx is a set or a path, it is kept in place (after fixing the pattern
384            according to the OS style)
385
386            otherwise it is simply kept in place
387
388 */
389static void resolve_value_for_macros (cmt_string& text)
390{
391  cmt_string pattern;
392  cmt_string symbol_name;
393  char end_pattern;
394
395  int start = 0;
396
397  for (;;)
398    {
399      //
400      // Try and substitute all ${xxx} $(xxx) or %xxx% patterns
401      // using symbol values, only when the symbol is a macro.
402      //
403
404      int begin;
405      int end;
406
407      symbol_marker markers[4];
408      int num = 0;
409
410      markers[num].set (text.find (start, "$("), ')', 2); num++;
411      markers[num].set (text.find (start, "${"), '}', 2); num++;
412
413#ifdef WIN32
414      markers[num].set (text.find (start, "%"), '%', 1); num++;
415#endif
416
417      markers[num].set (text.find (start, "`"), '`', 1); num++;
418
419      // Find the first of three patterns
420
421      symbol_marker& marker = symbol_marker::get_lowest (markers, num);
422
423      begin = marker.ptr;
424
425      if (begin == cmt_string::npos) break;
426
427      end_pattern = marker.pattern;
428      start = begin + marker.intro;
429
430      end = text.find (start, end_pattern);
431      if (end == cmt_string::npos)
432        {
433          // The pattern is a fake one (no ending!)
434          start++;
435          continue;
436        }
437
438      // This should never happen...
439      if (end < begin) break;
440
441      // Extract the complete pattern
442      text.substr (begin, end - begin + 1, pattern);
443
444      // Then only the macro name
445      text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name);
446
447      if (text[begin] == '`')
448        {
449          cmt_string command = symbol_name;
450          resolve_value (command);
451
452            // The macro value is a shell command that first needs
453            // to be applied. The output of the command is substituted
454
455          cmt_string result;
456
457          Symbol::all_set ();
458          CmtSystem::execute (command, result);
459         
460          int pos;
461          pos = result.find ('\n');
462          if (pos != cmt_string::npos) result.erase (pos);
463          pos = result.find ('\r');
464          if (pos != cmt_string::npos) result.erase (pos);
465         
466          if (Cmt::get_debug ())
467            {
468              cout << "   Executing [" << command << "] to expand a macro value =>[" 
469                   << result << "]" << endl;
470            }
471         
472          text.replace_all (pattern, result);
473
474          // The substitution will restart from the same place
475          // allowing for recursive replacements
476          start = begin;
477        }
478      else
479        {
480          Symbol* macro = Symbol::find (symbol_name);
481          if ((macro != 0) && 
482              (macro->type == Symbol::SymbolMacro))
483            {
484                // Macro found
485              cmt_string value = macro->resolve_macro_value ();
486              text.replace_all (pattern, value);
487
488                // The substitution will restart from the same place
489                // allowing for recursive replacements
490              start = begin;
491            }
492          else if ((macro == 0) || 
493                   ((macro->type == Symbol::SymbolSet) || (macro->type == Symbol::SymbolPath)))
494            {
495                // Set found
496                // ensure that the delimiters will match the OS dependent
497                // delimiters.
498             
499              cmt_string pattern_close = marker.pattern;
500             
501              if (pattern_close != CmtSystem::ev_close ())
502                {
503                  cmt_string new_pattern;
504                 
505                  new_pattern = CmtSystem::ev_open ();
506                  new_pattern += symbol_name;
507                  new_pattern += CmtSystem::ev_close ();
508                 
509                  text.replace (pattern, new_pattern);
510                }
511             
512              start = end + 1;
513            }
514          else
515            {
516              start = end + 1;
517            }
518        }
519    }
520}
521
522/**
523
524   This function suppress all OS delimiters ie ${ } or % % and replaces them
525   by the pure macro delimiters $( )
526
527   `xxx` pattern is replaced by the result of the execution of the command
528
529 */
530static void suppress_OS_delimiters (cmt_string& text)
531{
532  cmt_string pattern;
533  cmt_string symbol_name;
534  char end_pattern;
535
536  int start = 0;
537
538  for (;;)
539    {
540      int begin;
541      int end;
542
543      symbol_marker markers[3];
544      int num = 0;
545
546      markers[num].set (text.find (start, "${"), '}', 2); num++;
547      markers[num].set (text.find (start, "`"), '`', 1); num++;
548
549#ifdef WIN32
550      markers[num].set (text.find (start, "%"), '%', 1); num++;
551#endif
552
553      // Find the first of three patterns
554
555      symbol_marker& marker = symbol_marker::get_lowest (markers, num);
556
557      begin = marker.ptr;
558
559      if (begin == cmt_string::npos) break;
560
561      end_pattern = marker.pattern;
562      start = begin + marker.intro;
563
564      end = text.find (start, end_pattern);
565      if (end == cmt_string::npos)
566        {
567          // The pattern is a fake one (no ending!)
568          start++;
569          continue;
570        }
571
572      // This should never happen...
573      if (end < begin) break;
574
575      // Extract the complete pattern
576      text.substr (begin, end - begin + 1, pattern);
577
578      // Then only the macro name
579      text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name);
580
581      if (text[begin] == '`')
582        {
583          cmt_string command = symbol_name;
584          resolve_value (command);
585
586            // The macro value is a shell command that first needs
587            // to be applied. The output of the command is substituted
588
589          cmt_string result;
590
591          Symbol::all_set ();
592          CmtSystem::execute (command, result);
593         
594          int pos;
595          pos = result.find ('\n');
596          if (pos != cmt_string::npos) result.erase (pos);
597          pos = result.find ('\r');
598          if (pos != cmt_string::npos) result.erase (pos);
599         
600          if (Cmt::get_debug ())
601            {
602              cout << "   Executing [" << command << "] to expand a macro value =>[" 
603                   << result << "]" << endl;
604            }
605         
606          text.replace_all (pattern, result);
607
608          // The substitution will restart from the same place
609          // allowing for recursive replacements
610          start = begin;
611        }
612      else
613        {
614          cmt_string new_pattern;
615
616          new_pattern = "$(";
617          new_pattern += symbol_name;
618          new_pattern += ")";
619
620          text.replace (pattern, new_pattern);
621
622          start = begin;
623        }
624    }
625}
626
627//-------------------------------------------------------------
628/*                                                          */
629/*  Operations on SymbolValues                              */
630/*                                                          */
631//-------------------------------------------------------------
632
633//-------------------------------------------------------------
634SymbolValue::SymbolValue ()
635{
636  tag = 0;
637}
638
639//-------------------------------------------------------------
640SymbolValue::~SymbolValue ()
641{
642  tag = 0;
643}
644
645//-------------------------------------------------------------
646/*                                                          */
647/*  Operations on Symbols                                   */
648/*                                                          */
649//-------------------------------------------------------------
650
651//-------------------------------------------------------------
652Symbol* Symbol::create (const cmt_string& name,
653                        CommandType command,
654                        Use* use)
655{
656  static SetBuilder Set;
657  static PathBuilder Path;
658  static MacroBuilder Macro;
659  static ScriptBuilder Script;
660  static ActionBuilder Action;
661
662  static SymbolVector& Symbols = symbols ();
663  static SymbolMap& SymbolMap = symbol_map ();
664
665  SymbolType type = SymbolUndefined;
666
667  switch (command)
668    {
669    case CommandSet:
670    case CommandSetAppend:
671    case CommandSetPrepend:
672    case CommandSetRemove:
673    case CommandSetRemoveRegexp:
674      type = SymbolSet;
675      break;
676    case CommandPath:
677    case CommandPathAppend:
678    case CommandPathPrepend:
679    case CommandPathRemove:
680    case CommandPathRemoveRegexp:
681      type = SymbolPath;
682      break;
683    case CommandMacro:
684    case CommandMacroAppend:
685    case CommandMacroPrepend:
686    case CommandMacroRemove:
687    case CommandMacroRemoveRegexp:
688    case CommandMacroRemoveAll:
689    case CommandMacroRemoveAllRegexp:
690      type = SymbolMacro;
691      break;
692    case CommandAction:
693      type = SymbolAction;
694      break;
695    case CommandAlias:
696      type = SymbolAlias;
697      break;
698    case CommandSetupScript:
699      type = SymbolSetupScript;
700      break;
701    case CommandCleanupScript:
702      type = SymbolCleanupScript;
703      break;
704    }
705
706  {
707    Symbol* symbol;
708
709    symbol = find (name);
710    if (symbol != 0) 
711      {
712        if (symbol->type != type)
713          {
714            ActionType action = Cmt::get_action ();
715
716            if ((!Cmt::get_quiet ()) &&
717                (action != action_build_tag_makefile))
718              {
719                cmt_string s1;
720                cmt_string s2;
721
722                switch (symbol->type)
723                  {
724                  case SymbolSet:
725                    s1 = "set";
726                    break;
727                  case SymbolPath:
728                    s1 = "path";
729                    break;
730                  case SymbolMacro:
731                    s1 = "macro";
732                    break;
733                  case SymbolSetupScript:
734                    s1 = "setup_script";
735                    break;
736                  case SymbolCleanupScript:
737                    s1 = "cleanup_script";
738                    break;
739                  case SymbolAction:
740                    s1 = "action";
741                    break;
742                  case SymbolAlias:
743                    s1 = "alias";
744                    break;
745                  } 
746
747                switch (type)
748                  {
749                  case SymbolSet:
750                    s2 = "set";   
751                    break;
752                  case SymbolPath:
753                    s2 = "path";   
754                    break;
755                  case SymbolMacro:
756                    s2 = "macro";   
757                    break;
758                  case SymbolSetupScript:
759                    s2 = "setup_script"; 
760                    break;
761                  case SymbolCleanupScript:
762                    s2 = "cleanup_script"; 
763                    break;
764                  case SymbolAction:
765                    s2 = "action";
766                    break;
767                  case SymbolAlias:
768                    s2 = "alias";
769                    break;
770                  } 
771
772                cerr << "#CMT> Warning: Symbol " << name
773                     << " inconsistently redeclared from " << s1 << " to " << s2;
774                if (use != 0) cerr << " in package " << use->get_package_name ();
775                cerr << endl;
776              }
777          }
778
779        return (symbol);
780      }
781  }
782
783  Symbol& symbol = Symbols.add ();
784  SymbolMap.add (name, symbol);
785
786  symbol.name  = name;
787  symbol.scope = use->get_current_scope ();
788  symbol.type  = type;
789
790  symbol.value_lists.clear ();
791
792  switch (type)
793    {
794    case SymbolSet:
795      symbol.builder = &Set;
796      break;
797    case SymbolPath:
798      symbol.builder = &Path;
799      break;
800    case SymbolAlias:
801      symbol.builder = &Set;
802      break;
803    case SymbolMacro:
804      symbol.builder = &Macro;
805      break;
806    case SymbolSetupScript:
807    case SymbolCleanupScript:
808      symbol.builder = &Script;
809      break;
810    case SymbolAction:
811      symbol.builder = &Action;
812      break;
813    }
814
815  symbol.selected_value = -1;
816
817  return (&symbol);
818}
819
820//-------------------------------------------------------------
821Symbol* Symbol::find (const cmt_string& name)
822{
823  static SymbolMap& SymbolMap = symbol_map ();
824
825  Symbol* result = 0;
826
827  result = SymbolMap.find (name);
828
829  return (result);
830}
831
832//-------------------------------------------------------------
833int Symbol::symbol_number ()
834{
835  static SymbolVector& Symbols = symbols ();
836
837  return (Symbols.size ());
838}
839
840//-------------------------------------------------------------
841Symbol::SymbolVector& Symbol::symbols ()
842{
843  static Database& db = Database::instance ();
844  static SymbolVector& Symbols = db.symbols ();
845
846  return (Symbols);
847}
848
849//-------------------------------------------------------------
850Symbol::SymbolMap& Symbol::symbol_map ()
851{
852  static Database& db = Database::instance ();
853  static SymbolMap& SymbolMap = db.symbol_map ();
854
855  return (SymbolMap);
856}
857
858//-------------------------------------------------------------
859Symbol& Symbol::symbol (int index)
860{
861  static SymbolVector& Symbols = symbols ();
862
863  return (Symbols[index]);
864}
865
866//-------------------------------------------------------------
867void Symbol::action (const CmtSystem::cmt_string_vector& words,
868                     CommandType command_type,
869                     Use* use)
870{
871  int number;
872  Symbol* symbol;
873  Tag* tag;
874
875  if (words.size () < 1) return;
876  cmt_string name = words[1];
877
878  if ((command_type == CommandSetupScript) ||
879      (command_type == CommandCleanupScript))
880    {
881      cmt_string full_name;
882
883      Symbol::expand (name);
884
885      if (name != "")
886        {
887          if (CmtSystem::absolute_path (name)) 
888            {
889              full_name = name;
890            }
891          else
892            {
893#ifdef WIN32
894              full_name = "%";
895#else
896              full_name = "${";
897#endif
898              full_name += use->prefix;
899              full_name += "ROOT";
900#ifdef WIN32
901              full_name += "%";
902#else
903              full_name += "}";
904#endif
905              full_name += CmtSystem::file_separator ();
906              if (use->style == cmt_style) full_name += "cmt";
907              else if (use->style == no_version_style) full_name += "cmt";
908              else full_name += "mgr";
909              full_name += CmtSystem::file_separator ();
910              full_name += name;
911            }
912
913          symbol = create (full_name, command_type, use);
914          symbol->add_value_to_list (command_type, use,
915                                     Tag::get_default (), full_name);
916        }
917    }
918  else
919    {
920      if (words.size () < 2) return;
921      const cmt_string& default_value = words[2];
922
923      if (Cmt::get_debug ())
924        {
925          cout << "Symbol::action> name:" << name
926               << " access:" << Cmt::get_current_access () 
927               << " scope:" << use->get_current_scope () << endl;
928        }
929
930      if (Cmt::get_current_access () == UserMode)
931        {
932          if (name == "constituents") return;
933          if (name == "constituentscclean") return;
934
935          if (use->get_current_scope () == ScopePrivate) return;
936        }
937
938      symbol = create (name, command_type, use);
939
940      /*
941        Parse the default value.
942      */
943     
944      symbol->add_value_to_list (command_type, use,
945                                 Tag::get_default (), default_value);
946     
947      /*
948        Then parse all specific values
949       
950        <tag> <value>
951        ...
952      */
953     
954      number = 3;
955      while (number < (words.size () - 1))
956        {
957          cmt_string tag_name = words[number];
958          const cmt_string& value = words[number + 1];
959
960          expand (tag_name);
961
962          if (Cmt::get_debug ())
963            {
964              cout << "Symbol::action> tag_name=" << tag_name << endl;
965            }
966
967          tag = Tag::find (tag_name);
968          if (tag == 0)
969            {
970              tag = Tag::add (tag_name, PriorityUserTag, "use", use);
971            }
972
973          symbol->add_value_to_list (command_type, use, tag, value);
974         
975          number += 2;
976        }
977
978      if (name == "CMTPATH")
979        {
980          Cmt::configure_cmt_path (use);
981        }
982      else if (name == "CMTSITE")
983        {
984          Cmt::configure_site_tag (use);
985        }
986      else if (name == "CMTCONFIG")
987        {
988            //cerr << "redefining CMTCONFIG" << endl;
989          Cmt::configure_tags (use);
990        }
991      else if (name == "CMTHOME")
992        {
993          Cmt::configure_home (use);
994        }
995      else if (name == "CMTUSERCONTEXT")
996        {
997          Cmt::configure_user_context (use);
998        }
999      else if (name.find ("_native_version") != cmt_string::npos)
1000        {
1001          cmt_string n = use->get_package_name ();
1002          n += "_native_version";
1003
1004          if (name == n)
1005            {
1006              use->set_native_version (true);
1007            }
1008        }
1009    }
1010}
1011
1012//-------------------------------------------------------------
1013int Symbol::is_selected (const cmt_string& name)
1014{
1015  Symbol* symbol;
1016  int number;
1017  int value_number;
1018
1019  symbol = find (name);
1020  if (symbol == 0) return (0);
1021
1022  if (symbol->value_lists.size () == 0) return (0);
1023
1024  for (number = 0;
1025       number < symbol->value_lists.size ();
1026       number++)
1027    {
1028      const SymbolValueList& value_list = symbol->value_lists[number];
1029
1030      if (value_list.discarded) continue;
1031
1032      if ((value_list.command_type == CommandMacro) ||
1033          (value_list.command_type == CommandSet) ||
1034          (value_list.command_type == CommandSetAppend) ||
1035          (value_list.command_type == CommandSetPrepend) ||
1036          (value_list.command_type == CommandSetRemove) ||
1037          (value_list.command_type == CommandSetRemoveRegexp) ||
1038          (value_list.command_type == CommandAlias) ||
1039          (value_list.command_type == CommandAction))
1040        {
1041          for (value_number = 0;
1042               value_number < value_list.values.size ();
1043               value_number++)
1044            {
1045              Tag* tag;
1046
1047              SymbolValue& value = value_list.values[value_number];
1048
1049              tag = value.tag;
1050              if ((tag == 0) ||
1051                  (tag == Tag::get_default ()) ||
1052                  (tag->is_selected () != 0))
1053                {
1054                  return (1);
1055                }
1056            }
1057        }
1058    }
1059
1060  return (0);
1061}
1062
1063//-------------------------------------------------------------
1064Symbol::Symbol ()
1065{
1066  name = "";
1067}
1068
1069//-------------------------------------------------------------
1070Symbol::~Symbol ()
1071{
1072}
1073
1074/**
1075 *  Characterizes if a value is provided as the reference to itself.
1076 */
1077bool Symbol::value_is_reflexive (const cmt_string& text) const
1078{
1079  bool result = false;
1080  int text_length = text.size ();
1081
1082  if (text_length == (name.size () + 3))
1083    {
1084      static cmt_string temp;
1085             
1086      if (text[0] == '$')
1087        {
1088          if (text[1] == '(')
1089            {
1090              temp = "$(";
1091              temp += name;
1092              temp += ")";
1093             
1094              if (text == temp)
1095                {
1096                  result = true;
1097                }
1098            }
1099          else if (text[1] == '{')
1100            {
1101              temp = "${";
1102              temp += name;
1103              temp += "}";
1104             
1105              if (text == temp)
1106                {
1107                  result = true;
1108                }
1109            }
1110        }
1111    }
1112  else if (text_length == (name.size () + 2))
1113    {
1114      static cmt_string temp;
1115
1116      temp = "%";
1117      temp += name;
1118      temp += "%";
1119
1120      if (text == temp)
1121        {
1122          result = true;
1123        }
1124    }
1125
1126  return (result);
1127}
1128
1129//-------------------------------------------------------------
1130void Symbol::add_value_to_list (CommandType command_type,
1131                                Use* use,
1132                                Tag* tag,
1133                                const cmt_string& text)
1134{
1135  SymbolValueList* value_list = 0;
1136  bool is_reflexive = false;
1137
1138    //
1139    // First pickup the most recent value_list
1140    //
1141  if (value_lists.size () > 0) value_list = &(value_lists.back ());
1142
1143    //
1144    //  Create a new value list is we switch to another use or
1145    //  if we switch to a new command_type (eg. switching from
1146    //  macro to macro_append).
1147    //
1148  if ((value_list == 0) ||
1149      (use != value_list->use) ||
1150      (command_type != value_list->command_type) ||
1151      (tag == Tag::get_default ()))
1152    {
1153      value_list = &(value_lists.add ());
1154      value_list->use = use;
1155      value_list->command_type = command_type;
1156      value_list->values.clear ();
1157      value_list->discarded = false;
1158      value_list->is_reflexive = false;
1159    }
1160
1161/*
1162  else
1163    {
1164        value_list = &(value_lists[value_lists.size () - 1]);
1165    }
1166*/
1167
1168  is_reflexive = value_list->is_reflexive;
1169
1170    //
1171    //  If the command_type is command_macro or command_set,
1172    // this is considered as a full re-set of this symbol
1173    //   In this case, we have to discard all previous values
1174    //
1175    //  However, we'd like to exclude from this logic the cases where
1176    //  the value is **exactly*
1177    //
1178    //     $(<symbol>)
1179    //     ${<symbol>}
1180    //     %<symbol>%
1181    //
1182    //   which would then mean that we do not reset the value but rather
1183    //  override it.
1184    //
1185
1186    //
1187    // Inside this value_list, we add this new tag-value pair.
1188    //
1189
1190  if ((command_type == CommandMacro) ||
1191      (command_type == CommandSet) ||
1192      (command_type == CommandPath) ||
1193      (command_type == CommandAction))
1194    {
1195        //
1196        // Check whether we have to hide previous settings by this new definition
1197        //  (of course this is only useful if there WERE previous settings)
1198        //
1199      if ((value_lists.size () >= 1) && (!is_reflexive))
1200        {
1201          if (value_is_reflexive (text))
1202            {
1203              value_list->is_reflexive = true;
1204              is_reflexive = true;
1205            }
1206          else
1207            {
1208              //cout << "...discarding old values for symbol " << name << " text=[" << text << "]" << endl;
1209                 
1210              for (int i = 0; i < (value_lists.size () - 1); i++)
1211                {
1212                  SymbolValueList& vl = value_lists[i];
1213                 
1214                  if ((vl.use != 0) &&
1215                      (vl.use->discarded))
1216                    {
1217                      //vl.discarded = true;
1218                    }
1219                }
1220            }
1221        }
1222    }
1223
1224  SymbolValue& value = value_list->values.add ();
1225
1226  value.tag = tag;
1227  value.text = text;
1228  value.selected = 0;
1229}
1230
1231/**
1232   Compute the current value of all environment variables and set them to the
1233   shell
1234 */
1235void Symbol::all_set ()
1236{
1237  //cerr << "all_set" << endl;
1238
1239  if (Cmt::get_debug ())
1240    {
1241      cout << "Symbol::all_set> done" << Cmt::get_all_sets_done () << endl;
1242    }
1243
1244  if (Cmt::get_all_sets_done ()) return;
1245
1246  Cmt::set_all_sets_done ();
1247
1248  static SymbolVector& Symbols = symbols ();
1249
1250  static CmtSystem::cmt_string_vector envs;
1251
1252  envs.clear ();
1253
1254  int number;
1255
1256  if (Symbols.size () == 0) 
1257    {
1258        //running = false;
1259      return;
1260    }
1261
1262  cmt_string value;
1263
1264  for (number = 0; number < Symbol::symbol_number (); number++)
1265    {
1266      Symbol& symbol = Symbol::symbol (number);
1267
1268      if (symbol.type != SymbolSet) continue;
1269
1270      value = symbol.build_macro_value ();
1271      if (value != "")
1272        {
1273          cmt_string& temp = envs.add ();
1274
1275          temp = symbol.name;
1276          temp += '=';
1277          temp += value;
1278        }
1279    }
1280
1281  for (number = 0; number < Symbol::symbol_number (); number++)
1282    {
1283      Symbol& symbol = Symbol::symbol (number);
1284
1285      if ((symbol.type != SymbolPath)) continue;
1286
1287      value = symbol.build_macro_value ();
1288      if (value != "")
1289        {
1290          cmt_string& temp = envs.add ();
1291
1292          temp = symbol.name;
1293          temp += '=';
1294          temp += value;
1295        }
1296    }
1297
1298  for (number = 0; number < envs.size (); number++)
1299    {
1300      cmt_string& env = envs[number];
1301      Symbol::expand (env);
1302
1303#ifdef WIN32
1304      env.replace_all ("/", "\\");
1305#endif
1306
1307      if (Cmt::get_debug ())
1308        {
1309          cout << "Symbol::all_set> " << env << endl;
1310        }
1311      CmtSystem::putenv (env);
1312    }
1313
1314    //running = false;
1315}
1316
1317//-------------------------------------------------------------
1318void Symbol::all_print (PrintMode mode)
1319{
1320  static SymbolVector& Symbols = symbols ();
1321
1322  int number;
1323
1324  if (Symbols.size () == 0) return;
1325
1326  for (number = 0; number < Symbol::symbol_number (); number++)
1327    {
1328      Symbol& symbol = Symbol::symbol (number);
1329
1330      if ((symbol.type == SymbolSet) ||
1331          (symbol.type == SymbolAlias) ||
1332          (symbol.type == SymbolSetupScript))
1333        {
1334          if (symbol.print (mode))
1335            {
1336              if (mode == Bat)
1337                {
1338                  cout << endl;
1339                }
1340              else
1341                {
1342                  //cout << "; ";
1343                  cout << endl;
1344                }
1345            }
1346        }
1347    }
1348
1349  for (number = 0; number < Symbol::symbol_number (); number++)
1350    {
1351      Symbol& symbol = Symbol::symbol (number);
1352
1353      if ((symbol.type != SymbolPath)) continue;
1354
1355      if (symbol.print (mode))
1356        {
1357          if (mode == Bat)
1358            {
1359              cout << endl;
1360            }
1361          else
1362            {
1363              //cout << "; ";
1364              cout << endl;
1365            }
1366        }
1367    }
1368}
1369
1370//-------------------------------------------------------------
1371void Symbol::all_print_clean (PrintMode mode)
1372{
1373  static SymbolVector& Symbols = symbols ();
1374
1375  int number;
1376
1377  if (Symbols.size () == 0) return;
1378
1379  for (number = Symbols.size () - 1; number >= 0; number--)
1380    {
1381      Symbol& symbol = Symbols[number];
1382
1383      if ((symbol.type == SymbolSet) ||
1384          (symbol.type == SymbolAlias) ||
1385          (symbol.type == SymbolCleanupScript))
1386        {
1387          if (symbol.print_clean (mode))
1388            {
1389              cout << endl;
1390            }
1391        }
1392    }
1393
1394  for (number = Symbols.size () - 1; number >= 0; number--)
1395    {
1396      Symbol& symbol = Symbols[number];
1397
1398      if ((symbol.type != SymbolPath)) continue;
1399
1400      if (symbol.print_clean (mode))
1401        {
1402          cout << endl;
1403        }
1404    }
1405}
1406
1407//-------------------------------------------------------------
1408int Symbol::print_clean (PrintMode mode)
1409{
1410  int result = 0;
1411  static cmt_string temp;
1412
1413  if (name == "CMTCONFIG") return (0);
1414
1415  switch (type)
1416    {
1417    case SymbolSet :
1418      switch (mode)
1419        {
1420        case Csh :
1421          cout << "unsetenv " << name;
1422          result = 1;
1423          break;
1424        case Sh :
1425          cout << "unset " << name;
1426          result = 1;
1427          break;
1428        case Bat :
1429          cout << "set " << name << "=";
1430          result = 1;
1431          break;
1432        }
1433      break;
1434    case SymbolAlias :
1435      switch (mode)
1436        {
1437          case Csh :
1438            cout << "unalias " << name;
1439            result = 1;
1440            break;
1441          case Sh :
1442            cout << "unset " << name;
1443            result = 1;
1444            break;
1445        }
1446      break;
1447    case SymbolPath :
1448      temp = clean_macro_value ();
1449      switch (mode)
1450        {
1451        case Csh :
1452          if (temp == "")
1453            {
1454              cout << "unsetenv " << name;
1455            }
1456          else
1457            {
1458              cout << "setenv " << name << " " << temp;
1459            }
1460          result = 1;
1461          break;
1462        case Sh :
1463          cout << name << "=" << temp << "; export " << name;
1464          result = 1;
1465          break;
1466        case Bat :
1467          cout << "set " << name << "=" << temp;
1468          result = 1;
1469          break;
1470        }
1471      break;
1472    case SymbolCleanupScript :
1473      switch (mode)
1474        {
1475        case Csh :
1476          cout << "if ( -f " << name << ".csh ) then" << endl;
1477          cout << "  source " << name << ".csh" << endl;
1478          cout << "endif" << endl;
1479          result = 1;
1480          break;
1481        case Sh :
1482          cout << "if test -f " << name << ".sh; then" << endl;
1483          cout << "  . " << name << ".sh" << endl;
1484          cout << "fi" << endl;
1485          result = 1;
1486          break;
1487        case Bat :
1488          cout << "call " << name;
1489          result = 1;
1490          break;
1491        }
1492      break;
1493    }
1494
1495  return (result);
1496}
1497
1498//-------------------------------------------------------------
1499int Symbol::print (PrintMode mode)
1500{
1501  int result = 0;
1502  cmt_string temp;
1503
1504  temp = build_macro_value ();
1505
1506  bool empty = (temp.size () == 0) ? true : false;
1507
1508  switch (type)
1509    {
1510      case SymbolSet :
1511      case SymbolPath :
1512        switch (mode)
1513          {
1514            case Csh :
1515              if (empty) cout << "unsetenv " << name;
1516              else cout << "setenv " << name << " \"" << temp << "\"";
1517
1518              result = 1;
1519              break;
1520            case Sh :
1521              if (empty) cout << "unset " << name;
1522              else cout << name << "=\"" << temp << "\"; export " << name;
1523
1524              result = 1;
1525              break;
1526            case Bat :
1527              temp.replace_all ("/", "\\");
1528              cout << "set " << name << "=" << temp;
1529              result = 1;
1530              break;
1531          }
1532        break;
1533      case SymbolAlias :
1534        switch (mode)
1535          {
1536            case Csh :
1537              cout << "alias " << name <<
1538                  " \"" << temp << "\"";
1539              result = 1;
1540              break;
1541            case Sh :
1542              cout << "alias " << name <<
1543                  "=\"" << temp <<
1544                  "\"; export " << name;
1545              result = 1;
1546              break;
1547            case Bat :
1548              cout << "set " << name <<
1549                  "=" << temp;
1550              result = 1;
1551              break;
1552          }
1553        break;
1554      default :
1555        break;
1556    }
1557
1558  if (temp != "")
1559    {
1560      switch (type)
1561        {
1562          case SymbolSetupScript :
1563            switch (mode)
1564              {
1565                case Csh :
1566                  cout << "if ( -f " << name << ".csh ) then" << endl;
1567                  cout << "  source " << name << ".csh" << endl;
1568                  cout << "endif" << endl;
1569                  result = 1;
1570                  break;
1571                case Sh :
1572                  cout << "if test -f " << name << ".sh; then" << endl;
1573                  cout << "  . " << name << ".sh" << endl;
1574                  cout << "fi" << endl;
1575                  result = 1;
1576                  break;
1577                case Bat :
1578                  cout << "call " << name;
1579                  result = 1;
1580                  break;
1581              }
1582            break;
1583          default:
1584            break;
1585        }
1586    }
1587
1588  return (result);
1589}
1590
1591//-------------------------------------------------------------
1592cmt_string Symbol::build_macro_value () const
1593{
1594  cmt_string temp;
1595
1596  temp = builder->build (*this);
1597
1598  return (temp);
1599}
1600
1601//-------------------------------------------------------------
1602cmt_string Symbol::clean_macro_value () const
1603{
1604  cmt_string temp;
1605
1606  temp = builder->clean (*this);
1607
1608  return (temp);
1609}
1610
1611/**
1612
1613   Attempt to substitute into the symbol value all occurrences of
1614
1615      ${xxx}
1616      $(xxx)
1617      `xxx`
1618      %xxx%    [on Windows only]
1619
1620      by the appropriate value:
1621
1622        for `xxx` :
1623
1624            xxx is considered as a shell command. Value is the result of its execution
1625
1626        for other patterns:
1627
1628            if xxx is a symbol name, its value is substituted to the pattern
1629            otherwise, xxx is tried as an environment variable
1630
1631
1632     ===> In all cases, the pattern is filtered away.
1633
1634  */
1635cmt_string Symbol::resolve_macro_value (const cmt_string& tag_name)
1636{
1637  cmt_string temp = builder->build (*this, tag_name);
1638
1639  resolve_value (temp);
1640
1641  return (temp);
1642}
1643
1644//-------------------------------------------------------------
1645void Symbol::show_macro (PrintMode mode)
1646{
1647  if (Cmt::get_debug ())
1648    {
1649      cout << "Symbol::show_macro> " << name << endl;
1650    }
1651
1652  ActionType action = Cmt::get_action ();
1653
1654  cmt_string value = build_macro_value ();
1655
1656  if ((!Cmt::get_quiet ()) &&
1657      (action != action_build_tag_makefile) &&
1658      (action != action_show_macros) &&
1659      (action != action_show_actions) &&
1660      (action != action_show_sets))
1661    {
1662      cout << "#" << endl;
1663      cout << "# Selection : " << endl;
1664    }
1665
1666  if (value.size () > 0)
1667    {
1668      if ((action == action_show_macro) ||
1669          (action == action_show_macros) ||
1670          (action == action_show_sets) ||
1671          (action == action_show_set) ||
1672          (action == action_show_actions) ||
1673          (action == action_show_action) ||
1674          (action == action_build_tag_makefile) ||
1675          (action == action_load) ||
1676          (!Cmt::get_quiet ()))
1677        {
1678          if (mode == Make)
1679            {
1680              cout << name << "=";
1681            }
1682          else
1683            {
1684              cout << name << "='";
1685            }
1686        }
1687
1688      if ((action == action_show_macro_value) ||
1689          (action == action_show_set_value) ||
1690          (action == action_show_action_value))
1691        {
1692          expand (value);
1693        }
1694      else if (action == action_build_tag_makefile)
1695        {
1696            /*
1697               Unfortunately, the %xxx% pattern has to be kept on Unix. Therefore
1698               we cannot force all patterns to become $(xxx)
1699
1700               This was useful on Windows so as to only keep $(xxx)
1701             */
1702#ifdef WIN32
1703          suppress_OS_delimiters (value);
1704#endif
1705        }
1706
1707      cout << value;
1708
1709      if ((action == action_show_macro) ||
1710          (action == action_show_macros) ||
1711          (action == action_show_sets) ||
1712          (action == action_show_set) ||
1713          (action == action_show_actions) ||
1714          (action == action_show_action) ||
1715          (action == action_build_tag_makefile) ||
1716          (action == action_load) ||
1717          (!Cmt::get_quiet ()))
1718        {
1719          if (mode != Make)
1720            {
1721              cout << "'";
1722            }
1723#ifdef WIN32
1724          else
1725            {
1726              cout << " ";
1727            }
1728#endif
1729        }
1730
1731      cout << endl;
1732    }
1733}
1734
1735//-------------------------------------------------------------
1736void Symbol::clear_all ()
1737{
1738  static SymbolVector& Symbols = symbols ();
1739  static SymbolMap& SymbolMap = symbol_map ();
1740
1741  SymbolMap.clear ();
1742  Symbols.clear ();
1743}
1744
1745//-------------------------------------------------------------
1746void Symbol::expand (cmt_string& text)
1747{
1748  static cmt_regexp reg ("[$%`]");
1749
1750  if (!reg.match (text)) return;
1751
1752  resolve_value (text);
1753}
1754
1755//-------------------------------------------------------------
1756const cmt_string SetBuilder::build (const Symbol& symbol,
1757                                    const cmt_string& /*tag_name*/)
1758{
1759    // Control of recursivity
1760  static int level = 0;
1761
1762  int show_it = 0;
1763
1764  cmt_string temp;
1765  cmt_string previous_temp;
1766  cmt_string new_value;
1767  static const cmt_string empty;
1768
1769  ActionType action = Cmt::get_action ();
1770
1771  if (action == action_show_set)
1772    {
1773      if (symbol.name == Cmt::get_current_target ())
1774        {
1775             // Should not display on recursive calls
1776          if (level == 0) show_it = 1;
1777        }
1778    }
1779
1780  level++;
1781
1782  temp = "";
1783
1784  bool first_definition = true;
1785  bool defined = false;
1786
1787  for (int i = 0; i < symbol.value_lists.size (); i++)
1788    {
1789      const SymbolValueList& value_list = symbol.value_lists[i];
1790
1791      if ((value_list.use != 0) &&
1792          (value_list.use->discarded)) continue;
1793
1794      const int selected = value_list.select_first ();
1795
1796      if (selected < 0) continue;
1797
1798      SymbolValue& value = value_list.values[selected];
1799
1800      if (show_it)
1801        {
1802          value_list.show (symbol, value, first_definition);
1803        }
1804     
1805      if (value_list.discarded) continue;
1806
1807        //
1808        // One should accumulate values if it refers to
1809        // itself.
1810        //
1811     
1812      new_value = value.text;
1813     
1814      resolve_value_for_macros (new_value);
1815     
1816      switch (value_list.command_type)
1817        {
1818          case CommandSet :
1819
1820            if (!value_list.is_reflexive || 
1821                !symbol.value_is_reflexive (value.text))
1822              {
1823                resolve_value (new_value, symbol.name, temp);
1824                temp = new_value;
1825              }
1826            else if (temp == "")
1827              {
1828                temp = CmtSystem::getenv (symbol.name);
1829              }
1830
1831            if (!defined)
1832              {
1833                defined = true;
1834              }
1835            else
1836              {
1837                if ((!Cmt::get_quiet ()) &&
1838                    ((action == action_show_macro) ||
1839                     (action == action_show_set) ||
1840                     (action == action_show_action) ||
1841                     (action == action_show_macros) ||
1842                     (action == action_show_sets) ||
1843                     (action == action_show_actions)))
1844                  {
1845                    cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
1846
1847                    if (value_list.use != 0)
1848                      {
1849                        cerr << " in package " << value_list.use->get_package_name ();
1850                      }
1851
1852                    cerr << endl;
1853                  }
1854              }
1855
1856            break;
1857          case CommandSetAppend :
1858           
1859            if (new_value != "")
1860              {
1861                temp += new_value;
1862              }
1863           
1864            break;
1865          case CommandSetPrepend :
1866           
1867            if (new_value != "")
1868              {
1869                previous_temp = temp;
1870                temp = new_value;
1871                temp += previous_temp;
1872              }
1873           
1874            break;
1875          case CommandSetRemove :
1876           
1877            if (new_value != "")
1878              {
1879                temp.replace_all (new_value, empty);
1880              }
1881           
1882            break;
1883          case CommandSetRemoveRegexp :
1884           
1885            if (new_value != "")
1886              {
1887                cmt_regexp e (new_value);
1888                cmt_regexp::iterator it;
1889
1890                for (;;)
1891                  {
1892                    it = e.begin (temp);
1893                    if (it == e.end ()) break;
1894
1895                    temp.erase (it._pos, it._length);
1896                  }
1897              }
1898           
1899            break;
1900          case CommandAlias :
1901           
1902            resolve_value (new_value, symbol.name, temp);
1903            temp = new_value;
1904           
1905            break;
1906        }
1907    }
1908
1909  level--;
1910
1911  return (temp);
1912}
1913
1914static bool find_path_entry (const cmt_string& paths, const cmt_string& value)
1915{
1916  static const cmt_string path_separator = CmtSystem::path_separator ();
1917  static const cmt_string double_path_separator = path_separator + path_separator;
1918
1919  cmt_string complete_paths;
1920
1921  complete_paths = path_separator;
1922  complete_paths += paths;
1923  complete_paths += path_separator;
1924
1925  complete_paths.replace_all (double_path_separator, path_separator);
1926
1927  cmt_string complete_value;
1928  complete_value = path_separator;
1929  complete_value += value;
1930  complete_value += path_separator;
1931
1932  if (complete_paths.find (complete_value) == cmt_string::npos) return (false);
1933  else return (true);
1934}
1935
1936//-------------------------------------------------------------
1937const cmt_string PathBuilder::build (const Symbol& symbol,
1938                                     const cmt_string& /*tag_name*/)
1939{
1940    // Control of recursivity
1941  static int level = 0;
1942
1943  int show_it = 0;
1944
1945  cmt_string temp;
1946  cmt_string previous_temp;
1947  cmt_string new_value;
1948  static const cmt_string empty;
1949
1950  static cmt_string path_separator = CmtSystem::path_separator ();
1951
1952  ActionType action = Cmt::get_action ();
1953
1954  if (action == action_show_set)
1955    {
1956      if (symbol.name == Cmt::get_current_target ())
1957        {
1958            // Should not display on recursive calls
1959          if (level == 0) show_it = 1;
1960        }
1961    }
1962
1963  level++;
1964
1965  temp = CmtSystem::getenv (symbol.name);
1966
1967  bool first_definition = true;
1968  bool defined = false;
1969
1970  for (int i = 0; i < symbol.value_lists.size (); i++)
1971    {
1972      const SymbolValueList& value_list = symbol.value_lists[i];
1973
1974      if ((value_list.use != 0) &&
1975          (value_list.use->discarded)) continue;
1976
1977      const int selected = value_list.select_first ();
1978     
1979      if (selected < 0) continue;
1980 
1981      SymbolValue& value = value_list.values[selected];
1982         
1983      if (show_it)
1984        {
1985          value_list.show (symbol, value, first_definition);
1986        }
1987         
1988      if (value_list.discarded) continue;
1989
1990      new_value = value.text;
1991         
1992          //resolve_value (new_value);
1993      resolve_value_for_macros (new_value);
1994         
1995      switch (value_list.command_type)
1996        {
1997          case CommandPath :
1998           
1999            if (!value_list.is_reflexive || 
2000                !symbol.value_is_reflexive (value.text))
2001              {
2002                resolve_value (new_value, symbol.name, temp);
2003                temp = new_value;
2004
2005                if (!defined)
2006                  {
2007                    defined = true;
2008                  }
2009                else
2010                  {
2011                    if ((!Cmt::get_quiet ()) &&
2012                        ((action == action_show_macro) ||
2013                         (action == action_show_set) ||
2014                         (action == action_show_action) ||
2015                         (action == action_show_macros) ||
2016                         (action == action_show_sets) ||
2017                         (action == action_show_actions)))
2018                      {
2019                        cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
2020                       
2021                        if (value_list.use != 0)
2022                          {
2023                            cerr << " in package " << value_list.use->get_package_name ();
2024                          }
2025                       
2026                        cerr << endl;
2027                      }
2028                  }
2029              }
2030
2031            break;
2032          case CommandPathAppend :
2033             
2034            if (new_value != "")
2035              {
2036                if (!find_path_entry (temp, new_value))
2037                  {
2038                    if (temp != "") temp += path_separator;
2039                     
2040                    temp += new_value;
2041                  }
2042              }
2043                 
2044            break;
2045          case CommandPathPrepend :
2046             
2047            if (new_value != "")
2048              {
2049                if (!find_path_entry (temp, new_value))
2050                  {
2051                    previous_temp = temp;
2052                    temp = new_value;
2053                    if (previous_temp != "") temp += path_separator;
2054                    temp += previous_temp;
2055                  }
2056              }
2057                 
2058            break;
2059          case CommandPathRemove :
2060             
2061            if (new_value != "")
2062              {
2063                CmtSystem::cmt_string_vector paths;
2064                 
2065                CmtSystem::split (temp, path_separator, paths);
2066                 
2067                for (int j = 0; j < paths.size (); ++j)
2068                  {
2069                    cmt_string& s = paths[j];
2070                     
2071                    if (s.find (new_value) != cmt_string::npos)
2072                      {
2073                        s = "";
2074                      }
2075                  }
2076
2077                Cmt::vector_to_string (paths, path_separator, temp);
2078                temp.replace_all ("::", ":");
2079                temp.replace_all (";;", ";");
2080              }
2081             
2082            break;
2083          case CommandPathRemoveRegexp :
2084
2085            if (new_value != "")
2086              {
2087                cmt_regexp e (new_value);
2088
2089                CmtSystem::cmt_string_vector paths;
2090                 
2091                CmtSystem::split (temp, path_separator, paths);
2092                 
2093                for (int j = 0; j < paths.size (); ++j)
2094                  {
2095                    cmt_string& s = paths[j];
2096
2097                    if (CmtSystem::getenv ("TESTPRR") != "")
2098                      {
2099                        cout << "PRR> s=[" << s << "]";
2100                      }
2101
2102                    if (e.match (s))
2103                      {
2104                        s = "";
2105
2106                        if (CmtSystem::getenv ("TESTPRR") != "")
2107                          {
2108                            cout << " match ";
2109                          }
2110                      }
2111                    else
2112                      {
2113                        if (CmtSystem::getenv ("TESTPRR") != "")
2114                          {
2115                            cout << " no match ";
2116                          }
2117                      }
2118
2119                    if (CmtSystem::getenv ("TESTPRR") != "")
2120                      {
2121                        cout << endl;
2122                      }
2123                  }
2124
2125                Cmt::vector_to_string (paths, path_separator, temp);
2126                temp.replace_all ("::", ":");
2127                temp.replace_all (";;", ";");
2128              }
2129             
2130            break;
2131        }
2132
2133    }
2134
2135  level--;
2136 
2137  return (temp);
2138}
2139
2140//-------------------------------------------------------------
2141const cmt_string PathBuilder::clean (const Symbol& symbol,
2142                                     const cmt_string& /*tag_name*/)
2143{
2144    // Control of recursivity
2145  static int level = 0;
2146
2147  cmt_string temp;
2148  cmt_string new_value;
2149  static const cmt_string empty;
2150
2151  static cmt_string path_separator = CmtSystem::path_separator ();
2152
2153  temp = CmtSystem::getenv (symbol.name);
2154
2155    //cerr << "#####1 temp=" << temp << endl;
2156
2157  for (int i = 0; i < symbol.value_lists.size (); i++)
2158    {
2159      const SymbolValueList& value_list = symbol.value_lists[i];
2160
2161      if (value_list.discarded) continue;
2162
2163      if ((value_list.use != 0) &&
2164          (value_list.use->discarded)) continue;
2165
2166      const int selected = value_list.select_first ();
2167     
2168      if (selected < 0) continue;
2169 
2170      SymbolValue& value = value_list.values[selected];
2171         
2172      new_value = value.text;
2173         
2174          //resolve_value (new_value);
2175
2176        //cerr << "#####1 new_value=" << new_value << endl;
2177
2178      resolve_value_for_macros (new_value);
2179      resolve_value (new_value);
2180         
2181        //cerr << "#####2 new_value=" << new_value << endl;
2182
2183      switch (value_list.command_type)
2184        {
2185          case CommandPath :
2186           
2187            temp = "";
2188           
2189            break;
2190          case CommandPathAppend :
2191          case CommandPathPrepend :
2192          case CommandPathRemove :
2193
2194            if (new_value != "")
2195              {
2196                CmtSystem::cmt_string_vector paths;
2197                 
2198                CmtSystem::split (temp, path_separator, paths);
2199                 
2200                for (int j = 0; j < paths.size (); ++j)
2201                  {
2202                    cmt_string& s = paths[j];
2203                     
2204                    if (s.find (new_value) != cmt_string::npos)
2205                      {
2206                        s = "";
2207                      }
2208
2209                    if (j > 0)
2210                      {
2211                        cmt_string& s2 = paths[j-1];
2212                        if (s2 == s)
2213                          {
2214                            s2 = "";
2215                          }
2216                      }
2217                  }
2218
2219                Cmt::vector_to_string (paths, path_separator, temp);
2220                temp.replace_all ("::", ":");
2221                temp.replace_all (";;", ";");
2222              }
2223             
2224            break;
2225          case CommandPathRemoveRegexp :
2226
2227            if (new_value != "")
2228              {
2229                cmt_regexp e (new_value);
2230
2231                CmtSystem::cmt_string_vector paths;
2232                 
2233                CmtSystem::split (temp, path_separator, paths);
2234                 
2235                for (int j = 0; j < paths.size (); ++j)
2236                  {
2237                    cmt_string& s = paths[j];
2238                     
2239                    if (e.match (s))
2240                      {
2241                        s = "";
2242                      }
2243
2244                    if (j > 0)
2245                      {
2246                        cmt_string& s2 = paths[j-1];
2247                        if (s2 == s)
2248                          {
2249                            s2 = "";
2250                          }
2251                      }
2252                  }
2253
2254                Cmt::vector_to_string (paths, path_separator, temp);
2255                temp.replace_all ("::", ":");
2256                temp.replace_all (";;", ";");
2257              }
2258             
2259            break;
2260        }
2261    }
2262
2263    //cerr << "#####2 temp=" << temp << endl;
2264 
2265  return (temp);
2266}
2267
2268//-------------------------------------------------------------
2269const cmt_string MacroBuilder::build (const Symbol& symbol,
2270                                      const cmt_string& tag_name)
2271{
2272    // Control of recursivity
2273  static int level = 0;
2274
2275  cmt_string temp;
2276  cmt_string previous_temp;
2277  static const cmt_string empty;
2278  int show_it = 0;
2279
2280  ActionType action = Cmt::get_action ();
2281
2282  if (action == action_show_macro)
2283    {
2284      if (symbol.name == Cmt::get_current_target ())
2285        {
2286             // Should not display on recursive calls
2287          if (level == 0) show_it = 1;
2288        }
2289    }
2290
2291  level++;
2292
2293  temp = "";
2294
2295  int i;
2296
2297  bool first_definition = true;
2298  bool defined = false;
2299
2300  for (i = 0; i < symbol.value_lists.size (); i++)
2301    {
2302      const SymbolValueList& value_list = symbol.value_lists[i];
2303
2304      if ((value_list.use != 0) &&
2305          (value_list.use->discarded)) continue;
2306
2307      if (value_list.command_type != CommandMacroPrepend) continue;
2308
2309      const int selected = value_list.select_first (tag_name);
2310
2311      if (selected < 0) continue;
2312
2313      SymbolValue& value = value_list.values[selected];
2314
2315      if (show_it)
2316        {
2317          value_list.show (symbol, value, first_definition);
2318        }
2319
2320      if (value_list.discarded) continue;
2321
2322      previous_temp = temp;
2323      temp = value.text;
2324      temp += previous_temp;
2325    }
2326
2327  previous_temp = temp;
2328  temp = "";
2329
2330  first_definition = true;
2331
2332  for (i = 0; i < symbol.value_lists.size (); i++)
2333    {
2334      const SymbolValueList& value_list = symbol.value_lists[i];
2335
2336      if ((value_list.use != 0) &&
2337          (value_list.use->discarded)) continue;
2338
2339      if (value_list.command_type != CommandMacro) continue;
2340
2341      const int selected = value_list.select_first (tag_name);
2342
2343      if (selected < 0) continue;
2344
2345      SymbolValue& value = value_list.values[selected];
2346
2347      if (show_it)
2348        {
2349          value_list.show (symbol, value, first_definition);
2350        }
2351
2352      // WARNING:
2353      // Commented just for a test : should be uncommented after the test
2354      if (value_list.discarded) continue;
2355     
2356      if (!value_list.is_reflexive || 
2357          !symbol.value_is_reflexive (value.text))
2358        {
2359          temp = value.text;
2360
2361          if (!defined)
2362            {
2363              defined = true;
2364            }
2365          else
2366            {
2367              /*
2368              if ((!Cmt::get_quiet ()) &&
2369                  ((action == action_show_macro) ||
2370                   (action == action_show_set) ||
2371                   (action == action_show_action) ||
2372                   (action == action_show_macros) ||
2373                   (action == action_show_sets) ||
2374                   (action == action_show_actions)))
2375                {
2376                  cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
2377                 
2378                  if (value_list.use != 0)
2379                    {
2380                      cerr << " in package " << value_list.use->get_package_name ();
2381                    }
2382
2383                  cerr << endl;
2384                }
2385              */
2386            }
2387        }
2388    }
2389
2390  previous_temp += temp;
2391  temp = previous_temp;
2392
2393  for (i = 0; i < symbol.value_lists.size (); i++)
2394    {
2395      const SymbolValueList& value_list = symbol.value_lists[i];
2396
2397      if ((value_list.use != 0) &&
2398          (value_list.use->discarded)) continue;
2399
2400      if (value_list.command_type != CommandMacroAppend) continue;
2401
2402      const int selected = value_list.select_first (tag_name);
2403
2404      if (selected < 0) continue;
2405
2406      SymbolValue& value = value_list.values[selected];
2407
2408      if (show_it)
2409        {
2410          value_list.show (symbol, value, first_definition);
2411        }
2412
2413      if (value_list.discarded) continue;
2414
2415      temp += value.text;
2416    }
2417
2418  for (i = 0; i < symbol.value_lists.size (); i++)
2419    {
2420      const SymbolValueList& value_list = symbol.value_lists[i];
2421
2422      if ((value_list.use != 0) &&
2423          (value_list.use->discarded)) continue;
2424
2425      if ((value_list.command_type != CommandMacroRemove) &&
2426          (value_list.command_type != CommandMacroRemoveRegexp) &&
2427          (value_list.command_type != CommandMacroRemoveAll) &&
2428          (value_list.command_type != CommandMacroRemoveAllRegexp)) continue;
2429
2430      const int selected = value_list.select_first (tag_name);
2431
2432      if (selected < 0) continue;
2433
2434      SymbolValue& value = value_list.values[selected];
2435
2436      if (show_it)
2437        {
2438          value_list.show (symbol, value, first_definition);
2439        }
2440
2441      if (value_list.discarded) continue;
2442
2443      switch (value_list.command_type)
2444        {
2445          case CommandMacroRemove :
2446            temp.replace (value.text, empty);
2447            break;
2448          case CommandMacroRemoveRegexp :
2449            if (value.text != "")
2450              {
2451                cmt_regexp e (value.text);
2452                cmt_regexp::iterator it;
2453
2454                it = e.begin (temp);
2455                if (it != e.end ())
2456                  {
2457                    temp.erase (it._pos, it._length);
2458                  }
2459              }
2460            break;
2461          case CommandMacroRemoveAll :
2462            temp.replace_all (value.text, empty);
2463            break;
2464          case CommandMacroRemoveAllRegexp :
2465            if (value.text != "")
2466              {
2467                cmt_regexp e (value.text);
2468                cmt_regexp::iterator it;
2469
2470                for (;;)
2471                  {
2472                    it = e.begin (temp);
2473                    if (it != e.end ())
2474                      {
2475                        temp.erase (it._pos, it._length);
2476                      }
2477                    else
2478                      {
2479                        break;
2480                      }
2481                  }
2482              }
2483            break;
2484        }
2485    }
2486
2487  level--;
2488
2489  return (temp);
2490}
2491
2492//-------------------------------------------------------------
2493const cmt_string ScriptBuilder::build (const Symbol& symbol,
2494                                       const cmt_string& tag_name)
2495{
2496    // Control of recursivity
2497  static int level = 0;
2498
2499  static const cmt_string empty = "";
2500
2501  if (symbol.value_lists.size () > 0)
2502    {
2503      const SymbolValueList& value_list = symbol.value_lists[0];
2504
2505      if (value_list.discarded) return (empty);
2506
2507      if ((value_list.use != 0) &&
2508          (value_list.use->discarded)) return (empty);
2509    }
2510
2511  return (symbol.name);
2512}
2513
2514//-------------------------------------------------------------
2515const cmt_string ActionBuilder::build (const Symbol& symbol,
2516                                       const cmt_string& tag_name)
2517{
2518    // Control of recursivity
2519  static int level = 0;
2520
2521  cmt_string temp;
2522  cmt_string previous_temp;
2523  static const cmt_string empty;
2524  int show_it = 0;
2525
2526  ActionType action = Cmt::get_action ();
2527
2528  if (action == action_show_action)
2529    {
2530      if (symbol.name == Cmt::get_current_target ())
2531        {
2532             // Should not display on recursive calls
2533          if (level == 0) show_it = 1;
2534        }
2535    }
2536
2537  level++;
2538
2539  int i;
2540
2541  bool first_definition = true;
2542  bool defined = false;
2543
2544  temp = "";
2545
2546  for (i = 0; i < symbol.value_lists.size (); i++)
2547    {
2548      const SymbolValueList& value_list = symbol.value_lists[i];
2549
2550      if ((value_list.use != 0) &&
2551          (value_list.use->discarded)) continue;
2552
2553      if (value_list.command_type != CommandAction) continue;
2554
2555      const int selected = value_list.select_first (tag_name);
2556
2557      if (selected < 0) continue;
2558
2559      SymbolValue& value = value_list.values[selected];
2560
2561      if (show_it)
2562        {
2563          value_list.show (symbol, value, first_definition);
2564        }
2565
2566      // WARNING:
2567      // Commented just for a test : should be uncommented after the test
2568      if (value_list.discarded) continue;
2569     
2570      if (!value_list.is_reflexive || 
2571          !symbol.value_is_reflexive (value.text))
2572        {
2573          temp = value.text;
2574
2575          if (!defined)
2576            {
2577              defined = true;
2578            }
2579          else
2580            {
2581              if ((!Cmt::get_quiet ()) &&
2582                  ((action == action_show_macro) ||
2583                   (action == action_show_set) ||
2584                   (action == action_show_action) ||
2585                   (action == action_show_macros) ||
2586                   (action == action_show_sets) ||
2587                   (action == action_show_actions)))
2588                {
2589                  cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
2590                 
2591                  if (value_list.use != 0)
2592                    {
2593                      cerr << " in package " << value_list.use->get_package_name ();
2594                    }
2595
2596                  cerr << endl;
2597                }
2598            }
2599        }
2600    }
2601
2602  level--;
2603
2604  return (temp);
2605}
2606
2607//-------------------------------------------------------------
2608int SymbolValueList::select_first (const cmt_string& tag_name) const
2609{
2610  int priority = 0;
2611  int value_number;
2612  int selected = -1;
2613
2614  Tag* the_tag = 0;
2615
2616  if (tag_name != "") the_tag = Tag::find (tag_name);
2617
2618  for (value_number = 0;
2619       value_number < values.size ();
2620       value_number++)
2621    {
2622      const SymbolValue& value = values[value_number];
2623
2624      const Tag* tag = value.tag;
2625
2626      if (the_tag == 0)
2627        {
2628          if (!tag->is_selected ()) continue;
2629        }
2630      else
2631        {
2632          if (tag != the_tag) continue;
2633          selected = value_number;
2634        }
2635
2636      //
2637      // Only the first value at a given priority is
2638      // selected (which implies the '>' test instead
2639      // of '>=')
2640      //
2641
2642      if (tag->get_priority () > priority)
2643        {
2644          priority = tag->get_priority ();
2645          selected = value_number;
2646        }
2647    }
2648
2649  return (selected);
2650}
2651
2652//-------------------------------------------------------------
2653int SymbolValueList::select_last () const
2654{
2655  int priority = 0;
2656  int value_number;
2657  int selected = -1;
2658
2659  for (value_number = 0;
2660       value_number < values.size ();
2661       value_number++)
2662    {
2663      SymbolValue& value = values[value_number];
2664
2665      const Tag* tag = value.tag;
2666
2667      if (tag->is_selected ())
2668        {
2669          //
2670          // The last value at a given priority is
2671          // selected (which implies the '>=' test instead
2672          // of '>')
2673          //
2674
2675          if (tag->get_priority () >= priority)
2676            {
2677              priority = tag->get_priority ();
2678              selected = value_number;
2679            }
2680        }
2681    }
2682
2683  return (selected);
2684}
2685
2686//-------------------------------------------------------------
2687void SymbolValueList::show (const Symbol& symbol, 
2688                            const SymbolValue& value, 
2689                            bool& first_definition) const
2690{
2691  cmt_string discarded_text;
2692  cmt_string define_text;
2693  ActionType action = Cmt::get_action ();
2694
2695  if (value.text == "") return;
2696
2697  if (discarded) discarded_text = " (discarded by override)";
2698  else discarded_text = "";
2699
2700  if (first_definition) define_text = "defines";
2701  else define_text = "overrides";
2702
2703  cout << "# Package ";
2704  if (use != 0)
2705    {
2706      cout << use->get_package_name () << " " << use->version;
2707    }
2708
2709  switch (command_type)
2710    {
2711      case CommandSet :
2712        cout << " " << define_text << " set " << symbol.name << " as ";
2713        first_definition = false;
2714        break;
2715      case CommandSetAppend :
2716        cout << " appends to set " << symbol.name << " : ";
2717        break;
2718      case CommandSetPrepend :
2719        cout << " prepends to set " << symbol.name << " : ";
2720        break;
2721      case CommandSetRemove :
2722        cout << " removes from set " << symbol.name << " : ";
2723        break;
2724      case CommandSetRemoveRegexp :
2725        cout << " removes RE from set " << symbol.name << " : ";
2726        break;
2727      case CommandAlias :
2728        cout << " " << define_text << " alias " << symbol.name << " as ";
2729        first_definition = false;
2730        break;
2731      case CommandPath :
2732        cout << " " << define_text << " path " << symbol.name << " as ";
2733        first_definition = false;
2734        break;
2735      case CommandPathAppend :
2736        cout << " appends to path " << symbol.name << " : ";
2737        break;
2738      case CommandPathPrepend :
2739        cout << " prepends to path " << symbol.name << " : ";
2740        break;
2741      case CommandPathRemove :
2742        cout << " removes from path " << symbol.name << " : ";
2743        break;
2744      case CommandPathRemoveRegexp :
2745        cout << " removes RE from path " << symbol.name << " : ";
2746        break;
2747      case CommandMacroPrepend :
2748        cout << " prepends to macro " << symbol.name << " : ";
2749        break;
2750      case CommandMacro :
2751        cout << " " << define_text << " macro " << symbol.name << " as ";
2752        break;
2753      case CommandMacroAppend :
2754        cout << " appends to macro " << symbol.name << " : ";
2755        break;
2756      case CommandMacroRemove :
2757        cout << " remove from macro " << symbol.name << " : ";
2758        break;
2759      case CommandMacroRemoveRegexp :
2760        cout << " remove RE from macro " << symbol.name << " : ";
2761        break;
2762      case CommandMacroRemoveAll :
2763        cout << " remove all from macro " << symbol.name << " : ";
2764        break;
2765      case CommandMacroRemoveAllRegexp :
2766        cout << " remove all RE from macro " << symbol.name << " : ";
2767        break;
2768      case CommandAction :
2769        cout << " " << define_text << " action " << symbol.name << " as ";
2770        first_definition = false;
2771        break;
2772    }
2773
2774  cout << "'" << value.text << "'";
2775         
2776  Tag* selected_tag = value.tag;
2777         
2778  if ((selected_tag == 0) ||
2779      (selected_tag == Tag::get_default ()))
2780    {
2781      cout << " for default tag";
2782    }
2783  else
2784    {
2785      cout << " for tag '" << selected_tag->get_name () << "'";
2786    }
2787 
2788  cout << discarded_text << endl;
2789}
2790
Note: See TracBrowser for help on using the repository browser.