@@ -73,6 +73,13 @@ let s:pc_id = 12
7373let s: break_id = 13 " breakpoint number is added to this
7474let s: stopped = 1
7575
76+ " Take a breakpoint number as used by GDB and turn it into an integer.
77+ " The breakpoint may contain a dot: 123.4
78+ func s: Breakpoint2SignNumber (nr)
79+ let t = split (a: nr , ' \.' )
80+ return t [0 ] * 1000 + (len (t ) == 2 ? t [1 ] : 0 )
81+ endfunction
82+
7683func s: Highlight (init, old, new )
7784 let default = a: init ? ' default ' : ' '
7885 if a: new == # ' light' && a: old !=# ' light'
@@ -138,9 +145,9 @@ endfunc
138145func s: StartDebug_term (dict )
139146 " Open a terminal window without a job, to run the debugged program in.
140147 let s: ptybuf = term_start (' NONE' , {
141- \ ' term_name' : ' debugged program' ,
142- \ ' vertical' : s: vertical ,
143- \ })
148+ \ ' term_name' : ' debugged program' ,
149+ \ ' vertical' : s: vertical ,
150+ \ })
144151 if s: ptybuf == 0
145152 echoerr ' Failed to open the program terminal window'
146153 return
@@ -155,10 +162,10 @@ func s:StartDebug_term(dict)
155162
156163 " Create a hidden terminal window to communicate with gdb
157164 let s: commbuf = term_start (' NONE' , {
158- \ ' term_name' : ' gdb communication' ,
159- \ ' out_cb' : function (' s:CommOutput' ),
160- \ ' hidden' : 1 ,
161- \ })
165+ \ ' term_name' : ' gdb communication' ,
166+ \ ' out_cb' : function (' s:CommOutput' ),
167+ \ ' hidden' : 1 ,
168+ \ })
162169 if s: commbuf == 0
163170 echoerr ' Failed to open the communication terminal window'
164171 exe ' bwipe! ' . s: ptybuf
@@ -174,9 +181,9 @@ func s:StartDebug_term(dict)
174181 let cmd = [g: termdebugger , ' -quiet' , ' -tty' , pty] + gdb_args
175182 call ch_log (' executing "' . join (cmd) . ' "' )
176183 let s: gdbbuf = term_start (cmd, {
177- \ ' exit_cb' : function (' s:EndTermDebug' ),
178- \ ' term_finish' : ' close' ,
179- \ })
184+ \ ' exit_cb' : function (' s:EndTermDebug' ),
185+ \ ' term_finish' : ' close' ,
186+ \ })
180187 if s: gdbbuf == 0
181188 echoerr ' Failed to open the gdb terminal window'
182189 exe ' bwipe! ' . s: ptybuf
@@ -200,18 +207,18 @@ func s:StartDebug_term(dict)
200207 let response = ' '
201208 for lnum in range (1 ,200 )
202209 if term_getline (s: gdbbuf , lnum) = ~ ' new-ui mi '
203- " response can be in the same line or the next line
204- let response = term_getline (s: gdbbuf , lnum) . term_getline (s: gdbbuf , lnum + 1 )
205- if response = ~ ' Undefined command'
206- echoerr ' Sorry, your gdb is too old, gdb 7.12 is required'
207- exe ' bwipe! ' . s: ptybuf
208- exe ' bwipe! ' . s: commbuf
209- return
210- endif
211- if response = ~ ' New UI allocated'
212- " Success!
213- break
214- endif
210+ " response can be in the same line or the next line
211+ let response = term_getline (s: gdbbuf , lnum) . term_getline (s: gdbbuf , lnum + 1 )
212+ if response = ~ ' Undefined command'
213+ echoerr ' Sorry, your gdb is too old, gdb 7.12 is required'
214+ exe ' bwipe! ' . s: ptybuf
215+ exe ' bwipe! ' . s: commbuf
216+ return
217+ endif
218+ if response = ~ ' New UI allocated'
219+ " Success!
220+ break
221+ endif
215222 endif
216223 endfor
217224 if response = ~ ' New UI allocated'
@@ -268,9 +275,9 @@ func s:StartDebug_prompt(dict)
268275 call ch_log (' executing "' . join (cmd) . ' "' )
269276
270277 let s: gdbjob = job_start (cmd, {
271- \ ' exit_cb' : function (' s:EndPromptDebug' ),
272- \ ' out_cb' : function (' s:GdbOutCallback' ),
273- \ })
278+ \ ' exit_cb' : function (' s:EndPromptDebug' ),
279+ \ ' out_cb' : function (' s:GdbOutCallback' ),
280+ \ })
274281 if job_status (s: gdbjob ) != " run"
275282 echoerr ' Failed to start gdb'
276283 exe ' bwipe! ' . s: promptbuf
@@ -295,8 +302,8 @@ func s:StartDebug_prompt(dict)
295302 " Unix: Run the debugged program in a terminal window. Open it below the
296303 " gdb window.
297304 belowright let s: ptybuf = term_start (' NONE' , {
298- \ ' term_name' : ' debugged program' ,
299- \ })
305+ \ ' term_name' : ' debugged program' ,
306+ \ })
300307 if s: ptybuf == 0
301308 echoerr ' Failed to open the program terminal window'
302309 call job_stop (s: gdbjob )
@@ -353,7 +360,8 @@ func s:StartDebugCommon(dict)
353360 endif
354361 endif
355362
356- " Contains breakpoints that have been placed, key is the number.
363+ " Contains breakpoints that have been placed, key is a string with the GDB
364+ " breakpoint number.
357365 let s: breakpoints = {}
358366
359367 augroup TermDebug
@@ -466,9 +474,9 @@ func s:DecodeMessage(quotedText)
466474 if a: quotedText [i ] == ' \'
467475 let i += 1
468476 if a: quotedText [i ] == ' n'
469- " drop \n
470- let i += 1
471- continue
477+ " drop \n
478+ let i += 1
479+ continue
472480 endif
473481 endif
474482 let result .= a: quotedText [i ]
@@ -479,6 +487,9 @@ endfunc
479487
480488" Extract the "name" value from a gdb message with fullname="name".
481489func s: GetFullname (msg)
490+ if a: msg !~ ' fullname'
491+ return ' '
492+ endif
482493 let name = s: DecodeMessage (substitute (a: msg , ' .*fullname=' , ' ' , ' ' ))
483494 if has (' win32' ) && name = ~ ' :\\\\'
484495 " sometimes the name arrives double-escaped
@@ -549,17 +560,17 @@ func s:CommOutput(chan, msg)
549560 endif
550561 if msg != ' '
551562 if msg = ~ ' ^\(\*stopped\|\*running\|=thread-selected\)'
552- call s: HandleCursor (msg)
563+ call s: HandleCursor (msg)
553564 elseif msg = ~ ' ^\^done,bkpt=' || msg = ~ ' ^=breakpoint-created,'
554- call s: HandleNewBreakpoint (msg)
565+ call s: HandleNewBreakpoint (msg)
555566 elseif msg = ~ ' ^=breakpoint-deleted,'
556- call s: HandleBreakpointDelete (msg)
567+ call s: HandleBreakpointDelete (msg)
557568 elseif msg = ~ ' ^=thread-group-started'
558- call s: HandleProgramRun (msg)
569+ call s: HandleProgramRun (msg)
559570 elseif msg = ~ ' ^\^done,value='
560- call s: HandleEvaluate (msg)
571+ call s: HandleEvaluate (msg)
561572 elseif msg = ~ ' ^\^error,msg='
562- call s: HandleError (msg)
573+ call s: HandleError (msg)
563574 endif
564575 endif
565576 endfor
@@ -650,12 +661,12 @@ func s:DeleteCommands()
650661 let curwinid = win_getid (winnr ())
651662 for winid in s: winbar_winids
652663 if win_gotoid (winid)
653- aunmenu WinBar.Step
654- aunmenu WinBar.Next
655- aunmenu WinBar.Finish
656- aunmenu WinBar.Cont
657- aunmenu WinBar.Stop
658- aunmenu WinBar.Eval
664+ aunmenu WinBar.Step
665+ aunmenu WinBar.Next
666+ aunmenu WinBar.Finish
667+ aunmenu WinBar.Cont
668+ aunmenu WinBar.Stop
669+ aunmenu WinBar.Eval
659670 endif
660671 endfor
661672 call win_gotoid (curwinid)
@@ -673,7 +684,7 @@ func s:DeleteCommands()
673684
674685 exe ' sign unplace ' . s: pc_id
675686 for key in keys (s: breakpoints )
676- exe ' sign unplace ' . (s: break_id + key )
687+ exe ' sign unplace ' . (s: break_id + s: Breakpoint2SignNumber ( key ) )
677688 endfor
678689 unlet s: breakpoints
679690
@@ -700,7 +711,7 @@ func s:SetBreakpoint()
700711 endif
701712 " Use the fname:lnum format, older gdb can't handle --source.
702713 call s: SendCommand (' -break-insert '
703- \ . fnameescape (expand (' %:p' )) . ' :' . line (' .' ))
714+ \ . fnameescape (expand (' %:p' )) . ' :' . line (' .' ))
704715 if do_continue
705716 call s: SendCommand (' -exec-continue' )
706717 endif
@@ -714,7 +725,7 @@ func s:ClearBreakpoint()
714725 if val[' fname' ] == fname && val[' lnum' ] == lnum
715726 call s: SendCommand (' -break-delete ' . key )
716727 " Assume this always wors, the reply is simply "^done".
717- exe ' sign unplace ' . (s: break_id + key )
728+ exe ' sign unplace ' . (s: break_id + s: Breakpoint2SignNumber ( key ) )
718729 unlet s: breakpoints [key ]
719730 break
720731 endif
@@ -839,14 +850,14 @@ func s:HandleCursor(msg)
839850 if lnum = ~ ' ^[0-9]*$'
840851 call s: GotoSourcewinOrCreateIt ()
841852 if expand (' %:p' ) != fnamemodify (fname, ' :p' )
842- if &modified
843- " TODO: find existing window
844- exe ' split ' . fnameescape (fname)
845- let s: sourcewin = win_getid (winnr ())
846- call s: InstallWinbar ()
847- else
848- exe ' edit ' . fnameescape (fname)
849- endif
853+ if &modified
854+ " TODO: find existing window
855+ exe ' split ' . fnameescape (fname)
856+ let s: sourcewin = win_getid (winnr ())
857+ call s: InstallWinbar ()
858+ else
859+ exe ' edit ' . fnameescape (fname)
860+ endif
850861 endif
851862 exe lnum
852863 exe ' sign unplace ' . s: pc_id
@@ -865,61 +876,72 @@ let s:BreakpointSigns = []
865876func s: CreateBreakpoint (nr)
866877 if index (s: BreakpointSigns , a: nr ) == -1
867878 call add (s: BreakpointSigns , a: nr )
868- exe " sign define debugBreakpoint" . a: nr . " text=" . a: nr . " texthl=debugBreakpoint"
879+ exe " sign define debugBreakpoint" . a: nr . " text=" . substitute ( a: nr, ' \..* ' , ' ' , ' ' ) . " texthl=debugBreakpoint"
869880 endif
870881endfunc
871882
883+ func s: SplitMsg (s )
884+ return split (a: s , ' {\%([a-z-]\+=[^,]\+,*\)\+}\zs' )
885+ endfunction
886+
872887" Handle setting a breakpoint
873888" Will update the sign that shows the breakpoint
874889func s: HandleNewBreakpoint (msg)
875890 if a: msg !~ ' fullname='
876891 " a watch does not have a file name
877892 return
878893 endif
894+ for msg in s: SplitMsg (a: msg )
895+ let fname = s: GetFullname (msg)
896+ if empty (fname)
897+ continue
898+ endif
899+ let nr = substitute (msg, ' .*number="\([0-9.]*\)\".*' , ' \1' , ' ' )
900+ if empty (nr)
901+ return
902+ endif
903+ call s: CreateBreakpoint (nr)
879904
880- let nr = substitute (a: msg , ' .*number="\([0-9]*\)".*' , ' \1' , ' ' ) + 0
881- if nr == 0
882- return
883- endif
884- call s: CreateBreakpoint (nr)
885-
886- if has_key (s: breakpoints , nr)
887- let entry = s: breakpoints [nr]
888- else
889- let entry = {}
890- let s: breakpoints [nr] = entry
891- endif
905+ if has_key (s: breakpoints , nr)
906+ let entry = s: breakpoints [nr]
907+ else
908+ let entry = {}
909+ let s: breakpoints [nr] = entry
910+ endif
892911
893- let fname = s: GetFullname (a: msg )
894- let lnum = substitute (a: msg , ' .*line="\([^"]*\)".*' , ' \1' , ' ' )
895- let entry[' fname' ] = fname
896- let entry[' lnum' ] = lnum
912+ let lnum = substitute (msg, ' .*line="\([^"]*\)".*' , ' \1' , ' ' )
913+ let entry[' fname' ] = fname
914+ let entry[' lnum' ] = lnum
897915
898- if bufloaded (fname)
899- call s: PlaceSign (nr, entry)
900- endif
916+ if bufloaded (fname)
917+ call s: PlaceSign (nr, entry)
918+ endif
919+ endfor
901920endfunc
902921
903922func s: PlaceSign (nr, entry)
904- exe ' sign place ' . (s: break_id + a: nr ) . ' line=' . a: entry [' lnum' ] . ' name=debugBreakpoint' . a: nr . ' file=' . a: entry [' fname' ]
923+ exe ' sign place ' . (s: break_id + s: Breakpoint2SignNumber ( a: nr) ) . ' line=' . a: entry [' lnum' ] . ' name=debugBreakpoint' . a: nr . ' file=' . a: entry [' fname' ]
905924 let a: entry [' placed' ] = 1
906925endfunc
907926
908927" Handle deleting a breakpoint
909928" Will remove the sign that shows the breakpoint
910929func s: HandleBreakpointDelete (msg)
911- let nr = substitute (a: msg , ' .*id="\([0-9]*\)\".*' , ' \1' , ' ' ) + 0
912- if nr == 0
930+ let key = substitute (a: msg , ' .*id="\([0-9. ]*\)\".*' , ' \1' , ' ' )
931+ if empty ( key )
913932 return
914933 endif
915- if has_key (s: breakpoints , nr)
934+ for [nr, entry] in items (s: breakpoints )
935+ if stridx (nr, key ) != 0
936+ continue
937+ endif
916938 let entry = s: breakpoints [nr]
917939 if has_key (entry, ' placed' )
918- exe ' sign unplace ' . (s: break_id + nr )
940+ exe ' sign unplace ' . (s: break_id + s: Breakpoint2SignNumber (nr) )
919941 unlet entry[' placed' ]
920942 endif
921943 unlet s: breakpoints [nr]
922- endif
944+ endfor
923945endfunc
924946
925947" Handle the debugged program starting to run.
0 commit comments