Fix #25 - pre-process GDB's MI output
This commit is contained in:
parent
fa84d5c0a5
commit
3ef3f45016
@ -1,21 +1,13 @@
|
||||
"Read and return all new lines from a Vebugger pipe object.
|
||||
function! s:readNewLinesFromPipe(pipeObject)
|
||||
"read
|
||||
let l:text=a:pipeObject.pipe.read(1000,0)
|
||||
"Read bytes from pipe to buffer
|
||||
function! s:fillBufferFromPipe(pipeObject)
|
||||
let l:text = a:pipeObject.pipe.read(1024, 0)
|
||||
let l:totalBytesRead = 0
|
||||
while 0 < len(l:text)
|
||||
let l:totalBytesRead += len(l:text)
|
||||
let a:pipeObject.buffer .= l:text
|
||||
let l:text=a:pipeObject.pipe.read(1000,0)
|
||||
let l:text = a:pipeObject.pipe.read(1024, 0)
|
||||
endwhile
|
||||
|
||||
"parse
|
||||
let l:lastNewline=strridx(a:pipeObject.buffer,"\n")
|
||||
if 0<=l:lastNewline
|
||||
let l:outLines=split(strpart(a:pipeObject.buffer,0,l:lastNewline),'\r\n\|\n\|\r')
|
||||
let a:pipeObject.buffer=strpart(a:pipeObject.buffer,l:lastNewline+1)
|
||||
return l:outLines
|
||||
endif
|
||||
|
||||
return []
|
||||
return l:totalBytesRead
|
||||
endfunction
|
||||
|
||||
let s:f_debugger={}
|
||||
@ -43,10 +35,13 @@ endfunction
|
||||
function! s:f_debugger.invokeReading() dict
|
||||
let l:newLines = {}
|
||||
for l:k in keys(self.pipes)
|
||||
let l:nl=s:readNewLinesFromPipe(self.pipes[l:k])
|
||||
let l:pipe = self.pipes[l:k]
|
||||
if 0 < s:fillBufferFromPipe(l:pipe)
|
||||
let l:nl = l:pipe.bufferer()
|
||||
if 0 < len(l:nl)
|
||||
let l:newLines[l:k] = l:nl
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
for l:k in keys(l:newLines)
|
||||
for l:line in l:newLines[l:k]
|
||||
@ -252,6 +247,11 @@ function! vebugger#createDebugger(command)
|
||||
let l:debugger.pipes = {
|
||||
\ 'out': {'pipe':(l:debugger.shell.stdout), 'buffer': ''},
|
||||
\ 'err': {'pipe':(l:debugger.shell.stderr), 'buffer': '', 'annotation': "err:\t\t"}}
|
||||
for l:pipe in values(l:debugger.pipes)
|
||||
"let l:pipe.buffer = ''
|
||||
"let l:pipe.readIntoBuffer = function('vebugger#readIntoBuffer')
|
||||
"let l:pipe.bufferer = function('vebugger#readNewLinesFromPipe')
|
||||
endfor
|
||||
|
||||
let l:debugger.readResultTemplate={}
|
||||
let l:debugger.state={}
|
||||
|
@ -1,6 +1,7 @@
|
||||
function! vebugger#gdb#start(binaryFile,args)
|
||||
let l:debugger=vebugger#std#startDebugger(shellescape(vebugger#util#getToolFullPath('gdb',get(a:args,'version'),'gdb'))
|
||||
\.' -i mi --silent '.fnameescape(a:binaryFile))
|
||||
let l:debugger.pipes.out.bufferer = function('vebugger#gdb#readMILinesFromPipe')
|
||||
let l:debugger.state.gdb={}
|
||||
|
||||
|
||||
@ -57,6 +58,61 @@ function! s:findFolderFromStackTrace(src,nameFromStackTrace)
|
||||
return l:path
|
||||
endfunction
|
||||
|
||||
function! vebugger#gdb#readMILinesFromPipe() dict
|
||||
if !has_key(self, 'tildeBuffer')
|
||||
let self.tildeBuffer = ''
|
||||
endif
|
||||
let l:result = []
|
||||
|
||||
while 1
|
||||
let l:newLinePos = stridx(self.buffer, "\n")
|
||||
if l:newLinePos < 0
|
||||
break
|
||||
endif
|
||||
let l:firstChar = self.buffer[0]
|
||||
if l:firstChar == '~'
|
||||
while self.buffer[0] == '~'
|
||||
let l:newLinePos = stridx(self.buffer, "\n")
|
||||
let l:line = self.buffer[0 : l:newLinePos]
|
||||
let l:line = l:line[2 : strridx(l:line, '"') - 1]
|
||||
let self.buffer = strpart(self.buffer, l:newLinePos + 1)
|
||||
"let self.tildeBuffer .= l:line
|
||||
let l:line = substitute(l:line, '\\n', "\n", "g")
|
||||
let l:line = substitute(l:line, '\\t', "\t", "g")
|
||||
let l:line = substitute(l:line, '\\"', '"', "g")
|
||||
let self.tildeBuffer .= l:line
|
||||
endwhile
|
||||
let l:lastTildeNewLine = strridx(self.tildeBuffer, "\n")
|
||||
if 0 <= l:lastTildeNewLine
|
||||
let l:newTildeLines = split(self.tildeBuffer[: l:lastTildeNewLine - 1], '\n')
|
||||
call map(l:newTildeLines, '"~".v:val')
|
||||
let self.tildeBuffer = strpart(self.tildeBuffer, l:lastTildeNewLine + 1)
|
||||
call extend(l:result, l:newTildeLines)
|
||||
endif
|
||||
continue
|
||||
else
|
||||
if !empty(self.tildeBuffer)
|
||||
call extend(l:result, split(self.tildeBuffer, '\n'))
|
||||
let self.tildeBuffer = ''
|
||||
endif
|
||||
endif
|
||||
let l:line = self.buffer[0 : l:newLinePos]
|
||||
if l:firstChar == '&'
|
||||
let l:line = l:line[2 : strridx(l:line, '"') - 1]
|
||||
let l:line = substitute(l:line, '\\n', "\n", "g")
|
||||
let l:line = substitute(l:line, '\\t', "\t", "g")
|
||||
let l:line = substitute(l:line, '\\"', '"', "g")
|
||||
let l:line = '&'.l:line
|
||||
endif
|
||||
|
||||
let l:line = substitute(l:line, '\v[\n\r]+$', '', "")
|
||||
call add(l:result, l:line)
|
||||
let self.buffer = strpart(self.buffer, l:newLinePos + 1)
|
||||
endwhile
|
||||
|
||||
return l:result
|
||||
endfunction
|
||||
|
||||
function! vebugger#gdb#_readProgramOutput(pipeName,line,readResult,debugger)
|
||||
if 'err'==a:pipeName
|
||||
\&&a:line!~'\v^[=~*&^]'
|
||||
@ -67,7 +123,6 @@ endfunction
|
||||
|
||||
function! vebugger#gdb#_readWhere(pipeName,line,readResult,debugger)
|
||||
if 'out'==a:pipeName
|
||||
"let l:matches=matchlist(a:line,'\v^\~"#(\d+)\s+(.+)\s+\(.*\)\s+at\s+([^:]+):(\d+)')
|
||||
let l:matches=matchlist(a:line,'\v^\*stopped.*fullname\=\"([^"]+)\",line\=\"(\d+)"')
|
||||
if 2<len(l:matches)
|
||||
let l:file=l:matches[1]
|
||||
@ -80,7 +135,7 @@ function! vebugger#gdb#_readWhere(pipeName,line,readResult,debugger)
|
||||
endfunction
|
||||
|
||||
function! vebugger#gdb#_readFinish(pipeName,line,readResult,debugger)
|
||||
if a:line=~'\c\V\^~"[Inferior \.\*exited normally]'
|
||||
if a:line=~'\c\V*stopped\.\*exited\[ -]normally'
|
||||
let a:readResult.std.programFinish={'finish':1}
|
||||
endif
|
||||
endfunction
|
||||
@ -129,7 +184,7 @@ endfunction
|
||||
function! vebugger#gdb#_readEvaluatedExpressions(pipeName,line,readResult,debugger) dict
|
||||
if 'out' == a:pipeName
|
||||
if has_key(self, 'nextExpressionToBePrinted')
|
||||
let l:matches=matchlist(a:line,'\v^\~"\$(\d+) \= (.*)"$')
|
||||
let l:matches=matchlist(a:line,'\v^\~\$(\d+) \= (.*)$')
|
||||
if 2<len(l:matches)
|
||||
let l:expression=l:matches[1]
|
||||
let l:value=l:matches[2]
|
||||
@ -139,7 +194,7 @@ function! vebugger#gdb#_readEvaluatedExpressions(pipeName,line,readResult,debugg
|
||||
endif
|
||||
call remove(self,'nextExpressionToBePrinted')
|
||||
else
|
||||
let l:matches=matchlist(a:line,'\v^\&"print (.{-})(\\r)?(\\n)?"$')
|
||||
let l:matches=matchlist(a:line,'\v^\&print (.+)$')
|
||||
if 1<len(l:matches)
|
||||
let self.nextExpressionToBePrinted=s:unescapeString(l:matches[1])
|
||||
endif
|
||||
|
@ -1,5 +1,12 @@
|
||||
let g:vebugger_breakpoints=[]
|
||||
|
||||
"Initialize the default pipe bufferers
|
||||
function! vebugger#std#setStandardBufferers(debugger)
|
||||
for l:pipe in values(a:debugger.pipes)
|
||||
let l:pipe.bufferer = function('vebugger#std#readNewLinesFromPipe')
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
"Initialize the std part of the debugger's state
|
||||
function! vebugger#std#setStandardState(debugger)
|
||||
let a:debugger.state.std={
|
||||
@ -55,6 +62,7 @@ endfunction
|
||||
|
||||
"Performs the standard initialization of the debugger object
|
||||
function! vebugger#std#standardInit(debugger)
|
||||
call vebugger#std#setStandardBufferers(a:debugger)
|
||||
call vebugger#std#setStandardState(a:debugger)
|
||||
call vebugger#std#setStandardReadResultTemplate(a:debugger)
|
||||
call vebugger#std#setStandardWriteactionsTemplate(a:debugger)
|
||||
@ -73,6 +81,19 @@ function! vebugger#std#startDebugger(command)
|
||||
endfunction
|
||||
|
||||
|
||||
"Read and return all new lines from a Vebugger pipe object.
|
||||
function! vebugger#std#readNewLinesFromPipe() dict
|
||||
let l:lastNewline = strridx(self.buffer, "\n")
|
||||
if 0 <= l:lastNewline
|
||||
let l:outLines = split(strpart(self.buffer, 0, l:lastNewline), '\r\n\|\n\|\r')
|
||||
let self.buffer = strpart(self.buffer, l:lastNewline + 1)
|
||||
return l:outLines
|
||||
endif
|
||||
|
||||
return []
|
||||
endfunction
|
||||
|
||||
|
||||
"Opens the shell buffer for a debugger. The shell buffer displays the output
|
||||
"of the debugged program, and when it's closed the debugger gets terminated.
|
||||
"Shell buffers should not be used when attaching a debugger to a running
|
||||
|
@ -493,3 +493,26 @@ defines the "std" namespace, and plugins built on top of Vebugger can define a
|
||||
namespaced named after the plugin to contain their own read results. A
|
||||
debugger frontend implementation can also define it's own namespace for
|
||||
storing debugger-specific data and configuration.
|
||||
|
||||
COMPILER OUTPUT BUFFERERS *vebugger-architecture-bufferers*
|
||||
|
||||
Read handlers receive lines created by the debugger output bufferer. There is
|
||||
only one for each debugger, and if you just want to get the debugger output
|
||||
line-by-line "as is" you can just use the default one and ignore this section.
|
||||
|
||||
The debugger bufferer is a dict function(|:func-dict|) that operates on pipe
|
||||
objects. It will be called when the pipe object's "self.buffer", which
|
||||
represents everything read from a debugger's output stream, has new data.
|
||||
|
||||
The bufferer function should:
|
||||
* return a list of new lines that will be send to the read handlers, or an
|
||||
empty list if there are no new lines.
|
||||
* "advance" the buffer - delete from it's head everything that was handled.
|
||||
This can easily be done with |strpart()|.
|
||||
|
||||
Bufferers should be set individually for each pipe, usually in the debugger
|
||||
creation function:
|
||||
|
||||
Example: >
|
||||
let l:debugger.pipes.out.bufferer = function('g:myCustomBufferer')
|
||||
<
|
||||
|
Loading…
x
Reference in New Issue
Block a user