#include #include #include #include #include "cmt_use.h" #include "cmt_symbol.h" #include "cmt_system.h" #include "cmt_database.h" //------------------------------------------------------------- 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); } private: cmt_string temp; }; //------------------------------------------------------------- //------------------------------------------------------------- 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 = ""); private: cmt_string temp; }; //------------------------------------------------------------- //------------------------------------------------------------- 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); } private: cmt_string temp; }; //------------------------------------------------------------- //------------------------------------------------------------- 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); } private: cmt_string temp; }; //------------------------------------------------------------- //------------------------------------------------------------- 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 last) { static symbol_marker result; // discards trailing npos while ((last >= 0) && (markers[last].ptr == cmt_string::npos)) last--; if (last < 0) return (result); int i; // since we've passed the previous test, // at least one entry (last) is not npos. // Now discards other npos by moving them to the end for (i = 0; i <= last; i++) { if (markers[i].ptr == cmt_string::npos) { markers[i] = markers[last]; last--; if (last < 0) break; } } if (last < 0) return (result); // now all entries in [0, last] are not npos // let's sort the lowest one in [0] for (i = 1; i <= last;) { if (markers[0].ptr > markers[i].ptr) { symbol_marker temp = markers[0]; markers[0] = markers[i]; markers[i] = temp; i = 1; } else { i++; if (i > last) break; } } return (markers[0]); } int ptr; char pattern; int intro; }; //------------------------------------------------------------- //------------------------------------------------------------- static SetBuilder Set; static PathBuilder Path; static MacroBuilder Macro; static ScriptBuilder Script; //------------------------------------------------------------- //------------------------------------------------------------- static void resolve_value (cmt_string& text, const cmt_string& macro_name, const cmt_string& value) { static cmt_string pattern; pattern = "${"; pattern += macro_name; pattern += "}"; text.replace_all (pattern, value); pattern = "$("; pattern += macro_name; pattern += ")"; text.replace_all (pattern, value); #ifdef WIN32 pattern = "%"; pattern += macro_name; pattern += "%"; text.replace_all (pattern, value); #endif } //------------------------------------------------------------- static void resolve_value (cmt_string& text) { cmt_string pattern; cmt_string macro_name; char end_pattern; int start = 0; for (;;) { // // Try and substitute all ${xxx} $(xxx) or %xxx% patterns // using symbol values. // int begin; int end; symbol_marker markers[3]; markers[0].set (text.find (start, "$("), ')', 2); markers[1].set (text.find (start, "${"), '}', 2); markers[2].set (text.find (start, "%"), '%', 1); // Find the first of three patterns symbol_marker& marker = symbol_marker::get_lowest (markers, 2); 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, macro_name); Symbol* macro = Symbol::find (macro_name); if (macro != 0) { // 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 { // Macro not found. Look for env. variable cmt_string value = CmtSystem::getenv (macro_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; } } } //------------------------------------------------------------- static void resolve_value_for_macros (cmt_string& text) { cmt_string pattern; cmt_string macro_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[3]; markers[0].set (text.find (start, "$("), ')', 2); markers[1].set (text.find (start, "${"), '}', 2); markers[2].set (text.find (start, "%"), '%', 1); // Find the first of three patterns symbol_marker& marker = symbol_marker::get_lowest (markers, 2); 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, macro_name); Symbol* macro = Symbol::find (macro_name); if ((macro != 0) && (macro->command == CommandMacro)) { // 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->command == CommandSet) || (macro->command == CommandPath))) { // 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 += macro_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 pure macro delimiters. */ static void suppress_OS_delimiters (cmt_string& text) { cmt_string pattern; cmt_string macro_name; char end_pattern; int start = 0; for (;;) { int begin; int end; symbol_marker markers[3]; markers[0].set (text.find (start, "${"), '}', 2); #ifdef WIN32 markers[1].set (text.find (start, "%"), '%', 1); #endif // Find the first of three patterns symbol_marker& marker = symbol_marker::get_lowest (markers, 2); 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, macro_name); cmt_string new_pattern; new_pattern = "$("; new_pattern += macro_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, ScopeType scope) { static SymbolVector& Symbols = symbols (); { Symbol* symbol; symbol = find (name); if (symbol != 0) return (symbol); } Symbol& symbol = Symbols.add (); symbol.name = name; symbol.scope = scope; symbol.command = command; symbol.value_lists.clear (); switch (command) { case CommandSet: case CommandSetAppend: case CommandSetPrepend: case CommandSetRemove: symbol.builder = &Set; symbol.command = CommandSet; break; case CommandPath: case CommandPathAppend: case CommandPathPrepend: case CommandPathRemove: symbol.builder = &Path; break; case CommandAlias: symbol.builder = &Set; break; case CommandMacro: case CommandMacroAppend: case CommandMacroPrepend: case CommandMacroRemove: case CommandMacroRemoveAll: symbol.builder = &Macro; symbol.command = CommandMacro; break; case CommandSetupScript: case CommandCleanupScript: symbol.builder = &Script; break; } symbol.selected_value = -1; return (&symbol); } //------------------------------------------------------------- Symbol* Symbol::find (const cmt_string& name) { static SymbolVector& Symbols = symbols (); int number; Symbol* result = 0; for (number = 0; number < Symbols.size (); number++) { Symbol& s = Symbols[number]; if (s.name == name) { result = &s; } } 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& 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 { #ifdef WIN32 full_name = "%"; #else full_name = "${"; #endif full_name += use->prefix; full_name += "ROOT"; #ifdef WIN32 full_name += "%"; #else full_name += "}"; #endif full_name += CmtSystem::file_separator (); if (use->style == cmt_style) full_name += "cmt"; else full_name += "mgr"; full_name += CmtSystem::file_separator (); full_name += name; } symbol = create (full_name, command_type, Cmt::get_scope ()); 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]; if ((Cmt::get_current_access () == UserMode) && (Cmt::get_scope () == ScopePrivate)) return; symbol = create (name, command_type, Cmt::get_scope ()); /* 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)) { const cmt_string& tag_name = words[number]; const cmt_string& value = words[number + 1]; 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 == "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->package; 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 == CommandAlias)) { 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->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)) { // // 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 << endl; for (int i = 0; i < (value_lists.size () - 1); i++) { SymbolValueList& vl = value_lists[i]; if ((vl.use != 0) && (vl.use->discarded)) continue; vl.discarded = true; } } } } SymbolValue& value = value_list->values.add (); value.tag = tag; value.text = text; value.selected = 0; } //------------------------------------------------------------- // Check symbol's scope against current scope and symbol // type. //------------------------------------------------------------- int Symbol::valid (PrintMode mode) { int result = 0; if (command == CommandMacro) return (0); if (command == CommandMacroPrepend) return (0); if (command == CommandMacroAppend) return (0); if (command == CommandMacroRemove) return (0); if (command == CommandMacroRemoveAll) return (0); if (scope != Cmt::get_scope ()) return (0); return (1); } //------------------------------------------------------------- void Symbol::all_print (PrintMode mode) { 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.command == CommandSet) || (symbol.command == CommandAlias) || (symbol.command == CommandSetupScript)) { if (symbol.print (1, mode)) { if (mode == Bat) { cout << endl; } else { //cout << "; "; cout << endl; } } } } for (number = 0; number < Symbol::symbol_number (); number++) { Symbol& symbol = Symbol::symbol (number); if ((symbol.command != CommandPath) && (symbol.command != CommandPathAppend) && (symbol.command != CommandPathPrepend) && (symbol.command != CommandPathRemove)) continue; if (symbol.print (1, mode)) { if (mode == Bat) { cout << endl; } else { //cout << "; "; cout << endl; } } } } //------------------------------------------------------------- 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.command == CommandSet) || (symbol.command == CommandAlias) || (symbol.command == CommandCleanupScript)) { if (symbol.print_clean (0, mode)) { cout << endl; } } } for (number = Symbols.size () - 1; number >= 0; number--) { Symbol& symbol = Symbols[number]; if ((symbol.command != CommandPath) && (symbol.command != CommandPathAppend) && (symbol.command != CommandPathPrepend) && (symbol.command != CommandPathRemove)) continue; if (symbol.print_clean (0, mode)) { cout << endl; } } } //------------------------------------------------------------- int Symbol::print_clean (int tabs, PrintMode mode) { int result = 0; static cmt_string temp; if (name == "CMTCONFIG") return (0); switch (command) { case CommandSet : switch (mode) { case Csh : cout << "unsetenv " << name; result = 1; break; case Sh : cout << "unset " << name; result = 1; break; case Bat : cout << "set " << name << "="; result = 1; break; } break; case CommandAlias : switch (mode) { case Csh : cout << "unalias " << name; result = 1; break; case Sh : cout << "unset " << name; result = 1; break; } break; case CommandPath : case CommandPathAppend : case CommandPathPrepend : case CommandPathRemove : temp = clean_macro_value (); switch (mode) { case Csh : if (temp == "") { cout << "unsetenv " << name; } else { cout << "setenv " << name << " " << temp; } result = 1; break; case Sh : cout << name << "=" << temp << "; export " << name; result = 1; break; case Bat : cout << "set " << name << "=" << temp; result = 1; break; } break; case CommandCleanupScript : switch (mode) { case Csh : cout << "if ( -f " << name << ".csh ) then" << endl; cout << " source " << name << ".csh" << endl; cout << "endif" << endl; result = 1; break; case Sh : cout << "if test -f " << name << ".sh; then" << endl; cout << " . " << name << ".sh" << endl; cout << "fi" << endl; result = 1; break; case Bat : cout << "call " << name; result = 1; break; } break; } return (result); } //------------------------------------------------------------- int Symbol::print (int tabs, PrintMode mode) { int result = 0; static cmt_string temp; temp = build_macro_value (); switch (command) { case CommandSet : case CommandPath : case CommandPathAppend : case CommandPathPrepend : case CommandPathRemove : switch (mode) { case Csh : cout << "setenv " << name << " \"" << temp << "\""; result = 1; break; case Sh : cout << name << "=\"" << temp << "\"; export " << name; result = 1; break; case Bat : temp.replace_all ("/", "\\"); cout << "set " << name << "=" << temp; result = 1; break; } break; case CommandAlias : switch (mode) { case Csh : cout << "alias " << name << " \"" << temp << "\""; result = 1; break; case Sh : cout << "alias " << name << "=\"" << temp << "\"; export " << name; result = 1; break; case Bat : cout << "set " << name << "=" << temp; result = 1; break; } break; default : break; } if (temp != "") { switch (command) { case CommandSetupScript : switch (mode) { case Csh : cout << "if ( -f " << name << ".csh ) then" << endl; cout << " source " << name << ".csh" << endl; cout << "endif" << endl; result = 1; break; case Sh : cout << "if test -f " << name << ".sh; then" << endl; cout << " . " << name << ".sh" << endl; cout << "fi" << endl; result = 1; break; case Bat : cout << "call " << name; result = 1; break; } break; default: break; } } return (result); } //------------------------------------------------------------- cmt_string Symbol::build_macro_value () const { cmt_string temp; temp = builder->build (*this); return (temp); } //------------------------------------------------------------- cmt_string Symbol::clean_macro_value () const { cmt_string temp; temp = builder->clean (*this); return (temp); } //------------------------------------------------------------- cmt_string Symbol::resolve_macro_value (const cmt_string& tag_name) { cmt_string temp = builder->build (*this, tag_name); cmt_string pattern; cmt_string macro_name; char end_pattern; int start = 0; for (;;) { int begin; int end; symbol_marker markers[3]; markers[0].set (temp.find (start, "$("), ')', 2); markers[1].set (temp.find (start, "${"), '}', 2); markers[2].set (temp.find (start, "%"), '%', 1); // Find the first of three patterns symbol_marker& marker = symbol_marker::get_lowest (markers, 2); begin = marker.ptr; if (begin == cmt_string::npos) break; end_pattern = marker.pattern; start = begin + marker.intro; end = temp.find (start, end_pattern); if (end == cmt_string::npos) { // The pattern is a fake one (no ending!) start++; continue; } if (end < begin) break; temp.substr (begin, end - begin + 1, pattern); temp.substr (begin + marker.intro, end - begin - marker.intro, macro_name); Symbol* macro = find (macro_name); if (macro != 0) { // Macro found cmt_string value = macro->resolve_macro_value (tag_name); temp.replace_all (pattern, value); start = begin; } else { // Macro not found. Look for env. variable cmt_string value = CmtSystem::getenv (macro_name); temp.replace_all (pattern, value); start = begin; } } return (temp); } //------------------------------------------------------------- void Symbol::show_macro (PrintMode mode) { ActionType action = Cmt::get_action (); cmt_string value = build_macro_value (); if ((!Cmt::get_quiet ()) && (action != action_build_tag_makefile) && (action != action_show_macros) && (action != action_show_sets)) { cout << "#" << endl; cout << "# 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_build_tag_makefile) || (action == action_load) || (!Cmt::get_quiet ())) { if (mode == Make) { cout << name << "="; } else { cout << name << "='"; } } if ((action == action_show_macro_value) || (action == action_show_set_value)) { expand (value); } else if (action == action_build_tag_makefile) { suppress_OS_delimiters (value); } cout << value; if ((action == action_show_macro) || (action == action_show_macros) || (action == action_show_sets) || (action == action_show_set) || (action == action_build_tag_makefile) || (action == action_load) || (!Cmt::get_quiet ())) { if (mode != Make) { cout << "'"; } #ifdef WIN32 else { cout << " "; } #endif } cout << endl; } } //------------------------------------------------------------- void Symbol::clear_all () { static SymbolVector& Symbols = symbols (); Symbols.clear (); } //------------------------------------------------------------- void Symbol::expand (cmt_string& text) { resolve_value (text); } //------------------------------------------------------------- const cmt_string& SetBuilder::build (const Symbol& symbol, const cmt_string& /*tag_name*/) { int show_it = 0; static cmt_string previous_temp; cmt_string new_value; static const cmt_string empty; if (Cmt::get_action () == action_show_set) { if (symbol.name == Cmt::get_current_target ()) { show_it = 1; } } temp = ""; 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]; if (show_it) { cout << "# Package "; if (value_list.use != 0) { cout << value_list.use->package << " " << value_list.use->version; } } // // 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 (show_it) { cout << " defines set " << symbol.name << " as "; } 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 (show_it) { cout << " appends to set " << symbol.name << " : "; } if (new_value != "") { temp += new_value; } break; case CommandSetPrepend : if (show_it) { cout << " prepends to set " << symbol.name << " : "; } if (new_value != "") { previous_temp = temp; temp = new_value; temp += previous_temp; } break; case CommandSetRemove : if (show_it) { cout << " removes from set " << symbol.name << " : "; } if (new_value != "") { temp.replace_all (new_value, empty); } break; case CommandAlias : if (show_it) { cout << " defines alias " << symbol.name << " as "; } resolve_value (new_value, symbol.name, temp); temp = new_value; break; } if (show_it) { 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->name << "'"; } cout << endl; } } return (temp); } static bool find_path_entry (const cmt_string& paths, const cmt_string& value) { static const cmt_string path_separator = CmtSystem::path_separator (); static const cmt_string double_path_separator = path_separator + path_separator; cmt_string complete_paths; complete_paths = path_separator; complete_paths += paths; complete_paths += path_separator; complete_paths.replace_all (double_path_separator, path_separator); cmt_string complete_value; complete_value = path_separator; complete_value += value; complete_value += path_separator; if (complete_paths.find (complete_value) == cmt_string::npos) return (false); else return (true); } //------------------------------------------------------------- const cmt_string& PathBuilder::build (const Symbol& symbol, const cmt_string& /*tag_name*/) { int show_it = 0; static cmt_string previous_temp; cmt_string new_value; static const cmt_string empty; static cmt_string path_separator = CmtSystem::path_separator (); if (Cmt::get_action () == action_show_set) { if (symbol.name == Cmt::get_current_target ()) { show_it = 1; } } temp = CmtSystem::getenv (symbol.name); 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]; if (show_it) { cout << "# Package "; if (value_list.use != 0) { cout << value_list.use->package << " " << value_list.use->version; } } new_value = value.text; //resolve_value (new_value); resolve_value_for_macros (new_value); switch (value_list.command_type) { case CommandPath : if (show_it) { cout << " defines path " << symbol.name << " as "; } if (!value_list.is_reflexive || !symbol.value_is_reflexive (value.text)) { resolve_value (new_value, symbol.name, temp); temp = new_value; } break; case CommandPathAppend : if (show_it) { cout << " appends to path " << symbol.name << " : "; } if (new_value != "") { if (!find_path_entry (temp, new_value)) { if (temp != "") temp += path_separator; temp += new_value; } } break; case CommandPathPrepend : if (show_it) { cout << " prepends to path " << symbol.name << " : "; } if (new_value != "") { if (!find_path_entry (temp, new_value)) { previous_temp = temp; temp = new_value; if (previous_temp != "") temp += path_separator; temp += previous_temp; } } break; case CommandPathRemove : if (show_it) { cout << " removes from path " << symbol.name << " : "; } if (new_value != "") { static 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); temp.replace_all ("::", ":"); temp.replace_all (";;", ";"); } break; } if (show_it) { 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->name << "'"; } cout << endl; } } return (temp); } //------------------------------------------------------------- const cmt_string& PathBuilder::clean (const Symbol& symbol, const cmt_string& /*tag_name*/) { int show_it = 0; static cmt_string previous_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 != "") { static 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; } } //cerr << "#####2 temp=" << temp << endl; return (temp); } //------------------------------------------------------------- const cmt_string& MacroBuilder::build (const Symbol& symbol, const cmt_string& tag_name) { static cmt_string previous_temp; static const cmt_string empty; int show_it = 0; if (Cmt::get_action () == action_show_macro) { if (symbol.name == Cmt::get_current_target ()) { show_it = 1; } } temp = ""; int i; for (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; 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) { cout << "# Package "; if (value_list.use != 0) { cout << value_list.use->package << " " << value_list.use->version; } cout << " prepends to macro " << symbol.name << " : "; } temp += value.text; if (show_it) { 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->name << "'"; } cout << endl; } } previous_temp = temp; temp = ""; for (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; if (value_list.command_type != CommandMacro) continue; const int selected = value_list.select_first (tag_name); if (selected >= 0) { SymbolValue& value = value_list.values[selected]; if (show_it) { cout << "# Package "; if (value_list.use != 0) { cout << value_list.use->package << " " << value_list.use->version; } cout << " defines macro " << symbol.name << " as "; } if (!value_list.is_reflexive || !symbol.value_is_reflexive (value.text)) { temp = value.text; } if (show_it) { 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->name << "'"; } cout << endl; } } } 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.discarded) continue; 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) { cout << "# Package "; if (value_list.use != 0) { cout << value_list.use->package << " " << value_list.use->version; } cout << " appends to macro " << symbol.name << " : "; } temp += value.text; if (show_it) { 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->name << "'"; } cout << endl; } } for (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; if ((value_list.command_type != CommandMacroRemove) && (value_list.command_type != CommandMacroRemoveAll)) continue; const int selected = value_list.select_first (tag_name); if (selected < 0) continue; SymbolValue& value = value_list.values[selected]; if (show_it) { cout << "# Package "; if (value_list.use != 0) { cout << value_list.use->package << " " << value_list.use->version; } } switch (value_list.command_type) { case CommandMacroRemove : if (show_it) { cout << " remove from macro " << symbol.name << " : "; } temp.replace (value.text, empty); break; case CommandMacroRemoveAll : if (show_it) { cout << " remove all from macro " << symbol.name << " : "; } temp.replace_all (value.text, empty); break; } if (show_it) { 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->name << "'"; } cout << endl; } } return (temp); } //------------------------------------------------------------- const cmt_string& ScriptBuilder::build (const Symbol& symbol, const cmt_string& tag_name) { 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); } //------------------------------------------------------------- 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->selected) continue; } else { if (tag != the_tag) continue; selected = value_number; } // // Only the first value at a given priority is // selected (which implies the '>' test instead // of '>=') // if (tag->priority > priority) { priority = tag->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->selected) { // // The last value at a given priority is // selected (which implies the '>=' test instead // of '>') // if (tag->priority >= priority) { priority = tag->priority; selected = value_number; } } } return (selected); }