summaryrefslogtreecommitdiff
path: root/runtime/pack
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2018-12-02 13:47:03 +0100
committerBram Moolenaar <Bram@vim.org>2018-12-02 13:47:03 +0100
commit5378e1cf0a05121bfa76df2279944ad3b0b5ce4f (patch)
tree6f3482e0baaccdf668c772496fe750b1a217f24b /runtime/pack
parented8bc78d2386d22656ba1d3e5cf739dd12964dce (diff)
downloadvim-git-5378e1cf0a05121bfa76df2279944ad3b0b5ce4f.tar.gz
patch 8.1.0557: Termdebug: gdb may use X.Y for breakpoint numberv8.1.0557
Problem: Termdebug: gdb may use X.Y for breakpoint number. Solution: Handle X.Y breakpoint numbers. (Yasuhiro Matsumoto, close #3641)
Diffstat (limited to 'runtime/pack')
-rw-r--r--runtime/pack/dist/opt/termdebug/plugin/termdebug.vim182
1 files changed, 102 insertions, 80 deletions
diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
index 9f4c26a0e..61de9a34b 100644
--- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
+++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
@@ -73,6 +73,13 @@ let s:pc_id = 12
let s:break_id = 13 " breakpoint number is added to this
let s:stopped = 1
+" Take a breakpoint number as used by GDB and turn it into an integer.
+" The breakpoint may contain a dot: 123.4
+func s:Breakpoint2SignNumber(nr)
+ let t = split(a:nr, '\.')
+ return t[0] * 1000 + (len(t) == 2 ? t[1] : 0)
+endfunction
+
func s:Highlight(init, old, new)
let default = a:init ? 'default ' : ''
if a:new ==# 'light' && a:old !=# 'light'
@@ -138,9 +145,9 @@ endfunc
func s:StartDebug_term(dict)
" Open a terminal window without a job, to run the debugged program in.
let s:ptybuf = term_start('NONE', {
- \ 'term_name': 'debugged program',
- \ 'vertical': s:vertical,
- \ })
+ \ 'term_name': 'debugged program',
+ \ 'vertical': s:vertical,
+ \ })
if s:ptybuf == 0
echoerr 'Failed to open the program terminal window'
return
@@ -155,10 +162,10 @@ func s:StartDebug_term(dict)
" Create a hidden terminal window to communicate with gdb
let s:commbuf = term_start('NONE', {
- \ 'term_name': 'gdb communication',
- \ 'out_cb': function('s:CommOutput'),
- \ 'hidden': 1,
- \ })
+ \ 'term_name': 'gdb communication',
+ \ 'out_cb': function('s:CommOutput'),
+ \ 'hidden': 1,
+ \ })
if s:commbuf == 0
echoerr 'Failed to open the communication terminal window'
exe 'bwipe! ' . s:ptybuf
@@ -174,9 +181,9 @@ func s:StartDebug_term(dict)
let cmd = [g:termdebugger, '-quiet', '-tty', pty] + gdb_args
call ch_log('executing "' . join(cmd) . '"')
let s:gdbbuf = term_start(cmd, {
- \ 'exit_cb': function('s:EndTermDebug'),
- \ 'term_finish': 'close',
- \ })
+ \ 'exit_cb': function('s:EndTermDebug'),
+ \ 'term_finish': 'close',
+ \ })
if s:gdbbuf == 0
echoerr 'Failed to open the gdb terminal window'
exe 'bwipe! ' . s:ptybuf
@@ -200,18 +207,18 @@ func s:StartDebug_term(dict)
let response = ''
for lnum in range(1,200)
if term_getline(s:gdbbuf, lnum) =~ 'new-ui mi '
- " response can be in the same line or the next line
- let response = term_getline(s:gdbbuf, lnum) . term_getline(s:gdbbuf, lnum + 1)
- if response =~ 'Undefined command'
- echoerr 'Sorry, your gdb is too old, gdb 7.12 is required'
- exe 'bwipe! ' . s:ptybuf
- exe 'bwipe! ' . s:commbuf
- return
- endif
- if response =~ 'New UI allocated'
- " Success!
- break
- endif
+ " response can be in the same line or the next line
+ let response = term_getline(s:gdbbuf, lnum) . term_getline(s:gdbbuf, lnum + 1)
+ if response =~ 'Undefined command'
+ echoerr 'Sorry, your gdb is too old, gdb 7.12 is required'
+ exe 'bwipe! ' . s:ptybuf
+ exe 'bwipe! ' . s:commbuf
+ return
+ endif
+ if response =~ 'New UI allocated'
+ " Success!
+ break
+ endif
endif
endfor
if response =~ 'New UI allocated'
@@ -268,9 +275,9 @@ func s:StartDebug_prompt(dict)
call ch_log('executing "' . join(cmd) . '"')
let s:gdbjob = job_start(cmd, {
- \ 'exit_cb': function('s:EndPromptDebug'),
- \ 'out_cb': function('s:GdbOutCallback'),
- \ })
+ \ 'exit_cb': function('s:EndPromptDebug'),
+ \ 'out_cb': function('s:GdbOutCallback'),
+ \ })
if job_status(s:gdbjob) != "run"
echoerr 'Failed to start gdb'
exe 'bwipe! ' . s:promptbuf
@@ -295,8 +302,8 @@ func s:StartDebug_prompt(dict)
" Unix: Run the debugged program in a terminal window. Open it below the
" gdb window.
belowright let s:ptybuf = term_start('NONE', {
- \ 'term_name': 'debugged program',
- \ })
+ \ 'term_name': 'debugged program',
+ \ })
if s:ptybuf == 0
echoerr 'Failed to open the program terminal window'
call job_stop(s:gdbjob)
@@ -353,7 +360,8 @@ func s:StartDebugCommon(dict)
endif
endif
- " Contains breakpoints that have been placed, key is the number.
+ " Contains breakpoints that have been placed, key is a string with the GDB
+ " breakpoint number.
let s:breakpoints = {}
augroup TermDebug
@@ -466,9 +474,9 @@ func s:DecodeMessage(quotedText)
if a:quotedText[i] == '\'
let i += 1
if a:quotedText[i] == 'n'
- " drop \n
- let i += 1
- continue
+ " drop \n
+ let i += 1
+ continue
endif
endif
let result .= a:quotedText[i]
@@ -479,6 +487,9 @@ endfunc
" Extract the "name" value from a gdb message with fullname="name".
func s:GetFullname(msg)
+ if a:msg !~ 'fullname'
+ return ''
+ endif
let name = s:DecodeMessage(substitute(a:msg, '.*fullname=', '', ''))
if has('win32') && name =~ ':\\\\'
" sometimes the name arrives double-escaped
@@ -549,17 +560,17 @@ func s:CommOutput(chan, msg)
endif
if msg != ''
if msg =~ '^\(\*stopped\|\*running\|=thread-selected\)'
- call s:HandleCursor(msg)
+ call s:HandleCursor(msg)
elseif msg =~ '^\^done,bkpt=' || msg =~ '^=breakpoint-created,'
- call s:HandleNewBreakpoint(msg)
+ call s:HandleNewBreakpoint(msg)
elseif msg =~ '^=breakpoint-deleted,'
- call s:HandleBreakpointDelete(msg)
+ call s:HandleBreakpointDelete(msg)
elseif msg =~ '^=thread-group-started'
- call s:HandleProgramRun(msg)
+ call s:HandleProgramRun(msg)
elseif msg =~ '^\^done,value='
- call s:HandleEvaluate(msg)
+ call s:HandleEvaluate(msg)
elseif msg =~ '^\^error,msg='
- call s:HandleError(msg)
+ call s:HandleError(msg)
endif
endif
endfor
@@ -650,12 +661,12 @@ func s:DeleteCommands()
let curwinid = win_getid(winnr())
for winid in s:winbar_winids
if win_gotoid(winid)
- aunmenu WinBar.Step
- aunmenu WinBar.Next
- aunmenu WinBar.Finish
- aunmenu WinBar.Cont
- aunmenu WinBar.Stop
- aunmenu WinBar.Eval
+ aunmenu WinBar.Step
+ aunmenu WinBar.Next
+ aunmenu WinBar.Finish
+ aunmenu WinBar.Cont
+ aunmenu WinBar.Stop
+ aunmenu WinBar.Eval
endif
endfor
call win_gotoid(curwinid)
@@ -673,7 +684,7 @@ func s:DeleteCommands()
exe 'sign unplace ' . s:pc_id
for key in keys(s:breakpoints)
- exe 'sign unplace ' . (s:break_id + key)
+ exe 'sign unplace ' . (s:break_id + s:Breakpoint2SignNumber(key))
endfor
unlet s:breakpoints
@@ -700,7 +711,7 @@ func s:SetBreakpoint()
endif
" Use the fname:lnum format, older gdb can't handle --source.
call s:SendCommand('-break-insert '
- \ . fnameescape(expand('%:p')) . ':' . line('.'))
+ \ . fnameescape(expand('%:p')) . ':' . line('.'))
if do_continue
call s:SendCommand('-exec-continue')
endif
@@ -714,7 +725,7 @@ func s:ClearBreakpoint()
if val['fname'] == fname && val['lnum'] == lnum
call s:SendCommand('-break-delete ' . key)
" Assume this always wors, the reply is simply "^done".
- exe 'sign unplace ' . (s:break_id + key)
+ exe 'sign unplace ' . (s:break_id + s:Breakpoint2SignNumber(key))
unlet s:breakpoints[key]
break
endif
@@ -839,14 +850,14 @@ func s:HandleCursor(msg)
if lnum =~ '^[0-9]*$'
call s:GotoSourcewinOrCreateIt()
if expand('%:p') != fnamemodify(fname, ':p')
- if &modified
- " TODO: find existing window
- exe 'split ' . fnameescape(fname)
- let s:sourcewin = win_getid(winnr())
- call s:InstallWinbar()
- else
- exe 'edit ' . fnameescape(fname)
- endif
+ if &modified
+ " TODO: find existing window
+ exe 'split ' . fnameescape(fname)
+ let s:sourcewin = win_getid(winnr())
+ call s:InstallWinbar()
+ else
+ exe 'edit ' . fnameescape(fname)
+ endif
endif
exe lnum
exe 'sign unplace ' . s:pc_id
@@ -865,10 +876,14 @@ let s:BreakpointSigns = []
func s:CreateBreakpoint(nr)
if index(s:BreakpointSigns, a:nr) == -1
call add(s:BreakpointSigns, a:nr)
- exe "sign define debugBreakpoint" . a:nr . " text=" . a:nr . " texthl=debugBreakpoint"
+ exe "sign define debugBreakpoint" . a:nr . " text=" . substitute(a:nr, '\..*', '', '') . " texthl=debugBreakpoint"
endif
endfunc
+func s:SplitMsg(s)
+ return split(a:s, '{\%([a-z-]\+=[^,]\+,*\)\+}\zs')
+endfunction
+
" Handle setting a breakpoint
" Will update the sign that shows the breakpoint
func s:HandleNewBreakpoint(msg)
@@ -876,50 +891,57 @@ func s:HandleNewBreakpoint(msg)
" a watch does not have a file name
return
endif
+ for msg in s:SplitMsg(a:msg)
+ let fname = s:GetFullname(msg)
+ if empty(fname)
+ continue
+ endif
+ let nr = substitute(msg, '.*number="\([0-9.]*\)\".*', '\1', '')
+ if empty(nr)
+ return
+ endif
+ call s:CreateBreakpoint(nr)
- let nr = substitute(a:msg, '.*number="\([0-9]*\)".*', '\1', '') + 0
- if nr == 0
- return
- endif
- call s:CreateBreakpoint(nr)
-
- if has_key(s:breakpoints, nr)
- let entry = s:breakpoints[nr]
- else
- let entry = {}
- let s:breakpoints[nr] = entry
- endif
+ if has_key(s:breakpoints, nr)
+ let entry = s:breakpoints[nr]
+ else
+ let entry = {}
+ let s:breakpoints[nr] = entry
+ endif
- let fname = s:GetFullname(a:msg)
- let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '')
- let entry['fname'] = fname
- let entry['lnum'] = lnum
+ let lnum = substitute(msg, '.*line="\([^"]*\)".*', '\1', '')
+ let entry['fname'] = fname
+ let entry['lnum'] = lnum
- if bufloaded(fname)
- call s:PlaceSign(nr, entry)
- endif
+ if bufloaded(fname)
+ call s:PlaceSign(nr, entry)
+ endif
+ endfor
endfunc
func s:PlaceSign(nr, entry)
- exe 'sign place ' . (s:break_id + a:nr) . ' line=' . a:entry['lnum'] . ' name=debugBreakpoint' . a:nr . ' file=' . a:entry['fname']
+ exe 'sign place ' . (s:break_id + s:Breakpoint2SignNumber(a:nr)) . ' line=' . a:entry['lnum'] . ' name=debugBreakpoint' . a:nr . ' file=' . a:entry['fname']
let a:entry['placed'] = 1
endfunc
" Handle deleting a breakpoint
" Will remove the sign that shows the breakpoint
func s:HandleBreakpointDelete(msg)
- let nr = substitute(a:msg, '.*id="\([0-9]*\)\".*', '\1', '') + 0
- if nr == 0
+ let key = substitute(a:msg, '.*id="\([0-9.]*\)\".*', '\1', '')
+ if empty(key)
return
endif
- if has_key(s:breakpoints, nr)
+ for [nr, entry] in items(s:breakpoints)
+ if stridx(nr, key) != 0
+ continue
+ endif
let entry = s:breakpoints[nr]
if has_key(entry, 'placed')
- exe 'sign unplace ' . (s:break_id + nr)
+ exe 'sign unplace ' . (s:break_id + s:Breakpoint2SignNumber(nr))
unlet entry['placed']
endif
unlet s:breakpoints[nr]
- endif
+ endfor
endfunc
" Handle the debugged program starting to run.