//----------------------------------------------------------- // Copyright Christian Arnault LAL-Orsay CNRS // arnault@lal.in2p3.fr // See the complete license in cmt_license.txt "http://www.cecill.info". //----------------------------------------------------------- #include #include #include #include #include "cmt_use.h" #include "cmt_symbol.h" #include "cmt_system.h" #include "cmt_database.h" #include "cmt_log.h" // Global inhibitor of any display bool Symbol::m_inhibit_display = false; //------------------------------------------------------------- class SetBuilder : public ValueBuilder { public: const cmt_string build (const Symbol& symbol, const cmt_string& tag_name = ""); const cmt_string clean (const Symbol& symbol, const cmt_string& tag_name = "") { static const cmt_string empty = ""; return (empty); } }; //------------------------------------------------------------- //------------------------------------------------------------- class PathBuilder : public ValueBuilder { public: const cmt_string build (const Symbol& symbol, const cmt_string& tag_name = ""); const cmt_string clean (const Symbol& symbol, const cmt_string& tag_name = ""); }; //------------------------------------------------------------- //------------------------------------------------------------- class MacroBuilder : public ValueBuilder { public: const cmt_string build (const Symbol& symbol, const cmt_string& tag_name = ""); const cmt_string clean (const Symbol& symbol, const cmt_string& tag_name = "") { static const cmt_string empty = ""; return (empty); } }; //------------------------------------------------------------- //------------------------------------------------------------- class ScriptBuilder : public ValueBuilder { public: const cmt_string build (const Symbol& symbol, const cmt_string& tag_name = ""); const cmt_string clean (const Symbol& symbol, const cmt_string& tag_name = "") { static const cmt_string empty = ""; return (empty); } }; //------------------------------------------------------------- //------------------------------------------------------------- class ActionBuilder : public ValueBuilder { public: const cmt_string build (const Symbol& symbol, const cmt_string& tag_name = ""); const cmt_string clean (const Symbol& symbol, const cmt_string& tag_name = "") { static const cmt_string empty = ""; return (empty); } }; //------------------------------------------------------------- //------------------------------------------------------------- class symbol_marker { public: symbol_marker () { ptr = cmt_string::npos; pattern = 0; intro = 0; } symbol_marker (int a_ptr, char a_pattern, int a_intro) { ptr = a_ptr; pattern = a_pattern; intro = a_intro; } symbol_marker (const symbol_marker& other) { ptr = other.ptr; pattern = other.pattern; intro = other.intro; } void set (int a_ptr, char a_pattern, int a_intro) { ptr = a_ptr; pattern = a_pattern; intro = a_intro; } static symbol_marker& get_lowest (symbol_marker markers[], int count) { static symbol_marker result; int real_count = 0; int i; // Check that at least one marker has result for (i = 0; i < count; i++) { if (markers[i].ptr != cmt_string::npos) real_count++; } if (real_count == 0) return (result); // since we've passed the previous test, // at least one entry is not npos. // Now discards other npos by moving them to the end for (i = 0; i < count;) { if (markers[i].ptr == cmt_string::npos) { markers[i] = markers[count-1]; count--; if (count == 0) break; } else { i++; } } if (count == 0) return (result); // now all entries in [0, count-1] are not npos // let's sort the lowest one in [0] for (i = 1; i < count;) { if (markers[0].ptr > markers[i].ptr) { symbol_marker temp = markers[0]; markers[0] = markers[i]; markers[i] = temp; i = 1; } else { i++; } } return (markers[0]); } int ptr; char pattern; int intro; }; //------------------------------------------------------------- /** Attempt to substitute all occurrences of ${} $() %% [on Windows only] by the specified value in the given text. This is for one symbol only */ static void resolve_value (cmt_string& text, const cmt_string& symbol_name, const cmt_string& value) { static cmt_string pattern; pattern = "${"; pattern += symbol_name; pattern += "}"; text.replace_all (pattern, value); pattern = "$("; pattern += symbol_name; pattern += ")"; text.replace_all (pattern, value); #ifdef WIN32 pattern = "%"; pattern += symbol_name; pattern += "%"; text.replace_all (pattern, value); #endif } /** * similar to processing * `shell' function of GNU Make does * on command output */ static void process_cmd_output (cmt_string& text) { //cerr << "process_cmd_output (begin): [" << text << "]" << endl; // remove trailing (carriage-return and) newline(s) int nl = text.size (); while (nl > 0 && text[nl - 1] == '\n') { nl--; if (nl > 0 && text[nl - 1] == '\r') nl--; } if (nl != text.size ()) text.erase (nl); // convert each newline (or carriage-return / newline pair) to a single space text.replace_all ("\r\n", " "); text.replace_all ("\n", " "); //cerr << "process_cmd_output (end): [" << text << "]" << endl; } /** Attempt to substitute into the specified text all occurrences of ${xxx} $(xxx) `xxx` %xxx% [on Windows only] by the appropriate value: for `xxx` : xxx is considered as a shell command. Value is the result of its execution for other patterns: if xxx is a symbol name, its value is substituted to the pattern otherwise, xxx is tried as an environment variable ===> In all cases, the pattern is filtered away. */ static void resolve_value (cmt_string& text) { //static cmt_regexp reg ("[$%`]"); //if (!reg.match (text)) return; cmt_string pattern; cmt_string symbol_name; char end_pattern; int start = 0; for (;;) { int begin; int end; symbol_marker markers[4]; int num = 0; markers[num].set (text.find (start, "$("), ')', 2); num++; markers[num].set (text.find (start, "${"), '}', 2); num++; markers[num].set (text.find (start, "`"), '`', 1); num++; #ifdef WIN32 markers[num].set (text.find (start, "%"), '%', 1); num++; #endif // Find the first matching pattern symbol_marker& marker = symbol_marker::get_lowest (markers, num); begin = marker.ptr; if (begin == cmt_string::npos) break; end_pattern = marker.pattern; start = begin + marker.intro; end = text.find (start, end_pattern); if (end == cmt_string::npos) { // The pattern is a fake one (no ending!) start++; continue; } // This should never happen... if (end < begin) break; // Extract the complete pattern text.substr (begin, end - begin + 1, pattern); // Then only the symbol name text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name); if (text[begin] == '`') { cmt_string command = symbol_name; resolve_value (command); // The value is a shell command that first needs // to be applied. The output of the command is then substituted cmt_string result; Symbol::all_set (); CmtSystem::execute (command, result); /* int pos; pos = result.find ('\n'); if (pos != cmt_string::npos) result.erase (pos); pos = result.find ('\r'); if (pos != cmt_string::npos) result.erase (pos); */ process_cmd_output (result); if (Cmt::get_debug ()) { cout << "resolve_value: Executing [" << command << "] to expand a symbol value =>[" << result << "]" << endl; } text.replace_all (pattern, result); // The substitution will restart from the same place // allowing for recursive replacements start = begin; } else { Symbol* symbol = Symbol::find (symbol_name); if (symbol != 0) { // Symbol found cmt_string value = symbol->resolve_macro_value (); text.replace_all (pattern, value); // The substitution will restart from the same place // allowing for recursive replacements start = begin; } else { // Symbol not found. Look for env. variable cmt_string value = CmtSystem::getenv (symbol_name); // When the env. variable is not defined, the replacement is empty // thus all $(xxx) ${xxx} %xxx% patterns are always filtered away. text.replace_all (pattern, value); // The substitution will restart from the same place // allowing for recursive replacements start = begin; } } } } /** Attempt to substitute all occurrences of ${xxx} $(xxx) `xxx` %xxx% [on Windows only] by the appropriate value: for `xxx` : xxx is considered as a shell command. Value is the result of its execution for other patterns: if xxx is a macro name, its value is substituted to the pattern if xxx is a set or a path, it is kept in place (after fixing the pattern according to the OS style) otherwise it is simply kept in place */ static void resolve_value_for_macros (cmt_string& text) { cmt_string pattern; cmt_string symbol_name; char end_pattern; int start = 0; for (;;) { // // Try and substitute all ${xxx} $(xxx) or %xxx% patterns // using symbol values, only when the symbol is a macro. // int begin; int end; symbol_marker markers[4]; int num = 0; markers[num].set (text.find (start, "$("), ')', 2); num++; markers[num].set (text.find (start, "${"), '}', 2); num++; #ifdef WIN32 markers[num].set (text.find (start, "%"), '%', 1); num++; #endif markers[num].set (text.find (start, "`"), '`', 1); num++; // Find the first of three patterns symbol_marker& marker = symbol_marker::get_lowest (markers, num); begin = marker.ptr; if (begin == cmt_string::npos) break; end_pattern = marker.pattern; start = begin + marker.intro; end = text.find (start, end_pattern); if (end == cmt_string::npos) { // The pattern is a fake one (no ending!) start++; continue; } // This should never happen... if (end < begin) break; // Extract the complete pattern text.substr (begin, end - begin + 1, pattern); // Then only the macro name text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name); if (text[begin] == '`') { cmt_string command = symbol_name; resolve_value (command); // The macro value is a shell command that first needs // to be applied. The output of the command is substituted cmt_string result; Symbol::all_set (); CmtSystem::execute (command, result); /* int pos; pos = result.find ('\n'); if (pos != cmt_string::npos) result.erase (pos); pos = result.find ('\r'); if (pos != cmt_string::npos) result.erase (pos); */ process_cmd_output (result); if (Cmt::get_debug ()) { cout << " Executing [" << command << "] to expand a macro value =>[" << result << "]" << endl; } text.replace_all (pattern, result); // The substitution will restart from the same place // allowing for recursive replacements start = begin; } else { Symbol* macro = Symbol::find (symbol_name); if ((macro != 0) && (macro->type == Symbol::SymbolMacro)) { // Macro found cmt_string value = macro->resolve_macro_value (); text.replace_all (pattern, value); // The substitution will restart from the same place // allowing for recursive replacements start = begin; } else if ((macro == 0) || ((macro->type == Symbol::SymbolSet) || (macro->type == Symbol::SymbolPath))) { // Set found // ensure that the delimiters will match the OS dependent // delimiters. cmt_string pattern_close = marker.pattern; if (pattern_close != CmtSystem::ev_close ()) { cmt_string new_pattern; new_pattern = CmtSystem::ev_open (); new_pattern += symbol_name; new_pattern += CmtSystem::ev_close (); text.replace (pattern, new_pattern); } start = end + 1; } else { start = end + 1; } } } } /** This function suppress all OS delimiters ie ${ } or % % and replaces them by the pure macro delimiters $( ) `xxx` pattern is replaced by the result of the execution of the command */ static void suppress_OS_delimiters (cmt_string& text) { cmt_string pattern; cmt_string symbol_name; char end_pattern; int start = 0; for (;;) { int begin; int end; symbol_marker markers[3]; int num = 0; markers[num].set (text.find (start, "${"), '}', 2); num++; markers[num].set (text.find (start, "`"), '`', 1); num++; #ifdef WIN32 markers[num].set (text.find (start, "%"), '%', 1); num++; #endif // Find the first of three patterns symbol_marker& marker = symbol_marker::get_lowest (markers, num); begin = marker.ptr; if (begin == cmt_string::npos) break; end_pattern = marker.pattern; start = begin + marker.intro; end = text.find (start, end_pattern); if (end == cmt_string::npos) { // The pattern is a fake one (no ending!) start++; continue; } // This should never happen... if (end < begin) break; // Extract the complete pattern text.substr (begin, end - begin + 1, pattern); // Then only the macro name text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name); if (text[begin] == '`') { cmt_string command = symbol_name; resolve_value (command); // The macro value is a shell command that first needs // to be applied. The output of the command is substituted cmt_string result; Symbol::all_set (); CmtSystem::execute (command, result); /* int pos; pos = result.find ('\n'); if (pos != cmt_string::npos) result.erase (pos); pos = result.find ('\r'); if (pos != cmt_string::npos) result.erase (pos); */ process_cmd_output (result); if (Cmt::get_debug ()) { cout << " Executing [" << command << "] to expand a macro value =>[" << result << "]" << endl; } text.replace_all (pattern, result); // The substitution will restart from the same place // allowing for recursive replacements start = begin; } else { cmt_string new_pattern; new_pattern = "$("; new_pattern += symbol_name; new_pattern += ")"; text.replace (pattern, new_pattern); start = begin; } } } //------------------------------------------------------------- /* */ /* Operations on SymbolValues */ /* */ //------------------------------------------------------------- //------------------------------------------------------------- SymbolValue::SymbolValue () { tag = 0; } //------------------------------------------------------------- SymbolValue::~SymbolValue () { tag = 0; } //------------------------------------------------------------- /* */ /* Operations on Symbols */ /* */ //------------------------------------------------------------- //------------------------------------------------------------- Symbol* Symbol::create (const cmt_string& name, CommandType command, Use* use) { static SetBuilder Set; static PathBuilder Path; static MacroBuilder Macro; static ScriptBuilder Script; static ActionBuilder Action; static SymbolVector& Symbols = symbols (); static SymbolMap& SymbolMap = symbol_map (); SymbolType type = SymbolUndefined; switch (command) { case CommandSet: case CommandSetAppend: case CommandSetPrepend: case CommandSetRemove: case CommandSetRemoveRegexp: type = SymbolSet; break; case CommandPath: case CommandPathAppend: case CommandPathPrepend: case CommandPathRemove: case CommandPathRemoveRegexp: type = SymbolPath; break; case CommandMacro: case CommandMacroAppend: case CommandMacroPrepend: case CommandMacroRemove: case CommandMacroRemoveRegexp: case CommandMacroRemoveAll: case CommandMacroRemoveAllRegexp: type = SymbolMacro; break; case CommandAction: type = SymbolAction; break; case CommandAlias: type = SymbolAlias; break; case CommandSetupScript: type = SymbolSetupScript; break; case CommandCleanupScript: type = SymbolCleanupScript; break; } { Symbol* symbol; symbol = find (name); if (symbol != 0) { if (symbol->type != type) { ActionType action = Cmt::get_action (); if ((!Cmt::get_quiet ()) && (action != action_build_constituents_config) && (action != action_build_constituent_config)) { cmt_string s1; cmt_string s2; switch (symbol->type) { case SymbolSet: s1 = "set"; break; case SymbolPath: s1 = "path"; break; case SymbolMacro: s1 = "macro"; break; case SymbolSetupScript: s1 = "setup_script"; break; case SymbolCleanupScript: s1 = "cleanup_script"; break; case SymbolAction: s1 = "action"; break; case SymbolAlias: s1 = "alias"; break; } switch (type) { case SymbolSet: s2 = "set"; break; case SymbolPath: s2 = "path"; break; case SymbolMacro: s2 = "macro"; break; case SymbolSetupScript: s2 = "setup_script"; break; case SymbolCleanupScript: s2 = "cleanup_script"; break; case SymbolAction: s2 = "action"; break; case SymbolAlias: s2 = "alias"; break; } // ROOT macro is defined in // Use::fill_standard_macros <- SyntaxParser::parse_requirements // "cmt -requirements setup" may generate ROOT set // hence, warning // Symbol ROOT inconsistently redeclared from macro to set in package // below, we suppress the warning for current package if (use != &(Use::current()) || (Use::current().prefix + "ROOT") != name || symbol->type != SymbolMacro || type != SymbolSet) CmtMessage::warning ("Symbol " + name + " inconsistently redeclared from " + s1 + " to " + s2 + ( (use != 0) ? " in package " + use->get_package_name () : "" ) ); /* cerr << "#CMT> Warning: Symbol " << name << " inconsistently redeclared from " << s1 << " to " << s2; if (use != 0) cerr << " in package " << use->get_package_name (); cerr << endl; */ } } return (symbol); } } Symbol& symbol = Symbols.add (); SymbolMap.add (name, symbol); symbol.name = name; symbol.scope = use->get_current_scope (); symbol.type = type; symbol.value_lists.clear (); switch (type) { case SymbolSet: symbol.builder = &Set; break; case SymbolPath: symbol.builder = &Path; break; case SymbolAlias: symbol.builder = &Set; break; case SymbolMacro: symbol.builder = &Macro; break; case SymbolSetupScript: case SymbolCleanupScript: symbol.builder = &Script; break; case SymbolAction: symbol.builder = &Action; break; } symbol.selected_value = -1; symbol.printed = false; return (&symbol); } //------------------------------------------------------------- Symbol* Symbol::find (const cmt_string& name) { static SymbolMap& SymbolMap = symbol_map (); Symbol* result = 0; result = SymbolMap.find (name); return (result); } //------------------------------------------------------------- int Symbol::symbol_number () { static SymbolVector& Symbols = symbols (); return (Symbols.size ()); } //------------------------------------------------------------- Symbol::SymbolVector& Symbol::symbols () { static Database& db = Database::instance (); static SymbolVector& Symbols = db.symbols (); return (Symbols); } //------------------------------------------------------------- Symbol::SymbolMap& Symbol::symbol_map () { static Database& db = Database::instance (); static SymbolMap& SymbolMap = db.symbol_map (); return (SymbolMap); } /** Filter out faulty items of a path-like symbol value */ void Symbol::filter_path_value (const cmt_string& name, cmt_string& text) { CmtSystem::cmt_string_vector paths; CmtSystem::cmt_string_vector normalyzed_paths; CmtSystem::split (text, CmtSystem::path_separator (), paths); for (int j = 0; j < paths.size (); ++j) { cmt_string& t = paths[j]; /* if (!CmtSystem::test_directory (t)) if (Cmt::get_warnings ()) { cerr << "#CMT> Warning: Wrong path item " << t << " in " << name << endl; } */ int exist = 0; for (int i = 0; i < j; ++i) { cmt_string& u = paths[i]; if (u == t) { exist = 1; break; } } if (exist==0) { cmt_string& s = normalyzed_paths.add (); s = t; if (CmtMessage::active (Verbose)) if (!CmtSystem::test_directory (t)) { CmtMessage::warning ("Non-existent directory " + t + " in " + name); } } } Cmt::vector_to_string (normalyzed_paths, CmtSystem::path_separator (), text); for (;;) { int sz = text.size (); if (sz == 0) break; if ((text[0] == ';') || (text[0] == ':')) { text.erase (0, 1); } else if ((text[sz-1] == ';') || (text[sz-1] == ':')) { text.erase (sz-1, 1); } else { break; } } text.replace_all ("::", ":"); text.replace_all (";;", ";"); } //------------------------------------------------------------- Symbol& Symbol::symbol (int index) { static SymbolVector& Symbols = symbols (); return (Symbols[index]); } //------------------------------------------------------------- void Symbol::action (const CmtSystem::cmt_string_vector& words, CommandType command_type, Use* use) { int number; Symbol* symbol; Tag* tag; if (words.size () < 1) return; cmt_string name = words[1]; if ((command_type == CommandSetupScript) || (command_type == CommandCleanupScript)) { cmt_string full_name; Symbol::expand (name); if (name != "") { if (CmtSystem::absolute_path (name)) { full_name = name; } else { if (use->get_strategy ("SetupRoot") && use->get_package_name () != "cmt_standalone") { #ifdef WIN32 full_name = "%"; #else full_name = "${"; #endif full_name += CmtSystem::mangle (use->prefix); full_name += "ROOT"; #ifdef WIN32 full_name += "%"; #else full_name += "}"; #endif } else { full_name = use->get_full_path (); } if (use->style == cmt_style) { full_name += CmtSystem::file_separator (); full_name += "cmt"; } else if (use->style == mgr_style) { full_name += CmtSystem::file_separator (); full_name += "mgr"; } // else if (use->style == no_version_style) full_name += "cmt"; // else full_name += "mgr"; full_name += CmtSystem::file_separator (); full_name += name; } symbol = create (full_name, command_type, use); symbol->add_value_to_list (command_type, use, Tag::get_default (), full_name); } } else { if (words.size () < 2) return; const cmt_string& default_value = words[2]; Cmt::reset_all_sets_done (); if (Cmt::get_debug ()) { cout << "Symbol::action> name:" << name << " access:" << Cmt::get_current_access () << " scope:" << use->get_current_scope () << endl; } if (Cmt::get_current_access () == UserMode) { /* The following statements mean that some symbols are always private. This list is hardcoded. This should be replaced by a database of "private" symbols. */ if (name == "constituents") return; if (name == "constituentscclean") return; if (use->get_current_scope () == ScopePrivate) return; } symbol = create (name, command_type, use); /* Parse the default value. */ symbol->add_value_to_list (command_type, use, Tag::get_default (), default_value); /* Then parse all specific values ... */ number = 3; while (number < (words.size () - 1)) { cmt_string tag_name = words[number]; const cmt_string& value = words[number + 1]; expand (tag_name); if (Cmt::get_debug ()) { cout << "Symbol::action> tag_name=" << tag_name << endl; } tag = Tag::find (tag_name); if (tag == 0) { tag = Tag::add (tag_name, PriorityUserTag, "use", use); } symbol->add_value_to_list (command_type, use, tag, value); number += 2; } if (name == "CMTPATH") { Cmt::configure_cmt_path (use); } else if (name == "CMTPROJECTPATH") { Cmt::configure_cmt_path (use); } else if (name == "CMTSITE") { Cmt::configure_site_tag (use); } else if (name == "CMTCONFIG") { //cerr << "redefining CMTCONFIG" << endl; Cmt::configure_tags (use); } else if (name == "CMTHOME") { Cmt::configure_home (use); } else if (name == "CMTUSERCONTEXT") { Cmt::configure_user_context (use); } else if (name.find ("_native_version") != cmt_string::npos) { cmt_string n = use->get_package_name (); n += "_native_version"; if (name == n) { use->set_native_version (true); } } } } //------------------------------------------------------------- int Symbol::is_selected (const cmt_string& name) { Symbol* symbol; int number; int value_number; symbol = find (name); if (symbol == 0) return (0); if (symbol->value_lists.size () == 0) return (0); for (number = 0; number < symbol->value_lists.size (); number++) { const SymbolValueList& value_list = symbol->value_lists[number]; if (value_list.discarded) continue; if ((value_list.command_type == CommandMacro) || (value_list.command_type == CommandSet) || (value_list.command_type == CommandSetAppend) || (value_list.command_type == CommandSetPrepend) || (value_list.command_type == CommandSetRemove) || (value_list.command_type == CommandSetRemoveRegexp) || (value_list.command_type == CommandAlias) || (value_list.command_type == CommandAction)) { for (value_number = 0; value_number < value_list.values.size (); value_number++) { Tag* tag; SymbolValue& value = value_list.values[value_number]; tag = value.tag; if ((tag == 0) || (tag == Tag::get_default ()) || (tag->is_selected () != 0)) { return (1); } } } } return (0); } //------------------------------------------------------------- Symbol::Symbol () { name = ""; } //------------------------------------------------------------- Symbol::~Symbol () { } /** * Characterizes if a value is provided as the reference to itself. */ bool Symbol::value_is_reflexive (const cmt_string& text) const { bool result = false; int text_length = text.size (); if (text_length == (name.size () + 3)) { static cmt_string temp; if (text[0] == '$') { if (text[1] == '(') { temp = "$("; temp += name; temp += ")"; if (text == temp) { result = true; } } else if (text[1] == '{') { temp = "${"; temp += name; temp += "}"; if (text == temp) { result = true; } } } } else if (text_length == (name.size () + 2)) { static cmt_string temp; temp = "%"; temp += name; temp += "%"; if (text == temp) { result = true; } } return (result); } //------------------------------------------------------------- void Symbol::add_value_to_list (CommandType command_type, Use* use, Tag* tag, const cmt_string& text) { SymbolValueList* value_list = 0; bool is_reflexive = false; // // First pickup the most recent value_list // if (value_lists.size () > 0) value_list = &(value_lists.back ()); // // Create a new value list is we switch to another use or // if we switch to a new command_type (eg. switching from // macro to macro_append). // if ((value_list == 0) || (use != value_list->use) || (command_type != value_list->command_type) || (tag == Tag::get_default ())) { value_list = &(value_lists.add ()); value_list->use = use; value_list->command_type = command_type; value_list->values.clear (); value_list->discarded = false; value_list->is_reflexive = false; } /* else { value_list = &(value_lists[value_lists.size () - 1]); } */ is_reflexive = value_list->is_reflexive; // // If the command_type is command_macro or command_set, // this is considered as a full re-set of this symbol // In this case, we have to discard all previous values // // However, we'd like to exclude from this logic the cases where // the value is **exactly* // // $() // ${} // %% // // which would then mean that we do not reset the value but rather // override it. // // // Inside this value_list, we add this new tag-value pair. // if ((command_type == CommandMacro) || (command_type == CommandSet) || (command_type == CommandPath) || (command_type == CommandAction)) { // // Check whether we have to hide previous settings by this new definition // (of course this is only useful if there WERE previous settings) // if ((value_lists.size () >= 1) && (!is_reflexive)) { if (value_is_reflexive (text)) { value_list->is_reflexive = true; is_reflexive = true; } else { //cerr << "...discarding old values for symbol " << name << " text=[" << text << "]" << endl; for (int i = 0; i < (value_lists.size () - 1); i++) { SymbolValueList& vl = value_lists[i]; if ((vl.use != 0) && (vl.use->discarded)) { //vl.discarded = true; } } } } } SymbolValue& value = value_list->values.add (); value.tag = tag; value.text = text; value.selected = 0; } /** Compute the current value of all environment variables and set them to the shell */ void Symbol::all_set () { //cerr << "all_set" << endl; static bool running = false; if (Cmt::get_debug ()) { cout << "\nSymbol::all_set> done=" << running << endl; } if (Cmt::get_all_sets_done ()) return; if (running) return; running = true; Cmt::set_all_sets_done (); static SymbolVector& Symbols = symbols (); Use::UsePtrVector& Uses = Use::get_ordered_uses (); int number; if (Symbols.size () == 0) { running = false; return; } cmt_string value; for (number = 0; number < Symbol::symbol_number (); number++) { Symbol& symbol = Symbol::symbol (number); if (symbol.type != SymbolSet) continue; value = symbol.build_macro_value (); if (value != "") { Symbol::expand (value); CmtSystem::putenv (symbol.name, value); } } cmt_string cmtconfig = CmtSystem::get_cmt_config (); if (Uses.size () > 0) { int number; for (number = 0; number < Uses.size (); number++) { Use& use = *(Uses[number]); if (use.discarded) continue; if (use.get_package_name () == "cmt_standalone") continue; if (use.get_strategy ("SetupConfig")) { cmt_string temp; temp = use.prefix; temp += "CONFIG"; CmtSystem::putenv (temp, cmtconfig); } if (use.get_strategy ("SetupRoot")) { cmt_string temp; temp = use.prefix; temp += "ROOT"; CmtSystem::putenv (temp, use.get_full_path ()); } } } { Use& use = Use::current (); if (use.get_package_name () != "cmt_standalone") { if (use.get_strategy ("SetupConfig")) { cmt_string temp; temp = use.prefix; temp += "CONFIG"; CmtSystem::putenv (temp, cmtconfig); } if (use.get_strategy ("SetupRoot")) { cmt_string temp; temp = use.prefix; temp += "ROOT"; CmtSystem::putenv (temp, use.get_full_path ()); } } } for (number = 0; number < Symbol::symbol_number (); number++) { Symbol& symbol = Symbol::symbol (number); if ((symbol.type != SymbolPath)) continue; value = symbol.build_macro_value (); if (value != "") { Symbol::expand (value); filter_path_value (symbol.name, value); #ifdef WIN32 value.replace_all ("/", "\\"); #endif if (Cmt::get_debug ()) { cerr << "Symbol::all_set-2> " << symbol.name << " = " << value << endl; } CmtSystem::putenv (symbol.name, value); } } running = false; } //------------------------------------------------------------- void Symbol::all_print (PrintMode mode) { static SymbolVector& Symbols = symbols (); int number; if (Symbols.size () == 0) return; switch (mode) { case Requirements : for (number = 0; number < Symbol::symbol_number (); number++) { Symbol& symbol = Symbol::symbol (number); if ((symbol.type == SymbolSet) || (symbol.type == SymbolAlias) || (symbol.type == SymbolSetupScript) || (symbol.type == SymbolPath) || (symbol.type == SymbolMacro)) { if (symbol.print_macro (mode)) { // cout << endl; } } } break; default : for (number = 0; number < Symbol::symbol_number (); number++) { Symbol& symbol = Symbol::symbol (number); if ((symbol.type == SymbolSet) || (symbol.type == SymbolAlias) || (symbol.type == SymbolSetupScript) || (symbol.type == SymbolPath)) { if (symbol.print (mode)) { if (mode == Bat) { cout << endl; } else if (mode == Xml) { // cout << endl; } else { cout << endl; } } } } break; } } //------------------------------------------------------------- void Symbol::check_all_paths () { static SymbolVector& Symbols = symbols (); int number; if (Symbols.size () == 0) return; for (number = 0; number < Symbol::symbol_number (); number++) { Symbol& symbol = Symbol::symbol (number); if (symbol.type == SymbolPath) { cmt_string temp; temp = symbol.build_macro_value (); expand (temp); Symbol::filter_path_value (symbol.name, temp); } } } //------------------------------------------------------------- void Symbol::all_print_clean (PrintMode mode) { static SymbolVector& Symbols = symbols (); int number; if (Symbols.size () == 0) return; for (number = Symbols.size () - 1; number >= 0; number--) { Symbol& symbol = Symbols[number]; if ((symbol.type == SymbolSet) || (symbol.type == SymbolAlias) || (symbol.type == SymbolCleanupScript)) { if (symbol.print_clean (mode)) { cout << endl; } } } for (number = Symbols.size () - 1; number >= 0; number--) { Symbol& symbol = Symbols[number]; if ((symbol.type != SymbolPath)) continue; if (symbol.print_clean (mode)) { cout << endl; } } } //------------------------------------------------------------- int Symbol::print_clean (PrintMode mode) { int result = 0; static cmt_string temp; if (name == "CMTCONFIG") return (0); cmt_string _name; switch (type) { case SymbolSet : case SymbolPath : if (0 != CmtSystem::mangle (name, _name)) CmtMessage::info ("Replace " + name + " with " + _name); break; } switch (type) { case SymbolSet : switch (mode) { case Csh : cout << "unsetenv " << _name; result = 1; break; case Sh : cout << "[ -z ${" << _name << "+CMT} ] || unset " << _name; // cout << "unset " << _name; result = 1; break; case Bat : cout << "set " << _name << "="; result = 1; break; } break; case SymbolAlias : switch (mode) { case Csh : cout << "unalias " << name; result = 1; break; case Sh : cout << "[ -z ${" << name << "+CMT} ] || unset " << name; // cout << "unset " << name; result = 1; break; } break; case SymbolPath : temp = clean_macro_value (); switch (mode) { case Csh : if (temp == "") { cout << "unsetenv " << _name; } else { cout << "setenv " << _name << " " << CmtSystem::quote (temp, " \t"); } result = 1; break; case Sh : cout << _name << "=" << CmtSystem::quote (temp, " \t") << "; export " << _name; result = 1; break; case Bat : cout << "set " << _name << "=" << CmtSystem::quote (temp, " \t"); result = 1; break; } break; case SymbolCleanupScript : switch (mode) { case Csh : cout << "if ( -f " << CmtSystem::quote (name, " \t") << ".csh ) then" << endl; cout << " source " << CmtSystem::quote (name, " \t") << ".csh" << endl; cout << "if ( $status != 0 ) then\n" " set cmtcleanupstatus=1\n" "endif\n"; cout << "endif" << endl; result = 1; break; case Sh : cout << "if test -f " << CmtSystem::quote (name, " \t") << ".sh; then" << endl; cout << " . " << CmtSystem::quote (name, " \t") << ".sh" << endl; cout << "if test $? != 0; then\n" " cmtcleanupstatus=1\n" "fi\n"; cout << "fi" << endl; result = 1; break; case Bat : cout << "call " << CmtSystem::quote (name, " \t"); result = 1; break; } break; } return (result); } //------------------------------------------------------------- int Symbol::print (PrintMode mode) { int result = 0; cmt_string temp = build_macro_value (); bool empty = (temp.size () == 0) ? true : false; if (type == SymbolPath) { expand (temp); Symbol::filter_path_value (name, temp); } cmt_string _name; switch (type) { case SymbolSet : case SymbolPath : if (0 != CmtSystem::mangle (name, _name)) CmtMessage::info ("Replace " + name + " with " + _name); switch (mode) { case Csh : if (empty) cout << "unsetenv " << _name; else cout << "setenv " << _name << " \"" << temp << "\""; //else cout << "setenv " << name << " " << CmtSystem::quote (temp, " \t"); result = 1; break; case Sh : if (empty) cout << "[ -z ${" << _name << "+CMT} ] || unset " << _name; // if (empty) cout << "unset " << _name; else cout << _name << "=\"" << temp << "\"; export " << _name; //else cout << name << "=" << CmtSystem::quote (temp, " \t") << "; export " << name; result = 1; break; case Bat : temp.replace_all ("/", "\\"); cout << "set " << _name << "=" << CmtSystem::quote (temp, " \t"); //cout << "set " << name << "=" << temp; result = 1; break; case Xml : cout << "" << _name << "" << "" << temp << ""; result = 1; break; } break; case SymbolAlias : switch (mode) { case Csh : cout << "alias " << name << " \"" << temp << "\""; //CmtSystem::quote (temp, " \t"); result = 1; break; case Sh : cout << "alias " << name << "=\"" << temp << "\""; //"=" << CmtSystem::quote (temp, " \t"); result = 1; break; case Bat : cout << "set " << name << "=" << CmtSystem::quote (temp, " \t"); //"=" << temp; result = 1; break; case Xml : cout << "" << name << "" << "" << temp << ""; result = 1; break; } break; default : break; } if (temp != "") { switch (type) { case SymbolSetupScript : switch (mode) { case Csh : cout << "if ( -f " << CmtSystem::quote (name, " \t") << ".csh ) then" << endl; cout << " source " << CmtSystem::quote (name, " \t") << ".csh" << endl; cout << "if ( $status != 0 ) then\n" " set cmtsetupstatus=1\n" "endif\n"; cout << "endif" << endl; result = 1; break; case Sh : cout << "if test -f " << CmtSystem::quote (name, " \t") << ".sh; then" << endl; cout << " . " << CmtSystem::quote (name, " \t") << ".sh" << endl; cout << "if test $? != 0; then\n" " cmtsetupstatus=1\n" "fi\n"; cout << "fi" << endl; result = 1; break; case Bat : cout << "call " << CmtSystem::quote (name, " \t"); result = 1; break; case Xml : cout << ""; result = 1; break; } break; default: break; } } return (result); } //------------------------------------------------------------- cmt_string Symbol::build_macro_value (bool display_it) const { cmt_string temp; if (display_it) { temp = builder->build_and_display (*this); } else { temp = builder->build (*this); } return (temp); } //------------------------------------------------------------- int Symbol::print_macro (PrintMode mode, ostream& out) const { if (mode != Requirements || printed) return 0; return builder->print (*this, out); } //------------------------------------------------------------- cmt_string Symbol::clean_macro_value () const { cmt_string temp; temp = builder->clean (*this); return (temp); } /** Attempt to substitute into the symbol value all occurrences of ${xxx} $(xxx) `xxx` %xxx% [on Windows only] by the appropriate value: for `xxx` : xxx is considered as a shell command. Value is the result of its execution for other patterns: if xxx is a symbol name, its value is substituted to the pattern otherwise, xxx is tried as an environment variable ===> In all cases, the pattern is filtered away. */ cmt_string Symbol::resolve_macro_value (const cmt_string& tag_name) const { cmt_string temp = builder->build (*this, tag_name); resolve_value (temp); return (temp); } //------------------------------------------------------------- void Symbol::show_macro (PrintMode mode, ostream& out) //void Symbol::show_macro (PrintMode mode) { if (Cmt::get_debug ()) { cout << "Symbol::show_macro> " << name << endl; } ActionType action = Cmt::get_action (); cmt_string value = build_macro_value (true); if ((!Cmt::get_quiet ()) && (action != action_build_tag_makefile) && (action != action_build_constituents_config) && (action != action_build_constituent_config) && (action != action_build_broadcast_config) && (action != action_show_macros) && (action != action_show_actions) && (action != action_show_aliases) && (action != action_show_sets)) { out << "#" << endl; out << "# Selection : " << endl; } if (value.size () > 0) { if ((action == action_show_macro) || (action == action_show_macros) || (action == action_show_sets) || (action == action_show_set) || (action == action_show_actions) || (action == action_show_action) || (action == action_show_alias) || (action == action_show_aliases) || (action == action_build_tag_makefile) || (action == action_build_constituents_config) || (action == action_build_constituent_config) || (action == action_build_broadcast_config) || (action == action_load) || (!Cmt::get_quiet ())) { if (mode == Make) { out << name << "="; } else { out << name << "='"; } } if ((action == action_show_macro_value) || (action == action_show_set_value) || (action == action_show_action_value) || (action == action_show_alias_value)) { expand (value); } else if (action == action_build_tag_makefile || action == action_build_constituents_config || action == action_build_constituent_config || action == action_build_broadcast_config) { /* Unfortunately, the %xxx% pattern has to be kept on Unix. Therefore we cannot force all patterns to become $(xxx) This was useful on Windows so as to only keep $(xxx) */ #ifdef WIN32 suppress_OS_delimiters (value); #endif } out << value; if ((action == action_show_macro) || (action == action_show_macros) || (action == action_show_sets) || (action == action_show_set) || (action == action_show_actions) || (action == action_show_action) || (action == action_show_alias) || (action == action_show_aliases) || (action == action_build_tag_makefile) || (action == action_build_constituents_config) || (action == action_build_constituent_config) || (action == action_build_broadcast_config) || (action == action_load) || (!Cmt::get_quiet ())) { if (mode != Make) { out << "'"; } #ifdef WIN32 else { out << " "; } #endif } out << endl; } } //------------------------------------------------------------- void Symbol::clear_all () { static SymbolVector& Symbols = symbols (); static SymbolMap& SymbolMap = symbol_map (); SymbolMap.clear (); Symbols.clear (); } //------------------------------------------------------------- void Symbol::expand (cmt_string& text) { static cmt_regexp reg ("[$%`]"); if (!reg.match (text)) return; resolve_value (text); } //------------------------------------------------------------- ValueBuilder::ValueBuilder () { m_display_it = false; } //------------------------------------------------------------- const cmt_string ValueBuilder::build_and_display (const Symbol& symbol) { cmt_string temp; m_display_it = true; temp = build (symbol); m_display_it = false; return (temp); } //------------------------------------------------------------- int ValueBuilder::print (const Symbol& symbol, ostream& out) { int result (0); bool first_definition = true; for (int i = 0; i < symbol.value_lists.size (); i++) { const SymbolValueList& value_list = symbol.value_lists[i]; if ((value_list.use != 0) && (value_list.use->discarded)) continue; const int selected = value_list.select_first (); if (selected < 0) continue; SymbolValue& value = value_list.values[selected]; result += value_list.print (symbol, value, first_definition); } return result; } //------------------------------------------------------------- const cmt_string SetBuilder::build (const Symbol& symbol, const cmt_string& /*tag_name*/) { // Control of recursivity static int level = 0; bool show_it = false; cmt_string temp; cmt_string previous_temp; cmt_string new_value; static const cmt_string empty; ActionType action = Cmt::get_action (); if (action == action_show_set) { if (symbol.name == Cmt::get_current_target ()) { // Should not display on recursive calls if (level == 0) show_it = m_display_it; } } level++; temp = ""; bool first_definition = true; for (int i = 0; i < symbol.value_lists.size (); i++) { const SymbolValueList& value_list = symbol.value_lists[i]; if ((value_list.use != 0) && (value_list.use->discarded)) continue; const int selected = value_list.select_first (); if (selected < 0) continue; SymbolValue& value = value_list.values[selected]; if (show_it && !Symbol::get_inhibit_display()) { value_list.show (symbol, value, first_definition); } if (value_list.discarded) continue; // // One should accumulate values if it refers to // itself. // new_value = value.text; resolve_value_for_macros (new_value); switch (value_list.command_type) { case CommandSet : if (!value_list.is_reflexive || !symbol.value_is_reflexive (value.text)) { resolve_value (new_value, symbol.name, temp); temp = new_value; } else if (temp == "") { temp = CmtSystem::getenv (symbol.name); } break; case CommandSetAppend : if (new_value != "") { temp += new_value; } break; case CommandSetPrepend : if (new_value != "") { previous_temp = temp; temp = new_value; temp += previous_temp; } break; case CommandSetRemove : if (new_value != "") { temp.replace_all (new_value, empty); } break; case CommandSetRemoveRegexp : if (new_value != "") { cmt_regexp e (new_value); cmt_regexp::iterator it; for (;;) { it = e.begin (temp); if (it == e.end ()) break; temp.erase (it._pos, it._length); } } break; case CommandAlias : resolve_value (new_value, symbol.name, temp); temp = new_value; break; } } level--; return (temp); } static bool find_path_entry (const CmtSystem::cmt_string_vector& items, const cmt_string& value) { static const cmt_string path_separator = CmtSystem::path_separator (); static cmt_vmap realpaths; if (value.size () == 0) return true; cmt_string rvalue; const cmt_string * prvalue; if (!(prvalue = realpaths.find (value))) { if (!CmtSystem::realpath_ (value, rvalue)) { rvalue = value; CmtSystem::compress_path (rvalue); } prvalue = &rvalue; realpaths.add (value, rvalue); // cerr << "realpaths.add: " << value << " , " << rvalue << endl; } // CmtSystem::cmt_string_vector items; // CmtSystem::split (paths, path_separator, items); bool found = false; for (int i = 0; i < items.size (); i++) { const cmt_string& item = items[i]; if (item.size () == 0) continue; cmt_string ritem; const cmt_string * pritem; if (!(pritem = realpaths.find (item))) { if (!CmtSystem::realpath_ (item, ritem)) { ritem = item; CmtSystem::compress_path (ritem); } pritem = &ritem; realpaths.add (item, ritem); // cerr << "realpaths.add: " << item << " , " << ritem << endl; } if (*pritem == *prvalue) { found = true; break; } } return (found); } static bool find_path_entry (const cmt_string& paths, const cmt_string& value) { static const cmt_string path_separator = CmtSystem::path_separator (); static cmt_vmap realpaths; cmt_string rvalue; const cmt_string * prvalue; if (!(prvalue = realpaths.find (value))) { if (!CmtSystem::realpath_ (value, rvalue)) { rvalue = value; CmtSystem::compress_path (rvalue); } prvalue = &rvalue; realpaths.add (value, rvalue); // cerr << "realpaths.add: " << value << " , " << rvalue << endl; } CmtSystem::cmt_string_vector items; CmtSystem::split (paths, path_separator, items); bool found = false; for (int i = 0; i < items.size (); i++) { const cmt_string& item = items[i]; cmt_string ritem; const cmt_string * pritem; if (!(pritem = realpaths.find (item))) { if (!CmtSystem::realpath_ (item, ritem)) { ritem = item; CmtSystem::compress_path (ritem); } pritem = &ritem; realpaths.add (item, ritem); // cerr << "realpaths.add: " << item << " , " << ritem << endl; } if (*pritem == *prvalue) { found = true; break; } } return (found); } //------------------------------------------------------------- const cmt_string PathBuilder::build (const Symbol& symbol, const cmt_string& /*tag_name*/) { // Control of recursivity static int level = 0; bool show_it = false; cmt_string temp; CmtSystem::cmt_string_vector temp_vector; // cmt_string previous_temp; CmtSystem::cmt_string_vector new_value_vector; cmt_string new_value; static const cmt_string empty; static cmt_string path_separator = CmtSystem::path_separator (); ActionType action = Cmt::get_action (); if (action == action_show_set) { if (symbol.name == Cmt::get_current_target ()) { // Should not display on recursive calls if (level == 0) show_it = m_display_it; } } level++; CmtSystem::split (CmtSystem::getenv (symbol.name), path_separator, temp_vector); //temp = CmtSystem::getenv (symbol.name); bool first_definition = true; for (int i = 0; i < symbol.value_lists.size (); i++) { const SymbolValueList& value_list = symbol.value_lists[i]; if ((value_list.use != 0) && (value_list.use->discarded)) continue; const int selected = value_list.select_first (); if (selected < 0) continue; SymbolValue& value = value_list.values[selected]; if (show_it && !Symbol::get_inhibit_display()) { value_list.show (symbol, value, first_definition); } if (value_list.discarded) continue; new_value = value.text; //resolve_value (new_value); resolve_value_for_macros (new_value); switch (value_list.command_type) { case CommandPath : if (!value_list.is_reflexive || !symbol.value_is_reflexive (value.text)) { Cmt::vector_to_string (temp_vector, path_separator, temp); resolve_value (new_value, symbol.name, temp); CmtSystem::split (new_value, path_separator, temp_vector); //temp = new_value; } break; case CommandPathAppend : if (new_value != "") { CmtSystem::split (new_value, path_separator, new_value_vector); for (int i = 0; i < new_value_vector.size (); i++) if (!find_path_entry (temp_vector, new_value_vector[i])) //if (!find_path_entry (temp, new_value)) { temp_vector.push_back (new_value_vector[i]); /* if (temp != "") temp += path_separator; temp += new_value; */ } } break; case CommandPathPrepend : if (new_value != "") { CmtSystem::split (new_value, path_separator, new_value_vector); int n (new_value_vector.size ()); temp_vector.resize (temp_vector.size () + n); for (int i = temp_vector.size () - 1; i > n - 1; i--) temp_vector [i] = temp_vector [i - n]; for (int i = 0; i < new_value_vector.size (); i++) if (!find_path_entry (temp_vector, new_value_vector[i])) //if (!find_path_entry (temp, new_value)) { temp_vector [i] = new_value_vector[i]; /* previous_temp = temp; temp = new_value; if (previous_temp != "") temp += path_separator; temp += previous_temp; */ } else temp_vector [i] = ""; } break; case CommandPathRemove : if (new_value != "") { for (int j = 0; j < temp_vector.size (); ++j) { cmt_string& s = temp_vector[j]; if (s.find (new_value) != cmt_string::npos) { s = ""; } } /* CmtSystem::cmt_string_vector paths; CmtSystem::split (temp, path_separator, paths); for (int j = 0; j < paths.size (); ++j) { cmt_string& s = paths[j]; if (s.find (new_value) != cmt_string::npos) { s = ""; } } Cmt::vector_to_string (paths, path_separator, temp); */ } break; case CommandPathRemoveRegexp : if (new_value != "") { cmt_regexp e (new_value); for (int j = 0; j < temp_vector.size (); ++j) { cmt_string& s = temp_vector[j]; if (Cmt::get_debug () && CmtSystem::getenv ("TESTPRR") != "") { cerr << "PRR> s=[" << s << "]"; } if (e.match (s)) { s = ""; if (Cmt::get_debug () && CmtSystem::getenv ("TESTPRR") != "") { cerr << " match "; } } else { if (Cmt::get_debug () && CmtSystem::getenv ("TESTPRR") != "") { cerr << " no match "; } } if (Cmt::get_debug () && CmtSystem::getenv ("TESTPRR") != "") { cerr << endl; } } /* CmtSystem::cmt_string_vector paths; CmtSystem::split (temp, path_separator, paths); for (int j = 0; j < paths.size (); ++j) { cmt_string& s = paths[j]; if (CmtSystem::getenv ("TESTPRR") != "") { cerr << "PRR> s=[" << s << "]"; } if (e.match (s)) { s = ""; if (CmtSystem::getenv ("TESTPRR") != "") { cerr << " match "; } } else { if (CmtSystem::getenv ("TESTPRR") != "") { cerr << " no match "; } } if (CmtSystem::getenv ("TESTPRR") != "") { cerr << endl; } } Cmt::vector_to_string (paths, path_separator, temp); */ } break; } } Cmt::vector_to_string (temp_vector, path_separator, temp); level--; for (;;) { int sz = temp.size (); if (sz == 0) break; if ((temp[0] == ';') || (temp[0] == ':')) { temp.erase (0, 1); } else if ((temp[sz-1] == ';') || (temp[sz-1] == ':')) { temp.erase (sz-1, 1); } else { break; } } temp.replace_all ("::", ":"); temp.replace_all (";;", ";"); return (temp); } //------------------------------------------------------------- const cmt_string PathBuilder::clean (const Symbol& symbol, const cmt_string& /*tag_name*/) { // Control of recursivity static int level = 0; cmt_string temp; cmt_string new_value; static const cmt_string empty; static cmt_string path_separator = CmtSystem::path_separator (); temp = CmtSystem::getenv (symbol.name); //cerr << "#####1 temp=" << temp << endl; for (int i = 0; i < symbol.value_lists.size (); i++) { const SymbolValueList& value_list = symbol.value_lists[i]; if (value_list.discarded) continue; if ((value_list.use != 0) && (value_list.use->discarded)) continue; const int selected = value_list.select_first (); if (selected < 0) continue; SymbolValue& value = value_list.values[selected]; new_value = value.text; //resolve_value (new_value); //cerr << "#####1 new_value=" << new_value << endl; resolve_value_for_macros (new_value); resolve_value (new_value); //cerr << "#####2 new_value=" << new_value << endl; switch (value_list.command_type) { case CommandPath : temp = ""; break; case CommandPathAppend : case CommandPathPrepend : case CommandPathRemove : if (new_value != "") { CmtSystem::cmt_string_vector paths; CmtSystem::split (temp, path_separator, paths); for (int j = 0; j < paths.size (); ++j) { cmt_string& s = paths[j]; if (s.find (new_value) != cmt_string::npos) { s = ""; } if (j > 0) { cmt_string& s2 = paths[j-1]; if (s2 == s) { s2 = ""; } } } Cmt::vector_to_string (paths, path_separator, temp); temp.replace_all ("::", ":"); temp.replace_all (";;", ";"); } break; case CommandPathRemoveRegexp : if (new_value != "") { cmt_regexp e (new_value); CmtSystem::cmt_string_vector paths; CmtSystem::split (temp, path_separator, paths); for (int j = 0; j < paths.size (); ++j) { cmt_string& s = paths[j]; if (e.match (s)) { s = ""; } if (j > 0) { cmt_string& s2 = paths[j-1]; if (s2 == s) { s2 = ""; } } } Cmt::vector_to_string (paths, path_separator, temp); temp.replace_all ("::", ":"); temp.replace_all (";;", ";"); } break; } } //cerr << "#####2 temp=" << temp << endl; return (temp); } //------------------------------------------------------------- const cmt_string MacroBuilder::build (const Symbol& symbol, const cmt_string& tag_name) { // Control of recursivity static int level = 0; cmt_string temp; cmt_string previous_temp; static const cmt_string empty; bool show_it = false; ActionType action = Cmt::get_action (); if (action == action_show_macro) { if (symbol.name == Cmt::get_current_target ()) { // Should not display on recursive calls if (level == 0) show_it = m_display_it; } } level++; temp = ""; int i; bool first_definition = true; for (i = 0; i < symbol.value_lists.size (); i++) { const SymbolValueList& value_list = symbol.value_lists[i]; if ((value_list.use != 0) && (value_list.use->discarded)) continue; if (value_list.command_type != CommandMacroPrepend) continue; const int selected = value_list.select_first (tag_name); if (selected < 0) continue; SymbolValue& value = value_list.values[selected]; if (show_it && !Symbol::get_inhibit_display()) { value_list.show (symbol, value, first_definition); } if (value_list.discarded) continue; previous_temp = temp; temp = value.text; temp += previous_temp; } previous_temp = temp; temp = ""; first_definition = true; for (i = 0; i < symbol.value_lists.size (); i++) { const SymbolValueList& value_list = symbol.value_lists[i]; if ((value_list.use != 0) && (value_list.use->discarded)) continue; if (value_list.command_type != CommandMacro) continue; const int selected = value_list.select_first (tag_name); if (selected < 0) continue; SymbolValue& value = value_list.values[selected]; if (show_it && !Symbol::get_inhibit_display()) { value_list.show (symbol, value, first_definition); } // WARNING: // Commented just for a test : should be uncommented after the test if (value_list.discarded) continue; if (!value_list.is_reflexive || !symbol.value_is_reflexive (value.text)) { temp = value.text; } } previous_temp += temp; temp = previous_temp; for (i = 0; i < symbol.value_lists.size (); i++) { const SymbolValueList& value_list = symbol.value_lists[i]; if ((value_list.use != 0) && (value_list.use->discarded)) continue; if (value_list.command_type != CommandMacroAppend) continue; const int selected = value_list.select_first (tag_name); if (selected < 0) continue; SymbolValue& value = value_list.values[selected]; if (show_it && !Symbol::get_inhibit_display()) { value_list.show (symbol, value, first_definition); } if (value_list.discarded) continue; temp += value.text; } for (i = 0; i < symbol.value_lists.size (); i++) { const SymbolValueList& value_list = symbol.value_lists[i]; if ((value_list.use != 0) && (value_list.use->discarded)) continue; if ((value_list.command_type != CommandMacroRemove) && (value_list.command_type != CommandMacroRemoveRegexp) && (value_list.command_type != CommandMacroRemoveAll) && (value_list.command_type != CommandMacroRemoveAllRegexp)) continue; const int selected = value_list.select_first (tag_name); if (selected < 0) continue; SymbolValue& value = value_list.values[selected]; if (show_it && !Symbol::get_inhibit_display()) { value_list.show (symbol, value, first_definition); } if (value_list.discarded) continue; switch (value_list.command_type) { case CommandMacroRemove : temp.replace (value.text, empty); break; case CommandMacroRemoveRegexp : if (value.text != "") { cmt_regexp e (value.text); cmt_regexp::iterator it; it = e.begin (temp); if (it != e.end ()) { temp.erase (it._pos, it._length); } } break; case CommandMacroRemoveAll : temp.replace_all (value.text, empty); break; case CommandMacroRemoveAllRegexp : if (value.text != "") { cmt_regexp e (value.text); cmt_regexp::iterator it; for (;;) { it = e.begin (temp); if (it != e.end ()) { temp.erase (it._pos, it._length); } else { break; } } } break; } } level--; return (temp); } //------------------------------------------------------------- const cmt_string ScriptBuilder::build (const Symbol& symbol, const cmt_string& tag_name) { // Control of recursivity static int level = 0; static const cmt_string empty = ""; if (symbol.value_lists.size () > 0) { const SymbolValueList& value_list = symbol.value_lists[0]; if (value_list.discarded) return (empty); if ((value_list.use != 0) && (value_list.use->discarded)) return (empty); } return (symbol.name); } //------------------------------------------------------------- const cmt_string ActionBuilder::build (const Symbol& symbol, const cmt_string& tag_name) { // Control of recursivity static int level = 0; cmt_string temp; cmt_string previous_temp; static const cmt_string empty; bool show_it = false; ActionType action = Cmt::get_action (); if (action == action_show_action) { if (symbol.name == Cmt::get_current_target ()) { // Should not display on recursive calls if (level == 0) show_it = m_display_it; } } level++; int i; bool first_definition = true; temp = ""; for (i = 0; i < symbol.value_lists.size (); i++) { const SymbolValueList& value_list = symbol.value_lists[i]; if ((value_list.use != 0) && (value_list.use->discarded)) continue; if (value_list.command_type != CommandAction) continue; const int selected = value_list.select_first (tag_name); if (selected < 0) continue; SymbolValue& value = value_list.values[selected]; if (show_it && !Symbol::get_inhibit_display()) { value_list.show (symbol, value, first_definition); } // WARNING: // Commented just for a test : should be uncommented after the test if (value_list.discarded) continue; if (!value_list.is_reflexive || !symbol.value_is_reflexive (value.text)) { temp = value.text; } } level--; return (temp); } //------------------------------------------------------------- int SymbolValueList::select_first (const cmt_string& tag_name) const { int priority = 0; int value_number; int selected = -1; Tag* the_tag = 0; if (tag_name != "") the_tag = Tag::find (tag_name); for (value_number = 0; value_number < values.size (); value_number++) { const SymbolValue& value = values[value_number]; const Tag* tag = value.tag; if (the_tag == 0) { if (!tag->is_selected ()) continue; selected = value_number; if (tag == Tag::get_default ()) continue; } else { if (tag != the_tag) continue; selected = value_number; } // // Only the value for the first alternative (i.e. non-default) // matching tag expression is // selected (which means the selection stops here) // break; // // Only the first value at a given priority is // selected (which implies the '>' test instead // of '>=') // /* if (tag->get_priority () > priority) { priority = tag->get_priority (); selected = value_number; } */ } return (selected); } //------------------------------------------------------------- int SymbolValueList::select_last () const { int priority = 0; int value_number; int selected = -1; for (value_number = 0; value_number < values.size (); value_number++) { SymbolValue& value = values[value_number]; const Tag* tag = value.tag; if (tag->is_selected ()) { // // The last value at a given priority is // selected (which implies the '>=' test instead // of '>') // if (tag->get_priority () >= priority) { priority = tag->get_priority (); selected = value_number; } } } return (selected); } //------------------------------------------------------------- void SymbolValueList::show (const Symbol& symbol, const SymbolValue& value, bool& first_definition) const { cmt_string discarded_text; cmt_string define_text; ActionType action = Cmt::get_action (); switch (command_type) { //case CommandSet : case CommandSetAppend : case CommandSetPrepend : case CommandSetRemove : case CommandSetRemoveRegexp : //case CommandAlias : //case CommandPath : case CommandPathAppend : case CommandPathPrepend : case CommandPathRemove : case CommandPathRemoveRegexp : case CommandMacroPrepend : //case CommandMacro : case CommandMacroAppend : case CommandMacroRemove : case CommandMacroRemoveRegexp : case CommandMacroRemoveAll : case CommandMacroRemoveAllRegexp : //case CommandAction : if (value.text == "") return; break; } if (discarded) discarded_text = " (discarded by override)"; else discarded_text = ""; if (first_definition) define_text = "defines"; else define_text = "overrides"; cout << "# Package "; if (use != 0) { cout << use->get_package_name () << " " << use->version; } switch (command_type) { case CommandSet : cout << " " << define_text << " set " << symbol.name << " as "; first_definition = false; break; case CommandSetAppend : cout << " appends to set " << symbol.name << " : "; break; case CommandSetPrepend : cout << " prepends to set " << symbol.name << " : "; break; case CommandSetRemove : cout << " removes from set " << symbol.name << " : "; break; case CommandSetRemoveRegexp : cout << " removes RE from set " << symbol.name << " : "; break; case CommandAlias : cout << " " << define_text << " alias " << symbol.name << " as "; first_definition = false; break; case CommandPath : cout << " " << define_text << " path " << symbol.name << " as "; first_definition = false; break; case CommandPathAppend : cout << " appends to path " << symbol.name << " : "; break; case CommandPathPrepend : cout << " prepends to path " << symbol.name << " : "; break; case CommandPathRemove : cout << " removes from path " << symbol.name << " : "; break; case CommandPathRemoveRegexp : cout << " removes RE from path " << symbol.name << " : "; break; case CommandMacroPrepend : cout << " prepends to macro " << symbol.name << " : "; break; case CommandMacro : cout << " " << define_text << " macro " << symbol.name << " as "; break; case CommandMacroAppend : cout << " appends to macro " << symbol.name << " : "; break; case CommandMacroRemove : cout << " remove from macro " << symbol.name << " : "; break; case CommandMacroRemoveRegexp : cout << " remove RE from macro " << symbol.name << " : "; break; case CommandMacroRemoveAll : cout << " remove all from macro " << symbol.name << " : "; break; case CommandMacroRemoveAllRegexp : cout << " remove all RE from macro " << symbol.name << " : "; break; case CommandAction : cout << " " << define_text << " action " << symbol.name << " as "; first_definition = false; break; } cout << "'" << value.text << "'"; Tag* selected_tag = value.tag; if ((selected_tag == 0) || (selected_tag == Tag::get_default ())) { cout << " for default tag"; } else { cout << " for tag '" << selected_tag->get_name () << "'"; } cout << discarded_text << endl; } //------------------------------------------------------------- int SymbolValueList::print (const Symbol& symbol, const SymbolValue& value, bool& first_definition) const { int result (0); //if (use->get_package_name () == "CMT") return result; cmt_string discarded_text; cmt_string define_text; ActionType action = Cmt::get_action (); switch (command_type) { //case CommandSet : case CommandSetAppend : case CommandSetPrepend : case CommandSetRemove : case CommandSetRemoveRegexp : //case CommandAlias : //case CommandPath : case CommandPathAppend : case CommandPathPrepend : case CommandPathRemove : case CommandPathRemoveRegexp : case CommandMacroPrepend : //case CommandMacro : case CommandMacroAppend : case CommandMacroRemove : case CommandMacroRemoveRegexp : case CommandMacroRemoveAll : case CommandMacroRemoveAllRegexp : //case CommandAction : if (value.text == "") return result; break; } if (discarded) discarded_text = " (discarded by override)"; else discarded_text = ""; if (first_definition) define_text = "defines"; else define_text = "overrides"; if (CmtMessage::active (Verbose)) cout << "# Package " << (use != 0 ? use->get_package_name () + " " + use->version : ""); /* if (use != 0) { cout << use->get_package_name () << " " << use->version; } */ switch (command_type) { case CommandSet : if (CmtMessage::active (Verbose)) cout << " " << define_text << " set " << symbol.name << " as " << endl; // cout << " " << define_text << " set " << symbol.name << " as "; cout << "set " << symbol.name; first_definition = false; result = 1; break; case CommandSetAppend : if (CmtMessage::active (Verbose)) cout << " appends to set " << symbol.name << " : " << endl; // cout << " appends to set " << symbol.name << " : "; cout << "set_append " << symbol.name; result = 1; break; case CommandSetPrepend : if (CmtMessage::active (Verbose)) cout << " prepends to set " << symbol.name << " : " << endl; // cout << " prepends to set " << symbol.name << " : "; cout << "set_prepend " << symbol.name; result = 1; break; case CommandSetRemove : if (CmtMessage::active (Verbose)) cout << " removes from set " << symbol.name << " : " << endl; // cout << " removes from set " << symbol.name << " : "; cout << "set_remove " << symbol.name; result = 1; break; case CommandSetRemoveRegexp : if (CmtMessage::active (Verbose)) cout << " removes RE from set " << symbol.name << " : " << endl; // cout << " removes RE from set " << symbol.name << " : "; cout << "set_remove_regexp " << symbol.name; result = 1; break; case CommandAlias : if (CmtMessage::active (Verbose)) cout << " " << define_text << " alias " << symbol.name << endl; // cout << " " << define_text << " alias " << symbol.name << " as "; cout << "alias " << symbol.name; first_definition = false; result = 1; break; case CommandPath : if (CmtMessage::active (Verbose)) cout << " " << define_text << " path " << symbol.name << endl; // cout << " " << define_text << " path " << symbol.name << " as "; cout << "path " << symbol.name; first_definition = false; result = 1; break; case CommandPathAppend : if (CmtMessage::active (Verbose)) cout << " appends to path " << symbol.name << endl; // cout << " appends to path " << symbol.name << " : "; cout << "path_append " << symbol.name; result = 1; break; case CommandPathPrepend : if (CmtMessage::active (Verbose)) cout << " prepends to path " << symbol.name << " : " << endl; // cout << " prepends to path " << symbol.name << " : "; cout << "path_prepend " << symbol.name; result = 1; break; case CommandPathRemove : if (CmtMessage::active (Verbose)) cout << " removes from path " << symbol.name << " : " << endl; // cout << " removes from path " << symbol.name << " : "; cout << "path_remove " << symbol.name; result = 1; break; case CommandPathRemoveRegexp : if (CmtMessage::active (Verbose)) cout << " removes RE from path " << symbol.name << " : " << endl; // cout << " removes RE from path " << symbol.name << " : "; cout << "path_remove_regexp " << symbol.name; result = 1; break; case CommandMacro : if (CmtMessage::active (Verbose)) cout << " " << define_text << " macro " << symbol.name << " as " << endl; // cout << " " << define_text << " macro " << symbol.name << " as "; cout << "macro " << symbol.name; result = 1; break; case CommandMacroPrepend : if (CmtMessage::active (Verbose)) cout << " prepends to macro " << symbol.name << " : " << endl; // cout << " prepends to macro " << symbol.name << " : "; cout << "macro_prepend " << symbol.name; result = 1; break; case CommandMacroAppend : if (CmtMessage::active (Verbose)) cout << " appends to macro " << symbol.name << " : " << endl; // cout << " appends to macro " << symbol.name << " : "; cout << "macro_append " << symbol.name; result = 1; break; case CommandMacroRemove : if (CmtMessage::active (Verbose)) cout << " remove from macro " << symbol.name << " : " << endl; // cout << " remove from macro " << symbol.name << " : "; cout << "macro_remove " << symbol.name; result = 1; break; case CommandMacroRemoveRegexp : if (CmtMessage::active (Verbose)) cout << " remove RE from macro " << symbol.name << " : " << endl; // cout << " remove RE from macro " << symbol.name << " : "; cout << "macro_remove_regexp " << symbol.name; result = 1; break; case CommandMacroRemoveAll : if (CmtMessage::active (Verbose)) cout << " remove all from macro " << symbol.name << " : " << endl; // cout << " remove all from macro " << symbol.name << " : "; cout << "macro_remove_all " << symbol.name; result = 1; break; case CommandMacroRemoveAllRegexp : if (CmtMessage::active (Verbose)) cout << " remove all RE from macro " << symbol.name << " : " << endl; // cout << " remove all RE from macro " << symbol.name << " : "; cout << "macro_remove_all_regexp " << symbol.name; result = 1; break; case CommandSetupScript : if (CmtMessage::active (Verbose)) cout << " " << define_text << " setup script " << symbol.name << endl; // cout << " " << define_text << " action " << symbol.name << " as "; cout << "setup_script" /* << symbol.name */; first_definition = false; result = 1; break; /* case CommandAction : cout << " " << define_text << " action " << symbol.name << " as "; first_definition = false; break; */ } cout << " " << CmtSystem::quote (value.text, " \t"); // cout << "'" << value.text << "'"; /* Tag* selected_tag = value.tag; if ((selected_tag == 0) || (selected_tag == Tag::get_default ())) { cout << " for default tag"; } else { cout << " for tag '" << selected_tag->get_name () << "'"; } */ cout << endl; // cout << discarded_text << endl; return result; } //------------------------------------------------------------- bool Symbol::check_tag_used (const Tag* tag) { if (tag == 0) return (false); static SymbolVector& Symbols = symbols (); if (Symbols.size () == 0) { return (false); } for (int number = 0; number < Symbol::symbol_number (); number++) { Symbol& symbol = Symbol::symbol (number); for (int i = 0; i < symbol.value_lists.size (); i++) { const SymbolValueList& value_list = symbol.value_lists[i]; for (int j = 0; j < value_list.values.size (); j++) { const SymbolValue& value = value_list.values[j]; Tag* t = value.tag; if (t != 0) { if (t->use_operand (tag)) return (true); } } } } return (false); } //------------------------------------------------------------- cmt_string Symbol::get_env_value (const cmt_string& name) { cmt_string s; Symbol* symbol = Symbol::find (name); if (symbol != 0) { m_inhibit_display = true; s = symbol->build_macro_value (); Symbol::expand (s); m_inhibit_display = false; } else { s = CmtSystem::getenv (name); } return (s); } bool Symbol::get_inhibit_display () { return (m_inhibit_display); }