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