188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea# LLDB UI state in the Vim user interface.
388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleaimport os, re, sys
588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleaimport lldb
688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleaimport vim
788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleafrom vim_panes import *
888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleafrom vim_signs import *
988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
1088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleadef is_same_file(a, b):
1188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea  """ returns true if paths a and b are the same file """
1288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea  a = os.path.realpath(a)
1388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea  b = os.path.realpath(b)
1488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea  return a in b or b in a
1588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
1688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleaclass UI:
1788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea  def __init__(self):
1888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    """ Declare UI state variables """
1988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
2088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    # Default panes to display
2188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.defaultPanes = ['breakpoints', 'backtrace', 'locals', 'threads', 'registers', 'disassembly']
2288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
2388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    # map of tuples (filename, line) --> SBBreakpoint
2488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.markedBreakpoints = {}
2588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
2688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    # Currently shown signs
2788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.breakpointSigns = {}
2888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.pcSigns = []
2988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
3088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    # Container for panes
3188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.paneCol = PaneLayout()
3288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
3388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    # All possible LLDB panes
3488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.backtracePane = BacktracePane(self.paneCol)
3588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.threadPane = ThreadPane(self.paneCol)
3688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.disassemblyPane = DisassemblyPane(self.paneCol)
3788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.localsPane = LocalsPane(self.paneCol)
3888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.registersPane = RegistersPane(self.paneCol)
3988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.breakPane = BreakpointsPane(self.paneCol)
4088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
4188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea  def activate(self):
4288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    """ Activate UI: display default set of panes """
4388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.paneCol.prepare(self.defaultPanes)
4488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
4588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea  def get_user_buffers(self, filter_name=None):
4688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    """ Returns a list of buffers that are not a part of the LLDB UI. That is, they
4788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        are not contained in the PaneLayout object self.paneCol.
4888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    """
4988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    ret = []
5088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    for w in vim.windows:
5188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      b = w.buffer
5288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      if not self.paneCol.contains(b.name):
5388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        if filter_name is None or filter_name in b.name:
5488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea          ret.append(b)
5588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    return ret
5688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
5788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea  def update_pc(self, process, buffers, goto_file):
5888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    """ Place the PC sign on the PC location of each thread's selected frame """
5988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
6088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    def GetPCSourceLocation(thread):
6188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      """ Returns a tuple (thread_index, file, line, column) that represents where
6288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea          the PC sign should be placed for a thread.
6388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      """
6488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
6588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      frame = thread.GetSelectedFrame()
6688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      frame_num = frame.GetFrameID()
6788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      le = frame.GetLineEntry()
6888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      while not le.IsValid() and frame_num < thread.GetNumFrames():
6988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        frame_num += 1
7088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        le = thread.GetFrameAtIndex(frame_num).GetLineEntry()
7188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
7288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      if le.IsValid():
7388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        path = os.path.join(le.GetFileSpec().GetDirectory(), le.GetFileSpec().GetFilename())
7488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        return (thread.GetIndexID(), path, le.GetLine(), le.GetColumn())
7588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      return None
7688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
7788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
7888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    # Clear all existing PC signs
7988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    del_list = []
8088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    for sign in self.pcSigns:
8188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      sign.hide()
8288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      del_list.append(sign)
8388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    for sign in del_list:
8488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      self.pcSigns.remove(sign)
8588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      del sign
8688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
8788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    # Select a user (non-lldb) window
8888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    if not self.paneCol.selectWindow(False):
8988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      # No user window found; avoid clobbering by splitting
9088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      vim.command(":vsp")
9188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
9288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    # Show a PC marker for each thread
9388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    for thread in process:
9488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      loc = GetPCSourceLocation(thread)
9588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      if not loc:
9688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        # no valid source locations for PCs. hide all existing PC markers
9788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        continue
9888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
9988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      buf = None
10088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      (tid, fname, line, col) = loc
10188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      buffers = self.get_user_buffers(fname)
10288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      is_selected = thread.GetIndexID() == process.GetSelectedThread().GetIndexID()
10388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      if len(buffers) == 1:
10488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        buf = buffers[0]
10588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        if buf != vim.current.buffer:
10688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea          # Vim has an open buffer to the required file: select it
10788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea          vim.command('execute ":%db"' % buf.number)
10888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      elif is_selected and vim.current.buffer.name not in fname and os.path.exists(fname) and goto_file:
10988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        # FIXME: If current buffer is modified, vim will complain when we try to switch away.
11088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        #        Find a way to detect if the current buffer is modified, and...warn instead?
11188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        vim.command('execute ":e %s"' % fname)
11288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        buf = vim.current.buffer
11388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      elif len(buffers) > 1 and goto_file:
11488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        #FIXME: multiple open buffers match PC location
11588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        continue
11688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      else:
11788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        continue
11888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
11988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      self.pcSigns.append(PCSign(buf, line, is_selected))
12088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
12188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      if is_selected and goto_file:
12288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        # if the selected file has a PC marker, move the cursor there too
12388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        curname = vim.current.buffer.name
12488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        if curname is not None and is_same_file(curname, fname):
12588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea          move_cursor(line, 0)
12688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        elif move_cursor:
12788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea          print "FIXME: not sure where to move cursor because %s != %s " % (vim.current.buffer.name, fname)
12888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
12988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea  def update_breakpoints(self, target, buffers):
13088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    """ Decorates buffer with signs corresponding to breakpoints in target. """
13188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
13288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    def GetBreakpointLocations(bp):
13388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      """ Returns a list of tuples (resolved, filename, line) where a breakpoint was resolved. """
13488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      if not bp.IsValid():
13588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        sys.stderr.write("breakpoint is invalid, no locations")
13688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        return []
13788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
13888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      ret = []
13988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      numLocs = bp.GetNumLocations()
14088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      for i in range(numLocs):
14188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        loc = bp.GetLocationAtIndex(i)
14288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        desc = get_description(loc, lldb.eDescriptionLevelFull)
14388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        match = re.search('at\ ([^:]+):([\d]+)', desc)
14488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        try:
14588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea          lineNum = int(match.group(2).strip())
14688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea          ret.append((loc.IsResolved(), match.group(1), lineNum))
14788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        except ValueError as e:
14888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea          sys.stderr.write("unable to parse breakpoint location line number: '%s'" % match.group(2))
14988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea          sys.stderr.write(str(e))
15088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
15188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      return ret
15288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
15388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
15488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    if target is None or not target.IsValid():
15588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      return
15688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
15788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    needed_bps = {}
15888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    for bp_index in range(target.GetNumBreakpoints()):
15988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      bp = target.GetBreakpointAtIndex(bp_index)
16088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      locations = GetBreakpointLocations(bp)
16188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      for (is_resolved, file, line) in GetBreakpointLocations(bp):
16288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        for buf in buffers:
16388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea          if file in buf.name:
16488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea            needed_bps[(buf, line, is_resolved)] = bp
16588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
16688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    # Hide any signs that correspond with disabled breakpoints
16788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    del_list = []
16888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    for (b, l, r) in self.breakpointSigns:
16988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      if (b, l, r) not in needed_bps:
17088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        self.breakpointSigns[(b, l, r)].hide()
17188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        del_list.append((b, l, r))
17288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    for d in del_list:
17388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      del self.breakpointSigns[d]
17488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
17588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    # Show any signs for new breakpoints
17688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    for (b, l, r) in needed_bps:
17788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      bp = needed_bps[(b, l, r)]
17888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      if self.haveBreakpoint(b.name, l):
17988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        self.markedBreakpoints[(b.name, l)].append(bp)
18088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      else:
18188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        self.markedBreakpoints[(b.name, l)] = [bp]
18288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
18388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      if (b, l, r) not in self.breakpointSigns:
18488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        s = BreakpointSign(b, l, r)
18588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        self.breakpointSigns[(b, l, r)] = s
18688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
18788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea  def update(self, target, status, controller, goto_file=False):
18888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    """ Updates debugger info panels and breakpoint/pc marks and prints
18988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        status to the vim status line. If goto_file is True, the user's
19088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        cursor is moved to the source PC location in the selected frame.
19188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    """
19288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
19388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.paneCol.update(target, controller)
19488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.update_breakpoints(target, self.get_user_buffers())
19588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
19688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    if target is not None and target.IsValid():
19788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      process = target.GetProcess()
19888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      if process is not None and process.IsValid():
19988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea        self.update_pc(process, self.get_user_buffers, goto_file)
20088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
20188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    if status is not None and len(status) > 0:
20288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      print status
20388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
20488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea  def haveBreakpoint(self, file, line):
20588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    """ Returns True if we have a breakpoint at file:line, False otherwise  """
20688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    return (file, line) in self.markedBreakpoints
20788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
20888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea  def getBreakpoints(self, fname, line):
20988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    """ Returns the LLDB SBBreakpoint object at fname:line """
21088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    if self.haveBreakpoint(fname, line):
21188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      return self.markedBreakpoints[(fname, line)]
21288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    else:
21388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      return None
21488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
21588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea  def deleteBreakpoints(self, name, line):
21688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    del self.markedBreakpoints[(name, line)]
21788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
21888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea  def showWindow(self, name):
21988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    """ Shows (un-hides) window pane specified by name """
22088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    if not self.paneCol.havePane(name):
22188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      sys.stderr.write("unknown window: %s" % name)
22288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      return False
22388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.paneCol.prepare([name])
22488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    return True
22588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
22688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea  def hideWindow(self, name):
22788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    """ Hides window pane specified by name """
22888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    if not self.paneCol.havePane(name):
22988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      sys.stderr.write("unknown window: %s" % name)
23088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea      return False
23188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    self.paneCol.hide([name])
23288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea    return True
23388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea
23488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleaglobal ui
23588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleaui = UI()
236