OptionArgParser.cpp revision 360660
1251881Speter//===-- OptionArgParser.cpp -------------------------------------*- C++ -*-===// 2251881Speter// 3251881Speter// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4251881Speter// See https://llvm.org/LICENSE.txt for license information. 5251881Speter// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6251881Speter// 7251881Speter//===----------------------------------------------------------------------===// 8251881Speter 9251881Speter#include "lldb/Interpreter/OptionArgParser.h" 10251881Speter#include "lldb/DataFormatters/FormatManager.h" 11251881Speter#include "lldb/Target/Target.h" 12251881Speter#include "lldb/Utility/Status.h" 13251881Speter#include "lldb/Utility/StreamString.h" 14251881Speter 15251881Speterusing namespace lldb_private; 16251881Speterusing namespace lldb; 17251881Speter 18251881Speterbool OptionArgParser::ToBoolean(llvm::StringRef ref, bool fail_value, 19251881Speter bool *success_ptr) { 20251881Speter if (success_ptr) 21251881Speter *success_ptr = true; 22251881Speter ref = ref.trim(); 23251881Speter if (ref.equals_lower("false") || ref.equals_lower("off") || 24251881Speter ref.equals_lower("no") || ref.equals_lower("0")) { 25251881Speter return false; 26251881Speter } else if (ref.equals_lower("true") || ref.equals_lower("on") || 27251881Speter ref.equals_lower("yes") || ref.equals_lower("1")) { 28251881Speter return true; 29251881Speter } 30251881Speter if (success_ptr) 31251881Speter *success_ptr = false; 32251881Speter return fail_value; 33251881Speter} 34251881Speter 35251881Speterchar OptionArgParser::ToChar(llvm::StringRef s, char fail_value, 36251881Speter bool *success_ptr) { 37251881Speter if (success_ptr) 38251881Speter *success_ptr = false; 39251881Speter if (s.size() != 1) 40251881Speter return fail_value; 41251881Speter 42251881Speter if (success_ptr) 43251881Speter *success_ptr = true; 44251881Speter return s[0]; 45251881Speter} 46251881Speter 47251881Speterint64_t OptionArgParser::ToOptionEnum(llvm::StringRef s, 48251881Speter const OptionEnumValues &enum_values, 49251881Speter int32_t fail_value, Status &error) { 50251881Speter error.Clear(); 51251881Speter if (enum_values.empty()) { 52251881Speter error.SetErrorString("invalid enumeration argument"); 53251881Speter return fail_value; 54251881Speter } 55251881Speter 56251881Speter if (s.empty()) { 57251881Speter error.SetErrorString("empty enumeration string"); 58251881Speter return fail_value; 59251881Speter } 60251881Speter 61251881Speter for (const auto &enum_value : enum_values) { 62251881Speter llvm::StringRef this_enum(enum_value.string_value); 63251881Speter if (this_enum.startswith(s)) 64251881Speter return enum_value.value; 65251881Speter } 66251881Speter 67251881Speter StreamString strm; 68251881Speter strm.PutCString("invalid enumeration value, valid values are: "); 69251881Speter bool is_first = true; 70251881Speter for (const auto &enum_value : enum_values) { 71251881Speter strm.Printf("%s\"%s\"", 72251881Speter is_first ? is_first = false,"" : ", ", enum_value.string_value); 73251881Speter } 74251881Speter error.SetErrorString(strm.GetString()); 75251881Speter return fail_value; 76251881Speter} 77251881Speter 78251881SpeterStatus OptionArgParser::ToFormat(const char *s, lldb::Format &format, 79251881Speter size_t *byte_size_ptr) { 80251881Speter format = eFormatInvalid; 81251881Speter Status error; 82251881Speter 83251881Speter if (s && s[0]) { 84251881Speter if (byte_size_ptr) { 85251881Speter if (isdigit(s[0])) { 86251881Speter char *format_char = nullptr; 87251881Speter unsigned long byte_size = ::strtoul(s, &format_char, 0); 88251881Speter if (byte_size != ULONG_MAX) 89251881Speter *byte_size_ptr = byte_size; 90251881Speter s = format_char; 91251881Speter } else 92251881Speter *byte_size_ptr = 0; 93251881Speter } 94251881Speter 95251881Speter const bool partial_match_ok = true; 96251881Speter if (!FormatManager::GetFormatFromCString(s, partial_match_ok, format)) { 97251881Speter StreamString error_strm; 98251881Speter error_strm.Printf( 99251881Speter "Invalid format character or name '%s'. Valid values are:\n", s); 100251881Speter for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) { 101251881Speter char format_char = FormatManager::GetFormatAsFormatChar(f); 102251881Speter if (format_char) 103251881Speter error_strm.Printf("'%c' or ", format_char); 104251881Speter 105251881Speter error_strm.Printf("\"%s\"", FormatManager::GetFormatAsCString(f)); 106251881Speter error_strm.EOL(); 107251881Speter } 108251881Speter 109251881Speter if (byte_size_ptr) 110251881Speter error_strm.PutCString( 111251881Speter "An optional byte size can precede the format character.\n"); 112251881Speter error.SetErrorString(error_strm.GetString()); 113251881Speter } 114251881Speter 115251881Speter if (error.Fail()) 116251881Speter return error; 117251881Speter } else { 118251881Speter error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid"); 119251881Speter } 120251881Speter return error; 121251881Speter} 122251881Speter 123251881Speterlldb::ScriptLanguage OptionArgParser::ToScriptLanguage( 124251881Speter llvm::StringRef s, lldb::ScriptLanguage fail_value, bool *success_ptr) { 125251881Speter if (success_ptr) 126251881Speter *success_ptr = true; 127251881Speter 128251881Speter if (s.equals_lower("python")) 129251881Speter return eScriptLanguagePython; 130251881Speter if (s.equals_lower("default")) 131251881Speter return eScriptLanguageDefault; 132251881Speter if (s.equals_lower("none")) 133251881Speter return eScriptLanguageNone; 134251881Speter 135251881Speter if (success_ptr) 136251881Speter *success_ptr = false; 137251881Speter return fail_value; 138251881Speter} 139251881Speter 140251881Speterlldb::addr_t OptionArgParser::ToAddress(const ExecutionContext *exe_ctx, 141251881Speter llvm::StringRef s, 142251881Speter lldb::addr_t fail_value, 143251881Speter Status *error_ptr) { 144251881Speter bool error_set = false; 145251881Speter if (s.empty()) { 146251881Speter if (error_ptr) 147251881Speter error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", 148251881Speter s.str().c_str()); 149251881Speter return fail_value; 150251881Speter } 151251881Speter 152251881Speter llvm::StringRef sref = s; 153251881Speter 154251881Speter lldb::addr_t addr = LLDB_INVALID_ADDRESS; 155251881Speter if (!s.getAsInteger(0, addr)) { 156251881Speter if (error_ptr) 157251881Speter error_ptr->Clear(); 158251881Speter return addr; 159251881Speter } 160251881Speter 161251881Speter // Try base 16 with no prefix... 162251881Speter if (!s.getAsInteger(16, addr)) { 163251881Speter if (error_ptr) 164251881Speter error_ptr->Clear(); 165251881Speter return addr; 166251881Speter } 167251881Speter 168251881Speter Target *target = nullptr; 169251881Speter if (!exe_ctx || !(target = exe_ctx->GetTargetPtr())) { 170251881Speter if (error_ptr) 171251881Speter error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", 172251881Speter s.str().c_str()); 173251881Speter return fail_value; 174251881Speter } 175251881Speter 176251881Speter lldb::ValueObjectSP valobj_sp; 177251881Speter EvaluateExpressionOptions options; 178251881Speter options.SetCoerceToId(false); 179251881Speter options.SetUnwindOnError(true); 180251881Speter options.SetKeepInMemory(false); 181251881Speter options.SetTryAllThreads(true); 182251881Speter 183251881Speter ExpressionResults expr_result = 184251881Speter target->EvaluateExpression(s, exe_ctx->GetFramePtr(), valobj_sp, options); 185251881Speter 186251881Speter bool success = false; 187251881Speter if (expr_result == eExpressionCompleted) { 188251881Speter if (valobj_sp) 189251881Speter valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable( 190251881Speter valobj_sp->GetDynamicValueType(), true); 191251881Speter // Get the address to watch. 192251881Speter if (valobj_sp) 193251881Speter addr = valobj_sp->GetValueAsUnsigned(fail_value, &success); 194251881Speter if (success) { 195251881Speter if (error_ptr) 196251881Speter error_ptr->Clear(); 197251881Speter return addr; 198251881Speter } else { 199251881Speter if (error_ptr) { 200251881Speter error_set = true; 201251881Speter error_ptr->SetErrorStringWithFormat( 202251881Speter "address expression \"%s\" resulted in a value whose type " 203251881Speter "can't be converted to an address: %s", 204251881Speter s.str().c_str(), valobj_sp->GetTypeName().GetCString()); 205251881Speter } 206251881Speter } 207251881Speter 208251881Speter } else { 209251881Speter // Since the compiler can't handle things like "main + 12" we should try to 210251881Speter // do this for now. The compiler doesn't like adding offsets to function 211251881Speter // pointer types. 212251881Speter static RegularExpression g_symbol_plus_offset_regex( 213251881Speter "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$"); 214251881Speter RegularExpression::Match regex_match(3); 215251881Speter if (g_symbol_plus_offset_regex.Execute(sref, ®ex_match)) { 216251881Speter uint64_t offset = 0; 217251881Speter bool add = true; 218251881Speter std::string name; 219251881Speter std::string str; 220251881Speter if (regex_match.GetMatchAtIndex(s, 1, name)) { 221251881Speter if (regex_match.GetMatchAtIndex(s, 2, str)) { 222251881Speter add = str[0] == '+'; 223251881Speter 224251881Speter if (regex_match.GetMatchAtIndex(s, 3, str)) { 225251881Speter if (!llvm::StringRef(str).getAsInteger(0, offset)) { 226251881Speter Status error; 227251881Speter addr = ToAddress(exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, 228251881Speter &error); 229251881Speter if (addr != LLDB_INVALID_ADDRESS) { 230251881Speter if (add) 231251881Speter return addr + offset; 232251881Speter else 233251881Speter return addr - offset; 234251881Speter } 235251881Speter } 236251881Speter } 237251881Speter } 238251881Speter } 239251881Speter } 240251881Speter 241251881Speter if (error_ptr) { 242251881Speter error_set = true; 243251881Speter error_ptr->SetErrorStringWithFormat( 244251881Speter "address expression \"%s\" evaluation failed", s.str().c_str()); 245251881Speter } 246251881Speter } 247251881Speter 248251881Speter if (error_ptr) { 249251881Speter if (!error_set) 250251881Speter error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", 251251881Speter s.str().c_str()); 252251881Speter } 253251881Speter return fail_value; 254251881Speter} 255251881Speter