
#
# This file defines the layer that talks to lldb
#

import os, re, sys
import lldb
import vim
from vim_ui import UI

# =================================================
# Convert some enum value to its string counterpart
# =================================================

# Shamelessly copy/pasted from lldbutil.py in the test suite
def state_type_to_str(enum):
  """Returns the stateType string given an enum."""
  if enum == lldb.eStateInvalid:
    return "invalid"
  elif enum == lldb.eStateUnloaded:
    return "unloaded"
  elif enum == lldb.eStateConnected:
    return "connected"
  elif enum == lldb.eStateAttaching:
    return "attaching"
  elif enum == lldb.eStateLaunching:
    return "launching"
  elif enum == lldb.eStateStopped:
    return "stopped"
  elif enum == lldb.eStateRunning:
    return "running"
  elif enum == lldb.eStateStepping:
    return "stepping"
  elif enum == lldb.eStateCrashed:
    return "crashed"
  elif enum == lldb.eStateDetached:
    return "detached"
  elif enum == lldb.eStateExited:
    return "exited"
  elif enum == lldb.eStateSuspended:
    return "suspended"
  else:
    raise Exception("Unknown StateType enum")

class StepType:
  INSTRUCTION = 1
  INSTRUCTION_OVER = 2
  INTO = 3
  OVER = 4
  OUT = 5

