1fe386641SBram Moolenaar" Debugger plugin using gdb. 2c572da5fSBram Moolenaar" 3c572da5fSBram Moolenaar" WORK IN PROGRESS - much doesn't work yet 4c572da5fSBram Moolenaar" 5fe386641SBram Moolenaar" Open two visible terminal windows: 6c572da5fSBram Moolenaar" 1. run a pty, as with ":term NONE" 7c572da5fSBram Moolenaar" 2. run gdb, passing the pty 8fe386641SBram Moolenaar" The current window is used to view source code and follows gdb. 9fe386641SBram Moolenaar" 10fe386641SBram Moolenaar" A third terminal window is hidden, it is used for communication with gdb. 11fe386641SBram Moolenaar" 12fe386641SBram Moolenaar" The communication with gdb uses GDB/MI. See: 13fe386641SBram Moolenaar" https://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI.html 14c572da5fSBram Moolenaar" 15c572da5fSBram Moolenaar" Author: Bram Moolenaar 16fe386641SBram Moolenaar" Copyright: Vim license applies, see ":help license" 17c572da5fSBram Moolenaar 1837c64c78SBram Moolenaar" In case this gets loaded twice. 1937c64c78SBram Moolenaarif exists(':Termdebug') 2037c64c78SBram Moolenaar finish 2137c64c78SBram Moolenaarendif 2237c64c78SBram Moolenaar 2360e73f2aSBram Moolenaar" Uncomment this line to write logging in "debuglog". 2460e73f2aSBram Moolenaar" call ch_logfile('debuglog', 'w') 2560e73f2aSBram Moolenaar 26fe386641SBram Moolenaar" The command that starts debugging, e.g. ":Termdebug vim". 27fe386641SBram Moolenaar" To end type "quit" in the gdb window. 28c572da5fSBram Moolenaarcommand -nargs=* -complete=file Termdebug call s:StartDebug(<q-args>) 29c572da5fSBram Moolenaar 30fe386641SBram Moolenaar" Name of the gdb command, defaults to "gdb". 31e09ba7baSBram Moolenaarif !exists('termdebugger') 32e09ba7baSBram Moolenaar let termdebugger = 'gdb' 33c572da5fSBram Moolenaarendif 34c572da5fSBram Moolenaar 35fe386641SBram Moolenaarlet s:pc_id = 12 36e09ba7baSBram Moolenaarlet s:break_id = 13 3760e73f2aSBram Moolenaarlet s:stopped = 1 38e09ba7baSBram Moolenaar 39e09ba7baSBram Moolenaarif &background == 'light' 40e09ba7baSBram Moolenaar hi default debugPC term=reverse ctermbg=lightblue guibg=lightblue 41e09ba7baSBram Moolenaarelse 42e09ba7baSBram Moolenaar hi default debugPC term=reverse ctermbg=darkblue guibg=darkblue 43e09ba7baSBram Moolenaarendif 44e09ba7baSBram Moolenaarhi default debugBreakpoint term=reverse ctermbg=red guibg=red 45fe386641SBram Moolenaar 46c572da5fSBram Moolenaarfunc s:StartDebug(cmd) 47fe386641SBram Moolenaar let s:startwin = win_getid(winnr()) 48fe386641SBram Moolenaar let s:startsigncolumn = &signcolumn 49fe386641SBram Moolenaar 5024a98a0eSBram Moolenaar let s:save_columns = 0 5124a98a0eSBram Moolenaar if exists('g:termdebug_wide') 5224a98a0eSBram Moolenaar if &columns < g:termdebug_wide 5338baa3e6SBram Moolenaar let s:save_columns = &columns 5438baa3e6SBram Moolenaar let &columns = g:termdebug_wide 5524a98a0eSBram Moolenaar endif 5638baa3e6SBram Moolenaar let vertical = 1 5738baa3e6SBram Moolenaar else 5838baa3e6SBram Moolenaar let vertical = 0 5938baa3e6SBram Moolenaar endif 6038baa3e6SBram Moolenaar 61c572da5fSBram Moolenaar " Open a terminal window without a job, to run the debugged program 62fe386641SBram Moolenaar let s:ptybuf = term_start('NONE', { 63fe386641SBram Moolenaar \ 'term_name': 'gdb program', 6438baa3e6SBram Moolenaar \ 'vertical': vertical, 65fe386641SBram Moolenaar \ }) 66fe386641SBram Moolenaar if s:ptybuf == 0 67fe386641SBram Moolenaar echoerr 'Failed to open the program terminal window' 68fe386641SBram Moolenaar return 69fe386641SBram Moolenaar endif 70fe386641SBram Moolenaar let pty = job_info(term_getjob(s:ptybuf))['tty_out'] 7145d5f26dSBram Moolenaar let s:ptywin = win_getid(winnr()) 72*51b0f370SBram Moolenaar if vertical 73*51b0f370SBram Moolenaar " Assuming the source code window will get a signcolumn, use two more 74*51b0f370SBram Moolenaar " columns for that, thus one less for the terminal window. 75*51b0f370SBram Moolenaar exe (&columns / 2 - 1) . "wincmd |" 76*51b0f370SBram Moolenaar endif 77fe386641SBram Moolenaar 78fe386641SBram Moolenaar " Create a hidden terminal window to communicate with gdb 79fe386641SBram Moolenaar let s:commbuf = term_start('NONE', { 80fe386641SBram Moolenaar \ 'term_name': 'gdb communication', 81fe386641SBram Moolenaar \ 'out_cb': function('s:CommOutput'), 82fe386641SBram Moolenaar \ 'hidden': 1, 83fe386641SBram Moolenaar \ }) 84fe386641SBram Moolenaar if s:commbuf == 0 85fe386641SBram Moolenaar echoerr 'Failed to open the communication terminal window' 86fe386641SBram Moolenaar exe 'bwipe! ' . s:ptybuf 87fe386641SBram Moolenaar return 88fe386641SBram Moolenaar endif 89fe386641SBram Moolenaar let commpty = job_info(term_getjob(s:commbuf))['tty_out'] 90c572da5fSBram Moolenaar 91c572da5fSBram Moolenaar " Open a terminal window to run the debugger. 92c3632516SBram Moolenaar " Add -quiet to avoid the intro message causing a hit-enter prompt. 93c3632516SBram Moolenaar let cmd = [g:termdebugger, '-quiet', '-tty', pty, a:cmd] 94c572da5fSBram Moolenaar echomsg 'executing "' . join(cmd) . '"' 9560e73f2aSBram Moolenaar let s:gdbbuf = term_start(cmd, { 96c572da5fSBram Moolenaar \ 'exit_cb': function('s:EndDebug'), 97fe386641SBram Moolenaar \ 'term_finish': 'close', 98c572da5fSBram Moolenaar \ }) 9960e73f2aSBram Moolenaar if s:gdbbuf == 0 100fe386641SBram Moolenaar echoerr 'Failed to open the gdb terminal window' 101fe386641SBram Moolenaar exe 'bwipe! ' . s:ptybuf 102fe386641SBram Moolenaar exe 'bwipe! ' . s:commbuf 103fe386641SBram Moolenaar return 104fe386641SBram Moolenaar endif 10545d5f26dSBram Moolenaar let s:gdbwin = win_getid(winnr()) 106fe386641SBram Moolenaar 107fe386641SBram Moolenaar " Connect gdb to the communication pty, using the GDB/MI interface 10801164a65SBram Moolenaar " If you get an error "undefined command" your GDB is too old. 10960e73f2aSBram Moolenaar call term_sendkeys(s:gdbbuf, 'new-ui mi ' . commpty . "\r") 11060e73f2aSBram Moolenaar 11160e73f2aSBram Moolenaar " Interpret commands while the target is running. This should usualy only be 11260e73f2aSBram Moolenaar " exec-interrupt, since many commands don't work properly while the target is 11360e73f2aSBram Moolenaar " running. 11460e73f2aSBram Moolenaar call s:SendCommand('-gdb-set mi-async on') 115e09ba7baSBram Moolenaar 11638baa3e6SBram Moolenaar " Sign used to highlight the line where the program has stopped. 11738baa3e6SBram Moolenaar " There can be only one. 11838baa3e6SBram Moolenaar sign define debugPC linehl=debugPC 11938baa3e6SBram Moolenaar 12038baa3e6SBram Moolenaar " Sign used to indicate a breakpoint. 12138baa3e6SBram Moolenaar " Can be used multiple times. 12238baa3e6SBram Moolenaar sign define debugBreakpoint text=>> texthl=debugBreakpoint 12338baa3e6SBram Moolenaar 12445d5f26dSBram Moolenaar " Install debugger commands in the text window. 12545d5f26dSBram Moolenaar call win_gotoid(s:startwin) 126e09ba7baSBram Moolenaar call s:InstallCommands() 12745d5f26dSBram Moolenaar call win_gotoid(s:gdbwin) 128e09ba7baSBram Moolenaar 129*51b0f370SBram Moolenaar " Enable showing a balloon with eval info 130*51b0f370SBram Moolenaar if has("balloon_eval") 131*51b0f370SBram Moolenaar set ballooneval 132*51b0f370SBram Moolenaar set balloonexpr=TermDebugBalloonExpr() 133*51b0f370SBram Moolenaar if has("balloon_eval_term") 134*51b0f370SBram Moolenaar set balloonevalterm 135*51b0f370SBram Moolenaar endif 136*51b0f370SBram Moolenaar endif 137*51b0f370SBram Moolenaar 138e09ba7baSBram Moolenaar let s:breakpoints = {} 1391b9645deSBram Moolenaar 1401b9645deSBram Moolenaar augroup TermDebug 1411b9645deSBram Moolenaar au BufRead * call s:BufRead() 1421b9645deSBram Moolenaar au BufUnload * call s:BufUnloaded() 1431b9645deSBram Moolenaar augroup END 144c572da5fSBram Moolenaarendfunc 145c572da5fSBram Moolenaar 146c572da5fSBram Moolenaarfunc s:EndDebug(job, status) 147c572da5fSBram Moolenaar exe 'bwipe! ' . s:ptybuf 148fe386641SBram Moolenaar exe 'bwipe! ' . s:commbuf 149e09ba7baSBram Moolenaar 150e09ba7baSBram Moolenaar let curwinid = win_getid(winnr()) 151e09ba7baSBram Moolenaar 152e09ba7baSBram Moolenaar call win_gotoid(s:startwin) 153e09ba7baSBram Moolenaar let &signcolumn = s:startsigncolumn 154e09ba7baSBram Moolenaar call s:DeleteCommands() 155e09ba7baSBram Moolenaar 156e09ba7baSBram Moolenaar call win_gotoid(curwinid) 15738baa3e6SBram Moolenaar if s:save_columns > 0 15838baa3e6SBram Moolenaar let &columns = s:save_columns 15938baa3e6SBram Moolenaar endif 1601b9645deSBram Moolenaar 161*51b0f370SBram Moolenaar if has("balloon_eval") 162*51b0f370SBram Moolenaar set noballooneval 163*51b0f370SBram Moolenaar set balloonexpr= 164*51b0f370SBram Moolenaar if has("balloon_eval_term") 165*51b0f370SBram Moolenaar set noballoonevalterm 166*51b0f370SBram Moolenaar endif 167*51b0f370SBram Moolenaar endif 168*51b0f370SBram Moolenaar 1691b9645deSBram Moolenaar au! TermDebug 170fe386641SBram Moolenaarendfunc 171fe386641SBram Moolenaar 172fe386641SBram Moolenaar" Handle a message received from gdb on the GDB/MI interface. 173fe386641SBram Moolenaarfunc s:CommOutput(chan, msg) 174fe386641SBram Moolenaar let msgs = split(a:msg, "\r") 175fe386641SBram Moolenaar 176fe386641SBram Moolenaar for msg in msgs 177fe386641SBram Moolenaar " remove prefixed NL 178fe386641SBram Moolenaar if msg[0] == "\n" 179fe386641SBram Moolenaar let msg = msg[1:] 180fe386641SBram Moolenaar endif 181fe386641SBram Moolenaar if msg != '' 1821b9645deSBram Moolenaar if msg =~ '^\(\*stopped\|\*running\|=thread-selected\)' 183e09ba7baSBram Moolenaar call s:HandleCursor(msg) 18445d5f26dSBram Moolenaar elseif msg =~ '^\^done,bkpt=' || msg =~ '^=breakpoint-created,' 185e09ba7baSBram Moolenaar call s:HandleNewBreakpoint(msg) 186e09ba7baSBram Moolenaar elseif msg =~ '^=breakpoint-deleted,' 187e09ba7baSBram Moolenaar call s:HandleBreakpointDelete(msg) 18845d5f26dSBram Moolenaar elseif msg =~ '^\^done,value=' 18945d5f26dSBram Moolenaar call s:HandleEvaluate(msg) 19045d5f26dSBram Moolenaar elseif msg =~ '^\^error,msg=' 19145d5f26dSBram Moolenaar call s:HandleError(msg) 192e09ba7baSBram Moolenaar endif 193e09ba7baSBram Moolenaar endif 194e09ba7baSBram Moolenaar endfor 195e09ba7baSBram Moolenaarendfunc 196e09ba7baSBram Moolenaar 197e09ba7baSBram Moolenaar" Install commands in the current window to control the debugger. 198e09ba7baSBram Moolenaarfunc s:InstallCommands() 199e09ba7baSBram Moolenaar command Break call s:SetBreakpoint() 200e09ba7baSBram Moolenaar command Delete call s:DeleteBreakpoint() 201e09ba7baSBram Moolenaar command Step call s:SendCommand('-exec-step') 20245d5f26dSBram Moolenaar command Over call s:SendCommand('-exec-next') 203e09ba7baSBram Moolenaar command Finish call s:SendCommand('-exec-finish') 20460e73f2aSBram Moolenaar command -nargs=* Run call s:Run(<q-args>) 20560e73f2aSBram Moolenaar command -nargs=* Arguments call s:SendCommand('-exec-arguments ' . <q-args>) 20660e73f2aSBram Moolenaar command Stop call s:SendCommand('-exec-interrupt') 207e09ba7baSBram Moolenaar command Continue call s:SendCommand('-exec-continue') 20845d5f26dSBram Moolenaar command -range -nargs=* Evaluate call s:Evaluate(<range>, <q-args>) 20945d5f26dSBram Moolenaar command Gdb call win_gotoid(s:gdbwin) 21045d5f26dSBram Moolenaar command Program call win_gotoid(s:ptywin) 21145d5f26dSBram Moolenaar 21245d5f26dSBram Moolenaar " TODO: can the K mapping be restored? 21345d5f26dSBram Moolenaar nnoremap K :Evaluate<CR> 2141b9645deSBram Moolenaar 2151b9645deSBram Moolenaar if has('menu') 21624a98a0eSBram Moolenaar nnoremenu WinBar.Step :Step<CR> 21724a98a0eSBram Moolenaar nnoremenu WinBar.Next :Over<CR> 21824a98a0eSBram Moolenaar nnoremenu WinBar.Finish :Finish<CR> 21924a98a0eSBram Moolenaar nnoremenu WinBar.Cont :Continue<CR> 22060e73f2aSBram Moolenaar nnoremenu WinBar.Stop :Stop<CR> 22124a98a0eSBram Moolenaar nnoremenu WinBar.Eval :Evaluate<CR> 2221b9645deSBram Moolenaar endif 223e09ba7baSBram Moolenaarendfunc 224e09ba7baSBram Moolenaar 225e09ba7baSBram Moolenaar" Delete installed debugger commands in the current window. 226e09ba7baSBram Moolenaarfunc s:DeleteCommands() 227e09ba7baSBram Moolenaar delcommand Break 228e09ba7baSBram Moolenaar delcommand Delete 229e09ba7baSBram Moolenaar delcommand Step 23045d5f26dSBram Moolenaar delcommand Over 231e09ba7baSBram Moolenaar delcommand Finish 23260e73f2aSBram Moolenaar delcommand Run 23360e73f2aSBram Moolenaar delcommand Arguments 23460e73f2aSBram Moolenaar delcommand Stop 235e09ba7baSBram Moolenaar delcommand Continue 23645d5f26dSBram Moolenaar delcommand Evaluate 23745d5f26dSBram Moolenaar delcommand Gdb 23845d5f26dSBram Moolenaar delcommand Program 23945d5f26dSBram Moolenaar 24045d5f26dSBram Moolenaar nunmap K 2411b9645deSBram Moolenaar 2421b9645deSBram Moolenaar if has('menu') 2431b9645deSBram Moolenaar aunmenu WinBar.Step 2441b9645deSBram Moolenaar aunmenu WinBar.Next 2451b9645deSBram Moolenaar aunmenu WinBar.Finish 2461b9645deSBram Moolenaar aunmenu WinBar.Cont 24760e73f2aSBram Moolenaar aunmenu WinBar.Stop 2481b9645deSBram Moolenaar aunmenu WinBar.Eval 2491b9645deSBram Moolenaar endif 2501b9645deSBram Moolenaar 25145d5f26dSBram Moolenaar exe 'sign unplace ' . s:pc_id 25245d5f26dSBram Moolenaar for key in keys(s:breakpoints) 25345d5f26dSBram Moolenaar exe 'sign unplace ' . (s:break_id + key) 25445d5f26dSBram Moolenaar endfor 25538baa3e6SBram Moolenaar sign undefine debugPC 25638baa3e6SBram Moolenaar sign undefine debugBreakpoint 25745d5f26dSBram Moolenaar unlet s:breakpoints 258e09ba7baSBram Moolenaarendfunc 259e09ba7baSBram Moolenaar 260e09ba7baSBram Moolenaar" :Break - Set a breakpoint at the cursor position. 261e09ba7baSBram Moolenaarfunc s:SetBreakpoint() 26260e73f2aSBram Moolenaar " Setting a breakpoint may not work while the program is running. 26360e73f2aSBram Moolenaar " Interrupt to make it work. 26460e73f2aSBram Moolenaar let do_continue = 0 26560e73f2aSBram Moolenaar if !s:stopped 26660e73f2aSBram Moolenaar let do_continue = 1 26760e73f2aSBram Moolenaar call s:SendCommand('-exec-interrupt') 26860e73f2aSBram Moolenaar sleep 10m 26960e73f2aSBram Moolenaar endif 27060e73f2aSBram Moolenaar call s:SendCommand('-break-insert --source ' 27160e73f2aSBram Moolenaar \ . fnameescape(expand('%:p')) . ' --line ' . line('.')) 27260e73f2aSBram Moolenaar if do_continue 27360e73f2aSBram Moolenaar call s:SendCommand('-exec-continue') 27460e73f2aSBram Moolenaar endif 275e09ba7baSBram Moolenaarendfunc 276e09ba7baSBram Moolenaar 277e09ba7baSBram Moolenaar" :Delete - Delete a breakpoint at the cursor position. 278e09ba7baSBram Moolenaarfunc s:DeleteBreakpoint() 279e09ba7baSBram Moolenaar let fname = fnameescape(expand('%:p')) 280e09ba7baSBram Moolenaar let lnum = line('.') 281e09ba7baSBram Moolenaar for [key, val] in items(s:breakpoints) 282e09ba7baSBram Moolenaar if val['fname'] == fname && val['lnum'] == lnum 283e09ba7baSBram Moolenaar call term_sendkeys(s:commbuf, '-break-delete ' . key . "\r") 284e09ba7baSBram Moolenaar " Assume this always wors, the reply is simply "^done". 285e09ba7baSBram Moolenaar exe 'sign unplace ' . (s:break_id + key) 286e09ba7baSBram Moolenaar unlet s:breakpoints[key] 287e09ba7baSBram Moolenaar break 288e09ba7baSBram Moolenaar endif 289e09ba7baSBram Moolenaar endfor 290e09ba7baSBram Moolenaarendfunc 291e09ba7baSBram Moolenaar 292e09ba7baSBram Moolenaar" :Next, :Continue, etc - send a command to gdb 293e09ba7baSBram Moolenaarfunc s:SendCommand(cmd) 294e09ba7baSBram Moolenaar call term_sendkeys(s:commbuf, a:cmd . "\r") 295e09ba7baSBram Moolenaarendfunc 296e09ba7baSBram Moolenaar 29760e73f2aSBram Moolenaarfunc s:Run(args) 29860e73f2aSBram Moolenaar if a:args != '' 29960e73f2aSBram Moolenaar call s:SendCommand('-exec-arguments ' . a:args) 30060e73f2aSBram Moolenaar endif 30160e73f2aSBram Moolenaar call s:SendCommand('-exec-run') 30260e73f2aSBram Moolenaarendfunc 30360e73f2aSBram Moolenaar 304*51b0f370SBram Moolenaarfunc s:SendEval(expr) 305*51b0f370SBram Moolenaar call s:SendCommand('-data-evaluate-expression "' . a:expr . '"') 306*51b0f370SBram Moolenaar let s:evalexpr = a:expr 307*51b0f370SBram Moolenaarendfunc 308*51b0f370SBram Moolenaar 30945d5f26dSBram Moolenaar" :Evaluate - evaluate what is under the cursor 31045d5f26dSBram Moolenaarfunc s:Evaluate(range, arg) 31145d5f26dSBram Moolenaar if a:arg != '' 31245d5f26dSBram Moolenaar let expr = a:arg 31345d5f26dSBram Moolenaar elseif a:range == 2 31445d5f26dSBram Moolenaar let pos = getcurpos() 31545d5f26dSBram Moolenaar let reg = getreg('v', 1, 1) 31645d5f26dSBram Moolenaar let regt = getregtype('v') 31745d5f26dSBram Moolenaar normal! gv"vy 31845d5f26dSBram Moolenaar let expr = @v 31945d5f26dSBram Moolenaar call setpos('.', pos) 32045d5f26dSBram Moolenaar call setreg('v', reg, regt) 32145d5f26dSBram Moolenaar else 32245d5f26dSBram Moolenaar let expr = expand('<cexpr>') 32345d5f26dSBram Moolenaar endif 324*51b0f370SBram Moolenaar call s:SendEval(expr) 32545d5f26dSBram Moolenaarendfunc 32645d5f26dSBram Moolenaar 327*51b0f370SBram Moolenaarlet s:evalFromBalloonExpr = 0 328*51b0f370SBram Moolenaar 32945d5f26dSBram Moolenaar" Handle the result of data-evaluate-expression 33045d5f26dSBram Moolenaarfunc s:HandleEvaluate(msg) 3311b9645deSBram Moolenaar let value = substitute(a:msg, '.*value="\(.*\)"', '\1', '') 3321b9645deSBram Moolenaar let value = substitute(value, '\\"', '"', 'g') 333*51b0f370SBram Moolenaar if s:evalFromBalloonExpr 334*51b0f370SBram Moolenaar if s:evalFromBalloonExprResult == '' 335*51b0f370SBram Moolenaar let s:evalFromBalloonExprResult = s:evalexpr . ': ' . value 336*51b0f370SBram Moolenaar else 337*51b0f370SBram Moolenaar let s:evalFromBalloonExprResult .= ' = ' . value 338*51b0f370SBram Moolenaar endif 339*51b0f370SBram Moolenaar call balloon_show(s:evalFromBalloonExprResult) 340*51b0f370SBram Moolenaar else 3411b9645deSBram Moolenaar echomsg '"' . s:evalexpr . '": ' . value 342*51b0f370SBram Moolenaar endif 3431b9645deSBram Moolenaar 3447f2e9d7cSBram Moolenaar if s:evalexpr[0] != '*' && value =~ '^0x' && value != '0x0' && value !~ '"$' 3451b9645deSBram Moolenaar " Looks like a pointer, also display what it points to. 346*51b0f370SBram Moolenaar call s:SendEval('*' . s:evalexpr) 347*51b0f370SBram Moolenaar else 348*51b0f370SBram Moolenaar let s:evalFromBalloonExpr = 0 3491b9645deSBram Moolenaar endif 35045d5f26dSBram Moolenaarendfunc 35145d5f26dSBram Moolenaar 352*51b0f370SBram Moolenaar" Show a balloon with information of the variable under the mouse pointer, 353*51b0f370SBram Moolenaar" if there is any. 354*51b0f370SBram Moolenaarfunc TermDebugBalloonExpr() 355*51b0f370SBram Moolenaar if v:beval_winid != s:startwin 356*51b0f370SBram Moolenaar return 357*51b0f370SBram Moolenaar endif 358*51b0f370SBram Moolenaar call s:SendEval(v:beval_text) 359*51b0f370SBram Moolenaar let s:evalFromBalloonExpr = 1 360*51b0f370SBram Moolenaar let s:evalFromBalloonExprResult = '' 361*51b0f370SBram Moolenaar return '' 362*51b0f370SBram Moolenaarendfunc 363*51b0f370SBram Moolenaar 36445d5f26dSBram Moolenaar" Handle an error. 36545d5f26dSBram Moolenaarfunc s:HandleError(msg) 366*51b0f370SBram Moolenaar if a:msg =~ 'No symbol .* in current context' 367*51b0f370SBram Moolenaar \ || a:msg =~ 'Cannot access memory at address ' 368*51b0f370SBram Moolenaar \ || a:msg =~ 'Attempt to use a type name as an expression' 369*51b0f370SBram Moolenaar " Result of s:SendEval() failed, ignore. 370*51b0f370SBram Moolenaar return 371*51b0f370SBram Moolenaar endif 37245d5f26dSBram Moolenaar echoerr substitute(a:msg, '.*msg="\(.*\)"', '\1', '') 37345d5f26dSBram Moolenaarendfunc 37445d5f26dSBram Moolenaar 375e09ba7baSBram Moolenaar" Handle stopping and running message from gdb. 376e09ba7baSBram Moolenaar" Will update the sign that shows the current position. 377e09ba7baSBram Moolenaarfunc s:HandleCursor(msg) 378fe386641SBram Moolenaar let wid = win_getid(winnr()) 379fe386641SBram Moolenaar 38060e73f2aSBram Moolenaar if a:msg =~ '^\*stopped' 38160e73f2aSBram Moolenaar let s:stopped = 1 38260e73f2aSBram Moolenaar elseif a:msg =~ '^\*running' 38360e73f2aSBram Moolenaar let s:stopped = 0 38460e73f2aSBram Moolenaar endif 38560e73f2aSBram Moolenaar 386fe386641SBram Moolenaar if win_gotoid(s:startwin) 387e09ba7baSBram Moolenaar let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '') 3881b9645deSBram Moolenaar if a:msg =~ '^\(\*stopped\|=thread-selected\)' && filereadable(fname) 389e09ba7baSBram Moolenaar let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '') 390fe386641SBram Moolenaar if lnum =~ '^[0-9]*$' 3911b9645deSBram Moolenaar if expand('%:p') != fnamemodify(fname, ':p') 392fe386641SBram Moolenaar if &modified 393fe386641SBram Moolenaar " TODO: find existing window 394fe386641SBram Moolenaar exe 'split ' . fnameescape(fname) 395fe386641SBram Moolenaar let s:startwin = win_getid(winnr()) 396fe386641SBram Moolenaar else 397fe386641SBram Moolenaar exe 'edit ' . fnameescape(fname) 398fe386641SBram Moolenaar endif 399fe386641SBram Moolenaar endif 400fe386641SBram Moolenaar exe lnum 40101164a65SBram Moolenaar exe 'sign unplace ' . s:pc_id 4021b9645deSBram Moolenaar exe 'sign place ' . s:pc_id . ' line=' . lnum . ' name=debugPC file=' . fname 403fe386641SBram Moolenaar setlocal signcolumn=yes 404fe386641SBram Moolenaar endif 405fe386641SBram Moolenaar else 406fe386641SBram Moolenaar exe 'sign unplace ' . s:pc_id 407fe386641SBram Moolenaar endif 408fe386641SBram Moolenaar 409fe386641SBram Moolenaar call win_gotoid(wid) 410fe386641SBram Moolenaar endif 411e09ba7baSBram Moolenaarendfunc 412e09ba7baSBram Moolenaar 413e09ba7baSBram Moolenaar" Handle setting a breakpoint 414e09ba7baSBram Moolenaar" Will update the sign that shows the breakpoint 415e09ba7baSBram Moolenaarfunc s:HandleNewBreakpoint(msg) 416e09ba7baSBram Moolenaar let nr = substitute(a:msg, '.*number="\([0-9]\)*\".*', '\1', '') + 0 417e09ba7baSBram Moolenaar if nr == 0 418e09ba7baSBram Moolenaar return 419fe386641SBram Moolenaar endif 420e09ba7baSBram Moolenaar 421e09ba7baSBram Moolenaar if has_key(s:breakpoints, nr) 422e09ba7baSBram Moolenaar let entry = s:breakpoints[nr] 423e09ba7baSBram Moolenaar else 424e09ba7baSBram Moolenaar let entry = {} 425e09ba7baSBram Moolenaar let s:breakpoints[nr] = entry 426fe386641SBram Moolenaar endif 427e09ba7baSBram Moolenaar 428e09ba7baSBram Moolenaar let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '') 429e09ba7baSBram Moolenaar let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '') 430e09ba7baSBram Moolenaar let entry['fname'] = fname 431e09ba7baSBram Moolenaar let entry['lnum'] = lnum 4321b9645deSBram Moolenaar 4331b9645deSBram Moolenaar if bufloaded(fname) 4341b9645deSBram Moolenaar call s:PlaceSign(nr, entry) 4351b9645deSBram Moolenaar endif 4361b9645deSBram Moolenaarendfunc 4371b9645deSBram Moolenaar 4381b9645deSBram Moolenaarfunc s:PlaceSign(nr, entry) 4391b9645deSBram Moolenaar exe 'sign place ' . (s:break_id + a:nr) . ' line=' . a:entry['lnum'] . ' name=debugBreakpoint file=' . a:entry['fname'] 4401b9645deSBram Moolenaar let a:entry['placed'] = 1 441e09ba7baSBram Moolenaarendfunc 442e09ba7baSBram Moolenaar 443e09ba7baSBram Moolenaar" Handle deleting a breakpoint 444e09ba7baSBram Moolenaar" Will remove the sign that shows the breakpoint 445e09ba7baSBram Moolenaarfunc s:HandleBreakpointDelete(msg) 446e09ba7baSBram Moolenaar let nr = substitute(a:msg, '.*id="\([0-9]*\)\".*', '\1', '') + 0 447e09ba7baSBram Moolenaar if nr == 0 448e09ba7baSBram Moolenaar return 449e09ba7baSBram Moolenaar endif 4501b9645deSBram Moolenaar if has_key(s:breakpoints, nr) 4511b9645deSBram Moolenaar let entry = s:breakpoints[nr] 4521b9645deSBram Moolenaar if has_key(entry, 'placed') 453e09ba7baSBram Moolenaar exe 'sign unplace ' . (s:break_id + nr) 4541b9645deSBram Moolenaar unlet entry['placed'] 4551b9645deSBram Moolenaar endif 456e09ba7baSBram Moolenaar unlet s:breakpoints[nr] 4571b9645deSBram Moolenaar endif 458c572da5fSBram Moolenaarendfunc 4591b9645deSBram Moolenaar 4601b9645deSBram Moolenaar" Handle a BufRead autocommand event: place any signs. 4611b9645deSBram Moolenaarfunc s:BufRead() 4621b9645deSBram Moolenaar let fname = expand('<afile>:p') 4631b9645deSBram Moolenaar for [nr, entry] in items(s:breakpoints) 4641b9645deSBram Moolenaar if entry['fname'] == fname 4651b9645deSBram Moolenaar call s:PlaceSign(nr, entry) 4661b9645deSBram Moolenaar endif 4671b9645deSBram Moolenaar endfor 4681b9645deSBram Moolenaarendfunc 4691b9645deSBram Moolenaar 4701b9645deSBram Moolenaar" Handle a BufUnloaded autocommand event: unplace any signs. 4711b9645deSBram Moolenaarfunc s:BufUnloaded() 4721b9645deSBram Moolenaar let fname = expand('<afile>:p') 4731b9645deSBram Moolenaar for [nr, entry] in items(s:breakpoints) 4741b9645deSBram Moolenaar if entry['fname'] == fname 4751b9645deSBram Moolenaar let entry['placed'] = 0 4761b9645deSBram Moolenaar endif 4771b9645deSBram Moolenaar endfor 4781b9645deSBram Moolenaarendfunc 4791b9645deSBram Moolenaar 480