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