1 //===-- OptionGroupPythonClassWithDict.cpp --------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" 10 11 #include "lldb/Host/OptionParser.h" 12 13 using namespace lldb; 14 using namespace lldb_private; 15 16 OptionGroupPythonClassWithDict::OptionGroupPythonClassWithDict( 17 const char *class_use, bool is_class, int class_option, int key_option, 18 int value_option, uint16_t required_options) 19 : m_is_class(is_class), m_required_options(required_options) { 20 m_key_usage_text.assign("The key for a key/value pair passed to the " 21 "implementation of a "); 22 m_key_usage_text.append(class_use); 23 m_key_usage_text.append(". Pairs can be specified more than once."); 24 25 m_value_usage_text.assign("The value for the previous key in the pair passed " 26 "to the implementation of a "); 27 m_value_usage_text.append(class_use); 28 m_value_usage_text.append(". Pairs can be specified more than once."); 29 30 m_class_usage_text.assign("The name of the "); 31 m_class_usage_text.append(m_is_class ? "class" : "function"); 32 m_class_usage_text.append(" that will manage a "); 33 m_class_usage_text.append(class_use); 34 m_class_usage_text.append("."); 35 36 m_option_definition[0].usage_mask = LLDB_OPT_SET_1; 37 m_option_definition[0].required = m_required_options.Test(eScriptClass); 38 m_option_definition[0].long_option = "script-class"; 39 m_option_definition[0].short_option = class_option; 40 m_option_definition[0].validator = nullptr; 41 m_option_definition[0].option_has_arg = OptionParser::eRequiredArgument; 42 m_option_definition[0].enum_values = {}; 43 m_option_definition[0].completion_type = 0; 44 m_option_definition[0].argument_type = eArgTypePythonClass; 45 m_option_definition[0].usage_text = m_class_usage_text.data(); 46 47 m_option_definition[1].usage_mask = LLDB_OPT_SET_2; 48 m_option_definition[1].required = m_required_options.Test(eDictKey); 49 m_option_definition[1].long_option = "structured-data-key"; 50 m_option_definition[1].short_option = key_option; 51 m_option_definition[1].validator = nullptr; 52 m_option_definition[1].option_has_arg = OptionParser::eRequiredArgument; 53 m_option_definition[1].enum_values = {}; 54 m_option_definition[1].completion_type = 0; 55 m_option_definition[1].argument_type = eArgTypeNone; 56 m_option_definition[1].usage_text = m_key_usage_text.data(); 57 58 m_option_definition[2].usage_mask = LLDB_OPT_SET_2; 59 m_option_definition[2].required = m_required_options.Test(eDictValue); 60 m_option_definition[2].long_option = "structured-data-value"; 61 m_option_definition[2].short_option = value_option; 62 m_option_definition[2].validator = nullptr; 63 m_option_definition[2].option_has_arg = OptionParser::eRequiredArgument; 64 m_option_definition[2].enum_values = {}; 65 m_option_definition[2].completion_type = 0; 66 m_option_definition[2].argument_type = eArgTypeNone; 67 m_option_definition[2].usage_text = m_value_usage_text.data(); 68 69 m_option_definition[3].usage_mask = LLDB_OPT_SET_3; 70 m_option_definition[3].required = m_required_options.Test(ePythonFunction); 71 m_option_definition[3].long_option = "python-function"; 72 m_option_definition[3].short_option = class_option; 73 m_option_definition[3].validator = nullptr; 74 m_option_definition[3].option_has_arg = OptionParser::eRequiredArgument; 75 m_option_definition[3].enum_values = {}; 76 m_option_definition[3].completion_type = 0; 77 m_option_definition[3].argument_type = eArgTypePythonFunction; 78 m_option_definition[3].usage_text = m_class_usage_text.data(); 79 } 80 81 Status OptionGroupPythonClassWithDict::SetOptionValue( 82 uint32_t option_idx, 83 llvm::StringRef option_arg, 84 ExecutionContext *execution_context) { 85 Status error; 86 switch (option_idx) { 87 case 0: 88 case 3: { 89 m_name.assign(std::string(option_arg)); 90 } break; 91 case 1: { 92 if (!m_dict_sp) 93 m_dict_sp = std::make_shared<StructuredData::Dictionary>(); 94 if (m_current_key.empty()) 95 m_current_key.assign(std::string(option_arg)); 96 else 97 error.SetErrorStringWithFormat("Key: \"%s\" missing value.", 98 m_current_key.c_str()); 99 100 } break; 101 case 2: { 102 if (!m_dict_sp) 103 m_dict_sp = std::make_shared<StructuredData::Dictionary>(); 104 if (!m_current_key.empty()) { 105 if (!option_arg.empty()) { 106 double d = 0; 107 std::string opt = option_arg.lower(); 108 109 if (llvm::to_integer(option_arg, d)) { 110 if (opt[0] == '-') 111 m_dict_sp->AddIntegerItem(m_current_key, static_cast<int64_t>(d)); 112 else 113 m_dict_sp->AddIntegerItem(m_current_key, 114 static_cast<uint64_t>(d)); 115 } else if (llvm::to_float(option_arg, d)) { 116 m_dict_sp->AddFloatItem(m_current_key, d); 117 } else if (opt == "true" || opt == "false") { 118 m_dict_sp->AddBooleanItem(m_current_key, opt == "true"); 119 } else { 120 m_dict_sp->AddStringItem(m_current_key, option_arg); 121 } 122 } 123 124 m_current_key.clear(); 125 } 126 else 127 error.SetErrorStringWithFormat("Value: \"%s\" missing matching key.", 128 option_arg.str().c_str()); 129 } break; 130 default: 131 llvm_unreachable("Unimplemented option"); 132 } 133 return error; 134 } 135 136 void OptionGroupPythonClassWithDict::OptionParsingStarting( 137 ExecutionContext *execution_context) { 138 m_current_key.erase(); 139 // Leave the dictionary shared pointer unset. That way you can tell that 140 // the user didn't pass any -k -v pairs. We want to be able to warn if these 141 // were passed when the function they passed won't use them. 142 m_dict_sp.reset(); 143 m_name.clear(); 144 } 145 146 Status OptionGroupPythonClassWithDict::OptionParsingFinished( 147 ExecutionContext *execution_context) { 148 Status error; 149 // If we get here and there's contents in the m_current_key, somebody must 150 // have provided a key but no value. 151 if (!m_current_key.empty()) 152 error.SetErrorStringWithFormat("Key: \"%s\" missing value.", 153 m_current_key.c_str()); 154 return error; 155 } 156 157