| #include "get_cmd.h" | 
 |  | 
 | USING_YOSYS_NAMESPACE | 
 |  | 
 | void GetCmd::help() | 
 | { | 
 |     //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| | 
 |     log("\n"); | 
 |     log("   get_%ss [-quiet] [-filter filter_expression] " | 
 |         "<%s_selection> \n", | 
 |         TypeName().c_str(), TypeName().c_str()); | 
 |     log("\n"); | 
 |     log("Get matching %ss\n", TypeName().c_str()); | 
 |     log("\n"); | 
 |     log("Print the output to stdout too. This is useful when all Yosys " | 
 |         "is " | 
 |         "executed.\n"); | 
 |     log("\n"); | 
 |     log("    -filter\n"); | 
 |     log("        Name and value of attribute to be taken into " | 
 |         "account.\n"); | 
 |     log("        e.g. -filter { attr == \"true\" }\n"); | 
 |     log("\n"); | 
 |     log("    -quiet\n"); | 
 |     log("        Don't print the result of the execution to stdout.\n"); | 
 |     log("\n"); | 
 |     log("    <selection_pattern>\n"); | 
 |     log("        Selection of %s names. Default are all %ss in the " | 
 |         "design.\n", | 
 |         TypeName().c_str(), TypeName().c_str()); | 
 |     log("\n"); | 
 | } | 
 |  | 
 | void GetCmd::ExecuteSelection(RTLIL::Design *design, const CommandArgs &args) | 
 | { | 
 |     std::vector<std::string> selection_args; | 
 |     // Add name of top module to selection string | 
 |     std::transform(args.selection_objects.begin(), args.selection_objects.end(), std::back_inserter(selection_args), | 
 |                    [&](const std::string &obj) { return RTLIL::unescape_id(design->top_module()->name) + "/" + SelectionType() + ":" + obj; }); | 
 |     extra_args(selection_args, 0, design); | 
 |     if (design->selected_modules().empty()) { | 
 |         if (!args.is_quiet) { | 
 |             log_warning("Specified %s not found in design\n", TypeName().c_str()); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | void GetCmd::PackToTcl(const SelectionObjects &objects) | 
 | { | 
 |     Tcl_Obj *tcl_result; | 
 |     if (objects.size() == 1) { | 
 |         tcl_result = Tcl_NewStringObj(objects.at(0).c_str(), -1); | 
 |     } else { | 
 |         tcl_result = Tcl_NewListObj(0, NULL); | 
 |         for (const auto &object : objects) { | 
 |             Tcl_Obj *value_obj = Tcl_NewStringObj(object.c_str(), -1); | 
 |             Tcl_ListObjAppendElement(yosys_get_tcl_interp(), tcl_result, value_obj); | 
 |         } | 
 |     } | 
 |     Tcl_SetObjResult(yosys_get_tcl_interp(), tcl_result); | 
 | } | 
 |  | 
 | GetCmd::CommandArgs GetCmd::ParseCommand(const std::vector<std::string> &args) | 
 | { | 
 |     CommandArgs parsed_args{.filters = Filters(), .is_quiet = false, .selection_objects = SelectionObjects()}; | 
 |     size_t argidx(0); | 
 |     for (argidx = 1; argidx < args.size(); argidx++) { | 
 |         std::string arg = args[argidx]; | 
 |         if (arg == "-quiet") { | 
 |             parsed_args.is_quiet = true; | 
 |             continue; | 
 |         } | 
 |  | 
 |         if (arg == "-filter" and argidx + 1 < args.size()) { | 
 |             std::string filter_arg = args[++argidx]; | 
 |  | 
 |             // Remove spaces | 
 |             filter_arg.erase(std::remove_if(filter_arg.begin(), filter_arg.end(), isspace), filter_arg.end()); | 
 |  | 
 |             // Parse filters | 
 |             // TODO Add support for multiple condition expression | 
 |             // Currently only a single == is supported | 
 |             std::regex filter_attr_regex("(\\w+\\s?==\\s?\\w+)([(||)(&&)]*)"); | 
 |             std::regex_token_iterator<std::string::iterator> regex_end; | 
 |             std::regex_token_iterator<std::string::iterator> matches(filter_arg.begin(), filter_arg.end(), filter_attr_regex, 1); | 
 |             if (matches == regex_end) { | 
 |                 log_warning("Currently -filter switch supports only a single " | 
 |                             "'equal(==)' condition expression, the rest will be " | 
 |                             "ignored\n"); | 
 |             } | 
 |  | 
 |             while (matches != regex_end) { | 
 |                 std::string filter(*matches++); | 
 |                 auto separator = filter.find("=="); | 
 |                 if (separator == std::string::npos) { | 
 |                     log_cmd_error("Incorrect filter expression: %s\n", args[argidx].c_str()); | 
 |                 } | 
 |                 parsed_args.filters.emplace_back(filter.substr(0, separator), filter.substr(separator + 2)); | 
 |             } | 
 |             if (parsed_args.filters.size() > 1) { | 
 |                 log_warning("Currently -filter switch supports only a single " | 
 |                             "'equal(==)' condition expression, the rest will be " | 
 |                             "ignored\n"); | 
 |             } | 
 |             continue; | 
 |         } | 
 |  | 
 |         if (arg.size() > 0 and arg[0] == '-') { | 
 |             log_cmd_error("Unknown option %s.\n", arg.c_str()); | 
 |         } | 
 |  | 
 |         break; | 
 |     } | 
 |     std::copy(args.begin() + argidx, args.end(), std::back_inserter(parsed_args.selection_objects)); | 
 |     return parsed_args; | 
 | } | 
 |  | 
 | void GetCmd::execute(std::vector<std::string> args, RTLIL::Design *design) | 
 | { | 
 |     if (design->top_module() == nullptr) { | 
 |         log_cmd_error("No top module detected\n"); | 
 |     } | 
 |  | 
 |     CommandArgs parsed_args(ParseCommand(args)); | 
 |     ExecuteSelection(design, parsed_args); | 
 |     PackToTcl(ExtractSelection(design, parsed_args)); | 
 | } |