xref: /vim-8.2.3635/src/debugger.c (revision 5d684456)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * debugger.c: Vim script debugger functions
12  */
13 
14 #include "vim.h"
15 
16 #if defined(FEAT_EVAL) || defined(PROTO)
17 static int debug_greedy = FALSE;	// batch mode debugging: don't save
18 					// and restore typeahead.
19 static void do_setdebugtracelevel(char_u *arg);
20 static void do_checkbacktracelevel(void);
21 static void do_showbacktrace(char_u *cmd);
22 
23 static char_u *debug_oldval = NULL;	// old and newval for debug expressions
24 static char_u *debug_newval = NULL;
25 static int     debug_expr   = 0;        // use debug_expr
26 
27     int
28 has_watchexpr(void)
29 {
30     return debug_expr;
31 }
32 
33 /*
34  * do_debug(): Debug mode.
35  * Repeatedly get Ex commands, until told to continue normal execution.
36  */
37     void
38 do_debug(char_u *cmd)
39 {
40     int		save_msg_scroll = msg_scroll;
41     int		save_State = State;
42     int		save_did_emsg = did_emsg;
43     int		save_cmd_silent = cmd_silent;
44     int		save_msg_silent = msg_silent;
45     int		save_emsg_silent = emsg_silent;
46     int		save_redir_off = redir_off;
47     tasave_T	typeaheadbuf;
48     int		typeahead_saved = FALSE;
49     int		save_ignore_script = 0;
50     int		save_ex_normal_busy;
51     int		n;
52     char_u	*cmdline = NULL;
53     char_u	*p;
54     char	*tail = NULL;
55     static int	last_cmd = 0;
56 #define CMD_CONT	1
57 #define CMD_NEXT	2
58 #define CMD_STEP	3
59 #define CMD_FINISH	4
60 #define CMD_QUIT	5
61 #define CMD_INTERRUPT	6
62 #define CMD_BACKTRACE	7
63 #define CMD_FRAME	8
64 #define CMD_UP		9
65 #define CMD_DOWN	10
66 
67 #ifdef ALWAYS_USE_GUI
68     // Can't do this when there is no terminal for input/output.
69     if (!gui.in_use)
70     {
71 	// Break as soon as possible.
72 	debug_break_level = 9999;
73 	return;
74     }
75 #endif
76 
77     // Make sure we are in raw mode and start termcap mode.  Might have side
78     // effects...
79     settmode(TMODE_RAW);
80     starttermcap();
81 
82     ++RedrawingDisabled;	// don't redisplay the window
83     ++no_wait_return;		// don't wait for return
84     did_emsg = FALSE;		// don't use error from debugged stuff
85     cmd_silent = FALSE;		// display commands
86     msg_silent = FALSE;		// display messages
87     emsg_silent = FALSE;	// display error messages
88     redir_off = TRUE;		// don't redirect debug commands
89 
90     State = NORMAL;
91     debug_mode = TRUE;
92 
93     if (!debug_did_msg)
94 	msg(_("Entering Debug mode.  Type \"cont\" to continue."));
95     if (debug_oldval != NULL)
96     {
97 	smsg(_("Oldval = \"%s\""), debug_oldval);
98 	vim_free(debug_oldval);
99 	debug_oldval = NULL;
100     }
101     if (debug_newval != NULL)
102     {
103 	smsg(_("Newval = \"%s\""), debug_newval);
104 	vim_free(debug_newval);
105 	debug_newval = NULL;
106     }
107     if (sourcing_name != NULL)
108 	msg((char *)sourcing_name);
109     if (sourcing_lnum != 0)
110 	smsg(_("line %ld: %s"), (long)sourcing_lnum, cmd);
111     else
112 	smsg(_("cmd: %s"), cmd);
113 
114     // Repeat getting a command and executing it.
115     for (;;)
116     {
117 	msg_scroll = TRUE;
118 	need_wait_return = FALSE;
119 
120 	// Save the current typeahead buffer and replace it with an empty one.
121 	// This makes sure we get input from the user here and don't interfere
122 	// with the commands being executed.  Reset "ex_normal_busy" to avoid
123 	// the side effects of using ":normal". Save the stuff buffer and make
124 	// it empty. Set ignore_script to avoid reading from script input.
125 	save_ex_normal_busy = ex_normal_busy;
126 	ex_normal_busy = 0;
127 	if (!debug_greedy)
128 	{
129 	    save_typeahead(&typeaheadbuf);
130 	    typeahead_saved = TRUE;
131 	    save_ignore_script = ignore_script;
132 	    ignore_script = TRUE;
133 	}
134 
135 	vim_free(cmdline);
136 	cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL);
137 
138 	if (typeahead_saved)
139 	{
140 	    restore_typeahead(&typeaheadbuf);
141 	    ignore_script = save_ignore_script;
142 	}
143 	ex_normal_busy = save_ex_normal_busy;
144 
145 	cmdline_row = msg_row;
146 	msg_starthere();
147 	if (cmdline != NULL)
148 	{
149 	    // If this is a debug command, set "last_cmd".
150 	    // If not, reset "last_cmd".
151 	    // For a blank line use previous command.
152 	    p = skipwhite(cmdline);
153 	    if (*p != NUL)
154 	    {
155 		switch (*p)
156 		{
157 		    case 'c': last_cmd = CMD_CONT;
158 			      tail = "ont";
159 			      break;
160 		    case 'n': last_cmd = CMD_NEXT;
161 			      tail = "ext";
162 			      break;
163 		    case 's': last_cmd = CMD_STEP;
164 			      tail = "tep";
165 			      break;
166 		    case 'f':
167 			      last_cmd = 0;
168 			      if (p[1] == 'r')
169 			      {
170 				  last_cmd = CMD_FRAME;
171 				  tail = "rame";
172 			      }
173 			      else
174 			      {
175 				  last_cmd = CMD_FINISH;
176 				  tail = "inish";
177 			      }
178 			      break;
179 		    case 'q': last_cmd = CMD_QUIT;
180 			      tail = "uit";
181 			      break;
182 		    case 'i': last_cmd = CMD_INTERRUPT;
183 			      tail = "nterrupt";
184 			      break;
185 		    case 'b': last_cmd = CMD_BACKTRACE;
186 			      if (p[1] == 't')
187 				  tail = "t";
188 			      else
189 				  tail = "acktrace";
190 			      break;
191 		    case 'w': last_cmd = CMD_BACKTRACE;
192 			      tail = "here";
193 			      break;
194 		    case 'u': last_cmd = CMD_UP;
195 			      tail = "p";
196 			      break;
197 		    case 'd': last_cmd = CMD_DOWN;
198 			      tail = "own";
199 			      break;
200 		    default: last_cmd = 0;
201 		}
202 		if (last_cmd != 0)
203 		{
204 		    // Check that the tail matches.
205 		    ++p;
206 		    while (*p != NUL && *p == *tail)
207 		    {
208 			++p;
209 			++tail;
210 		    }
211 		    if (ASCII_ISALPHA(*p) && last_cmd != CMD_FRAME)
212 			last_cmd = 0;
213 		}
214 	    }
215 
216 	    if (last_cmd != 0)
217 	    {
218 		// Execute debug command: decided where to break next and
219 		// return.
220 		switch (last_cmd)
221 		{
222 		    case CMD_CONT:
223 			debug_break_level = -1;
224 			break;
225 		    case CMD_NEXT:
226 			debug_break_level = ex_nesting_level;
227 			break;
228 		    case CMD_STEP:
229 			debug_break_level = 9999;
230 			break;
231 		    case CMD_FINISH:
232 			debug_break_level = ex_nesting_level - 1;
233 			break;
234 		    case CMD_QUIT:
235 			got_int = TRUE;
236 			debug_break_level = -1;
237 			break;
238 		    case CMD_INTERRUPT:
239 			got_int = TRUE;
240 			debug_break_level = 9999;
241 			// Do not repeat ">interrupt" cmd, continue stepping.
242 			last_cmd = CMD_STEP;
243 			break;
244 		    case CMD_BACKTRACE:
245 			do_showbacktrace(cmd);
246 			continue;
247 		    case CMD_FRAME:
248 			if (*p == NUL)
249 			{
250 			    do_showbacktrace(cmd);
251 			}
252 			else
253 			{
254 			    p = skipwhite(p);
255 			    do_setdebugtracelevel(p);
256 			}
257 			continue;
258 		    case CMD_UP:
259 			debug_backtrace_level++;
260 			do_checkbacktracelevel();
261 			continue;
262 		    case CMD_DOWN:
263 			debug_backtrace_level--;
264 			do_checkbacktracelevel();
265 			continue;
266 		}
267 		// Going out reset backtrace_level
268 		debug_backtrace_level = 0;
269 		break;
270 	    }
271 
272 	    // don't debug this command
273 	    n = debug_break_level;
274 	    debug_break_level = -1;
275 	    (void)do_cmdline(cmdline, getexline, NULL,
276 						DOCMD_VERBOSE|DOCMD_EXCRESET);
277 	    debug_break_level = n;
278 	}
279 	lines_left = Rows - 1;
280     }
281     vim_free(cmdline);
282 
283     --RedrawingDisabled;
284     --no_wait_return;
285     redraw_all_later(NOT_VALID);
286     need_wait_return = FALSE;
287     msg_scroll = save_msg_scroll;
288     lines_left = Rows - 1;
289     State = save_State;
290     debug_mode = FALSE;
291     did_emsg = save_did_emsg;
292     cmd_silent = save_cmd_silent;
293     msg_silent = save_msg_silent;
294     emsg_silent = save_emsg_silent;
295     redir_off = save_redir_off;
296 
297     // Only print the message again when typing a command before coming back
298     // here.
299     debug_did_msg = TRUE;
300 }
301 
302     static int
303 get_maxbacktrace_level(void)
304 {
305     char	*p, *q;
306     int		maxbacktrace = 0;
307 
308     if (sourcing_name != NULL)
309     {
310 	p = (char *)sourcing_name;
311 	while ((q = strstr(p, "..")) != NULL)
312 	{
313 	    p = q + 2;
314 	    maxbacktrace++;
315 	}
316     }
317     return maxbacktrace;
318 }
319 
320     static void
321 do_setdebugtracelevel(char_u *arg)
322 {
323     int level;
324 
325     level = atoi((char *)arg);
326     if (*arg == '+' || level < 0)
327 	debug_backtrace_level += level;
328     else
329 	debug_backtrace_level = level;
330 
331     do_checkbacktracelevel();
332 }
333 
334     static void
335 do_checkbacktracelevel(void)
336 {
337     if (debug_backtrace_level < 0)
338     {
339 	debug_backtrace_level = 0;
340 	msg(_("frame is zero"));
341     }
342     else
343     {
344 	int max = get_maxbacktrace_level();
345 
346 	if (debug_backtrace_level > max)
347 	{
348 	    debug_backtrace_level = max;
349 	    smsg(_("frame at highest level: %d"), max);
350 	}
351     }
352 }
353 
354     static void
355 do_showbacktrace(char_u *cmd)
356 {
357     char    *cur;
358     char    *next;
359     int	    i = 0;
360     int	    max = get_maxbacktrace_level();
361 
362     if (sourcing_name != NULL)
363     {
364 	cur = (char *)sourcing_name;
365 	while (!got_int)
366 	{
367 	    next = strstr(cur, "..");
368 	    if (next != NULL)
369 		*next = NUL;
370 	    if (i == max - debug_backtrace_level)
371 		smsg("->%d %s", max - i, cur);
372 	    else
373 		smsg("  %d %s", max - i, cur);
374 	    ++i;
375 	    if (next == NULL)
376 		break;
377 	    *next = '.';
378 	    cur = next + 2;
379 	}
380     }
381     if (sourcing_lnum != 0)
382        smsg(_("line %ld: %s"), (long)sourcing_lnum, cmd);
383     else
384        smsg(_("cmd: %s"), cmd);
385 }
386 
387 /*
388  * ":debug".
389  */
390     void
391 ex_debug(exarg_T *eap)
392 {
393     int		debug_break_level_save = debug_break_level;
394 
395     debug_break_level = 9999;
396     do_cmdline_cmd(eap->arg);
397     debug_break_level = debug_break_level_save;
398 }
399 
400 static char_u	*debug_breakpoint_name = NULL;
401 static linenr_T	debug_breakpoint_lnum;
402 
403 /*
404  * When debugging or a breakpoint is set on a skipped command, no debug prompt
405  * is shown by do_one_cmd().  This situation is indicated by debug_skipped, and
406  * debug_skipped_name is then set to the source name in the breakpoint case.  If
407  * a skipped command decides itself that a debug prompt should be displayed, it
408  * can do so by calling dbg_check_skipped().
409  */
410 static int	debug_skipped;
411 static char_u	*debug_skipped_name;
412 
413 /*
414  * Go to debug mode when a breakpoint was encountered or "ex_nesting_level" is
415  * at or below the break level.  But only when the line is actually
416  * executed.  Return TRUE and set breakpoint_name for skipped commands that
417  * decide to execute something themselves.
418  * Called from do_one_cmd() before executing a command.
419  */
420     void
421 dbg_check_breakpoint(exarg_T *eap)
422 {
423     char_u	*p;
424 
425     debug_skipped = FALSE;
426     if (debug_breakpoint_name != NULL)
427     {
428 	if (!eap->skip)
429 	{
430 	    // replace K_SNR with "<SNR>"
431 	    if (debug_breakpoint_name[0] == K_SPECIAL
432 		    && debug_breakpoint_name[1] == KS_EXTRA
433 		    && debug_breakpoint_name[2] == (int)KE_SNR)
434 		p = (char_u *)"<SNR>";
435 	    else
436 		p = (char_u *)"";
437 	    smsg(_("Breakpoint in \"%s%s\" line %ld"),
438 		    p,
439 		    debug_breakpoint_name + (*p == NUL ? 0 : 3),
440 		    (long)debug_breakpoint_lnum);
441 	    debug_breakpoint_name = NULL;
442 	    do_debug(eap->cmd);
443 	}
444 	else
445 	{
446 	    debug_skipped = TRUE;
447 	    debug_skipped_name = debug_breakpoint_name;
448 	    debug_breakpoint_name = NULL;
449 	}
450     }
451     else if (ex_nesting_level <= debug_break_level)
452     {
453 	if (!eap->skip)
454 	    do_debug(eap->cmd);
455 	else
456 	{
457 	    debug_skipped = TRUE;
458 	    debug_skipped_name = NULL;
459 	}
460     }
461 }
462 
463 /*
464  * Go to debug mode if skipped by dbg_check_breakpoint() because eap->skip was
465  * set.  Return TRUE when the debug mode is entered this time.
466  */
467     int
468 dbg_check_skipped(exarg_T *eap)
469 {
470     int		prev_got_int;
471 
472     if (debug_skipped)
473     {
474 	// Save the value of got_int and reset it.  We don't want a previous
475 	// interruption cause flushing the input buffer.
476 	prev_got_int = got_int;
477 	got_int = FALSE;
478 	debug_breakpoint_name = debug_skipped_name;
479 	// eap->skip is TRUE
480 	eap->skip = FALSE;
481 	(void)dbg_check_breakpoint(eap);
482 	eap->skip = TRUE;
483 	got_int |= prev_got_int;
484 	return TRUE;
485     }
486     return FALSE;
487 }
488 
489 /*
490  * The list of breakpoints: dbg_breakp.
491  * This is a grow-array of structs.
492  */
493 struct debuggy
494 {
495     int		dbg_nr;		// breakpoint number
496     int		dbg_type;	// DBG_FUNC, DBG_FILE or DBG_EXPR
497     char_u	*dbg_name;	// function, expression or file name
498     regprog_T	*dbg_prog;	// regexp program
499     linenr_T	dbg_lnum;	// line number in function or file
500     int		dbg_forceit;	// ! used
501 #ifdef FEAT_EVAL
502     typval_T    *dbg_val;       // last result of watchexpression
503 #endif
504     int		dbg_level;      // stored nested level for expr
505 };
506 
507 static garray_T dbg_breakp = {0, 0, sizeof(struct debuggy), 4, NULL};
508 #define BREAKP(idx)		(((struct debuggy *)dbg_breakp.ga_data)[idx])
509 #define DEBUGGY(gap, idx)	(((struct debuggy *)gap->ga_data)[idx])
510 static int last_breakp = 0;	// nr of last defined breakpoint
511 
512 #ifdef FEAT_PROFILE
513 // Profiling uses file and func names similar to breakpoints.
514 static garray_T prof_ga = {0, 0, sizeof(struct debuggy), 4, NULL};
515 #endif
516 #define DBG_FUNC	1
517 #define DBG_FILE	2
518 #define DBG_EXPR	3
519 
520 static linenr_T debuggy_find(int file,char_u *fname, linenr_T after, garray_T *gap, int *fp);
521 
522 /*
523  * Parse the arguments of ":profile", ":breakadd" or ":breakdel" and put them
524  * in the entry just after the last one in dbg_breakp.  Note that "dbg_name"
525  * is allocated.
526  * Returns FAIL for failure.
527  */
528     static int
529 dbg_parsearg(
530     char_u	*arg,
531     garray_T	*gap)	    // either &dbg_breakp or &prof_ga
532 {
533     char_u	*p = arg;
534     char_u	*q;
535     struct debuggy *bp;
536     int		here = FALSE;
537 
538     if (ga_grow(gap, 1) == FAIL)
539 	return FAIL;
540     bp = &DEBUGGY(gap, gap->ga_len);
541 
542     // Find "func" or "file".
543     if (STRNCMP(p, "func", 4) == 0)
544 	bp->dbg_type = DBG_FUNC;
545     else if (STRNCMP(p, "file", 4) == 0)
546 	bp->dbg_type = DBG_FILE;
547     else if (
548 #ifdef FEAT_PROFILE
549 	    gap != &prof_ga &&
550 #endif
551 	    STRNCMP(p, "here", 4) == 0)
552     {
553 	if (curbuf->b_ffname == NULL)
554 	{
555 	    emsg(_(e_noname));
556 	    return FAIL;
557 	}
558 	bp->dbg_type = DBG_FILE;
559 	here = TRUE;
560     }
561     else if (
562 #ifdef FEAT_PROFILE
563 	    gap != &prof_ga &&
564 #endif
565 	    STRNCMP(p, "expr", 4) == 0)
566 	bp->dbg_type = DBG_EXPR;
567     else
568     {
569 	semsg(_(e_invarg2), p);
570 	return FAIL;
571     }
572     p = skipwhite(p + 4);
573 
574     // Find optional line number.
575     if (here)
576 	bp->dbg_lnum = curwin->w_cursor.lnum;
577     else if (
578 #ifdef FEAT_PROFILE
579 	    gap != &prof_ga &&
580 #endif
581 	    VIM_ISDIGIT(*p))
582     {
583 	bp->dbg_lnum = getdigits(&p);
584 	p = skipwhite(p);
585     }
586     else
587 	bp->dbg_lnum = 0;
588 
589     // Find the function or file name.  Don't accept a function name with ().
590     if ((!here && *p == NUL)
591 	    || (here && *p != NUL)
592 	    || (bp->dbg_type == DBG_FUNC && strstr((char *)p, "()") != NULL))
593     {
594 	semsg(_(e_invarg2), arg);
595 	return FAIL;
596     }
597 
598     if (bp->dbg_type == DBG_FUNC)
599 	bp->dbg_name = vim_strsave(p);
600     else if (here)
601 	bp->dbg_name = vim_strsave(curbuf->b_ffname);
602     else if (bp->dbg_type == DBG_EXPR)
603     {
604 	bp->dbg_name = vim_strsave(p);
605 	if (bp->dbg_name != NULL)
606 	    bp->dbg_val = eval_expr(bp->dbg_name, NULL);
607     }
608     else
609     {
610 	// Expand the file name in the same way as do_source().  This means
611 	// doing it twice, so that $DIR/file gets expanded when $DIR is
612 	// "~/dir".
613 	q = expand_env_save(p);
614 	if (q == NULL)
615 	    return FAIL;
616 	p = expand_env_save(q);
617 	vim_free(q);
618 	if (p == NULL)
619 	    return FAIL;
620 	if (*p != '*')
621 	{
622 	    bp->dbg_name = fix_fname(p);
623 	    vim_free(p);
624 	}
625 	else
626 	    bp->dbg_name = p;
627     }
628 
629     if (bp->dbg_name == NULL)
630 	return FAIL;
631     return OK;
632 }
633 
634 /*
635  * ":breakadd".  Also used for ":profile".
636  */
637     void
638 ex_breakadd(exarg_T *eap)
639 {
640     struct debuggy *bp;
641     char_u	*pat;
642     garray_T	*gap;
643 
644     gap = &dbg_breakp;
645 #ifdef FEAT_PROFILE
646     if (eap->cmdidx == CMD_profile)
647 	gap = &prof_ga;
648 #endif
649 
650     if (dbg_parsearg(eap->arg, gap) == OK)
651     {
652 	bp = &DEBUGGY(gap, gap->ga_len);
653 	bp->dbg_forceit = eap->forceit;
654 
655 	if (bp->dbg_type != DBG_EXPR)
656 	{
657 	    pat = file_pat_to_reg_pat(bp->dbg_name, NULL, NULL, FALSE);
658 	    if (pat != NULL)
659 	    {
660 		bp->dbg_prog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
661 		vim_free(pat);
662 	    }
663 	    if (pat == NULL || bp->dbg_prog == NULL)
664 		vim_free(bp->dbg_name);
665 	    else
666 	    {
667 		if (bp->dbg_lnum == 0)	// default line number is 1
668 		    bp->dbg_lnum = 1;
669 #ifdef FEAT_PROFILE
670 		if (eap->cmdidx != CMD_profile)
671 #endif
672 		{
673 		    DEBUGGY(gap, gap->ga_len).dbg_nr = ++last_breakp;
674 		    ++debug_tick;
675 		}
676 		++gap->ga_len;
677 	    }
678 	}
679 	else
680 	{
681 	    // DBG_EXPR
682 	    DEBUGGY(gap, gap->ga_len++).dbg_nr = ++last_breakp;
683 	    ++debug_tick;
684 	}
685     }
686 }
687 
688 /*
689  * ":debuggreedy".
690  */
691     void
692 ex_debuggreedy(exarg_T *eap)
693 {
694     if (eap->addr_count == 0 || eap->line2 != 0)
695 	debug_greedy = TRUE;
696     else
697 	debug_greedy = FALSE;
698 }
699 
700 /*
701  * ":breakdel" and ":profdel".
702  */
703     void
704 ex_breakdel(exarg_T *eap)
705 {
706     struct debuggy *bp, *bpi;
707     int		nr;
708     int		todel = -1;
709     int		del_all = FALSE;
710     int		i;
711     linenr_T	best_lnum = 0;
712     garray_T	*gap;
713 
714     gap = &dbg_breakp;
715     if (eap->cmdidx == CMD_profdel)
716     {
717 #ifdef FEAT_PROFILE
718 	gap = &prof_ga;
719 #else
720 	ex_ni(eap);
721 	return;
722 #endif
723     }
724 
725     if (vim_isdigit(*eap->arg))
726     {
727 	// ":breakdel {nr}"
728 	nr = atol((char *)eap->arg);
729 	for (i = 0; i < gap->ga_len; ++i)
730 	    if (DEBUGGY(gap, i).dbg_nr == nr)
731 	    {
732 		todel = i;
733 		break;
734 	    }
735     }
736     else if (*eap->arg == '*')
737     {
738 	todel = 0;
739 	del_all = TRUE;
740     }
741     else
742     {
743 	// ":breakdel {func|file|expr} [lnum] {name}"
744 	if (dbg_parsearg(eap->arg, gap) == FAIL)
745 	    return;
746 	bp = &DEBUGGY(gap, gap->ga_len);
747 	for (i = 0; i < gap->ga_len; ++i)
748 	{
749 	    bpi = &DEBUGGY(gap, i);
750 	    if (bp->dbg_type == bpi->dbg_type
751 		    && STRCMP(bp->dbg_name, bpi->dbg_name) == 0
752 		    && (bp->dbg_lnum == bpi->dbg_lnum
753 			|| (bp->dbg_lnum == 0
754 			    && (best_lnum == 0
755 				|| bpi->dbg_lnum < best_lnum))))
756 	    {
757 		todel = i;
758 		best_lnum = bpi->dbg_lnum;
759 	    }
760 	}
761 	vim_free(bp->dbg_name);
762     }
763 
764     if (todel < 0)
765 	semsg(_("E161: Breakpoint not found: %s"), eap->arg);
766     else
767     {
768 	while (gap->ga_len > 0)
769 	{
770 	    vim_free(DEBUGGY(gap, todel).dbg_name);
771 #ifdef FEAT_EVAL
772 	    if (DEBUGGY(gap, todel).dbg_type == DBG_EXPR
773 		    && DEBUGGY(gap, todel).dbg_val != NULL)
774 		free_tv(DEBUGGY(gap, todel).dbg_val);
775 #endif
776 	    vim_regfree(DEBUGGY(gap, todel).dbg_prog);
777 	    --gap->ga_len;
778 	    if (todel < gap->ga_len)
779 		mch_memmove(&DEBUGGY(gap, todel), &DEBUGGY(gap, todel + 1),
780 			      (gap->ga_len - todel) * sizeof(struct debuggy));
781 #ifdef FEAT_PROFILE
782 	    if (eap->cmdidx == CMD_breakdel)
783 #endif
784 		++debug_tick;
785 	    if (!del_all)
786 		break;
787 	}
788 
789 	// If all breakpoints were removed clear the array.
790 	if (gap->ga_len == 0)
791 	    ga_clear(gap);
792     }
793 }
794 
795 /*
796  * ":breaklist".
797  */
798     void
799 ex_breaklist(exarg_T *eap UNUSED)
800 {
801     struct debuggy *bp;
802     int		i;
803 
804     if (dbg_breakp.ga_len == 0)
805 	msg(_("No breakpoints defined"));
806     else
807 	for (i = 0; i < dbg_breakp.ga_len; ++i)
808 	{
809 	    bp = &BREAKP(i);
810 	    if (bp->dbg_type == DBG_FILE)
811 		home_replace(NULL, bp->dbg_name, NameBuff, MAXPATHL, TRUE);
812 	    if (bp->dbg_type != DBG_EXPR)
813 		smsg(_("%3d  %s %s  line %ld"),
814 		    bp->dbg_nr,
815 		    bp->dbg_type == DBG_FUNC ? "func" : "file",
816 		    bp->dbg_type == DBG_FUNC ? bp->dbg_name : NameBuff,
817 		    (long)bp->dbg_lnum);
818 	    else
819 		smsg(_("%3d  expr %s"),
820 		    bp->dbg_nr, bp->dbg_name);
821 	}
822 }
823 
824 /*
825  * Find a breakpoint for a function or sourced file.
826  * Returns line number at which to break; zero when no matching breakpoint.
827  */
828     linenr_T
829 dbg_find_breakpoint(
830     int		file,	    // TRUE for a file, FALSE for a function
831     char_u	*fname,	    // file or function name
832     linenr_T	after)	    // after this line number
833 {
834     return debuggy_find(file, fname, after, &dbg_breakp, NULL);
835 }
836 
837 #if defined(FEAT_PROFILE) || defined(PROTO)
838 /*
839  * Return TRUE if profiling is on for a function or sourced file.
840  */
841     int
842 has_profiling(
843     int		file,	    // TRUE for a file, FALSE for a function
844     char_u	*fname,	    // file or function name
845     int		*fp)	    // return: forceit
846 {
847     return (debuggy_find(file, fname, (linenr_T)0, &prof_ga, fp)
848 							      != (linenr_T)0);
849 }
850 #endif
851 
852 /*
853  * Common code for dbg_find_breakpoint() and has_profiling().
854  */
855     static linenr_T
856 debuggy_find(
857     int		file,	    // TRUE for a file, FALSE for a function
858     char_u	*fname,	    // file or function name
859     linenr_T	after,	    // after this line number
860     garray_T	*gap,	    // either &dbg_breakp or &prof_ga
861     int		*fp)	    // if not NULL: return forceit
862 {
863     struct debuggy *bp;
864     int		i;
865     linenr_T	lnum = 0;
866     char_u	*name = fname;
867     int		prev_got_int;
868 
869     // Return quickly when there are no breakpoints.
870     if (gap->ga_len == 0)
871 	return (linenr_T)0;
872 
873     // Replace K_SNR in function name with "<SNR>".
874     if (!file && fname[0] == K_SPECIAL)
875     {
876 	name = alloc(STRLEN(fname) + 3);
877 	if (name == NULL)
878 	    name = fname;
879 	else
880 	{
881 	    STRCPY(name, "<SNR>");
882 	    STRCPY(name + 5, fname + 3);
883 	}
884     }
885 
886     for (i = 0; i < gap->ga_len; ++i)
887     {
888 	// Skip entries that are not useful or are for a line that is beyond
889 	// an already found breakpoint.
890 	bp = &DEBUGGY(gap, i);
891 	if (((bp->dbg_type == DBG_FILE) == file &&
892 		bp->dbg_type != DBG_EXPR && (
893 #ifdef FEAT_PROFILE
894 		gap == &prof_ga ||
895 #endif
896 		(bp->dbg_lnum > after && (lnum == 0 || bp->dbg_lnum < lnum)))))
897 	{
898 	    // Save the value of got_int and reset it.  We don't want a
899 	    // previous interruption cancel matching, only hitting CTRL-C
900 	    // while matching should abort it.
901 	    prev_got_int = got_int;
902 	    got_int = FALSE;
903 	    if (vim_regexec_prog(&bp->dbg_prog, FALSE, name, (colnr_T)0))
904 	    {
905 		lnum = bp->dbg_lnum;
906 		if (fp != NULL)
907 		    *fp = bp->dbg_forceit;
908 	    }
909 	    got_int |= prev_got_int;
910 	}
911 #ifdef FEAT_EVAL
912 	else if (bp->dbg_type == DBG_EXPR)
913 	{
914 	    typval_T *tv;
915 	    int	      line = FALSE;
916 
917 	    prev_got_int = got_int;
918 	    got_int = FALSE;
919 
920 	    tv = eval_expr(bp->dbg_name, NULL);
921 	    if (tv != NULL)
922 	    {
923 		if (bp->dbg_val == NULL)
924 		{
925 		    debug_oldval = typval_tostring(NULL);
926 		    bp->dbg_val = tv;
927 		    debug_newval = typval_tostring(bp->dbg_val);
928 		    line = TRUE;
929 		}
930 		else
931 		{
932 		    if (typval_compare(tv, bp->dbg_val, TYPE_EQUAL,
933 							     TRUE, FALSE) == OK
934 			    && tv->vval.v_number == FALSE)
935 		    {
936 			typval_T *v;
937 
938 			line = TRUE;
939 			debug_oldval = typval_tostring(bp->dbg_val);
940 			// Need to evaluate again, typval_compare() overwrites
941 			// "tv".
942 			v = eval_expr(bp->dbg_name, NULL);
943 			debug_newval = typval_tostring(v);
944 			free_tv(bp->dbg_val);
945 			bp->dbg_val = v;
946 		    }
947 		    free_tv(tv);
948 		}
949 	    }
950 	    else if (bp->dbg_val != NULL)
951 	    {
952 		debug_oldval = typval_tostring(bp->dbg_val);
953 		debug_newval = typval_tostring(NULL);
954 		free_tv(bp->dbg_val);
955 		bp->dbg_val = NULL;
956 		line = TRUE;
957 	    }
958 
959 	    if (line)
960 	    {
961 		lnum = after > 0 ? after : 1;
962 		break;
963 	    }
964 
965 	    got_int |= prev_got_int;
966 	}
967 #endif
968     }
969     if (name != fname)
970 	vim_free(name);
971 
972     return lnum;
973 }
974 
975 /*
976  * Called when a breakpoint was encountered.
977  */
978     void
979 dbg_breakpoint(char_u *name, linenr_T lnum)
980 {
981     // We need to check if this line is actually executed in do_one_cmd()
982     debug_breakpoint_name = name;
983     debug_breakpoint_lnum = lnum;
984 }
985 #endif
986