blob: 10dc86dcc67c975c6072de1de13898a5707cf6e2 [file] [log] [blame]
Bram Moolenaareead75c2019-04-21 11:35:00 +02001/* 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)
17static int debug_greedy = FALSE; /* batch mode debugging: don't save
18 and restore typeahead. */
19static void do_setdebugtracelevel(char_u *arg);
20static void do_checkbacktracelevel(void);
21static void do_showbacktrace(char_u *cmd);
22
23static char_u *debug_oldval = NULL; /* old and newval for debug expressions */
24static char_u *debug_newval = NULL;
25static int debug_expr = 0; /* use debug_expr */
26
27 int
28has_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
38do_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
304get_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
322do_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
336do_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
356do_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
392ex_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
401static char_u *debug_breakpoint_name = NULL;
402static 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 */
411static int debug_skipped;
412static 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
422dbg_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
469dbg_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 */
496struct 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
510static 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])
513static int last_breakp = 0; /* nr of last defined breakpoint */
514
515#ifdef FEAT_PROFILE
516/* Profiling uses file and func names similar to breakpoints. */
517static 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
523static 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
532dbg_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
641ex_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
695ex_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
707ex_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
802ex_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
832dbg_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
845has_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
859debuggy_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
984dbg_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