Main?Page | Class?Hierarchy | Class?List | File?List | Class?Members | File?Members

cmt_symbol.cxx

Go to the documentation of this file.
00001 //-----------------------------------------------------------
00002 // Copyright Christian Arnault LAL-Orsay CNRS
00003 // 
00004 // See the complete license in cmt_license.txt "http://www.cecill.info". 
00005 //-----------------------------------------------------------
00006 
00007 #include 
00008 #include 
00009 #include 
00010 #include 
00011 
00012 #include "cmt_use.h"
00013 #include "cmt_symbol.h"
00014 #include "cmt_system.h"
00015 #include "cmt_database.h"
00016 
00017 //-------------------------------------------------------------
00018 class SetBuilder : public ValueBuilder
00019 {
00020 public:
00021   const cmt_string build (const Symbol& symbol,
00022                           const cmt_string& tag_name = "");
00023   const cmt_string clean (const Symbol& symbol,
00024                           const cmt_string& tag_name = "")
00025       {
00026         static const cmt_string empty = "";
00027         return (empty);
00028       }
00029 };
00030 //-------------------------------------------------------------
00031 
00032 //-------------------------------------------------------------
00033 class PathBuilder : public ValueBuilder
00034 {
00035 public:
00036   const cmt_string build (const Symbol& symbol,
00037                           const cmt_string& tag_name = "");
00038   const cmt_string clean (const Symbol& symbol,
00039                           const cmt_string& tag_name = "");
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 //-------------------------------------------------------------
00057 
00058 //-------------------------------------------------------------
00059 class ScriptBuilder : public ValueBuilder
00060 {
00061 public:
00062   const cmt_string build (const Symbol& symbol,
00063                           const cmt_string& tag_name = "");
00064   const cmt_string clean (const Symbol& symbol,
00065                           const cmt_string& tag_name = "")
00066       {
00067         static const cmt_string empty = "";
00068         return (empty);
00069       }
00070 };
00071 //-------------------------------------------------------------
00072 
00073 //-------------------------------------------------------------
00074 class ActionBuilder : public ValueBuilder
00075 {
00076 public:
00077   const cmt_string build (const Symbol& symbol,
00078                           const cmt_string& tag_name = "");
00079   const cmt_string clean (const Symbol& symbol,
00080                           const cmt_string& tag_name = "")
00081       {
00082         static const cmt_string empty = "";
00083         return (empty);
00084       }
00085 };
00086 //-------------------------------------------------------------
00087 
00088 //-------------------------------------------------------------
00089 class symbol_marker
00090 {
00091 public:
00092   symbol_marker ()
00093   {
00094     ptr = cmt_string::npos;
00095     pattern = 0;
00096     intro = 0;
00097   }
00098 
00099   symbol_marker (int a_ptr, char a_pattern, int a_intro)
00100   {
00101     ptr = a_ptr;
00102     pattern = a_pattern;
00103     intro = a_intro;
00104   }
00105 
00106   symbol_marker (const symbol_marker& other)
00107   {
00108     ptr = other.ptr;
00109     pattern = other.pattern;
00110     intro = other.intro;
00111   }
00112 
00113   void set (int a_ptr, char a_pattern, int a_intro)
00114   {
00115     ptr = a_ptr;
00116     pattern = a_pattern;
00117     intro = a_intro;
00118   }
00119 
00120   static symbol_marker& get_lowest (symbol_marker markers[], int count)
00121   {
00122     static symbol_marker result;
00123     int real_count = 0;
00124     int i;
00125 
00126       // Check that at least one marker has result
00127 
00128     for (i = 0; i < count; i++)
00129       {
00130         if (markers[i].ptr != cmt_string::npos) real_count++;
00131       }
00132 
00133     if (real_count == 0) return (result);
00134 
00135     // since we've passed the previous test, 
00136     // at least one entry is not npos.
00137     // Now discards other npos by moving them to the end
00138     
00139     for (i = 0; i < count;)
00140       {
00141         if (markers[i].ptr == cmt_string::npos)
00142           {
00143             markers[i] = markers[count-1];
00144             count--;
00145             if (count == 0) break;
00146           }
00147         else
00148           {
00149             i++;
00150           }
00151       }
00152     
00153     if (count == 0) return (result);
00154     
00155     // now all entries in [0, count-1] are not npos
00156     // let's sort the lowest one in [0]
00157     
00158     for (i = 1; i < count;)
00159       {
00160         if (markers[0].ptr > markers[i].ptr)
00161           {
00162             symbol_marker temp = markers[0];
00163             markers[0] = markers[i];
00164             markers[i] = temp;
00165             i = 1;
00166           }
00167         else
00168           {
00169             i++;
00170           }
00171       }
00172     
00173     return (markers[0]);
00174   }
00175 
00176   int ptr;
00177   char pattern;
00178   int intro;
00179 };
00180 //-------------------------------------------------------------
00181 
00195 static void resolve_value (cmt_string& text,
00196                            const cmt_string& symbol_name,
00197                            const cmt_string& value)
00198 {
00199   static cmt_string pattern;
00200 
00201   pattern = "${";
00202   pattern += symbol_name;
00203   pattern += "}";
00204 
00205   text.replace_all (pattern, value);
00206 
00207   pattern = "$(";
00208   pattern += symbol_name;
00209   pattern += ")";
00210 
00211   text.replace_all (pattern, value);
00212 
00213 #ifdef WIN32
00214   pattern = "%";
00215   pattern += symbol_name;
00216   pattern += "%";
00217 
00218   text.replace_all (pattern, value);
00219 #endif
00220 }
00221 
00247 static void resolve_value (cmt_string& text)
00248 {
00249   //static cmt_regexp reg ("[$%`]");
00250 
00251   //if (!reg.match (text)) return;
00252 
00253   cmt_string pattern;
00254   cmt_string symbol_name;
00255   char end_pattern;
00256 
00257   int start = 0;
00258 
00259   for (;;)
00260     {
00261       int begin;
00262       int end;
00263 
00264       symbol_marker markers[4];
00265       int num = 0;
00266 
00267       markers[num].set (text.find (start, "$("), ')', 2); num++;
00268       markers[num].set (text.find (start, "${"), '}', 2); num++;
00269       markers[num].set (text.find (start, "`"), '`', 1); num++;
00270 
00271 #ifdef WIN32
00272       markers[num].set (text.find (start, "%"), '%', 1); num++;
00273 #endif
00274 
00275       // Find the first matching pattern
00276 
00277       symbol_marker& marker = symbol_marker::get_lowest (markers, num);
00278 
00279       begin = marker.ptr;
00280 
00281       if (begin == cmt_string::npos) break;
00282 
00283       end_pattern = marker.pattern;
00284       start = begin + marker.intro;
00285 
00286       end = text.find (start, end_pattern);
00287       if (end == cmt_string::npos)
00288         {
00289           // The pattern is a fake one (no ending!)
00290           start++;
00291           continue;
00292         }
00293 
00294       // This should never happen...
00295       if (end < begin) break;
00296 
00297       // Extract the complete pattern
00298       text.substr (begin, end - begin + 1, pattern);
00299 
00300       // Then only the symbol name
00301       text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name);
00302 
00303       if (text[begin] == '`')
00304         {
00305           cmt_string command = symbol_name;
00306           resolve_value (command);
00307 
00308             // The value is a shell command that first needs
00309             // to be applied. The output of the command is then substituted
00310 
00311           cmt_string result;
00312 
00313           Symbol::all_set ();
00314           CmtSystem::execute (command, result);
00315           
00316           int pos;
00317           pos = result.find ('\n');
00318           if (pos != cmt_string::npos) result.erase (pos);
00319           pos = result.find ('\r');
00320           if (pos != cmt_string::npos) result.erase (pos);
00321           
00322           if (Cmt::get_debug ())
00323             {
00324               cout << "   Executing [" << command << "] to expand a symbol value =>[" 
00325                    << result << "]" << endl;
00326             }
00327           
00328           text.replace_all (pattern, result);
00329 
00330           // The substitution will restart from the same place
00331           // allowing for recursive replacements
00332           start = begin;
00333         }
00334       else
00335         {
00336           Symbol* symbol = Symbol::find (symbol_name);
00337           if (symbol != 0)
00338             {
00339                 // Symbol found
00340               cmt_string value = symbol->resolve_macro_value ();
00341               text.replace_all (pattern, value);
00342               
00343                 // The substitution will restart from the same place
00344                 // allowing for recursive replacements
00345               start = begin;
00346             }
00347           else
00348             {
00349                 // Symbol not found. Look for env. variable
00350               cmt_string value = CmtSystem::getenv (symbol_name);
00351               
00352                 // When the env. variable is not defined, the replacement is empty
00353                 // thus all $(xxx) ${xxx} %xxx% patterns are always filtered away.
00354               text.replace_all (pattern, value);
00355               
00356                 // The substitution will restart from the same place
00357                 // allowing for recursive replacements
00358               start = begin;
00359             }
00360         }
00361     }
00362 }
00363 
00389 static void resolve_value_for_macros (cmt_string& text)
00390 {
00391   cmt_string pattern;
00392   cmt_string symbol_name;
00393   char end_pattern;
00394 
00395   int start = 0;
00396 
00397   for (;;)
00398     {
00399       //
00400       // Try and substitute all ${xxx} $(xxx) or %xxx% patterns
00401       // using symbol values, only when the symbol is a macro.
00402       //
00403 
00404       int begin;
00405       int end;
00406 
00407       symbol_marker markers[4];
00408       int num = 0;
00409 
00410       markers[num].set (text.find (start, "$("), ')', 2); num++;
00411       markers[num].set (text.find (start, "${"), '}', 2); num++;
00412 
00413 #ifdef WIN32
00414       markers[num].set (text.find (start, "%"), '%', 1); num++;
00415 #endif
00416 
00417       markers[num].set (text.find (start, "`"), '`', 1); num++;
00418 
00419       // Find the first of three patterns
00420 
00421       symbol_marker& marker = symbol_marker::get_lowest (markers, num);
00422 
00423       begin = marker.ptr;
00424 
00425       if (begin == cmt_string::npos) break;
00426 
00427       end_pattern = marker.pattern;
00428       start = begin + marker.intro;
00429 
00430       end = text.find (start, end_pattern);
00431       if (end == cmt_string::npos)
00432         {
00433           // The pattern is a fake one (no ending!)
00434           start++;
00435           continue;
00436         }
00437 
00438       // This should never happen...
00439       if (end < begin) break;
00440 
00441       // Extract the complete pattern
00442       text.substr (begin, end - begin + 1, pattern);
00443 
00444       // Then only the macro name
00445       text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name);
00446 
00447       if (text[begin] == '`')
00448         {
00449           cmt_string command = symbol_name;
00450           resolve_value (command);
00451 
00452             // The macro value is a shell command that first needs
00453             // to be applied. The output of the command is substituted
00454 
00455           cmt_string result;
00456 
00457           Symbol::all_set ();
00458           CmtSystem::execute (command, result);
00459           
00460           int pos;
00461           pos = result.find ('\n');
00462           if (pos != cmt_string::npos) result.erase (pos);
00463           pos = result.find ('\r');
00464           if (pos != cmt_string::npos) result.erase (pos);
00465           
00466           if (Cmt::get_debug ())
00467             {
00468               cout << "   Executing [" << command << "] to expand a macro value =>[" 
00469                    << result << "]" << endl;
00470             }
00471           
00472           text.replace_all (pattern, result);
00473 
00474           // The substitution will restart from the same place
00475           // allowing for recursive replacements
00476           start = begin;
00477         }
00478       else
00479         {
00480           Symbol* macro = Symbol::find (symbol_name);
00481           if ((macro != 0) && 
00482               (macro->type == Symbol::SymbolMacro))
00483             {
00484                 // Macro found
00485               cmt_string value = macro->resolve_macro_value ();
00486               text.replace_all (pattern, value);
00487 
00488                 // The substitution will restart from the same place
00489                 // allowing for recursive replacements
00490               start = begin;
00491             }
00492           else if ((macro == 0) || 
00493                    ((macro->type == Symbol::SymbolSet) || (macro->type == Symbol::SymbolPath)))
00494             {
00495                 // Set found
00496                 // ensure that the delimiters will match the OS dependent
00497                 // delimiters.
00498               
00499               cmt_string pattern_close = marker.pattern;
00500               
00501               if (pattern_close != CmtSystem::ev_close ())
00502                 {
00503                   cmt_string new_pattern;
00504                   
00505                   new_pattern = CmtSystem::ev_open ();
00506                   new_pattern += symbol_name;
00507                   new_pattern += CmtSystem::ev_close ();
00508                   
00509                   text.replace (pattern, new_pattern);
00510                 }
00511               
00512               start = end + 1;
00513             }
00514           else
00515             {
00516               start = end + 1;
00517             }
00518         }
00519     }
00520 }
00521 
00530 static void suppress_OS_delimiters (cmt_string& text)
00531 {
00532   cmt_string pattern;
00533   cmt_string symbol_name;
00534   char end_pattern;
00535 
00536   int start = 0;
00537 
00538   for (;;)
00539     {
00540       int begin;
00541       int end;
00542 
00543       symbol_marker markers[3];
00544       int num = 0;
00545 
00546       markers[num].set (text.find (start, "${"), '}', 2); num++;
00547       markers[num].set (text.find (start, "`"), '`', 1); num++;
00548 
00549 #ifdef WIN32
00550       markers[num].set (text.find (start, "%"), '%', 1); num++;
00551 #endif
00552 
00553       // Find the first of three patterns
00554 
00555       symbol_marker& marker = symbol_marker::get_lowest (markers, num);
00556 
00557       begin = marker.ptr;
00558 
00559       if (begin == cmt_string::npos) break;
00560 
00561       end_pattern = marker.pattern;
00562       start = begin + marker.intro;
00563 
00564       end = text.find (start, end_pattern);
00565       if (end == cmt_string::npos)
00566         {
00567           // The pattern is a fake one (no ending!)
00568           start++;
00569           continue;
00570         }
00571 
00572       // This should never happen...
00573       if (end < begin) break;
00574 
00575       // Extract the complete pattern
00576       text.substr (begin, end - begin + 1, pattern);
00577 
00578       // Then only the macro name
00579       text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name);
00580 
00581       if (text[begin] == '`')
00582         {
00583           cmt_string command = symbol_name;
00584           resolve_value (command);
00585 
00586             // The macro value is a shell command that first needs
00587             // to be applied. The output of the command is substituted
00588 
00589           cmt_string result;
00590 
00591           Symbol::all_set ();
00592           CmtSystem::execute (command, result);
00593           
00594           int pos;
00595           pos = result.find ('\n');
00596           if (pos != cmt_string::npos) result.erase (pos);
00597           pos = result.find ('\r');
00598           if (pos != cmt_string::npos) result.erase (pos);
00599           
00600           if (Cmt::get_debug ())
00601             {
00602               cout << "   Executing [" << command << "] to expand a macro value =>[" 
00603                    << result << "]" << endl;
00604             }
00605           
00606           text.replace_all (pattern, result);
00607 
00608           // The substitution will restart from the same place
00609           // allowing for recursive replacements
00610           start = begin;
00611         }
00612       else
00613         {
00614           cmt_string new_pattern;
00615 
00616           new_pattern = "$(";
00617           new_pattern += symbol_name;
00618           new_pattern += ")";
00619 
00620           text.replace (pattern, new_pattern);
00621 
00622           start = begin;
00623         }
00624     }
00625 }
00626 
00627 //-------------------------------------------------------------
00628 /*                                                          */
00629 /*  Operations on SymbolValues                              */
00630 /*                                                          */
00631 //-------------------------------------------------------------
00632 
00633 //-------------------------------------------------------------
00634 SymbolValue::SymbolValue ()
00635 {
00636   tag = 0;
00637 }
00638 
00639 //-------------------------------------------------------------
00640 SymbolValue::~SymbolValue ()
00641 {
00642   tag = 0;
00643 }
00644 
00645 //-------------------------------------------------------------
00646 /*                                                          */
00647 /*  Operations on Symbols                                   */
00648 /*                                                          */
00649 //-------------------------------------------------------------
00650 
00651 //-------------------------------------------------------------
00652 Symbol* Symbol::create (const cmt_string& name,
00653                         CommandType command,
00654                         Use* use)
00655 {
00656   static SetBuilder Set;
00657   static PathBuilder Path;
00658   static MacroBuilder Macro;
00659   static ScriptBuilder Script;
00660   static ActionBuilder Action;
00661 
00662   static SymbolVector& Symbols = symbols ();
00663   static SymbolMap& SymbolMap = symbol_map ();
00664 
00665   SymbolType type = SymbolUndefined;
00666 
00667   switch (command)
00668     {
00669     case CommandSet:
00670     case CommandSetAppend:
00671     case CommandSetPrepend:
00672     case CommandSetRemove:
00673     case CommandSetRemoveRegexp:
00674       type = SymbolSet;
00675       break;
00676     case CommandPath:
00677     case CommandPathAppend:
00678     case CommandPathPrepend:
00679     case CommandPathRemove:
00680     case CommandPathRemoveRegexp:
00681       type = SymbolPath;
00682       break;
00683     case CommandMacro:
00684     case CommandMacroAppend:
00685     case CommandMacroPrepend:
00686     case CommandMacroRemove:
00687     case CommandMacroRemoveRegexp:
00688     case CommandMacroRemoveAll:
00689     case CommandMacroRemoveAllRegexp:
00690       type = SymbolMacro;
00691       break;
00692     case CommandAction:
00693       type = SymbolAction;
00694       break;
00695     case CommandAlias:
00696       type = SymbolAlias;
00697       break;
00698     case CommandSetupScript:
00699       type = SymbolSetupScript;
00700       break;
00701     case CommandCleanupScript:
00702       type = SymbolCleanupScript;
00703       break;
00704     }
00705 
00706   {
00707     Symbol* symbol;
00708 
00709     symbol = find (name);
00710     if (symbol != 0) 
00711       {
00712         if (symbol->type != type)
00713           {
00714             ActionType action = Cmt::get_action ();
00715 
00716             if ((!Cmt::get_quiet ()) &&
00717                 (action != action_build_tag_makefile))
00718               {
00719                 cmt_string s1;
00720                 cmt_string s2;
00721 
00722                 switch (symbol->type)
00723                   {
00724                   case SymbolSet:
00725                     s1 = "set";
00726                     break;
00727                   case SymbolPath:
00728                     s1 = "path";
00729                     break;
00730                   case SymbolMacro:
00731                     s1 = "macro";
00732                     break;
00733                   case SymbolSetupScript:
00734                     s1 = "setup_script";
00735                     break;
00736                   case SymbolCleanupScript:
00737                     s1 = "cleanup_script";
00738                     break;
00739                   case SymbolAction:
00740                     s1 = "action";
00741                     break;
00742                   case SymbolAlias:
00743                     s1 = "alias";
00744                     break;
00745                   } 
00746 
00747                 switch (type)
00748                   {
00749                   case SymbolSet:
00750                     s2 = "set";   
00751                     break;
00752                   case SymbolPath:
00753                     s2 = "path";   
00754                     break;
00755                   case SymbolMacro:
00756                     s2 = "macro";   
00757                     break;
00758                   case SymbolSetupScript:
00759                     s2 = "setup_script";  
00760                     break;
00761                   case SymbolCleanupScript:
00762                     s2 = "cleanup_script";  
00763                     break;
00764                   case SymbolAction:
00765                     s2 = "action";
00766                     break;
00767                   case SymbolAlias:
00768                     s2 = "alias";
00769                     break;
00770                   } 
00771 
00772                 cerr << "#CMT> Warning: Symbol " << name 
00773                      << " inconsistently redeclared from " << s1 << " to " << s2;
00774                 if (use != 0) cerr << " in package " << use->get_package_name ();
00775                 cerr << endl;
00776               }
00777           }
00778 
00779         return (symbol);
00780       }
00781   }
00782 
00783   Symbol& symbol = Symbols.add ();
00784   SymbolMap.add (name, symbol);
00785 
00786   symbol.name  = name;
00787   symbol.scope = use->get_current_scope ();
00788   symbol.type  = type;
00789 
00790   symbol.value_lists.clear ();
00791 
00792   switch (type)
00793     {
00794     case SymbolSet:
00795       symbol.builder = &Set;
00796       break;
00797     case SymbolPath:
00798       symbol.builder = &Path;
00799       break;
00800     case SymbolAlias:
00801       symbol.builder = &Set;
00802       break;
00803     case SymbolMacro:
00804       symbol.builder = &Macro;
00805       break;
00806     case SymbolSetupScript:
00807     case SymbolCleanupScript:
00808       symbol.builder = &Script;
00809       break;
00810     case SymbolAction:
00811       symbol.builder = &Action;
00812       break;
00813     }
00814 
00815   symbol.selected_value = -1;
00816 
00817   return (&symbol);
00818 }
00819 
00820 //-------------------------------------------------------------
00821 Symbol* Symbol::find (const cmt_string& name)
00822 {
00823   static SymbolMap& SymbolMap = symbol_map ();
00824 
00825   Symbol* result = 0;
00826 
00827   result = SymbolMap.find (name);
00828 
00829   return (result);
00830 }
00831 
00832 //-------------------------------------------------------------
00833 int Symbol::symbol_number ()
00834 {
00835   static SymbolVector& Symbols = symbols ();
00836 
00837   return (Symbols.size ());
00838 }
00839 
00840 //-------------------------------------------------------------
00841 Symbol::SymbolVector& Symbol::symbols ()
00842 {
00843   static Database& db = Database::instance ();
00844   static SymbolVector& Symbols = db.symbols ();
00845 
00846   return (Symbols);
00847 }
00848 
00849 //-------------------------------------------------------------
00850 Symbol::SymbolMap& Symbol::symbol_map ()
00851 {
00852   static Database& db = Database::instance ();
00853   static SymbolMap& SymbolMap = db.symbol_map ();
00854 
00855   return (SymbolMap);
00856 }
00857 
00858 //-------------------------------------------------------------
00859 Symbol& Symbol::symbol (int index)
00860 {
00861   static SymbolVector& Symbols = symbols ();
00862 
00863   return (Symbols[index]);
00864 }
00865 
00866 //-------------------------------------------------------------
00867 void Symbol::action (const CmtSystem::cmt_string_vector& words,
00868                      CommandType command_type,
00869                      Use* use)
00870 {
00871   int number;
00872   Symbol* symbol;
00873   Tag* tag;
00874 
00875   if (words.size () < 1) return;
00876   cmt_string name = words[1];
00877 
00878   if ((command_type == CommandSetupScript) ||
00879       (command_type == CommandCleanupScript))
00880     {
00881       cmt_string full_name;
00882 
00883       Symbol::expand (name);
00884 
00885       if (name != "")
00886         {
00887           if (CmtSystem::absolute_path (name)) 
00888             {
00889               full_name = name;
00890             }
00891           else
00892             {
00893 #ifdef WIN32
00894               full_name = "%";
00895 #else
00896               full_name = "${";
00897 #endif
00898               full_name += use->prefix;
00899               full_name += "ROOT";
00900 #ifdef WIN32
00901               full_name += "%";
00902 #else
00903               full_name += "}";
00904 #endif
00905               full_name += CmtSystem::file_separator ();
00906               if (use->style == cmt_style) full_name += "cmt";
00907               else if (use->style == no_version_style) full_name += "cmt";
00908               else full_name += "mgr";
00909               full_name += CmtSystem::file_separator ();
00910               full_name += name;
00911             }
00912 
00913           symbol = create (full_name, command_type, use);
00914           symbol->add_value_to_list (command_type, use,
00915                                      Tag::get_default (), full_name);
00916         }
00917     }
00918   else
00919     {
00920       if (words.size () < 2) return;
00921       const cmt_string& default_value = words[2];
00922 
00923       if (Cmt::get_debug ())
00924         {
00925           cout << "Symbol::action> name:" << name 
00926                << " access:" << Cmt::get_current_access () 
00927                << " scope:" << use->get_current_scope () << endl;
00928         }
00929 
00930       if (Cmt::get_current_access () == UserMode)
00931         {
00932           if (name == "constituents") return;
00933           if (name == "constituentscclean") return;
00934 
00935           if (use->get_current_scope () == ScopePrivate) return;
00936         }
00937 
00938       symbol = create (name, command_type, use);
00939 
00940       /*
00941         Parse the default value.
00942       */
00943       
00944       symbol->add_value_to_list (command_type, use,
00945                                  Tag::get_default (), default_value);
00946       
00947       /*
00948         Then parse all specific values
00949         
00950          
00951         ...
00952       */
00953       
00954       number = 3;
00955       while (number < (words.size () - 1))
00956         {
00957           cmt_string tag_name = words[number];
00958           const cmt_string& value = words[number + 1];
00959 
00960           expand (tag_name);
00961 
00962           if (Cmt::get_debug ())
00963             {
00964               cout << "Symbol::action> tag_name=" << tag_name << endl;
00965             }
00966 
00967           tag = Tag::find (tag_name);
00968           if (tag == 0)
00969             {
00970               tag = Tag::add (tag_name, PriorityUserTag, "use", use);
00971             }
00972 
00973           symbol->add_value_to_list (command_type, use, tag, value);
00974           
00975           number += 2;
00976         }
00977 
00978       if (name == "CMTPATH")
00979         {
00980           Cmt::configure_cmt_path (use);
00981         }
00982       else if (name == "CMTSITE")
00983         {
00984           Cmt::configure_site_tag (use);
00985         }
00986       else if (name == "CMTCONFIG")
00987         {
00988             //cerr << "redefining CMTCONFIG" << endl;
00989           Cmt::configure_tags (use);
00990         }
00991       else if (name == "CMTHOME")
00992         {
00993           Cmt::configure_home (use);
00994         }
00995       else if (name == "CMTUSERCONTEXT")
00996         {
00997           Cmt::configure_user_context (use);
00998         }
00999       else if (name.find ("_native_version") != cmt_string::npos)
01000         {
01001           cmt_string n = use->get_package_name ();
01002           n += "_native_version";
01003 
01004           if (name == n)
01005             {
01006               use->set_native_version (true);
01007             }
01008         }
01009     }
01010 }
01011 
01012 //-------------------------------------------------------------
01013 int Symbol::is_selected (const cmt_string& name)
01014 {
01015   Symbol* symbol;
01016   int number;
01017   int value_number;
01018 
01019   symbol = find (name);
01020   if (symbol == 0) return (0);
01021 
01022   if (symbol->value_lists.size () == 0) return (0);
01023 
01024   for (number = 0;
01025        number < symbol->value_lists.size ();
01026        number++)
01027     {
01028       const SymbolValueList& value_list = symbol->value_lists[number];
01029 
01030       if (value_list.discarded) continue;
01031 
01032       if ((value_list.command_type == CommandMacro) ||
01033           (value_list.command_type == CommandSet) ||
01034           (value_list.command_type == CommandSetAppend) ||
01035           (value_list.command_type == CommandSetPrepend) ||
01036           (value_list.command_type == CommandSetRemove) ||
01037           (value_list.command_type == CommandSetRemoveRegexp) ||
01038           (value_list.command_type == CommandAlias) ||
01039           (value_list.command_type == CommandAction))
01040         {
01041           for (value_number = 0;
01042                value_number < value_list.values.size ();
01043                value_number++)
01044             {
01045               Tag* tag;
01046 
01047               SymbolValue& value = value_list.values[value_number];
01048 
01049               tag = value.tag;
01050               if ((tag == 0) ||
01051                   (tag == Tag::get_default ()) ||
01052                   (tag->is_selected () != 0))
01053                 {
01054                   return (1);
01055                 }
01056             }
01057         }
01058     }
01059 
01060   return (0);
01061 }
01062 
01063 //-------------------------------------------------------------
01064 Symbol::Symbol ()
01065 {
01066   name = "";
01067 }
01068 
01069 //-------------------------------------------------------------
01070 Symbol::~Symbol ()
01071 {
01072 }
01073 
01077 bool Symbol::value_is_reflexive (const cmt_string& text) const
01078 {
01079   bool result = false;
01080   int text_length = text.size ();
01081 
01082   if (text_length == (name.size () + 3))
01083     {
01084       static cmt_string temp;
01085               
01086       if (text[0] == '$')
01087         {
01088           if (text[1] == '(')
01089             {
01090               temp = "$(";
01091               temp += name;
01092               temp += ")";
01093               
01094               if (text == temp)
01095                 {
01096                   result = true;
01097                 }
01098             }
01099           else if (text[1] == '{')
01100             {
01101               temp = "${";
01102               temp += name;
01103               temp += "}";
01104               
01105               if (text == temp)
01106                 {
01107                   result = true;
01108                 }
01109             }
01110         }
01111     }
01112   else if (text_length == (name.size () + 2))
01113     {
01114       static cmt_string temp;
01115 
01116       temp = "%";
01117       temp += name;
01118       temp += "%";
01119 
01120       if (text == temp)
01121         {
01122           result = true;
01123         }
01124     }
01125 
01126   return (result);
01127 }
01128 
01129 //-------------------------------------------------------------
01130 void Symbol::add_value_to_list (CommandType command_type,
01131                                 Use* use,
01132                                 Tag* tag,
01133                                 const cmt_string& text)
01134 {
01135   SymbolValueList* value_list = 0;
01136   bool is_reflexive = false;
01137 
01138     //
01139     // First pickup the most recent value_list
01140     //
01141   if (value_lists.size () > 0) value_list = &(value_lists.back ());
01142 
01143     //
01144     //  Create a new value list is we switch to another use or
01145     //  if we switch to a new command_type (eg. switching from
01146     //  macro to macro_append).
01147     //
01148   if ((value_list == 0) ||
01149       (use != value_list->use) ||
01150       (command_type != value_list->command_type) ||
01151       (tag == Tag::get_default ()))
01152     {
01153       value_list = &(value_lists.add ());
01154       value_list->use = use;
01155       value_list->command_type = command_type;
01156       value_list->values.clear ();
01157       value_list->discarded = false;
01158       value_list->is_reflexive = false;
01159     }
01160 
01161 /*
01162   else
01163     {
01164         value_list = &(value_lists[value_lists.size () - 1]);
01165     }
01166 */
01167 
01168   is_reflexive = value_list->is_reflexive;
01169 
01170     //
01171     //  If the command_type is command_macro or command_set, 
01172     // this is considered as a full re-set of this symbol 
01173     //   In this case, we have to discard all previous values
01174     //
01175     //  However, we'd like to exclude from this logic the cases where
01176     //  the value is **exactly* 
01177     //
01178     //     $()
01179     //     ${}
01180     //     %%
01181     //
01182     //   which would then mean that we do not reset the value but rather
01183     //  override it.
01184     //
01185 
01186     //
01187     // Inside this value_list, we add this new tag-value pair.
01188     //
01189 
01190   if ((command_type == CommandMacro) ||
01191       (command_type == CommandSet) ||
01192       (command_type == CommandPath) ||
01193       (command_type == CommandAction))
01194     {
01195         //
01196         // Check whether we have to hide previous settings by this new definition
01197         //  (of course this is only useful if there WERE previous settings)
01198         //
01199       if ((value_lists.size () >= 1) && (!is_reflexive))
01200         {
01201           if (value_is_reflexive (text))
01202             {
01203               value_list->is_reflexive = true;
01204               is_reflexive = true;
01205             }
01206           else
01207             {
01208               //cout << "...discarding old values for symbol " << name << " text=[" << text << "]" << endl;
01209                   
01210               for (int i = 0; i < (value_lists.size () - 1); i++)
01211                 {
01212                   SymbolValueList& vl = value_lists[i];
01213                   
01214                   if ((vl.use != 0) &&
01215                       (vl.use->discarded))
01216                     {
01217                       //vl.discarded = true;
01218                     }
01219                 }
01220             }
01221         }
01222     }
01223 
01224   SymbolValue& value = value_list->values.add ();
01225 
01226   value.tag = tag;
01227   value.text = text;
01228   value.selected = 0;
01229 }
01230 
01235 void Symbol::all_set ()
01236 {
01237   //cerr << "all_set" << endl;
01238 
01239   if (Cmt::get_debug ())
01240     {
01241       cout << "Symbol::all_set> done" << Cmt::get_all_sets_done () << endl;
01242     }
01243 
01244   if (Cmt::get_all_sets_done ()) return;
01245 
01246   Cmt::set_all_sets_done ();
01247 
01248   static SymbolVector& Symbols = symbols ();
01249   Use::UsePtrVector& Uses = Use::get_ordered_uses ();
01250 
01251   static CmtSystem::cmt_string_vector envs;
01252 
01253   envs.clear ();
01254 
01255   int number;
01256 
01257   if (Symbols.size () == 0) 
01258     {
01259         //running = false;
01260       return;
01261     }
01262 
01263   cmt_string value;
01264 
01265   for (number = 0; number < Symbol::symbol_number (); number++)
01266     {
01267       Symbol& symbol = Symbol::symbol (number);
01268 
01269       if (symbol.type != SymbolSet) continue;
01270 
01271       value = symbol.build_macro_value ();
01272       if (value != "")
01273         {
01274           cmt_string& temp = envs.add ();
01275 
01276           temp = symbol.name;
01277           temp += '=';
01278           temp += value;
01279         }
01280     }
01281 
01282   cmt_string cmtconfig = CmtSystem::get_cmt_config ();
01283 
01284   if (Uses.size () > 0)
01285     {
01286       int number;
01287 
01288       for (number = 0; number < Uses.size (); number++)
01289         {
01290           Use& use = *(Uses[number]);
01291 
01292           if (use.discarded) continue;
01293 
01294           if (use.get_package_name () == "cmt_standalone") continue;
01295 
01296           if (use.get_strategy ("SetupConfig"))
01297             {
01298               cmt_string& temp = envs.add ();
01299 
01300               temp = use.prefix;
01301               temp += "CONFIG=";
01302               temp += cmtconfig;
01303             }
01304 
01305           if (use.get_strategy ("SetupRoot"))
01306             {
01307               cmt_string& temp = envs.add ();
01308 
01309               temp = use.prefix;
01310               temp += "ROOT=";
01311               temp += use.get_full_path ();
01312             }
01313         }
01314     }
01315 
01316   {
01317     Use& use = Use::current ();
01318 
01319     if (use.get_package_name () != "cmt_standalone")
01320       {
01321         if (use.get_strategy ("SetupConfig"))
01322           {
01323             cmt_string& temp = envs.add ();
01324             
01325             temp = use.prefix;
01326             temp += "CONFIG=";
01327             temp += cmtconfig;
01328           }
01329         
01330         if (use.get_strategy ("SetupRoot"))
01331           {
01332             cmt_string& temp = envs.add ();
01333             
01334             temp = use.prefix;
01335             temp += "ROOT=";
01336             temp += use.get_full_path ();
01337           }
01338       }
01339   }
01340 
01341   for (number = 0; number < Symbol::symbol_number (); number++)
01342     {
01343       Symbol& symbol = Symbol::symbol (number);
01344 
01345       if ((symbol.type != SymbolPath)) continue;
01346 
01347       value = symbol.build_macro_value ();
01348       if (value != "")
01349         {
01350           cmt_string& temp = envs.add ();
01351 
01352           temp = symbol.name;
01353           temp += '=';
01354           temp += value;
01355         }
01356     }
01357 
01358   for (number = 0; number < envs.size (); number++)
01359     {
01360       cmt_string& env = envs[number];
01361       Symbol::expand (env);
01362 
01363 #ifdef WIN32
01364       env.replace_all ("/", "\\");
01365 #endif
01366 
01367       if (Cmt::get_debug ())
01368         {
01369           cout << "Symbol::all_set> " << env << endl;
01370         }
01371       CmtSystem::putenv (env);
01372     }
01373 
01374     //running = false;
01375 }
01376 
01377 //-------------------------------------------------------------
01378 void Symbol::all_print (PrintMode mode)
01379 {
01380   static SymbolVector& Symbols = symbols ();
01381 
01382   int number;
01383 
01384   if (Symbols.size () == 0) return;
01385 
01386   for (number = 0; number < Symbol::symbol_number (); number++)
01387     {
01388       Symbol& symbol = Symbol::symbol (number);
01389 
01390       if ((symbol.type == SymbolSet) ||
01391           (symbol.type == SymbolAlias) ||
01392           (symbol.type == SymbolSetupScript))
01393         {
01394           if (symbol.print (mode))
01395             {
01396               if (mode == Bat)
01397                 {
01398                   cout << endl;
01399                 }
01400               else
01401                 {
01402                   //cout << "; ";
01403                   cout << endl;
01404                 }
01405             }
01406         }
01407     }
01408 
01409   for (number = 0; number < Symbol::symbol_number (); number++)
01410     {
01411       Symbol& symbol = Symbol::symbol (number);
01412 
01413       if ((symbol.type != SymbolPath)) continue;
01414 
01415       if (symbol.print (mode))
01416         {
01417           if (mode == Bat)
01418             {
01419               cout << endl;
01420             }
01421           else
01422             {
01423               //cout << "; ";
01424               cout << endl;
01425             }
01426         }
01427     }
01428 }
01429 
01430 //-------------------------------------------------------------
01431 void Symbol::all_print_clean (PrintMode mode)
01432 {
01433   static SymbolVector& Symbols = symbols ();
01434 
01435   int number;
01436 
01437   if (Symbols.size () == 0) return;
01438 
01439   for (number = Symbols.size () - 1; number >= 0; number--)
01440     {
01441       Symbol& symbol = Symbols[number];
01442 
01443       if ((symbol.type == SymbolSet) ||
01444           (symbol.type == SymbolAlias) ||
01445           (symbol.type == SymbolCleanupScript))
01446         {
01447           if (symbol.print_clean (mode))
01448             {
01449               cout << endl;
01450             }
01451         }
01452     }
01453 
01454   for (number = Symbols.size () - 1; number >= 0; number--)
01455     {
01456       Symbol& symbol = Symbols[number];
01457 
01458       if ((symbol.type != SymbolPath)) continue;
01459 
01460       if (symbol.print_clean (mode))
01461         {
01462           cout << endl;
01463         }
01464     }
01465 }
01466 
01467 //-------------------------------------------------------------
01468 int Symbol::print_clean (PrintMode mode)
01469 {
01470   int result = 0;
01471   static cmt_string temp;
01472 
01473   if (name == "CMTCONFIG") return (0);
01474 
01475   switch (type)
01476     {
01477     case SymbolSet :
01478       switch (mode)
01479         {
01480         case Csh :
01481           cout << "unsetenv " << name;
01482           result = 1;
01483           break;
01484         case Sh :
01485           cout << "unset " << name;
01486           result = 1;
01487           break;
01488         case Bat :
01489           cout << "set " << name << "=";
01490           result = 1;
01491           break;
01492         }
01493       break;
01494     case SymbolAlias :
01495       switch (mode)
01496         {
01497           case Csh :
01498             cout << "unalias " << name;
01499             result = 1;
01500             break;
01501           case Sh :
01502             cout << "unset " << name;
01503             result = 1;
01504             break;
01505         }
01506       break;
01507     case SymbolPath :
01508       temp = clean_macro_value ();
01509       switch (mode)
01510         {
01511         case Csh :
01512           if (temp == "")
01513             {
01514               cout << "unsetenv " << name;
01515             }
01516           else
01517             {
01518               cout << "setenv " << name << " " << temp;
01519             }
01520           result = 1;
01521           break;
01522         case Sh :
01523           cout << name << "=" << temp << "; export " << name;
01524           result = 1;
01525           break;
01526         case Bat :
01527           cout << "set " << name << "=" << temp;
01528           result = 1;
01529           break;
01530         }
01531       break;
01532     case SymbolCleanupScript :
01533       switch (mode)
01534         {
01535         case Csh :
01536           cout << "if ( -f " << name << ".csh ) then" << endl;
01537           cout << "  source " << name << ".csh" << endl;
01538           cout << "endif" << endl;
01539           result = 1;
01540           break;
01541         case Sh :
01542           cout << "if test -f " << name << ".sh; then" << endl;
01543           cout << "  . " << name << ".sh" << endl;
01544           cout << "fi" << endl;
01545           result = 1;
01546           break;
01547         case Bat :
01548           cout << "call " << name;
01549           result = 1;
01550           break;
01551         }
01552       break;
01553     }
01554 
01555   return (result);
01556 }
01557 
01558 //-------------------------------------------------------------
01559 int Symbol::print (PrintMode mode)
01560 {
01561   int result = 0;
01562   cmt_string temp;
01563 
01564   temp = build_macro_value ();
01565 
01566   bool empty = (temp.size () == 0) ? true : false;
01567 
01568   switch (type)
01569     {
01570       case SymbolSet :
01571       case SymbolPath :
01572         switch (mode)
01573           {
01574             case Csh :
01575               if (empty) cout << "unsetenv " << name;
01576               else cout << "setenv " << name << " \"" << temp << "\"";
01577 
01578               result = 1;
01579               break;
01580             case Sh :
01581               if (empty) cout << "unset " << name;
01582               else cout << name << "=\"" << temp << "\"; export " << name;
01583 
01584               result = 1;
01585               break;
01586             case Bat :
01587               temp.replace_all ("/", "\\");
01588               cout << "set " << name << "=" << temp;
01589               result = 1;
01590               break;
01591           }
01592         break;
01593       case SymbolAlias :
01594         switch (mode)
01595           {
01596             case Csh :
01597               cout << "alias " << name <<
01598                   " \"" << temp << "\"";
01599               result = 1;
01600               break;
01601             case Sh :
01602               cout << "alias " << name <<
01603                   "=\"" << temp << "\"";
01604               result = 1;
01605               break;
01606             case Bat :
01607               cout << "set " << name <<
01608                   "=" << temp;
01609               result = 1;
01610               break;
01611           }
01612         break;
01613       default :
01614         break;
01615     }
01616 
01617   if (temp != "")
01618     {
01619       switch (type)
01620         {
01621           case SymbolSetupScript :
01622             switch (mode)
01623               {
01624                 case Csh :
01625                   cout << "if ( -f " << name << ".csh ) then" << endl;
01626                   cout << "  source " << name << ".csh" << endl;
01627                   cout << "endif" << endl;
01628                   result = 1;
01629                   break;
01630                 case Sh :
01631                   cout << "if test -f " << name << ".sh; then" << endl;
01632                   cout << "  . " << name << ".sh" << endl;
01633                   cout << "fi" << endl;
01634                   result = 1;
01635                   break;
01636                 case Bat :
01637                   cout << "call " << name;
01638                   result = 1;
01639                   break;
01640               }
01641             break;
01642           default:
01643             break;
01644         }
01645     }
01646 
01647   return (result);
01648 }
01649 
01650 //-------------------------------------------------------------
01651 cmt_string Symbol::build_macro_value (bool display_it) const
01652 {
01653   cmt_string temp;
01654 
01655   if (display_it)
01656     {
01657       temp = builder->build_and_display (*this);
01658     }
01659   else
01660     {
01661       temp = builder->build (*this);
01662     }
01663 
01664   return (temp);
01665 }
01666 
01667 //-------------------------------------------------------------
01668 cmt_string Symbol::clean_macro_value () const
01669 {
01670   cmt_string temp;
01671 
01672   temp = builder->clean (*this);
01673 
01674   return (temp);
01675 }
01676 
01701 cmt_string Symbol::resolve_macro_value (const cmt_string& tag_name)
01702 {
01703   cmt_string temp = builder->build (*this, tag_name);
01704 
01705   resolve_value (temp);
01706 
01707   return (temp);
01708 }
01709 
01710 //-------------------------------------------------------------
01711 void Symbol::show_macro (PrintMode mode)
01712 {
01713   if (Cmt::get_debug ())
01714     {
01715       cout << "Symbol::show_macro> " << name << endl;
01716     }
01717 
01718   ActionType action = Cmt::get_action ();
01719 
01720   cmt_string value = build_macro_value (true);
01721 
01722   if ((!Cmt::get_quiet ()) &&
01723       (action != action_build_tag_makefile) &&
01724       (action != action_show_macros) &&
01725       (action != action_show_actions) &&
01726       (action != action_show_sets))
01727     {
01728       cout << "#" << endl;
01729       cout << "# Selection : " << endl;
01730     }
01731 
01732   if (value.size () > 0)
01733     {
01734       if ((action == action_show_macro) ||
01735           (action == action_show_macros) ||
01736           (action == action_show_sets) ||
01737           (action == action_show_set) ||
01738           (action == action_show_actions) ||
01739           (action == action_show_action) ||
01740           (action == action_build_tag_makefile) ||
01741           (action == action_load) ||
01742           (!Cmt::get_quiet ()))
01743         {
01744           if (mode == Make)
01745             {
01746               cout << name << "=";
01747             }
01748           else
01749             {
01750               cout << name << "='";
01751             }
01752         }
01753 
01754       if ((action == action_show_macro_value) ||
01755           (action == action_show_set_value) ||
01756           (action == action_show_action_value))
01757         {
01758           expand (value);
01759         }
01760       else if (action == action_build_tag_makefile)
01761         {
01762             /* 
01763                Unfortunately, the %xxx% pattern has to be kept on Unix. Therefore
01764                we cannot force all patterns to become $(xxx)
01765 
01766                This was useful on Windows so as to only keep $(xxx)
01767              */
01768 #ifdef WIN32
01769           suppress_OS_delimiters (value);
01770 #endif
01771         }
01772 
01773       cout << value;
01774 
01775       if ((action == action_show_macro) ||
01776           (action == action_show_macros) ||
01777           (action == action_show_sets) ||
01778           (action == action_show_set) ||
01779           (action == action_show_actions) ||
01780           (action == action_show_action) ||
01781           (action == action_build_tag_makefile) ||
01782           (action == action_load) ||
01783           (!Cmt::get_quiet ()))
01784         {
01785           if (mode != Make)
01786             {
01787               cout << "'";
01788             }
01789 #ifdef WIN32
01790           else
01791             {
01792               cout << " ";
01793             }
01794 #endif
01795         }
01796 
01797       cout << endl;
01798     }
01799 }
01800 
01801 //-------------------------------------------------------------
01802 void Symbol::clear_all ()
01803 {
01804   static SymbolVector& Symbols = symbols ();
01805   static SymbolMap& SymbolMap = symbol_map ();
01806 
01807   SymbolMap.clear ();
01808   Symbols.clear ();
01809 }
01810 
01811 //-------------------------------------------------------------
01812 void Symbol::expand (cmt_string& text)
01813 {
01814   static cmt_regexp reg ("[$%`]");
01815 
01816   if (!reg.match (text)) return;
01817 
01818   resolve_value (text);
01819 }
01820 
01821 //-------------------------------------------------------------
01822 ValueBuilder::ValueBuilder ()
01823 {
01824   m_display_it = false;
01825 }
01826 
01827 //-------------------------------------------------------------
01828 const cmt_string ValueBuilder::build_and_display (const Symbol& symbol)
01829 {
01830   cmt_string temp;
01831 
01832   m_display_it = true;
01833   temp = build (symbol);
01834   m_display_it = false;
01835 
01836   return (temp);
01837 }
01838 
01839 //-------------------------------------------------------------
01840 const cmt_string SetBuilder::build (const Symbol& symbol,
01841                                     const cmt_string& /*tag_name*/)
01842 {
01843     // Control of recursivity
01844   static int level = 0;
01845 
01846   bool show_it = false;
01847 
01848   cmt_string temp;
01849   cmt_string previous_temp;
01850   cmt_string new_value;
01851   static const cmt_string empty;
01852 
01853   ActionType action = Cmt::get_action ();
01854 
01855   if (action == action_show_set)
01856     {
01857       if (symbol.name == Cmt::get_current_target ())
01858         {
01859              // Should not display on recursive calls
01860           if (level == 0) show_it = m_display_it;
01861         }
01862     }
01863 
01864   level++;
01865 
01866   temp = "";
01867 
01868   bool first_definition = true;
01869   bool defined = false;
01870 
01871   for (int i = 0; i < symbol.value_lists.size (); i++)
01872     {
01873       const SymbolValueList& value_list = symbol.value_lists[i];
01874 
01875       if ((value_list.use != 0) &&
01876           (value_list.use->discarded)) continue;
01877 
01878       const int selected = value_list.select_first ();
01879 
01880       if (selected < 0) continue;
01881 
01882       SymbolValue& value = value_list.values[selected];
01883 
01884       if (show_it)
01885         {
01886           value_list.show (symbol, value, first_definition);
01887         }
01888       
01889       if (value_list.discarded) continue;
01890 
01891         //
01892         // One should accumulate values if it refers to
01893         // itself.
01894         //
01895       
01896       new_value = value.text;
01897       
01898       resolve_value_for_macros (new_value);
01899       
01900       switch (value_list.command_type)
01901         {
01902           case CommandSet :
01903 
01904             if (!value_list.is_reflexive || 
01905                 !symbol.value_is_reflexive (value.text))
01906               {
01907                 resolve_value (new_value, symbol.name, temp);
01908                 temp = new_value;
01909               }
01910             else if (temp == "")
01911               {
01912                 temp = CmtSystem::getenv (symbol.name);
01913               }
01914 
01915             if (!defined)
01916               {
01917                 defined = true;
01918               }
01919             else
01920               {
01921                 if ((!Cmt::get_quiet ()) &&
01922                     ((action == action_show_macro) ||
01923                      (action == action_show_set) ||
01924                      (action == action_show_action) ||
01925                      (action == action_show_macros) ||
01926                      (action == action_show_sets) ||
01927                      (action == action_show_actions)))
01928                   {
01929                     cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
01930 
01931                     if (value_list.use != 0)
01932                       {
01933                         cerr << " in package " << value_list.use->get_package_name ();
01934                       }
01935 
01936                     cerr << endl;
01937                   }
01938               }
01939 
01940             break;
01941           case CommandSetAppend :
01942             
01943             if (new_value != "")
01944               {
01945                 temp += new_value;
01946               }
01947             
01948             break;
01949           case CommandSetPrepend :
01950             
01951             if (new_value != "")
01952               {
01953                 previous_temp = temp;
01954                 temp = new_value;
01955                 temp += previous_temp;
01956               }
01957             
01958             break;
01959           case CommandSetRemove :
01960             
01961             if (new_value != "")
01962               {
01963                 temp.replace_all (new_value, empty);
01964               }
01965             
01966             break;
01967           case CommandSetRemoveRegexp :
01968             
01969             if (new_value != "")
01970               {
01971                 cmt_regexp e (new_value);
01972                 cmt_regexp::iterator it;
01973 
01974                 for (;;)
01975                   {
01976                     it = e.begin (temp);
01977                     if (it == e.end ()) break;
01978 
01979                     temp.erase (it._pos, it._length);
01980                   }
01981               }
01982             
01983             break;
01984           case CommandAlias :
01985             
01986             resolve_value (new_value, symbol.name, temp);
01987             temp = new_value;
01988             
01989             break;
01990         }
01991     }
01992 
01993   level--;
01994 
01995   return (temp);
01996 }
01997 
01998 static bool find_path_entry (const cmt_string& paths, const cmt_string& value)
01999 {
02000   static const cmt_string path_separator = CmtSystem::path_separator ();
02001 
02002   cmt_string here = CmtSystem::pwd ();
02003   cmt_string rvalue = value;
02004 
02005   if (CmtSystem::cd (value))
02006     {
02007       rvalue = CmtSystem::pwd ();
02008     }
02009   else
02010     {
02011       CmtSystem::compress_path (rvalue);
02012     }
02013 
02014   CmtSystem::cmt_string_vector items;
02015   CmtSystem::split (paths, path_separator, items);
02016 
02017   bool found = false;
02018 
02019   for (int i = 0; i < items.size (); i++)
02020     {
02021       const cmt_string& item = items[i];
02022       cmt_string ritem = item;
02023       if (CmtSystem::cd (item))
02024         {
02025           ritem = CmtSystem::pwd ();
02026         }
02027       else
02028         {
02029           CmtSystem::compress_path (ritem);
02030         }
02031 
02032       if (ritem == rvalue)
02033         {
02034           found = true;
02035           break;
02036         }
02037     }
02038 
02039   CmtSystem::cd (here);
02040   return (found);
02041 }
02042 
02043 //-------------------------------------------------------------
02044 const cmt_string PathBuilder::build (const Symbol& symbol,
02045                                      const cmt_string& /*tag_name*/)
02046 {
02047     // Control of recursivity
02048   static int level = 0;
02049 
02050   bool show_it = false;
02051 
02052   cmt_string temp;
02053   cmt_string previous_temp;
02054   cmt_string new_value;
02055   static const cmt_string empty;
02056 
02057   static cmt_string path_separator = CmtSystem::path_separator ();
02058 
02059   ActionType action = Cmt::get_action ();
02060 
02061   if (action == action_show_set)
02062     {
02063       if (symbol.name == Cmt::get_current_target ())
02064         {
02065             // Should not display on recursive calls
02066           if (level == 0) show_it = m_display_it;
02067         }
02068     }
02069 
02070   level++;
02071 
02072   temp = CmtSystem::getenv (symbol.name);
02073 
02074   bool first_definition = true;
02075   bool defined = false;
02076 
02077   for (int i = 0; i < symbol.value_lists.size (); i++)
02078     {
02079       const SymbolValueList& value_list = symbol.value_lists[i];
02080 
02081       if ((value_list.use != 0) &&
02082           (value_list.use->discarded)) continue;
02083 
02084       const int selected = value_list.select_first ();
02085       
02086       if (selected < 0) continue;
02087  
02088       SymbolValue& value = value_list.values[selected];
02089           
02090       if (show_it)
02091         {
02092           value_list.show (symbol, value, first_definition);
02093         }
02094           
02095       if (value_list.discarded) continue;
02096 
02097       new_value = value.text;
02098           
02099           //resolve_value (new_value);
02100       resolve_value_for_macros (new_value);
02101           
02102       switch (value_list.command_type)
02103         {
02104           case CommandPath :
02105             
02106             if (!value_list.is_reflexive || 
02107                 !symbol.value_is_reflexive (value.text))
02108               {
02109                 resolve_value (new_value, symbol.name, temp);
02110                 temp = new_value;
02111 
02112                 if (!defined)
02113                   {
02114                     defined = true;
02115                   }
02116                 else
02117                   {
02118                     if ((!Cmt::get_quiet ()) &&
02119                         ((action == action_show_macro) ||
02120                          (action == action_show_set) ||
02121                          (action == action_show_action) ||
02122                          (action == action_show_macros) ||
02123                          (action == action_show_sets) ||
02124                          (action == action_show_actions)))
02125                       {
02126                         cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
02127                         
02128                         if (value_list.use != 0)
02129                           {
02130                             cerr << " in package " << value_list.use->get_package_name ();
02131                           }
02132                         
02133                         cerr << endl;
02134                       }
02135                   }
02136               }
02137 
02138             break;
02139           case CommandPathAppend :
02140               
02141             if (new_value != "")
02142               {
02143                 if (!find_path_entry (temp, new_value))
02144                   {
02145                     if (temp != "") temp += path_separator;
02146                       
02147                     temp += new_value;
02148                   }
02149               }
02150                   
02151             break;
02152           case CommandPathPrepend :
02153               
02154             if (new_value != "")
02155               {
02156                 if (!find_path_entry (temp, new_value))
02157                   {
02158                     previous_temp = temp;
02159                     temp = new_value;
02160                     if (previous_temp != "") temp += path_separator;
02161                     temp += previous_temp;
02162                   }
02163               }
02164                   
02165             break;
02166           case CommandPathRemove :
02167               
02168             if (new_value != "")
02169               {
02170                 CmtSystem::cmt_string_vector paths;
02171                   
02172                 CmtSystem::split (temp, path_separator, paths);
02173                   
02174                 for (int j = 0; j < paths.size (); ++j)
02175                   {
02176                     cmt_string& s = paths[j];
02177                       
02178                     if (s.find (new_value) != cmt_string::npos)
02179                       {
02180                         s = "";
02181                       }
02182                   }
02183 
02184                 Cmt::vector_to_string (paths, path_separator, temp);
02185               }
02186               
02187             break;
02188           case CommandPathRemoveRegexp :
02189 
02190             if (new_value != "")
02191               {
02192                 cmt_regexp e (new_value);
02193 
02194                 CmtSystem::cmt_string_vector paths;
02195                   
02196                 CmtSystem::split (temp, path_separator, paths);
02197                   
02198                 for (int j = 0; j < paths.size (); ++j)
02199                   {
02200                     cmt_string& s = paths[j];
02201 
02202                     if (CmtSystem::getenv ("TESTPRR") != "")
02203                       {
02204                         cout << "PRR> s=[" << s << "]";
02205                       }
02206 
02207                     if (e.match (s))
02208                       {
02209                         s = "";
02210 
02211                         if (CmtSystem::getenv ("TESTPRR") != "")
02212                           {
02213                             cout << " match ";
02214                           }
02215                       }
02216                     else
02217                       {
02218                         if (CmtSystem::getenv ("TESTPRR") != "")
02219                           {
02220                             cout << " no match ";
02221                           }
02222                       }
02223 
02224                     if (CmtSystem::getenv ("TESTPRR") != "")
02225                       {
02226                         cout << endl;
02227                       }
02228                   }
02229 
02230                 Cmt::vector_to_string (paths, path_separator, temp);
02231               }
02232               
02233             break;
02234         }
02235 
02236     }
02237 
02238   level--;
02239 
02240   for (;;)
02241     {
02242       int sz = temp.size ();
02243 
02244       if (sz == 0) break;
02245 
02246       if ((temp[0] == ';') || (temp[0] == ':'))
02247         {
02248           temp.erase (0, 1);
02249         }
02250       else if ((temp[sz-1] == ';') || (temp[sz-1] == ':'))
02251         {
02252           temp.erase (sz-1, 1);
02253         }
02254       else
02255         {
02256           break;
02257         }
02258     }
02259 
02260   temp.replace_all ("::", ":");
02261   temp.replace_all (";;", ";");
02262   
02263   return (temp);
02264 }
02265 
02266 //-------------------------------------------------------------
02267 const cmt_string PathBuilder::clean (const Symbol& symbol,
02268                                      const cmt_string& /*tag_name*/)
02269 {
02270     // Control of recursivity
02271   static int level = 0;
02272 
02273   cmt_string temp;
02274   cmt_string new_value;
02275   static const cmt_string empty;
02276 
02277   static cmt_string path_separator = CmtSystem::path_separator ();
02278 
02279   temp = CmtSystem::getenv (symbol.name);
02280 
02281     //cerr << "#####1 temp=" << temp << endl;
02282 
02283   for (int i = 0; i < symbol.value_lists.size (); i++)
02284     {
02285       const SymbolValueList& value_list = symbol.value_lists[i];
02286 
02287       if (value_list.discarded) continue;
02288 
02289       if ((value_list.use != 0) &&
02290           (value_list.use->discarded)) continue;
02291 
02292       const int selected = value_list.select_first ();
02293       
02294       if (selected < 0) continue;
02295  
02296       SymbolValue& value = value_list.values[selected];
02297           
02298       new_value = value.text;
02299           
02300           //resolve_value (new_value);
02301 
02302         //cerr << "#####1 new_value=" << new_value << endl;
02303 
02304       resolve_value_for_macros (new_value);
02305       resolve_value (new_value);
02306           
02307         //cerr << "#####2 new_value=" << new_value << endl;
02308 
02309       switch (value_list.command_type)
02310         {
02311           case CommandPath :
02312             
02313             temp = "";
02314             
02315             break;
02316           case CommandPathAppend :
02317           case CommandPathPrepend :
02318           case CommandPathRemove :
02319 
02320             if (new_value != "")
02321               {
02322                 CmtSystem::cmt_string_vector paths;
02323                   
02324                 CmtSystem::split (temp, path_separator, paths);
02325                   
02326                 for (int j = 0; j < paths.size (); ++j)
02327                   {
02328                     cmt_string& s = paths[j];
02329                       
02330                     if (s.find (new_value) != cmt_string::npos)
02331                       {
02332                         s = "";
02333                       }
02334 
02335                     if (j > 0)
02336                       {
02337                         cmt_string& s2 = paths[j-1];
02338                         if (s2 == s)
02339                           {
02340                             s2 = "";
02341                           }
02342                       }
02343                   }
02344 
02345                 Cmt::vector_to_string (paths, path_separator, temp);
02346                 temp.replace_all ("::", ":");
02347                 temp.replace_all (";;", ";");
02348               }
02349               
02350             break;
02351           case CommandPathRemoveRegexp :
02352 
02353             if (new_value != "")
02354               {
02355                 cmt_regexp e (new_value);
02356 
02357                 CmtSystem::cmt_string_vector paths;
02358                   
02359                 CmtSystem::split (temp, path_separator, paths);
02360                   
02361                 for (int j = 0; j < paths.size (); ++j)
02362                   {
02363                     cmt_string& s = paths[j];
02364                       
02365                     if (e.match (s))
02366                       {
02367                         s = "";
02368                       }
02369 
02370                     if (j > 0)
02371                       {
02372                         cmt_string& s2 = paths[j-1];
02373                         if (s2 == s)
02374                           {
02375                             s2 = "";
02376                           }
02377                       }
02378                   }
02379 
02380                 Cmt::vector_to_string (paths, path_separator, temp);
02381                 temp.replace_all ("::", ":");
02382                 temp.replace_all (";;", ";");
02383               }
02384               
02385             break;
02386         }
02387     }
02388 
02389     //cerr << "#####2 temp=" << temp << endl;
02390   
02391   return (temp);
02392 }
02393 
02394 //-------------------------------------------------------------
02395 const cmt_string MacroBuilder::build (const Symbol& symbol,
02396                                       const cmt_string& tag_name)
02397 {
02398     // Control of recursivity
02399   static int level = 0;
02400 
02401   cmt_string temp;
02402   cmt_string previous_temp;
02403   static const cmt_string empty;
02404   bool show_it = false;
02405 
02406   ActionType action = Cmt::get_action ();
02407 
02408   if (action == action_show_macro)
02409     {
02410       if (symbol.name == Cmt::get_current_target ())
02411         {
02412              // Should not display on recursive calls
02413           if (level == 0) show_it = m_display_it;
02414         }
02415     }
02416 
02417   level++;
02418 
02419   temp = "";
02420 
02421   int i;
02422 
02423   bool first_definition = true;
02424   bool defined = false;
02425 
02426   for (i = 0; i < symbol.value_lists.size (); i++)
02427     {
02428       const SymbolValueList& value_list = symbol.value_lists[i];
02429 
02430       if ((value_list.use != 0) &&
02431           (value_list.use->discarded)) continue;
02432 
02433       if (value_list.command_type != CommandMacroPrepend) continue;
02434 
02435       const int selected = value_list.select_first (tag_name);
02436 
02437       if (selected < 0) continue;
02438 
02439       SymbolValue& value = value_list.values[selected];
02440 
02441       if (show_it)
02442         {
02443           value_list.show (symbol, value, first_definition);
02444         }
02445 
02446       if (value_list.discarded) continue;
02447 
02448       previous_temp = temp;
02449       temp = value.text;
02450       temp += previous_temp;
02451     }
02452 
02453   previous_temp = temp;
02454   temp = "";
02455 
02456   first_definition = true;
02457 
02458   for (i = 0; i < symbol.value_lists.size (); i++)
02459     {
02460       const SymbolValueList& value_list = symbol.value_lists[i];
02461 
02462       if ((value_list.use != 0) &&
02463           (value_list.use->discarded)) continue;
02464 
02465       if (value_list.command_type != CommandMacro) continue;
02466 
02467       const int selected = value_list.select_first (tag_name);
02468 
02469       if (selected < 0) continue;
02470 
02471       SymbolValue& value = value_list.values[selected];
02472 
02473       if (show_it)
02474         {
02475           value_list.show (symbol, value, first_definition);
02476         }
02477 
02478       // WARNING:
02479       // Commented just for a test : should be uncommented after the test
02480       if (value_list.discarded) continue;
02481       
02482       if (!value_list.is_reflexive || 
02483           !symbol.value_is_reflexive (value.text))
02484         {
02485           temp = value.text;
02486 
02487           if (!defined)
02488             {
02489               defined = true;
02490             }
02491           else
02492             {
02493               /*
02494               if ((!Cmt::get_quiet ()) &&
02495                   ((action == action_show_macro) ||
02496                    (action == action_show_set) ||
02497                    (action == action_show_action) ||
02498                    (action == action_show_macros) ||
02499                    (action == action_show_sets) ||
02500                    (action == action_show_actions)))
02501                 {
02502                   cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
02503                   
02504                   if (value_list.use != 0)
02505                     {
02506                       cerr << " in package " << value_list.use->get_package_name ();
02507                     }
02508 
02509                   cerr << endl;
02510                 }
02511               */
02512             }
02513         }
02514     }
02515 
02516   previous_temp += temp;
02517   temp = previous_temp;
02518 
02519   for (i = 0; i < symbol.value_lists.size (); i++)
02520     {
02521       const SymbolValueList& value_list = symbol.value_lists[i];
02522 
02523       if ((value_list.use != 0) &&
02524           (value_list.use->discarded)) continue;
02525 
02526       if (value_list.command_type != CommandMacroAppend) continue;
02527 
02528       const int selected = value_list.select_first (tag_name);
02529 
02530       if (selected < 0) continue;
02531 
02532       SymbolValue& value = value_list.values[selected];
02533 
02534       if (show_it)
02535         {
02536           value_list.show (symbol, value, first_definition);
02537         }
02538 
02539       if (value_list.discarded) continue;
02540 
02541       temp += value.text;
02542     }
02543 
02544   for (i = 0; i < symbol.value_lists.size (); i++)
02545     {
02546       const SymbolValueList& value_list = symbol.value_lists[i];
02547 
02548       if ((value_list.use != 0) &&
02549           (value_list.use->discarded)) continue;
02550 
02551       if ((value_list.command_type != CommandMacroRemove) &&
02552           (value_list.command_type != CommandMacroRemoveRegexp) &&
02553           (value_list.command_type != CommandMacroRemoveAll) &&
02554           (value_list.command_type != CommandMacroRemoveAllRegexp)) continue;
02555 
02556       const int selected = value_list.select_first (tag_name);
02557 
02558       if (selected < 0) continue;
02559 
02560       SymbolValue& value = value_list.values[selected];
02561 
02562       if (show_it)
02563         {
02564           value_list.show (symbol, value, first_definition);
02565         }
02566 
02567       if (value_list.discarded) continue;
02568 
02569       switch (value_list.command_type)
02570         {
02571           case CommandMacroRemove :
02572             temp.replace (value.text, empty);
02573             break;
02574           case CommandMacroRemoveRegexp :
02575             if (value.text != "")
02576               {
02577                 cmt_regexp e (value.text);
02578                 cmt_regexp::iterator it;
02579 
02580                 it = e.begin (temp);
02581                 if (it != e.end ())
02582                   {
02583                     temp.erase (it._pos, it._length);
02584                   }
02585               }
02586             break;
02587           case CommandMacroRemoveAll :
02588             temp.replace_all (value.text, empty);
02589             break;
02590           case CommandMacroRemoveAllRegexp :
02591             if (value.text != "")
02592               {
02593                 cmt_regexp e (value.text);
02594                 cmt_regexp::iterator it;
02595 
02596                 for (;;)
02597                   {
02598                     it = e.begin (temp);
02599                     if (it != e.end ())
02600                       {
02601                         temp.erase (it._pos, it._length);
02602                       }
02603                     else
02604                       {
02605                         break;
02606                       }
02607                   }
02608               }
02609             break;
02610         }
02611     }
02612 
02613   level--;
02614 
02615   return (temp);
02616 }
02617 
02618 //-------------------------------------------------------------
02619 const cmt_string ScriptBuilder::build (const Symbol& symbol,
02620                                        const cmt_string& tag_name)
02621 {
02622     // Control of recursivity
02623   static int level = 0;
02624 
02625   static const cmt_string empty = "";
02626 
02627   if (symbol.value_lists.size () > 0)
02628     {
02629       const SymbolValueList& value_list = symbol.value_lists[0];
02630 
02631       if (value_list.discarded) return (empty);
02632 
02633       if ((value_list.use != 0) &&
02634           (value_list.use->discarded)) return (empty);
02635     }
02636 
02637   return (symbol.name);
02638 }
02639 
02640 //-------------------------------------------------------------
02641 const cmt_string ActionBuilder::build (const Symbol& symbol,
02642                                        const cmt_string& tag_name)
02643 {
02644     // Control of recursivity
02645   static int level = 0;
02646 
02647   cmt_string temp;
02648   cmt_string previous_temp;
02649   static const cmt_string empty;
02650   bool show_it = false;
02651 
02652   ActionType action = Cmt::get_action ();
02653 
02654   if (action == action_show_action)
02655     {
02656       if (symbol.name == Cmt::get_current_target ())
02657         {
02658              // Should not display on recursive calls
02659           if (level == 0) show_it = m_display_it;
02660         }
02661     }
02662 
02663   level++;
02664 
02665   int i;
02666 
02667   bool first_definition = true;
02668   bool defined = false;
02669 
02670   temp = "";
02671 
02672   for (i = 0; i < symbol.value_lists.size (); i++)
02673     {
02674       const SymbolValueList& value_list = symbol.value_lists[i];
02675 
02676       if ((value_list.use != 0) &&
02677           (value_list.use->discarded)) continue;
02678 
02679       if (value_list.command_type != CommandAction) continue;
02680 
02681       const int selected = value_list.select_first (tag_name);
02682 
02683       if (selected < 0) continue;
02684 
02685       SymbolValue& value = value_list.values[selected];
02686 
02687       if (show_it)
02688         {
02689           value_list.show (symbol, value, first_definition);
02690         }
02691 
02692       // WARNING:
02693       // Commented just for a test : should be uncommented after the test
02694       if (value_list.discarded) continue;
02695       
02696       if (!value_list.is_reflexive || 
02697           !symbol.value_is_reflexive (value.text))
02698         {
02699           temp = value.text;
02700 
02701           if (!defined)
02702             {
02703               defined = true;
02704             }
02705           else
02706             {
02707               if ((!Cmt::get_quiet ()) &&
02708                   ((action == action_show_macro) ||
02709                    (action == action_show_set) ||
02710                    (action == action_show_action) ||
02711                    (action == action_show_macros) ||
02712                    (action == action_show_sets) ||
02713                    (action == action_show_actions)))
02714                 {
02715                   cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
02716                   
02717                   if (value_list.use != 0)
02718                     {
02719                       cerr << " in package " << value_list.use->get_package_name ();
02720                     }
02721 
02722                   cerr << endl;
02723                 }
02724             }
02725         }
02726     }
02727 
02728   level--;
02729 
02730   return (temp);
02731 }
02732 
02733 //-------------------------------------------------------------
02734 int SymbolValueList::select_first (const cmt_string& tag_name) const
02735 {
02736   int priority = 0;
02737   int value_number;
02738   int selected = -1;
02739 
02740   Tag* the_tag = 0;
02741 
02742   if (tag_name != "") the_tag = Tag::find (tag_name);
02743 
02744   for (value_number = 0;
02745        value_number < values.size ();
02746        value_number++)
02747     {
02748       const SymbolValue& value = values[value_number];
02749 
02750       const Tag* tag = value.tag;
02751 
02752       if (the_tag == 0)
02753         {
02754           if (!tag->is_selected ()) continue;
02755         }
02756       else
02757         {
02758           if (tag != the_tag) continue;
02759           selected = value_number;
02760         }
02761 
02762       //
02763       // Only the first value at a given priority is
02764       // selected (which implies the '>' test instead
02765       // of '>=')
02766       //
02767 
02768       if (tag->get_priority () > priority)
02769         {
02770           priority = tag->get_priority ();
02771           selected = value_number;
02772         }
02773     }
02774 
02775   return (selected);
02776 }
02777 
02778 //-------------------------------------------------------------
02779 int SymbolValueList::select_last () const
02780 {
02781   int priority = 0;
02782   int value_number;
02783   int selected = -1;
02784 
02785   for (value_number = 0;
02786        value_number < values.size ();
02787        value_number++)
02788     {
02789       SymbolValue& value = values[value_number];
02790 
02791       const Tag* tag = value.tag;
02792 
02793       if (tag->is_selected ())
02794         {
02795           //
02796           // The last value at a given priority is
02797           // selected (which implies the '>=' test instead
02798           // of '>')
02799           //
02800 
02801           if (tag->get_priority () >= priority)
02802             {
02803               priority = tag->get_priority ();
02804               selected = value_number;
02805             }
02806         }
02807     }
02808 
02809   return (selected);
02810 }
02811 
02812 //-------------------------------------------------------------
02813 void SymbolValueList::show (const Symbol& symbol, 
02814                             const SymbolValue& value, 
02815                             bool& first_definition) const
02816 {
02817   cmt_string discarded_text;
02818   cmt_string define_text;
02819   ActionType action = Cmt::get_action ();
02820 
02821   if (value.text == "") return;
02822 
02823   if (discarded) discarded_text = " (discarded by override)";
02824   else discarded_text = "";
02825 
02826   if (first_definition) define_text = "defines";
02827   else define_text = "overrides";
02828 
02829   cout << "# Package ";
02830   if (use != 0)
02831     {
02832       cout << use->get_package_name () << " " << use->version;
02833     }
02834 
02835   switch (command_type)
02836     {
02837       case CommandSet :
02838         cout << " " << define_text << " set " << symbol.name << " as ";
02839         first_definition = false;
02840         break;
02841       case CommandSetAppend :
02842         cout << " appends to set " << symbol.name << " : ";
02843         break;
02844       case CommandSetPrepend :
02845         cout << " prepends to set " << symbol.name << " : ";
02846         break;
02847       case CommandSetRemove :
02848         cout << " removes from set " << symbol.name << " : ";
02849         break;
02850       case CommandSetRemoveRegexp :
02851         cout << " removes RE from set " << symbol.name << " : ";
02852         break;
02853       case CommandAlias :
02854         cout << " " << define_text << " alias " << symbol.name << " as ";
02855         first_definition = false;
02856         break;
02857       case CommandPath :
02858         cout << " " << define_text << " path " << symbol.name << " as ";
02859         first_definition = false;
02860         break;
02861       case CommandPathAppend :
02862         cout << " appends to path " << symbol.name << " : ";
02863         break;
02864       case CommandPathPrepend :
02865         cout << " prepends to path " << symbol.name << " : ";
02866         break;
02867       case CommandPathRemove :
02868         cout << " removes from path " << symbol.name << " : ";
02869         break;
02870       case CommandPathRemoveRegexp :
02871         cout << " removes RE from path " << symbol.name << " : ";
02872         break;
02873       case CommandMacroPrepend :
02874         cout << " prepends to macro " << symbol.name << " : ";
02875         break;
02876       case CommandMacro :
02877         cout << " " << define_text << " macro " << symbol.name << " as ";
02878         break;
02879       case CommandMacroAppend :
02880         cout << " appends to macro " << symbol.name << " : ";
02881         break;
02882       case CommandMacroRemove :
02883         cout << " remove from macro " << symbol.name << " : ";
02884         break;
02885       case CommandMacroRemoveRegexp :
02886         cout << " remove RE from macro " << symbol.name << " : ";
02887         break;
02888       case CommandMacroRemoveAll :
02889         cout << " remove all from macro " << symbol.name << " : ";
02890         break;
02891       case CommandMacroRemoveAllRegexp :
02892         cout << " remove all RE from macro " << symbol.name << " : ";
02893         break;
02894       case CommandAction :
02895         cout << " " << define_text << " action " << symbol.name << " as ";
02896         first_definition = false;
02897         break;
02898     }
02899 
02900   cout << "'" << value.text << "'";
02901           
02902   Tag* selected_tag = value.tag;
02903           
02904   if ((selected_tag == 0) ||
02905       (selected_tag == Tag::get_default ()))
02906     {
02907       cout << " for default tag";
02908     }
02909   else
02910     {
02911       cout << " for tag '" << selected_tag->get_name () << "'";
02912     }
02913   
02914   cout << discarded_text << endl;
02915 }
02916 
02917 //-------------------------------------------------------------
02918 bool Symbol::check_tag_used (Tag* tag)
02919 {
02920   if (tag == 0) return (false);
02921 
02922   static SymbolVector& Symbols = symbols ();
02923 
02924   if (Symbols.size () == 0) 
02925     {
02926       return (false);
02927     }
02928 
02929   for (int number = 0; number < Symbol::symbol_number (); number++)
02930     {
02931       Symbol& symbol = Symbol::symbol (number);
02932 
02933       for (int i = 0; i < symbol.value_lists.size (); i++)
02934         {
02935           const SymbolValueList& value_list = symbol.value_lists[i];
02936 
02937           for (int j = 0; j < value_list.values.size (); j++)
02938             {
02939               const SymbolValue& value = value_list.values[j];
02940               Tag* t = value.tag;
02941 
02942               if (t != 0)
02943                 {
02944                   if (t->use_operand (tag)) return (true);
02945                 }
02946             }
02947         }
02948     }
02949 
02950   return (false);
02951 }
02952 

Generated on Mon Sep 5 16:30:48 2005 for CMT by 1.3.5