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 }

Generated at Thu Apr 11 16:49:43 2002 for CMT by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000