cmt_symbol.cxx Source File

Main Page Class Hierarchy Compound List File List Compound Members File Members

# cmt_symbol.cxx

Go to the documentation of this file.

    00001 #include <stdio.h>
    00002 #include <stdlib.h>
    00003 #include <string.h>
    00004 #include <ctype.h>
    00005
    00006 #include "cmt_use.h"
    00007 #include "cmt_symbol.h"
    00008 #include "cmt_system.h"
    00009 #include "cmt_database.h"
    00010
    00011 //-------------------------------------------------------------
    00012 class SetBuilder : public ValueBuilder
    00013 {
    00014 public:
    00015   const cmt_string& build (const Symbol& symbol,
    00016                            const cmt_string& tag_name = "");
    00017   const cmt_string& clean (const Symbol& symbol,
    00018                            const cmt_string& tag_name = "")
    00019       {
    00020         static const cmt_string empty = "";
    00021         return (empty);
    00022       }
    00023
    00024 private:
    00025   cmt_string temp;
    00026 };
    00027 //-------------------------------------------------------------
    00028
    00029 //-------------------------------------------------------------
    00030 class PathBuilder : public ValueBuilder
    00031 {
    00032 public:
    00033   const cmt_string& build (const Symbol& symbol,
    00034                            const cmt_string& tag_name = "");
    00035   const cmt_string& clean (const Symbol& symbol,
    00036                            const cmt_string& tag_name = "");
    00037
    00038 private:
    00039   cmt_string temp;
    00040 };
    00041 //-------------------------------------------------------------
    00042
    00043 //-------------------------------------------------------------
    00044 class MacroBuilder : public ValueBuilder
    00045 {
    00046 public:
    00047   const cmt_string& build (const Symbol& symbol,
    00048                            const cmt_string& tag_name = "");
    00049   const cmt_string& clean (const Symbol& symbol,
    00050                            const cmt_string& tag_name = "")
    00051       {
    00052         static const cmt_string empty = "";
    00053         return (empty);
    00054       }
    00055
    00056 private:
    00057   cmt_string temp;
    00058 };
    00059 //-------------------------------------------------------------
    00060
    00061 //-------------------------------------------------------------
    00062 class ScriptBuilder : public ValueBuilder
    00063 {
    00064 public:
    00065   const cmt_string& build (const Symbol& symbol,
    00066                            const cmt_string& tag_name = "");
    00067   const cmt_string& clean (const Symbol& symbol,
    00068                            const cmt_string& tag_name = "")
    00069       {
    00070         static const cmt_string empty = "";
    00071         return (empty);
    00072       }
    00073
    00074 private:
    00075   cmt_string temp;
    00076 };
    00077 //-------------------------------------------------------------
    00078
    00079 //-------------------------------------------------------------
    00080 class symbol_marker
    00081 {
    00082 public:
    00083   symbol_marker ()
    00084   {
    00085     ptr = cmt_string::npos;
    00086     pattern = 0;
    00087     intro = 0;
    00088   }
    00089
    00090   symbol_marker (int a_ptr, char a_pattern, int a_intro)
    00091   {
    00092     ptr = a_ptr;
    00093     pattern = a_pattern;
    00094     intro = a_intro;
    00095   }
    00096
    00097   symbol_marker (const symbol_marker& other)
    00098   {
    00099     ptr = other.ptr;
    00100     pattern = other.pattern;
    00101     intro = other.intro;
    00102   }
    00103
    00104   void set (int a_ptr, char a_pattern, int a_intro)
    00105   {
    00106     ptr = a_ptr;
    00107     pattern = a_pattern;
    00108     intro = a_intro;
    00109   }
    00110
    00111   static symbol_marker& get_lowest (symbol_marker markers[], int last)
    00112   {
    00113     static symbol_marker result;
    00114
    00115     // discards trailing npos
    00116     while ((last >= 0) && (markers[last].ptr == cmt_string::npos)) last--;
    00117
    00118     if (last < 0) return (result);
    00119
    00120     int i;
    00121
    00122     // since we've passed the previous test,
    00123     // at least one entry (last) is not npos.
    00124     // Now discards other npos by moving them to the end
    00125
    00126     for (i = 0; i <= last; i++)
    00127       {
    00128         if (markers[i].ptr == cmt_string::npos)
    00129           {
    00130             markers[i] = markers[last];
    00131             last--;
    00132             if (last < 0) break;
    00133           }
    00134       }
    00135
    00136     if (last < 0) return (result);
    00137
    00138     // now all entries in [0, last] are not npos
    00139     // let's sort the lowest one in [0]
    00140
    00141     for (i = 1; i <= last;)
    00142       {
    00143         if (markers[0].ptr > markers[i].ptr)
    00144           {
    00145             symbol_marker temp = markers[0];
    00146             markers[0] = markers[i];
    00147             markers[i] = temp;
    00148             i = 1;
    00149           }
    00150         else
    00151           {
    00152             i++;
    00153             if (i > last) break;
    00154           }
    00155       }
    00156
    00157     return (markers[0]);
    00158   }
    00159
    00160   int ptr;
    00161   char pattern;
    00162   int intro;
    00163 };
    00164 //-------------------------------------------------------------
    00165
    00166 //-------------------------------------------------------------
    00167 static SetBuilder Set;
    00168 static PathBuilder Path;
    00169 static MacroBuilder Macro;
    00170 static ScriptBuilder Script;
    00171 //-------------------------------------------------------------
    00172
    00173 //-------------------------------------------------------------
    00174 static void resolve_value (cmt_string& text,
    00175                            const cmt_string& macro_name,
    00176                            const cmt_string& value)
    00177 {
    00178   static cmt_string pattern;
    00179
    00180   pattern = "${";
    00181   pattern += macro_name;
    00182   pattern += "}";
    00183
    00184   text.replace_all (pattern, value);
    00185
    00186   pattern = "$(";
    00187   pattern += macro_name;
    00188   pattern += ")";
    00189
    00190   text.replace_all (pattern, value);
    00191
    00192 #ifdef WIN32
    00193   pattern = "%";
    00194   pattern += macro_name;
    00195   pattern += "%";
    00196
    00197   text.replace_all (pattern, value);
    00198 #endif
    00199 }
    00200
    00201 //-------------------------------------------------------------
    00202 static void resolve_value (cmt_string& text)
    00203 {
    00204   cmt_string pattern;
    00205   cmt_string macro_name;
    00206   char end_pattern;
    00207
    00208   int start = 0;
    00209
    00210   for (;;)
    00211     {
    00212       //
    00213       // Try and substitute all ${xxx} $(xxx) or %xxx% patterns
    00214       // using symbol values.
    00215       //
    00216
    00217       int begin;
    00218       int end;
    00219
    00220       symbol_marker markers[3];
    00221
    00222       markers[0].set (text.find (start, "$("), ')', 2);
    00223       markers[1].set (text.find (start, "${"), '}', 2);
    00224       markers[2].set (text.find (start, "%"), '%', 1);
    00225
    00226       // Find the first of three patterns
    00227
    00228       symbol_marker& marker = symbol_marker::get_lowest (markers, 2);
    00229
    00230       begin = marker.ptr;
    00231
    00232       if (begin == cmt_string::npos) break;
    00233
    00234       end_pattern = marker.pattern;
    00235       start = begin + marker.intro;
    00236
    00237       end = text.find (start, end_pattern);
    00238       if (end == cmt_string::npos)
    00239         {
    00240           // The pattern is a fake one (no ending!)
    00241           start++;
    00242           continue;
    00243         }
    00244
    00245       // This should never happen...
    00246       if (end < begin) break;
    00247
    00248       // Extract the complete pattern
    00249       text.substr (begin, end - begin + 1, pattern);
    00250
    00251       // Then only the macro name
    00252       text.substr (begin + marker.intro, end - begin - marker.intro, macro_name);
    00253
    00254       Symbol* macro = Symbol::find (macro_name);
    00255       if (macro != 0)
    00256         {
    00257           // Macro found
    00258           cmt_string value = macro->resolve_macro_value ();
    00259           text.replace_all (pattern, value);
    00260
    00261           // The substitution will restart from the same place
    00262           // allowing for recursive replacements
    00263           start = begin;
    00264         }
    00265       else
    00266         {
    00267           // Macro not found. Look for env. variable
    00268           cmt_string value = CmtSystem::getenv (macro_name);
    00269
    00270           // When the env. variable is not defined, the replacement is empty
    00271           // thus all $(xxx) ${xxx} %xxx% patterns are always filtered away.
    00272           text.replace_all (pattern, value);
    00273
    00274           // The substitution will restart from the same place
    00275           // allowing for recursive replacements
    00276           start = begin;
    00277         }
    00278     }
    00279 }
    00280
    00281 //-------------------------------------------------------------
    00282 static void resolve_value_for_macros (cmt_string& text)
    00283 {
    00284   cmt_string pattern;
    00285   cmt_string macro_name;
    00286   char end_pattern;
    00287
    00288   int start = 0;
    00289
    00290   for (;;)
    00291     {
    00292       //
    00293       // Try and substitute all ${xxx} $(xxx) or %xxx% patterns
    00294       // using symbol values, only when the symbol is a macro.
    00295       //
    00296
    00297       int begin;
    00298       int end;
    00299
    00300       symbol_marker markers[3];
    00301
    00302       markers[0].set (text.find (start, "$("), ')', 2);
    00303       markers[1].set (text.find (start, "${"), '}', 2);
    00304       markers[2].set (text.find (start, "%"), '%', 1);
    00305
    00306       // Find the first of three patterns
    00307
    00308       symbol_marker& marker = symbol_marker::get_lowest (markers, 2);
    00309
    00310       begin = marker.ptr;
    00311
    00312       if (begin == cmt_string::npos) break;
    00313
    00314       end_pattern = marker.pattern;
    00315       start = begin + marker.intro;
    00316
    00317       end = text.find (start, end_pattern);
    00318       if (end == cmt_string::npos)
    00319         {
    00320           // The pattern is a fake one (no ending!)
    00321           start++;
    00322           continue;
    00323         }
    00324
    00325       // This should never happen...
    00326       if (end < begin) break;
    00327
    00328       // Extract the complete pattern
    00329       text.substr (begin, end - begin + 1, pattern);
    00330
    00331       // Then only the macro name
    00332       text.substr (begin + marker.intro, end - begin - marker.intro, macro_name);
    00333
    00334       Symbol* macro = Symbol::find (macro_name);
    00335       if ((macro != 0) &&
    00336           (macro->command == CommandMacro))
    00337         {
    00338           // Macro found
    00339           cmt_string value = macro->resolve_macro_value ();
    00340           text.replace_all (pattern, value);
    00341
    00342           // The substitution will restart from the same place
    00343           // allowing for recursive replacements
    00344           start = begin;
    00345         }
    00346       else if ((macro == 0) ||
    00347                ((macro->command == CommandSet) || (macro->command == CommandPath)))
    00348         {
    00349           // Set found
    00350           // ensure that the delimiters will match the OS dependent
    00351           // delimiters.
    00352
    00353           cmt_string pattern_close = marker.pattern;
    00354
    00355           if (pattern_close != CmtSystem::ev_close ())
    00356             {
    00357               cmt_string new_pattern;
    00358
    00359               new_pattern = CmtSystem::ev_open ();
    00360               new_pattern += macro_name;
    00361               new_pattern += CmtSystem::ev_close ();
    00362
    00363               text.replace (pattern, new_pattern);
    00364             }
    00365
    00366           start = end + 1;
    00367         }
    00368       else
    00369         {
    00370           start = end + 1;
    00371         }
    00372     }
    00373 }
    00374
    00379 static void suppress_OS_delimiters (cmt_string& text)
    00380 {
    00381   cmt_string pattern;
    00382   cmt_string macro_name;
    00383   char end_pattern;
    00384
    00385   int start = 0;
    00386
    00387   for (;;)
    00388     {
    00389       int begin;
    00390       int end;
    00391
    00392       symbol_marker markers[3];
    00393
    00394       markers[0].set (text.find (start, "${"), '}', 2);
    00395
    00396 #ifdef WIN32
    00397       markers[1].set (text.find (start, "%"), '%', 1);
    00398 #endif
    00399
    00400       // Find the first of three patterns
    00401
    00402       symbol_marker& marker = symbol_marker::get_lowest (markers, 2);
    00403
    00404       begin = marker.ptr;
    00405
    00406       if (begin == cmt_string::npos) break;
    00407
    00408       end_pattern = marker.pattern;
    00409       start = begin + marker.intro;
    00410
    00411       end = text.find (start, end_pattern);
    00412       if (end == cmt_string::npos)
    00413         {
    00414           // The pattern is a fake one (no ending!)
    00415           start++;
    00416           continue;
    00417         }
    00418
    00419       // This should never happen...
    00420       if (end < begin) break;
    00421
    00422       // Extract the complete pattern
    00423       text.substr (begin, end - begin + 1, pattern);
    00424
    00425       // Then only the macro name
    00426       text.substr (begin + marker.intro, end - begin - marker.intro, macro_name);
    00427
    00428       cmt_string new_pattern;
    00429
    00430       new_pattern = "$(";
    00431       new_pattern += macro_name;
    00432       new_pattern += ")";
    00433
    00434       text.replace (pattern, new_pattern);
    00435
    00436       start = begin;
    00437     }
    00438 }
    00439
    00440 //-------------------------------------------------------------
    00441 /*                                                          */
    00442 /*  Operations on SymbolValues                              */
    00443 /*                                                          */
    00444 //-------------------------------------------------------------
    00445
    00446 //-------------------------------------------------------------
    00447 SymbolValue::SymbolValue ()
    00448 {
    00449   tag = 0;
    00450 }
    00451
    00452 //-------------------------------------------------------------
    00453 SymbolValue::~SymbolValue ()
    00454 {
    00455   tag = 0;
    00456 }
    00457
    00458 //-------------------------------------------------------------
    00459 /*                                                          */
    00460 /*  Operations on Symbols                                   */
    00461 /*                                                          */
    00462 //-------------------------------------------------------------
    00463
    00464 //-------------------------------------------------------------
    00465 Symbol* Symbol::create (const cmt_string& name,
    00466                         CommandType command,
    00467                         ScopeType scope)
    00468 {
    00469   static SymbolVector& Symbols = symbols ();
    00470
    00471   {
    00472     Symbol* symbol;
    00473
    00474     symbol = find (name);
    00475     if (symbol != 0) return (symbol);
    00476   }
    00477
    00478   Symbol& symbol = Symbols.add ();
    00479
    00480   symbol.name    = name;
    00481   symbol.scope   = scope;
    00482   symbol.command = command;
    00483
    00484   symbol.value_lists.clear ();
    00485
    00486   switch (command)
    00487     {
    00488     case CommandSet:
    00489     case CommandSetAppend:
    00490     case CommandSetPrepend:
    00491     case CommandSetRemove:
    00492       symbol.builder = &Set;
    00493       symbol.command = CommandSet;
    00494       break;
    00495     case CommandPath:
    00496     case CommandPathAppend:
    00497     case CommandPathPrepend:
    00498     case CommandPathRemove:
    00499       symbol.builder = &Path;
    00500       break;
    00501     case CommandAlias:
    00502       symbol.builder = &Set;
    00503       break;
    00504     case CommandMacro:
    00505     case CommandMacroAppend:
    00506     case CommandMacroPrepend:
    00507     case CommandMacroRemove:
    00508     case CommandMacroRemoveAll:
    00509       symbol.builder = &Macro;
    00510       symbol.command = CommandMacro;
    00511       break;
    00512     case CommandSetupScript:
    00513     case CommandCleanupScript:
    00514       symbol.builder = &Script;
    00515       break;
    00516     }
    00517
    00518   symbol.selected_value = -1;
    00519
    00520   return (&symbol);
    00521 }
    00522
    00523 //-------------------------------------------------------------
    00524 Symbol* Symbol::find (const cmt_string& name)
    00525 {
    00526   static SymbolVector& Symbols = symbols ();
    00527
    00528   int number;
    00529   Symbol* result = 0;
    00530
    00531   for (number = 0; number < Symbols.size (); number++)
    00532     {
    00533       Symbol& s = Symbols[number];
    00534
    00535       if (s.name == name)
    00536         {
    00537           result = &s;
    00538         }
    00539     }
    00540
    00541   return (result);
    00542 }
    00543
    00544 //-------------------------------------------------------------
    00545 int Symbol::symbol_number ()
    00546 {
    00547   static SymbolVector& Symbols = symbols ();
    00548
    00549   return (Symbols.size ());
    00550 }
    00551
    00552 //-------------------------------------------------------------
    00553 Symbol::SymbolVector& Symbol::symbols ()
    00554 {
    00555   static Database& db = Database::instance ();
    00556   static SymbolVector& Symbols = db.symbols ();
    00557
    00558   return (Symbols);
    00559 }
    00560
    00561 //-------------------------------------------------------------
    00562 Symbol& Symbol::symbol (int index)
    00563 {
    00564   static SymbolVector& Symbols = symbols ();
    00565
    00566   return (Symbols[index]);
    00567 }
    00568
    00569 //-------------------------------------------------------------
    00570 void Symbol::action (const CmtSystem::cmt_string_vector& words,
    00571                      CommandType command_type,
    00572                      Use* use)
    00573 {
    00574   int number;
    00575   Symbol* symbol;
    00576   Tag* tag;
    00577
    00578   if (words.size () < 1) return;
    00579   cmt_string name = words[1];
    00580
    00581   if ((command_type == CommandSetupScript) ||
    00582       (command_type == CommandCleanupScript))
    00583     {
    00584       cmt_string full_name;
    00585
    00586       Symbol::expand (name);
    00587
    00588       if (name != "")
    00589         {
    00590           if (CmtSystem::absolute_path (name))
    00591             {
    00592               full_name = name;
    00593             }
    00594           else
    00595             {
    00596 #ifdef WIN32
    00597               full_name = "%";
    00598 #else
    00599               full_name = "${";
    00600 #endif
    00601               full_name += use->prefix;
    00602               full_name += "ROOT";
    00603 #ifdef WIN32
    00604               full_name += "%";
    00605 #else
    00606               full_name += "}";
    00607 #endif
    00608               full_name += CmtSystem::file_separator ();
    00609               if (use->style == cmt_style) full_name += "cmt";
    00610               else full_name += "mgr";
    00611               full_name += CmtSystem::file_separator ();
    00612               full_name += name;
    00613             }
    00614
    00615           symbol = create (full_name, command_type, Cmt::get_scope ());
    00616           symbol->add_value_to_list (command_type, use,
    00617                                      Tag::get_default (), full_name);
    00618         }
    00619     }
    00620   else
    00621     {
    00622       if (words.size () < 2) return;
    00623       const cmt_string& default_value = words[2];
    00624
    00625       if ((Cmt::get_current_access () == UserMode) &&
    00626           (Cmt::get_scope () == ScopePrivate)) return;
    00627
    00628       symbol = create (name, command_type, Cmt::get_scope ());
    00629
    00630       /*
    00631         Parse the default value.
    00632       */
    00633
    00634       symbol->add_value_to_list (command_type, use,
    00635                                  Tag::get_default (), default_value);
    00636
    00637       /*
    00638         Then parse all specific values
    00639
    00640         <tag> <value>
    00641         ...
    00642       */
    00643
    00644       number = 3;
    00645       while (number < (words.size () - 1))
    00646         {
    00647           const cmt_string& tag_name = words[number];
    00648           const cmt_string& value = words[number + 1];
    00649
    00650           tag = Tag::find (tag_name);
    00651           if (tag == 0)
    00652             {
    00653               tag = Tag::add (tag_name, PriorityUserTag, "use", use);
    00654             }
    00655
    00656           symbol->add_value_to_list (command_type, use, tag, value);
    00657
    00658           number += 2;
    00659         }
    00660
    00661       if (name == "CMTPATH")
    00662         {
    00663           Cmt::configure_cmt_path (use);
    00664         }
    00665       else if (name == "CMTSITE")
    00666         {
    00667           Cmt::configure_site_tag (use);
    00668         }
    00669       else if (name == "CMTCONFIG")
    00670         {
    00671             //cerr << "redefining CMTCONFIG" << endl;
    00672           Cmt::configure_tags (use);
    00673         }
    00674       else if (name == "CMTHOME")
    00675         {
    00676           Cmt::configure_home (use);
    00677         }
    00678       else if (name == "CMTUSERCONTEXT")
    00679         {
    00680           Cmt::configure_user_context (use);
    00681         }
    00682       else if (name.find ("_native_version") != cmt_string::npos)
    00683         {
    00684           cmt_string n = use->package;
    00685           n += "_native_version";
    00686
    00687           if (name == n)
    00688             {
    00689               use->set_native_version (true);
    00690             }
    00691         }
    00692     }
    00693 }
    00694
    00695 //-------------------------------------------------------------
    00696 int Symbol::is_selected (const cmt_string& name)
    00697 {
    00698   Symbol* symbol;
    00699   int number;
    00700   int value_number;
    00701
    00702   symbol = find (name);
    00703   if (symbol == 0) return (0);
    00704
    00705   if (symbol->value_lists.size () == 0) return (0);
    00706
    00707   for (number = 0;
    00708        number < symbol->value_lists.size ();
    00709        number++)
    00710     {
    00711       const SymbolValueList& value_list = symbol->value_lists[number];
    00712
    00713       if (value_list.discarded) continue;
    00714
    00715       if ((value_list.command_type == CommandMacro) ||
    00716           (value_list.command_type == CommandSet) ||
    00717           (value_list.command_type == CommandSetAppend) ||
    00718           (value_list.command_type == CommandSetPrepend) ||
    00719           (value_list.command_type == CommandSetRemove) ||
    00720           (value_list.command_type == CommandAlias))
    00721         {
    00722           for (value_number = 0;
    00723                value_number < value_list.values.size ();
    00724                value_number++)
    00725             {
    00726               Tag* tag;
    00727
    00728               SymbolValue& value = value_list.values[value_number];
    00729
    00730               tag = value.tag;
    00731               if ((tag == 0) ||
    00732                   (tag == Tag::get_default ()) ||
    00733                   (tag->selected != 0))
    00734                 {
    00735                   return (1);
    00736                 }
    00737             }
    00738         }
    00739     }
    00740
    00741   return (0);
    00742 }
    00743
    00744 //-------------------------------------------------------------
    00745 Symbol::Symbol ()
    00746 {
    00747   name = "";
    00748 }
    00749
    00750 //-------------------------------------------------------------
    00751 Symbol::~Symbol ()
    00752 {
    00753 }
    00754
    00758 bool Symbol::value_is_reflexive (const cmt_string& text) const
    00759 {
    00760   bool result = false;
    00761   int text_length = text.size ();
    00762
    00763   if (text_length == (name.size () + 3))
    00764     {
    00765       static cmt_string temp;
    00766
    00767       if (text[0] == '$')
    00768         {
    00769           if (text[1] == '(')
    00770             {
    00771               temp = "$(";
    00772               temp += name;
    00773               temp += ")";
    00774
    00775               if (text == temp)
    00776                 {
    00777                   result = true;
    00778                 }
    00779             }
    00780           else if (text[1] == '{')
    00781             {
    00782               temp = "${";
    00783               temp += name;
    00784               temp += "}";
    00785
    00786               if (text == temp)
    00787                 {
    00788                   result = true;
    00789                 }
    00790             }
    00791         }
    00792     }
    00793   else if (text_length == (name.size () + 2))
    00794     {
    00795       static cmt_string temp;
    00796
    00797       temp = "%";
    00798       temp += name;
    00799       temp += "%";
    00800
    00801       if (text == temp)
    00802         {
    00803           result = true;
    00804         }
    00805     }
    00806
    00807   return (result);
    00808 }
    00809
    00810 //-------------------------------------------------------------
    00811 void Symbol::add_value_to_list (CommandType command_type,
    00812                                 Use* use,
    00813                                 Tag* tag,
    00814                                 const cmt_string& text)
    00815 {
    00816   SymbolValueList* value_list = 0;
    00817   bool is_reflexive = false;
    00818
    00819     //
    00820     // First pickup the most recent value_list
    00821     //
    00822   if (value_lists.size () > 0) value_list = &(value_lists.back ());
    00823
    00824     //
    00825     //  Create a new value list is we switch to another use or
    00826     //  if we switch to a new command_type (eg. switching from
    00827     //  macro to macro_append).
    00828     //
    00829   if ((value_list == 0) ||
    00830       (use != value_list->use) ||
    00831       (command_type != value_list->command_type) ||
    00832       (tag == Tag::get_default ()))
    00833     {
    00834       value_list = &(value_lists.add ());
    00835       value_list->use = use;
    00836       value_list->command_type = command_type;
    00837       value_list->values.clear ();
    00838       value_list->discarded = false;
    00839       value_list->is_reflexive = false;
    00840     }
    00841   else
    00842     {
    00843       value_list = &(value_lists[value_lists.size () - 1]);
    00844     }
    00845
    00846   is_reflexive = value_list->is_reflexive;
    00847
    00848     //
    00849     //  If the command_type is command_macro or command_set,
    00850     // this is considered as a full re-set of this symbol
    00851     //   In this case, we have to discard all previous values
    00852     //
    00853     //  However, we'd like to exclude from this logic the cases where
    00854     //  the value is **exactly*
    00855     //
    00856     //     $(<symbol>)
    00857     //     ${<symbol>}
    00858     //     %<symbol>%
    00859     //
    00860     //   which would then mean that we do not reset the value but rather
    00861     //  override it.
    00862     //
    00863
    00864     //
    00865     // Inside this value_list, we add this new tag-value pair.
    00866     //
    00867
    00868   if ((command_type == CommandMacro) ||
    00869       (command_type == CommandSet))
    00870     {
    00871         //
    00872         // Check whether we have to hide previous settings by this new definition
    00873         //  (of course this is only useful if there WERE previous settings)
    00874         //
    00875       if ((value_lists.size () >= 1) && (!is_reflexive))
    00876         {
    00877           if (value_is_reflexive (text))
    00878             {
    00879               value_list->is_reflexive = true;
    00880               is_reflexive = true;
    00881             }
    00882           else
    00883             {
    00884                 //cerr << "...discarding old values for symbol " << name << endl;
    00885
    00886               for (int i = 0; i < (value_lists.size () - 1); i++)
    00887                 {
    00888                   SymbolValueList& vl = value_lists[i];
    00889
    00890                   if ((vl.use != 0) &&
    00891                       (vl.use->discarded)) continue;
    00892
    00893                   vl.discarded = true;
    00894                 }
    00895             }
    00896         }
    00897     }
    00898
    00899   SymbolValue& value = value_list->values.add ();
    00900
    00901   value.tag = tag;
    00902   value.text = text;
    00903   value.selected = 0;
    00904 }
    00905
    00906 //-------------------------------------------------------------
    00907 //  Check symbol's scope against current scope and symbol
    00908 // type.
    00909 //-------------------------------------------------------------
    00910 int Symbol::valid (PrintMode mode)
    00911 {
    00912   int result = 0;
    00913
    00914   if (command == CommandMacro) return (0);
    00915   if (command == CommandMacroPrepend) return (0);
    00916   if (command == CommandMacroAppend) return (0);
    00917   if (command == CommandMacroRemove) return (0);
    00918   if (command == CommandMacroRemoveAll) return (0);
    00919   if (scope != Cmt::get_scope ()) return (0);
    00920
    00921   return (1);
    00922 }
    00923
    00924 //-------------------------------------------------------------
    00925 void Symbol::all_print (PrintMode mode)
    00926 {
    00927   static SymbolVector& Symbols = symbols ();
    00928
    00929   int number;
    00930
    00931   if (Symbols.size () == 0) return;
    00932
    00933   for (number = 0; number < Symbol::symbol_number (); number++)
    00934     {
    00935       Symbol& symbol = Symbol::symbol (number);
    00936
    00937       if ((symbol.command == CommandSet) ||
    00938           (symbol.command == CommandAlias) ||
    00939           (symbol.command == CommandSetupScript))
    00940         {
    00941           if (symbol.print (1, mode))
    00942             {
    00943               if (mode == Bat)
    00944                 {
    00945                   cout << endl;
    00946                 }
    00947               else
    00948                 {
    00949                   //cout << "; ";
    00950                   cout << endl;
    00951                 }
    00952             }
    00953         }
    00954     }
    00955
    00956   for (number = 0; number < Symbol::symbol_number (); number++)
    00957     {
    00958       Symbol& symbol = Symbol::symbol (number);
    00959
    00960       if ((symbol.command != CommandPath) &&
    00961           (symbol.command != CommandPathAppend) &&
    00962           (symbol.command != CommandPathPrepend) &&
    00963           (symbol.command != CommandPathRemove)) continue;
    00964
    00965       if (symbol.print (1, mode))
    00966         {
    00967           if (mode == Bat)
    00968             {
    00969               cout << endl;
    00970             }
    00971           else
    00972             {
    00973               //cout << "; ";
    00974               cout << endl;
    00975             }
    00976         }
    00977     }
    00978 }
    00979
    00980 //-------------------------------------------------------------
    00981 void Symbol::all_print_clean (PrintMode mode)
    00982 {
    00983   static SymbolVector& Symbols = symbols ();
    00984
    00985   int number;
    00986
    00987   if (Symbols.size () == 0) return;
    00988
    00989   for (number = Symbols.size () - 1; number >= 0; number--)
    00990     {
    00991       Symbol& symbol = Symbols[number];
    00992
    00993       if ((symbol.command == CommandSet) ||
    00994           (symbol.command == CommandAlias) ||
    00995           (symbol.command == CommandCleanupScript))
    00996         {
    00997           if (symbol.print_clean (0, mode))
    00998             {
    00999               cout << endl;
    01000             }
    01001         }
    01002     }
    01003
    01004   for (number = Symbols.size () - 1; number >= 0; number--)
    01005     {
    01006       Symbol& symbol = Symbols[number];
    01007
    01008       if ((symbol.command != CommandPath) &&
    01009           (symbol.command != CommandPathAppend) &&
    01010           (symbol.command != CommandPathPrepend) &&
    01011           (symbol.command != CommandPathRemove)) continue;
    01012
    01013       if (symbol.print_clean (0, mode))
    01014         {
    01015           cout << endl;
    01016         }
    01017     }
    01018 }
    01019
    01020 //-------------------------------------------------------------
    01021 int Symbol::print_clean (int tabs, PrintMode mode)
    01022 {
    01023   int result = 0;
    01024   static cmt_string temp;
    01025
    01026   if (name == "CMTCONFIG") return (0);
    01027
    01028   switch (command)
    01029     {
    01030     case CommandSet :
    01031       switch (mode)
    01032         {
    01033         case Csh :
    01034           cout << "unsetenv " << name;
    01035           result = 1;
    01036           break;
    01037         case Sh :
    01038           cout << "unset " << name;
    01039           result = 1;
    01040           break;
    01041         case Bat :
    01042           cout << "set " << name << "=";
    01043           result = 1;
    01044           break;
    01045         }
    01046       break;
    01047     case CommandAlias :
    01048       switch (mode)
    01049         {
    01050           case Csh :
    01051             cout << "unalias " << name;
    01052             result = 1;
    01053             break;
    01054           case Sh :
    01055             cout << "unset " << name;
    01056             result = 1;
    01057             break;
    01058         }
    01059       break;
    01060     case CommandPath :
    01061     case CommandPathAppend :
    01062     case CommandPathPrepend :
    01063     case CommandPathRemove :
    01064       temp = clean_macro_value ();
    01065       switch (mode)
    01066         {
    01067         case Csh :
    01068           if (temp == "")
    01069             {
    01070               cout << "unsetenv " << name;
    01071             }
    01072           else
    01073             {
    01074               cout << "setenv " << name << " " << temp;
    01075             }
    01076           result = 1;
    01077           break;
    01078         case Sh :
    01079           cout << name << "=" << temp << "; export " << name;
    01080           result = 1;
    01081           break;
    01082         case Bat :
    01083           cout << "set " << name << "=" << temp;
    01084           result = 1;
    01085           break;
    01086         }
    01087       break;
    01088     case CommandCleanupScript :
    01089       switch (mode)
    01090         {
    01091         case Csh :
    01092           cout << "if ( -f " << name << ".csh ) then" << endl;
    01093           cout << "  source " << name << ".csh" << endl;
    01094           cout << "endif" << endl;
    01095           result = 1;
    01096           break;
    01097         case Sh :
    01098           cout << "if test -f " << name << ".sh; then" << endl;
    01099           cout << "  . " << name << ".sh" << endl;
    01100           cout << "fi" << endl;
    01101           result = 1;
    01102           break;
    01103         case Bat :
    01104           cout << "call " << name;
    01105           result = 1;
    01106           break;
    01107         }
    01108       break;
    01109     }
    01110
    01111   return (result);
    01112 }
    01113
    01114 //-------------------------------------------------------------
    01115 int Symbol::print (int tabs, PrintMode mode)
    01116 {
    01117   int result = 0;
    01118   static cmt_string temp;
    01119
    01120   temp = build_macro_value ();
    01121
    01122   switch (command)
    01123     {
    01124       case CommandSet :
    01125       case CommandPath :
    01126       case CommandPathAppend :
    01127       case CommandPathPrepend :
    01128       case CommandPathRemove :
    01129         switch (mode)
    01130           {
    01131             case Csh :
    01132               cout << "setenv " << name <<
    01133                   " \"" << temp << "\"";
    01134               result = 1;
    01135               break;
    01136             case Sh :
    01137               cout << name <<
    01138                   "=\"" << temp <<
    01139                   "\"; export " << name;
    01140               result = 1;
    01141               break;
    01142             case Bat :
    01143               temp.replace_all ("/", "\\");
    01144               cout << "set " << name <<
    01145                   "=" << temp;
    01146               result = 1;
    01147               break;
    01148           }
    01149         break;
    01150       case CommandAlias :
    01151         switch (mode)
    01152           {
    01153             case Csh :
    01154               cout << "alias " << name <<
    01155                   " \"" << temp << "\"";
    01156               result = 1;
    01157               break;
    01158             case Sh :
    01159               cout << "alias " << name <<
    01160                   "=\"" << temp <<
    01161                   "\"; export " << name;
    01162               result = 1;
    01163               break;
    01164             case Bat :
    01165               cout << "set " << name <<
    01166                   "=" << temp;
    01167               result = 1;
    01168               break;
    01169           }
    01170         break;
    01171       default :
    01172         break;
    01173     }
    01174
    01175   if (temp != "")
    01176     {
    01177       switch (command)
    01178         {
    01179           case CommandSetupScript :
    01180             switch (mode)
    01181               {
    01182                 case Csh :
    01183                   cout << "if ( -f " << name << ".csh ) then" << endl;
    01184                   cout << "  source " << name << ".csh" << endl;
    01185                   cout << "endif" << endl;
    01186                   result = 1;
    01187                   break;
    01188                 case Sh :
    01189                   cout << "if test -f " << name << ".sh; then" << endl;
    01190                   cout << "  . " << name << ".sh" << endl;
    01191                   cout << "fi" << endl;
    01192                   result = 1;
    01193                   break;
    01194                 case Bat :
    01195                   cout << "call " << name;
    01196                   result = 1;
    01197                   break;
    01198               }
    01199             break;
    01200           default:
    01201             break;
    01202         }
    01203     }
    01204
    01205   return (result);
    01206 }
    01207
    01208 //-------------------------------------------------------------
    01209 cmt_string Symbol::build_macro_value () const
    01210 {
    01211   cmt_string temp;
    01212
    01213   temp = builder->build (*this);
    01214
    01215   return (temp);
    01216 }
    01217
    01218 //-------------------------------------------------------------
    01219 cmt_string Symbol::clean_macro_value () const
    01220 {
    01221   cmt_string temp;
    01222
    01223   temp = builder->clean (*this);
    01224
    01225   return (temp);
    01226 }
    01227
    01228 //-------------------------------------------------------------
    01229 cmt_string Symbol::resolve_macro_value (const cmt_string& tag_name)
    01230 {
    01231   cmt_string temp = builder->build (*this, tag_name);
    01232   cmt_string pattern;
    01233   cmt_string macro_name;
    01234   char end_pattern;
    01235
    01236   int start = 0;
    01237
    01238   for (;;)
    01239     {
    01240       int begin;
    01241       int end;
    01242
    01243       symbol_marker markers[3];
    01244
    01245       markers[0].set (temp.find (start, "$("), ')', 2);
    01246       markers[1].set (temp.find (start, "${"), '}', 2);
    01247       markers[2].set (temp.find (start, "%"), '%', 1);
    01248
    01249       // Find the first of three patterns
    01250
    01251       symbol_marker& marker = symbol_marker::get_lowest (markers, 2);
    01252
    01253       begin = marker.ptr;
    01254
    01255       if (begin == cmt_string::npos) break;
    01256
    01257       end_pattern = marker.pattern;
    01258       start = begin + marker.intro;
    01259
    01260       end = temp.find (start, end_pattern);
    01261       if (end == cmt_string::npos)
    01262         {
    01263           // The pattern is a fake one (no ending!)
    01264           start++;
    01265           continue;
    01266         }
    01267
    01268       if (end < begin) break;
    01269
    01270       temp.substr (begin, end - begin + 1, pattern);
    01271       temp.substr (begin + marker.intro, end - begin - marker.intro, macro_name);
    01272       Symbol* macro = find (macro_name);
    01273       if (macro != 0)
    01274         {
    01275           // Macro found
    01276           cmt_string value = macro->resolve_macro_value (tag_name);
    01277           temp.replace_all (pattern, value);
    01278           start = begin;
    01279         }
    01280       else
    01281         {
    01282           // Macro not found. Look for env. variable
    01283           cmt_string value = CmtSystem::getenv (macro_name);
    01284           temp.replace_all (pattern, value);
    01285           start = begin;
    01286         }
    01287     }
    01288
    01289   return (temp);
    01290 }
    01291
    01292 //-------------------------------------------------------------
    01293 void Symbol::show_macro (PrintMode mode)
    01294 {
    01295   ActionType action = Cmt::get_action ();
    01296
    01297   cmt_string value = build_macro_value ();
    01298
    01299   if ((!Cmt::get_quiet ()) &&
    01300       (action != action_build_tag_makefile) &&
    01301       (action != action_show_macros) &&
    01302       (action != action_show_sets))
    01303     {
    01304       cout << "#" << endl;
    01305       cout << "# Selection : " << endl;
    01306     }
    01307
    01308   if (value.size () > 0)
    01309     {
    01310       if ((action == action_show_macro) ||
    01311           (action == action_show_macros) ||
    01312           (action == action_show_sets) ||
    01313           (action == action_show_set) ||
    01314           (action == action_build_tag_makefile) ||
    01315           (action == action_load) ||
    01316           (!Cmt::get_quiet ()))
    01317         {
    01318           if (mode == Make)
    01319             {
    01320               cout << name << "=";
    01321             }
    01322           else
    01323             {
    01324               cout << name << "='";
    01325             }
    01326         }
    01327
    01328       if ((action == action_show_macro_value) ||
    01329           (action == action_show_set_value))
    01330         {
    01331           expand (value);
    01332         }
    01333       else if (action == action_build_tag_makefile)
    01334         {
    01335           suppress_OS_delimiters (value);
    01336         }
    01337
    01338       cout << value;
    01339
    01340       if ((action == action_show_macro) ||
    01341           (action == action_show_macros) ||
    01342           (action == action_show_sets) ||
    01343           (action == action_show_set) ||
    01344           (action == action_build_tag_makefile) ||
    01345           (action == action_load) ||
    01346           (!Cmt::get_quiet ()))
    01347         {
    01348           if (mode != Make)
    01349             {
    01350               cout << "'";
    01351             }
    01352 #ifdef WIN32
    01353           else
    01354             {
    01355               cout << " ";
    01356             }
    01357 #endif
    01358         }
    01359
    01360       cout << endl;
    01361     }
    01362 }
    01363
    01364 //-------------------------------------------------------------
    01365 void Symbol::clear_all ()
    01366 {
    01367   static SymbolVector& Symbols = symbols ();
    01368
    01369   Symbols.clear ();
    01370 }
    01371
    01372 //-------------------------------------------------------------
    01373 void Symbol::expand (cmt_string& text)
    01374 {
    01375   resolve_value (text);
    01376 }
    01377
    01378 //-------------------------------------------------------------
    01379 const cmt_string& SetBuilder::build (const Symbol& symbol,
    01380                                      const cmt_string& /*tag_name*/)
    01381 {
    01382   int show_it = 0;
    01383
    01384   static cmt_string previous_temp;
    01385   cmt_string new_value;
    01386   static const cmt_string empty;
    01387
    01388   if (Cmt::get_action () == action_show_set)
    01389     {
    01390       if (symbol.name == Cmt::get_current_target ())
    01391         {
    01392           show_it = 1;
    01393         }
    01394     }
    01395
    01396   temp = "";
    01397
    01398   for (int i = 0; i < symbol.value_lists.size (); i++)
    01399     {
    01400       const SymbolValueList& value_list = symbol.value_lists[i];
    01401
    01402       if (value_list.discarded) continue;
    01403
    01404       if ((value_list.use != 0) &&
    01405           (value_list.use->discarded)) continue;
    01406
    01407       const int selected = value_list.select_first ();
    01408
    01409       if (selected < 0) continue;
    01410
    01411       SymbolValue& value = value_list.values[selected];
    01412
    01413       if (show_it)
    01414         {
    01415           cout << "# Package ";
    01416           if (value_list.use != 0)
    01417             {
    01418               cout << value_list.use->package << " " << value_list.use->version;
    01419             }
    01420         }
    01421
    01422         //
    01423         // One should accumulate values if it refers to
    01424         // itself.
    01425         //
    01426
    01427       new_value = value.text;
    01428
    01429       resolve_value_for_macros (new_value);
    01430
    01431       switch (value_list.command_type)
    01432         {
    01433           case CommandSet :
    01434
    01435             if (show_it)
    01436               {
    01437                 cout << " defines set " << symbol.name << " as ";
    01438               }
    01439
    01440             if (!value_list.is_reflexive ||
    01441                 !symbol.value_is_reflexive (value.text))
    01442               {
    01443                 resolve_value (new_value, symbol.name, temp);
    01444                 temp = new_value;
    01445               }
    01446             else if (temp == "")
    01447               {
    01448                 temp = CmtSystem::getenv (symbol.name);
    01449               }
    01450
    01451             break;
    01452           case CommandSetAppend :
    01453
    01454             if (show_it)
    01455               {
    01456                 cout << " appends to set " << symbol.name << " : ";
    01457               }
    01458
    01459             if (new_value != "")
    01460               {
    01461                 temp += new_value;
    01462               }
    01463
    01464             break;
    01465           case CommandSetPrepend :
    01466
    01467             if (show_it)
    01468               {
    01469                 cout << " prepends to set " << symbol.name << " : ";
    01470               }
    01471
    01472             if (new_value != "")
    01473               {
    01474                 previous_temp = temp;
    01475                 temp = new_value;
    01476                 temp += previous_temp;
    01477               }
    01478
    01479             break;
    01480           case CommandSetRemove :
    01481
    01482             if (show_it)
    01483               {
    01484                 cout << " removes from set " << symbol.name << " : ";
    01485               }
    01486
    01487             if (new_value != "")
    01488               {
    01489                 temp.replace_all (new_value, empty);
    01490               }
    01491
    01492             break;
    01493           case CommandAlias :
    01494
    01495             if (show_it)
    01496               {
    01497                 cout << " defines alias " << symbol.name << " as ";
    01498               }
    01499
    01500             resolve_value (new_value, symbol.name, temp);
    01501             temp = new_value;
    01502
    01503             break;
    01504         }
    01505
    01506       if (show_it)
    01507         {
    01508           cout << "'" << value.text << "'";
    01509
    01510           Tag* selected_tag = value.tag;
    01511
    01512           if ((selected_tag == 0) ||
    01513               (selected_tag == Tag::get_default ()))
    01514             {
    01515               cout << " for default tag";
    01516             }
    01517           else
    01518             {
    01519               cout << " for tag '" << selected_tag->name << "'";
    01520             }
    01521
    01522           cout << endl;
    01523         }
    01524     }
    01525
    01526   return (temp);
    01527 }
    01528
    01529 static bool find_path_entry (const cmt_string& paths, const cmt_string& value)
    01530 {
    01531   static const cmt_string path_separator = CmtSystem::path_separator ();
    01532   static const cmt_string double_path_separator = path_separator + path_separator;
    01533
    01534   cmt_string complete_paths;
    01535
    01536   complete_paths = path_separator;
    01537   complete_paths += paths;
    01538   complete_paths += path_separator;
    01539
    01540   complete_paths.replace_all (double_path_separator, path_separator);
    01541
    01542   cmt_string complete_value;
    01543   complete_value = path_separator;
    01544   complete_value += value;
    01545   complete_value += path_separator;
    01546
    01547   if (complete_paths.find (complete_value) == cmt_string::npos) return (false);
    01548   else return (true);
    01549 }
    01550
    01551 //-------------------------------------------------------------
    01552 const cmt_string& PathBuilder::build (const Symbol& symbol,
    01553                                       const cmt_string& /*tag_name*/)
    01554 {
    01555   int show_it = 0;
    01556
    01557   static cmt_string previous_temp;
    01558   cmt_string new_value;
    01559   static const cmt_string empty;
    01560
    01561   static cmt_string path_separator = CmtSystem::path_separator ();
    01562
    01563   if (Cmt::get_action () == action_show_set)
    01564     {
    01565       if (symbol.name == Cmt::get_current_target ())
    01566         {
    01567           show_it = 1;
    01568         }
    01569     }
    01570
    01571   temp = CmtSystem::getenv (symbol.name);
    01572
    01573   for (int i = 0; i < symbol.value_lists.size (); i++)
    01574     {
    01575       const SymbolValueList& value_list = symbol.value_lists[i];
    01576
    01577       if (value_list.discarded) continue;
    01578
    01579       if ((value_list.use != 0) &&
    01580           (value_list.use->discarded)) continue;
    01581
    01582       const int selected = value_list.select_first ();
    01583
    01584       if (selected < 0) continue;
    01585
    01586       SymbolValue& value = value_list.values[selected];
    01587
    01588       if (show_it)
    01589         {
    01590           cout << "# Package ";
    01591           if (value_list.use != 0)
    01592             {
    01593               cout << value_list.use->package << " " << value_list.use->version;
    01594             }
    01595         }
    01596
    01597       new_value = value.text;
    01598
    01599           //resolve_value (new_value);
    01600       resolve_value_for_macros (new_value);
    01601
    01602       switch (value_list.command_type)
    01603         {
    01604           case CommandPath :
    01605
    01606             if (show_it)
    01607               {
    01608                 cout << " defines path " << symbol.name << " as ";
    01609               }
    01610
    01611             if (!value_list.is_reflexive ||
    01612                 !symbol.value_is_reflexive (value.text))
    01613               {
    01614                 resolve_value (new_value, symbol.name, temp);
    01615                 temp = new_value;
    01616               }
    01617
    01618             break;
    01619           case CommandPathAppend :
    01620
    01621             if (show_it)
    01622               {
    01623                 cout << " appends to path " << symbol.name << " : ";
    01624               }
    01625
    01626             if (new_value != "")
    01627               {
    01628                 if (!find_path_entry (temp, new_value))
    01629                   {
    01630                     if (temp != "") temp += path_separator;
    01631
    01632                     temp += new_value;
    01633                   }
    01634               }
    01635
    01636             break;
    01637           case CommandPathPrepend :
    01638
    01639             if (show_it)
    01640               {
    01641                 cout << " prepends to path " << symbol.name << " : ";
    01642               }
    01643
    01644             if (new_value != "")
    01645               {
    01646                 if (!find_path_entry (temp, new_value))
    01647                   {
    01648                     previous_temp = temp;
    01649                     temp = new_value;
    01650                     if (previous_temp != "") temp += path_separator;
    01651                     temp += previous_temp;
    01652                   }
    01653               }
    01654
    01655             break;
    01656           case CommandPathRemove :
    01657
    01658             if (show_it)
    01659               {
    01660                 cout << " removes from path " << symbol.name << " : ";
    01661               }
    01662
    01663             if (new_value != "")
    01664               {
    01665                 static CmtSystem::cmt_string_vector paths;
    01666
    01667                 CmtSystem::split (temp, path_separator, paths);
    01668
    01669                 for (int j = 0; j < paths.size (); ++j)
    01670                   {
    01671                     cmt_string& s = paths[j];
    01672
    01673                     if (s.find (new_value) != cmt_string::npos)
    01674                       {
    01675                         s = "";
    01676                       }
    01677                   }
    01678
    01679                 Cmt::vector_to_string (paths, path_separator, temp);
    01680                 temp.replace_all ("::", ":");
    01681                 temp.replace_all (";;", ";");
    01682               }
    01683
    01684             break;
    01685         }
    01686
    01687       if (show_it)
    01688         {
    01689           cout << "'" << value.text << "'";
    01690
    01691           Tag* selected_tag = value.tag;
    01692
    01693           if ((selected_tag == 0) ||
    01694               (selected_tag == Tag::get_default ()))
    01695             {
    01696               cout << " for default tag";
    01697             }
    01698           else
    01699             {
    01700               cout << " for tag '" << selected_tag->name << "'";
    01701             }
    01702
    01703           cout << endl;
    01704         }
    01705     }
    01706
    01707   return (temp);
    01708 }
    01709
    01710 //-------------------------------------------------------------
    01711 const cmt_string& PathBuilder::clean (const Symbol& symbol,
    01712                                       const cmt_string& /*tag_name*/)
    01713 {
    01714   int show_it = 0;
    01715
    01716   static cmt_string previous_temp;
    01717   cmt_string new_value;
    01718   static const cmt_string empty;
    01719
    01720   static cmt_string path_separator = CmtSystem::path_separator ();
    01721
    01722   temp = CmtSystem::getenv (symbol.name);
    01723
    01724     //cerr << "#####1 temp=" << temp << endl;
    01725
    01726   for (int i = 0; i < symbol.value_lists.size (); i++)
    01727     {
    01728       const SymbolValueList& value_list = symbol.value_lists[i];
    01729
    01730       if (value_list.discarded) continue;
    01731
    01732       if ((value_list.use != 0) &&
    01733           (value_list.use->discarded)) continue;
    01734
    01735       const int selected = value_list.select_first ();
    01736
    01737       if (selected < 0) continue;
    01738
    01739       SymbolValue& value = value_list.values[selected];
    01740
    01741       new_value = value.text;
    01742
    01743           //resolve_value (new_value);
    01744
    01745         //cerr << "#####1 new_value=" << new_value << endl;
    01746
    01747       resolve_value_for_macros (new_value);
    01748       resolve_value (new_value);
    01749
    01750         //cerr << "#####2 new_value=" << new_value << endl;
    01751
    01752       switch (value_list.command_type)
    01753         {
    01754           case CommandPath :
    01755
    01756             temp = "";
    01757
    01758             break;
    01759           case CommandPathAppend :
    01760           case CommandPathPrepend :
    01761           case CommandPathRemove :
    01762
    01763             if (new_value != "")
    01764               {
    01765                 static CmtSystem::cmt_string_vector paths;
    01766
    01767                 CmtSystem::split (temp, path_separator, paths);
    01768
    01769                 for (int j = 0; j < paths.size (); ++j)
    01770                   {
    01771                     cmt_string& s = paths[j];
    01772
    01773                     if (s.find (new_value) != cmt_string::npos)
    01774                       {
    01775                         s = "";
    01776                       }
    01777
    01778                     if (j > 0)
    01779                       {
    01780                         cmt_string& s2 = paths[j-1];
    01781                         if (s2 == s)
    01782                           {
    01783                             s2 = "";
    01784                           }
    01785                       }
    01786                   }
    01787
    01788                 Cmt::vector_to_string (paths, path_separator, temp);
    01789                 temp.replace_all ("::", ":");
    01790                 temp.replace_all (";;", ";");
    01791               }
    01792
    01793             break;
    01794         }
    01795     }
    01796
    01797     //cerr << "#####2 temp=" << temp << endl;
    01798
    01799   return (temp);
    01800 }
    01801
    01802 //-------------------------------------------------------------
    01803 const cmt_string& MacroBuilder::build (const Symbol& symbol,
    01804                                        const cmt_string& tag_name)
    01805 {
    01806   static cmt_string previous_temp;
    01807   static const cmt_string empty;
    01808   int show_it = 0;
    01809
    01810   if (Cmt::get_action () == action_show_macro)
    01811     {
    01812       if (symbol.name == Cmt::get_current_target ())
    01813         {
    01814           show_it = 1;
    01815         }
    01816     }
    01817
    01818   temp = "";
    01819
    01820   int i;
    01821
    01822   for (i = 0; i < symbol.value_lists.size (); i++)
    01823     {
    01824       const SymbolValueList& value_list = symbol.value_lists[i];
    01825
    01826       if (value_list.discarded) continue;
    01827
    01828       if ((value_list.use != 0) &&
    01829           (value_list.use->discarded)) continue;
    01830
    01831       if (value_list.command_type != CommandMacroPrepend) continue;
    01832
    01833       const int selected = value_list.select_first (tag_name);
    01834
    01835       if (selected < 0) continue;
    01836
    01837       SymbolValue& value = value_list.values[selected];
    01838
    01839       if (show_it)
    01840         {
    01841           cout << "# Package ";
    01842           if (value_list.use != 0)
    01843             {
    01844               cout << value_list.use->package << " " << value_list.use->version;
    01845             }
    01846           cout << " prepends to macro " << symbol.name << " : ";
    01847         }
    01848
    01849       temp += value.text;
    01850
    01851       if (show_it)
    01852         {
    01853           cout << "'" << value.text << "'";
    01854
    01855           Tag* selected_tag = value.tag;
    01856
    01857           if ((selected_tag == 0) ||
    01858               (selected_tag == Tag::get_default ()))
    01859             {
    01860               cout << " for default tag";
    01861             }
    01862           else
    01863             {
    01864               cout << " for tag '" << selected_tag->name << "'";
    01865             }
    01866
    01867           cout << endl;
    01868         }
    01869     }
    01870
    01871   previous_temp = temp;
    01872   temp = "";
    01873
    01874   for (i = 0; i < symbol.value_lists.size (); i++)
    01875     {
    01876       const SymbolValueList& value_list = symbol.value_lists[i];
    01877
    01878       if (value_list.discarded) continue;
    01879
    01880       if ((value_list.use != 0) &&
    01881           (value_list.use->discarded)) continue;
    01882
    01883       if (value_list.command_type != CommandMacro) continue;
    01884
    01885       const int selected = value_list.select_first (tag_name);
    01886
    01887       if (selected >= 0)
    01888         {
    01889           SymbolValue& value = value_list.values[selected];
    01890
    01891           if (show_it)
    01892             {
    01893               cout << "# Package ";
    01894               if (value_list.use != 0)
    01895                 {
    01896                   cout << value_list.use->package << " " << value_list.use->version;
    01897                 }
    01898               cout << " defines macro " << symbol.name << " as ";
    01899             }
    01900
    01901           if (!value_list.is_reflexive ||
    01902               !symbol.value_is_reflexive (value.text))
    01903             {
    01904               temp = value.text;
    01905             }
    01906
    01907           if (show_it)
    01908             {
    01909               cout << "'" << value.text << "'";
    01910
    01911               Tag* selected_tag = value.tag;
    01912
    01913               if ((selected_tag == 0) ||
    01914                   (selected_tag == Tag::get_default ()))
    01915                 {
    01916                   cout << " for default tag";
    01917                 }
    01918               else
    01919                 {
    01920                   cout << " for tag '" << selected_tag->name << "'";
    01921                 }
    01922
    01923               cout << endl;
    01924             }
    01925         }
    01926     }
    01927
    01928   previous_temp += temp;
    01929   temp = previous_temp;
    01930
    01931   for (i = 0; i < symbol.value_lists.size (); i++)
    01932     {
    01933       const SymbolValueList& value_list = symbol.value_lists[i];
    01934
    01935       if (value_list.discarded) continue;
    01936
    01937       if ((value_list.use != 0) &&
    01938           (value_list.use->discarded)) continue;
    01939
    01940       if (value_list.command_type != CommandMacroAppend) continue;
    01941
    01942       const int selected = value_list.select_first (tag_name);
    01943
    01944       if (selected < 0) continue;
    01945
    01946       SymbolValue& value = value_list.values[selected];
    01947
    01948       if (show_it)
    01949         {
    01950           cout << "# Package ";
    01951           if (value_list.use != 0)
    01952             {
    01953               cout << value_list.use->package << " " << value_list.use->version;
    01954             }
    01955           cout << " appends to macro " << symbol.name << " : ";
    01956         }
    01957
    01958       temp += value.text;
    01959
    01960       if (show_it)
    01961         {
    01962           cout << "'" << value.text << "'";
    01963
    01964           Tag* selected_tag = value.tag;
    01965
    01966           if ((selected_tag == 0) ||
    01967               (selected_tag == Tag::get_default ()))
    01968             {
    01969               cout << " for default tag";
    01970             }
    01971           else
    01972             {
    01973               cout << " for tag '" << selected_tag->name << "'";
    01974             }
    01975
    01976           cout << endl;
    01977         }
    01978     }
    01979
    01980   for (i = 0; i < symbol.value_lists.size (); i++)
    01981     {
    01982       const SymbolValueList& value_list = symbol.value_lists[i];
    01983
    01984       if (value_list.discarded) continue;
    01985
    01986       if ((value_list.use != 0) &&
    01987           (value_list.use->discarded)) continue;
    01988
    01989       if ((value_list.command_type != CommandMacroRemove) &&
    01990           (value_list.command_type != CommandMacroRemoveAll)) continue;
    01991
    01992       const int selected = value_list.select_first (tag_name);
    01993
    01994       if (selected < 0) continue;
    01995
    01996       SymbolValue& value = value_list.values[selected];
    01997
    01998       if (show_it)
    01999         {
    02000           cout << "# Package ";
    02001           if (value_list.use != 0)
    02002             {
    02003               cout << value_list.use->package << " " << value_list.use->version;
    02004             }
    02005         }
    02006
    02007       switch (value_list.command_type)
    02008         {
    02009           case CommandMacroRemove :
    02010             if (show_it)
    02011               {
    02012                 cout << " remove from macro " << symbol.name << " : ";
    02013               }
    02014             temp.replace (value.text, empty);
    02015             break;
    02016           case CommandMacroRemoveAll :
    02017             if (show_it)
    02018               {
    02019                 cout << " remove all from macro " << symbol.name << " : ";
    02020               }
    02021             temp.replace_all (value.text, empty);
    02022             break;
    02023         }
    02024
    02025       if (show_it)
    02026         {
    02027           cout << "'" << value.text << "'";
    02028
    02029           Tag* selected_tag = value.tag;
    02030
    02031           if ((selected_tag == 0) ||
    02032               (selected_tag == Tag::get_default ()))
    02033             {
    02034               cout << " for default tag";
    02035             }
    02036           else
    02037             {
    02038               cout << " for tag '" << selected_tag->name << "'";
    02039             }
    02040
    02041           cout << endl;
    02042         }
    02043     }
    02044
    02045   return (temp);
    02046 }
    02047
    02048 //-------------------------------------------------------------
    02049 const cmt_string& ScriptBuilder::build (const Symbol& symbol,
    02050                                         const cmt_string& tag_name)
    02051 {
    02052   static const cmt_string empty = "";
    02053
    02054   if (symbol.value_lists.size () > 0)
    02055     {
    02056       const SymbolValueList& value_list = symbol.value_lists[0];
    02057
    02058       if (value_list.discarded) return (empty);
    02059
    02060       if ((value_list.use != 0) &&
    02061           (value_list.use->discarded)) return (empty);
    02062     }
    02063
    02064   return (symbol.name);
    02065 }
    02066
    02067 //-------------------------------------------------------------
    02068 int SymbolValueList::select_first (const cmt_string& tag_name) const
    02069 {
    02070   int priority = 0;
    02071   int value_number;
    02072   int selected = -1;
    02073
    02074   Tag* the_tag = 0;
    02075
    02076   if (tag_name != "") the_tag = Tag::find (tag_name);
    02077
    02078   for (value_number = 0;
    02079        value_number < values.size ();
    02080        value_number++)
    02081     {
    02082       const SymbolValue& value = values[value_number];
    02083
    02084       const Tag* tag = value.tag;
    02085
    02086       if (the_tag == 0)
    02087         {
    02088           if (!tag->selected) continue;
    02089         }
    02090       else
    02091         {
    02092           if (tag != the_tag) continue;
    02093           selected = value_number;
    02094         }
    02095
    02096       //
    02097       // Only the first value at a given priority is
    02098       // selected (which implies the '>' test instead
    02099       // of '>=')
    02100       //
    02101
    02102       if (tag->priority > priority)
    02103         {
    02104           priority = tag->priority;
    02105           selected = value_number;
    02106         }
    02107     }
    02108
    02109   return (selected);
    02110 }
    02111
    02112 //-------------------------------------------------------------
    02113 int SymbolValueList::select_last () const
    02114 {
    02115   int priority = 0;
    02116   int value_number;
    02117   int selected = -1;
    02118
    02119   for (value_number = 0;
    02120        value_number < values.size ();
    02121        value_number++)
    02122     {
    02123       SymbolValue& value = values[value_number];
    02124
    02125       const Tag* tag = value.tag;
    02126
    02127       if (tag->selected)
    02128         {
    02129           //
    02130           // The last value at a given priority is
    02131           // selected (which implies the '>=' test instead
    02132           // of '>')
    02133           //
    02134
    02135           if (tag->priority >= priority)
    02136             {
    02137               priority = tag->priority;
    02138               selected = value_number;
    02139             }
    02140         }
    02141     }
    02142
    02143   return (selected);
    02144 }