bool Mangled::NameMatches (const RegularExpression& regex, lldb::LanguageType language) const { if (m_mangled && regex.Execute (m_mangled.AsCString())) return true; ConstString demangled = GetDemangledName(language); if (demangled && regex.Execute (demangled.AsCString())) return true; return false; }
bool Variable::NameMatches (const RegularExpression& regex) const { if (regex.Execute (m_name.AsCString())) return true; return m_mangled.NameMatches (regex); }
void AddressSanitizerRuntime::ModulesDidLoad(lldb_private::ModuleList &module_list) { if (IsActive()) return; if (m_runtime_module) { Activate(); return; } Mutex::Locker modules_locker(module_list.GetMutex()); const size_t num_modules = module_list.GetSize(); for (size_t i = 0; i < num_modules; ++i) { Module *module_pointer = module_list.GetModulePointerAtIndexUnlocked(i); const FileSpec & file_spec = module_pointer->GetFileSpec(); if (! file_spec) continue; static RegularExpression g_asan_runtime_regex("libclang_rt.asan_(.*)_dynamic\\.dylib"); if (g_asan_runtime_regex.Execute (file_spec.GetFilename().GetCString()) || module_pointer->IsExecutable()) { if (ModuleContainsASanRuntime(module_pointer)) { m_runtime_module = module_pointer->shared_from_this(); Activate(); return; } } } }
void SourceManager::File::FindLinesMatchingRegex (RegularExpression& regex, uint32_t start_line, uint32_t end_line, std::vector<uint32_t> &match_lines) { TimeValue curr_mod_time (m_file_spec.GetModificationTime()); if (m_mod_time != curr_mod_time) { m_mod_time = curr_mod_time; m_data_sp = m_file_spec.ReadFileContents (); m_offsets.clear(); } match_lines.clear(); if (!LineIsValid(start_line) || (end_line != UINT32_MAX && !LineIsValid(end_line))) return; if (start_line > end_line) return; for (uint32_t line_no = start_line; line_no < end_line; line_no++) { std::string buffer; if (!GetLine (line_no, buffer)) break; if (regex.Execute(buffer.c_str())) { match_lines.push_back(line_no); } } }
bool lldb_private::NameMatches (const char *name, NameMatchType match_type, const char *match) { if (match_type == eNameMatchIgnore) return true; if (name == match) return true; if (name && match) { llvm::StringRef name_sref(name); llvm::StringRef match_sref(match); switch (match_type) { case eNameMatchIgnore: // This case cannot occur: tested before return true; case eNameMatchEquals: return name_sref == match_sref; case eNameMatchContains: return name_sref.find (match_sref) != llvm::StringRef::npos; case eNameMatchStartsWith: return name_sref.startswith (match_sref); case eNameMatchEndsWith: return name_sref.endswith (match_sref); case eNameMatchRegularExpression: { RegularExpression regex (match); return regex.Execute (name); } break; } } return false; }
uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®exp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) { Mutex::Locker locker (m_mutex); uint32_t prev_size = indexes.size(); uint32_t sym_end = m_symbols.size(); for (uint32_t i = 0; i < sym_end; i++) { if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) { if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false) continue; const char *name = m_symbols[i].GetMangled().GetName().AsCString(); if (name) { if (regexp.Execute (name)) indexes.push_back(i); } } } return indexes.size() - prev_size; }
static bool DecodeHostAndPort (const char *host_and_port, std::string &host_str, std::string &port_str, int32_t& port, Error *error_ptr) { RegularExpression regex ("([^:]+):([0-9]+)"); if (regex.Execute (host_and_port, 2)) { if (regex.GetMatchAtIndex (host_and_port, 1, host_str) && regex.GetMatchAtIndex (host_and_port, 2, port_str)) { port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN); if (port != INT32_MIN) { if (error_ptr) error_ptr->Clear(); return true; } } } host_str.clear(); port_str.clear(); port = INT32_MIN; if (error_ptr) error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port); return false; }
bool Variable::NameMatches (const RegularExpression& regex) const { if (regex.Execute (m_name.AsCString())) return true; if (m_mangled) return m_mangled.NameMatches (regex, GetLanguage()); return false; }
//------------------------------------------------------------------ /// Returns true if the filespec represents an implementation source /// file (files with a ".c", ".cpp", ".m", ".mm" (many more) /// extension). /// /// @return /// \b true if the filespec represents an implementation source /// file, \b false otherwise. //------------------------------------------------------------------ bool FileSpec::IsSourceImplementationFile () const { ConstString extension (GetFileNameExtension()); if (extension) { static RegularExpression g_source_file_regex ("^(c|m|mm|cpp|c\\+\\+|cxx|cc|cp|s|asm|f|f77|f90|f95|f03|for|ftn|fpp|ada|adb|ads)$", llvm::Regex::IgnoreCase); return g_source_file_regex.Execute (extension.GetCString()); } return false; }
bool CPlusPlusLanguage::ExtractContextAndIdentifier( const char *name, llvm::StringRef &context, llvm::StringRef &identifier) { static RegularExpression g_basename_regex(llvm::StringRef( "^(([A-Za-z_][A-Za-z_0-9]*::)*)(~?[A-Za-z_~][A-Za-z_0-9]*)$")); RegularExpression::Match match(4); if (g_basename_regex.Execute(llvm::StringRef::withNullAsEmpty(name), &match)) { match.GetMatchAtIndex(name, 1, context); match.GetMatchAtIndex(name, 3, identifier); return true; } return false; }
static bool IsValidBasename(const llvm::StringRef &basename) { // Check that the basename matches with the following regular expression or is // an operator name: // "^~?([A-Za-z_][A-Za-z_0-9]*)(<.*>)?$" // We are using a hand written implementation because it is significantly more // efficient then // using the general purpose regular expression library. size_t idx = 0; if (basename.size() > 0 && basename[0] == '~') idx = 1; if (basename.size() <= idx) return false; // Empty string or "~" if (!std::isalpha(basename[idx]) && basename[idx] != '_') return false; // First charater (after removing the possible '~'') isn't in // [A-Za-z_] // Read all characters matching [A-Za-z_0-9] ++idx; while (idx < basename.size()) { if (!std::isalnum(basename[idx]) && basename[idx] != '_') break; ++idx; } // We processed all characters. It is a vaild basename. if (idx == basename.size()) return true; // Check for basename with template arguments // TODO: Improve the quality of the validation with validating the template // arguments if (basename[idx] == '<' && basename.back() == '>') return true; // Check if the basename is a vaild C++ operator name if (!basename.startswith("operator")) return false; static RegularExpression g_operator_regex( llvm::StringRef("^(operator)( " "?)([A-Za-z_][A-Za-z_0-9]*|\\(\\)|" "\\[\\]|[\\^<>=!\\/" "*+-]+)(<.*>)?(\\[\\])?$")); std::string basename_str(basename.str()); return g_operator_regex.Execute(basename_str, nullptr); }
bool Socket::DecodeHostAndPort(llvm::StringRef host_and_port, std::string &host_str, std::string &port_str, int32_t& port, Error *error_ptr) { static RegularExpression g_regex ("([^:]+):([0-9]+)"); RegularExpression::Match regex_match(2); if (g_regex.Execute (host_and_port.data(), ®ex_match)) { if (regex_match.GetMatchAtIndex (host_and_port.data(), 1, host_str) && regex_match.GetMatchAtIndex (host_and_port.data(), 2, port_str)) { bool ok = false; port = StringConvert::ToUInt32 (port_str.c_str(), UINT32_MAX, 10, &ok); if (ok && port <= UINT16_MAX) { if (error_ptr) error_ptr->Clear(); return true; } // port is too large if (error_ptr) error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data()); return false; } } // If this was unsuccessful, then check if it's simply a signed 32-bit integer, representing // a port with an empty host. host_str.clear(); port_str.clear(); bool ok = false; port = StringConvert::ToUInt32 (host_and_port.data(), UINT32_MAX, 10, &ok); if (ok && port < UINT16_MAX) { port_str = host_and_port; if (error_ptr) error_ptr->Clear(); return true; } if (error_ptr) error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data()); return false; }
bool Socket::DecodeHostAndPort(llvm::StringRef host_and_port, std::string &host_str, std::string &port_str, int32_t &port, Status *error_ptr) { static RegularExpression g_regex( llvm::StringRef("([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)")); RegularExpression::Match regex_match(2); if (g_regex.Execute(host_and_port, ®ex_match)) { if (regex_match.GetMatchAtIndex(host_and_port.data(), 1, host_str) && regex_match.GetMatchAtIndex(host_and_port.data(), 2, port_str)) { // IPv6 addresses are wrapped in [] when specified with ports if (host_str.front() == '[' && host_str.back() == ']') host_str = host_str.substr(1, host_str.size() - 2); bool ok = false; port = StringConvert::ToUInt32(port_str.c_str(), UINT32_MAX, 10, &ok); if (ok && port <= UINT16_MAX) { if (error_ptr) error_ptr->Clear(); return true; } // port is too large if (error_ptr) error_ptr->SetErrorStringWithFormat( "invalid host:port specification: '%s'", host_and_port.data()); return false; } } // If this was unsuccessful, then check if it's simply a signed 32-bit // integer, representing a port with an empty host. host_str.clear(); port_str.clear(); bool ok = false; port = StringConvert::ToUInt32(host_and_port.data(), UINT32_MAX, 10, &ok); if (ok && port < UINT16_MAX) { port_str = host_and_port; if (error_ptr) error_ptr->Clear(); return true; } if (error_ptr) error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data()); return false; }
void DWARFCompileUnit::ParseProducerInfo () { m_producer_version_major = UINT32_MAX; m_producer_version_minor = UINT32_MAX; m_producer_version_update = UINT32_MAX; const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly(); if (die) { const char *producer_cstr = die->GetAttributeValueAsString(m_dwarf2Data, this, DW_AT_producer, NULL); if (producer_cstr) { RegularExpression llvm_gcc_regex("^4\\.[012]\\.[01] \\(Based on Apple Inc\\. build [0-9]+\\) \\(LLVM build [\\.0-9]+\\)$"); if (llvm_gcc_regex.Execute (producer_cstr)) { m_producer = eProducerLLVMGCC; } else if (strstr(producer_cstr, "clang")) { static RegularExpression g_clang_version_regex("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)"); RegularExpression::Match regex_match(3); if (g_clang_version_regex.Execute (producer_cstr, ®ex_match)) { std::string str; if (regex_match.GetMatchAtIndex (producer_cstr, 1, str)) m_producer_version_major = StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); if (regex_match.GetMatchAtIndex (producer_cstr, 2, str)) m_producer_version_minor = StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); if (regex_match.GetMatchAtIndex (producer_cstr, 3, str)) m_producer_version_update = StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); } m_producer = eProducerClang; } else if (strstr(producer_cstr, "GNU")) m_producer = eProducerGCC; } } if (m_producer == eProducerInvalid) m_producer = eProcucerOther; }
uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( const RegularExpression ®exp, SymbolType symbol_type, std::vector<uint32_t> &indexes) { std::lock_guard<std::recursive_mutex> guard(m_mutex); uint32_t prev_size = indexes.size(); uint32_t sym_end = m_symbols.size(); for (uint32_t i = 0; i < sym_end; i++) { if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) { const char *name = m_symbols[i].GetName().AsCString(); if (name) { if (regexp.Execute(name)) indexes.push_back(i); } } } return indexes.size() - prev_size; }
void SourceManager::File::FindLinesMatchingRegex( RegularExpression ®ex, uint32_t start_line, uint32_t end_line, std::vector<uint32_t> &match_lines) { match_lines.clear(); if (!LineIsValid(start_line) || (end_line != UINT32_MAX && !LineIsValid(end_line))) return; if (start_line > end_line) return; for (uint32_t line_no = start_line; line_no < end_line; line_no++) { std::string buffer; if (!GetLine(line_no, buffer)) break; if (regex.Execute(buffer)) { match_lines.push_back(line_no); } } }
ConnectionStatus ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error_ptr) { lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, "%p ConnectionFileDescriptor::SocketConnect (host/port = %s)", this, host_and_port); Close (m_fd, false); m_is_socket = true; RegularExpression regex ("([^:]+):([0-9]+)"); if (regex.Execute (host_and_port, 2) == false) { if (error_ptr) error_ptr->SetErrorStringWithFormat("Invalid host:port specification: '%s'.\n", host_and_port); return eConnectionStatusError; } std::string host_str; std::string port_str; if (regex.GetMatchAtIndex (host_and_port, 1, host_str) == false || regex.GetMatchAtIndex (host_and_port, 2, port_str) == false) { if (error_ptr) error_ptr->SetErrorStringWithFormat("Invalid host:port specification '%s'.\n", host_and_port); return eConnectionStatusError; } int32_t port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN); if (port == INT32_MIN) { if (error_ptr) error_ptr->SetErrorStringWithFormat("Invalid port '%s'.\n", port_str.c_str()); return eConnectionStatusError; } // Create the socket m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_fd == -1) { if (error_ptr) error_ptr->SetErrorToErrno(); return eConnectionStatusError; } m_should_close_fd = true; // Enable local address reuse SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1); struct sockaddr_in sa; ::bzero (&sa, sizeof (sa)); sa.sin_family = AF_INET; sa.sin_port = htons (port); int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); if (inet_pton_result <= 0) { struct hostent *host_entry = gethostbyname (host_str.c_str()); if (host_entry) host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list); inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); if (inet_pton_result <= 0) { if (error_ptr) { if (inet_pton_result == -1) error_ptr->SetErrorToErrno(); else error_ptr->SetErrorStringWithFormat("Invalid host string: '%s'.\n", host_str.c_str()); } Close (m_fd, false); return eConnectionStatusError; } } if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) { if (error_ptr) error_ptr->SetErrorToErrno(); Close (m_fd, false); return eConnectionStatusError; } // Keep our TCP packets coming without any delays. SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); if (error_ptr) error_ptr->Clear(); return eConnectionStatusSuccess; }
virtual void CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx) { DataExtractor data; const AddressClass address_class = GetAddressClass (); if (m_opcode.GetData(data)) { char out_string[512]; DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr; if (address_class == eAddressClassCodeAlternateISA) mc_disasm_ptr = llvm_disasm.m_alternate_disasm_ap.get(); else mc_disasm_ptr = llvm_disasm.m_disasm_ap.get(); lldb::addr_t pc = m_address.GetFileAddress(); m_using_file_addr = true; const bool data_from_file = GetDisassemblerLLVMC().m_data_from_file; bool use_hex_immediates = true; Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC; if (exe_ctx) { Target *target = exe_ctx->GetTargetPtr(); if (target) { use_hex_immediates = target->GetUseHexImmediates(); hex_style = target->GetHexImmediateStyle(); if (!data_from_file) { const lldb::addr_t load_addr = m_address.GetLoadAddress(target); if (load_addr != LLDB_INVALID_ADDRESS) { pc = load_addr; m_using_file_addr = false; } } } } llvm_disasm.Lock(this, exe_ctx); const uint8_t *opcode_data = data.GetDataStart(); const size_t opcode_data_len = data.GetByteSize(); llvm::MCInst inst; size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, opcode_data_len, pc, inst); if (inst_size > 0) { mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string)); } llvm_disasm.Unlock(); if (inst_size == 0) { m_comment.assign ("unknown opcode"); inst_size = m_opcode.GetByteSize(); StreamString mnemonic_strm; lldb::offset_t offset = 0; lldb::ByteOrder byte_order = data.GetByteOrder(); switch (inst_size) { case 1: { const uint8_t uval8 = data.GetU8 (&offset); m_opcode.SetOpcode8 (uval8, byte_order); m_opcode_name.assign (".byte"); mnemonic_strm.Printf("0x%2.2x", uval8); } break; case 2: { const uint16_t uval16 = data.GetU16(&offset); m_opcode.SetOpcode16(uval16, byte_order); m_opcode_name.assign (".short"); mnemonic_strm.Printf("0x%4.4x", uval16); } break; case 4: { const uint32_t uval32 = data.GetU32(&offset); m_opcode.SetOpcode32(uval32, byte_order); m_opcode_name.assign (".long"); mnemonic_strm.Printf("0x%8.8x", uval32); } break; case 8: { const uint64_t uval64 = data.GetU64(&offset); m_opcode.SetOpcode64(uval64, byte_order); m_opcode_name.assign (".quad"); mnemonic_strm.Printf("0x%16.16" PRIx64, uval64); } break; default: if (inst_size == 0) return; else { const uint8_t *bytes = data.PeekData(offset, inst_size); if (bytes == NULL) return; m_opcode_name.assign (".byte"); m_opcode.SetOpcodeBytes(bytes, inst_size); mnemonic_strm.Printf("0x%2.2x", bytes[0]); for (uint32_t i=1; i<inst_size; ++i) mnemonic_strm.Printf(" 0x%2.2x", bytes[i]); } break; } m_mnemonics.swap(mnemonic_strm.GetString()); return; } else { if (m_does_branch == eLazyBoolCalculate) { const bool can_branch = mc_disasm_ptr->CanBranch(inst); if (can_branch) m_does_branch = eLazyBoolYes; else m_does_branch = eLazyBoolNo; } } static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED); RegularExpression::Match matches(3); if (s_regex.Execute(out_string, &matches)) { matches.GetMatchAtIndex(out_string, 1, m_opcode_name); matches.GetMatchAtIndex(out_string, 2, m_mnemonics); } } }
size_t DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, ByteOrder byte_order) { assert(!m_finalized); StructuredData::Array *sets = nullptr; if (dict.GetValueForKeyAsArray("sets", sets)) { const uint32_t num_sets = sets->GetSize(); for (uint32_t i=0; i<num_sets; ++i) { std::string set_name_str; ConstString set_name; if (sets->GetItemAtIndexAsString(i, set_name_str)) set_name.SetCString(set_name_str.c_str()); if (set_name) { RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL }; m_sets.push_back (new_set); } else { Clear(); printf("error: register sets must have valid names\n"); return 0; } } m_set_reg_nums.resize(m_sets.size()); } StructuredData::Array *regs = nullptr; if (!dict.GetValueForKeyAsArray("registers", regs)) return 0; const uint32_t num_regs = regs->GetSize(); // typedef std::map<std::string, std::vector<std::string> > InvalidateNameMap; // InvalidateNameMap invalidate_map; for (uint32_t i = 0; i < num_regs; ++i) { StructuredData::Dictionary *reg_info_dict = nullptr; if (!regs->GetItemAtIndexAsDictionary(i, reg_info_dict)) { Clear(); printf("error: items in the 'registers' array must be dictionaries\n"); regs->DumpToStdout(); return 0; } // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 2, // 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', }, RegisterInfo reg_info; std::vector<uint32_t> value_regs; std::vector<uint32_t> invalidate_regs; memset(®_info, 0, sizeof(reg_info)); ConstString name_val; ConstString alt_name_val; if (!reg_info_dict->GetValueForKeyAsString("name", name_val, nullptr)) { Clear(); printf("error: registers must have valid names and offsets\n"); reg_info_dict->DumpToStdout(); return 0; } reg_info.name = name_val.GetCString(); reg_info_dict->GetValueForKeyAsString("alt-name", alt_name_val, nullptr); reg_info.alt_name = alt_name_val.GetCString(); reg_info_dict->GetValueForKeyAsInteger("offset", reg_info.byte_offset, UINT32_MAX); if (reg_info.byte_offset == UINT32_MAX) { // No offset for this register, see if the register has a value expression // which indicates this register is part of another register. Value expressions // are things like "rax[31:0]" which state that the current register's value // is in a concrete register "rax" in bits 31:0. If there is a value expression // we can calculate the offset bool success = false; std::string slice_str; if (reg_info_dict->GetValueForKeyAsString("slice", slice_str, nullptr)) { // Slices use the following format: // REGNAME[MSBIT:LSBIT] // REGNAME - name of the register to grab a slice of // MSBIT - the most significant bit at which the current register value starts at // LSBIT - the least significant bit at which the current register value ends at static RegularExpression g_bitfield_regex("([A-Za-z_][A-Za-z0-9_]*)\\[([0-9]+):([0-9]+)\\]"); RegularExpression::Match regex_match(3); if (g_bitfield_regex.Execute(slice_str.c_str(), ®ex_match)) { llvm::StringRef reg_name_str; std::string msbit_str; std::string lsbit_str; if (regex_match.GetMatchAtIndex(slice_str.c_str(), 1, reg_name_str) && regex_match.GetMatchAtIndex(slice_str.c_str(), 2, msbit_str) && regex_match.GetMatchAtIndex(slice_str.c_str(), 3, lsbit_str)) { const uint32_t msbit = StringConvert::ToUInt32(msbit_str.c_str(), UINT32_MAX); const uint32_t lsbit = StringConvert::ToUInt32(lsbit_str.c_str(), UINT32_MAX); if (msbit != UINT32_MAX && lsbit != UINT32_MAX) { if (msbit > lsbit) { const uint32_t msbyte = msbit / 8; const uint32_t lsbyte = lsbit / 8; ConstString containing_reg_name(reg_name_str); RegisterInfo *containing_reg_info = GetRegisterInfo(containing_reg_name); if (containing_reg_info) { const uint32_t max_bit = containing_reg_info->byte_size * 8; if (msbit < max_bit && lsbit < max_bit) { m_invalidate_regs_map[containing_reg_info->kinds[eRegisterKindLLDB]].push_back(i); m_value_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]); m_invalidate_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]); if (byte_order == eByteOrderLittle) { success = true; reg_info.byte_offset = containing_reg_info->byte_offset + lsbyte; } else if (byte_order == eByteOrderBig) { success = true; reg_info.byte_offset = containing_reg_info->byte_offset + msbyte; } else { assert(!"Invalid byte order"); } } else { if (msbit > max_bit) printf("error: msbit (%u) must be less than the bitsize of the register (%u)\n", msbit, max_bit); else printf("error: lsbit (%u) must be less than the bitsize of the register (%u)\n", lsbit, max_bit); } } else { printf("error: invalid concrete register \"%s\"\n", containing_reg_name.GetCString()); } } else { printf("error: msbit (%u) must be greater than lsbit (%u)\n", msbit, lsbit); } } else { printf("error: msbit (%u) and lsbit (%u) must be valid\n", msbit, lsbit); } } else { // TODO: print error invalid slice string that doesn't follow the format printf("error: failed to extract regex matches for parsing the register bitfield regex\n"); } } else { // TODO: print error invalid slice string that doesn't follow the format printf("error: failed to match against register bitfield regex\n"); } } else { StructuredData::Array *composite_reg_list = nullptr; if (reg_info_dict->GetValueForKeyAsArray("composite", composite_reg_list)) { const size_t num_composite_regs = composite_reg_list->GetSize(); if (num_composite_regs > 0) { uint32_t composite_offset = UINT32_MAX; for (uint32_t composite_idx = 0; composite_idx < num_composite_regs; ++composite_idx) { ConstString composite_reg_name; if (composite_reg_list->GetItemAtIndexAsString(composite_idx, composite_reg_name, nullptr)) { RegisterInfo *composite_reg_info = GetRegisterInfo(composite_reg_name); if (composite_reg_info) { composite_offset = std::min(composite_offset, composite_reg_info->byte_offset); m_value_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]); m_invalidate_regs_map[composite_reg_info->kinds[eRegisterKindLLDB]].push_back(i); m_invalidate_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]); } else { // TODO: print error invalid slice string that doesn't follow the format printf("error: failed to find composite register by name: \"%s\"\n", composite_reg_name.GetCString()); } } else { printf("error: 'composite' list value wasn't a python string\n"); } } if (composite_offset != UINT32_MAX) { reg_info.byte_offset = composite_offset; success = m_value_regs_map.find(i) != m_value_regs_map.end(); } else { printf("error: 'composite' registers must specify at least one real register\n"); } } else { printf("error: 'composite' list was empty\n"); } } } if (!success) { Clear(); reg_info_dict->DumpToStdout(); return 0; } } int64_t bitsize = 0; if (!reg_info_dict->GetValueForKeyAsInteger("bitsize", bitsize)) { Clear(); printf("error: invalid or missing 'bitsize' key/value pair in register dictionary\n"); reg_info_dict->DumpToStdout(); return 0; } reg_info.byte_size = bitsize / 8; std::string format_str; if (reg_info_dict->GetValueForKeyAsString("format", format_str, nullptr)) { if (Args::StringToFormat(format_str.c_str(), reg_info.format, NULL).Fail()) { Clear(); printf("error: invalid 'format' value in register dictionary\n"); reg_info_dict->DumpToStdout(); return 0; } } else { reg_info_dict->GetValueForKeyAsInteger("format", reg_info.format, eFormatHex); } std::string encoding_str; if (reg_info_dict->GetValueForKeyAsString("encoding", encoding_str)) reg_info.encoding = Args::StringToEncoding(encoding_str.c_str(), eEncodingUint); else reg_info_dict->GetValueForKeyAsInteger("encoding", reg_info.encoding, eEncodingUint); size_t set = 0; if (!reg_info_dict->GetValueForKeyAsInteger<size_t>("set", set, -1) || set >= m_sets.size()) { Clear(); printf("error: invalid 'set' value in register dictionary, valid values are 0 - %i\n", (int)set); reg_info_dict->DumpToStdout(); return 0; } // Fill in the register numbers reg_info.kinds[lldb::eRegisterKindLLDB] = i; reg_info.kinds[lldb::eRegisterKindGDB] = i; reg_info_dict->GetValueForKeyAsInteger("gcc", reg_info.kinds[lldb::eRegisterKindGCC], LLDB_INVALID_REGNUM); reg_info_dict->GetValueForKeyAsInteger("dwarf", reg_info.kinds[lldb::eRegisterKindDWARF], LLDB_INVALID_REGNUM); std::string generic_str; if (reg_info_dict->GetValueForKeyAsString("generic", generic_str)) reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister(generic_str.c_str()); else reg_info_dict->GetValueForKeyAsInteger("generic", reg_info.kinds[lldb::eRegisterKindGeneric], LLDB_INVALID_REGNUM); // Check if this register invalidates any other register values when it is modified StructuredData::Array *invalidate_reg_list = nullptr; if (reg_info_dict->GetValueForKeyAsArray("invalidate-regs", invalidate_reg_list)) { const size_t num_regs = invalidate_reg_list->GetSize(); if (num_regs > 0) { for (uint32_t idx = 0; idx < num_regs; ++idx) { ConstString invalidate_reg_name; uint64_t invalidate_reg_num; if (invalidate_reg_list->GetItemAtIndexAsString(idx, invalidate_reg_name)) { RegisterInfo *invalidate_reg_info = GetRegisterInfo(invalidate_reg_name); if (invalidate_reg_info) { m_invalidate_regs_map[i].push_back(invalidate_reg_info->kinds[eRegisterKindLLDB]); } else { // TODO: print error invalid slice string that doesn't follow the format printf("error: failed to find a 'invalidate-regs' register for \"%s\" while parsing register \"%s\"\n", invalidate_reg_name.GetCString(), reg_info.name); } } else if (invalidate_reg_list->GetItemAtIndexAsInteger(idx, invalidate_reg_num)) { if (invalidate_reg_num != UINT64_MAX) m_invalidate_regs_map[i].push_back(invalidate_reg_num); else printf("error: 'invalidate-regs' list value wasn't a valid integer\n"); } else { printf("error: 'invalidate-regs' list value wasn't a python string or integer\n"); } } } else { printf("error: 'invalidate-regs' contained an empty list\n"); } } // Calculate the register offset const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size; if (m_reg_data_byte_size < end_reg_offset) m_reg_data_byte_size = end_reg_offset; m_regs.push_back(reg_info); m_set_reg_nums[set].push_back(i); } Finalize(); return m_regs.size(); }
Error Variable::GetValuesForVariableExpressionPath (const char *variable_expr_path, ExecutionContextScope *scope, GetVariableCallback callback, void *baton, VariableList &variable_list, ValueObjectList &valobj_list) { Error error; if (variable_expr_path && callback) { switch (variable_expr_path[0]) { case '*': { error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1, scope, callback, baton, variable_list, valobj_list); if (error.Success()) { for (uint32_t i=0; i<valobj_list.GetSize(); ) { Error tmp_error; ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->Dereference(tmp_error)); if (tmp_error.Fail()) { variable_list.RemoveVariableAtIndex (i); valobj_list.RemoveValueObjectAtIndex (i); } else { valobj_list.SetValueObjectAtIndex (i, valobj_sp); ++i; } } } else { error.SetErrorString ("unknown error"); } return error; } break; case '&': { error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1, scope, callback, baton, variable_list, valobj_list); if (error.Success()) { for (uint32_t i=0; i<valobj_list.GetSize(); ) { Error tmp_error; ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error)); if (tmp_error.Fail()) { variable_list.RemoveVariableAtIndex (i); valobj_list.RemoveValueObjectAtIndex (i); } else { valobj_list.SetValueObjectAtIndex (i, valobj_sp); ++i; } } } else { error.SetErrorString ("unknown error"); } return error; } break; default: { static RegularExpression g_regex ("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)"); RegularExpression::Match regex_match(1); if (g_regex.Execute(variable_expr_path, ®ex_match)) { std::string variable_name; if (regex_match.GetMatchAtIndex(variable_expr_path, 1, variable_name)) { variable_list.Clear(); if (callback (baton, variable_name.c_str(), variable_list)) { uint32_t i=0; while (i < variable_list.GetSize()) { VariableSP var_sp (variable_list.GetVariableAtIndex (i)); ValueObjectSP valobj_sp; if (var_sp) { ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp)); if (variable_valobj_sp) { const char *variable_sub_expr_path = variable_expr_path + variable_name.size(); if (*variable_sub_expr_path) { const char* first_unparsed = nullptr; ValueObject::ExpressionPathScanEndReason reason_to_stop; ValueObject::ExpressionPathEndResultType final_value_type; ValueObject::GetValueForExpressionPathOptions options; ValueObject::ExpressionPathAftermath final_task_on_target; valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_sub_expr_path, &first_unparsed, &reason_to_stop, &final_value_type, options, &final_task_on_target); if (!valobj_sp) { error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'", variable_sub_expr_path, var_sp->GetName().GetCString()); } } else { // Just the name of a variable with no extras valobj_sp = variable_valobj_sp; } } } if (!var_sp || !valobj_sp) { variable_list.RemoveVariableAtIndex (i); } else { valobj_list.Append(valobj_sp); ++i; } } if (variable_list.GetSize() > 0) { error.Clear(); return error; } } } } error.SetErrorStringWithFormat ("unable to extract a variable name from '%s'", variable_expr_path); } break; } } error.SetErrorString ("unknown error"); return error; }
size_t DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict, ByteOrder byte_order) { assert(!m_finalized); #ifndef LLDB_DISABLE_PYTHON PythonList sets (dict.GetItemForKey("sets")); if (sets) { const uint32_t num_sets = sets.GetSize(); for (uint32_t i=0; i<num_sets; ++i) { PythonString py_set_name(sets.GetItemAtIndex(i)); ConstString set_name; if (py_set_name) set_name.SetCString(py_set_name.GetString()); if (set_name) { RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL }; m_sets.push_back (new_set); } else { Clear(); return 0; } } m_set_reg_nums.resize(m_sets.size()); } PythonList regs (dict.GetItemForKey("registers")); if (regs) { const uint32_t num_regs = regs.GetSize(); PythonString name_pystr("name"); PythonString altname_pystr("alt-name"); PythonString bitsize_pystr("bitsize"); PythonString offset_pystr("offset"); PythonString encoding_pystr("encoding"); PythonString format_pystr("format"); PythonString set_pystr("set"); PythonString gcc_pystr("gcc"); PythonString dwarf_pystr("dwarf"); PythonString generic_pystr("generic"); PythonString slice_pystr("slice"); PythonString composite_pystr("composite"); PythonString invalidate_regs_pystr("invalidate-regs"); // typedef std::map<std::string, std::vector<std::string> > InvalidateNameMap; // InvalidateNameMap invalidate_map; for (uint32_t i=0; i<num_regs; ++i) { PythonDictionary reg_info_dict(regs.GetItemAtIndex(i)); if (reg_info_dict) { // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 2, 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', }, RegisterInfo reg_info; std::vector<uint32_t> value_regs; std::vector<uint32_t> invalidate_regs; bzero (®_info, sizeof(reg_info)); reg_info.name = ConstString (reg_info_dict.GetItemForKeyAsString(name_pystr)).GetCString(); if (reg_info.name == NULL) { Clear(); return 0; } reg_info.alt_name = ConstString (reg_info_dict.GetItemForKeyAsString(altname_pystr)).GetCString(); reg_info.byte_offset = reg_info_dict.GetItemForKeyAsInteger(offset_pystr, UINT32_MAX); if (reg_info.byte_offset == UINT32_MAX) { // No offset for this register, see if the register has a value expression // which indicates this register is part of another register. Value expressions // are things like "rax[31:0]" which state that the current register's value // is in a concrete register "rax" in bits 31:0. If there is a value expression // we can calculate the offset bool success = false; const char *slice_cstr = reg_info_dict.GetItemForKeyAsString(slice_pystr); if (slice_cstr) { // Slices use the following format: // REGNAME[MSBIT:LSBIT] // REGNAME - name of the register to grab a slice of // MSBIT - the most significant bit at which the current register value starts at // LSBIT - the least significant bit at which the current register value ends at static RegularExpression g_bitfield_regex("([A-Za-z_][A-Za-z0-9_]*)\\[([0-9]+):([0-9]+)\\]"); RegularExpression::Match regex_match(3); if (g_bitfield_regex.Execute(slice_cstr, ®ex_match)) { llvm::StringRef reg_name_str; std::string msbit_str; std::string lsbit_str; if (regex_match.GetMatchAtIndex(slice_cstr, 1, reg_name_str) && regex_match.GetMatchAtIndex(slice_cstr, 2, msbit_str) && regex_match.GetMatchAtIndex(slice_cstr, 3, lsbit_str)) { const uint32_t msbit = Args::StringToUInt32(msbit_str.c_str(), UINT32_MAX); const uint32_t lsbit = Args::StringToUInt32(lsbit_str.c_str(), UINT32_MAX); if (msbit != UINT32_MAX && lsbit != UINT32_MAX) { if (msbit > lsbit) { const uint32_t msbyte = msbit / 8; const uint32_t lsbyte = lsbit / 8; ConstString containing_reg_name(reg_name_str); RegisterInfo *containing_reg_info = GetRegisterInfo (containing_reg_name); if (containing_reg_info) { const uint32_t max_bit = containing_reg_info->byte_size * 8; if (msbit < max_bit && lsbit < max_bit) { m_invalidate_regs_map[containing_reg_info->kinds[eRegisterKindLLDB]].push_back(i); m_value_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]); m_invalidate_regs_map[i].push_back(containing_reg_info->kinds[eRegisterKindLLDB]); if (byte_order == eByteOrderLittle) { success = true; reg_info.byte_offset = containing_reg_info->byte_offset + lsbyte; } else if (byte_order == eByteOrderBig) { success = true; reg_info.byte_offset = containing_reg_info->byte_offset + msbyte; } else { assert(!"Invalid byte order"); } } else { if (msbit > max_bit) printf("error: msbit (%u) must be less than the bitsize of the register (%u)\n", msbit, max_bit); else printf("error: lsbit (%u) must be less than the bitsize of the register (%u)\n", lsbit, max_bit); } } else { printf("error: invalid concrete register \"%s\"\n", containing_reg_name.GetCString()); } } else { printf("error: msbit (%u) must be greater than lsbit (%u)\n", msbit, lsbit); } } else { printf("error: msbit (%u) and lsbit (%u) must be valid\n", msbit, lsbit); } } else { // TODO: print error invalid slice string that doesn't follow the format printf("error: failed to extract regex matches for parsing the register bitfield regex\n"); } } else { // TODO: print error invalid slice string that doesn't follow the format printf("error: failed to match against register bitfield regex\n"); } } else { PythonList composite_reg_list (reg_info_dict.GetItemForKey(composite_pystr)); if (composite_reg_list) { const size_t num_composite_regs = composite_reg_list.GetSize(); if (num_composite_regs > 0) { uint32_t composite_offset = UINT32_MAX; for (uint32_t composite_idx=0; composite_idx<num_composite_regs; ++composite_idx) { PythonString composite_reg_name_pystr(composite_reg_list.GetItemAtIndex(composite_idx)); if (composite_reg_name_pystr) { ConstString composite_reg_name(composite_reg_name_pystr.GetString()); if (composite_reg_name) { RegisterInfo *composite_reg_info = GetRegisterInfo (composite_reg_name); if (composite_reg_info) { if (composite_offset > composite_reg_info->byte_offset) composite_offset = composite_reg_info->byte_offset; m_value_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]); m_invalidate_regs_map[composite_reg_info->kinds[eRegisterKindLLDB]].push_back(i); m_invalidate_regs_map[i].push_back(composite_reg_info->kinds[eRegisterKindLLDB]); } else { // TODO: print error invalid slice string that doesn't follow the format printf("error: failed to find composite register by name: \"%s\"\n", composite_reg_name.GetCString()); } } else { printf("error: 'composite' key contained an empty string\n"); } } else { printf("error: 'composite' list value wasn't a python string\n"); } } if (composite_offset != UINT32_MAX) { reg_info.byte_offset = composite_offset; success = m_value_regs_map.find(i) != m_value_regs_map.end(); } else { printf("error: 'composite' registers must specify at least one real register\n"); } } else { printf("error: 'composite' list was empty\n"); } } } if (!success) { Clear(); return 0; } } const int64_t bitsize = reg_info_dict.GetItemForKeyAsInteger(bitsize_pystr, 0); if (bitsize == 0) { Clear(); return 0; } reg_info.byte_size = bitsize / 8; const char *format_cstr = reg_info_dict.GetItemForKeyAsString(format_pystr); if (format_cstr) { if (Args::StringToFormat(format_cstr, reg_info.format, NULL).Fail()) { Clear(); return 0; } } else { reg_info.format = (Format)reg_info_dict.GetItemForKeyAsInteger (format_pystr, eFormatHex); } const char *encoding_cstr = reg_info_dict.GetItemForKeyAsString(encoding_pystr); if (encoding_cstr) reg_info.encoding = Args::StringToEncoding (encoding_cstr, eEncodingUint); else reg_info.encoding = (Encoding)reg_info_dict.GetItemForKeyAsInteger (encoding_pystr, eEncodingUint); const int64_t set = reg_info_dict.GetItemForKeyAsInteger(set_pystr, -1); if (set >= m_sets.size()) { Clear(); return 0; } // Fill in the register numbers reg_info.kinds[lldb::eRegisterKindLLDB] = i; reg_info.kinds[lldb::eRegisterKindGDB] = i; reg_info.kinds[lldb::eRegisterKindGCC] = reg_info_dict.GetItemForKeyAsInteger(gcc_pystr, LLDB_INVALID_REGNUM); reg_info.kinds[lldb::eRegisterKindDWARF] = reg_info_dict.GetItemForKeyAsInteger(dwarf_pystr, LLDB_INVALID_REGNUM); const char *generic_cstr = reg_info_dict.GetItemForKeyAsString(generic_pystr); if (generic_cstr) reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister (generic_cstr); else reg_info.kinds[lldb::eRegisterKindGeneric] = reg_info_dict.GetItemForKeyAsInteger(generic_pystr, LLDB_INVALID_REGNUM); // Check if this register invalidates any other register values when it is modified PythonList invalidate_reg_list (reg_info_dict.GetItemForKey(invalidate_regs_pystr)); if (invalidate_reg_list) { const size_t num_regs = invalidate_reg_list.GetSize(); if (num_regs > 0) { for (uint32_t idx=0; idx<num_regs; ++idx) { PythonObject invalidate_reg_object (invalidate_reg_list.GetItemAtIndex(idx)); PythonString invalidate_reg_name_pystr(invalidate_reg_object); if (invalidate_reg_name_pystr) { ConstString invalidate_reg_name(invalidate_reg_name_pystr.GetString()); if (invalidate_reg_name) { RegisterInfo *invalidate_reg_info = GetRegisterInfo (invalidate_reg_name); if (invalidate_reg_info) { m_invalidate_regs_map[i].push_back(invalidate_reg_info->kinds[eRegisterKindLLDB]); } else { // TODO: print error invalid slice string that doesn't follow the format printf("error: failed to find a 'invalidate-regs' register for \"%s\" while parsing register \"%s\"\n", invalidate_reg_name.GetCString(), reg_info.name); } } else { printf("error: 'invalidate-regs' list value was an empty string\n"); } } else { PythonInteger invalidate_reg_num(invalidate_reg_object); if (invalidate_reg_num) { const int64_t r = invalidate_reg_num.GetInteger(); if (r != UINT64_MAX) m_invalidate_regs_map[i].push_back(r); else printf("error: 'invalidate-regs' list value wasn't a valid integer\n"); } else { printf("error: 'invalidate-regs' list value wasn't a python string or integer\n"); } } } } else { printf("error: 'invalidate-regs' contained an empty list\n"); } } // Calculate the register offset const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size; if (m_reg_data_byte_size < end_reg_offset) m_reg_data_byte_size = end_reg_offset; m_regs.push_back (reg_info); m_set_reg_nums[set].push_back(i); } else { Clear(); return 0; } } Finalize (); } #endif return m_regs.size(); }
OptionValueSP Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type) { bool done = false; char buffer[1024]; OptionValueSP option_value_sp (new OptionValueArray (1u << data_type)); int idx = 0; while (!done) { if (!fgets (buffer, 1023, in_file)) { out_stream->Printf ("Instruction::ReadArray: Error reading file (fgets).\n"); option_value_sp.reset (); return option_value_sp; } std::string line (buffer); size_t len = line.size(); if (line[len-1] == '\n') { line[len-1] = '\0'; line.resize (len-1); } if ((line.size() == 1) && line[0] == ']') { done = true; line.clear(); } if (line.size() > 0) { std::string value; static RegularExpression g_reg_exp ("^[ \t]*([^ \t]+)[ \t]*$"); RegularExpression::Match regex_match(1); bool reg_exp_success = g_reg_exp.Execute (line.c_str(), ®ex_match); if (reg_exp_success) regex_match.GetMatchAtIndex (line.c_str(), 1, value); else value = line; OptionValueSP data_value_sp; switch (data_type) { case OptionValue::eTypeUInt64: data_value_sp.reset (new OptionValueUInt64 (0, 0)); data_value_sp->SetValueFromString (value); break; // Other types can be added later as needed. default: data_value_sp.reset (new OptionValueString (value.c_str(), "")); break; } option_value_sp->GetAsArray()->InsertValue (idx, data_value_sp); ++idx; } } return option_value_sp; }
OptionValueSP Instruction::ReadDictionary (FILE *in_file, Stream *out_stream) { bool done = false; char buffer[1024]; OptionValueSP option_value_sp (new OptionValueDictionary()); static ConstString encoding_key ("data_encoding"); OptionValue::Type data_type = OptionValue::eTypeInvalid; while (!done) { // Read the next line in the file if (!fgets (buffer, 1023, in_file)) { out_stream->Printf ("Instruction::ReadDictionary: Error reading file (fgets).\n"); option_value_sp.reset (); return option_value_sp; } // Check to see if the line contains the end-of-dictionary marker ("}") std::string line (buffer); size_t len = line.size(); if (line[len-1] == '\n') { line[len-1] = '\0'; line.resize (len-1); } if ((line.size() == 1) && (line[0] == '}')) { done = true; line.clear(); } // Try to find a key-value pair in the current line and add it to the dictionary. if (line.size() > 0) { static RegularExpression g_reg_exp ("^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$"); RegularExpression::Match regex_match(2); bool reg_exp_success = g_reg_exp.Execute (line.c_str(), ®ex_match); std::string key; std::string value; if (reg_exp_success) { regex_match.GetMatchAtIndex (line.c_str(), 1, key); regex_match.GetMatchAtIndex (line.c_str(), 2, value); } else { out_stream->Printf ("Instruction::ReadDictionary: Failure executing regular expression.\n"); option_value_sp.reset(); return option_value_sp; } ConstString const_key (key.c_str()); // Check value to see if it's the start of an array or dictionary. lldb::OptionValueSP value_sp; assert (value.empty() == false); assert (key.empty() == false); if (value[0] == '{') { assert (value.size() == 1); // value is a dictionary value_sp = ReadDictionary (in_file, out_stream); if (value_sp.get() == NULL) { option_value_sp.reset (); return option_value_sp; } } else if (value[0] == '[') { assert (value.size() == 1); // value is an array value_sp = ReadArray (in_file, out_stream, data_type); if (value_sp.get() == NULL) { option_value_sp.reset (); return option_value_sp; } // We've used the data_type to read an array; re-set the type to Invalid data_type = OptionValue::eTypeInvalid; } else if ((value[0] == '0') && (value[1] == 'x')) { value_sp.reset (new OptionValueUInt64 (0, 0)); value_sp->SetValueFromString (value); } else { size_t len = value.size(); if ((value[0] == '"') && (value[len-1] == '"')) value = value.substr (1, len-2); value_sp.reset (new OptionValueString (value.c_str(), "")); } if (const_key == encoding_key) { // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data indicating the // data type of an upcoming array (usually the next bit of data to be read in). if (strcmp (value.c_str(), "uint32_t") == 0) data_type = OptionValue::eTypeUInt64; } else option_value_sp->GetAsDictionary()->SetValueForKey (const_key, value_sp, false); } } return option_value_sp; }