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