[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(), &regex_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(), &regex_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(), &regex_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(), &regex_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 &reg_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 &reg_value) {
+  RegisterInfo reg_info;
+  if (GetRegisterInfo(reg_kind, reg_num, reg_info))
+    return ReadRegister(&reg_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 &reg_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 &reg_value) {
+  RegisterInfo reg_info;
+  if (GetRegisterInfo(reg_kind, reg_num, reg_info))
+    return WriteRegister(context, &reg_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, &reg_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 (&reg_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, &reg_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, &reg_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 &reg_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 &reg_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 &reg_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 &reg_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 &reg_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 &reg_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 &reg_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 &reg_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 &reg_kind,
+    uint32_t &reg_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 &reg_kind,
-                                                  uint32_t &reg_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 &reg_info)
-{
-    lldb::RegisterKind reg_kind;
-    uint32_t reg_num;
-    if (reg_ctx && GetBestRegisterKindAndNumber (&reg_info, reg_kind, reg_num))
-        return reg_ctx->ConvertRegisterKindToRegisterNumber (reg_kind, reg_num);
-    return LLDB_INVALID_REGNUM;
+EmulateInstruction::GetInternalRegisterNumber(RegisterContext *reg_ctx,
+                                              const RegisterInfo &reg_info) {
+  lldb::RegisterKind reg_kind;
+  uint32_t reg_num;
+  if (reg_ctx && GetBestRegisterKindAndNumber(&reg_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 &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;
 }
 
 //----------------------------------------------------------------------
 // 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