OptionArgParser.cpp revision 336985
1//===-- OptionArgParser.cpp -------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "lldb/Interpreter/OptionArgParser.h" 11#include "lldb/DataFormatters/FormatManager.h" 12#include "lldb/Target/Target.h" 13#include "lldb/Utility/Status.h" 14#include "lldb/Utility/StreamString.h" 15 16using namespace lldb_private; 17using namespace lldb; 18 19bool OptionArgParser::ToBoolean(llvm::StringRef ref, bool fail_value, 20 bool *success_ptr) { 21 if (success_ptr) 22 *success_ptr = true; 23 ref = ref.trim(); 24 if (ref.equals_lower("false") || ref.equals_lower("off") || 25 ref.equals_lower("no") || ref.equals_lower("0")) { 26 return false; 27 } else if (ref.equals_lower("true") || ref.equals_lower("on") || 28 ref.equals_lower("yes") || ref.equals_lower("1")) { 29 return true; 30 } 31 if (success_ptr) 32 *success_ptr = false; 33 return fail_value; 34} 35 36char OptionArgParser::ToChar(llvm::StringRef s, char fail_value, 37 bool *success_ptr) { 38 if (success_ptr) 39 *success_ptr = false; 40 if (s.size() != 1) 41 return fail_value; 42 43 if (success_ptr) 44 *success_ptr = true; 45 return s[0]; 46} 47 48int64_t OptionArgParser::ToOptionEnum(llvm::StringRef s, 49 OptionEnumValueElement *enum_values, 50 int32_t fail_value, Status &error) { 51 error.Clear(); 52 if (!enum_values) { 53 error.SetErrorString("invalid enumeration argument"); 54 return fail_value; 55 } 56 57 if (s.empty()) { 58 error.SetErrorString("empty enumeration string"); 59 return fail_value; 60 } 61 62 for (int i = 0; enum_values[i].string_value != nullptr; i++) { 63 llvm::StringRef this_enum(enum_values[i].string_value); 64 if (this_enum.startswith(s)) 65 return enum_values[i].value; 66 } 67 68 StreamString strm; 69 strm.PutCString("invalid enumeration value, valid values are: "); 70 for (int i = 0; enum_values[i].string_value != nullptr; i++) { 71 strm.Printf("%s\"%s\"", i > 0 ? ", " : "", enum_values[i].string_value); 72 } 73 error.SetErrorString(strm.GetString()); 74 return fail_value; 75} 76 77Status OptionArgParser::ToFormat(const char *s, lldb::Format &format, 78 size_t *byte_size_ptr) { 79 format = eFormatInvalid; 80 Status error; 81 82 if (s && s[0]) { 83 if (byte_size_ptr) { 84 if (isdigit(s[0])) { 85 char *format_char = nullptr; 86 unsigned long byte_size = ::strtoul(s, &format_char, 0); 87 if (byte_size != ULONG_MAX) 88 *byte_size_ptr = byte_size; 89 s = format_char; 90 } else 91 *byte_size_ptr = 0; 92 } 93 94 const bool partial_match_ok = true; 95 if (!FormatManager::GetFormatFromCString(s, partial_match_ok, format)) { 96 StreamString error_strm; 97 error_strm.Printf( 98 "Invalid format character or name '%s'. Valid values are:\n", s); 99 for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) { 100 char format_char = FormatManager::GetFormatAsFormatChar(f); 101 if (format_char) 102 error_strm.Printf("'%c' or ", format_char); 103 104 error_strm.Printf("\"%s\"", FormatManager::GetFormatAsCString(f)); 105 error_strm.EOL(); 106 } 107 108 if (byte_size_ptr) 109 error_strm.PutCString( 110 "An optional byte size can precede the format character.\n"); 111 error.SetErrorString(error_strm.GetString()); 112 } 113 114 if (error.Fail()) 115 return error; 116 } else { 117 error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid"); 118 } 119 return error; 120} 121 122lldb::ScriptLanguage OptionArgParser::ToScriptLanguage( 123 llvm::StringRef s, lldb::ScriptLanguage fail_value, bool *success_ptr) { 124 if (success_ptr) 125 *success_ptr = true; 126 127 if (s.equals_lower("python")) 128 return eScriptLanguagePython; 129 if (s.equals_lower("default")) 130 return eScriptLanguageDefault; 131 if (s.equals_lower("none")) 132 return eScriptLanguageNone; 133 134 if (success_ptr) 135 *success_ptr = false; 136 return fail_value; 137} 138 139lldb::addr_t OptionArgParser::ToAddress(const ExecutionContext *exe_ctx, 140 llvm::StringRef s, 141 lldb::addr_t fail_value, 142 Status *error_ptr) { 143 bool error_set = false; 144 if (s.empty()) { 145 if (error_ptr) 146 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", 147 s.str().c_str()); 148 return fail_value; 149 } 150 151 llvm::StringRef sref = s; 152 153 lldb::addr_t addr = LLDB_INVALID_ADDRESS; 154 if (!s.getAsInteger(0, addr)) { 155 if (error_ptr) 156 error_ptr->Clear(); 157 return addr; 158 } 159 160 // Try base 16 with no prefix... 161 if (!s.getAsInteger(16, addr)) { 162 if (error_ptr) 163 error_ptr->Clear(); 164 return addr; 165 } 166 167 Target *target = nullptr; 168 if (!exe_ctx || !(target = exe_ctx->GetTargetPtr())) { 169 if (error_ptr) 170 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", 171 s.str().c_str()); 172 return fail_value; 173 } 174 175 lldb::ValueObjectSP valobj_sp; 176 EvaluateExpressionOptions options; 177 options.SetCoerceToId(false); 178 options.SetUnwindOnError(true); 179 options.SetKeepInMemory(false); 180 options.SetTryAllThreads(true); 181 182 ExpressionResults expr_result = 183 target->EvaluateExpression(s, exe_ctx->GetFramePtr(), valobj_sp, options); 184 185 bool success = false; 186 if (expr_result == eExpressionCompleted) { 187 if (valobj_sp) 188 valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable( 189 valobj_sp->GetDynamicValueType(), true); 190 // Get the address to watch. 191 if (valobj_sp) 192 addr = valobj_sp->GetValueAsUnsigned(fail_value, &success); 193 if (success) { 194 if (error_ptr) 195 error_ptr->Clear(); 196 return addr; 197 } else { 198 if (error_ptr) { 199 error_set = true; 200 error_ptr->SetErrorStringWithFormat( 201 "address expression \"%s\" resulted in a value whose type " 202 "can't be converted to an address: %s", 203 s.str().c_str(), valobj_sp->GetTypeName().GetCString()); 204 } 205 } 206 207 } else { 208 // Since the compiler can't handle things like "main + 12" we should try to 209 // do this for now. The compiler doesn't like adding offsets to function 210 // pointer types. 211 static RegularExpression g_symbol_plus_offset_regex( 212 "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$"); 213 RegularExpression::Match regex_match(3); 214 if (g_symbol_plus_offset_regex.Execute(sref, ®ex_match)) { 215 uint64_t offset = 0; 216 bool add = true; 217 std::string name; 218 std::string str; 219 if (regex_match.GetMatchAtIndex(s, 1, name)) { 220 if (regex_match.GetMatchAtIndex(s, 2, str)) { 221 add = str[0] == '+'; 222 223 if (regex_match.GetMatchAtIndex(s, 3, str)) { 224 if (!llvm::StringRef(str).getAsInteger(0, offset)) { 225 Status error; 226 addr = ToAddress(exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, 227 &error); 228 if (addr != LLDB_INVALID_ADDRESS) { 229 if (add) 230 return addr + offset; 231 else 232 return addr - offset; 233 } 234 } 235 } 236 } 237 } 238 } 239 240 if (error_ptr) { 241 error_set = true; 242 error_ptr->SetErrorStringWithFormat( 243 "address expression \"%s\" evaluation failed", s.str().c_str()); 244 } 245 } 246 247 if (error_ptr) { 248 if (!error_set) 249 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", 250 s.str().c_str()); 251 } 252 return fail_value; 253} 254