[Lldb-commits] [lldb] r280751 - *** This commit represents a complete reformatting of the LLDB source code
Kate Stone via lldb-commits
lldb-commits at lists.llvm.org
Tue Sep 6 13:58:36 PDT 2016
Modified: lldb/trunk/source/Core/Disassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Disassembler.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Core/Disassembler.cpp (original)
+++ lldb/trunk/source/Core/Disassembler.cpp Tue Sep 6 15:57:50 2016
@@ -45,1271 +45,1042 @@
using namespace lldb;
using namespace lldb_private;
-DisassemblerSP
-Disassembler::FindPlugin (const ArchSpec &arch, const char *flavor, const char *plugin_name)
-{
- Timer scoped_timer (LLVM_PRETTY_FUNCTION,
- "Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
- arch.GetArchitectureName(),
- plugin_name);
-
- DisassemblerCreateInstance create_callback = nullptr;
-
- if (plugin_name)
- {
- ConstString const_plugin_name (plugin_name);
- create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName (const_plugin_name);
- if (create_callback)
- {
- DisassemblerSP disassembler_sp(create_callback(arch, flavor));
-
- if (disassembler_sp)
- return disassembler_sp;
- }
- }
- else
- {
- for (uint32_t idx = 0; (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(idx)) != nullptr; ++idx)
- {
- DisassemblerSP disassembler_sp(create_callback(arch, flavor));
-
- if (disassembler_sp)
- return disassembler_sp;
- }
- }
- return DisassemblerSP();
-}
-
-DisassemblerSP
-Disassembler::FindPluginForTarget(const TargetSP target_sp, const ArchSpec &arch, const char *flavor, const char *plugin_name)
-{
- if (target_sp && flavor == nullptr)
- {
- // FIXME - we don't have the mechanism in place to do per-architecture settings. But since we know that for now
- // we only support flavors on x86 & x86_64,
- if (arch.GetTriple().getArch() == llvm::Triple::x86
- || arch.GetTriple().getArch() == llvm::Triple::x86_64)
- flavor = target_sp->GetDisassemblyFlavor();
- }
- return FindPlugin(arch, flavor, plugin_name);
-}
-
-static void
-ResolveAddress (const ExecutionContext &exe_ctx,
- const Address &addr,
- Address &resolved_addr)
-{
- if (!addr.IsSectionOffset())
- {
- // If we weren't passed in a section offset address range,
- // try and resolve it to something
- Target *target = exe_ctx.GetTargetPtr();
- if (target)
- {
- if (target->GetSectionLoadList().IsEmpty())
- {
- target->GetImages().ResolveFileAddress (addr.GetOffset(), resolved_addr);
- }
- else
- {
- target->GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), resolved_addr);
- }
- // We weren't able to resolve the address, just treat it as a
- // raw address
- if (resolved_addr.IsValid())
- return;
- }
+DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch,
+ const char *flavor,
+ const char *plugin_name) {
+ Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ "Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
+ arch.GetArchitectureName(), plugin_name);
+
+ DisassemblerCreateInstance create_callback = nullptr;
+
+ if (plugin_name) {
+ ConstString const_plugin_name(plugin_name);
+ create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName(
+ const_plugin_name);
+ if (create_callback) {
+ DisassemblerSP disassembler_sp(create_callback(arch, flavor));
+
+ if (disassembler_sp)
+ return disassembler_sp;
+ }
+ } else {
+ for (uint32_t idx = 0;
+ (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(
+ idx)) != nullptr;
+ ++idx) {
+ DisassemblerSP disassembler_sp(create_callback(arch, flavor));
+
+ if (disassembler_sp)
+ return disassembler_sp;
+ }
+ }
+ return DisassemblerSP();
+}
+
+DisassemblerSP Disassembler::FindPluginForTarget(const TargetSP target_sp,
+ const ArchSpec &arch,
+ const char *flavor,
+ const char *plugin_name) {
+ if (target_sp && flavor == nullptr) {
+ // FIXME - we don't have the mechanism in place to do per-architecture
+ // settings. But since we know that for now
+ // we only support flavors on x86 & x86_64,
+ if (arch.GetTriple().getArch() == llvm::Triple::x86 ||
+ arch.GetTriple().getArch() == llvm::Triple::x86_64)
+ flavor = target_sp->GetDisassemblyFlavor();
+ }
+ return FindPlugin(arch, flavor, plugin_name);
+}
+
+static void ResolveAddress(const ExecutionContext &exe_ctx, const Address &addr,
+ Address &resolved_addr) {
+ if (!addr.IsSectionOffset()) {
+ // If we weren't passed in a section offset address range,
+ // try and resolve it to something
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target) {
+ if (target->GetSectionLoadList().IsEmpty()) {
+ target->GetImages().ResolveFileAddress(addr.GetOffset(), resolved_addr);
+ } else {
+ target->GetSectionLoadList().ResolveLoadAddress(addr.GetOffset(),
+ resolved_addr);
+ }
+ // We weren't able to resolve the address, just treat it as a
+ // raw address
+ if (resolved_addr.IsValid())
+ return;
}
- resolved_addr = addr;
+ }
+ resolved_addr = addr;
}
-size_t
-Disassembler::Disassemble(Debugger &debugger,
- const ArchSpec &arch,
- const char *plugin_name,
- const char *flavor,
- const ExecutionContext &exe_ctx,
- SymbolContextList &sc_list,
- uint32_t num_instructions,
- uint32_t num_mixed_context_lines,
- uint32_t options,
- Stream &strm)
-{
- size_t success_count = 0;
- const size_t count = sc_list.GetSize();
- SymbolContext sc;
- AddressRange range;
- const uint32_t scope = eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol;
- const bool use_inline_block_range = true;
- for (size_t i = 0; i < count; ++i)
- {
- if (!sc_list.GetContextAtIndex(i, sc))
- break;
- for (uint32_t range_idx = 0; sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); ++range_idx)
- {
- if (Disassemble (debugger,
- arch,
- plugin_name,
- flavor,
- exe_ctx,
- range,
- num_instructions,
- num_mixed_context_lines,
- options,
- strm))
- {
- ++success_count;
- strm.EOL();
- }
- }
+size_t Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
+ const char *plugin_name, const char *flavor,
+ const ExecutionContext &exe_ctx,
+ SymbolContextList &sc_list,
+ uint32_t num_instructions,
+ uint32_t num_mixed_context_lines,
+ uint32_t options, Stream &strm) {
+ size_t success_count = 0;
+ const size_t count = sc_list.GetSize();
+ SymbolContext sc;
+ AddressRange range;
+ const uint32_t scope =
+ eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol;
+ const bool use_inline_block_range = true;
+ for (size_t i = 0; i < count; ++i) {
+ if (!sc_list.GetContextAtIndex(i, sc))
+ break;
+ for (uint32_t range_idx = 0;
+ sc.GetAddressRange(scope, range_idx, use_inline_block_range, range);
+ ++range_idx) {
+ if (Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range,
+ num_instructions, num_mixed_context_lines, options,
+ strm)) {
+ ++success_count;
+ strm.EOL();
+ }
}
- return success_count;
+ }
+ return success_count;
}
-bool
-Disassembler::Disassemble(Debugger &debugger,
- const ArchSpec &arch,
- const char *plugin_name,
- const char *flavor,
- const ExecutionContext &exe_ctx,
- const ConstString &name,
- Module *module,
- uint32_t num_instructions,
- uint32_t num_mixed_context_lines,
- uint32_t options,
- Stream &strm)
-{
- SymbolContextList sc_list;
- if (name)
- {
- const bool include_symbols = true;
- const bool include_inlines = true;
- if (module)
- {
- module->FindFunctions(name,
- nullptr,
- eFunctionNameTypeAuto,
- include_symbols,
- include_inlines,
- true,
- sc_list);
- }
- else if (exe_ctx.GetTargetPtr())
- {
- exe_ctx.GetTargetPtr()->GetImages().FindFunctions (name,
- eFunctionNameTypeAuto,
- include_symbols,
- include_inlines,
- false,
- sc_list);
- }
- }
-
- if (sc_list.GetSize ())
- {
- return Disassemble (debugger,
- arch,
- plugin_name,
- flavor,
- exe_ctx,
- sc_list,
- num_instructions,
- num_mixed_context_lines,
- options,
- strm);
+bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
+ const char *plugin_name, const char *flavor,
+ const ExecutionContext &exe_ctx,
+ const ConstString &name, Module *module,
+ uint32_t num_instructions,
+ uint32_t num_mixed_context_lines,
+ uint32_t options, Stream &strm) {
+ SymbolContextList sc_list;
+ if (name) {
+ const bool include_symbols = true;
+ const bool include_inlines = true;
+ if (module) {
+ module->FindFunctions(name, nullptr, eFunctionNameTypeAuto,
+ include_symbols, include_inlines, true, sc_list);
+ } else if (exe_ctx.GetTargetPtr()) {
+ exe_ctx.GetTargetPtr()->GetImages().FindFunctions(
+ name, eFunctionNameTypeAuto, include_symbols, include_inlines, false,
+ sc_list);
+ }
+ }
+
+ if (sc_list.GetSize()) {
+ return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, sc_list,
+ num_instructions, num_mixed_context_lines, options,
+ strm);
+ }
+ return false;
+}
+
+lldb::DisassemblerSP Disassembler::DisassembleRange(
+ const ArchSpec &arch, const char *plugin_name, const char *flavor,
+ const ExecutionContext &exe_ctx, const AddressRange &range,
+ bool prefer_file_cache) {
+ lldb::DisassemblerSP disasm_sp;
+ if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid()) {
+ disasm_sp = Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch,
+ flavor, plugin_name);
+
+ if (disasm_sp) {
+ size_t bytes_disassembled = disasm_sp->ParseInstructions(
+ &exe_ctx, range, nullptr, prefer_file_cache);
+ if (bytes_disassembled == 0)
+ disasm_sp.reset();
}
- return false;
+ }
+ return disasm_sp;
}
lldb::DisassemblerSP
-Disassembler::DisassembleRange(const ArchSpec &arch,
- const char *plugin_name,
- const char *flavor,
- const ExecutionContext &exe_ctx,
- const AddressRange &range,
- bool prefer_file_cache)
-{
- lldb::DisassemblerSP disasm_sp;
- if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid())
- {
- disasm_sp = Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, flavor, plugin_name);
-
- if (disasm_sp)
- {
- size_t bytes_disassembled = disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache);
- if (bytes_disassembled == 0)
- disasm_sp.reset();
- }
- }
- return disasm_sp;
-}
+Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name,
+ const char *flavor, const Address &start,
+ const void *src, size_t src_len,
+ uint32_t num_instructions, bool data_from_file) {
+ lldb::DisassemblerSP disasm_sp;
-lldb::DisassemblerSP
-Disassembler::DisassembleBytes (const ArchSpec &arch,
- const char *plugin_name,
- const char *flavor,
- const Address &start,
- const void *src,
- size_t src_len,
- uint32_t num_instructions,
- bool data_from_file)
-{
- lldb::DisassemblerSP disasm_sp;
-
- if (src)
- {
- disasm_sp = Disassembler::FindPlugin(arch, flavor, plugin_name);
-
- if (disasm_sp)
- {
- DataExtractor data(src, src_len, arch.GetByteOrder(), arch.GetAddressByteSize());
-
- (void)disasm_sp->DecodeInstructions (start,
- data,
- 0,
- num_instructions,
- false,
- data_from_file);
- }
- }
-
- return disasm_sp;
-}
+ if (src) {
+ disasm_sp = Disassembler::FindPlugin(arch, flavor, plugin_name);
-bool
-Disassembler::Disassemble(Debugger &debugger,
- const ArchSpec &arch,
- const char *plugin_name,
- const char *flavor,
- const ExecutionContext &exe_ctx,
- const AddressRange &disasm_range,
- uint32_t num_instructions,
- uint32_t num_mixed_context_lines,
- uint32_t options,
- Stream &strm)
-{
- if (disasm_range.GetByteSize())
- {
- lldb::DisassemblerSP disasm_sp (Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, flavor, plugin_name));
-
- if (disasm_sp)
- {
- AddressRange range;
- ResolveAddress (exe_ctx, disasm_range.GetBaseAddress(), range.GetBaseAddress());
- range.SetByteSize (disasm_range.GetByteSize());
- const bool prefer_file_cache = false;
- size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, &strm, prefer_file_cache);
- if (bytes_disassembled == 0)
- return false;
+ if (disasm_sp) {
+ DataExtractor data(src, src_len, arch.GetByteOrder(),
+ arch.GetAddressByteSize());
- return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, num_instructions,
- num_mixed_context_lines, options, strm);
- }
+ (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions,
+ false, data_from_file);
}
- return false;
+ }
+
+ return disasm_sp;
}
-
-bool
-Disassembler::Disassemble(Debugger &debugger,
- const ArchSpec &arch,
- const char *plugin_name,
- const char *flavor,
- const ExecutionContext &exe_ctx,
- const Address &start_address,
- uint32_t num_instructions,
- uint32_t num_mixed_context_lines,
- uint32_t options,
- Stream &strm)
-{
- if (num_instructions > 0)
- {
- lldb::DisassemblerSP disasm_sp (Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(),
- arch,
- flavor,
- plugin_name));
- if (disasm_sp)
- {
- Address addr;
- ResolveAddress (exe_ctx, start_address, addr);
- const bool prefer_file_cache = false;
- size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx,
- addr,
- num_instructions,
- prefer_file_cache);
- if (bytes_disassembled == 0)
- return false;
- return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, num_instructions,
- num_mixed_context_lines, options, strm);
- }
+
+bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
+ const char *plugin_name, const char *flavor,
+ const ExecutionContext &exe_ctx,
+ const AddressRange &disasm_range,
+ uint32_t num_instructions,
+ uint32_t num_mixed_context_lines,
+ uint32_t options, Stream &strm) {
+ if (disasm_range.GetByteSize()) {
+ lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget(
+ exe_ctx.GetTargetSP(), arch, flavor, plugin_name));
+
+ if (disasm_sp) {
+ AddressRange range;
+ ResolveAddress(exe_ctx, disasm_range.GetBaseAddress(),
+ range.GetBaseAddress());
+ range.SetByteSize(disasm_range.GetByteSize());
+ const bool prefer_file_cache = false;
+ size_t bytes_disassembled = disasm_sp->ParseInstructions(
+ &exe_ctx, range, &strm, prefer_file_cache);
+ if (bytes_disassembled == 0)
+ return false;
+
+ return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx,
+ num_instructions, num_mixed_context_lines,
+ options, strm);
}
- return false;
+ }
+ return false;
}
-bool
-Disassembler::PrintInstructions(Disassembler *disasm_ptr, Debugger &debugger, const ArchSpec &arch,
- const ExecutionContext &exe_ctx, uint32_t num_instructions,
- uint32_t num_mixed_context_lines, uint32_t options, Stream &strm)
-{
- // We got some things disassembled...
- size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
-
- if (num_instructions > 0 && num_instructions < num_instructions_found)
- num_instructions_found = num_instructions;
-
- const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize ();
- uint32_t offset = 0;
- SymbolContext sc;
- SymbolContext prev_sc;
- AddressRange sc_range;
- const Address *pc_addr_ptr = nullptr;
- StackFrame *frame = exe_ctx.GetFramePtr();
-
- TargetSP target_sp (exe_ctx.GetTargetSP());
- SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager();
-
- if (frame)
- {
- pc_addr_ptr = &frame->GetFrameCodeAddress();
- }
- const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
- const bool use_inline_block_range = false;
-
- const FormatEntity::Entry *disassembly_format = nullptr;
- FormatEntity::Entry format;
- if (exe_ctx.HasTargetScope())
- {
- disassembly_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat ();
- }
- else
- {
- FormatEntity::Parse("${addr}: ", format);
- disassembly_format = &format;
- }
-
- // First pass: step through the list of instructions,
- // find how long the initial addresses strings are, insert padding
- // in the second pass so the opcodes all line up nicely.
- size_t address_text_size = 0;
- for (size_t i = 0; i < num_instructions_found; ++i)
- {
- Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
- if (inst)
- {
- const Address &addr = inst->GetAddress();
- ModuleSP module_sp (addr.GetModule());
- if (module_sp)
- {
- const uint32_t resolve_mask = eSymbolContextFunction | eSymbolContextSymbol;
- uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc);
- if (resolved_mask)
- {
- StreamString strmstr;
- Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr, &exe_ctx, &addr, strmstr);
- size_t cur_line = strmstr.GetSizeOfLastLine();
- if (cur_line > address_text_size)
- address_text_size = cur_line;
- }
- sc.Clear(false);
- }
- }
- }
+bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
+ const char *plugin_name, const char *flavor,
+ const ExecutionContext &exe_ctx,
+ const Address &start_address,
+ uint32_t num_instructions,
+ uint32_t num_mixed_context_lines,
+ uint32_t options, Stream &strm) {
+ if (num_instructions > 0) {
+ lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget(
+ exe_ctx.GetTargetSP(), arch, flavor, plugin_name));
+ if (disasm_sp) {
+ Address addr;
+ ResolveAddress(exe_ctx, start_address, addr);
+ const bool prefer_file_cache = false;
+ size_t bytes_disassembled = disasm_sp->ParseInstructions(
+ &exe_ctx, addr, num_instructions, prefer_file_cache);
+ if (bytes_disassembled == 0)
+ return false;
+ return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx,
+ num_instructions, num_mixed_context_lines,
+ options, strm);
+ }
+ }
+ return false;
+}
+
+bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
+ Debugger &debugger, const ArchSpec &arch,
+ const ExecutionContext &exe_ctx,
+ uint32_t num_instructions,
+ uint32_t num_mixed_context_lines,
+ uint32_t options, Stream &strm) {
+ // We got some things disassembled...
+ size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
+
+ if (num_instructions > 0 && num_instructions < num_instructions_found)
+ num_instructions_found = num_instructions;
+
+ const uint32_t max_opcode_byte_size =
+ disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize();
+ uint32_t offset = 0;
+ SymbolContext sc;
+ SymbolContext prev_sc;
+ AddressRange sc_range;
+ const Address *pc_addr_ptr = nullptr;
+ StackFrame *frame = exe_ctx.GetFramePtr();
+
+ TargetSP target_sp(exe_ctx.GetTargetSP());
+ SourceManager &source_manager =
+ target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager();
+
+ if (frame) {
+ pc_addr_ptr = &frame->GetFrameCodeAddress();
+ }
+ const uint32_t scope =
+ eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
+ const bool use_inline_block_range = false;
+
+ const FormatEntity::Entry *disassembly_format = nullptr;
+ FormatEntity::Entry format;
+ if (exe_ctx.HasTargetScope()) {
+ disassembly_format =
+ exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat();
+ } else {
+ FormatEntity::Parse("${addr}: ", format);
+ disassembly_format = &format;
+ }
+
+ // First pass: step through the list of instructions,
+ // find how long the initial addresses strings are, insert padding
+ // in the second pass so the opcodes all line up nicely.
+ size_t address_text_size = 0;
+ for (size_t i = 0; i < num_instructions_found; ++i) {
+ Instruction *inst =
+ disasm_ptr->GetInstructionList().GetInstructionAtIndex(i).get();
+ if (inst) {
+ const Address &addr = inst->GetAddress();
+ ModuleSP module_sp(addr.GetModule());
+ if (module_sp) {
+ const uint32_t resolve_mask =
+ eSymbolContextFunction | eSymbolContextSymbol;
+ uint32_t resolved_mask =
+ module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc);
+ if (resolved_mask) {
+ StreamString strmstr;
+ Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr,
+ &exe_ctx, &addr, strmstr);
+ size_t cur_line = strmstr.GetSizeOfLastLine();
+ if (cur_line > address_text_size)
+ address_text_size = cur_line;
+ }
+ sc.Clear(false);
+ }
+ }
+ }
+
+ for (size_t i = 0; i < num_instructions_found; ++i) {
+ Instruction *inst =
+ disasm_ptr->GetInstructionList().GetInstructionAtIndex(i).get();
+ if (inst) {
+ const Address &addr = inst->GetAddress();
+ const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
+
+ prev_sc = sc;
+
+ ModuleSP module_sp(addr.GetModule());
+ if (module_sp) {
+ uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(
+ addr, eSymbolContextEverything, sc);
+ if (resolved_mask) {
+ if (num_mixed_context_lines) {
+ if (!sc_range.ContainsFileAddress(addr)) {
+ sc.GetAddressRange(scope, 0, use_inline_block_range, sc_range);
+
+ if (sc != prev_sc) {
+ if (offset != 0)
+ strm.EOL();
- for (size_t i = 0; i < num_instructions_found; ++i)
- {
- Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
- if (inst)
- {
- const Address &addr = inst->GetAddress();
- const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
-
- prev_sc = sc;
-
- ModuleSP module_sp (addr.GetModule());
- if (module_sp)
- {
- uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
- if (resolved_mask)
- {
- if (num_mixed_context_lines)
- {
- if (!sc_range.ContainsFileAddress (addr))
- {
- sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range);
-
- if (sc != prev_sc)
- {
- if (offset != 0)
- strm.EOL();
-
- sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false, false, true);
- strm.EOL();
-
- if (sc.comp_unit && sc.line_entry.IsValid())
- {
- source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
- sc.line_entry.line,
- num_mixed_context_lines,
- num_mixed_context_lines,
- ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""),
- &strm);
- }
- }
- }
- }
- }
- else
- {
- sc.Clear(true);
+ sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false,
+ true, false, false, true);
+ strm.EOL();
+
+ if (sc.comp_unit && sc.line_entry.IsValid()) {
+ source_manager.DisplaySourceLinesWithLineNumbers(
+ sc.line_entry.file, sc.line_entry.line,
+ num_mixed_context_lines, num_mixed_context_lines,
+ ((inst_is_at_pc && (options & eOptionMarkPCSourceLine))
+ ? "->"
+ : ""),
+ &strm);
}
+ }
}
-
- const bool show_bytes = (options & eOptionShowBytes) != 0;
- inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, &prev_sc, nullptr, address_text_size);
- strm.EOL();
- }
- else
- {
- break;
- }
- }
-
- return true;
-}
-
-bool
-Disassembler::Disassemble(Debugger &debugger,
- const ArchSpec &arch,
- const char *plugin_name,
- const char *flavor,
- const ExecutionContext &exe_ctx,
- uint32_t num_instructions,
- uint32_t num_mixed_context_lines,
- uint32_t options,
- Stream &strm)
-{
- AddressRange range;
- StackFrame *frame = exe_ctx.GetFramePtr();
- if (frame)
- {
- SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
- if (sc.function)
- {
- range = sc.function->GetAddressRange();
- }
- else if (sc.symbol && sc.symbol->ValueIsAddress())
- {
- range.GetBaseAddress() = sc.symbol->GetAddressRef();
- range.SetByteSize (sc.symbol->GetByteSize());
- }
- else
- {
- range.GetBaseAddress() = frame->GetFrameCodeAddress();
+ }
+ } else {
+ sc.Clear(true);
}
+ }
- if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
- range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
+ const bool show_bytes = (options & eOptionShowBytes) != 0;
+ inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc,
+ &prev_sc, nullptr, address_text_size);
+ strm.EOL();
+ } else {
+ break;
}
+ }
- return Disassemble (debugger,
- arch,
- plugin_name,
- flavor,
- exe_ctx,
- range,
- num_instructions,
- num_mixed_context_lines,
- options,
- strm);
-}
-
-Instruction::Instruction(const Address &address, AddressClass addr_class) :
- m_address (address),
- m_address_class (addr_class),
- m_opcode(),
- m_calculated_strings(false)
-{
+ return true;
}
+bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
+ const char *plugin_name, const char *flavor,
+ const ExecutionContext &exe_ctx,
+ uint32_t num_instructions,
+ uint32_t num_mixed_context_lines,
+ uint32_t options, Stream &strm) {
+ AddressRange range;
+ StackFrame *frame = exe_ctx.GetFramePtr();
+ if (frame) {
+ SymbolContext sc(
+ frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
+ if (sc.function) {
+ range = sc.function->GetAddressRange();
+ } else if (sc.symbol && sc.symbol->ValueIsAddress()) {
+ range.GetBaseAddress() = sc.symbol->GetAddressRef();
+ range.SetByteSize(sc.symbol->GetByteSize());
+ } else {
+ range.GetBaseAddress() = frame->GetFrameCodeAddress();
+ }
+
+ if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
+ range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
+ }
+
+ return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range,
+ num_instructions, num_mixed_context_lines, options, strm);
+}
+
+Instruction::Instruction(const Address &address, AddressClass addr_class)
+ : m_address(address), m_address_class(addr_class), m_opcode(),
+ m_calculated_strings(false) {}
+
Instruction::~Instruction() = default;
-AddressClass
-Instruction::GetAddressClass ()
-{
- if (m_address_class == eAddressClassInvalid)
- m_address_class = m_address.GetAddressClass();
- return m_address_class;
-}
-
-void
-Instruction::Dump (lldb_private::Stream *s,
- uint32_t max_opcode_byte_size,
- bool show_address,
- bool show_bytes,
- const ExecutionContext* exe_ctx,
- const SymbolContext *sym_ctx,
- const SymbolContext *prev_sym_ctx,
- const FormatEntity::Entry *disassembly_addr_format,
- size_t max_address_text_size)
-{
- size_t opcode_column_width = 7;
- const size_t operand_column_width = 25;
-
- CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx);
-
- StreamString ss;
-
- if (show_address)
- {
- Debugger::FormatDisassemblerAddress (disassembly_addr_format, sym_ctx, prev_sym_ctx, exe_ctx, &m_address, ss);
- ss.FillLastLineToColumn (max_address_text_size, ' ');
- }
-
- if (show_bytes)
- {
- if (m_opcode.GetType() == Opcode::eTypeBytes)
- {
- // x86_64 and i386 are the only ones that use bytes right now so
- // pad out the byte dump to be able to always show 15 bytes (3 chars each)
- // plus a space
- if (max_opcode_byte_size > 0)
- m_opcode.Dump (&ss, max_opcode_byte_size * 3 + 1);
- else
- m_opcode.Dump (&ss, 15 * 3 + 1);
- }
- else
- {
- // Else, we have ARM or MIPS which can show up to a uint32_t
- // 0x00000000 (10 spaces) plus two for padding...
- if (max_opcode_byte_size > 0)
- m_opcode.Dump (&ss, max_opcode_byte_size * 3 + 1);
- else
- m_opcode.Dump (&ss, 12);
- }
- }
-
- const size_t opcode_pos = ss.GetSizeOfLastLine();
-
- // The default opcode size of 7 characters is plenty for most architectures
- // but some like arm can pull out the occasional vqrshrun.s16. We won't get
- // consistent column spacing in these cases, unfortunately.
- if (m_opcode_name.length() >= opcode_column_width)
- {
- opcode_column_width = m_opcode_name.length() + 1;
- }
-
- ss.PutCString (m_opcode_name.c_str());
- ss.FillLastLineToColumn (opcode_pos + opcode_column_width, ' ');
- ss.PutCString (m_mnemonics.c_str());
-
- if (!m_comment.empty())
- {
- ss.FillLastLineToColumn (opcode_pos + opcode_column_width + operand_column_width, ' ');
- ss.PutCString (" ; ");
- ss.PutCString (m_comment.c_str());
- }
- s->Write (ss.GetData(), ss.GetSize());
-}
-
-bool
-Instruction::DumpEmulation (const ArchSpec &arch)
-{
- std::unique_ptr<EmulateInstruction> insn_emulator_ap(EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
- if (insn_emulator_ap)
- {
- insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr);
- return insn_emulator_ap->EvaluateInstruction (0);
+AddressClass Instruction::GetAddressClass() {
+ if (m_address_class == eAddressClassInvalid)
+ m_address_class = m_address.GetAddressClass();
+ return m_address_class;
+}
+
+void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size,
+ bool show_address, bool show_bytes,
+ const ExecutionContext *exe_ctx,
+ const SymbolContext *sym_ctx,
+ const SymbolContext *prev_sym_ctx,
+ const FormatEntity::Entry *disassembly_addr_format,
+ size_t max_address_text_size) {
+ size_t opcode_column_width = 7;
+ const size_t operand_column_width = 25;
+
+ CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx);
+
+ StreamString ss;
+
+ if (show_address) {
+ Debugger::FormatDisassemblerAddress(disassembly_addr_format, sym_ctx,
+ prev_sym_ctx, exe_ctx, &m_address, ss);
+ ss.FillLastLineToColumn(max_address_text_size, ' ');
+ }
+
+ if (show_bytes) {
+ if (m_opcode.GetType() == Opcode::eTypeBytes) {
+ // x86_64 and i386 are the only ones that use bytes right now so
+ // pad out the byte dump to be able to always show 15 bytes (3 chars each)
+ // plus a space
+ if (max_opcode_byte_size > 0)
+ m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
+ else
+ m_opcode.Dump(&ss, 15 * 3 + 1);
+ } else {
+ // Else, we have ARM or MIPS which can show up to a uint32_t
+ // 0x00000000 (10 spaces) plus two for padding...
+ if (max_opcode_byte_size > 0)
+ m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
+ else
+ m_opcode.Dump(&ss, 12);
+ }
+ }
+
+ const size_t opcode_pos = ss.GetSizeOfLastLine();
+
+ // The default opcode size of 7 characters is plenty for most architectures
+ // but some like arm can pull out the occasional vqrshrun.s16. We won't get
+ // consistent column spacing in these cases, unfortunately.
+ if (m_opcode_name.length() >= opcode_column_width) {
+ opcode_column_width = m_opcode_name.length() + 1;
+ }
+
+ ss.PutCString(m_opcode_name.c_str());
+ ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' ');
+ ss.PutCString(m_mnemonics.c_str());
+
+ if (!m_comment.empty()) {
+ ss.FillLastLineToColumn(
+ opcode_pos + opcode_column_width + operand_column_width, ' ');
+ ss.PutCString(" ; ");
+ ss.PutCString(m_comment.c_str());
+ }
+ s->Write(ss.GetData(), ss.GetSize());
+}
+
+bool Instruction::DumpEmulation(const ArchSpec &arch) {
+ std::unique_ptr<EmulateInstruction> insn_emulator_ap(
+ EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
+ if (insn_emulator_ap) {
+ insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr);
+ return insn_emulator_ap->EvaluateInstruction(0);
+ }
+
+ return false;
+}
+
+bool Instruction::HasDelaySlot() {
+ // Default is false.
+ return false;
+}
+
+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.empty()) {
+ 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.empty()) {
+ 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) {
+ 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) {
+ 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 false;
+ return option_value_sp;
}
-bool
-Instruction::HasDelaySlot ()
-{
- // Default is false.
+bool Instruction::TestEmulation(Stream *out_stream, const char *file_name) {
+ if (!out_stream)
return false;
-}
-
-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.empty())
- {
- 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;
- }
+ if (!file_name) {
+ out_stream->Printf("Instruction::TestEmulation: Missing file_name.");
+ return false;
+ }
+ FILE *test_file = FileSystem::Fopen(file_name, "r");
+ if (!test_file) {
+ out_stream->Printf(
+ "Instruction::TestEmulation: Attempt to open test file failed.");
+ return false;
+ }
- option_value_sp->GetAsArray()->InsertValue (idx, data_value_sp);
- ++idx;
- }
- }
-
- return option_value_sp;
-}
+ char buffer[256];
+ if (!fgets(buffer, 255, test_file)) {
+ out_stream->Printf(
+ "Instruction::TestEmulation: Error reading first line of test file.\n");
+ fclose(test_file);
+ return false;
+ }
-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.empty())
- {
- 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)
- {
- 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)
- {
- 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 (strncmp(buffer, "InstructionEmulationState={", 27) != 0) {
+ out_stream->Printf("Instructin::TestEmulation: Test file does not contain "
+ "emulation state dictionary\n");
+ fclose(test_file);
+ return false;
+ }
- 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;
-}
+ // Read all the test information from the test file into an
+ // OptionValueDictionary.
-bool
-Instruction::TestEmulation (Stream *out_stream, const char *file_name)
-{
- if (!out_stream)
- return false;
+ OptionValueSP data_dictionary_sp(ReadDictionary(test_file, out_stream));
+ if (!data_dictionary_sp) {
+ out_stream->Printf(
+ "Instruction::TestEmulation: Error reading Dictionary Object.\n");
+ fclose(test_file);
+ return false;
+ }
- if (!file_name)
- {
- out_stream->Printf ("Instruction::TestEmulation: Missing file_name.");
- return false;
- }
- FILE *test_file = FileSystem::Fopen(file_name, "r");
- if (!test_file)
- {
- out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed.");
- return false;
- }
+ fclose(test_file);
- char buffer[256];
- if (!fgets (buffer, 255, test_file))
- {
- out_stream->Printf ("Instruction::TestEmulation: Error reading first line of test file.\n");
- fclose (test_file);
- return false;
- }
-
- if (strncmp (buffer, "InstructionEmulationState={", 27) != 0)
- {
- out_stream->Printf ("Instructin::TestEmulation: Test file does not contain emulation state dictionary\n");
- fclose (test_file);
- return false;
- }
+ OptionValueDictionary *data_dictionary =
+ data_dictionary_sp->GetAsDictionary();
+ static ConstString description_key("assembly_string");
+ static ConstString triple_key("triple");
- // Read all the test information from the test file into an OptionValueDictionary.
+ OptionValueSP value_sp = data_dictionary->GetValueForKey(description_key);
- OptionValueSP data_dictionary_sp (ReadDictionary (test_file, out_stream));
- if (!data_dictionary_sp)
- {
- out_stream->Printf ("Instruction::TestEmulation: Error reading Dictionary Object.\n");
- fclose (test_file);
- return false;
- }
+ if (!value_sp) {
+ out_stream->Printf("Instruction::TestEmulation: Test file does not "
+ "contain description string.\n");
+ return false;
+ }
- fclose (test_file);
+ SetDescription(value_sp->GetStringValue());
- OptionValueDictionary *data_dictionary = data_dictionary_sp->GetAsDictionary();
- static ConstString description_key ("assembly_string");
- static ConstString triple_key ("triple");
-
- OptionValueSP value_sp = data_dictionary->GetValueForKey (description_key);
-
- if (!value_sp)
- {
- out_stream->Printf ("Instruction::TestEmulation: Test file does not contain description string.\n");
- return false;
- }
+ value_sp = data_dictionary->GetValueForKey(triple_key);
+ if (!value_sp) {
+ out_stream->Printf(
+ "Instruction::TestEmulation: Test file does not contain triple.\n");
+ return false;
+ }
- SetDescription (value_sp->GetStringValue());
+ ArchSpec arch;
+ arch.SetTriple(llvm::Triple(value_sp->GetStringValue()));
- value_sp = data_dictionary->GetValueForKey (triple_key);
- if (!value_sp)
- {
- out_stream->Printf ("Instruction::TestEmulation: Test file does not contain triple.\n");
- return false;
- }
-
- ArchSpec arch;
- arch.SetTriple (llvm::Triple (value_sp->GetStringValue()));
-
- bool success = false;
- std::unique_ptr<EmulateInstruction> insn_emulator_ap(EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
- if (insn_emulator_ap)
- success = insn_emulator_ap->TestEmulation (out_stream, arch, data_dictionary);
-
- if (success)
- out_stream->Printf ("Emulation test succeeded.");
- else
- out_stream->Printf ("Emulation test failed.");
-
- return success;
-}
-
-bool
-Instruction::Emulate (const ArchSpec &arch,
- uint32_t evaluate_options,
- void *baton,
- EmulateInstruction::ReadMemoryCallback read_mem_callback,
- EmulateInstruction::WriteMemoryCallback write_mem_callback,
- EmulateInstruction::ReadRegisterCallback read_reg_callback,
- EmulateInstruction::WriteRegisterCallback write_reg_callback)
-{
- std::unique_ptr<EmulateInstruction> insn_emulator_ap(EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
- if (insn_emulator_ap)
- {
- insn_emulator_ap->SetBaton(baton);
- insn_emulator_ap->SetCallbacks(read_mem_callback, write_mem_callback, read_reg_callback, write_reg_callback);
- insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr);
- return insn_emulator_ap->EvaluateInstruction(evaluate_options);
- }
+ bool success = false;
+ std::unique_ptr<EmulateInstruction> insn_emulator_ap(
+ EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
+ if (insn_emulator_ap)
+ success =
+ insn_emulator_ap->TestEmulation(out_stream, arch, data_dictionary);
+
+ if (success)
+ out_stream->Printf("Emulation test succeeded.");
+ else
+ out_stream->Printf("Emulation test failed.");
+
+ return success;
+}
+
+bool Instruction::Emulate(
+ const ArchSpec &arch, uint32_t evaluate_options, void *baton,
+ EmulateInstruction::ReadMemoryCallback read_mem_callback,
+ EmulateInstruction::WriteMemoryCallback write_mem_callback,
+ EmulateInstruction::ReadRegisterCallback read_reg_callback,
+ EmulateInstruction::WriteRegisterCallback write_reg_callback) {
+ std::unique_ptr<EmulateInstruction> insn_emulator_ap(
+ EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
+ if (insn_emulator_ap) {
+ insn_emulator_ap->SetBaton(baton);
+ insn_emulator_ap->SetCallbacks(read_mem_callback, write_mem_callback,
+ read_reg_callback, write_reg_callback);
+ insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr);
+ return insn_emulator_ap->EvaluateInstruction(evaluate_options);
+ }
- return false;
+ return false;
}
-uint32_t
-Instruction::GetData (DataExtractor &data)
-{
- return m_opcode.GetData(data);
+uint32_t Instruction::GetData(DataExtractor &data) {
+ return m_opcode.GetData(data);
}
-InstructionList::InstructionList() :
- m_instructions()
-{
-}
+InstructionList::InstructionList() : m_instructions() {}
InstructionList::~InstructionList() = default;
-size_t
-InstructionList::GetSize() const
-{
- return m_instructions.size();
-}
+size_t InstructionList::GetSize() const { return m_instructions.size(); }
-uint32_t
-InstructionList::GetMaxOpcocdeByteSize () const
-{
- uint32_t max_inst_size = 0;
- collection::const_iterator pos, end;
- for (pos = m_instructions.begin(), end = m_instructions.end();
- pos != end;
- ++pos)
- {
- uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
- if (max_inst_size < inst_size)
- max_inst_size = inst_size;
- }
- return max_inst_size;
-}
-
-InstructionSP
-InstructionList::GetInstructionAtIndex (size_t idx) const
-{
- InstructionSP inst_sp;
- if (idx < m_instructions.size())
- inst_sp = m_instructions[idx];
- return inst_sp;
-}
-
-void
-InstructionList::Dump (Stream *s,
- bool show_address,
- bool show_bytes,
- const ExecutionContext* exe_ctx)
-{
- const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize();
- collection::const_iterator pos, begin, end;
-
- const FormatEntity::Entry *disassembly_format = nullptr;
- FormatEntity::Entry format;
- if (exe_ctx && exe_ctx->HasTargetScope())
- {
- disassembly_format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat ();
- }
- else
- {
- FormatEntity::Parse("${addr}: ", format);
- disassembly_format = &format;
- }
-
- for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin;
- pos != end;
- ++pos)
- {
- if (pos != begin)
- s->EOL();
- (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx, nullptr, nullptr, disassembly_format, 0);
- }
-}
-
-void
-InstructionList::Clear()
-{
- m_instructions.clear();
-}
-
-void
-InstructionList::Append (lldb::InstructionSP &inst_sp)
-{
- if (inst_sp)
- m_instructions.push_back(inst_sp);
+uint32_t InstructionList::GetMaxOpcocdeByteSize() const {
+ uint32_t max_inst_size = 0;
+ collection::const_iterator pos, end;
+ for (pos = m_instructions.begin(), end = m_instructions.end(); pos != end;
+ ++pos) {
+ uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
+ if (max_inst_size < inst_size)
+ max_inst_size = inst_size;
+ }
+ return max_inst_size;
+}
+
+InstructionSP InstructionList::GetInstructionAtIndex(size_t idx) const {
+ InstructionSP inst_sp;
+ if (idx < m_instructions.size())
+ inst_sp = m_instructions[idx];
+ return inst_sp;
+}
+
+void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes,
+ const ExecutionContext *exe_ctx) {
+ const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize();
+ collection::const_iterator pos, begin, end;
+
+ const FormatEntity::Entry *disassembly_format = nullptr;
+ FormatEntity::Entry format;
+ if (exe_ctx && exe_ctx->HasTargetScope()) {
+ disassembly_format =
+ exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
+ } else {
+ FormatEntity::Parse("${addr}: ", format);
+ disassembly_format = &format;
+ }
+
+ for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin;
+ pos != end; ++pos) {
+ if (pos != begin)
+ s->EOL();
+ (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx,
+ nullptr, nullptr, disassembly_format, 0);
+ }
+}
+
+void InstructionList::Clear() { m_instructions.clear(); }
+
+void InstructionList::Append(lldb::InstructionSP &inst_sp) {
+ if (inst_sp)
+ m_instructions.push_back(inst_sp);
}
uint32_t
-InstructionList::GetIndexOfNextBranchInstruction(uint32_t start, Target &target) const
-{
- size_t num_instructions = m_instructions.size();
-
- uint32_t next_branch = UINT32_MAX;
- size_t i;
- for (i = start; i < num_instructions; i++)
- {
- if (m_instructions[i]->DoesBranch())
- {
- next_branch = i;
- break;
- }
- }
-
- // Hexagon needs the first instruction of the packet with the branch.
- // Go backwards until we find an instruction marked end-of-packet, or
- // until we hit start.
- if (target.GetArchitecture().GetTriple().getArch() == llvm::Triple::hexagon)
- {
- // If we didn't find a branch, find the last packet start.
- if (next_branch == UINT32_MAX)
- {
- i = num_instructions - 1;
- }
-
- while (i > start)
- {
- --i;
-
- Error error;
- uint32_t inst_bytes;
- bool prefer_file_cache = false; // Read from process if process is running
- lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
- target.ReadMemory(m_instructions[i]->GetAddress(),
- prefer_file_cache,
- &inst_bytes,
- sizeof(inst_bytes),
- error,
- &load_addr);
- // If we have an error reading memory, return start
- if (!error.Success())
- return start;
- // check if this is the last instruction in a packet
- // bits 15:14 will be 11b or 00b for a duplex
- if (((inst_bytes & 0xC000) == 0xC000) ||
- ((inst_bytes & 0xC000) == 0x0000))
- {
- // instruction after this should be the start of next packet
- next_branch = i + 1;
- break;
- }
- }
-
- if (next_branch == UINT32_MAX)
- {
- // We couldn't find the previous packet, so return start
- next_branch = start;
- }
+InstructionList::GetIndexOfNextBranchInstruction(uint32_t start,
+ Target &target) const {
+ size_t num_instructions = m_instructions.size();
+
+ uint32_t next_branch = UINT32_MAX;
+ size_t i;
+ for (i = start; i < num_instructions; i++) {
+ if (m_instructions[i]->DoesBranch()) {
+ next_branch = i;
+ break;
+ }
+ }
+
+ // Hexagon needs the first instruction of the packet with the branch.
+ // Go backwards until we find an instruction marked end-of-packet, or
+ // until we hit start.
+ if (target.GetArchitecture().GetTriple().getArch() == llvm::Triple::hexagon) {
+ // If we didn't find a branch, find the last packet start.
+ if (next_branch == UINT32_MAX) {
+ i = num_instructions - 1;
+ }
+
+ while (i > start) {
+ --i;
+
+ Error error;
+ uint32_t inst_bytes;
+ bool prefer_file_cache = false; // Read from process if process is running
+ lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
+ target.ReadMemory(m_instructions[i]->GetAddress(), prefer_file_cache,
+ &inst_bytes, sizeof(inst_bytes), error, &load_addr);
+ // If we have an error reading memory, return start
+ if (!error.Success())
+ return start;
+ // check if this is the last instruction in a packet
+ // bits 15:14 will be 11b or 00b for a duplex
+ if (((inst_bytes & 0xC000) == 0xC000) ||
+ ((inst_bytes & 0xC000) == 0x0000)) {
+ // instruction after this should be the start of next packet
+ next_branch = i + 1;
+ break;
+ }
+ }
+
+ if (next_branch == UINT32_MAX) {
+ // We couldn't find the previous packet, so return start
+ next_branch = start;
}
- return next_branch;
+ }
+ return next_branch;
}
uint32_t
-InstructionList::GetIndexOfInstructionAtAddress (const Address &address)
-{
- size_t num_instructions = m_instructions.size();
- uint32_t index = UINT32_MAX;
- for (size_t i = 0; i < num_instructions; i++)
- {
- if (m_instructions[i]->GetAddress() == address)
- {
- index = i;
- break;
- }
+InstructionList::GetIndexOfInstructionAtAddress(const Address &address) {
+ size_t num_instructions = m_instructions.size();
+ uint32_t index = UINT32_MAX;
+ for (size_t i = 0; i < num_instructions; i++) {
+ if (m_instructions[i]->GetAddress() == address) {
+ index = i;
+ break;
}
- return index;
+ }
+ return index;
}
uint32_t
-InstructionList::GetIndexOfInstructionAtLoadAddress (lldb::addr_t load_addr, Target &target)
-{
- Address address;
- address.SetLoadAddress(load_addr, &target);
- return GetIndexOfInstructionAtAddress(address);
-}
-
-size_t
-Disassembler::ParseInstructions (const ExecutionContext *exe_ctx,
- const AddressRange &range,
- Stream *error_strm_ptr,
- bool prefer_file_cache)
-{
- if (exe_ctx)
- {
- Target *target = exe_ctx->GetTargetPtr();
- const addr_t byte_size = range.GetByteSize();
- if (target == nullptr || byte_size == 0 || !range.GetBaseAddress().IsValid())
- return 0;
-
- DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
- DataBufferSP data_sp(heap_buffer);
-
- Error error;
- lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
- const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(),
- prefer_file_cache,
- heap_buffer->GetBytes(),
- heap_buffer->GetByteSize(),
- error,
- &load_addr);
-
- if (bytes_read > 0)
- {
- if (bytes_read != heap_buffer->GetByteSize())
- heap_buffer->SetByteSize (bytes_read);
- DataExtractor data (data_sp,
- m_arch.GetByteOrder(),
- m_arch.GetAddressByteSize());
- const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
- return DecodeInstructions(range.GetBaseAddress(), data, 0, UINT32_MAX, false,
- data_from_file);
- }
- else if (error_strm_ptr)
- {
- const char *error_cstr = error.AsCString();
- if (error_cstr)
- {
- error_strm_ptr->Printf("error: %s\n", error_cstr);
- }
- }
- }
- else if (error_strm_ptr)
- {
- error_strm_ptr->PutCString("error: invalid execution context\n");
- }
- return 0;
+InstructionList::GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr,
+ Target &target) {
+ Address address;
+ address.SetLoadAddress(load_addr, &target);
+ return GetIndexOfInstructionAtAddress(address);
}
-size_t
-Disassembler::ParseInstructions (const ExecutionContext *exe_ctx,
- const Address &start,
- uint32_t num_instructions,
- bool prefer_file_cache)
-{
- m_instruction_list.Clear();
-
- if (exe_ctx == nullptr || num_instructions == 0 || !start.IsValid())
- return 0;
-
+size_t Disassembler::ParseInstructions(const ExecutionContext *exe_ctx,
+ const AddressRange &range,
+ Stream *error_strm_ptr,
+ bool prefer_file_cache) {
+ if (exe_ctx) {
Target *target = exe_ctx->GetTargetPtr();
- // Calculate the max buffer size we will need in order to disassemble
- const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize();
-
- if (target == nullptr || byte_size == 0)
- return 0;
+ const addr_t byte_size = range.GetByteSize();
+ if (target == nullptr || byte_size == 0 ||
+ !range.GetBaseAddress().IsValid())
+ return 0;
- DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
- DataBufferSP data_sp (heap_buffer);
+ DataBufferHeap *heap_buffer = new DataBufferHeap(byte_size, '\0');
+ DataBufferSP data_sp(heap_buffer);
Error error;
lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
- const size_t bytes_read = target->ReadMemory (start,
- prefer_file_cache,
- heap_buffer->GetBytes(),
- byte_size,
- error,
- &load_addr);
-
- const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
-
- if (bytes_read == 0)
- return 0;
- DataExtractor data (data_sp,
- m_arch.GetByteOrder(),
- m_arch.GetAddressByteSize());
-
- const bool append_instructions = true;
- DecodeInstructions (start,
- data,
- 0,
- num_instructions,
- append_instructions,
- data_from_file);
+ const size_t bytes_read = target->ReadMemory(
+ range.GetBaseAddress(), prefer_file_cache, heap_buffer->GetBytes(),
+ heap_buffer->GetByteSize(), error, &load_addr);
+
+ if (bytes_read > 0) {
+ if (bytes_read != heap_buffer->GetByteSize())
+ heap_buffer->SetByteSize(bytes_read);
+ DataExtractor data(data_sp, m_arch.GetByteOrder(),
+ m_arch.GetAddressByteSize());
+ const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
+ return DecodeInstructions(range.GetBaseAddress(), data, 0, UINT32_MAX,
+ false, data_from_file);
+ } else if (error_strm_ptr) {
+ const char *error_cstr = error.AsCString();
+ if (error_cstr) {
+ error_strm_ptr->Printf("error: %s\n", error_cstr);
+ }
+ }
+ } else if (error_strm_ptr) {
+ error_strm_ptr->PutCString("error: invalid execution context\n");
+ }
+ return 0;
+}
+
+size_t Disassembler::ParseInstructions(const ExecutionContext *exe_ctx,
+ const Address &start,
+ uint32_t num_instructions,
+ bool prefer_file_cache) {
+ m_instruction_list.Clear();
+
+ if (exe_ctx == nullptr || num_instructions == 0 || !start.IsValid())
+ return 0;
+
+ Target *target = exe_ctx->GetTargetPtr();
+ // Calculate the max buffer size we will need in order to disassemble
+ const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize();
+
+ if (target == nullptr || byte_size == 0)
+ return 0;
- return m_instruction_list.GetSize();
+ DataBufferHeap *heap_buffer = new DataBufferHeap(byte_size, '\0');
+ DataBufferSP data_sp(heap_buffer);
+
+ Error error;
+ lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
+ const size_t bytes_read =
+ target->ReadMemory(start, prefer_file_cache, heap_buffer->GetBytes(),
+ byte_size, error, &load_addr);
+
+ const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
+
+ if (bytes_read == 0)
+ return 0;
+ DataExtractor data(data_sp, m_arch.GetByteOrder(),
+ m_arch.GetAddressByteSize());
+
+ const bool append_instructions = true;
+ DecodeInstructions(start, data, 0, num_instructions, append_instructions,
+ data_from_file);
+
+ return m_instruction_list.GetSize();
}
//----------------------------------------------------------------------
// Disassembler copy constructor
//----------------------------------------------------------------------
-Disassembler::Disassembler(const ArchSpec& arch, const char *flavor) :
- m_arch (arch),
- m_instruction_list(),
- m_base_addr(LLDB_INVALID_ADDRESS),
- m_flavor ()
-{
- if (flavor == nullptr)
- m_flavor.assign("default");
- else
- m_flavor.assign(flavor);
-
- // If this is an arm variant that can only include thumb (T16, T32)
- // instructions, force the arch triple to be "thumbv.." instead of
- // "armv..."
- if (arch.IsAlwaysThumbInstructions())
- {
- std::string thumb_arch_name (arch.GetTriple().getArchName().str());
- // Replace "arm" with "thumb" so we get all thumb variants correct
- if (thumb_arch_name.size() > 3)
- {
- thumb_arch_name.erase(0, 3);
- thumb_arch_name.insert(0, "thumb");
- }
- m_arch.SetTriple (thumb_arch_name.c_str());
+Disassembler::Disassembler(const ArchSpec &arch, const char *flavor)
+ : m_arch(arch), m_instruction_list(), m_base_addr(LLDB_INVALID_ADDRESS),
+ m_flavor() {
+ if (flavor == nullptr)
+ m_flavor.assign("default");
+ else
+ m_flavor.assign(flavor);
+
+ // If this is an arm variant that can only include thumb (T16, T32)
+ // instructions, force the arch triple to be "thumbv.." instead of
+ // "armv..."
+ if (arch.IsAlwaysThumbInstructions()) {
+ std::string thumb_arch_name(arch.GetTriple().getArchName().str());
+ // Replace "arm" with "thumb" so we get all thumb variants correct
+ if (thumb_arch_name.size() > 3) {
+ thumb_arch_name.erase(0, 3);
+ thumb_arch_name.insert(0, "thumb");
}
+ m_arch.SetTriple(thumb_arch_name.c_str());
+ }
}
Disassembler::~Disassembler() = default;
-InstructionList &
-Disassembler::GetInstructionList ()
-{
- return m_instruction_list;
+InstructionList &Disassembler::GetInstructionList() {
+ return m_instruction_list;
}
-const InstructionList &
-Disassembler::GetInstructionList () const
-{
- return m_instruction_list;
+const InstructionList &Disassembler::GetInstructionList() const {
+ return m_instruction_list;
}
//----------------------------------------------------------------------
// Class PseudoInstruction
//----------------------------------------------------------------------
-PseudoInstruction::PseudoInstruction () :
- Instruction (Address(), eAddressClassUnknown),
- m_description ()
-{
-}
+PseudoInstruction::PseudoInstruction()
+ : Instruction(Address(), eAddressClassUnknown), m_description() {}
PseudoInstruction::~PseudoInstruction() = default;
-
-bool
-PseudoInstruction::DoesBranch ()
-{
- // This is NOT a valid question for a pseudo instruction.
- return false;
-}
-
-bool
-PseudoInstruction::HasDelaySlot ()
-{
- // This is NOT a valid question for a pseudo instruction.
- return false;
-}
-
-size_t
-PseudoInstruction::Decode (const lldb_private::Disassembler &disassembler,
- const lldb_private::DataExtractor &data,
- lldb::offset_t data_offset)
-{
- return m_opcode.GetByteSize();
-}
-
-void
-PseudoInstruction::SetOpcode (size_t opcode_size, void *opcode_data)
-{
- if (!opcode_data)
- return;
-
- switch (opcode_size)
- {
- case 8:
- {
- uint8_t value8 = *((uint8_t *) opcode_data);
- m_opcode.SetOpcode8 (value8, eByteOrderInvalid);
- break;
- }
- case 16:
- {
- uint16_t value16 = *((uint16_t *) opcode_data);
- m_opcode.SetOpcode16 (value16, eByteOrderInvalid);
- break;
- }
- case 32:
- {
- uint32_t value32 = *((uint32_t *) opcode_data);
- m_opcode.SetOpcode32 (value32, eByteOrderInvalid);
- break;
- }
- case 64:
- {
- uint64_t value64 = *((uint64_t *) opcode_data);
- m_opcode.SetOpcode64 (value64, eByteOrderInvalid);
- break;
- }
- default:
- break;
- }
-}
-void
-PseudoInstruction::SetDescription (const char *description)
-{
- if (description && strlen (description) > 0)
- m_description = description;
+bool PseudoInstruction::DoesBranch() {
+ // This is NOT a valid question for a pseudo instruction.
+ return false;
+}
+
+bool PseudoInstruction::HasDelaySlot() {
+ // This is NOT a valid question for a pseudo instruction.
+ return false;
+}
+
+size_t PseudoInstruction::Decode(const lldb_private::Disassembler &disassembler,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t data_offset) {
+ return m_opcode.GetByteSize();
+}
+
+void PseudoInstruction::SetOpcode(size_t opcode_size, void *opcode_data) {
+ if (!opcode_data)
+ return;
+
+ switch (opcode_size) {
+ case 8: {
+ uint8_t value8 = *((uint8_t *)opcode_data);
+ m_opcode.SetOpcode8(value8, eByteOrderInvalid);
+ break;
+ }
+ case 16: {
+ uint16_t value16 = *((uint16_t *)opcode_data);
+ m_opcode.SetOpcode16(value16, eByteOrderInvalid);
+ break;
+ }
+ case 32: {
+ uint32_t value32 = *((uint32_t *)opcode_data);
+ m_opcode.SetOpcode32(value32, eByteOrderInvalid);
+ break;
+ }
+ case 64: {
+ uint64_t value64 = *((uint64_t *)opcode_data);
+ m_opcode.SetOpcode64(value64, eByteOrderInvalid);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void PseudoInstruction::SetDescription(const char *description) {
+ if (description && strlen(description) > 0)
+ m_description = description;
}
Modified: lldb/trunk/source/Core/DynamicLoader.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/DynamicLoader.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Core/DynamicLoader.cpp (original)
+++ lldb/trunk/source/Core/DynamicLoader.cpp Tue Sep 6 15:57:50 2016
@@ -11,50 +11,49 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-private.h"
+#include "lldb/Target/DynamicLoader.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
-#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
+#include "lldb/lldb-private.h"
using namespace lldb;
using namespace lldb_private;
-DynamicLoader*
-DynamicLoader::FindPlugin (Process *process, const char *plugin_name)
-{
- DynamicLoaderCreateInstance create_callback = nullptr;
- if (plugin_name)
- {
- ConstString const_plugin_name(plugin_name);
- create_callback = PluginManager::GetDynamicLoaderCreateCallbackForPluginName (const_plugin_name);
- if (create_callback)
- {
- std::unique_ptr<DynamicLoader> instance_ap(create_callback(process, true));
- if (instance_ap)
- return instance_ap.release();
- }
+DynamicLoader *DynamicLoader::FindPlugin(Process *process,
+ const char *plugin_name) {
+ DynamicLoaderCreateInstance create_callback = nullptr;
+ if (plugin_name) {
+ ConstString const_plugin_name(plugin_name);
+ create_callback =
+ PluginManager::GetDynamicLoaderCreateCallbackForPluginName(
+ const_plugin_name);
+ if (create_callback) {
+ std::unique_ptr<DynamicLoader> instance_ap(
+ create_callback(process, true));
+ if (instance_ap)
+ return instance_ap.release();
+ }
+ } else {
+ for (uint32_t idx = 0;
+ (create_callback =
+ PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) !=
+ nullptr;
+ ++idx) {
+ std::unique_ptr<DynamicLoader> instance_ap(
+ create_callback(process, false));
+ if (instance_ap)
+ return instance_ap.release();
}
- else
- {
- for (uint32_t idx = 0; (create_callback = PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) != nullptr; ++idx)
- {
- std::unique_ptr<DynamicLoader> instance_ap(create_callback(process, false));
- if (instance_ap)
- return instance_ap.release();
- }
- }
- return nullptr;
+ }
+ return nullptr;
}
-DynamicLoader::DynamicLoader(Process *process) :
- m_process (process)
-{
-}
+DynamicLoader::DynamicLoader(Process *process) : m_process(process) {}
DynamicLoader::~DynamicLoader() = default;
@@ -63,203 +62,174 @@ DynamicLoader::~DynamicLoader() = defaul
// (shared library) loading/unloading.
//----------------------------------------------------------------------
-bool
-DynamicLoader::GetStopWhenImagesChange () const
-{
- return m_process->GetStopOnSharedLibraryEvents();
-}
-
-void
-DynamicLoader::SetStopWhenImagesChange (bool stop)
-{
- m_process->SetStopOnSharedLibraryEvents (stop);
-}
-
-ModuleSP
-DynamicLoader::GetTargetExecutable()
-{
- Target &target = m_process->GetTarget();
- ModuleSP executable = target.GetExecutableModule();
-
- if (executable)
- {
- if (executable->GetFileSpec().Exists())
- {
- ModuleSpec module_spec (executable->GetFileSpec(), executable->GetArchitecture());
- ModuleSP module_sp (new Module (module_spec));
-
- // Check if the executable has changed and set it to the target executable if they differ.
- if (module_sp && module_sp->GetUUID().IsValid() && executable->GetUUID().IsValid())
- {
- if (module_sp->GetUUID() != executable->GetUUID())
- executable.reset();
- }
- else if (executable->FileHasChanged())
- {
- executable.reset();
- }
-
- if (!executable)
- {
- executable = target.GetSharedModule(module_spec);
- if (executable.get() != target.GetExecutableModulePointer())
- {
- // Don't load dependent images since we are in dyld where we will know
- // and find out about all images that are loaded
- const bool get_dependent_images = false;
- target.SetExecutableModule(executable, get_dependent_images);
- }
- }
- }
- }
- return executable;
+bool DynamicLoader::GetStopWhenImagesChange() const {
+ return m_process->GetStopOnSharedLibraryEvents();
}
-void
-DynamicLoader::UpdateLoadedSections(ModuleSP module,
- addr_t link_map_addr,
- addr_t base_addr,
- bool base_addr_is_offset)
-{
- UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
-}
-
-void
-DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module,
- addr_t base_addr,
- bool base_addr_is_offset)
-{
- bool changed;
- module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset, changed);
-}
-
-void
-DynamicLoader::UnloadSections(const ModuleSP module)
-{
- UnloadSectionsCommon(module);
-}
-
-void
-DynamicLoader::UnloadSectionsCommon(const ModuleSP module)
-{
- Target &target = m_process->GetTarget();
- const SectionList *sections = GetSectionListFromModule(module);
-
- assert(sections && "SectionList missing from unloaded module.");
-
- const size_t num_sections = sections->GetSize();
- for (size_t i = 0; i < num_sections; ++i)
- {
- SectionSP section_sp (sections->GetSectionAtIndex(i));
- target.SetSectionUnloaded(section_sp);
- }
+void DynamicLoader::SetStopWhenImagesChange(bool stop) {
+ m_process->SetStopOnSharedLibraryEvents(stop);
}
-const SectionList *
-DynamicLoader::GetSectionListFromModule(const ModuleSP module) const
-{
- SectionList *sections = nullptr;
- if (module)
- {
- ObjectFile *obj_file = module->GetObjectFile();
- if (obj_file != nullptr)
- {
- sections = obj_file->GetSectionList();
+ModuleSP DynamicLoader::GetTargetExecutable() {
+ Target &target = m_process->GetTarget();
+ ModuleSP executable = target.GetExecutableModule();
+
+ if (executable) {
+ if (executable->GetFileSpec().Exists()) {
+ ModuleSpec module_spec(executable->GetFileSpec(),
+ executable->GetArchitecture());
+ ModuleSP module_sp(new Module(module_spec));
+
+ // Check if the executable has changed and set it to the target executable
+ // if they differ.
+ if (module_sp && module_sp->GetUUID().IsValid() &&
+ executable->GetUUID().IsValid()) {
+ if (module_sp->GetUUID() != executable->GetUUID())
+ executable.reset();
+ } else if (executable->FileHasChanged()) {
+ executable.reset();
+ }
+
+ if (!executable) {
+ executable = target.GetSharedModule(module_spec);
+ if (executable.get() != target.GetExecutableModulePointer()) {
+ // Don't load dependent images since we are in dyld where we will know
+ // and find out about all images that are loaded
+ const bool get_dependent_images = false;
+ target.SetExecutableModule(executable, get_dependent_images);
}
+ }
}
- return sections;
+ }
+ return executable;
}
-ModuleSP
-DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
- addr_t link_map_addr,
- addr_t base_addr,
- bool base_addr_is_offset)
-{
- Target &target = m_process->GetTarget();
- ModuleList &modules = target.GetImages();
- ModuleSpec module_spec (file, target.GetArchitecture());
- ModuleSP module_sp;
-
- if ((module_sp = modules.FindFirstModule (module_spec)))
- {
- UpdateLoadedSections(module_sp, link_map_addr, base_addr, base_addr_is_offset);
- return module_sp;
- }
+void DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr,
+ addr_t base_addr,
+ bool base_addr_is_offset) {
+ UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
+}
- if ((module_sp = target.GetSharedModule(module_spec)))
- {
- UpdateLoadedSections(module_sp, link_map_addr, base_addr, base_addr_is_offset);
- return module_sp;
- }
+void DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module,
+ addr_t base_addr,
+ bool base_addr_is_offset) {
+ bool changed;
+ module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset,
+ changed);
+}
- bool check_alternative_file_name = true;
- if (base_addr_is_offset)
- {
- // Try to fetch the load address of the file from the process as we need absolute load
- // address to read the file out of the memory instead of a load bias.
- bool is_loaded = false;
- lldb::addr_t load_addr;
- Error error = m_process->GetFileLoadAddress(file, is_loaded, load_addr);
- if (error.Success() && is_loaded)
- {
- check_alternative_file_name = false;
- base_addr = load_addr;
- }
- }
+void DynamicLoader::UnloadSections(const ModuleSP module) {
+ UnloadSectionsCommon(module);
+}
- // We failed to find the module based on its name. Lets try to check if we can find a
- // different name based on the memory region info.
- if (check_alternative_file_name)
- {
- MemoryRegionInfo memory_info;
- Error error = m_process->GetMemoryRegionInfo(base_addr, memory_info);
- if (error.Success() && memory_info.GetMapped() && memory_info.GetRange().GetRangeBase() == base_addr)
- {
- ModuleSpec new_module_spec(FileSpec(memory_info.GetName().AsCString(), false),
- target.GetArchitecture());
-
- if ((module_sp = modules.FindFirstModule(new_module_spec)))
- {
- UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
- return module_sp;
- }
-
- if ((module_sp = target.GetSharedModule(new_module_spec)))
- {
- UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
- return module_sp;
- }
- }
- }
+void DynamicLoader::UnloadSectionsCommon(const ModuleSP module) {
+ Target &target = m_process->GetTarget();
+ const SectionList *sections = GetSectionListFromModule(module);
- if ((module_sp = m_process->ReadModuleFromMemory(file, base_addr)))
- {
- UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
- target.GetImages().AppendIfNeeded(module_sp);
- }
+ assert(sections && "SectionList missing from unloaded module.");
- return module_sp;
+ const size_t num_sections = sections->GetSize();
+ for (size_t i = 0; i < num_sections; ++i) {
+ SectionSP section_sp(sections->GetSectionAtIndex(i));
+ target.SetSectionUnloaded(section_sp);
+ }
}
-int64_t
-DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr, int size_in_bytes)
-{
- Error error;
- uint64_t value = m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error);
- if (error.Fail())
- return -1;
- else
- return (int64_t)value;
-}
-
-addr_t
-DynamicLoader::ReadPointer(addr_t addr)
-{
- Error error;
- addr_t value = m_process->ReadPointerFromMemory(addr, error);
- if (error.Fail())
- return LLDB_INVALID_ADDRESS;
- else
- return value;
+const SectionList *
+DynamicLoader::GetSectionListFromModule(const ModuleSP module) const {
+ SectionList *sections = nullptr;
+ if (module) {
+ ObjectFile *obj_file = module->GetObjectFile();
+ if (obj_file != nullptr) {
+ sections = obj_file->GetSectionList();
+ }
+ }
+ return sections;
+}
+
+ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
+ addr_t link_map_addr,
+ addr_t base_addr,
+ bool base_addr_is_offset) {
+ Target &target = m_process->GetTarget();
+ ModuleList &modules = target.GetImages();
+ ModuleSpec module_spec(file, target.GetArchitecture());
+ ModuleSP module_sp;
+
+ if ((module_sp = modules.FindFirstModule(module_spec))) {
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr,
+ base_addr_is_offset);
+ return module_sp;
+ }
+
+ if ((module_sp = target.GetSharedModule(module_spec))) {
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr,
+ base_addr_is_offset);
+ return module_sp;
+ }
+
+ bool check_alternative_file_name = true;
+ if (base_addr_is_offset) {
+ // Try to fetch the load address of the file from the process as we need
+ // absolute load
+ // address to read the file out of the memory instead of a load bias.
+ bool is_loaded = false;
+ lldb::addr_t load_addr;
+ Error error = m_process->GetFileLoadAddress(file, is_loaded, load_addr);
+ if (error.Success() && is_loaded) {
+ check_alternative_file_name = false;
+ base_addr = load_addr;
+ }
+ }
+
+ // We failed to find the module based on its name. Lets try to check if we can
+ // find a
+ // different name based on the memory region info.
+ if (check_alternative_file_name) {
+ MemoryRegionInfo memory_info;
+ Error error = m_process->GetMemoryRegionInfo(base_addr, memory_info);
+ if (error.Success() && memory_info.GetMapped() &&
+ memory_info.GetRange().GetRangeBase() == base_addr) {
+ ModuleSpec new_module_spec(
+ FileSpec(memory_info.GetName().AsCString(), false),
+ target.GetArchitecture());
+
+ if ((module_sp = modules.FindFirstModule(new_module_spec))) {
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
+ return module_sp;
+ }
+
+ if ((module_sp = target.GetSharedModule(new_module_spec))) {
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
+ return module_sp;
+ }
+ }
+ }
+
+ if ((module_sp = m_process->ReadModuleFromMemory(file, base_addr))) {
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
+ target.GetImages().AppendIfNeeded(module_sp);
+ }
+
+ return module_sp;
+}
+
+int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr,
+ int size_in_bytes) {
+ Error error;
+ uint64_t value =
+ m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error);
+ if (error.Fail())
+ return -1;
+ else
+ return (int64_t)value;
+}
+
+addr_t DynamicLoader::ReadPointer(addr_t addr) {
+ Error error;
+ addr_t value = m_process->ReadPointerFromMemory(addr, error);
+ if (error.Fail())
+ return LLDB_INVALID_ADDRESS;
+ else
+ return value;
}
Modified: lldb/trunk/source/Core/EmulateInstruction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/EmulateInstruction.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Core/EmulateInstruction.cpp (original)
+++ lldb/trunk/source/Core/EmulateInstruction.cpp Tue Sep 6 15:57:50 2016
@@ -32,621 +32,553 @@
using namespace lldb;
using namespace lldb_private;
-EmulateInstruction*
-EmulateInstruction::FindPlugin (const ArchSpec &arch, InstructionType supported_inst_type, const char *plugin_name)
-{
- EmulateInstructionCreateInstance create_callback = nullptr;
- if (plugin_name)
- {
- ConstString const_plugin_name (plugin_name);
- create_callback = PluginManager::GetEmulateInstructionCreateCallbackForPluginName (const_plugin_name);
- if (create_callback)
- {
- EmulateInstruction *emulate_insn_ptr = create_callback(arch, supported_inst_type);
- if (emulate_insn_ptr)
- return emulate_insn_ptr;
- }
- }
- else
- {
- for (uint32_t idx = 0; (create_callback = PluginManager::GetEmulateInstructionCreateCallbackAtIndex(idx)) != nullptr; ++idx)
- {
- EmulateInstruction *emulate_insn_ptr = create_callback(arch, supported_inst_type);
- if (emulate_insn_ptr)
- return emulate_insn_ptr;
- }
- }
- return nullptr;
+EmulateInstruction *
+EmulateInstruction::FindPlugin(const ArchSpec &arch,
+ InstructionType supported_inst_type,
+ const char *plugin_name) {
+ EmulateInstructionCreateInstance create_callback = nullptr;
+ if (plugin_name) {
+ ConstString const_plugin_name(plugin_name);
+ create_callback =
+ PluginManager::GetEmulateInstructionCreateCallbackForPluginName(
+ const_plugin_name);
+ if (create_callback) {
+ EmulateInstruction *emulate_insn_ptr =
+ create_callback(arch, supported_inst_type);
+ if (emulate_insn_ptr)
+ return emulate_insn_ptr;
+ }
+ } else {
+ for (uint32_t idx = 0;
+ (create_callback =
+ PluginManager::GetEmulateInstructionCreateCallbackAtIndex(idx)) !=
+ nullptr;
+ ++idx) {
+ EmulateInstruction *emulate_insn_ptr =
+ create_callback(arch, supported_inst_type);
+ if (emulate_insn_ptr)
+ return emulate_insn_ptr;
+ }
+ }
+ return nullptr;
+}
+
+EmulateInstruction::EmulateInstruction(const ArchSpec &arch)
+ : m_arch(arch), m_baton(nullptr), m_read_mem_callback(&ReadMemoryDefault),
+ m_write_mem_callback(&WriteMemoryDefault),
+ m_read_reg_callback(&ReadRegisterDefault),
+ m_write_reg_callback(&WriteRegisterDefault),
+ m_addr(LLDB_INVALID_ADDRESS) {
+ ::memset(&m_opcode, 0, sizeof(m_opcode));
+}
+
+bool EmulateInstruction::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue ®_value) {
+ if (m_read_reg_callback != nullptr)
+ return m_read_reg_callback(this, m_baton, reg_info, reg_value);
+ return false;
+}
+
+bool EmulateInstruction::ReadRegister(lldb::RegisterKind reg_kind,
+ uint32_t reg_num,
+ RegisterValue ®_value) {
+ RegisterInfo reg_info;
+ if (GetRegisterInfo(reg_kind, reg_num, reg_info))
+ return ReadRegister(®_info, reg_value);
+ return false;
+}
+
+uint64_t EmulateInstruction::ReadRegisterUnsigned(lldb::RegisterKind reg_kind,
+ uint32_t reg_num,
+ uint64_t fail_value,
+ bool *success_ptr) {
+ RegisterValue reg_value;
+ if (ReadRegister(reg_kind, reg_num, reg_value))
+ return reg_value.GetAsUInt64(fail_value, success_ptr);
+ if (success_ptr)
+ *success_ptr = false;
+ return fail_value;
+}
+
+uint64_t EmulateInstruction::ReadRegisterUnsigned(const RegisterInfo *reg_info,
+ uint64_t fail_value,
+ bool *success_ptr) {
+ RegisterValue reg_value;
+ if (ReadRegister(reg_info, reg_value))
+ return reg_value.GetAsUInt64(fail_value, success_ptr);
+ if (success_ptr)
+ *success_ptr = false;
+ return fail_value;
+}
+
+bool EmulateInstruction::WriteRegister(const Context &context,
+ const RegisterInfo *reg_info,
+ const RegisterValue ®_value) {
+ if (m_write_reg_callback != nullptr)
+ return m_write_reg_callback(this, m_baton, context, reg_info, reg_value);
+ return false;
+}
+
+bool EmulateInstruction::WriteRegister(const Context &context,
+ lldb::RegisterKind reg_kind,
+ uint32_t reg_num,
+ const RegisterValue ®_value) {
+ RegisterInfo reg_info;
+ if (GetRegisterInfo(reg_kind, reg_num, reg_info))
+ return WriteRegister(context, ®_info, reg_value);
+ return false;
+}
+
+bool EmulateInstruction::WriteRegisterUnsigned(const Context &context,
+ lldb::RegisterKind reg_kind,
+ uint32_t reg_num,
+ uint64_t uint_value) {
+ RegisterInfo reg_info;
+ if (GetRegisterInfo(reg_kind, reg_num, reg_info)) {
+ RegisterValue reg_value;
+ if (reg_value.SetUInt(uint_value, reg_info.byte_size))
+ return WriteRegister(context, ®_info, reg_value);
+ }
+ return false;
}
-EmulateInstruction::EmulateInstruction (const ArchSpec &arch) :
- m_arch(arch),
- m_baton(nullptr),
- m_read_mem_callback(&ReadMemoryDefault),
- m_write_mem_callback(&WriteMemoryDefault),
- m_read_reg_callback(&ReadRegisterDefault),
- m_write_reg_callback(&WriteRegisterDefault),
- m_addr(LLDB_INVALID_ADDRESS)
-{
- ::memset (&m_opcode, 0, sizeof (m_opcode));
-}
-
-bool
-EmulateInstruction::ReadRegister (const RegisterInfo *reg_info, RegisterValue& reg_value)
-{
- if (m_read_reg_callback != nullptr)
- return m_read_reg_callback (this, m_baton, reg_info, reg_value);
- return false;
+bool EmulateInstruction::WriteRegisterUnsigned(const Context &context,
+ const RegisterInfo *reg_info,
+ uint64_t uint_value) {
+ if (reg_info != nullptr) {
+ RegisterValue reg_value;
+ if (reg_value.SetUInt(uint_value, reg_info->byte_size))
+ return WriteRegister(context, reg_info, reg_value);
+ }
+ return false;
}
-bool
-EmulateInstruction::ReadRegister (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterValue& reg_value)
-{
- RegisterInfo reg_info;
- if (GetRegisterInfo(reg_kind, reg_num, reg_info))
- return ReadRegister (®_info, reg_value);
- return false;
+size_t EmulateInstruction::ReadMemory(const Context &context, lldb::addr_t addr,
+ void *dst, size_t dst_len) {
+ if (m_read_mem_callback != nullptr)
+ return m_read_mem_callback(this, m_baton, context, addr, dst, dst_len) ==
+ dst_len;
+ return false;
}
-uint64_t
-EmulateInstruction::ReadRegisterUnsigned (lldb::RegisterKind reg_kind,
- uint32_t reg_num,
- uint64_t fail_value,
- bool *success_ptr)
-{
- RegisterValue reg_value;
- if (ReadRegister (reg_kind, reg_num, reg_value))
- return reg_value.GetAsUInt64(fail_value, success_ptr);
- if (success_ptr)
- *success_ptr = false;
- return fail_value;
-}
+uint64_t EmulateInstruction::ReadMemoryUnsigned(const Context &context,
+ lldb::addr_t addr,
+ size_t byte_size,
+ uint64_t fail_value,
+ bool *success_ptr) {
+ uint64_t uval64 = 0;
+ bool success = false;
+ if (byte_size <= 8) {
+ uint8_t buf[sizeof(uint64_t)];
+ size_t bytes_read =
+ m_read_mem_callback(this, m_baton, context, addr, buf, byte_size);
+ if (bytes_read == byte_size) {
+ lldb::offset_t offset = 0;
+ DataExtractor data(buf, byte_size, GetByteOrder(), GetAddressByteSize());
+ uval64 = data.GetMaxU64(&offset, byte_size);
+ success = true;
+ }
+ }
-uint64_t
-EmulateInstruction::ReadRegisterUnsigned (const RegisterInfo *reg_info,
- uint64_t fail_value,
- bool *success_ptr)
-{
- RegisterValue reg_value;
- if (ReadRegister (reg_info, reg_value))
- return reg_value.GetAsUInt64(fail_value, success_ptr);
- if (success_ptr)
- *success_ptr = false;
- return fail_value;
-}
+ if (success_ptr)
+ *success_ptr = success;
-bool
-EmulateInstruction::WriteRegister (const Context &context,
- const RegisterInfo *reg_info,
- const RegisterValue& reg_value)
-{
- if (m_write_reg_callback != nullptr)
- return m_write_reg_callback (this, m_baton, context, reg_info, reg_value);
- return false;
+ if (!success)
+ uval64 = fail_value;
+ return uval64;
}
-bool
-EmulateInstruction::WriteRegister (const Context &context,
- lldb::RegisterKind reg_kind,
- uint32_t reg_num,
- const RegisterValue& reg_value)
-{
- RegisterInfo reg_info;
- if (GetRegisterInfo(reg_kind, reg_num, reg_info))
- return WriteRegister (context, ®_info, reg_value);
- return false;
-}
+bool EmulateInstruction::WriteMemoryUnsigned(const Context &context,
+ lldb::addr_t addr, uint64_t uval,
+ size_t uval_byte_size) {
+ StreamString strm(Stream::eBinary, GetAddressByteSize(), GetByteOrder());
+ strm.PutMaxHex64(uval, uval_byte_size);
-bool
-EmulateInstruction::WriteRegisterUnsigned (const Context &context,
- lldb::RegisterKind reg_kind,
- uint32_t reg_num,
- uint64_t uint_value)
-{
- RegisterInfo reg_info;
- if (GetRegisterInfo(reg_kind, reg_num, reg_info))
- {
- RegisterValue reg_value;
- if (reg_value.SetUInt(uint_value, reg_info.byte_size))
- return WriteRegister (context, ®_info, reg_value);
- }
- return false;
+ size_t bytes_written = m_write_mem_callback(this, m_baton, context, addr,
+ strm.GetData(), uval_byte_size);
+ return (bytes_written == uval_byte_size);
}
-bool
-EmulateInstruction::WriteRegisterUnsigned (const Context &context,
- const RegisterInfo *reg_info,
- uint64_t uint_value)
-{
- if (reg_info != nullptr)
- {
- RegisterValue reg_value;
- if (reg_value.SetUInt(uint_value, reg_info->byte_size))
- return WriteRegister (context, reg_info, reg_value);
- }
- return false;
+bool EmulateInstruction::WriteMemory(const Context &context, lldb::addr_t addr,
+ const void *src, size_t src_len) {
+ if (m_write_mem_callback != nullptr)
+ return m_write_mem_callback(this, m_baton, context, addr, src, src_len) ==
+ src_len;
+ return false;
}
-size_t
-EmulateInstruction::ReadMemory (const Context &context,
- lldb::addr_t addr,
- void *dst,
- size_t dst_len)
-{
- if (m_read_mem_callback != nullptr)
- return m_read_mem_callback (this, m_baton, context, addr, dst, dst_len) == dst_len;
- return false;
+void EmulateInstruction::SetBaton(void *baton) { m_baton = baton; }
+
+void EmulateInstruction::SetCallbacks(
+ ReadMemoryCallback read_mem_callback,
+ WriteMemoryCallback write_mem_callback,
+ ReadRegisterCallback read_reg_callback,
+ WriteRegisterCallback write_reg_callback) {
+ m_read_mem_callback = read_mem_callback;
+ m_write_mem_callback = write_mem_callback;
+ m_read_reg_callback = read_reg_callback;
+ m_write_reg_callback = write_reg_callback;
}
-uint64_t
-EmulateInstruction::ReadMemoryUnsigned (const Context &context, lldb::addr_t addr, size_t byte_size, uint64_t fail_value, bool *success_ptr)
-{
- uint64_t uval64 = 0;
- bool success = false;
- if (byte_size <= 8)
- {
- uint8_t buf[sizeof(uint64_t)];
- size_t bytes_read = m_read_mem_callback (this, m_baton, context, addr, buf, byte_size);
- if (bytes_read == byte_size)
- {
- lldb::offset_t offset = 0;
- DataExtractor data (buf, byte_size, GetByteOrder(), GetAddressByteSize());
- uval64 = data.GetMaxU64 (&offset, byte_size);
- success = true;
- }
- }
+void EmulateInstruction::SetReadMemCallback(
+ ReadMemoryCallback read_mem_callback) {
+ m_read_mem_callback = read_mem_callback;
+}
- if (success_ptr)
- *success_ptr = success;
+void EmulateInstruction::SetWriteMemCallback(
+ WriteMemoryCallback write_mem_callback) {
+ m_write_mem_callback = write_mem_callback;
+}
- if (!success)
- uval64 = fail_value;
- return uval64;
-}
-
-bool
-EmulateInstruction::WriteMemoryUnsigned (const Context &context,
- lldb::addr_t addr,
- uint64_t uval,
- size_t uval_byte_size)
-{
- StreamString strm(Stream::eBinary, GetAddressByteSize(), GetByteOrder());
- strm.PutMaxHex64 (uval, uval_byte_size);
-
- size_t bytes_written = m_write_mem_callback (this, m_baton, context, addr, strm.GetData(), uval_byte_size);
- return (bytes_written == uval_byte_size);
-}
-
-bool
-EmulateInstruction::WriteMemory (const Context &context,
- lldb::addr_t addr,
- const void *src,
- size_t src_len)
-{
- if (m_write_mem_callback != nullptr)
- return m_write_mem_callback (this, m_baton, context, addr, src, src_len) == src_len;
- return false;
+void EmulateInstruction::SetReadRegCallback(
+ ReadRegisterCallback read_reg_callback) {
+ m_read_reg_callback = read_reg_callback;
}
-void
-EmulateInstruction::SetBaton (void *baton)
-{
- m_baton = baton;
-}
-
-void
-EmulateInstruction::SetCallbacks (ReadMemoryCallback read_mem_callback,
- WriteMemoryCallback write_mem_callback,
- ReadRegisterCallback read_reg_callback,
- WriteRegisterCallback write_reg_callback)
-{
- m_read_mem_callback = read_mem_callback;
- m_write_mem_callback = write_mem_callback;
- m_read_reg_callback = read_reg_callback;
- m_write_reg_callback = write_reg_callback;
-}
-
-void
-EmulateInstruction::SetReadMemCallback (ReadMemoryCallback read_mem_callback)
-{
- m_read_mem_callback = read_mem_callback;
-}
-
-void
-EmulateInstruction::SetWriteMemCallback (WriteMemoryCallback write_mem_callback)
-{
- m_write_mem_callback = write_mem_callback;
-}
-
-void
-EmulateInstruction::SetReadRegCallback (ReadRegisterCallback read_reg_callback)
-{
- m_read_reg_callback = read_reg_callback;
-}
-
-void
-EmulateInstruction::SetWriteRegCallback (WriteRegisterCallback write_reg_callback)
-{
- m_write_reg_callback = write_reg_callback;
+void EmulateInstruction::SetWriteRegCallback(
+ WriteRegisterCallback write_reg_callback) {
+ m_write_reg_callback = write_reg_callback;
}
//
// Read & Write Memory and Registers callback functions.
//
-size_t
-EmulateInstruction::ReadMemoryFrame (EmulateInstruction *instruction,
- void *baton,
- const Context &context,
- lldb::addr_t addr,
- void *dst,
- size_t dst_len)
-{
- if (baton == nullptr || dst == nullptr || dst_len == 0)
- return 0;
-
- StackFrame *frame = (StackFrame *) baton;
-
- ProcessSP process_sp (frame->CalculateProcess());
- if (process_sp)
- {
- Error error;
- return process_sp->ReadMemory (addr, dst, dst_len, error);
- }
+size_t EmulateInstruction::ReadMemoryFrame(EmulateInstruction *instruction,
+ void *baton, const Context &context,
+ lldb::addr_t addr, void *dst,
+ size_t dst_len) {
+ if (baton == nullptr || dst == nullptr || dst_len == 0)
return 0;
+
+ StackFrame *frame = (StackFrame *)baton;
+
+ ProcessSP process_sp(frame->CalculateProcess());
+ if (process_sp) {
+ Error error;
+ return process_sp->ReadMemory(addr, dst, dst_len, error);
+ }
+ return 0;
}
-size_t
-EmulateInstruction::WriteMemoryFrame (EmulateInstruction *instruction,
- void *baton,
- const Context &context,
- lldb::addr_t addr,
- const void *src,
- size_t src_len)
-{
- if (baton == nullptr || src == nullptr || src_len == 0)
- return 0;
-
- StackFrame *frame = (StackFrame *) baton;
-
- ProcessSP process_sp (frame->CalculateProcess());
- if (process_sp)
- {
- Error error;
- return process_sp->WriteMemory (addr, src, src_len, error);
- }
-
+size_t EmulateInstruction::WriteMemoryFrame(EmulateInstruction *instruction,
+ void *baton, const Context &context,
+ lldb::addr_t addr, const void *src,
+ size_t src_len) {
+ if (baton == nullptr || src == nullptr || src_len == 0)
return 0;
-}
-bool
-EmulateInstruction::ReadRegisterFrame (EmulateInstruction *instruction,
- void *baton,
- const RegisterInfo *reg_info,
- RegisterValue ®_value)
-{
- if (baton == nullptr)
- return false;
-
- StackFrame *frame = (StackFrame *) baton;
- return frame->GetRegisterContext()->ReadRegister (reg_info, reg_value);
-}
-
-bool
-EmulateInstruction::WriteRegisterFrame (EmulateInstruction *instruction,
- void *baton,
- const Context &context,
- const RegisterInfo *reg_info,
- const RegisterValue ®_value)
-{
- if (baton == nullptr)
- return false;
-
- StackFrame *frame = (StackFrame *) baton;
- return frame->GetRegisterContext()->WriteRegister (reg_info, reg_value);
-}
-
-size_t
-EmulateInstruction::ReadMemoryDefault (EmulateInstruction *instruction,
- void *baton,
- const Context &context,
- lldb::addr_t addr,
- void *dst,
- size_t length)
-{
- StreamFile strm (stdout, false);
- strm.Printf (" Read from Memory (address = 0x%" PRIx64 ", length = %" PRIu64 ", context = ", addr, (uint64_t)length);
- context.Dump (strm, instruction);
- strm.EOL();
- *((uint64_t *) dst) = 0xdeadbeef;
- return length;
-}
-
-size_t
-EmulateInstruction::WriteMemoryDefault (EmulateInstruction *instruction,
- void *baton,
- const Context &context,
- lldb::addr_t addr,
- const void *dst,
- size_t length)
-{
- StreamFile strm (stdout, false);
- strm.Printf (" Write to Memory (address = 0x%" PRIx64 ", length = %" PRIu64 ", context = ", addr, (uint64_t)length);
- context.Dump (strm, instruction);
- strm.EOL();
- return length;
-}
-
-bool
-EmulateInstruction::ReadRegisterDefault (EmulateInstruction *instruction,
- void *baton,
- const RegisterInfo *reg_info,
- RegisterValue ®_value)
-{
- StreamFile strm (stdout, false);
- strm.Printf (" Read Register (%s)\n", reg_info->name);
- lldb::RegisterKind reg_kind;
- uint32_t reg_num;
- if (GetBestRegisterKindAndNumber (reg_info, reg_kind, reg_num))
- reg_value.SetUInt64((uint64_t)reg_kind << 24 | reg_num);
- else
- reg_value.SetUInt64(0);
+ StackFrame *frame = (StackFrame *)baton;
- return true;
+ ProcessSP process_sp(frame->CalculateProcess());
+ if (process_sp) {
+ Error error;
+ return process_sp->WriteMemory(addr, src, src_len, error);
+ }
+
+ return 0;
}
-bool
-EmulateInstruction::WriteRegisterDefault (EmulateInstruction *instruction,
- void *baton,
- const Context &context,
- const RegisterInfo *reg_info,
- const RegisterValue ®_value)
-{
- StreamFile strm (stdout, false);
- strm.Printf (" Write to Register (name = %s, value = " , reg_info->name);
- reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
- strm.PutCString (", context = ");
- context.Dump (strm, instruction);
- strm.EOL();
- return true;
+bool EmulateInstruction::ReadRegisterFrame(EmulateInstruction *instruction,
+ void *baton,
+ const RegisterInfo *reg_info,
+ RegisterValue ®_value) {
+ if (baton == nullptr)
+ return false;
+
+ StackFrame *frame = (StackFrame *)baton;
+ return frame->GetRegisterContext()->ReadRegister(reg_info, reg_value);
}
-void
-EmulateInstruction::Context::Dump (Stream &strm,
- EmulateInstruction *instruction) const
-{
- switch (type)
- {
- case eContextReadOpcode:
- strm.PutCString ("reading opcode");
- break;
-
- case eContextImmediate:
- strm.PutCString ("immediate");
- break;
-
- case eContextPushRegisterOnStack:
- strm.PutCString ("push register");
- break;
-
- case eContextPopRegisterOffStack:
- strm.PutCString ("pop register");
- break;
-
- case eContextAdjustStackPointer:
- strm.PutCString ("adjust sp");
- break;
-
- case eContextSetFramePointer:
- strm.PutCString ("set frame pointer");
- break;
-
- case eContextAdjustBaseRegister:
- strm.PutCString ("adjusting (writing value back to) a base register");
- break;
-
- case eContextRegisterPlusOffset:
- strm.PutCString ("register + offset");
- break;
-
- case eContextRegisterStore:
- strm.PutCString ("store register");
- break;
-
- case eContextRegisterLoad:
- strm.PutCString ("load register");
- break;
-
- case eContextRelativeBranchImmediate:
- strm.PutCString ("relative branch immediate");
- break;
-
- case eContextAbsoluteBranchRegister:
- strm.PutCString ("absolute branch register");
- break;
-
- case eContextSupervisorCall:
- strm.PutCString ("supervisor call");
- break;
-
- case eContextTableBranchReadMemory:
- strm.PutCString ("table branch read memory");
- break;
-
- case eContextWriteRegisterRandomBits:
- strm.PutCString ("write random bits to a register");
- break;
-
- case eContextWriteMemoryRandomBits:
- strm.PutCString ("write random bits to a memory address");
- break;
-
- case eContextArithmetic:
- strm.PutCString ("arithmetic");
- break;
-
- case eContextReturnFromException:
- strm.PutCString ("return from exception");
- break;
-
- default:
- strm.PutCString ("unrecognized context.");
- break;
- }
-
- switch (info_type)
- {
- case eInfoTypeRegisterPlusOffset:
- strm.Printf(" (reg_plus_offset = %s%+" PRId64 ")",
- info.RegisterPlusOffset.reg.name,
- info.RegisterPlusOffset.signed_offset);
- break;
-
- case eInfoTypeRegisterPlusIndirectOffset:
- strm.Printf(" (reg_plus_reg = %s + %s)",
- info.RegisterPlusIndirectOffset.base_reg.name,
- info.RegisterPlusIndirectOffset.offset_reg.name);
- break;
-
- case eInfoTypeRegisterToRegisterPlusOffset:
- strm.Printf(" (base_and_imm_offset = %s%+" PRId64 ", data_reg = %s)",
- info.RegisterToRegisterPlusOffset.base_reg.name,
- info.RegisterToRegisterPlusOffset.offset,
- info.RegisterToRegisterPlusOffset.data_reg.name);
- break;
-
- case eInfoTypeRegisterToRegisterPlusIndirectOffset:
- strm.Printf(" (base_and_reg_offset = %s + %s, data_reg = %s)",
- info.RegisterToRegisterPlusIndirectOffset.base_reg.name,
- info.RegisterToRegisterPlusIndirectOffset.offset_reg.name,
- info.RegisterToRegisterPlusIndirectOffset.data_reg.name);
- break;
-
- case eInfoTypeRegisterRegisterOperands:
- strm.Printf(" (register to register binary op: %s and %s)",
- info.RegisterRegisterOperands.operand1.name,
- info.RegisterRegisterOperands.operand2.name);
- break;
-
- case eInfoTypeOffset:
- strm.Printf (" (signed_offset = %+" PRId64 ")", info.signed_offset);
- break;
-
- case eInfoTypeRegister:
- strm.Printf (" (reg = %s)", info.reg.name);
- break;
-
- case eInfoTypeImmediate:
- strm.Printf (" (unsigned_immediate = %" PRIu64 " (0x%16.16" PRIx64 "))",
- info.unsigned_immediate,
- info.unsigned_immediate);
- break;
-
- case eInfoTypeImmediateSigned:
- strm.Printf (" (signed_immediate = %+" PRId64 " (0x%16.16" PRIx64 "))",
- info.signed_immediate,
- info.signed_immediate);
- break;
-
- case eInfoTypeAddress:
- strm.Printf (" (address = 0x%" PRIx64 ")", info.address);
- break;
-
- case eInfoTypeISAAndImmediate:
- strm.Printf (" (isa = %u, unsigned_immediate = %u (0x%8.8x))",
- info.ISAAndImmediate.isa,
- info.ISAAndImmediate.unsigned_data32,
- info.ISAAndImmediate.unsigned_data32);
- break;
-
- case eInfoTypeISAAndImmediateSigned:
- strm.Printf (" (isa = %u, signed_immediate = %i (0x%8.8x))",
- info.ISAAndImmediateSigned.isa,
- info.ISAAndImmediateSigned.signed_data32,
- info.ISAAndImmediateSigned.signed_data32);
- break;
-
- case eInfoTypeISA:
- strm.Printf (" (isa = %u)", info.isa);
- break;
-
- case eInfoTypeNoArgs:
- break;
- }
+bool EmulateInstruction::WriteRegisterFrame(EmulateInstruction *instruction,
+ void *baton, const Context &context,
+ const RegisterInfo *reg_info,
+ const RegisterValue ®_value) {
+ if (baton == nullptr)
+ return false;
+
+ StackFrame *frame = (StackFrame *)baton;
+ return frame->GetRegisterContext()->WriteRegister(reg_info, reg_value);
}
-bool
-EmulateInstruction::SetInstruction (const Opcode &opcode, const Address &inst_addr, Target *target)
-{
- m_opcode = opcode;
- m_addr = LLDB_INVALID_ADDRESS;
- if (inst_addr.IsValid())
- {
- if (target != nullptr)
- m_addr = inst_addr.GetLoadAddress (target);
- if (m_addr == LLDB_INVALID_ADDRESS)
- m_addr = inst_addr.GetFileAddress ();
- }
+size_t EmulateInstruction::ReadMemoryDefault(EmulateInstruction *instruction,
+ void *baton,
+ const Context &context,
+ lldb::addr_t addr, void *dst,
+ size_t length) {
+ StreamFile strm(stdout, false);
+ strm.Printf(" Read from Memory (address = 0x%" PRIx64 ", length = %" PRIu64
+ ", context = ",
+ addr, (uint64_t)length);
+ context.Dump(strm, instruction);
+ strm.EOL();
+ *((uint64_t *)dst) = 0xdeadbeef;
+ return length;
+}
+
+size_t EmulateInstruction::WriteMemoryDefault(EmulateInstruction *instruction,
+ void *baton,
+ const Context &context,
+ lldb::addr_t addr,
+ const void *dst, size_t length) {
+ StreamFile strm(stdout, false);
+ strm.Printf(" Write to Memory (address = 0x%" PRIx64 ", length = %" PRIu64
+ ", context = ",
+ addr, (uint64_t)length);
+ context.Dump(strm, instruction);
+ strm.EOL();
+ return length;
+}
+
+bool EmulateInstruction::ReadRegisterDefault(EmulateInstruction *instruction,
+ void *baton,
+ const RegisterInfo *reg_info,
+ RegisterValue ®_value) {
+ StreamFile strm(stdout, false);
+ strm.Printf(" Read Register (%s)\n", reg_info->name);
+ lldb::RegisterKind reg_kind;
+ uint32_t reg_num;
+ if (GetBestRegisterKindAndNumber(reg_info, reg_kind, reg_num))
+ reg_value.SetUInt64((uint64_t)reg_kind << 24 | reg_num);
+ else
+ reg_value.SetUInt64(0);
+
+ return true;
+}
+
+bool EmulateInstruction::WriteRegisterDefault(EmulateInstruction *instruction,
+ void *baton,
+ const Context &context,
+ const RegisterInfo *reg_info,
+ const RegisterValue ®_value) {
+ StreamFile strm(stdout, false);
+ strm.Printf(" Write to Register (name = %s, value = ", reg_info->name);
+ reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
+ strm.PutCString(", context = ");
+ context.Dump(strm, instruction);
+ strm.EOL();
+ return true;
+}
+
+void EmulateInstruction::Context::Dump(Stream &strm,
+ EmulateInstruction *instruction) const {
+ switch (type) {
+ case eContextReadOpcode:
+ strm.PutCString("reading opcode");
+ break;
+
+ case eContextImmediate:
+ strm.PutCString("immediate");
+ break;
+
+ case eContextPushRegisterOnStack:
+ strm.PutCString("push register");
+ break;
+
+ case eContextPopRegisterOffStack:
+ strm.PutCString("pop register");
+ break;
+
+ case eContextAdjustStackPointer:
+ strm.PutCString("adjust sp");
+ break;
+
+ case eContextSetFramePointer:
+ strm.PutCString("set frame pointer");
+ break;
+
+ case eContextAdjustBaseRegister:
+ strm.PutCString("adjusting (writing value back to) a base register");
+ break;
+
+ case eContextRegisterPlusOffset:
+ strm.PutCString("register + offset");
+ break;
+
+ case eContextRegisterStore:
+ strm.PutCString("store register");
+ break;
+
+ case eContextRegisterLoad:
+ strm.PutCString("load register");
+ break;
+
+ case eContextRelativeBranchImmediate:
+ strm.PutCString("relative branch immediate");
+ break;
+
+ case eContextAbsoluteBranchRegister:
+ strm.PutCString("absolute branch register");
+ break;
+
+ case eContextSupervisorCall:
+ strm.PutCString("supervisor call");
+ break;
+
+ case eContextTableBranchReadMemory:
+ strm.PutCString("table branch read memory");
+ break;
+
+ case eContextWriteRegisterRandomBits:
+ strm.PutCString("write random bits to a register");
+ break;
+
+ case eContextWriteMemoryRandomBits:
+ strm.PutCString("write random bits to a memory address");
+ break;
+
+ case eContextArithmetic:
+ strm.PutCString("arithmetic");
+ break;
+
+ case eContextReturnFromException:
+ strm.PutCString("return from exception");
+ break;
+
+ default:
+ strm.PutCString("unrecognized context.");
+ break;
+ }
+
+ switch (info_type) {
+ case eInfoTypeRegisterPlusOffset:
+ strm.Printf(" (reg_plus_offset = %s%+" PRId64 ")",
+ info.RegisterPlusOffset.reg.name,
+ info.RegisterPlusOffset.signed_offset);
+ break;
+
+ case eInfoTypeRegisterPlusIndirectOffset:
+ strm.Printf(" (reg_plus_reg = %s + %s)",
+ info.RegisterPlusIndirectOffset.base_reg.name,
+ info.RegisterPlusIndirectOffset.offset_reg.name);
+ break;
+
+ case eInfoTypeRegisterToRegisterPlusOffset:
+ strm.Printf(" (base_and_imm_offset = %s%+" PRId64 ", data_reg = %s)",
+ info.RegisterToRegisterPlusOffset.base_reg.name,
+ info.RegisterToRegisterPlusOffset.offset,
+ info.RegisterToRegisterPlusOffset.data_reg.name);
+ break;
+
+ case eInfoTypeRegisterToRegisterPlusIndirectOffset:
+ strm.Printf(" (base_and_reg_offset = %s + %s, data_reg = %s)",
+ info.RegisterToRegisterPlusIndirectOffset.base_reg.name,
+ info.RegisterToRegisterPlusIndirectOffset.offset_reg.name,
+ info.RegisterToRegisterPlusIndirectOffset.data_reg.name);
+ break;
+
+ case eInfoTypeRegisterRegisterOperands:
+ strm.Printf(" (register to register binary op: %s and %s)",
+ info.RegisterRegisterOperands.operand1.name,
+ info.RegisterRegisterOperands.operand2.name);
+ break;
+
+ case eInfoTypeOffset:
+ strm.Printf(" (signed_offset = %+" PRId64 ")", info.signed_offset);
+ break;
+
+ case eInfoTypeRegister:
+ strm.Printf(" (reg = %s)", info.reg.name);
+ break;
+
+ case eInfoTypeImmediate:
+ strm.Printf(" (unsigned_immediate = %" PRIu64 " (0x%16.16" PRIx64 "))",
+ info.unsigned_immediate, info.unsigned_immediate);
+ break;
+
+ case eInfoTypeImmediateSigned:
+ strm.Printf(" (signed_immediate = %+" PRId64 " (0x%16.16" PRIx64 "))",
+ info.signed_immediate, info.signed_immediate);
+ break;
+
+ case eInfoTypeAddress:
+ strm.Printf(" (address = 0x%" PRIx64 ")", info.address);
+ break;
+
+ case eInfoTypeISAAndImmediate:
+ strm.Printf(" (isa = %u, unsigned_immediate = %u (0x%8.8x))",
+ info.ISAAndImmediate.isa, info.ISAAndImmediate.unsigned_data32,
+ info.ISAAndImmediate.unsigned_data32);
+ break;
+
+ case eInfoTypeISAAndImmediateSigned:
+ strm.Printf(" (isa = %u, signed_immediate = %i (0x%8.8x))",
+ info.ISAAndImmediateSigned.isa,
+ info.ISAAndImmediateSigned.signed_data32,
+ info.ISAAndImmediateSigned.signed_data32);
+ break;
+
+ case eInfoTypeISA:
+ strm.Printf(" (isa = %u)", info.isa);
+ break;
+
+ case eInfoTypeNoArgs:
+ break;
+ }
+}
+
+bool EmulateInstruction::SetInstruction(const Opcode &opcode,
+ const Address &inst_addr,
+ Target *target) {
+ m_opcode = opcode;
+ m_addr = LLDB_INVALID_ADDRESS;
+ if (inst_addr.IsValid()) {
+ if (target != nullptr)
+ m_addr = inst_addr.GetLoadAddress(target);
+ if (m_addr == LLDB_INVALID_ADDRESS)
+ m_addr = inst_addr.GetFileAddress();
+ }
+ return true;
+}
+
+bool EmulateInstruction::GetBestRegisterKindAndNumber(
+ const RegisterInfo *reg_info, lldb::RegisterKind ®_kind,
+ uint32_t ®_num) {
+ // Generic and DWARF should be the two most popular register kinds when
+ // emulating instructions since they are the most platform agnostic...
+ reg_num = reg_info->kinds[eRegisterKindGeneric];
+ if (reg_num != LLDB_INVALID_REGNUM) {
+ reg_kind = eRegisterKindGeneric;
return true;
-}
+ }
-bool
-EmulateInstruction::GetBestRegisterKindAndNumber (const RegisterInfo *reg_info,
- lldb::RegisterKind ®_kind,
- uint32_t ®_num)
-{
- // Generic and DWARF should be the two most popular register kinds when
- // emulating instructions since they are the most platform agnostic...
- reg_num = reg_info->kinds[eRegisterKindGeneric];
- if (reg_num != LLDB_INVALID_REGNUM)
- {
- reg_kind = eRegisterKindGeneric;
- return true;
- }
-
- reg_num = reg_info->kinds[eRegisterKindDWARF];
- if (reg_num != LLDB_INVALID_REGNUM)
- {
- reg_kind = eRegisterKindDWARF;
- return true;
- }
+ reg_num = reg_info->kinds[eRegisterKindDWARF];
+ if (reg_num != LLDB_INVALID_REGNUM) {
+ reg_kind = eRegisterKindDWARF;
+ return true;
+ }
- reg_num = reg_info->kinds[eRegisterKindLLDB];
- if (reg_num != LLDB_INVALID_REGNUM)
- {
- reg_kind = eRegisterKindLLDB;
- return true;
- }
+ reg_num = reg_info->kinds[eRegisterKindLLDB];
+ if (reg_num != LLDB_INVALID_REGNUM) {
+ reg_kind = eRegisterKindLLDB;
+ return true;
+ }
- reg_num = reg_info->kinds[eRegisterKindEHFrame];
- if (reg_num != LLDB_INVALID_REGNUM)
- {
- reg_kind = eRegisterKindEHFrame;
- return true;
- }
+ reg_num = reg_info->kinds[eRegisterKindEHFrame];
+ if (reg_num != LLDB_INVALID_REGNUM) {
+ reg_kind = eRegisterKindEHFrame;
+ return true;
+ }
- reg_num = reg_info->kinds[eRegisterKindProcessPlugin];
- if (reg_num != LLDB_INVALID_REGNUM)
- {
- reg_kind = eRegisterKindProcessPlugin;
- return true;
- }
- return false;
+ reg_num = reg_info->kinds[eRegisterKindProcessPlugin];
+ if (reg_num != LLDB_INVALID_REGNUM) {
+ reg_kind = eRegisterKindProcessPlugin;
+ return true;
+ }
+ return false;
}
uint32_t
-EmulateInstruction::GetInternalRegisterNumber (RegisterContext *reg_ctx, const RegisterInfo ®_info)
-{
- lldb::RegisterKind reg_kind;
- uint32_t reg_num;
- if (reg_ctx && GetBestRegisterKindAndNumber (®_info, reg_kind, reg_num))
- return reg_ctx->ConvertRegisterKindToRegisterNumber (reg_kind, reg_num);
- return LLDB_INVALID_REGNUM;
+EmulateInstruction::GetInternalRegisterNumber(RegisterContext *reg_ctx,
+ const RegisterInfo ®_info) {
+ lldb::RegisterKind reg_kind;
+ uint32_t reg_num;
+ if (reg_ctx && GetBestRegisterKindAndNumber(®_info, reg_kind, reg_num))
+ return reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
+ return LLDB_INVALID_REGNUM;
}
-bool
-EmulateInstruction::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
-{
- unwind_plan.Clear();
- return false;
+bool EmulateInstruction::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) {
+ unwind_plan.Clear();
+ return false;
}
Modified: lldb/trunk/source/Core/Error.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Error.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Core/Error.cpp (original)
+++ lldb/trunk/source/Core/Error.cpp Tue Sep 6 15:57:50 2016
@@ -27,59 +27,42 @@
using namespace lldb;
using namespace lldb_private;
-Error::Error ():
- m_code (0),
- m_type (eErrorTypeInvalid),
- m_string ()
-{
-}
+Error::Error() : m_code(0), m_type(eErrorTypeInvalid), m_string() {}
-Error::Error(ValueType err, ErrorType type) :
- m_code (err),
- m_type (type),
- m_string ()
-{
-}
+Error::Error(ValueType err, ErrorType type)
+ : m_code(err), m_type(type), m_string() {}
Error::Error(const Error &rhs) = default;
-Error::Error (const char* format, ...):
- m_code (0),
- m_type (eErrorTypeInvalid),
- m_string ()
-{
- va_list args;
- va_start (args, format);
- SetErrorToGenericError ();
- SetErrorStringWithVarArg (format, args);
- va_end (args);
+Error::Error(const char *format, ...)
+ : m_code(0), m_type(eErrorTypeInvalid), m_string() {
+ va_list args;
+ va_start(args, format);
+ SetErrorToGenericError();
+ SetErrorStringWithVarArg(format, args);
+ va_end(args);
}
//----------------------------------------------------------------------
// Assignment operator
//----------------------------------------------------------------------
-const Error&
-Error::operator = (const Error& rhs)
-{
- if (this != &rhs)
- {
- m_code = rhs.m_code;
- m_type = rhs.m_type;
- m_string = rhs.m_string;
- }
- return *this;
+const Error &Error::operator=(const Error &rhs) {
+ if (this != &rhs) {
+ m_code = rhs.m_code;
+ m_type = rhs.m_type;
+ m_string = rhs.m_string;
+ }
+ return *this;
}
//----------------------------------------------------------------------
// Assignment operator
//----------------------------------------------------------------------
-const Error&
-Error::operator = (uint32_t err)
-{
- m_code = err;
- m_type = eErrorTypeMachKernel;
- m_string.clear();
- return *this;
+const Error &Error::operator=(uint32_t err) {
+ m_code = err;
+ m_type = eErrorTypeMachKernel;
+ m_string.clear();
+ return *this;
}
Error::~Error() = default;
@@ -89,81 +72,62 @@ Error::~Error() = default;
// fetched and cached on demand. The cached error string value will
// remain until the error value is changed or cleared.
//----------------------------------------------------------------------
-const char *
-Error::AsCString(const char *default_error_str) const
-{
- if (Success())
- return nullptr;
-
- if (m_string.empty())
- {
- const char *s = nullptr;
- switch (m_type)
- {
- case eErrorTypeMachKernel:
-#if defined (__APPLE__)
- s = ::mach_error_string (m_code);
+const char *Error::AsCString(const char *default_error_str) const {
+ if (Success())
+ return nullptr;
+
+ if (m_string.empty()) {
+ const char *s = nullptr;
+ switch (m_type) {
+ case eErrorTypeMachKernel:
+#if defined(__APPLE__)
+ s = ::mach_error_string(m_code);
#endif
- break;
+ break;
- case eErrorTypePOSIX:
- s = ::strerror (m_code);
- break;
-
- default:
- break;
- }
- if (s != nullptr)
- m_string.assign(s);
- }
- if (m_string.empty())
- {
- if (default_error_str)
- m_string.assign(default_error_str);
- else
- return nullptr; // User wanted a nullptr string back...
- }
- return m_string.c_str();
+ case eErrorTypePOSIX:
+ s = ::strerror(m_code);
+ break;
+
+ default:
+ break;
+ }
+ if (s != nullptr)
+ m_string.assign(s);
+ }
+ if (m_string.empty()) {
+ if (default_error_str)
+ m_string.assign(default_error_str);
+ else
+ return nullptr; // User wanted a nullptr string back...
+ }
+ return m_string.c_str();
}
//----------------------------------------------------------------------
// Clear the error and any cached error string that it might contain.
//----------------------------------------------------------------------
-void
-Error::Clear ()
-{
- m_code = 0;
- m_type = eErrorTypeInvalid;
- m_string.clear();
+void Error::Clear() {
+ m_code = 0;
+ m_type = eErrorTypeInvalid;
+ m_string.clear();
}
//----------------------------------------------------------------------
// Access the error value.
//----------------------------------------------------------------------
-Error::ValueType
-Error::GetError () const
-{
- return m_code;
-}
+Error::ValueType Error::GetError() const { return m_code; }
//----------------------------------------------------------------------
// Access the error type.
//----------------------------------------------------------------------
-ErrorType
-Error::GetType () const
-{
- return m_type;
-}
+ErrorType Error::GetType() const { return m_type; }
//----------------------------------------------------------------------
// Returns true if this object contains a value that describes an
// error or otherwise non-success result.
//----------------------------------------------------------------------
-bool
-Error::Fail () const
-{
- return m_code != 0;
-}
+bool Error::Fail() const { return m_code != 0; }
//----------------------------------------------------------------------
// Log the error given a string with format. If the this object
@@ -174,34 +138,29 @@ Error::Fail () const
// cached in this object. Logging always occurs even when the error
// code contains a non-error value.
//----------------------------------------------------------------------
-void
-Error::PutToLog (Log *log, const char *format, ...)
-{
- char *arg_msg = nullptr;
- va_list args;
- va_start (args, format);
- ::vasprintf (&arg_msg, format, args);
- va_end (args);
-
- if (arg_msg != nullptr)
- {
- if (Fail())
- {
- const char *err_str = AsCString();
- if (err_str == nullptr)
- err_str = "???";
-
- SetErrorStringWithFormat("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_code);
- if (log != nullptr)
- log->Error("%s", m_string.c_str());
- }
- else
- {
- if (log != nullptr)
- log->Printf("%s err = 0x%8.8x", arg_msg, m_code);
- }
- ::free (arg_msg);
+void Error::PutToLog(Log *log, const char *format, ...) {
+ char *arg_msg = nullptr;
+ va_list args;
+ va_start(args, format);
+ ::vasprintf(&arg_msg, format, args);
+ va_end(args);
+
+ if (arg_msg != nullptr) {
+ if (Fail()) {
+ const char *err_str = AsCString();
+ if (err_str == nullptr)
+ err_str = "???";
+
+ SetErrorStringWithFormat("error: %s err = %s (0x%8.8x)", arg_msg, err_str,
+ m_code);
+ if (log != nullptr)
+ log->Error("%s", m_string.c_str());
+ } else {
+ if (log != nullptr)
+ log->Printf("%s err = 0x%8.8x", arg_msg, m_code);
}
+ ::free(arg_msg);
+ }
}
//----------------------------------------------------------------------
@@ -213,106 +172,90 @@ Error::PutToLog (Log *log, const char *f
// cached in this object. Logging only occurs even when the error
// code contains a error value.
//----------------------------------------------------------------------
-void
-Error::LogIfError (Log *log, const char *format, ...)
-{
- if (Fail())
- {
- char *arg_msg = nullptr;
- va_list args;
- va_start (args, format);
- ::vasprintf (&arg_msg, format, args);
- va_end (args);
-
- if (arg_msg != nullptr)
- {
- const char *err_str = AsCString();
- if (err_str == nullptr)
- err_str = "???";
-
- SetErrorStringWithFormat("%s err = %s (0x%8.8x)", arg_msg, err_str, m_code);
- if (log != nullptr)
- log->Error("%s", m_string.c_str());
+void Error::LogIfError(Log *log, const char *format, ...) {
+ if (Fail()) {
+ char *arg_msg = nullptr;
+ va_list args;
+ va_start(args, format);
+ ::vasprintf(&arg_msg, format, args);
+ va_end(args);
+
+ if (arg_msg != nullptr) {
+ const char *err_str = AsCString();
+ if (err_str == nullptr)
+ err_str = "???";
+
+ SetErrorStringWithFormat("%s err = %s (0x%8.8x)", arg_msg, err_str,
+ m_code);
+ if (log != nullptr)
+ log->Error("%s", m_string.c_str());
- ::free (arg_msg);
- }
+ ::free(arg_msg);
}
+ }
}
//----------------------------------------------------------------------
// Set accesssor for the error value to "err" and the type to
// "eErrorTypeMachKernel"
//----------------------------------------------------------------------
-void
-Error::SetMachError (uint32_t err)
-{
- m_code = err;
- m_type = eErrorTypeMachKernel;
- m_string.clear();
+void Error::SetMachError(uint32_t err) {
+ m_code = err;
+ m_type = eErrorTypeMachKernel;
+ m_string.clear();
}
-void
-Error::SetExpressionError (lldb::ExpressionResults result, const char *mssg)
-{
- m_code = result;
- m_type = eErrorTypeExpression;
- m_string = mssg;
-}
-
-int
-Error::SetExpressionErrorWithFormat (lldb::ExpressionResults result, const char *format, ...)
-{
- int length = 0;
-
- if (format != nullptr && format[0])
- {
- va_list args;
- va_start (args, format);
- length = SetErrorStringWithVarArg (format, args);
- va_end (args);
- }
- else
- {
- m_string.clear();
- }
- m_code = result;
- m_type = eErrorTypeExpression;
- return length;
+void Error::SetExpressionError(lldb::ExpressionResults result,
+ const char *mssg) {
+ m_code = result;
+ m_type = eErrorTypeExpression;
+ m_string = mssg;
+}
+
+int Error::SetExpressionErrorWithFormat(lldb::ExpressionResults result,
+ const char *format, ...) {
+ int length = 0;
+
+ if (format != nullptr && format[0]) {
+ va_list args;
+ va_start(args, format);
+ length = SetErrorStringWithVarArg(format, args);
+ va_end(args);
+ } else {
+ m_string.clear();
+ }
+ m_code = result;
+ m_type = eErrorTypeExpression;
+ return length;
}
//----------------------------------------------------------------------
// Set accesssor for the error value and type.
//----------------------------------------------------------------------
-void
-Error::SetError (ValueType err, ErrorType type)
-{
- m_code = err;
- m_type = type;
- m_string.clear();
+void Error::SetError(ValueType err, ErrorType type) {
+ m_code = err;
+ m_type = type;
+ m_string.clear();
}
//----------------------------------------------------------------------
// Update the error value to be "errno" and update the type to
// be "POSIX".
//----------------------------------------------------------------------
-void
-Error::SetErrorToErrno()
-{
- m_code = errno;
- m_type = eErrorTypePOSIX;
- m_string.clear();
+void Error::SetErrorToErrno() {
+ m_code = errno;
+ m_type = eErrorTypePOSIX;
+ m_string.clear();
}
//----------------------------------------------------------------------
// Update the error value to be LLDB_GENERIC_ERROR and update the type
// to be "Generic".
//----------------------------------------------------------------------
-void
-Error::SetErrorToGenericError ()
-{
- m_code = LLDB_GENERIC_ERROR;
- m_type = eErrorTypeGeneric;
- m_string.clear();
+void Error::SetErrorToGenericError() {
+ m_code = LLDB_GENERIC_ERROR;
+ m_type = eErrorTypeGeneric;
+ m_string.clear();
}
//----------------------------------------------------------------------
@@ -321,19 +264,15 @@ Error::SetErrorToGenericError ()
// The error string value will remain until the error value is
// cleared or a new error value/type is assigned.
//----------------------------------------------------------------------
-void
-Error::SetErrorString (const char *err_str)
-{
- if (err_str != nullptr && err_str[0])
- {
- // If we have an error string, we should always at least have
- // an error set to a generic value.
- if (Success())
- SetErrorToGenericError();
- m_string = err_str;
- }
- else
- m_string.clear();
+void Error::SetErrorString(const char *err_str) {
+ if (err_str != nullptr && err_str[0]) {
+ // If we have an error string, we should always at least have
+ // an error set to a generic value.
+ if (Success())
+ SetErrorToGenericError();
+ m_string = err_str;
+ } else
+ m_string.clear();
}
//------------------------------------------------------------------
@@ -342,74 +281,57 @@ Error::SetErrorString (const char *err_s
/// @param format
/// A printf style format string
//------------------------------------------------------------------
-int
-Error::SetErrorStringWithFormat (const char *format, ...)
-{
- if (format != nullptr && format[0])
- {
- va_list args;
- va_start (args, format);
- int length = SetErrorStringWithVarArg (format, args);
- va_end (args);
- return length;
- }
- else
- {
- m_string.clear();
- }
- return 0;
+int Error::SetErrorStringWithFormat(const char *format, ...) {
+ if (format != nullptr && format[0]) {
+ va_list args;
+ va_start(args, format);
+ int length = SetErrorStringWithVarArg(format, args);
+ va_end(args);
+ return length;
+ } else {
+ m_string.clear();
+ }
+ return 0;
}
-int
-Error::SetErrorStringWithVarArg (const char *format, va_list args)
-{
- if (format != nullptr && format[0])
- {
- // If we have an error string, we should always at least have
- // an error set to a generic value.
- if (Success())
- SetErrorToGenericError();
-
- // Try and fit our error into a 1024 byte buffer first...
- llvm::SmallVector<char, 1024> buf;
- buf.resize(1024);
- // Copy in case our first call to vsnprintf doesn't fit into our
- // allocated buffer above
- va_list copy_args;
- va_copy (copy_args, args);
- unsigned length = ::vsnprintf (buf.data(), buf.size(), format, args);
- if (length >= buf.size())
- {
- // The error formatted string didn't fit into our buffer, resize it
- // to the exact needed size, and retry
- buf.resize(length + 1);
- length = ::vsnprintf (buf.data(), buf.size(), format, copy_args);
- va_end (copy_args);
- assert (length < buf.size());
- }
- m_string.assign(buf.data(), length);
- va_end (args);
- return length;
- }
- else
- {
- m_string.clear();
+int Error::SetErrorStringWithVarArg(const char *format, va_list args) {
+ if (format != nullptr && format[0]) {
+ // If we have an error string, we should always at least have
+ // an error set to a generic value.
+ if (Success())
+ SetErrorToGenericError();
+
+ // Try and fit our error into a 1024 byte buffer first...
+ llvm::SmallVector<char, 1024> buf;
+ buf.resize(1024);
+ // Copy in case our first call to vsnprintf doesn't fit into our
+ // allocated buffer above
+ va_list copy_args;
+ va_copy(copy_args, args);
+ unsigned length = ::vsnprintf(buf.data(), buf.size(), format, args);
+ if (length >= buf.size()) {
+ // The error formatted string didn't fit into our buffer, resize it
+ // to the exact needed size, and retry
+ buf.resize(length + 1);
+ length = ::vsnprintf(buf.data(), buf.size(), format, copy_args);
+ va_end(copy_args);
+ assert(length < buf.size());
}
- return 0;
+ m_string.assign(buf.data(), length);
+ va_end(args);
+ return length;
+ } else {
+ m_string.clear();
+ }
+ return 0;
}
//----------------------------------------------------------------------
// Returns true if the error code in this object is considered a
// successful return value.
//----------------------------------------------------------------------
-bool
-Error::Success() const
-{
- return m_code == 0;
-}
+bool Error::Success() const { return m_code == 0; }
-bool
-Error::WasInterrupted() const
-{
- return (m_type == eErrorTypePOSIX && m_code == EINTR);
+bool Error::WasInterrupted() const {
+ return (m_type == eErrorTypePOSIX && m_code == EINTR);
}
Modified: lldb/trunk/source/Core/Event.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Event.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Core/Event.cpp (original)
+++ lldb/trunk/source/Core/Event.cpp Tue Sep 6 15:57:50 2016
@@ -13,9 +13,9 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/Core/Event.h"
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Event.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
#include "lldb/Core/Stream.h"
@@ -32,80 +32,59 @@ using namespace lldb_private;
// Event functions
//------------------------------------------------------------------
-Event::Event (Broadcaster *broadcaster, uint32_t event_type, EventData *data) :
- m_broadcaster_wp(broadcaster->GetBroadcasterImpl()),
- m_type(event_type),
- m_data_sp(data)
-{
-}
-
-Event::Event (Broadcaster *broadcaster, uint32_t event_type, const EventDataSP &event_data_sp) :
- m_broadcaster_wp(broadcaster->GetBroadcasterImpl()),
- m_type(event_type),
- m_data_sp(event_data_sp)
-{
-}
-
-Event::Event(uint32_t event_type, EventData *data) :
- m_broadcaster_wp(),
- m_type(event_type),
- m_data_sp(data)
-{
-}
-
-Event::Event(uint32_t event_type, const EventDataSP &event_data_sp) :
- m_broadcaster_wp(),
- m_type(event_type),
- m_data_sp(event_data_sp)
-{
-}
+Event::Event(Broadcaster *broadcaster, uint32_t event_type, EventData *data)
+ : m_broadcaster_wp(broadcaster->GetBroadcasterImpl()), m_type(event_type),
+ m_data_sp(data) {}
+
+Event::Event(Broadcaster *broadcaster, uint32_t event_type,
+ const EventDataSP &event_data_sp)
+ : m_broadcaster_wp(broadcaster->GetBroadcasterImpl()), m_type(event_type),
+ m_data_sp(event_data_sp) {}
-Event::~Event() = default;
+Event::Event(uint32_t event_type, EventData *data)
+ : m_broadcaster_wp(), m_type(event_type), m_data_sp(data) {}
-void
-Event::Dump (Stream *s) const
-{
- Broadcaster *broadcaster;
- Broadcaster::BroadcasterImplSP broadcaster_impl_sp(m_broadcaster_wp.lock());
- if (broadcaster_impl_sp)
- broadcaster = broadcaster_impl_sp->GetBroadcaster();
- else
- broadcaster = nullptr;
-
- if (broadcaster)
- {
- StreamString event_name;
- if (broadcaster->GetEventNames (event_name, m_type, false))
- s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x (%s), data = ",
- static_cast<const void*>(this),
- static_cast<void*>(broadcaster),
- broadcaster->GetBroadcasterName().GetCString(),
- m_type, event_name.GetString().c_str());
- else
- s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x, data = ",
- static_cast<const void*>(this),
- static_cast<void*>(broadcaster),
- broadcaster->GetBroadcasterName().GetCString(), m_type);
- }
- else
- s->Printf("%p Event: broadcaster = NULL, type = 0x%8.8x, data = ",
- static_cast<const void*>(this), m_type);
+Event::Event(uint32_t event_type, const EventDataSP &event_data_sp)
+ : m_broadcaster_wp(), m_type(event_type), m_data_sp(event_data_sp) {}
- if (m_data_sp)
- {
- s->PutChar('{');
- m_data_sp->Dump (s);
- s->PutChar('}');
- }
- else
- s->Printf ("<NULL>");
-}
+Event::~Event() = default;
-void
-Event::DoOnRemoval ()
-{
- if (m_data_sp)
- m_data_sp->DoOnRemoval (this);
+void Event::Dump(Stream *s) const {
+ Broadcaster *broadcaster;
+ Broadcaster::BroadcasterImplSP broadcaster_impl_sp(m_broadcaster_wp.lock());
+ if (broadcaster_impl_sp)
+ broadcaster = broadcaster_impl_sp->GetBroadcaster();
+ else
+ broadcaster = nullptr;
+
+ if (broadcaster) {
+ StreamString event_name;
+ if (broadcaster->GetEventNames(event_name, m_type, false))
+ s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x (%s), data = ",
+ static_cast<const void *>(this),
+ static_cast<void *>(broadcaster),
+ broadcaster->GetBroadcasterName().GetCString(), m_type,
+ event_name.GetString().c_str());
+ else
+ s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x, data = ",
+ static_cast<const void *>(this),
+ static_cast<void *>(broadcaster),
+ broadcaster->GetBroadcasterName().GetCString(), m_type);
+ } else
+ s->Printf("%p Event: broadcaster = NULL, type = 0x%8.8x, data = ",
+ static_cast<const void *>(this), m_type);
+
+ if (m_data_sp) {
+ s->PutChar('{');
+ m_data_sp->Dump(s);
+ s->PutChar('}');
+ } else
+ s->Printf("<NULL>");
+}
+
+void Event::DoOnRemoval() {
+ if (m_data_sp)
+ m_data_sp->DoOnRemoval(this);
}
#pragma mark -
@@ -119,11 +98,7 @@ EventData::EventData() = default;
EventData::~EventData() = default;
-void
-EventData::Dump (Stream *s) const
-{
- s->PutCString ("Generic Event Data");
-}
+void EventData::Dump(Stream *s) const { s->PutCString("Generic Event Data"); }
#pragma mark -
#pragma mark EventDataBytes
@@ -132,119 +107,87 @@ EventData::Dump (Stream *s) const
// EventDataBytes functions
//------------------------------------------------------------------
+EventDataBytes::EventDataBytes() : m_bytes() {}
-EventDataBytes::EventDataBytes () :
- m_bytes()
-{
+EventDataBytes::EventDataBytes(const char *cstr) : m_bytes() {
+ SetBytesFromCString(cstr);
}
-EventDataBytes::EventDataBytes (const char *cstr) :
- m_bytes()
-{
- SetBytesFromCString (cstr);
+EventDataBytes::EventDataBytes(const void *src, size_t src_len) : m_bytes() {
+ SetBytes(src, src_len);
}
-EventDataBytes::EventDataBytes (const void *src, size_t src_len) :
- m_bytes()
-{
- SetBytes (src, src_len);
+EventDataBytes::~EventDataBytes() = default;
+
+const ConstString &EventDataBytes::GetFlavorString() {
+ static ConstString g_flavor("EventDataBytes");
+ return g_flavor;
}
-EventDataBytes::~EventDataBytes() = default;
+const ConstString &EventDataBytes::GetFlavor() const {
+ return EventDataBytes::GetFlavorString();
+}
-const ConstString &
-EventDataBytes::GetFlavorString ()
-{
- static ConstString g_flavor ("EventDataBytes");
- return g_flavor;
-}
-
-const ConstString &
-EventDataBytes::GetFlavor () const
-{
- return EventDataBytes::GetFlavorString ();
-}
-
-void
-EventDataBytes::Dump (Stream *s) const
-{
- size_t num_printable_chars = std::count_if (m_bytes.begin(), m_bytes.end(), isprint);
- if (num_printable_chars == m_bytes.size())
- {
- s->Printf("\"%s\"", m_bytes.c_str());
- }
- else if (!m_bytes.empty())
- {
- DataExtractor data;
- data.SetData(m_bytes.data(), m_bytes.size(), endian::InlHostByteOrder());
- data.Dump(s, 0, eFormatBytes, 1, m_bytes.size(), 32, LLDB_INVALID_ADDRESS, 0, 0);
- }
-}
-
-const void *
-EventDataBytes::GetBytes() const
-{
- return (m_bytes.empty() ? nullptr : m_bytes.data());
-}
-
-size_t
-EventDataBytes::GetByteSize() const
-{
- return m_bytes.size ();
-}
-
-void
-EventDataBytes::SetBytes (const void *src, size_t src_len)
-{
- if (src != nullptr && src_len > 0)
- m_bytes.assign ((const char *)src, src_len);
- else
- m_bytes.clear();
+void EventDataBytes::Dump(Stream *s) const {
+ size_t num_printable_chars =
+ std::count_if(m_bytes.begin(), m_bytes.end(), isprint);
+ if (num_printable_chars == m_bytes.size()) {
+ s->Printf("\"%s\"", m_bytes.c_str());
+ } else if (!m_bytes.empty()) {
+ DataExtractor data;
+ data.SetData(m_bytes.data(), m_bytes.size(), endian::InlHostByteOrder());
+ data.Dump(s, 0, eFormatBytes, 1, m_bytes.size(), 32, LLDB_INVALID_ADDRESS,
+ 0, 0);
+ }
}
-void
-EventDataBytes::SetBytesFromCString (const char *cstr)
-{
- if (cstr != nullptr && cstr[0])
- m_bytes.assign (cstr);
- else
- m_bytes.clear();
+const void *EventDataBytes::GetBytes() const {
+ return (m_bytes.empty() ? nullptr : m_bytes.data());
}
-const void *
-EventDataBytes::GetBytesFromEvent (const Event *event_ptr)
-{
- const EventDataBytes *e = GetEventDataFromEvent (event_ptr);
- if (e != nullptr)
- return e->GetBytes();
- return nullptr;
+size_t EventDataBytes::GetByteSize() const { return m_bytes.size(); }
+
+void EventDataBytes::SetBytes(const void *src, size_t src_len) {
+ if (src != nullptr && src_len > 0)
+ m_bytes.assign((const char *)src, src_len);
+ else
+ m_bytes.clear();
}
-size_t
-EventDataBytes::GetByteSizeFromEvent (const Event *event_ptr)
-{
- const EventDataBytes *e = GetEventDataFromEvent (event_ptr);
- if (e != nullptr)
- return e->GetByteSize();
- return 0;
+void EventDataBytes::SetBytesFromCString(const char *cstr) {
+ if (cstr != nullptr && cstr[0])
+ m_bytes.assign(cstr);
+ else
+ m_bytes.clear();
+}
+
+const void *EventDataBytes::GetBytesFromEvent(const Event *event_ptr) {
+ const EventDataBytes *e = GetEventDataFromEvent(event_ptr);
+ if (e != nullptr)
+ return e->GetBytes();
+ return nullptr;
+}
+
+size_t EventDataBytes::GetByteSizeFromEvent(const Event *event_ptr) {
+ const EventDataBytes *e = GetEventDataFromEvent(event_ptr);
+ if (e != nullptr)
+ return e->GetByteSize();
+ return 0;
}
const EventDataBytes *
-EventDataBytes::GetEventDataFromEvent (const Event *event_ptr)
-{
- if (event_ptr != nullptr)
- {
- const EventData *event_data = event_ptr->GetData();
- if (event_data && event_data->GetFlavor() == EventDataBytes::GetFlavorString())
- return static_cast <const EventDataBytes *> (event_data);
- }
- return nullptr;
+EventDataBytes::GetEventDataFromEvent(const Event *event_ptr) {
+ if (event_ptr != nullptr) {
+ const EventData *event_data = event_ptr->GetData();
+ if (event_data &&
+ event_data->GetFlavor() == EventDataBytes::GetFlavorString())
+ return static_cast<const EventDataBytes *>(event_data);
+ }
+ return nullptr;
}
-void
-EventDataBytes::SwapBytes (std::string &new_bytes)
-{
- m_bytes.swap (new_bytes);
+void EventDataBytes::SwapBytes(std::string &new_bytes) {
+ m_bytes.swap(new_bytes);
}
#pragma mark -
@@ -254,142 +197,104 @@ EventDataBytes::SwapBytes (std::string &
// EventDataStructuredData definitions
//------------------------------------------------------------------
-EventDataStructuredData::EventDataStructuredData() :
- EventData(),
- m_process_sp(),
- m_object_sp(),
- m_plugin_sp()
-{
-}
-
-EventDataStructuredData::EventDataStructuredData(const ProcessSP &process_sp,
- const StructuredData::ObjectSP
- &object_sp,
- const
- lldb::StructuredDataPluginSP
- &plugin_sp) :
- EventData(),
- m_process_sp(process_sp),
- m_object_sp(object_sp),
- m_plugin_sp(plugin_sp)
-{
-}
+EventDataStructuredData::EventDataStructuredData()
+ : EventData(), m_process_sp(), m_object_sp(), m_plugin_sp() {}
-EventDataStructuredData::~EventDataStructuredData()
-{
-}
+EventDataStructuredData::EventDataStructuredData(
+ const ProcessSP &process_sp, const StructuredData::ObjectSP &object_sp,
+ const lldb::StructuredDataPluginSP &plugin_sp)
+ : EventData(), m_process_sp(process_sp), m_object_sp(object_sp),
+ m_plugin_sp(plugin_sp) {}
+
+EventDataStructuredData::~EventDataStructuredData() {}
//------------------------------------------------------------------
// EventDataStructuredData member functions
//------------------------------------------------------------------
-const ConstString &
-EventDataStructuredData::GetFlavor() const
-{
- return EventDataStructuredData::GetFlavorString();
+const ConstString &EventDataStructuredData::GetFlavor() const {
+ return EventDataStructuredData::GetFlavorString();
}
-void
-EventDataStructuredData::Dump(Stream *s) const
-{
- if (!s)
- return;
+void EventDataStructuredData::Dump(Stream *s) const {
+ if (!s)
+ return;
- if (m_object_sp)
- m_object_sp->Dump(*s);
+ if (m_object_sp)
+ m_object_sp->Dump(*s);
}
-const ProcessSP&
-EventDataStructuredData::GetProcess() const
-{
- return m_process_sp;
+const ProcessSP &EventDataStructuredData::GetProcess() const {
+ return m_process_sp;
}
-const StructuredData::ObjectSP&
-EventDataStructuredData::GetObject() const
-{
- return m_object_sp;
+const StructuredData::ObjectSP &EventDataStructuredData::GetObject() const {
+ return m_object_sp;
}
-const lldb::StructuredDataPluginSP&
-EventDataStructuredData::GetStructuredDataPlugin() const
-{
- return m_plugin_sp;
+const lldb::StructuredDataPluginSP &
+EventDataStructuredData::GetStructuredDataPlugin() const {
+ return m_plugin_sp;
}
-void
-EventDataStructuredData::SetProcess(const ProcessSP &process_sp)
-{
- m_process_sp = process_sp;
+void EventDataStructuredData::SetProcess(const ProcessSP &process_sp) {
+ m_process_sp = process_sp;
}
-void
-EventDataStructuredData::SetObject(const StructuredData::ObjectSP &object_sp)
-{
- m_object_sp = object_sp;
+void EventDataStructuredData::SetObject(
+ const StructuredData::ObjectSP &object_sp) {
+ m_object_sp = object_sp;
}
-void
-EventDataStructuredData::SetStructuredDataPlugin(const
- lldb::StructuredDataPluginSP
- &plugin_sp)
-{
- m_plugin_sp = plugin_sp;
+void EventDataStructuredData::SetStructuredDataPlugin(
+ const lldb::StructuredDataPluginSP &plugin_sp) {
+ m_plugin_sp = plugin_sp;
}
//------------------------------------------------------------------
// EventDataStructuredData static functions
//------------------------------------------------------------------
-const EventDataStructuredData*
-EventDataStructuredData::GetEventDataFromEvent(const Event *event_ptr)
-{
- if (event_ptr == nullptr)
- return nullptr;
+const EventDataStructuredData *
+EventDataStructuredData::GetEventDataFromEvent(const Event *event_ptr) {
+ if (event_ptr == nullptr)
+ return nullptr;
- const EventData *event_data = event_ptr->GetData();
- if (!event_data || event_data->GetFlavor() !=
- EventDataStructuredData::GetFlavorString())
- return nullptr;
-
- return static_cast<const EventDataStructuredData*>(event_data);
+ const EventData *event_data = event_ptr->GetData();
+ if (!event_data ||
+ event_data->GetFlavor() != EventDataStructuredData::GetFlavorString())
+ return nullptr;
+
+ return static_cast<const EventDataStructuredData *>(event_data);
}
-ProcessSP
-EventDataStructuredData::GetProcessFromEvent(const Event *event_ptr)
-{
- auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr);
- if (event_data)
- return event_data->GetProcess();
- else
- return ProcessSP();
+ProcessSP EventDataStructuredData::GetProcessFromEvent(const Event *event_ptr) {
+ auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr);
+ if (event_data)
+ return event_data->GetProcess();
+ else
+ return ProcessSP();
}
StructuredData::ObjectSP
-EventDataStructuredData::GetObjectFromEvent(const Event *event_ptr)
-{
- auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr);
- if (event_data)
- return event_data->GetObject();
- else
- return StructuredData::ObjectSP();
+EventDataStructuredData::GetObjectFromEvent(const Event *event_ptr) {
+ auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr);
+ if (event_data)
+ return event_data->GetObject();
+ else
+ return StructuredData::ObjectSP();
}
lldb::StructuredDataPluginSP
-EventDataStructuredData::GetPluginFromEvent(const Event *event_ptr)
-{
- auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr);
- if (event_data)
- return event_data->GetStructuredDataPlugin();
- else
- return StructuredDataPluginSP();
+EventDataStructuredData::GetPluginFromEvent(const Event *event_ptr) {
+ auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr);
+ if (event_data)
+ return event_data->GetStructuredDataPlugin();
+ else
+ return StructuredDataPluginSP();
}
-const ConstString &
-EventDataStructuredData::GetFlavorString ()
-{
- static ConstString s_flavor("EventDataStructuredData");
- return s_flavor;
+const ConstString &EventDataStructuredData::GetFlavorString() {
+ static ConstString s_flavor("EventDataStructuredData");
+ return s_flavor;
}
-
-
Modified: lldb/trunk/source/Core/FastDemangle.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FastDemangle.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Core/FastDemangle.cpp (original)
+++ lldb/trunk/source/Core/FastDemangle.cpp Tue Sep 6 15:57:50 2016
@@ -8,8 +8,8 @@
//===----------------------------------------------------------------------===//
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
+#include <string.h>
#include "lldb/lldb-private.h"
@@ -23,57 +23,52 @@ namespace {
/// @brief Represents the collection of qualifiers on a type
-enum Qualifiers
-{
- QualifierNone = 0,
- QualifierConst = 1,
- QualifierRestrict = 2,
- QualifierVolatile = 4,
- QualifierReference = 8,
- QualifierRValueReference = 16,
- QualifierPointer = 32
+enum Qualifiers {
+ QualifierNone = 0,
+ QualifierConst = 1,
+ QualifierRestrict = 2,
+ QualifierVolatile = 4,
+ QualifierReference = 8,
+ QualifierRValueReference = 16,
+ QualifierPointer = 32
};
/// @brief Categorizes the recognized operators
-enum class OperatorKind
-{
- Unary,
- Postfix,
- Binary,
- Ternary,
- Other,
- ConversionOperator,
- Vendor,
- NoMatch
+enum class OperatorKind {
+ Unary,
+ Postfix,
+ Binary,
+ Ternary,
+ Other,
+ ConversionOperator,
+ Vendor,
+ NoMatch
};
/// @brief Represents one of the recognized two-character operator
/// abbreviations used when parsing operators as names and expressions
-struct Operator
-{
- const char *name;
- OperatorKind kind;
+struct Operator {
+ const char *name;
+ OperatorKind kind;
};
/// @brief Represents a range of characters in the output buffer, typically for
/// use with RewriteRange()
-struct BufferRange
-{
- int offset;
- int length;
+struct BufferRange {
+ int offset;
+ int length;
};
/// @brief Transient state required while parsing a name
-struct NameState
-{
- bool parse_function_params;
- bool is_last_generic;
- bool has_no_return_type;
- BufferRange last_name_range;
+struct NameState {
+ bool parse_function_params;
+ bool is_last_generic;
+ bool has_no_return_type;
+ BufferRange last_name_range;
};
/// @brief LLDB's fast C++ demangler
@@ -86,942 +81,914 @@ struct NameState
/// Over time the full mangling spec should be supported without compromising
/// performance for the most common cases.
-class SymbolDemangler
-{
+class SymbolDemangler {
public:
-
- //----------------------------------------------------
- // Public API
- //----------------------------------------------------
-
- /// @brief Create a SymbolDemangler
- ///
- /// The newly created demangler allocates and owns scratch memory sufficient
- /// for demangling typical symbols. Additional memory will be allocated if
- /// needed and managed by the demangler instance.
-
- SymbolDemangler()
- {
- m_buffer = (char *) malloc(8192);
- m_buffer_end = m_buffer + 8192;
- m_owns_buffer = true;
-
- m_rewrite_ranges = (BufferRange *) malloc(128 * sizeof (BufferRange));
- m_rewrite_ranges_size = 128;
- m_owns_m_rewrite_ranges = true;
- }
-
- /// @brief Create a SymbolDemangler that uses provided scratch memory
- ///
- /// The provided memory is not owned by the demangler. It will be
- /// overwritten during calls to GetDemangledCopy() but can be used for
- /// other purposes between calls. The provided memory will not be freed
- /// when this instance is destroyed.
- ///
- /// If demangling a symbol requires additional space it will be allocated
- /// and managed by the demangler instance.
- ///
- /// @param storage_ptr Valid pointer to at least storage_size bytes of
- /// space that the SymbolDemangler can use during demangling
- ///
- /// @param storage_size Number of bytes of space available scratch memory
- /// referenced by storage_ptr
-
- SymbolDemangler(void *storage_ptr, int storage_size)
- {
- // Use up to 1/8th of the provided space for rewrite ranges
- m_rewrite_ranges_size = (storage_size >> 3) / sizeof (BufferRange);
- m_rewrite_ranges = (BufferRange *) storage_ptr;
- m_owns_m_rewrite_ranges = false;
-
- // Use the rest for the character buffer
- m_buffer = (char *) storage_ptr + m_rewrite_ranges_size * sizeof (BufferRange);
- m_buffer_end = (const char *)storage_ptr + storage_size;
- m_owns_buffer = false;
- }
-
- /// @brief Destroys the SymbolDemangler and deallocates any scratch
- /// memory that it owns
-
- ~SymbolDemangler()
- {
- if (m_owns_buffer)
- free(m_buffer);
- if (m_owns_m_rewrite_ranges)
- free(m_rewrite_ranges);
- }
+ //----------------------------------------------------
+ // Public API
+ //----------------------------------------------------
+
+ /// @brief Create a SymbolDemangler
+ ///
+ /// The newly created demangler allocates and owns scratch memory sufficient
+ /// for demangling typical symbols. Additional memory will be allocated if
+ /// needed and managed by the demangler instance.
+
+ SymbolDemangler() {
+ m_buffer = (char *)malloc(8192);
+ m_buffer_end = m_buffer + 8192;
+ m_owns_buffer = true;
+
+ m_rewrite_ranges = (BufferRange *)malloc(128 * sizeof(BufferRange));
+ m_rewrite_ranges_size = 128;
+ m_owns_m_rewrite_ranges = true;
+ }
+
+ /// @brief Create a SymbolDemangler that uses provided scratch memory
+ ///
+ /// The provided memory is not owned by the demangler. It will be
+ /// overwritten during calls to GetDemangledCopy() but can be used for
+ /// other purposes between calls. The provided memory will not be freed
+ /// when this instance is destroyed.
+ ///
+ /// If demangling a symbol requires additional space it will be allocated
+ /// and managed by the demangler instance.
+ ///
+ /// @param storage_ptr Valid pointer to at least storage_size bytes of
+ /// space that the SymbolDemangler can use during demangling
+ ///
+ /// @param storage_size Number of bytes of space available scratch memory
+ /// referenced by storage_ptr
+
+ SymbolDemangler(void *storage_ptr, int storage_size) {
+ // Use up to 1/8th of the provided space for rewrite ranges
+ m_rewrite_ranges_size = (storage_size >> 3) / sizeof(BufferRange);
+ m_rewrite_ranges = (BufferRange *)storage_ptr;
+ m_owns_m_rewrite_ranges = false;
+
+ // Use the rest for the character buffer
+ m_buffer =
+ (char *)storage_ptr + m_rewrite_ranges_size * sizeof(BufferRange);
+ m_buffer_end = (const char *)storage_ptr + storage_size;
+ m_owns_buffer = false;
+ }
+
+ /// @brief Destroys the SymbolDemangler and deallocates any scratch
+ /// memory that it owns
+
+ ~SymbolDemangler() {
+ if (m_owns_buffer)
+ free(m_buffer);
+ if (m_owns_m_rewrite_ranges)
+ free(m_rewrite_ranges);
+ }
#ifdef DEBUG_HIGHWATER
- int highwater_store = 0;
- int highwater_buffer = 0;
+ int highwater_store = 0;
+ int highwater_buffer = 0;
#endif
- /// @brief Parses the provided mangled name and returns a newly allocated
- /// demangling
- ///
- /// @param mangled_name Valid null-terminated C++ mangled name following
- /// the Itanium C++ ABI mangling specification as implemented by Clang
- ///
- /// @result Newly allocated null-terminated demangled name when demangling
- /// is successful, and nullptr when demangling fails. The caller is
- /// responsible for freeing the allocated memory.
-
- char *
- GetDemangledCopy(const char *mangled_name,
- long mangled_name_length = 0)
- {
- if (!ParseMangling(mangled_name, mangled_name_length))
- return nullptr;
+ /// @brief Parses the provided mangled name and returns a newly allocated
+ /// demangling
+ ///
+ /// @param mangled_name Valid null-terminated C++ mangled name following
+ /// the Itanium C++ ABI mangling specification as implemented by Clang
+ ///
+ /// @result Newly allocated null-terminated demangled name when demangling
+ /// is successful, and nullptr when demangling fails. The caller is
+ /// responsible for freeing the allocated memory.
+
+ char *GetDemangledCopy(const char *mangled_name,
+ long mangled_name_length = 0) {
+ if (!ParseMangling(mangled_name, mangled_name_length))
+ return nullptr;
#ifdef DEBUG_HIGHWATER
- int rewrite_count = m_next_substitute_index +
- (m_rewrite_ranges_size - 1 - m_next_template_arg_index);
- int buffer_size = (int)(m_write_ptr - m_buffer);
- if (rewrite_count > highwater_store)
- highwater_store = rewrite_count;
- if (buffer_size > highwater_buffer)
- highwater_buffer = buffer_size;
+ int rewrite_count = m_next_substitute_index +
+ (m_rewrite_ranges_size - 1 - m_next_template_arg_index);
+ int buffer_size = (int)(m_write_ptr - m_buffer);
+ if (rewrite_count > highwater_store)
+ highwater_store = rewrite_count;
+ if (buffer_size > highwater_buffer)
+ highwater_buffer = buffer_size;
#endif
- int length = (int)(m_write_ptr - m_buffer);
- char *copy = (char *)malloc(length + 1);
- memcpy(copy, m_buffer, length);
- copy[length] = '\0';
- return copy;
- }
+ int length = (int)(m_write_ptr - m_buffer);
+ char *copy = (char *)malloc(length + 1);
+ memcpy(copy, m_buffer, length);
+ copy[length] = '\0';
+ return copy;
+ }
private:
+ //----------------------------------------------------
+ // Grow methods
+ //
+ // Manage the storage used during demangling
+ //----------------------------------------------------
+
+ void GrowBuffer(long min_growth = 0) {
+ // By default, double the size of the buffer
+ long growth = m_buffer_end - m_buffer;
+
+ // Avoid growing by more than 1MB at a time
+ if (growth > 1 << 20)
+ growth = 1 << 20;
+
+ // ... but never grow by less than requested,
+ // or 1K, whichever is greater
+ if (min_growth < 1024)
+ min_growth = 1024;
+ if (growth < min_growth)
+ growth = min_growth;
+
+ // Allocate the new m_buffer and migrate content
+ long new_size = (m_buffer_end - m_buffer) + growth;
+ char *new_buffer = (char *)malloc(new_size);
+ memcpy(new_buffer, m_buffer, m_write_ptr - m_buffer);
+ if (m_owns_buffer)
+ free(m_buffer);
+ m_owns_buffer = true;
+
+ // Update references to the new buffer
+ m_write_ptr = new_buffer + (m_write_ptr - m_buffer);
+ m_buffer = new_buffer;
+ m_buffer_end = m_buffer + new_size;
+ }
+
+ void GrowRewriteRanges() {
+ // By default, double the size of the array
+ int growth = m_rewrite_ranges_size;
+
+ // Apply reasonable minimum and maximum sizes for growth
+ if (growth > 128)
+ growth = 128;
+ if (growth < 16)
+ growth = 16;
+
+ // Allocate the new array and migrate content
+ int bytes = (m_rewrite_ranges_size + growth) * sizeof(BufferRange);
+ BufferRange *new_ranges = (BufferRange *)malloc(bytes);
+ for (int index = 0; index < m_next_substitute_index; index++) {
+ new_ranges[index] = m_rewrite_ranges[index];
+ }
+ for (int index = m_rewrite_ranges_size - 1;
+ index > m_next_template_arg_index; index--) {
+ new_ranges[index + growth] = m_rewrite_ranges[index];
+ }
+ if (m_owns_m_rewrite_ranges)
+ free(m_rewrite_ranges);
+ m_owns_m_rewrite_ranges = true;
+
+ // Update references to the new array
+ m_rewrite_ranges = new_ranges;
+ m_rewrite_ranges_size += growth;
+ m_next_template_arg_index += growth;
+ }
+
+ //----------------------------------------------------
+ // Range and state management
+ //----------------------------------------------------
+
+ int GetStartCookie() { return (int)(m_write_ptr - m_buffer); }
+
+ BufferRange EndRange(int start_cookie) {
+ return {start_cookie, (int)(m_write_ptr - (m_buffer + start_cookie))};
+ }
+
+ void ReorderRange(BufferRange source_range, int insertion_point_cookie) {
+ // Ensure there's room the preserve the source range
+ if (m_write_ptr + source_range.length > m_buffer_end) {
+ GrowBuffer(m_write_ptr + source_range.length - m_buffer_end);
+ }
+
+ // Reorder the content
+ memcpy(m_write_ptr, m_buffer + source_range.offset, source_range.length);
+ memmove(m_buffer + insertion_point_cookie + source_range.length,
+ m_buffer + insertion_point_cookie,
+ source_range.offset - insertion_point_cookie);
+ memcpy(m_buffer + insertion_point_cookie, m_write_ptr, source_range.length);
+
+ // Fix up rewritable ranges, covering both substitutions and templates
+ int index = 0;
+ while (true) {
+ if (index == m_next_substitute_index)
+ index = m_next_template_arg_index + 1;
+ if (index == m_rewrite_ranges_size)
+ break;
+
+ // Affected ranges are either shuffled forward when after the
+ // insertion but before the source, or backward when inside the
+ // source
+ int candidate_offset = m_rewrite_ranges[index].offset;
+ if (candidate_offset >= insertion_point_cookie) {
+ if (candidate_offset < source_range.offset) {
+ m_rewrite_ranges[index].offset += source_range.length;
+ } else if (candidate_offset >= source_range.offset) {
+ m_rewrite_ranges[index].offset -=
+ (source_range.offset - insertion_point_cookie);
+ }
+ }
+ ++index;
+ }
+ }
+
+ void EndSubstitution(int start_cookie) {
+ if (m_next_substitute_index == m_next_template_arg_index)
+ GrowRewriteRanges();
- //----------------------------------------------------
- // Grow methods
- //
- // Manage the storage used during demangling
- //----------------------------------------------------
-
- void GrowBuffer(long min_growth = 0)
- {
- // By default, double the size of the buffer
- long growth = m_buffer_end - m_buffer;
-
- // Avoid growing by more than 1MB at a time
- if (growth > 1 << 20)
- growth = 1 << 20;
-
- // ... but never grow by less than requested,
- // or 1K, whichever is greater
- if (min_growth < 1024)
- min_growth = 1024;
- if (growth < min_growth)
- growth = min_growth;
-
- // Allocate the new m_buffer and migrate content
- long new_size = (m_buffer_end - m_buffer) + growth;
- char *new_buffer = (char *) malloc(new_size);
- memcpy(new_buffer, m_buffer, m_write_ptr - m_buffer);
- if (m_owns_buffer)
- free(m_buffer);
- m_owns_buffer = true;
-
- // Update references to the new buffer
- m_write_ptr = new_buffer + (m_write_ptr - m_buffer);
- m_buffer = new_buffer;
- m_buffer_end = m_buffer + new_size;
- }
-
- void
- GrowRewriteRanges()
- {
- // By default, double the size of the array
- int growth = m_rewrite_ranges_size;
-
- // Apply reasonable minimum and maximum sizes for growth
- if (growth > 128)
- growth = 128;
- if (growth < 16)
- growth = 16;
-
- // Allocate the new array and migrate content
- int bytes = (m_rewrite_ranges_size + growth) * sizeof (BufferRange);
- BufferRange *new_ranges = (BufferRange *) malloc (bytes);
- for (int index = 0; index < m_next_substitute_index; index++)
- {
- new_ranges[index] = m_rewrite_ranges[index];
- }
- for (int index = m_rewrite_ranges_size - 1;
- index > m_next_template_arg_index; index--)
- {
- new_ranges[index + growth] = m_rewrite_ranges[index];
- }
- if (m_owns_m_rewrite_ranges)
- free(m_rewrite_ranges);
- m_owns_m_rewrite_ranges = true;
-
- // Update references to the new array
- m_rewrite_ranges = new_ranges;
- m_rewrite_ranges_size += growth;
- m_next_template_arg_index += growth;
- }
-
- //----------------------------------------------------
- // Range and state management
- //----------------------------------------------------
-
- int
- GetStartCookie()
- {
- return (int)(m_write_ptr - m_buffer);
- }
-
- BufferRange
- EndRange(int start_cookie)
- {
- return { start_cookie, (int)(m_write_ptr - (m_buffer + start_cookie)) };
- }
-
- void
- ReorderRange(BufferRange source_range, int insertion_point_cookie)
- {
- // Ensure there's room the preserve the source range
- if (m_write_ptr + source_range.length > m_buffer_end)
- {
- GrowBuffer(m_write_ptr + source_range.length - m_buffer_end);
- }
-
- // Reorder the content
- memcpy(m_write_ptr, m_buffer + source_range.offset, source_range.length);
- memmove(m_buffer + insertion_point_cookie + source_range.length,
- m_buffer + insertion_point_cookie,
- source_range.offset - insertion_point_cookie);
- memcpy(m_buffer + insertion_point_cookie, m_write_ptr, source_range.length);
-
- // Fix up rewritable ranges, covering both substitutions and templates
- int index = 0;
- while (true)
- {
- if (index == m_next_substitute_index)
- index = m_next_template_arg_index + 1;
- if (index == m_rewrite_ranges_size)
- break;
-
- // Affected ranges are either shuffled forward when after the
- // insertion but before the source, or backward when inside the
- // source
- int candidate_offset = m_rewrite_ranges[index].offset;
- if (candidate_offset >= insertion_point_cookie)
- {
- if (candidate_offset < source_range.offset)
- {
- m_rewrite_ranges[index].offset += source_range.length;
- }
- else if (candidate_offset >= source_range.offset)
- {
- m_rewrite_ranges[index].offset -= (source_range.offset - insertion_point_cookie);
- }
- }
- ++index;
- }
- }
-
- void
- EndSubstitution(int start_cookie)
- {
- if (m_next_substitute_index == m_next_template_arg_index)
- GrowRewriteRanges();
-
- int index = m_next_substitute_index++;
- m_rewrite_ranges[index] = EndRange(start_cookie);
+ int index = m_next_substitute_index++;
+ m_rewrite_ranges[index] = EndRange(start_cookie);
#ifdef DEBUG_SUBSTITUTIONS
- printf("Saved substitution # %d = %.*s\n", index,
- m_rewrite_ranges[index].length, m_buffer + start_cookie);
+ printf("Saved substitution # %d = %.*s\n", index,
+ m_rewrite_ranges[index].length, m_buffer + start_cookie);
#endif
- }
+ }
- void
- EndTemplateArg(int start_cookie)
- {
- if (m_next_substitute_index == m_next_template_arg_index)
- GrowRewriteRanges();
+ void EndTemplateArg(int start_cookie) {
+ if (m_next_substitute_index == m_next_template_arg_index)
+ GrowRewriteRanges();
- int index = m_next_template_arg_index--;
- m_rewrite_ranges[index] = EndRange(start_cookie);
+ int index = m_next_template_arg_index--;
+ m_rewrite_ranges[index] = EndRange(start_cookie);
#ifdef DEBUG_TEMPLATE_ARGS
- printf("Saved template arg # %d = %.*s\n",
- m_rewrite_ranges_size - index - 1,
- m_rewrite_ranges[index].length, m_buffer + start_cookie);
-#endif
- }
-
- void
- ResetTemplateArgs()
- {
- //TODO: this works, but is it the right thing to do?
- // Should we push/pop somehow at the call sites?
- m_next_template_arg_index = m_rewrite_ranges_size - 1;
- }
-
- //----------------------------------------------------
- // Write methods
- //
- // Appends content to the existing output buffer
- //----------------------------------------------------
-
- void
- Write(char character)
- {
- if (m_write_ptr == m_buffer_end)
- GrowBuffer();
- *m_write_ptr++ = character;
- }
-
- void
- Write(const char *content)
- {
- Write(content, strlen(content));
- }
-
- void
- Write(const char *content, long content_length)
- {
- char *end_m_write_ptr = m_write_ptr + content_length;
- if (end_m_write_ptr > m_buffer_end)
- {
- if (content >= m_buffer && content < m_buffer_end)
- {
- long offset = content - m_buffer;
- GrowBuffer (end_m_write_ptr - m_buffer_end);
- content = m_buffer + offset;
- }
- else
- {
- GrowBuffer (end_m_write_ptr - m_buffer_end);
- }
- end_m_write_ptr = m_write_ptr + content_length;
- }
- memcpy (m_write_ptr, content, content_length);
- m_write_ptr = end_m_write_ptr;
- }
-#define WRITE(x) Write(x, sizeof (x) - 1)
-
- void
- WriteTemplateStart()
- {
- Write('<');
- }
-
- void
- WriteTemplateEnd()
- {
- // Put a space between terminal > characters when nesting templates
- if (m_write_ptr != m_buffer && *(m_write_ptr - 1) == '>')
- WRITE(" >");
- else Write('>');
- }
-
- void
- WriteCommaSpace()
- {
- WRITE(", ");
- }
-
- void
- WriteNamespaceSeparator()
- {
- WRITE("::");
- }
-
- void
- WriteStdPrefix()
- {
- WRITE("std::");
- }
-
- void
- WriteQualifiers(int qualifiers, bool space_before_reference = true)
- {
- if (qualifiers & QualifierPointer)
- Write('*');
- if (qualifiers & QualifierConst)
- WRITE(" const");
- if (qualifiers & QualifierVolatile)
- WRITE(" volatile");
- if (qualifiers & QualifierRestrict)
- WRITE(" restrict");
- if (qualifiers & QualifierReference)
- {
- if (space_before_reference)
- WRITE(" &");
- else Write('&');
- }
- if (qualifiers & QualifierRValueReference)
- {
- if (space_before_reference)
- WRITE(" &&");
- else WRITE("&&");
- }
- }
-
- //----------------------------------------------------
- // Rewrite methods
- //
- // Write another copy of content already present
- // earlier in the output buffer
- //----------------------------------------------------
-
- void
- RewriteRange(BufferRange range)
- {
- Write(m_buffer + range.offset, range.length);
- }
-
- bool
- RewriteSubstitution(int index)
- {
- if (index < 0 || index >= m_next_substitute_index)
- {
-#ifdef DEBUG_FAILURES
- printf("*** Invalid substitution #%d\n", index);
-#endif
- return false;
- }
- RewriteRange(m_rewrite_ranges[index]);
- return true;
- }
-
- bool
- RewriteTemplateArg(int template_index)
- {
- int index = m_rewrite_ranges_size - 1 - template_index;
- if (template_index < 0 || index <= m_next_template_arg_index)
- {
-#ifdef DEBUG_FAILURES
- printf("*** Invalid template arg reference #%d\n", template_index);
-#endif
- return false;
- }
- RewriteRange(m_rewrite_ranges[index]);
- return true;
- }
-
- //----------------------------------------------------
- // TryParse methods
- //
- // Provide information with return values instead of
- // writing to the output buffer
- //
- // Values indicating failure guarantee that the pre-
- // call m_read_ptr is unchanged
- //----------------------------------------------------
-
- int
- TryParseNumber()
- {
- unsigned char digit = *m_read_ptr - '0';
- if (digit > 9)
- return -1;
-
- int count = digit;
- while (true)
- {
- digit = *++m_read_ptr - '0';
- if (digit > 9)
- break;
-
- count = count * 10 + digit;
- }
- return count;
- }
-
- int
- TryParseBase36Number()
- {
- char digit = *m_read_ptr;
- int count;
- if (digit >= '0' && digit <= '9')
- count = digit -= '0';
- else if (digit >= 'A' && digit <= 'Z')
- count = digit -= ('A' - 10);
- else return -1;
-
- while (true)
- {
- digit = *++m_read_ptr;
- if (digit >= '0' && digit <= '9')
- digit -= '0';
- else if (digit >= 'A' && digit <= 'Z')
- digit -= ('A' - 10);
- else break;
-
- count = count * 36 + digit;
- }
- return count;
- }
-
- // <builtin-type> ::= v # void
- // ::= w # wchar_t
- // ::= b # bool
- // ::= c # char
- // ::= a # signed char
- // ::= h # unsigned char
- // ::= s # short
- // ::= t # unsigned short
- // ::= i # int
- // ::= j # unsigned int
- // ::= l # long
- // ::= m # unsigned long
- // ::= x # long long, __int64
- // ::= y # unsigned long long, __int64
- // ::= n # __int128
- // ::= o # unsigned __int128
- // ::= f # float
- // ::= d # double
- // ::= e # long double, __float80
- // ::= g # __float128
- // ::= z # ellipsis
- // ::= Dd # IEEE 754r decimal floating point (64 bits)
- // ::= De # IEEE 754r decimal floating point (128 bits)
- // ::= Df # IEEE 754r decimal floating point (32 bits)
- // ::= Dh # IEEE 754r half-precision floating point (16 bits)
- // ::= Di # char32_t
- // ::= Ds # char16_t
- // ::= Da # auto (in dependent new-expressions)
- // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
- // ::= u <source-name> # vendor extended type
-
- const char *
- TryParseBuiltinType()
- {
- switch (*m_read_ptr++)
- {
- case 'v': return "void";
- case 'w': return "wchar_t";
- case 'b': return "bool";
- case 'c': return "char";
- case 'a': return "signed char";
- case 'h': return "unsigned char";
- case 's': return "short";
- case 't': return "unsigned short";
- case 'i': return "int";
- case 'j': return "unsigned int";
- case 'l': return "long";
- case 'm': return "unsigned long";
- case 'x': return "long long";
- case 'y': return "unsigned long long";
- case 'n': return "__int128";
- case 'o': return "unsigned __int128";
- case 'f': return "float";
- case 'd': return "double";
- case 'e': return "long double";
- case 'g': return "__float128";
- case 'z': return "...";
- case 'D':
- {
- switch (*m_read_ptr++)
- {
- case 'd': return "decimal64";
- case 'e': return "decimal128";
- case 'f': return "decimal32";
- case 'h': return "decimal16";
- case 'i': return "char32_t";
- case 's': return "char16_t";
- case 'a': return "auto";
- case 'c': return "decltype(auto)";
- case 'n': return "std::nullptr_t";
- default:
- --m_read_ptr;
- }
- }
- }
- --m_read_ptr;
- return nullptr;
- }
-
- // <operator-name>
- // ::= aa # &&
- // ::= ad # & (unary)
- // ::= an # &
- // ::= aN # &=
- // ::= aS # =
- // ::= cl # ()
- // ::= cm # ,
- // ::= co # ~
- // ::= da # delete[]
- // ::= de # * (unary)
- // ::= dl # delete
- // ::= dv # /
- // ::= dV # /=
- // ::= eo # ^
- // ::= eO # ^=
- // ::= eq # ==
- // ::= ge # >=
- // ::= gt # >
- // ::= ix # []
- // ::= le # <=
- // ::= ls # <<
- // ::= lS # <<=
- // ::= lt # <
- // ::= mi # -
- // ::= mI # -=
- // ::= ml # *
- // ::= mL # *=
- // ::= mm # -- (postfix in <expression> context)
- // ::= na # new[]
- // ::= ne # !=
- // ::= ng # - (unary)
- // ::= nt # !
- // ::= nw # new
- // ::= oo # ||
- // ::= or # |
- // ::= oR # |=
- // ::= pm # ->*
- // ::= pl # +
- // ::= pL # +=
- // ::= pp # ++ (postfix in <expression> context)
- // ::= ps # + (unary)
- // ::= pt # ->
- // ::= qu # ?
- // ::= rm # %
- // ::= rM # %=
- // ::= rs # >>
- // ::= rS # >>=
- // ::= cv <type> # (cast)
- // ::= v <digit> <source-name> # vendor extended operator
-
- Operator
- TryParseOperator()
- {
- switch (*m_read_ptr++)
- {
- case 'a':
- switch (*m_read_ptr++)
- {
- case 'a': return { "&&", OperatorKind::Binary };
- case 'd': return { "&", OperatorKind::Unary };
- case 'n': return { "&", OperatorKind::Binary };
- case 'N': return { "&=", OperatorKind::Binary };
- case 'S': return { "=", OperatorKind::Binary };
- }
- --m_read_ptr;
- break;
- case 'c':
- switch (*m_read_ptr++)
- {
- case 'l': return { "()", OperatorKind::Other };
- case 'm': return { ",", OperatorKind::Other };
- case 'o': return { "~", OperatorKind::Unary };
- case 'v': return { nullptr, OperatorKind::ConversionOperator };
- }
- --m_read_ptr;
- break;
- case 'd':
- switch (*m_read_ptr++)
- {
- case 'a': return { " delete[]", OperatorKind::Other };
- case 'e': return { "*", OperatorKind::Unary };
- case 'l': return { " delete", OperatorKind::Other };
- case 'v': return { "/", OperatorKind::Binary };
- case 'V': return { "/=", OperatorKind::Binary };
- }
- --m_read_ptr;
- break;
- case 'e':
- switch (*m_read_ptr++)
- {
- case 'o': return { "^", OperatorKind::Binary };
- case 'O': return { "^=", OperatorKind::Binary };
- case 'q': return { "==", OperatorKind::Binary };
- }
- --m_read_ptr;
- break;
- case 'g':
- switch (*m_read_ptr++)
- {
- case 'e': return { ">=", OperatorKind::Binary };
- case 't': return { ">", OperatorKind::Binary };
- }
- --m_read_ptr;
- break;
- case 'i':
- switch (*m_read_ptr++)
- {
- case 'x': return { "[]", OperatorKind::Other };
- }
- --m_read_ptr;
- break;
- case 'l':
- switch (*m_read_ptr++)
- {
- case 'e': return { "<=", OperatorKind::Binary };
- case 's': return { "<<", OperatorKind::Binary };
- case 'S': return { "<<=", OperatorKind::Binary };
- case 't': return { "<", OperatorKind::Binary };
- // case 'i': return { "?", OperatorKind::Binary };
- }
- --m_read_ptr;
- break;
- case 'm':
- switch (*m_read_ptr++)
- {
- case 'i': return { "-", OperatorKind::Binary };
- case 'I': return { "-=", OperatorKind::Binary };
- case 'l': return { "*", OperatorKind::Binary };
- case 'L': return { "*=", OperatorKind::Binary };
- case 'm': return { "--", OperatorKind::Postfix };
- }
- --m_read_ptr;
- break;
- case 'n':
- switch (*m_read_ptr++)
- {
- case 'a': return { " new[]", OperatorKind::Other };
- case 'e': return { "!=", OperatorKind::Binary };
- case 'g': return { "-", OperatorKind::Unary };
- case 't': return { "!", OperatorKind::Unary };
- case 'w': return { " new", OperatorKind::Other };
- }
- --m_read_ptr;
- break;
- case 'o':
- switch (*m_read_ptr++)
- {
- case 'o': return { "||", OperatorKind::Binary };
- case 'r': return { "|", OperatorKind::Binary };
- case 'R': return { "|=", OperatorKind::Binary };
- }
- --m_read_ptr;
- break;
- case 'p':
- switch (*m_read_ptr++)
- {
- case 'm': return { "->*", OperatorKind::Binary };
- case 's': return { "+", OperatorKind::Unary };
- case 'l': return { "+", OperatorKind::Binary };
- case 'L': return { "+=", OperatorKind::Binary };
- case 'p': return { "++", OperatorKind::Postfix };
- case 't': return { "->", OperatorKind::Binary };
- }
- --m_read_ptr;
- break;
- case 'q':
- switch (*m_read_ptr++)
- {
- case 'u': return { "?", OperatorKind::Ternary };
- }
- --m_read_ptr;
- break;
- case 'r':
- switch (*m_read_ptr++)
- {
- case 'm': return { "%", OperatorKind::Binary };
- case 'M': return { "%=", OperatorKind::Binary };
- case 's': return { ">>", OperatorKind::Binary };
- case 'S': return { ">=", OperatorKind::Binary };
- }
- --m_read_ptr;
- break;
- case 'v':
- char digit = *m_read_ptr;
- if (digit >= '0' && digit <= '9')
- {
- m_read_ptr++;
- return { nullptr, OperatorKind::Vendor };
- }
- --m_read_ptr;
- break;
- }
+ printf("Saved template arg # %d = %.*s\n",
+ m_rewrite_ranges_size - index - 1, m_rewrite_ranges[index].length,
+ m_buffer + start_cookie);
+#endif
+ }
+
+ void ResetTemplateArgs() {
+ // TODO: this works, but is it the right thing to do?
+ // Should we push/pop somehow at the call sites?
+ m_next_template_arg_index = m_rewrite_ranges_size - 1;
+ }
+
+ //----------------------------------------------------
+ // Write methods
+ //
+ // Appends content to the existing output buffer
+ //----------------------------------------------------
+
+ void Write(char character) {
+ if (m_write_ptr == m_buffer_end)
+ GrowBuffer();
+ *m_write_ptr++ = character;
+ }
+
+ void Write(const char *content) { Write(content, strlen(content)); }
+
+ void Write(const char *content, long content_length) {
+ char *end_m_write_ptr = m_write_ptr + content_length;
+ if (end_m_write_ptr > m_buffer_end) {
+ if (content >= m_buffer && content < m_buffer_end) {
+ long offset = content - m_buffer;
+ GrowBuffer(end_m_write_ptr - m_buffer_end);
+ content = m_buffer + offset;
+ } else {
+ GrowBuffer(end_m_write_ptr - m_buffer_end);
+ }
+ end_m_write_ptr = m_write_ptr + content_length;
+ }
+ memcpy(m_write_ptr, content, content_length);
+ m_write_ptr = end_m_write_ptr;
+ }
+#define WRITE(x) Write(x, sizeof(x) - 1)
+
+ void WriteTemplateStart() { Write('<'); }
+
+ void WriteTemplateEnd() {
+ // Put a space between terminal > characters when nesting templates
+ if (m_write_ptr != m_buffer && *(m_write_ptr - 1) == '>')
+ WRITE(" >");
+ else
+ Write('>');
+ }
+
+ void WriteCommaSpace() { WRITE(", "); }
+
+ void WriteNamespaceSeparator() { WRITE("::"); }
+
+ void WriteStdPrefix() { WRITE("std::"); }
+
+ void WriteQualifiers(int qualifiers, bool space_before_reference = true) {
+ if (qualifiers & QualifierPointer)
+ Write('*');
+ if (qualifiers & QualifierConst)
+ WRITE(" const");
+ if (qualifiers & QualifierVolatile)
+ WRITE(" volatile");
+ if (qualifiers & QualifierRestrict)
+ WRITE(" restrict");
+ if (qualifiers & QualifierReference) {
+ if (space_before_reference)
+ WRITE(" &");
+ else
+ Write('&');
+ }
+ if (qualifiers & QualifierRValueReference) {
+ if (space_before_reference)
+ WRITE(" &&");
+ else
+ WRITE("&&");
+ }
+ }
+
+ //----------------------------------------------------
+ // Rewrite methods
+ //
+ // Write another copy of content already present
+ // earlier in the output buffer
+ //----------------------------------------------------
+
+ void RewriteRange(BufferRange range) {
+ Write(m_buffer + range.offset, range.length);
+ }
+
+ bool RewriteSubstitution(int index) {
+ if (index < 0 || index >= m_next_substitute_index) {
+#ifdef DEBUG_FAILURES
+ printf("*** Invalid substitution #%d\n", index);
+#endif
+ return false;
+ }
+ RewriteRange(m_rewrite_ranges[index]);
+ return true;
+ }
+
+ bool RewriteTemplateArg(int template_index) {
+ int index = m_rewrite_ranges_size - 1 - template_index;
+ if (template_index < 0 || index <= m_next_template_arg_index) {
+#ifdef DEBUG_FAILURES
+ printf("*** Invalid template arg reference #%d\n", template_index);
+#endif
+ return false;
+ }
+ RewriteRange(m_rewrite_ranges[index]);
+ return true;
+ }
+
+ //----------------------------------------------------
+ // TryParse methods
+ //
+ // Provide information with return values instead of
+ // writing to the output buffer
+ //
+ // Values indicating failure guarantee that the pre-
+ // call m_read_ptr is unchanged
+ //----------------------------------------------------
+
+ int TryParseNumber() {
+ unsigned char digit = *m_read_ptr - '0';
+ if (digit > 9)
+ return -1;
+
+ int count = digit;
+ while (true) {
+ digit = *++m_read_ptr - '0';
+ if (digit > 9)
+ break;
+
+ count = count * 10 + digit;
+ }
+ return count;
+ }
+
+ int TryParseBase36Number() {
+ char digit = *m_read_ptr;
+ int count;
+ if (digit >= '0' && digit <= '9')
+ count = digit -= '0';
+ else if (digit >= 'A' && digit <= 'Z')
+ count = digit -= ('A' - 10);
+ else
+ return -1;
+
+ while (true) {
+ digit = *++m_read_ptr;
+ if (digit >= '0' && digit <= '9')
+ digit -= '0';
+ else if (digit >= 'A' && digit <= 'Z')
+ digit -= ('A' - 10);
+ else
+ break;
+
+ count = count * 36 + digit;
+ }
+ return count;
+ }
+
+ // <builtin-type> ::= v # void
+ // ::= w # wchar_t
+ // ::= b # bool
+ // ::= c # char
+ // ::= a # signed char
+ // ::= h # unsigned char
+ // ::= s # short
+ // ::= t # unsigned short
+ // ::= i # int
+ // ::= j # unsigned int
+ // ::= l # long
+ // ::= m # unsigned long
+ // ::= x # long long, __int64
+ // ::= y # unsigned long long, __int64
+ // ::= n # __int128
+ // ::= o # unsigned __int128
+ // ::= f # float
+ // ::= d # double
+ // ::= e # long double, __float80
+ // ::= g # __float128
+ // ::= z # ellipsis
+ // ::= Dd # IEEE 754r decimal floating point (64 bits)
+ // ::= De # IEEE 754r decimal floating point (128 bits)
+ // ::= Df # IEEE 754r decimal floating point (32 bits)
+ // ::= Dh # IEEE 754r half-precision floating point (16 bits)
+ // ::= Di # char32_t
+ // ::= Ds # char16_t
+ // ::= Da # auto (in dependent new-expressions)
+ // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
+ // ::= u <source-name> # vendor extended type
+
+ const char *TryParseBuiltinType() {
+ switch (*m_read_ptr++) {
+ case 'v':
+ return "void";
+ case 'w':
+ return "wchar_t";
+ case 'b':
+ return "bool";
+ case 'c':
+ return "char";
+ case 'a':
+ return "signed char";
+ case 'h':
+ return "unsigned char";
+ case 's':
+ return "short";
+ case 't':
+ return "unsigned short";
+ case 'i':
+ return "int";
+ case 'j':
+ return "unsigned int";
+ case 'l':
+ return "long";
+ case 'm':
+ return "unsigned long";
+ case 'x':
+ return "long long";
+ case 'y':
+ return "unsigned long long";
+ case 'n':
+ return "__int128";
+ case 'o':
+ return "unsigned __int128";
+ case 'f':
+ return "float";
+ case 'd':
+ return "double";
+ case 'e':
+ return "long double";
+ case 'g':
+ return "__float128";
+ case 'z':
+ return "...";
+ case 'D': {
+ switch (*m_read_ptr++) {
+ case 'd':
+ return "decimal64";
+ case 'e':
+ return "decimal128";
+ case 'f':
+ return "decimal32";
+ case 'h':
+ return "decimal16";
+ case 'i':
+ return "char32_t";
+ case 's':
+ return "char16_t";
+ case 'a':
+ return "auto";
+ case 'c':
+ return "decltype(auto)";
+ case 'n':
+ return "std::nullptr_t";
+ default:
--m_read_ptr;
- return { nullptr, OperatorKind::NoMatch };
- }
-
- // <CV-qualifiers> ::= [r] [V] [K]
- // <ref-qualifier> ::= R # & ref-qualifier
- // <ref-qualifier> ::= O # && ref-qualifier
-
- int
- TryParseQualifiers(bool allow_cv, bool allow_ro)
- {
- int qualifiers = QualifierNone;
- char next = *m_read_ptr;
- if (allow_cv)
- {
- if (next == 'r') // restrict
- {
- qualifiers |= QualifierRestrict;
- next = *++m_read_ptr;
- }
- if (next == 'V') // volatile
- {
- qualifiers |= QualifierVolatile;
- next = *++m_read_ptr;
- }
- if (next == 'K') // const
- {
- qualifiers |= QualifierConst;
- next = *++m_read_ptr;
- }
- }
- if (allow_ro)
- {
- if (next == 'R')
- {
- ++m_read_ptr;
- qualifiers |= QualifierReference;
- }
- else if (next =='O')
- {
- ++m_read_ptr;
- qualifiers |= QualifierRValueReference;
- }
- }
- return qualifiers;
+ }
}
-
- // <discriminator> := _ <non-negative number> # when number < 10
- // := __ <non-negative number> _ # when number >= 10
- // extension := decimal-digit+
-
- int
- TryParseDiscriminator()
- {
- const char *discriminator_start = m_read_ptr;
-
- // Test the extension first, since it's what Clang uses
- int discriminator_value = TryParseNumber();
- if (discriminator_value != -1)
- return discriminator_value;
-
- char next = *m_read_ptr;
- if (next == '_')
- {
- next = *++m_read_ptr;
- if (next == '_')
- {
- ++m_read_ptr;
- discriminator_value = TryParseNumber();
- if (discriminator_value != -1 && *m_read_ptr++ != '_')
- {
- return discriminator_value;
- }
- }
- else if (next >= '0' && next <= '9')
- {
- ++m_read_ptr;
- return next - '0';
- }
- }
-
- // Not a valid discriminator
- m_read_ptr = discriminator_start;
- return -1;
}
-
- //----------------------------------------------------
- // Parse methods
- //
- // Consume input starting from m_read_ptr and produce
- // buffered output at m_write_ptr
- //
- // Failures return false and may leave m_read_ptr in an
- // indeterminate state
- //----------------------------------------------------
-
- bool
- Parse(char character)
- {
- if (*m_read_ptr++ == character)
- return true;
-#ifdef DEBUG_FAILURES
- printf("*** Expected '%c'\n", character);
-#endif
- return false;
+ --m_read_ptr;
+ return nullptr;
+ }
+
+ // <operator-name>
+ // ::= aa # &&
+ // ::= ad # & (unary)
+ // ::= an # &
+ // ::= aN # &=
+ // ::= aS # =
+ // ::= cl # ()
+ // ::= cm # ,
+ // ::= co # ~
+ // ::= da # delete[]
+ // ::= de # * (unary)
+ // ::= dl # delete
+ // ::= dv # /
+ // ::= dV # /=
+ // ::= eo # ^
+ // ::= eO # ^=
+ // ::= eq # ==
+ // ::= ge # >=
+ // ::= gt # >
+ // ::= ix # []
+ // ::= le # <=
+ // ::= ls # <<
+ // ::= lS # <<=
+ // ::= lt # <
+ // ::= mi # -
+ // ::= mI # -=
+ // ::= ml # *
+ // ::= mL # *=
+ // ::= mm # -- (postfix in <expression> context)
+ // ::= na # new[]
+ // ::= ne # !=
+ // ::= ng # - (unary)
+ // ::= nt # !
+ // ::= nw # new
+ // ::= oo # ||
+ // ::= or # |
+ // ::= oR # |=
+ // ::= pm # ->*
+ // ::= pl # +
+ // ::= pL # +=
+ // ::= pp # ++ (postfix in <expression> context)
+ // ::= ps # + (unary)
+ // ::= pt # ->
+ // ::= qu # ?
+ // ::= rm # %
+ // ::= rM # %=
+ // ::= rs # >>
+ // ::= rS # >>=
+ // ::= cv <type> # (cast)
+ // ::= v <digit> <source-name> # vendor extended
+ // operator
+
+ Operator TryParseOperator() {
+ switch (*m_read_ptr++) {
+ case 'a':
+ switch (*m_read_ptr++) {
+ case 'a':
+ return {"&&", OperatorKind::Binary};
+ case 'd':
+ return {"&", OperatorKind::Unary};
+ case 'n':
+ return {"&", OperatorKind::Binary};
+ case 'N':
+ return {"&=", OperatorKind::Binary};
+ case 'S':
+ return {"=", OperatorKind::Binary};
+ }
+ --m_read_ptr;
+ break;
+ case 'c':
+ switch (*m_read_ptr++) {
+ case 'l':
+ return {"()", OperatorKind::Other};
+ case 'm':
+ return {",", OperatorKind::Other};
+ case 'o':
+ return {"~", OperatorKind::Unary};
+ case 'v':
+ return {nullptr, OperatorKind::ConversionOperator};
+ }
+ --m_read_ptr;
+ break;
+ case 'd':
+ switch (*m_read_ptr++) {
+ case 'a':
+ return {" delete[]", OperatorKind::Other};
+ case 'e':
+ return {"*", OperatorKind::Unary};
+ case 'l':
+ return {" delete", OperatorKind::Other};
+ case 'v':
+ return {"/", OperatorKind::Binary};
+ case 'V':
+ return {"/=", OperatorKind::Binary};
+ }
+ --m_read_ptr;
+ break;
+ case 'e':
+ switch (*m_read_ptr++) {
+ case 'o':
+ return {"^", OperatorKind::Binary};
+ case 'O':
+ return {"^=", OperatorKind::Binary};
+ case 'q':
+ return {"==", OperatorKind::Binary};
+ }
+ --m_read_ptr;
+ break;
+ case 'g':
+ switch (*m_read_ptr++) {
+ case 'e':
+ return {">=", OperatorKind::Binary};
+ case 't':
+ return {">", OperatorKind::Binary};
+ }
+ --m_read_ptr;
+ break;
+ case 'i':
+ switch (*m_read_ptr++) {
+ case 'x':
+ return {"[]", OperatorKind::Other};
+ }
+ --m_read_ptr;
+ break;
+ case 'l':
+ switch (*m_read_ptr++) {
+ case 'e':
+ return {"<=", OperatorKind::Binary};
+ case 's':
+ return {"<<", OperatorKind::Binary};
+ case 'S':
+ return {"<<=", OperatorKind::Binary};
+ case 't':
+ return {"<", OperatorKind::Binary};
+ // case 'i': return { "?", OperatorKind::Binary };
+ }
+ --m_read_ptr;
+ break;
+ case 'm':
+ switch (*m_read_ptr++) {
+ case 'i':
+ return {"-", OperatorKind::Binary};
+ case 'I':
+ return {"-=", OperatorKind::Binary};
+ case 'l':
+ return {"*", OperatorKind::Binary};
+ case 'L':
+ return {"*=", OperatorKind::Binary};
+ case 'm':
+ return {"--", OperatorKind::Postfix};
+ }
+ --m_read_ptr;
+ break;
+ case 'n':
+ switch (*m_read_ptr++) {
+ case 'a':
+ return {" new[]", OperatorKind::Other};
+ case 'e':
+ return {"!=", OperatorKind::Binary};
+ case 'g':
+ return {"-", OperatorKind::Unary};
+ case 't':
+ return {"!", OperatorKind::Unary};
+ case 'w':
+ return {" new", OperatorKind::Other};
+ }
+ --m_read_ptr;
+ break;
+ case 'o':
+ switch (*m_read_ptr++) {
+ case 'o':
+ return {"||", OperatorKind::Binary};
+ case 'r':
+ return {"|", OperatorKind::Binary};
+ case 'R':
+ return {"|=", OperatorKind::Binary};
+ }
+ --m_read_ptr;
+ break;
+ case 'p':
+ switch (*m_read_ptr++) {
+ case 'm':
+ return {"->*", OperatorKind::Binary};
+ case 's':
+ return {"+", OperatorKind::Unary};
+ case 'l':
+ return {"+", OperatorKind::Binary};
+ case 'L':
+ return {"+=", OperatorKind::Binary};
+ case 'p':
+ return {"++", OperatorKind::Postfix};
+ case 't':
+ return {"->", OperatorKind::Binary};
+ }
+ --m_read_ptr;
+ break;
+ case 'q':
+ switch (*m_read_ptr++) {
+ case 'u':
+ return {"?", OperatorKind::Ternary};
+ }
+ --m_read_ptr;
+ break;
+ case 'r':
+ switch (*m_read_ptr++) {
+ case 'm':
+ return {"%", OperatorKind::Binary};
+ case 'M':
+ return {"%=", OperatorKind::Binary};
+ case 's':
+ return {">>", OperatorKind::Binary};
+ case 'S':
+ return {">=", OperatorKind::Binary};
+ }
+ --m_read_ptr;
+ break;
+ case 'v':
+ char digit = *m_read_ptr;
+ if (digit >= '0' && digit <= '9') {
+ m_read_ptr++;
+ return {nullptr, OperatorKind::Vendor};
+ }
+ --m_read_ptr;
+ break;
+ }
+ --m_read_ptr;
+ return {nullptr, OperatorKind::NoMatch};
+ }
+
+ // <CV-qualifiers> ::= [r] [V] [K]
+ // <ref-qualifier> ::= R # & ref-qualifier
+ // <ref-qualifier> ::= O # && ref-qualifier
+
+ int TryParseQualifiers(bool allow_cv, bool allow_ro) {
+ int qualifiers = QualifierNone;
+ char next = *m_read_ptr;
+ if (allow_cv) {
+ if (next == 'r') // restrict
+ {
+ qualifiers |= QualifierRestrict;
+ next = *++m_read_ptr;
+ }
+ if (next == 'V') // volatile
+ {
+ qualifiers |= QualifierVolatile;
+ next = *++m_read_ptr;
+ }
+ if (next == 'K') // const
+ {
+ qualifiers |= QualifierConst;
+ next = *++m_read_ptr;
+ }
}
-
- // <number> ::= [n] <non-negative decimal integer>
-
- bool
- ParseNumber(bool allow_negative = false)
- {
- if (allow_negative && *m_read_ptr == 'n')
- {
- Write('-');
- ++m_read_ptr;
- }
- const char *before_digits = m_read_ptr;
- while (true)
- {
- unsigned char digit = *m_read_ptr - '0';
- if (digit > 9)
- break;
- ++m_read_ptr;
- }
- if (int digit_count = (int)(m_read_ptr - before_digits))
- {
- Write(before_digits, digit_count);
- return true;
- }
-#ifdef DEBUG_FAILURES
- printf("*** Expected number\n");
-#endif
- return false;
+ if (allow_ro) {
+ if (next == 'R') {
+ ++m_read_ptr;
+ qualifiers |= QualifierReference;
+ } else if (next == 'O') {
+ ++m_read_ptr;
+ qualifiers |= QualifierRValueReference;
+ }
}
+ return qualifiers;
+ }
- // <substitution> ::= S <seq-id> _
- // ::= S_
- // <substitution> ::= Sa # ::std::allocator
- // <substitution> ::= Sb # ::std::basic_string
- // <substitution> ::= Ss # ::std::basic_string < char,
- // ::std::char_traits<char>,
- // ::std::allocator<char> >
- // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
- // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
- // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
-
- bool
- ParseSubstitution()
- {
- const char *substitution;
- switch (*m_read_ptr)
- {
- case 'a': substitution = "std::allocator"; break;
- case 'b': substitution = "std::basic_string"; break;
- case 's': substitution = "std::string"; break;
- case 'i': substitution = "std::istream"; break;
- case 'o': substitution = "std::ostream"; break;
- case 'd': substitution = "std::iostream"; break;
- default:
- // A failed attempt to parse a number will return -1 which turns out to be
- // perfect here as S_ is the first substitution, S0_ the next and so forth
- int substitution_index = TryParseBase36Number();
- if (*m_read_ptr++ != '_')
- {
-#ifdef DEBUG_FAILURES
- printf("*** Expected terminal _ in substitution\n");
-#endif
- return false;
- }
- return RewriteSubstitution (substitution_index + 1);
+ // <discriminator> := _ <non-negative number> # when number < 10
+ // := __ <non-negative number> _ # when number >= 10
+ // extension := decimal-digit+
+
+ int TryParseDiscriminator() {
+ const char *discriminator_start = m_read_ptr;
+
+ // Test the extension first, since it's what Clang uses
+ int discriminator_value = TryParseNumber();
+ if (discriminator_value != -1)
+ return discriminator_value;
+
+ char next = *m_read_ptr;
+ if (next == '_') {
+ next = *++m_read_ptr;
+ if (next == '_') {
+ ++m_read_ptr;
+ discriminator_value = TryParseNumber();
+ if (discriminator_value != -1 && *m_read_ptr++ != '_') {
+ return discriminator_value;
}
- Write(substitution);
+ } else if (next >= '0' && next <= '9') {
++m_read_ptr;
- return true;
+ return next - '0';
+ }
}
- // <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
- //
- // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types
-
- bool
- ParseFunctionType (int inner_qualifiers = QualifierNone)
- {
+ // Not a valid discriminator
+ m_read_ptr = discriminator_start;
+ return -1;
+ }
+
+ //----------------------------------------------------
+ // Parse methods
+ //
+ // Consume input starting from m_read_ptr and produce
+ // buffered output at m_write_ptr
+ //
+ // Failures return false and may leave m_read_ptr in an
+ // indeterminate state
+ //----------------------------------------------------
+
+ bool Parse(char character) {
+ if (*m_read_ptr++ == character)
+ return true;
+#ifdef DEBUG_FAILURES
+ printf("*** Expected '%c'\n", character);
+#endif
+ return false;
+ }
+
+ // <number> ::= [n] <non-negative decimal integer>
+
+ bool ParseNumber(bool allow_negative = false) {
+ if (allow_negative && *m_read_ptr == 'n') {
+ Write('-');
+ ++m_read_ptr;
+ }
+ const char *before_digits = m_read_ptr;
+ while (true) {
+ unsigned char digit = *m_read_ptr - '0';
+ if (digit > 9)
+ break;
+ ++m_read_ptr;
+ }
+ if (int digit_count = (int)(m_read_ptr - before_digits)) {
+ Write(before_digits, digit_count);
+ return true;
+ }
+#ifdef DEBUG_FAILURES
+ printf("*** Expected number\n");
+#endif
+ return false;
+ }
+
+ // <substitution> ::= S <seq-id> _
+ // ::= S_
+ // <substitution> ::= Sa # ::std::allocator
+ // <substitution> ::= Sb # ::std::basic_string
+ // <substitution> ::= Ss # ::std::basic_string < char,
+ // ::std::char_traits<char>,
+ // ::std::allocator<char> >
+ // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char>
+ // >
+ // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char>
+ // >
+ // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char>
+ // >
+
+ bool ParseSubstitution() {
+ const char *substitution;
+ switch (*m_read_ptr) {
+ case 'a':
+ substitution = "std::allocator";
+ break;
+ case 'b':
+ substitution = "std::basic_string";
+ break;
+ case 's':
+ substitution = "std::string";
+ break;
+ case 'i':
+ substitution = "std::istream";
+ break;
+ case 'o':
+ substitution = "std::ostream";
+ break;
+ case 'd':
+ substitution = "std::iostream";
+ break;
+ default:
+ // A failed attempt to parse a number will return -1 which turns out to be
+ // perfect here as S_ is the first substitution, S0_ the next and so forth
+ int substitution_index = TryParseBase36Number();
+ if (*m_read_ptr++ != '_') {
#ifdef DEBUG_FAILURES
- printf("*** Function types not supported\n");
+ printf("*** Expected terminal _ in substitution\n");
#endif
- //TODO: first steps toward an implementation follow, but they're far
- // from complete. Function types tend to bracket other types eg:
- // int (*)() when used as the type for "name" becomes int (*name)().
- // This makes substitution et al ... interesting.
return false;
+ }
+ return RewriteSubstitution(substitution_index + 1);
+ }
+ Write(substitution);
+ ++m_read_ptr;
+ return true;
+ }
+
+ // <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
+ //
+ // <bare-function-type> ::= <signature type>+ # types are possible return
+ // type, then parameter types
+
+ bool ParseFunctionType(int inner_qualifiers = QualifierNone) {
+#ifdef DEBUG_FAILURES
+ printf("*** Function types not supported\n");
+#endif
+ // TODO: first steps toward an implementation follow, but they're far
+ // from complete. Function types tend to bracket other types eg:
+ // int (*)() when used as the type for "name" becomes int (*name)().
+ // This makes substitution et al ... interesting.
+ return false;
-#if 0 // TODO
+#if 0 // TODO
if (*m_read_ptr == 'Y')
++m_read_ptr;
@@ -1083,28 +1050,26 @@ private:
ReorderRange (EndRange (qualifier_start_cookie), insert_cookie);
}
return true;
-#endif // TODO
- }
+#endif // TODO
+ }
- // <array-type> ::= A <positive dimension number> _ <element type>
- // ::= A [<dimension expression>] _ <element type>
+ // <array-type> ::= A <positive dimension number> _ <element type>
+ // ::= A [<dimension expression>] _ <element type>
- bool
- ParseArrayType(int qualifiers = QualifierNone)
- {
+ bool ParseArrayType(int qualifiers = QualifierNone) {
#ifdef DEBUG_FAILURES
- printf("*** Array type unsupported\n");
+ printf("*** Array type unsupported\n");
#endif
- //TODO: We fail horribly when recalling these as substitutions or
- // templates and trying to constify them eg:
- // _ZN4llvm2cl5applyIA28_cNS0_3optIbLb0ENS0_6parserIbEEEEEEvRKT_PT0_
- //
- //TODO: Chances are we don't do any better with references and pointers
- // that should be type (&) [] instead of type & []
+ // TODO: We fail horribly when recalling these as substitutions or
+ // templates and trying to constify them eg:
+ // _ZN4llvm2cl5applyIA28_cNS0_3optIbLb0ENS0_6parserIbEEEEEEvRKT_PT0_
+ //
+ // TODO: Chances are we don't do any better with references and pointers
+ // that should be type (&) [] instead of type & []
- return false;
+ return false;
-#if 0 // TODO
+#if 0 // TODO
if (*m_read_ptr == '_')
{
++m_read_ptr;
@@ -1152,589 +1117,573 @@ private:
return true;
}
#endif // TODO
- }
+ }
- // <pointer-to-member-type> ::= M <class type> <member type>
+ // <pointer-to-member-type> ::= M <class type> <member type>
- //TODO: Determine how to handle pointers to function members correctly,
- // currently not an issue because we don't have function types at all...
- bool
- ParsePointerToMemberType()
- {
- int insertion_cookie = GetStartCookie();
- Write(' ');
+ // TODO: Determine how to handle pointers to function members correctly,
+ // currently not an issue because we don't have function types at all...
+ bool ParsePointerToMemberType() {
+ int insertion_cookie = GetStartCookie();
+ Write(' ');
+ if (!ParseType())
+ return false;
+ WRITE("::*");
+
+ int type_cookie = GetStartCookie();
+ if (!ParseType())
+ return false;
+ ReorderRange(EndRange(type_cookie), insertion_cookie);
+ return true;
+ }
+
+ // <template-param> ::= T_ # first template parameter
+ // ::= T <parameter-2 non-negative number> _
+
+ bool ParseTemplateParam() {
+ int count = TryParseNumber();
+ if (!Parse('_'))
+ return false;
+
+ // When no number is present we get -1, which is convenient since
+ // T_ is the zeroth element T0_ is element 1, and so on
+ return RewriteTemplateArg(count + 1);
+ }
+
+ // <type> ::= <builtin-type>
+ // ::= <function-type>
+ // ::= <class-enum-type>
+ // ::= <array-type>
+ // ::= <pointer-to-member-type>
+ // ::= <template-param>
+ // ::= <template-template-param> <template-args>
+ // ::= <decltype>
+ // ::= <substitution>
+ // ::= <CV-qualifiers> <type>
+ // ::= P <type> # pointer-to
+ // ::= R <type> # reference-to
+ // ::= O <type> # rvalue reference-to (C++0x)
+ // ::= C <type> # complex pair (C 2000)
+ // ::= G <type> # imaginary (C 2000)
+ // ::= Dp <type> # pack expansion (C++0x)
+ // ::= U <source-name> <type> # vendor extended type qualifier
+ // extension := U <objc-name> <objc-type> # objc-type<identifier>
+ // extension := <vector-type> # <vector-type> starts with Dv
+
+ // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 +
+ // <number of digits in k1> + k1
+ // <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name>
+ // 11objc_object -> id<source-name>
+
+ bool ParseType() {
+#ifdef DEBUG_FAILURES
+ const char *failed_type = m_read_ptr;
+#endif
+ int type_start_cookie = GetStartCookie();
+ bool suppress_substitution = false;
+
+ int qualifiers = TryParseQualifiers(true, false);
+ switch (*m_read_ptr) {
+ case 'D':
+ ++m_read_ptr;
+ switch (*m_read_ptr++) {
+ case 'p':
if (!ParseType())
- return false;
- WRITE("::*");
-
- int type_cookie = GetStartCookie();
+ return false;
+ break;
+ case 'T':
+ case 't':
+ case 'v':
+ default:
+#ifdef DEBUG_FAILURES
+ printf("*** Unsupported type: %.3s\n", failed_type);
+#endif
+ return false;
+ }
+ break;
+ case 'T':
+ ++m_read_ptr;
+ if (!ParseTemplateParam())
+ return false;
+ break;
+ case 'M':
+ ++m_read_ptr;
+ if (!ParsePointerToMemberType())
+ return false;
+ break;
+ case 'A':
+ ++m_read_ptr;
+ if (!ParseArrayType())
+ return false;
+ break;
+ case 'F':
+ ++m_read_ptr;
+ if (!ParseFunctionType())
+ return false;
+ break;
+ case 'S':
+ if (*++m_read_ptr == 't') {
+ ++m_read_ptr;
+ WriteStdPrefix();
+ if (!ParseName())
+ return false;
+ } else {
+ suppress_substitution = true;
+ if (!ParseSubstitution())
+ return false;
+ }
+ break;
+ case 'P': {
+ switch (*++m_read_ptr) {
+ case 'F':
+ ++m_read_ptr;
+ if (!ParseFunctionType(QualifierPointer))
+ return false;
+ break;
+ default:
if (!ParseType())
- return false;
- ReorderRange (EndRange (type_cookie), insertion_cookie);
- return true;
+ return false;
+ Write('*');
+ break;
+ }
+ break;
+ }
+ case 'R': {
+ ++m_read_ptr;
+ if (!ParseType())
+ return false;
+ Write('&');
+ break;
+ }
+ case 'O': {
+ ++m_read_ptr;
+ if (!ParseType())
+ return false;
+ Write('&');
+ Write('&');
+ break;
+ }
+ case 'C':
+ case 'G':
+ case 'U':
+#ifdef DEBUG_FAILURES
+ printf("*** Unsupported type: %.3s\n", failed_type);
+#endif
+ return false;
+ // Test for common cases to avoid TryParseBuiltinType() overhead
+ case 'N':
+ case 'Z':
+ case 'L':
+ if (!ParseName())
+ return false;
+ break;
+ default:
+ if (const char *builtin = TryParseBuiltinType()) {
+ Write(builtin);
+ suppress_substitution = true;
+ } else {
+ if (!ParseName())
+ return false;
+ }
+ break;
+ }
+
+ // Allow base substitutions to be suppressed, but always record
+ // substitutions for the qualified variant
+ if (!suppress_substitution)
+ EndSubstitution(type_start_cookie);
+ if (qualifiers) {
+ WriteQualifiers(qualifiers, false);
+ EndSubstitution(type_start_cookie);
+ }
+ return true;
+ }
+
+ // <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
+ // ::= <closure-type-name>
+ //
+ // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
+ //
+ // <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda
+ // has no parameters
+
+ bool ParseUnnamedTypeName(NameState &name_state) {
+ switch (*m_read_ptr++) {
+ case 't': {
+ int cookie = GetStartCookie();
+ WRITE("'unnamed");
+ const char *before_digits = m_read_ptr;
+ if (TryParseNumber() != -1)
+ Write(before_digits, m_read_ptr - before_digits);
+ if (!Parse('_'))
+ return false;
+ Write('\'');
+ name_state.last_name_range = EndRange(cookie);
+ return true;
+ }
+ case 'b': {
+ int cookie = GetStartCookie();
+ WRITE("'block");
+ const char *before_digits = m_read_ptr;
+ if (TryParseNumber() != -1)
+ Write(before_digits, m_read_ptr - before_digits);
+ if (!Parse('_'))
+ return false;
+ Write('\'');
+ name_state.last_name_range = EndRange(cookie);
+ return true;
}
+ case 'l':
+#ifdef DEBUG_FAILURES
+ printf("*** Lambda type names unsupported\n");
+#endif
+ return false;
+ }
+#ifdef DEBUG_FAILURES
+ printf("*** Unknown unnamed type %.3s\n", m_read_ptr - 2);
+#endif
+ return false;
+ }
- // <template-param> ::= T_ # first template parameter
- // ::= T <parameter-2 non-negative number> _
+ // <ctor-dtor-name> ::= C1 # complete object constructor
+ // ::= C2 # base object constructor
+ // ::= C3 # complete object allocating constructor
- bool
- ParseTemplateParam()
- {
- int count = TryParseNumber();
- if (!Parse('_'))
- return false;
+ bool ParseCtor(NameState &name_state) {
+ char next = *m_read_ptr;
+ if (next == '1' || next == '2' || next == '3' || next == '5') {
+ RewriteRange(name_state.last_name_range);
+ name_state.has_no_return_type = true;
+ ++m_read_ptr;
+ return true;
+ }
+#ifdef DEBUG_FAILURES
+ printf("*** Broken constructor\n");
+#endif
+ return false;
+ }
+
+ // <ctor-dtor-name> ::= D0 # deleting destructor
+ // ::= D1 # complete object destructor
+ // ::= D2 # base object destructor
- // When no number is present we get -1, which is convenient since
- // T_ is the zeroth element T0_ is element 1, and so on
- return RewriteTemplateArg (count + 1);
- }
-
- // <type> ::= <builtin-type>
- // ::= <function-type>
- // ::= <class-enum-type>
- // ::= <array-type>
- // ::= <pointer-to-member-type>
- // ::= <template-param>
- // ::= <template-template-param> <template-args>
- // ::= <decltype>
- // ::= <substitution>
- // ::= <CV-qualifiers> <type>
- // ::= P <type> # pointer-to
- // ::= R <type> # reference-to
- // ::= O <type> # rvalue reference-to (C++0x)
- // ::= C <type> # complex pair (C 2000)
- // ::= G <type> # imaginary (C 2000)
- // ::= Dp <type> # pack expansion (C++0x)
- // ::= U <source-name> <type> # vendor extended type qualifier
- // extension := U <objc-name> <objc-type> # objc-type<identifier>
- // extension := <vector-type> # <vector-type> starts with Dv
-
- // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
- // <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
-
- bool
- ParseType()
- {
+ bool ParseDtor(NameState &name_state) {
+ char next = *m_read_ptr;
+ if (next == '0' || next == '1' || next == '2' || next == '5') {
+ Write('~');
+ RewriteRange(name_state.last_name_range);
+ name_state.has_no_return_type = true;
+ ++m_read_ptr;
+ return true;
+ }
#ifdef DEBUG_FAILURES
- const char *failed_type = m_read_ptr;
+ printf("*** Broken destructor\n");
#endif
- int type_start_cookie = GetStartCookie();
- bool suppress_substitution = false;
+ return false;
+ }
- int qualifiers = TryParseQualifiers (true, false);
- switch (*m_read_ptr)
- {
- case 'D':
- ++m_read_ptr;
- switch (*m_read_ptr++)
- {
- case 'p':
- if (!ParseType())
- return false;
- break;
- case 'T':
- case 't':
- case 'v':
- default:
+ // See TryParseOperator()
+
+ bool ParseOperatorName(NameState &name_state) {
#ifdef DEBUG_FAILURES
- printf("*** Unsupported type: %.3s\n", failed_type);
+ const char *operator_ptr = m_read_ptr;
#endif
- return false;
- }
- break;
- case 'T':
- ++m_read_ptr;
- if (!ParseTemplateParam())
- return false;
- break;
- case 'M':
- ++m_read_ptr;
- if (!ParsePointerToMemberType())
- return false;
- break;
- case 'A':
- ++m_read_ptr;
- if (!ParseArrayType())
- return false;
- break;
- case 'F':
- ++m_read_ptr;
- if (!ParseFunctionType())
- return false;
- break;
- case 'S':
- if (*++m_read_ptr == 't')
- {
- ++m_read_ptr;
- WriteStdPrefix();
- if (!ParseName())
- return false;
- }
- else
- {
- suppress_substitution = true;
- if (!ParseSubstitution())
- return false;
- }
- break;
- case 'P':
- {
- switch (*++m_read_ptr)
- {
- case 'F':
- ++m_read_ptr;
- if (!ParseFunctionType(QualifierPointer))
- return false;
- break;
- default:
- if (!ParseType())
- return false;
- Write('*');
- break;
- }
- break;
- }
- case 'R':
- {
- ++m_read_ptr;
- if (!ParseType())
- return false;
- Write('&');
- break;
- }
- case 'O':
- {
- ++m_read_ptr;
- if (!ParseType())
- return false;
- Write('&');
- Write('&');
- break;
- }
- case 'C':
- case 'G':
- case 'U':
-#ifdef DEBUG_FAILURES
- printf("*** Unsupported type: %.3s\n", failed_type);
-#endif
- return false;
- // Test for common cases to avoid TryParseBuiltinType() overhead
- case 'N':
- case 'Z':
- case 'L':
- if (!ParseName())
- return false;
- break;
- default:
- if (const char *builtin = TryParseBuiltinType())
- {
- Write(builtin);
- suppress_substitution = true;
- }
- else
- {
- if (!ParseName())
- return false;
- }
- break;
- }
-
- // Allow base substitutions to be suppressed, but always record
- // substitutions for the qualified variant
- if (!suppress_substitution)
- EndSubstitution(type_start_cookie);
- if (qualifiers)
- {
- WriteQualifiers(qualifiers, false);
- EndSubstitution(type_start_cookie);
- }
- return true;
+ Operator parsed_operator = TryParseOperator();
+ if (parsed_operator.name) {
+ WRITE("operator");
+ Write(parsed_operator.name);
+ return true;
}
- // <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
- // ::= <closure-type-name>
- //
- // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
- //
- // <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
-
- bool
- ParseUnnamedTypeName(NameState & name_state)
- {
- switch (*m_read_ptr++)
- {
- case 't':
- {
- int cookie = GetStartCookie();
- WRITE("'unnamed");
- const char *before_digits = m_read_ptr;
- if (TryParseNumber() != -1) Write (before_digits,
- m_read_ptr - before_digits);
- if (!Parse('_'))
- return false;
- Write('\'');
- name_state.last_name_range = EndRange (cookie);
- return true;
- }
- case 'b':
- {
- int cookie = GetStartCookie();
- WRITE("'block");
- const char *before_digits = m_read_ptr;
- if (TryParseNumber() != -1) Write (before_digits,
- m_read_ptr - before_digits);
- if (!Parse('_'))
- return false;
- Write('\'');
- name_state.last_name_range = EndRange (cookie);
- return true;
- }
- case 'l':
-#ifdef DEBUG_FAILURES
- printf("*** Lambda type names unsupported\n");
-#endif
- return false;
- }
+ // Handle special operators
+ switch (parsed_operator.kind) {
+ case OperatorKind::Vendor:
+ WRITE("operator ");
+ return ParseSourceName();
+ case OperatorKind::ConversionOperator:
+ ResetTemplateArgs();
+ name_state.has_no_return_type = true;
+ WRITE("operator ");
+ return ParseType();
+ default:
#ifdef DEBUG_FAILURES
- printf("*** Unknown unnamed type %.3s\n", m_read_ptr - 2);
+ printf("*** Unknown operator: %.2s\n", operator_ptr);
#endif
- return false;
+ return false;
}
+ }
- // <ctor-dtor-name> ::= C1 # complete object constructor
- // ::= C2 # base object constructor
- // ::= C3 # complete object allocating constructor
+ // <source-name> ::= <positive length number> <identifier>
- bool
- ParseCtor(NameState & name_state)
- {
- char next = *m_read_ptr;
- if (next == '1' || next == '2' || next == '3' || next == '5')
- {
- RewriteRange (name_state.last_name_range);
- name_state.has_no_return_type = true;
- ++m_read_ptr;
- return true;
- }
+ bool ParseSourceName() {
+ int count = TryParseNumber();
+ if (count == -1) {
#ifdef DEBUG_FAILURES
- printf("*** Broken constructor\n");
+ printf("*** Malformed source name, missing length count\n");
#endif
- return false;
+ return false;
}
- // <ctor-dtor-name> ::= D0 # deleting destructor
- // ::= D1 # complete object destructor
- // ::= D2 # base object destructor
-
- bool
- ParseDtor(NameState & name_state)
- {
- char next = *m_read_ptr;
- if (next == '0' || next == '1' || next == '2' || next == '5')
- {
- Write('~');
- RewriteRange(name_state.last_name_range);
- name_state.has_no_return_type = true;
- ++m_read_ptr;
- return true;
- }
+ const char *next_m_read_ptr = m_read_ptr + count;
+ if (next_m_read_ptr > m_read_end) {
#ifdef DEBUG_FAILURES
- printf("*** Broken destructor\n");
+ printf("*** Malformed source name, premature termination\n");
#endif
- return false;
+ return false;
}
- // See TryParseOperator()
-
- bool
- ParseOperatorName(NameState & name_state)
- {
-#ifdef DEBUG_FAILURES
- const char *operator_ptr = m_read_ptr;
-#endif
- Operator parsed_operator = TryParseOperator();
- if (parsed_operator.name)
- {
- WRITE("operator");
- Write(parsed_operator.name);
- return true;
- }
+ if (count >= 10 && strncmp(m_read_ptr, "_GLOBAL__N", 10) == 0)
+ WRITE("(anonymous namespace)");
+ else
+ Write(m_read_ptr, count);
- // Handle special operators
- switch (parsed_operator.kind)
- {
- case OperatorKind::Vendor:
- WRITE("operator ");
- return ParseSourceName();
- case OperatorKind::ConversionOperator:
- ResetTemplateArgs();
- name_state.has_no_return_type = true;
- WRITE("operator ");
- return ParseType();
- default:
-#ifdef DEBUG_FAILURES
- printf("*** Unknown operator: %.2s\n", operator_ptr);
-#endif
- return false;
- }
- }
+ m_read_ptr = next_m_read_ptr;
+ return true;
+ }
- // <source-name> ::= <positive length number> <identifier>
+ // <unqualified-name> ::= <operator-name>
+ // ::= <ctor-dtor-name>
+ // ::= <source-name>
+ // ::= <unnamed-type-name>
- bool
- ParseSourceName()
- {
- int count = TryParseNumber();
- if (count == -1)
- {
-#ifdef DEBUG_FAILURES
- printf("*** Malformed source name, missing length count\n");
-#endif
- return false;
- }
-
- const char *next_m_read_ptr = m_read_ptr + count;
- if (next_m_read_ptr > m_read_end)
- {
-#ifdef DEBUG_FAILURES
- printf("*** Malformed source name, premature termination\n");
-#endif
- return false;
- }
-
- if (count >= 10 && strncmp(m_read_ptr, "_GLOBAL__N", 10) == 0)
- WRITE("(anonymous namespace)");
- else Write(m_read_ptr, count);
-
- m_read_ptr = next_m_read_ptr;
- return true;
- }
-
- // <unqualified-name> ::= <operator-name>
- // ::= <ctor-dtor-name>
- // ::= <source-name>
- // ::= <unnamed-type-name>
-
- bool
- ParseUnqualifiedName(NameState & name_state)
- {
- // Note that these are detected directly in ParseNestedName for
- // performance rather than switching on the same options twice
- char next = *m_read_ptr;
- switch (next)
- {
- case 'C':
- ++m_read_ptr;
- return ParseCtor(name_state);
- case 'D':
- ++m_read_ptr;
- return ParseDtor(name_state);
- case 'U':
- ++m_read_ptr;
- return ParseUnnamedTypeName(name_state);
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- {
- int name_start_cookie = GetStartCookie();
- if (!ParseSourceName())
- return false;
- name_state.last_name_range = EndRange(name_start_cookie);
- return true;
- }
- default:
- return ParseOperatorName(name_state);
- };
- }
-
- // <unscoped-name> ::= <unqualified-name>
- // ::= St <unqualified-name> # ::std::
- // extension ::= StL<unqualified-name>
-
- bool
- ParseUnscopedName(NameState & name_state)
- {
- if (*m_read_ptr == 'S' && *(m_read_ptr + 1) == 't')
- {
- WriteStdPrefix();
- if (*(m_read_ptr += 2) == 'L')
- ++m_read_ptr;
- }
- return ParseUnqualifiedName(name_state);
+ bool ParseUnqualifiedName(NameState &name_state) {
+ // Note that these are detected directly in ParseNestedName for
+ // performance rather than switching on the same options twice
+ char next = *m_read_ptr;
+ switch (next) {
+ case 'C':
+ ++m_read_ptr;
+ return ParseCtor(name_state);
+ case 'D':
+ ++m_read_ptr;
+ return ParseDtor(name_state);
+ case 'U':
+ ++m_read_ptr;
+ return ParseUnnamedTypeName(name_state);
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': {
+ int name_start_cookie = GetStartCookie();
+ if (!ParseSourceName())
+ return false;
+ name_state.last_name_range = EndRange(name_start_cookie);
+ return true;
}
-
- bool
- ParseIntegerLiteral(const char *prefix, const char *suffix,
- bool allow_negative)
- {
- if (prefix)
- Write(prefix);
- if (!ParseNumber(allow_negative))
- return false;
- if (suffix)
- Write(suffix);
- return Parse('E');
+ default:
+ return ParseOperatorName(name_state);
+ };
+ }
+
+ // <unscoped-name> ::= <unqualified-name>
+ // ::= St <unqualified-name> # ::std::
+ // extension ::= StL<unqualified-name>
+
+ bool ParseUnscopedName(NameState &name_state) {
+ if (*m_read_ptr == 'S' && *(m_read_ptr + 1) == 't') {
+ WriteStdPrefix();
+ if (*(m_read_ptr += 2) == 'L')
+ ++m_read_ptr;
}
+ return ParseUnqualifiedName(name_state);
+ }
- bool
- ParseBooleanLiteral()
- {
- switch (*m_read_ptr++)
- {
- case '0': WRITE("false"); break;
- case '1': WRITE("true"); break;
- default:
-#ifdef DEBUG_FAILURES
- printf("*** Boolean literal not 0 or 1\n");
-#endif
- return false;
- }
+ bool ParseIntegerLiteral(const char *prefix, const char *suffix,
+ bool allow_negative) {
+ if (prefix)
+ Write(prefix);
+ if (!ParseNumber(allow_negative))
+ return false;
+ if (suffix)
+ Write(suffix);
+ return Parse('E');
+ }
+
+ bool ParseBooleanLiteral() {
+ switch (*m_read_ptr++) {
+ case '0':
+ WRITE("false");
+ break;
+ case '1':
+ WRITE("true");
+ break;
+ default:
+#ifdef DEBUG_FAILURES
+ printf("*** Boolean literal not 0 or 1\n");
+#endif
+ return false;
+ }
+ return Parse('E');
+ }
+
+ // <expr-primary> ::= L <type> <value number> E #
+ // integer literal
+ // ::= L <type> <value float> E #
+ // floating literal
+ // ::= L <string type> E #
+ // string literal
+ // ::= L <nullptr type> E #
+ // nullptr literal (i.e., "LDnE")
+ // ::= L <type> <real-part float> _ <imag-part float> E #
+ // complex floating point literal (C 2000)
+ // ::= L <mangled-name> E #
+ // external name
+
+ bool ParseExpressionPrimary() {
+ switch (*m_read_ptr++) {
+ case 'b':
+ return ParseBooleanLiteral();
+ case 'x':
+ return ParseIntegerLiteral(nullptr, "ll", true);
+ case 'l':
+ return ParseIntegerLiteral(nullptr, "l", true);
+ case 'i':
+ return ParseIntegerLiteral(nullptr, nullptr, true);
+ case 'n':
+ return ParseIntegerLiteral("(__int128)", nullptr, true);
+ case 'j':
+ return ParseIntegerLiteral(nullptr, "u", false);
+ case 'm':
+ return ParseIntegerLiteral(nullptr, "ul", false);
+ case 'y':
+ return ParseIntegerLiteral(nullptr, "ull", false);
+ case 'o':
+ return ParseIntegerLiteral("(unsigned __int128)", nullptr, false);
+ case '_':
+ if (*m_read_ptr++ == 'Z') {
+ if (!ParseEncoding())
+ return false;
return Parse('E');
+ }
+ --m_read_ptr;
+ LLVM_FALLTHROUGH;
+ case 'w':
+ case 'c':
+ case 'a':
+ case 'h':
+ case 's':
+ case 't':
+ case 'f':
+ case 'd':
+ case 'e':
+#ifdef DEBUG_FAILURES
+ printf("*** Unsupported primary expression %.5s\n", m_read_ptr - 1);
+#endif
+ return false;
+ case 'T':
+// Invalid mangled name per
+// http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
+#ifdef DEBUG_FAILURES
+ printf("*** Invalid primary expr encoding\n");
+#endif
+ return false;
+ default:
+ --m_read_ptr;
+ Write('(');
+ if (!ParseType())
+ return false;
+ Write(')');
+ if (!ParseNumber())
+ return false;
+ return Parse('E');
}
+ }
- // <expr-primary> ::= L <type> <value number> E # integer literal
- // ::= L <type> <value float> E # floating literal
- // ::= L <string type> E # string literal
- // ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
- // ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
- // ::= L <mangled-name> E # external name
-
- bool
- ParseExpressionPrimary()
- {
- switch (*m_read_ptr++)
- {
- case 'b': return ParseBooleanLiteral();
- case 'x': return ParseIntegerLiteral(nullptr, "ll", true);
- case 'l': return ParseIntegerLiteral(nullptr, "l", true);
- case 'i': return ParseIntegerLiteral(nullptr, nullptr, true);
- case 'n': return ParseIntegerLiteral("(__int128)", nullptr, true);
- case 'j': return ParseIntegerLiteral(nullptr, "u", false);
- case 'm': return ParseIntegerLiteral(nullptr, "ul", false);
- case 'y': return ParseIntegerLiteral(nullptr, "ull", false);
- case 'o': return ParseIntegerLiteral("(unsigned __int128)",
- nullptr, false);
- case '_':
- if (*m_read_ptr++ == 'Z')
- {
- if (!ParseEncoding())
- return false;
- return Parse('E');
- }
- --m_read_ptr;
- LLVM_FALLTHROUGH;
- case 'w':
- case 'c':
- case 'a':
- case 'h':
- case 's':
- case 't':
- case 'f':
- case 'd':
- case 'e':
-#ifdef DEBUG_FAILURES
- printf("*** Unsupported primary expression %.5s\n", m_read_ptr - 1);
-#endif
- return false;
- case 'T':
- // Invalid mangled name per
- // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
-#ifdef DEBUG_FAILURES
- printf("*** Invalid primary expr encoding\n");
-#endif
- return false;
- default:
- --m_read_ptr;
- Write('(');
- if (!ParseType())
- return false;
- Write(')');
- if (!ParseNumber())
- return false;
- return Parse('E');
- }
- }
-
- // <unresolved-type> ::= <template-param>
- // ::= <decltype>
- // ::= <substitution>
-
- bool
- ParseUnresolvedType()
- {
- int type_start_cookie = GetStartCookie();
- switch (*m_read_ptr++)
- {
- case 'T':
- if (!ParseTemplateParam())
- return false;
- EndSubstitution(type_start_cookie);
- return true;
- case 'S':
- {
- if (*m_read_ptr != 't')
- return ParseSubstitution();
-
- ++m_read_ptr;
- WriteStdPrefix();
- NameState type_name = {};
- if (!ParseUnqualifiedName(type_name))
- return false;
- EndSubstitution(type_start_cookie);
- return true;
-
- }
- case 'D':
- default:
-#ifdef DEBUG_FAILURES
- printf("*** Unsupported unqualified type: %3s\n", m_read_ptr - 1);
-#endif
- return false;
- }
+ // <unresolved-type> ::= <template-param>
+ // ::= <decltype>
+ // ::= <substitution>
+
+ bool ParseUnresolvedType() {
+ int type_start_cookie = GetStartCookie();
+ switch (*m_read_ptr++) {
+ case 'T':
+ if (!ParseTemplateParam())
+ return false;
+ EndSubstitution(type_start_cookie);
+ return true;
+ case 'S': {
+ if (*m_read_ptr != 't')
+ return ParseSubstitution();
+
+ ++m_read_ptr;
+ WriteStdPrefix();
+ NameState type_name = {};
+ if (!ParseUnqualifiedName(type_name))
+ return false;
+ EndSubstitution(type_start_cookie);
+ return true;
}
-
- // <base-unresolved-name> ::= <simple-id> # unresolved name
- // extension ::= <operator-name> # unresolved operator-function-id
- // extension ::= <operator-name> <template-args> # unresolved operator template-id
- // ::= on <operator-name> # unresolved operator-function-id
- // ::= on <operator-name> <template-args> # unresolved operator template-id
- // ::= dn <destructor-name> # destructor or pseudo-destructor;
- // # e.g. ~X or ~X<N-1>
-
- bool
- ParseBaseUnresolvedName()
- {
+ case 'D':
+ default:
#ifdef DEBUG_FAILURES
- printf("*** Base unresolved name unsupported\n");
+ printf("*** Unsupported unqualified type: %3s\n", m_read_ptr - 1);
#endif
- return false;
- }
-
- // <unresolved-name>
- // extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
- // ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
- // ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
- // # A::x, N::y, A<T>::z; "gs" means leading "::"
- // ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
- // extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
- // # T::N::x /decltype(p)::N::x
- // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
+ return false;
+ }
+ }
+
+ // <base-unresolved-name> ::= <simple-id> #
+ // unresolved name
+ // extension ::= <operator-name> #
+ // unresolved operator-function-id
+ // extension ::= <operator-name> <template-args> #
+ // unresolved operator template-id
+ // ::= on <operator-name> #
+ // unresolved operator-function-id
+ // ::= on <operator-name> <template-args> #
+ // unresolved operator template-id
+ // ::= dn <destructor-name> #
+ // destructor or pseudo-destructor;
+ // #
+ // e.g.
+ // ~X
+ // or
+ // ~X<N-1>
+
+ bool ParseBaseUnresolvedName() {
+#ifdef DEBUG_FAILURES
+ printf("*** Base unresolved name unsupported\n");
+#endif
+ return false;
+ }
+
+ // <unresolved-name>
+ // extension ::= srN <unresolved-type> [<template-args>]
+ // <unresolved-qualifier-level>* E <base-unresolved-name>
+ // ::= [gs] <base-unresolved-name> # x
+ // or (with "gs") ::x
+ // ::= [gs] sr <unresolved-qualifier-level>+ E
+ // <base-unresolved-name>
+ // #
+ // A::x,
+ // N::y,
+ // A<T>::z;
+ // "gs"
+ // means
+ // leading
+ // "::"
+ // ::= sr <unresolved-type> <base-unresolved-name> #
+ // T::x / decltype(p)::x
+ // extension ::= sr <unresolved-type> <template-args>
+ // <base-unresolved-name>
+ // #
+ // T::N::x
+ // /decltype(p)::N::x
+ // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+
+ // E <base-unresolved-name>
- bool
- ParseUnresolvedName()
- {
+ bool ParseUnresolvedName() {
#ifdef DEBUG_FAILURES
- printf("*** Unresolved names not supported\n");
+ printf("*** Unresolved names not supported\n");
#endif
- //TODO: grammar for all of this seems unclear...
- return false;
+ // TODO: grammar for all of this seems unclear...
+ return false;
#if 0 // TODO
if (*m_read_ptr == 'g' && *(m_read_ptr + 1) == 's')
@@ -1743,677 +1692,675 @@ private:
WriteNamespaceSeparator();
}
#endif // TODO
- }
+ }
- // <expression> ::= <unary operator-name> <expression>
- // ::= <binary operator-name> <expression> <expression>
- // ::= <ternary operator-name> <expression> <expression> <expression>
- // ::= cl <expression>+ E # call
- // ::= cv <type> <expression> # conversion with one argument
- // ::= cv <type> _ <expression>* E # conversion with a different number of arguments
- // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
- // ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
- // ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
- // ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
- // ::= [gs] dl <expression> # delete expression
- // ::= [gs] da <expression> # delete[] expression
- // ::= pp_ <expression> # prefix ++
- // ::= mm_ <expression> # prefix --
- // ::= ti <type> # typeid (type)
- // ::= te <expression> # typeid (expression)
- // ::= dc <type> <expression> # dynamic_cast<type> (expression)
- // ::= sc <type> <expression> # static_cast<type> (expression)
- // ::= cc <type> <expression> # const_cast<type> (expression)
- // ::= rc <type> <expression> # reinterpret_cast<type> (expression)
- // ::= st <type> # sizeof (a type)
- // ::= sz <expression> # sizeof (an expression)
- // ::= at <type> # alignof (a type)
- // ::= az <expression> # alignof (an expression)
- // ::= nx <expression> # noexcept (expression)
- // ::= <template-param>
- // ::= <function-param>
- // ::= dt <expression> <unresolved-name> # expr.name
- // ::= pt <expression> <unresolved-name> # expr->name
- // ::= ds <expression> <expression> # expr.*expr
- // ::= sZ <template-param> # size of a parameter pack
- // ::= sZ <function-param> # size of a function parameter pack
- // ::= sp <expression> # pack expansion
- // ::= tw <expression> # throw expression
- // ::= tr # throw with no operand (rethrow)
- // ::= <unresolved-name> # f(p), N::f(p), ::f(p),
- // # freestanding dependent name (e.g., T::x),
- // # objectless nonstatic member reference
- // ::= <expr-primary>
-
- bool
- ParseExpression()
- {
- Operator expression_operator = TryParseOperator();
- switch (expression_operator.kind)
- {
- case OperatorKind::Unary:
- Write(expression_operator.name);
- Write('(');
- if (!ParseExpression())
- return false;
- Write(')');
- return true;
- case OperatorKind::Binary:
- if (!ParseExpression())
- return false;
- Write(expression_operator.name);
- return ParseExpression();
- case OperatorKind::Ternary:
- if (!ParseExpression())
- return false;
- Write('?');
- if (!ParseExpression())
- return false;
- Write(':');
- return ParseExpression();
- case OperatorKind::NoMatch:
- break;
- case OperatorKind::Other:
- default:
-#ifdef DEBUG_FAILURES
- printf("*** Unsupported operator: %s\n", expression_operator.name);
-#endif
- return false;
- }
-
- switch (*m_read_ptr++)
- {
- case 'T': return ParseTemplateParam();
- case 'L': return ParseExpressionPrimary();
- case 's':
- if (*m_read_ptr++ == 'r')
- return ParseUnresolvedName();
- --m_read_ptr;
- LLVM_FALLTHROUGH;
- default:
- return ParseExpressionPrimary();
- }
- }
+ // <expression> ::= <unary operator-name> <expression>
+ // ::= <binary operator-name> <expression> <expression>
+ // ::= <ternary operator-name> <expression> <expression>
+ // <expression>
+ // ::= cl <expression>+ E #
+ // call
+ // ::= cv <type> <expression> #
+ // conversion with one argument
+ // ::= cv <type> _ <expression>* E #
+ // conversion with a different number of arguments
+ // ::= [gs] nw <expression>* _ <type> E # new
+ // (expr-list) type
+ // ::= [gs] nw <expression>* _ <type> <initializer> # new
+ // (expr-list) type (init)
+ // ::= [gs] na <expression>* _ <type> E #
+ // new[] (expr-list) type
+ // ::= [gs] na <expression>* _ <type> <initializer> #
+ // new[] (expr-list) type (init)
+ // ::= [gs] dl <expression> #
+ // delete expression
+ // ::= [gs] da <expression> #
+ // delete[] expression
+ // ::= pp_ <expression> #
+ // prefix ++
+ // ::= mm_ <expression> #
+ // prefix --
+ // ::= ti <type> #
+ // typeid (type)
+ // ::= te <expression> #
+ // typeid (expression)
+ // ::= dc <type> <expression> #
+ // dynamic_cast<type> (expression)
+ // ::= sc <type> <expression> #
+ // static_cast<type> (expression)
+ // ::= cc <type> <expression> #
+ // const_cast<type> (expression)
+ // ::= rc <type> <expression> #
+ // reinterpret_cast<type> (expression)
+ // ::= st <type> #
+ // sizeof (a type)
+ // ::= sz <expression> #
+ // sizeof (an expression)
+ // ::= at <type> #
+ // alignof (a type)
+ // ::= az <expression> #
+ // alignof (an expression)
+ // ::= nx <expression> #
+ // noexcept (expression)
+ // ::= <template-param>
+ // ::= <function-param>
+ // ::= dt <expression> <unresolved-name> #
+ // expr.name
+ // ::= pt <expression> <unresolved-name> #
+ // expr->name
+ // ::= ds <expression> <expression> #
+ // expr.*expr
+ // ::= sZ <template-param> #
+ // size of a parameter pack
+ // ::= sZ <function-param> #
+ // size of a function parameter pack
+ // ::= sp <expression> #
+ // pack expansion
+ // ::= tw <expression> #
+ // throw expression
+ // ::= tr #
+ // throw with no operand (rethrow)
+ // ::= <unresolved-name> #
+ // f(p), N::f(p), ::f(p),
+ // #
+ // freestanding
+ // dependent
+ // name
+ // (e.g.,
+ // T::x),
+ // #
+ // objectless
+ // nonstatic
+ // member
+ // reference
+ // ::= <expr-primary>
+
+ bool ParseExpression() {
+ Operator expression_operator = TryParseOperator();
+ switch (expression_operator.kind) {
+ case OperatorKind::Unary:
+ Write(expression_operator.name);
+ Write('(');
+ if (!ParseExpression())
+ return false;
+ Write(')');
+ return true;
+ case OperatorKind::Binary:
+ if (!ParseExpression())
+ return false;
+ Write(expression_operator.name);
+ return ParseExpression();
+ case OperatorKind::Ternary:
+ if (!ParseExpression())
+ return false;
+ Write('?');
+ if (!ParseExpression())
+ return false;
+ Write(':');
+ return ParseExpression();
+ case OperatorKind::NoMatch:
+ break;
+ case OperatorKind::Other:
+ default:
+#ifdef DEBUG_FAILURES
+ printf("*** Unsupported operator: %s\n", expression_operator.name);
+#endif
+ return false;
+ }
+
+ switch (*m_read_ptr++) {
+ case 'T':
+ return ParseTemplateParam();
+ case 'L':
+ return ParseExpressionPrimary();
+ case 's':
+ if (*m_read_ptr++ == 'r')
+ return ParseUnresolvedName();
+ --m_read_ptr;
+ LLVM_FALLTHROUGH;
+ default:
+ return ParseExpressionPrimary();
+ }
+ }
+
+ // <template-arg> ::= <type> #
+ // type or template
+ // ::= X <expression> E #
+ // expression
+ // ::= <expr-primary> #
+ // simple expressions
+ // ::= J <template-arg>* E #
+ // argument pack
+ // ::= LZ <encoding> E #
+ // extension
+
+ bool ParseTemplateArg() {
+ switch (*m_read_ptr) {
+ case 'J':
+#ifdef DEBUG_FAILURES
+ printf("*** Template argument packs unsupported\n");
+#endif
+ return false;
+ case 'X':
+ ++m_read_ptr;
+ if (!ParseExpression())
+ return false;
+ return Parse('E');
+ case 'L':
+ ++m_read_ptr;
+ return ParseExpressionPrimary();
+ default:
+ return ParseType();
+ }
+ }
+
+ // <template-args> ::= I <template-arg>* E
+ // extension, the abi says <template-arg>+
+
+ bool ParseTemplateArgs(bool record_template_args = false) {
+ if (record_template_args)
+ ResetTemplateArgs();
+
+ bool first_arg = true;
+ while (*m_read_ptr != 'E') {
+ if (first_arg)
+ first_arg = false;
+ else
+ WriteCommaSpace();
- // <template-arg> ::= <type> # type or template
- // ::= X <expression> E # expression
- // ::= <expr-primary> # simple expressions
- // ::= J <template-arg>* E # argument pack
- // ::= LZ <encoding> E # extension
-
- bool
- ParseTemplateArg()
- {
- switch (*m_read_ptr) {
- case 'J':
-#ifdef DEBUG_FAILURES
- printf("*** Template argument packs unsupported\n");
-#endif
- return false;
- case 'X':
- ++m_read_ptr;
- if (!ParseExpression())
- return false;
- return Parse('E');
- case 'L':
- ++m_read_ptr;
- return ParseExpressionPrimary();
- default:
- return ParseType();
- }
+ int template_start_cookie = GetStartCookie();
+ if (!ParseTemplateArg())
+ return false;
+ if (record_template_args)
+ EndTemplateArg(template_start_cookie);
}
+ ++m_read_ptr;
+ return true;
+ }
+
+ // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix>
+ // <unqualified-name> E
+ // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix>
+ // <template-args> E
+ //
+ // <prefix> ::= <prefix> <unqualified-name>
+ // ::= <template-prefix> <template-args>
+ // ::= <template-param>
+ // ::= <decltype>
+ // ::= # empty
+ // ::= <substitution>
+ // ::= <prefix> <data-member-prefix>
+ // extension ::= L
+ //
+ // <template-prefix> ::= <prefix> <template unqualified-name>
+ // ::= <template-param>
+ // ::= <substitution>
+ //
+ // <unqualified-name> ::= <operator-name>
+ // ::= <ctor-dtor-name>
+ // ::= <source-name>
+ // ::= <unnamed-type-name>
+
+ bool ParseNestedName(NameState &name_state,
+ bool parse_discriminator = false) {
+ int qualifiers = TryParseQualifiers(true, true);
+ bool first_part = true;
+ bool suppress_substitution = true;
+ int name_start_cookie = GetStartCookie();
+ while (true) {
+ char next = *m_read_ptr;
+ if (next == 'E') {
+ ++m_read_ptr;
+ break;
+ }
- // <template-args> ::= I <template-arg>* E
- // extension, the abi says <template-arg>+
-
- bool
- ParseTemplateArgs(bool record_template_args = false)
- {
- if (record_template_args)
- ResetTemplateArgs();
-
- bool first_arg = true;
- while (*m_read_ptr != 'E')
- {
- if (first_arg)
- first_arg = false;
- else WriteCommaSpace();
+ // Record a substitution candidate for all prefixes, but not the full name
+ if (suppress_substitution)
+ suppress_substitution = false;
+ else
+ EndSubstitution(name_start_cookie);
- int template_start_cookie = GetStartCookie();
- if (!ParseTemplateArg())
- return false;
- if (record_template_args)
- EndTemplateArg(template_start_cookie);
- }
+ if (next == 'I') {
++m_read_ptr;
- return true;
- }
-
- // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
- // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
- //
- // <prefix> ::= <prefix> <unqualified-name>
- // ::= <template-prefix> <template-args>
- // ::= <template-param>
- // ::= <decltype>
- // ::= # empty
- // ::= <substitution>
- // ::= <prefix> <data-member-prefix>
- // extension ::= L
- //
- // <template-prefix> ::= <prefix> <template unqualified-name>
- // ::= <template-param>
- // ::= <substitution>
- //
- // <unqualified-name> ::= <operator-name>
- // ::= <ctor-dtor-name>
- // ::= <source-name>
- // ::= <unnamed-type-name>
-
- bool
- ParseNestedName(NameState & name_state, bool parse_discriminator = false)
- {
- int qualifiers = TryParseQualifiers(true, true);
- bool first_part = true;
- bool suppress_substitution = true;
+ name_state.is_last_generic = true;
+ WriteTemplateStart();
+ if (!ParseTemplateArgs(name_state.parse_function_params))
+ return false;
+ WriteTemplateEnd();
+ continue;
+ }
+
+ if (first_part)
+ first_part = false;
+ else
+ WriteNamespaceSeparator();
+
+ name_state.is_last_generic = false;
+ switch (next) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': {
int name_start_cookie = GetStartCookie();
- while (true)
- {
- char next = *m_read_ptr;
- if (next == 'E')
- {
- ++m_read_ptr;
- break;
- }
-
- // Record a substitution candidate for all prefixes, but not the full name
- if (suppress_substitution)
- suppress_substitution = false;
- else EndSubstitution(name_start_cookie);
-
- if (next == 'I')
- {
- ++m_read_ptr;
- name_state.is_last_generic = true;
- WriteTemplateStart();
- if (!ParseTemplateArgs(name_state.parse_function_params))
- return false;
- WriteTemplateEnd();
- continue;
- }
-
- if (first_part)
- first_part = false;
- else WriteNamespaceSeparator();
-
- name_state.is_last_generic = false;
- switch (next)
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- {
- int name_start_cookie = GetStartCookie();
- if (!ParseSourceName())
- return false;
- name_state.last_name_range = EndRange(name_start_cookie);
- continue;
- }
- case 'S':
- if (*++m_read_ptr == 't')
- {
- WriteStdPrefix();
- ++m_read_ptr;
- if (!ParseUnqualifiedName(name_state))
- return false;
- }
- else
- {
- if (!ParseSubstitution())
- return false;
- suppress_substitution = true;
- }
- continue;
- case 'T':
- ++m_read_ptr;
- if (!ParseTemplateParam())
- return false;
- continue;
- case 'C':
- ++m_read_ptr;
- if (!ParseCtor(name_state))
- return false;
- continue;
- case 'D':
- {
- switch (*(m_read_ptr + 1))
- {
- case 't':
- case 'T':
-#ifdef DEBUG_FAILURES
- printf("*** Decltype unsupported\n");
-#endif
- return false;
- }
- ++m_read_ptr;
- if (!ParseDtor(name_state))
- return false;
- continue;
- }
- case 'U':
- ++m_read_ptr;
- if (!ParseUnnamedTypeName(name_state))
- return false;
- continue;
- case 'L':
- ++m_read_ptr;
- if (!ParseUnqualifiedName(name_state))
- return false;
- continue;
- default:
- if (!ParseOperatorName(name_state))
- return false;
- }
- }
-
- if (parse_discriminator)
- TryParseDiscriminator();
- if (name_state.parse_function_params
- && !ParseFunctionArgs(name_state, name_start_cookie))
- {
- return false;
- }
- if (qualifiers)
- WriteQualifiers(qualifiers);
- return true;
- }
-
- // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
- // := Z <function encoding> E s [<discriminator>]
- // := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
-
- bool
- ParseLocalName(bool parse_function_params)
- {
- if (!ParseEncoding())
+ if (!ParseSourceName())
+ return false;
+ name_state.last_name_range = EndRange(name_start_cookie);
+ continue;
+ }
+ case 'S':
+ if (*++m_read_ptr == 't') {
+ WriteStdPrefix();
+ ++m_read_ptr;
+ if (!ParseUnqualifiedName(name_state))
return false;
- if (!Parse('E'))
+ } else {
+ if (!ParseSubstitution())
return false;
-
- switch (*m_read_ptr)
- {
- case 's':
- ++m_read_ptr;
- TryParseDiscriminator(); // Optional and ignored
- WRITE("::string literal");
- break;
- case 'd':
- ++m_read_ptr;
- TryParseNumber(); // Optional and ignored
- if (!Parse('_'))
- return false;
- WriteNamespaceSeparator();
- if (!ParseName())
- return false;
- break;
- default:
- WriteNamespaceSeparator();
- if (!ParseName(parse_function_params, true))
- return false;
- TryParseDiscriminator(); // Optional and ignored
+ suppress_substitution = true;
}
- return true;
+ continue;
+ case 'T':
+ ++m_read_ptr;
+ if (!ParseTemplateParam())
+ return false;
+ continue;
+ case 'C':
+ ++m_read_ptr;
+ if (!ParseCtor(name_state))
+ return false;
+ continue;
+ case 'D': {
+ switch (*(m_read_ptr + 1)) {
+ case 't':
+ case 'T':
+#ifdef DEBUG_FAILURES
+ printf("*** Decltype unsupported\n");
+#endif
+ return false;
+ }
+ ++m_read_ptr;
+ if (!ParseDtor(name_state))
+ return false;
+ continue;
+ }
+ case 'U':
+ ++m_read_ptr;
+ if (!ParseUnnamedTypeName(name_state))
+ return false;
+ continue;
+ case 'L':
+ ++m_read_ptr;
+ if (!ParseUnqualifiedName(name_state))
+ return false;
+ continue;
+ default:
+ if (!ParseOperatorName(name_state))
+ return false;
+ }
+ }
+
+ if (parse_discriminator)
+ TryParseDiscriminator();
+ if (name_state.parse_function_params &&
+ !ParseFunctionArgs(name_state, name_start_cookie)) {
+ return false;
+ }
+ if (qualifiers)
+ WriteQualifiers(qualifiers);
+ return true;
+ }
+
+ // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
+ // := Z <function encoding> E s [<discriminator>]
+ // := Z <function encoding> Ed [ <parameter number> ] _ <entity
+ // name>
+
+ bool ParseLocalName(bool parse_function_params) {
+ if (!ParseEncoding())
+ return false;
+ if (!Parse('E'))
+ return false;
+
+ switch (*m_read_ptr) {
+ case 's':
+ ++m_read_ptr;
+ TryParseDiscriminator(); // Optional and ignored
+ WRITE("::string literal");
+ break;
+ case 'd':
+ ++m_read_ptr;
+ TryParseNumber(); // Optional and ignored
+ if (!Parse('_'))
+ return false;
+ WriteNamespaceSeparator();
+ if (!ParseName())
+ return false;
+ break;
+ default:
+ WriteNamespaceSeparator();
+ if (!ParseName(parse_function_params, true))
+ return false;
+ TryParseDiscriminator(); // Optional and ignored
}
+ return true;
+ }
- // <name> ::= <nested-name>
- // ::= <local-name>
- // ::= <unscoped-template-name> <template-args>
- // ::= <unscoped-name>
-
- // <unscoped-template-name> ::= <unscoped-name>
- // ::= <substitution>
-
- bool
- ParseName(bool parse_function_params = false,
- bool parse_discriminator = false)
- {
- NameState name_state = { parse_function_params, false, false, {0, 0}};
- int name_start_cookie = GetStartCookie();
-
- switch (*m_read_ptr)
- {
- case 'N':
- ++m_read_ptr;
- return ParseNestedName(name_state, parse_discriminator);
- case 'Z':
- {
- ++m_read_ptr;
- if (!ParseLocalName(parse_function_params))
- return false;
- break;
- }
- case 'L':
- ++m_read_ptr;
- LLVM_FALLTHROUGH;
- default:
- {
- if (!ParseUnscopedName(name_state))
- return false;
-
- if (*m_read_ptr == 'I')
- {
- EndSubstitution(name_start_cookie);
-
- ++m_read_ptr;
- name_state.is_last_generic = true;
- WriteTemplateStart();
- if (!ParseTemplateArgs(parse_function_params))
- return false;
- WriteTemplateEnd();
- }
- break;
- }
- }
- if (parse_discriminator)
- TryParseDiscriminator();
- if (parse_function_params &&
- !ParseFunctionArgs(name_state, name_start_cookie))
- {
- return false;
- }
- return true;
+ // <name> ::= <nested-name>
+ // ::= <local-name>
+ // ::= <unscoped-template-name> <template-args>
+ // ::= <unscoped-name>
+
+ // <unscoped-template-name> ::= <unscoped-name>
+ // ::= <substitution>
+
+ bool ParseName(bool parse_function_params = false,
+ bool parse_discriminator = false) {
+ NameState name_state = {parse_function_params, false, false, {0, 0}};
+ int name_start_cookie = GetStartCookie();
+
+ switch (*m_read_ptr) {
+ case 'N':
+ ++m_read_ptr;
+ return ParseNestedName(name_state, parse_discriminator);
+ case 'Z': {
+ ++m_read_ptr;
+ if (!ParseLocalName(parse_function_params))
+ return false;
+ break;
}
+ case 'L':
+ ++m_read_ptr;
+ LLVM_FALLTHROUGH;
+ default: {
+ if (!ParseUnscopedName(name_state))
+ return false;
- // <call-offset> ::= h <nv-offset> _
- // ::= v <v-offset> _
- //
- // <nv-offset> ::= <offset number>
- // # non-virtual base override
- //
- // <v-offset> ::= <offset number> _ <virtual offset number>
- // # virtual base override, with vcall offset
+ if (*m_read_ptr == 'I') {
+ EndSubstitution(name_start_cookie);
- bool
- ParseCallOffset()
- {
- switch (*m_read_ptr++)
- {
- case 'h':
- if (*m_read_ptr == 'n')
- ++m_read_ptr;
- if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
- break;
- return true;
- case 'v':
- if (*m_read_ptr == 'n')
- ++m_read_ptr;
- if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
- break;
- if (*m_read_ptr == 'n')
- ++m_read_ptr;
- if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
- break;
- return true;
- }
-#ifdef DEBUG_FAILURES
- printf("*** Malformed call offset\n");
-#endif
+ ++m_read_ptr;
+ name_state.is_last_generic = true;
+ WriteTemplateStart();
+ if (!ParseTemplateArgs(parse_function_params))
+ return false;
+ WriteTemplateEnd();
+ }
+ break;
+ }
+ }
+ if (parse_discriminator)
+ TryParseDiscriminator();
+ if (parse_function_params &&
+ !ParseFunctionArgs(name_state, name_start_cookie)) {
+ return false;
+ }
+ return true;
+ }
+
+ // <call-offset> ::= h <nv-offset> _
+ // ::= v <v-offset> _
+ //
+ // <nv-offset> ::= <offset number>
+ // # non-virtual base override
+ //
+ // <v-offset> ::= <offset number> _ <virtual offset number>
+ // # virtual base override, with vcall offset
+
+ bool ParseCallOffset() {
+ switch (*m_read_ptr++) {
+ case 'h':
+ if (*m_read_ptr == 'n')
+ ++m_read_ptr;
+ if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
+ break;
+ return true;
+ case 'v':
+ if (*m_read_ptr == 'n')
+ ++m_read_ptr;
+ if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
+ break;
+ if (*m_read_ptr == 'n')
+ ++m_read_ptr;
+ if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
+ break;
+ return true;
+ }
+#ifdef DEBUG_FAILURES
+ printf("*** Malformed call offset\n");
+#endif
+ return false;
+ }
+
+ // <special-name> ::= TV <type> # virtual table
+ // ::= TT <type> # VTT structure (construction vtable index)
+ // ::= TI <type> # typeinfo structure
+ // ::= TS <type> # typeinfo name (null-terminated byte
+ // string)
+ // ::= Tc <call-offset> <call-offset> <base encoding>
+ // # base is the nominal target function of thunk
+ // # first call-offset is 'this' adjustment
+ // # second call-offset is result adjustment
+ // ::= T <call-offset> <base encoding>
+ // # base is the nominal target function of thunk
+ // extension ::= TC <first type> <number> _ <second type> # construction
+ // vtable for second-in-first
+
+ bool ParseSpecialNameT() {
+ switch (*m_read_ptr++) {
+ case 'V':
+ WRITE("vtable for ");
+ return ParseType();
+ case 'T':
+ WRITE("VTT for ");
+ return ParseType();
+ case 'I':
+ WRITE("typeinfo for ");
+ return ParseType();
+ case 'S':
+ WRITE("typeinfo name for ");
+ return ParseType();
+ case 'c':
+ case 'C':
+#ifdef DEBUG_FAILURES
+ printf("*** Unsupported thunk or construction vtable name: %.3s\n",
+ m_read_ptr - 1);
+#endif
+ return false;
+ default:
+ if (*--m_read_ptr == 'v') {
+ WRITE("virtual thunk to ");
+ } else {
+ WRITE("non-virtual thunk to ");
+ }
+ if (!ParseCallOffset())
return false;
+ return ParseEncoding();
}
+ }
- // <special-name> ::= TV <type> # virtual table
- // ::= TT <type> # VTT structure (construction vtable index)
- // ::= TI <type> # typeinfo structure
- // ::= TS <type> # typeinfo name (null-terminated byte string)
- // ::= Tc <call-offset> <call-offset> <base encoding>
- // # base is the nominal target function of thunk
- // # first call-offset is 'this' adjustment
- // # second call-offset is result adjustment
- // ::= T <call-offset> <base encoding>
- // # base is the nominal target function of thunk
- // extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
-
- bool
- ParseSpecialNameT()
- {
- switch (*m_read_ptr++)
- {
- case 'V':
- WRITE("vtable for ");
- return ParseType();
- case 'T':
- WRITE("VTT for ");
- return ParseType();
- case 'I':
- WRITE("typeinfo for ");
- return ParseType();
- case 'S':
- WRITE("typeinfo name for ");
- return ParseType();
- case 'c':
- case 'C':
+ // <special-name> ::= GV <object name> # Guard variable for one-time
+ // initialization
+ // # No <type>
+ // extension ::= GR <object name> # reference temporary for object
+
+ bool ParseSpecialNameG() {
+ switch (*m_read_ptr++) {
+ case 'V':
+ WRITE("guard variable for ");
+ if (!ParseName(true))
+ return false;
+ break;
+ case 'R':
+ WRITE("reference temporary for ");
+ if (!ParseName(true))
+ return false;
+ break;
+ default:
#ifdef DEBUG_FAILURES
- printf("*** Unsupported thunk or construction vtable name: %.3s\n", m_read_ptr - 1);
+ printf("*** Unknown G encoding\n");
#endif
- return false;
- default:
- if (*--m_read_ptr == 'v')
- {
- WRITE("virtual thunk to ");
- }
- else
- {
- WRITE("non-virtual thunk to ");
- }
- if (!ParseCallOffset())
- return false;
- return ParseEncoding();
- }
+ return false;
}
-
- // <special-name> ::= GV <object name> # Guard variable for one-time initialization
- // # No <type>
- // extension ::= GR <object name> # reference temporary for object
-
- bool
- ParseSpecialNameG()
- {
- switch (*m_read_ptr++)
- {
- case 'V':
- WRITE("guard variable for ");
- if (!ParseName(true))
- return false;
- break;
- case 'R':
- WRITE("reference temporary for ");
- if (!ParseName(true))
- return false;
- break;
- default:
-#ifdef DEBUG_FAILURES
- printf("*** Unknown G encoding\n");
-#endif
- return false;
- }
+ return true;
+ }
+
+ // <bare-function-type> ::= <signature type>+ # types are possible
+ // return type, then parameter types
+
+ bool ParseFunctionArgs(NameState &name_state, int return_insert_cookie) {
+ char next = *m_read_ptr;
+ if (next == 'E' || next == '\0' || next == '.')
+ return true;
+
+ // Clang has a bad habit of making unique manglings by just sticking numbers
+ // on the end of a symbol,
+ // which is ambiguous with malformed source name manglings
+ const char *before_clang_uniquing_test = m_read_ptr;
+ if (TryParseNumber()) {
+ if (*m_read_ptr == '\0')
return true;
+ m_read_ptr = before_clang_uniquing_test;
}
- // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types
-
- bool
- ParseFunctionArgs(NameState & name_state, int return_insert_cookie)
- {
- char next = *m_read_ptr;
- if (next == 'E' || next == '\0' || next == '.')
- return true;
-
- // Clang has a bad habit of making unique manglings by just sticking numbers on the end of a symbol,
- // which is ambiguous with malformed source name manglings
- const char *before_clang_uniquing_test = m_read_ptr;
- if (TryParseNumber())
- {
- if (*m_read_ptr == '\0')
- return true;
- m_read_ptr = before_clang_uniquing_test;
- }
-
- if (name_state.is_last_generic && !name_state.has_no_return_type)
- {
- int return_type_start_cookie = GetStartCookie();
- if (!ParseType())
- return false;
- Write(' ');
- ReorderRange(EndRange(return_type_start_cookie),
- return_insert_cookie);
- }
-
- Write('(');
- bool first_param = true;
- while (true)
- {
- switch (*m_read_ptr)
- {
- case '\0':
- case 'E':
- case '.':
- break;
- case 'v':
- ++m_read_ptr;
- continue;
- case '_':
- // Not a formal part of the mangling specification, but clang emits suffixes starting with _block_invoke
- if (strncmp(m_read_ptr, "_block_invoke", 13) == 0)
- {
- m_read_ptr += strlen(m_read_ptr);
- break;
- }
- LLVM_FALLTHROUGH;
- default:
- if (first_param)
- first_param = false;
- else WriteCommaSpace();
-
- if (!ParseType())
- return false;
- continue;
- }
- break;
- }
- Write(')');
- return true;
+ if (name_state.is_last_generic && !name_state.has_no_return_type) {
+ int return_type_start_cookie = GetStartCookie();
+ if (!ParseType())
+ return false;
+ Write(' ');
+ ReorderRange(EndRange(return_type_start_cookie), return_insert_cookie);
}
- // <encoding> ::= <function name> <bare-function-type>
- // ::= <data name>
- // ::= <special-name>
-
- bool
- ParseEncoding()
- {
- switch (*m_read_ptr)
- {
- case 'T':
- ++m_read_ptr;
- if (!ParseSpecialNameT())
- return false;
- break;
- case 'G':
- ++m_read_ptr;
- if (!ParseSpecialNameG())
- return false;
- break;
- default:
- if (!ParseName(true))
- return false;
- break;
- }
- return true;
- }
+ Write('(');
+ bool first_param = true;
+ while (true) {
+ switch (*m_read_ptr) {
+ case '\0':
+ case 'E':
+ case '.':
+ break;
+ case 'v':
+ ++m_read_ptr;
+ continue;
+ case '_':
+ // Not a formal part of the mangling specification, but clang emits
+ // suffixes starting with _block_invoke
+ if (strncmp(m_read_ptr, "_block_invoke", 13) == 0) {
+ m_read_ptr += strlen(m_read_ptr);
+ break;
+ }
+ LLVM_FALLTHROUGH;
+ default:
+ if (first_param)
+ first_param = false;
+ else
+ WriteCommaSpace();
- bool
- ParseMangling(const char *mangled_name, long mangled_name_length = 0)
- {
- if (!mangled_name_length)
- mangled_name_length = strlen(mangled_name);
- m_read_end = mangled_name + mangled_name_length;
- m_read_ptr = mangled_name;
- m_write_ptr = m_buffer;
- m_next_substitute_index = 0;
- m_next_template_arg_index = m_rewrite_ranges_size - 1;
+ if (!ParseType())
+ return false;
+ continue;
+ }
+ break;
+ }
+ Write(')');
+ return true;
+ }
+
+ // <encoding> ::= <function name> <bare-function-type>
+ // ::= <data name>
+ // ::= <special-name>
+
+ bool ParseEncoding() {
+ switch (*m_read_ptr) {
+ case 'T':
+ ++m_read_ptr;
+ if (!ParseSpecialNameT())
+ return false;
+ break;
+ case 'G':
+ ++m_read_ptr;
+ if (!ParseSpecialNameG())
+ return false;
+ break;
+ default:
+ if (!ParseName(true))
+ return false;
+ break;
+ }
+ return true;
+ }
- if (*m_read_ptr++ != '_' || *m_read_ptr++ != 'Z')
- {
+ bool ParseMangling(const char *mangled_name, long mangled_name_length = 0) {
+ if (!mangled_name_length)
+ mangled_name_length = strlen(mangled_name);
+ m_read_end = mangled_name + mangled_name_length;
+ m_read_ptr = mangled_name;
+ m_write_ptr = m_buffer;
+ m_next_substitute_index = 0;
+ m_next_template_arg_index = m_rewrite_ranges_size - 1;
+
+ if (*m_read_ptr++ != '_' || *m_read_ptr++ != 'Z') {
+#ifdef DEBUG_FAILURES
+ printf("*** Missing _Z prefix\n");
+#endif
+ return false;
+ }
+ if (!ParseEncoding())
+ return false;
+ switch (*m_read_ptr) {
+ case '.':
+ Write(' ');
+ Write('(');
+ Write(m_read_ptr, m_read_end - m_read_ptr);
+ Write(')');
+ LLVM_FALLTHROUGH;
+ case '\0':
+ return true;
+ default:
#ifdef DEBUG_FAILURES
- printf("*** Missing _Z prefix\n");
+ printf("*** Unparsed mangled content\n");
#endif
- return false;
- }
- if (!ParseEncoding())
- return false;
- switch (*m_read_ptr)
- {
- case '.':
- Write(' ');
- Write('(');
- Write(m_read_ptr, m_read_end - m_read_ptr);
- Write(')');
- LLVM_FALLTHROUGH;
- case '\0':
- return true;
- default:
-#ifdef DEBUG_FAILURES
- printf("*** Unparsed mangled content\n");
-#endif
- return false;
- }
+ return false;
}
+ }
private:
+ // External scratch storage used during demanglings
- // External scratch storage used during demanglings
-
- char *m_buffer;
- const char *m_buffer_end;
- BufferRange *m_rewrite_ranges;
- int m_rewrite_ranges_size;
- bool m_owns_buffer;
- bool m_owns_m_rewrite_ranges;
-
- // Internal state used during demangling
-
- const char *m_read_ptr;
- const char *m_read_end;
- char *m_write_ptr;
- int m_next_template_arg_index;
- int m_next_substitute_index;
+ char *m_buffer;
+ const char *m_buffer_end;
+ BufferRange *m_rewrite_ranges;
+ int m_rewrite_ranges_size;
+ bool m_owns_buffer;
+ bool m_owns_m_rewrite_ranges;
+
+ // Internal state used during demangling
+
+ const char *m_read_ptr;
+ const char *m_read_end;
+ char *m_write_ptr;
+ int m_next_template_arg_index;
+ int m_next_substitute_index;
};
} // Anonymous namespace
// Public entry points referenced from Mangled.cpp
-namespace lldb_private
-{
- char *
- FastDemangle(const char *mangled_name)
- {
- char buffer[16384];
- SymbolDemangler demangler(buffer, sizeof (buffer));
- return demangler.GetDemangledCopy(mangled_name);
- }
-
- char *
- FastDemangle(const char *mangled_name, long mangled_name_length)
- {
- char buffer[16384];
- SymbolDemangler demangler(buffer, sizeof (buffer));
- return demangler.GetDemangledCopy(mangled_name, mangled_name_length);
- }
+namespace lldb_private {
+char *FastDemangle(const char *mangled_name) {
+ char buffer[16384];
+ SymbolDemangler demangler(buffer, sizeof(buffer));
+ return demangler.GetDemangledCopy(mangled_name);
+}
+
+char *FastDemangle(const char *mangled_name, long mangled_name_length) {
+ char buffer[16384];
+ SymbolDemangler demangler(buffer, sizeof(buffer));
+ return demangler.GetDemangledCopy(mangled_name, mangled_name_length);
+}
} // lldb_private namespace
Modified: lldb/trunk/source/Core/FileLineResolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FileLineResolver.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Core/FileLineResolver.cpp (original)
+++ lldb/trunk/source/Core/FileLineResolver.cpp Tue Sep 6 15:57:50 2016
@@ -21,96 +21,66 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// FileLineResolver:
//----------------------------------------------------------------------
-FileLineResolver::FileLineResolver
-(
- const FileSpec &file_spec,
- uint32_t line_no,
- bool check_inlines
-) :
- Searcher (),
- m_file_spec (file_spec),
- m_line_number (line_no),
- m_inlines (check_inlines)
-{
-}
+FileLineResolver::FileLineResolver(const FileSpec &file_spec, uint32_t line_no,
+ bool check_inlines)
+ : Searcher(), m_file_spec(file_spec), m_line_number(line_no),
+ m_inlines(check_inlines) {}
-FileLineResolver::~FileLineResolver ()
-{
-}
+FileLineResolver::~FileLineResolver() {}
Searcher::CallbackReturn
-FileLineResolver::SearchCallback
-(
- SearchFilter &filter,
- SymbolContext &context,
- Address *addr,
- bool containing
-)
-{
- CompileUnit *cu = context.comp_unit;
-
- if (m_inlines || m_file_spec.Compare(*cu, m_file_spec, (bool)m_file_spec.GetDirectory()))
- {
- uint32_t start_file_idx = 0;
- uint32_t file_idx = cu->GetSupportFiles().FindFileIndex(start_file_idx, m_file_spec, false);
- if (file_idx != UINT32_MAX)
- {
- LineTable *line_table = cu->GetLineTable();
- if (line_table)
- {
- if (m_line_number == 0)
- {
- // Match all lines in a file...
- const bool append = true;
- while (file_idx != UINT32_MAX)
- {
- line_table->FineLineEntriesForFileIndex (file_idx, append, m_sc_list);
- // Get the next file index in case we have multiple file
- // entries for the same file
- file_idx = cu->GetSupportFiles().FindFileIndex(file_idx + 1, m_file_spec, false);
- }
- }
- else
- {
- // Match a specific line in a file...
- }
- }
+FileLineResolver::SearchCallback(SearchFilter &filter, SymbolContext &context,
+ Address *addr, bool containing) {
+ CompileUnit *cu = context.comp_unit;
+
+ if (m_inlines ||
+ m_file_spec.Compare(*cu, m_file_spec, (bool)m_file_spec.GetDirectory())) {
+ uint32_t start_file_idx = 0;
+ uint32_t file_idx =
+ cu->GetSupportFiles().FindFileIndex(start_file_idx, m_file_spec, false);
+ if (file_idx != UINT32_MAX) {
+ LineTable *line_table = cu->GetLineTable();
+ if (line_table) {
+ if (m_line_number == 0) {
+ // Match all lines in a file...
+ const bool append = true;
+ while (file_idx != UINT32_MAX) {
+ line_table->FineLineEntriesForFileIndex(file_idx, append,
+ m_sc_list);
+ // Get the next file index in case we have multiple file
+ // entries for the same file
+ file_idx = cu->GetSupportFiles().FindFileIndex(file_idx + 1,
+ m_file_spec, false);
+ }
+ } else {
+ // Match a specific line in a file...
}
+ }
}
- return Searcher::eCallbackReturnContinue;
+ }
+ return Searcher::eCallbackReturnContinue;
}
-Searcher::Depth
-FileLineResolver::GetDepth()
-{
- return Searcher::eDepthCompUnit;
+Searcher::Depth FileLineResolver::GetDepth() {
+ return Searcher::eDepthCompUnit;
}
-void
-FileLineResolver::GetDescription (Stream *s)
-{
- s->Printf ("File and line resolver for file: \"%s\" line: %u",
- m_file_spec.GetPath().c_str(),
- m_line_number);
+void FileLineResolver::GetDescription(Stream *s) {
+ s->Printf("File and line resolver for file: \"%s\" line: %u",
+ m_file_spec.GetPath().c_str(), m_line_number);
}
-void
-FileLineResolver::Clear()
-{
- m_file_spec.Clear();
- m_line_number = UINT32_MAX;
- m_sc_list.Clear();
- m_inlines = true;
+void FileLineResolver::Clear() {
+ m_file_spec.Clear();
+ m_line_number = UINT32_MAX;
+ m_sc_list.Clear();
+ m_inlines = true;
}
-void
-FileLineResolver::Reset (const FileSpec &file_spec,
- uint32_t line,
- bool check_inlines)
-{
- m_file_spec = file_spec;
- m_line_number = line;
- m_sc_list.Clear();
- m_inlines = check_inlines;
+void FileLineResolver::Reset(const FileSpec &file_spec, uint32_t line,
+ bool check_inlines) {
+ m_file_spec = file_spec;
+ m_line_number = line;
+ m_sc_list.Clear();
+ m_inlines = check_inlines;
}
-
Modified: lldb/trunk/source/Core/FileSpecList.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FileSpecList.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Core/FileSpecList.cpp (original)
+++ lldb/trunk/source/Core/FileSpecList.cpp Tue Sep 6 15:57:50 2016
@@ -20,33 +20,26 @@
using namespace lldb_private;
using namespace std;
-FileSpecList::FileSpecList() :
- m_files()
-{
-}
+FileSpecList::FileSpecList() : m_files() {}
-FileSpecList::FileSpecList(const FileSpecList& rhs) = default;
+FileSpecList::FileSpecList(const FileSpecList &rhs) = default;
FileSpecList::~FileSpecList() = default;
//------------------------------------------------------------------
// Assignment operator
//------------------------------------------------------------------
-const FileSpecList&
-FileSpecList::operator= (const FileSpecList& rhs)
-{
- if (this != &rhs)
- m_files = rhs.m_files;
- return *this;
+const FileSpecList &FileSpecList::operator=(const FileSpecList &rhs) {
+ if (this != &rhs)
+ m_files = rhs.m_files;
+ return *this;
}
//------------------------------------------------------------------
// Append the "file_spec" to the end of the file spec list.
//------------------------------------------------------------------
-void
-FileSpecList::Append(const FileSpec &file_spec)
-{
- m_files.push_back(file_spec);
+void FileSpecList::Append(const FileSpec &file_spec) {
+ m_files.push_back(file_spec);
}
//------------------------------------------------------------------
@@ -56,40 +49,30 @@ FileSpecList::Append(const FileSpec &fil
// Returns true if "file_spec" was added, false if this list already
// contained a copy of "file_spec".
//------------------------------------------------------------------
-bool
-FileSpecList::AppendIfUnique(const FileSpec &file_spec)
-{
- collection::iterator pos, end = m_files.end();
- if (find(m_files.begin(), end, file_spec) == end)
- {
- m_files.push_back(file_spec);
- return true;
- }
- return false;
+bool FileSpecList::AppendIfUnique(const FileSpec &file_spec) {
+ collection::iterator pos, end = m_files.end();
+ if (find(m_files.begin(), end, file_spec) == end) {
+ m_files.push_back(file_spec);
+ return true;
+ }
+ return false;
}
//------------------------------------------------------------------
// Clears the file list.
//------------------------------------------------------------------
-void
-FileSpecList::Clear()
-{
- m_files.clear();
-}
+void FileSpecList::Clear() { m_files.clear(); }
//------------------------------------------------------------------
// Dumps the file list to the supplied stream pointer "s".
//------------------------------------------------------------------
-void
-FileSpecList::Dump(Stream *s, const char *separator_cstr) const
-{
- collection::const_iterator pos, end = m_files.end();
- for (pos = m_files.begin(); pos != end; ++pos)
- {
- pos->Dump(s);
- if (separator_cstr && ((pos + 1) != end))
- s->PutCString(separator_cstr);
- }
+void FileSpecList::Dump(Stream *s, const char *separator_cstr) const {
+ collection::const_iterator pos, end = m_files.end();
+ for (pos = m_files.begin(); pos != end; ++pos) {
+ pos->Dump(s);
+ if (separator_cstr && ((pos + 1) != end))
+ s->PutCString(separator_cstr);
+ }
}
//------------------------------------------------------------------
@@ -99,53 +82,45 @@ FileSpecList::Dump(Stream *s, const char
// Returns the valid index of the file that matches "file_spec" if
// it is found, else std::numeric_limits<uint32_t>::max() is returned.
//------------------------------------------------------------------
-size_t
-FileSpecList::FindFileIndex (size_t start_idx, const FileSpec &file_spec, bool full, bool remove_dots) const
-{
- const size_t num_files = m_files.size();
-
- // When looking for files, we will compare only the filename if the
- // FILE_SPEC argument is empty
- bool compare_filename_only = file_spec.GetDirectory().IsEmpty();
-
- for (size_t idx = start_idx; idx < num_files; ++idx)
- {
- if (compare_filename_only)
- {
- if (ConstString::Equals(m_files[idx].GetFilename(), file_spec.GetFilename(),
- file_spec.IsCaseSensitive() || m_files[idx].IsCaseSensitive()))
- return idx;
- }
- else
- {
- if (FileSpec::Equal (m_files[idx], file_spec, full, remove_dots))
- return idx;
- }
+size_t FileSpecList::FindFileIndex(size_t start_idx, const FileSpec &file_spec,
+ bool full, bool remove_dots) const {
+ const size_t num_files = m_files.size();
+
+ // When looking for files, we will compare only the filename if the
+ // FILE_SPEC argument is empty
+ bool compare_filename_only = file_spec.GetDirectory().IsEmpty();
+
+ for (size_t idx = start_idx; idx < num_files; ++idx) {
+ if (compare_filename_only) {
+ if (ConstString::Equals(
+ m_files[idx].GetFilename(), file_spec.GetFilename(),
+ file_spec.IsCaseSensitive() || m_files[idx].IsCaseSensitive()))
+ return idx;
+ } else {
+ if (FileSpec::Equal(m_files[idx], file_spec, full, remove_dots))
+ return idx;
}
+ }
- // We didn't find the file, return an invalid index
- return UINT32_MAX;
+ // We didn't find the file, return an invalid index
+ return UINT32_MAX;
}
//------------------------------------------------------------------
// Returns the FileSpec object at index "idx". If "idx" is out of
// range, then an empty FileSpec object will be returned.
//------------------------------------------------------------------
-const FileSpec &
-FileSpecList::GetFileSpecAtIndex(size_t idx) const
-{
- if (idx < m_files.size())
- return m_files[idx];
- static FileSpec g_empty_file_spec;
- return g_empty_file_spec;
+const FileSpec &FileSpecList::GetFileSpecAtIndex(size_t idx) const {
+ if (idx < m_files.size())
+ return m_files[idx];
+ static FileSpec g_empty_file_spec;
+ return g_empty_file_spec;
}
-const FileSpec *
-FileSpecList::GetFileSpecPointerAtIndex(size_t idx) const
-{
- if (idx < m_files.size())
- return &m_files[idx];
- return nullptr;
+const FileSpec *FileSpecList::GetFileSpecPointerAtIndex(size_t idx) const {
+ if (idx < m_files.size())
+ return &m_files[idx];
+ return nullptr;
}
//------------------------------------------------------------------
@@ -155,32 +130,25 @@ FileSpecList::GetFileSpecPointerAtIndex(
// doesn't not include the string values for the directories any
// filenames as those are in shared string pools.
//------------------------------------------------------------------
-size_t
-FileSpecList::MemorySize () const
-{
- size_t mem_size = sizeof(FileSpecList);
- collection::const_iterator pos, end = m_files.end();
- for (pos = m_files.begin(); pos != end; ++pos)
- {
- mem_size += pos->MemorySize();
- }
+size_t FileSpecList::MemorySize() const {
+ size_t mem_size = sizeof(FileSpecList);
+ collection::const_iterator pos, end = m_files.end();
+ for (pos = m_files.begin(); pos != end; ++pos) {
+ mem_size += pos->MemorySize();
+ }
- return mem_size;
+ return mem_size;
}
//------------------------------------------------------------------
// Return the number of files in the file spec list.
//------------------------------------------------------------------
-size_t
-FileSpecList::GetSize() const
-{
- return m_files.size();
-}
+size_t FileSpecList::GetSize() const { return m_files.size(); }
-size_t
-FileSpecList::GetFilesMatchingPartialPath (const char *path, bool dir_okay, FileSpecList &matches)
-{
-#if 0 // FIXME: Just sketching...
+size_t FileSpecList::GetFilesMatchingPartialPath(const char *path,
+ bool dir_okay,
+ FileSpecList &matches) {
+#if 0 // FIXME: Just sketching...
matches.Clear();
FileSpec path_spec = FileSpec (path);
if (path_spec.Exists ())
@@ -220,5 +188,5 @@ FileSpecList::GetFilesMatchingPartialPat
}
}
#endif
- return 0;
+ return 0;
}
Modified: lldb/trunk/source/Core/FormatEntity.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FormatEntity.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Core/FormatEntity.cpp (original)
+++ lldb/trunk/source/Core/FormatEntity.cpp Tue Sep 6 15:57:50 2016
@@ -49,251 +49,244 @@
using namespace lldb;
using namespace lldb_private;
-enum FileKind
-{
- FileError = 0,
- Basename,
- Dirname,
- Fullpath
-};
-
-#define ENTRY(n,t,f) { n, nullptr, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0, 0, nullptr, false}
-#define ENTRY_VALUE(n,t,f,v) { n, nullptr, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, v, 0, nullptr, false}
-#define ENTRY_CHILDREN(n,t,f,c) { n, nullptr, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0, llvm::array_lengthof(c), c, false}
-#define ENTRY_CHILDREN_KEEP_SEP(n,t,f,c) { n, nullptr, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0, llvm::array_lengthof(c), c, true}
-#define ENTRY_STRING(n,s) { n, s, FormatEntity::Entry::Type::InsertString, FormatEntity::Entry::FormatType::None, 0, 0, nullptr, false}
-static FormatEntity::Entry::Definition g_string_entry[] =
-{
- ENTRY("*", ParentString, None)
-};
+enum FileKind { FileError = 0, Basename, Dirname, Fullpath };
-static FormatEntity::Entry::Definition g_addr_entries[] =
-{
- ENTRY ("load", AddressLoad , UInt64),
- ENTRY ("file", AddressFile , UInt64),
- ENTRY ("load", AddressLoadOrFile, UInt64),
+#define ENTRY(n, t, f) \
+ { \
+ n, nullptr, FormatEntity::Entry::Type::t, \
+ FormatEntity::Entry::FormatType::f, 0, 0, nullptr, false \
+ }
+#define ENTRY_VALUE(n, t, f, v) \
+ { \
+ n, nullptr, FormatEntity::Entry::Type::t, \
+ FormatEntity::Entry::FormatType::f, v, 0, nullptr, false \
+ }
+#define ENTRY_CHILDREN(n, t, f, c) \
+ { \
+ n, nullptr, FormatEntity::Entry::Type::t, \
+ FormatEntity::Entry::FormatType::f, 0, llvm::array_lengthof(c), c, \
+ false \
+ }
+#define ENTRY_CHILDREN_KEEP_SEP(n, t, f, c) \
+ { \
+ n, nullptr, FormatEntity::Entry::Type::t, \
+ FormatEntity::Entry::FormatType::f, 0, llvm::array_lengthof(c), c, \
+ true \
+ }
+#define ENTRY_STRING(n, s) \
+ { \
+ n, s, FormatEntity::Entry::Type::InsertString, \
+ FormatEntity::Entry::FormatType::None, 0, 0, nullptr, false \
+ }
+static FormatEntity::Entry::Definition g_string_entry[] = {
+ ENTRY("*", ParentString, None)};
+
+static FormatEntity::Entry::Definition g_addr_entries[] = {
+ ENTRY("load", AddressLoad, UInt64), ENTRY("file", AddressFile, UInt64),
+ ENTRY("load", AddressLoadOrFile, UInt64),
};
-static FormatEntity::Entry::Definition g_file_child_entries[] =
-{
+static FormatEntity::Entry::Definition g_file_child_entries[] = {
ENTRY_VALUE("basename", ParentNumber, CString, FileKind::Basename),
ENTRY_VALUE("dirname", ParentNumber, CString, FileKind::Dirname),
- ENTRY_VALUE("fullpath", ParentNumber, CString, FileKind::Fullpath)
-};
+ ENTRY_VALUE("fullpath", ParentNumber, CString, FileKind::Fullpath)};
-static FormatEntity::Entry::Definition g_frame_child_entries[] =
-{
- ENTRY ("index", FrameIndex , UInt32),
- ENTRY ("pc" , FrameRegisterPC , UInt64),
- ENTRY ("fp" , FrameRegisterFP , UInt64),
- ENTRY ("sp" , FrameRegisterSP , UInt64),
- ENTRY ("flags", FrameRegisterFlags, UInt64),
- ENTRY_CHILDREN ("reg", FrameRegisterByName, UInt64, g_string_entry),
-};
-
-static FormatEntity::Entry::Definition g_function_child_entries[] =
-{
- ENTRY ("id" , FunctionID , UInt64),
- ENTRY ("name" , FunctionName , CString),
- ENTRY ("name-without-args" , FunctionNameNoArgs , CString),
- ENTRY ("name-with-args" , FunctionNameWithArgs , CString),
- ENTRY ("addr-offset" , FunctionAddrOffset , UInt64),
- ENTRY ("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete, UInt64),
- ENTRY ("line-offset" , FunctionLineOffset , UInt64),
- ENTRY ("pc-offset" , FunctionPCOffset , UInt64),
- ENTRY ("initial-function" , FunctionInitial , None),
- ENTRY ("changed" , FunctionChanged , None),
- ENTRY ("is-optimized" , FunctionIsOptimized , None)
+static FormatEntity::Entry::Definition g_frame_child_entries[] = {
+ ENTRY("index", FrameIndex, UInt32),
+ ENTRY("pc", FrameRegisterPC, UInt64),
+ ENTRY("fp", FrameRegisterFP, UInt64),
+ ENTRY("sp", FrameRegisterSP, UInt64),
+ ENTRY("flags", FrameRegisterFlags, UInt64),
+ ENTRY_CHILDREN("reg", FrameRegisterByName, UInt64, g_string_entry),
};
-static FormatEntity::Entry::Definition g_line_child_entries[] =
-{
- ENTRY_CHILDREN("file", LineEntryFile , None , g_file_child_entries),
- ENTRY("number" , LineEntryLineNumber , UInt32),
- ENTRY("start-addr" , LineEntryStartAddress, UInt64),
- ENTRY("end-addr" , LineEntryEndAddress , UInt64),
+static FormatEntity::Entry::Definition g_function_child_entries[] = {
+ ENTRY("id", FunctionID, UInt64), ENTRY("name", FunctionName, CString),
+ ENTRY("name-without-args", FunctionNameNoArgs, CString),
+ ENTRY("name-with-args", FunctionNameWithArgs, CString),
+ ENTRY("addr-offset", FunctionAddrOffset, UInt64),
+ ENTRY("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete,
+ UInt64),
+ ENTRY("line-offset", FunctionLineOffset, UInt64),
+ ENTRY("pc-offset", FunctionPCOffset, UInt64),
+ ENTRY("initial-function", FunctionInitial, None),
+ ENTRY("changed", FunctionChanged, None),
+ ENTRY("is-optimized", FunctionIsOptimized, None)};
+
+static FormatEntity::Entry::Definition g_line_child_entries[] = {
+ ENTRY_CHILDREN("file", LineEntryFile, None, g_file_child_entries),
+ ENTRY("number", LineEntryLineNumber, UInt32),
+ ENTRY("start-addr", LineEntryStartAddress, UInt64),
+ ENTRY("end-addr", LineEntryEndAddress, UInt64),
};
-static FormatEntity::Entry::Definition g_module_child_entries[] =
-{
+static FormatEntity::Entry::Definition g_module_child_entries[] = {
ENTRY_CHILDREN("file", ModuleFile, None, g_file_child_entries),
};
-static FormatEntity::Entry::Definition g_process_child_entries[] =
-{
- ENTRY ( "id" , ProcessID , UInt64 ),
- ENTRY_VALUE ( "name" , ProcessFile , CString , FileKind::Basename),
- ENTRY_CHILDREN ( "file" , ProcessFile , None , g_file_child_entries),
+static FormatEntity::Entry::Definition g_process_child_entries[] = {
+ ENTRY("id", ProcessID, UInt64),
+ ENTRY_VALUE("name", ProcessFile, CString, FileKind::Basename),
+ ENTRY_CHILDREN("file", ProcessFile, None, g_file_child_entries),
};
-static FormatEntity::Entry::Definition g_svar_child_entries[] =
-{
- ENTRY ( "*" , ParentString , None)
-};
+static FormatEntity::Entry::Definition g_svar_child_entries[] = {
+ ENTRY("*", ParentString, None)};
-static FormatEntity::Entry::Definition g_var_child_entries[] =
-{
- ENTRY ( "*" , ParentString , None)
-};
+static FormatEntity::Entry::Definition g_var_child_entries[] = {
+ ENTRY("*", ParentString, None)};
-static FormatEntity::Entry::Definition g_thread_child_entries[] =
-{
- ENTRY ( "id" , ThreadID , UInt64 ),
- ENTRY ( "protocol_id" , ThreadProtocolID , UInt64 ),
- ENTRY ( "index" , ThreadIndexID , UInt32 ),
- ENTRY_CHILDREN ( "info" , ThreadInfo , None , g_string_entry),
- ENTRY ( "queue" , ThreadQueue , CString ),
- ENTRY ( "name" , ThreadName , CString ),
- ENTRY ( "stop-reason" , ThreadStopReason , CString ),
- ENTRY ( "return-value" , ThreadReturnValue , CString ),
- ENTRY ( "completed-expression", ThreadCompletedExpression , CString ),
+static FormatEntity::Entry::Definition g_thread_child_entries[] = {
+ ENTRY("id", ThreadID, UInt64),
+ ENTRY("protocol_id", ThreadProtocolID, UInt64),
+ ENTRY("index", ThreadIndexID, UInt32),
+ ENTRY_CHILDREN("info", ThreadInfo, None, g_string_entry),
+ ENTRY("queue", ThreadQueue, CString),
+ ENTRY("name", ThreadName, CString),
+ ENTRY("stop-reason", ThreadStopReason, CString),
+ ENTRY("return-value", ThreadReturnValue, CString),
+ ENTRY("completed-expression", ThreadCompletedExpression, CString),
};
-static FormatEntity::Entry::Definition g_target_child_entries[] =
-{
- ENTRY ( "arch" , TargetArch , CString ),
+static FormatEntity::Entry::Definition g_target_child_entries[] = {
+ ENTRY("arch", TargetArch, CString),
};
#define _TO_STR2(_val) #_val
#define _TO_STR(_val) _TO_STR2(_val)
-static FormatEntity::Entry::Definition g_ansi_fg_entries[] =
-{
- ENTRY_STRING ("black" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
- ENTRY_STRING ("red" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
- ENTRY_STRING ("green" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
- ENTRY_STRING ("yellow" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
- ENTRY_STRING ("blue" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
- ENTRY_STRING ("purple" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
- ENTRY_STRING ("cyan" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
- ENTRY_STRING ("white" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
+static FormatEntity::Entry::Definition g_ansi_fg_entries[] = {
+ ENTRY_STRING("black",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
+ ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
+ ENTRY_STRING("green",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
+ ENTRY_STRING("yellow",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
+ ENTRY_STRING("blue",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
+ ENTRY_STRING("purple",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
+ ENTRY_STRING("cyan",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
+ ENTRY_STRING("white",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
};
-static FormatEntity::Entry::Definition g_ansi_bg_entries[] =
-{
- ENTRY_STRING ("black" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
- ENTRY_STRING ("red" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
- ENTRY_STRING ("green" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
- ENTRY_STRING ("yellow" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
- ENTRY_STRING ("blue" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
- ENTRY_STRING ("purple" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
- ENTRY_STRING ("cyan" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
- ENTRY_STRING ("white" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
+static FormatEntity::Entry::Definition g_ansi_bg_entries[] = {
+ ENTRY_STRING("black",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
+ ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
+ ENTRY_STRING("green",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
+ ENTRY_STRING("yellow",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
+ ENTRY_STRING("blue",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
+ ENTRY_STRING("purple",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
+ ENTRY_STRING("cyan",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
+ ENTRY_STRING("white",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
};
-static FormatEntity::Entry::Definition g_ansi_entries[] =
-{
- ENTRY_CHILDREN ( "fg" , Invalid , None , g_ansi_fg_entries),
- ENTRY_CHILDREN ( "bg" , Invalid , None , g_ansi_bg_entries),
- ENTRY_STRING ( "normal" , ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
- ENTRY_STRING ( "bold" , ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
- ENTRY_STRING ( "faint" , ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
- ENTRY_STRING ( "italic" , ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
- ENTRY_STRING ( "underline" , ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
- ENTRY_STRING ( "slow-blink" , ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
- ENTRY_STRING ( "fast-blink" , ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
- ENTRY_STRING ( "negative" , ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
- ENTRY_STRING ( "conceal" , ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
- ENTRY_STRING ( "crossed-out" , ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
+static FormatEntity::Entry::Definition g_ansi_entries[] = {
+ ENTRY_CHILDREN("fg", Invalid, None, g_ansi_fg_entries),
+ ENTRY_CHILDREN("bg", Invalid, None, g_ansi_bg_entries),
+ ENTRY_STRING("normal",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
+ ENTRY_STRING("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
+ ENTRY_STRING("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
+ ENTRY_STRING("italic",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
+ ENTRY_STRING("underline",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
+ ENTRY_STRING("slow-blink",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
+ ENTRY_STRING("fast-blink",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
+ ENTRY_STRING("negative",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
+ ENTRY_STRING("conceal",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
+ ENTRY_STRING("crossed-out",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
};
-static FormatEntity::Entry::Definition g_script_child_entries[] =
-{
- ENTRY ( "frame" , ScriptFrame , None),
- ENTRY ( "process" , ScriptProcess , None),
- ENTRY ( "target" , ScriptTarget , None),
- ENTRY ( "thread" , ScriptThread , None),
- ENTRY ( "var" , ScriptVariable , None),
- ENTRY ( "svar" , ScriptVariableSynthetic , None),
- ENTRY ( "thread" , ScriptThread , None),
+static FormatEntity::Entry::Definition g_script_child_entries[] = {
+ ENTRY("frame", ScriptFrame, None),
+ ENTRY("process", ScriptProcess, None),
+ ENTRY("target", ScriptTarget, None),
+ ENTRY("thread", ScriptThread, None),
+ ENTRY("var", ScriptVariable, None),
+ ENTRY("svar", ScriptVariableSynthetic, None),
+ ENTRY("thread", ScriptThread, None),
};
-static FormatEntity::Entry::Definition g_top_level_entries[] =
-{
- ENTRY_CHILDREN ("addr" , AddressLoadOrFile , UInt64 , g_addr_entries),
- ENTRY ("addr-file-or-load" , AddressLoadOrFile , UInt64 ),
- ENTRY_CHILDREN ("ansi" , Invalid , None , g_ansi_entries),
- ENTRY ("current-pc-arrow" , CurrentPCArrow , CString ),
- ENTRY_CHILDREN ("file" , File , CString , g_file_child_entries),
- ENTRY ("language" , Lang , CString),
- ENTRY_CHILDREN ("frame" , Invalid , None , g_frame_child_entries),
- ENTRY_CHILDREN ("function" , Invalid , None , g_function_child_entries),
- ENTRY_CHILDREN ("line" , Invalid , None , g_line_child_entries),
- ENTRY_CHILDREN ("module" , Invalid , None , g_module_child_entries),
- ENTRY_CHILDREN ("process" , Invalid , None , g_process_child_entries),
- ENTRY_CHILDREN ("script" , Invalid , None , g_script_child_entries),
- ENTRY_CHILDREN_KEEP_SEP ("svar" , VariableSynthetic , None , g_svar_child_entries),
- ENTRY_CHILDREN ("thread" , Invalid , None , g_thread_child_entries),
- ENTRY_CHILDREN ("target" , Invalid , None , g_target_child_entries),
- ENTRY_CHILDREN_KEEP_SEP ("var" , Variable , None , g_var_child_entries),
+static FormatEntity::Entry::Definition g_top_level_entries[] = {
+ ENTRY_CHILDREN("addr", AddressLoadOrFile, UInt64, g_addr_entries),
+ ENTRY("addr-file-or-load", AddressLoadOrFile, UInt64),
+ ENTRY_CHILDREN("ansi", Invalid, None, g_ansi_entries),
+ ENTRY("current-pc-arrow", CurrentPCArrow, CString),
+ ENTRY_CHILDREN("file", File, CString, g_file_child_entries),
+ ENTRY("language", Lang, CString),
+ ENTRY_CHILDREN("frame", Invalid, None, g_frame_child_entries),
+ ENTRY_CHILDREN("function", Invalid, None, g_function_child_entries),
+ ENTRY_CHILDREN("line", Invalid, None, g_line_child_entries),
+ ENTRY_CHILDREN("module", Invalid, None, g_module_child_entries),
+ ENTRY_CHILDREN("process", Invalid, None, g_process_child_entries),
+ ENTRY_CHILDREN("script", Invalid, None, g_script_child_entries),
+ ENTRY_CHILDREN_KEEP_SEP("svar", VariableSynthetic, None,
+ g_svar_child_entries),
+ ENTRY_CHILDREN("thread", Invalid, None, g_thread_child_entries),
+ ENTRY_CHILDREN("target", Invalid, None, g_target_child_entries),
+ ENTRY_CHILDREN_KEEP_SEP("var", Variable, None, g_var_child_entries),
};
-static FormatEntity::Entry::Definition g_root = ENTRY_CHILDREN ("<root>", Root, None, g_top_level_entries);
+static FormatEntity::Entry::Definition g_root =
+ ENTRY_CHILDREN("<root>", Root, None, g_top_level_entries);
-FormatEntity::Entry::Entry (llvm::StringRef s) :
- string (s.data(), s.size()),
- printf_format (),
- children (),
- definition(nullptr),
- type (Type::String),
- fmt (lldb::eFormatDefault),
- number (0),
- deref (false)
-{
-}
+FormatEntity::Entry::Entry(llvm::StringRef s)
+ : string(s.data(), s.size()), printf_format(), children(),
+ definition(nullptr), type(Type::String), fmt(lldb::eFormatDefault),
+ number(0), deref(false) {}
-FormatEntity::Entry::Entry (char ch) :
- string (1, ch),
- printf_format (),
- children (),
- definition(nullptr),
- type (Type::String),
- fmt (lldb::eFormatDefault),
- number (0),
- deref (false)
-{
-}
+FormatEntity::Entry::Entry(char ch)
+ : string(1, ch), printf_format(), children(), definition(nullptr),
+ type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {}
-void
-FormatEntity::Entry::AppendChar (char ch)
-{
- if (children.empty() || children.back().type != Entry::Type::String)
- children.push_back(Entry(ch));
- else
- children.back().string.append(1, ch);
+void FormatEntity::Entry::AppendChar(char ch) {
+ if (children.empty() || children.back().type != Entry::Type::String)
+ children.push_back(Entry(ch));
+ else
+ children.back().string.append(1, ch);
}
-void
-FormatEntity::Entry::AppendText (const llvm::StringRef &s)
-{
- if (children.empty() || children.back().type != Entry::Type::String)
- children.push_back(Entry(s));
- else
- children.back().string.append(s.data(), s.size());
+void FormatEntity::Entry::AppendText(const llvm::StringRef &s) {
+ if (children.empty() || children.back().type != Entry::Type::String)
+ children.push_back(Entry(s));
+ else
+ children.back().string.append(s.data(), s.size());
}
-void
-FormatEntity::Entry::AppendText (const char *cstr)
-{
- return AppendText (llvm::StringRef(cstr));
+void FormatEntity::Entry::AppendText(const char *cstr) {
+ return AppendText(llvm::StringRef(cstr));
}
-Error
-FormatEntity::Parse (const llvm::StringRef &format_str, Entry &entry)
-{
- entry.Clear();
- entry.type = Entry::Type::Root;
- llvm::StringRef modifiable_format (format_str);
- return ParseInternal (modifiable_format, entry, 0);
+Error FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) {
+ entry.Clear();
+ entry.type = Entry::Type::Root;
+ llvm::StringRef modifiable_format(format_str);
+ return ParseInternal(modifiable_format, entry, 0);
}
-#define ENUM_TO_CSTR(eee) case FormatEntity::Entry::Type::eee: return #eee
+#define ENUM_TO_CSTR(eee) \
+ case FormatEntity::Entry::Type::eee: \
+ return #eee
-const char *
-FormatEntity::Entry::TypeToCString (Type t)
-{
- switch (t)
- {
+const char *FormatEntity::Entry::TypeToCString(Type t) {
+ switch (t) {
ENUM_TO_CSTR(Invalid);
ENUM_TO_CSTR(ParentNumber);
ENUM_TO_CSTR(ParentString);
@@ -351,2280 +344,2034 @@ FormatEntity::Entry::TypeToCString (Type
ENUM_TO_CSTR(LineEntryStartAddress);
ENUM_TO_CSTR(LineEntryEndAddress);
ENUM_TO_CSTR(CurrentPCArrow);
- }
- return "???";
+ }
+ return "???";
}
#undef ENUM_TO_CSTR
-void
-FormatEntity::Entry::Dump (Stream &s, int depth) const
-{
- s.Printf ("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type));
- if (fmt != eFormatDefault)
- s.Printf ("lldb-format = %s, ", FormatManager::GetFormatAsCString (fmt));
- if (!string.empty())
- s.Printf ("string = \"%s\"", string.c_str());
- if (!printf_format.empty())
- s.Printf ("printf_format = \"%s\"", printf_format.c_str());
- if (number != 0)
- s.Printf ("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number);
- if (deref)
- s.Printf ("deref = true, ");
- s.EOL();
- for (const auto &child : children)
- {
- child.Dump(s, depth + 1);
- }
+void FormatEntity::Entry::Dump(Stream &s, int depth) const {
+ s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type));
+ if (fmt != eFormatDefault)
+ s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt));
+ if (!string.empty())
+ s.Printf("string = \"%s\"", string.c_str());
+ if (!printf_format.empty())
+ s.Printf("printf_format = \"%s\"", printf_format.c_str());
+ if (number != 0)
+ s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number);
+ if (deref)
+ s.Printf("deref = true, ");
+ s.EOL();
+ for (const auto &child : children) {
+ child.Dump(s, depth + 1);
+ }
}
template <typename T>
-static bool RunScriptFormatKeyword(Stream &s,
- const SymbolContext *sc,
- const ExecutionContext *exe_ctx,
- T t,
- const char *script_function_name)
-{
- Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
-
- if (target)
- {
- ScriptInterpreter *script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
- if (script_interpreter)
- {
- Error error;
- std::string script_output;
-
- if (script_interpreter->RunScriptFormatKeyword(script_function_name, t, script_output, error) && error.Success())
- {
- s.Printf("%s", script_output.c_str());
- return true;
- }
- else
- {
- s.Printf("<error: %s>",error.AsCString());
- }
- }
+static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc,
+ const ExecutionContext *exe_ctx, T t,
+ const char *script_function_name) {
+ Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
+
+ if (target) {
+ ScriptInterpreter *script_interpreter =
+ target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+ if (script_interpreter) {
+ Error error;
+ std::string script_output;
+
+ if (script_interpreter->RunScriptFormatKeyword(script_function_name, t,
+ script_output, error) &&
+ error.Success()) {
+ s.Printf("%s", script_output.c_str());
+ return true;
+ } else {
+ s.Printf("<error: %s>", error.AsCString());
+ }
+ }
+ }
+ return false;
+}
+
+static bool DumpAddress(Stream &s, const SymbolContext *sc,
+ const ExecutionContext *exe_ctx, const Address &addr,
+ bool print_file_addr_or_load_addr) {
+ Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
+ addr_t vaddr = LLDB_INVALID_ADDRESS;
+ if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
+ vaddr = addr.GetLoadAddress(target);
+ if (vaddr == LLDB_INVALID_ADDRESS)
+ vaddr = addr.GetFileAddress();
+
+ if (vaddr != LLDB_INVALID_ADDRESS) {
+ int addr_width = 0;
+ if (exe_ctx && target) {
+ addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
+ }
+ if (addr_width == 0)
+ addr_width = 16;
+ if (print_file_addr_or_load_addr) {
+ ExecutionContextScope *exe_scope = nullptr;
+ if (exe_ctx)
+ exe_scope = exe_ctx->GetBestExecutionContextScope();
+ addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress,
+ Address::DumpStyleModuleWithFileAddress, 0);
+ } else {
+ s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
}
- return false;
+ return true;
+ }
+ return false;
}
-static bool
-DumpAddress (Stream &s,
- const SymbolContext *sc,
- const ExecutionContext *exe_ctx,
- const Address &addr,
- bool print_file_addr_or_load_addr)
-{
- Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
- addr_t vaddr = LLDB_INVALID_ADDRESS;
- if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
- vaddr = addr.GetLoadAddress (target);
- if (vaddr == LLDB_INVALID_ADDRESS)
- vaddr = addr.GetFileAddress ();
-
- if (vaddr != LLDB_INVALID_ADDRESS)
- {
- int addr_width = 0;
- if (exe_ctx && target)
- {
- addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
- }
- if (addr_width == 0)
- addr_width = 16;
- if (print_file_addr_or_load_addr)
- {
- ExecutionContextScope *exe_scope = nullptr;
- if (exe_ctx)
- exe_scope = exe_ctx->GetBestExecutionContextScope();
- addr.Dump (&s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0);
- }
- else
- {
- s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
+static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ const Address &format_addr,
+ bool concrete_only, bool no_padding,
+ bool print_zero_offsets) {
+ if (format_addr.IsValid()) {
+ Address func_addr;
+
+ if (sc) {
+ if (sc->function) {
+ func_addr = sc->function->GetAddressRange().GetBaseAddress();
+ if (sc->block && !concrete_only) {
+ // Check to make sure we aren't in an inline
+ // function. If we are, use the inline block
+ // range that contains "format_addr" since
+ // blocks can be discontiguous.
+ Block *inline_block = sc->block->GetContainingInlinedBlock();
+ AddressRange inline_range;
+ if (inline_block &&
+ inline_block->GetRangeContainingAddress(format_addr,
+ inline_range))
+ func_addr = inline_range.GetBaseAddress();
+ }
+ } else if (sc->symbol && sc->symbol->ValueIsAddress())
+ func_addr = sc->symbol->GetAddressRef();
+ }
+
+ if (func_addr.IsValid()) {
+ const char *addr_offset_padding = no_padding ? "" : " ";
+
+ if (func_addr.GetSection() == format_addr.GetSection()) {
+ addr_t func_file_addr = func_addr.GetFileAddress();
+ addr_t addr_file_addr = format_addr.GetFileAddress();
+ if (addr_file_addr > func_file_addr ||
+ (addr_file_addr == func_file_addr && print_zero_offsets)) {
+ s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
+ addr_file_addr - func_file_addr);
+ } else if (addr_file_addr < func_file_addr) {
+ s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
+ func_file_addr - addr_file_addr);
}
return true;
- }
+ } else {
+ Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
+ if (target) {
+ addr_t func_load_addr = func_addr.GetLoadAddress(target);
+ addr_t addr_load_addr = format_addr.GetLoadAddress(target);
+ if (addr_load_addr > func_load_addr ||
+ (addr_load_addr == func_load_addr && print_zero_offsets)) {
+ s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
+ addr_load_addr - func_load_addr);
+ } else if (addr_load_addr < func_load_addr) {
+ s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
+ func_load_addr - addr_load_addr);
+ }
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+static bool ScanBracketedRange(llvm::StringRef subpath,
+ size_t &close_bracket_index,
+ const char *&var_name_final_if_array_range,
+ int64_t &index_lower, int64_t &index_higher) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
+ close_bracket_index = llvm::StringRef::npos;
+ const size_t open_bracket_index = subpath.find('[');
+ if (open_bracket_index == llvm::StringRef::npos) {
+ if (log)
+ log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
return false;
-}
+ }
-static bool
-DumpAddressOffsetFromFunction (Stream &s,
- const SymbolContext *sc,
- const ExecutionContext *exe_ctx,
- const Address &format_addr,
- bool concrete_only,
- bool no_padding,
- bool print_zero_offsets)
-{
- if (format_addr.IsValid())
- {
- Address func_addr;
-
- if (sc)
- {
- if (sc->function)
- {
- func_addr = sc->function->GetAddressRange().GetBaseAddress();
- if (sc->block && !concrete_only)
- {
- // Check to make sure we aren't in an inline
- // function. If we are, use the inline block
- // range that contains "format_addr" since
- // blocks can be discontiguous.
- Block *inline_block = sc->block->GetContainingInlinedBlock ();
- AddressRange inline_range;
- if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range))
- func_addr = inline_range.GetBaseAddress();
- }
- }
- else if (sc->symbol && sc->symbol->ValueIsAddress())
- func_addr = sc->symbol->GetAddressRef();
- }
+ close_bracket_index = subpath.find(']', open_bracket_index + 1);
- if (func_addr.IsValid())
- {
- const char *addr_offset_padding = no_padding ? "" : " ";
+ if (close_bracket_index == llvm::StringRef::npos) {
+ if (log)
+ log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
+ return false;
+ } else {
+ var_name_final_if_array_range = subpath.data() + open_bracket_index;
- if (func_addr.GetSection() == format_addr.GetSection())
- {
- addr_t func_file_addr = func_addr.GetFileAddress();
- addr_t addr_file_addr = format_addr.GetFileAddress();
- if (addr_file_addr > func_file_addr
- || (addr_file_addr == func_file_addr && print_zero_offsets))
- {
- s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_file_addr - func_file_addr);
- }
- else if (addr_file_addr < func_file_addr)
- {
- s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_file_addr - addr_file_addr);
- }
- return true;
- }
- else
- {
- Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
- if (target)
- {
- addr_t func_load_addr = func_addr.GetLoadAddress (target);
- addr_t addr_load_addr = format_addr.GetLoadAddress (target);
- if (addr_load_addr > func_load_addr
- || (addr_load_addr == func_load_addr && print_zero_offsets))
- {
- s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_load_addr - func_load_addr);
- }
- else if (addr_load_addr < func_load_addr)
- {
- s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_load_addr - addr_load_addr);
- }
- return true;
- }
- }
+ if (close_bracket_index - open_bracket_index == 1) {
+ if (log)
+ log->Printf(
+ "[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
+ index_lower = 0;
+ } else {
+ const size_t separator_index = subpath.find('-', open_bracket_index + 1);
+
+ if (separator_index == llvm::StringRef::npos) {
+ const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
+ index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
+ index_higher = index_lower;
+ if (log)
+ log->Printf("[ScanBracketedRange] [%" PRId64
+ "] detected, high index is same",
+ index_lower);
+ } else {
+ const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
+ const char *index_higher_cstr = subpath.data() + separator_index + 1;
+ index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
+ index_higher = ::strtoul(index_higher_cstr, nullptr, 0);
+ if (log)
+ log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected",
+ index_lower, index_higher);
+ }
+ if (index_lower > index_higher && index_higher > 0) {
+ if (log)
+ log->Printf("[ScanBracketedRange] swapping indices");
+ const int64_t temp = index_lower;
+ index_lower = index_higher;
+ index_higher = temp;
+ }
+ }
+ }
+ return true;
+}
+
+static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) {
+ switch (file_kind) {
+ case FileKind::FileError:
+ break;
+
+ case FileKind::Basename:
+ if (file.GetFilename()) {
+ s << file.GetFilename();
+ return true;
+ }
+ break;
+
+ case FileKind::Dirname:
+ if (file.GetDirectory()) {
+ s << file.GetDirectory();
+ return true;
+ }
+ break;
+
+ case FileKind::Fullpath:
+ if (file) {
+ s << file;
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
+ uint32_t reg_num, Format format)
+
+{
+ if (frame) {
+ RegisterContext *reg_ctx = frame->GetRegisterContext().get();
+
+ if (reg_ctx) {
+ const uint32_t lldb_reg_num =
+ reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
+ if (lldb_reg_num != LLDB_INVALID_REGNUM) {
+ const RegisterInfo *reg_info =
+ reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num);
+ if (reg_info) {
+ RegisterValue reg_value;
+ if (reg_ctx->ReadRegister(reg_info, reg_value)) {
+ reg_value.Dump(&s, reg_info, false, false, format);
+ return true;
+ }
}
+ }
}
- return false;
+ }
+ return false;
}
-static bool
-ScanBracketedRange (llvm::StringRef subpath,
- size_t& close_bracket_index,
- const char*& var_name_final_if_array_range,
- int64_t& index_lower,
- int64_t& index_higher)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
- close_bracket_index = llvm::StringRef::npos;
- const size_t open_bracket_index = subpath.find('[');
- if (open_bracket_index == llvm::StringRef::npos)
- {
- if (log)
- log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
- return false;
- }
+static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index,
+ StackFrame *frame,
+ bool deref_pointer) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
+ const char *ptr_deref_format = "[%d]";
+ std::string ptr_deref_buffer(10, 0);
+ ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index);
+ if (log)
+ log->Printf("[ExpandIndexedExpression] name to deref: %s",
+ ptr_deref_buffer.c_str());
+ const char *first_unparsed;
+ ValueObject::GetValueForExpressionPathOptions options;
+ ValueObject::ExpressionPathEndResultType final_value_type;
+ ValueObject::ExpressionPathScanEndReason reason_to_stop;
+ ValueObject::ExpressionPathAftermath what_next =
+ (deref_pointer ? ValueObject::eExpressionPathAftermathDereference
+ : ValueObject::eExpressionPathAftermathNothing);
+ ValueObjectSP item = valobj->GetValueForExpressionPath(
+ ptr_deref_buffer.c_str(), &first_unparsed, &reason_to_stop,
+ &final_value_type, options, &what_next);
+ if (!item) {
+ if (log)
+ log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why "
+ "stopping = %d,"
+ " final_value_type %d",
+ first_unparsed, reason_to_stop, final_value_type);
+ } else {
+ if (log)
+ log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, "
+ "why stopping = %d,"
+ " final_value_type %d",
+ first_unparsed, reason_to_stop, final_value_type);
+ }
+ return item;
+}
+
+static char ConvertValueObjectStyleToChar(
+ ValueObject::ValueObjectRepresentationStyle style) {
+ switch (style) {
+ case ValueObject::eValueObjectRepresentationStyleLanguageSpecific:
+ return '@';
+ case ValueObject::eValueObjectRepresentationStyleValue:
+ return 'V';
+ case ValueObject::eValueObjectRepresentationStyleLocation:
+ return 'L';
+ case ValueObject::eValueObjectRepresentationStyleSummary:
+ return 'S';
+ case ValueObject::eValueObjectRepresentationStyleChildrenCount:
+ return '#';
+ case ValueObject::eValueObjectRepresentationStyleType:
+ return 'T';
+ case ValueObject::eValueObjectRepresentationStyleName:
+ return 'N';
+ case ValueObject::eValueObjectRepresentationStyleExpressionPath:
+ return '>';
+ }
+ return '\0';
+}
- close_bracket_index = subpath.find(']', open_bracket_index + 1);
+static bool DumpValue(Stream &s, const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ const FormatEntity::Entry &entry, ValueObject *valobj) {
+ if (valobj == nullptr)
+ return false;
- if (close_bracket_index == llvm::StringRef::npos)
- {
- if (log)
- log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
+ Format custom_format = eFormatInvalid;
+ ValueObject::ValueObjectRepresentationStyle val_obj_display =
+ entry.string.empty()
+ ? ValueObject::eValueObjectRepresentationStyleValue
+ : ValueObject::eValueObjectRepresentationStyleSummary;
+
+ bool do_deref_pointer = entry.deref;
+ bool is_script = false;
+ switch (entry.type) {
+ case FormatEntity::Entry::Type::ScriptVariable:
+ is_script = true;
+ break;
+
+ case FormatEntity::Entry::Type::Variable:
+ custom_format = entry.fmt;
+ val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
+ break;
+
+ case FormatEntity::Entry::Type::ScriptVariableSynthetic:
+ is_script = true;
+ LLVM_FALLTHROUGH;
+ case FormatEntity::Entry::Type::VariableSynthetic:
+ custom_format = entry.fmt;
+ val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
+ if (!valobj->IsSynthetic()) {
+ valobj = valobj->GetSyntheticValue().get();
+ if (valobj == nullptr)
return false;
}
- else
- {
- var_name_final_if_array_range = subpath.data() + open_bracket_index;
+ break;
- if (close_bracket_index - open_bracket_index == 1)
- {
- if (log)
- log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
- index_lower = 0;
- }
- else
- {
- const size_t separator_index = subpath.find('-', open_bracket_index + 1);
+ default:
+ return false;
+ }
- if (separator_index == llvm::StringRef::npos)
- {
- const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
- index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
- index_higher = index_lower;
- if (log)
- log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", index_lower);
- }
- else
- {
- const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
- const char *index_higher_cstr = subpath.data() + separator_index + 1;
- index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
- index_higher = ::strtoul(index_higher_cstr, nullptr, 0);
- if (log)
- log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", index_lower, index_higher);
- }
- if (index_lower > index_higher && index_higher > 0)
- {
- if (log)
- log->Printf("[ScanBracketedRange] swapping indices");
- const int64_t temp = index_lower;
- index_lower = index_higher;
- index_higher = temp;
- }
- }
- }
- return true;
-}
+ if (valobj == nullptr)
+ return false;
-static bool
-DumpFile (Stream &s, const FileSpec &file, FileKind file_kind)
-{
- switch (file_kind)
- {
- case FileKind::FileError:
- break;
+ ValueObject::ExpressionPathAftermath what_next =
+ (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference
+ : ValueObject::eExpressionPathAftermathNothing);
+ ValueObject::GetValueForExpressionPathOptions options;
+ options.DontCheckDotVsArrowSyntax()
+ .DoAllowBitfieldSyntax()
+ .DoAllowFragileIVar()
+ .SetSyntheticChildrenTraversal(
+ ValueObject::GetValueForExpressionPathOptions::
+ SyntheticChildrenTraversal::Both);
+ ValueObject *target = nullptr;
+ const char *var_name_final_if_array_range = nullptr;
+ size_t close_bracket_index = llvm::StringRef::npos;
+ int64_t index_lower = -1;
+ int64_t index_higher = -1;
+ bool is_array_range = false;
+ const char *first_unparsed;
+ bool was_plain_var = false;
+ bool was_var_format = false;
+ bool was_var_indexed = false;
+ ValueObject::ExpressionPathScanEndReason reason_to_stop =
+ ValueObject::eExpressionPathScanEndReasonEndOfString;
+ ValueObject::ExpressionPathEndResultType final_value_type =
+ ValueObject::eExpressionPathEndResultTypePlain;
+
+ if (is_script) {
+ return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str());
+ }
+
+ llvm::StringRef subpath(entry.string);
+ // simplest case ${var}, just print valobj's value
+ if (entry.string.empty()) {
+ if (entry.printf_format.empty() && entry.fmt == eFormatDefault &&
+ entry.number == ValueObject::eValueObjectRepresentationStyleValue)
+ was_plain_var = true;
+ else
+ was_var_format = true;
+ target = valobj;
+ } else // this is ${var.something} or multiple .something nested
+ {
+ if (entry.string[0] == '[')
+ was_var_indexed = true;
+ ScanBracketedRange(subpath, close_bracket_index,
+ var_name_final_if_array_range, index_lower,
+ index_higher);
- case FileKind::Basename:
- if (file.GetFilename())
- {
- s << file.GetFilename();
- return true;
- }
- break;
+ Error error;
- case FileKind::Dirname:
- if (file.GetDirectory())
- {
- s << file.GetDirectory();
- return true;
- }
- break;
+ const std::string &expr_path = entry.string;
- case FileKind::Fullpath:
- if (file)
- {
- s << file;
- return true;
- }
- break;
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",
+ expr_path.c_str());
+
+ target = valobj
+ ->GetValueForExpressionPath(expr_path.c_str(), &first_unparsed,
+ &reason_to_stop, &final_value_type,
+ options, &what_next)
+ .get();
+
+ if (!target) {
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, "
+ "why stopping = %d,"
+ " final_value_type %d",
+ first_unparsed, reason_to_stop, final_value_type);
+ return false;
+ } else {
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = "
+ "%s, why stopping = %d,"
+ " final_value_type %d",
+ first_unparsed, reason_to_stop, final_value_type);
+ target = target
+ ->GetQualifiedRepresentationIfAvailable(
+ target->GetDynamicValueType(), true)
+ .get();
+ }
+ }
+
+ is_array_range =
+ (final_value_type ==
+ ValueObject::eExpressionPathEndResultTypeBoundedRange ||
+ final_value_type ==
+ ValueObject::eExpressionPathEndResultTypeUnboundedRange);
+
+ do_deref_pointer =
+ (what_next == ValueObject::eExpressionPathAftermathDereference);
+
+ if (do_deref_pointer && !is_array_range) {
+ // I have not deref-ed yet, let's do it
+ // this happens when we are not going through
+ // GetValueForVariableExpressionPath
+ // to get to the target ValueObject
+ Error error;
+ target = target->Dereference(error).get();
+ if (error.Fail()) {
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] ERROR: %s\n",
+ error.AsCString("unknown"));
+ return false;
}
+ do_deref_pointer = false;
+ }
+
+ if (!target) {
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] could not calculate target for "
+ "prompt expression");
return false;
-}
+ }
-static bool
-DumpRegister (Stream &s,
- StackFrame *frame,
- RegisterKind reg_kind,
- uint32_t reg_num,
- Format format)
+ // we do not want to use the summary for a bitfield of type T:n
+ // if we were originally dealing with just a T - that would get
+ // us into an endless recursion
+ if (target->IsBitfield() && was_var_indexed) {
+ // TODO: check for a (T:n)-specific summary - we should still obey that
+ StreamString bitfield_name;
+ bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(),
+ target->GetBitfieldBitSize());
+ lldb::TypeNameSpecifierImplSP type_sp(
+ new TypeNameSpecifierImpl(bitfield_name.GetData(), false));
+ if (val_obj_display ==
+ ValueObject::eValueObjectRepresentationStyleSummary &&
+ !DataVisualization::GetSummaryForType(type_sp))
+ val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
+ }
+
+ // TODO use flags for these
+ const uint32_t type_info_flags =
+ target->GetCompilerType().GetTypeInfo(nullptr);
+ bool is_array = (type_info_flags & eTypeIsArray) != 0;
+ bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
+ bool is_aggregate = target->GetCompilerType().IsAggregateType();
+
+ if ((is_array || is_pointer) && (!is_array_range) &&
+ val_obj_display ==
+ ValueObject::eValueObjectRepresentationStyleValue) // this should be
+ // wrong, but there
+ // are some
+ // exceptions
+ {
+ StreamString str_temp;
+ if (log)
+ log->Printf(
+ "[Debugger::FormatPrompt] I am into array || pointer && !range");
-{
- if (frame)
- {
- RegisterContext *reg_ctx = frame->GetRegisterContext().get();
+ if (target->HasSpecialPrintableRepresentation(val_obj_display,
+ custom_format)) {
+ // try to use the special cases
+ bool success = target->DumpPrintableRepresentation(
+ str_temp, val_obj_display, custom_format);
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] special cases did%s match",
+ success ? "" : "n't");
+
+ // should not happen
+ if (success)
+ s << str_temp.GetData();
+ return true;
+ } else {
+ if (was_plain_var) // if ${var}
+ {
+ s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
+ } else if (is_pointer) // if pointer, value is the address stored
+ {
+ target->DumpPrintableRepresentation(
+ s, val_obj_display, custom_format,
+ ValueObject::ePrintableRepresentationSpecialCasesDisable);
+ }
+ return true;
+ }
+ }
+
+ // if directly trying to print ${var}, and this is an aggregate, display a
+ // nice
+ // type @ location message
+ if (is_aggregate && was_plain_var) {
+ s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
+ return true;
+ }
- if (reg_ctx)
- {
- const uint32_t lldb_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
- if (lldb_reg_num != LLDB_INVALID_REGNUM)
- {
- const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (lldb_reg_num);
- if (reg_info)
- {
- RegisterValue reg_value;
- if (reg_ctx->ReadRegister (reg_info, reg_value))
- {
- reg_value.Dump(&s, reg_info, false, false, format);
- return true;
- }
- }
- }
- }
- }
- return false;
-}
+ // if directly trying to print ${var%V}, and this is an aggregate, do not let
+ // the user do it
+ if (is_aggregate &&
+ ((was_var_format &&
+ val_obj_display ==
+ ValueObject::eValueObjectRepresentationStyleValue))) {
+ s << "<invalid use of aggregate type>";
+ return true;
+ }
-static ValueObjectSP
-ExpandIndexedExpression (ValueObject* valobj,
- size_t index,
- StackFrame* frame,
- bool deref_pointer)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
- const char* ptr_deref_format = "[%d]";
- std::string ptr_deref_buffer(10,0);
- ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index);
+ if (!is_array_range) {
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output");
+ return target->DumpPrintableRepresentation(s, val_obj_display,
+ custom_format);
+ } else {
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] checking if I can handle as array");
+ if (!is_array && !is_pointer)
+ return false;
if (log)
- log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str());
- const char* first_unparsed;
- ValueObject::GetValueForExpressionPathOptions options;
- ValueObject::ExpressionPathEndResultType final_value_type;
- ValueObject::ExpressionPathScanEndReason reason_to_stop;
- ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing);
- ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(),
- &first_unparsed,
- &reason_to_stop,
- &final_value_type,
- options,
- &what_next);
- if (!item)
- {
+ log->Printf("[Debugger::FormatPrompt] handle as array");
+ StreamString special_directions_stream;
+ llvm::StringRef special_directions;
+ if (close_bracket_index != llvm::StringRef::npos &&
+ subpath.size() > close_bracket_index) {
+ ConstString additional_data(subpath.drop_front(close_bracket_index + 1));
+ special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "",
+ additional_data.GetCString());
+
+ if (entry.fmt != eFormatDefault) {
+ const char format_char =
+ FormatManager::GetFormatAsFormatChar(entry.fmt);
+ if (format_char != '\0')
+ special_directions_stream.Printf("%%%c", format_char);
+ else {
+ const char *format_cstr =
+ FormatManager::GetFormatAsCString(entry.fmt);
+ special_directions_stream.Printf("%%%s", format_cstr);
+ }
+ } else if (entry.number != 0) {
+ const char style_char = ConvertValueObjectStyleToChar(
+ (ValueObject::ValueObjectRepresentationStyle)entry.number);
+ if (style_char)
+ special_directions_stream.Printf("%%%c", style_char);
+ }
+ special_directions_stream.PutChar('}');
+ special_directions =
+ llvm::StringRef(special_directions_stream.GetString());
+ }
+
+ // let us display items index_lower thru index_higher of this array
+ s.PutChar('[');
+
+ if (index_higher < 0)
+ index_higher = valobj->GetNumChildren() - 1;
+
+ uint32_t max_num_children =
+ target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
+
+ bool success = true;
+ for (int64_t index = index_lower; index <= index_higher; ++index) {
+ ValueObject *item =
+ ExpandIndexedExpression(target, index, exe_ctx->GetFramePtr(), false)
+ .get();
+
+ if (!item) {
if (log)
- log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d,"
- " final_value_type %d",
- first_unparsed, reason_to_stop, final_value_type);
- }
- else
- {
+ log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at "
+ "index %" PRId64,
+ index);
+ } else {
if (log)
- log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d,"
- " final_value_type %d",
- first_unparsed, reason_to_stop, final_value_type);
+ log->Printf(
+ "[Debugger::FormatPrompt] special_directions for child item: %s",
+ special_directions.data() ? special_directions.data() : "");
+ }
+
+ if (special_directions.empty()) {
+ success &= item->DumpPrintableRepresentation(s, val_obj_display,
+ custom_format);
+ } else {
+ success &= FormatEntity::FormatStringRef(
+ special_directions, s, sc, exe_ctx, nullptr, item, false, false);
+ }
+
+ if (--max_num_children == 0) {
+ s.PutCString(", ...");
+ break;
+ }
+
+ if (index < index_higher)
+ s.PutChar(',');
+ }
+ s.PutChar(']');
+ return success;
+ }
+}
+
+static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name,
+ Format format) {
+ if (frame) {
+ RegisterContext *reg_ctx = frame->GetRegisterContext().get();
+
+ if (reg_ctx) {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
+ if (reg_info) {
+ RegisterValue reg_value;
+ if (reg_ctx->ReadRegister(reg_info, reg_value)) {
+ reg_value.Dump(&s, reg_info, false, false, format);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+static bool FormatThreadExtendedInfoRecurse(
+ const FormatEntity::Entry &entry,
+ const StructuredData::ObjectSP &thread_info_dictionary,
+ const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) {
+ llvm::StringRef path(entry.string);
+
+ StructuredData::ObjectSP value =
+ thread_info_dictionary->GetObjectForDotSeparatedPath(path);
+
+ if (value) {
+ if (value->GetType() == StructuredData::Type::eTypeInteger) {
+ const char *token_format = "0x%4.4" PRIx64;
+ if (!entry.printf_format.empty())
+ token_format = entry.printf_format.c_str();
+ s.Printf(token_format, value->GetAsInteger()->GetValue());
+ return true;
+ } else if (value->GetType() == StructuredData::Type::eTypeFloat) {
+ s.Printf("%f", value->GetAsFloat()->GetValue());
+ return true;
+ } else if (value->GetType() == StructuredData::Type::eTypeString) {
+ s.Printf("%s", value->GetAsString()->GetValue().c_str());
+ return true;
+ } else if (value->GetType() == StructuredData::Type::eTypeArray) {
+ if (value->GetAsArray()->GetSize() > 0) {
+ s.Printf("%zu", value->GetAsArray()->GetSize());
+ return true;
+ }
+ } else if (value->GetType() == StructuredData::Type::eTypeDictionary) {
+ s.Printf("%zu",
+ value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
+ return true;
}
- return item;
+ }
+
+ return false;
}
-static char
-ConvertValueObjectStyleToChar(ValueObject::ValueObjectRepresentationStyle style)
-{
- switch (style)
- {
- case ValueObject::eValueObjectRepresentationStyleLanguageSpecific: return '@';
- case ValueObject::eValueObjectRepresentationStyleValue: return 'V';
- case ValueObject::eValueObjectRepresentationStyleLocation: return 'L';
- case ValueObject::eValueObjectRepresentationStyleSummary: return 'S';
- case ValueObject::eValueObjectRepresentationStyleChildrenCount: return '#';
- case ValueObject::eValueObjectRepresentationStyleType: return 'T';
- case ValueObject::eValueObjectRepresentationStyleName: return 'N';
- case ValueObject::eValueObjectRepresentationStyleExpressionPath: return '>';
- }
- return '\0';
-}
-
-static bool
-DumpValue (Stream &s,
- const SymbolContext *sc,
- const ExecutionContext *exe_ctx,
- const FormatEntity::Entry &entry,
- ValueObject *valobj)
-{
- if (valobj == nullptr)
- return false;
+static inline bool IsToken(const char *var_name_begin, const char *var) {
+ return (::strncmp(var_name_begin, var, strlen(var)) == 0);
+}
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
- Format custom_format = eFormatInvalid;
- ValueObject::ValueObjectRepresentationStyle val_obj_display = entry.string.empty() ? ValueObject::eValueObjectRepresentationStyleValue : ValueObject::eValueObjectRepresentationStyleSummary;
-
- bool do_deref_pointer = entry.deref;
- bool is_script = false;
- switch (entry.type)
- {
- case FormatEntity::Entry::Type::ScriptVariable:
- is_script = true;
- break;
+bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s,
+ const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ const Address *addr, ValueObject *valobj,
+ bool function_changed,
+ bool initial_function) {
+ if (!format_str.empty()) {
+ FormatEntity::Entry root;
+ Error error = FormatEntity::Parse(format_str, root);
+ if (error.Success()) {
+ return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
+ function_changed, initial_function);
+ }
+ }
+ return false;
+}
+
+bool FormatEntity::FormatCString(const char *format, Stream &s,
+ const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ const Address *addr, ValueObject *valobj,
+ bool function_changed, bool initial_function) {
+ if (format && format[0]) {
+ FormatEntity::Entry root;
+ llvm::StringRef format_str(format);
+ Error error = FormatEntity::Parse(format_str, root);
+ if (error.Success()) {
+ return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
+ function_changed, initial_function);
+ }
+ }
+ return false;
+}
+
+bool FormatEntity::Format(const Entry &entry, Stream &s,
+ const SymbolContext *sc,
+ const ExecutionContext *exe_ctx, const Address *addr,
+ ValueObject *valobj, bool function_changed,
+ bool initial_function) {
+ switch (entry.type) {
+ case Entry::Type::Invalid:
+ case Entry::Type::ParentNumber: // Only used for
+ // FormatEntity::Entry::Definition encoding
+ case Entry::Type::ParentString: // Only used for
+ // FormatEntity::Entry::Definition encoding
+ case Entry::Type::InsertString: // Only used for
+ // FormatEntity::Entry::Definition encoding
+ return false;
- case FormatEntity::Entry::Type::Variable:
- custom_format = entry.fmt;
- val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
- break;
+ case Entry::Type::Root:
+ for (const auto &child : entry.children) {
+ if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed,
+ initial_function)) {
+ return false; // If any item of root fails, then the formatting fails
+ }
+ }
+ return true; // Only return true if all items succeeded
- case FormatEntity::Entry::Type::ScriptVariableSynthetic:
- is_script = true;
- LLVM_FALLTHROUGH;
- case FormatEntity::Entry::Type::VariableSynthetic:
- custom_format = entry.fmt;
- val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
- if (!valobj->IsSynthetic())
- {
- valobj = valobj->GetSyntheticValue().get();
- if (valobj == nullptr)
- return false;
- }
- break;
+ case Entry::Type::String:
+ s.PutCString(entry.string.c_str());
+ return true;
- default:
- return false;
+ case Entry::Type::Scope: {
+ StreamString scope_stream;
+ bool success = false;
+ for (const auto &child : entry.children) {
+ success = Format(child, scope_stream, sc, exe_ctx, addr, valobj,
+ function_changed, initial_function);
+ if (!success)
+ break;
}
+ // Only if all items in a scope succeed, then do we
+ // print the output into the main stream
+ if (success)
+ s.Write(scope_stream.GetString().data(), scope_stream.GetString().size());
+ }
+ return true; // Scopes always successfully print themselves
+
+ case Entry::Type::Variable:
+ case Entry::Type::VariableSynthetic:
+ case Entry::Type::ScriptVariable:
+ case Entry::Type::ScriptVariableSynthetic:
+ return DumpValue(s, sc, exe_ctx, entry, valobj);
+
+ case Entry::Type::AddressFile:
+ case Entry::Type::AddressLoad:
+ case Entry::Type::AddressLoadOrFile:
+ return (addr != nullptr && addr->IsValid() &&
+ DumpAddress(s, sc, exe_ctx, *addr,
+ entry.type == Entry::Type::AddressLoadOrFile));
+
+ case Entry::Type::ProcessID:
+ if (exe_ctx) {
+ Process *process = exe_ctx->GetProcessPtr();
+ if (process) {
+ const char *format = "%" PRIu64;
+ if (!entry.printf_format.empty())
+ format = entry.printf_format.c_str();
+ s.Printf(format, process->GetID());
+ return true;
+ }
+ }
+ return false;
- if (valobj == nullptr)
- return false;
-
- ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ?
- ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing);
- ValueObject::GetValueForExpressionPathOptions options;
- options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().SetSyntheticChildrenTraversal(ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal::Both);
- ValueObject* target = nullptr;
- const char* var_name_final_if_array_range = nullptr;
- size_t close_bracket_index = llvm::StringRef::npos;
- int64_t index_lower = -1;
- int64_t index_higher = -1;
- bool is_array_range = false;
- const char* first_unparsed;
- bool was_plain_var = false;
- bool was_var_format = false;
- bool was_var_indexed = false;
- ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
- ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain;
-
- if (is_script)
- {
- return RunScriptFormatKeyword (s, sc, exe_ctx, valobj, entry.string.c_str());
- }
-
- llvm::StringRef subpath (entry.string);
- // simplest case ${var}, just print valobj's value
- if (entry.string.empty())
- {
- if (entry.printf_format.empty() && entry.fmt == eFormatDefault && entry.number == ValueObject::eValueObjectRepresentationStyleValue)
- was_plain_var = true;
- else
- was_var_format = true;
- target = valobj;
+ case Entry::Type::ProcessFile:
+ if (exe_ctx) {
+ Process *process = exe_ctx->GetProcessPtr();
+ if (process) {
+ Module *exe_module = process->GetTarget().GetExecutableModulePointer();
+ if (exe_module) {
+ if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
+ return true;
+ }
+ }
}
- else // this is ${var.something} or multiple .something nested
- {
- if (entry.string[0] == '[')
- was_var_indexed = true;
- ScanBracketedRange (subpath,
- close_bracket_index,
- var_name_final_if_array_range,
- index_lower,
- index_higher);
+ return false;
- Error error;
+ case Entry::Type::ScriptProcess:
+ if (exe_ctx) {
+ Process *process = exe_ctx->GetProcessPtr();
+ if (process)
+ return RunScriptFormatKeyword(s, sc, exe_ctx, process,
+ entry.string.c_str());
+ }
+ return false;
- const std::string &expr_path = entry.string;
+ case Entry::Type::ThreadID:
+ if (exe_ctx) {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread) {
+ const char *format = "0x%4.4" PRIx64;
+ if (!entry.printf_format.empty()) {
+ // Watch for the special "tid" format...
+ if (entry.printf_format == "tid") {
+ // TODO(zturner): Rather than hardcoding this to be platform
+ // specific, it should be controlled by a
+ // setting and the default value of the setting can be different
+ // depending on the platform.
+ Target &target = thread->GetProcess()->GetTarget();
+ ArchSpec arch(target.GetArchitecture());
+ llvm::Triple::OSType ostype = arch.IsValid()
+ ? arch.GetTriple().getOS()
+ : llvm::Triple::UnknownOS;
+ if ((ostype == llvm::Triple::FreeBSD) ||
+ (ostype == llvm::Triple::Linux)) {
+ format = "%" PRIu64;
+ }
+ } else {
+ format = entry.printf_format.c_str();
+ }
+ }
+ s.Printf(format, thread->GetID());
+ return true;
+ }
+ }
+ return false;
- if (log)
- log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str());
+ case Entry::Type::ThreadProtocolID:
+ if (exe_ctx) {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread) {
+ const char *format = "0x%4.4" PRIx64;
+ if (!entry.printf_format.empty())
+ format = entry.printf_format.c_str();
+ s.Printf(format, thread->GetProtocolID());
+ return true;
+ }
+ }
+ return false;
- target = valobj->GetValueForExpressionPath(expr_path.c_str(),
- &first_unparsed,
- &reason_to_stop,
- &final_value_type,
- options,
- &what_next).get();
+ case Entry::Type::ThreadIndexID:
+ if (exe_ctx) {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread) {
+ const char *format = "%" PRIu32;
+ if (!entry.printf_format.empty())
+ format = entry.printf_format.c_str();
+ s.Printf(format, thread->GetIndexID());
+ return true;
+ }
+ }
+ return false;
- if (!target)
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d,"
- " final_value_type %d",
- first_unparsed, reason_to_stop, final_value_type);
- return false;
- }
- else
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d,"
- " final_value_type %d",
- first_unparsed, reason_to_stop, final_value_type);
- target = target->GetQualifiedRepresentationIfAvailable(target->GetDynamicValueType(), true).get();
+ case Entry::Type::ThreadName:
+ if (exe_ctx) {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread) {
+ const char *cstr = thread->GetName();
+ if (cstr && cstr[0]) {
+ s.PutCString(cstr);
+ return true;
}
+ }
}
+ return false;
- is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange ||
- final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange);
-
- do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference);
-
- if (do_deref_pointer && !is_array_range)
- {
- // I have not deref-ed yet, let's do it
- // this happens when we are not going through GetValueForVariableExpressionPath
- // to get to the target ValueObject
- Error error;
- target = target->Dereference(error).get();
- if (error.Fail())
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \
- return false;
+ case Entry::Type::ThreadQueue:
+ if (exe_ctx) {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread) {
+ const char *cstr = thread->GetQueueName();
+ if (cstr && cstr[0]) {
+ s.PutCString(cstr);
+ return true;
}
- do_deref_pointer = false;
+ }
}
+ return false;
- if (!target)
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] could not calculate target for prompt expression");
- return false;
+ case Entry::Type::ThreadStopReason:
+ if (exe_ctx) {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread) {
+ StopInfoSP stop_info_sp = thread->GetStopInfo();
+ if (stop_info_sp && stop_info_sp->IsValid()) {
+ const char *cstr = stop_info_sp->GetDescription();
+ if (cstr && cstr[0]) {
+ s.PutCString(cstr);
+ return true;
+ }
+ }
+ }
}
+ return false;
- // we do not want to use the summary for a bitfield of type T:n
- // if we were originally dealing with just a T - that would get
- // us into an endless recursion
- if (target->IsBitfield() && was_var_indexed)
- {
- // TODO: check for a (T:n)-specific summary - we should still obey that
- StreamString bitfield_name;
- bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize());
- lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false));
- if (val_obj_display == ValueObject::eValueObjectRepresentationStyleSummary && !DataVisualization::GetSummaryForType(type_sp))
- val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
- }
-
- // TODO use flags for these
- const uint32_t type_info_flags = target->GetCompilerType().GetTypeInfo(nullptr);
- bool is_array = (type_info_flags & eTypeIsArray) != 0;
- bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
- bool is_aggregate = target->GetCompilerType().IsAggregateType();
-
- if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions
- {
- StreamString str_temp;
- if (log)
- log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range");
-
- if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format))
- {
- // try to use the special cases
- bool success = target->DumpPrintableRepresentation(str_temp,
- val_obj_display,
- custom_format);
- if (log)
- log->Printf("[Debugger::FormatPrompt] special cases did%s match", success ? "" : "n't");
-
- // should not happen
- if (success)
- s << str_temp.GetData();
+ case Entry::Type::ThreadReturnValue:
+ if (exe_ctx) {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread) {
+ StopInfoSP stop_info_sp = thread->GetStopInfo();
+ if (stop_info_sp && stop_info_sp->IsValid()) {
+ ValueObjectSP return_valobj_sp =
+ StopInfo::GetReturnValueObject(stop_info_sp);
+ if (return_valobj_sp) {
+ return_valobj_sp->Dump(s);
return true;
+ }
}
- else
- {
- if (was_plain_var) // if ${var}
- {
- s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
- }
- else if (is_pointer) // if pointer, value is the address stored
- {
- target->DumpPrintableRepresentation (s,
- val_obj_display,
- custom_format,
- ValueObject::ePrintableRepresentationSpecialCasesDisable);
- }
+ }
+ }
+ return false;
+
+ case Entry::Type::ThreadCompletedExpression:
+ if (exe_ctx) {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread) {
+ StopInfoSP stop_info_sp = thread->GetStopInfo();
+ if (stop_info_sp && stop_info_sp->IsValid()) {
+ ExpressionVariableSP expression_var_sp =
+ StopInfo::GetExpressionVariable(stop_info_sp);
+ if (expression_var_sp && expression_var_sp->GetValueObject()) {
+ expression_var_sp->GetValueObject()->Dump(s);
return true;
+ }
}
+ }
}
+ return false;
- // if directly trying to print ${var}, and this is an aggregate, display a nice
- // type @ location message
- if (is_aggregate && was_plain_var)
- {
- s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
- return true;
+ case Entry::Type::ScriptThread:
+ if (exe_ctx) {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread)
+ return RunScriptFormatKeyword(s, sc, exe_ctx, thread,
+ entry.string.c_str());
}
+ return false;
- // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it
- if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue)))
- {
- s << "<invalid use of aggregate type>";
- return true;
+ case Entry::Type::ThreadInfo:
+ if (exe_ctx) {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread) {
+ StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
+ if (object_sp &&
+ object_sp->GetType() == StructuredData::Type::eTypeDictionary) {
+ if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s))
+ return true;
+ }
+ }
}
+ return false;
- if (!is_array_range)
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output");
- return target->DumpPrintableRepresentation(s,val_obj_display, custom_format);
- }
- else
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] checking if I can handle as array");
- if (!is_array && !is_pointer)
- return false;
- if (log)
- log->Printf("[Debugger::FormatPrompt] handle as array");
- StreamString special_directions_stream;
- llvm::StringRef special_directions;
- if (close_bracket_index != llvm::StringRef::npos && subpath.size() > close_bracket_index)
- {
- ConstString additional_data (subpath.drop_front(close_bracket_index+1));
- special_directions_stream.Printf("${%svar%s",
- do_deref_pointer ? "*" : "",
- additional_data.GetCString());
-
- if (entry.fmt != eFormatDefault)
- {
- const char format_char = FormatManager::GetFormatAsFormatChar(entry.fmt);
- if (format_char != '\0')
- special_directions_stream.Printf("%%%c", format_char);
- else
- {
- const char *format_cstr = FormatManager::GetFormatAsCString(entry.fmt);
- special_directions_stream.Printf("%%%s", format_cstr);
- }
- }
- else if (entry.number != 0)
- {
- const char style_char = ConvertValueObjectStyleToChar ((ValueObject::ValueObjectRepresentationStyle)entry.number);
- if (style_char)
- special_directions_stream.Printf("%%%c", style_char);
- }
- special_directions_stream.PutChar('}');
- special_directions = llvm::StringRef(special_directions_stream.GetString());
+ case Entry::Type::TargetArch:
+ if (exe_ctx) {
+ Target *target = exe_ctx->GetTargetPtr();
+ if (target) {
+ const ArchSpec &arch = target->GetArchitecture();
+ if (arch.IsValid()) {
+ s.PutCString(arch.GetArchitectureName());
+ return true;
}
+ }
+ }
+ return false;
- // let us display items index_lower thru index_higher of this array
- s.PutChar('[');
-
- if (index_higher < 0)
- index_higher = valobj->GetNumChildren() - 1;
-
- uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
-
- bool success = true;
- for (int64_t index = index_lower;index<=index_higher; ++index)
- {
- ValueObject* item = ExpandIndexedExpression (target,
- index,
- exe_ctx->GetFramePtr(),
- false).get();
-
- if (!item)
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index);
- }
- else
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions.data() ? special_directions.data() : "");
- }
-
- if (special_directions.empty())
- {
- success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format);
- }
- else
- {
- success &= FormatEntity::FormatStringRef(special_directions, s, sc, exe_ctx, nullptr, item, false, false);
- }
-
- if (--max_num_children == 0)
- {
- s.PutCString(", ...");
- break;
- }
+ case Entry::Type::ScriptTarget:
+ if (exe_ctx) {
+ Target *target = exe_ctx->GetTargetPtr();
+ if (target)
+ return RunScriptFormatKeyword(s, sc, exe_ctx, target,
+ entry.string.c_str());
+ }
+ return false;
- if (index < index_higher)
- s.PutChar(',');
- }
- s.PutChar(']');
- return success;
+ case Entry::Type::ModuleFile:
+ if (sc) {
+ Module *module = sc->module_sp.get();
+ if (module) {
+ if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
+ return true;
+ }
}
-}
+ return false;
-static bool
-DumpRegister (Stream &s,
- StackFrame *frame,
- const char *reg_name,
- Format format)
-{
- if (frame)
- {
- RegisterContext *reg_ctx = frame->GetRegisterContext().get();
+ case Entry::Type::File:
+ if (sc) {
+ CompileUnit *cu = sc->comp_unit;
+ if (cu) {
+ // CompileUnit is a FileSpec
+ if (DumpFile(s, *cu, (FileKind)entry.number))
+ return true;
+ }
+ }
+ return false;
- if (reg_ctx)
- {
- const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
- if (reg_info)
- {
- RegisterValue reg_value;
- if (reg_ctx->ReadRegister (reg_info, reg_value))
- {
- reg_value.Dump(&s, reg_info, false, false, format);
- return true;
- }
- }
+ case Entry::Type::Lang:
+ if (sc) {
+ CompileUnit *cu = sc->comp_unit;
+ if (cu) {
+ const char *lang_name =
+ Language::GetNameForLanguageType(cu->GetLanguage());
+ if (lang_name) {
+ s.PutCString(lang_name);
+ return true;
}
+ }
}
return false;
-}
-static bool
-FormatThreadExtendedInfoRecurse(const FormatEntity::Entry &entry,
- const StructuredData::ObjectSP &thread_info_dictionary,
- const SymbolContext *sc,
- const ExecutionContext *exe_ctx,
- Stream &s)
-{
- llvm::StringRef path(entry.string);
-
- StructuredData::ObjectSP value = thread_info_dictionary->GetObjectForDotSeparatedPath (path);
+ case Entry::Type::FrameIndex:
+ if (exe_ctx) {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame) {
+ const char *format = "%" PRIu32;
+ if (!entry.printf_format.empty())
+ format = entry.printf_format.c_str();
+ s.Printf(format, frame->GetFrameIndex());
+ return true;
+ }
+ }
+ return false;
- if (value)
- {
- if (value->GetType() == StructuredData::Type::eTypeInteger)
- {
- const char *token_format = "0x%4.4" PRIx64;
- if (!entry.printf_format.empty())
- token_format = entry.printf_format.c_str();
- s.Printf(token_format, value->GetAsInteger()->GetValue());
- return true;
- }
- else if (value->GetType() == StructuredData::Type::eTypeFloat)
- {
- s.Printf ("%f", value->GetAsFloat()->GetValue());
- return true;
- }
- else if (value->GetType() == StructuredData::Type::eTypeString)
- {
- s.Printf("%s", value->GetAsString()->GetValue().c_str());
- return true;
- }
- else if (value->GetType() == StructuredData::Type::eTypeArray)
- {
- if (value->GetAsArray()->GetSize() > 0)
- {
- s.Printf ("%zu", value->GetAsArray()->GetSize());
- return true;
- }
- }
- else if (value->GetType() == StructuredData::Type::eTypeDictionary)
- {
- s.Printf ("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
+ case Entry::Type::FrameRegisterPC:
+ if (exe_ctx) {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame) {
+ const Address &pc_addr = frame->GetFrameCodeAddress();
+ if (pc_addr.IsValid()) {
+ if (DumpAddress(s, sc, exe_ctx, pc_addr, false))
return true;
}
+ }
}
-
return false;
-}
-static inline bool
-IsToken(const char *var_name_begin, const char *var)
-{
- return (::strncmp (var_name_begin, var, strlen(var)) == 0);
-}
-
-bool
-FormatEntity::FormatStringRef (const llvm::StringRef &format_str,
- Stream &s,
- const SymbolContext *sc,
- const ExecutionContext *exe_ctx,
- const Address *addr,
- ValueObject* valobj,
- bool function_changed,
- bool initial_function)
-{
- if (!format_str.empty())
- {
- FormatEntity::Entry root;
- Error error = FormatEntity::Parse(format_str, root);
- if (error.Success())
- {
- return FormatEntity::Format (root,
- s,
- sc,
- exe_ctx,
- addr,
- valobj,
- function_changed,
- initial_function);
- }
+ case Entry::Type::FrameRegisterSP:
+ if (exe_ctx) {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame) {
+ if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP,
+ (lldb::Format)entry.number))
+ return true;
+ }
}
return false;
-}
-bool
-FormatEntity::FormatCString (const char *format,
- Stream &s,
- const SymbolContext *sc,
- const ExecutionContext *exe_ctx,
- const Address *addr,
- ValueObject* valobj,
- bool function_changed,
- bool initial_function)
-{
- if (format && format[0])
- {
- FormatEntity::Entry root;
- llvm::StringRef format_str(format);
- Error error = FormatEntity::Parse(format_str, root);
- if (error.Success())
- {
- return FormatEntity::Format (root,
- s,
- sc,
- exe_ctx,
- addr,
- valobj,
- function_changed,
- initial_function);
- }
+ case Entry::Type::FrameRegisterFP:
+ if (exe_ctx) {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame) {
+ if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP,
+ (lldb::Format)entry.number))
+ return true;
+ }
}
return false;
-}
-
-bool
-FormatEntity::Format (const Entry &entry,
- Stream &s,
- const SymbolContext *sc,
- const ExecutionContext *exe_ctx,
- const Address *addr,
- ValueObject* valobj,
- bool function_changed,
- bool initial_function)
-{
- switch (entry.type)
- {
- case Entry::Type::Invalid:
- case Entry::Type::ParentNumber: // Only used for FormatEntity::Entry::Definition encoding
- case Entry::Type::ParentString: // Only used for FormatEntity::Entry::Definition encoding
- case Entry::Type::InsertString: // Only used for FormatEntity::Entry::Definition encoding
- return false;
-
- case Entry::Type::Root:
- for (const auto &child : entry.children)
- {
- if (!Format(child,
- s,
- sc,
- exe_ctx,
- addr,
- valobj,
- function_changed,
- initial_function))
- {
- return false; // If any item of root fails, then the formatting fails
- }
- }
- return true; // Only return true if all items succeeded
-
- case Entry::Type::String:
- s.PutCString(entry.string.c_str());
- return true;
-
- case Entry::Type::Scope:
- {
- StreamString scope_stream;
- bool success = false;
- for (const auto &child : entry.children)
- {
- success = Format (child, scope_stream, sc, exe_ctx, addr, valobj, function_changed, initial_function);
- if (!success)
- break;
- }
- // Only if all items in a scope succeed, then do we
- // print the output into the main stream
- if (success)
- s.Write(scope_stream.GetString().data(), scope_stream.GetString().size());
- }
- return true; // Scopes always successfully print themselves
-
- case Entry::Type::Variable:
- case Entry::Type::VariableSynthetic:
- case Entry::Type::ScriptVariable:
- case Entry::Type::ScriptVariableSynthetic:
- return DumpValue(s, sc, exe_ctx, entry, valobj);
-
- case Entry::Type::AddressFile:
- case Entry::Type::AddressLoad:
- case Entry::Type::AddressLoadOrFile:
- return (addr != nullptr && addr->IsValid() &&
- DumpAddress(s, sc, exe_ctx, *addr, entry.type == Entry::Type::AddressLoadOrFile));
-
- case Entry::Type::ProcessID:
- if (exe_ctx)
- {
- Process *process = exe_ctx->GetProcessPtr();
- if (process)
- {
- const char *format = "%" PRIu64;
- if (!entry.printf_format.empty())
- format = entry.printf_format.c_str();
- s.Printf(format, process->GetID());
- return true;
- }
- }
- return false;
-
- case Entry::Type::ProcessFile:
- if (exe_ctx)
- {
- Process *process = exe_ctx->GetProcessPtr();
- if (process)
- {
- Module *exe_module = process->GetTarget().GetExecutableModulePointer();
- if (exe_module)
- {
- if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
- return true;
- }
- }
- }
- return false;
-
- case Entry::Type::ScriptProcess:
- if (exe_ctx)
- {
- Process *process = exe_ctx->GetProcessPtr();
- if (process)
- return RunScriptFormatKeyword (s, sc, exe_ctx, process, entry.string.c_str());
- }
- return false;
-
- case Entry::Type::ThreadID:
- if (exe_ctx)
- {
- Thread *thread = exe_ctx->GetThreadPtr();
- if (thread)
- {
- const char *format = "0x%4.4" PRIx64;
- if (!entry.printf_format.empty())
- {
- // Watch for the special "tid" format...
- if (entry.printf_format == "tid")
- {
- // TODO(zturner): Rather than hardcoding this to be platform specific, it should be controlled by a
- // setting and the default value of the setting can be different depending on the platform.
- Target &target = thread->GetProcess()->GetTarget();
- ArchSpec arch (target.GetArchitecture ());
- llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS;
- if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux))
- {
- format = "%" PRIu64;
- }
- }
- else
- {
- format = entry.printf_format.c_str();
- }
- }
- s.Printf(format, thread->GetID());
- return true;
- }
- }
- return false;
-
- case Entry::Type::ThreadProtocolID:
- if (exe_ctx)
- {
- Thread *thread = exe_ctx->GetThreadPtr();
- if (thread)
- {
- const char *format = "0x%4.4" PRIx64;
- if (!entry.printf_format.empty())
- format = entry.printf_format.c_str();
- s.Printf(format, thread->GetProtocolID());
- return true;
- }
- }
- return false;
-
- case Entry::Type::ThreadIndexID:
- if (exe_ctx)
- {
- Thread *thread = exe_ctx->GetThreadPtr();
- if (thread)
- {
- const char *format = "%" PRIu32;
- if (!entry.printf_format.empty())
- format = entry.printf_format.c_str();
- s.Printf(format, thread->GetIndexID());
- return true;
- }
- }
- return false;
-
- case Entry::Type::ThreadName:
- if (exe_ctx)
- {
- Thread *thread = exe_ctx->GetThreadPtr();
- if (thread)
- {
- const char *cstr = thread->GetName();
- if (cstr && cstr[0])
- {
- s.PutCString(cstr);
- return true;
- }
- }
- }
- return false;
-
- case Entry::Type::ThreadQueue:
- if (exe_ctx)
- {
- Thread *thread = exe_ctx->GetThreadPtr();
- if (thread)
- {
- const char *cstr = thread->GetQueueName();
- if (cstr && cstr[0])
- {
- s.PutCString(cstr);
- return true;
- }
- }
- }
- return false;
-
- case Entry::Type::ThreadStopReason:
- if (exe_ctx)
- {
- Thread *thread = exe_ctx->GetThreadPtr();
- if (thread)
- {
- StopInfoSP stop_info_sp = thread->GetStopInfo ();
- if (stop_info_sp && stop_info_sp->IsValid())
- {
- const char *cstr = stop_info_sp->GetDescription();
- if (cstr && cstr[0])
- {
- s.PutCString(cstr);
- return true;
- }
- }
- }
- }
- return false;
-
- case Entry::Type::ThreadReturnValue:
- if (exe_ctx)
- {
- Thread *thread = exe_ctx->GetThreadPtr();
- if (thread)
- {
- StopInfoSP stop_info_sp = thread->GetStopInfo ();
- if (stop_info_sp && stop_info_sp->IsValid())
- {
- ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
- if (return_valobj_sp)
- {
- return_valobj_sp->Dump(s);
- return true;
- }
- }
- }
- }
- return false;
-
- case Entry::Type::ThreadCompletedExpression:
- if (exe_ctx)
- {
- Thread *thread = exe_ctx->GetThreadPtr();
- if (thread)
- {
- StopInfoSP stop_info_sp = thread->GetStopInfo ();
- if (stop_info_sp && stop_info_sp->IsValid())
- {
- ExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp);
- if (expression_var_sp && expression_var_sp->GetValueObject())
- {
- expression_var_sp->GetValueObject()->Dump(s);
- return true;
- }
- }
- }
- }
- return false;
- case Entry::Type::ScriptThread:
- if (exe_ctx)
- {
- Thread *thread = exe_ctx->GetThreadPtr();
- if (thread)
- return RunScriptFormatKeyword (s, sc, exe_ctx, thread, entry.string.c_str());
- }
- return false;
-
- case Entry::Type::ThreadInfo:
- if (exe_ctx)
- {
- Thread *thread = exe_ctx->GetThreadPtr();
- if (thread)
- {
- StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
- if (object_sp && object_sp->GetType() == StructuredData::Type::eTypeDictionary)
- {
- if (FormatThreadExtendedInfoRecurse (entry, object_sp, sc, exe_ctx, s))
- return true;
- }
- }
- }
- return false;
-
- case Entry::Type::TargetArch:
- if (exe_ctx)
- {
- Target *target = exe_ctx->GetTargetPtr();
- if (target)
- {
- const ArchSpec &arch = target->GetArchitecture ();
- if (arch.IsValid())
- {
- s.PutCString (arch.GetArchitectureName());
- return true;
- }
- }
- }
- return false;
-
- case Entry::Type::ScriptTarget:
- if (exe_ctx)
- {
- Target *target = exe_ctx->GetTargetPtr();
- if (target)
- return RunScriptFormatKeyword (s, sc, exe_ctx, target, entry.string.c_str());
- }
- return false;
-
- case Entry::Type::ModuleFile:
- if (sc)
- {
- Module *module = sc->module_sp.get();
- if (module)
- {
- if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
- return true;
- }
- }
- return false;
-
- case Entry::Type::File:
- if (sc)
- {
- CompileUnit *cu = sc->comp_unit;
- if (cu)
- {
- // CompileUnit is a FileSpec
- if (DumpFile(s, *cu, (FileKind)entry.number))
- return true;
- }
- }
- return false;
-
- case Entry::Type::Lang:
- if (sc)
- {
- CompileUnit *cu = sc->comp_unit;
- if (cu)
- {
- const char *lang_name = Language::GetNameForLanguageType(cu->GetLanguage());
- if (lang_name)
- {
- s.PutCString(lang_name);
- return true;
- }
- }
- }
- return false;
-
- case Entry::Type::FrameIndex:
- if (exe_ctx)
- {
- StackFrame *frame = exe_ctx->GetFramePtr();
- if (frame)
- {
- const char *format = "%" PRIu32;
- if (!entry.printf_format.empty())
- format = entry.printf_format.c_str();
- s.Printf(format, frame->GetFrameIndex());
- return true;
- }
- }
- return false;
-
- case Entry::Type::FrameRegisterPC:
- if (exe_ctx)
- {
- StackFrame *frame = exe_ctx->GetFramePtr();
- if (frame)
- {
- const Address &pc_addr = frame->GetFrameCodeAddress();
- if (pc_addr.IsValid())
- {
- if (DumpAddress(s, sc, exe_ctx, pc_addr, false))
- return true;
- }
- }
- }
- return false;
-
- case Entry::Type::FrameRegisterSP:
- if (exe_ctx)
- {
- StackFrame *frame = exe_ctx->GetFramePtr();
- if (frame)
- {
- if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, (lldb::Format)entry.number))
- return true;
- }
- }
- return false;
-
- case Entry::Type::FrameRegisterFP:
- if (exe_ctx)
- {
- StackFrame *frame = exe_ctx->GetFramePtr();
- if (frame)
- {
- if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, (lldb::Format)entry.number))
- return true;
- }
- }
- return false;
-
- case Entry::Type::FrameRegisterFlags:
- if (exe_ctx)
- {
- StackFrame *frame = exe_ctx->GetFramePtr();
- if (frame)
- {
- if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number))
- return true;
- }
- }
- return false;
+ case Entry::Type::FrameRegisterFlags:
+ if (exe_ctx) {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame) {
+ if (DumpRegister(s, frame, eRegisterKindGeneric,
+ LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number))
+ return true;
+ }
+ }
+ return false;
- case Entry::Type::FrameRegisterByName:
- if (exe_ctx)
- {
- StackFrame *frame = exe_ctx->GetFramePtr();
- if (frame)
- {
- if (DumpRegister (s, frame, entry.string.c_str(), (lldb::Format)entry.number))
- return true;
- }
- }
- return false;
+ case Entry::Type::FrameRegisterByName:
+ if (exe_ctx) {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame) {
+ if (DumpRegister(s, frame, entry.string.c_str(),
+ (lldb::Format)entry.number))
+ return true;
+ }
+ }
+ return false;
- case Entry::Type::ScriptFrame:
- if (exe_ctx)
- {
- StackFrame *frame = exe_ctx->GetFramePtr();
- if (frame)
- return RunScriptFormatKeyword (s, sc, exe_ctx, frame, entry.string.c_str());
- }
- return false;
+ case Entry::Type::ScriptFrame:
+ if (exe_ctx) {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame)
+ return RunScriptFormatKeyword(s, sc, exe_ctx, frame,
+ entry.string.c_str());
+ }
+ return false;
- case Entry::Type::FunctionID:
- if (sc)
- {
- if (sc->function)
- {
- s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
- return true;
- }
- else if (sc->symbol)
- {
- s.Printf("symbol[%u]", sc->symbol->GetID());
- return true;
- }
- }
- return false;
+ case Entry::Type::FunctionID:
+ if (sc) {
+ if (sc->function) {
+ s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
+ return true;
+ } else if (sc->symbol) {
+ s.Printf("symbol[%u]", sc->symbol->GetID());
+ return true;
+ }
+ }
+ return false;
- case Entry::Type::FunctionDidChange:
- return function_changed;
+ case Entry::Type::FunctionDidChange:
+ return function_changed;
- case Entry::Type::FunctionInitialFunction:
- return initial_function;
+ case Entry::Type::FunctionInitialFunction:
+ return initial_function;
- case Entry::Type::FunctionName:
- {
- Language *language_plugin = nullptr;
- bool language_plugin_handled = false;
- StreamString ss;
- if (sc->function)
- language_plugin = Language::FindPlugin(sc->function->GetLanguage());
- else if (sc->symbol)
- language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
- if (language_plugin)
- {
- language_plugin_handled = language_plugin->GetFunctionDisplayName(sc,
- exe_ctx,
- Language::FunctionNameRepresentation::eName,
- ss);
- }
- if (language_plugin_handled)
- {
- s.PutCString(ss.GetData());
- return true;
- }
- else
- {
- const char *name = nullptr;
- if (sc->function)
- name = sc->function->GetName().AsCString(nullptr);
- else if (sc->symbol)
- name = sc->symbol->GetName().AsCString(nullptr);
- if (name)
- {
- s.PutCString(name);
-
- if (sc->block)
- {
- Block *inline_block = sc->block->GetContainingInlinedBlock ();
- if (inline_block)
- {
- const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo();
- if (inline_info)
- {
- s.PutCString(" [inlined] ");
- inline_info->GetName(sc->function->GetLanguage()).Dump(&s);
- }
- }
- }
- return true;
- }
- }
+ case Entry::Type::FunctionName: {
+ Language *language_plugin = nullptr;
+ bool language_plugin_handled = false;
+ StreamString ss;
+ if (sc->function)
+ language_plugin = Language::FindPlugin(sc->function->GetLanguage());
+ else if (sc->symbol)
+ language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
+ if (language_plugin) {
+ language_plugin_handled = language_plugin->GetFunctionDisplayName(
+ sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss);
+ }
+ if (language_plugin_handled) {
+ s.PutCString(ss.GetData());
+ return true;
+ } else {
+ const char *name = nullptr;
+ if (sc->function)
+ name = sc->function->GetName().AsCString(nullptr);
+ else if (sc->symbol)
+ name = sc->symbol->GetName().AsCString(nullptr);
+ if (name) {
+ s.PutCString(name);
+
+ if (sc->block) {
+ Block *inline_block = sc->block->GetContainingInlinedBlock();
+ if (inline_block) {
+ const InlineFunctionInfo *inline_info =
+ sc->block->GetInlinedFunctionInfo();
+ if (inline_info) {
+ s.PutCString(" [inlined] ");
+ inline_info->GetName(sc->function->GetLanguage()).Dump(&s);
}
- return false;
+ }
+ }
+ return true;
+ }
+ }
+ }
+ return false;
- case Entry::Type::FunctionNameNoArgs:
- {
- Language *language_plugin = nullptr;
- bool language_plugin_handled = false;
- StreamString ss;
- if (sc->function)
- language_plugin = Language::FindPlugin(sc->function->GetLanguage());
- else if (sc->symbol)
- language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
- if (language_plugin)
- {
- language_plugin_handled = language_plugin->GetFunctionDisplayName(sc,
- exe_ctx,
- Language::FunctionNameRepresentation::eNameWithNoArgs,
- ss);
- }
- if (language_plugin_handled)
- {
- s.PutCString(ss.GetData());
- return true;
- }
- else
- {
- ConstString name;
- if (sc->function)
- name = sc->function->GetNameNoArguments();
- else if (sc->symbol)
- name = sc->symbol->GetNameNoArguments();
- if (name)
- {
- s.PutCString(name.GetCString());
- return true;
- }
- }
- }
- return false;
+ case Entry::Type::FunctionNameNoArgs: {
+ Language *language_plugin = nullptr;
+ bool language_plugin_handled = false;
+ StreamString ss;
+ if (sc->function)
+ language_plugin = Language::FindPlugin(sc->function->GetLanguage());
+ else if (sc->symbol)
+ language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
+ if (language_plugin) {
+ language_plugin_handled = language_plugin->GetFunctionDisplayName(
+ sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs,
+ ss);
+ }
+ if (language_plugin_handled) {
+ s.PutCString(ss.GetData());
+ return true;
+ } else {
+ ConstString name;
+ if (sc->function)
+ name = sc->function->GetNameNoArguments();
+ else if (sc->symbol)
+ name = sc->symbol->GetNameNoArguments();
+ if (name) {
+ s.PutCString(name.GetCString());
+ return true;
+ }
+ }
+ }
+ return false;
- case Entry::Type::FunctionNameWithArgs:
- {
- Language *language_plugin = nullptr;
- bool language_plugin_handled = false;
- StreamString ss;
- if (sc->function)
- language_plugin = Language::FindPlugin(sc->function->GetLanguage());
- else if (sc->symbol)
- language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
- if (language_plugin)
- {
- language_plugin_handled = language_plugin->GetFunctionDisplayName(sc,
- exe_ctx,
- Language::FunctionNameRepresentation::eNameWithArgs,
- ss);
- }
- if (language_plugin_handled)
- {
- s.PutCString(ss.GetData());
- return true;
- }
+ case Entry::Type::FunctionNameWithArgs: {
+ Language *language_plugin = nullptr;
+ bool language_plugin_handled = false;
+ StreamString ss;
+ if (sc->function)
+ language_plugin = Language::FindPlugin(sc->function->GetLanguage());
+ else if (sc->symbol)
+ language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
+ if (language_plugin) {
+ language_plugin_handled = language_plugin->GetFunctionDisplayName(
+ sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss);
+ }
+ if (language_plugin_handled) {
+ s.PutCString(ss.GetData());
+ return true;
+ } else {
+ // Print the function name with arguments in it
+ if (sc->function) {
+ ExecutionContextScope *exe_scope =
+ exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
+ const char *cstr = sc->function->GetName().AsCString(nullptr);
+ if (cstr) {
+ const InlineFunctionInfo *inline_info = nullptr;
+ VariableListSP variable_list_sp;
+ bool get_function_vars = true;
+ if (sc->block) {
+ Block *inline_block = sc->block->GetContainingInlinedBlock();
+
+ if (inline_block) {
+ get_function_vars = false;
+ inline_info = sc->block->GetInlinedFunctionInfo();
+ if (inline_info)
+ variable_list_sp = inline_block->GetBlockVariableList(true);
+ }
+ }
+
+ if (get_function_vars) {
+ variable_list_sp =
+ sc->function->GetBlock(true).GetBlockVariableList(true);
+ }
+
+ if (inline_info) {
+ s.PutCString(cstr);
+ s.PutCString(" [inlined] ");
+ cstr =
+ inline_info->GetName(sc->function->GetLanguage()).GetCString();
+ }
+
+ VariableList args;
+ if (variable_list_sp)
+ variable_list_sp->AppendVariablesWithScope(
+ eValueTypeVariableArgument, args);
+ if (args.GetSize() > 0) {
+ const char *open_paren = strchr(cstr, '(');
+ const char *close_paren = nullptr;
+ const char *generic = strchr(cstr, '<');
+ // if before the arguments list begins there is a template sign
+ // then scan to the end of the generic args before you try to find
+ // the arguments list
+ if (generic && open_paren && generic < open_paren) {
+ int generic_depth = 1;
+ ++generic;
+ for (; *generic && generic_depth > 0; generic++) {
+ if (*generic == '<')
+ generic_depth++;
+ if (*generic == '>')
+ generic_depth--;
+ }
+ if (*generic)
+ open_paren = strchr(generic, '(');
+ else
+ open_paren = nullptr;
+ }
+ if (open_paren) {
+ if (IsToken(open_paren, "(anonymous namespace)")) {
+ open_paren =
+ strchr(open_paren + strlen("(anonymous namespace)"), '(');
+ if (open_paren)
+ close_paren = strchr(open_paren, ')');
+ } else
+ close_paren = strchr(open_paren, ')');
+ }
+
+ if (open_paren)
+ s.Write(cstr, open_paren - cstr + 1);
+ else {
+ s.PutCString(cstr);
+ s.PutChar('(');
+ }
+ const size_t num_args = args.GetSize();
+ for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
+ std::string buffer;
+
+ VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
+ ValueObjectSP var_value_sp(
+ ValueObjectVariable::Create(exe_scope, var_sp));
+ StreamString ss;
+ const char *var_representation = nullptr;
+ const char *var_name = var_value_sp->GetName().GetCString();
+ if (var_value_sp->GetCompilerType().IsValid()) {
+ if (var_value_sp && exe_scope->CalculateTarget())
+ var_value_sp =
+ var_value_sp->GetQualifiedRepresentationIfAvailable(
+ exe_scope->CalculateTarget()
+ ->TargetProperties::GetPreferDynamicValue(),
+ exe_scope->CalculateTarget()
+ ->TargetProperties::GetEnableSyntheticValue());
+ if (var_value_sp->GetCompilerType().IsAggregateType() &&
+ DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) {
+ static StringSummaryFormat format(
+ TypeSummaryImpl::Flags()
+ .SetHideItemNames(false)
+ .SetShowMembersOneLiner(true),
+ "");
+ format.FormatObject(var_value_sp.get(), buffer,
+ TypeSummaryOptions());
+ var_representation = buffer.c_str();
+ } else
+ var_value_sp->DumpPrintableRepresentation(
+ ss, ValueObject::ValueObjectRepresentationStyle::
+ eValueObjectRepresentationStyleSummary,
+ eFormatDefault,
+ ValueObject::PrintableRepresentationSpecialCases::
+ ePrintableRepresentationSpecialCasesAllow,
+ false);
+ }
+
+ if (ss.GetData() && ss.GetSize())
+ var_representation = ss.GetData();
+ if (arg_idx > 0)
+ s.PutCString(", ");
+ if (var_value_sp->GetError().Success()) {
+ if (var_representation)
+ s.Printf("%s=%s", var_name, var_representation);
else
- {
- // Print the function name with arguments in it
- if (sc->function)
- {
- ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
- const char *cstr = sc->function->GetName().AsCString(nullptr);
- if (cstr)
- {
- const InlineFunctionInfo *inline_info = nullptr;
- VariableListSP variable_list_sp;
- bool get_function_vars = true;
- if (sc->block)
- {
- Block *inline_block = sc->block->GetContainingInlinedBlock ();
-
- if (inline_block)
- {
- get_function_vars = false;
- inline_info = sc->block->GetInlinedFunctionInfo();
- if (inline_info)
- variable_list_sp = inline_block->GetBlockVariableList (true);
- }
- }
-
- if (get_function_vars)
- {
- variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true);
- }
-
- if (inline_info)
- {
- s.PutCString (cstr);
- s.PutCString (" [inlined] ");
- cstr = inline_info->GetName(sc->function->GetLanguage()).GetCString();
- }
-
- VariableList args;
- if (variable_list_sp)
- variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args);
- if (args.GetSize() > 0)
- {
- const char *open_paren = strchr (cstr, '(');
- const char *close_paren = nullptr;
- const char *generic = strchr(cstr, '<');
- // if before the arguments list begins there is a template sign
- // then scan to the end of the generic args before you try to find
- // the arguments list
- if (generic && open_paren && generic < open_paren)
- {
- int generic_depth = 1;
- ++generic;
- for (;
- *generic && generic_depth > 0;
- generic++)
- {
- if (*generic == '<')
- generic_depth++;
- if (*generic == '>')
- generic_depth--;
- }
- if (*generic)
- open_paren = strchr(generic, '(');
- else
- open_paren = nullptr;
- }
- if (open_paren)
- {
- if (IsToken (open_paren, "(anonymous namespace)"))
- {
- open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '(');
- if (open_paren)
- close_paren = strchr (open_paren, ')');
- }
- else
- close_paren = strchr (open_paren, ')');
- }
-
- if (open_paren)
- s.Write(cstr, open_paren - cstr + 1);
- else
- {
- s.PutCString (cstr);
- s.PutChar ('(');
- }
- const size_t num_args = args.GetSize();
- for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx)
- {
- std::string buffer;
-
- VariableSP var_sp (args.GetVariableAtIndex (arg_idx));
- ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp));
- StreamString ss;
- const char *var_representation = nullptr;
- const char *var_name = var_value_sp->GetName().GetCString();
- if (var_value_sp->GetCompilerType().IsValid())
- {
- if (var_value_sp && exe_scope->CalculateTarget())
- var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable(exe_scope->CalculateTarget()->TargetProperties::GetPreferDynamicValue(),
- exe_scope->CalculateTarget()->TargetProperties::GetEnableSyntheticValue());
- if (var_value_sp->GetCompilerType().IsAggregateType() &&
- DataVisualization::ShouldPrintAsOneLiner(*var_value_sp))
- {
- static StringSummaryFormat format(TypeSummaryImpl::Flags()
- .SetHideItemNames(false)
- .SetShowMembersOneLiner(true),
- "");
- format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
- var_representation = buffer.c_str();
- }
- else
- var_value_sp->DumpPrintableRepresentation(ss,
- ValueObject::ValueObjectRepresentationStyle::eValueObjectRepresentationStyleSummary,
- eFormatDefault,
- ValueObject::PrintableRepresentationSpecialCases::ePrintableRepresentationSpecialCasesAllow,
- false);
- }
-
- if (ss.GetData() && ss.GetSize())
- var_representation = ss.GetData();
- if (arg_idx > 0)
- s.PutCString (", ");
- if (var_value_sp->GetError().Success())
- {
- if (var_representation)
- s.Printf ("%s=%s", var_name, var_representation);
- else
- s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString());
- }
- else
- s.Printf ("%s=<unavailable>", var_name);
- }
-
- if (close_paren)
- s.PutCString (close_paren);
- else
- s.PutChar(')');
-
- }
- else
- {
- s.PutCString(cstr);
- }
- return true;
- }
- }
- else if (sc->symbol)
- {
- const char *cstr = sc->symbol->GetName().AsCString(nullptr);
- if (cstr)
- {
- s.PutCString(cstr);
- return true;
- }
- }
- }
- }
- return false;
-
- case Entry::Type::FunctionAddrOffset:
- if (addr)
- {
- if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, *addr, false, false, false))
- return true;
+ s.Printf("%s=%s at %s", var_name,
+ var_value_sp->GetTypeName().GetCString(),
+ var_value_sp->GetLocationAsCString());
+ } else
+ s.Printf("%s=<unavailable>", var_name);
}
- return false;
- case Entry::Type::FunctionAddrOffsetConcrete:
- if (addr)
- {
- if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, *addr, true, true, true))
- return true;
- }
- return false;
-
- case Entry::Type::FunctionLineOffset:
- return (DumpAddressOffsetFromFunction (s, sc, exe_ctx, sc->line_entry.range.GetBaseAddress(), false, false, false));
-
- case Entry::Type::FunctionPCOffset:
- if (exe_ctx)
- {
- StackFrame *frame = exe_ctx->GetFramePtr();
- if (frame)
- {
- if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, frame->GetFrameCodeAddress(), false, false, false))
- return true;
- }
- }
- return false;
+ if (close_paren)
+ s.PutCString(close_paren);
+ else
+ s.PutChar(')');
- case Entry::Type::FunctionChanged:
- return function_changed;
+ } else {
+ s.PutCString(cstr);
+ }
+ return true;
+ }
+ } else if (sc->symbol) {
+ const char *cstr = sc->symbol->GetName().AsCString(nullptr);
+ if (cstr) {
+ s.PutCString(cstr);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
- case Entry::Type::FunctionIsOptimized:
- {
- bool is_optimized = false;
- if (sc->function && sc->function->GetIsOptimized())
- {
- is_optimized = true;
- }
- return is_optimized;
- }
+ case Entry::Type::FunctionAddrOffset:
+ if (addr) {
+ if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false,
+ false))
+ return true;
+ }
+ return false;
- case Entry::Type::FunctionInitial:
- return initial_function;
+ case Entry::Type::FunctionAddrOffsetConcrete:
+ if (addr) {
+ if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true,
+ true))
+ return true;
+ }
+ return false;
- case Entry::Type::LineEntryFile:
- if (sc && sc->line_entry.IsValid())
- {
- Module *module = sc->module_sp.get();
- if (module)
- {
- if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number))
- return true;
- }
- }
- return false;
+ case Entry::Type::FunctionLineOffset:
+ return (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
+ sc->line_entry.range.GetBaseAddress(),
+ false, false, false));
+
+ case Entry::Type::FunctionPCOffset:
+ if (exe_ctx) {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame) {
+ if (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
+ frame->GetFrameCodeAddress(), false,
+ false, false))
+ return true;
+ }
+ }
+ return false;
- case Entry::Type::LineEntryLineNumber:
- if (sc && sc->line_entry.IsValid())
- {
- const char *format = "%" PRIu32;
- if (!entry.printf_format.empty())
- format = entry.printf_format.c_str();
- s.Printf(format, sc->line_entry.line);
- return true;
- }
- return false;
+ case Entry::Type::FunctionChanged:
+ return function_changed;
- case Entry::Type::LineEntryStartAddress:
- case Entry::Type::LineEntryEndAddress:
- if (sc && sc->line_entry.range.GetBaseAddress().IsValid())
- {
- Address addr = sc->line_entry.range.GetBaseAddress();
-
- if (entry.type == Entry::Type::LineEntryEndAddress)
- addr.Slide(sc->line_entry.range.GetByteSize());
- if (DumpAddress(s, sc, exe_ctx, addr, false))
- return true;
- }
- return false;
+ case Entry::Type::FunctionIsOptimized: {
+ bool is_optimized = false;
+ if (sc->function && sc->function->GetIsOptimized()) {
+ is_optimized = true;
+ }
+ return is_optimized;
+ }
+
+ case Entry::Type::FunctionInitial:
+ return initial_function;
+
+ case Entry::Type::LineEntryFile:
+ if (sc && sc->line_entry.IsValid()) {
+ Module *module = sc->module_sp.get();
+ if (module) {
+ if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number))
+ return true;
+ }
+ }
+ return false;
- case Entry::Type::CurrentPCArrow:
- if (addr && exe_ctx && exe_ctx->GetFramePtr())
- {
- RegisterContextSP reg_ctx = exe_ctx->GetFramePtr()->GetRegisterContextSP();
- if (reg_ctx)
- {
- addr_t pc_loadaddr = reg_ctx->GetPC();
- if (pc_loadaddr != LLDB_INVALID_ADDRESS)
- {
- Address pc;
- pc.SetLoadAddress (pc_loadaddr, exe_ctx->GetTargetPtr());
- if (pc == *addr)
- {
- s.Printf ("-> ");
- return true;
- }
- }
- }
- s.Printf(" ");
- return true;
- }
- return false;
+ case Entry::Type::LineEntryLineNumber:
+ if (sc && sc->line_entry.IsValid()) {
+ const char *format = "%" PRIu32;
+ if (!entry.printf_format.empty())
+ format = entry.printf_format.c_str();
+ s.Printf(format, sc->line_entry.line);
+ return true;
}
return false;
-}
-static bool
-DumpCommaSeparatedChildEntryNames (Stream &s, const FormatEntity::Entry::Definition *parent)
-{
- if (parent->children)
- {
- const size_t n = parent->num_children;
- for (size_t i = 0; i < n; ++i)
- {
- if (i > 0)
- s.PutCString(", ");
- s.Printf ("\"%s\"", parent->children[i].name);
- }
+ case Entry::Type::LineEntryStartAddress:
+ case Entry::Type::LineEntryEndAddress:
+ if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) {
+ Address addr = sc->line_entry.range.GetBaseAddress();
+
+ if (entry.type == Entry::Type::LineEntryEndAddress)
+ addr.Slide(sc->line_entry.range.GetByteSize());
+ if (DumpAddress(s, sc, exe_ctx, addr, false))
return true;
}
return false;
-}
-
-static Error
-ParseEntry (const llvm::StringRef &format_str,
- const FormatEntity::Entry::Definition *parent,
- FormatEntity::Entry &entry)
-{
- Error error;
-
- const size_t sep_pos = format_str.find_first_of(".[:");
- const char sep_char = (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
- llvm::StringRef key = format_str.substr(0, sep_pos);
- const size_t n = parent->num_children;
- for (size_t i = 0; i < n; ++i)
- {
- const FormatEntity::Entry::Definition *entry_def = parent->children + i;
- if (key.equals(entry_def->name) || entry_def->name[0] == '*')
- {
- llvm::StringRef value;
- if (sep_char)
- value = format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
- switch (entry_def->type)
- {
- case FormatEntity::Entry::Type::ParentString:
- entry.string = format_str.str();
- return error; // Success
-
- case FormatEntity::Entry::Type::ParentNumber:
- entry.number = entry_def->data;
- return error; // Success
-
- case FormatEntity::Entry::Type::InsertString:
- entry.type = entry_def->type;
- entry.string = entry_def->string;
- return error; // Success
-
- default:
- entry.type = entry_def->type;
- break;
- }
-
- if (value.empty())
- {
- if (entry_def->type == FormatEntity::Entry::Type::Invalid)
- {
- if (entry_def->children)
- {
- StreamString error_strm;
- error_strm.Printf("'%s' can't be specified on its own, you must access one of its children: ", entry_def->name);
- DumpCommaSeparatedChildEntryNames (error_strm, entry_def);
- error.SetErrorStringWithFormat("%s", error_strm.GetString().c_str());
- }
- else if (sep_char == ':')
- {
- // Any value whose separator is a with a ':' means this value has a string argument
- // that needs to be stored in the entry (like "${script.var:}").
- // In this case the string value is the empty string which is ok.
- }
- else
- {
- error.SetErrorStringWithFormat("%s", "invalid entry definitions");
- }
- }
- }
- else
- {
- if (entry_def->children)
- {
- error = ParseEntry (value, entry_def, entry);
- }
- else if (sep_char == ':')
- {
- // Any value whose separator is a with a ':' means this value has a string argument
- // that needs to be stored in the entry (like "${script.var:modulename.function}")
- entry.string = value.str();
- }
- else
- {
- error.SetErrorStringWithFormat("'%s' followed by '%s' but it has no children",
- key.str().c_str(),
- value.str().c_str());
- }
- }
- return error;
+ case Entry::Type::CurrentPCArrow:
+ if (addr && exe_ctx && exe_ctx->GetFramePtr()) {
+ RegisterContextSP reg_ctx =
+ exe_ctx->GetFramePtr()->GetRegisterContextSP();
+ if (reg_ctx) {
+ addr_t pc_loadaddr = reg_ctx->GetPC();
+ if (pc_loadaddr != LLDB_INVALID_ADDRESS) {
+ Address pc;
+ pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr());
+ if (pc == *addr) {
+ s.Printf("-> ");
+ return true;
+ }
}
+ }
+ s.Printf(" ");
+ return true;
}
- StreamString error_strm;
- if (parent->type == FormatEntity::Entry::Type::Root)
- error_strm.Printf("invalid top level item '%s'. Valid top level items are: ", key.str().c_str());
- else
- error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ", key.str().c_str(), parent->name);
- DumpCommaSeparatedChildEntryNames (error_strm, parent);
- error.SetErrorStringWithFormat("%s", error_strm.GetString().c_str());
- return error;
+ return false;
+ }
+ return false;
}
-static const FormatEntity::Entry::Definition *
-FindEntry (const llvm::StringRef &format_str, const FormatEntity::Entry::Definition *parent, llvm::StringRef &remainder)
-{
- Error error;
-
- std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
+static bool DumpCommaSeparatedChildEntryNames(
+ Stream &s, const FormatEntity::Entry::Definition *parent) {
+ if (parent->children) {
const size_t n = parent->num_children;
- for (size_t i = 0; i < n; ++i)
- {
- const FormatEntity::Entry::Definition *entry_def = parent->children + i;
- if (p.first.equals(entry_def->name) || entry_def->name[0] == '*')
- {
- if (p.second.empty())
- {
- if (format_str.back() == '.')
- remainder = format_str.drop_front(format_str.size() - 1);
- else
- remainder = llvm::StringRef(); // Exact match
- return entry_def;
- }
- else
- {
- if (entry_def->children)
- {
- return FindEntry (p.second, entry_def, remainder);
- }
- else
- {
- remainder = p.second;
- return entry_def;
- }
- }
- }
+ for (size_t i = 0; i < n; ++i) {
+ if (i > 0)
+ s.PutCString(", ");
+ s.Printf("\"%s\"", parent->children[i].name);
}
- remainder = format_str;
- return parent;
+ return true;
+ }
+ return false;
}
-Error
-FormatEntity::ParseInternal (llvm::StringRef &format, Entry &parent_entry, uint32_t depth)
-{
- Error error;
- while (!format.empty() && error.Success())
- {
- const size_t non_special_chars = format.find_first_of("${}\\");
+static Error ParseEntry(const llvm::StringRef &format_str,
+ const FormatEntity::Entry::Definition *parent,
+ FormatEntity::Entry &entry) {
+ Error error;
+
+ const size_t sep_pos = format_str.find_first_of(".[:");
+ const char sep_char =
+ (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
+ llvm::StringRef key = format_str.substr(0, sep_pos);
+
+ const size_t n = parent->num_children;
+ for (size_t i = 0; i < n; ++i) {
+ const FormatEntity::Entry::Definition *entry_def = parent->children + i;
+ if (key.equals(entry_def->name) || entry_def->name[0] == '*') {
+ llvm::StringRef value;
+ if (sep_char)
+ value =
+ format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
+ switch (entry_def->type) {
+ case FormatEntity::Entry::Type::ParentString:
+ entry.string = format_str.str();
+ return error; // Success
+
+ case FormatEntity::Entry::Type::ParentNumber:
+ entry.number = entry_def->data;
+ return error; // Success
+
+ case FormatEntity::Entry::Type::InsertString:
+ entry.type = entry_def->type;
+ entry.string = entry_def->string;
+ return error; // Success
+
+ default:
+ entry.type = entry_def->type;
+ break;
+ }
+
+ if (value.empty()) {
+ if (entry_def->type == FormatEntity::Entry::Type::Invalid) {
+ if (entry_def->children) {
+ StreamString error_strm;
+ error_strm.Printf("'%s' can't be specified on its own, you must "
+ "access one of its children: ",
+ entry_def->name);
+ DumpCommaSeparatedChildEntryNames(error_strm, entry_def);
+ error.SetErrorStringWithFormat("%s",
+ error_strm.GetString().c_str());
+ } else if (sep_char == ':') {
+ // Any value whose separator is a with a ':' means this value has a
+ // string argument
+ // that needs to be stored in the entry (like "${script.var:}").
+ // In this case the string value is the empty string which is ok.
+ } else {
+ error.SetErrorStringWithFormat("%s", "invalid entry definitions");
+ }
+ }
+ } else {
+ if (entry_def->children) {
+ error = ParseEntry(value, entry_def, entry);
+ } else if (sep_char == ':') {
+ // Any value whose separator is a with a ':' means this value has a
+ // string argument
+ // that needs to be stored in the entry (like
+ // "${script.var:modulename.function}")
+ entry.string = value.str();
+ } else {
+ error.SetErrorStringWithFormat(
+ "'%s' followed by '%s' but it has no children", key.str().c_str(),
+ value.str().c_str());
+ }
+ }
+ return error;
+ }
+ }
+ StreamString error_strm;
+ if (parent->type == FormatEntity::Entry::Type::Root)
+ error_strm.Printf(
+ "invalid top level item '%s'. Valid top level items are: ",
+ key.str().c_str());
+ else
+ error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ",
+ key.str().c_str(), parent->name);
+ DumpCommaSeparatedChildEntryNames(error_strm, parent);
+ error.SetErrorStringWithFormat("%s", error_strm.GetString().c_str());
+ return error;
+}
- if (non_special_chars == llvm::StringRef::npos)
+static const FormatEntity::Entry::Definition *
+FindEntry(const llvm::StringRef &format_str,
+ const FormatEntity::Entry::Definition *parent,
+ llvm::StringRef &remainder) {
+ Error error;
+
+ std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
+ const size_t n = parent->num_children;
+ for (size_t i = 0; i < n; ++i) {
+ const FormatEntity::Entry::Definition *entry_def = parent->children + i;
+ if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') {
+ if (p.second.empty()) {
+ if (format_str.back() == '.')
+ remainder = format_str.drop_front(format_str.size() - 1);
+ else
+ remainder = llvm::StringRef(); // Exact match
+ return entry_def;
+ } else {
+ if (entry_def->children) {
+ return FindEntry(p.second, entry_def, remainder);
+ } else {
+ remainder = p.second;
+ return entry_def;
+ }
+ }
+ }
+ }
+ remainder = format_str;
+ return parent;
+}
+
+Error FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry,
+ uint32_t depth) {
+ Error error;
+ while (!format.empty() && error.Success()) {
+ const size_t non_special_chars = format.find_first_of("${}\\");
+
+ if (non_special_chars == llvm::StringRef::npos) {
+ // No special characters, just string bytes so add them and we are done
+ parent_entry.AppendText(format);
+ return error;
+ }
+
+ if (non_special_chars > 0) {
+ // We have a special character, so add all characters before these as a
+ // plain string
+ parent_entry.AppendText(format.substr(0, non_special_chars));
+ format = format.drop_front(non_special_chars);
+ }
+
+ switch (format[0]) {
+ case '\0':
+ return error;
+
+ case '{': {
+ format = format.drop_front(); // Skip the '{'
+ Entry scope_entry(Entry::Type::Scope);
+ error = FormatEntity::ParseInternal(format, scope_entry, depth + 1);
+ if (error.Fail())
+ return error;
+ parent_entry.AppendEntry(std::move(scope_entry));
+ } break;
+
+ case '}':
+ if (depth == 0)
+ error.SetErrorString("unmatched '}' character");
+ else
+ format =
+ format
+ .drop_front(); // Skip the '}' as we are at the end of the scope
+ return error;
+
+ case '\\': {
+ format = format.drop_front(); // Skip the '\' character
+ if (format.empty()) {
+ error.SetErrorString(
+ "'\\' character was not followed by another character");
+ return error;
+ }
+
+ const char desens_char = format[0];
+ format = format.drop_front(); // Skip the desensitized char character
+ switch (desens_char) {
+ case 'a':
+ parent_entry.AppendChar('\a');
+ break;
+ case 'b':
+ parent_entry.AppendChar('\b');
+ break;
+ case 'f':
+ parent_entry.AppendChar('\f');
+ break;
+ case 'n':
+ parent_entry.AppendChar('\n');
+ break;
+ case 'r':
+ parent_entry.AppendChar('\r');
+ break;
+ case 't':
+ parent_entry.AppendChar('\t');
+ break;
+ case 'v':
+ parent_entry.AppendChar('\v');
+ break;
+ case '\'':
+ parent_entry.AppendChar('\'');
+ break;
+ case '\\':
+ parent_entry.AppendChar('\\');
+ break;
+ case '0':
+ // 1 to 3 octal chars
{
- // No special characters, just string bytes so add them and we are done
- parent_entry.AppendText(format);
+ // Make a string that can hold onto the initial zero char,
+ // up to 3 octal digits, and a terminating NULL.
+ char oct_str[5] = {0, 0, 0, 0, 0};
+
+ int i;
+ for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i)
+ oct_str[i] = format[i];
+
+ // We don't want to consume the last octal character since
+ // the main for loop will do this for us, so we advance p by
+ // one less than i (even if i is zero)
+ format = format.drop_front(i);
+ unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
+ if (octal_value <= UINT8_MAX) {
+ parent_entry.AppendChar((char)octal_value);
+ } else {
+ error.SetErrorString("octal number is larger than a single byte");
return error;
+ }
}
+ break;
- if (non_special_chars > 0)
- {
- // We have a special character, so add all characters before these as a plain string
- parent_entry.AppendText(format.substr(0,non_special_chars));
- format = format.drop_front(non_special_chars);
+ case 'x':
+ // hex number in the format
+ if (isxdigit(format[0])) {
+ // Make a string that can hold onto two hex chars plus a
+ // NULL terminator
+ char hex_str[3] = {0, 0, 0};
+ hex_str[0] = format[0];
+
+ format = format.drop_front();
+
+ if (isxdigit(format[0])) {
+ hex_str[1] = format[0];
+ format = format.drop_front();
+ }
+
+ unsigned long hex_value = strtoul(hex_str, nullptr, 16);
+ if (hex_value <= UINT8_MAX) {
+ parent_entry.AppendChar((char)hex_value);
+ } else {
+ error.SetErrorString("hex number is larger than a single byte");
+ return error;
+ }
+ } else {
+ parent_entry.AppendChar(desens_char);
}
+ break;
- switch (format[0])
- {
- case '\0':
- return error;
-
- case '{':
- {
- format = format.drop_front(); // Skip the '{'
- Entry scope_entry(Entry::Type::Scope);
- error = FormatEntity::ParseInternal (format, scope_entry, depth+1);
- if (error.Fail())
- return error;
- parent_entry.AppendEntry(std::move(scope_entry));
- }
- break;
+ default:
+ // Just desensitize any other character by just printing what
+ // came after the '\'
+ parent_entry.AppendChar(desens_char);
+ break;
+ }
+ } break;
- case '}':
- if (depth == 0)
- error.SetErrorString("unmatched '}' character");
- else
- format = format.drop_front(); // Skip the '}' as we are at the end of the scope
+ case '$':
+ if (format.size() == 1) {
+ // '$' at the end of a format string, just print the '$'
+ parent_entry.AppendText("$");
+ } else {
+ format = format.drop_front(); // Skip the '$'
+
+ if (format[0] == '{') {
+ format = format.drop_front(); // Skip the '{'
+
+ llvm::StringRef variable, variable_format;
+ error = FormatEntity::ExtractVariableInfo(format, variable,
+ variable_format);
+ if (error.Fail())
+ return error;
+ bool verify_is_thread_id = false;
+ Entry entry;
+ if (!variable_format.empty()) {
+ entry.printf_format = variable_format.str();
+
+ // If the format contains a '%' we are going to assume this is
+ // a printf style format. So if you want to format your thread ID
+ // using "0x%llx" you can use:
+ // ${thread.id%0x%llx}
+ //
+ // If there is no '%' in the format, then it is assumed to be a
+ // LLDB format name, or one of the extended formats specified in
+ // the switch statement below.
+
+ if (entry.printf_format.find('%') == std::string::npos) {
+ bool clear_printf = false;
+
+ if (FormatManager::GetFormatFromCString(
+ entry.printf_format.c_str(), false, entry.fmt)) {
+ // We have an LLDB format, so clear the printf format
+ clear_printf = true;
+ } else if (entry.printf_format.size() == 1) {
+ switch (entry.printf_format[0]) {
+ case '@': // if this is an @ sign, print ObjC description
+ entry.number = ValueObject::
+ eValueObjectRepresentationStyleLanguageSpecific;
+ clear_printf = true;
+ break;
+ case 'V': // if this is a V, print the value using the default
+ // format
+ entry.number =
+ ValueObject::eValueObjectRepresentationStyleValue;
+ clear_printf = true;
+ break;
+ case 'L': // if this is an L, print the location of the value
+ entry.number =
+ ValueObject::eValueObjectRepresentationStyleLocation;
+ clear_printf = true;
+ break;
+ case 'S': // if this is an S, print the summary after all
+ entry.number =
+ ValueObject::eValueObjectRepresentationStyleSummary;
+ clear_printf = true;
+ break;
+ case '#': // if this is a '#', print the number of children
+ entry.number =
+ ValueObject::eValueObjectRepresentationStyleChildrenCount;
+ clear_printf = true;
+ break;
+ case 'T': // if this is a 'T', print the type
+ entry.number =
+ ValueObject::eValueObjectRepresentationStyleType;
+ clear_printf = true;
+ break;
+ case 'N': // if this is a 'N', print the name
+ entry.number =
+ ValueObject::eValueObjectRepresentationStyleName;
+ clear_printf = true;
+ break;
+ case '>': // if this is a '>', print the expression path
+ entry.number = ValueObject::
+ eValueObjectRepresentationStyleExpressionPath;
+ clear_printf = true;
+ break;
+ default:
+ error.SetErrorStringWithFormat("invalid format: '%s'",
+ entry.printf_format.c_str());
+ return error;
+ }
+ } else if (FormatManager::GetFormatFromCString(
+ entry.printf_format.c_str(), true, entry.fmt)) {
+ clear_printf = true;
+ } else if (entry.printf_format == "tid") {
+ verify_is_thread_id = true;
+ } else {
+ error.SetErrorStringWithFormat("invalid format: '%s'",
+ entry.printf_format.c_str());
return error;
+ }
- case '\\':
- {
- format = format.drop_front(); // Skip the '\' character
- if (format.empty())
- {
- error.SetErrorString("'\\' character was not followed by another character");
- return error;
- }
-
- const char desens_char = format[0];
- format = format.drop_front(); // Skip the desensitized char character
- switch (desens_char)
- {
- case 'a': parent_entry.AppendChar('\a'); break;
- case 'b': parent_entry.AppendChar('\b'); break;
- case 'f': parent_entry.AppendChar('\f'); break;
- case 'n': parent_entry.AppendChar('\n'); break;
- case 'r': parent_entry.AppendChar('\r'); break;
- case 't': parent_entry.AppendChar('\t'); break;
- case 'v': parent_entry.AppendChar('\v'); break;
- case '\'': parent_entry.AppendChar('\''); break;
- case '\\': parent_entry.AppendChar('\\'); break;
- case '0':
- // 1 to 3 octal chars
- {
- // Make a string that can hold onto the initial zero char,
- // up to 3 octal digits, and a terminating NULL.
- char oct_str[5] = { 0, 0, 0, 0, 0 };
-
- int i;
- for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i)
- oct_str[i] = format[i];
-
- // We don't want to consume the last octal character since
- // the main for loop will do this for us, so we advance p by
- // one less than i (even if i is zero)
- format = format.drop_front(i);
- unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
- if (octal_value <= UINT8_MAX)
- {
- parent_entry.AppendChar((char)octal_value);
- }
- else
- {
- error.SetErrorString("octal number is larger than a single byte");
- return error;
- }
- }
- break;
-
- case 'x':
- // hex number in the format
- if (isxdigit(format[0]))
- {
- // Make a string that can hold onto two hex chars plus a
- // NULL terminator
- char hex_str[3] = { 0,0,0 };
- hex_str[0] = format[0];
-
- format = format.drop_front();
-
- if (isxdigit(format[0]))
- {
- hex_str[1] = format[0];
- format = format.drop_front();
- }
-
- unsigned long hex_value = strtoul(hex_str, nullptr, 16);
- if (hex_value <= UINT8_MAX)
- {
- parent_entry.AppendChar((char)hex_value);
- }
- else
- {
- error.SetErrorString("hex number is larger than a single byte");
- return error;
- }
- }
- else
- {
- parent_entry.AppendChar(desens_char);
- }
- break;
-
- default:
- // Just desensitize any other character by just printing what
- // came after the '\'
- parent_entry.AppendChar(desens_char);
- break;
- }
- }
- break;
-
- case '$':
- if (format.size() == 1)
- {
- // '$' at the end of a format string, just print the '$'
- parent_entry.AppendText("$");
- }
- else
- {
- format = format.drop_front(); // Skip the '$'
-
- if (format[0] == '{')
- {
- format = format.drop_front(); // Skip the '{'
-
- llvm::StringRef variable, variable_format;
- error = FormatEntity::ExtractVariableInfo (format, variable, variable_format);
- if (error.Fail())
- return error;
- bool verify_is_thread_id = false;
- Entry entry;
- if (!variable_format.empty())
- {
- entry.printf_format = variable_format.str();
-
- // If the format contains a '%' we are going to assume this is
- // a printf style format. So if you want to format your thread ID
- // using "0x%llx" you can use:
- // ${thread.id%0x%llx}
- //
- // If there is no '%' in the format, then it is assumed to be a
- // LLDB format name, or one of the extended formats specified in
- // the switch statement below.
-
- if (entry.printf_format.find('%') == std::string::npos)
- {
- bool clear_printf = false;
-
- if (FormatManager::GetFormatFromCString(entry.printf_format.c_str(),
- false,
- entry.fmt))
- {
- // We have an LLDB format, so clear the printf format
- clear_printf = true;
- }
- else if (entry.printf_format.size() == 1)
- {
- switch (entry.printf_format[0])
- {
- case '@': // if this is an @ sign, print ObjC description
- entry.number = ValueObject::eValueObjectRepresentationStyleLanguageSpecific;
- clear_printf = true;
- break;
- case 'V': // if this is a V, print the value using the default format
- entry.number = ValueObject::eValueObjectRepresentationStyleValue;
- clear_printf = true;
- break;
- case 'L': // if this is an L, print the location of the value
- entry.number = ValueObject::eValueObjectRepresentationStyleLocation;
- clear_printf = true;
- break;
- case 'S': // if this is an S, print the summary after all
- entry.number = ValueObject::eValueObjectRepresentationStyleSummary;
- clear_printf = true;
- break;
- case '#': // if this is a '#', print the number of children
- entry.number = ValueObject::eValueObjectRepresentationStyleChildrenCount;
- clear_printf = true;
- break;
- case 'T': // if this is a 'T', print the type
- entry.number = ValueObject::eValueObjectRepresentationStyleType;
- clear_printf = true;
- break;
- case 'N': // if this is a 'N', print the name
- entry.number = ValueObject::eValueObjectRepresentationStyleName;
- clear_printf = true;
- break;
- case '>': // if this is a '>', print the expression path
- entry.number = ValueObject::eValueObjectRepresentationStyleExpressionPath;
- clear_printf = true;
- break;
- default:
- error.SetErrorStringWithFormat("invalid format: '%s'", entry.printf_format.c_str());
- return error;
- }
- }
- else if (FormatManager::GetFormatFromCString(entry.printf_format.c_str(),
- true,
- entry.fmt))
- {
- clear_printf = true;
- }
- else if (entry.printf_format == "tid")
- {
- verify_is_thread_id = true;
- }
- else
- {
- error.SetErrorStringWithFormat("invalid format: '%s'", entry.printf_format.c_str());
- return error;
- }
-
- // Our format string turned out to not be a printf style format
- // so lets clear the string
- if (clear_printf)
- entry.printf_format.clear();
- }
- }
-
- // Check for dereferences
- if (variable[0] == '*')
- {
- entry.deref = true;
- variable = variable.drop_front();
- }
-
- error = ParseEntry (variable, &g_root, entry);
- if (error.Fail())
- return error;
-
- if (verify_is_thread_id)
- {
- if (entry.type != Entry::Type::ThreadID &&
- entry.type != Entry::Type::ThreadProtocolID)
- {
- error.SetErrorString("the 'tid' format can only be used on ${thread.id} and ${thread.protocol_id}");
- }
- }
-
- switch (entry.type)
- {
- case Entry::Type::Variable:
- case Entry::Type::VariableSynthetic:
- if (entry.number == 0)
- {
- if (entry.string.empty())
- entry.number = ValueObject::eValueObjectRepresentationStyleValue;
- else
- entry.number = ValueObject::eValueObjectRepresentationStyleSummary;
- }
- break;
- default:
- // Make sure someone didn't try to dereference anything but ${var} or ${svar}
- if (entry.deref)
- {
- error.SetErrorStringWithFormat("${%s} can't be dereferenced, only ${var} and ${svar} can.", variable.str().c_str());
- return error;
- }
- }
- // Check if this entry just wants to insert a constant string
- // value into the parent_entry, if so, insert the string with
- // AppendText, else append the entry to the parent_entry.
- if (entry.type == Entry::Type::InsertString)
- parent_entry.AppendText(entry.string.c_str());
- else
- parent_entry.AppendEntry(std::move(entry));
- }
- }
- break;
- }
- }
- return error;
-}
+ // Our format string turned out to not be a printf style format
+ // so lets clear the string
+ if (clear_printf)
+ entry.printf_format.clear();
+ }
+ }
+
+ // Check for dereferences
+ if (variable[0] == '*') {
+ entry.deref = true;
+ variable = variable.drop_front();
+ }
-Error
-FormatEntity::ExtractVariableInfo (llvm::StringRef &format_str, llvm::StringRef &variable_name, llvm::StringRef &variable_format)
-{
- Error error;
- variable_name = llvm::StringRef();
- variable_format = llvm::StringRef();
+ error = ParseEntry(variable, &g_root, entry);
+ if (error.Fail())
+ return error;
- const size_t paren_pos = format_str.find('}');
- if (paren_pos != llvm::StringRef::npos)
- {
- const size_t percent_pos = format_str.find('%');
- if (percent_pos < paren_pos)
- {
- if (percent_pos > 0)
- {
- if (percent_pos > 1)
- variable_name = format_str.substr(0, percent_pos);
- variable_format = format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
+ if (verify_is_thread_id) {
+ if (entry.type != Entry::Type::ThreadID &&
+ entry.type != Entry::Type::ThreadProtocolID) {
+ error.SetErrorString("the 'tid' format can only be used on "
+ "${thread.id} and ${thread.protocol_id}");
+ }
+ }
+
+ switch (entry.type) {
+ case Entry::Type::Variable:
+ case Entry::Type::VariableSynthetic:
+ if (entry.number == 0) {
+ if (entry.string.empty())
+ entry.number =
+ ValueObject::eValueObjectRepresentationStyleValue;
+ else
+ entry.number =
+ ValueObject::eValueObjectRepresentationStyleSummary;
}
- }
- else
- {
- variable_name = format_str.substr(0, paren_pos);
- }
- // Strip off elements and the formatting and the trailing '}'
- format_str = format_str.substr(paren_pos + 1);
- }
- else
- {
- error.SetErrorStringWithFormat("missing terminating '}' character for '${%s'", format_str.str().c_str());
- }
- return error;
-}
-
-bool
-FormatEntity::FormatFileSpec (const FileSpec &file_spec, Stream &s, llvm::StringRef variable_name, llvm::StringRef variable_format)
-{
- if (variable_name.empty() || variable_name.equals(".fullpath"))
- {
- file_spec.Dump(&s);
- return true;
- }
- else if (variable_name.equals(".basename"))
- {
- s.PutCString(file_spec.GetFilename().AsCString(""));
- return true;
- }
- else if (variable_name.equals(".dirname"))
- {
- s.PutCString(file_spec.GetFilename().AsCString(""));
- return true;
- }
- return false;
-}
-
-static std::string
-MakeMatch (const llvm::StringRef &prefix, const char *suffix)
-{
- std::string match(prefix.str());
- match.append(suffix);
- return match;
-}
-
-static void
-AddMatches (const FormatEntity::Entry::Definition *def,
- const llvm::StringRef &prefix,
- const llvm::StringRef &match_prefix,
- StringList &matches)
-{
- const size_t n = def->num_children;
- if (n > 0)
- {
- for (size_t i = 0; i < n; ++i)
- {
- std::string match = prefix.str();
- if (match_prefix.empty())
- matches.AppendString(MakeMatch (prefix, def->children[i].name));
- else if (strncmp(def->children[i].name, match_prefix.data(), match_prefix.size()) == 0)
- matches.AppendString(MakeMatch (prefix, def->children[i].name + match_prefix.size()));
- }
- }
+ break;
+ default:
+ // Make sure someone didn't try to dereference anything but ${var}
+ // or ${svar}
+ if (entry.deref) {
+ error.SetErrorStringWithFormat(
+ "${%s} can't be dereferenced, only ${var} and ${svar} can.",
+ variable.str().c_str());
+ return error;
+ }
+ }
+ // Check if this entry just wants to insert a constant string
+ // value into the parent_entry, if so, insert the string with
+ // AppendText, else append the entry to the parent_entry.
+ if (entry.type == Entry::Type::InsertString)
+ parent_entry.AppendText(entry.string.c_str());
+ else
+ parent_entry.AppendEntry(std::move(entry));
+ }
+ }
+ break;
+ }
+ }
+ return error;
+}
+
+Error FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str,
+ llvm::StringRef &variable_name,
+ llvm::StringRef &variable_format) {
+ Error error;
+ variable_name = llvm::StringRef();
+ variable_format = llvm::StringRef();
+
+ const size_t paren_pos = format_str.find('}');
+ if (paren_pos != llvm::StringRef::npos) {
+ const size_t percent_pos = format_str.find('%');
+ if (percent_pos < paren_pos) {
+ if (percent_pos > 0) {
+ if (percent_pos > 1)
+ variable_name = format_str.substr(0, percent_pos);
+ variable_format =
+ format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
+ }
+ } else {
+ variable_name = format_str.substr(0, paren_pos);
+ }
+ // Strip off elements and the formatting and the trailing '}'
+ format_str = format_str.substr(paren_pos + 1);
+ } else {
+ error.SetErrorStringWithFormat(
+ "missing terminating '}' character for '${%s'",
+ format_str.str().c_str());
+ }
+ return error;
+}
+
+bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s,
+ llvm::StringRef variable_name,
+ llvm::StringRef variable_format) {
+ if (variable_name.empty() || variable_name.equals(".fullpath")) {
+ file_spec.Dump(&s);
+ return true;
+ } else if (variable_name.equals(".basename")) {
+ s.PutCString(file_spec.GetFilename().AsCString(""));
+ return true;
+ } else if (variable_name.equals(".dirname")) {
+ s.PutCString(file_spec.GetFilename().AsCString(""));
+ return true;
+ }
+ return false;
}
-size_t
-FormatEntity::AutoComplete (const char *s,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches)
-{
- word_complete = false;
- llvm::StringRef str(s + match_start_point);
- matches.Clear();
-
- const size_t dollar_pos = str.rfind('$');
- if (dollar_pos != llvm::StringRef::npos)
- {
- // Hitting TAB after $ at the end of the string add a "{"
- if (dollar_pos == str.size() - 1)
- {
- std::string match = str.str();
- match.append("{");
- matches.AppendString(std::move(match));
- }
- else if (str[dollar_pos + 1] == '{')
- {
- const size_t close_pos = str.find('}', dollar_pos + 2);
- if (close_pos == llvm::StringRef::npos)
- {
- const size_t format_pos = str.find('%', dollar_pos + 2);
- if (format_pos == llvm::StringRef::npos)
- {
- llvm::StringRef partial_variable (str.substr(dollar_pos + 2));
- if (partial_variable.empty())
- {
- // Suggest all top level entites as we are just past "${"
- AddMatches(&g_root, str, llvm::StringRef(), matches);
- }
- else
- {
- // We have a partially specified variable, find it
- llvm::StringRef remainder;
- const FormatEntity::Entry::Definition* entry_def = FindEntry (partial_variable, &g_root, remainder);
- if (entry_def)
- {
- const size_t n = entry_def->num_children;
-
- if (remainder.empty())
- {
- // Exact match
- if (n > 0)
- {
- // "${thread.info" <TAB>
- matches.AppendString(MakeMatch(str, "."));
- }
- else
- {
- // "${thread.id" <TAB>
- matches.AppendString(MakeMatch (str, "}"));
- word_complete = true;
- }
- }
- else if (remainder.equals("."))
- {
- // "${thread." <TAB>
- AddMatches(entry_def, str, llvm::StringRef(), matches);
- }
- else
- {
- // We have a partial match
- // "${thre" <TAB>
- AddMatches(entry_def, str, remainder, matches);
- }
- }
- }
- }
+static std::string MakeMatch(const llvm::StringRef &prefix,
+ const char *suffix) {
+ std::string match(prefix.str());
+ match.append(suffix);
+ return match;
+}
+
+static void AddMatches(const FormatEntity::Entry::Definition *def,
+ const llvm::StringRef &prefix,
+ const llvm::StringRef &match_prefix,
+ StringList &matches) {
+ const size_t n = def->num_children;
+ if (n > 0) {
+ for (size_t i = 0; i < n; ++i) {
+ std::string match = prefix.str();
+ if (match_prefix.empty())
+ matches.AppendString(MakeMatch(prefix, def->children[i].name));
+ else if (strncmp(def->children[i].name, match_prefix.data(),
+ match_prefix.size()) == 0)
+ matches.AppendString(
+ MakeMatch(prefix, def->children[i].name + match_prefix.size()));
+ }
+ }
+}
+
+size_t FormatEntity::AutoComplete(const char *s, int match_start_point,
+ int max_return_elements, bool &word_complete,
+ StringList &matches) {
+ word_complete = false;
+ llvm::StringRef str(s + match_start_point);
+ matches.Clear();
+
+ const size_t dollar_pos = str.rfind('$');
+ if (dollar_pos != llvm::StringRef::npos) {
+ // Hitting TAB after $ at the end of the string add a "{"
+ if (dollar_pos == str.size() - 1) {
+ std::string match = str.str();
+ match.append("{");
+ matches.AppendString(std::move(match));
+ } else if (str[dollar_pos + 1] == '{') {
+ const size_t close_pos = str.find('}', dollar_pos + 2);
+ if (close_pos == llvm::StringRef::npos) {
+ const size_t format_pos = str.find('%', dollar_pos + 2);
+ if (format_pos == llvm::StringRef::npos) {
+ llvm::StringRef partial_variable(str.substr(dollar_pos + 2));
+ if (partial_variable.empty()) {
+ // Suggest all top level entites as we are just past "${"
+ AddMatches(&g_root, str, llvm::StringRef(), matches);
+ } else {
+ // We have a partially specified variable, find it
+ llvm::StringRef remainder;
+ const FormatEntity::Entry::Definition *entry_def =
+ FindEntry(partial_variable, &g_root, remainder);
+ if (entry_def) {
+ const size_t n = entry_def->num_children;
+
+ if (remainder.empty()) {
+ // Exact match
+ if (n > 0) {
+ // "${thread.info" <TAB>
+ matches.AppendString(MakeMatch(str, "."));
+ } else {
+ // "${thread.id" <TAB>
+ matches.AppendString(MakeMatch(str, "}"));
+ word_complete = true;
+ }
+ } else if (remainder.equals(".")) {
+ // "${thread." <TAB>
+ AddMatches(entry_def, str, llvm::StringRef(), matches);
+ } else {
+ // We have a partial match
+ // "${thre" <TAB>
+ AddMatches(entry_def, str, remainder, matches);
+ }
}
+ }
}
+ }
}
- return matches.GetSize();
+ }
+ return matches.GetSize();
}
Modified: lldb/trunk/source/Core/History.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/History.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Core/History.cpp (original)
+++ lldb/trunk/source/Core/History.cpp Tue Sep 6 15:57:50 2016
@@ -19,8 +19,6 @@
using namespace lldb;
using namespace lldb_private;
-void
-HistorySourceUInt::DumpHistoryEvent (Stream &strm, HistoryEvent event)
-{
- strm.Printf ("%s %" PRIu64, m_name.c_str(), (uint64_t)((uintptr_t)event));
+void HistorySourceUInt::DumpHistoryEvent(Stream &strm, HistoryEvent event) {
+ strm.Printf("%s %" PRIu64, m_name.c_str(), (uint64_t)((uintptr_t)event));
}
Modified: lldb/trunk/source/Core/IOHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/IOHandler.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Core/IOHandler.cpp (original)
+++ lldb/trunk/source/Core/IOHandler.cpp Tue Sep 6 15:57:50 2016
@@ -22,8 +22,8 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Core/IOHandler.h"
#include "lldb/Core/Debugger.h"
+#include "lldb/Core/IOHandler.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
@@ -41,10 +41,10 @@
#ifndef LLDB_DISABLE_CURSES
#include "lldb/Core/ValueObject.h"
#include "lldb/Symbol/VariableList.h"
-#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
-#include "lldb/Target/Thread.h"
#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
#endif
#ifdef _MSC_VER
@@ -54,771 +54,585 @@
using namespace lldb;
using namespace lldb_private;
-IOHandler::IOHandler (Debugger &debugger, IOHandler::Type type) :
- IOHandler (debugger,
- type,
- StreamFileSP(), // Adopt STDIN from top input reader
- StreamFileSP(), // Adopt STDOUT from top input reader
- StreamFileSP(), // Adopt STDERR from top input reader
- 0) // Flags
-{
-}
-
-IOHandler::IOHandler (Debugger &debugger,
- IOHandler::Type type,
- const lldb::StreamFileSP &input_sp,
- const lldb::StreamFileSP &output_sp,
- const lldb::StreamFileSP &error_sp,
- uint32_t flags) :
- m_debugger (debugger),
- m_input_sp (input_sp),
- m_output_sp (output_sp),
- m_error_sp (error_sp),
- m_popped (false),
- m_flags (flags),
- m_type (type),
- m_user_data(nullptr),
- m_done (false),
- m_active (false)
-{
- // If any files are not specified, then adopt them from the top input reader.
- if (!m_input_sp || !m_output_sp || !m_error_sp)
- debugger.AdoptTopIOHandlerFilesIfInvalid (m_input_sp,
- m_output_sp,
- m_error_sp);
+IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type)
+ : IOHandler(debugger, type,
+ StreamFileSP(), // Adopt STDIN from top input reader
+ StreamFileSP(), // Adopt STDOUT from top input reader
+ StreamFileSP(), // Adopt STDERR from top input reader
+ 0) // Flags
+{}
+
+IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type,
+ const lldb::StreamFileSP &input_sp,
+ const lldb::StreamFileSP &output_sp,
+ const lldb::StreamFileSP &error_sp, uint32_t flags)
+ : m_debugger(debugger), m_input_sp(input_sp), m_output_sp(output_sp),
+ m_error_sp(error_sp), m_popped(false), m_flags(flags), m_type(type),
+ m_user_data(nullptr), m_done(false), m_active(false) {
+ // If any files are not specified, then adopt them from the top input reader.
+ if (!m_input_sp || !m_output_sp || !m_error_sp)
+ debugger.AdoptTopIOHandlerFilesIfInvalid(m_input_sp, m_output_sp,
+ m_error_sp);
}
IOHandler::~IOHandler() = default;
-int
-IOHandler::GetInputFD()
-{
- return (m_input_sp ? m_input_sp->GetFile().GetDescriptor() : -1);
-}
-
-int
-IOHandler::GetOutputFD()
-{
- return (m_output_sp ? m_output_sp->GetFile().GetDescriptor() : -1);
+int IOHandler::GetInputFD() {
+ return (m_input_sp ? m_input_sp->GetFile().GetDescriptor() : -1);
}
-int
-IOHandler::GetErrorFD()
-{
- return (m_error_sp ? m_error_sp->GetFile().GetDescriptor() : -1);
+int IOHandler::GetOutputFD() {
+ return (m_output_sp ? m_output_sp->GetFile().GetDescriptor() : -1);
}
-FILE *
-IOHandler::GetInputFILE()
-{
- return (m_input_sp ? m_input_sp->GetFile().GetStream() : nullptr);
+int IOHandler::GetErrorFD() {
+ return (m_error_sp ? m_error_sp->GetFile().GetDescriptor() : -1);
}
-FILE *
-IOHandler::GetOutputFILE()
-{
- return (m_output_sp ? m_output_sp->GetFile().GetStream() : nullptr);
+FILE *IOHandler::GetInputFILE() {
+ return (m_input_sp ? m_input_sp->GetFile().GetStream() : nullptr);
}
-FILE *
-IOHandler::GetErrorFILE()
-{
- return (m_error_sp ? m_error_sp->GetFile().GetStream() : nullptr);
+FILE *IOHandler::GetOutputFILE() {
+ return (m_output_sp ? m_output_sp->GetFile().GetStream() : nullptr);
}
-StreamFileSP &
-IOHandler::GetInputStreamFile()
-{
- return m_input_sp;
+FILE *IOHandler::GetErrorFILE() {
+ return (m_error_sp ? m_error_sp->GetFile().GetStream() : nullptr);
}
-StreamFileSP &
-IOHandler::GetOutputStreamFile()
-{
- return m_output_sp;
-}
-
-StreamFileSP &
-IOHandler::GetErrorStreamFile()
-{
- return m_error_sp;
-}
-
-bool
-IOHandler::GetIsInteractive ()
-{
- return GetInputStreamFile()->GetFile().GetIsInteractive ();
-}
+StreamFileSP &IOHandler::GetInputStreamFile() { return m_input_sp; }
-bool
-IOHandler::GetIsRealTerminal ()
-{
- return GetInputStreamFile()->GetFile().GetIsRealTerminal();
-}
+StreamFileSP &IOHandler::GetOutputStreamFile() { return m_output_sp; }
-void
-IOHandler::SetPopped (bool b)
-{
- m_popped.SetValue(b, eBroadcastOnChange);
-}
+StreamFileSP &IOHandler::GetErrorStreamFile() { return m_error_sp; }
-void
-IOHandler::WaitForPop ()
-{
- m_popped.WaitForValueEqualTo(true);
+bool IOHandler::GetIsInteractive() {
+ return GetInputStreamFile()->GetFile().GetIsInteractive();
}
-void
-IOHandlerStack::PrintAsync(Stream *stream, const char *s, size_t len)
-{
- if (stream)
- {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (m_top)
- m_top->PrintAsync(stream, s, len);
- }
+bool IOHandler::GetIsRealTerminal() {
+ return GetInputStreamFile()->GetFile().GetIsRealTerminal();
}
-IOHandlerConfirm::IOHandlerConfirm (Debugger &debugger,
- const char *prompt,
- bool default_response) :
- IOHandlerEditline(debugger,
- IOHandler::Type::Confirm,
- nullptr, // nullptr editline_name means no history loaded/saved
- nullptr, // No prompt
- nullptr, // No continuation prompt
- false, // Multi-line
- false, // Don't colorize the prompt (i.e. the confirm message.)
- 0,
- *this),
- m_default_response (default_response),
- m_user_response (default_response)
-{
- StreamString prompt_stream;
- prompt_stream.PutCString(prompt);
- if (m_default_response)
- prompt_stream.Printf(": [Y/n] ");
- else
- prompt_stream.Printf(": [y/N] ");
-
- SetPrompt (prompt_stream.GetString().c_str());
-}
+void IOHandler::SetPopped(bool b) { m_popped.SetValue(b, eBroadcastOnChange); }
-IOHandlerConfirm::~IOHandlerConfirm() = default;
+void IOHandler::WaitForPop() { m_popped.WaitForValueEqualTo(true); }
-int
-IOHandlerConfirm::IOHandlerComplete (IOHandler &io_handler,
- const char *current_line,
- const char *cursor,
- const char *last_char,
- int skip_first_n_matches,
- int max_matches,
- StringList &matches)
-{
- if (current_line == cursor)
- {
- if (m_default_response)
- {
- matches.AppendString("y");
- }
- else
- {
- matches.AppendString("n");
- }
- }
- return matches.GetSize();
+void IOHandlerStack::PrintAsync(Stream *stream, const char *s, size_t len) {
+ if (stream) {
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ if (m_top)
+ m_top->PrintAsync(stream, s, len);
+ }
}
-void
-IOHandlerConfirm::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
-{
- if (line.empty())
- {
- // User just hit enter, set the response to the default
- m_user_response = m_default_response;
- io_handler.SetIsDone(true);
- return;
- }
-
- if (line.size() == 1)
- {
- switch (line[0])
- {
- case 'y':
- case 'Y':
- m_user_response = true;
- io_handler.SetIsDone(true);
- return;
- case 'n':
- case 'N':
- m_user_response = false;
- io_handler.SetIsDone(true);
- return;
- default:
- break;
- }
- }
+IOHandlerConfirm::IOHandlerConfirm(Debugger &debugger, const char *prompt,
+ bool default_response)
+ : IOHandlerEditline(
+ debugger, IOHandler::Type::Confirm,
+ nullptr, // nullptr editline_name means no history loaded/saved
+ nullptr, // No prompt
+ nullptr, // No continuation prompt
+ false, // Multi-line
+ false, // Don't colorize the prompt (i.e. the confirm message.)
+ 0, *this),
+ m_default_response(default_response), m_user_response(default_response) {
+ StreamString prompt_stream;
+ prompt_stream.PutCString(prompt);
+ if (m_default_response)
+ prompt_stream.Printf(": [Y/n] ");
+ else
+ prompt_stream.Printf(": [y/N] ");
- if (line == "yes" || line == "YES" || line == "Yes")
- {
- m_user_response = true;
- io_handler.SetIsDone(true);
- }
- else if (line == "no" || line == "NO" || line == "No")
- {
- m_user_response = false;
- io_handler.SetIsDone(true);
- }
+ SetPrompt(prompt_stream.GetString().c_str());
}
-int
-IOHandlerDelegate::IOHandlerComplete (IOHandler &io_handler,
- const char *current_line,
- const char *cursor,
- const char *last_char,
- int skip_first_n_matches,
- int max_matches,
- StringList &matches)
-{
- switch (m_completion)
- {
- case Completion::None:
- break;
+IOHandlerConfirm::~IOHandlerConfirm() = default;
- case Completion::LLDBCommand:
- return io_handler.GetDebugger().GetCommandInterpreter().HandleCompletion (current_line,
- cursor,
- last_char,
- skip_first_n_matches,
- max_matches,
- matches);
-
- case Completion::Expression:
- {
- bool word_complete = false;
- const char *word_start = cursor;
- if (cursor > current_line)
- --word_start;
- while (word_start > current_line && !isspace(*word_start))
- --word_start;
- CommandCompletions::InvokeCommonCompletionCallbacks(io_handler.GetDebugger().GetCommandInterpreter(),
- CommandCompletions::eVariablePathCompletion,
- word_start,
- skip_first_n_matches,
- max_matches,
- nullptr,
- word_complete,
- matches);
-
- size_t num_matches = matches.GetSize();
- if (num_matches > 0)
- {
- std::string common_prefix;
- matches.LongestCommonPrefix (common_prefix);
- const size_t partial_name_len = strlen(word_start);
-
- // If we matched a unique single command, add a space...
- // Only do this if the completer told us this was a complete word, however...
- if (num_matches == 1 && word_complete)
- {
- common_prefix.push_back(' ');
- }
- common_prefix.erase (0, partial_name_len);
- matches.InsertStringAtIndex(0, std::move(common_prefix));
- }
- return num_matches;
- }
- break;
- }
-
- return 0;
+int IOHandlerConfirm::IOHandlerComplete(IOHandler &io_handler,
+ const char *current_line,
+ const char *cursor,
+ const char *last_char,
+ int skip_first_n_matches,
+ int max_matches, StringList &matches) {
+ if (current_line == cursor) {
+ if (m_default_response) {
+ matches.AppendString("y");
+ } else {
+ matches.AppendString("n");
+ }
+ }
+ return matches.GetSize();
+}
+
+void IOHandlerConfirm::IOHandlerInputComplete(IOHandler &io_handler,
+ std::string &line) {
+ if (line.empty()) {
+ // User just hit enter, set the response to the default
+ m_user_response = m_default_response;
+ io_handler.SetIsDone(true);
+ return;
+ }
+
+ if (line.size() == 1) {
+ switch (line[0]) {
+ case 'y':
+ case 'Y':
+ m_user_response = true;
+ io_handler.SetIsDone(true);
+ return;
+ case 'n':
+ case 'N':
+ m_user_response = false;
+ io_handler.SetIsDone(true);
+ return;
+ default:
+ break;
+ }
+ }
+
+ if (line == "yes" || line == "YES" || line == "Yes") {
+ m_user_response = true;
+ io_handler.SetIsDone(true);
+ } else if (line == "no" || line == "NO" || line == "No") {
+ m_user_response = false;
+ io_handler.SetIsDone(true);
+ }
}
-IOHandlerEditline::IOHandlerEditline (Debugger &debugger,
- IOHandler::Type type,
- const char *editline_name, // Used for saving history files
- const char *prompt,
- const char *continuation_prompt,
- bool multi_line,
- bool color_prompts,
- uint32_t line_number_start,
- IOHandlerDelegate &delegate) :
- IOHandlerEditline(debugger,
- type,
- StreamFileSP(), // Inherit input from top input reader
- StreamFileSP(), // Inherit output from top input reader
- StreamFileSP(), // Inherit error from top input reader
- 0, // Flags
- editline_name, // Used for saving history files
- prompt,
- continuation_prompt,
- multi_line,
- color_prompts,
- line_number_start,
- delegate)
-{
-}
-
-IOHandlerEditline::IOHandlerEditline (Debugger &debugger,
- IOHandler::Type type,
- const lldb::StreamFileSP &input_sp,
- const lldb::StreamFileSP &output_sp,
- const lldb::StreamFileSP &error_sp,
- uint32_t flags,
- const char *editline_name, // Used for saving history files
- const char *prompt,
- const char *continuation_prompt,
- bool multi_line,
- bool color_prompts,
- uint32_t line_number_start,
- IOHandlerDelegate &delegate) :
- IOHandler (debugger, type, input_sp, output_sp, error_sp, flags),
+int IOHandlerDelegate::IOHandlerComplete(IOHandler &io_handler,
+ const char *current_line,
+ const char *cursor,
+ const char *last_char,
+ int skip_first_n_matches,
+ int max_matches, StringList &matches) {
+ switch (m_completion) {
+ case Completion::None:
+ break;
+
+ case Completion::LLDBCommand:
+ return io_handler.GetDebugger().GetCommandInterpreter().HandleCompletion(
+ current_line, cursor, last_char, skip_first_n_matches, max_matches,
+ matches);
+
+ case Completion::Expression: {
+ bool word_complete = false;
+ const char *word_start = cursor;
+ if (cursor > current_line)
+ --word_start;
+ while (word_start > current_line && !isspace(*word_start))
+ --word_start;
+ CommandCompletions::InvokeCommonCompletionCallbacks(
+ io_handler.GetDebugger().GetCommandInterpreter(),
+ CommandCompletions::eVariablePathCompletion, word_start,
+ skip_first_n_matches, max_matches, nullptr, word_complete, matches);
+
+ size_t num_matches = matches.GetSize();
+ if (num_matches > 0) {
+ std::string common_prefix;
+ matches.LongestCommonPrefix(common_prefix);
+ const size_t partial_name_len = strlen(word_start);
+
+ // If we matched a unique single command, add a space...
+ // Only do this if the completer told us this was a complete word,
+ // however...
+ if (num_matches == 1 && word_complete) {
+ common_prefix.push_back(' ');
+ }
+ common_prefix.erase(0, partial_name_len);
+ matches.InsertStringAtIndex(0, std::move(common_prefix));
+ }
+ return num_matches;
+ } break;
+ }
+
+ return 0;
+}
+
+IOHandlerEditline::IOHandlerEditline(
+ Debugger &debugger, IOHandler::Type type,
+ const char *editline_name, // Used for saving history files
+ const char *prompt, const char *continuation_prompt, bool multi_line,
+ bool color_prompts, uint32_t line_number_start, IOHandlerDelegate &delegate)
+ : IOHandlerEditline(debugger, type,
+ StreamFileSP(), // Inherit input from top input reader
+ StreamFileSP(), // Inherit output from top input reader
+ StreamFileSP(), // Inherit error from top input reader
+ 0, // Flags
+ editline_name, // Used for saving history files
+ prompt, continuation_prompt, multi_line, color_prompts,
+ line_number_start, delegate) {}
+
+IOHandlerEditline::IOHandlerEditline(
+ Debugger &debugger, IOHandler::Type type,
+ const lldb::StreamFileSP &input_sp, const lldb::StreamFileSP &output_sp,
+ const lldb::StreamFileSP &error_sp, uint32_t flags,
+ const char *editline_name, // Used for saving history files
+ const char *prompt, const char *continuation_prompt, bool multi_line,
+ bool color_prompts, uint32_t line_number_start, IOHandlerDelegate &delegate)
+ : IOHandler(debugger, type, input_sp, output_sp, error_sp, flags),
#ifndef LLDB_DISABLE_LIBEDIT
- m_editline_ap (),
+ m_editline_ap(),
#endif
- m_delegate (delegate),
- m_prompt (),
- m_continuation_prompt(),
- m_current_lines_ptr(nullptr),
- m_base_line_number (line_number_start),
- m_curr_line_idx (UINT32_MAX),
- m_multi_line (multi_line),
- m_color_prompts (color_prompts),
- m_interrupt_exits (true),
- m_editing (false)
-{
- SetPrompt(prompt);
+ m_delegate(delegate), m_prompt(), m_continuation_prompt(),
+ m_current_lines_ptr(nullptr), m_base_line_number(line_number_start),
+ m_curr_line_idx(UINT32_MAX), m_multi_line(multi_line),
+ m_color_prompts(color_prompts), m_interrupt_exits(true),
+ m_editing(false) {
+ SetPrompt(prompt);
#ifndef LLDB_DISABLE_LIBEDIT
- bool use_editline = false;
-
- use_editline = m_input_sp->GetFile().GetIsRealTerminal();
+ bool use_editline = false;
- if (use_editline)
- {
- m_editline_ap.reset(new Editline (editline_name,
- GetInputFILE (),
- GetOutputFILE (),
- GetErrorFILE (),
- m_color_prompts));
- m_editline_ap->SetIsInputCompleteCallback (IsInputCompleteCallback, this);
- m_editline_ap->SetAutoCompleteCallback (AutoCompleteCallback, this);
- // See if the delegate supports fixing indentation
- const char *indent_chars = delegate.IOHandlerGetFixIndentationCharacters();
- if (indent_chars)
- {
- // The delegate does support indentation, hook it up so when any indentation
- // character is typed, the delegate gets a chance to fix it
- m_editline_ap->SetFixIndentationCallback (FixIndentationCallback, this, indent_chars);
- }
+ use_editline = m_input_sp->GetFile().GetIsRealTerminal();
+
+ if (use_editline) {
+ m_editline_ap.reset(new Editline(editline_name, GetInputFILE(),
+ GetOutputFILE(), GetErrorFILE(),
+ m_color_prompts));
+ m_editline_ap->SetIsInputCompleteCallback(IsInputCompleteCallback, this);
+ m_editline_ap->SetAutoCompleteCallback(AutoCompleteCallback, this);
+ // See if the delegate supports fixing indentation
+ const char *indent_chars = delegate.IOHandlerGetFixIndentationCharacters();
+ if (indent_chars) {
+ // The delegate does support indentation, hook it up so when any
+ // indentation
+ // character is typed, the delegate gets a chance to fix it
+ m_editline_ap->SetFixIndentationCallback(FixIndentationCallback, this,
+ indent_chars);
}
+ }
#endif
- SetBaseLineNumber (m_base_line_number);
- SetPrompt(prompt ? prompt : "");
- SetContinuationPrompt(continuation_prompt);
+ SetBaseLineNumber(m_base_line_number);
+ SetPrompt(prompt ? prompt : "");
+ SetContinuationPrompt(continuation_prompt);
}
-IOHandlerEditline::~IOHandlerEditline ()
-{
+IOHandlerEditline::~IOHandlerEditline() {
#ifndef LLDB_DISABLE_LIBEDIT
- m_editline_ap.reset();
+ m_editline_ap.reset();
#endif
}
-void
-IOHandlerEditline::Activate ()
-{
- IOHandler::Activate();
- m_delegate.IOHandlerActivated(*this);
-}
-
-void
-IOHandlerEditline::Deactivate ()
-{
- IOHandler::Deactivate();
- m_delegate.IOHandlerDeactivated(*this);
-}
-
-bool
-IOHandlerEditline::GetLine (std::string &line, bool &interrupted)
-{
+void IOHandlerEditline::Activate() {
+ IOHandler::Activate();
+ m_delegate.IOHandlerActivated(*this);
+}
+
+void IOHandlerEditline::Deactivate() {
+ IOHandler::Deactivate();
+ m_delegate.IOHandlerDeactivated(*this);
+}
+
+bool IOHandlerEditline::GetLine(std::string &line, bool &interrupted) {
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- {
- return m_editline_ap->GetLine (line, interrupted);
- }
- else
- {
+ if (m_editline_ap) {
+ return m_editline_ap->GetLine(line, interrupted);
+ } else {
#endif
- line.clear();
+ line.clear();
- FILE *in = GetInputFILE();
- if (in)
- {
- if (GetIsInteractive())
- {
- const char *prompt = nullptr;
-
- if (m_multi_line && m_curr_line_idx > 0)
- prompt = GetContinuationPrompt();
-
- if (prompt == nullptr)
- prompt = GetPrompt();
-
- if (prompt && prompt[0])
- {
- FILE *out = GetOutputFILE();
- if (out)
- {
- ::fprintf(out, "%s", prompt);
- ::fflush(out);
- }
- }
- }
- char buffer[256];
- bool done = false;
- bool got_line = false;
- m_editing = true;
- while (!done)
- {
- if (fgets(buffer, sizeof(buffer), in) == nullptr)
- {
- const int saved_errno = errno;
- if (feof(in))
- done = true;
- else if (ferror(in))
- {
- if (saved_errno != EINTR)
- done = true;
- }
- }
- else
- {
- got_line = true;
- size_t buffer_len = strlen(buffer);
- assert (buffer[buffer_len] == '\0');
- char last_char = buffer[buffer_len-1];
- if (last_char == '\r' || last_char == '\n')
- {
- done = true;
- // Strip trailing newlines
- while (last_char == '\r' || last_char == '\n')
- {
- --buffer_len;
- if (buffer_len == 0)
- break;
- last_char = buffer[buffer_len-1];
- }
- }
- line.append(buffer, buffer_len);
- }
+ FILE *in = GetInputFILE();
+ if (in) {
+ if (GetIsInteractive()) {
+ const char *prompt = nullptr;
+
+ if (m_multi_line && m_curr_line_idx > 0)
+ prompt = GetContinuationPrompt();
+
+ if (prompt == nullptr)
+ prompt = GetPrompt();
+
+ if (prompt && prompt[0]) {
+ FILE *out = GetOutputFILE();
+ if (out) {
+ ::fprintf(out, "%s", prompt);
+ ::fflush(out);
+ }
+ }
+ }
+ char buffer[256];
+ bool done = false;
+ bool got_line = false;
+ m_editing = true;
+ while (!done) {
+ if (fgets(buffer, sizeof(buffer), in) == nullptr) {
+ const int saved_errno = errno;
+ if (feof(in))
+ done = true;
+ else if (ferror(in)) {
+ if (saved_errno != EINTR)
+ done = true;
+ }
+ } else {
+ got_line = true;
+ size_t buffer_len = strlen(buffer);
+ assert(buffer[buffer_len] == '\0');
+ char last_char = buffer[buffer_len - 1];
+ if (last_char == '\r' || last_char == '\n') {
+ done = true;
+ // Strip trailing newlines
+ while (last_char == '\r' || last_char == '\n') {
+ --buffer_len;
+ if (buffer_len == 0)
+ break;
+ last_char = buffer[buffer_len - 1];
}
- m_editing = false;
- // We might have gotten a newline on a line by itself
- // make sure to return true in this case.
- return got_line;
- }
- else
- {
- // No more input file, we are done...
- SetIsDone(true);
+ }
+ line.append(buffer, buffer_len);
}
- return false;
-#ifndef LLDB_DISABLE_LIBEDIT
+ }
+ m_editing = false;
+ // We might have gotten a newline on a line by itself
+ // make sure to return true in this case.
+ return got_line;
+ } else {
+ // No more input file, we are done...
+ SetIsDone(true);
}
+ return false;
+#ifndef LLDB_DISABLE_LIBEDIT
+ }
#endif
}
#ifndef LLDB_DISABLE_LIBEDIT
-bool
-IOHandlerEditline::IsInputCompleteCallback (Editline *editline,
- StringList &lines,
- void *baton)
-{
- IOHandlerEditline *editline_reader = (IOHandlerEditline *) baton;
- return editline_reader->m_delegate.IOHandlerIsInputComplete(*editline_reader, lines);
-}
-
-int
-IOHandlerEditline::FixIndentationCallback (Editline *editline,
- const StringList &lines,
- int cursor_position,
- void *baton)
-{
- IOHandlerEditline *editline_reader = (IOHandlerEditline *) baton;
- return editline_reader->m_delegate.IOHandlerFixIndentation(*editline_reader, lines, cursor_position);
-}
-
-int
-IOHandlerEditline::AutoCompleteCallback (const char *current_line,
- const char *cursor,
- const char *last_char,
- int skip_first_n_matches,
- int max_matches,
- StringList &matches,
- void *baton)
-{
- IOHandlerEditline *editline_reader = (IOHandlerEditline *) baton;
- if (editline_reader)
- return editline_reader->m_delegate.IOHandlerComplete (*editline_reader,
- current_line,
- cursor,
- last_char,
- skip_first_n_matches,
- max_matches,
- matches);
- return 0;
+bool IOHandlerEditline::IsInputCompleteCallback(Editline *editline,
+ StringList &lines,
+ void *baton) {
+ IOHandlerEditline *editline_reader = (IOHandlerEditline *)baton;
+ return editline_reader->m_delegate.IOHandlerIsInputComplete(*editline_reader,
+ lines);
+}
+
+int IOHandlerEditline::FixIndentationCallback(Editline *editline,
+ const StringList &lines,
+ int cursor_position,
+ void *baton) {
+ IOHandlerEditline *editline_reader = (IOHandlerEditline *)baton;
+ return editline_reader->m_delegate.IOHandlerFixIndentation(
+ *editline_reader, lines, cursor_position);
+}
+
+int IOHandlerEditline::AutoCompleteCallback(const char *current_line,
+ const char *cursor,
+ const char *last_char,
+ int skip_first_n_matches,
+ int max_matches,
+ StringList &matches, void *baton) {
+ IOHandlerEditline *editline_reader = (IOHandlerEditline *)baton;
+ if (editline_reader)
+ return editline_reader->m_delegate.IOHandlerComplete(
+ *editline_reader, current_line, cursor, last_char, skip_first_n_matches,
+ max_matches, matches);
+ return 0;
}
#endif
-const char *
-IOHandlerEditline::GetPrompt ()
-{
+const char *IOHandlerEditline::GetPrompt() {
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- {
- return m_editline_ap->GetPrompt ();
- }
- else
- {
+ if (m_editline_ap) {
+ return m_editline_ap->GetPrompt();
+ } else {
#endif
- if (m_prompt.empty())
- return nullptr;
+ if (m_prompt.empty())
+ return nullptr;
#ifndef LLDB_DISABLE_LIBEDIT
- }
+ }
#endif
- return m_prompt.c_str();
+ return m_prompt.c_str();
}
-bool
-IOHandlerEditline::SetPrompt (const char *p)
-{
- if (p && p[0])
- m_prompt = p;
- else
- m_prompt.clear();
+bool IOHandlerEditline::SetPrompt(const char *p) {
+ if (p && p[0])
+ m_prompt = p;
+ else
+ m_prompt.clear();
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- m_editline_ap->SetPrompt(m_prompt.empty() ? nullptr : m_prompt.c_str());
+ if (m_editline_ap)
+ m_editline_ap->SetPrompt(m_prompt.empty() ? nullptr : m_prompt.c_str());
#endif
- return true;
+ return true;
}
-const char *
-IOHandlerEditline::GetContinuationPrompt ()
-{
- return (m_continuation_prompt.empty() ? nullptr : m_continuation_prompt.c_str());
+const char *IOHandlerEditline::GetContinuationPrompt() {
+ return (m_continuation_prompt.empty() ? nullptr
+ : m_continuation_prompt.c_str());
}
-void
-IOHandlerEditline::SetContinuationPrompt (const char *p)
-{
- if (p && p[0])
- m_continuation_prompt = p;
- else
- m_continuation_prompt.clear();
+void IOHandlerEditline::SetContinuationPrompt(const char *p) {
+ if (p && p[0])
+ m_continuation_prompt = p;
+ else
+ m_continuation_prompt.clear();
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- m_editline_ap->SetContinuationPrompt(m_continuation_prompt.empty() ? nullptr : m_continuation_prompt.c_str());
+ if (m_editline_ap)
+ m_editline_ap->SetContinuationPrompt(m_continuation_prompt.empty()
+ ? nullptr
+ : m_continuation_prompt.c_str());
#endif
}
-void
-IOHandlerEditline::SetBaseLineNumber (uint32_t line)
-{
- m_base_line_number = line;
+void IOHandlerEditline::SetBaseLineNumber(uint32_t line) {
+ m_base_line_number = line;
}
-uint32_t
-IOHandlerEditline::GetCurrentLineIndex () const
-{
+uint32_t IOHandlerEditline::GetCurrentLineIndex() const {
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- return m_editline_ap->GetCurrentLine();
+ if (m_editline_ap)
+ return m_editline_ap->GetCurrentLine();
#endif
- return m_curr_line_idx;
+ return m_curr_line_idx;
}
-bool
-IOHandlerEditline::GetLines (StringList &lines, bool &interrupted)
-{
- m_current_lines_ptr = &lines;
-
- bool success = false;
+bool IOHandlerEditline::GetLines(StringList &lines, bool &interrupted) {
+ m_current_lines_ptr = &lines;
+
+ bool success = false;
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- {
- return m_editline_ap->GetLines (m_base_line_number, lines, interrupted);
- }
- else
- {
+ if (m_editline_ap) {
+ return m_editline_ap->GetLines(m_base_line_number, lines, interrupted);
+ } else {
#endif
- bool done = false;
- Error error;
+ bool done = false;
+ Error error;
- while (!done)
- {
- // Show line numbers if we are asked to
- std::string line;
- if (m_base_line_number > 0 && GetIsInteractive())
- {
- FILE *out = GetOutputFILE();
- if (out)
- ::fprintf(out, "%u%s", m_base_line_number + (uint32_t)lines.GetSize(), GetPrompt() == nullptr ? " " : "");
- }
-
- m_curr_line_idx = lines.GetSize();
-
- bool interrupted = false;
- if (GetLine(line, interrupted) && !interrupted)
- {
- lines.AppendString(line);
- done = m_delegate.IOHandlerIsInputComplete(*this, lines);
- }
- else
- {
- done = true;
- }
- }
- success = lines.GetSize() > 0;
-#ifndef LLDB_DISABLE_LIBEDIT
+ while (!done) {
+ // Show line numbers if we are asked to
+ std::string line;
+ if (m_base_line_number > 0 && GetIsInteractive()) {
+ FILE *out = GetOutputFILE();
+ if (out)
+ ::fprintf(out, "%u%s", m_base_line_number + (uint32_t)lines.GetSize(),
+ GetPrompt() == nullptr ? " " : "");
+ }
+
+ m_curr_line_idx = lines.GetSize();
+
+ bool interrupted = false;
+ if (GetLine(line, interrupted) && !interrupted) {
+ lines.AppendString(line);
+ done = m_delegate.IOHandlerIsInputComplete(*this, lines);
+ } else {
+ done = true;
+ }
}
+ success = lines.GetSize() > 0;
+#ifndef LLDB_DISABLE_LIBEDIT
+ }
#endif
- return success;
+ return success;
}
// Each IOHandler gets to run until it is done. It should read data
// from the "in" and place output into "out" and "err and return
// when done.
-void
-IOHandlerEditline::Run ()
-{
- std::string line;
- while (IsActive())
- {
- bool interrupted = false;
- if (m_multi_line)
- {
- StringList lines;
- if (GetLines (lines, interrupted))
- {
- if (interrupted)
- {
- m_done = m_interrupt_exits;
- m_delegate.IOHandlerInputInterrupted (*this, line);
-
- }
- else
- {
- line = lines.CopyList();
- m_delegate.IOHandlerInputComplete (*this, line);
- }
- }
- else
- {
- m_done = true;
- }
- }
+void IOHandlerEditline::Run() {
+ std::string line;
+ while (IsActive()) {
+ bool interrupted = false;
+ if (m_multi_line) {
+ StringList lines;
+ if (GetLines(lines, interrupted)) {
+ if (interrupted) {
+ m_done = m_interrupt_exits;
+ m_delegate.IOHandlerInputInterrupted(*this, line);
+
+ } else {
+ line = lines.CopyList();
+ m_delegate.IOHandlerInputComplete(*this, line);
+ }
+ } else {
+ m_done = true;
+ }
+ } else {
+ if (GetLine(line, interrupted)) {
+ if (interrupted)
+ m_delegate.IOHandlerInputInterrupted(*this, line);
else
- {
- if (GetLine(line, interrupted))
- {
- if (interrupted)
- m_delegate.IOHandlerInputInterrupted (*this, line);
- else
- m_delegate.IOHandlerInputComplete (*this, line);
- }
- else
- {
- m_done = true;
- }
- }
+ m_delegate.IOHandlerInputComplete(*this, line);
+ } else {
+ m_done = true;
+ }
}
+ }
}
-void
-IOHandlerEditline::Cancel ()
-{
+void IOHandlerEditline::Cancel() {
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- m_editline_ap->Cancel ();
+ if (m_editline_ap)
+ m_editline_ap->Cancel();
#endif
}
-bool
-IOHandlerEditline::Interrupt ()
-{
- // Let the delgate handle it first
- if (m_delegate.IOHandlerInterrupt(*this))
- return true;
+bool IOHandlerEditline::Interrupt() {
+ // Let the delgate handle it first
+ if (m_delegate.IOHandlerInterrupt(*this))
+ return true;
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- return m_editline_ap->Interrupt();
+ if (m_editline_ap)
+ return m_editline_ap->Interrupt();
#endif
- return false;
+ return false;
}
-void
-IOHandlerEditline::GotEOF()
-{
+void IOHandlerEditline::GotEOF() {
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- m_editline_ap->Interrupt();
+ if (m_editline_ap)
+ m_editline_ap->Interrupt();
#endif
}
-void
-IOHandlerEditline::PrintAsync (Stream *stream, const char *s, size_t len)
-{
+void IOHandlerEditline::PrintAsync(Stream *stream, const char *s, size_t len) {
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- m_editline_ap->PrintAsync(stream, s, len);
- else
+ if (m_editline_ap)
+ m_editline_ap->PrintAsync(stream, s, len);
+ else
#endif
- {
- const char *prompt = GetPrompt();
+ {
+ const char *prompt = GetPrompt();
#ifdef _MSC_VER
- if (prompt)
- {
- // Back up over previous prompt using Windows API
- CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
- HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
- GetConsoleScreenBufferInfo(console_handle, &screen_buffer_info);
- COORD coord = screen_buffer_info.dwCursorPosition;
- coord.X -= strlen(prompt);
- if (coord.X < 0)
- coord.X = 0;
- SetConsoleCursorPosition(console_handle, coord);
- }
-#endif
- IOHandler::PrintAsync(stream, s, len);
- if (prompt)
- IOHandler::PrintAsync(GetOutputStreamFile().get(), prompt, strlen(prompt));
+ if (prompt) {
+ // Back up over previous prompt using Windows API
+ CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
+ HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
+ GetConsoleScreenBufferInfo(console_handle, &screen_buffer_info);
+ COORD coord = screen_buffer_info.dwCursorPosition;
+ coord.X -= strlen(prompt);
+ if (coord.X < 0)
+ coord.X = 0;
+ SetConsoleCursorPosition(console_handle, coord);
}
+#endif
+ IOHandler::PrintAsync(stream, s, len);
+ if (prompt)
+ IOHandler::PrintAsync(GetOutputStreamFile().get(), prompt,
+ strlen(prompt));
+ }
}
// we may want curses to be disabled for some builds
// for instance, windows
#ifndef LLDB_DISABLE_CURSES
-#define KEY_RETURN 10
-#define KEY_ESCAPE 27
+#define KEY_RETURN 10
+#define KEY_ESCAPE 27
-namespace curses
-{
- class Menu;
- class MenuDelegate;
- class Window;
- class WindowDelegate;
- typedef std::shared_ptr<Menu> MenuSP;
- typedef std::shared_ptr<MenuDelegate> MenuDelegateSP;
- typedef std::shared_ptr<Window> WindowSP;
- typedef std::shared_ptr<WindowDelegate> WindowDelegateSP;
- typedef std::vector<MenuSP> Menus;
- typedef std::vector<WindowSP> Windows;
- typedef std::vector<WindowDelegateSP> WindowDelegates;
+namespace curses {
+class Menu;
+class MenuDelegate;
+class Window;
+class WindowDelegate;
+typedef std::shared_ptr<Menu> MenuSP;
+typedef std::shared_ptr<MenuDelegate> MenuDelegateSP;
+typedef std::shared_ptr<Window> WindowSP;
+typedef std::shared_ptr<WindowDelegate> WindowDelegateSP;
+typedef std::vector<MenuSP> Menus;
+typedef std::vector<WindowSP> Windows;
+typedef std::vector<WindowDelegateSP> WindowDelegates;
#if 0
type summary add -s "x=${var.x}, y=${var.y}" curses::Point
@@ -826,4754 +640,4009 @@ type summary add -s "w=${var.width}, h=$
type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
#endif
- struct Point
- {
- int x;
- int y;
-
- Point (int _x = 0, int _y = 0) :
- x(_x),
- y(_y)
- {
- }
-
- void
- Clear ()
- {
- x = 0;
- y = 0;
- }
-
- Point &
- operator += (const Point &rhs)
- {
- x += rhs.x;
- y += rhs.y;
- return *this;
- }
-
- void
- Dump ()
- {
- printf ("(x=%i, y=%i)\n", x, y);
- }
- };
-
- bool operator == (const Point &lhs, const Point &rhs)
- {
- return lhs.x == rhs.x && lhs.y == rhs.y;
- }
+struct Point {
+ int x;
+ int y;
+
+ Point(int _x = 0, int _y = 0) : x(_x), y(_y) {}
+
+ void Clear() {
+ x = 0;
+ y = 0;
+ }
+
+ Point &operator+=(const Point &rhs) {
+ x += rhs.x;
+ y += rhs.y;
+ return *this;
+ }
- bool operator != (const Point &lhs, const Point &rhs)
- {
- return lhs.x != rhs.x || lhs.y != rhs.y;
- }
+ void Dump() { printf("(x=%i, y=%i)\n", x, y); }
+};
- struct Size
- {
- int width;
- int height;
- Size (int w = 0, int h = 0) :
- width (w),
- height (h)
- {
- }
-
- void
- Clear ()
- {
- width = 0;
- height = 0;
- }
-
- void
- Dump ()
- {
- printf ("(w=%i, h=%i)\n", width, height);
- }
- };
-
- bool operator == (const Size &lhs, const Size &rhs)
- {
- return lhs.width == rhs.width && lhs.height == rhs.height;
- }
+bool operator==(const Point &lhs, const Point &rhs) {
+ return lhs.x == rhs.x && lhs.y == rhs.y;
+}
- bool operator != (const Size &lhs, const Size &rhs)
- {
- return lhs.width != rhs.width || lhs.height != rhs.height;
- }
+bool operator!=(const Point &lhs, const Point &rhs) {
+ return lhs.x != rhs.x || lhs.y != rhs.y;
+}
- struct Rect
- {
- Point origin;
- Size size;
-
- Rect () :
- origin(),
- size()
- {
- }
-
- Rect (const Point &p, const Size &s) :
- origin (p),
- size (s)
- {
- }
-
- void
- Clear ()
- {
- origin.Clear();
- size.Clear();
- }
-
- void
- Dump ()
- {
- printf ("(x=%i, y=%i), w=%i, h=%i)\n", origin.x, origin.y, size.width, size.height);
- }
-
- void
- Inset (int w, int h)
- {
- if (size.width > w*2)
- size.width -= w*2;
- origin.x += w;
-
- if (size.height > h*2)
- size.height -= h*2;
- origin.y += h;
- }
-
- // Return a status bar rectangle which is the last line of
- // this rectangle. This rectangle will be modified to not
- // include the status bar area.
- Rect
- MakeStatusBar ()
- {
- Rect status_bar;
- if (size.height > 1)
- {
- status_bar.origin.x = origin.x;
- status_bar.origin.y = size.height;
- status_bar.size.width = size.width;
- status_bar.size.height = 1;
- --size.height;
- }
- return status_bar;
- }
+struct Size {
+ int width;
+ int height;
+ Size(int w = 0, int h = 0) : width(w), height(h) {}
- // Return a menubar rectangle which is the first line of
- // this rectangle. This rectangle will be modified to not
- // include the menubar area.
- Rect
- MakeMenuBar ()
- {
- Rect menubar;
- if (size.height > 1)
- {
- menubar.origin.x = origin.x;
- menubar.origin.y = origin.y;
- menubar.size.width = size.width;
- menubar.size.height = 1;
- ++origin.y;
- --size.height;
- }
- return menubar;
- }
+ void Clear() {
+ width = 0;
+ height = 0;
+ }
- void
- HorizontalSplitPercentage (float top_percentage, Rect &top, Rect &bottom) const
- {
- float top_height = top_percentage * size.height;
- HorizontalSplit (top_height, top, bottom);
- }
-
- void
- HorizontalSplit (int top_height, Rect &top, Rect &bottom) const
- {
- top = *this;
- if (top_height < size.height)
- {
- top.size.height = top_height;
- bottom.origin.x = origin.x;
- bottom.origin.y = origin.y + top.size.height;
- bottom.size.width = size.width;
- bottom.size.height = size.height - top.size.height;
- }
- else
- {
- bottom.Clear();
- }
- }
-
- void
- VerticalSplitPercentage (float left_percentage, Rect &left, Rect &right) const
- {
- float left_width = left_percentage * size.width;
- VerticalSplit (left_width, left, right);
- }
-
- void
- VerticalSplit (int left_width, Rect &left, Rect &right) const
- {
- left = *this;
- if (left_width < size.width)
- {
- left.size.width = left_width;
- right.origin.x = origin.x + left.size.width;
- right.origin.y = origin.y;
- right.size.width = size.width - left.size.width;
- right.size.height = size.height;
- }
- else
- {
- right.Clear();
- }
- }
- };
+ void Dump() { printf("(w=%i, h=%i)\n", width, height); }
+};
- bool operator == (const Rect &lhs, const Rect &rhs)
- {
- return lhs.origin == rhs.origin && lhs.size == rhs.size;
- }
+bool operator==(const Size &lhs, const Size &rhs) {
+ return lhs.width == rhs.width && lhs.height == rhs.height;
+}
- bool operator != (const Rect &lhs, const Rect &rhs)
- {
- return lhs.origin != rhs.origin || lhs.size != rhs.size;
+bool operator!=(const Size &lhs, const Size &rhs) {
+ return lhs.width != rhs.width || lhs.height != rhs.height;
+}
+
+struct Rect {
+ Point origin;
+ Size size;
+
+ Rect() : origin(), size() {}
+
+ Rect(const Point &p, const Size &s) : origin(p), size(s) {}
+
+ void Clear() {
+ origin.Clear();
+ size.Clear();
+ }
+
+ void Dump() {
+ printf("(x=%i, y=%i), w=%i, h=%i)\n", origin.x, origin.y, size.width,
+ size.height);
+ }
+
+ void Inset(int w, int h) {
+ if (size.width > w * 2)
+ size.width -= w * 2;
+ origin.x += w;
+
+ if (size.height > h * 2)
+ size.height -= h * 2;
+ origin.y += h;
+ }
+
+ // Return a status bar rectangle which is the last line of
+ // this rectangle. This rectangle will be modified to not
+ // include the status bar area.
+ Rect MakeStatusBar() {
+ Rect status_bar;
+ if (size.height > 1) {
+ status_bar.origin.x = origin.x;
+ status_bar.origin.y = size.height;
+ status_bar.size.width = size.width;
+ status_bar.size.height = 1;
+ --size.height;
+ }
+ return status_bar;
+ }
+
+ // Return a menubar rectangle which is the first line of
+ // this rectangle. This rectangle will be modified to not
+ // include the menubar area.
+ Rect MakeMenuBar() {
+ Rect menubar;
+ if (size.height > 1) {
+ menubar.origin.x = origin.x;
+ menubar.origin.y = origin.y;
+ menubar.size.width = size.width;
+ menubar.size.height = 1;
+ ++origin.y;
+ --size.height;
+ }
+ return menubar;
+ }
+
+ void HorizontalSplitPercentage(float top_percentage, Rect &top,
+ Rect &bottom) const {
+ float top_height = top_percentage * size.height;
+ HorizontalSplit(top_height, top, bottom);
+ }
+
+ void HorizontalSplit(int top_height, Rect &top, Rect &bottom) const {
+ top = *this;
+ if (top_height < size.height) {
+ top.size.height = top_height;
+ bottom.origin.x = origin.x;
+ bottom.origin.y = origin.y + top.size.height;
+ bottom.size.width = size.width;
+ bottom.size.height = size.height - top.size.height;
+ } else {
+ bottom.Clear();
+ }
+ }
+
+ void VerticalSplitPercentage(float left_percentage, Rect &left,
+ Rect &right) const {
+ float left_width = left_percentage * size.width;
+ VerticalSplit(left_width, left, right);
+ }
+
+ void VerticalSplit(int left_width, Rect &left, Rect &right) const {
+ left = *this;
+ if (left_width < size.width) {
+ left.size.width = left_width;
+ right.origin.x = origin.x + left.size.width;
+ right.origin.y = origin.y;
+ right.size.width = size.width - left.size.width;
+ right.size.height = size.height;
+ } else {
+ right.Clear();
}
+ }
+};
- enum HandleCharResult
- {
- eKeyNotHandled = 0,
- eKeyHandled = 1,
- eQuitApplication = 2
- };
-
- enum class MenuActionResult
- {
- Handled,
- NotHandled,
- Quit // Exit all menus and quit
- };
+bool operator==(const Rect &lhs, const Rect &rhs) {
+ return lhs.origin == rhs.origin && lhs.size == rhs.size;
+}
- struct KeyHelp
- {
- int ch;
- const char *description;
- };
+bool operator!=(const Rect &lhs, const Rect &rhs) {
+ return lhs.origin != rhs.origin || lhs.size != rhs.size;
+}
- class WindowDelegate
- {
- public:
- virtual
- ~WindowDelegate() = default;
-
- virtual bool
- WindowDelegateDraw (Window &window, bool force)
- {
- return false; // Drawing not handled
- }
-
- virtual HandleCharResult
- WindowDelegateHandleChar (Window &window, int key)
- {
- return eKeyNotHandled;
- }
-
- virtual const char *
- WindowDelegateGetHelpText ()
- {
- return nullptr;
- }
-
- virtual KeyHelp *
- WindowDelegateGetKeyHelp ()
- {
- return nullptr;
- }
- };
-
- class HelpDialogDelegate :
- public WindowDelegate
- {
- public:
- HelpDialogDelegate (const char *text, KeyHelp *key_help_array);
+enum HandleCharResult {
+ eKeyNotHandled = 0,
+ eKeyHandled = 1,
+ eQuitApplication = 2
+};
- ~HelpDialogDelegate() override;
+enum class MenuActionResult {
+ Handled,
+ NotHandled,
+ Quit // Exit all menus and quit
+};
- bool
- WindowDelegateDraw (Window &window, bool force) override;
-
- HandleCharResult
- WindowDelegateHandleChar (Window &window, int key) override;
-
- size_t
- GetNumLines() const
- {
- return m_text.GetSize();
- }
-
- size_t
- GetMaxLineLength () const
- {
- return m_text.GetMaxStringLength();
- }
-
- protected:
- StringList m_text;
- int m_first_visible_line;
- };
+struct KeyHelp {
+ int ch;
+ const char *description;
+};
- class Window
- {
- public:
- Window (const char *name) :
- m_name (name),
- m_window(nullptr),
- m_panel(nullptr),
- m_parent(nullptr),
- m_subwindows (),
- m_delegate_sp (),
- m_curr_active_window_idx (UINT32_MAX),
- m_prev_active_window_idx (UINT32_MAX),
- m_delete (false),
- m_needs_update (true),
- m_can_activate (true),
- m_is_subwin (false)
- {
- }
-
- Window (const char *name, WINDOW *w, bool del = true) :
- m_name (name),
- m_window(nullptr),
- m_panel(nullptr),
- m_parent(nullptr),
- m_subwindows (),
- m_delegate_sp (),
- m_curr_active_window_idx (UINT32_MAX),
- m_prev_active_window_idx (UINT32_MAX),
- m_delete (del),
- m_needs_update (true),
- m_can_activate (true),
- m_is_subwin (false)
- {
- if (w)
- Reset(w);
- }
-
- Window (const char *name, const Rect &bounds) :
- m_name (name),
- m_window(nullptr),
- m_parent(nullptr),
- m_subwindows (),
- m_delegate_sp (),
- m_curr_active_window_idx (UINT32_MAX),
- m_prev_active_window_idx (UINT32_MAX),
- m_delete (true),
- m_needs_update (true),
- m_can_activate (true),
- m_is_subwin (false)
- {
- Reset (::newwin (bounds.size.height, bounds.size.width, bounds.origin.y, bounds.origin.y));
- }
-
- virtual
- ~Window ()
- {
- RemoveSubWindows ();
- Reset ();
- }
-
- void
- Reset(WINDOW *w = nullptr, bool del = true)
- {
- if (m_window == w)
- return;
-
- if (m_panel)
- {
- ::del_panel (m_panel);
- m_panel = nullptr;
- }
- if (m_window && m_delete)
- {
- ::delwin (m_window);
- m_window = nullptr;
- m_delete = false;
- }
- if (w)
- {
- m_window = w;
- m_panel = ::new_panel (m_window);
- m_delete = del;
- }
- }
-
- void AttributeOn (attr_t attr) { ::wattron (m_window, attr); }
- void AttributeOff (attr_t attr) { ::wattroff (m_window, attr); }
- void Box (chtype v_char = ACS_VLINE, chtype h_char = ACS_HLINE) { ::box(m_window, v_char, h_char); }
- void Clear () { ::wclear (m_window); }
- void Erase () { ::werase (m_window); }
- Rect GetBounds () { return Rect (GetParentOrigin(), GetSize()); } // Get the rectangle in our parent window
- int GetChar () { return ::wgetch (m_window); }
- int GetCursorX () { return getcurx (m_window); }
- int GetCursorY () { return getcury (m_window); }
- Rect GetFrame () { return Rect (Point(), GetSize()); } // Get our rectangle in our own coordinate system
- Point GetParentOrigin() { return Point (GetParentX(), GetParentY()); }
- Size GetSize() { return Size (GetWidth(), GetHeight()); }
- int GetParentX () { return getparx (m_window); }
- int GetParentY () { return getpary (m_window); }
- int GetMaxX() { return getmaxx (m_window); }
- int GetMaxY() { return getmaxy (m_window); }
- int GetWidth() { return GetMaxX(); }
- int GetHeight() { return GetMaxY(); }
- void MoveCursor (int x, int y) { ::wmove (m_window, y, x); }
- void MoveWindow (int x, int y) { MoveWindow(Point(x,y)); }
- void Resize (int w, int h) { ::wresize(m_window, h, w); }
- void Resize (const Size &size) { ::wresize(m_window, size.height, size.width); }
- void PutChar (int ch) { ::waddch (m_window, ch); }
- void PutCString (const char *s, int len = -1) { ::waddnstr (m_window, s, len); }
- void Refresh () { ::wrefresh (m_window); }
- void DeferredRefresh ()
- {
- // We are using panels, so we don't need to call this...
- //::wnoutrefresh(m_window);
- }
- void SetBackground (int color_pair_idx) { ::wbkgd (m_window,COLOR_PAIR(color_pair_idx)); }
- void UnderlineOn () { AttributeOn(A_UNDERLINE); }
- void UnderlineOff () { AttributeOff(A_UNDERLINE); }
-
- void PutCStringTruncated (const char *s, int right_pad)
- {
- int bytes_left = GetWidth() - GetCursorX();
- if (bytes_left > right_pad)
- {
- bytes_left -= right_pad;
- ::waddnstr (m_window, s, bytes_left);
- }
- }
+class WindowDelegate {
+public:
+ virtual ~WindowDelegate() = default;
- void
- MoveWindow (const Point &origin)
- {
- const bool moving_window = origin != GetParentOrigin();
- if (m_is_subwin && moving_window)
- {
- // Can't move subwindows, must delete and re-create
- Size size = GetSize();
- Reset (::subwin (m_parent->m_window,
- size.height,
- size.width,
- origin.y,
- origin.x), true);
- }
- else
- {
- ::mvwin (m_window, origin.y, origin.x);
- }
- }
+ virtual bool WindowDelegateDraw(Window &window, bool force) {
+ return false; // Drawing not handled
+ }
- void
- SetBounds (const Rect &bounds)
- {
- const bool moving_window = bounds.origin != GetParentOrigin();
- if (m_is_subwin && moving_window)
- {
- // Can't move subwindows, must delete and re-create
- Reset (::subwin (m_parent->m_window,
- bounds.size.height,
- bounds.size.width,
- bounds.origin.y,
- bounds.origin.x), true);
- }
- else
- {
- if (moving_window)
- MoveWindow(bounds.origin);
- Resize (bounds.size);
- }
- }
+ virtual HandleCharResult WindowDelegateHandleChar(Window &window, int key) {
+ return eKeyNotHandled;
+ }
- void
- Printf (const char *format, ...) __attribute__ ((format (printf, 2, 3)))
- {
- va_list args;
- va_start (args, format);
- vwprintw(m_window, format, args);
- va_end (args);
- }
-
- void
- Touch ()
- {
- ::touchwin (m_window);
- if (m_parent)
- m_parent->Touch();
- }
-
- WindowSP
- CreateSubWindow (const char *name, const Rect &bounds, bool make_active)
- {
- WindowSP subwindow_sp;
- if (m_window)
- {
- subwindow_sp.reset(new Window(name, ::subwin (m_window,
- bounds.size.height,
- bounds.size.width,
- bounds.origin.y,
- bounds.origin.x), true));
- subwindow_sp->m_is_subwin = true;
- }
- else
- {
- subwindow_sp.reset(new Window(name, ::newwin (bounds.size.height,
- bounds.size.width,
- bounds.origin.y,
- bounds.origin.x), true));
- subwindow_sp->m_is_subwin = false;
- }
- subwindow_sp->m_parent = this;
- if (make_active)
- {
- m_prev_active_window_idx = m_curr_active_window_idx;
- m_curr_active_window_idx = m_subwindows.size();
- }
- m_subwindows.push_back(subwindow_sp);
- ::top_panel (subwindow_sp->m_panel);
- m_needs_update = true;
- return subwindow_sp;
- }
-
- bool
- RemoveSubWindow (Window *window)
- {
- Windows::iterator pos, end = m_subwindows.end();
- size_t i = 0;
- for (pos = m_subwindows.begin(); pos != end; ++pos, ++i)
- {
- if ((*pos).get() == window)
- {
- if (m_prev_active_window_idx == i)
- m_prev_active_window_idx = UINT32_MAX;
- else if (m_prev_active_window_idx != UINT32_MAX && m_prev_active_window_idx > i)
- --m_prev_active_window_idx;
-
- if (m_curr_active_window_idx == i)
- m_curr_active_window_idx = UINT32_MAX;
- else if (m_curr_active_window_idx != UINT32_MAX && m_curr_active_window_idx > i)
- --m_curr_active_window_idx;
- window->Erase();
- m_subwindows.erase(pos);
- m_needs_update = true;
- if (m_parent)
- m_parent->Touch();
- else
- ::touchwin (stdscr);
- return true;
- }
- }
- return false;
- }
-
- WindowSP
- FindSubWindow (const char *name)
- {
- Windows::iterator pos, end = m_subwindows.end();
- size_t i = 0;
- for (pos = m_subwindows.begin(); pos != end; ++pos, ++i)
- {
- if ((*pos)->m_name.compare(name) == 0)
- return *pos;
- }
- return WindowSP();
- }
-
- void
- RemoveSubWindows ()
- {
- m_curr_active_window_idx = UINT32_MAX;
- m_prev_active_window_idx = UINT32_MAX;
- for (Windows::iterator pos = m_subwindows.begin();
- pos != m_subwindows.end();
- pos = m_subwindows.erase(pos))
- {
- (*pos)->Erase();
- }
- if (m_parent)
- m_parent->Touch();
- else
- ::touchwin (stdscr);
- }
-
- WINDOW *
- get()
- {
- return m_window;
- }
-
- operator WINDOW *()
- {
- return m_window;
- }
-
- //----------------------------------------------------------------------
- // Window drawing utilities
- //----------------------------------------------------------------------
- void
- DrawTitleBox(const char *title, const char *bottom_message = nullptr)
- {
- attr_t attr = 0;
- if (IsActive())
- attr = A_BOLD | COLOR_PAIR(2);
- else
- attr = 0;
- if (attr)
- AttributeOn(attr);
-
- Box();
- MoveCursor(3, 0);
-
- if (title && title[0])
- {
- PutChar ('<');
- PutCString (title);
- PutChar ('>');
- }
-
- if (bottom_message && bottom_message[0])
- {
- int bottom_message_length = strlen(bottom_message);
- int x = GetWidth() - 3 - (bottom_message_length + 2);
-
- if (x > 0)
- {
- MoveCursor (x, GetHeight() - 1);
- PutChar ('[');
- PutCString(bottom_message);
- PutChar (']');
- }
- else
- {
- MoveCursor (1, GetHeight() - 1);
- PutChar ('[');
- PutCStringTruncated (bottom_message, 1);
- }
- }
- if (attr)
- AttributeOff(attr);
- }
+ virtual const char *WindowDelegateGetHelpText() { return nullptr; }
- virtual void
- Draw (bool force)
- {
- if (m_delegate_sp && m_delegate_sp->WindowDelegateDraw (*this, force))
- return;
-
- for (auto &subwindow_sp : m_subwindows)
- subwindow_sp->Draw(force);
- }
-
- bool
- CreateHelpSubwindow ()
- {
- if (m_delegate_sp)
- {
- const char *text = m_delegate_sp->WindowDelegateGetHelpText ();
- KeyHelp *key_help = m_delegate_sp->WindowDelegateGetKeyHelp ();
- if ((text && text[0]) || key_help)
- {
- std::auto_ptr<HelpDialogDelegate> help_delegate_ap(new HelpDialogDelegate(text, key_help));
- const size_t num_lines = help_delegate_ap->GetNumLines();
- const size_t max_length = help_delegate_ap->GetMaxLineLength();
- Rect bounds = GetBounds();
- bounds.Inset(1, 1);
- if (max_length + 4 < static_cast<size_t>(bounds.size.width))
- {
- bounds.origin.x += (bounds.size.width - max_length + 4)/2;
- bounds.size.width = max_length + 4;
- }
- else
- {
- if (bounds.size.width > 100)
- {
- const int inset_w = bounds.size.width / 4;
- bounds.origin.x += inset_w;
- bounds.size.width -= 2*inset_w;
- }
- }
-
- if (num_lines + 2 < static_cast<size_t>(bounds.size.height))
- {
- bounds.origin.y += (bounds.size.height - num_lines + 2)/2;
- bounds.size.height = num_lines + 2;
- }
- else
- {
- if (bounds.size.height > 100)
- {
- const int inset_h = bounds.size.height / 4;
- bounds.origin.y += inset_h;
- bounds.size.height -= 2*inset_h;
- }
- }
- WindowSP help_window_sp;
- Window *parent_window = GetParent();
- if (parent_window)
- help_window_sp = parent_window->CreateSubWindow("Help", bounds, true);
- else
- help_window_sp = CreateSubWindow("Help", bounds, true);
- help_window_sp->SetDelegate(WindowDelegateSP(help_delegate_ap.release()));
- return true;
- }
- }
- return false;
- }
+ virtual KeyHelp *WindowDelegateGetKeyHelp() { return nullptr; }
+};
- virtual HandleCharResult
- HandleChar (int key)
- {
- // Always check the active window first
- HandleCharResult result = eKeyNotHandled;
- WindowSP active_window_sp = GetActiveWindow ();
- if (active_window_sp)
- {
- result = active_window_sp->HandleChar (key);
- if (result != eKeyNotHandled)
- return result;
- }
-
- if (m_delegate_sp)
- {
- result = m_delegate_sp->WindowDelegateHandleChar (*this, key);
- if (result != eKeyNotHandled)
- return result;
- }
+class HelpDialogDelegate : public WindowDelegate {
+public:
+ HelpDialogDelegate(const char *text, KeyHelp *key_help_array);
- // Then check for any windows that want any keys
- // that weren't handled. This is typically only
- // for a menubar.
- // Make a copy of the subwindows in case any HandleChar()
- // functions muck with the subwindows. If we don't do this,
- // we can crash when iterating over the subwindows.
- Windows subwindows (m_subwindows);
- for (auto subwindow_sp : subwindows)
- {
- if (!subwindow_sp->m_can_activate)
- {
- HandleCharResult result = subwindow_sp->HandleChar(key);
- if (result != eKeyNotHandled)
- return result;
- }
- }
+ ~HelpDialogDelegate() override;
- return eKeyNotHandled;
- }
+ bool WindowDelegateDraw(Window &window, bool force) override;
- bool
- SetActiveWindow (Window *window)
- {
- const size_t num_subwindows = m_subwindows.size();
- for (size_t i = 0; i < num_subwindows; ++i)
- {
- if (m_subwindows[i].get() == window)
- {
- m_prev_active_window_idx = m_curr_active_window_idx;
- ::top_panel (window->m_panel);
- m_curr_active_window_idx = i;
- return true;
- }
- }
- return false;
- }
+ HandleCharResult WindowDelegateHandleChar(Window &window, int key) override;
- WindowSP
- GetActiveWindow ()
- {
- if (!m_subwindows.empty())
- {
- if (m_curr_active_window_idx >= m_subwindows.size())
- {
- if (m_prev_active_window_idx < m_subwindows.size())
- {
- m_curr_active_window_idx = m_prev_active_window_idx;
- m_prev_active_window_idx = UINT32_MAX;
- }
- else if (IsActive())
- {
- m_prev_active_window_idx = UINT32_MAX;
- m_curr_active_window_idx = UINT32_MAX;
-
- // Find first window that wants to be active if this window is active
- const size_t num_subwindows = m_subwindows.size();
- for (size_t i = 0; i < num_subwindows; ++i)
- {
- if (m_subwindows[i]->GetCanBeActive())
- {
- m_curr_active_window_idx = i;
- break;
- }
- }
- }
- }
-
- if (m_curr_active_window_idx < m_subwindows.size())
- return m_subwindows[m_curr_active_window_idx];
- }
- return WindowSP();
- }
-
- bool
- GetCanBeActive () const
- {
- return m_can_activate;
- }
-
- void
- SetCanBeActive (bool b)
- {
- m_can_activate = b;
- }
-
- const WindowDelegateSP &
- GetDelegate () const
- {
- return m_delegate_sp;
- }
-
- void
- SetDelegate (const WindowDelegateSP &delegate_sp)
- {
- m_delegate_sp = delegate_sp;
- }
-
- Window *
- GetParent () const
- {
- return m_parent;
- }
-
- bool
- IsActive () const
- {
- if (m_parent)
- return m_parent->GetActiveWindow().get() == this;
- else
- return true; // Top level window is always active
- }
-
- void
- SelectNextWindowAsActive ()
- {
- // Move active focus to next window
- const size_t num_subwindows = m_subwindows.size();
- if (m_curr_active_window_idx == UINT32_MAX)
- {
- uint32_t idx = 0;
- for (auto subwindow_sp : m_subwindows)
- {
- if (subwindow_sp->GetCanBeActive())
- {
- m_curr_active_window_idx = idx;
- break;
- }
- ++idx;
- }
- }
- else if (m_curr_active_window_idx + 1 < num_subwindows)
- {
- bool handled = false;
- m_prev_active_window_idx = m_curr_active_window_idx;
- for (size_t idx=m_curr_active_window_idx + 1; idx<num_subwindows; ++idx)
- {
- if (m_subwindows[idx]->GetCanBeActive())
- {
- m_curr_active_window_idx = idx;
- handled = true;
- break;
- }
- }
- if (!handled)
- {
- for (size_t idx=0; idx<=m_prev_active_window_idx; ++idx)
- {
- if (m_subwindows[idx]->GetCanBeActive())
- {
- m_curr_active_window_idx = idx;
- break;
- }
- }
- }
- }
- else
- {
- m_prev_active_window_idx = m_curr_active_window_idx;
- for (size_t idx=0; idx<num_subwindows; ++idx)
- {
- if (m_subwindows[idx]->GetCanBeActive())
- {
- m_curr_active_window_idx = idx;
- break;
- }
- }
- }
- }
+ size_t GetNumLines() const { return m_text.GetSize(); }
- const char *
- GetName () const
- {
- return m_name.c_str();
- }
-
- protected:
- std::string m_name;
- WINDOW *m_window;
- PANEL *m_panel;
- Window *m_parent;
- Windows m_subwindows;
- WindowDelegateSP m_delegate_sp;
- uint32_t m_curr_active_window_idx;
- uint32_t m_prev_active_window_idx;
- bool m_delete;
- bool m_needs_update;
- bool m_can_activate;
- bool m_is_subwin;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Window);
- };
-
- class MenuDelegate
- {
- public:
- virtual ~MenuDelegate() = default;
+ size_t GetMaxLineLength() const { return m_text.GetMaxStringLength(); }
- virtual MenuActionResult
- MenuDelegateAction (Menu &menu) = 0;
- };
+protected:
+ StringList m_text;
+ int m_first_visible_line;
+};
- class Menu : public WindowDelegate
- {
- public:
- enum class Type
- {
- Invalid,
- Bar,
- Item,
- Separator
- };
-
- // Menubar or separator constructor
- Menu (Type type);
-
- // Menuitem constructor
- Menu (const char *name,
- const char *key_name,
- int key_value,
- uint64_t identifier);
-
- ~Menu() override = default;
-
- const MenuDelegateSP &
- GetDelegate () const
- {
- return m_delegate_sp;
- }
-
- void
- SetDelegate (const MenuDelegateSP &delegate_sp)
- {
- m_delegate_sp = delegate_sp;
- }
-
- void
- RecalculateNameLengths();
-
- void
- AddSubmenu (const MenuSP &menu_sp);
-
- int
- DrawAndRunMenu (Window &window);
-
- void
- DrawMenuTitle (Window &window, bool highlight);
-
- bool
- WindowDelegateDraw (Window &window, bool force) override;
-
- HandleCharResult
- WindowDelegateHandleChar (Window &window, int key) override;
-
- MenuActionResult
- ActionPrivate (Menu &menu)
- {
- MenuActionResult result = MenuActionResult::NotHandled;
- if (m_delegate_sp)
- {
- result = m_delegate_sp->MenuDelegateAction (menu);
- if (result != MenuActionResult::NotHandled)
- return result;
- }
- else if (m_parent)
- {
- result = m_parent->ActionPrivate(menu);
- if (result != MenuActionResult::NotHandled)
- return result;
- }
- return m_canned_result;
- }
+class Window {
+public:
+ Window(const char *name)
+ : m_name(name), m_window(nullptr), m_panel(nullptr), m_parent(nullptr),
+ m_subwindows(), m_delegate_sp(), m_curr_active_window_idx(UINT32_MAX),
+ m_prev_active_window_idx(UINT32_MAX), m_delete(false),
+ m_needs_update(true), m_can_activate(true), m_is_subwin(false) {}
+
+ Window(const char *name, WINDOW *w, bool del = true)
+ : m_name(name), m_window(nullptr), m_panel(nullptr), m_parent(nullptr),
+ m_subwindows(), m_delegate_sp(), m_curr_active_window_idx(UINT32_MAX),
+ m_prev_active_window_idx(UINT32_MAX), m_delete(del),
+ m_needs_update(true), m_can_activate(true), m_is_subwin(false) {
+ if (w)
+ Reset(w);
+ }
+
+ Window(const char *name, const Rect &bounds)
+ : m_name(name), m_window(nullptr), m_parent(nullptr), m_subwindows(),
+ m_delegate_sp(), m_curr_active_window_idx(UINT32_MAX),
+ m_prev_active_window_idx(UINT32_MAX), m_delete(true),
+ m_needs_update(true), m_can_activate(true), m_is_subwin(false) {
+ Reset(::newwin(bounds.size.height, bounds.size.width, bounds.origin.y,
+ bounds.origin.y));
+ }
+
+ virtual ~Window() {
+ RemoveSubWindows();
+ Reset();
+ }
+
+ void Reset(WINDOW *w = nullptr, bool del = true) {
+ if (m_window == w)
+ return;
+
+ if (m_panel) {
+ ::del_panel(m_panel);
+ m_panel = nullptr;
+ }
+ if (m_window && m_delete) {
+ ::delwin(m_window);
+ m_window = nullptr;
+ m_delete = false;
+ }
+ if (w) {
+ m_window = w;
+ m_panel = ::new_panel(m_window);
+ m_delete = del;
+ }
+ }
+
+ void AttributeOn(attr_t attr) { ::wattron(m_window, attr); }
+ void AttributeOff(attr_t attr) { ::wattroff(m_window, attr); }
+ void Box(chtype v_char = ACS_VLINE, chtype h_char = ACS_HLINE) {
+ ::box(m_window, v_char, h_char);
+ }
+ void Clear() { ::wclear(m_window); }
+ void Erase() { ::werase(m_window); }
+ Rect GetBounds() {
+ return Rect(GetParentOrigin(), GetSize());
+ } // Get the rectangle in our parent window
+ int GetChar() { return ::wgetch(m_window); }
+ int GetCursorX() { return getcurx(m_window); }
+ int GetCursorY() { return getcury(m_window); }
+ Rect GetFrame() {
+ return Rect(Point(), GetSize());
+ } // Get our rectangle in our own coordinate system
+ Point GetParentOrigin() { return Point(GetParentX(), GetParentY()); }
+ Size GetSize() { return Size(GetWidth(), GetHeight()); }
+ int GetParentX() { return getparx(m_window); }
+ int GetParentY() { return getpary(m_window); }
+ int GetMaxX() { return getmaxx(m_window); }
+ int GetMaxY() { return getmaxy(m_window); }
+ int GetWidth() { return GetMaxX(); }
+ int GetHeight() { return GetMaxY(); }
+ void MoveCursor(int x, int y) { ::wmove(m_window, y, x); }
+ void MoveWindow(int x, int y) { MoveWindow(Point(x, y)); }
+ void Resize(int w, int h) { ::wresize(m_window, h, w); }
+ void Resize(const Size &size) {
+ ::wresize(m_window, size.height, size.width);
+ }
+ void PutChar(int ch) { ::waddch(m_window, ch); }
+ void PutCString(const char *s, int len = -1) { ::waddnstr(m_window, s, len); }
+ void Refresh() { ::wrefresh(m_window); }
+ void DeferredRefresh() {
+ // We are using panels, so we don't need to call this...
+ //::wnoutrefresh(m_window);
+ }
+ void SetBackground(int color_pair_idx) {
+ ::wbkgd(m_window, COLOR_PAIR(color_pair_idx));
+ }
+ void UnderlineOn() { AttributeOn(A_UNDERLINE); }
+ void UnderlineOff() { AttributeOff(A_UNDERLINE); }
+
+ void PutCStringTruncated(const char *s, int right_pad) {
+ int bytes_left = GetWidth() - GetCursorX();
+ if (bytes_left > right_pad) {
+ bytes_left -= right_pad;
+ ::waddnstr(m_window, s, bytes_left);
+ }
+ }
+
+ void MoveWindow(const Point &origin) {
+ const bool moving_window = origin != GetParentOrigin();
+ if (m_is_subwin && moving_window) {
+ // Can't move subwindows, must delete and re-create
+ Size size = GetSize();
+ Reset(::subwin(m_parent->m_window, size.height, size.width, origin.y,
+ origin.x),
+ true);
+ } else {
+ ::mvwin(m_window, origin.y, origin.x);
+ }
+ }
+
+ void SetBounds(const Rect &bounds) {
+ const bool moving_window = bounds.origin != GetParentOrigin();
+ if (m_is_subwin && moving_window) {
+ // Can't move subwindows, must delete and re-create
+ Reset(::subwin(m_parent->m_window, bounds.size.height, bounds.size.width,
+ bounds.origin.y, bounds.origin.x),
+ true);
+ } else {
+ if (moving_window)
+ MoveWindow(bounds.origin);
+ Resize(bounds.size);
+ }
+ }
+
+ void Printf(const char *format, ...) __attribute__((format(printf, 2, 3))) {
+ va_list args;
+ va_start(args, format);
+ vwprintw(m_window, format, args);
+ va_end(args);
+ }
+
+ void Touch() {
+ ::touchwin(m_window);
+ if (m_parent)
+ m_parent->Touch();
+ }
+
+ WindowSP CreateSubWindow(const char *name, const Rect &bounds,
+ bool make_active) {
+ WindowSP subwindow_sp;
+ if (m_window) {
+ subwindow_sp.reset(new Window(
+ name, ::subwin(m_window, bounds.size.height, bounds.size.width,
+ bounds.origin.y, bounds.origin.x),
+ true));
+ subwindow_sp->m_is_subwin = true;
+ } else {
+ subwindow_sp.reset(
+ new Window(name, ::newwin(bounds.size.height, bounds.size.width,
+ bounds.origin.y, bounds.origin.x),
+ true));
+ subwindow_sp->m_is_subwin = false;
+ }
+ subwindow_sp->m_parent = this;
+ if (make_active) {
+ m_prev_active_window_idx = m_curr_active_window_idx;
+ m_curr_active_window_idx = m_subwindows.size();
+ }
+ m_subwindows.push_back(subwindow_sp);
+ ::top_panel(subwindow_sp->m_panel);
+ m_needs_update = true;
+ return subwindow_sp;
+ }
+
+ bool RemoveSubWindow(Window *window) {
+ Windows::iterator pos, end = m_subwindows.end();
+ size_t i = 0;
+ for (pos = m_subwindows.begin(); pos != end; ++pos, ++i) {
+ if ((*pos).get() == window) {
+ if (m_prev_active_window_idx == i)
+ m_prev_active_window_idx = UINT32_MAX;
+ else if (m_prev_active_window_idx != UINT32_MAX &&
+ m_prev_active_window_idx > i)
+ --m_prev_active_window_idx;
+
+ if (m_curr_active_window_idx == i)
+ m_curr_active_window_idx = UINT32_MAX;
+ else if (m_curr_active_window_idx != UINT32_MAX &&
+ m_curr_active_window_idx > i)
+ --m_curr_active_window_idx;
+ window->Erase();
+ m_subwindows.erase(pos);
+ m_needs_update = true;
+ if (m_parent)
+ m_parent->Touch();
+ else
+ ::touchwin(stdscr);
+ return true;
+ }
+ }
+ return false;
+ }
- MenuActionResult
- Action ()
- {
- // Call the recursive action so it can try to handle it
- // with the menu delegate, and if not, try our parent menu
- return ActionPrivate (*this);
- }
-
- void
- SetCannedResult (MenuActionResult result)
- {
- m_canned_result = result;
- }
-
- Menus &
- GetSubmenus()
- {
- return m_submenus;
- }
-
- const Menus &
- GetSubmenus() const
- {
- return m_submenus;
- }
-
- int
- GetSelectedSubmenuIndex () const
- {
- return m_selected;
- }
-
- void
- SetSelectedSubmenuIndex (int idx)
- {
- m_selected = idx;
- }
-
- Type
- GetType () const
- {
- return m_type;
- }
-
- int
- GetStartingColumn() const
- {
- return m_start_col;
- }
-
- void
- SetStartingColumn(int col)
- {
- m_start_col = col;
- }
-
- int
- GetKeyValue() const
- {
- return m_key_value;
- }
-
- void
- SetKeyValue(int key_value)
- {
- m_key_value = key_value;
- }
-
- std::string &
- GetName()
- {
- return m_name;
- }
-
- std::string &
- GetKeyName()
- {
- return m_key_name;
- }
-
- int
- GetDrawWidth () const
- {
- return m_max_submenu_name_length + m_max_submenu_key_name_length + 8;
- }
-
- uint64_t
- GetIdentifier() const
- {
- return m_identifier;
- }
-
- void
- SetIdentifier (uint64_t identifier)
- {
- m_identifier = identifier;
- }
-
- protected:
- std::string m_name;
- std::string m_key_name;
- uint64_t m_identifier;
- Type m_type;
- int m_key_value;
- int m_start_col;
- int m_max_submenu_name_length;
- int m_max_submenu_key_name_length;
- int m_selected;
- Menu *m_parent;
- Menus m_submenus;
- WindowSP m_menu_window_sp;
- MenuActionResult m_canned_result;
- MenuDelegateSP m_delegate_sp;
- };
-
- // Menubar or separator constructor
- Menu::Menu (Type type) :
- m_name (),
- m_key_name (),
- m_identifier (0),
- m_type (type),
- m_key_value (0),
- m_start_col (0),
- m_max_submenu_name_length (0),
- m_max_submenu_key_name_length (0),
- m_selected (0),
- m_parent(nullptr),
- m_submenus (),
- m_canned_result (MenuActionResult::NotHandled),
- m_delegate_sp()
- {
+ WindowSP FindSubWindow(const char *name) {
+ Windows::iterator pos, end = m_subwindows.end();
+ size_t i = 0;
+ for (pos = m_subwindows.begin(); pos != end; ++pos, ++i) {
+ if ((*pos)->m_name.compare(name) == 0)
+ return *pos;
+ }
+ return WindowSP();
+ }
+
+ void RemoveSubWindows() {
+ m_curr_active_window_idx = UINT32_MAX;
+ m_prev_active_window_idx = UINT32_MAX;
+ for (Windows::iterator pos = m_subwindows.begin();
+ pos != m_subwindows.end(); pos = m_subwindows.erase(pos)) {
+ (*pos)->Erase();
}
+ if (m_parent)
+ m_parent->Touch();
+ else
+ ::touchwin(stdscr);
+ }
- // Menuitem constructor
- Menu::Menu (const char *name,
- const char *key_name,
- int key_value,
- uint64_t identifier) :
- m_name (),
- m_key_name (),
- m_identifier (identifier),
- m_type (Type::Invalid),
- m_key_value (key_value),
- m_start_col (0),
- m_max_submenu_name_length (0),
- m_max_submenu_key_name_length (0),
- m_selected (0),
- m_parent(nullptr),
- m_submenus (),
- m_canned_result (MenuActionResult::NotHandled),
- m_delegate_sp()
- {
- if (name && name[0])
- {
- m_name = name;
- m_type = Type::Item;
- if (key_name && key_name[0])
- m_key_name = key_name;
- }
+ WINDOW *get() { return m_window; }
+
+ operator WINDOW *() { return m_window; }
+
+ //----------------------------------------------------------------------
+ // Window drawing utilities
+ //----------------------------------------------------------------------
+ void DrawTitleBox(const char *title, const char *bottom_message = nullptr) {
+ attr_t attr = 0;
+ if (IsActive())
+ attr = A_BOLD | COLOR_PAIR(2);
+ else
+ attr = 0;
+ if (attr)
+ AttributeOn(attr);
+
+ Box();
+ MoveCursor(3, 0);
+
+ if (title && title[0]) {
+ PutChar('<');
+ PutCString(title);
+ PutChar('>');
+ }
+
+ if (bottom_message && bottom_message[0]) {
+ int bottom_message_length = strlen(bottom_message);
+ int x = GetWidth() - 3 - (bottom_message_length + 2);
+
+ if (x > 0) {
+ MoveCursor(x, GetHeight() - 1);
+ PutChar('[');
+ PutCString(bottom_message);
+ PutChar(']');
+ } else {
+ MoveCursor(1, GetHeight() - 1);
+ PutChar('[');
+ PutCStringTruncated(bottom_message, 1);
+ }
+ }
+ if (attr)
+ AttributeOff(attr);
+ }
+
+ virtual void Draw(bool force) {
+ if (m_delegate_sp && m_delegate_sp->WindowDelegateDraw(*this, force))
+ return;
+
+ for (auto &subwindow_sp : m_subwindows)
+ subwindow_sp->Draw(force);
+ }
+
+ bool CreateHelpSubwindow() {
+ if (m_delegate_sp) {
+ const char *text = m_delegate_sp->WindowDelegateGetHelpText();
+ KeyHelp *key_help = m_delegate_sp->WindowDelegateGetKeyHelp();
+ if ((text && text[0]) || key_help) {
+ std::auto_ptr<HelpDialogDelegate> help_delegate_ap(
+ new HelpDialogDelegate(text, key_help));
+ const size_t num_lines = help_delegate_ap->GetNumLines();
+ const size_t max_length = help_delegate_ap->GetMaxLineLength();
+ Rect bounds = GetBounds();
+ bounds.Inset(1, 1);
+ if (max_length + 4 < static_cast<size_t>(bounds.size.width)) {
+ bounds.origin.x += (bounds.size.width - max_length + 4) / 2;
+ bounds.size.width = max_length + 4;
+ } else {
+ if (bounds.size.width > 100) {
+ const int inset_w = bounds.size.width / 4;
+ bounds.origin.x += inset_w;
+ bounds.size.width -= 2 * inset_w;
+ }
+ }
+
+ if (num_lines + 2 < static_cast<size_t>(bounds.size.height)) {
+ bounds.origin.y += (bounds.size.height - num_lines + 2) / 2;
+ bounds.size.height = num_lines + 2;
+ } else {
+ if (bounds.size.height > 100) {
+ const int inset_h = bounds.size.height / 4;
+ bounds.origin.y += inset_h;
+ bounds.size.height -= 2 * inset_h;
+ }
+ }
+ WindowSP help_window_sp;
+ Window *parent_window = GetParent();
+ if (parent_window)
+ help_window_sp = parent_window->CreateSubWindow("Help", bounds, true);
else
- {
- m_type = Type::Separator;
- }
+ help_window_sp = CreateSubWindow("Help", bounds, true);
+ help_window_sp->SetDelegate(
+ WindowDelegateSP(help_delegate_ap.release()));
+ return true;
+ }
}
+ return false;
+ }
- void
- Menu::RecalculateNameLengths()
- {
- m_max_submenu_name_length = 0;
- m_max_submenu_key_name_length = 0;
- Menus &submenus = GetSubmenus();
- const size_t num_submenus = submenus.size();
- for (size_t i = 0; i < num_submenus; ++i)
- {
- Menu *submenu = submenus[i].get();
- if (static_cast<size_t>(m_max_submenu_name_length) < submenu->m_name.size())
- m_max_submenu_name_length = submenu->m_name.size();
- if (static_cast<size_t>(m_max_submenu_key_name_length) < submenu->m_key_name.size())
- m_max_submenu_key_name_length = submenu->m_key_name.size();
- }
+ virtual HandleCharResult HandleChar(int key) {
+ // Always check the active window first
+ HandleCharResult result = eKeyNotHandled;
+ WindowSP active_window_sp = GetActiveWindow();
+ if (active_window_sp) {
+ result = active_window_sp->HandleChar(key);
+ if (result != eKeyNotHandled)
+ return result;
}
- void
- Menu::AddSubmenu (const MenuSP &menu_sp)
- {
- menu_sp->m_parent = this;
- if (static_cast<size_t>(m_max_submenu_name_length) < menu_sp->m_name.size())
- m_max_submenu_name_length = menu_sp->m_name.size();
- if (static_cast<size_t>(m_max_submenu_key_name_length) < menu_sp->m_key_name.size())
- m_max_submenu_key_name_length = menu_sp->m_key_name.size();
- m_submenus.push_back(menu_sp);
+ if (m_delegate_sp) {
+ result = m_delegate_sp->WindowDelegateHandleChar(*this, key);
+ if (result != eKeyNotHandled)
+ return result;
}
- void
- Menu::DrawMenuTitle (Window &window, bool highlight)
- {
- if (m_type == Type::Separator)
- {
- window.MoveCursor(0, window.GetCursorY());
- window.PutChar(ACS_LTEE);
- int width = window.GetWidth();
- if (width > 2)
- {
- width -= 2;
- for (int i = 0; i < width; ++i)
- window.PutChar(ACS_HLINE);
- }
- window.PutChar(ACS_RTEE);
- }
- else
- {
- const int shortcut_key = m_key_value;
- bool underlined_shortcut = false;
- const attr_t hilgight_attr = A_REVERSE;
- if (highlight)
- window.AttributeOn(hilgight_attr);
- if (isprint(shortcut_key))
- {
- size_t lower_pos = m_name.find(tolower(shortcut_key));
- size_t upper_pos = m_name.find(toupper(shortcut_key));
- const char *name = m_name.c_str();
- size_t pos = std::min<size_t>(lower_pos, upper_pos);
- if (pos != std::string::npos)
- {
- underlined_shortcut = true;
- if (pos > 0)
- {
- window.PutCString(name, pos);
- name += pos;
- }
- const attr_t shortcut_attr = A_UNDERLINE|A_BOLD;
- window.AttributeOn (shortcut_attr);
- window.PutChar(name[0]);
- window.AttributeOff(shortcut_attr);
- name++;
- if (name[0])
- window.PutCString(name);
- }
- }
-
- if (!underlined_shortcut)
- {
- window.PutCString(m_name.c_str());
- }
+ // Then check for any windows that want any keys
+ // that weren't handled. This is typically only
+ // for a menubar.
+ // Make a copy of the subwindows in case any HandleChar()
+ // functions muck with the subwindows. If we don't do this,
+ // we can crash when iterating over the subwindows.
+ Windows subwindows(m_subwindows);
+ for (auto subwindow_sp : subwindows) {
+ if (!subwindow_sp->m_can_activate) {
+ HandleCharResult result = subwindow_sp->HandleChar(key);
+ if (result != eKeyNotHandled)
+ return result;
+ }
+ }
+
+ return eKeyNotHandled;
+ }
+
+ bool SetActiveWindow(Window *window) {
+ const size_t num_subwindows = m_subwindows.size();
+ for (size_t i = 0; i < num_subwindows; ++i) {
+ if (m_subwindows[i].get() == window) {
+ m_prev_active_window_idx = m_curr_active_window_idx;
+ ::top_panel(window->m_panel);
+ m_curr_active_window_idx = i;
+ return true;
+ }
+ }
+ return false;
+ }
- if (highlight)
- window.AttributeOff(hilgight_attr);
+ WindowSP GetActiveWindow() {
+ if (!m_subwindows.empty()) {
+ if (m_curr_active_window_idx >= m_subwindows.size()) {
+ if (m_prev_active_window_idx < m_subwindows.size()) {
+ m_curr_active_window_idx = m_prev_active_window_idx;
+ m_prev_active_window_idx = UINT32_MAX;
+ } else if (IsActive()) {
+ m_prev_active_window_idx = UINT32_MAX;
+ m_curr_active_window_idx = UINT32_MAX;
- if (m_key_name.empty())
- {
- if (!underlined_shortcut && isprint(m_key_value))
- {
- window.AttributeOn (COLOR_PAIR(3));
- window.Printf (" (%c)", m_key_value);
- window.AttributeOff (COLOR_PAIR(3));
- }
- }
- else
- {
- window.AttributeOn (COLOR_PAIR(3));
- window.Printf (" (%s)", m_key_name.c_str());
- window.AttributeOff (COLOR_PAIR(3));
+ // Find first window that wants to be active if this window is active
+ const size_t num_subwindows = m_subwindows.size();
+ for (size_t i = 0; i < num_subwindows; ++i) {
+ if (m_subwindows[i]->GetCanBeActive()) {
+ m_curr_active_window_idx = i;
+ break;
}
+ }
}
+ }
+
+ if (m_curr_active_window_idx < m_subwindows.size())
+ return m_subwindows[m_curr_active_window_idx];
}
-
- bool
- Menu::WindowDelegateDraw (Window &window, bool force)
- {
- Menus &submenus = GetSubmenus();
- const size_t num_submenus = submenus.size();
- const int selected_idx = GetSelectedSubmenuIndex();
- Menu::Type menu_type = GetType ();
- switch (menu_type)
- {
- case Menu::Type::Bar:
- {
- window.SetBackground(2);
- window.MoveCursor(0, 0);
- for (size_t i = 0; i < num_submenus; ++i)
- {
- Menu *menu = submenus[i].get();
- if (i > 0)
- window.PutChar(' ');
- menu->SetStartingColumn (window.GetCursorX());
- window.PutCString("| ");
- menu->DrawMenuTitle (window, false);
- }
- window.PutCString(" |");
- window.DeferredRefresh();
- }
- break;
-
- case Menu::Type::Item:
- {
- int y = 1;
- int x = 3;
- // Draw the menu
- int cursor_x = 0;
- int cursor_y = 0;
- window.Erase();
- window.SetBackground(2);
- window.Box();
- for (size_t i = 0; i < num_submenus; ++i)
- {
- const bool is_selected =
- (i == static_cast<size_t>(selected_idx));
- window.MoveCursor(x, y + i);
- if (is_selected)
- {
- // Remember where we want the cursor to be
- cursor_x = x-1;
- cursor_y = y+i;
- }
- submenus[i]->DrawMenuTitle (window, is_selected);
- }
- window.MoveCursor(cursor_x, cursor_y);
- window.DeferredRefresh();
- }
- break;
+ return WindowSP();
+ }
- default:
- case Menu::Type::Separator:
- break;
- }
- return true; // Drawing handled...
- }
-
- HandleCharResult
- Menu::WindowDelegateHandleChar (Window &window, int key)
- {
- HandleCharResult result = eKeyNotHandled;
-
- Menus &submenus = GetSubmenus();
- const size_t num_submenus = submenus.size();
- const int selected_idx = GetSelectedSubmenuIndex();
- Menu::Type menu_type = GetType ();
- if (menu_type == Menu::Type::Bar)
- {
- MenuSP run_menu_sp;
- switch (key)
- {
- case KEY_DOWN:
- case KEY_UP:
- // Show last menu or first menu
- if (selected_idx < static_cast<int>(num_submenus))
- run_menu_sp = submenus[selected_idx];
- else if (!submenus.empty())
- run_menu_sp = submenus.front();
- result = eKeyHandled;
- break;
-
- case KEY_RIGHT:
- ++m_selected;
- if (m_selected >= static_cast<int>(num_submenus))
- m_selected = 0;
- if (m_selected < static_cast<int>(num_submenus))
- run_menu_sp = submenus[m_selected];
- else if (!submenus.empty())
- run_menu_sp = submenus.front();
- result = eKeyHandled;
- break;
-
- case KEY_LEFT:
- --m_selected;
- if (m_selected < 0)
- m_selected = num_submenus - 1;
- if (m_selected < static_cast<int>(num_submenus))
- run_menu_sp = submenus[m_selected];
- else if (!submenus.empty())
- run_menu_sp = submenus.front();
- result = eKeyHandled;
- break;
-
- default:
- for (size_t i = 0; i < num_submenus; ++i)
- {
- if (submenus[i]->GetKeyValue() == key)
- {
- SetSelectedSubmenuIndex(i);
- run_menu_sp = submenus[i];
- result = eKeyHandled;
- break;
- }
- }
- break;
- }
-
- if (run_menu_sp)
- {
- // Run the action on this menu in case we need to populate the
- // menu with dynamic content and also in case check marks, and
- // any other menu decorations need to be calculated
- if (run_menu_sp->Action() == MenuActionResult::Quit)
- return eQuitApplication;
-
- Rect menu_bounds;
- menu_bounds.origin.x = run_menu_sp->GetStartingColumn();
- menu_bounds.origin.y = 1;
- menu_bounds.size.width = run_menu_sp->GetDrawWidth();
- menu_bounds.size.height = run_menu_sp->GetSubmenus().size() + 2;
- if (m_menu_window_sp)
- window.GetParent()->RemoveSubWindow(m_menu_window_sp.get());
-
- m_menu_window_sp = window.GetParent()->CreateSubWindow (run_menu_sp->GetName().c_str(),
- menu_bounds,
- true);
- m_menu_window_sp->SetDelegate (run_menu_sp);
- }
- }
- else if (menu_type == Menu::Type::Item)
- {
- switch (key)
- {
- case KEY_DOWN:
- if (m_submenus.size() > 1)
- {
- const int start_select = m_selected;
- while (++m_selected != start_select)
- {
- if (static_cast<size_t>(m_selected) >= num_submenus)
- m_selected = 0;
- if (m_submenus[m_selected]->GetType() == Type::Separator)
- continue;
- else
- break;
- }
- return eKeyHandled;
- }
- break;
-
- case KEY_UP:
- if (m_submenus.size() > 1)
- {
- const int start_select = m_selected;
- while (--m_selected != start_select)
- {
- if (m_selected < static_cast<int>(0))
- m_selected = num_submenus - 1;
- if (m_submenus[m_selected]->GetType() == Type::Separator)
- continue;
- else
- break;
- }
- return eKeyHandled;
- }
- break;
-
- case KEY_RETURN:
- if (static_cast<size_t>(selected_idx) < num_submenus)
- {
- if (submenus[selected_idx]->Action() == MenuActionResult::Quit)
- return eQuitApplication;
- window.GetParent()->RemoveSubWindow(&window);
- return eKeyHandled;
- }
- break;
-
- case KEY_ESCAPE: // Beware: pressing escape key has 1 to 2 second delay in case other chars are entered for escaped sequences
- window.GetParent()->RemoveSubWindow(&window);
- return eKeyHandled;
-
- default:
- for (size_t i = 0; i < num_submenus; ++i)
- {
- Menu *menu = submenus[i].get();
- if (menu->GetKeyValue() == key)
- {
- SetSelectedSubmenuIndex(i);
- window.GetParent()->RemoveSubWindow(&window);
- if (menu->Action() == MenuActionResult::Quit)
- return eQuitApplication;
- return eKeyHandled;
- }
- }
- break;
- }
- }
- else if (menu_type == Menu::Type::Separator)
- {
- }
- return result;
- }
-
- class Application
- {
- public:
- Application (FILE *in, FILE *out) :
- m_window_sp(),
- m_screen(nullptr),
- m_in (in),
- m_out (out)
- {
- }
-
- ~Application ()
- {
- m_window_delegates.clear();
- m_window_sp.reset();
- if (m_screen)
- {
- ::delscreen(m_screen);
- m_screen = nullptr;
- }
- }
-
- void
- Initialize ()
- {
- ::setlocale(LC_ALL, "");
- ::setlocale(LC_CTYPE, "");
-#if 0
- ::initscr();
-#else
- m_screen = ::newterm(nullptr, m_out, m_in);
-#endif
- ::start_color();
- ::curs_set(0);
- ::noecho();
- ::keypad(stdscr,TRUE);
- }
-
- void
- Terminate ()
- {
- ::endwin();
- }
-
- void
- Run (Debugger &debugger)
- {
- bool done = false;
- int delay_in_tenths_of_a_second = 1;
-
- // Alas the threading model in curses is a bit lame so we need to
- // resort to polling every 0.5 seconds. We could poll for stdin
- // ourselves and then pass the keys down but then we need to
- // translate all of the escape sequences ourselves. So we resort to
- // polling for input because we need to receive async process events
- // while in this loop.
-
- halfdelay(delay_in_tenths_of_a_second); // Poll using some number of tenths of seconds seconds when calling Window::GetChar()
-
- ListenerSP listener_sp (Listener::MakeListener("lldb.IOHandler.curses.Application"));
- ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
- ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
- ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
- debugger.EnableForwardEvents (listener_sp);
+ bool GetCanBeActive() const { return m_can_activate; }
- bool update = true;
-#if defined(__APPLE__)
- std::deque<int> escape_chars;
-#endif
-
- while (!done)
- {
- if (update)
- {
- m_window_sp->Draw(false);
- // All windows should be calling Window::DeferredRefresh() instead
- // of Window::Refresh() so we can do a single update and avoid
- // any screen blinking
- update_panels();
+ void SetCanBeActive(bool b) { m_can_activate = b; }
- // Cursor hiding isn't working on MacOSX, so hide it in the top left corner
- m_window_sp->MoveCursor(0, 0);
+ const WindowDelegateSP &GetDelegate() const { return m_delegate_sp; }
- doupdate();
- update = false;
- }
-
-#if defined(__APPLE__)
- // Terminal.app doesn't map its function keys correctly, F1-F4 default to:
- // \033OP, \033OQ, \033OR, \033OS, so lets take care of this here if possible
- int ch;
- if (escape_chars.empty())
- ch = m_window_sp->GetChar();
- else
- {
- ch = escape_chars.front();
- escape_chars.pop_front();
- }
- if (ch == KEY_ESCAPE)
- {
- int ch2 = m_window_sp->GetChar();
- if (ch2 == 'O')
- {
- int ch3 = m_window_sp->GetChar();
- switch (ch3)
- {
- case 'P': ch = KEY_F(1); break;
- case 'Q': ch = KEY_F(2); break;
- case 'R': ch = KEY_F(3); break;
- case 'S': ch = KEY_F(4); break;
- default:
- escape_chars.push_back(ch2);
- if (ch3 != -1)
- escape_chars.push_back(ch3);
- break;
- }
- }
- else if (ch2 != -1)
- escape_chars.push_back(ch2);
- }
-#else
- int ch = m_window_sp->GetChar();
+ void SetDelegate(const WindowDelegateSP &delegate_sp) {
+ m_delegate_sp = delegate_sp;
+ }
-#endif
- if (ch == -1)
- {
- if (feof(m_in) || ferror(m_in))
- {
- done = true;
- }
- else
- {
- // Just a timeout from using halfdelay(), check for events
- EventSP event_sp;
- while (listener_sp->PeekAtNextEvent())
- {
- listener_sp->GetNextEvent(event_sp);
-
- if (event_sp)
- {
- Broadcaster *broadcaster = event_sp->GetBroadcaster();
- if (broadcaster)
- {
- //uint32_t event_type = event_sp->GetType();
- ConstString broadcaster_class (broadcaster->GetBroadcasterClass());
- if (broadcaster_class == broadcaster_class_process)
- {
- debugger.GetCommandInterpreter().UpdateExecutionContext(nullptr);
- update = true;
- continue; // Don't get any key, just update our view
- }
- }
- }
- }
- }
- }
- else
- {
- HandleCharResult key_result = m_window_sp->HandleChar(ch);
- switch (key_result)
- {
- case eKeyHandled:
- debugger.GetCommandInterpreter().UpdateExecutionContext(nullptr);
- update = true;
- break;
- case eKeyNotHandled:
- break;
- case eQuitApplication:
- done = true;
- break;
- }
- }
- }
-
- debugger.CancelForwardEvents (listener_sp);
- }
-
- WindowSP &
- GetMainWindow ()
- {
- if (!m_window_sp)
- m_window_sp.reset (new Window ("main", stdscr, false));
- return m_window_sp;
- }
-
- WindowDelegates &
- GetWindowDelegates ()
- {
- return m_window_delegates;
- }
-
- protected:
- WindowSP m_window_sp;
- WindowDelegates m_window_delegates;
- SCREEN *m_screen;
- FILE *m_in;
- FILE *m_out;
- };
+ Window *GetParent() const { return m_parent; }
-} // namespace curses
-
-using namespace curses;
+ bool IsActive() const {
+ if (m_parent)
+ return m_parent->GetActiveWindow().get() == this;
+ else
+ return true; // Top level window is always active
+ }
-struct Row
-{
- ValueObjectSP valobj;
- Row *parent;
- int row_idx;
- int x;
- int y;
- bool might_have_children;
- bool expanded;
- bool calculated_children;
- std::vector<Row> children;
-
- Row (const ValueObjectSP &v, Row *p) :
- valobj (v),
- parent (p),
- row_idx(0),
- x(1),
- y(1),
- might_have_children (v ? v->MightHaveChildren() : false),
- expanded (false),
- calculated_children (false),
- children()
- {
- }
-
- size_t
- GetDepth () const
- {
- if (parent)
- return 1 + parent->GetDepth();
- return 0;
- }
-
- void
- Expand()
- {
- expanded = true;
- if (!calculated_children)
- {
- calculated_children = true;
- if (valobj)
- {
- const size_t num_children = valobj->GetNumChildren();
- for (size_t i = 0; i < num_children; ++i)
- {
- children.push_back(Row (valobj->GetChildAtIndex(i, true), this));
- }
- }
+ void SelectNextWindowAsActive() {
+ // Move active focus to next window
+ const size_t num_subwindows = m_subwindows.size();
+ if (m_curr_active_window_idx == UINT32_MAX) {
+ uint32_t idx = 0;
+ for (auto subwindow_sp : m_subwindows) {
+ if (subwindow_sp->GetCanBeActive()) {
+ m_curr_active_window_idx = idx;
+ break;
+ }
+ ++idx;
+ }
+ } else if (m_curr_active_window_idx + 1 < num_subwindows) {
+ bool handled = false;
+ m_prev_active_window_idx = m_curr_active_window_idx;
+ for (size_t idx = m_curr_active_window_idx + 1; idx < num_subwindows;
+ ++idx) {
+ if (m_subwindows[idx]->GetCanBeActive()) {
+ m_curr_active_window_idx = idx;
+ handled = true;
+ break;
+ }
+ }
+ if (!handled) {
+ for (size_t idx = 0; idx <= m_prev_active_window_idx; ++idx) {
+ if (m_subwindows[idx]->GetCanBeActive()) {
+ m_curr_active_window_idx = idx;
+ break;
+ }
}
- }
-
- void
- Unexpand ()
- {
- expanded = false;
- }
-
- void
- DrawTree (Window &window)
- {
- if (parent)
- parent->DrawTreeForChild (window, this, 0);
-
- if (might_have_children)
- {
- // It we can get UTF8 characters to work we should try to use the "symbol"
- // UTF8 string below
-// const char *symbol = "";
-// if (row.expanded)
-// symbol = "\xe2\x96\xbd ";
-// else
-// symbol = "\xe2\x96\xb7 ";
-// window.PutCString (symbol);
-
- // The ACS_DARROW and ACS_RARROW don't look very nice they are just a
- // 'v' or '>' character...
-// if (expanded)
-// window.PutChar (ACS_DARROW);
-// else
-// window.PutChar (ACS_RARROW);
- // Since we can't find any good looking right arrow/down arrow
- // symbols, just use a diamond...
- window.PutChar (ACS_DIAMOND);
- window.PutChar (ACS_HLINE);
+ }
+ } else {
+ m_prev_active_window_idx = m_curr_active_window_idx;
+ for (size_t idx = 0; idx < num_subwindows; ++idx) {
+ if (m_subwindows[idx]->GetCanBeActive()) {
+ m_curr_active_window_idx = idx;
+ break;
}
+ }
}
+ }
- void
- DrawTreeForChild (Window &window, Row *child, uint32_t reverse_depth)
- {
- if (parent)
- parent->DrawTreeForChild (window, this, reverse_depth + 1);
-
- if (&children.back() == child)
- {
- // Last child
- if (reverse_depth == 0)
- {
- window.PutChar (ACS_LLCORNER);
- window.PutChar (ACS_HLINE);
- }
- else
- {
- window.PutChar (' ');
- window.PutChar (' ');
- }
- }
- else
- {
- if (reverse_depth == 0)
- {
- window.PutChar (ACS_LTEE);
- window.PutChar (ACS_HLINE);
- }
- else
- {
- window.PutChar (ACS_VLINE);
- window.PutChar (' ');
- }
- }
- }
-};
+ const char *GetName() const { return m_name.c_str(); }
-struct DisplayOptions
-{
- bool show_types;
-};
+protected:
+ std::string m_name;
+ WINDOW *m_window;
+ PANEL *m_panel;
+ Window *m_parent;
+ Windows m_subwindows;
+ WindowDelegateSP m_delegate_sp;
+ uint32_t m_curr_active_window_idx;
+ uint32_t m_prev_active_window_idx;
+ bool m_delete;
+ bool m_needs_update;
+ bool m_can_activate;
+ bool m_is_subwin;
-class TreeItem;
+private:
+ DISALLOW_COPY_AND_ASSIGN(Window);
+};
-class TreeDelegate
-{
+class MenuDelegate {
public:
- TreeDelegate() = default;
- virtual ~TreeDelegate() = default;
+ virtual ~MenuDelegate() = default;
- virtual void TreeDelegateDrawTreeItem (TreeItem &item, Window &window) = 0;
- virtual void TreeDelegateGenerateChildren (TreeItem &item) = 0;
- virtual bool TreeDelegateItemSelected (TreeItem &item) = 0; // Return true if we need to update views
+ virtual MenuActionResult MenuDelegateAction(Menu &menu) = 0;
};
-typedef std::shared_ptr<TreeDelegate> TreeDelegateSP;
-
-class TreeItem
-{
+class Menu : public WindowDelegate {
public:
- TreeItem (TreeItem *parent, TreeDelegate &delegate, bool might_have_children) :
- m_parent (parent),
- m_delegate (delegate),
- m_user_data(nullptr),
- m_identifier (0),
- m_row_idx (-1),
- m_children (),
- m_might_have_children (might_have_children),
- m_is_expanded (false)
- {
- }
+ enum class Type { Invalid, Bar, Item, Separator };
- TreeItem &
- operator=(const TreeItem &rhs)
- {
- if (this != &rhs)
- {
- m_parent = rhs.m_parent;
- m_delegate = rhs.m_delegate;
- m_user_data = rhs.m_user_data;
- m_identifier = rhs.m_identifier;
- m_row_idx = rhs.m_row_idx;
- m_children = rhs.m_children;
- m_might_have_children = rhs.m_might_have_children;
- m_is_expanded = rhs.m_is_expanded;
- }
- return *this;
- }
+ // Menubar or separator constructor
+ Menu(Type type);
- size_t
- GetDepth () const
- {
- if (m_parent)
- return 1 + m_parent->GetDepth();
- return 0;
- }
-
- int
- GetRowIndex () const
- {
- return m_row_idx;
- }
+ // Menuitem constructor
+ Menu(const char *name, const char *key_name, int key_value,
+ uint64_t identifier);
- void
- ClearChildren ()
- {
- m_children.clear();
- }
+ ~Menu() override = default;
- void
- Resize (size_t n, const TreeItem &t)
- {
- m_children.resize(n, t);
- }
-
- TreeItem &
- operator [](size_t i)
- {
- return m_children[i];
- }
+ const MenuDelegateSP &GetDelegate() const { return m_delegate_sp; }
- void
- SetRowIndex (int row_idx)
- {
- m_row_idx = row_idx;
- }
+ void SetDelegate(const MenuDelegateSP &delegate_sp) {
+ m_delegate_sp = delegate_sp;
+ }
- size_t
- GetNumChildren ()
- {
- m_delegate.TreeDelegateGenerateChildren (*this);
- return m_children.size();
- }
+ void RecalculateNameLengths();
- void
- ItemWasSelected ()
- {
- m_delegate.TreeDelegateItemSelected(*this);
- }
+ void AddSubmenu(const MenuSP &menu_sp);
- void
- CalculateRowIndexes (int &row_idx)
- {
- SetRowIndex(row_idx);
- ++row_idx;
+ int DrawAndRunMenu(Window &window);
- const bool expanded = IsExpanded();
+ void DrawMenuTitle(Window &window, bool highlight);
- // The root item must calculate its children,
- // or we must calculate the number of children
- // if the item is expanded
- if (m_parent == nullptr || expanded)
- GetNumChildren();
-
- for (auto &item : m_children)
- {
- if (expanded)
- item.CalculateRowIndexes(row_idx);
- else
- item.SetRowIndex(-1);
- }
- }
+ bool WindowDelegateDraw(Window &window, bool force) override;
- TreeItem *
- GetParent ()
- {
- return m_parent;
- }
+ HandleCharResult WindowDelegateHandleChar(Window &window, int key) override;
- bool
- IsExpanded () const
- {
- return m_is_expanded;
+ MenuActionResult ActionPrivate(Menu &menu) {
+ MenuActionResult result = MenuActionResult::NotHandled;
+ if (m_delegate_sp) {
+ result = m_delegate_sp->MenuDelegateAction(menu);
+ if (result != MenuActionResult::NotHandled)
+ return result;
+ } else if (m_parent) {
+ result = m_parent->ActionPrivate(menu);
+ if (result != MenuActionResult::NotHandled)
+ return result;
}
+ return m_canned_result;
+ }
- void
- Expand()
- {
- m_is_expanded = true;
- }
-
- void
- Unexpand ()
- {
- m_is_expanded = false;
- }
-
- bool
- Draw (Window &window,
- const int first_visible_row,
- const uint32_t selected_row_idx,
- int &row_idx,
- int &num_rows_left)
- {
- if (num_rows_left <= 0)
- return false;
+ MenuActionResult Action() {
+ // Call the recursive action so it can try to handle it
+ // with the menu delegate, and if not, try our parent menu
+ return ActionPrivate(*this);
+ }
- if (m_row_idx >= first_visible_row)
- {
- window.MoveCursor(2, row_idx + 1);
-
- if (m_parent)
- m_parent->DrawTreeForChild (window, this, 0);
-
- if (m_might_have_children)
- {
- // It we can get UTF8 characters to work we should try to use the "symbol"
- // UTF8 string below
- // const char *symbol = "";
- // if (row.expanded)
- // symbol = "\xe2\x96\xbd ";
- // else
- // symbol = "\xe2\x96\xb7 ";
- // window.PutCString (symbol);
-
- // The ACS_DARROW and ACS_RARROW don't look very nice they are just a
- // 'v' or '>' character...
- // if (expanded)
- // window.PutChar (ACS_DARROW);
- // else
- // window.PutChar (ACS_RARROW);
- // Since we can't find any good looking right arrow/down arrow
- // symbols, just use a diamond...
- window.PutChar (ACS_DIAMOND);
- window.PutChar (ACS_HLINE);
- }
- bool highlight =
- (selected_row_idx == static_cast<size_t>(m_row_idx)) && window.IsActive();
+ void SetCannedResult(MenuActionResult result) { m_canned_result = result; }
- if (highlight)
- window.AttributeOn(A_REVERSE);
+ Menus &GetSubmenus() { return m_submenus; }
- m_delegate.TreeDelegateDrawTreeItem(*this, window);
+ const Menus &GetSubmenus() const { return m_submenus; }
- if (highlight)
- window.AttributeOff(A_REVERSE);
- ++row_idx;
- --num_rows_left;
- }
-
- if (num_rows_left <= 0)
- return false; // We are done drawing...
-
- if (IsExpanded())
- {
- for (auto &item : m_children)
- {
- // If we displayed all the rows and item.Draw() returns
- // false we are done drawing and can exit this for loop
- if (!item.Draw(window, first_visible_row, selected_row_idx, row_idx, num_rows_left))
- break;
- }
- }
- return num_rows_left >= 0; // Return true if not done drawing yet
- }
-
- void
- DrawTreeForChild (Window &window, TreeItem *child, uint32_t reverse_depth)
- {
- if (m_parent)
- m_parent->DrawTreeForChild (window, this, reverse_depth + 1);
-
- if (&m_children.back() == child)
- {
- // Last child
- if (reverse_depth == 0)
- {
- window.PutChar (ACS_LLCORNER);
- window.PutChar (ACS_HLINE);
- }
- else
- {
- window.PutChar (' ');
- window.PutChar (' ');
- }
- }
- else
- {
- if (reverse_depth == 0)
- {
- window.PutChar (ACS_LTEE);
- window.PutChar (ACS_HLINE);
- }
- else
- {
- window.PutChar (ACS_VLINE);
- window.PutChar (' ');
- }
- }
- }
-
- TreeItem *
- GetItemForRowIndex (uint32_t row_idx)
- {
- if (static_cast<uint32_t>(m_row_idx) == row_idx)
- return this;
- if (m_children.empty())
- return nullptr;
- if (IsExpanded())
- {
- for (auto &item : m_children)
- {
- TreeItem *selected_item_ptr = item.GetItemForRowIndex(row_idx);
- if (selected_item_ptr)
- return selected_item_ptr;
- }
- }
- return nullptr;
- }
-
- void *
- GetUserData() const
- {
- return m_user_data;
- }
-
- void
- SetUserData (void *user_data)
- {
- m_user_data = user_data;
- }
+ int GetSelectedSubmenuIndex() const { return m_selected; }
- uint64_t
- GetIdentifier() const
- {
- return m_identifier;
- }
-
- void
- SetIdentifier (uint64_t identifier)
- {
- m_identifier = identifier;
- }
+ void SetSelectedSubmenuIndex(int idx) { m_selected = idx; }
- void
- SetMightHaveChildren (bool b)
- {
- m_might_have_children = b;
- }
+ Type GetType() const { return m_type; }
-protected:
- TreeItem *m_parent;
- TreeDelegate &m_delegate;
- void *m_user_data;
- uint64_t m_identifier;
- int m_row_idx; // Zero based visible row index, -1 if not visible or for the root item
- std::vector<TreeItem> m_children;
- bool m_might_have_children;
- bool m_is_expanded;
-};
+ int GetStartingColumn() const { return m_start_col; }
-class TreeWindowDelegate : public WindowDelegate
-{
-public:
- TreeWindowDelegate (Debugger &debugger, const TreeDelegateSP &delegate_sp) :
- m_debugger (debugger),
- m_delegate_sp (delegate_sp),
- m_root(nullptr, *delegate_sp, true),
- m_selected_item(nullptr),
- m_num_rows (0),
- m_selected_row_idx (0),
- m_first_visible_row (0),
- m_min_x (0),
- m_min_y (0),
- m_max_x (0),
- m_max_y (0)
- {
- }
-
- int
- NumVisibleRows () const
- {
- return m_max_y - m_min_y;
- }
+ void SetStartingColumn(int col) { m_start_col = col; }
- bool
- WindowDelegateDraw (Window &window, bool force) override
- {
- ExecutionContext exe_ctx (m_debugger.GetCommandInterpreter().GetExecutionContext());
- Process *process = exe_ctx.GetProcessPtr();
-
- bool display_content = false;
- if (process)
- {
- StateType state = process->GetState();
- if (StateIsStoppedState(state, true))
- {
- // We are stopped, so it is ok to
- display_content = true;
- }
- else if (StateIsRunningState(state))
- {
- return true; // Don't do any updating when we are running
- }
- }
+ int GetKeyValue() const { return m_key_value; }
- m_min_x = 2;
- m_min_y = 1;
- m_max_x = window.GetWidth() - 1;
- m_max_y = window.GetHeight() - 1;
-
- window.Erase();
- window.DrawTitleBox (window.GetName());
-
- if (display_content)
- {
- const int num_visible_rows = NumVisibleRows();
- m_num_rows = 0;
- m_root.CalculateRowIndexes(m_num_rows);
-
- // If we unexpanded while having something selected our
- // total number of rows is less than the num visible rows,
- // then make sure we show all the rows by setting the first
- // visible row accordingly.
- if (m_first_visible_row > 0 && m_num_rows < num_visible_rows)
- m_first_visible_row = 0;
-
- // Make sure the selected row is always visible
- if (m_selected_row_idx < m_first_visible_row)
- m_first_visible_row = m_selected_row_idx;
- else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx)
- m_first_visible_row = m_selected_row_idx - num_visible_rows + 1;
-
- int row_idx = 0;
- int num_rows_left = num_visible_rows;
- m_root.Draw (window, m_first_visible_row, m_selected_row_idx, row_idx, num_rows_left);
- // Get the selected row
- m_selected_item = m_root.GetItemForRowIndex (m_selected_row_idx);
- }
- else
- {
- m_selected_item = nullptr;
- }
-
- window.DeferredRefresh();
+ void SetKeyValue(int key_value) { m_key_value = key_value; }
- return true; // Drawing handled
- }
+ std::string &GetName() { return m_name; }
- const char *
- WindowDelegateGetHelpText () override
- {
- return "Thread window keyboard shortcuts:";
- }
-
- KeyHelp *
- WindowDelegateGetKeyHelp () override
- {
- static curses::KeyHelp g_source_view_key_help[] = {
- { KEY_UP, "Select previous item" },
- { KEY_DOWN, "Select next item" },
- { KEY_RIGHT, "Expand the selected item" },
- { KEY_LEFT, "Unexpand the selected item or select parent if not expanded" },
- { KEY_PPAGE, "Page up" },
- { KEY_NPAGE, "Page down" },
- { 'h', "Show help dialog" },
- { ' ', "Toggle item expansion" },
- { ',', "Page up" },
- { '.', "Page down" },
- { '\0', nullptr }
- };
- return g_source_view_key_help;
- }
-
- HandleCharResult
- WindowDelegateHandleChar (Window &window, int c) override
- {
- switch(c)
- {
- case ',':
- case KEY_PPAGE:
- // Page up key
- if (m_first_visible_row > 0)
- {
- if (m_first_visible_row > m_max_y)
- m_first_visible_row -= m_max_y;
- else
- m_first_visible_row = 0;
- m_selected_row_idx = m_first_visible_row;
- m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
- if (m_selected_item)
- m_selected_item->ItemWasSelected ();
- }
- return eKeyHandled;
-
- case '.':
- case KEY_NPAGE:
- // Page down key
- if (m_num_rows > m_max_y)
- {
- if (m_first_visible_row + m_max_y < m_num_rows)
- {
- m_first_visible_row += m_max_y;
- m_selected_row_idx = m_first_visible_row;
- m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
- if (m_selected_item)
- m_selected_item->ItemWasSelected ();
- }
- }
- return eKeyHandled;
-
- case KEY_UP:
- if (m_selected_row_idx > 0)
- {
- --m_selected_row_idx;
- m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
- if (m_selected_item)
- m_selected_item->ItemWasSelected ();
- }
- return eKeyHandled;
+ std::string &GetKeyName() { return m_key_name; }
- case KEY_DOWN:
- if (m_selected_row_idx + 1 < m_num_rows)
- {
- ++m_selected_row_idx;
- m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
- if (m_selected_item)
- m_selected_item->ItemWasSelected ();
- }
- return eKeyHandled;
-
- case KEY_RIGHT:
- if (m_selected_item)
- {
- if (!m_selected_item->IsExpanded())
- m_selected_item->Expand();
- }
- return eKeyHandled;
-
- case KEY_LEFT:
- if (m_selected_item)
- {
- if (m_selected_item->IsExpanded())
- m_selected_item->Unexpand();
- else if (m_selected_item->GetParent())
- {
- m_selected_row_idx = m_selected_item->GetParent()->GetRowIndex();
- m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
- if (m_selected_item)
- m_selected_item->ItemWasSelected ();
- }
- }
- return eKeyHandled;
-
- case ' ':
- // Toggle expansion state when SPACE is pressed
- if (m_selected_item)
- {
- if (m_selected_item->IsExpanded())
- m_selected_item->Unexpand();
- else
- m_selected_item->Expand();
- }
- return eKeyHandled;
-
- case 'h':
- window.CreateHelpSubwindow ();
- return eKeyHandled;
-
- default:
- break;
- }
- return eKeyNotHandled;
- }
-
-protected:
- Debugger &m_debugger;
- TreeDelegateSP m_delegate_sp;
- TreeItem m_root;
- TreeItem *m_selected_item;
- int m_num_rows;
- int m_selected_row_idx;
- int m_first_visible_row;
- int m_min_x;
- int m_min_y;
- int m_max_x;
- int m_max_y;
-};
+ int GetDrawWidth() const {
+ return m_max_submenu_name_length + m_max_submenu_key_name_length + 8;
+ }
-class FrameTreeDelegate : public TreeDelegate
-{
-public:
- FrameTreeDelegate () :
- TreeDelegate()
- {
- FormatEntity::Parse ("frame #${frame.index}: {${function.name}${function.pc-offset}}}",
- m_format);
- }
+ uint64_t GetIdentifier() const { return m_identifier; }
- ~FrameTreeDelegate() override = default;
-
- void
- TreeDelegateDrawTreeItem (TreeItem &item, Window &window) override
- {
- Thread* thread = (Thread*)item.GetUserData();
- if (thread)
- {
- const uint64_t frame_idx = item.GetIdentifier();
- StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_idx);
- if (frame_sp)
- {
- StreamString strm;
- const SymbolContext &sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
- ExecutionContext exe_ctx (frame_sp);
- if (FormatEntity::Format(m_format, strm, &sc, &exe_ctx, nullptr, nullptr, false, false))
- {
- int right_pad = 1;
- window.PutCStringTruncated(strm.GetString().c_str(), right_pad);
- }
- }
- }
- }
-
- void
- TreeDelegateGenerateChildren (TreeItem &item) override
- {
- // No children for frames yet...
- }
-
- bool
- TreeDelegateItemSelected (TreeItem &item) override
- {
- Thread* thread = (Thread*)item.GetUserData();
- if (thread)
- {
- thread->GetProcess()->GetThreadList().SetSelectedThreadByID(thread->GetID());
- const uint64_t frame_idx = item.GetIdentifier();
- thread->SetSelectedFrameByIndex(frame_idx);
- return true;
- }
- return false;
- }
+ void SetIdentifier(uint64_t identifier) { m_identifier = identifier; }
protected:
- FormatEntity::Entry m_format;
+ std::string m_name;
+ std::string m_key_name;
+ uint64_t m_identifier;
+ Type m_type;
+ int m_key_value;
+ int m_start_col;
+ int m_max_submenu_name_length;
+ int m_max_submenu_key_name_length;
+ int m_selected;
+ Menu *m_parent;
+ Menus m_submenus;
+ WindowSP m_menu_window_sp;
+ MenuActionResult m_canned_result;
+ MenuDelegateSP m_delegate_sp;
};
-class ThreadTreeDelegate : public TreeDelegate
-{
-public:
- ThreadTreeDelegate (Debugger &debugger) :
- TreeDelegate(),
- m_debugger (debugger),
- m_tid (LLDB_INVALID_THREAD_ID),
- m_stop_id (UINT32_MAX)
- {
- FormatEntity::Parse ("thread #${thread.index}: tid = ${thread.id}{, stop reason = ${thread.stop-reason}}",
- m_format);
- }
-
- ~ThreadTreeDelegate() override = default;
+// Menubar or separator constructor
+Menu::Menu(Type type)
+ : m_name(), m_key_name(), m_identifier(0), m_type(type), m_key_value(0),
+ m_start_col(0), m_max_submenu_name_length(0),
+ m_max_submenu_key_name_length(0), m_selected(0), m_parent(nullptr),
+ m_submenus(), m_canned_result(MenuActionResult::NotHandled),
+ m_delegate_sp() {}
+
+// Menuitem constructor
+Menu::Menu(const char *name, const char *key_name, int key_value,
+ uint64_t identifier)
+ : m_name(), m_key_name(), m_identifier(identifier), m_type(Type::Invalid),
+ m_key_value(key_value), m_start_col(0), m_max_submenu_name_length(0),
+ m_max_submenu_key_name_length(0), m_selected(0), m_parent(nullptr),
+ m_submenus(), m_canned_result(MenuActionResult::NotHandled),
+ m_delegate_sp() {
+ if (name && name[0]) {
+ m_name = name;
+ m_type = Type::Item;
+ if (key_name && key_name[0])
+ m_key_name = key_name;
+ } else {
+ m_type = Type::Separator;
+ }
+}
+
+void Menu::RecalculateNameLengths() {
+ m_max_submenu_name_length = 0;
+ m_max_submenu_key_name_length = 0;
+ Menus &submenus = GetSubmenus();
+ const size_t num_submenus = submenus.size();
+ for (size_t i = 0; i < num_submenus; ++i) {
+ Menu *submenu = submenus[i].get();
+ if (static_cast<size_t>(m_max_submenu_name_length) < submenu->m_name.size())
+ m_max_submenu_name_length = submenu->m_name.size();
+ if (static_cast<size_t>(m_max_submenu_key_name_length) <
+ submenu->m_key_name.size())
+ m_max_submenu_key_name_length = submenu->m_key_name.size();
+ }
+}
+
+void Menu::AddSubmenu(const MenuSP &menu_sp) {
+ menu_sp->m_parent = this;
+ if (static_cast<size_t>(m_max_submenu_name_length) < menu_sp->m_name.size())
+ m_max_submenu_name_length = menu_sp->m_name.size();
+ if (static_cast<size_t>(m_max_submenu_key_name_length) <
+ menu_sp->m_key_name.size())
+ m_max_submenu_key_name_length = menu_sp->m_key_name.size();
+ m_submenus.push_back(menu_sp);
+}
+
+void Menu::DrawMenuTitle(Window &window, bool highlight) {
+ if (m_type == Type::Separator) {
+ window.MoveCursor(0, window.GetCursorY());
+ window.PutChar(ACS_LTEE);
+ int width = window.GetWidth();
+ if (width > 2) {
+ width -= 2;
+ for (int i = 0; i < width; ++i)
+ window.PutChar(ACS_HLINE);
+ }
+ window.PutChar(ACS_RTEE);
+ } else {
+ const int shortcut_key = m_key_value;
+ bool underlined_shortcut = false;
+ const attr_t hilgight_attr = A_REVERSE;
+ if (highlight)
+ window.AttributeOn(hilgight_attr);
+ if (isprint(shortcut_key)) {
+ size_t lower_pos = m_name.find(tolower(shortcut_key));
+ size_t upper_pos = m_name.find(toupper(shortcut_key));
+ const char *name = m_name.c_str();
+ size_t pos = std::min<size_t>(lower_pos, upper_pos);
+ if (pos != std::string::npos) {
+ underlined_shortcut = true;
+ if (pos > 0) {
+ window.PutCString(name, pos);
+ name += pos;
+ }
+ const attr_t shortcut_attr = A_UNDERLINE | A_BOLD;
+ window.AttributeOn(shortcut_attr);
+ window.PutChar(name[0]);
+ window.AttributeOff(shortcut_attr);
+ name++;
+ if (name[0])
+ window.PutCString(name);
+ }
+ }
+
+ if (!underlined_shortcut) {
+ window.PutCString(m_name.c_str());
+ }
+
+ if (highlight)
+ window.AttributeOff(hilgight_attr);
+
+ if (m_key_name.empty()) {
+ if (!underlined_shortcut && isprint(m_key_value)) {
+ window.AttributeOn(COLOR_PAIR(3));
+ window.Printf(" (%c)", m_key_value);
+ window.AttributeOff(COLOR_PAIR(3));
+ }
+ } else {
+ window.AttributeOn(COLOR_PAIR(3));
+ window.Printf(" (%s)", m_key_name.c_str());
+ window.AttributeOff(COLOR_PAIR(3));
+ }
+ }
+}
+
+bool Menu::WindowDelegateDraw(Window &window, bool force) {
+ Menus &submenus = GetSubmenus();
+ const size_t num_submenus = submenus.size();
+ const int selected_idx = GetSelectedSubmenuIndex();
+ Menu::Type menu_type = GetType();
+ switch (menu_type) {
+ case Menu::Type::Bar: {
+ window.SetBackground(2);
+ window.MoveCursor(0, 0);
+ for (size_t i = 0; i < num_submenus; ++i) {
+ Menu *menu = submenus[i].get();
+ if (i > 0)
+ window.PutChar(' ');
+ menu->SetStartingColumn(window.GetCursorX());
+ window.PutCString("| ");
+ menu->DrawMenuTitle(window, false);
+ }
+ window.PutCString(" |");
+ window.DeferredRefresh();
+ } break;
- ProcessSP
- GetProcess ()
- {
- return m_debugger.GetCommandInterpreter().GetExecutionContext().GetProcessSP();
- }
-
- ThreadSP
- GetThread (const TreeItem &item)
- {
- ProcessSP process_sp = GetProcess ();
- if (process_sp)
- return process_sp->GetThreadList().FindThreadByID(item.GetIdentifier());
- return ThreadSP();
- }
-
- void
- TreeDelegateDrawTreeItem (TreeItem &item, Window &window) override
- {
- ThreadSP thread_sp = GetThread (item);
- if (thread_sp)
- {
- StreamString strm;
- ExecutionContext exe_ctx (thread_sp);
- if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr, nullptr, false, false))
- {
- int right_pad = 1;
- window.PutCStringTruncated(strm.GetString().c_str(), right_pad);
- }
- }
- }
-
- void
- TreeDelegateGenerateChildren (TreeItem &item) override
- {
- ProcessSP process_sp = GetProcess ();
- if (process_sp && process_sp->IsAlive())
- {
- StateType state = process_sp->GetState();
- if (StateIsStoppedState(state, true))
- {
- ThreadSP thread_sp = GetThread (item);
- if (thread_sp)
- {
- if (m_stop_id == process_sp->GetStopID() && thread_sp->GetID() == m_tid)
- return; // Children are already up to date
- if (!m_frame_delegate_sp)
- {
- // Always expand the thread item the first time we show it
- m_frame_delegate_sp.reset (new FrameTreeDelegate());
- }
-
- m_stop_id = process_sp->GetStopID();
- m_tid = thread_sp->GetID();
-
- TreeItem t (&item, *m_frame_delegate_sp, false);
- size_t num_frames = thread_sp->GetStackFrameCount();
- item.Resize (num_frames, t);
- for (size_t i = 0; i < num_frames; ++i)
- {
- item[i].SetUserData(thread_sp.get());
- item[i].SetIdentifier(i);
- }
- }
- return;
- }
- }
- item.ClearChildren();
- }
-
- bool
- TreeDelegateItemSelected (TreeItem &item) override
- {
- ProcessSP process_sp = GetProcess ();
- if (process_sp && process_sp->IsAlive())
- {
- StateType state = process_sp->GetState();
- if (StateIsStoppedState(state, true))
- {
- ThreadSP thread_sp = GetThread (item);
- if (thread_sp)
- {
- ThreadList &thread_list = thread_sp->GetProcess()->GetThreadList();
- std::lock_guard<std::recursive_mutex> guard(thread_list.GetMutex());
- ThreadSP selected_thread_sp = thread_list.GetSelectedThread();
- if (selected_thread_sp->GetID() != thread_sp->GetID())
- {
- thread_list.SetSelectedThreadByID(thread_sp->GetID());
- return true;
- }
- }
- }
- }
- return false;
- }
-
-protected:
- Debugger &m_debugger;
- std::shared_ptr<FrameTreeDelegate> m_frame_delegate_sp;
- lldb::user_id_t m_tid;
- uint32_t m_stop_id;
- FormatEntity::Entry m_format;
-};
-
-class ThreadsTreeDelegate : public TreeDelegate
-{
-public:
- ThreadsTreeDelegate (Debugger &debugger) :
- TreeDelegate(),
- m_thread_delegate_sp (),
- m_debugger (debugger),
- m_stop_id (UINT32_MAX)
- {
- FormatEntity::Parse("process ${process.id}{, name = ${process.name}}",
- m_format);
- }
-
- ~ThreadsTreeDelegate() override = default;
-
- ProcessSP
- GetProcess ()
- {
- return m_debugger.GetCommandInterpreter().GetExecutionContext().GetProcessSP();
- }
-
- void
- TreeDelegateDrawTreeItem (TreeItem &item, Window &window) override
- {
- ProcessSP process_sp = GetProcess ();
- if (process_sp && process_sp->IsAlive())
- {
- StreamString strm;
- ExecutionContext exe_ctx (process_sp);
- if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr, nullptr, false, false))
- {
- int right_pad = 1;
- window.PutCStringTruncated(strm.GetString().c_str(), right_pad);
- }
+ case Menu::Type::Item: {
+ int y = 1;
+ int x = 3;
+ // Draw the menu
+ int cursor_x = 0;
+ int cursor_y = 0;
+ window.Erase();
+ window.SetBackground(2);
+ window.Box();
+ for (size_t i = 0; i < num_submenus; ++i) {
+ const bool is_selected = (i == static_cast<size_t>(selected_idx));
+ window.MoveCursor(x, y + i);
+ if (is_selected) {
+ // Remember where we want the cursor to be
+ cursor_x = x - 1;
+ cursor_y = y + i;
+ }
+ submenus[i]->DrawMenuTitle(window, is_selected);
+ }
+ window.MoveCursor(cursor_x, cursor_y);
+ window.DeferredRefresh();
+ } break;
+
+ default:
+ case Menu::Type::Separator:
+ break;
+ }
+ return true; // Drawing handled...
+}
+
+HandleCharResult Menu::WindowDelegateHandleChar(Window &window, int key) {
+ HandleCharResult result = eKeyNotHandled;
+
+ Menus &submenus = GetSubmenus();
+ const size_t num_submenus = submenus.size();
+ const int selected_idx = GetSelectedSubmenuIndex();
+ Menu::Type menu_type = GetType();
+ if (menu_type == Menu::Type::Bar) {
+ MenuSP run_menu_sp;
+ switch (key) {
+ case KEY_DOWN:
+ case KEY_UP:
+ // Show last menu or first menu
+ if (selected_idx < static_cast<int>(num_submenus))
+ run_menu_sp = submenus[selected_idx];
+ else if (!submenus.empty())
+ run_menu_sp = submenus.front();
+ result = eKeyHandled;
+ break;
+
+ case KEY_RIGHT:
+ ++m_selected;
+ if (m_selected >= static_cast<int>(num_submenus))
+ m_selected = 0;
+ if (m_selected < static_cast<int>(num_submenus))
+ run_menu_sp = submenus[m_selected];
+ else if (!submenus.empty())
+ run_menu_sp = submenus.front();
+ result = eKeyHandled;
+ break;
+
+ case KEY_LEFT:
+ --m_selected;
+ if (m_selected < 0)
+ m_selected = num_submenus - 1;
+ if (m_selected < static_cast<int>(num_submenus))
+ run_menu_sp = submenus[m_selected];
+ else if (!submenus.empty())
+ run_menu_sp = submenus.front();
+ result = eKeyHandled;
+ break;
+
+ default:
+ for (size_t i = 0; i < num_submenus; ++i) {
+ if (submenus[i]->GetKeyValue() == key) {
+ SetSelectedSubmenuIndex(i);
+ run_menu_sp = submenus[i];
+ result = eKeyHandled;
+ break;
+ }
+ }
+ break;
+ }
+
+ if (run_menu_sp) {
+ // Run the action on this menu in case we need to populate the
+ // menu with dynamic content and also in case check marks, and
+ // any other menu decorations need to be calculated
+ if (run_menu_sp->Action() == MenuActionResult::Quit)
+ return eQuitApplication;
+
+ Rect menu_bounds;
+ menu_bounds.origin.x = run_menu_sp->GetStartingColumn();
+ menu_bounds.origin.y = 1;
+ menu_bounds.size.width = run_menu_sp->GetDrawWidth();
+ menu_bounds.size.height = run_menu_sp->GetSubmenus().size() + 2;
+ if (m_menu_window_sp)
+ window.GetParent()->RemoveSubWindow(m_menu_window_sp.get());
+
+ m_menu_window_sp = window.GetParent()->CreateSubWindow(
+ run_menu_sp->GetName().c_str(), menu_bounds, true);
+ m_menu_window_sp->SetDelegate(run_menu_sp);
+ }
+ } else if (menu_type == Menu::Type::Item) {
+ switch (key) {
+ case KEY_DOWN:
+ if (m_submenus.size() > 1) {
+ const int start_select = m_selected;
+ while (++m_selected != start_select) {
+ if (static_cast<size_t>(m_selected) >= num_submenus)
+ m_selected = 0;
+ if (m_submenus[m_selected]->GetType() == Type::Separator)
+ continue;
+ else
+ break;
}
- }
-
- void
- TreeDelegateGenerateChildren (TreeItem &item) override
- {
- ProcessSP process_sp = GetProcess ();
- if (process_sp && process_sp->IsAlive())
- {
- StateType state = process_sp->GetState();
- if (StateIsStoppedState(state, true))
- {
- const uint32_t stop_id = process_sp->GetStopID();
- if (m_stop_id == stop_id)
- return; // Children are already up to date
-
- m_stop_id = stop_id;
-
- if (!m_thread_delegate_sp)
- {
- // Always expand the thread item the first time we show it
- //item.Expand();
- m_thread_delegate_sp.reset (new ThreadTreeDelegate(m_debugger));
- }
-
- TreeItem t (&item, *m_thread_delegate_sp, false);
- ThreadList &threads = process_sp->GetThreadList();
- std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
- size_t num_threads = threads.GetSize();
- item.Resize (num_threads, t);
- for (size_t i = 0; i < num_threads; ++i)
- {
- item[i].SetIdentifier(threads.GetThreadAtIndex(i)->GetID());
- item[i].SetMightHaveChildren(true);
- }
- return;
- }
+ return eKeyHandled;
+ }
+ break;
+
+ case KEY_UP:
+ if (m_submenus.size() > 1) {
+ const int start_select = m_selected;
+ while (--m_selected != start_select) {
+ if (m_selected < static_cast<int>(0))
+ m_selected = num_submenus - 1;
+ if (m_submenus[m_selected]->GetType() == Type::Separator)
+ continue;
+ else
+ break;
}
- item.ClearChildren();
- }
-
- bool
- TreeDelegateItemSelected (TreeItem &item) override
- {
- return false;
- }
-
-protected:
- std::shared_ptr<ThreadTreeDelegate> m_thread_delegate_sp;
- Debugger &m_debugger;
- uint32_t m_stop_id;
- FormatEntity::Entry m_format;
-};
+ return eKeyHandled;
+ }
+ break;
+
+ case KEY_RETURN:
+ if (static_cast<size_t>(selected_idx) < num_submenus) {
+ if (submenus[selected_idx]->Action() == MenuActionResult::Quit)
+ return eQuitApplication;
+ window.GetParent()->RemoveSubWindow(&window);
+ return eKeyHandled;
+ }
+ break;
+
+ case KEY_ESCAPE: // Beware: pressing escape key has 1 to 2 second delay in
+ // case other chars are entered for escaped sequences
+ window.GetParent()->RemoveSubWindow(&window);
+ return eKeyHandled;
+
+ default:
+ for (size_t i = 0; i < num_submenus; ++i) {
+ Menu *menu = submenus[i].get();
+ if (menu->GetKeyValue() == key) {
+ SetSelectedSubmenuIndex(i);
+ window.GetParent()->RemoveSubWindow(&window);
+ if (menu->Action() == MenuActionResult::Quit)
+ return eQuitApplication;
+ return eKeyHandled;
+ }
+ }
+ break;
+ }
+ } else if (menu_type == Menu::Type::Separator) {
+ }
+ return result;
+}
-class ValueObjectListDelegate : public WindowDelegate
-{
+class Application {
public:
- ValueObjectListDelegate () :
- m_valobj_list (),
- m_rows (),
- m_selected_row(nullptr),
- m_selected_row_idx (0),
- m_first_visible_row (0),
- m_num_rows (0),
- m_max_x (0),
- m_max_y (0)
- {
- }
-
- ValueObjectListDelegate (ValueObjectList &valobj_list) :
- m_valobj_list (valobj_list),
- m_rows (),
- m_selected_row(nullptr),
- m_selected_row_idx (0),
- m_first_visible_row (0),
- m_num_rows (0),
- m_max_x (0),
- m_max_y (0)
- {
- SetValues (valobj_list);
- }
-
- ~ValueObjectListDelegate() override = default;
-
- void
- SetValues (ValueObjectList &valobj_list)
- {
- m_selected_row = nullptr;
- m_selected_row_idx = 0;
- m_first_visible_row = 0;
- m_num_rows = 0;
- m_rows.clear();
- m_valobj_list = valobj_list;
- const size_t num_values = m_valobj_list.GetSize();
- for (size_t i = 0; i < num_values; ++i)
- m_rows.push_back(Row(m_valobj_list.GetValueObjectAtIndex(i), nullptr));
- }
-
- bool
- WindowDelegateDraw (Window &window, bool force) override
- {
- m_num_rows = 0;
- m_min_x = 2;
- m_min_y = 1;
- m_max_x = window.GetWidth() - 1;
- m_max_y = window.GetHeight() - 1;
-
- window.Erase();
- window.DrawTitleBox (window.GetName());
-
- const int num_visible_rows = NumVisibleRows();
- const int num_rows = CalculateTotalNumberRows (m_rows);
-
- // If we unexpanded while having something selected our
- // total number of rows is less than the num visible rows,
- // then make sure we show all the rows by setting the first
- // visible row accordingly.
- if (m_first_visible_row > 0 && num_rows < num_visible_rows)
- m_first_visible_row = 0;
-
- // Make sure the selected row is always visible
- if (m_selected_row_idx < m_first_visible_row)
- m_first_visible_row = m_selected_row_idx;
- else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx)
- m_first_visible_row = m_selected_row_idx - num_visible_rows + 1;
-
- DisplayRows (window, m_rows, g_options);
-
- window.DeferredRefresh();
-
- // Get the selected row
- m_selected_row = GetRowForRowIndex (m_selected_row_idx);
- // Keep the cursor on the selected row so the highlight and the cursor
- // are always on the same line
- if (m_selected_row)
- window.MoveCursor (m_selected_row->x,
- m_selected_row->y);
-
- return true; // Drawing handled
- }
-
- KeyHelp *
- WindowDelegateGetKeyHelp () override
- {
- static curses::KeyHelp g_source_view_key_help[] = {
- { KEY_UP, "Select previous item" },
- { KEY_DOWN, "Select next item" },
- { KEY_RIGHT, "Expand selected item" },
- { KEY_LEFT, "Unexpand selected item or select parent if not expanded" },
- { KEY_PPAGE, "Page up" },
- { KEY_NPAGE, "Page down" },
- { 'A', "Format as annotated address" },
- { 'b', "Format as binary" },
- { 'B', "Format as hex bytes with ASCII" },
- { 'c', "Format as character" },
- { 'd', "Format as a signed integer" },
- { 'D', "Format selected value using the default format for the type" },
- { 'f', "Format as float" },
- { 'h', "Show help dialog" },
- { 'i', "Format as instructions" },
- { 'o', "Format as octal" },
- { 'p', "Format as pointer" },
- { 's', "Format as C string" },
- { 't', "Toggle showing/hiding type names" },
- { 'u', "Format as an unsigned integer" },
- { 'x', "Format as hex" },
- { 'X', "Format as uppercase hex" },
- { ' ', "Toggle item expansion" },
- { ',', "Page up" },
- { '.', "Page down" },
- { '\0', nullptr }
- };
- return g_source_view_key_help;
- }
-
- HandleCharResult
- WindowDelegateHandleChar (Window &window, int c) override
- {
- switch(c)
- {
- case 'x':
- case 'X':
- case 'o':
- case 's':
- case 'u':
- case 'd':
- case 'D':
- case 'i':
- case 'A':
- case 'p':
- case 'c':
- case 'b':
- case 'B':
- case 'f':
- // Change the format for the currently selected item
- if (m_selected_row)
- m_selected_row->valobj->SetFormat (FormatForChar (c));
- return eKeyHandled;
-
- case 't':
- // Toggle showing type names
- g_options.show_types = !g_options.show_types;
- return eKeyHandled;
-
- case ',':
- case KEY_PPAGE:
- // Page up key
- if (m_first_visible_row > 0)
- {
- if (static_cast<int>(m_first_visible_row) > m_max_y)
- m_first_visible_row -= m_max_y;
- else
- m_first_visible_row = 0;
- m_selected_row_idx = m_first_visible_row;
- }
- return eKeyHandled;
-
- case '.':
- case KEY_NPAGE:
- // Page down key
- if (m_num_rows > static_cast<size_t>(m_max_y))
- {
- if (m_first_visible_row + m_max_y < m_num_rows)
- {
- m_first_visible_row += m_max_y;
- m_selected_row_idx = m_first_visible_row;
- }
- }
- return eKeyHandled;
-
- case KEY_UP:
- if (m_selected_row_idx > 0)
- --m_selected_row_idx;
- return eKeyHandled;
-
- case KEY_DOWN:
- if (m_selected_row_idx + 1 < m_num_rows)
- ++m_selected_row_idx;
- return eKeyHandled;
-
- case KEY_RIGHT:
- if (m_selected_row)
- {
- if (!m_selected_row->expanded)
- m_selected_row->Expand();
- }
- return eKeyHandled;
-
- case KEY_LEFT:
- if (m_selected_row)
- {
- if (m_selected_row->expanded)
- m_selected_row->Unexpand();
- else if (m_selected_row->parent)
- m_selected_row_idx = m_selected_row->parent->row_idx;
- }
- return eKeyHandled;
-
- case ' ':
- // Toggle expansion state when SPACE is pressed
- if (m_selected_row)
- {
- if (m_selected_row->expanded)
- m_selected_row->Unexpand();
- else
- m_selected_row->Expand();
- }
- return eKeyHandled;
-
- case 'h':
- window.CreateHelpSubwindow ();
- return eKeyHandled;
-
- default:
- break;
- }
- return eKeyNotHandled;
- }
-
-protected:
- ValueObjectList m_valobj_list;
- std::vector<Row> m_rows;
- Row *m_selected_row;
- uint32_t m_selected_row_idx;
- uint32_t m_first_visible_row;
- uint32_t m_num_rows;
- int m_min_x;
- int m_min_y;
- int m_max_x;
- int m_max_y;
+ Application(FILE *in, FILE *out)
+ : m_window_sp(), m_screen(nullptr), m_in(in), m_out(out) {}
- static Format
- FormatForChar (int c)
- {
- switch (c)
- {
- case 'x': return eFormatHex;
- case 'X': return eFormatHexUppercase;
- case 'o': return eFormatOctal;
- case 's': return eFormatCString;
- case 'u': return eFormatUnsigned;
- case 'd': return eFormatDecimal;
- case 'D': return eFormatDefault;
- case 'i': return eFormatInstruction;
- case 'A': return eFormatAddressInfo;
- case 'p': return eFormatPointer;
- case 'c': return eFormatChar;
- case 'b': return eFormatBinary;
- case 'B': return eFormatBytesWithASCII;
- case 'f': return eFormatFloat;
- }
- return eFormatDefault;
- }
-
- bool
- DisplayRowObject (Window &window,
- Row &row,
- DisplayOptions &options,
- bool highlight,
- bool last_child)
- {
- ValueObject *valobj = row.valobj.get();
-
- if (valobj == nullptr)
- return false;
-
- const char *type_name = options.show_types ? valobj->GetTypeName().GetCString() : nullptr;
- const char *name = valobj->GetName().GetCString();
- const char *value = valobj->GetValueAsCString ();
- const char *summary = valobj->GetSummaryAsCString ();
-
- window.MoveCursor (row.x, row.y);
-
- row.DrawTree (window);
-
- if (highlight)
- window.AttributeOn(A_REVERSE);
-
- if (type_name && type_name[0])
- window.Printf ("(%s) ", type_name);
-
- if (name && name[0])
- window.PutCString(name);
-
- attr_t changd_attr = 0;
- if (valobj->GetValueDidChange())
- changd_attr = COLOR_PAIR(5) | A_BOLD;
-
- if (value && value[0])
- {
- window.PutCString(" = ");
- if (changd_attr)
- window.AttributeOn(changd_attr);
- window.PutCString (value);
- if (changd_attr)
- window.AttributeOff(changd_attr);
- }
-
- if (summary && summary[0])
- {
- window.PutChar(' ');
- if (changd_attr)
- window.AttributeOn(changd_attr);
- window.PutCString(summary);
- if (changd_attr)
- window.AttributeOff(changd_attr);
- }
-
- if (highlight)
- window.AttributeOff (A_REVERSE);
-
- return true;
- }
-
- void
- DisplayRows (Window &window,
- std::vector<Row> &rows,
- DisplayOptions &options)
- {
- // > 0x25B7
- // \/ 0x25BD
-
- bool window_is_active = window.IsActive();
- for (auto &row : rows)
- {
- const bool last_child = row.parent && &rows[rows.size()-1] == &row;
- // Save the row index in each Row structure
- row.row_idx = m_num_rows;
- if ((m_num_rows >= m_first_visible_row) &&
- ((m_num_rows - m_first_visible_row) < static_cast<size_t>(NumVisibleRows())))
- {
- row.x = m_min_x;
- row.y = m_num_rows - m_first_visible_row + 1;
- if (DisplayRowObject (window,
- row,
- options,
- window_is_active && m_num_rows == m_selected_row_idx,
- last_child))
- {
- ++m_num_rows;
- }
- else
- {
- row.x = 0;
- row.y = 0;
- }
- }
- else
- {
- row.x = 0;
- row.y = 0;
- ++m_num_rows;
- }
-
- if (row.expanded && !row.children.empty())
- {
- DisplayRows (window,
- row.children,
- options);
- }
- }
- }
-
- int
- CalculateTotalNumberRows (const std::vector<Row> &rows)
- {
- int row_count = 0;
- for (const auto &row : rows)
- {
- ++row_count;
- if (row.expanded)
- row_count += CalculateTotalNumberRows(row.children);
- }
- return row_count;
- }
-
- static Row *
- GetRowForRowIndexImpl (std::vector<Row> &rows, size_t &row_index)
- {
- for (auto &row : rows)
- {
- if (row_index == 0)
- return &row;
- else
- {
- --row_index;
- if (row.expanded && !row.children.empty())
- {
- Row *result = GetRowForRowIndexImpl (row.children, row_index);
- if (result)
- return result;
- }
- }
- }
- return nullptr;
- }
-
- Row *
- GetRowForRowIndex (size_t row_index)
- {
- return GetRowForRowIndexImpl (m_rows, row_index);
- }
-
- int
- NumVisibleRows () const
- {
- return m_max_y - m_min_y;
- }
-
- static DisplayOptions g_options;
-};
+ ~Application() {
+ m_window_delegates.clear();
+ m_window_sp.reset();
+ if (m_screen) {
+ ::delscreen(m_screen);
+ m_screen = nullptr;
+ }
+ }
+
+ void Initialize() {
+ ::setlocale(LC_ALL, "");
+ ::setlocale(LC_CTYPE, "");
+#if 0
+ ::initscr();
+#else
+ m_screen = ::newterm(nullptr, m_out, m_in);
+#endif
+ ::start_color();
+ ::curs_set(0);
+ ::noecho();
+ ::keypad(stdscr, TRUE);
+ }
-class FrameVariablesWindowDelegate : public ValueObjectListDelegate
-{
-public:
- FrameVariablesWindowDelegate (Debugger &debugger) :
- ValueObjectListDelegate (),
- m_debugger (debugger),
- m_frame_block(nullptr)
- {
- }
+ void Terminate() { ::endwin(); }
- ~FrameVariablesWindowDelegate() override = default;
+ void Run(Debugger &debugger) {
+ bool done = false;
+ int delay_in_tenths_of_a_second = 1;
- const char *
- WindowDelegateGetHelpText () override
- {
- return "Frame variable window keyboard shortcuts:";
- }
-
- bool
- WindowDelegateDraw (Window &window, bool force) override
- {
- ExecutionContext exe_ctx (m_debugger.GetCommandInterpreter().GetExecutionContext());
- Process *process = exe_ctx.GetProcessPtr();
- Block *frame_block = nullptr;
- StackFrame *frame = nullptr;
-
- if (process)
- {
- StateType state = process->GetState();
- if (StateIsStoppedState(state, true))
- {
- frame = exe_ctx.GetFramePtr();
- if (frame)
- frame_block = frame->GetFrameBlock ();
- }
- else if (StateIsRunningState(state))
- {
- return true; // Don't do any updating when we are running
- }
- }
+ // Alas the threading model in curses is a bit lame so we need to
+ // resort to polling every 0.5 seconds. We could poll for stdin
+ // ourselves and then pass the keys down but then we need to
+ // translate all of the escape sequences ourselves. So we resort to
+ // polling for input because we need to receive async process events
+ // while in this loop.
+
+ halfdelay(delay_in_tenths_of_a_second); // Poll using some number of tenths
+ // of seconds seconds when calling
+ // Window::GetChar()
+
+ ListenerSP listener_sp(
+ Listener::MakeListener("lldb.IOHandler.curses.Application"));
+ ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
+ ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
+ ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
+ debugger.EnableForwardEvents(listener_sp);
- ValueObjectList local_values;
- if (frame_block)
- {
- // Only update the variables if they have changed
- if (m_frame_block != frame_block)
- {
- m_frame_block = frame_block;
-
- VariableList *locals = frame->GetVariableList(true);
- if (locals)
- {
- const DynamicValueType use_dynamic = eDynamicDontRunTarget;
- const size_t num_locals = locals->GetSize();
- for (size_t i = 0; i < num_locals; ++i)
- {
- ValueObjectSP value_sp = frame->GetValueObjectForFrameVariable (locals->GetVariableAtIndex(i), use_dynamic);
- if (value_sp)
- {
- ValueObjectSP synthetic_value_sp = value_sp->GetSyntheticValue();
- if (synthetic_value_sp)
- local_values.Append(synthetic_value_sp);
- else
- local_values.Append(value_sp);
- }
- }
- // Update the values
- SetValues(local_values);
- }
- }
- }
- else
- {
- m_frame_block = nullptr;
- // Update the values with an empty list if there is no frame
- SetValues(local_values);
- }
-
- return ValueObjectListDelegate::WindowDelegateDraw (window, force);
- }
+ bool update = true;
+#if defined(__APPLE__)
+ std::deque<int> escape_chars;
+#endif
-protected:
- Debugger &m_debugger;
- Block *m_frame_block;
-};
+ while (!done) {
+ if (update) {
+ m_window_sp->Draw(false);
+ // All windows should be calling Window::DeferredRefresh() instead
+ // of Window::Refresh() so we can do a single update and avoid
+ // any screen blinking
+ update_panels();
+
+ // Cursor hiding isn't working on MacOSX, so hide it in the top left
+ // corner
+ m_window_sp->MoveCursor(0, 0);
+
+ doupdate();
+ update = false;
+ }
-class RegistersWindowDelegate : public ValueObjectListDelegate
-{
-public:
- RegistersWindowDelegate (Debugger &debugger) :
- ValueObjectListDelegate (),
- m_debugger (debugger)
- {
- }
+#if defined(__APPLE__)
+ // Terminal.app doesn't map its function keys correctly, F1-F4 default to:
+ // \033OP, \033OQ, \033OR, \033OS, so lets take care of this here if
+ // possible
+ int ch;
+ if (escape_chars.empty())
+ ch = m_window_sp->GetChar();
+ else {
+ ch = escape_chars.front();
+ escape_chars.pop_front();
+ }
+ if (ch == KEY_ESCAPE) {
+ int ch2 = m_window_sp->GetChar();
+ if (ch2 == 'O') {
+ int ch3 = m_window_sp->GetChar();
+ switch (ch3) {
+ case 'P':
+ ch = KEY_F(1);
+ break;
+ case 'Q':
+ ch = KEY_F(2);
+ break;
+ case 'R':
+ ch = KEY_F(3);
+ break;
+ case 'S':
+ ch = KEY_F(4);
+ break;
+ default:
+ escape_chars.push_back(ch2);
+ if (ch3 != -1)
+ escape_chars.push_back(ch3);
+ break;
+ }
+ } else if (ch2 != -1)
+ escape_chars.push_back(ch2);
+ }
+#else
+ int ch = m_window_sp->GetChar();
- ~RegistersWindowDelegate() override = default;
+#endif
+ if (ch == -1) {
+ if (feof(m_in) || ferror(m_in)) {
+ done = true;
+ } else {
+ // Just a timeout from using halfdelay(), check for events
+ EventSP event_sp;
+ while (listener_sp->PeekAtNextEvent()) {
+ listener_sp->GetNextEvent(event_sp);
+
+ if (event_sp) {
+ Broadcaster *broadcaster = event_sp->GetBroadcaster();
+ if (broadcaster) {
+ // uint32_t event_type = event_sp->GetType();
+ ConstString broadcaster_class(
+ broadcaster->GetBroadcasterClass());
+ if (broadcaster_class == broadcaster_class_process) {
+ debugger.GetCommandInterpreter().UpdateExecutionContext(
+ nullptr);
+ update = true;
+ continue; // Don't get any key, just update our view
+ }
+ }
+ }
+ }
+ }
+ } else {
+ HandleCharResult key_result = m_window_sp->HandleChar(ch);
+ switch (key_result) {
+ case eKeyHandled:
+ debugger.GetCommandInterpreter().UpdateExecutionContext(nullptr);
+ update = true;
+ break;
+ case eKeyNotHandled:
+ break;
+ case eQuitApplication:
+ done = true;
+ break;
+ }
+ }
+ }
+
+ debugger.CancelForwardEvents(listener_sp);
+ }
+
+ WindowSP &GetMainWindow() {
+ if (!m_window_sp)
+ m_window_sp.reset(new Window("main", stdscr, false));
+ return m_window_sp;
+ }
- const char *
- WindowDelegateGetHelpText () override
- {
- return "Register window keyboard shortcuts:";
- }
+ WindowDelegates &GetWindowDelegates() { return m_window_delegates; }
- bool
- WindowDelegateDraw (Window &window, bool force) override
- {
- ExecutionContext exe_ctx (m_debugger.GetCommandInterpreter().GetExecutionContext());
- StackFrame *frame = exe_ctx.GetFramePtr();
-
- ValueObjectList value_list;
- if (frame)
- {
- if (frame->GetStackID() != m_stack_id)
- {
- m_stack_id = frame->GetStackID();
- RegisterContextSP reg_ctx (frame->GetRegisterContext());
- if (reg_ctx)
- {
- const uint32_t num_sets = reg_ctx->GetRegisterSetCount();
- for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx)
- {
- value_list.Append(ValueObjectRegisterSet::Create (frame, reg_ctx, set_idx));
- }
- }
- SetValues(value_list);
- }
- }
- else
- {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive())
- return true; // Don't do any updating if we are running
- else
- {
- // Update the values with an empty list if there
- // is no process or the process isn't alive anymore
- SetValues(value_list);
- }
- }
- return ValueObjectListDelegate::WindowDelegateDraw (window, force);
- }
-
protected:
- Debugger &m_debugger;
- StackID m_stack_id;
+ WindowSP m_window_sp;
+ WindowDelegates m_window_delegates;
+ SCREEN *m_screen;
+ FILE *m_in;
+ FILE *m_out;
};
-static const char *
-CursesKeyToCString (int ch)
-{
- static char g_desc[32];
- if (ch >= KEY_F0 && ch < KEY_F0 + 64)
- {
- snprintf(g_desc, sizeof(g_desc), "F%u", ch - KEY_F0);
- return g_desc;
- }
- switch (ch)
- {
- case KEY_DOWN: return "down";
- case KEY_UP: return "up";
- case KEY_LEFT: return "left";
- case KEY_RIGHT: return "right";
- case KEY_HOME: return "home";
- case KEY_BACKSPACE: return "backspace";
- case KEY_DL: return "delete-line";
- case KEY_IL: return "insert-line";
- case KEY_DC: return "delete-char";
- case KEY_IC: return "insert-char";
- case KEY_CLEAR: return "clear";
- case KEY_EOS: return "clear-to-eos";
- case KEY_EOL: return "clear-to-eol";
- case KEY_SF: return "scroll-forward";
- case KEY_SR: return "scroll-backward";
- case KEY_NPAGE: return "page-down";
- case KEY_PPAGE: return "page-up";
- case KEY_STAB: return "set-tab";
- case KEY_CTAB: return "clear-tab";
- case KEY_CATAB: return "clear-all-tabs";
- case KEY_ENTER: return "enter";
- case KEY_PRINT: return "print";
- case KEY_LL: return "lower-left key";
- case KEY_A1: return "upper left of keypad";
- case KEY_A3: return "upper right of keypad";
- case KEY_B2: return "center of keypad";
- case KEY_C1: return "lower left of keypad";
- case KEY_C3: return "lower right of keypad";
- case KEY_BTAB: return "back-tab key";
- case KEY_BEG: return "begin key";
- case KEY_CANCEL: return "cancel key";
- case KEY_CLOSE: return "close key";
- case KEY_COMMAND: return "command key";
- case KEY_COPY: return "copy key";
- case KEY_CREATE: return "create key";
- case KEY_END: return "end key";
- case KEY_EXIT: return "exit key";
- case KEY_FIND: return "find key";
- case KEY_HELP: return "help key";
- case KEY_MARK: return "mark key";
- case KEY_MESSAGE: return "message key";
- case KEY_MOVE: return "move key";
- case KEY_NEXT: return "next key";
- case KEY_OPEN: return "open key";
- case KEY_OPTIONS: return "options key";
- case KEY_PREVIOUS: return "previous key";
- case KEY_REDO: return "redo key";
- case KEY_REFERENCE: return "reference key";
- case KEY_REFRESH: return "refresh key";
- case KEY_REPLACE: return "replace key";
- case KEY_RESTART: return "restart key";
- case KEY_RESUME: return "resume key";
- case KEY_SAVE: return "save key";
- case KEY_SBEG: return "shifted begin key";
- case KEY_SCANCEL: return "shifted cancel key";
- case KEY_SCOMMAND: return "shifted command key";
- case KEY_SCOPY: return "shifted copy key";
- case KEY_SCREATE: return "shifted create key";
- case KEY_SDC: return "shifted delete-character key";
- case KEY_SDL: return "shifted delete-line key";
- case KEY_SELECT: return "select key";
- case KEY_SEND: return "shifted end key";
- case KEY_SEOL: return "shifted clear-to-end-of-line key";
- case KEY_SEXIT: return "shifted exit key";
- case KEY_SFIND: return "shifted find key";
- case KEY_SHELP: return "shifted help key";
- case KEY_SHOME: return "shifted home key";
- case KEY_SIC: return "shifted insert-character key";
- case KEY_SLEFT: return "shifted left-arrow key";
- case KEY_SMESSAGE: return "shifted message key";
- case KEY_SMOVE: return "shifted move key";
- case KEY_SNEXT: return "shifted next key";
- case KEY_SOPTIONS: return "shifted options key";
- case KEY_SPREVIOUS: return "shifted previous key";
- case KEY_SPRINT: return "shifted print key";
- case KEY_SREDO: return "shifted redo key";
- case KEY_SREPLACE: return "shifted replace key";
- case KEY_SRIGHT: return "shifted right-arrow key";
- case KEY_SRSUME: return "shifted resume key";
- case KEY_SSAVE: return "shifted save key";
- case KEY_SSUSPEND: return "shifted suspend key";
- case KEY_SUNDO: return "shifted undo key";
- case KEY_SUSPEND: return "suspend key";
- case KEY_UNDO: return "undo key";
- case KEY_MOUSE: return "Mouse event has occurred";
- case KEY_RESIZE: return "Terminal resize event";
-#ifdef KEY_EVENT
- case KEY_EVENT: return "We were interrupted by an event";
-#endif
- case KEY_RETURN: return "return";
- case ' ': return "space";
- case '\t': return "tab";
- case KEY_ESCAPE: return "escape";
- default:
- if (isprint(ch))
- snprintf(g_desc, sizeof(g_desc), "%c", ch);
- else
- snprintf(g_desc, sizeof(g_desc), "\\x%2.2x", ch);
- return g_desc;
- }
- return nullptr;
-}
+} // namespace curses
-HelpDialogDelegate::HelpDialogDelegate (const char *text, KeyHelp *key_help_array) :
- m_text (),
- m_first_visible_line (0)
-{
- if (text && text[0])
- {
- m_text.SplitIntoLines(text);
- m_text.AppendString("");
- }
- if (key_help_array)
- {
- for (KeyHelp *key = key_help_array; key->ch; ++key)
- {
- StreamString key_description;
- key_description.Printf("%10s - %s", CursesKeyToCString(key->ch), key->description);
- m_text.AppendString(std::move(key_description.GetString()));
- }
- }
-}
+using namespace curses;
-HelpDialogDelegate::~HelpDialogDelegate() = default;
-
-bool
-HelpDialogDelegate::WindowDelegateDraw (Window &window, bool force)
-{
- window.Erase();
- const int window_height = window.GetHeight();
- int x = 2;
- int y = 1;
- const int min_y = y;
- const int max_y = window_height - 1 - y;
- const size_t num_visible_lines = max_y - min_y + 1;
- const size_t num_lines = m_text.GetSize();
- const char *bottom_message;
- if (num_lines <= num_visible_lines)
- bottom_message = "Press any key to exit";
- else
- bottom_message = "Use arrows to scroll, any other key to exit";
- window.DrawTitleBox(window.GetName(), bottom_message);
- while (y <= max_y)
- {
- window.MoveCursor(x, y);
- window.PutCStringTruncated(m_text.GetStringAtIndex(m_first_visible_line + y - min_y), 1);
- ++y;
- }
- return true;
-}
+struct Row {
+ ValueObjectSP valobj;
+ Row *parent;
+ int row_idx;
+ int x;
+ int y;
+ bool might_have_children;
+ bool expanded;
+ bool calculated_children;
+ std::vector<Row> children;
+
+ Row(const ValueObjectSP &v, Row *p)
+ : valobj(v), parent(p), row_idx(0), x(1), y(1),
+ might_have_children(v ? v->MightHaveChildren() : false),
+ expanded(false), calculated_children(false), children() {}
+
+ size_t GetDepth() const {
+ if (parent)
+ return 1 + parent->GetDepth();
+ return 0;
+ }
-HandleCharResult
-HelpDialogDelegate::WindowDelegateHandleChar (Window &window, int key)
-{
- bool done = false;
- const size_t num_lines = m_text.GetSize();
- const size_t num_visible_lines = window.GetHeight() - 2;
-
- if (num_lines <= num_visible_lines)
- {
- done = true;
- // If we have all lines visible and don't need scrolling, then any
- // key press will cause us to exit
+ void Expand() {
+ expanded = true;
+ if (!calculated_children) {
+ calculated_children = true;
+ if (valobj) {
+ const size_t num_children = valobj->GetNumChildren();
+ for (size_t i = 0; i < num_children; ++i) {
+ children.push_back(Row(valobj->GetChildAtIndex(i, true), this));
+ }
+ }
+ }
+ }
+
+ void Unexpand() { expanded = false; }
+
+ void DrawTree(Window &window) {
+ if (parent)
+ parent->DrawTreeForChild(window, this, 0);
+
+ if (might_have_children) {
+ // It we can get UTF8 characters to work we should try to use the "symbol"
+ // UTF8 string below
+ // const char *symbol = "";
+ // if (row.expanded)
+ // symbol = "\xe2\x96\xbd ";
+ // else
+ // symbol = "\xe2\x96\xb7 ";
+ // window.PutCString (symbol);
+
+ // The ACS_DARROW and ACS_RARROW don't look very nice they are just a
+ // 'v' or '>' character...
+ // if (expanded)
+ // window.PutChar (ACS_DARROW);
+ // else
+ // window.PutChar (ACS_RARROW);
+ // Since we can't find any good looking right arrow/down arrow
+ // symbols, just use a diamond...
+ window.PutChar(ACS_DIAMOND);
+ window.PutChar(ACS_HLINE);
+ }
+ }
+
+ void DrawTreeForChild(Window &window, Row *child, uint32_t reverse_depth) {
+ if (parent)
+ parent->DrawTreeForChild(window, this, reverse_depth + 1);
+
+ if (&children.back() == child) {
+ // Last child
+ if (reverse_depth == 0) {
+ window.PutChar(ACS_LLCORNER);
+ window.PutChar(ACS_HLINE);
+ } else {
+ window.PutChar(' ');
+ window.PutChar(' ');
+ }
+ } else {
+ if (reverse_depth == 0) {
+ window.PutChar(ACS_LTEE);
+ window.PutChar(ACS_HLINE);
+ } else {
+ window.PutChar(ACS_VLINE);
+ window.PutChar(' ');
+ }
}
- else
- {
- switch (key)
- {
- case KEY_UP:
- if (m_first_visible_line > 0)
- --m_first_visible_line;
- break;
+ }
+};
- case KEY_DOWN:
- if (m_first_visible_line + num_visible_lines < num_lines)
- ++m_first_visible_line;
- break;
+struct DisplayOptions {
+ bool show_types;
+};
- case KEY_PPAGE:
- case ',':
- if (m_first_visible_line > 0)
- {
- if (static_cast<size_t>(m_first_visible_line) >= num_visible_lines)
- m_first_visible_line -= num_visible_lines;
- else
- m_first_visible_line = 0;
- }
- break;
+class TreeItem;
- case KEY_NPAGE:
- case '.':
- if (m_first_visible_line + num_visible_lines < num_lines)
- {
- m_first_visible_line += num_visible_lines;
- if (static_cast<size_t>(m_first_visible_line) > num_lines)
- m_first_visible_line = num_lines - num_visible_lines;
- }
- break;
+class TreeDelegate {
+public:
+ TreeDelegate() = default;
+ virtual ~TreeDelegate() = default;
- default:
- done = true;
- break;
- }
- }
- if (done)
- window.GetParent()->RemoveSubWindow(&window);
- return eKeyHandled;
-}
+ virtual void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) = 0;
+ virtual void TreeDelegateGenerateChildren(TreeItem &item) = 0;
+ virtual bool TreeDelegateItemSelected(
+ TreeItem &item) = 0; // Return true if we need to update views
+};
-class ApplicationDelegate :
- public WindowDelegate,
- public MenuDelegate
-{
+typedef std::shared_ptr<TreeDelegate> TreeDelegateSP;
+
+class TreeItem {
public:
- enum {
- eMenuID_LLDB = 1,
- eMenuID_LLDBAbout,
- eMenuID_LLDBExit,
-
- eMenuID_Target,
- eMenuID_TargetCreate,
- eMenuID_TargetDelete,
-
- eMenuID_Process,
- eMenuID_ProcessAttach,
- eMenuID_ProcessDetach,
- eMenuID_ProcessLaunch,
- eMenuID_ProcessContinue,
- eMenuID_ProcessHalt,
- eMenuID_ProcessKill,
-
- eMenuID_Thread,
- eMenuID_ThreadStepIn,
- eMenuID_ThreadStepOver,
- eMenuID_ThreadStepOut,
-
- eMenuID_View,
- eMenuID_ViewBacktrace,
- eMenuID_ViewRegisters,
- eMenuID_ViewSource,
- eMenuID_ViewVariables,
-
- eMenuID_Help,
- eMenuID_HelpGUIHelp
- };
-
- ApplicationDelegate (Application &app, Debugger &debugger) :
- WindowDelegate (),
- MenuDelegate (),
- m_app (app),
- m_debugger (debugger)
- {
- }
+ TreeItem(TreeItem *parent, TreeDelegate &delegate, bool might_have_children)
+ : m_parent(parent), m_delegate(delegate), m_user_data(nullptr),
+ m_identifier(0), m_row_idx(-1), m_children(),
+ m_might_have_children(might_have_children), m_is_expanded(false) {}
+
+ TreeItem &operator=(const TreeItem &rhs) {
+ if (this != &rhs) {
+ m_parent = rhs.m_parent;
+ m_delegate = rhs.m_delegate;
+ m_user_data = rhs.m_user_data;
+ m_identifier = rhs.m_identifier;
+ m_row_idx = rhs.m_row_idx;
+ m_children = rhs.m_children;
+ m_might_have_children = rhs.m_might_have_children;
+ m_is_expanded = rhs.m_is_expanded;
+ }
+ return *this;
+ }
+
+ size_t GetDepth() const {
+ if (m_parent)
+ return 1 + m_parent->GetDepth();
+ return 0;
+ }
- ~ApplicationDelegate() override = default;
+ int GetRowIndex() const { return m_row_idx; }
- bool
- WindowDelegateDraw (Window &window, bool force) override
- {
- return false; // Drawing not handled, let standard window drawing happen
- }
-
- HandleCharResult
- WindowDelegateHandleChar (Window &window, int key) override
- {
- switch (key)
- {
- case '\t':
- window.SelectNextWindowAsActive();
- return eKeyHandled;
-
- case 'h':
- window.CreateHelpSubwindow();
- return eKeyHandled;
+ void ClearChildren() { m_children.clear(); }
- case KEY_ESCAPE:
- return eQuitApplication;
+ void Resize(size_t n, const TreeItem &t) { m_children.resize(n, t); }
- default:
- break;
- }
- return eKeyNotHandled;
+ TreeItem &operator[](size_t i) { return m_children[i]; }
+
+ void SetRowIndex(int row_idx) { m_row_idx = row_idx; }
+
+ size_t GetNumChildren() {
+ m_delegate.TreeDelegateGenerateChildren(*this);
+ return m_children.size();
+ }
+
+ void ItemWasSelected() { m_delegate.TreeDelegateItemSelected(*this); }
+
+ void CalculateRowIndexes(int &row_idx) {
+ SetRowIndex(row_idx);
+ ++row_idx;
+
+ const bool expanded = IsExpanded();
+
+ // The root item must calculate its children,
+ // or we must calculate the number of children
+ // if the item is expanded
+ if (m_parent == nullptr || expanded)
+ GetNumChildren();
+
+ for (auto &item : m_children) {
+ if (expanded)
+ item.CalculateRowIndexes(row_idx);
+ else
+ item.SetRowIndex(-1);
+ }
+ }
+
+ TreeItem *GetParent() { return m_parent; }
+
+ bool IsExpanded() const { return m_is_expanded; }
+
+ void Expand() { m_is_expanded = true; }
+
+ void Unexpand() { m_is_expanded = false; }
+
+ bool Draw(Window &window, const int first_visible_row,
+ const uint32_t selected_row_idx, int &row_idx, int &num_rows_left) {
+ if (num_rows_left <= 0)
+ return false;
+
+ if (m_row_idx >= first_visible_row) {
+ window.MoveCursor(2, row_idx + 1);
+
+ if (m_parent)
+ m_parent->DrawTreeForChild(window, this, 0);
+
+ if (m_might_have_children) {
+ // It we can get UTF8 characters to work we should try to use the
+ // "symbol"
+ // UTF8 string below
+ // const char *symbol = "";
+ // if (row.expanded)
+ // symbol = "\xe2\x96\xbd ";
+ // else
+ // symbol = "\xe2\x96\xb7 ";
+ // window.PutCString (symbol);
+
+ // The ACS_DARROW and ACS_RARROW don't look very nice they are just a
+ // 'v' or '>' character...
+ // if (expanded)
+ // window.PutChar (ACS_DARROW);
+ // else
+ // window.PutChar (ACS_RARROW);
+ // Since we can't find any good looking right arrow/down arrow
+ // symbols, just use a diamond...
+ window.PutChar(ACS_DIAMOND);
+ window.PutChar(ACS_HLINE);
+ }
+ bool highlight = (selected_row_idx == static_cast<size_t>(m_row_idx)) &&
+ window.IsActive();
+
+ if (highlight)
+ window.AttributeOn(A_REVERSE);
+
+ m_delegate.TreeDelegateDrawTreeItem(*this, window);
+
+ if (highlight)
+ window.AttributeOff(A_REVERSE);
+ ++row_idx;
+ --num_rows_left;
+ }
+
+ if (num_rows_left <= 0)
+ return false; // We are done drawing...
+
+ if (IsExpanded()) {
+ for (auto &item : m_children) {
+ // If we displayed all the rows and item.Draw() returns
+ // false we are done drawing and can exit this for loop
+ if (!item.Draw(window, first_visible_row, selected_row_idx, row_idx,
+ num_rows_left))
+ break;
+ }
+ }
+ return num_rows_left >= 0; // Return true if not done drawing yet
+ }
+
+ void DrawTreeForChild(Window &window, TreeItem *child,
+ uint32_t reverse_depth) {
+ if (m_parent)
+ m_parent->DrawTreeForChild(window, this, reverse_depth + 1);
+
+ if (&m_children.back() == child) {
+ // Last child
+ if (reverse_depth == 0) {
+ window.PutChar(ACS_LLCORNER);
+ window.PutChar(ACS_HLINE);
+ } else {
+ window.PutChar(' ');
+ window.PutChar(' ');
+ }
+ } else {
+ if (reverse_depth == 0) {
+ window.PutChar(ACS_LTEE);
+ window.PutChar(ACS_HLINE);
+ } else {
+ window.PutChar(ACS_VLINE);
+ window.PutChar(' ');
+ }
+ }
+ }
+
+ TreeItem *GetItemForRowIndex(uint32_t row_idx) {
+ if (static_cast<uint32_t>(m_row_idx) == row_idx)
+ return this;
+ if (m_children.empty())
+ return nullptr;
+ if (IsExpanded()) {
+ for (auto &item : m_children) {
+ TreeItem *selected_item_ptr = item.GetItemForRowIndex(row_idx);
+ if (selected_item_ptr)
+ return selected_item_ptr;
+ }
}
+ return nullptr;
+ }
- const char *
- WindowDelegateGetHelpText () override
- {
- return "Welcome to the LLDB curses GUI.\n\n"
- "Press the TAB key to change the selected view.\n"
- "Each view has its own keyboard shortcuts, press 'h' to open a dialog to display them.\n\n"
- "Common key bindings for all views:";
- }
-
- KeyHelp *
- WindowDelegateGetKeyHelp () override
- {
- static curses::KeyHelp g_source_view_key_help[] = {
- { '\t', "Select next view" },
- { 'h', "Show help dialog with view specific key bindings" },
- { ',', "Page up" },
- { '.', "Page down" },
- { KEY_UP, "Select previous" },
- { KEY_DOWN, "Select next" },
- { KEY_LEFT, "Unexpand or select parent" },
- { KEY_RIGHT, "Expand" },
- { KEY_PPAGE, "Page up" },
- { KEY_NPAGE, "Page down" },
- { '\0', nullptr }
- };
- return g_source_view_key_help;
- }
-
- MenuActionResult
- MenuDelegateAction (Menu &menu) override
- {
- switch (menu.GetIdentifier())
- {
- case eMenuID_ThreadStepIn:
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasThreadScope())
- {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive() && StateIsStoppedState (process->GetState(), true))
- exe_ctx.GetThreadRef().StepIn(true);
- }
- }
- return MenuActionResult::Handled;
-
- case eMenuID_ThreadStepOut:
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasThreadScope())
- {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive() && StateIsStoppedState (process->GetState(), true))
- exe_ctx.GetThreadRef().StepOut();
- }
- }
- return MenuActionResult::Handled;
-
- case eMenuID_ThreadStepOver:
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasThreadScope())
- {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive() && StateIsStoppedState (process->GetState(), true))
- exe_ctx.GetThreadRef().StepOver(true);
- }
- }
- return MenuActionResult::Handled;
+ void *GetUserData() const { return m_user_data; }
- case eMenuID_ProcessContinue:
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope())
- {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive() && StateIsStoppedState (process->GetState(), true))
- process->Resume();
- }
- }
- return MenuActionResult::Handled;
+ void SetUserData(void *user_data) { m_user_data = user_data; }
- case eMenuID_ProcessKill:
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope())
- {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive())
- process->Destroy(false);
- }
- }
- return MenuActionResult::Handled;
+ uint64_t GetIdentifier() const { return m_identifier; }
- case eMenuID_ProcessHalt:
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope())
- {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive())
- process->Halt();
- }
- }
- return MenuActionResult::Handled;
+ void SetIdentifier(uint64_t identifier) { m_identifier = identifier; }
- case eMenuID_ProcessDetach:
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope())
- {
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive())
- process->Detach(false);
- }
- }
- return MenuActionResult::Handled;
+ void SetMightHaveChildren(bool b) { m_might_have_children = b; }
- case eMenuID_Process:
- {
- // Populate the menu with all of the threads if the process is stopped when
- // the Process menu gets selected and is about to display its submenu.
- Menus &submenus = menu.GetSubmenus();
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- Process *process = exe_ctx.GetProcessPtr();
- if (process && process->IsAlive() && StateIsStoppedState (process->GetState(), true))
- {
- if (submenus.size() == 7)
- menu.AddSubmenu (MenuSP (new Menu(Menu::Type::Separator)));
- else if (submenus.size() > 8)
- submenus.erase (submenus.begin() + 8, submenus.end());
-
- ThreadList &threads = process->GetThreadList();
- std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
- size_t num_threads = threads.GetSize();
- for (size_t i = 0; i < num_threads; ++i)
- {
- ThreadSP thread_sp = threads.GetThreadAtIndex(i);
- char menu_char = '\0';
- if (i < 9)
- menu_char = '1' + i;
- StreamString thread_menu_title;
- thread_menu_title.Printf("Thread %u", thread_sp->GetIndexID());
- const char *thread_name = thread_sp->GetName();
- if (thread_name && thread_name[0])
- thread_menu_title.Printf (" %s", thread_name);
- else
- {
- const char *queue_name = thread_sp->GetQueueName();
- if (queue_name && queue_name[0])
- thread_menu_title.Printf (" %s", queue_name);
- }
- menu.AddSubmenu(MenuSP(new Menu(thread_menu_title.GetString().c_str(), nullptr, menu_char, thread_sp->GetID())));
- }
- }
- else if (submenus.size() > 7)
- {
- // Remove the separator and any other thread submenu items
- // that were previously added
- submenus.erase (submenus.begin() + 7, submenus.end());
- }
- // Since we are adding and removing items we need to recalculate the name lengths
- menu.RecalculateNameLengths();
- }
- return MenuActionResult::Handled;
-
- case eMenuID_ViewVariables:
- {
- WindowSP main_window_sp = m_app.GetMainWindow();
- WindowSP source_window_sp = main_window_sp->FindSubWindow("Source");
- WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables");
- WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers");
- const Rect source_bounds = source_window_sp->GetBounds();
-
- if (variables_window_sp)
- {
- const Rect variables_bounds = variables_window_sp->GetBounds();
-
- main_window_sp->RemoveSubWindow(variables_window_sp.get());
-
- if (registers_window_sp)
- {
- // We have a registers window, so give all the area back to the registers window
- Rect registers_bounds = variables_bounds;
- registers_bounds.size.width = source_bounds.size.width;
- registers_window_sp->SetBounds(registers_bounds);
- }
- else
- {
- // We have no registers window showing so give the bottom
- // area back to the source view
- source_window_sp->Resize (source_bounds.size.width,
- source_bounds.size.height + variables_bounds.size.height);
- }
- }
- else
- {
- Rect new_variables_rect;
- if (registers_window_sp)
- {
- // We have a registers window so split the area of the registers
- // window into two columns where the left hand side will be the
- // variables and the right hand side will be the registers
- const Rect variables_bounds = registers_window_sp->GetBounds();
- Rect new_registers_rect;
- variables_bounds.VerticalSplitPercentage (0.50, new_variables_rect, new_registers_rect);
- registers_window_sp->SetBounds (new_registers_rect);
- }
- else
- {
- // No variables window, grab the bottom part of the source window
- Rect new_source_rect;
- source_bounds.HorizontalSplitPercentage (0.70, new_source_rect, new_variables_rect);
- source_window_sp->SetBounds (new_source_rect);
- }
- WindowSP new_window_sp = main_window_sp->CreateSubWindow ("Variables",
- new_variables_rect,
- false);
- new_window_sp->SetDelegate (WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger)));
- }
- touchwin(stdscr);
- }
- return MenuActionResult::Handled;
+protected:
+ TreeItem *m_parent;
+ TreeDelegate &m_delegate;
+ void *m_user_data;
+ uint64_t m_identifier;
+ int m_row_idx; // Zero based visible row index, -1 if not visible or for the
+ // root item
+ std::vector<TreeItem> m_children;
+ bool m_might_have_children;
+ bool m_is_expanded;
+};
- case eMenuID_ViewRegisters:
- {
- WindowSP main_window_sp = m_app.GetMainWindow();
- WindowSP source_window_sp = main_window_sp->FindSubWindow("Source");
- WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables");
- WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers");
- const Rect source_bounds = source_window_sp->GetBounds();
-
- if (registers_window_sp)
- {
- if (variables_window_sp)
- {
- const Rect variables_bounds = variables_window_sp->GetBounds();
-
- // We have a variables window, so give all the area back to the variables window
- variables_window_sp->Resize (variables_bounds.size.width + registers_window_sp->GetWidth(),
- variables_bounds.size.height);
- }
- else
- {
- // We have no variables window showing so give the bottom
- // area back to the source view
- source_window_sp->Resize (source_bounds.size.width,
- source_bounds.size.height + registers_window_sp->GetHeight());
- }
- main_window_sp->RemoveSubWindow(registers_window_sp.get());
- }
- else
- {
- Rect new_regs_rect;
- if (variables_window_sp)
- {
- // We have a variables window, split it into two columns
- // where the left hand side will be the variables and the
- // right hand side will be the registers
- const Rect variables_bounds = variables_window_sp->GetBounds();
- Rect new_vars_rect;
- variables_bounds.VerticalSplitPercentage (0.50, new_vars_rect, new_regs_rect);
- variables_window_sp->SetBounds (new_vars_rect);
- }
- else
- {
- // No registers window, grab the bottom part of the source window
- Rect new_source_rect;
- source_bounds.HorizontalSplitPercentage (0.70, new_source_rect, new_regs_rect);
- source_window_sp->SetBounds (new_source_rect);
- }
- WindowSP new_window_sp = main_window_sp->CreateSubWindow ("Registers",
- new_regs_rect,
- false);
- new_window_sp->SetDelegate (WindowDelegateSP(new RegistersWindowDelegate(m_debugger)));
- }
- touchwin(stdscr);
- }
- return MenuActionResult::Handled;
-
- case eMenuID_HelpGUIHelp:
- m_app.GetMainWindow ()->CreateHelpSubwindow();
- return MenuActionResult::Handled;
-
- default:
- break;
- }
+class TreeWindowDelegate : public WindowDelegate {
+public:
+ TreeWindowDelegate(Debugger &debugger, const TreeDelegateSP &delegate_sp)
+ : m_debugger(debugger), m_delegate_sp(delegate_sp),
+ m_root(nullptr, *delegate_sp, true), m_selected_item(nullptr),
+ m_num_rows(0), m_selected_row_idx(0), m_first_visible_row(0),
+ m_min_x(0), m_min_y(0), m_max_x(0), m_max_y(0) {}
+
+ int NumVisibleRows() const { return m_max_y - m_min_y; }
+
+ bool WindowDelegateDraw(Window &window, bool force) override {
+ ExecutionContext exe_ctx(
+ m_debugger.GetCommandInterpreter().GetExecutionContext());
+ Process *process = exe_ctx.GetProcessPtr();
+
+ bool display_content = false;
+ if (process) {
+ StateType state = process->GetState();
+ if (StateIsStoppedState(state, true)) {
+ // We are stopped, so it is ok to
+ display_content = true;
+ } else if (StateIsRunningState(state)) {
+ return true; // Don't do any updating when we are running
+ }
+ }
+
+ m_min_x = 2;
+ m_min_y = 1;
+ m_max_x = window.GetWidth() - 1;
+ m_max_y = window.GetHeight() - 1;
+
+ window.Erase();
+ window.DrawTitleBox(window.GetName());
+
+ if (display_content) {
+ const int num_visible_rows = NumVisibleRows();
+ m_num_rows = 0;
+ m_root.CalculateRowIndexes(m_num_rows);
+
+ // If we unexpanded while having something selected our
+ // total number of rows is less than the num visible rows,
+ // then make sure we show all the rows by setting the first
+ // visible row accordingly.
+ if (m_first_visible_row > 0 && m_num_rows < num_visible_rows)
+ m_first_visible_row = 0;
+
+ // Make sure the selected row is always visible
+ if (m_selected_row_idx < m_first_visible_row)
+ m_first_visible_row = m_selected_row_idx;
+ else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx)
+ m_first_visible_row = m_selected_row_idx - num_visible_rows + 1;
+
+ int row_idx = 0;
+ int num_rows_left = num_visible_rows;
+ m_root.Draw(window, m_first_visible_row, m_selected_row_idx, row_idx,
+ num_rows_left);
+ // Get the selected row
+ m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
+ } else {
+ m_selected_item = nullptr;
+ }
+
+ window.DeferredRefresh();
+
+ return true; // Drawing handled
+ }
+
+ const char *WindowDelegateGetHelpText() override {
+ return "Thread window keyboard shortcuts:";
+ }
+
+ KeyHelp *WindowDelegateGetKeyHelp() override {
+ static curses::KeyHelp g_source_view_key_help[] = {
+ {KEY_UP, "Select previous item"},
+ {KEY_DOWN, "Select next item"},
+ {KEY_RIGHT, "Expand the selected item"},
+ {KEY_LEFT,
+ "Unexpand the selected item or select parent if not expanded"},
+ {KEY_PPAGE, "Page up"},
+ {KEY_NPAGE, "Page down"},
+ {'h', "Show help dialog"},
+ {' ', "Toggle item expansion"},
+ {',', "Page up"},
+ {'.', "Page down"},
+ {'\0', nullptr}};
+ return g_source_view_key_help;
+ }
+
+ HandleCharResult WindowDelegateHandleChar(Window &window, int c) override {
+ switch (c) {
+ case ',':
+ case KEY_PPAGE:
+ // Page up key
+ if (m_first_visible_row > 0) {
+ if (m_first_visible_row > m_max_y)
+ m_first_visible_row -= m_max_y;
+ else
+ m_first_visible_row = 0;
+ m_selected_row_idx = m_first_visible_row;
+ m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
+ if (m_selected_item)
+ m_selected_item->ItemWasSelected();
+ }
+ return eKeyHandled;
+
+ case '.':
+ case KEY_NPAGE:
+ // Page down key
+ if (m_num_rows > m_max_y) {
+ if (m_first_visible_row + m_max_y < m_num_rows) {
+ m_first_visible_row += m_max_y;
+ m_selected_row_idx = m_first_visible_row;
+ m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
+ if (m_selected_item)
+ m_selected_item->ItemWasSelected();
+ }
+ }
+ return eKeyHandled;
+
+ case KEY_UP:
+ if (m_selected_row_idx > 0) {
+ --m_selected_row_idx;
+ m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
+ if (m_selected_item)
+ m_selected_item->ItemWasSelected();
+ }
+ return eKeyHandled;
+
+ case KEY_DOWN:
+ if (m_selected_row_idx + 1 < m_num_rows) {
+ ++m_selected_row_idx;
+ m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
+ if (m_selected_item)
+ m_selected_item->ItemWasSelected();
+ }
+ return eKeyHandled;
+
+ case KEY_RIGHT:
+ if (m_selected_item) {
+ if (!m_selected_item->IsExpanded())
+ m_selected_item->Expand();
+ }
+ return eKeyHandled;
+
+ case KEY_LEFT:
+ if (m_selected_item) {
+ if (m_selected_item->IsExpanded())
+ m_selected_item->Unexpand();
+ else if (m_selected_item->GetParent()) {
+ m_selected_row_idx = m_selected_item->GetParent()->GetRowIndex();
+ m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
+ if (m_selected_item)
+ m_selected_item->ItemWasSelected();
+ }
+ }
+ return eKeyHandled;
+
+ case ' ':
+ // Toggle expansion state when SPACE is pressed
+ if (m_selected_item) {
+ if (m_selected_item->IsExpanded())
+ m_selected_item->Unexpand();
+ else
+ m_selected_item->Expand();
+ }
+ return eKeyHandled;
+
+ case 'h':
+ window.CreateHelpSubwindow();
+ return eKeyHandled;
- return MenuActionResult::NotHandled;
+ default:
+ break;
}
+ return eKeyNotHandled;
+ }
+
protected:
- Application &m_app;
- Debugger &m_debugger;
+ Debugger &m_debugger;
+ TreeDelegateSP m_delegate_sp;
+ TreeItem m_root;
+ TreeItem *m_selected_item;
+ int m_num_rows;
+ int m_selected_row_idx;
+ int m_first_visible_row;
+ int m_min_x;
+ int m_min_y;
+ int m_max_x;
+ int m_max_y;
};
-class StatusBarWindowDelegate : public WindowDelegate
-{
+class FrameTreeDelegate : public TreeDelegate {
public:
- StatusBarWindowDelegate (Debugger &debugger) :
- m_debugger (debugger)
- {
- FormatEntity::Parse("Thread: ${thread.id%tid}",
- m_format);
+ FrameTreeDelegate() : TreeDelegate() {
+ FormatEntity::Parse(
+ "frame #${frame.index}: {${function.name}${function.pc-offset}}}",
+ m_format);
+ }
+
+ ~FrameTreeDelegate() override = default;
+
+ void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
+ Thread *thread = (Thread *)item.GetUserData();
+ if (thread) {
+ const uint64_t frame_idx = item.GetIdentifier();
+ StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_idx);
+ if (frame_sp) {
+ StreamString strm;
+ const SymbolContext &sc =
+ frame_sp->GetSymbolContext(eSymbolContextEverything);
+ ExecutionContext exe_ctx(frame_sp);
+ if (FormatEntity::Format(m_format, strm, &sc, &exe_ctx, nullptr,
+ nullptr, false, false)) {
+ int right_pad = 1;
+ window.PutCStringTruncated(strm.GetString().c_str(), right_pad);
+ }
+ }
+ }
+ }
+
+ void TreeDelegateGenerateChildren(TreeItem &item) override {
+ // No children for frames yet...
+ }
+
+ bool TreeDelegateItemSelected(TreeItem &item) override {
+ Thread *thread = (Thread *)item.GetUserData();
+ if (thread) {
+ thread->GetProcess()->GetThreadList().SetSelectedThreadByID(
+ thread->GetID());
+ const uint64_t frame_idx = item.GetIdentifier();
+ thread->SetSelectedFrameByIndex(frame_idx);
+ return true;
}
+ return false;
+ }
- ~StatusBarWindowDelegate() override = default;
+protected:
+ FormatEntity::Entry m_format;
+};
- bool
- WindowDelegateDraw (Window &window, bool force) override
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- Process *process = exe_ctx.GetProcessPtr();
- Thread *thread = exe_ctx.GetThreadPtr();
- StackFrame *frame = exe_ctx.GetFramePtr();
- window.Erase();
- window.SetBackground(2);
- window.MoveCursor (0, 0);
- if (process)
- {
- const StateType state = process->GetState();
- window.Printf ("Process: %5" PRIu64 " %10s", process->GetID(), StateAsCString(state));
-
- if (StateIsStoppedState(state, true))
- {
- StreamString strm;
- if (thread && FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr, nullptr, false, false))
- {
- window.MoveCursor (40, 0);
- window.PutCStringTruncated(strm.GetString().c_str(), 1);
- }
+class ThreadTreeDelegate : public TreeDelegate {
+public:
+ ThreadTreeDelegate(Debugger &debugger)
+ : TreeDelegate(), m_debugger(debugger), m_tid(LLDB_INVALID_THREAD_ID),
+ m_stop_id(UINT32_MAX) {
+ FormatEntity::Parse("thread #${thread.index}: tid = ${thread.id}{, stop "
+ "reason = ${thread.stop-reason}}",
+ m_format);
+ }
+
+ ~ThreadTreeDelegate() override = default;
+
+ ProcessSP GetProcess() {
+ return m_debugger.GetCommandInterpreter()
+ .GetExecutionContext()
+ .GetProcessSP();
+ }
+
+ ThreadSP GetThread(const TreeItem &item) {
+ ProcessSP process_sp = GetProcess();
+ if (process_sp)
+ return process_sp->GetThreadList().FindThreadByID(item.GetIdentifier());
+ return ThreadSP();
+ }
+
+ void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
+ ThreadSP thread_sp = GetThread(item);
+ if (thread_sp) {
+ StreamString strm;
+ ExecutionContext exe_ctx(thread_sp);
+ if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr,
+ nullptr, false, false)) {
+ int right_pad = 1;
+ window.PutCStringTruncated(strm.GetString().c_str(), right_pad);
+ }
+ }
+ }
+
+ void TreeDelegateGenerateChildren(TreeItem &item) override {
+ ProcessSP process_sp = GetProcess();
+ if (process_sp && process_sp->IsAlive()) {
+ StateType state = process_sp->GetState();
+ if (StateIsStoppedState(state, true)) {
+ ThreadSP thread_sp = GetThread(item);
+ if (thread_sp) {
+ if (m_stop_id == process_sp->GetStopID() &&
+ thread_sp->GetID() == m_tid)
+ return; // Children are already up to date
+ if (!m_frame_delegate_sp) {
+ // Always expand the thread item the first time we show it
+ m_frame_delegate_sp.reset(new FrameTreeDelegate());
+ }
+
+ m_stop_id = process_sp->GetStopID();
+ m_tid = thread_sp->GetID();
+
+ TreeItem t(&item, *m_frame_delegate_sp, false);
+ size_t num_frames = thread_sp->GetStackFrameCount();
+ item.Resize(num_frames, t);
+ for (size_t i = 0; i < num_frames; ++i) {
+ item[i].SetUserData(thread_sp.get());
+ item[i].SetIdentifier(i);
+ }
+ }
+ return;
+ }
+ }
+ item.ClearChildren();
+ }
- window.MoveCursor (60, 0);
- if (frame)
- window.Printf ("Frame: %3u PC = 0x%16.16" PRIx64, frame->GetFrameIndex(), frame->GetFrameCodeAddress().GetOpcodeLoadAddress (exe_ctx.GetTargetPtr()));
- }
- else if (state == eStateExited)
- {
- const char *exit_desc = process->GetExitDescription();
- const int exit_status = process->GetExitStatus();
- if (exit_desc && exit_desc[0])
- window.Printf (" with status = %i (%s)", exit_status, exit_desc);
- else
- window.Printf (" with status = %i", exit_status);
- }
+ bool TreeDelegateItemSelected(TreeItem &item) override {
+ ProcessSP process_sp = GetProcess();
+ if (process_sp && process_sp->IsAlive()) {
+ StateType state = process_sp->GetState();
+ if (StateIsStoppedState(state, true)) {
+ ThreadSP thread_sp = GetThread(item);
+ if (thread_sp) {
+ ThreadList &thread_list = thread_sp->GetProcess()->GetThreadList();
+ std::lock_guard<std::recursive_mutex> guard(thread_list.GetMutex());
+ ThreadSP selected_thread_sp = thread_list.GetSelectedThread();
+ if (selected_thread_sp->GetID() != thread_sp->GetID()) {
+ thread_list.SetSelectedThreadByID(thread_sp->GetID());
+ return true;
+ }
}
- window.DeferredRefresh();
- return true;
+ }
}
+ return false;
+ }
protected:
- Debugger &m_debugger;
- FormatEntity::Entry m_format;
+ Debugger &m_debugger;
+ std::shared_ptr<FrameTreeDelegate> m_frame_delegate_sp;
+ lldb::user_id_t m_tid;
+ uint32_t m_stop_id;
+ FormatEntity::Entry m_format;
};
-class SourceFileWindowDelegate : public WindowDelegate
-{
+class ThreadsTreeDelegate : public TreeDelegate {
public:
- SourceFileWindowDelegate (Debugger &debugger) :
- WindowDelegate (),
- m_debugger (debugger),
- m_sc (),
- m_file_sp (),
- m_disassembly_scope(nullptr),
- m_disassembly_sp (),
- m_disassembly_range (),
- m_title (),
- m_line_width (4),
- m_selected_line (0),
- m_pc_line (0),
- m_stop_id (0),
- m_frame_idx (UINT32_MAX),
- m_first_visible_line (0),
- m_min_x (0),
- m_min_y (0),
- m_max_x (0),
- m_max_y (0)
- {
+ ThreadsTreeDelegate(Debugger &debugger)
+ : TreeDelegate(), m_thread_delegate_sp(), m_debugger(debugger),
+ m_stop_id(UINT32_MAX) {
+ FormatEntity::Parse("process ${process.id}{, name = ${process.name}}",
+ m_format);
+ }
+
+ ~ThreadsTreeDelegate() override = default;
+
+ ProcessSP GetProcess() {
+ return m_debugger.GetCommandInterpreter()
+ .GetExecutionContext()
+ .GetProcessSP();
+ }
+
+ void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
+ ProcessSP process_sp = GetProcess();
+ if (process_sp && process_sp->IsAlive()) {
+ StreamString strm;
+ ExecutionContext exe_ctx(process_sp);
+ if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr,
+ nullptr, false, false)) {
+ int right_pad = 1;
+ window.PutCStringTruncated(strm.GetString().c_str(), right_pad);
+ }
+ }
+ }
+
+ void TreeDelegateGenerateChildren(TreeItem &item) override {
+ ProcessSP process_sp = GetProcess();
+ if (process_sp && process_sp->IsAlive()) {
+ StateType state = process_sp->GetState();
+ if (StateIsStoppedState(state, true)) {
+ const uint32_t stop_id = process_sp->GetStopID();
+ if (m_stop_id == stop_id)
+ return; // Children are already up to date
+
+ m_stop_id = stop_id;
+
+ if (!m_thread_delegate_sp) {
+ // Always expand the thread item the first time we show it
+ // item.Expand();
+ m_thread_delegate_sp.reset(new ThreadTreeDelegate(m_debugger));
+ }
+
+ TreeItem t(&item, *m_thread_delegate_sp, false);
+ ThreadList &threads = process_sp->GetThreadList();
+ std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
+ size_t num_threads = threads.GetSize();
+ item.Resize(num_threads, t);
+ for (size_t i = 0; i < num_threads; ++i) {
+ item[i].SetIdentifier(threads.GetThreadAtIndex(i)->GetID());
+ item[i].SetMightHaveChildren(true);
+ }
+ return;
+ }
}
+ item.ClearChildren();
+ }
- ~SourceFileWindowDelegate() override = default;
+ bool TreeDelegateItemSelected(TreeItem &item) override { return false; }
- void
- Update (const SymbolContext &sc)
- {
- m_sc = sc;
- }
-
- uint32_t
- NumVisibleLines () const
- {
- return m_max_y - m_min_y;
- }
+protected:
+ std::shared_ptr<ThreadTreeDelegate> m_thread_delegate_sp;
+ Debugger &m_debugger;
+ uint32_t m_stop_id;
+ FormatEntity::Entry m_format;
+};
- const char *
- WindowDelegateGetHelpText () override
- {
- return "Source/Disassembly window keyboard shortcuts:";
- }
+class ValueObjectListDelegate : public WindowDelegate {
+public:
+ ValueObjectListDelegate()
+ : m_valobj_list(), m_rows(), m_selected_row(nullptr),
+ m_selected_row_idx(0), m_first_visible_row(0), m_num_rows(0),
+ m_max_x(0), m_max_y(0) {}
+
+ ValueObjectListDelegate(ValueObjectList &valobj_list)
+ : m_valobj_list(valobj_list), m_rows(), m_selected_row(nullptr),
+ m_selected_row_idx(0), m_first_visible_row(0), m_num_rows(0),
+ m_max_x(0), m_max_y(0) {
+ SetValues(valobj_list);
+ }
+
+ ~ValueObjectListDelegate() override = default;
+
+ void SetValues(ValueObjectList &valobj_list) {
+ m_selected_row = nullptr;
+ m_selected_row_idx = 0;
+ m_first_visible_row = 0;
+ m_num_rows = 0;
+ m_rows.clear();
+ m_valobj_list = valobj_list;
+ const size_t num_values = m_valobj_list.GetSize();
+ for (size_t i = 0; i < num_values; ++i)
+ m_rows.push_back(Row(m_valobj_list.GetValueObjectAtIndex(i), nullptr));
+ }
+
+ bool WindowDelegateDraw(Window &window, bool force) override {
+ m_num_rows = 0;
+ m_min_x = 2;
+ m_min_y = 1;
+ m_max_x = window.GetWidth() - 1;
+ m_max_y = window.GetHeight() - 1;
- KeyHelp *
- WindowDelegateGetKeyHelp () override
- {
- static curses::KeyHelp g_source_view_key_help[] = {
- { KEY_RETURN, "Run to selected line with one shot breakpoint" },
- { KEY_UP, "Select previous source line" },
- { KEY_DOWN, "Select next source line" },
- { KEY_PPAGE, "Page up" },
- { KEY_NPAGE, "Page down" },
- { 'b', "Set breakpoint on selected source/disassembly line" },
- { 'c', "Continue process" },
- { 'd', "Detach and resume process" },
- { 'D', "Detach with process suspended" },
- { 'h', "Show help dialog" },
- { 'k', "Kill process" },
- { 'n', "Step over (source line)" },
- { 'N', "Step over (single instruction)" },
- { 'o', "Step out" },
- { 's', "Step in (source line)" },
- { 'S', "Step in (single instruction)" },
- { ',', "Page up" },
- { '.', "Page down" },
- { '\0', nullptr }
- };
- return g_source_view_key_help;
- }
+ window.Erase();
+ window.DrawTitleBox(window.GetName());
- bool
- WindowDelegateDraw (Window &window, bool force) override
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- Process *process = exe_ctx.GetProcessPtr();
- Thread *thread = nullptr;
+ const int num_visible_rows = NumVisibleRows();
+ const int num_rows = CalculateTotalNumberRows(m_rows);
- bool update_location = false;
- if (process)
- {
- StateType state = process->GetState();
- if (StateIsStoppedState(state, true))
- {
- // We are stopped, so it is ok to
- update_location = true;
- }
- }
+ // If we unexpanded while having something selected our
+ // total number of rows is less than the num visible rows,
+ // then make sure we show all the rows by setting the first
+ // visible row accordingly.
+ if (m_first_visible_row > 0 && num_rows < num_visible_rows)
+ m_first_visible_row = 0;
+
+ // Make sure the selected row is always visible
+ if (m_selected_row_idx < m_first_visible_row)
+ m_first_visible_row = m_selected_row_idx;
+ else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx)
+ m_first_visible_row = m_selected_row_idx - num_visible_rows + 1;
+
+ DisplayRows(window, m_rows, g_options);
+
+ window.DeferredRefresh();
+
+ // Get the selected row
+ m_selected_row = GetRowForRowIndex(m_selected_row_idx);
+ // Keep the cursor on the selected row so the highlight and the cursor
+ // are always on the same line
+ if (m_selected_row)
+ window.MoveCursor(m_selected_row->x, m_selected_row->y);
+
+ return true; // Drawing handled
+ }
+
+ KeyHelp *WindowDelegateGetKeyHelp() override {
+ static curses::KeyHelp g_source_view_key_help[] = {
+ {KEY_UP, "Select previous item"},
+ {KEY_DOWN, "Select next item"},
+ {KEY_RIGHT, "Expand selected item"},
+ {KEY_LEFT, "Unexpand selected item or select parent if not expanded"},
+ {KEY_PPAGE, "Page up"},
+ {KEY_NPAGE, "Page down"},
+ {'A', "Format as annotated address"},
+ {'b', "Format as binary"},
+ {'B', "Format as hex bytes with ASCII"},
+ {'c', "Format as character"},
+ {'d', "Format as a signed integer"},
+ {'D', "Format selected value using the default format for the type"},
+ {'f', "Format as float"},
+ {'h', "Show help dialog"},
+ {'i', "Format as instructions"},
+ {'o', "Format as octal"},
+ {'p', "Format as pointer"},
+ {'s', "Format as C string"},
+ {'t', "Toggle showing/hiding type names"},
+ {'u', "Format as an unsigned integer"},
+ {'x', "Format as hex"},
+ {'X', "Format as uppercase hex"},
+ {' ', "Toggle item expansion"},
+ {',', "Page up"},
+ {'.', "Page down"},
+ {'\0', nullptr}};
+ return g_source_view_key_help;
+ }
+
+ HandleCharResult WindowDelegateHandleChar(Window &window, int c) override {
+ switch (c) {
+ case 'x':
+ case 'X':
+ case 'o':
+ case 's':
+ case 'u':
+ case 'd':
+ case 'D':
+ case 'i':
+ case 'A':
+ case 'p':
+ case 'c':
+ case 'b':
+ case 'B':
+ case 'f':
+ // Change the format for the currently selected item
+ if (m_selected_row)
+ m_selected_row->valobj->SetFormat(FormatForChar(c));
+ return eKeyHandled;
+
+ case 't':
+ // Toggle showing type names
+ g_options.show_types = !g_options.show_types;
+ return eKeyHandled;
+
+ case ',':
+ case KEY_PPAGE:
+ // Page up key
+ if (m_first_visible_row > 0) {
+ if (static_cast<int>(m_first_visible_row) > m_max_y)
+ m_first_visible_row -= m_max_y;
+ else
+ m_first_visible_row = 0;
+ m_selected_row_idx = m_first_visible_row;
+ }
+ return eKeyHandled;
+
+ case '.':
+ case KEY_NPAGE:
+ // Page down key
+ if (m_num_rows > static_cast<size_t>(m_max_y)) {
+ if (m_first_visible_row + m_max_y < m_num_rows) {
+ m_first_visible_row += m_max_y;
+ m_selected_row_idx = m_first_visible_row;
+ }
+ }
+ return eKeyHandled;
+
+ case KEY_UP:
+ if (m_selected_row_idx > 0)
+ --m_selected_row_idx;
+ return eKeyHandled;
+
+ case KEY_DOWN:
+ if (m_selected_row_idx + 1 < m_num_rows)
+ ++m_selected_row_idx;
+ return eKeyHandled;
+
+ case KEY_RIGHT:
+ if (m_selected_row) {
+ if (!m_selected_row->expanded)
+ m_selected_row->Expand();
+ }
+ return eKeyHandled;
+
+ case KEY_LEFT:
+ if (m_selected_row) {
+ if (m_selected_row->expanded)
+ m_selected_row->Unexpand();
+ else if (m_selected_row->parent)
+ m_selected_row_idx = m_selected_row->parent->row_idx;
+ }
+ return eKeyHandled;
+
+ case ' ':
+ // Toggle expansion state when SPACE is pressed
+ if (m_selected_row) {
+ if (m_selected_row->expanded)
+ m_selected_row->Unexpand();
+ else
+ m_selected_row->Expand();
+ }
+ return eKeyHandled;
+
+ case 'h':
+ window.CreateHelpSubwindow();
+ return eKeyHandled;
- m_min_x = 1;
- m_min_y = 2;
- m_max_x = window.GetMaxX()-1;
- m_max_y = window.GetMaxY()-1;
-
- const uint32_t num_visible_lines = NumVisibleLines();
- StackFrameSP frame_sp;
- bool set_selected_line_to_pc = false;
-
- if (update_location)
- {
- const bool process_alive = process ? process->IsAlive() : false;
- bool thread_changed = false;
- if (process_alive)
- {
- thread = exe_ctx.GetThreadPtr();
- if (thread)
- {
- frame_sp = thread->GetSelectedFrame();
- auto tid = thread->GetID();
- thread_changed = tid != m_tid;
- m_tid = tid;
- }
- else
- {
- if (m_tid != LLDB_INVALID_THREAD_ID)
- {
- thread_changed = true;
- m_tid = LLDB_INVALID_THREAD_ID;
- }
- }
- }
- const uint32_t stop_id = process ? process->GetStopID() : 0;
- const bool stop_id_changed = stop_id != m_stop_id;
- bool frame_changed = false;
- m_stop_id = stop_id;
- m_title.Clear();
- if (frame_sp)
- {
- m_sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
- if (m_sc.module_sp)
- {
- m_title.Printf("%s", m_sc.module_sp->GetFileSpec().GetFilename().GetCString());
- ConstString func_name = m_sc.GetFunctionName();
- if (func_name)
- m_title.Printf("`%s", func_name.GetCString());
- }
- const uint32_t frame_idx = frame_sp->GetFrameIndex();
- frame_changed = frame_idx != m_frame_idx;
- m_frame_idx = frame_idx;
- }
- else
- {
- m_sc.Clear(true);
- frame_changed = m_frame_idx != UINT32_MAX;
- m_frame_idx = UINT32_MAX;
- }
+ default:
+ break;
+ }
+ return eKeyNotHandled;
+ }
- const bool context_changed = thread_changed || frame_changed || stop_id_changed;
+protected:
+ ValueObjectList m_valobj_list;
+ std::vector<Row> m_rows;
+ Row *m_selected_row;
+ uint32_t m_selected_row_idx;
+ uint32_t m_first_visible_row;
+ uint32_t m_num_rows;
+ int m_min_x;
+ int m_min_y;
+ int m_max_x;
+ int m_max_y;
+
+ static Format FormatForChar(int c) {
+ switch (c) {
+ case 'x':
+ return eFormatHex;
+ case 'X':
+ return eFormatHexUppercase;
+ case 'o':
+ return eFormatOctal;
+ case 's':
+ return eFormatCString;
+ case 'u':
+ return eFormatUnsigned;
+ case 'd':
+ return eFormatDecimal;
+ case 'D':
+ return eFormatDefault;
+ case 'i':
+ return eFormatInstruction;
+ case 'A':
+ return eFormatAddressInfo;
+ case 'p':
+ return eFormatPointer;
+ case 'c':
+ return eFormatChar;
+ case 'b':
+ return eFormatBinary;
+ case 'B':
+ return eFormatBytesWithASCII;
+ case 'f':
+ return eFormatFloat;
+ }
+ return eFormatDefault;
+ }
+
+ bool DisplayRowObject(Window &window, Row &row, DisplayOptions &options,
+ bool highlight, bool last_child) {
+ ValueObject *valobj = row.valobj.get();
+
+ if (valobj == nullptr)
+ return false;
+
+ const char *type_name =
+ options.show_types ? valobj->GetTypeName().GetCString() : nullptr;
+ const char *name = valobj->GetName().GetCString();
+ const char *value = valobj->GetValueAsCString();
+ const char *summary = valobj->GetSummaryAsCString();
+
+ window.MoveCursor(row.x, row.y);
+
+ row.DrawTree(window);
+
+ if (highlight)
+ window.AttributeOn(A_REVERSE);
+
+ if (type_name && type_name[0])
+ window.Printf("(%s) ", type_name);
+
+ if (name && name[0])
+ window.PutCString(name);
+
+ attr_t changd_attr = 0;
+ if (valobj->GetValueDidChange())
+ changd_attr = COLOR_PAIR(5) | A_BOLD;
+
+ if (value && value[0]) {
+ window.PutCString(" = ");
+ if (changd_attr)
+ window.AttributeOn(changd_attr);
+ window.PutCString(value);
+ if (changd_attr)
+ window.AttributeOff(changd_attr);
+ }
+
+ if (summary && summary[0]) {
+ window.PutChar(' ');
+ if (changd_attr)
+ window.AttributeOn(changd_attr);
+ window.PutCString(summary);
+ if (changd_attr)
+ window.AttributeOff(changd_attr);
+ }
- if (process_alive)
- {
- if (m_sc.line_entry.IsValid())
- {
- m_pc_line = m_sc.line_entry.line;
- if (m_pc_line != UINT32_MAX)
- --m_pc_line; // Convert to zero based line number...
- // Update the selected line if the stop ID changed...
- if (context_changed)
- m_selected_line = m_pc_line;
-
- if (m_file_sp && m_file_sp->FileSpecMatches(m_sc.line_entry.file))
- {
- // Same file, nothing to do, we should either have the
- // lines or not (source file missing)
- if (m_selected_line >= static_cast<size_t>(m_first_visible_line))
- {
- if (m_selected_line >= m_first_visible_line + num_visible_lines)
- m_first_visible_line = m_selected_line - 10;
- }
- else
- {
- if (m_selected_line > 10)
- m_first_visible_line = m_selected_line - 10;
- else
- m_first_visible_line = 0;
- }
- }
- else
- {
- // File changed, set selected line to the line with the PC
- m_selected_line = m_pc_line;
- m_file_sp = m_debugger.GetSourceManager().GetFile(m_sc.line_entry.file);
- if (m_file_sp)
- {
- const size_t num_lines = m_file_sp->GetNumLines();
- int m_line_width = 1;
- for (size_t n = num_lines; n >= 10; n = n / 10)
- ++m_line_width;
-
- snprintf (m_line_format, sizeof(m_line_format), " %%%iu ", m_line_width);
- if (num_lines < num_visible_lines || m_selected_line < num_visible_lines)
- m_first_visible_line = 0;
- else
- m_first_visible_line = m_selected_line - 10;
- }
- }
- }
- else
- {
- m_file_sp.reset();
- }
+ if (highlight)
+ window.AttributeOff(A_REVERSE);
- if (!m_file_sp || m_file_sp->GetNumLines() == 0)
- {
- // Show disassembly
- bool prefer_file_cache = false;
- if (m_sc.function)
- {
- if (m_disassembly_scope != m_sc.function)
- {
- m_disassembly_scope = m_sc.function;
- m_disassembly_sp = m_sc.function->GetInstructions(exe_ctx, nullptr, prefer_file_cache);
- if (m_disassembly_sp)
- {
- set_selected_line_to_pc = true;
- m_disassembly_range = m_sc.function->GetAddressRange();
- }
- else
- {
- m_disassembly_range.Clear();
- }
- }
- else
- {
- set_selected_line_to_pc = context_changed;
- }
- }
- else if (m_sc.symbol)
- {
- if (m_disassembly_scope != m_sc.symbol)
- {
- m_disassembly_scope = m_sc.symbol;
- m_disassembly_sp = m_sc.symbol->GetInstructions(exe_ctx, nullptr, prefer_file_cache);
- if (m_disassembly_sp)
- {
- set_selected_line_to_pc = true;
- m_disassembly_range.GetBaseAddress() = m_sc.symbol->GetAddress();
- m_disassembly_range.SetByteSize(m_sc.symbol->GetByteSize());
- }
- else
- {
- m_disassembly_range.Clear();
- }
- }
- else
- {
- set_selected_line_to_pc = context_changed;
- }
- }
- }
- }
- else
- {
- m_pc_line = UINT32_MAX;
- }
- }
+ return true;
+ }
- const int window_width = window.GetWidth();
- window.Erase();
- window.DrawTitleBox ("Sources");
- if (!m_title.GetString().empty())
- {
- window.AttributeOn(A_REVERSE);
- window.MoveCursor(1, 1);
- window.PutChar(' ');
- window.PutCStringTruncated(m_title.GetString().c_str(), 1);
- int x = window.GetCursorX();
- if (x < window_width - 1)
- {
- window.Printf ("%*s", window_width - x - 1, "");
- }
- window.AttributeOff(A_REVERSE);
+ void DisplayRows(Window &window, std::vector<Row> &rows,
+ DisplayOptions &options) {
+ // > 0x25B7
+ // \/ 0x25BD
+
+ bool window_is_active = window.IsActive();
+ for (auto &row : rows) {
+ const bool last_child = row.parent && &rows[rows.size() - 1] == &row;
+ // Save the row index in each Row structure
+ row.row_idx = m_num_rows;
+ if ((m_num_rows >= m_first_visible_row) &&
+ ((m_num_rows - m_first_visible_row) <
+ static_cast<size_t>(NumVisibleRows()))) {
+ row.x = m_min_x;
+ row.y = m_num_rows - m_first_visible_row + 1;
+ if (DisplayRowObject(window, row, options,
+ window_is_active &&
+ m_num_rows == m_selected_row_idx,
+ last_child)) {
+ ++m_num_rows;
+ } else {
+ row.x = 0;
+ row.y = 0;
+ }
+ } else {
+ row.x = 0;
+ row.y = 0;
+ ++m_num_rows;
+ }
+
+ if (row.expanded && !row.children.empty()) {
+ DisplayRows(window, row.children, options);
+ }
+ }
+ }
+
+ int CalculateTotalNumberRows(const std::vector<Row> &rows) {
+ int row_count = 0;
+ for (const auto &row : rows) {
+ ++row_count;
+ if (row.expanded)
+ row_count += CalculateTotalNumberRows(row.children);
+ }
+ return row_count;
+ }
+
+ static Row *GetRowForRowIndexImpl(std::vector<Row> &rows, size_t &row_index) {
+ for (auto &row : rows) {
+ if (row_index == 0)
+ return &row;
+ else {
+ --row_index;
+ if (row.expanded && !row.children.empty()) {
+ Row *result = GetRowForRowIndexImpl(row.children, row_index);
+ if (result)
+ return result;
}
+ }
+ }
+ return nullptr;
+ }
- Target *target = exe_ctx.GetTargetPtr();
- const size_t num_source_lines = GetNumSourceLines();
- if (num_source_lines > 0)
- {
- // Display source
- BreakpointLines bp_lines;
- if (target)
- {
- BreakpointList &bp_list = target->GetBreakpointList();
- const size_t num_bps = bp_list.GetSize();
- for (size_t bp_idx=0; bp_idx<num_bps; ++bp_idx)
- {
- BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
- const size_t num_bps_locs = bp_sp->GetNumLocations();
- for (size_t bp_loc_idx=0; bp_loc_idx<num_bps_locs; ++bp_loc_idx)
- {
- BreakpointLocationSP bp_loc_sp = bp_sp->GetLocationAtIndex(bp_loc_idx);
- LineEntry bp_loc_line_entry;
- if (bp_loc_sp->GetAddress().CalculateSymbolContextLineEntry (bp_loc_line_entry))
- {
- if (m_file_sp->GetFileSpec() == bp_loc_line_entry.file)
- {
- bp_lines.insert(bp_loc_line_entry.line);
- }
- }
- }
- }
- }
+ Row *GetRowForRowIndex(size_t row_index) {
+ return GetRowForRowIndexImpl(m_rows, row_index);
+ }
- const attr_t selected_highlight_attr = A_REVERSE;
- const attr_t pc_highlight_attr = COLOR_PAIR(1);
+ int NumVisibleRows() const { return m_max_y - m_min_y; }
- for (size_t i = 0; i < num_visible_lines; ++i)
- {
- const uint32_t curr_line = m_first_visible_line + i;
- if (curr_line < num_source_lines)
- {
- const int line_y = m_min_y+i;
- window.MoveCursor(1, line_y);
- const bool is_pc_line = curr_line == m_pc_line;
- const bool line_is_selected = m_selected_line == curr_line;
- // Highlight the line as the PC line first, then if the selected line
- // isn't the same as the PC line, highlight it differently
- attr_t highlight_attr = 0;
- attr_t bp_attr = 0;
- if (is_pc_line)
- highlight_attr = pc_highlight_attr;
- else if (line_is_selected)
- highlight_attr = selected_highlight_attr;
-
- if (bp_lines.find(curr_line+1) != bp_lines.end())
- bp_attr = COLOR_PAIR(2);
-
- if (bp_attr)
- window.AttributeOn(bp_attr);
-
- window.Printf (m_line_format, curr_line + 1);
-
- if (bp_attr)
- window.AttributeOff(bp_attr);
-
- window.PutChar(ACS_VLINE);
- // Mark the line with the PC with a diamond
- if (is_pc_line)
- window.PutChar(ACS_DIAMOND);
- else
- window.PutChar(' ');
-
- if (highlight_attr)
- window.AttributeOn(highlight_attr);
- const uint32_t line_len = m_file_sp->GetLineLength(curr_line + 1, false);
- if (line_len > 0)
- window.PutCString(m_file_sp->PeekLineData(curr_line + 1), line_len);
-
- if (is_pc_line && frame_sp && frame_sp->GetConcreteFrameIndex() == 0)
- {
- StopInfoSP stop_info_sp;
- if (thread)
- stop_info_sp = thread->GetStopInfo();
- if (stop_info_sp)
- {
- const char *stop_description = stop_info_sp->GetDescription();
- if (stop_description && stop_description[0])
- {
- size_t stop_description_len = strlen(stop_description);
- int desc_x = window_width - stop_description_len - 16;
- window.Printf ("%*s", desc_x - window.GetCursorX(), "");
- //window.MoveCursor(window_width - stop_description_len - 15, line_y);
- window.Printf ("<<< Thread %u: %s ", thread->GetIndexID(), stop_description);
- }
- }
- else
- {
- window.Printf ("%*s", window_width - window.GetCursorX() - 1, "");
- }
- }
- if (highlight_attr)
- window.AttributeOff(highlight_attr);
- }
- else
- {
- break;
- }
- }
- }
- else
- {
- size_t num_disassembly_lines = GetNumDisassemblyLines();
- if (num_disassembly_lines > 0)
- {
- // Display disassembly
- BreakpointAddrs bp_file_addrs;
- Target *target = exe_ctx.GetTargetPtr();
- if (target)
- {
- BreakpointList &bp_list = target->GetBreakpointList();
- const size_t num_bps = bp_list.GetSize();
- for (size_t bp_idx=0; bp_idx<num_bps; ++bp_idx)
- {
- BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
- const size_t num_bps_locs = bp_sp->GetNumLocations();
- for (size_t bp_loc_idx=0; bp_loc_idx<num_bps_locs; ++bp_loc_idx)
- {
- BreakpointLocationSP bp_loc_sp = bp_sp->GetLocationAtIndex(bp_loc_idx);
- LineEntry bp_loc_line_entry;
- const lldb::addr_t file_addr = bp_loc_sp->GetAddress().GetFileAddress();
- if (file_addr != LLDB_INVALID_ADDRESS)
- {
- if (m_disassembly_range.ContainsFileAddress(file_addr))
- bp_file_addrs.insert(file_addr);
- }
- }
- }
- }
+ static DisplayOptions g_options;
+};
- const attr_t selected_highlight_attr = A_REVERSE;
- const attr_t pc_highlight_attr = COLOR_PAIR(1);
+class FrameVariablesWindowDelegate : public ValueObjectListDelegate {
+public:
+ FrameVariablesWindowDelegate(Debugger &debugger)
+ : ValueObjectListDelegate(), m_debugger(debugger),
+ m_frame_block(nullptr) {}
+
+ ~FrameVariablesWindowDelegate() override = default;
+
+ const char *WindowDelegateGetHelpText() override {
+ return "Frame variable window keyboard shortcuts:";
+ }
+
+ bool WindowDelegateDraw(Window &window, bool force) override {
+ ExecutionContext exe_ctx(
+ m_debugger.GetCommandInterpreter().GetExecutionContext());
+ Process *process = exe_ctx.GetProcessPtr();
+ Block *frame_block = nullptr;
+ StackFrame *frame = nullptr;
+
+ if (process) {
+ StateType state = process->GetState();
+ if (StateIsStoppedState(state, true)) {
+ frame = exe_ctx.GetFramePtr();
+ if (frame)
+ frame_block = frame->GetFrameBlock();
+ } else if (StateIsRunningState(state)) {
+ return true; // Don't do any updating when we are running
+ }
+ }
+
+ ValueObjectList local_values;
+ if (frame_block) {
+ // Only update the variables if they have changed
+ if (m_frame_block != frame_block) {
+ m_frame_block = frame_block;
+
+ VariableList *locals = frame->GetVariableList(true);
+ if (locals) {
+ const DynamicValueType use_dynamic = eDynamicDontRunTarget;
+ const size_t num_locals = locals->GetSize();
+ for (size_t i = 0; i < num_locals; ++i) {
+ ValueObjectSP value_sp = frame->GetValueObjectForFrameVariable(
+ locals->GetVariableAtIndex(i), use_dynamic);
+ if (value_sp) {
+ ValueObjectSP synthetic_value_sp = value_sp->GetSyntheticValue();
+ if (synthetic_value_sp)
+ local_values.Append(synthetic_value_sp);
+ else
+ local_values.Append(value_sp);
+ }
+ }
+ // Update the values
+ SetValues(local_values);
+ }
+ }
+ } else {
+ m_frame_block = nullptr;
+ // Update the values with an empty list if there is no frame
+ SetValues(local_values);
+ }
- StreamString strm;
+ return ValueObjectListDelegate::WindowDelegateDraw(window, force);
+ }
- InstructionList &insts = m_disassembly_sp->GetInstructionList();
- Address pc_address;
+protected:
+ Debugger &m_debugger;
+ Block *m_frame_block;
+};
- if (frame_sp)
- pc_address = frame_sp->GetFrameCodeAddress();
- const uint32_t pc_idx = pc_address.IsValid() ? insts.GetIndexOfInstructionAtAddress (pc_address) : UINT32_MAX;
- if (set_selected_line_to_pc)
- {
- m_selected_line = pc_idx;
- }
+class RegistersWindowDelegate : public ValueObjectListDelegate {
+public:
+ RegistersWindowDelegate(Debugger &debugger)
+ : ValueObjectListDelegate(), m_debugger(debugger) {}
- const uint32_t non_visible_pc_offset = (num_visible_lines / 5);
- if (static_cast<size_t>(m_first_visible_line) >= num_disassembly_lines)
- m_first_visible_line = 0;
-
- if (pc_idx < num_disassembly_lines)
- {
- if (pc_idx < static_cast<uint32_t>(m_first_visible_line) ||
- pc_idx >= m_first_visible_line + num_visible_lines)
- m_first_visible_line = pc_idx - non_visible_pc_offset;
- }
+ ~RegistersWindowDelegate() override = default;
- for (size_t i = 0; i < num_visible_lines; ++i)
- {
- const uint32_t inst_idx = m_first_visible_line + i;
- Instruction *inst = insts.GetInstructionAtIndex(inst_idx).get();
- if (!inst)
- break;
-
- const int line_y = m_min_y+i;
- window.MoveCursor(1, line_y);
- const bool is_pc_line = frame_sp && inst_idx == pc_idx;
- const bool line_is_selected = m_selected_line == inst_idx;
- // Highlight the line as the PC line first, then if the selected line
- // isn't the same as the PC line, highlight it differently
- attr_t highlight_attr = 0;
- attr_t bp_attr = 0;
- if (is_pc_line)
- highlight_attr = pc_highlight_attr;
- else if (line_is_selected)
- highlight_attr = selected_highlight_attr;
-
- if (bp_file_addrs.find(inst->GetAddress().GetFileAddress()) != bp_file_addrs.end())
- bp_attr = COLOR_PAIR(2);
-
- if (bp_attr)
- window.AttributeOn(bp_attr);
-
- window.Printf (" 0x%16.16llx ",
- static_cast<unsigned long long>(inst->GetAddress().GetLoadAddress(target)));
-
- if (bp_attr)
- window.AttributeOff(bp_attr);
-
- window.PutChar(ACS_VLINE);
- // Mark the line with the PC with a diamond
- if (is_pc_line)
- window.PutChar(ACS_DIAMOND);
- else
- window.PutChar(' ');
-
- if (highlight_attr)
- window.AttributeOn(highlight_attr);
-
- const char *mnemonic = inst->GetMnemonic(&exe_ctx);
- const char *operands = inst->GetOperands(&exe_ctx);
- const char *comment = inst->GetComment(&exe_ctx);
-
- if (mnemonic != nullptr && mnemonic[0] == '\0')
- mnemonic = nullptr;
- if (operands != nullptr && operands[0] == '\0')
- operands = nullptr;
- if (comment != nullptr && comment[0] == '\0')
- comment = nullptr;
-
- strm.Clear();
-
- if (mnemonic != nullptr && operands != nullptr && comment != nullptr)
- strm.Printf ("%-8s %-25s ; %s", mnemonic, operands, comment);
- else if (mnemonic != nullptr && operands != nullptr)
- strm.Printf ("%-8s %s", mnemonic, operands);
- else if (mnemonic != nullptr)
- strm.Printf ("%s", mnemonic);
-
- int right_pad = 1;
- window.PutCStringTruncated(strm.GetString().c_str(), right_pad);
-
- if (is_pc_line && frame_sp && frame_sp->GetConcreteFrameIndex() == 0)
- {
- StopInfoSP stop_info_sp;
- if (thread)
- stop_info_sp = thread->GetStopInfo();
- if (stop_info_sp)
- {
- const char *stop_description = stop_info_sp->GetDescription();
- if (stop_description && stop_description[0])
- {
- size_t stop_description_len = strlen(stop_description);
- int desc_x = window_width - stop_description_len - 16;
- window.Printf ("%*s", desc_x - window.GetCursorX(), "");
- //window.MoveCursor(window_width - stop_description_len - 15, line_y);
- window.Printf ("<<< Thread %u: %s ", thread->GetIndexID(), stop_description);
- }
- }
- else
- {
- window.Printf ("%*s", window_width - window.GetCursorX() - 1, "");
- }
- }
- if (highlight_attr)
- window.AttributeOff(highlight_attr);
- }
- }
- }
- window.DeferredRefresh();
- return true; // Drawing handled
+ const char *WindowDelegateGetHelpText() override {
+ return "Register window keyboard shortcuts:";
+ }
+
+ bool WindowDelegateDraw(Window &window, bool force) override {
+ ExecutionContext exe_ctx(
+ m_debugger.GetCommandInterpreter().GetExecutionContext());
+ StackFrame *frame = exe_ctx.GetFramePtr();
+
+ ValueObjectList value_list;
+ if (frame) {
+ if (frame->GetStackID() != m_stack_id) {
+ m_stack_id = frame->GetStackID();
+ RegisterContextSP reg_ctx(frame->GetRegisterContext());
+ if (reg_ctx) {
+ const uint32_t num_sets = reg_ctx->GetRegisterSetCount();
+ for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) {
+ value_list.Append(
+ ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx));
+ }
+ }
+ SetValues(value_list);
+ }
+ } else {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive())
+ return true; // Don't do any updating if we are running
+ else {
+ // Update the values with an empty list if there
+ // is no process or the process isn't alive anymore
+ SetValues(value_list);
+ }
}
+ return ValueObjectListDelegate::WindowDelegateDraw(window, force);
+ }
- size_t
- GetNumLines ()
- {
- size_t num_lines = GetNumSourceLines();
- if (num_lines == 0)
- num_lines = GetNumDisassemblyLines();
- return num_lines;
- }
+protected:
+ Debugger &m_debugger;
+ StackID m_stack_id;
+};
- size_t
- GetNumSourceLines () const
- {
- if (m_file_sp)
- return m_file_sp->GetNumLines();
- return 0;
+static const char *CursesKeyToCString(int ch) {
+ static char g_desc[32];
+ if (ch >= KEY_F0 && ch < KEY_F0 + 64) {
+ snprintf(g_desc, sizeof(g_desc), "F%u", ch - KEY_F0);
+ return g_desc;
+ }
+ switch (ch) {
+ case KEY_DOWN:
+ return "down";
+ case KEY_UP:
+ return "up";
+ case KEY_LEFT:
+ return "left";
+ case KEY_RIGHT:
+ return "right";
+ case KEY_HOME:
+ return "home";
+ case KEY_BACKSPACE:
+ return "backspace";
+ case KEY_DL:
+ return "delete-line";
+ case KEY_IL:
+ return "insert-line";
+ case KEY_DC:
+ return "delete-char";
+ case KEY_IC:
+ return "insert-char";
+ case KEY_CLEAR:
+ return "clear";
+ case KEY_EOS:
+ return "clear-to-eos";
+ case KEY_EOL:
+ return "clear-to-eol";
+ case KEY_SF:
+ return "scroll-forward";
+ case KEY_SR:
+ return "scroll-backward";
+ case KEY_NPAGE:
+ return "page-down";
+ case KEY_PPAGE:
+ return "page-up";
+ case KEY_STAB:
+ return "set-tab";
+ case KEY_CTAB:
+ return "clear-tab";
+ case KEY_CATAB:
+ return "clear-all-tabs";
+ case KEY_ENTER:
+ return "enter";
+ case KEY_PRINT:
+ return "print";
+ case KEY_LL:
+ return "lower-left key";
+ case KEY_A1:
+ return "upper left of keypad";
+ case KEY_A3:
+ return "upper right of keypad";
+ case KEY_B2:
+ return "center of keypad";
+ case KEY_C1:
+ return "lower left of keypad";
+ case KEY_C3:
+ return "lower right of keypad";
+ case KEY_BTAB:
+ return "back-tab key";
+ case KEY_BEG:
+ return "begin key";
+ case KEY_CANCEL:
+ return "cancel key";
+ case KEY_CLOSE:
+ return "close key";
+ case KEY_COMMAND:
+ return "command key";
+ case KEY_COPY:
+ return "copy key";
+ case KEY_CREATE:
+ return "create key";
+ case KEY_END:
+ return "end key";
+ case KEY_EXIT:
+ return "exit key";
+ case KEY_FIND:
+ return "find key";
+ case KEY_HELP:
+ return "help key";
+ case KEY_MARK:
+ return "mark key";
+ case KEY_MESSAGE:
+ return "message key";
+ case KEY_MOVE:
+ return "move key";
+ case KEY_NEXT:
+ return "next key";
+ case KEY_OPEN:
+ return "open key";
+ case KEY_OPTIONS:
+ return "options key";
+ case KEY_PREVIOUS:
+ return "previous key";
+ case KEY_REDO:
+ return "redo key";
+ case KEY_REFERENCE:
+ return "reference key";
+ case KEY_REFRESH:
+ return "refresh key";
+ case KEY_REPLACE:
+ return "replace key";
+ case KEY_RESTART:
+ return "restart key";
+ case KEY_RESUME:
+ return "resume key";
+ case KEY_SAVE:
+ return "save key";
+ case KEY_SBEG:
+ return "shifted begin key";
+ case KEY_SCANCEL:
+ return "shifted cancel key";
+ case KEY_SCOMMAND:
+ return "shifted command key";
+ case KEY_SCOPY:
+ return "shifted copy key";
+ case KEY_SCREATE:
+ return "shifted create key";
+ case KEY_SDC:
+ return "shifted delete-character key";
+ case KEY_SDL:
+ return "shifted delete-line key";
+ case KEY_SELECT:
+ return "select key";
+ case KEY_SEND:
+ return "shifted end key";
+ case KEY_SEOL:
+ return "shifted clear-to-end-of-line key";
+ case KEY_SEXIT:
+ return "shifted exit key";
+ case KEY_SFIND:
+ return "shifted find key";
+ case KEY_SHELP:
+ return "shifted help key";
+ case KEY_SHOME:
+ return "shifted home key";
+ case KEY_SIC:
+ return "shifted insert-character key";
+ case KEY_SLEFT:
+ return "shifted left-arrow key";
+ case KEY_SMESSAGE:
+ return "shifted message key";
+ case KEY_SMOVE:
+ return "shifted move key";
+ case KEY_SNEXT:
+ return "shifted next key";
+ case KEY_SOPTIONS:
+ return "shifted options key";
+ case KEY_SPREVIOUS:
+ return "shifted previous key";
+ case KEY_SPRINT:
+ return "shifted print key";
+ case KEY_SREDO:
+ return "shifted redo key";
+ case KEY_SREPLACE:
+ return "shifted replace key";
+ case KEY_SRIGHT:
+ return "shifted right-arrow key";
+ case KEY_SRSUME:
+ return "shifted resume key";
+ case KEY_SSAVE:
+ return "shifted save key";
+ case KEY_SSUSPEND:
+ return "shifted suspend key";
+ case KEY_SUNDO:
+ return "shifted undo key";
+ case KEY_SUSPEND:
+ return "suspend key";
+ case KEY_UNDO:
+ return "undo key";
+ case KEY_MOUSE:
+ return "Mouse event has occurred";
+ case KEY_RESIZE:
+ return "Terminal resize event";
+#ifdef KEY_EVENT
+ case KEY_EVENT:
+ return "We were interrupted by an event";
+#endif
+ case KEY_RETURN:
+ return "return";
+ case ' ':
+ return "space";
+ case '\t':
+ return "tab";
+ case KEY_ESCAPE:
+ return "escape";
+ default:
+ if (isprint(ch))
+ snprintf(g_desc, sizeof(g_desc), "%c", ch);
+ else
+ snprintf(g_desc, sizeof(g_desc), "\\x%2.2x", ch);
+ return g_desc;
+ }
+ return nullptr;
+}
+
+HelpDialogDelegate::HelpDialogDelegate(const char *text,
+ KeyHelp *key_help_array)
+ : m_text(), m_first_visible_line(0) {
+ if (text && text[0]) {
+ m_text.SplitIntoLines(text);
+ m_text.AppendString("");
+ }
+ if (key_help_array) {
+ for (KeyHelp *key = key_help_array; key->ch; ++key) {
+ StreamString key_description;
+ key_description.Printf("%10s - %s", CursesKeyToCString(key->ch),
+ key->description);
+ m_text.AppendString(std::move(key_description.GetString()));
}
+ }
+}
- size_t
- GetNumDisassemblyLines () const
- {
- if (m_disassembly_sp)
- return m_disassembly_sp->GetInstructionList().GetSize();
- return 0;
+HelpDialogDelegate::~HelpDialogDelegate() = default;
+
+bool HelpDialogDelegate::WindowDelegateDraw(Window &window, bool force) {
+ window.Erase();
+ const int window_height = window.GetHeight();
+ int x = 2;
+ int y = 1;
+ const int min_y = y;
+ const int max_y = window_height - 1 - y;
+ const size_t num_visible_lines = max_y - min_y + 1;
+ const size_t num_lines = m_text.GetSize();
+ const char *bottom_message;
+ if (num_lines <= num_visible_lines)
+ bottom_message = "Press any key to exit";
+ else
+ bottom_message = "Use arrows to scroll, any other key to exit";
+ window.DrawTitleBox(window.GetName(), bottom_message);
+ while (y <= max_y) {
+ window.MoveCursor(x, y);
+ window.PutCStringTruncated(
+ m_text.GetStringAtIndex(m_first_visible_line + y - min_y), 1);
+ ++y;
+ }
+ return true;
+}
+
+HandleCharResult HelpDialogDelegate::WindowDelegateHandleChar(Window &window,
+ int key) {
+ bool done = false;
+ const size_t num_lines = m_text.GetSize();
+ const size_t num_visible_lines = window.GetHeight() - 2;
+
+ if (num_lines <= num_visible_lines) {
+ done = true;
+ // If we have all lines visible and don't need scrolling, then any
+ // key press will cause us to exit
+ } else {
+ switch (key) {
+ case KEY_UP:
+ if (m_first_visible_line > 0)
+ --m_first_visible_line;
+ break;
+
+ case KEY_DOWN:
+ if (m_first_visible_line + num_visible_lines < num_lines)
+ ++m_first_visible_line;
+ break;
+
+ case KEY_PPAGE:
+ case ',':
+ if (m_first_visible_line > 0) {
+ if (static_cast<size_t>(m_first_visible_line) >= num_visible_lines)
+ m_first_visible_line -= num_visible_lines;
+ else
+ m_first_visible_line = 0;
+ }
+ break;
+
+ case KEY_NPAGE:
+ case '.':
+ if (m_first_visible_line + num_visible_lines < num_lines) {
+ m_first_visible_line += num_visible_lines;
+ if (static_cast<size_t>(m_first_visible_line) > num_lines)
+ m_first_visible_line = num_lines - num_visible_lines;
+ }
+ break;
+
+ default:
+ done = true;
+ break;
+ }
+ }
+ if (done)
+ window.GetParent()->RemoveSubWindow(&window);
+ return eKeyHandled;
+}
+
+class ApplicationDelegate : public WindowDelegate, public MenuDelegate {
+public:
+ enum {
+ eMenuID_LLDB = 1,
+ eMenuID_LLDBAbout,
+ eMenuID_LLDBExit,
+
+ eMenuID_Target,
+ eMenuID_TargetCreate,
+ eMenuID_TargetDelete,
+
+ eMenuID_Process,
+ eMenuID_ProcessAttach,
+ eMenuID_ProcessDetach,
+ eMenuID_ProcessLaunch,
+ eMenuID_ProcessContinue,
+ eMenuID_ProcessHalt,
+ eMenuID_ProcessKill,
+
+ eMenuID_Thread,
+ eMenuID_ThreadStepIn,
+ eMenuID_ThreadStepOver,
+ eMenuID_ThreadStepOut,
+
+ eMenuID_View,
+ eMenuID_ViewBacktrace,
+ eMenuID_ViewRegisters,
+ eMenuID_ViewSource,
+ eMenuID_ViewVariables,
+
+ eMenuID_Help,
+ eMenuID_HelpGUIHelp
+ };
+
+ ApplicationDelegate(Application &app, Debugger &debugger)
+ : WindowDelegate(), MenuDelegate(), m_app(app), m_debugger(debugger) {}
+
+ ~ApplicationDelegate() override = default;
+
+ bool WindowDelegateDraw(Window &window, bool force) override {
+ return false; // Drawing not handled, let standard window drawing happen
+ }
+
+ HandleCharResult WindowDelegateHandleChar(Window &window, int key) override {
+ switch (key) {
+ case '\t':
+ window.SelectNextWindowAsActive();
+ return eKeyHandled;
+
+ case 'h':
+ window.CreateHelpSubwindow();
+ return eKeyHandled;
+
+ case KEY_ESCAPE:
+ return eQuitApplication;
+
+ default:
+ break;
+ }
+ return eKeyNotHandled;
+ }
+
+ const char *WindowDelegateGetHelpText() override {
+ return "Welcome to the LLDB curses GUI.\n\n"
+ "Press the TAB key to change the selected view.\n"
+ "Each view has its own keyboard shortcuts, press 'h' to open a "
+ "dialog to display them.\n\n"
+ "Common key bindings for all views:";
+ }
+
+ KeyHelp *WindowDelegateGetKeyHelp() override {
+ static curses::KeyHelp g_source_view_key_help[] = {
+ {'\t', "Select next view"},
+ {'h', "Show help dialog with view specific key bindings"},
+ {',', "Page up"},
+ {'.', "Page down"},
+ {KEY_UP, "Select previous"},
+ {KEY_DOWN, "Select next"},
+ {KEY_LEFT, "Unexpand or select parent"},
+ {KEY_RIGHT, "Expand"},
+ {KEY_PPAGE, "Page up"},
+ {KEY_NPAGE, "Page down"},
+ {'\0', nullptr}};
+ return g_source_view_key_help;
+ }
+
+ MenuActionResult MenuDelegateAction(Menu &menu) override {
+ switch (menu.GetIdentifier()) {
+ case eMenuID_ThreadStepIn: {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasThreadScope()) {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive() &&
+ StateIsStoppedState(process->GetState(), true))
+ exe_ctx.GetThreadRef().StepIn(true);
+ }
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ThreadStepOut: {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasThreadScope()) {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive() &&
+ StateIsStoppedState(process->GetState(), true))
+ exe_ctx.GetThreadRef().StepOut();
+ }
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ThreadStepOver: {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasThreadScope()) {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive() &&
+ StateIsStoppedState(process->GetState(), true))
+ exe_ctx.GetThreadRef().StepOver(true);
+ }
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ProcessContinue: {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope()) {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive() &&
+ StateIsStoppedState(process->GetState(), true))
+ process->Resume();
+ }
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ProcessKill: {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope()) {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive())
+ process->Destroy(false);
+ }
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ProcessHalt: {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope()) {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive())
+ process->Halt();
+ }
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ProcessDetach: {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope()) {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive())
+ process->Detach(false);
+ }
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_Process: {
+ // Populate the menu with all of the threads if the process is stopped
+ // when
+ // the Process menu gets selected and is about to display its submenu.
+ Menus &submenus = menu.GetSubmenus();
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive() &&
+ StateIsStoppedState(process->GetState(), true)) {
+ if (submenus.size() == 7)
+ menu.AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
+ else if (submenus.size() > 8)
+ submenus.erase(submenus.begin() + 8, submenus.end());
+
+ ThreadList &threads = process->GetThreadList();
+ std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
+ size_t num_threads = threads.GetSize();
+ for (size_t i = 0; i < num_threads; ++i) {
+ ThreadSP thread_sp = threads.GetThreadAtIndex(i);
+ char menu_char = '\0';
+ if (i < 9)
+ menu_char = '1' + i;
+ StreamString thread_menu_title;
+ thread_menu_title.Printf("Thread %u", thread_sp->GetIndexID());
+ const char *thread_name = thread_sp->GetName();
+ if (thread_name && thread_name[0])
+ thread_menu_title.Printf(" %s", thread_name);
+ else {
+ const char *queue_name = thread_sp->GetQueueName();
+ if (queue_name && queue_name[0])
+ thread_menu_title.Printf(" %s", queue_name);
+ }
+ menu.AddSubmenu(
+ MenuSP(new Menu(thread_menu_title.GetString().c_str(), nullptr,
+ menu_char, thread_sp->GetID())));
+ }
+ } else if (submenus.size() > 7) {
+ // Remove the separator and any other thread submenu items
+ // that were previously added
+ submenus.erase(submenus.begin() + 7, submenus.end());
+ }
+ // Since we are adding and removing items we need to recalculate the name
+ // lengths
+ menu.RecalculateNameLengths();
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ViewVariables: {
+ WindowSP main_window_sp = m_app.GetMainWindow();
+ WindowSP source_window_sp = main_window_sp->FindSubWindow("Source");
+ WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables");
+ WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers");
+ const Rect source_bounds = source_window_sp->GetBounds();
+
+ if (variables_window_sp) {
+ const Rect variables_bounds = variables_window_sp->GetBounds();
+
+ main_window_sp->RemoveSubWindow(variables_window_sp.get());
+
+ if (registers_window_sp) {
+ // We have a registers window, so give all the area back to the
+ // registers window
+ Rect registers_bounds = variables_bounds;
+ registers_bounds.size.width = source_bounds.size.width;
+ registers_window_sp->SetBounds(registers_bounds);
+ } else {
+ // We have no registers window showing so give the bottom
+ // area back to the source view
+ source_window_sp->Resize(source_bounds.size.width,
+ source_bounds.size.height +
+ variables_bounds.size.height);
+ }
+ } else {
+ Rect new_variables_rect;
+ if (registers_window_sp) {
+ // We have a registers window so split the area of the registers
+ // window into two columns where the left hand side will be the
+ // variables and the right hand side will be the registers
+ const Rect variables_bounds = registers_window_sp->GetBounds();
+ Rect new_registers_rect;
+ variables_bounds.VerticalSplitPercentage(0.50, new_variables_rect,
+ new_registers_rect);
+ registers_window_sp->SetBounds(new_registers_rect);
+ } else {
+ // No variables window, grab the bottom part of the source window
+ Rect new_source_rect;
+ source_bounds.HorizontalSplitPercentage(0.70, new_source_rect,
+ new_variables_rect);
+ source_window_sp->SetBounds(new_source_rect);
+ }
+ WindowSP new_window_sp = main_window_sp->CreateSubWindow(
+ "Variables", new_variables_rect, false);
+ new_window_sp->SetDelegate(
+ WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger)));
+ }
+ touchwin(stdscr);
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_ViewRegisters: {
+ WindowSP main_window_sp = m_app.GetMainWindow();
+ WindowSP source_window_sp = main_window_sp->FindSubWindow("Source");
+ WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables");
+ WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers");
+ const Rect source_bounds = source_window_sp->GetBounds();
+
+ if (registers_window_sp) {
+ if (variables_window_sp) {
+ const Rect variables_bounds = variables_window_sp->GetBounds();
+
+ // We have a variables window, so give all the area back to the
+ // variables window
+ variables_window_sp->Resize(variables_bounds.size.width +
+ registers_window_sp->GetWidth(),
+ variables_bounds.size.height);
+ } else {
+ // We have no variables window showing so give the bottom
+ // area back to the source view
+ source_window_sp->Resize(source_bounds.size.width,
+ source_bounds.size.height +
+ registers_window_sp->GetHeight());
+ }
+ main_window_sp->RemoveSubWindow(registers_window_sp.get());
+ } else {
+ Rect new_regs_rect;
+ if (variables_window_sp) {
+ // We have a variables window, split it into two columns
+ // where the left hand side will be the variables and the
+ // right hand side will be the registers
+ const Rect variables_bounds = variables_window_sp->GetBounds();
+ Rect new_vars_rect;
+ variables_bounds.VerticalSplitPercentage(0.50, new_vars_rect,
+ new_regs_rect);
+ variables_window_sp->SetBounds(new_vars_rect);
+ } else {
+ // No registers window, grab the bottom part of the source window
+ Rect new_source_rect;
+ source_bounds.HorizontalSplitPercentage(0.70, new_source_rect,
+ new_regs_rect);
+ source_window_sp->SetBounds(new_source_rect);
+ }
+ WindowSP new_window_sp =
+ main_window_sp->CreateSubWindow("Registers", new_regs_rect, false);
+ new_window_sp->SetDelegate(
+ WindowDelegateSP(new RegistersWindowDelegate(m_debugger)));
+ }
+ touchwin(stdscr);
+ }
+ return MenuActionResult::Handled;
+
+ case eMenuID_HelpGUIHelp:
+ m_app.GetMainWindow()->CreateHelpSubwindow();
+ return MenuActionResult::Handled;
+
+ default:
+ break;
}
- HandleCharResult
- WindowDelegateHandleChar (Window &window, int c) override
- {
- const uint32_t num_visible_lines = NumVisibleLines();
- const size_t num_lines = GetNumLines ();
+ return MenuActionResult::NotHandled;
+ }
- switch (c)
- {
- case ',':
- case KEY_PPAGE:
- // Page up key
- if (static_cast<uint32_t>(m_first_visible_line) > num_visible_lines)
- m_first_visible_line -= num_visible_lines;
- else
- m_first_visible_line = 0;
- m_selected_line = m_first_visible_line;
- return eKeyHandled;
-
- case '.':
- case KEY_NPAGE:
- // Page down key
- {
- if (m_first_visible_line + num_visible_lines < num_lines)
- m_first_visible_line += num_visible_lines;
- else if (num_lines < num_visible_lines)
- m_first_visible_line = 0;
- else
- m_first_visible_line = num_lines - num_visible_lines;
- m_selected_line = m_first_visible_line;
- }
- return eKeyHandled;
+protected:
+ Application &m_app;
+ Debugger &m_debugger;
+};
- case KEY_UP:
- if (m_selected_line > 0)
- {
- m_selected_line--;
- if (static_cast<size_t>(m_first_visible_line) > m_selected_line)
- m_first_visible_line = m_selected_line;
- }
- return eKeyHandled;
+class StatusBarWindowDelegate : public WindowDelegate {
+public:
+ StatusBarWindowDelegate(Debugger &debugger) : m_debugger(debugger) {
+ FormatEntity::Parse("Thread: ${thread.id%tid}", m_format);
+ }
+
+ ~StatusBarWindowDelegate() override = default;
+
+ bool WindowDelegateDraw(Window &window, bool force) override {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ Process *process = exe_ctx.GetProcessPtr();
+ Thread *thread = exe_ctx.GetThreadPtr();
+ StackFrame *frame = exe_ctx.GetFramePtr();
+ window.Erase();
+ window.SetBackground(2);
+ window.MoveCursor(0, 0);
+ if (process) {
+ const StateType state = process->GetState();
+ window.Printf("Process: %5" PRIu64 " %10s", process->GetID(),
+ StateAsCString(state));
+
+ if (StateIsStoppedState(state, true)) {
+ StreamString strm;
+ if (thread && FormatEntity::Format(m_format, strm, nullptr, &exe_ctx,
+ nullptr, nullptr, false, false)) {
+ window.MoveCursor(40, 0);
+ window.PutCStringTruncated(strm.GetString().c_str(), 1);
+ }
- case KEY_DOWN:
- if (m_selected_line + 1 < num_lines)
- {
- m_selected_line++;
- if (m_first_visible_line + num_visible_lines < m_selected_line)
- m_first_visible_line++;
- }
- return eKeyHandled;
+ window.MoveCursor(60, 0);
+ if (frame)
+ window.Printf("Frame: %3u PC = 0x%16.16" PRIx64,
+ frame->GetFrameIndex(),
+ frame->GetFrameCodeAddress().GetOpcodeLoadAddress(
+ exe_ctx.GetTargetPtr()));
+ } else if (state == eStateExited) {
+ const char *exit_desc = process->GetExitDescription();
+ const int exit_status = process->GetExitStatus();
+ if (exit_desc && exit_desc[0])
+ window.Printf(" with status = %i (%s)", exit_status, exit_desc);
+ else
+ window.Printf(" with status = %i", exit_status);
+ }
+ }
+ window.DeferredRefresh();
+ return true;
+ }
- case '\r':
- case '\n':
- case KEY_ENTER:
- // Set a breakpoint and run to the line using a one shot breakpoint
- if (GetNumSourceLines() > 0)
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope() && exe_ctx.GetProcessRef().IsAlive())
- {
- BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(nullptr, // Don't limit the breakpoint to certain modules
- m_file_sp->GetFileSpec(), // Source file
- m_selected_line + 1, // Source line number (m_selected_line is zero based)
- 0, // No offset
- eLazyBoolCalculate, // Check inlines using global setting
- eLazyBoolCalculate, // Skip prologue using global setting,
- false, // internal
- false, // request_hardware
- eLazyBoolCalculate); // move_to_nearest_code
- // Make breakpoint one shot
- bp_sp->GetOptions()->SetOneShot(true);
- exe_ctx.GetProcessRef().Resume();
- }
- }
- else if (m_selected_line < GetNumDisassemblyLines())
- {
- const Instruction *inst = m_disassembly_sp->GetInstructionList().GetInstructionAtIndex(m_selected_line).get();
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasTargetScope())
- {
- Address addr = inst->GetAddress();
- BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint (addr, // lldb_private::Address
- false, // internal
- false); // request_hardware
- // Make breakpoint one shot
- bp_sp->GetOptions()->SetOneShot(true);
- exe_ctx.GetProcessRef().Resume();
- }
- }
- return eKeyHandled;
+protected:
+ Debugger &m_debugger;
+ FormatEntity::Entry m_format;
+};
- case 'b': // 'b' == toggle breakpoint on currently selected line
- if (m_selected_line < GetNumSourceLines())
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasTargetScope())
- {
- BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(nullptr, // Don't limit the breakpoint to certain modules
- m_file_sp->GetFileSpec(), // Source file
- m_selected_line + 1, // Source line number (m_selected_line is zero based)
- 0, // No offset
- eLazyBoolCalculate, // Check inlines using global setting
- eLazyBoolCalculate, // Skip prologue using global setting,
- false, // internal
- false, // request_hardware
- eLazyBoolCalculate); // move_to_nearest_code
- }
- }
- else if (m_selected_line < GetNumDisassemblyLines())
- {
- const Instruction *inst = m_disassembly_sp->GetInstructionList().GetInstructionAtIndex(m_selected_line).get();
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasTargetScope())
- {
- Address addr = inst->GetAddress();
- BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint (addr, // lldb_private::Address
- false, // internal
- false); // request_hardware
- }
- }
- return eKeyHandled;
+class SourceFileWindowDelegate : public WindowDelegate {
+public:
+ SourceFileWindowDelegate(Debugger &debugger)
+ : WindowDelegate(), m_debugger(debugger), m_sc(), m_file_sp(),
+ m_disassembly_scope(nullptr), m_disassembly_sp(), m_disassembly_range(),
+ m_title(), m_line_width(4), m_selected_line(0), m_pc_line(0),
+ m_stop_id(0), m_frame_idx(UINT32_MAX), m_first_visible_line(0),
+ m_min_x(0), m_min_y(0), m_max_x(0), m_max_y(0) {}
+
+ ~SourceFileWindowDelegate() override = default;
+
+ void Update(const SymbolContext &sc) { m_sc = sc; }
+
+ uint32_t NumVisibleLines() const { return m_max_y - m_min_y; }
+
+ const char *WindowDelegateGetHelpText() override {
+ return "Source/Disassembly window keyboard shortcuts:";
+ }
+
+ KeyHelp *WindowDelegateGetKeyHelp() override {
+ static curses::KeyHelp g_source_view_key_help[] = {
+ {KEY_RETURN, "Run to selected line with one shot breakpoint"},
+ {KEY_UP, "Select previous source line"},
+ {KEY_DOWN, "Select next source line"},
+ {KEY_PPAGE, "Page up"},
+ {KEY_NPAGE, "Page down"},
+ {'b', "Set breakpoint on selected source/disassembly line"},
+ {'c', "Continue process"},
+ {'d', "Detach and resume process"},
+ {'D', "Detach with process suspended"},
+ {'h', "Show help dialog"},
+ {'k', "Kill process"},
+ {'n', "Step over (source line)"},
+ {'N', "Step over (single instruction)"},
+ {'o', "Step out"},
+ {'s', "Step in (source line)"},
+ {'S', "Step in (single instruction)"},
+ {',', "Page up"},
+ {'.', "Page down"},
+ {'\0', nullptr}};
+ return g_source_view_key_help;
+ }
+
+ bool WindowDelegateDraw(Window &window, bool force) override {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ Process *process = exe_ctx.GetProcessPtr();
+ Thread *thread = nullptr;
+
+ bool update_location = false;
+ if (process) {
+ StateType state = process->GetState();
+ if (StateIsStoppedState(state, true)) {
+ // We are stopped, so it is ok to
+ update_location = true;
+ }
+ }
+
+ m_min_x = 1;
+ m_min_y = 2;
+ m_max_x = window.GetMaxX() - 1;
+ m_max_y = window.GetMaxY() - 1;
+
+ const uint32_t num_visible_lines = NumVisibleLines();
+ StackFrameSP frame_sp;
+ bool set_selected_line_to_pc = false;
+
+ if (update_location) {
+ const bool process_alive = process ? process->IsAlive() : false;
+ bool thread_changed = false;
+ if (process_alive) {
+ thread = exe_ctx.GetThreadPtr();
+ if (thread) {
+ frame_sp = thread->GetSelectedFrame();
+ auto tid = thread->GetID();
+ thread_changed = tid != m_tid;
+ m_tid = tid;
+ } else {
+ if (m_tid != LLDB_INVALID_THREAD_ID) {
+ thread_changed = true;
+ m_tid = LLDB_INVALID_THREAD_ID;
+ }
+ }
+ }
+ const uint32_t stop_id = process ? process->GetStopID() : 0;
+ const bool stop_id_changed = stop_id != m_stop_id;
+ bool frame_changed = false;
+ m_stop_id = stop_id;
+ m_title.Clear();
+ if (frame_sp) {
+ m_sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
+ if (m_sc.module_sp) {
+ m_title.Printf(
+ "%s", m_sc.module_sp->GetFileSpec().GetFilename().GetCString());
+ ConstString func_name = m_sc.GetFunctionName();
+ if (func_name)
+ m_title.Printf("`%s", func_name.GetCString());
+ }
+ const uint32_t frame_idx = frame_sp->GetFrameIndex();
+ frame_changed = frame_idx != m_frame_idx;
+ m_frame_idx = frame_idx;
+ } else {
+ m_sc.Clear(true);
+ frame_changed = m_frame_idx != UINT32_MAX;
+ m_frame_idx = UINT32_MAX;
+ }
+
+ const bool context_changed =
+ thread_changed || frame_changed || stop_id_changed;
+
+ if (process_alive) {
+ if (m_sc.line_entry.IsValid()) {
+ m_pc_line = m_sc.line_entry.line;
+ if (m_pc_line != UINT32_MAX)
+ --m_pc_line; // Convert to zero based line number...
+ // Update the selected line if the stop ID changed...
+ if (context_changed)
+ m_selected_line = m_pc_line;
+
+ if (m_file_sp && m_file_sp->FileSpecMatches(m_sc.line_entry.file)) {
+ // Same file, nothing to do, we should either have the
+ // lines or not (source file missing)
+ if (m_selected_line >= static_cast<size_t>(m_first_visible_line)) {
+ if (m_selected_line >= m_first_visible_line + num_visible_lines)
+ m_first_visible_line = m_selected_line - 10;
+ } else {
+ if (m_selected_line > 10)
+ m_first_visible_line = m_selected_line - 10;
+ else
+ m_first_visible_line = 0;
+ }
+ } else {
+ // File changed, set selected line to the line with the PC
+ m_selected_line = m_pc_line;
+ m_file_sp =
+ m_debugger.GetSourceManager().GetFile(m_sc.line_entry.file);
+ if (m_file_sp) {
+ const size_t num_lines = m_file_sp->GetNumLines();
+ int m_line_width = 1;
+ for (size_t n = num_lines; n >= 10; n = n / 10)
+ ++m_line_width;
+
+ snprintf(m_line_format, sizeof(m_line_format), " %%%iu ",
+ m_line_width);
+ if (num_lines < num_visible_lines ||
+ m_selected_line < num_visible_lines)
+ m_first_visible_line = 0;
+ else
+ m_first_visible_line = m_selected_line - 10;
+ }
+ }
+ } else {
+ m_file_sp.reset();
+ }
+
+ if (!m_file_sp || m_file_sp->GetNumLines() == 0) {
+ // Show disassembly
+ bool prefer_file_cache = false;
+ if (m_sc.function) {
+ if (m_disassembly_scope != m_sc.function) {
+ m_disassembly_scope = m_sc.function;
+ m_disassembly_sp = m_sc.function->GetInstructions(
+ exe_ctx, nullptr, prefer_file_cache);
+ if (m_disassembly_sp) {
+ set_selected_line_to_pc = true;
+ m_disassembly_range = m_sc.function->GetAddressRange();
+ } else {
+ m_disassembly_range.Clear();
+ }
+ } else {
+ set_selected_line_to_pc = context_changed;
+ }
+ } else if (m_sc.symbol) {
+ if (m_disassembly_scope != m_sc.symbol) {
+ m_disassembly_scope = m_sc.symbol;
+ m_disassembly_sp = m_sc.symbol->GetInstructions(
+ exe_ctx, nullptr, prefer_file_cache);
+ if (m_disassembly_sp) {
+ set_selected_line_to_pc = true;
+ m_disassembly_range.GetBaseAddress() =
+ m_sc.symbol->GetAddress();
+ m_disassembly_range.SetByteSize(m_sc.symbol->GetByteSize());
+ } else {
+ m_disassembly_range.Clear();
+ }
+ } else {
+ set_selected_line_to_pc = context_changed;
+ }
+ }
+ }
+ } else {
+ m_pc_line = UINT32_MAX;
+ }
+ }
- case 'd': // 'd' == detach and let run
- case 'D': // 'D' == detach and keep stopped
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope())
- exe_ctx.GetProcessRef().Detach(c == 'D');
- }
- return eKeyHandled;
+ const int window_width = window.GetWidth();
+ window.Erase();
+ window.DrawTitleBox("Sources");
+ if (!m_title.GetString().empty()) {
+ window.AttributeOn(A_REVERSE);
+ window.MoveCursor(1, 1);
+ window.PutChar(' ');
+ window.PutCStringTruncated(m_title.GetString().c_str(), 1);
+ int x = window.GetCursorX();
+ if (x < window_width - 1) {
+ window.Printf("%*s", window_width - x - 1, "");
+ }
+ window.AttributeOff(A_REVERSE);
+ }
+
+ Target *target = exe_ctx.GetTargetPtr();
+ const size_t num_source_lines = GetNumSourceLines();
+ if (num_source_lines > 0) {
+ // Display source
+ BreakpointLines bp_lines;
+ if (target) {
+ BreakpointList &bp_list = target->GetBreakpointList();
+ const size_t num_bps = bp_list.GetSize();
+ for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
+ BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
+ const size_t num_bps_locs = bp_sp->GetNumLocations();
+ for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs; ++bp_loc_idx) {
+ BreakpointLocationSP bp_loc_sp =
+ bp_sp->GetLocationAtIndex(bp_loc_idx);
+ LineEntry bp_loc_line_entry;
+ if (bp_loc_sp->GetAddress().CalculateSymbolContextLineEntry(
+ bp_loc_line_entry)) {
+ if (m_file_sp->GetFileSpec() == bp_loc_line_entry.file) {
+ bp_lines.insert(bp_loc_line_entry.line);
+ }
+ }
+ }
+ }
+ }
+
+ const attr_t selected_highlight_attr = A_REVERSE;
+ const attr_t pc_highlight_attr = COLOR_PAIR(1);
+
+ for (size_t i = 0; i < num_visible_lines; ++i) {
+ const uint32_t curr_line = m_first_visible_line + i;
+ if (curr_line < num_source_lines) {
+ const int line_y = m_min_y + i;
+ window.MoveCursor(1, line_y);
+ const bool is_pc_line = curr_line == m_pc_line;
+ const bool line_is_selected = m_selected_line == curr_line;
+ // Highlight the line as the PC line first, then if the selected line
+ // isn't the same as the PC line, highlight it differently
+ attr_t highlight_attr = 0;
+ attr_t bp_attr = 0;
+ if (is_pc_line)
+ highlight_attr = pc_highlight_attr;
+ else if (line_is_selected)
+ highlight_attr = selected_highlight_attr;
+
+ if (bp_lines.find(curr_line + 1) != bp_lines.end())
+ bp_attr = COLOR_PAIR(2);
+
+ if (bp_attr)
+ window.AttributeOn(bp_attr);
+
+ window.Printf(m_line_format, curr_line + 1);
+
+ if (bp_attr)
+ window.AttributeOff(bp_attr);
+
+ window.PutChar(ACS_VLINE);
+ // Mark the line with the PC with a diamond
+ if (is_pc_line)
+ window.PutChar(ACS_DIAMOND);
+ else
+ window.PutChar(' ');
- case 'k':
- // 'k' == kill
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope())
- exe_ctx.GetProcessRef().Destroy(false);
- }
- return eKeyHandled;
+ if (highlight_attr)
+ window.AttributeOn(highlight_attr);
+ const uint32_t line_len =
+ m_file_sp->GetLineLength(curr_line + 1, false);
+ if (line_len > 0)
+ window.PutCString(m_file_sp->PeekLineData(curr_line + 1), line_len);
+
+ if (is_pc_line && frame_sp &&
+ frame_sp->GetConcreteFrameIndex() == 0) {
+ StopInfoSP stop_info_sp;
+ if (thread)
+ stop_info_sp = thread->GetStopInfo();
+ if (stop_info_sp) {
+ const char *stop_description = stop_info_sp->GetDescription();
+ if (stop_description && stop_description[0]) {
+ size_t stop_description_len = strlen(stop_description);
+ int desc_x = window_width - stop_description_len - 16;
+ window.Printf("%*s", desc_x - window.GetCursorX(), "");
+ // window.MoveCursor(window_width - stop_description_len - 15,
+ // line_y);
+ window.Printf("<<< Thread %u: %s ", thread->GetIndexID(),
+ stop_description);
+ }
+ } else {
+ window.Printf("%*s", window_width - window.GetCursorX() - 1, "");
+ }
+ }
+ if (highlight_attr)
+ window.AttributeOff(highlight_attr);
+ } else {
+ break;
+ }
+ }
+ } else {
+ size_t num_disassembly_lines = GetNumDisassemblyLines();
+ if (num_disassembly_lines > 0) {
+ // Display disassembly
+ BreakpointAddrs bp_file_addrs;
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target) {
+ BreakpointList &bp_list = target->GetBreakpointList();
+ const size_t num_bps = bp_list.GetSize();
+ for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
+ BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
+ const size_t num_bps_locs = bp_sp->GetNumLocations();
+ for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs;
+ ++bp_loc_idx) {
+ BreakpointLocationSP bp_loc_sp =
+ bp_sp->GetLocationAtIndex(bp_loc_idx);
+ LineEntry bp_loc_line_entry;
+ const lldb::addr_t file_addr =
+ bp_loc_sp->GetAddress().GetFileAddress();
+ if (file_addr != LLDB_INVALID_ADDRESS) {
+ if (m_disassembly_range.ContainsFileAddress(file_addr))
+ bp_file_addrs.insert(file_addr);
+ }
+ }
+ }
+ }
+
+ const attr_t selected_highlight_attr = A_REVERSE;
+ const attr_t pc_highlight_attr = COLOR_PAIR(1);
+
+ StreamString strm;
+
+ InstructionList &insts = m_disassembly_sp->GetInstructionList();
+ Address pc_address;
+
+ if (frame_sp)
+ pc_address = frame_sp->GetFrameCodeAddress();
+ const uint32_t pc_idx =
+ pc_address.IsValid()
+ ? insts.GetIndexOfInstructionAtAddress(pc_address)
+ : UINT32_MAX;
+ if (set_selected_line_to_pc) {
+ m_selected_line = pc_idx;
+ }
+
+ const uint32_t non_visible_pc_offset = (num_visible_lines / 5);
+ if (static_cast<size_t>(m_first_visible_line) >= num_disassembly_lines)
+ m_first_visible_line = 0;
+
+ if (pc_idx < num_disassembly_lines) {
+ if (pc_idx < static_cast<uint32_t>(m_first_visible_line) ||
+ pc_idx >= m_first_visible_line + num_visible_lines)
+ m_first_visible_line = pc_idx - non_visible_pc_offset;
+ }
+
+ for (size_t i = 0; i < num_visible_lines; ++i) {
+ const uint32_t inst_idx = m_first_visible_line + i;
+ Instruction *inst = insts.GetInstructionAtIndex(inst_idx).get();
+ if (!inst)
+ break;
- case 'c':
- // 'c' == continue
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope())
- exe_ctx.GetProcessRef().Resume();
- }
- return eKeyHandled;
+ const int line_y = m_min_y + i;
+ window.MoveCursor(1, line_y);
+ const bool is_pc_line = frame_sp && inst_idx == pc_idx;
+ const bool line_is_selected = m_selected_line == inst_idx;
+ // Highlight the line as the PC line first, then if the selected line
+ // isn't the same as the PC line, highlight it differently
+ attr_t highlight_attr = 0;
+ attr_t bp_attr = 0;
+ if (is_pc_line)
+ highlight_attr = pc_highlight_attr;
+ else if (line_is_selected)
+ highlight_attr = selected_highlight_attr;
+
+ if (bp_file_addrs.find(inst->GetAddress().GetFileAddress()) !=
+ bp_file_addrs.end())
+ bp_attr = COLOR_PAIR(2);
+
+ if (bp_attr)
+ window.AttributeOn(bp_attr);
+
+ window.Printf(" 0x%16.16llx ",
+ static_cast<unsigned long long>(
+ inst->GetAddress().GetLoadAddress(target)));
+
+ if (bp_attr)
+ window.AttributeOff(bp_attr);
+
+ window.PutChar(ACS_VLINE);
+ // Mark the line with the PC with a diamond
+ if (is_pc_line)
+ window.PutChar(ACS_DIAMOND);
+ else
+ window.PutChar(' ');
- case 'o':
- // 'o' == step out
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasThreadScope() && StateIsStoppedState (exe_ctx.GetProcessRef().GetState(), true))
- {
- exe_ctx.GetThreadRef().StepOut();
- }
- }
- return eKeyHandled;
+ if (highlight_attr)
+ window.AttributeOn(highlight_attr);
- case 'n': // 'n' == step over
- case 'N': // 'N' == step over instruction
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasThreadScope() && StateIsStoppedState (exe_ctx.GetProcessRef().GetState(), true))
- {
- bool source_step = (c == 'n');
- exe_ctx.GetThreadRef().StepOver(source_step);
- }
- }
- return eKeyHandled;
+ const char *mnemonic = inst->GetMnemonic(&exe_ctx);
+ const char *operands = inst->GetOperands(&exe_ctx);
+ const char *comment = inst->GetComment(&exe_ctx);
+
+ if (mnemonic != nullptr && mnemonic[0] == '\0')
+ mnemonic = nullptr;
+ if (operands != nullptr && operands[0] == '\0')
+ operands = nullptr;
+ if (comment != nullptr && comment[0] == '\0')
+ comment = nullptr;
+
+ strm.Clear();
+
+ if (mnemonic != nullptr && operands != nullptr && comment != nullptr)
+ strm.Printf("%-8s %-25s ; %s", mnemonic, operands, comment);
+ else if (mnemonic != nullptr && operands != nullptr)
+ strm.Printf("%-8s %s", mnemonic, operands);
+ else if (mnemonic != nullptr)
+ strm.Printf("%s", mnemonic);
+
+ int right_pad = 1;
+ window.PutCStringTruncated(strm.GetString().c_str(), right_pad);
+
+ if (is_pc_line && frame_sp &&
+ frame_sp->GetConcreteFrameIndex() == 0) {
+ StopInfoSP stop_info_sp;
+ if (thread)
+ stop_info_sp = thread->GetStopInfo();
+ if (stop_info_sp) {
+ const char *stop_description = stop_info_sp->GetDescription();
+ if (stop_description && stop_description[0]) {
+ size_t stop_description_len = strlen(stop_description);
+ int desc_x = window_width - stop_description_len - 16;
+ window.Printf("%*s", desc_x - window.GetCursorX(), "");
+ // window.MoveCursor(window_width - stop_description_len - 15,
+ // line_y);
+ window.Printf("<<< Thread %u: %s ", thread->GetIndexID(),
+ stop_description);
+ }
+ } else {
+ window.Printf("%*s", window_width - window.GetCursorX() - 1, "");
+ }
+ }
+ if (highlight_attr)
+ window.AttributeOff(highlight_attr);
+ }
+ }
+ }
+ window.DeferredRefresh();
+ return true; // Drawing handled
+ }
+
+ size_t GetNumLines() {
+ size_t num_lines = GetNumSourceLines();
+ if (num_lines == 0)
+ num_lines = GetNumDisassemblyLines();
+ return num_lines;
+ }
+
+ size_t GetNumSourceLines() const {
+ if (m_file_sp)
+ return m_file_sp->GetNumLines();
+ return 0;
+ }
- case 's': // 's' == step into
- case 'S': // 'S' == step into instruction
- {
- ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasThreadScope() && StateIsStoppedState (exe_ctx.GetProcessRef().GetState(), true))
- {
- bool source_step = (c == 's');
- exe_ctx.GetThreadRef().StepIn(source_step);
- }
- }
- return eKeyHandled;
+ size_t GetNumDisassemblyLines() const {
+ if (m_disassembly_sp)
+ return m_disassembly_sp->GetInstructionList().GetSize();
+ return 0;
+ }
- case 'h':
- window.CreateHelpSubwindow ();
- return eKeyHandled;
+ HandleCharResult WindowDelegateHandleChar(Window &window, int c) override {
+ const uint32_t num_visible_lines = NumVisibleLines();
+ const size_t num_lines = GetNumLines();
+
+ switch (c) {
+ case ',':
+ case KEY_PPAGE:
+ // Page up key
+ if (static_cast<uint32_t>(m_first_visible_line) > num_visible_lines)
+ m_first_visible_line -= num_visible_lines;
+ else
+ m_first_visible_line = 0;
+ m_selected_line = m_first_visible_line;
+ return eKeyHandled;
+
+ case '.':
+ case KEY_NPAGE:
+ // Page down key
+ {
+ if (m_first_visible_line + num_visible_lines < num_lines)
+ m_first_visible_line += num_visible_lines;
+ else if (num_lines < num_visible_lines)
+ m_first_visible_line = 0;
+ else
+ m_first_visible_line = num_lines - num_visible_lines;
+ m_selected_line = m_first_visible_line;
+ }
+ return eKeyHandled;
+
+ case KEY_UP:
+ if (m_selected_line > 0) {
+ m_selected_line--;
+ if (static_cast<size_t>(m_first_visible_line) > m_selected_line)
+ m_first_visible_line = m_selected_line;
+ }
+ return eKeyHandled;
+
+ case KEY_DOWN:
+ if (m_selected_line + 1 < num_lines) {
+ m_selected_line++;
+ if (m_first_visible_line + num_visible_lines < m_selected_line)
+ m_first_visible_line++;
+ }
+ return eKeyHandled;
+
+ case '\r':
+ case '\n':
+ case KEY_ENTER:
+ // Set a breakpoint and run to the line using a one shot breakpoint
+ if (GetNumSourceLines() > 0) {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope() && exe_ctx.GetProcessRef().IsAlive()) {
+ BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
+ nullptr, // Don't limit the breakpoint to certain modules
+ m_file_sp->GetFileSpec(), // Source file
+ m_selected_line +
+ 1, // Source line number (m_selected_line is zero based)
+ 0, // No offset
+ eLazyBoolCalculate, // Check inlines using global setting
+ eLazyBoolCalculate, // Skip prologue using global setting,
+ false, // internal
+ false, // request_hardware
+ eLazyBoolCalculate); // move_to_nearest_code
+ // Make breakpoint one shot
+ bp_sp->GetOptions()->SetOneShot(true);
+ exe_ctx.GetProcessRef().Resume();
+ }
+ } else if (m_selected_line < GetNumDisassemblyLines()) {
+ const Instruction *inst = m_disassembly_sp->GetInstructionList()
+ .GetInstructionAtIndex(m_selected_line)
+ .get();
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasTargetScope()) {
+ Address addr = inst->GetAddress();
+ BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
+ addr, // lldb_private::Address
+ false, // internal
+ false); // request_hardware
+ // Make breakpoint one shot
+ bp_sp->GetOptions()->SetOneShot(true);
+ exe_ctx.GetProcessRef().Resume();
+ }
+ }
+ return eKeyHandled;
+
+ case 'b': // 'b' == toggle breakpoint on currently selected line
+ if (m_selected_line < GetNumSourceLines()) {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasTargetScope()) {
+ BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
+ nullptr, // Don't limit the breakpoint to certain modules
+ m_file_sp->GetFileSpec(), // Source file
+ m_selected_line +
+ 1, // Source line number (m_selected_line is zero based)
+ 0, // No offset
+ eLazyBoolCalculate, // Check inlines using global setting
+ eLazyBoolCalculate, // Skip prologue using global setting,
+ false, // internal
+ false, // request_hardware
+ eLazyBoolCalculate); // move_to_nearest_code
+ }
+ } else if (m_selected_line < GetNumDisassemblyLines()) {
+ const Instruction *inst = m_disassembly_sp->GetInstructionList()
+ .GetInstructionAtIndex(m_selected_line)
+ .get();
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasTargetScope()) {
+ Address addr = inst->GetAddress();
+ BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
+ addr, // lldb_private::Address
+ false, // internal
+ false); // request_hardware
+ }
+ }
+ return eKeyHandled;
+
+ case 'd': // 'd' == detach and let run
+ case 'D': // 'D' == detach and keep stopped
+ {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope())
+ exe_ctx.GetProcessRef().Detach(c == 'D');
+ }
+ return eKeyHandled;
+
+ case 'k':
+ // 'k' == kill
+ {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope())
+ exe_ctx.GetProcessRef().Destroy(false);
+ }
+ return eKeyHandled;
+
+ case 'c':
+ // 'c' == continue
+ {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasProcessScope())
+ exe_ctx.GetProcessRef().Resume();
+ }
+ return eKeyHandled;
+
+ case 'o':
+ // 'o' == step out
+ {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasThreadScope() &&
+ StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
+ exe_ctx.GetThreadRef().StepOut();
+ }
+ }
+ return eKeyHandled;
+
+ case 'n': // 'n' == step over
+ case 'N': // 'N' == step over instruction
+ {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasThreadScope() &&
+ StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
+ bool source_step = (c == 'n');
+ exe_ctx.GetThreadRef().StepOver(source_step);
+ }
+ }
+ return eKeyHandled;
+
+ case 's': // 's' == step into
+ case 'S': // 'S' == step into instruction
+ {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasThreadScope() &&
+ StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
+ bool source_step = (c == 's');
+ exe_ctx.GetThreadRef().StepIn(source_step);
+ }
+ }
+ return eKeyHandled;
+
+ case 'h':
+ window.CreateHelpSubwindow();
+ return eKeyHandled;
- default:
- break;
- }
- return eKeyNotHandled;
+ default:
+ break;
}
+ return eKeyNotHandled;
+ }
protected:
- typedef std::set<uint32_t> BreakpointLines;
- typedef std::set<lldb::addr_t> BreakpointAddrs;
+ typedef std::set<uint32_t> BreakpointLines;
+ typedef std::set<lldb::addr_t> BreakpointAddrs;
- Debugger &m_debugger;
- SymbolContext m_sc;
- SourceManager::FileSP m_file_sp;
- SymbolContextScope *m_disassembly_scope;
- lldb::DisassemblerSP m_disassembly_sp;
- AddressRange m_disassembly_range;
- StreamString m_title;
- lldb::user_id_t m_tid;
- char m_line_format[8];
- int m_line_width;
- uint32_t m_selected_line; // The selected line
- uint32_t m_pc_line; // The line with the PC
- uint32_t m_stop_id;
- uint32_t m_frame_idx;
- int m_first_visible_line;
- int m_min_x;
- int m_min_y;
- int m_max_x;
- int m_max_y;
+ Debugger &m_debugger;
+ SymbolContext m_sc;
+ SourceManager::FileSP m_file_sp;
+ SymbolContextScope *m_disassembly_scope;
+ lldb::DisassemblerSP m_disassembly_sp;
+ AddressRange m_disassembly_range;
+ StreamString m_title;
+ lldb::user_id_t m_tid;
+ char m_line_format[8];
+ int m_line_width;
+ uint32_t m_selected_line; // The selected line
+ uint32_t m_pc_line; // The line with the PC
+ uint32_t m_stop_id;
+ uint32_t m_frame_idx;
+ int m_first_visible_line;
+ int m_min_x;
+ int m_min_y;
+ int m_max_x;
+ int m_max_y;
};
-DisplayOptions ValueObjectListDelegate::g_options = { true };
-
-IOHandlerCursesGUI::IOHandlerCursesGUI (Debugger &debugger) :
- IOHandler (debugger, IOHandler::Type::Curses)
-{
-}
+DisplayOptions ValueObjectListDelegate::g_options = {true};
-void
-IOHandlerCursesGUI::Activate ()
-{
- IOHandler::Activate();
- if (!m_app_ap)
- {
- m_app_ap.reset (new Application (GetInputFILE(), GetOutputFILE()));
+IOHandlerCursesGUI::IOHandlerCursesGUI(Debugger &debugger)
+ : IOHandler(debugger, IOHandler::Type::Curses) {}
- // This is both a window and a menu delegate
- std::shared_ptr<ApplicationDelegate> app_delegate_sp(new ApplicationDelegate(*m_app_ap, m_debugger));
-
- MenuDelegateSP app_menu_delegate_sp = std::static_pointer_cast<MenuDelegate>(app_delegate_sp);
- MenuSP lldb_menu_sp(new Menu("LLDB" , "F1", KEY_F(1), ApplicationDelegate::eMenuID_LLDB));
- MenuSP exit_menuitem_sp(new Menu("Exit", nullptr, 'x', ApplicationDelegate::eMenuID_LLDBExit));
- exit_menuitem_sp->SetCannedResult(MenuActionResult::Quit);
- lldb_menu_sp->AddSubmenu (MenuSP (new Menu("About LLDB", nullptr, 'a', ApplicationDelegate::eMenuID_LLDBAbout)));
- lldb_menu_sp->AddSubmenu (MenuSP (new Menu(Menu::Type::Separator)));
- lldb_menu_sp->AddSubmenu (exit_menuitem_sp);
-
- MenuSP target_menu_sp(new Menu("Target" ,"F2", KEY_F(2), ApplicationDelegate::eMenuID_Target));
- target_menu_sp->AddSubmenu (MenuSP (new Menu("Create", nullptr, 'c', ApplicationDelegate::eMenuID_TargetCreate)));
- target_menu_sp->AddSubmenu (MenuSP (new Menu("Delete", nullptr, 'd', ApplicationDelegate::eMenuID_TargetDelete)));
-
- MenuSP process_menu_sp(new Menu("Process", "F3", KEY_F(3), ApplicationDelegate::eMenuID_Process));
- process_menu_sp->AddSubmenu (MenuSP (new Menu("Attach" , nullptr, 'a', ApplicationDelegate::eMenuID_ProcessAttach)));
- process_menu_sp->AddSubmenu (MenuSP (new Menu("Detach" , nullptr, 'd', ApplicationDelegate::eMenuID_ProcessDetach)));
- process_menu_sp->AddSubmenu (MenuSP (new Menu("Launch" , nullptr, 'l', ApplicationDelegate::eMenuID_ProcessLaunch)));
- process_menu_sp->AddSubmenu (MenuSP (new Menu(Menu::Type::Separator)));
- process_menu_sp->AddSubmenu (MenuSP (new Menu("Continue", nullptr, 'c', ApplicationDelegate::eMenuID_ProcessContinue)));
- process_menu_sp->AddSubmenu (MenuSP (new Menu("Halt" , nullptr, 'h', ApplicationDelegate::eMenuID_ProcessHalt)));
- process_menu_sp->AddSubmenu (MenuSP (new Menu("Kill" , nullptr, 'k', ApplicationDelegate::eMenuID_ProcessKill)));
-
- MenuSP thread_menu_sp(new Menu("Thread", "F4", KEY_F(4), ApplicationDelegate::eMenuID_Thread));
- thread_menu_sp->AddSubmenu (MenuSP (new Menu("Step In" , nullptr, 'i', ApplicationDelegate::eMenuID_ThreadStepIn)));
- thread_menu_sp->AddSubmenu (MenuSP (new Menu("Step Over", nullptr, 'v', ApplicationDelegate::eMenuID_ThreadStepOver)));
- thread_menu_sp->AddSubmenu (MenuSP (new Menu("Step Out" , nullptr, 'o', ApplicationDelegate::eMenuID_ThreadStepOut)));
-
- MenuSP view_menu_sp(new Menu("View", "F5", KEY_F(5), ApplicationDelegate::eMenuID_View));
- view_menu_sp->AddSubmenu (MenuSP (new Menu("Backtrace", nullptr, 'b', ApplicationDelegate::eMenuID_ViewBacktrace)));
- view_menu_sp->AddSubmenu (MenuSP (new Menu("Registers", nullptr, 'r', ApplicationDelegate::eMenuID_ViewRegisters)));
- view_menu_sp->AddSubmenu (MenuSP (new Menu("Source" , nullptr, 's', ApplicationDelegate::eMenuID_ViewSource)));
- view_menu_sp->AddSubmenu (MenuSP (new Menu("Variables", nullptr, 'v', ApplicationDelegate::eMenuID_ViewVariables)));
-
- MenuSP help_menu_sp(new Menu("Help", "F6", KEY_F(6), ApplicationDelegate::eMenuID_Help));
- help_menu_sp->AddSubmenu (MenuSP (new Menu("GUI Help", nullptr, 'g', ApplicationDelegate::eMenuID_HelpGUIHelp)));
-
- m_app_ap->Initialize();
- WindowSP &main_window_sp = m_app_ap->GetMainWindow();
-
- MenuSP menubar_sp(new Menu(Menu::Type::Bar));
- menubar_sp->AddSubmenu (lldb_menu_sp);
- menubar_sp->AddSubmenu (target_menu_sp);
- menubar_sp->AddSubmenu (process_menu_sp);
- menubar_sp->AddSubmenu (thread_menu_sp);
- menubar_sp->AddSubmenu (view_menu_sp);
- menubar_sp->AddSubmenu (help_menu_sp);
- menubar_sp->SetDelegate(app_menu_delegate_sp);
-
- Rect content_bounds = main_window_sp->GetFrame();
- Rect menubar_bounds = content_bounds.MakeMenuBar();
- Rect status_bounds = content_bounds.MakeStatusBar();
- Rect source_bounds;
- Rect variables_bounds;
- Rect threads_bounds;
- Rect source_variables_bounds;
- content_bounds.VerticalSplitPercentage(0.80, source_variables_bounds, threads_bounds);
- source_variables_bounds.HorizontalSplitPercentage(0.70, source_bounds, variables_bounds);
-
- WindowSP menubar_window_sp = main_window_sp->CreateSubWindow("Menubar", menubar_bounds, false);
- // Let the menubar get keys if the active window doesn't handle the
- // keys that are typed so it can respond to menubar key presses.
- menubar_window_sp->SetCanBeActive(false); // Don't let the menubar become the active window
- menubar_window_sp->SetDelegate(menubar_sp);
-
- WindowSP source_window_sp (main_window_sp->CreateSubWindow("Source",
- source_bounds,
- true));
- WindowSP variables_window_sp (main_window_sp->CreateSubWindow("Variables",
- variables_bounds,
- false));
- WindowSP threads_window_sp (main_window_sp->CreateSubWindow("Threads",
- threads_bounds,
- false));
- WindowSP status_window_sp (main_window_sp->CreateSubWindow("Status",
- status_bounds,
- false));
- status_window_sp->SetCanBeActive(false); // Don't let the status bar become the active window
- main_window_sp->SetDelegate (std::static_pointer_cast<WindowDelegate>(app_delegate_sp));
- source_window_sp->SetDelegate (WindowDelegateSP(new SourceFileWindowDelegate(m_debugger)));
- variables_window_sp->SetDelegate (WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger)));
- TreeDelegateSP thread_delegate_sp (new ThreadsTreeDelegate(m_debugger));
- threads_window_sp->SetDelegate (WindowDelegateSP(new TreeWindowDelegate(m_debugger, thread_delegate_sp)));
- status_window_sp->SetDelegate (WindowDelegateSP(new StatusBarWindowDelegate(m_debugger)));
-
- // Show the main help window once the first time the curses GUI is launched
- static bool g_showed_help = false;
- if (!g_showed_help)
- {
- g_showed_help = true;
- main_window_sp->CreateHelpSubwindow();
- }
-
- init_pair (1, COLOR_WHITE , COLOR_BLUE );
- init_pair (2, COLOR_BLACK , COLOR_WHITE );
- init_pair (3, COLOR_MAGENTA , COLOR_WHITE );
- init_pair (4, COLOR_MAGENTA , COLOR_BLACK );
- init_pair (5, COLOR_RED , COLOR_BLACK );
- }
-}
-
-void
-IOHandlerCursesGUI::Deactivate ()
-{
- m_app_ap->Terminate();
-}
-
-void
-IOHandlerCursesGUI::Run ()
-{
- m_app_ap->Run(m_debugger);
- SetIsDone(true);
+void IOHandlerCursesGUI::Activate() {
+ IOHandler::Activate();
+ if (!m_app_ap) {
+ m_app_ap.reset(new Application(GetInputFILE(), GetOutputFILE()));
+
+ // This is both a window and a menu delegate
+ std::shared_ptr<ApplicationDelegate> app_delegate_sp(
+ new ApplicationDelegate(*m_app_ap, m_debugger));
+
+ MenuDelegateSP app_menu_delegate_sp =
+ std::static_pointer_cast<MenuDelegate>(app_delegate_sp);
+ MenuSP lldb_menu_sp(
+ new Menu("LLDB", "F1", KEY_F(1), ApplicationDelegate::eMenuID_LLDB));
+ MenuSP exit_menuitem_sp(
+ new Menu("Exit", nullptr, 'x', ApplicationDelegate::eMenuID_LLDBExit));
+ exit_menuitem_sp->SetCannedResult(MenuActionResult::Quit);
+ lldb_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "About LLDB", nullptr, 'a', ApplicationDelegate::eMenuID_LLDBAbout)));
+ lldb_menu_sp->AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
+ lldb_menu_sp->AddSubmenu(exit_menuitem_sp);
+
+ MenuSP target_menu_sp(new Menu("Target", "F2", KEY_F(2),
+ ApplicationDelegate::eMenuID_Target));
+ target_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Create", nullptr, 'c', ApplicationDelegate::eMenuID_TargetCreate)));
+ target_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Delete", nullptr, 'd', ApplicationDelegate::eMenuID_TargetDelete)));
+
+ MenuSP process_menu_sp(new Menu("Process", "F3", KEY_F(3),
+ ApplicationDelegate::eMenuID_Process));
+ process_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Attach", nullptr, 'a', ApplicationDelegate::eMenuID_ProcessAttach)));
+ process_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Detach", nullptr, 'd', ApplicationDelegate::eMenuID_ProcessDetach)));
+ process_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Launch", nullptr, 'l', ApplicationDelegate::eMenuID_ProcessLaunch)));
+ process_menu_sp->AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
+ process_menu_sp->AddSubmenu(
+ MenuSP(new Menu("Continue", nullptr, 'c',
+ ApplicationDelegate::eMenuID_ProcessContinue)));
+ process_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Halt", nullptr, 'h', ApplicationDelegate::eMenuID_ProcessHalt)));
+ process_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Kill", nullptr, 'k', ApplicationDelegate::eMenuID_ProcessKill)));
+
+ MenuSP thread_menu_sp(new Menu("Thread", "F4", KEY_F(4),
+ ApplicationDelegate::eMenuID_Thread));
+ thread_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Step In", nullptr, 'i', ApplicationDelegate::eMenuID_ThreadStepIn)));
+ thread_menu_sp->AddSubmenu(
+ MenuSP(new Menu("Step Over", nullptr, 'v',
+ ApplicationDelegate::eMenuID_ThreadStepOver)));
+ thread_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Step Out", nullptr, 'o', ApplicationDelegate::eMenuID_ThreadStepOut)));
+
+ MenuSP view_menu_sp(
+ new Menu("View", "F5", KEY_F(5), ApplicationDelegate::eMenuID_View));
+ view_menu_sp->AddSubmenu(
+ MenuSP(new Menu("Backtrace", nullptr, 'b',
+ ApplicationDelegate::eMenuID_ViewBacktrace)));
+ view_menu_sp->AddSubmenu(
+ MenuSP(new Menu("Registers", nullptr, 'r',
+ ApplicationDelegate::eMenuID_ViewRegisters)));
+ view_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "Source", nullptr, 's', ApplicationDelegate::eMenuID_ViewSource)));
+ view_menu_sp->AddSubmenu(
+ MenuSP(new Menu("Variables", nullptr, 'v',
+ ApplicationDelegate::eMenuID_ViewVariables)));
+
+ MenuSP help_menu_sp(
+ new Menu("Help", "F6", KEY_F(6), ApplicationDelegate::eMenuID_Help));
+ help_menu_sp->AddSubmenu(MenuSP(new Menu(
+ "GUI Help", nullptr, 'g', ApplicationDelegate::eMenuID_HelpGUIHelp)));
+
+ m_app_ap->Initialize();
+ WindowSP &main_window_sp = m_app_ap->GetMainWindow();
+
+ MenuSP menubar_sp(new Menu(Menu::Type::Bar));
+ menubar_sp->AddSubmenu(lldb_menu_sp);
+ menubar_sp->AddSubmenu(target_menu_sp);
+ menubar_sp->AddSubmenu(process_menu_sp);
+ menubar_sp->AddSubmenu(thread_menu_sp);
+ menubar_sp->AddSubmenu(view_menu_sp);
+ menubar_sp->AddSubmenu(help_menu_sp);
+ menubar_sp->SetDelegate(app_menu_delegate_sp);
+
+ Rect content_bounds = main_window_sp->GetFrame();
+ Rect menubar_bounds = content_bounds.MakeMenuBar();
+ Rect status_bounds = content_bounds.MakeStatusBar();
+ Rect source_bounds;
+ Rect variables_bounds;
+ Rect threads_bounds;
+ Rect source_variables_bounds;
+ content_bounds.VerticalSplitPercentage(0.80, source_variables_bounds,
+ threads_bounds);
+ source_variables_bounds.HorizontalSplitPercentage(0.70, source_bounds,
+ variables_bounds);
+
+ WindowSP menubar_window_sp =
+ main_window_sp->CreateSubWindow("Menubar", menubar_bounds, false);
+ // Let the menubar get keys if the active window doesn't handle the
+ // keys that are typed so it can respond to menubar key presses.
+ menubar_window_sp->SetCanBeActive(
+ false); // Don't let the menubar become the active window
+ menubar_window_sp->SetDelegate(menubar_sp);
+
+ WindowSP source_window_sp(
+ main_window_sp->CreateSubWindow("Source", source_bounds, true));
+ WindowSP variables_window_sp(
+ main_window_sp->CreateSubWindow("Variables", variables_bounds, false));
+ WindowSP threads_window_sp(
+ main_window_sp->CreateSubWindow("Threads", threads_bounds, false));
+ WindowSP status_window_sp(
+ main_window_sp->CreateSubWindow("Status", status_bounds, false));
+ status_window_sp->SetCanBeActive(
+ false); // Don't let the status bar become the active window
+ main_window_sp->SetDelegate(
+ std::static_pointer_cast<WindowDelegate>(app_delegate_sp));
+ source_window_sp->SetDelegate(
+ WindowDelegateSP(new SourceFileWindowDelegate(m_debugger)));
+ variables_window_sp->SetDelegate(
+ WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger)));
+ TreeDelegateSP thread_delegate_sp(new ThreadsTreeDelegate(m_debugger));
+ threads_window_sp->SetDelegate(WindowDelegateSP(
+ new TreeWindowDelegate(m_debugger, thread_delegate_sp)));
+ status_window_sp->SetDelegate(
+ WindowDelegateSP(new StatusBarWindowDelegate(m_debugger)));
+
+ // Show the main help window once the first time the curses GUI is launched
+ static bool g_showed_help = false;
+ if (!g_showed_help) {
+ g_showed_help = true;
+ main_window_sp->CreateHelpSubwindow();
+ }
+
+ init_pair(1, COLOR_WHITE, COLOR_BLUE);
+ init_pair(2, COLOR_BLACK, COLOR_WHITE);
+ init_pair(3, COLOR_MAGENTA, COLOR_WHITE);
+ init_pair(4, COLOR_MAGENTA, COLOR_BLACK);
+ init_pair(5, COLOR_RED, COLOR_BLACK);
+ }
+}
+
+void IOHandlerCursesGUI::Deactivate() { m_app_ap->Terminate(); }
+
+void IOHandlerCursesGUI::Run() {
+ m_app_ap->Run(m_debugger);
+ SetIsDone(true);
}
IOHandlerCursesGUI::~IOHandlerCursesGUI() = default;
-void
-IOHandlerCursesGUI::Cancel ()
-{
-}
+void IOHandlerCursesGUI::Cancel() {}
-bool
-IOHandlerCursesGUI::Interrupt ()
-{
- return false;
-}
+bool IOHandlerCursesGUI::Interrupt() { return false; }
-void
-IOHandlerCursesGUI::GotEOF()
-{
-}
+void IOHandlerCursesGUI::GotEOF() {}
#endif // LLDB_DISABLE_CURSES
Modified: lldb/trunk/source/Core/Listener.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Listener.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Core/Listener.cpp (original)
+++ lldb/trunk/source/Core/Listener.cpp Tue Sep 6 15:57:50 2016
@@ -16,516 +16,489 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/Event.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
-#include "lldb/Core/Event.h"
using namespace lldb;
using namespace lldb_private;
-namespace
-{
- class BroadcasterManagerWPMatcher
- {
- public:
- BroadcasterManagerWPMatcher (BroadcasterManagerSP manager_sp) : m_manager_sp(manager_sp) {}
- bool operator() (const BroadcasterManagerWP input_wp) const
- {
- BroadcasterManagerSP input_sp = input_wp.lock();
- return (input_sp && input_sp == m_manager_sp);
- }
+namespace {
+class BroadcasterManagerWPMatcher {
+public:
+ BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp)
+ : m_manager_sp(manager_sp) {}
+ bool operator()(const BroadcasterManagerWP input_wp) const {
+ BroadcasterManagerSP input_sp = input_wp.lock();
+ return (input_sp && input_sp == m_manager_sp);
+ }
- BroadcasterManagerSP m_manager_sp;
- };
+ BroadcasterManagerSP m_manager_sp;
+};
} // anonymous namespace
Listener::Listener(const char *name)
- : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(), m_events_mutex()
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
- if (log != nullptr)
- log->Printf ("%p Listener::Listener('%s')",
- static_cast<void*>(this), m_name.c_str());
-}
-
-Listener::~Listener()
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
-
- Clear();
-
- if (log)
- log->Printf("%p Listener::%s('%s')", static_cast<void *>(this), __FUNCTION__, m_name.c_str());
-}
-
-void
-Listener::Clear()
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
- std::lock_guard<std::recursive_mutex> broadcasters_guard(m_broadcasters_mutex);
- broadcaster_collection::iterator pos, end = m_broadcasters.end();
- for (pos = m_broadcasters.begin(); pos != end; ++pos)
- {
- Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock());
- if (broadcaster_sp)
- broadcaster_sp->RemoveListener (this, pos->second.event_mask);
+ : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(),
+ m_events_mutex() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
+ if (log != nullptr)
+ log->Printf("%p Listener::Listener('%s')", static_cast<void *>(this),
+ m_name.c_str());
+}
+
+Listener::~Listener() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
+
+ Clear();
+
+ if (log)
+ log->Printf("%p Listener::%s('%s')", static_cast<void *>(this),
+ __FUNCTION__, m_name.c_str());
+}
+
+void Listener::Clear() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
+ std::lock_guard<std::recursive_mutex> broadcasters_guard(
+ m_broadcasters_mutex);
+ broadcaster_collection::iterator pos, end = m_broadcasters.end();
+ for (pos = m_broadcasters.begin(); pos != end; ++pos) {
+ Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock());
+ if (broadcaster_sp)
+ broadcaster_sp->RemoveListener(this, pos->second.event_mask);
+ }
+ m_broadcasters.clear();
+
+ std::lock_guard<std::mutex> events_guard(m_events_mutex);
+ m_events.clear();
+ size_t num_managers = m_broadcaster_managers.size();
+
+ for (size_t i = 0; i < num_managers; i++) {
+ BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock());
+ if (manager_sp)
+ manager_sp->RemoveListener(this);
+ }
+
+ if (log)
+ log->Printf("%p Listener::%s('%s')", static_cast<void *>(this),
+ __FUNCTION__, m_name.c_str());
+}
+
+uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster,
+ uint32_t event_mask) {
+ if (broadcaster) {
+ // Scope for "locker"
+ // Tell the broadcaster to add this object as a listener
+ {
+ std::lock_guard<std::recursive_mutex> broadcasters_guard(
+ m_broadcasters_mutex);
+ Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
+ m_broadcasters.insert(
+ std::make_pair(impl_wp, BroadcasterInfo(event_mask)));
}
- m_broadcasters.clear();
- std::lock_guard<std::mutex> events_guard(m_events_mutex);
- m_events.clear();
- size_t num_managers = m_broadcaster_managers.size();
-
- for (size_t i = 0; i < num_managers; i++)
- {
- BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock());
- if (manager_sp)
- manager_sp->RemoveListener(this);
- }
-
- if (log)
- log->Printf("%p Listener::%s('%s')", static_cast<void *>(this), __FUNCTION__, m_name.c_str());
-}
-
-uint32_t
-Listener::StartListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask)
-{
- if (broadcaster)
- {
- // Scope for "locker"
- // Tell the broadcaster to add this object as a listener
- {
- std::lock_guard<std::recursive_mutex> broadcasters_guard(m_broadcasters_mutex);
- Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
- m_broadcasters.insert(std::make_pair(impl_wp, BroadcasterInfo(event_mask)));
- }
-
- uint32_t acquired_mask = broadcaster->AddListener (this->shared_from_this(), event_mask);
+ uint32_t acquired_mask =
+ broadcaster->AddListener(this->shared_from_this(), event_mask);
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));
- if (log != nullptr)
- log->Printf ("%p Listener::StartListeningForEvents (broadcaster = %p, mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s",
- static_cast<void*>(this),
- static_cast<void*>(broadcaster), event_mask,
- acquired_mask, m_name.c_str());
-
- return acquired_mask;
- }
- return 0;
-}
-
-uint32_t
-Listener::StartListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask, HandleBroadcastCallback callback, void *callback_user_data)
-{
- if (broadcaster)
- {
- // Scope for "locker"
- // Tell the broadcaster to add this object as a listener
- {
- std::lock_guard<std::recursive_mutex> broadcasters_guard(m_broadcasters_mutex);
- Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
- m_broadcasters.insert(std::make_pair(impl_wp,
- BroadcasterInfo(event_mask, callback, callback_user_data)));
- }
-
- uint32_t acquired_mask = broadcaster->AddListener (this->shared_from_this(), event_mask);
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));
- if (log != nullptr)
- {
- void **pointer = reinterpret_cast<void**>(&callback);
- log->Printf ("%p Listener::StartListeningForEvents (broadcaster = %p, mask = 0x%8.8x, callback = %p, user_data = %p) acquired_mask = 0x%8.8x for %s",
- static_cast<void*>(this),
- static_cast<void*>(broadcaster), event_mask, *pointer,
- static_cast<void*>(callback_user_data), acquired_mask,
- m_name.c_str());
- }
-
- return acquired_mask;
- }
- return 0;
-}
-
-bool
-Listener::StopListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask)
-{
- if (broadcaster)
- {
- // Scope for "locker"
- {
- std::lock_guard<std::recursive_mutex> broadcasters_guard(m_broadcasters_mutex);
- m_broadcasters.erase (broadcaster->GetBroadcasterImpl());
- }
- // Remove the broadcaster from our set of broadcasters
- return broadcaster->RemoveListener (this->shared_from_this(), event_mask);
- }
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
+ if (log != nullptr)
+ log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, "
+ "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s",
+ static_cast<void *>(this), static_cast<void *>(broadcaster),
+ event_mask, acquired_mask, m_name.c_str());
+
+ return acquired_mask;
+ }
+ return 0;
+}
+
+uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster,
+ uint32_t event_mask,
+ HandleBroadcastCallback callback,
+ void *callback_user_data) {
+ if (broadcaster) {
+ // Scope for "locker"
+ // Tell the broadcaster to add this object as a listener
+ {
+ std::lock_guard<std::recursive_mutex> broadcasters_guard(
+ m_broadcasters_mutex);
+ Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
+ m_broadcasters.insert(std::make_pair(
+ impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data)));
+ }
+
+ uint32_t acquired_mask =
+ broadcaster->AddListener(this->shared_from_this(), event_mask);
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
+ if (log != nullptr) {
+ void **pointer = reinterpret_cast<void **>(&callback);
+ log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, "
+ "mask = 0x%8.8x, callback = %p, user_data = %p) "
+ "acquired_mask = 0x%8.8x for %s",
+ static_cast<void *>(this), static_cast<void *>(broadcaster),
+ event_mask, *pointer, static_cast<void *>(callback_user_data),
+ acquired_mask, m_name.c_str());
+ }
+
+ return acquired_mask;
+ }
+ return 0;
+}
+
+bool Listener::StopListeningForEvents(Broadcaster *broadcaster,
+ uint32_t event_mask) {
+ if (broadcaster) {
+ // Scope for "locker"
+ {
+ std::lock_guard<std::recursive_mutex> broadcasters_guard(
+ m_broadcasters_mutex);
+ m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
+ }
+ // Remove the broadcaster from our set of broadcasters
+ return broadcaster->RemoveListener(this->shared_from_this(), event_mask);
+ }
- return false;
+ return false;
}
// Called when a Broadcaster is in its destructor. We need to remove all
// knowledge of this broadcaster and any events that it may have queued up
-void
-Listener::BroadcasterWillDestruct (Broadcaster *broadcaster)
-{
- // Scope for "broadcasters_locker"
- {
- std::lock_guard<std::recursive_mutex> broadcasters_guard(m_broadcasters_mutex);
- m_broadcasters.erase (broadcaster->GetBroadcasterImpl());
- }
-
- // Scope for "event_locker"
- {
- std::lock_guard<std::mutex> events_guard(m_events_mutex);
- // Remove all events for this broadcaster object.
- event_collection::iterator pos = m_events.begin();
- while (pos != m_events.end())
- {
- if ((*pos)->GetBroadcaster() == broadcaster)
- pos = m_events.erase(pos);
- else
- ++pos;
- }
- }
-}
-
-void
-Listener::BroadcasterManagerWillDestruct (BroadcasterManagerSP manager_sp)
-{
- // Just need to remove this broadcast manager from the list of managers:
- broadcaster_manager_collection::iterator iter, end_iter = m_broadcaster_managers.end();
- BroadcasterManagerWP manager_wp;
-
- BroadcasterManagerWPMatcher matcher(manager_sp);
- iter = std::find_if<broadcaster_manager_collection::iterator, BroadcasterManagerWPMatcher>(m_broadcaster_managers.begin(), end_iter, matcher);
- if (iter != end_iter)
- m_broadcaster_managers.erase (iter);
-}
-
-void
-Listener::AddEvent (EventSP &event_sp)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));
- if (log != nullptr)
- log->Printf ("%p Listener('%s')::AddEvent (event_sp = {%p})",
- static_cast<void*>(this), m_name.c_str(),
- static_cast<void*>(event_sp.get()));
+void Listener::BroadcasterWillDestruct(Broadcaster *broadcaster) {
+ // Scope for "broadcasters_locker"
+ {
+ std::lock_guard<std::recursive_mutex> broadcasters_guard(
+ m_broadcasters_mutex);
+ m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
+ }
- std::lock_guard<std::mutex> guard(m_events_mutex);
- m_events.push_back (event_sp);
- m_events_condition.notify_all();
+ // Scope for "event_locker"
+ {
+ std::lock_guard<std::mutex> events_guard(m_events_mutex);
+ // Remove all events for this broadcaster object.
+ event_collection::iterator pos = m_events.begin();
+ while (pos != m_events.end()) {
+ if ((*pos)->GetBroadcaster() == broadcaster)
+ pos = m_events.erase(pos);
+ else
+ ++pos;
+ }
+ }
+}
+
+void Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp) {
+ // Just need to remove this broadcast manager from the list of managers:
+ broadcaster_manager_collection::iterator iter,
+ end_iter = m_broadcaster_managers.end();
+ BroadcasterManagerWP manager_wp;
+
+ BroadcasterManagerWPMatcher matcher(manager_sp);
+ iter = std::find_if<broadcaster_manager_collection::iterator,
+ BroadcasterManagerWPMatcher>(
+ m_broadcaster_managers.begin(), end_iter, matcher);
+ if (iter != end_iter)
+ m_broadcaster_managers.erase(iter);
+}
+
+void Listener::AddEvent(EventSP &event_sp) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
+ if (log != nullptr)
+ log->Printf("%p Listener('%s')::AddEvent (event_sp = {%p})",
+ static_cast<void *>(this), m_name.c_str(),
+ static_cast<void *>(event_sp.get()));
+
+ std::lock_guard<std::mutex> guard(m_events_mutex);
+ m_events.push_back(event_sp);
+ m_events_condition.notify_all();
}
-class EventBroadcasterMatches
-{
+class EventBroadcasterMatches {
public:
- EventBroadcasterMatches (Broadcaster *broadcaster) :
- m_broadcaster (broadcaster)
- {
- }
+ EventBroadcasterMatches(Broadcaster *broadcaster)
+ : m_broadcaster(broadcaster) {}
- bool operator() (const EventSP &event_sp) const
- {
- return event_sp->BroadcasterIs(m_broadcaster);
- }
+ bool operator()(const EventSP &event_sp) const {
+ return event_sp->BroadcasterIs(m_broadcaster);
+ }
private:
- Broadcaster *m_broadcaster;
+ Broadcaster *m_broadcaster;
};
-class EventMatcher
-{
+class EventMatcher {
public:
- EventMatcher (Broadcaster *broadcaster, const ConstString *broadcaster_names, uint32_t num_broadcaster_names, uint32_t event_type_mask) :
- m_broadcaster (broadcaster),
- m_broadcaster_names (broadcaster_names),
- m_num_broadcaster_names (num_broadcaster_names),
- m_event_type_mask (event_type_mask)
- {
- }
-
- bool operator() (const EventSP &event_sp) const
- {
- if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster))
- return false;
-
- if (m_broadcaster_names)
- {
- bool found_source = false;
- const ConstString &event_broadcaster_name = event_sp->GetBroadcaster()->GetBroadcasterName();
- for (uint32_t i = 0; i < m_num_broadcaster_names; ++i)
- {
- if (m_broadcaster_names[i] == event_broadcaster_name)
- {
- found_source = true;
- break;
- }
- }
- if (!found_source)
- return false;
+ EventMatcher(Broadcaster *broadcaster, const ConstString *broadcaster_names,
+ uint32_t num_broadcaster_names, uint32_t event_type_mask)
+ : m_broadcaster(broadcaster), m_broadcaster_names(broadcaster_names),
+ m_num_broadcaster_names(num_broadcaster_names),
+ m_event_type_mask(event_type_mask) {}
+
+ bool operator()(const EventSP &event_sp) const {
+ if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster))
+ return false;
+
+ if (m_broadcaster_names) {
+ bool found_source = false;
+ const ConstString &event_broadcaster_name =
+ event_sp->GetBroadcaster()->GetBroadcasterName();
+ for (uint32_t i = 0; i < m_num_broadcaster_names; ++i) {
+ if (m_broadcaster_names[i] == event_broadcaster_name) {
+ found_source = true;
+ break;
}
-
- if (m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType())
- return true;
+ }
+ if (!found_source)
return false;
}
+ if (m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType())
+ return true;
+ return false;
+ }
+
private:
- Broadcaster *m_broadcaster;
- const ConstString *m_broadcaster_names;
- const uint32_t m_num_broadcaster_names;
- const uint32_t m_event_type_mask;
+ Broadcaster *m_broadcaster;
+ const ConstString *m_broadcaster_names;
+ const uint32_t m_num_broadcaster_names;
+ const uint32_t m_event_type_mask;
};
-bool
-Listener::FindNextEventInternal(std::unique_lock<std::mutex> &lock,
- Broadcaster *broadcaster, // nullptr for any broadcaster
- const ConstString *broadcaster_names, // nullptr for any event
- uint32_t num_broadcaster_names, uint32_t event_type_mask, EventSP &event_sp,
- bool remove)
-{
- // NOTE: callers of this function must lock m_events_mutex using a Mutex::Locker
- // and pass the locker as the first argument. m_events_mutex is no longer recursive.
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));
+bool Listener::FindNextEventInternal(
+ std::unique_lock<std::mutex> &lock,
+ Broadcaster *broadcaster, // nullptr for any broadcaster
+ const ConstString *broadcaster_names, // nullptr for any event
+ uint32_t num_broadcaster_names, uint32_t event_type_mask, EventSP &event_sp,
+ bool remove) {
+ // NOTE: callers of this function must lock m_events_mutex using a
+ // Mutex::Locker
+ // and pass the locker as the first argument. m_events_mutex is no longer
+ // recursive.
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
- if (m_events.empty())
- return false;
-
- Listener::event_collection::iterator pos = m_events.end();
+ if (m_events.empty())
+ return false;
- if (broadcaster == nullptr && broadcaster_names == nullptr && event_type_mask == 0)
- {
- pos = m_events.begin();
- }
- else
- {
- pos = std::find_if (m_events.begin(), m_events.end(), EventMatcher (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask));
- }
+ Listener::event_collection::iterator pos = m_events.end();
- if (pos != m_events.end())
- {
- event_sp = *pos;
+ if (broadcaster == nullptr && broadcaster_names == nullptr &&
+ event_type_mask == 0) {
+ pos = m_events.begin();
+ } else {
+ pos = std::find_if(m_events.begin(), m_events.end(),
+ EventMatcher(broadcaster, broadcaster_names,
+ num_broadcaster_names, event_type_mask));
+ }
- if (log != nullptr)
- log->Printf ("%p '%s' Listener::FindNextEventInternal(broadcaster=%p, broadcaster_names=%p[%u], event_type_mask=0x%8.8x, remove=%i) event %p",
- static_cast<void*>(this), GetName(),
- static_cast<void*>(broadcaster),
- static_cast<const void*>(broadcaster_names),
- num_broadcaster_names, event_type_mask, remove,
- static_cast<void*>(event_sp.get()));
-
- if (remove)
- {
- m_events.erase(pos);
- // Unlock the event queue here. We've removed this event and are about to return
- // it so it should be okay to get the next event off the queue here - and it might
- // be useful to do that in the "DoOnRemoval".
- lock.unlock();
- event_sp->DoOnRemoval();
- }
- return true;
- }
+ if (pos != m_events.end()) {
+ event_sp = *pos;
- event_sp.reset();
- return false;
+ if (log != nullptr)
+ log->Printf("%p '%s' Listener::FindNextEventInternal(broadcaster=%p, "
+ "broadcaster_names=%p[%u], event_type_mask=0x%8.8x, "
+ "remove=%i) event %p",
+ static_cast<void *>(this), GetName(),
+ static_cast<void *>(broadcaster),
+ static_cast<const void *>(broadcaster_names),
+ num_broadcaster_names, event_type_mask, remove,
+ static_cast<void *>(event_sp.get()));
+
+ if (remove) {
+ m_events.erase(pos);
+ // Unlock the event queue here. We've removed this event and are about to
+ // return
+ // it so it should be okay to get the next event off the queue here - and
+ // it might
+ // be useful to do that in the "DoOnRemoval".
+ lock.unlock();
+ event_sp->DoOnRemoval();
+ }
+ return true;
+ }
+
+ event_sp.reset();
+ return false;
+}
+
+Event *Listener::PeekAtNextEvent() {
+ std::unique_lock<std::mutex> guard(m_events_mutex);
+ EventSP event_sp;
+ if (FindNextEventInternal(guard, nullptr, nullptr, 0, 0, event_sp, false))
+ return event_sp.get();
+ return nullptr;
+}
+
+Event *Listener::PeekAtNextEventForBroadcaster(Broadcaster *broadcaster) {
+ std::unique_lock<std::mutex> guard(m_events_mutex);
+ EventSP event_sp;
+ if (FindNextEventInternal(guard, broadcaster, nullptr, 0, 0, event_sp, false))
+ return event_sp.get();
+ return nullptr;
}
Event *
-Listener::PeekAtNextEvent ()
-{
- std::unique_lock<std::mutex> guard(m_events_mutex);
- EventSP event_sp;
- if (FindNextEventInternal(guard, nullptr, nullptr, 0, 0, event_sp, false))
- return event_sp.get();
- return nullptr;
-}
+Listener::PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster,
+ uint32_t event_type_mask) {
+ std::unique_lock<std::mutex> guard(m_events_mutex);
+ EventSP event_sp;
+ if (FindNextEventInternal(guard, broadcaster, nullptr, 0, event_type_mask,
+ event_sp, false))
+ return event_sp.get();
+ return nullptr;
+}
+
+bool Listener::GetNextEventInternal(
+ Broadcaster *broadcaster, // nullptr for any broadcaster
+ const ConstString *broadcaster_names, // nullptr for any event
+ uint32_t num_broadcaster_names, uint32_t event_type_mask,
+ EventSP &event_sp) {
+ std::unique_lock<std::mutex> guard(m_events_mutex);
+ return FindNextEventInternal(guard, broadcaster, broadcaster_names,
+ num_broadcaster_names, event_type_mask, event_sp,
+ true);
+}
+
+bool Listener::GetNextEvent(EventSP &event_sp) {
+ return GetNextEventInternal(nullptr, nullptr, 0, 0, event_sp);
+}
+
+bool Listener::GetNextEventForBroadcaster(Broadcaster *broadcaster,
+ EventSP &event_sp) {
+ return GetNextEventInternal(broadcaster, nullptr, 0, 0, event_sp);
+}
+
+bool Listener::GetNextEventForBroadcasterWithType(Broadcaster *broadcaster,
+ uint32_t event_type_mask,
+ EventSP &event_sp) {
+ return GetNextEventInternal(broadcaster, nullptr, 0, event_type_mask,
+ event_sp);
+}
+
+bool Listener::WaitForEventsInternal(
+ const std::chrono::microseconds &timeout,
+ Broadcaster *broadcaster, // nullptr for any broadcaster
+ const ConstString *broadcaster_names, // nullptr for any event
+ uint32_t num_broadcaster_names, uint32_t event_type_mask,
+ EventSP &event_sp) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
+ if (log != nullptr)
+ log->Printf("%p Listener::WaitForEventsInternal (timeout = %llu us) for %s",
+ static_cast<void *>(this),
+ static_cast<unsigned long long>(timeout.count()),
+ m_name.c_str());
+
+ std::unique_lock<std::mutex> lock(m_events_mutex);
+
+ while (true) {
+ if (FindNextEventInternal(lock, broadcaster, broadcaster_names,
+ num_broadcaster_names, event_type_mask, event_sp,
+ true)) {
+ return true;
+ } else {
+ std::cv_status result = std::cv_status::no_timeout;
+ if (timeout == std::chrono::microseconds(0))
+ m_events_condition.wait(lock);
+ else
+ result = m_events_condition.wait_for(lock, timeout);
+
+ if (result == std::cv_status::timeout) {
+ log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS);
+ if (log)
+ log->Printf("%p Listener::WaitForEventsInternal() timed out for %s",
+ static_cast<void *>(this), m_name.c_str());
+ return false;
+ } else if (result != std::cv_status::no_timeout) {
+ log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS);
+ if (log)
+ log->Printf(
+ "%p Listener::WaitForEventsInternal() unknown error for %s",
+ static_cast<void *>(this), m_name.c_str());
+ return false;
+ }
+ }
+ }
-Event *
-Listener::PeekAtNextEventForBroadcaster (Broadcaster *broadcaster)
-{
- std::unique_lock<std::mutex> guard(m_events_mutex);
- EventSP event_sp;
- if (FindNextEventInternal(guard, broadcaster, nullptr, 0, 0, event_sp, false))
- return event_sp.get();
- return nullptr;
+ return false;
}
-Event *
-Listener::PeekAtNextEventForBroadcasterWithType (Broadcaster *broadcaster, uint32_t event_type_mask)
-{
- std::unique_lock<std::mutex> guard(m_events_mutex);
- EventSP event_sp;
- if (FindNextEventInternal(guard, broadcaster, nullptr, 0, event_type_mask, event_sp, false))
- return event_sp.get();
- return nullptr;
-}
-
-bool
-Listener::GetNextEventInternal(Broadcaster *broadcaster, // nullptr for any broadcaster
- const ConstString *broadcaster_names, // nullptr for any event
- uint32_t num_broadcaster_names,
- uint32_t event_type_mask,
- EventSP &event_sp)
-{
- std::unique_lock<std::mutex> guard(m_events_mutex);
- return FindNextEventInternal(guard, broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask,
- event_sp, true);
-}
-
-bool
-Listener::GetNextEvent (EventSP &event_sp)
-{
- return GetNextEventInternal(nullptr, nullptr, 0, 0, event_sp);
-}
-
-bool
-Listener::GetNextEventForBroadcaster (Broadcaster *broadcaster, EventSP &event_sp)
-{
- return GetNextEventInternal(broadcaster, nullptr, 0, 0, event_sp);
-}
-
-bool
-Listener::GetNextEventForBroadcasterWithType (Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp)
-{
- return GetNextEventInternal(broadcaster, nullptr, 0, event_type_mask, event_sp);
-}
-
-bool
-Listener::WaitForEventsInternal(const std::chrono::microseconds &timeout,
- Broadcaster *broadcaster, // nullptr for any broadcaster
- const ConstString *broadcaster_names, // nullptr for any event
- uint32_t num_broadcaster_names, uint32_t event_type_mask, EventSP &event_sp)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));
- if (log != nullptr)
- log->Printf("%p Listener::WaitForEventsInternal (timeout = %llu us) for %s", static_cast<void *>(this),
- static_cast<unsigned long long>(timeout.count()), m_name.c_str());
-
- std::unique_lock<std::mutex> lock(m_events_mutex);
+bool Listener::WaitForEventForBroadcasterWithType(
+ const std::chrono::microseconds &timeout, Broadcaster *broadcaster,
+ uint32_t event_type_mask, EventSP &event_sp) {
+ return WaitForEventsInternal(timeout, broadcaster, nullptr, 0,
+ event_type_mask, event_sp);
+}
- while (true)
- {
- if (FindNextEventInternal (lock, broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, true))
- {
- return true;
- }
- else
- {
- std::cv_status result = std::cv_status::no_timeout;
- if (timeout == std::chrono::microseconds(0))
- m_events_condition.wait(lock);
- else
- result = m_events_condition.wait_for(lock, timeout);
-
- if (result == std::cv_status::timeout)
- {
- log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS);
- if (log)
- log->Printf("%p Listener::WaitForEventsInternal() timed out for %s", static_cast<void *>(this),
- m_name.c_str());
- return false;
- }
- else if (result != std::cv_status::no_timeout)
- {
- log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS);
- if (log)
- log->Printf("%p Listener::WaitForEventsInternal() unknown error for %s", static_cast<void *>(this),
- m_name.c_str());
- return false;
- }
- }
- }
+bool Listener::WaitForEventForBroadcaster(
+ const std::chrono::microseconds &timeout, Broadcaster *broadcaster,
+ EventSP &event_sp) {
+ return WaitForEventsInternal(timeout, broadcaster, nullptr, 0, 0, event_sp);
+}
- return false;
+bool Listener::WaitForEvent(const std::chrono::microseconds &timeout,
+ EventSP &event_sp) {
+ return WaitForEventsInternal(timeout, nullptr, nullptr, 0, 0, event_sp);
}
-bool
-Listener::WaitForEventForBroadcasterWithType(const std::chrono::microseconds &timeout, Broadcaster *broadcaster,
- uint32_t event_type_mask, EventSP &event_sp)
-{
- return WaitForEventsInternal(timeout, broadcaster, nullptr, 0, event_type_mask, event_sp);
-}
-
-bool
-Listener::WaitForEventForBroadcaster(const std::chrono::microseconds &timeout, Broadcaster *broadcaster,
- EventSP &event_sp)
-{
- return WaitForEventsInternal(timeout, broadcaster, nullptr, 0, 0, event_sp);
-}
-
-bool
-Listener::WaitForEvent(const std::chrono::microseconds &timeout, EventSP &event_sp)
-{
- return WaitForEventsInternal(timeout, nullptr, nullptr, 0, 0, event_sp);
-}
-
-size_t
-Listener::HandleBroadcastEvent (EventSP &event_sp)
-{
- size_t num_handled = 0;
- std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
- Broadcaster *broadcaster = event_sp->GetBroadcaster();
- if (!broadcaster)
- return 0;
- broadcaster_collection::iterator pos;
- broadcaster_collection::iterator end = m_broadcasters.end();
- Broadcaster::BroadcasterImplSP broadcaster_impl_sp(broadcaster->GetBroadcasterImpl());
- for (pos = m_broadcasters.find (broadcaster_impl_sp);
- pos != end && pos->first.lock() == broadcaster_impl_sp;
- ++pos)
- {
- BroadcasterInfo info = pos->second;
- if (event_sp->GetType () & info.event_mask)
- {
- if (info.callback != nullptr)
- {
- info.callback (event_sp, info.callback_user_data);
- ++num_handled;
- }
- }
+size_t Listener::HandleBroadcastEvent(EventSP &event_sp) {
+ size_t num_handled = 0;
+ std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
+ Broadcaster *broadcaster = event_sp->GetBroadcaster();
+ if (!broadcaster)
+ return 0;
+ broadcaster_collection::iterator pos;
+ broadcaster_collection::iterator end = m_broadcasters.end();
+ Broadcaster::BroadcasterImplSP broadcaster_impl_sp(
+ broadcaster->GetBroadcasterImpl());
+ for (pos = m_broadcasters.find(broadcaster_impl_sp);
+ pos != end && pos->first.lock() == broadcaster_impl_sp; ++pos) {
+ BroadcasterInfo info = pos->second;
+ if (event_sp->GetType() & info.event_mask) {
+ if (info.callback != nullptr) {
+ info.callback(event_sp, info.callback_user_data);
+ ++num_handled;
+ }
}
- return num_handled;
+ }
+ return num_handled;
}
uint32_t
-Listener::StartListeningForEventSpec (BroadcasterManagerSP manager_sp,
- const BroadcastEventSpec &event_spec)
-{
- if (!manager_sp)
- return 0;
-
- // The BroadcasterManager mutex must be locked before m_broadcasters_mutex
- // to avoid violating the lock hierarchy (manager before broadcasters).
- std::lock_guard<std::recursive_mutex> manager_guard(manager_sp->m_manager_mutex);
- std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
+Listener::StartListeningForEventSpec(BroadcasterManagerSP manager_sp,
+ const BroadcastEventSpec &event_spec) {
+ if (!manager_sp)
+ return 0;
- uint32_t bits_acquired = manager_sp->RegisterListenerForEvents(this->shared_from_this(), event_spec);
- if (bits_acquired)
- {
- broadcaster_manager_collection::iterator iter, end_iter = m_broadcaster_managers.end();
- BroadcasterManagerWP manager_wp(manager_sp);
- BroadcasterManagerWPMatcher matcher(manager_sp);
- iter = std::find_if<broadcaster_manager_collection::iterator, BroadcasterManagerWPMatcher>(m_broadcaster_managers.begin(), end_iter, matcher);
- if (iter == end_iter)
- m_broadcaster_managers.push_back(manager_wp);
- }
-
- return bits_acquired;
+ // The BroadcasterManager mutex must be locked before m_broadcasters_mutex
+ // to avoid violating the lock hierarchy (manager before broadcasters).
+ std::lock_guard<std::recursive_mutex> manager_guard(
+ manager_sp->m_manager_mutex);
+ std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
+
+ uint32_t bits_acquired = manager_sp->RegisterListenerForEvents(
+ this->shared_from_this(), event_spec);
+ if (bits_acquired) {
+ broadcaster_manager_collection::iterator iter,
+ end_iter = m_broadcaster_managers.end();
+ BroadcasterManagerWP manager_wp(manager_sp);
+ BroadcasterManagerWPMatcher matcher(manager_sp);
+ iter = std::find_if<broadcaster_manager_collection::iterator,
+ BroadcasterManagerWPMatcher>(
+ m_broadcaster_managers.begin(), end_iter, matcher);
+ if (iter == end_iter)
+ m_broadcaster_managers.push_back(manager_wp);
+ }
+
+ return bits_acquired;
}
-
-bool
-Listener::StopListeningForEventSpec (BroadcasterManagerSP manager_sp,
- const BroadcastEventSpec &event_spec)
-{
- if (!manager_sp)
- return false;
- std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
- return manager_sp->UnregisterListenerForEvents (this->shared_from_this(), event_spec);
+bool Listener::StopListeningForEventSpec(BroadcasterManagerSP manager_sp,
+ const BroadcastEventSpec &event_spec) {
+ if (!manager_sp)
+ return false;
+
+ std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
+ return manager_sp->UnregisterListenerForEvents(this->shared_from_this(),
+ event_spec);
}
-
-ListenerSP
-Listener::MakeListener(const char *name)
-{
- return ListenerSP(new Listener(name));
+
+ListenerSP Listener::MakeListener(const char *name) {
+ return ListenerSP(new Listener(name));
}
Modified: lldb/trunk/source/Core/Log.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Log.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Core/Log.cpp (original)
+++ lldb/trunk/source/Core/Log.cpp Tue Sep 6 15:57:50 2016
@@ -18,8 +18,8 @@
// Other libraries and framework includes
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Signals.h"
+#include "llvm/Support/raw_ostream.h"
// Project includes
#include "lldb/Core/Log.h"
@@ -35,62 +35,31 @@
using namespace lldb;
using namespace lldb_private;
-Log::Log () :
- m_stream_sp(),
- m_options(0),
- m_mask_bits(0)
-{
-}
+Log::Log() : m_stream_sp(), m_options(0), m_mask_bits(0) {}
-Log::Log (const StreamSP &stream_sp) :
- m_stream_sp(stream_sp),
- m_options(0),
- m_mask_bits(0)
-{
-}
+Log::Log(const StreamSP &stream_sp)
+ : m_stream_sp(stream_sp), m_options(0), m_mask_bits(0) {}
Log::~Log() = default;
-Flags &
-Log::GetOptions()
-{
- return m_options;
-}
+Flags &Log::GetOptions() { return m_options; }
-const Flags &
-Log::GetOptions() const
-{
- return m_options;
-}
+const Flags &Log::GetOptions() const { return m_options; }
-Flags &
-Log::GetMask()
-{
- return m_mask_bits;
-}
+Flags &Log::GetMask() { return m_mask_bits; }
-const Flags &
-Log::GetMask() const
-{
- return m_mask_bits;
-}
+const Flags &Log::GetMask() const { return m_mask_bits; }
-void
-Log::PutCString(const char *cstr)
-{
- Printf("%s", cstr);
-}
+void Log::PutCString(const char *cstr) { Printf("%s", cstr); }
//----------------------------------------------------------------------
// Simple variable argument logging with flags.
//----------------------------------------------------------------------
-void
-Log::Printf(const char *format, ...)
-{
- va_list args;
- va_start(args, format);
- VAPrintf(format, args);
- va_end(args);
+void Log::Printf(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ VAPrintf(format, args);
+ va_end(args);
}
//----------------------------------------------------------------------
@@ -98,459 +67,384 @@ Log::Printf(const char *format, ...)
// a callback registered, then we call the logging callback. If we have
// a valid file handle, we also log to the file.
//----------------------------------------------------------------------
-void
-Log::VAPrintf(const char *format, va_list args)
-{
- // Make a copy of our stream shared pointer in case someone disables our
- // log while we are logging and releases the stream
- StreamSP stream_sp(m_stream_sp);
- if (stream_sp)
- {
- static uint32_t g_sequence_id = 0;
- StreamString header;
-
- // Add a sequence ID if requested
- if (m_options.Test (LLDB_LOG_OPTION_PREPEND_SEQUENCE))
- header.Printf ("%u ", ++g_sequence_id);
-
- // Timestamp if requested
- if (m_options.Test (LLDB_LOG_OPTION_PREPEND_TIMESTAMP))
- {
- TimeValue now = TimeValue::Now();
- header.Printf ("%9d.%09.9d ", now.seconds(), now.nanoseconds());
- }
-
- // Add the process and thread if requested
- if (m_options.Test (LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD))
- header.Printf ("[%4.4x/%4.4" PRIx64 "]: ", getpid(), Host::GetCurrentThreadID());
-
- // Add the thread name if requested
- if (m_options.Test (LLDB_LOG_OPTION_PREPEND_THREAD_NAME))
- {
- llvm::SmallString<32> thread_name;
- ThisThread::GetName(thread_name);
- if (!thread_name.empty())
- header.Printf ("%s ", thread_name.c_str());
- }
-
- header.PrintfVarArg (format, args);
- header.PutCString("\n");
-
- if (m_options.Test(LLDB_LOG_OPTION_BACKTRACE))
- {
- std::string back_trace;
- llvm::raw_string_ostream stream(back_trace);
- llvm::sys::PrintStackTrace(stream);
- stream.flush();
- header.PutCString(back_trace.c_str());
- }
-
- if (m_options.Test(LLDB_LOG_OPTION_THREADSAFE))
- {
- static std::recursive_mutex g_LogThreadedMutex;
- std::lock_guard<std::recursive_mutex> guard(g_LogThreadedMutex);
- stream_sp->PutCString(header.GetString().c_str());
- stream_sp->Flush();
- }
- else
- {
- stream_sp->PutCString(header.GetString().c_str());
- stream_sp->Flush();
- }
+void Log::VAPrintf(const char *format, va_list args) {
+ // Make a copy of our stream shared pointer in case someone disables our
+ // log while we are logging and releases the stream
+ StreamSP stream_sp(m_stream_sp);
+ if (stream_sp) {
+ static uint32_t g_sequence_id = 0;
+ StreamString header;
+
+ // Add a sequence ID if requested
+ if (m_options.Test(LLDB_LOG_OPTION_PREPEND_SEQUENCE))
+ header.Printf("%u ", ++g_sequence_id);
+
+ // Timestamp if requested
+ if (m_options.Test(LLDB_LOG_OPTION_PREPEND_TIMESTAMP)) {
+ TimeValue now = TimeValue::Now();
+ header.Printf("%9d.%09.9d ", now.seconds(), now.nanoseconds());
+ }
+
+ // Add the process and thread if requested
+ if (m_options.Test(LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD))
+ header.Printf("[%4.4x/%4.4" PRIx64 "]: ", getpid(),
+ Host::GetCurrentThreadID());
+
+ // Add the thread name if requested
+ if (m_options.Test(LLDB_LOG_OPTION_PREPEND_THREAD_NAME)) {
+ llvm::SmallString<32> thread_name;
+ ThisThread::GetName(thread_name);
+ if (!thread_name.empty())
+ header.Printf("%s ", thread_name.c_str());
+ }
+
+ header.PrintfVarArg(format, args);
+ header.PutCString("\n");
+
+ if (m_options.Test(LLDB_LOG_OPTION_BACKTRACE)) {
+ std::string back_trace;
+ llvm::raw_string_ostream stream(back_trace);
+ llvm::sys::PrintStackTrace(stream);
+ stream.flush();
+ header.PutCString(back_trace.c_str());
+ }
+
+ if (m_options.Test(LLDB_LOG_OPTION_THREADSAFE)) {
+ static std::recursive_mutex g_LogThreadedMutex;
+ std::lock_guard<std::recursive_mutex> guard(g_LogThreadedMutex);
+ stream_sp->PutCString(header.GetString().c_str());
+ stream_sp->Flush();
+ } else {
+ stream_sp->PutCString(header.GetString().c_str());
+ stream_sp->Flush();
}
+ }
}
//----------------------------------------------------------------------
// Print debug strings if and only if the global debug option is set to
// a non-zero value.
//----------------------------------------------------------------------
-void
-Log::Debug(const char *format, ...)
-{
- if (!GetOptions().Test(LLDB_LOG_OPTION_DEBUG))
- return;
-
- va_list args;
- va_start(args, format);
- VAPrintf(format, args);
- va_end(args);
+void Log::Debug(const char *format, ...) {
+ if (!GetOptions().Test(LLDB_LOG_OPTION_DEBUG))
+ return;
+
+ va_list args;
+ va_start(args, format);
+ VAPrintf(format, args);
+ va_end(args);
}
//----------------------------------------------------------------------
// Print debug strings if and only if the global debug option is set to
// a non-zero value.
//----------------------------------------------------------------------
-void
-Log::DebugVerbose(const char *format, ...)
-{
- if (!GetOptions().AllSet(LLDB_LOG_OPTION_DEBUG | LLDB_LOG_OPTION_VERBOSE))
- return;
-
- va_list args;
- va_start(args, format);
- VAPrintf(format, args);
- va_end(args);
+void Log::DebugVerbose(const char *format, ...) {
+ if (!GetOptions().AllSet(LLDB_LOG_OPTION_DEBUG | LLDB_LOG_OPTION_VERBOSE))
+ return;
+
+ va_list args;
+ va_start(args, format);
+ VAPrintf(format, args);
+ va_end(args);
}
//----------------------------------------------------------------------
// Log only if all of the bits are set
//----------------------------------------------------------------------
-void
-Log::LogIf(uint32_t bits, const char *format, ...)
-{
- if (!m_options.AllSet(bits))
- return;
-
- va_list args;
- va_start(args, format);
- VAPrintf(format, args);
- va_end(args);
+void Log::LogIf(uint32_t bits, const char *format, ...) {
+ if (!m_options.AllSet(bits))
+ return;
+
+ va_list args;
+ va_start(args, format);
+ VAPrintf(format, args);
+ va_end(args);
}
//----------------------------------------------------------------------
// Printing of errors that are not fatal.
//----------------------------------------------------------------------
-void
-Log::Error(const char *format, ...)
-{
- va_list args;
- va_start(args, format);
- VAError(format, args);
- va_end(args);
-}
-
-void
-Log::VAError(const char *format, va_list args)
-{
- char *arg_msg = nullptr;
- ::vasprintf(&arg_msg, format, args);
+void Log::Error(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ VAError(format, args);
+ va_end(args);
+}
+
+void Log::VAError(const char *format, va_list args) {
+ char *arg_msg = nullptr;
+ ::vasprintf(&arg_msg, format, args);
- if (arg_msg == nullptr)
- return;
+ if (arg_msg == nullptr)
+ return;
- Printf("error: %s", arg_msg);
- free(arg_msg);
+ Printf("error: %s", arg_msg);
+ free(arg_msg);
}
//----------------------------------------------------------------------
// Printing of errors that ARE fatal. Exit with ERR exit code
// immediately.
//----------------------------------------------------------------------
-void
-Log::FatalError(int err, const char *format, ...)
-{
- char *arg_msg = nullptr;
- va_list args;
- va_start(args, format);
- ::vasprintf(&arg_msg, format, args);
- va_end(args);
-
- if (arg_msg != nullptr)
- {
- Printf("error: %s", arg_msg);
- ::free(arg_msg);
- }
- ::exit(err);
+void Log::FatalError(int err, const char *format, ...) {
+ char *arg_msg = nullptr;
+ va_list args;
+ va_start(args, format);
+ ::vasprintf(&arg_msg, format, args);
+ va_end(args);
+
+ if (arg_msg != nullptr) {
+ Printf("error: %s", arg_msg);
+ ::free(arg_msg);
+ }
+ ::exit(err);
}
//----------------------------------------------------------------------
// Printing of warnings that are not fatal only if verbose mode is
// enabled.
//----------------------------------------------------------------------
-void
-Log::Verbose(const char *format, ...)
-{
- if (!m_options.Test(LLDB_LOG_OPTION_VERBOSE))
- return;
-
- va_list args;
- va_start(args, format);
- VAPrintf(format, args);
- va_end(args);
+void Log::Verbose(const char *format, ...) {
+ if (!m_options.Test(LLDB_LOG_OPTION_VERBOSE))
+ return;
+
+ va_list args;
+ va_start(args, format);
+ VAPrintf(format, args);
+ va_end(args);
}
//----------------------------------------------------------------------
// Printing of warnings that are not fatal only if verbose mode is
// enabled.
//----------------------------------------------------------------------
-void
-Log::WarningVerbose(const char *format, ...)
-{
- if (!m_options.Test(LLDB_LOG_OPTION_VERBOSE))
- return;
-
- char *arg_msg = nullptr;
- va_list args;
- va_start(args, format);
- ::vasprintf(&arg_msg, format, args);
- va_end(args);
+void Log::WarningVerbose(const char *format, ...) {
+ if (!m_options.Test(LLDB_LOG_OPTION_VERBOSE))
+ return;
+
+ char *arg_msg = nullptr;
+ va_list args;
+ va_start(args, format);
+ ::vasprintf(&arg_msg, format, args);
+ va_end(args);
- if (arg_msg == nullptr)
- return;
+ if (arg_msg == nullptr)
+ return;
- Printf("warning: %s", arg_msg);
- free(arg_msg);
+ Printf("warning: %s", arg_msg);
+ free(arg_msg);
}
//----------------------------------------------------------------------
// Printing of warnings that are not fatal.
//----------------------------------------------------------------------
-void
-Log::Warning(const char *format, ...)
-{
- char *arg_msg = nullptr;
- va_list args;
- va_start(args, format);
- ::vasprintf(&arg_msg, format, args);
- va_end(args);
+void Log::Warning(const char *format, ...) {
+ char *arg_msg = nullptr;
+ va_list args;
+ va_start(args, format);
+ ::vasprintf(&arg_msg, format, args);
+ va_end(args);
- if (arg_msg == nullptr)
- return;
+ if (arg_msg == nullptr)
+ return;
- Printf("warning: %s", arg_msg);
- free(arg_msg);
+ Printf("warning: %s", arg_msg);
+ free(arg_msg);
}
-typedef std::map <ConstString, Log::Callbacks> CallbackMap;
+typedef std::map<ConstString, Log::Callbacks> CallbackMap;
typedef CallbackMap::iterator CallbackMapIter;
-typedef std::map <ConstString, LogChannelSP> LogChannelMap;
+typedef std::map<ConstString, LogChannelSP> LogChannelMap;
typedef LogChannelMap::iterator LogChannelMapIter;
// Surround our callback map with a singleton function so we don't have any
// global initializers.
-static CallbackMap &
-GetCallbackMap ()
-{
- static CallbackMap g_callback_map;
- return g_callback_map;
-}
-
-static LogChannelMap &
-GetChannelMap ()
-{
- static LogChannelMap g_channel_map;
- return g_channel_map;
-}
-
-void
-Log::RegisterLogChannel (const ConstString &channel, const Log::Callbacks &log_callbacks)
-{
- GetCallbackMap().insert(std::make_pair(channel, log_callbacks));
-}
-
-bool
-Log::UnregisterLogChannel (const ConstString &channel)
-{
- return GetCallbackMap().erase(channel) != 0;
-}
-
-bool
-Log::GetLogChannelCallbacks (const ConstString &channel, Log::Callbacks &log_callbacks)
-{
- CallbackMap &callback_map = GetCallbackMap ();
- CallbackMapIter pos = callback_map.find(channel);
- if (pos != callback_map.end())
- {
- log_callbacks = pos->second;
- return true;
+static CallbackMap &GetCallbackMap() {
+ static CallbackMap g_callback_map;
+ return g_callback_map;
+}
+
+static LogChannelMap &GetChannelMap() {
+ static LogChannelMap g_channel_map;
+ return g_channel_map;
+}
+
+void Log::RegisterLogChannel(const ConstString &channel,
+ const Log::Callbacks &log_callbacks) {
+ GetCallbackMap().insert(std::make_pair(channel, log_callbacks));
+}
+
+bool Log::UnregisterLogChannel(const ConstString &channel) {
+ return GetCallbackMap().erase(channel) != 0;
+}
+
+bool Log::GetLogChannelCallbacks(const ConstString &channel,
+ Log::Callbacks &log_callbacks) {
+ CallbackMap &callback_map = GetCallbackMap();
+ CallbackMapIter pos = callback_map.find(channel);
+ if (pos != callback_map.end()) {
+ log_callbacks = pos->second;
+ return true;
+ }
+ ::memset(&log_callbacks, 0, sizeof(log_callbacks));
+ return false;
+}
+
+bool Log::EnableLogChannel(lldb::StreamSP &log_stream_sp, uint32_t log_options,
+ const char *channel, const char **categories,
+ Stream &error_stream) {
+ Log::Callbacks log_callbacks;
+ if (Log::GetLogChannelCallbacks(ConstString(channel), log_callbacks)) {
+ log_callbacks.enable(log_stream_sp, log_options, categories, &error_stream);
+ return true;
+ }
+
+ LogChannelSP log_channel_sp(LogChannel::FindPlugin(channel));
+ if (log_channel_sp) {
+ if (log_channel_sp->Enable(log_stream_sp, log_options, &error_stream,
+ categories)) {
+ return true;
+ } else {
+ error_stream.Printf("Invalid log channel '%s'.\n", channel);
+ return false;
}
- ::memset (&log_callbacks, 0, sizeof(log_callbacks));
+ } else {
+ error_stream.Printf("Invalid log channel '%s'.\n", channel);
return false;
+ }
}
-bool
-Log::EnableLogChannel(lldb::StreamSP &log_stream_sp,
- uint32_t log_options,
- const char *channel,
- const char **categories,
- Stream &error_stream)
-{
- Log::Callbacks log_callbacks;
- if (Log::GetLogChannelCallbacks (ConstString(channel), log_callbacks))
- {
- log_callbacks.enable (log_stream_sp, log_options, categories, &error_stream);
- return true;
- }
-
- LogChannelSP log_channel_sp (LogChannel::FindPlugin (channel));
+void Log::EnableAllLogChannels(StreamSP &log_stream_sp, uint32_t log_options,
+ const char **categories, Stream *feedback_strm) {
+ CallbackMap &callback_map = GetCallbackMap();
+ CallbackMapIter pos, end = callback_map.end();
+
+ for (pos = callback_map.begin(); pos != end; ++pos)
+ pos->second.enable(log_stream_sp, log_options, categories, feedback_strm);
+
+ LogChannelMap &channel_map = GetChannelMap();
+ LogChannelMapIter channel_pos, channel_end = channel_map.end();
+ for (channel_pos = channel_map.begin(); channel_pos != channel_end;
+ ++channel_pos) {
+ channel_pos->second->Enable(log_stream_sp, log_options, feedback_strm,
+ categories);
+ }
+}
+
+void Log::AutoCompleteChannelName(const char *channel_name,
+ StringList &matches) {
+ LogChannelMap &map = GetChannelMap();
+ LogChannelMapIter pos, end = map.end();
+ for (pos = map.begin(); pos != end; ++pos) {
+ const char *pos_channel_name = pos->first.GetCString();
+ if (channel_name && channel_name[0]) {
+ if (NameMatches(channel_name, eNameMatchStartsWith, pos_channel_name)) {
+ matches.AppendString(pos_channel_name);
+ }
+ } else
+ matches.AppendString(pos_channel_name);
+ }
+}
+
+void Log::DisableAllLogChannels(Stream *feedback_strm) {
+ CallbackMap &callback_map = GetCallbackMap();
+ CallbackMapIter pos, end = callback_map.end();
+ const char *categories[] = {"all", nullptr};
+
+ for (pos = callback_map.begin(); pos != end; ++pos)
+ pos->second.disable(categories, feedback_strm);
+
+ LogChannelMap &channel_map = GetChannelMap();
+ LogChannelMapIter channel_pos, channel_end = channel_map.end();
+ for (channel_pos = channel_map.begin(); channel_pos != channel_end;
+ ++channel_pos)
+ channel_pos->second->Disable(categories, feedback_strm);
+}
+
+void Log::Initialize() {
+ Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories};
+ Log::RegisterLogChannel(ConstString("lldb"), log_callbacks);
+}
+
+void Log::Terminate() { DisableAllLogChannels(nullptr); }
+
+void Log::ListAllLogChannels(Stream *strm) {
+ CallbackMap &callback_map = GetCallbackMap();
+ LogChannelMap &channel_map = GetChannelMap();
+
+ if (callback_map.empty() && channel_map.empty()) {
+ strm->PutCString("No logging channels are currently registered.\n");
+ return;
+ }
+
+ CallbackMapIter pos, end = callback_map.end();
+ for (pos = callback_map.begin(); pos != end; ++pos)
+ pos->second.list_categories(strm);
+
+ uint32_t idx = 0;
+ const char *name;
+ for (idx = 0;
+ (name = PluginManager::GetLogChannelCreateNameAtIndex(idx)) != nullptr;
+ ++idx) {
+ LogChannelSP log_channel_sp(LogChannel::FindPlugin(name));
if (log_channel_sp)
- {
- if (log_channel_sp->Enable (log_stream_sp, log_options, &error_stream, categories))
- {
- return true;
- }
- else
- {
- error_stream.Printf ("Invalid log channel '%s'.\n", channel);
- return false;
- }
- }
- else
- {
- error_stream.Printf ("Invalid log channel '%s'.\n", channel);
- return false;
- }
-}
-
-void
-Log::EnableAllLogChannels(StreamSP &log_stream_sp,
- uint32_t log_options,
- const char **categories,
- Stream *feedback_strm)
-{
- CallbackMap &callback_map = GetCallbackMap ();
- CallbackMapIter pos, end = callback_map.end();
-
- for (pos = callback_map.begin(); pos != end; ++pos)
- pos->second.enable (log_stream_sp, log_options, categories, feedback_strm);
-
- LogChannelMap &channel_map = GetChannelMap ();
- LogChannelMapIter channel_pos, channel_end = channel_map.end();
- for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
- {
- channel_pos->second->Enable (log_stream_sp, log_options, feedback_strm, categories);
- }
+ log_channel_sp->ListCategories(strm);
+ }
}
-void
-Log::AutoCompleteChannelName (const char *channel_name, StringList &matches)
-{
- LogChannelMap &map = GetChannelMap ();
- LogChannelMapIter pos, end = map.end();
- for (pos = map.begin(); pos != end; ++pos)
- {
- const char *pos_channel_name = pos->first.GetCString();
- if (channel_name && channel_name[0])
- {
- if (NameMatches (channel_name, eNameMatchStartsWith, pos_channel_name))
- {
- matches.AppendString(pos_channel_name);
- }
- }
- else
- matches.AppendString(pos_channel_name);
- }
-}
-
-void
-Log::DisableAllLogChannels (Stream *feedback_strm)
-{
- CallbackMap &callback_map = GetCallbackMap ();
- CallbackMapIter pos, end = callback_map.end();
- const char *categories[] = {"all", nullptr};
-
- for (pos = callback_map.begin(); pos != end; ++pos)
- pos->second.disable (categories, feedback_strm);
-
- LogChannelMap &channel_map = GetChannelMap ();
- LogChannelMapIter channel_pos, channel_end = channel_map.end();
- for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
- channel_pos->second->Disable (categories, feedback_strm);
-}
-
-void
-Log::Initialize()
-{
- Log::Callbacks log_callbacks = { DisableLog, EnableLog, ListLogCategories };
- Log::RegisterLogChannel (ConstString("lldb"), log_callbacks);
-}
-
-void
-Log::Terminate ()
-{
- DisableAllLogChannels(nullptr);
-}
-
-void
-Log::ListAllLogChannels (Stream *strm)
-{
- CallbackMap &callback_map = GetCallbackMap ();
- LogChannelMap &channel_map = GetChannelMap ();
-
- if (callback_map.empty() && channel_map.empty())
- {
- strm->PutCString ("No logging channels are currently registered.\n");
- return;
- }
-
- CallbackMapIter pos, end = callback_map.end();
- for (pos = callback_map.begin(); pos != end; ++pos)
- pos->second.list_categories (strm);
-
- uint32_t idx = 0;
- const char *name;
- for (idx = 0; (name = PluginManager::GetLogChannelCreateNameAtIndex (idx)) != nullptr; ++idx)
- {
- LogChannelSP log_channel_sp(LogChannel::FindPlugin (name));
- if (log_channel_sp)
- log_channel_sp->ListCategories (strm);
- }
-}
-
-bool
-Log::GetVerbose() const
-{
- // FIXME: This has to be centralized between the stream and the log...
- if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
- return true;
-
- // Make a copy of our stream shared pointer in case someone disables our
- // log while we are logging and releases the stream
- StreamSP stream_sp(m_stream_sp);
- if (stream_sp)
- return stream_sp->GetVerbose();
- return false;
+bool Log::GetVerbose() const {
+ // FIXME: This has to be centralized between the stream and the log...
+ if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
+ return true;
+
+ // Make a copy of our stream shared pointer in case someone disables our
+ // log while we are logging and releases the stream
+ StreamSP stream_sp(m_stream_sp);
+ if (stream_sp)
+ return stream_sp->GetVerbose();
+ return false;
}
//------------------------------------------------------------------
// Returns true if the debug flag bit is set in this stream.
//------------------------------------------------------------------
-bool
-Log::GetDebug() const
-{
- // Make a copy of our stream shared pointer in case someone disables our
- // log while we are logging and releases the stream
- StreamSP stream_sp(m_stream_sp);
- if (stream_sp)
- return stream_sp->GetDebug();
- return false;
-}
-
-LogChannelSP
-LogChannel::FindPlugin (const char *plugin_name)
-{
- LogChannelSP log_channel_sp;
- LogChannelMap &channel_map = GetChannelMap ();
- ConstString log_channel_name (plugin_name);
- LogChannelMapIter pos = channel_map.find (log_channel_name);
- if (pos == channel_map.end())
- {
- ConstString const_plugin_name (plugin_name);
- LogChannelCreateInstance create_callback = PluginManager::GetLogChannelCreateCallbackForPluginName (const_plugin_name);
- if (create_callback)
- {
- log_channel_sp.reset(create_callback());
- if (log_channel_sp)
- {
- // Cache the one and only loaded instance of each log channel
- // plug-in after it has been loaded once.
- channel_map[log_channel_name] = log_channel_sp;
- }
- }
- }
- else
- {
- // We have already loaded an instance of this log channel class,
- // so just return the cached instance.
- log_channel_sp = pos->second;
- }
- return log_channel_sp;
+bool Log::GetDebug() const {
+ // Make a copy of our stream shared pointer in case someone disables our
+ // log while we are logging and releases the stream
+ StreamSP stream_sp(m_stream_sp);
+ if (stream_sp)
+ return stream_sp->GetDebug();
+ return false;
+}
+
+LogChannelSP LogChannel::FindPlugin(const char *plugin_name) {
+ LogChannelSP log_channel_sp;
+ LogChannelMap &channel_map = GetChannelMap();
+ ConstString log_channel_name(plugin_name);
+ LogChannelMapIter pos = channel_map.find(log_channel_name);
+ if (pos == channel_map.end()) {
+ ConstString const_plugin_name(plugin_name);
+ LogChannelCreateInstance create_callback =
+ PluginManager::GetLogChannelCreateCallbackForPluginName(
+ const_plugin_name);
+ if (create_callback) {
+ log_channel_sp.reset(create_callback());
+ if (log_channel_sp) {
+ // Cache the one and only loaded instance of each log channel
+ // plug-in after it has been loaded once.
+ channel_map[log_channel_name] = log_channel_sp;
+ }
+ }
+ } else {
+ // We have already loaded an instance of this log channel class,
+ // so just return the cached instance.
+ log_channel_sp = pos->second;
+ }
+ return log_channel_sp;
}
-LogChannel::LogChannel () :
- m_log_ap ()
-{
-}
+LogChannel::LogChannel() : m_log_ap() {}
LogChannel::~LogChannel() = default;
Modified: lldb/trunk/source/Core/Logging.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Logging.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Core/Logging.cpp (original)
+++ lldb/trunk/source/Core/Logging.cpp Tue Sep 6 15:57:50 2016
@@ -11,14 +11,14 @@
// C Includes
// C++ Includes
-#include <cstring>
#include <atomic>
+#include <cstring>
// Other libraries and framework includes
// Project includes
-#include "lldb/Interpreter/Args.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Interpreter/Args.h"
using namespace lldb;
using namespace lldb_private;
@@ -28,254 +28,295 @@ using namespace lldb_private;
// that will construct the static g_lob_sp the first time this function is
// called.
-static std::atomic<bool> g_log_enabled {false};
-static Log * g_log = nullptr;
+static std::atomic<bool> g_log_enabled{false};
+static Log *g_log = nullptr;
-static Log *
-GetLog ()
-{
- if (!g_log_enabled)
- return nullptr;
- return g_log;
+static Log *GetLog() {
+ if (!g_log_enabled)
+ return nullptr;
+ return g_log;
}
-uint32_t
-lldb_private::GetLogMask ()
-{
- Log *log(GetLog ());
- if (log)
- return log->GetMask().Get();
- return 0;
+uint32_t lldb_private::GetLogMask() {
+ Log *log(GetLog());
+ if (log)
+ return log->GetMask().Get();
+ return 0;
}
-bool
-lldb_private::IsLogVerbose ()
-{
- uint32_t mask = GetLogMask();
- return (mask & LIBLLDB_LOG_VERBOSE);
+bool lldb_private::IsLogVerbose() {
+ uint32_t mask = GetLogMask();
+ return (mask & LIBLLDB_LOG_VERBOSE);
}
-Log *
-lldb_private::GetLogIfAllCategoriesSet (uint32_t mask)
-{
- Log *log(GetLog ());
- if (log && mask)
- {
- uint32_t log_mask = log->GetMask().Get();
- if ((log_mask & mask) != mask)
- return nullptr;
- }
- return log;
+Log *lldb_private::GetLogIfAllCategoriesSet(uint32_t mask) {
+ Log *log(GetLog());
+ if (log && mask) {
+ uint32_t log_mask = log->GetMask().Get();
+ if ((log_mask & mask) != mask)
+ return nullptr;
+ }
+ return log;
}
-void
-lldb_private::LogIfAllCategoriesSet (uint32_t mask, const char *format, ...)
-{
- Log *log(GetLogIfAllCategoriesSet (mask));
- if (log)
- {
- va_list args;
- va_start (args, format);
- log->VAPrintf (format, args);
- va_end (args);
- }
+void lldb_private::LogIfAllCategoriesSet(uint32_t mask, const char *format,
+ ...) {
+ Log *log(GetLogIfAllCategoriesSet(mask));
+ if (log) {
+ va_list args;
+ va_start(args, format);
+ log->VAPrintf(format, args);
+ va_end(args);
+ }
}
-void
-lldb_private::LogIfAnyCategoriesSet (uint32_t mask, const char *format, ...)
-{
- Log *log(GetLogIfAnyCategoriesSet (mask));
- if (log != nullptr)
- {
- va_list args;
- va_start (args, format);
- log->VAPrintf (format, args);
- va_end (args);
- }
+void lldb_private::LogIfAnyCategoriesSet(uint32_t mask, const char *format,
+ ...) {
+ Log *log(GetLogIfAnyCategoriesSet(mask));
+ if (log != nullptr) {
+ va_list args;
+ va_start(args, format);
+ log->VAPrintf(format, args);
+ va_end(args);
+ }
}
-Log *
-lldb_private::GetLogIfAnyCategoriesSet (uint32_t mask)
-{
- Log *log(GetLog ());
- if (log != nullptr && mask && (mask & log->GetMask().Get()))
- return log;
- return nullptr;
+Log *lldb_private::GetLogIfAnyCategoriesSet(uint32_t mask) {
+ Log *log(GetLog());
+ if (log != nullptr && mask && (mask & log->GetMask().Get()))
+ return log;
+ return nullptr;
}
-void
-lldb_private::DisableLog (const char **categories, Stream *feedback_strm)
-{
- Log *log(GetLog ());
-
- if (log != nullptr)
- {
- uint32_t flag_bits = 0;
- if (categories[0] != nullptr)
- {
- flag_bits = log->GetMask().Get();
- for (size_t i = 0; categories[i] != nullptr; ++i)
- {
- const char *arg = categories[i];
-
- if (0 == ::strcasecmp(arg, "all")) flag_bits &= ~LIBLLDB_LOG_ALL;
- else if (0 == ::strcasecmp(arg, "api")) flag_bits &= ~LIBLLDB_LOG_API;
- else if (0 == ::strncasecmp(arg, "break", 5)) flag_bits &= ~LIBLLDB_LOG_BREAKPOINTS;
- else if (0 == ::strcasecmp(arg, "commands")) flag_bits &= ~LIBLLDB_LOG_COMMANDS;
- else if (0 == ::strcasecmp(arg, "default")) flag_bits &= ~LIBLLDB_LOG_DEFAULT;
- else if (0 == ::strcasecmp(arg, "dyld")) flag_bits &= ~LIBLLDB_LOG_DYNAMIC_LOADER;
- else if (0 == ::strncasecmp(arg, "event", 5)) flag_bits &= ~LIBLLDB_LOG_EVENTS;
- else if (0 == ::strncasecmp(arg, "expr", 4)) flag_bits &= ~LIBLLDB_LOG_EXPRESSIONS;
- else if (0 == ::strncasecmp(arg, "object", 6)) flag_bits &= ~LIBLLDB_LOG_OBJECT;
- else if (0 == ::strcasecmp(arg, "process")) flag_bits &= ~LIBLLDB_LOG_PROCESS;
- else if (0 == ::strcasecmp(arg, "platform")) flag_bits &= ~LIBLLDB_LOG_PLATFORM;
- else if (0 == ::strcasecmp(arg, "script")) flag_bits &= ~LIBLLDB_LOG_SCRIPT;
- else if (0 == ::strcasecmp(arg, "state")) flag_bits &= ~LIBLLDB_LOG_STATE;
- else if (0 == ::strcasecmp(arg, "step")) flag_bits &= ~LIBLLDB_LOG_STEP;
- else if (0 == ::strcasecmp(arg, "thread")) flag_bits &= ~LIBLLDB_LOG_THREAD;
- else if (0 == ::strcasecmp(arg, "target")) flag_bits &= ~LIBLLDB_LOG_TARGET;
- else if (0 == ::strcasecmp(arg, "verbose")) flag_bits &= ~LIBLLDB_LOG_VERBOSE;
- else if (0 == ::strncasecmp(arg, "watch", 5)) flag_bits &= ~LIBLLDB_LOG_WATCHPOINTS;
- else if (0 == ::strncasecmp(arg, "temp", 4)) flag_bits &= ~LIBLLDB_LOG_TEMPORARY;
- else if (0 == ::strncasecmp(arg, "comm", 4)) flag_bits &= ~LIBLLDB_LOG_COMMUNICATION;
- else if (0 == ::strncasecmp(arg, "conn", 4)) flag_bits &= ~LIBLLDB_LOG_CONNECTION;
- else if (0 == ::strncasecmp(arg, "host", 4)) flag_bits &= ~LIBLLDB_LOG_HOST;
- else if (0 == ::strncasecmp(arg, "unwind", 6)) flag_bits &= ~LIBLLDB_LOG_UNWIND;
- else if (0 == ::strncasecmp(arg, "types", 5)) flag_bits &= ~LIBLLDB_LOG_TYPES;
- else if (0 == ::strncasecmp(arg, "symbol", 6)) flag_bits &= ~LIBLLDB_LOG_SYMBOLS;
- else if (0 == ::strcasecmp(arg, "system-runtime")) flag_bits &= ~LIBLLDB_LOG_SYSTEM_RUNTIME;
- else if (0 == ::strncasecmp(arg, "module", 6)) flag_bits &= ~LIBLLDB_LOG_MODULES;
- else if (0 == ::strncasecmp(arg, "mmap", 4)) flag_bits &= ~LIBLLDB_LOG_MMAP;
- else if (0 == ::strcasecmp(arg, "os")) flag_bits &= ~LIBLLDB_LOG_OS;
- else if (0 == ::strcasecmp(arg, "jit")) flag_bits &= ~LIBLLDB_LOG_JIT_LOADER;
- else if (0 == ::strcasecmp(arg, "language")) flag_bits &= ~LIBLLDB_LOG_LANGUAGE;
- else if (0 == ::strncasecmp(arg, "formatters", 10)) flag_bits &= ~LIBLLDB_LOG_DATAFORMATTERS;
- else if (0 == ::strncasecmp(arg, "demangle", 8)) flag_bits &= ~LIBLLDB_LOG_DEMANGLE;
- else
- {
- feedback_strm->Printf ("error: unrecognized log category '%s'\n", arg);
- ListLogCategories (feedback_strm);
- return;
- }
- }
- }
- log->GetMask().Reset (flag_bits);
- if (flag_bits == 0)
- {
- log->SetStream(lldb::StreamSP());
- g_log_enabled = false;
+void lldb_private::DisableLog(const char **categories, Stream *feedback_strm) {
+ Log *log(GetLog());
+
+ if (log != nullptr) {
+ uint32_t flag_bits = 0;
+ if (categories[0] != nullptr) {
+ flag_bits = log->GetMask().Get();
+ for (size_t i = 0; categories[i] != nullptr; ++i) {
+ const char *arg = categories[i];
+
+ if (0 == ::strcasecmp(arg, "all"))
+ flag_bits &= ~LIBLLDB_LOG_ALL;
+ else if (0 == ::strcasecmp(arg, "api"))
+ flag_bits &= ~LIBLLDB_LOG_API;
+ else if (0 == ::strncasecmp(arg, "break", 5))
+ flag_bits &= ~LIBLLDB_LOG_BREAKPOINTS;
+ else if (0 == ::strcasecmp(arg, "commands"))
+ flag_bits &= ~LIBLLDB_LOG_COMMANDS;
+ else if (0 == ::strcasecmp(arg, "default"))
+ flag_bits &= ~LIBLLDB_LOG_DEFAULT;
+ else if (0 == ::strcasecmp(arg, "dyld"))
+ flag_bits &= ~LIBLLDB_LOG_DYNAMIC_LOADER;
+ else if (0 == ::strncasecmp(arg, "event", 5))
+ flag_bits &= ~LIBLLDB_LOG_EVENTS;
+ else if (0 == ::strncasecmp(arg, "expr", 4))
+ flag_bits &= ~LIBLLDB_LOG_EXPRESSIONS;
+ else if (0 == ::strncasecmp(arg, "object", 6))
+ flag_bits &= ~LIBLLDB_LOG_OBJECT;
+ else if (0 == ::strcasecmp(arg, "process"))
+ flag_bits &= ~LIBLLDB_LOG_PROCESS;
+ else if (0 == ::strcasecmp(arg, "platform"))
+ flag_bits &= ~LIBLLDB_LOG_PLATFORM;
+ else if (0 == ::strcasecmp(arg, "script"))
+ flag_bits &= ~LIBLLDB_LOG_SCRIPT;
+ else if (0 == ::strcasecmp(arg, "state"))
+ flag_bits &= ~LIBLLDB_LOG_STATE;
+ else if (0 == ::strcasecmp(arg, "step"))
+ flag_bits &= ~LIBLLDB_LOG_STEP;
+ else if (0 == ::strcasecmp(arg, "thread"))
+ flag_bits &= ~LIBLLDB_LOG_THREAD;
+ else if (0 == ::strcasecmp(arg, "target"))
+ flag_bits &= ~LIBLLDB_LOG_TARGET;
+ else if (0 == ::strcasecmp(arg, "verbose"))
+ flag_bits &= ~LIBLLDB_LOG_VERBOSE;
+ else if (0 == ::strncasecmp(arg, "watch", 5))
+ flag_bits &= ~LIBLLDB_LOG_WATCHPOINTS;
+ else if (0 == ::strncasecmp(arg, "temp", 4))
+ flag_bits &= ~LIBLLDB_LOG_TEMPORARY;
+ else if (0 == ::strncasecmp(arg, "comm", 4))
+ flag_bits &= ~LIBLLDB_LOG_COMMUNICATION;
+ else if (0 == ::strncasecmp(arg, "conn", 4))
+ flag_bits &= ~LIBLLDB_LOG_CONNECTION;
+ else if (0 == ::strncasecmp(arg, "host", 4))
+ flag_bits &= ~LIBLLDB_LOG_HOST;
+ else if (0 == ::strncasecmp(arg, "unwind", 6))
+ flag_bits &= ~LIBLLDB_LOG_UNWIND;
+ else if (0 == ::strncasecmp(arg, "types", 5))
+ flag_bits &= ~LIBLLDB_LOG_TYPES;
+ else if (0 == ::strncasecmp(arg, "symbol", 6))
+ flag_bits &= ~LIBLLDB_LOG_SYMBOLS;
+ else if (0 == ::strcasecmp(arg, "system-runtime"))
+ flag_bits &= ~LIBLLDB_LOG_SYSTEM_RUNTIME;
+ else if (0 == ::strncasecmp(arg, "module", 6))
+ flag_bits &= ~LIBLLDB_LOG_MODULES;
+ else if (0 == ::strncasecmp(arg, "mmap", 4))
+ flag_bits &= ~LIBLLDB_LOG_MMAP;
+ else if (0 == ::strcasecmp(arg, "os"))
+ flag_bits &= ~LIBLLDB_LOG_OS;
+ else if (0 == ::strcasecmp(arg, "jit"))
+ flag_bits &= ~LIBLLDB_LOG_JIT_LOADER;
+ else if (0 == ::strcasecmp(arg, "language"))
+ flag_bits &= ~LIBLLDB_LOG_LANGUAGE;
+ else if (0 == ::strncasecmp(arg, "formatters", 10))
+ flag_bits &= ~LIBLLDB_LOG_DATAFORMATTERS;
+ else if (0 == ::strncasecmp(arg, "demangle", 8))
+ flag_bits &= ~LIBLLDB_LOG_DEMANGLE;
+ else {
+ feedback_strm->Printf("error: unrecognized log category '%s'\n",
+ arg);
+ ListLogCategories(feedback_strm);
+ return;
}
+ }
}
+ log->GetMask().Reset(flag_bits);
+ if (flag_bits == 0) {
+ log->SetStream(lldb::StreamSP());
+ g_log_enabled = false;
+ }
+ }
}
-Log *
-lldb_private::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **categories, Stream *feedback_strm)
-{
- // Try see if there already is a log - that way we can reuse its settings.
- // We could reuse the log in toto, but we don't know that the stream is the same.
- uint32_t flag_bits;
+Log *lldb_private::EnableLog(StreamSP &log_stream_sp, uint32_t log_options,
+ const char **categories, Stream *feedback_strm) {
+ // Try see if there already is a log - that way we can reuse its settings.
+ // We could reuse the log in toto, but we don't know that the stream is the
+ // same.
+ uint32_t flag_bits;
+ if (g_log != nullptr)
+ flag_bits = g_log->GetMask().Get();
+ else
+ flag_bits = 0;
+
+ // Now make a new log with this stream if one was provided
+ if (log_stream_sp) {
if (g_log != nullptr)
- flag_bits = g_log->GetMask().Get();
+ g_log->SetStream(log_stream_sp);
else
- flag_bits = 0;
+ g_log = new Log(log_stream_sp);
+ }
- // Now make a new log with this stream if one was provided
- if (log_stream_sp)
- {
- if (g_log != nullptr)
- g_log->SetStream(log_stream_sp);
- else
- g_log = new Log(log_stream_sp);
+ if (g_log != nullptr) {
+ for (size_t i = 0; categories[i] != nullptr; ++i) {
+ const char *arg = categories[i];
+
+ if (0 == ::strcasecmp(arg, "all"))
+ flag_bits |= LIBLLDB_LOG_ALL;
+ else if (0 == ::strcasecmp(arg, "api"))
+ flag_bits |= LIBLLDB_LOG_API;
+ else if (0 == ::strncasecmp(arg, "break", 5))
+ flag_bits |= LIBLLDB_LOG_BREAKPOINTS;
+ else if (0 == ::strcasecmp(arg, "commands"))
+ flag_bits |= LIBLLDB_LOG_COMMANDS;
+ else if (0 == ::strncasecmp(arg, "commu", 5))
+ flag_bits |= LIBLLDB_LOG_COMMUNICATION;
+ else if (0 == ::strncasecmp(arg, "conn", 4))
+ flag_bits |= LIBLLDB_LOG_CONNECTION;
+ else if (0 == ::strcasecmp(arg, "default"))
+ flag_bits |= LIBLLDB_LOG_DEFAULT;
+ else if (0 == ::strcasecmp(arg, "dyld"))
+ flag_bits |= LIBLLDB_LOG_DYNAMIC_LOADER;
+ else if (0 == ::strncasecmp(arg, "event", 5))
+ flag_bits |= LIBLLDB_LOG_EVENTS;
+ else if (0 == ::strncasecmp(arg, "expr", 4))
+ flag_bits |= LIBLLDB_LOG_EXPRESSIONS;
+ else if (0 == ::strncasecmp(arg, "host", 4))
+ flag_bits |= LIBLLDB_LOG_HOST;
+ else if (0 == ::strncasecmp(arg, "mmap", 4))
+ flag_bits |= LIBLLDB_LOG_MMAP;
+ else if (0 == ::strncasecmp(arg, "module", 6))
+ flag_bits |= LIBLLDB_LOG_MODULES;
+ else if (0 == ::strncasecmp(arg, "object", 6))
+ flag_bits |= LIBLLDB_LOG_OBJECT;
+ else if (0 == ::strcasecmp(arg, "os"))
+ flag_bits |= LIBLLDB_LOG_OS;
+ else if (0 == ::strcasecmp(arg, "platform"))
+ flag_bits |= LIBLLDB_LOG_PLATFORM;
+ else if (0 == ::strcasecmp(arg, "process"))
+ flag_bits |= LIBLLDB_LOG_PROCESS;
+ else if (0 == ::strcasecmp(arg, "script"))
+ flag_bits |= LIBLLDB_LOG_SCRIPT;
+ else if (0 == ::strcasecmp(arg, "state"))
+ flag_bits |= LIBLLDB_LOG_STATE;
+ else if (0 == ::strcasecmp(arg, "step"))
+ flag_bits |= LIBLLDB_LOG_STEP;
+ else if (0 == ::strncasecmp(arg, "symbol", 6))
+ flag_bits |= LIBLLDB_LOG_SYMBOLS;
+ else if (0 == ::strcasecmp(arg, "system-runtime"))
+ flag_bits |= LIBLLDB_LOG_SYSTEM_RUNTIME;
+ else if (0 == ::strcasecmp(arg, "target"))
+ flag_bits |= LIBLLDB_LOG_TARGET;
+ else if (0 == ::strncasecmp(arg, "temp", 4))
+ flag_bits |= LIBLLDB_LOG_TEMPORARY;
+ else if (0 == ::strcasecmp(arg, "thread"))
+ flag_bits |= LIBLLDB_LOG_THREAD;
+ else if (0 == ::strncasecmp(arg, "types", 5))
+ flag_bits |= LIBLLDB_LOG_TYPES;
+ else if (0 == ::strncasecmp(arg, "unwind", 6))
+ flag_bits |= LIBLLDB_LOG_UNWIND;
+ else if (0 == ::strcasecmp(arg, "verbose"))
+ flag_bits |= LIBLLDB_LOG_VERBOSE;
+ else if (0 == ::strncasecmp(arg, "watch", 5))
+ flag_bits |= LIBLLDB_LOG_WATCHPOINTS;
+ else if (0 == ::strcasecmp(arg, "jit"))
+ flag_bits |= LIBLLDB_LOG_JIT_LOADER;
+ else if (0 == ::strcasecmp(arg, "language"))
+ flag_bits |= LIBLLDB_LOG_LANGUAGE;
+ else if (0 == ::strncasecmp(arg, "formatters", 10))
+ flag_bits |= LIBLLDB_LOG_DATAFORMATTERS;
+ else if (0 == ::strncasecmp(arg, "demangle", 8))
+ flag_bits |= LIBLLDB_LOG_DEMANGLE;
+ else {
+ feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+ ListLogCategories(feedback_strm);
+ return g_log;
+ }
}
- if (g_log != nullptr)
- {
- for (size_t i = 0; categories[i] != nullptr; ++i)
- {
- const char *arg = categories[i];
-
- if (0 == ::strcasecmp(arg, "all")) flag_bits |= LIBLLDB_LOG_ALL;
- else if (0 == ::strcasecmp(arg, "api")) flag_bits |= LIBLLDB_LOG_API;
- else if (0 == ::strncasecmp(arg, "break", 5)) flag_bits |= LIBLLDB_LOG_BREAKPOINTS;
- else if (0 == ::strcasecmp(arg, "commands")) flag_bits |= LIBLLDB_LOG_COMMANDS;
- else if (0 == ::strncasecmp(arg, "commu", 5)) flag_bits |= LIBLLDB_LOG_COMMUNICATION;
- else if (0 == ::strncasecmp(arg, "conn", 4)) flag_bits |= LIBLLDB_LOG_CONNECTION;
- else if (0 == ::strcasecmp(arg, "default")) flag_bits |= LIBLLDB_LOG_DEFAULT;
- else if (0 == ::strcasecmp(arg, "dyld")) flag_bits |= LIBLLDB_LOG_DYNAMIC_LOADER;
- else if (0 == ::strncasecmp(arg, "event", 5)) flag_bits |= LIBLLDB_LOG_EVENTS;
- else if (0 == ::strncasecmp(arg, "expr", 4)) flag_bits |= LIBLLDB_LOG_EXPRESSIONS;
- else if (0 == ::strncasecmp(arg, "host", 4)) flag_bits |= LIBLLDB_LOG_HOST;
- else if (0 == ::strncasecmp(arg, "mmap", 4)) flag_bits |= LIBLLDB_LOG_MMAP;
- else if (0 == ::strncasecmp(arg, "module", 6)) flag_bits |= LIBLLDB_LOG_MODULES;
- else if (0 == ::strncasecmp(arg, "object", 6)) flag_bits |= LIBLLDB_LOG_OBJECT;
- else if (0 == ::strcasecmp(arg, "os")) flag_bits |= LIBLLDB_LOG_OS;
- else if (0 == ::strcasecmp(arg, "platform")) flag_bits |= LIBLLDB_LOG_PLATFORM;
- else if (0 == ::strcasecmp(arg, "process")) flag_bits |= LIBLLDB_LOG_PROCESS;
- else if (0 == ::strcasecmp(arg, "script")) flag_bits |= LIBLLDB_LOG_SCRIPT;
- else if (0 == ::strcasecmp(arg, "state")) flag_bits |= LIBLLDB_LOG_STATE;
- else if (0 == ::strcasecmp(arg, "step")) flag_bits |= LIBLLDB_LOG_STEP;
- else if (0 == ::strncasecmp(arg, "symbol", 6)) flag_bits |= LIBLLDB_LOG_SYMBOLS;
- else if (0 == ::strcasecmp(arg, "system-runtime")) flag_bits |= LIBLLDB_LOG_SYSTEM_RUNTIME;
- else if (0 == ::strcasecmp(arg, "target")) flag_bits |= LIBLLDB_LOG_TARGET;
- else if (0 == ::strncasecmp(arg, "temp", 4)) flag_bits |= LIBLLDB_LOG_TEMPORARY;
- else if (0 == ::strcasecmp(arg, "thread")) flag_bits |= LIBLLDB_LOG_THREAD;
- else if (0 == ::strncasecmp(arg, "types", 5)) flag_bits |= LIBLLDB_LOG_TYPES;
- else if (0 == ::strncasecmp(arg, "unwind", 6)) flag_bits |= LIBLLDB_LOG_UNWIND;
- else if (0 == ::strcasecmp(arg, "verbose")) flag_bits |= LIBLLDB_LOG_VERBOSE;
- else if (0 == ::strncasecmp(arg, "watch", 5)) flag_bits |= LIBLLDB_LOG_WATCHPOINTS;
- else if (0 == ::strcasecmp(arg, "jit")) flag_bits |= LIBLLDB_LOG_JIT_LOADER;
- else if (0 == ::strcasecmp(arg, "language")) flag_bits |= LIBLLDB_LOG_LANGUAGE;
- else if (0 == ::strncasecmp(arg, "formatters", 10)) flag_bits |= LIBLLDB_LOG_DATAFORMATTERS;
- else if (0 == ::strncasecmp(arg, "demangle", 8)) flag_bits |= LIBLLDB_LOG_DEMANGLE;
- else
- {
- feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
- ListLogCategories (feedback_strm);
- return g_log;
- }
- }
-
- g_log->GetMask().Reset(flag_bits);
- g_log->GetOptions().Reset(log_options);
- }
- g_log_enabled = true;
- return g_log;
+ g_log->GetMask().Reset(flag_bits);
+ g_log->GetOptions().Reset(log_options);
+ }
+ g_log_enabled = true;
+ return g_log;
}
-void
-lldb_private::ListLogCategories (Stream *strm)
-{
- strm->Printf("Logging categories for 'lldb':\n"
- " all - turn on all available logging categories\n"
- " api - enable logging of API calls and return values\n"
- " break - log breakpoints\n"
- " commands - log command argument parsing\n"
- " communication - log communication activities\n"
- " connection - log connection details\n"
- " default - enable the default set of logging categories for liblldb\n"
- " demangle - log mangled names to catch demangler crashes\n"
- " dyld - log shared library related activities\n"
- " events - log broadcaster, listener and event queue activities\n"
- " expr - log expressions\n"
- " formatters - log data formatters related activities\n"
- " host - log host activities\n"
- " jit - log JIT events in the target\n"
- " language - log language runtime events\n"
- " mmap - log mmap related activities\n"
- " module - log module activities such as when modules are created, destroyed, replaced, and more\n"
- " object - log object construction/destruction for important objects\n"
- " os - log OperatingSystem plugin related activities\n"
- " platform - log platform events and activities\n"
- " process - log process events and activities\n"
- " script - log events about the script interpreter\n"
- " state - log private and public process state changes\n"
- " step - log step related activities\n"
- " symbol - log symbol related issues and warnings\n"
- " system-runtime - log system runtime events\n"
- " target - log target events and activities\n"
- " thread - log thread events and activities\n"
- " types - log type system related activities\n"
- " unwind - log stack unwind activities\n"
- " verbose - enable verbose logging\n"
- " watch - log watchpoint related activities\n");
+void lldb_private::ListLogCategories(Stream *strm) {
+ strm->Printf(
+ "Logging categories for 'lldb':\n"
+ " all - turn on all available logging categories\n"
+ " api - enable logging of API calls and return values\n"
+ " break - log breakpoints\n"
+ " commands - log command argument parsing\n"
+ " communication - log communication activities\n"
+ " connection - log connection details\n"
+ " default - enable the default set of logging categories for liblldb\n"
+ " demangle - log mangled names to catch demangler crashes\n"
+ " dyld - log shared library related activities\n"
+ " events - log broadcaster, listener and event queue activities\n"
+ " expr - log expressions\n"
+ " formatters - log data formatters related activities\n"
+ " host - log host activities\n"
+ " jit - log JIT events in the target\n"
+ " language - log language runtime events\n"
+ " mmap - log mmap related activities\n"
+ " module - log module activities such as when modules are created, "
+ "destroyed, replaced, and more\n"
+ " object - log object construction/destruction for important objects\n"
+ " os - log OperatingSystem plugin related activities\n"
+ " platform - log platform events and activities\n"
+ " process - log process events and activities\n"
+ " script - log events about the script interpreter\n"
+ " state - log private and public process state changes\n"
+ " step - log step related activities\n"
+ " symbol - log symbol related issues and warnings\n"
+ " system-runtime - log system runtime events\n"
+ " target - log target events and activities\n"
+ " thread - log thread events and activities\n"
+ " types - log type system related activities\n"
+ " unwind - log stack unwind activities\n"
+ " verbose - enable verbose logging\n"
+ " watch - log watchpoint related activities\n");
}
Modified: lldb/trunk/source/Core/Mangled.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Mangled.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Core/Mangled.cpp (original)
+++ lldb/trunk/source/Core/Mangled.cpp Tue Sep 6 15:57:50 2016
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-
// FreeBSD9-STABLE requires this to know about size_t in cxxabi.h
#include <cstddef>
#if defined(_MSC_VER)
@@ -19,15 +18,16 @@
#ifdef LLDB_USE_BUILTIN_DEMANGLER
// Provide a fast-path demangler implemented in FastDemangle.cpp until it can
// replace the existing C++ demangler with a complete implementation
-#include "lldb/Core/FastDemangle.h"
#include "lldb/Core/CxaDemangle.h"
+#include "lldb/Core/FastDemangle.h"
#else
#include <cxxabi.h>
#endif
-
#include "llvm/ADT/DenseMap.h"
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Logging.h"
@@ -35,119 +35,104 @@
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/Timer.h"
-#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
-#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include <ctype.h>
-#include <string.h>
#include <stdlib.h>
-
+#include <string.h>
using namespace lldb_private;
-static inline Mangled::ManglingScheme
-cstring_mangling_scheme(const char *s)
-{
- if (s)
- {
- if (s[0] == '?')
- return Mangled::eManglingSchemeMSVC;
- if (s[0] == '_' && s[1] == 'Z')
- return Mangled::eManglingSchemeItanium;
- }
- return Mangled::eManglingSchemeNone;
+static inline Mangled::ManglingScheme cstring_mangling_scheme(const char *s) {
+ if (s) {
+ if (s[0] == '?')
+ return Mangled::eManglingSchemeMSVC;
+ if (s[0] == '_' && s[1] == 'Z')
+ return Mangled::eManglingSchemeItanium;
+ }
+ return Mangled::eManglingSchemeNone;
}
-static inline bool
-cstring_is_mangled(const char *s)
-{
- return cstring_mangling_scheme(s) != Mangled::eManglingSchemeNone;
+static inline bool cstring_is_mangled(const char *s) {
+ return cstring_mangling_scheme(s) != Mangled::eManglingSchemeNone;
}
static const ConstString &
-get_demangled_name_without_arguments (ConstString mangled, ConstString demangled)
-{
- // This pair is <mangled name, demangled name without function arguments>
- static std::pair<ConstString, ConstString> g_most_recent_mangled_to_name_sans_args;
-
- // Need to have the mangled & demangled names we're currently examining as statics
- // so we can return a const ref to them at the end of the func if we don't have
- // anything better.
- static ConstString g_last_mangled;
- static ConstString g_last_demangled;
-
- if (mangled && g_most_recent_mangled_to_name_sans_args.first == mangled)
- {
+get_demangled_name_without_arguments(ConstString mangled,
+ ConstString demangled) {
+ // This pair is <mangled name, demangled name without function arguments>
+ static std::pair<ConstString, ConstString>
+ g_most_recent_mangled_to_name_sans_args;
+
+ // Need to have the mangled & demangled names we're currently examining as
+ // statics
+ // so we can return a const ref to them at the end of the func if we don't
+ // have
+ // anything better.
+ static ConstString g_last_mangled;
+ static ConstString g_last_demangled;
+
+ if (mangled && g_most_recent_mangled_to_name_sans_args.first == mangled) {
+ return g_most_recent_mangled_to_name_sans_args.second;
+ }
+
+ g_last_demangled = demangled;
+ g_last_mangled = mangled;
+
+ const char *mangled_name_cstr = mangled.GetCString();
+
+ if (demangled && mangled_name_cstr && mangled_name_cstr[0]) {
+ if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' &&
+ (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure,
+ // typeinfo structure, and typeinfo
+ // mangled_name
+ mangled_name_cstr[2] != 'G' && // avoid guard variables
+ mangled_name_cstr[2] != 'Z')) // named local entities (if we eventually
+ // handle eSymbolTypeData, we will want
+ // this back)
+ {
+ CPlusPlusLanguage::MethodName cxx_method(demangled);
+ if (!cxx_method.GetBasename().empty()) {
+ std::string shortname;
+ if (!cxx_method.GetContext().empty())
+ shortname = cxx_method.GetContext().str() + "::";
+ shortname += cxx_method.GetBasename().str();
+ ConstString result(shortname.c_str());
+ g_most_recent_mangled_to_name_sans_args.first = mangled;
+ g_most_recent_mangled_to_name_sans_args.second = result;
return g_most_recent_mangled_to_name_sans_args.second;
+ }
}
+ }
- g_last_demangled = demangled;
- g_last_mangled = mangled;
-
- const char *mangled_name_cstr = mangled.GetCString();
-
- if (demangled && mangled_name_cstr && mangled_name_cstr[0])
- {
- if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' &&
- (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure, typeinfo structure, and typeinfo mangled_name
- mangled_name_cstr[2] != 'G' && // avoid guard variables
- mangled_name_cstr[2] != 'Z')) // named local entities (if we eventually handle eSymbolTypeData, we will want this back)
- {
- CPlusPlusLanguage::MethodName cxx_method (demangled);
- if (!cxx_method.GetBasename().empty())
- {
- std::string shortname;
- if (!cxx_method.GetContext().empty())
- shortname = cxx_method.GetContext().str() + "::";
- shortname += cxx_method.GetBasename().str();
- ConstString result(shortname.c_str());
- g_most_recent_mangled_to_name_sans_args.first = mangled;
- g_most_recent_mangled_to_name_sans_args.second = result;
- return g_most_recent_mangled_to_name_sans_args.second;
- }
- }
- }
-
- if (demangled)
- return g_last_demangled;
- return g_last_mangled;
+ if (demangled)
+ return g_last_demangled;
+ return g_last_mangled;
}
#pragma mark Mangled
//----------------------------------------------------------------------
// Default constructor
//----------------------------------------------------------------------
-Mangled::Mangled () :
- m_mangled(),
- m_demangled()
-{
-}
+Mangled::Mangled() : m_mangled(), m_demangled() {}
//----------------------------------------------------------------------
// Constructor with an optional string and a boolean indicating if it is
// the mangled version.
//----------------------------------------------------------------------
-Mangled::Mangled (const ConstString &s, bool mangled) :
- m_mangled(),
- m_demangled()
-{
- if (s)
- SetValue(s, mangled);
+Mangled::Mangled(const ConstString &s, bool mangled)
+ : m_mangled(), m_demangled() {
+ if (s)
+ SetValue(s, mangled);
}
-Mangled::Mangled (const ConstString &s) :
- m_mangled(),
- m_demangled()
-{
- if (s)
- SetValue(s);
+Mangled::Mangled(const ConstString &s) : m_mangled(), m_demangled() {
+ if (s)
+ SetValue(s);
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-Mangled::~Mangled ()
-{
-}
+Mangled::~Mangled() {}
//----------------------------------------------------------------------
// Convert to pointer operator. This allows code to check any Mangled
@@ -157,9 +142,8 @@ Mangled::~Mangled ()
// if (mangled)
// { ...
//----------------------------------------------------------------------
-Mangled::operator void* () const
-{
- return (m_mangled) ? const_cast<Mangled*>(this) : NULL;
+Mangled::operator void *() const {
+ return (m_mangled) ? const_cast<Mangled *>(this) : NULL;
}
//----------------------------------------------------------------------
@@ -170,83 +154,58 @@ Mangled::operator void* () const
// if (!file_spec)
// { ...
//----------------------------------------------------------------------
-bool
-Mangled::operator! () const
-{
- return !m_mangled;
-}
+bool Mangled::operator!() const { return !m_mangled; }
//----------------------------------------------------------------------
// Clear the mangled and demangled values.
//----------------------------------------------------------------------
-void
-Mangled::Clear ()
-{
- m_mangled.Clear();
- m_demangled.Clear();
+void Mangled::Clear() {
+ m_mangled.Clear();
+ m_demangled.Clear();
}
-
//----------------------------------------------------------------------
// Compare the string values.
//----------------------------------------------------------------------
-int
-Mangled::Compare (const Mangled& a, const Mangled& b)
-{
- return ConstString::Compare(a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled), a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled));
+int Mangled::Compare(const Mangled &a, const Mangled &b) {
+ return ConstString::Compare(
+ a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled),
+ a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled));
}
-
-
//----------------------------------------------------------------------
// Set the string value in this objects. If "mangled" is true, then
// the mangled named is set with the new value in "s", else the
// demangled name is set.
//----------------------------------------------------------------------
-void
-Mangled::SetValue (const ConstString &s, bool mangled)
-{
- if (s)
- {
- if (mangled)
- {
- m_demangled.Clear();
- m_mangled = s;
- }
- else
- {
- m_demangled = s;
- m_mangled.Clear();
- }
- }
- else
- {
- m_demangled.Clear();
- m_mangled.Clear();
+void Mangled::SetValue(const ConstString &s, bool mangled) {
+ if (s) {
+ if (mangled) {
+ m_demangled.Clear();
+ m_mangled = s;
+ } else {
+ m_demangled = s;
+ m_mangled.Clear();
}
+ } else {
+ m_demangled.Clear();
+ m_mangled.Clear();
+ }
}
-void
-Mangled::SetValue (const ConstString &name)
-{
- if (name)
- {
- if (cstring_is_mangled(name.GetCString()))
- {
- m_demangled.Clear();
- m_mangled = name;
- }
- else
- {
- m_demangled = name;
- m_mangled.Clear();
- }
- }
- else
- {
- m_demangled.Clear();
- m_mangled.Clear();
+void Mangled::SetValue(const ConstString &name) {
+ if (name) {
+ if (cstring_is_mangled(name.GetCString())) {
+ m_demangled.Clear();
+ m_mangled = name;
+ } else {
+ m_demangled = name;
+ m_mangled.Clear();
}
+ } else {
+ m_demangled.Clear();
+ m_mangled.Clear();
+ }
}
//----------------------------------------------------------------------
@@ -256,180 +215,165 @@ Mangled::SetValue (const ConstString &na
// new string value is supplied to this object, or until the end of the
// object's lifetime.
//----------------------------------------------------------------------
-const ConstString&
-Mangled::GetDemangledName (lldb::LanguageType language) const
-{
- // Check to make sure we have a valid mangled name and that we
- // haven't already decoded our mangled name.
- if (m_mangled && !m_demangled)
- {
- // We need to generate and cache the demangled name.
- Timer scoped_timer (LLVM_PRETTY_FUNCTION,
- "Mangled::GetDemangledName (m_mangled = %s)",
- m_mangled.GetCString());
-
- Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DEMANGLE);
-
- // Don't bother running anything that isn't mangled
- const char *mangled_name = m_mangled.GetCString();
- ManglingScheme mangling_scheme{cstring_mangling_scheme(mangled_name)};
- if (mangling_scheme != eManglingSchemeNone &&
- !m_mangled.GetMangledCounterpart(m_demangled))
- {
- // We didn't already mangle this name, demangle it and if all goes well
- // add it to our map.
- char *demangled_name = nullptr;
- switch (mangling_scheme)
- {
- case eManglingSchemeMSVC:
- {
+const ConstString &
+Mangled::GetDemangledName(lldb::LanguageType language) const {
+ // Check to make sure we have a valid mangled name and that we
+ // haven't already decoded our mangled name.
+ if (m_mangled && !m_demangled) {
+ // We need to generate and cache the demangled name.
+ Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ "Mangled::GetDemangledName (m_mangled = %s)",
+ m_mangled.GetCString());
+
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE);
+
+ // Don't bother running anything that isn't mangled
+ const char *mangled_name = m_mangled.GetCString();
+ ManglingScheme mangling_scheme{cstring_mangling_scheme(mangled_name)};
+ if (mangling_scheme != eManglingSchemeNone &&
+ !m_mangled.GetMangledCounterpart(m_demangled)) {
+ // We didn't already mangle this name, demangle it and if all goes well
+ // add it to our map.
+ char *demangled_name = nullptr;
+ switch (mangling_scheme) {
+ case eManglingSchemeMSVC: {
#if defined(_MSC_VER)
- if (log)
- log->Printf("demangle msvc: %s", mangled_name);
- const size_t demangled_length = 2048;
- demangled_name = static_cast<char *>(::malloc(demangled_length));
- ::ZeroMemory(demangled_name, demangled_length);
- DWORD result = ::UnDecorateSymbolName(mangled_name, demangled_name, demangled_length,
- UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected keywords
- UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc keywords
- UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications
- UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers
- UNDNAME_NO_MS_KEYWORDS // Strip all MS extension keywords
- );
- if (log)
- {
- if (demangled_name && demangled_name[0])
- log->Printf("demangled msvc: %s -> \"%s\"", mangled_name, demangled_name);
- else
- log->Printf("demangled msvc: %s -> error: 0x%" PRIx64, mangled_name, result);
- }
-
- if (result == 0)
- {
- free(demangled_name);
- demangled_name = nullptr;
- }
+ if (log)
+ log->Printf("demangle msvc: %s", mangled_name);
+ const size_t demangled_length = 2048;
+ demangled_name = static_cast<char *>(::malloc(demangled_length));
+ ::ZeroMemory(demangled_name, demangled_length);
+ DWORD result = ::UnDecorateSymbolName(
+ mangled_name, demangled_name, demangled_length,
+ UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected
+ // keywords
+ UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall,
+ // etc keywords
+ UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications
+ UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc
+ // specifiers
+ UNDNAME_NO_MS_KEYWORDS // Strip all MS extension keywords
+ );
+ if (log) {
+ if (demangled_name && demangled_name[0])
+ log->Printf("demangled msvc: %s -> \"%s\"", mangled_name,
+ demangled_name);
+ else
+ log->Printf("demangled msvc: %s -> error: 0x%" PRIx64, mangled_name,
+ result);
+ }
+
+ if (result == 0) {
+ free(demangled_name);
+ demangled_name = nullptr;
+ }
#endif
- break;
- }
- case eManglingSchemeItanium:
- {
+ break;
+ }
+ case eManglingSchemeItanium: {
#ifdef LLDB_USE_BUILTIN_DEMANGLER
- if (log)
- log->Printf("demangle itanium: %s", mangled_name);
- // Try to use the fast-path demangler first for the
- // performance win, falling back to the full demangler only
- // when necessary
- demangled_name = FastDemangle(mangled_name, m_mangled.GetLength());
- if (!demangled_name)
- demangled_name = __cxa_demangle(mangled_name, NULL, NULL, NULL);
+ if (log)
+ log->Printf("demangle itanium: %s", mangled_name);
+ // Try to use the fast-path demangler first for the
+ // performance win, falling back to the full demangler only
+ // when necessary
+ demangled_name = FastDemangle(mangled_name, m_mangled.GetLength());
+ if (!demangled_name)
+ demangled_name = __cxa_demangle(mangled_name, NULL, NULL, NULL);
#else
- demangled_name = abi::__cxa_demangle(mangled_name, NULL, NULL, NULL);
+ demangled_name = abi::__cxa_demangle(mangled_name, NULL, NULL, NULL);
#endif
- if (log)
- {
- if (demangled_name)
- log->Printf("demangled itanium: %s -> \"%s\"", mangled_name, demangled_name);
- else
- log->Printf("demangled itanium: %s -> error: failed to demangle", mangled_name);
- }
- break;
- }
- case eManglingSchemeNone:
- break;
- }
- if (demangled_name)
- {
- m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled);
- free(demangled_name);
- }
- }
- if (!m_demangled)
- {
- // Set the demangled string to the empty string to indicate we
- // tried to parse it once and failed.
- m_demangled.SetCString("");
+ if (log) {
+ if (demangled_name)
+ log->Printf("demangled itanium: %s -> \"%s\"", mangled_name,
+ demangled_name);
+ else
+ log->Printf("demangled itanium: %s -> error: failed to demangle",
+ mangled_name);
}
+ break;
+ }
+ case eManglingSchemeNone:
+ break;
+ }
+ if (demangled_name) {
+ m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled);
+ free(demangled_name);
+ }
+ }
+ if (!m_demangled) {
+ // Set the demangled string to the empty string to indicate we
+ // tried to parse it once and failed.
+ m_demangled.SetCString("");
}
+ }
- return m_demangled;
+ return m_demangled;
}
-
ConstString
-Mangled::GetDisplayDemangledName (lldb::LanguageType language) const
-{
- return GetDemangledName(language);
+Mangled::GetDisplayDemangledName(lldb::LanguageType language) const {
+ return GetDemangledName(language);
}
-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 Mangled::NameMatches(const RegularExpression ®ex,
+ 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;
}
//----------------------------------------------------------------------
// Get the demangled name if there is one, else return the mangled name.
//----------------------------------------------------------------------
-ConstString
-Mangled::GetName (lldb::LanguageType language, Mangled::NamePreference preference) const
-{
- if (preference == ePreferMangled && m_mangled)
- return m_mangled;
-
- ConstString demangled = GetDemangledName(language);
-
- if (preference == ePreferDemangledWithoutArguments)
- {
- return get_demangled_name_without_arguments (m_mangled, demangled);
- }
- if (preference == ePreferDemangled)
- {
- // Call the accessor to make sure we get a demangled name in case
- // it hasn't been demangled yet...
- if (demangled)
- return demangled;
- return m_mangled;
- }
- return demangled;
+ConstString Mangled::GetName(lldb::LanguageType language,
+ Mangled::NamePreference preference) const {
+ if (preference == ePreferMangled && m_mangled)
+ return m_mangled;
+
+ ConstString demangled = GetDemangledName(language);
+
+ if (preference == ePreferDemangledWithoutArguments) {
+ return get_demangled_name_without_arguments(m_mangled, demangled);
+ }
+ if (preference == ePreferDemangled) {
+ // Call the accessor to make sure we get a demangled name in case
+ // it hasn't been demangled yet...
+ if (demangled)
+ return demangled;
+ return m_mangled;
+ }
+ return demangled;
}
//----------------------------------------------------------------------
// Dump a Mangled object to stream "s". We don't force our
// demangled name to be computed currently (we don't use the accessor).
//----------------------------------------------------------------------
-void
-Mangled::Dump (Stream *s) const
-{
- if (m_mangled)
- {
- *s << ", mangled = " << m_mangled;
- }
- if (m_demangled)
- {
- const char * demangled = m_demangled.AsCString();
- s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");
- }
+void Mangled::Dump(Stream *s) const {
+ if (m_mangled) {
+ *s << ", mangled = " << m_mangled;
+ }
+ if (m_demangled) {
+ const char *demangled = m_demangled.AsCString();
+ s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");
+ }
}
//----------------------------------------------------------------------
// Dumps a debug version of this string with extra object and state
// information to stream "s".
//----------------------------------------------------------------------
-void
-Mangled::DumpDebug (Stream *s) const
-{
- s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void*) * 2),
- static_cast<const void*>(this));
- m_mangled.DumpDebug(s);
- s->Printf(", demangled = ");
- m_demangled.DumpDebug(s);
+void Mangled::DumpDebug(Stream *s) const {
+ s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void *) * 2),
+ static_cast<const void *>(this));
+ m_mangled.DumpDebug(s);
+ s->Printf(", demangled = ");
+ m_demangled.DumpDebug(s);
}
//----------------------------------------------------------------------
@@ -437,10 +381,8 @@ Mangled::DumpDebug (Stream *s) const
// includes the size of the objects it owns, and not the strings that
// it references because they are shared strings.
//----------------------------------------------------------------------
-size_t
-Mangled::MemorySize () const
-{
- return m_mangled.MemorySize() + m_demangled.MemorySize();
+size_t Mangled::MemorySize() const {
+ return m_mangled.MemorySize() + m_demangled.MemorySize();
}
//----------------------------------------------------------------------
@@ -451,37 +393,32 @@ Mangled::MemorySize () const
// different ways of mangling names from a given language, likewise the
// compilation units within those targets.
//----------------------------------------------------------------------
-lldb::LanguageType
-Mangled::GuessLanguage () const
-{
- ConstString mangled = GetMangledName();
- if (mangled)
- {
- if (GetDemangledName(lldb::eLanguageTypeUnknown))
- {
- const char *mangled_name = mangled.GetCString();
- if (CPlusPlusLanguage::IsCPPMangledName(mangled_name))
- return lldb::eLanguageTypeC_plus_plus;
- else if (ObjCLanguage::IsPossibleObjCMethodName(mangled_name))
- return lldb::eLanguageTypeObjC;
- }
+lldb::LanguageType Mangled::GuessLanguage() const {
+ ConstString mangled = GetMangledName();
+ if (mangled) {
+ if (GetDemangledName(lldb::eLanguageTypeUnknown)) {
+ const char *mangled_name = mangled.GetCString();
+ if (CPlusPlusLanguage::IsCPPMangledName(mangled_name))
+ return lldb::eLanguageTypeC_plus_plus;
+ else if (ObjCLanguage::IsPossibleObjCMethodName(mangled_name))
+ return lldb::eLanguageTypeObjC;
}
- return lldb::eLanguageTypeUnknown;
+ }
+ return lldb::eLanguageTypeUnknown;
}
//----------------------------------------------------------------------
// Dump OBJ to the supplied stream S.
//----------------------------------------------------------------------
-Stream&
-operator << (Stream& s, const Mangled& obj)
-{
- if (obj.GetMangledName())
- s << "mangled = '" << obj.GetMangledName() << "'";
-
- const ConstString& demangled = obj.GetDemangledName(lldb::eLanguageTypeUnknown);
- if (demangled)
- s << ", demangled = '" << demangled << '\'';
- else
- s << ", demangled = <error>";
- return s;
+Stream &operator<<(Stream &s, const Mangled &obj) {
+ if (obj.GetMangledName())
+ s << "mangled = '" << obj.GetMangledName() << "'";
+
+ const ConstString &demangled =
+ obj.GetDemangledName(lldb::eLanguageTypeUnknown);
+ if (demangled)
+ s << ", demangled = '" << demangled << '\'';
+ else
+ s << ", demangled = <error>";
+ return s;
}
More information about the lldb-commits
mailing list