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 // arnault@lal.in2p3.fr
00004 // See the complete license in cmt_license.txt "http://www.cecill.info". 
00005 //-----------------------------------------------------------
00006 
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <string.h>
00010 #include <ctype.h>
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         <tag> <value>
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     //     $(<symbol>)
01179     //     ${<symbol>}
01180     //     %<symbol>%
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 
01250   static CmtSystem::cmt_string_vector envs;
01251 
01252   envs.clear ();
01253 
01254   int number;
01255 
01256   if (Symbols.size () == 0) 
01257     {
01258         //running = false;
01259       return;
01260     }
01261 
01262   cmt_string value;
01263 
01264   for (number = 0; number < Symbol::symbol_number (); number++)
01265     {
01266       Symbol& symbol = Symbol::symbol (number);
01267 
01268       if (symbol.type != SymbolSet) continue;
01269 
01270       value = symbol.build_macro_value ();
01271       if (value != "")
01272         {
01273           cmt_string& temp = envs.add ();
01274 
01275           temp = symbol.name;
01276           temp += '=';
01277           temp += value;
01278         }
01279     }
01280 
01281   for (number = 0; number < Symbol::symbol_number (); number++)
01282     {
01283       Symbol& symbol = Symbol::symbol (number);
01284 
01285       if ((symbol.type != SymbolPath)) continue;
01286 
01287       value = symbol.build_macro_value ();
01288       if (value != "")
01289         {
01290           cmt_string& temp = envs.add ();
01291 
01292           temp = symbol.name;
01293           temp += '=';
01294           temp += value;
01295         }
01296     }
01297 
01298   for (number = 0; number < envs.size (); number++)
01299     {
01300       cmt_string& env = envs[number];
01301       Symbol::expand (env);
01302 
01303 #ifdef WIN32
01304       env.replace_all ("/", "\\");
01305 #endif
01306 
01307       if (Cmt::get_debug ())
01308         {
01309           cout << "Symbol::all_set> " << env << endl;
01310         }
01311       CmtSystem::putenv (env);
01312     }
01313 
01314     //running = false;
01315 }
01316 
01317 //-------------------------------------------------------------
01318 void Symbol::all_print (PrintMode mode)
01319 {
01320   static SymbolVector& Symbols = symbols ();
01321 
01322   int number;
01323 
01324   if (Symbols.size () == 0) return;
01325 
01326   for (number = 0; number < Symbol::symbol_number (); number++)
01327     {
01328       Symbol& symbol = Symbol::symbol (number);
01329 
01330       if ((symbol.type == SymbolSet) ||
01331           (symbol.type == SymbolAlias) ||
01332           (symbol.type == SymbolSetupScript))
01333         {
01334           if (symbol.print (mode))
01335             {
01336               if (mode == Bat)
01337                 {
01338                   cout << endl;
01339                 }
01340               else
01341                 {
01342                   //cout << "; ";
01343                   cout << endl;
01344                 }
01345             }
01346         }
01347     }
01348 
01349   for (number = 0; number < Symbol::symbol_number (); number++)
01350     {
01351       Symbol& symbol = Symbol::symbol (number);
01352 
01353       if ((symbol.type != SymbolPath)) continue;
01354 
01355       if (symbol.print (mode))
01356         {
01357           if (mode == Bat)
01358             {
01359               cout << endl;
01360             }
01361           else
01362             {
01363               //cout << "; ";
01364               cout << endl;
01365             }
01366         }
01367     }
01368 }
01369 
01370 //-------------------------------------------------------------
01371 void Symbol::all_print_clean (PrintMode mode)
01372 {
01373   static SymbolVector& Symbols = symbols ();
01374 
01375   int number;
01376 
01377   if (Symbols.size () == 0) return;
01378 
01379   for (number = Symbols.size () - 1; number >= 0; number--)
01380     {
01381       Symbol& symbol = Symbols[number];
01382 
01383       if ((symbol.type == SymbolSet) ||
01384           (symbol.type == SymbolAlias) ||
01385           (symbol.type == SymbolCleanupScript))
01386         {
01387           if (symbol.print_clean (mode))
01388             {
01389               cout << endl;
01390             }
01391         }
01392     }
01393 
01394   for (number = Symbols.size () - 1; number >= 0; number--)
01395     {
01396       Symbol& symbol = Symbols[number];
01397 
01398       if ((symbol.type != SymbolPath)) continue;
01399 
01400       if (symbol.print_clean (mode))
01401         {
01402           cout << endl;
01403         }
01404     }
01405 }
01406 
01407 //-------------------------------------------------------------
01408 int Symbol::print_clean (PrintMode mode)
01409 {
01410   int result = 0;
01411   static cmt_string temp;
01412 
01413   if (name == "CMTCONFIG") return (0);
01414 
01415   switch (type)
01416     {
01417     case SymbolSet :
01418       switch (mode)
01419         {
01420         case Csh :
01421           cout << "unsetenv " << name;
01422           result = 1;
01423           break;
01424         case Sh :
01425           cout << "unset " << name;
01426           result = 1;
01427           break;
01428         case Bat :
01429           cout << "set " << name << "=";
01430           result = 1;
01431           break;
01432         }
01433       break;
01434     case SymbolAlias :
01435       switch (mode)
01436         {
01437           case Csh :
01438             cout << "unalias " << name;
01439             result = 1;
01440             break;
01441           case Sh :
01442             cout << "unset " << name;
01443             result = 1;
01444             break;
01445         }
01446       break;
01447     case SymbolPath :
01448       temp = clean_macro_value ();
01449       switch (mode)
01450         {
01451         case Csh :
01452           if (temp == "")
01453             {
01454               cout << "unsetenv " << name;
01455             }
01456           else
01457             {
01458               cout << "setenv " << name << " " << temp;
01459             }
01460           result = 1;
01461           break;
01462         case Sh :
01463           cout << name << "=" << temp << "; export " << name;
01464           result = 1;
01465           break;
01466         case Bat :
01467           cout << "set " << name << "=" << temp;
01468           result = 1;
01469           break;
01470         }
01471       break;
01472     case SymbolCleanupScript :
01473       switch (mode)
01474         {
01475         case Csh :
01476           cout << "if ( -f " << name << ".csh ) then" << endl;
01477           cout << "  source " << name << ".csh" << endl;
01478           cout << "endif" << endl;
01479           result = 1;
01480           break;
01481         case Sh :
01482           cout << "if test -f " << name << ".sh; then" << endl;
01483           cout << "  . " << name << ".sh" << endl;
01484           cout << "fi" << endl;
01485           result = 1;
01486           break;
01487         case Bat :
01488           cout << "call " << name;
01489           result = 1;
01490           break;
01491         }
01492       break;
01493     }
01494 
01495   return (result);
01496 }
01497 
01498 //-------------------------------------------------------------
01499 int Symbol::print (PrintMode mode)
01500 {
01501   int result = 0;
01502   cmt_string temp;
01503 
01504   temp = build_macro_value ();
01505 
01506   bool empty = (temp.size () == 0) ? true : false;
01507 
01508   switch (type)
01509     {
01510       case SymbolSet :
01511       case SymbolPath :
01512         switch (mode)
01513           {
01514             case Csh :
01515               if (empty) cout << "unsetenv " << name;
01516               else cout << "setenv " << name << " \"" << temp << "\"";
01517 
01518               result = 1;
01519               break;
01520             case Sh :
01521               if (empty) cout << "unset " << name;
01522               else cout << name << "=\"" << temp << "\"; export " << name;
01523 
01524               result = 1;
01525               break;
01526             case Bat :
01527               temp.replace_all ("/", "\\");
01528               cout << "set " << name << "=" << temp;
01529               result = 1;
01530               break;
01531           }
01532         break;
01533       case SymbolAlias :
01534         switch (mode)
01535           {
01536             case Csh :
01537               cout << "alias " << name <<
01538                   " \"" << temp << "\"";
01539               result = 1;
01540               break;
01541             case Sh :
01542               cout << "alias " << name <<
01543                   "=\"" << temp << "\"";
01544               result = 1;
01545               break;
01546             case Bat :
01547               cout << "set " << name <<
01548                   "=" << temp;
01549               result = 1;
01550               break;
01551           }
01552         break;
01553       default :
01554         break;
01555     }
01556 
01557   if (temp != "")
01558     {
01559       switch (type)
01560         {
01561           case SymbolSetupScript :
01562             switch (mode)
01563               {
01564                 case Csh :
01565                   cout << "if ( -f " << name << ".csh ) then" << endl;
01566                   cout << "  source " << name << ".csh" << endl;
01567                   cout << "endif" << endl;
01568                   result = 1;
01569                   break;
01570                 case Sh :
01571                   cout << "if test -f " << name << ".sh; then" << endl;
01572                   cout << "  . " << name << ".sh" << endl;
01573                   cout << "fi" << endl;
01574                   result = 1;
01575                   break;
01576                 case Bat :
01577                   cout << "call " << name;
01578                   result = 1;
01579                   break;
01580               }
01581             break;
01582           default:
01583             break;
01584         }
01585     }
01586 
01587   return (result);
01588 }
01589 
01590 //-------------------------------------------------------------
01591 cmt_string Symbol::build_macro_value (bool display_it) const
01592 {
01593   cmt_string temp;
01594 
01595   if (display_it)
01596     {
01597       temp = builder->build_and_display (*this);
01598     }
01599   else
01600     {
01601       temp = builder->build (*this);
01602     }
01603 
01604   return (temp);
01605 }
01606 
01607 //-------------------------------------------------------------
01608 cmt_string Symbol::clean_macro_value () const
01609 {
01610   cmt_string temp;
01611 
01612   temp = builder->clean (*this);
01613 
01614   return (temp);
01615 }
01616 
01641 cmt_string Symbol::resolve_macro_value (const cmt_string& tag_name)
01642 {
01643   cmt_string temp = builder->build (*this, tag_name);
01644 
01645   resolve_value (temp);
01646 
01647   return (temp);
01648 }
01649 
01650 //-------------------------------------------------------------
01651 void Symbol::show_macro (PrintMode mode)
01652 {
01653   if (Cmt::get_debug ())
01654     {
01655       cout << "Symbol::show_macro> " << name << endl;
01656     }
01657 
01658   ActionType action = Cmt::get_action ();
01659 
01660   cmt_string value = build_macro_value (true);
01661 
01662   if ((!Cmt::get_quiet ()) &&
01663       (action != action_build_tag_makefile) &&
01664       (action != action_show_macros) &&
01665       (action != action_show_actions) &&
01666       (action != action_show_sets))
01667     {
01668       cout << "#" << endl;
01669       cout << "# Selection : " << endl;
01670     }
01671 
01672   if (value.size () > 0)
01673     {
01674       if ((action == action_show_macro) ||
01675           (action == action_show_macros) ||
01676           (action == action_show_sets) ||
01677           (action == action_show_set) ||
01678           (action == action_show_actions) ||
01679           (action == action_show_action) ||
01680           (action == action_build_tag_makefile) ||
01681           (action == action_load) ||
01682           (!Cmt::get_quiet ()))
01683         {
01684           if (mode == Make)
01685             {
01686               cout << name << "=";
01687             }
01688           else
01689             {
01690               cout << name << "='";
01691             }
01692         }
01693 
01694       if ((action == action_show_macro_value) ||
01695           (action == action_show_set_value) ||
01696           (action == action_show_action_value))
01697         {
01698           expand (value);
01699         }
01700       else if (action == action_build_tag_makefile)
01701         {
01702             /* 
01703                Unfortunately, the %xxx% pattern has to be kept on Unix. Therefore
01704                we cannot force all patterns to become $(xxx)
01705 
01706                This was useful on Windows so as to only keep $(xxx)
01707              */
01708 #ifdef WIN32
01709           suppress_OS_delimiters (value);
01710 #endif
01711         }
01712 
01713       cout << value;
01714 
01715       if ((action == action_show_macro) ||
01716           (action == action_show_macros) ||
01717           (action == action_show_sets) ||
01718           (action == action_show_set) ||
01719           (action == action_show_actions) ||
01720           (action == action_show_action) ||
01721           (action == action_build_tag_makefile) ||
01722           (action == action_load) ||
01723           (!Cmt::get_quiet ()))
01724         {
01725           if (mode != Make)
01726             {
01727               cout << "'";
01728             }
01729 #ifdef WIN32
01730           else
01731             {
01732               cout << " ";
01733             }
01734 #endif
01735         }
01736 
01737       cout << endl;
01738     }
01739 }
01740 
01741 //-------------------------------------------------------------
01742 void Symbol::clear_all ()
01743 {
01744   static SymbolVector& Symbols = symbols ();
01745   static SymbolMap& SymbolMap = symbol_map ();
01746 
01747   SymbolMap.clear ();
01748   Symbols.clear ();
01749 }
01750 
01751 //-------------------------------------------------------------
01752 void Symbol::expand (cmt_string& text)
01753 {
01754   static cmt_regexp reg ("[$%`]");
01755 
01756   if (!reg.match (text)) return;
01757 
01758   resolve_value (text);
01759 }
01760 
01761 //-------------------------------------------------------------
01762 ValueBuilder::ValueBuilder ()
01763 {
01764   m_display_it = false;
01765 }
01766 
01767 //-------------------------------------------------------------
01768 const cmt_string ValueBuilder::build_and_display (const Symbol& symbol)
01769 {
01770   cmt_string temp;
01771 
01772   m_display_it = true;
01773   temp = build (symbol);
01774   m_display_it = false;
01775 
01776   return (temp);
01777 }
01778 
01779 //-------------------------------------------------------------
01780 const cmt_string SetBuilder::build (const Symbol& symbol,
01781                                     const cmt_string& /*tag_name*/)
01782 {
01783     // Control of recursivity
01784   static int level = 0;
01785 
01786   bool show_it = false;
01787 
01788   cmt_string temp;
01789   cmt_string previous_temp;
01790   cmt_string new_value;
01791   static const cmt_string empty;
01792 
01793   ActionType action = Cmt::get_action ();
01794 
01795   if (action == action_show_set)
01796     {
01797       if (symbol.name == Cmt::get_current_target ())
01798         {
01799              // Should not display on recursive calls
01800           if (level == 0) show_it = m_display_it;
01801         }
01802     }
01803 
01804   level++;
01805 
01806   temp = "";
01807 
01808   bool first_definition = true;
01809   bool defined = false;
01810 
01811   for (int i = 0; i < symbol.value_lists.size (); i++)
01812     {
01813       const SymbolValueList& value_list = symbol.value_lists[i];
01814 
01815       if ((value_list.use != 0) &&
01816           (value_list.use->discarded)) continue;
01817 
01818       const int selected = value_list.select_first ();
01819 
01820       if (selected < 0) continue;
01821 
01822       SymbolValue& value = value_list.values[selected];
01823 
01824       if (show_it)
01825         {
01826           value_list.show (symbol, value, first_definition);
01827         }
01828       
01829       if (value_list.discarded) continue;
01830 
01831         //
01832         // One should accumulate values if it refers to
01833         // itself.
01834         //
01835       
01836       new_value = value.text;
01837       
01838       resolve_value_for_macros (new_value);
01839       
01840       switch (value_list.command_type)
01841         {
01842           case CommandSet :
01843 
01844             if (!value_list.is_reflexive || 
01845                 !symbol.value_is_reflexive (value.text))
01846               {
01847                 resolve_value (new_value, symbol.name, temp);
01848                 temp = new_value;
01849               }
01850             else if (temp == "")
01851               {
01852                 temp = CmtSystem::getenv (symbol.name);
01853               }
01854 
01855             if (!defined)
01856               {
01857                 defined = true;
01858               }
01859             else
01860               {
01861                 if ((!Cmt::get_quiet ()) &&
01862                     ((action == action_show_macro) ||
01863                      (action == action_show_set) ||
01864                      (action == action_show_action) ||
01865                      (action == action_show_macros) ||
01866                      (action == action_show_sets) ||
01867                      (action == action_show_actions)))
01868                   {
01869                     cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
01870 
01871                     if (value_list.use != 0)
01872                       {
01873                         cerr << " in package " << value_list.use->get_package_name ();
01874                       }
01875 
01876                     cerr << endl;
01877                   }
01878               }
01879 
01880             break;
01881           case CommandSetAppend :
01882             
01883             if (new_value != "")
01884               {
01885                 temp += new_value;
01886               }
01887             
01888             break;
01889           case CommandSetPrepend :
01890             
01891             if (new_value != "")
01892               {
01893                 previous_temp = temp;
01894                 temp = new_value;
01895                 temp += previous_temp;
01896               }
01897             
01898             break;
01899           case CommandSetRemove :
01900             
01901             if (new_value != "")
01902               {
01903                 temp.replace_all (new_value, empty);
01904               }
01905             
01906             break;
01907           case CommandSetRemoveRegexp :
01908             
01909             if (new_value != "")
01910               {
01911                 cmt_regexp e (new_value);
01912                 cmt_regexp::iterator it;
01913 
01914                 for (;;)
01915                   {
01916                     it = e.begin (temp);
01917                     if (it == e.end ()) break;
01918 
01919                     temp.erase (it._pos, it._length);
01920                   }
01921               }
01922             
01923             break;
01924           case CommandAlias :
01925             
01926             resolve_value (new_value, symbol.name, temp);
01927             temp = new_value;
01928             
01929             break;
01930         }
01931     }
01932 
01933   level--;
01934 
01935   return (temp);
01936 }
01937 
01938 static bool find_path_entry (const cmt_string& paths, const cmt_string& value)
01939 {
01940   static const cmt_string path_separator = CmtSystem::path_separator ();
01941 
01942   cmt_string here = CmtSystem::pwd ();
01943   cmt_string rvalue = value;
01944 
01945   if (CmtSystem::cd (value))
01946     {
01947       rvalue = CmtSystem::pwd ();
01948     }
01949   else
01950     {
01951       CmtSystem::compress_path (rvalue);
01952     }
01953 
01954   CmtSystem::cmt_string_vector items;
01955   CmtSystem::split (paths, path_separator, items);
01956 
01957   bool found = false;
01958 
01959   for (int i = 0; i < items.size (); i++)
01960     {
01961       const cmt_string& item = items[i];
01962       cmt_string ritem = item;
01963       if (CmtSystem::cd (item))
01964         {
01965           ritem = CmtSystem::pwd ();
01966         }
01967       else
01968         {
01969           CmtSystem::compress_path (ritem);
01970         }
01971 
01972       if (ritem == rvalue)
01973         {
01974           found = true;
01975           break;
01976         }
01977     }
01978 
01979   CmtSystem::cd (here);
01980   return (found);
01981 }
01982 
01983 //-------------------------------------------------------------
01984 const cmt_string PathBuilder::build (const Symbol& symbol,
01985                                      const cmt_string& /*tag_name*/)
01986 {
01987     // Control of recursivity
01988   static int level = 0;
01989 
01990   bool show_it = false;
01991 
01992   cmt_string temp;
01993   cmt_string previous_temp;
01994   cmt_string new_value;
01995   static const cmt_string empty;
01996 
01997   static cmt_string path_separator = CmtSystem::path_separator ();
01998 
01999   ActionType action = Cmt::get_action ();
02000 
02001   if (action == action_show_set)
02002     {
02003       if (symbol.name == Cmt::get_current_target ())
02004         {
02005             // Should not display on recursive calls
02006           if (level == 0) show_it = m_display_it;
02007         }
02008     }
02009 
02010   level++;
02011 
02012   temp = CmtSystem::getenv (symbol.name);
02013 
02014   bool first_definition = true;
02015   bool defined = false;
02016 
02017   for (int i = 0; i < symbol.value_lists.size (); i++)
02018     {
02019       const SymbolValueList& value_list = symbol.value_lists[i];
02020 
02021       if ((value_list.use != 0) &&
02022           (value_list.use->discarded)) continue;
02023 
02024       const int selected = value_list.select_first ();
02025       
02026       if (selected < 0) continue;
02027  
02028       SymbolValue& value = value_list.values[selected];
02029           
02030       if (show_it)
02031         {
02032           value_list.show (symbol, value, first_definition);
02033         }
02034           
02035       if (value_list.discarded) continue;
02036 
02037       new_value = value.text;
02038           
02039           //resolve_value (new_value);
02040       resolve_value_for_macros (new_value);
02041           
02042       switch (value_list.command_type)
02043         {
02044           case CommandPath :
02045             
02046             if (!value_list.is_reflexive || 
02047                 !symbol.value_is_reflexive (value.text))
02048               {
02049                 resolve_value (new_value, symbol.name, temp);
02050                 temp = new_value;
02051 
02052                 if (!defined)
02053                   {
02054                     defined = true;
02055                   }
02056                 else
02057                   {
02058                     if ((!Cmt::get_quiet ()) &&
02059                         ((action == action_show_macro) ||
02060                          (action == action_show_set) ||
02061                          (action == action_show_action) ||
02062                          (action == action_show_macros) ||
02063                          (action == action_show_sets) ||
02064                          (action == action_show_actions)))
02065                       {
02066                         cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
02067                         
02068                         if (value_list.use != 0)
02069                           {
02070                             cerr << " in package " << value_list.use->get_package_name ();
02071                           }
02072                         
02073                         cerr << endl;
02074                       }
02075                   }
02076               }
02077 
02078             break;
02079           case CommandPathAppend :
02080               
02081             if (new_value != "")
02082               {
02083                 if (!find_path_entry (temp, new_value))
02084                   {
02085                     if (temp != "") temp += path_separator;
02086                       
02087                     temp += new_value;
02088                   }
02089               }
02090                   
02091             break;
02092           case CommandPathPrepend :
02093               
02094             if (new_value != "")
02095               {
02096                 if (!find_path_entry (temp, new_value))
02097                   {
02098                     previous_temp = temp;
02099                     temp = new_value;
02100                     if (previous_temp != "") temp += path_separator;
02101                     temp += previous_temp;
02102                   }
02103               }
02104                   
02105             break;
02106           case CommandPathRemove :
02107               
02108             if (new_value != "")
02109               {
02110                 CmtSystem::cmt_string_vector paths;
02111                   
02112                 CmtSystem::split (temp, path_separator, paths);
02113                   
02114                 for (int j = 0; j < paths.size (); ++j)
02115                   {
02116                     cmt_string& s = paths[j];
02117                       
02118                     if (s.find (new_value) != cmt_string::npos)
02119                       {
02120                         s = "";
02121                       }
02122                   }
02123 
02124                 Cmt::vector_to_string (paths, path_separator, temp);
02125                 temp.replace_all ("::", ":");
02126                 temp.replace_all (";;", ";");
02127               }
02128               
02129             break;
02130           case CommandPathRemoveRegexp :
02131 
02132             if (new_value != "")
02133               {
02134                 cmt_regexp e (new_value);
02135 
02136                 CmtSystem::cmt_string_vector paths;
02137                   
02138                 CmtSystem::split (temp, path_separator, paths);
02139                   
02140                 for (int j = 0; j < paths.size (); ++j)
02141                   {
02142                     cmt_string& s = paths[j];
02143 
02144                     if (CmtSystem::getenv ("TESTPRR") != "")
02145                       {
02146                         cout << "PRR> s=[" << s << "]";
02147                       }
02148 
02149                     if (e.match (s))
02150                       {
02151                         s = "";
02152 
02153                         if (CmtSystem::getenv ("TESTPRR") != "")
02154                           {
02155                             cout << " match ";
02156                           }
02157                       }
02158                     else
02159                       {
02160                         if (CmtSystem::getenv ("TESTPRR") != "")
02161                           {
02162                             cout << " no match ";
02163                           }
02164                       }
02165 
02166                     if (CmtSystem::getenv ("TESTPRR") != "")
02167                       {
02168                         cout << endl;
02169                       }
02170                   }
02171 
02172                 Cmt::vector_to_string (paths, path_separator, temp);
02173                 temp.replace_all ("::", ":");
02174                 temp.replace_all (";;", ";");
02175               }
02176               
02177             break;
02178         }
02179 
02180     }
02181 
02182   level--;
02183   
02184   return (temp);
02185 }
02186 
02187 //-------------------------------------------------------------
02188 const cmt_string PathBuilder::clean (const Symbol& symbol,
02189                                      const cmt_string& /*tag_name*/)
02190 {
02191     // Control of recursivity
02192   static int level = 0;
02193 
02194   cmt_string temp;
02195   cmt_string new_value;
02196   static const cmt_string empty;
02197 
02198   static cmt_string path_separator = CmtSystem::path_separator ();
02199 
02200   temp = CmtSystem::getenv (symbol.name);
02201 
02202     //cerr << "#####1 temp=" << temp << endl;
02203 
02204   for (int i = 0; i < symbol.value_lists.size (); i++)
02205     {
02206       const SymbolValueList& value_list = symbol.value_lists[i];
02207 
02208       if (value_list.discarded) continue;
02209 
02210       if ((value_list.use != 0) &&
02211           (value_list.use->discarded)) continue;
02212 
02213       const int selected = value_list.select_first ();
02214       
02215       if (selected < 0) continue;
02216  
02217       SymbolValue& value = value_list.values[selected];
02218           
02219       new_value = value.text;
02220           
02221           //resolve_value (new_value);
02222 
02223         //cerr << "#####1 new_value=" << new_value << endl;
02224 
02225       resolve_value_for_macros (new_value);
02226       resolve_value (new_value);
02227           
02228         //cerr << "#####2 new_value=" << new_value << endl;
02229 
02230       switch (value_list.command_type)
02231         {
02232           case CommandPath :
02233             
02234             temp = "";
02235             
02236             break;
02237           case CommandPathAppend :
02238           case CommandPathPrepend :
02239           case CommandPathRemove :
02240 
02241             if (new_value != "")
02242               {
02243                 CmtSystem::cmt_string_vector paths;
02244                   
02245                 CmtSystem::split (temp, path_separator, paths);
02246                   
02247                 for (int j = 0; j < paths.size (); ++j)
02248                   {
02249                     cmt_string& s = paths[j];
02250                       
02251                     if (s.find (new_value) != cmt_string::npos)
02252                       {
02253                         s = "";
02254                       }
02255 
02256                     if (j > 0)
02257                       {
02258                         cmt_string& s2 = paths[j-1];
02259                         if (s2 == s)
02260                           {
02261                             s2 = "";
02262                           }
02263                       }
02264                   }
02265 
02266                 Cmt::vector_to_string (paths, path_separator, temp);
02267                 temp.replace_all ("::", ":");
02268                 temp.replace_all (";;", ";");
02269               }
02270               
02271             break;
02272           case CommandPathRemoveRegexp :
02273 
02274             if (new_value != "")
02275               {
02276                 cmt_regexp e (new_value);
02277 
02278                 CmtSystem::cmt_string_vector paths;
02279                   
02280                 CmtSystem::split (temp, path_separator, paths);
02281                   
02282                 for (int j = 0; j < paths.size (); ++j)
02283                   {
02284                     cmt_string& s = paths[j];
02285                       
02286                     if (e.match (s))
02287                       {
02288                         s = "";
02289                       }
02290 
02291                     if (j > 0)
02292                       {
02293                         cmt_string& s2 = paths[j-1];
02294                         if (s2 == s)
02295                           {
02296                             s2 = "";
02297                           }
02298                       }
02299                   }
02300 
02301                 Cmt::vector_to_string (paths, path_separator, temp);
02302                 temp.replace_all ("::", ":");
02303                 temp.replace_all (";;", ";");
02304               }
02305               
02306             break;
02307         }
02308     }
02309 
02310     //cerr << "#####2 temp=" << temp << endl;
02311   
02312   return (temp);
02313 }
02314 
02315 //-------------------------------------------------------------
02316 const cmt_string MacroBuilder::build (const Symbol& symbol,
02317                                       const cmt_string& tag_name)
02318 {
02319     // Control of recursivity
02320   static int level = 0;
02321 
02322   cmt_string temp;
02323   cmt_string previous_temp;
02324   static const cmt_string empty;
02325   bool show_it = false;
02326 
02327   ActionType action = Cmt::get_action ();
02328 
02329   if (action == action_show_macro)
02330     {
02331       if (symbol.name == Cmt::get_current_target ())
02332         {
02333              // Should not display on recursive calls
02334           if (level == 0) show_it = m_display_it;
02335         }
02336     }
02337 
02338   level++;
02339 
02340   temp = "";
02341 
02342   int i;
02343 
02344   bool first_definition = true;
02345   bool defined = false;
02346 
02347   for (i = 0; i < symbol.value_lists.size (); i++)
02348     {
02349       const SymbolValueList& value_list = symbol.value_lists[i];
02350 
02351       if ((value_list.use != 0) &&
02352           (value_list.use->discarded)) continue;
02353 
02354       if (value_list.command_type != CommandMacroPrepend) continue;
02355 
02356       const int selected = value_list.select_first (tag_name);
02357 
02358       if (selected < 0) continue;
02359 
02360       SymbolValue& value = value_list.values[selected];
02361 
02362       if (show_it)
02363         {
02364           value_list.show (symbol, value, first_definition);
02365         }
02366 
02367       if (value_list.discarded) continue;
02368 
02369       previous_temp = temp;
02370       temp = value.text;
02371       temp += previous_temp;
02372     }
02373 
02374   previous_temp = temp;
02375   temp = "";
02376 
02377   first_definition = true;
02378 
02379   for (i = 0; i < symbol.value_lists.size (); i++)
02380     {
02381       const SymbolValueList& value_list = symbol.value_lists[i];
02382 
02383       if ((value_list.use != 0) &&
02384           (value_list.use->discarded)) continue;
02385 
02386       if (value_list.command_type != CommandMacro) continue;
02387 
02388       const int selected = value_list.select_first (tag_name);
02389 
02390       if (selected < 0) continue;
02391 
02392       SymbolValue& value = value_list.values[selected];
02393 
02394       if (show_it)
02395         {
02396           value_list.show (symbol, value, first_definition);
02397         }
02398 
02399       // WARNING:
02400       // Commented just for a test : should be uncommented after the test
02401       if (value_list.discarded) continue;
02402       
02403       if (!value_list.is_reflexive || 
02404           !symbol.value_is_reflexive (value.text))
02405         {
02406           temp = value.text;
02407 
02408           if (!defined)
02409             {
02410               defined = true;
02411             }
02412           else
02413             {
02414               /*
02415               if ((!Cmt::get_quiet ()) &&
02416                   ((action == action_show_macro) ||
02417                    (action == action_show_set) ||
02418                    (action == action_show_action) ||
02419                    (action == action_show_macros) ||
02420                    (action == action_show_sets) ||
02421                    (action == action_show_actions)))
02422                 {
02423                   cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
02424                   
02425                   if (value_list.use != 0)
02426                     {
02427                       cerr << " in package " << value_list.use->get_package_name ();
02428                     }
02429 
02430                   cerr << endl;
02431                 }
02432               */
02433             }
02434         }
02435     }
02436 
02437   previous_temp += temp;
02438   temp = previous_temp;
02439 
02440   for (i = 0; i < symbol.value_lists.size (); i++)
02441     {
02442       const SymbolValueList& value_list = symbol.value_lists[i];
02443 
02444       if ((value_list.use != 0) &&
02445           (value_list.use->discarded)) continue;
02446 
02447       if (value_list.command_type != CommandMacroAppend) continue;
02448 
02449       const int selected = value_list.select_first (tag_name);
02450 
02451       if (selected < 0) continue;
02452 
02453       SymbolValue& value = value_list.values[selected];
02454 
02455       if (show_it)
02456         {
02457           value_list.show (symbol, value, first_definition);
02458         }
02459 
02460       if (value_list.discarded) continue;
02461 
02462       temp += value.text;
02463     }
02464 
02465   for (i = 0; i < symbol.value_lists.size (); i++)
02466     {
02467       const SymbolValueList& value_list = symbol.value_lists[i];
02468 
02469       if ((value_list.use != 0) &&
02470           (value_list.use->discarded)) continue;
02471 
02472       if ((value_list.command_type != CommandMacroRemove) &&
02473           (value_list.command_type != CommandMacroRemoveRegexp) &&
02474           (value_list.command_type != CommandMacroRemoveAll) &&
02475           (value_list.command_type != CommandMacroRemoveAllRegexp)) continue;
02476 
02477       const int selected = value_list.select_first (tag_name);
02478 
02479       if (selected < 0) continue;
02480 
02481       SymbolValue& value = value_list.values[selected];
02482 
02483       if (show_it)
02484         {
02485           value_list.show (symbol, value, first_definition);
02486         }
02487 
02488       if (value_list.discarded) continue;
02489 
02490       switch (value_list.command_type)
02491         {
02492           case CommandMacroRemove :
02493             temp.replace (value.text, empty);
02494             break;
02495           case CommandMacroRemoveRegexp :
02496             if (value.text != "")
02497               {
02498                 cmt_regexp e (value.text);
02499                 cmt_regexp::iterator it;
02500 
02501                 it = e.begin (temp);
02502                 if (it != e.end ())
02503                   {
02504                     temp.erase (it._pos, it._length);
02505                   }
02506               }
02507             break;
02508           case CommandMacroRemoveAll :
02509             temp.replace_all (value.text, empty);
02510             break;
02511           case CommandMacroRemoveAllRegexp :
02512             if (value.text != "")
02513               {
02514                 cmt_regexp e (value.text);
02515                 cmt_regexp::iterator it;
02516 
02517                 for (;;)
02518                   {
02519                     it = e.begin (temp);
02520                     if (it != e.end ())
02521                       {
02522                         temp.erase (it._pos, it._length);
02523                       }
02524                     else
02525                       {
02526                         break;
02527                       }
02528                   }
02529               }
02530             break;
02531         }
02532     }
02533 
02534   level--;
02535 
02536   return (temp);
02537 }
02538 
02539 //-------------------------------------------------------------
02540 const cmt_string ScriptBuilder::build (const Symbol& symbol,
02541                                        const cmt_string& tag_name)
02542 {
02543     // Control of recursivity
02544   static int level = 0;
02545 
02546   static const cmt_string empty = "";
02547 
02548   if (symbol.value_lists.size () > 0)
02549     {
02550       const SymbolValueList& value_list = symbol.value_lists[0];
02551 
02552       if (value_list.discarded) return (empty);
02553 
02554       if ((value_list.use != 0) &&
02555           (value_list.use->discarded)) return (empty);
02556     }
02557 
02558   return (symbol.name);
02559 }
02560 
02561 //-------------------------------------------------------------
02562 const cmt_string ActionBuilder::build (const Symbol& symbol,
02563                                        const cmt_string& tag_name)
02564 {
02565     // Control of recursivity
02566   static int level = 0;
02567 
02568   cmt_string temp;
02569   cmt_string previous_temp;
02570   static const cmt_string empty;
02571   bool show_it = false;
02572 
02573   ActionType action = Cmt::get_action ();
02574 
02575   if (action == action_show_action)
02576     {
02577       if (symbol.name == Cmt::get_current_target ())
02578         {
02579              // Should not display on recursive calls
02580           if (level == 0) show_it = m_display_it;
02581         }
02582     }
02583 
02584   level++;
02585 
02586   int i;
02587 
02588   bool first_definition = true;
02589   bool defined = false;
02590 
02591   temp = "";
02592 
02593   for (i = 0; i < symbol.value_lists.size (); i++)
02594     {
02595       const SymbolValueList& value_list = symbol.value_lists[i];
02596 
02597       if ((value_list.use != 0) &&
02598           (value_list.use->discarded)) continue;
02599 
02600       if (value_list.command_type != CommandAction) continue;
02601 
02602       const int selected = value_list.select_first (tag_name);
02603 
02604       if (selected < 0) continue;
02605 
02606       SymbolValue& value = value_list.values[selected];
02607 
02608       if (show_it)
02609         {
02610           value_list.show (symbol, value, first_definition);
02611         }
02612 
02613       // WARNING:
02614       // Commented just for a test : should be uncommented after the test
02615       if (value_list.discarded) continue;
02616       
02617       if (!value_list.is_reflexive || 
02618           !symbol.value_is_reflexive (value.text))
02619         {
02620           temp = value.text;
02621 
02622           if (!defined)
02623             {
02624               defined = true;
02625             }
02626           else
02627             {
02628               if ((!Cmt::get_quiet ()) &&
02629                   ((action == action_show_macro) ||
02630                    (action == action_show_set) ||
02631                    (action == action_show_action) ||
02632                    (action == action_show_macros) ||
02633                    (action == action_show_sets) ||
02634                    (action == action_show_actions)))
02635                 {
02636                   cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
02637                   
02638                   if (value_list.use != 0)
02639                     {
02640                       cerr << " in package " << value_list.use->get_package_name ();
02641                     }
02642 
02643                   cerr << endl;
02644                 }
02645             }
02646         }
02647     }
02648 
02649   level--;
02650 
02651   return (temp);
02652 }
02653 
02654 //-------------------------------------------------------------
02655 int SymbolValueList::select_first (const cmt_string& tag_name) const
02656 {
02657   int priority = 0;
02658   int value_number;
02659   int selected = -1;
02660 
02661   Tag* the_tag = 0;
02662 
02663   if (tag_name != "") the_tag = Tag::find (tag_name);
02664 
02665   for (value_number = 0;
02666        value_number < values.size ();
02667        value_number++)
02668     {
02669       const SymbolValue& value = values[value_number];
02670 
02671       const Tag* tag = value.tag;
02672 
02673       if (the_tag == 0)
02674         {
02675           if (!tag->is_selected ()) continue;
02676         }
02677       else
02678         {
02679           if (tag != the_tag) continue;
02680           selected = value_number;
02681         }
02682 
02683       //
02684       // Only the first value at a given priority is
02685       // selected (which implies the '>' test instead
02686       // of '>=')
02687       //
02688 
02689       if (tag->get_priority () > priority)
02690         {
02691           priority = tag->get_priority ();
02692           selected = value_number;
02693         }
02694     }
02695 
02696   return (selected);
02697 }
02698 
02699 //-------------------------------------------------------------
02700 int SymbolValueList::select_last () const
02701 {
02702   int priority = 0;
02703   int value_number;
02704   int selected = -1;
02705 
02706   for (value_number = 0;
02707        value_number < values.size ();
02708        value_number++)
02709     {
02710       SymbolValue& value = values[value_number];
02711 
02712       const Tag* tag = value.tag;
02713 
02714       if (tag->is_selected ())
02715         {
02716           //
02717           // The last value at a given priority is
02718           // selected (which implies the '>=' test instead
02719           // of '>')
02720           //
02721 
02722           if (tag->get_priority () >= priority)
02723             {
02724               priority = tag->get_priority ();
02725               selected = value_number;
02726             }
02727         }
02728     }
02729 
02730   return (selected);
02731 }
02732 
02733 //-------------------------------------------------------------
02734 void SymbolValueList::show (const Symbol& symbol, 
02735                             const SymbolValue& value, 
02736                             bool& first_definition) const
02737 {
02738   cmt_string discarded_text;
02739   cmt_string define_text;
02740   ActionType action = Cmt::get_action ();
02741 
02742   if (value.text == "") return;
02743 
02744   if (discarded) discarded_text = " (discarded by override)";
02745   else discarded_text = "";
02746 
02747   if (first_definition) define_text = "defines";
02748   else define_text = "overrides";
02749 
02750   cout << "# Package ";
02751   if (use != 0)
02752     {
02753       cout << use->get_package_name () << " " << use->version;
02754     }
02755 
02756   switch (command_type)
02757     {
02758       case CommandSet :
02759         cout << " " << define_text << " set " << symbol.name << " as ";
02760         first_definition = false;
02761         break;
02762       case CommandSetAppend :
02763         cout << " appends to set " << symbol.name << " : ";
02764         break;
02765       case CommandSetPrepend :
02766         cout << " prepends to set " << symbol.name << " : ";
02767         break;
02768       case CommandSetRemove :
02769         cout << " removes from set " << symbol.name << " : ";
02770         break;
02771       case CommandSetRemoveRegexp :
02772         cout << " removes RE from set " << symbol.name << " : ";
02773         break;
02774       case CommandAlias :
02775         cout << " " << define_text << " alias " << symbol.name << " as ";
02776         first_definition = false;
02777         break;
02778       case CommandPath :
02779         cout << " " << define_text << " path " << symbol.name << " as ";
02780         first_definition = false;
02781         break;
02782       case CommandPathAppend :
02783         cout << " appends to path " << symbol.name << " : ";
02784         break;
02785       case CommandPathPrepend :
02786         cout << " prepends to path " << symbol.name << " : ";
02787         break;
02788       case CommandPathRemove :
02789         cout << " removes from path " << symbol.name << " : ";
02790         break;
02791       case CommandPathRemoveRegexp :
02792         cout << " removes RE from path " << symbol.name << " : ";
02793         break;
02794       case CommandMacroPrepend :
02795         cout << " prepends to macro " << symbol.name << " : ";
02796         break;
02797       case CommandMacro :
02798         cout << " " << define_text << " macro " << symbol.name << " as ";
02799         break;
02800       case CommandMacroAppend :
02801         cout << " appends to macro " << symbol.name << " : ";
02802         break;
02803       case CommandMacroRemove :
02804         cout << " remove from macro " << symbol.name << " : ";
02805         break;
02806       case CommandMacroRemoveRegexp :
02807         cout << " remove RE from macro " << symbol.name << " : ";
02808         break;
02809       case CommandMacroRemoveAll :
02810         cout << " remove all from macro " << symbol.name << " : ";
02811         break;
02812       case CommandMacroRemoveAllRegexp :
02813         cout << " remove all RE from macro " << symbol.name << " : ";
02814         break;
02815       case CommandAction :
02816         cout << " " << define_text << " action " << symbol.name << " as ";
02817         first_definition = false;
02818         break;
02819     }
02820 
02821   cout << "'" << value.text << "'";
02822           
02823   Tag* selected_tag = value.tag;
02824           
02825   if ((selected_tag == 0) ||
02826       (selected_tag == Tag::get_default ()))
02827     {
02828       cout << " for default tag";
02829     }
02830   else
02831     {
02832       cout << " for tag '" << selected_tag->get_name () << "'";
02833     }
02834   
02835   cout << discarded_text << endl;
02836 }
02837 
02838 //-------------------------------------------------------------
02839 bool Symbol::check_tag_used (Tag* tag)
02840 {
02841   if (tag == 0) return (false);
02842 
02843   static SymbolVector& Symbols = symbols ();
02844 
02845   if (Symbols.size () == 0) 
02846     {
02847       return (false);
02848     }
02849 
02850   for (int number = 0; number < Symbol::symbol_number (); number++)
02851     {
02852       Symbol& symbol = Symbol::symbol (number);
02853 
02854       for (int i = 0; i < symbol.value_lists.size (); i++)
02855         {
02856           const SymbolValueList& value_list = symbol.value_lists[i];
02857 
02858           for (int j = 0; j < value_list.values.size (); j++)
02859             {
02860               const SymbolValue& value = value_list.values[j];
02861               Tag* t = value.tag;
02862 
02863               if (t != 0)
02864                 {
02865                   if (t->use_operand (tag)) return (true);
02866                 }
02867             }
02868         }
02869     }
02870 
02871   return (false);
02872 }
02873 

Generated on Mon May 2 10:25:05 2005 for CMT by doxygen 1.3.5