From 84ad71e66e8c70c10126eab9359731c7e40ffc35 Mon Sep 17 00:00:00 2001 From: Kenneth Griesser Date: Mon, 26 Jan 2026 21:50:14 -0700 Subject: [PATCH] provided user prompting to select a variable name when more than one match is found. This can be disabled using "confirm false" in the console which will revert to the prototype functionality of simply selecting the first match. This should be removed by ensuring the object map has unique variable names ( and not use std::multimap )... presumably --- src/sst/core/impl/interactive/simpleDebug.cc | 13 ++++--- src/sst/core/impl/interactive/simpleDebug.h | 2 +- src/sst/core/serialization/objectMap.cc | 4 +- src/sst/core/serialization/objectMap.h | 41 +++++++++++++++++++- 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/sst/core/impl/interactive/simpleDebug.cc b/src/sst/core/impl/interactive/simpleDebug.cc index 98727f57d..fb8277b0e 100644 --- a/src/sst/core/impl/interactive/simpleDebug.cc +++ b/src/sst/core/impl/interactive/simpleDebug.cc @@ -31,13 +31,14 @@ namespace SST::IMPL::Interactive { // Static Initialization +//TODO kg is there a naming convention for static vars? bool SimpleDebugger::autoCompleteEnable = true; std::ofstream SimpleDebugger::loggingFile; std::ifstream SimpleDebugger::replayFile; std::string SimpleDebugger::loggingFilePath = "sst-console.out"; std::string SimpleDebugger::replayFilePath = "sst-console.in"; bool SimpleDebugger::enLogging = false; -bool SimpleDebugger::confirm = true; +bool SimpleDebugger::confirm_ = true; SimpleDebugger::SimpleDebugger(Params& params) : InteractiveConsole() { @@ -736,7 +737,7 @@ SimpleDebugger::cmd_cd(std::vector& tokens) } bool loop_detected = false; - SST::Core::Serialization::ObjectMap* new_obj = obj_->selectVariable(selection, loop_detected); + SST::Core::Serialization::ObjectMap* new_obj = obj_->selectVariable(selection, loop_detected, confirm_); if ( !new_obj || (new_obj == obj_) ) { printf("Unknown object in cd command: %s\n", selection.c_str()); return false; @@ -1607,15 +1608,15 @@ SimpleDebugger::cmd_setConfirm(std::vector& tokens) } if ( (tokens[1] == "true") || (tokens[1] == "t") || (tokens[1] == "T") || (tokens[1] == "1") ) { - confirm = true; + confirm_ = true; return true; } else if ( (tokens[1] == "false") || (tokens[1] == "f") || (tokens[1] == "F") || (tokens[1] == "0") ) { - confirm = false; + confirm_ = false; return true; } - std::cout << "Invalid argument for confirm: must be true or false" << tokens[1] << std::endl; + std::cout << "Invalid argument for confirm: must be true or false. <" << tokens[1] << ">" << std::endl; return false; } @@ -1623,7 +1624,7 @@ bool SimpleDebugger::clear_watchlist() { - if ( confirm ) { + if ( confirm_ ) { std::string line; std::cout << "Do you want to delete all watchpoints? [yes, no]\n"; std::getline(std::cin, line); diff --git a/src/sst/core/impl/interactive/simpleDebug.h b/src/sst/core/impl/interactive/simpleDebug.h index 1f1e56d83..620ebfc78 100644 --- a/src/sst/core/impl/interactive/simpleDebug.h +++ b/src/sst/core/impl/interactive/simpleDebug.h @@ -297,7 +297,7 @@ class SimpleDebugger : public SST::InteractiveConsole // Keep track of all the WatchPoints std::vector> watch_points_; bool clear_watchlist(); - static bool confirm; // skk = true; // Ask for confirmation to clear watchlist + static bool confirm_; // skk = true; // Ask for confirmation to clear watchlist std::vector tokenize(std::vector& tokens, const std::string& input); diff --git a/src/sst/core/serialization/objectMap.cc b/src/sst/core/serialization/objectMap.cc index 2ada2008b..be0687da6 100644 --- a/src/sst/core/serialization/objectMap.cc +++ b/src/sst/core/serialization/objectMap.cc @@ -47,12 +47,12 @@ ObjectMap::selectParent() } ObjectMap* -ObjectMap::selectVariable(std::string name, bool& loop_detected) +ObjectMap::selectVariable(std::string name, bool& loop_detected, bool confirm) { // kg maybe there is a way we can go through this to detect problems // before changing objmap state to avoid memory corruption bugs. loop_detected = false; - ObjectMap* var = findVariable(name); + ObjectMap* var = findVariable(name, confirm); // TODO Would prefer this be a simple nullptr to avoid confusion (bugs) // If we get nullptr back, then it didn't exist. Just return this diff --git a/src/sst/core/serialization/objectMap.h b/src/sst/core/serialization/objectMap.h index bae7915d4..0746e4cd9 100644 --- a/src/sst/core/serialization/objectMap.h +++ b/src/sst/core/serialization/objectMap.h @@ -382,11 +382,12 @@ class ObjectMap TODO: prefer this return nullptr as bugs have occurred with incorrect use @param name Name of variable to select + @param confirm Prompt user to resolve duplicate match of name. Select first found if false. @return ObjectMap for specified variable, if it exists, this otherwise */ - ObjectMap* selectVariable(std::string name, bool& loop_detected); + ObjectMap* selectVariable(std::string name, bool& loop_detected, bool confirm = false); /** Adds a variable to this ObjectMap. NOTE: calls to this @@ -544,16 +545,52 @@ class ObjectMap Find a variable in this object map @param name Name of variable to find + @param confirm Prompt user to resolve duplicate match of name. Select first found if false. @return ObjectMap representing the requested variable if it is found, nullptr otherwise */ - ObjectMap* findVariable(const std::string& name) const + ObjectMap* findVariable(const std::string& name, bool confirm = false) const { +// TODO move body into objectMap.cc +#if 1 + // Would prefer we can uniquify the variable list whilst mapping and not use a multimap. + // Assuming multimap is sorted. + auto& variables = getVariables(); + auto range = variables.equal_range(name); + auto count = std::distance(range.first, range.second); + if ( count == 0 ) return nullptr; + if ( count == 1 || (!confirm) ) return range.first->second; + // more than 1 found and confirm is true + std::vector selections = {}; + for ( auto [it, end] = variables.equal_range(name); it != end; ++it ) + selections.push_back(it->second); + + std::cout << "[Found multiple entries for <" << name << ">]" << std::endl; + int remaining = 3; + int n; + std::string user_input; + while ( remaining-- > 0 ) { + for ( size_t i = 0; i < selections.size(); i++ ) + std::cout << i << ": " << selections[i]->getName() << " " << selections[i]->getType() << std::endl; + std::cout << "-1: None" << std::endl; + std::cout << "[?] "; + std::getline(std::cin, user_input); + std::stringstream ss(user_input); + if ( (ss >> n) && ss.eof() ) { + if ( n < 0 ) return nullptr; + if ( n < (int)selections.size() ) return selections[n]; + } + std::cout << "Invalid entry" << std::endl; + } + std::cout << "Too many attempts\n" << std::endl; + return nullptr; +#else auto& variables = getVariables(); for ( auto [it, end] = variables.equal_range(name); it != end; ++it ) return it->second; // For now, we return only the first match if multiple matches return nullptr; +#endif } /**