1*fe386641SBram Moolenaar" Debugger plugin using gdb. 2c572da5fSBram Moolenaar" 3c572da5fSBram Moolenaar" WORK IN PROGRESS - much doesn't work yet 4c572da5fSBram Moolenaar" 5*fe386641SBram Moolenaar" Open two visible terminal windows: 6c572da5fSBram Moolenaar" 1. run a pty, as with ":term NONE" 7c572da5fSBram Moolenaar" 2. run gdb, passing the pty 8*fe386641SBram Moolenaar" The current window is used to view source code and follows gdb. 9*fe386641SBram Moolenaar" 10*fe386641SBram Moolenaar" A third terminal window is hidden, it is used for communication with gdb. 11*fe386641SBram Moolenaar" 12*fe386641SBram Moolenaar" The communication with gdb uses GDB/MI. See: 13*fe386641SBram Moolenaar" https://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI.html 14c572da5fSBram Moolenaar" 15c572da5fSBram Moolenaar" Author: Bram Moolenaar 16*fe386641SBram Moolenaar" Copyright: Vim license applies, see ":help license" 17c572da5fSBram Moolenaar 18*fe386641SBram Moolenaar" The command that starts debugging, e.g. ":Termdebug vim". 19*fe386641SBram Moolenaar" To end type "quit" in the gdb window. 20c572da5fSBram Moolenaarcommand -nargs=* -complete=file Termdebug call s:StartDebug(<q-args>) 21c572da5fSBram Moolenaar 22*fe386641SBram Moolenaar" Name of the gdb command, defaults to "gdb". 23c572da5fSBram Moolenaarif !exists('debugger') 24c572da5fSBram Moolenaar let debugger = 'gdb' 25c572da5fSBram Moolenaarendif 26c572da5fSBram Moolenaar 27*fe386641SBram Moolenaar" Sign used to highlight the line where the program has stopped. 28*fe386641SBram Moolenaarsign define debugPC linehl=debugPC 29*fe386641SBram Moolenaarif &background == 'light' 30*fe386641SBram Moolenaar hi debugPC term=reverse ctermbg=lightblue guibg=lightblue 31*fe386641SBram Moolenaarelse 32*fe386641SBram Moolenaar hi debugPC term=reverse ctermbg=darkblue guibg=darkblue 33*fe386641SBram Moolenaarendif 34*fe386641SBram Moolenaarlet s:pc_id = 12 35*fe386641SBram Moolenaar 36c572da5fSBram Moolenaarfunc s:StartDebug(cmd) 37*fe386641SBram Moolenaar let s:startwin = win_getid(winnr()) 38*fe386641SBram Moolenaar let s:startsigncolumn = &signcolumn 39*fe386641SBram Moolenaar 40c572da5fSBram Moolenaar " Open a terminal window without a job, to run the debugged program 41*fe386641SBram Moolenaar let s:ptybuf = term_start('NONE', { 42*fe386641SBram Moolenaar \ 'term_name': 'gdb program', 43*fe386641SBram Moolenaar \ }) 44*fe386641SBram Moolenaar if s:ptybuf == 0 45*fe386641SBram Moolenaar echoerr 'Failed to open the program terminal window' 46*fe386641SBram Moolenaar return 47*fe386641SBram Moolenaar endif 48*fe386641SBram Moolenaar let pty = job_info(term_getjob(s:ptybuf))['tty_out'] 49*fe386641SBram Moolenaar 50*fe386641SBram Moolenaar " Create a hidden terminal window to communicate with gdb 51*fe386641SBram Moolenaar let s:commbuf = term_start('NONE', { 52*fe386641SBram Moolenaar \ 'term_name': 'gdb communication', 53*fe386641SBram Moolenaar \ 'out_cb': function('s:CommOutput'), 54*fe386641SBram Moolenaar \ 'hidden': 1, 55*fe386641SBram Moolenaar \ }) 56*fe386641SBram Moolenaar if s:commbuf == 0 57*fe386641SBram Moolenaar echoerr 'Failed to open the communication terminal window' 58*fe386641SBram Moolenaar exe 'bwipe! ' . s:ptybuf 59*fe386641SBram Moolenaar return 60*fe386641SBram Moolenaar endif 61*fe386641SBram Moolenaar let commpty = job_info(term_getjob(s:commbuf))['tty_out'] 62c572da5fSBram Moolenaar 63c572da5fSBram Moolenaar " Open a terminal window to run the debugger. 64c572da5fSBram Moolenaar let cmd = [g:debugger, '-tty', pty, a:cmd] 65c572da5fSBram Moolenaar echomsg 'executing "' . join(cmd) . '"' 66c572da5fSBram Moolenaar let gdbbuf = term_start(cmd, { 67c572da5fSBram Moolenaar \ 'exit_cb': function('s:EndDebug'), 68*fe386641SBram Moolenaar \ 'term_finish': 'close', 69c572da5fSBram Moolenaar \ }) 70*fe386641SBram Moolenaar if gdbbuf == 0 71*fe386641SBram Moolenaar echoerr 'Failed to open the gdb terminal window' 72*fe386641SBram Moolenaar exe 'bwipe! ' . s:ptybuf 73*fe386641SBram Moolenaar exe 'bwipe! ' . s:commbuf 74*fe386641SBram Moolenaar return 75*fe386641SBram Moolenaar endif 76*fe386641SBram Moolenaar 77*fe386641SBram Moolenaar " Connect gdb to the communication pty, using the GDB/MI interface 78*fe386641SBram Moolenaar call term_sendkeys(gdbbuf, 'new-ui mi ' . commpty . "\r") 79c572da5fSBram Moolenaarendfunc 80c572da5fSBram Moolenaar 81c572da5fSBram Moolenaarfunc s:EndDebug(job, status) 82c572da5fSBram Moolenaar exe 'bwipe! ' . s:ptybuf 83*fe386641SBram Moolenaar exe 'bwipe! ' . s:commbuf 84*fe386641SBram Moolenaar call setwinvar(s:startwin, '&signcolumn', s:startsigncolumn) 85*fe386641SBram Moolenaarendfunc 86*fe386641SBram Moolenaar 87*fe386641SBram Moolenaar" Handle a message received from gdb on the GDB/MI interface. 88*fe386641SBram Moolenaarfunc s:CommOutput(chan, msg) 89*fe386641SBram Moolenaar let msgs = split(a:msg, "\r") 90*fe386641SBram Moolenaar 91*fe386641SBram Moolenaar for msg in msgs 92*fe386641SBram Moolenaar " remove prefixed NL 93*fe386641SBram Moolenaar if msg[0] == "\n" 94*fe386641SBram Moolenaar let msg = msg[1:] 95*fe386641SBram Moolenaar endif 96*fe386641SBram Moolenaar if msg != '' 97*fe386641SBram Moolenaar if msg =~ '^\*\(stopped\|running\)' 98*fe386641SBram Moolenaar let wid = win_getid(winnr()) 99*fe386641SBram Moolenaar 100*fe386641SBram Moolenaar if win_gotoid(s:startwin) 101*fe386641SBram Moolenaar if msg =~ '^\*stopped' 102*fe386641SBram Moolenaar " TODO: proper parsing 103*fe386641SBram Moolenaar let fname = substitute(msg, '.*fullname="\([^"]*\)".*', '\1', '') 104*fe386641SBram Moolenaar let lnum = substitute(msg, '.*line="\([^"]*\)".*', '\1', '') 105*fe386641SBram Moolenaar if lnum =~ '^[0-9]*$' 106*fe386641SBram Moolenaar if expand('%:h') != fname 107*fe386641SBram Moolenaar if &modified 108*fe386641SBram Moolenaar " TODO: find existing window 109*fe386641SBram Moolenaar exe 'split ' . fnameescape(fname) 110*fe386641SBram Moolenaar let s:startwin = win_getid(winnr()) 111*fe386641SBram Moolenaar else 112*fe386641SBram Moolenaar exe 'edit ' . fnameescape(fname) 113*fe386641SBram Moolenaar endif 114*fe386641SBram Moolenaar endif 115*fe386641SBram Moolenaar exe lnum 116*fe386641SBram Moolenaar exe 'sign place ' . s:pc_id . ' line=' . lnum . ' name=debugPC file=' . fnameescape(fname) 117*fe386641SBram Moolenaar setlocal signcolumn=yes 118*fe386641SBram Moolenaar endif 119*fe386641SBram Moolenaar else 120*fe386641SBram Moolenaar exe 'sign unplace ' . s:pc_id 121*fe386641SBram Moolenaar endif 122*fe386641SBram Moolenaar 123*fe386641SBram Moolenaar call win_gotoid(wid) 124*fe386641SBram Moolenaar endif 125*fe386641SBram Moolenaar endif 126*fe386641SBram Moolenaar endif 127*fe386641SBram Moolenaar endfor 128c572da5fSBram Moolenaarendfunc 129