class LLDBController(object):
  """ Handles Vim and LLDB events such as commands and lldb events. """

  # Timeouts (sec) for waiting on new events. Because vim is not multi-threaded, we are restricted to
  # servicing LLDB events from the main UI thread. Usually, we only process events that are already
  # sitting on the queue. But in some situations (when we are expecting an event as a result of some
  # user interaction) we want to wait for it. The constants below set these wait period in which the
  # Vim UI is "blocked". Lower numbers will make Vim more responsive, but LLDB will be delayed and higher
  # numbers will mean that LLDB events are processed faster, but the Vim UI may appear less responsive at
  # times.
  eventDelayStep = 2
  eventDelayLaunch = 1
  eventDelayContinue = 1

  def __init__(self):
    """ Creates the LLDB SBDebugger object and initializes the UI class. """
    self.target = None
    self.process = None
    self.load_dependent_modules = True

    self.dbg = lldb.SBDebugger.Create()
    self.commandInterpreter = self.dbg.GetCommandInterpreter()

    self.ui = UI()

  def completeCommand(self, a, l, p):
    """ Returns a list of viable completions for command a with length l and cursor at p  """

    assert l[0] == 'L'
    # Remove first 'L' character that all commands start with
    l = l[1:]

    # Adjust length as string has 1 less character
    p = int(p) - 1

    result = lldb.SBStringList()
    num = self.commandInterpreter.HandleCompletion(l, p, 1, -1, result)

    if num == -1:
      # FIXME: insert completion character... what's a completion character?
      pass
    elif num == -2:
      # FIXME: replace line with result.GetStringAtIndex(0)
      pass

    if result.GetSize() > 0:
      results =  filter(None, [result.GetStringAtIndex(x) for x in range(result.GetSize())])
      return results
    else:
      return []

  def doStep(self, stepType):
    """ Perform a step command and block the UI for eventDelayStep seconds in order to process
        events on lldb's event queue.
        FIXME: if the step does not complete in eventDelayStep seconds, we relinquish control to
               the main thread to avoid the appearance of a "hang". If this happens, the UI will
               update whenever; usually when the user moves the cursor. This is somewhat annoying.
    """
    if not self.process:
      sys.stderr.write("No process to step")
      return
    
    t = self.process.GetSelectedThread()
    if stepType == StepType.INSTRUCTION:
      t.StepInstruction(False)
    if stepType == StepType.INSTRUCTION_OVER:
      t.StepInstruction(True)
    elif stepType == StepType.INTO:
      t.StepInto()
    elif stepType == StepType.OVER:
      t.StepOver()
    elif stepType == StepType.OUT:
      t.StepOut()

    self.processPendingEvents(self.eventDelayStep, True)

  def doSelect(self, command, args):
    """ Like doCommand, but suppress output when "select" is the first argument."""
    a = args.split(' ')
    return self.doCommand(command, args, "select" != a[0], True)

  def doProcess(self, args):
    """ Handle 'process' command. If 'launch' is requested, use doLaunch() instead
        of the command interpreter to start the inferior process.
    """
    a = args.split(' ')
    if len(args) == 0 or (len(a) > 0 and a[0] != 'launch'):
      self.doCommand("process", args)
      #self.ui.update(self.target, "", self)
    else:
      self.doLaunch('-s' not in args, "")

  def doAttach(self, process_name):
    """ Handle process attach.  """
    error = lldb.SBError()
    
    self.processListener = lldb.SBListener("process_event_listener")
    self.target = self.dbg.CreateTarget('')
    self.process = self.target.AttachToProcessWithName(self.processListener, process_name, False, error)
    if not error.Success():
      sys.stderr.write("Error during attach: " + str(error))
      return

    self.ui.activate()
    self.pid = self.process.GetProcessID()

    print "Attached to %s (pid=%d)" % (process_name, self.pid)

  def doDetach(self):
    if self.process is not None and self.process.IsValid():
      pid = self.process.GetProcessID()
      state = state_type_to_str(self.process.GetState())
      self.process.Detach()
      self.processPendingEvents(self.eventDelayLaunch)

  def doLaunch(self, stop_at_entry, args):
    """ Handle process launch.  """
    error = lldb.SBError()

    fs = self.target.GetExecutable()
    exe = os.path.join(fs.GetDirectory(), fs.GetFilename())
    if self.process is not None and self.process.IsValid():
      pid = self.process.GetProcessID()
      state = state_type_to_str(self.process.GetState())
      self.process.Destroy()

    launchInfo = lldb.SBLaunchInfo(args.split(' '))
    self.process = self.target.Launch(launchInfo, error)
    if not error.Success():
      sys.stderr.write("Error during launch: " + str(error))
      return

    # launch succeeded, store pid and add some event listeners
    self.pid = self.process.GetProcessID()
    self.processListener = lldb.SBListener("process_event_listener")
    self.process.GetBroadcaster().AddListener(self.processListener, lldb.SBProcess.eBroadcastBitStateChanged)

    print "Launched %s %s (pid=%d)" % (exe, args, self.pid)

    if not stop_at_entry:
      self.doContinue()
    else:
      self.processPendingEvents(self.eventDelayLaunch)

  def doTarget(self, args):
    """ Pass target command to interpreter, except if argument is not one of the valid options, or
        is create, in which case try to create a target with the argument as the executable. For example:
          target list        ==> handled by interpreter
          target create blah ==> custom creation of target 'blah'
          target blah        ==> also creates target blah
    """
    target_args = [#"create",
                   "delete",
                   "list",
                   "modules",
                   "select",
                   "stop-hook",
                   "symbols",
                   "variable"]

    a = args.split(' ')
    if len(args) == 0 or (len(a) > 0 and a[0] in target_args):
      self.doCommand("target", args)
      return
    elif len(a) > 1 and a[0] == "create":
      exe = a[1]
    elif len(a) == 1 and a[0] not in target_args:
      exe = a[0]

    err = lldb.SBError()
    self.target = self.dbg.CreateTarget(exe, None, None, self.load_dependent_modules, err)
    if not self.target:
      sys.stderr.write("Error creating target %s. %s" % (str(exe), str(err)))
      return

    self.ui.activate()
    self.ui.update(self.target, "created target %s" % str(exe), self)

  def doContinue(self):
    """ Handle 'contiue' command.
        FIXME: switch to doCommand("continue", ...) to handle -i ignore-count param.
    """
    if not self.process or not self.process.IsValid():
      sys.stderr.write("No process to continue")
      return

    self.process.Continue()
    self.processPendingEvents(self.eventDelayContinue)

  def doBreakpoint(self, args):
    """ Handle breakpoint command with command interpreter, except if the user calls
        "breakpoint" with no other args, in which case add a breakpoint at the line
        under the cursor.
    """
    a = args.split(' ')
    if len(args) == 0:
      show_output = False

      # User called us with no args, so toggle the bp under cursor
      cw = vim.current.window
      cb = vim.current.buffer
      name = cb.name
      line = cw.cursor[0]

      # Since the UI is responsbile for placing signs at bp locations, we have to
      # ask it if there already is one or more breakpoints at (file, line)...
      if self.ui.haveBreakpoint(name, line):
        bps = self.ui.getBreakpoints(name, line)
        args = "delete %s" % " ".join([str(b.GetID()) for b in bps])
        self.ui.deleteBreakpoints(name, line)
      else:
        args = "set -f %s -l %d" % (name, line)
    else:
      show_output = True

    self.doCommand("breakpoint", args, show_output)
    return

  def doRefresh(self):
    """ process pending events and update UI on request """
    status = self.processPendingEvents()

  def doShow(self, name):
    """ handle :Lshow <name> """
    if not name:
      self.ui.activate()
      return

    if self.ui.showWindow(name):
      self.ui.update(self.target, "", self)

  def doHide(self, name):
    """ handle :Lhide <name> """
    if self.ui.hideWindow(name):
      self.ui.update(self.target, "", self)

  def doExit(self):
    self.dbg.Terminate()
    self.dbg = None

  def getCommandResult(self, command, command_args):
    """ Run cmd in the command interpreter and returns (success, output) """
    result = lldb.SBCommandReturnObject()
    cmd = "%s %s" % (command, command_args)

    self.commandInterpreter.HandleCommand(cmd, result)
    return (result.Succeeded(), result.GetOutput() if result.Succeeded() else result.GetError())

  def doCommand(self, command, command_args, print_on_success = True, goto_file=False):
    """ Run cmd in interpreter and print result (success or failure) on the vim status line. """
    (success, output) = self.getCommandResult(command, command_args)
    if success:
      self.ui.update(self.target, "", self, goto_file)
      if len(output) > 0 and print_on_success:
        print output
    else:
      sys.stderr.write(output)

  def getCommandOutput(self, command, command_args=""):
    """ runs cmd in the command interpreter andreturns (status, result) """
    result = lldb.SBCommandReturnObject()
    cmd = "%s %s" % (command, command_args)
    self.commandInterpreter.HandleCommand(cmd, result)
    return (result.Succeeded(), result.GetOutput() if result.Succeeded() else result.GetError())

  def processPendingEvents(self, wait_seconds=0, goto_file=True):
    """ Handle any events that are queued from the inferior.
        Blocks for at most wait_seconds, or if wait_seconds == 0,
        process only events that are already queued.
    """

    status = None
    num_events_handled = 0

    if self.process is not None:
      event = lldb.SBEvent()
      old_state = self.process.GetState()
      new_state = None
      done = False
      if old_state == lldb.eStateInvalid or old_state == lldb.eStateExited:
        # Early-exit if we are in 'boring' states
        pass
      else:
        while not done and self.processListener is not None:
          if not self.processListener.PeekAtNextEvent(event):
            if wait_seconds > 0:
              # No events on the queue, but we are allowed to wait for wait_seconds
              # for any events to show up.
              self.processListener.WaitForEvent(wait_seconds, event)
              new_state = lldb.SBProcess.GetStateFromEvent(event)

              num_events_handled += 1

            done = not self.processListener.PeekAtNextEvent(event)
          else:
            # An event is on the queue, process it here.
            self.processListener.GetNextEvent(event)
            new_state = lldb.SBProcess.GetStateFromEvent(event)

            # continue if stopped after attaching
            if old_state == lldb.eStateAttaching and new_state == lldb.eStateStopped:
              self.process.Continue()

            # If needed, perform any event-specific behaviour here
            num_events_handled += 1

    if num_events_handled == 0:
      pass
    else:
      if old_state == new_state:
        status = ""
      self.ui.update(self.target, status, self, goto_file)


def returnCompleteCommand(a, l, p):
  """ Returns a "\n"-separated string with possible completion results
      for command a with length l and cursor at p.
  """
  separator = "\n"
  results = ctrl.completeCommand(a, l, p)
  vim.command('return "%s%s"' % (separator.join(results), separator))

def returnCompleteWindow(a, l, p):
  """ Returns a "\n"-separated string with possible completion results
      for commands that expect a window name parameter (like hide/show).
      FIXME: connect to ctrl.ui instead of hardcoding the list here
  """
  separator = "\n"
  results = ['breakpoints', 'backtrace', 'disassembly', 'locals', 'threads', 'registers']
  vim.command('return "%s%s"' % (separator.join(results), separator))

global ctrl
ctrl = LLDBController()
