diff --git a/icpconfigApp/src/icpconfig.cpp b/icpconfigApp/src/icpconfig.cpp index c11e46a..fa986ff 100644 --- a/icpconfigApp/src/icpconfig.cpp +++ b/icpconfigApp/src/icpconfig.cpp @@ -108,6 +108,7 @@ struct PVSetItem }; static std::map pvset_map; +static bool defaultsSet = false; struct MacroItem { @@ -565,6 +566,34 @@ epicsShareExtern void icpconfigGetMacros(const std::string& iocName, const std:: } } +static int loadDefaultMacros(MAC_HANDLE *h, const std::string& config_name){ + pugi::xml_document confXMLDoc; + std::string configXMLDir = std::string(macEnvExpand("$(IOC)")) +"/config.xml"; + std::string confXML = std::string(macEnvExpand("$(TOP)")) +"/iocBoot/" + configXMLDir; + pugi::xml_parse_result result = confXMLDoc.load_file(confXML.c_str()); + if (!result) + { + std::cerr << "icpconfigLoad: Error in \"" << confXML << "\" " << result.description() << " at offset " << result.offset << std::endl; + return -1; + } + pugi::xpath_node_set default_macros = confXMLDoc.select_nodes("/ioc_config/config_part/macros/macro"); + default_macros.sort(); // forward document order + if (!quiet) + { + printf("icpconfigLoad: Checking %d macro(s) for default values in %s\n", (int)default_macros.size(), confXML.c_str()); + } + for (pugi::xpath_node_set::const_iterator it = default_macros.begin(); it != default_macros.end(); ++it) + { + if (it->node().attribute("hasDefault").as_bool()) { + std::string name = it->node().attribute("name").value(); + std::string value = it->node().attribute("defaultValue").value(); + setValue(h, name.c_str(), value.c_str(), configXMLDir.c_str()); + } + } + defaultsSet = true; + return 0; +} + static int loadIOCs(MAC_HANDLE *h, const std::string& config_name, const std::string& config_root, const std::string& ioc_name, const std::string& ioc_group, bool warn_if_not_found, bool filter, bool verbose) { pugi::xml_document doc; @@ -575,24 +604,19 @@ static int loadIOCs(MAC_HANDLE *h, const std::string& config_name, const std::st std::cerr << "icpconfigLoad: Error in \"" << xfile << "\" " << result.description() << " at offset " << result.offset << std::endl; return -1; } + pugi::xpath_variable_set vars; vars.add("iocname", pugi::xpath_type_string); vars.add("iocgroup", pugi::xpath_type_string); vars.set("iocname",ioc_name.c_str()); vars.set("iocgroup",ioc_group.c_str()); - // default macros - if (!quiet) - { - printf("icpconfigLoad: Loading default macros for \"%s\"\n", config_name.c_str()); - } - pugi::xpath_node_set default_macros = doc.select_nodes("/iocs/defaults/macros/macro"); - default_macros.sort(); // forward document order - for (pugi::xpath_node_set::const_iterator it = default_macros.begin(); it != default_macros.end(); ++it) - { - std::string name = it->node().attribute("name").value(); - std::string value = it->node().attribute("value").value(); - setValue(h, name.c_str(), value.c_str(), config_name.c_str()); + // default macros but only if they aren't already loaded, this prevents overwrites + if(!defaultsSet){ + if (loadDefaultMacros(h, config_name)) { + return -1; + } } + // ioc sim level if (!quiet) { @@ -645,7 +669,7 @@ static int loadIOCs(MAC_HANDLE *h, const std::string& config_name, const std::st { std::string name = it->node().attribute("name").value(); std::string value = it->node().attribute("value").value(); - setValue(h, name.c_str(), value.c_str(), config_name.c_str()); + setValue(h, name.c_str(), value.c_str(), config_name.c_str()); } // ioc pvs if (!quiet)