15ffd83dbSDimitry Andric //===-- OptionGroupPythonClassWithDict.cpp --------------------------------===//
29dba64beSDimitry Andric //
39dba64beSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
49dba64beSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
59dba64beSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69dba64beSDimitry Andric //
79dba64beSDimitry Andric //===----------------------------------------------------------------------===//
89dba64beSDimitry Andric
99dba64beSDimitry Andric #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
109dba64beSDimitry Andric
119dba64beSDimitry Andric #include "lldb/Host/OptionParser.h"
129dba64beSDimitry Andric
139dba64beSDimitry Andric using namespace lldb;
149dba64beSDimitry Andric using namespace lldb_private;
159dba64beSDimitry Andric
OptionGroupPythonClassWithDict(const char * class_use,bool is_class,int class_option,int key_option,int value_option,uint16_t required_options)16fe6060f1SDimitry Andric OptionGroupPythonClassWithDict::OptionGroupPythonClassWithDict(
17fe6060f1SDimitry Andric const char *class_use, bool is_class, int class_option, int key_option,
18fe6060f1SDimitry Andric int value_option, uint16_t required_options)
19fe6060f1SDimitry Andric : m_is_class(is_class), m_required_options(required_options) {
20480093f4SDimitry Andric m_key_usage_text.assign("The key for a key/value pair passed to the "
21480093f4SDimitry Andric "implementation of a ");
229dba64beSDimitry Andric m_key_usage_text.append(class_use);
239dba64beSDimitry Andric m_key_usage_text.append(". Pairs can be specified more than once.");
249dba64beSDimitry Andric
25480093f4SDimitry Andric m_value_usage_text.assign("The value for the previous key in the pair passed "
26480093f4SDimitry Andric "to the implementation of a ");
279dba64beSDimitry Andric m_value_usage_text.append(class_use);
289dba64beSDimitry Andric m_value_usage_text.append(". Pairs can be specified more than once.");
299dba64beSDimitry Andric
30480093f4SDimitry Andric m_class_usage_text.assign("The name of the ");
31480093f4SDimitry Andric m_class_usage_text.append(m_is_class ? "class" : "function");
32480093f4SDimitry Andric m_class_usage_text.append(" that will manage a ");
339dba64beSDimitry Andric m_class_usage_text.append(class_use);
349dba64beSDimitry Andric m_class_usage_text.append(".");
359dba64beSDimitry Andric
369dba64beSDimitry Andric m_option_definition[0].usage_mask = LLDB_OPT_SET_1;
37fe6060f1SDimitry Andric m_option_definition[0].required = m_required_options.Test(eScriptClass);
38480093f4SDimitry Andric m_option_definition[0].long_option = "script-class";
399dba64beSDimitry Andric m_option_definition[0].short_option = class_option;
409dba64beSDimitry Andric m_option_definition[0].validator = nullptr;
419dba64beSDimitry Andric m_option_definition[0].option_has_arg = OptionParser::eRequiredArgument;
429dba64beSDimitry Andric m_option_definition[0].enum_values = {};
439dba64beSDimitry Andric m_option_definition[0].completion_type = 0;
449dba64beSDimitry Andric m_option_definition[0].argument_type = eArgTypePythonClass;
459dba64beSDimitry Andric m_option_definition[0].usage_text = m_class_usage_text.data();
469dba64beSDimitry Andric
47480093f4SDimitry Andric m_option_definition[1].usage_mask = LLDB_OPT_SET_2;
48fe6060f1SDimitry Andric m_option_definition[1].required = m_required_options.Test(eDictKey);
49480093f4SDimitry Andric m_option_definition[1].long_option = "structured-data-key";
509dba64beSDimitry Andric m_option_definition[1].short_option = key_option;
519dba64beSDimitry Andric m_option_definition[1].validator = nullptr;
529dba64beSDimitry Andric m_option_definition[1].option_has_arg = OptionParser::eRequiredArgument;
539dba64beSDimitry Andric m_option_definition[1].enum_values = {};
549dba64beSDimitry Andric m_option_definition[1].completion_type = 0;
559dba64beSDimitry Andric m_option_definition[1].argument_type = eArgTypeNone;
569dba64beSDimitry Andric m_option_definition[1].usage_text = m_key_usage_text.data();
579dba64beSDimitry Andric
58480093f4SDimitry Andric m_option_definition[2].usage_mask = LLDB_OPT_SET_2;
59fe6060f1SDimitry Andric m_option_definition[2].required = m_required_options.Test(eDictValue);
60480093f4SDimitry Andric m_option_definition[2].long_option = "structured-data-value";
619dba64beSDimitry Andric m_option_definition[2].short_option = value_option;
629dba64beSDimitry Andric m_option_definition[2].validator = nullptr;
639dba64beSDimitry Andric m_option_definition[2].option_has_arg = OptionParser::eRequiredArgument;
649dba64beSDimitry Andric m_option_definition[2].enum_values = {};
659dba64beSDimitry Andric m_option_definition[2].completion_type = 0;
669dba64beSDimitry Andric m_option_definition[2].argument_type = eArgTypeNone;
679dba64beSDimitry Andric m_option_definition[2].usage_text = m_value_usage_text.data();
68480093f4SDimitry Andric
69480093f4SDimitry Andric m_option_definition[3].usage_mask = LLDB_OPT_SET_3;
70fe6060f1SDimitry Andric m_option_definition[3].required = m_required_options.Test(ePythonFunction);
71480093f4SDimitry Andric m_option_definition[3].long_option = "python-function";
72480093f4SDimitry Andric m_option_definition[3].short_option = class_option;
73480093f4SDimitry Andric m_option_definition[3].validator = nullptr;
74480093f4SDimitry Andric m_option_definition[3].option_has_arg = OptionParser::eRequiredArgument;
75480093f4SDimitry Andric m_option_definition[3].enum_values = {};
76480093f4SDimitry Andric m_option_definition[3].completion_type = 0;
77480093f4SDimitry Andric m_option_definition[3].argument_type = eArgTypePythonFunction;
78480093f4SDimitry Andric m_option_definition[3].usage_text = m_class_usage_text.data();
799dba64beSDimitry Andric }
809dba64beSDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)819dba64beSDimitry Andric Status OptionGroupPythonClassWithDict::SetOptionValue(
829dba64beSDimitry Andric uint32_t option_idx,
839dba64beSDimitry Andric llvm::StringRef option_arg,
849dba64beSDimitry Andric ExecutionContext *execution_context) {
859dba64beSDimitry Andric Status error;
869dba64beSDimitry Andric switch (option_idx) {
87480093f4SDimitry Andric case 0:
88480093f4SDimitry Andric case 3: {
895ffd83dbSDimitry Andric m_name.assign(std::string(option_arg));
909dba64beSDimitry Andric } break;
919dba64beSDimitry Andric case 1: {
92480093f4SDimitry Andric if (!m_dict_sp)
93480093f4SDimitry Andric m_dict_sp = std::make_shared<StructuredData::Dictionary>();
949dba64beSDimitry Andric if (m_current_key.empty())
955ffd83dbSDimitry Andric m_current_key.assign(std::string(option_arg));
969dba64beSDimitry Andric else
979dba64beSDimitry Andric error.SetErrorStringWithFormat("Key: \"%s\" missing value.",
989dba64beSDimitry Andric m_current_key.c_str());
999dba64beSDimitry Andric
1009dba64beSDimitry Andric } break;
1019dba64beSDimitry Andric case 2: {
102480093f4SDimitry Andric if (!m_dict_sp)
103480093f4SDimitry Andric m_dict_sp = std::make_shared<StructuredData::Dictionary>();
1049dba64beSDimitry Andric if (!m_current_key.empty()) {
105*06c3fb27SDimitry Andric if (!option_arg.empty()) {
106*06c3fb27SDimitry Andric double d = 0;
107*06c3fb27SDimitry Andric std::string opt = option_arg.lower();
108*06c3fb27SDimitry Andric
109*06c3fb27SDimitry Andric if (llvm::to_integer(option_arg, d)) {
110*06c3fb27SDimitry Andric if (opt[0] == '-')
111*06c3fb27SDimitry Andric m_dict_sp->AddIntegerItem(m_current_key, static_cast<int64_t>(d));
112*06c3fb27SDimitry Andric else
113*06c3fb27SDimitry Andric m_dict_sp->AddIntegerItem(m_current_key,
114*06c3fb27SDimitry Andric static_cast<uint64_t>(d));
115*06c3fb27SDimitry Andric } else if (llvm::to_float(option_arg, d)) {
116*06c3fb27SDimitry Andric m_dict_sp->AddFloatItem(m_current_key, d);
117*06c3fb27SDimitry Andric } else if (opt == "true" || opt == "false") {
118*06c3fb27SDimitry Andric m_dict_sp->AddBooleanItem(m_current_key, opt == "true");
119*06c3fb27SDimitry Andric } else {
1209dba64beSDimitry Andric m_dict_sp->AddStringItem(m_current_key, option_arg);
121*06c3fb27SDimitry Andric }
122*06c3fb27SDimitry Andric }
123*06c3fb27SDimitry Andric
1249dba64beSDimitry Andric m_current_key.clear();
1259dba64beSDimitry Andric }
1269dba64beSDimitry Andric else
1279dba64beSDimitry Andric error.SetErrorStringWithFormat("Value: \"%s\" missing matching key.",
1289dba64beSDimitry Andric option_arg.str().c_str());
1299dba64beSDimitry Andric } break;
1309dba64beSDimitry Andric default:
1319dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
1329dba64beSDimitry Andric }
1339dba64beSDimitry Andric return error;
1349dba64beSDimitry Andric }
1359dba64beSDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)1369dba64beSDimitry Andric void OptionGroupPythonClassWithDict::OptionParsingStarting(
1379dba64beSDimitry Andric ExecutionContext *execution_context) {
1389dba64beSDimitry Andric m_current_key.erase();
139480093f4SDimitry Andric // Leave the dictionary shared pointer unset. That way you can tell that
140480093f4SDimitry Andric // the user didn't pass any -k -v pairs. We want to be able to warn if these
141480093f4SDimitry Andric // were passed when the function they passed won't use them.
142480093f4SDimitry Andric m_dict_sp.reset();
143480093f4SDimitry Andric m_name.clear();
1449dba64beSDimitry Andric }
1459dba64beSDimitry Andric
OptionParsingFinished(ExecutionContext * execution_context)1469dba64beSDimitry Andric Status OptionGroupPythonClassWithDict::OptionParsingFinished(
1479dba64beSDimitry Andric ExecutionContext *execution_context) {
1489dba64beSDimitry Andric Status error;
1499dba64beSDimitry Andric // If we get here and there's contents in the m_current_key, somebody must
1509dba64beSDimitry Andric // have provided a key but no value.
1519dba64beSDimitry Andric if (!m_current_key.empty())
1529dba64beSDimitry Andric error.SetErrorStringWithFormat("Key: \"%s\" missing value.",
1539dba64beSDimitry Andric m_current_key.c_str());
1549dba64beSDimitry Andric return error;
1559dba64beSDimitry Andric }
1569dba64beSDimitry Andric
157