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