Mercurial > vim
comparison src/ex_cmds2.c @ 13262:69278c25429d v8.0.1505
patch 8.0.1505: debugger can't break on a condition
commit https://github.com/vim/vim/commit/c6f9f739d32084923c3031cbf6f581f8c8bf7fd2
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Feb 11 19:06:26 2018 +0100
patch 8.0.1505: debugger can't break on a condition
Problem: Debugger can't break on a condition. (Charles Campbell)
Solution: Add ":breakadd expr". (Christian Brabandt, closes https://github.com/vim/vim/issues/859)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sun, 11 Feb 2018 19:15:05 +0100 |
parents | ac42c4b11dbc |
children | 50e1077e0c3d |
comparison
equal
deleted
inserted
replaced
13261:fa53b212be26 | 13262:69278c25429d |
---|---|
71 static int get_maxbacktrace_level(void); | 71 static int get_maxbacktrace_level(void); |
72 static void do_setdebugtracelevel(char_u *arg); | 72 static void do_setdebugtracelevel(char_u *arg); |
73 static void do_checkbacktracelevel(void); | 73 static void do_checkbacktracelevel(void); |
74 static void do_showbacktrace(char_u *cmd); | 74 static void do_showbacktrace(char_u *cmd); |
75 | 75 |
76 static char_u *debug_oldval = NULL; /* old and newval for debug expressions */ | |
77 static char_u *debug_newval = NULL; | |
78 static int debug_expr = 0; /* use debug_expr */ | |
79 | |
80 int | |
81 has_watchexpr(void) | |
82 { | |
83 return debug_expr; | |
84 } | |
85 | |
76 /* | 86 /* |
77 * do_debug(): Debug mode. | 87 * do_debug(): Debug mode. |
78 * Repeatedly get Ex commands, until told to continue normal execution. | 88 * Repeatedly get Ex commands, until told to continue normal execution. |
79 */ | 89 */ |
80 void | 90 void |
133 State = NORMAL; | 143 State = NORMAL; |
134 debug_mode = TRUE; | 144 debug_mode = TRUE; |
135 | 145 |
136 if (!debug_did_msg) | 146 if (!debug_did_msg) |
137 MSG(_("Entering Debug mode. Type \"cont\" to continue.")); | 147 MSG(_("Entering Debug mode. Type \"cont\" to continue.")); |
148 if (debug_oldval != NULL) | |
149 { | |
150 smsg((char_u *)_("Oldval = \"%s\""), debug_oldval); | |
151 vim_free(debug_oldval); | |
152 debug_oldval = NULL; | |
153 } | |
154 if (debug_newval != NULL) | |
155 { | |
156 smsg((char_u *)_("Newval = \"%s\""), debug_newval); | |
157 vim_free(debug_newval); | |
158 debug_newval = NULL; | |
159 } | |
138 if (sourcing_name != NULL) | 160 if (sourcing_name != NULL) |
139 msg(sourcing_name); | 161 msg(sourcing_name); |
140 if (sourcing_lnum != 0) | 162 if (sourcing_lnum != 0) |
141 smsg((char_u *)_("line %ld: %s"), (long)sourcing_lnum, cmd); | 163 smsg((char_u *)_("line %ld: %s"), (long)sourcing_lnum, cmd); |
142 else | 164 else |
143 smsg((char_u *)_("cmd: %s"), cmd); | 165 smsg((char_u *)_("cmd: %s"), cmd); |
144 | |
145 /* | 166 /* |
146 * Repeat getting a command and executing it. | 167 * Repeat getting a command and executing it. |
147 */ | 168 */ |
148 for (;;) | 169 for (;;) |
149 { | 170 { |
526 * This is a grow-array of structs. | 547 * This is a grow-array of structs. |
527 */ | 548 */ |
528 struct debuggy | 549 struct debuggy |
529 { | 550 { |
530 int dbg_nr; /* breakpoint number */ | 551 int dbg_nr; /* breakpoint number */ |
531 int dbg_type; /* DBG_FUNC or DBG_FILE */ | 552 int dbg_type; /* DBG_FUNC, DBG_FILE or DBG_EXPR */ |
532 char_u *dbg_name; /* function or file name */ | 553 char_u *dbg_name; /* function, expression or file name */ |
533 regprog_T *dbg_prog; /* regexp program */ | 554 regprog_T *dbg_prog; /* regexp program */ |
534 linenr_T dbg_lnum; /* line number in function or file */ | 555 linenr_T dbg_lnum; /* line number in function or file */ |
535 int dbg_forceit; /* ! used */ | 556 int dbg_forceit; /* ! used */ |
557 #ifdef FEAT_EVAL | |
558 typval_T *dbg_val; /* last result of watchexpression */ | |
559 #endif | |
560 int dbg_level; /* stored nested level for expr */ | |
536 }; | 561 }; |
537 | 562 |
538 static garray_T dbg_breakp = {0, 0, sizeof(struct debuggy), 4, NULL}; | 563 static garray_T dbg_breakp = {0, 0, sizeof(struct debuggy), 4, NULL}; |
539 #define BREAKP(idx) (((struct debuggy *)dbg_breakp.ga_data)[idx]) | 564 #define BREAKP(idx) (((struct debuggy *)dbg_breakp.ga_data)[idx]) |
540 #define DEBUGGY(gap, idx) (((struct debuggy *)gap->ga_data)[idx]) | 565 #define DEBUGGY(gap, idx) (((struct debuggy *)gap->ga_data)[idx]) |
544 /* Profiling uses file and func names similar to breakpoints. */ | 569 /* Profiling uses file and func names similar to breakpoints. */ |
545 static garray_T prof_ga = {0, 0, sizeof(struct debuggy), 4, NULL}; | 570 static garray_T prof_ga = {0, 0, sizeof(struct debuggy), 4, NULL}; |
546 #endif | 571 #endif |
547 #define DBG_FUNC 1 | 572 #define DBG_FUNC 1 |
548 #define DBG_FILE 2 | 573 #define DBG_FILE 2 |
574 #define DBG_EXPR 3 | |
549 | 575 |
550 static int dbg_parsearg(char_u *arg, garray_T *gap); | 576 static int dbg_parsearg(char_u *arg, garray_T *gap); |
551 static linenr_T debuggy_find(int file,char_u *fname, linenr_T after, garray_T *gap, int *fp); | 577 static linenr_T debuggy_find(int file,char_u *fname, linenr_T after, garray_T *gap, int *fp); |
552 | 578 |
553 /* | 579 /* |
587 return FAIL; | 613 return FAIL; |
588 } | 614 } |
589 bp->dbg_type = DBG_FILE; | 615 bp->dbg_type = DBG_FILE; |
590 here = TRUE; | 616 here = TRUE; |
591 } | 617 } |
618 else if ( | |
619 #ifdef FEAT_PROFILE | |
620 gap != &prof_ga && | |
621 #endif | |
622 STRNCMP(p, "expr", 4) == 0) | |
623 bp->dbg_type = DBG_EXPR; | |
592 else | 624 else |
593 { | 625 { |
594 EMSG2(_(e_invarg2), p); | 626 EMSG2(_(e_invarg2), p); |
595 return FAIL; | 627 return FAIL; |
596 } | 628 } |
622 | 654 |
623 if (bp->dbg_type == DBG_FUNC) | 655 if (bp->dbg_type == DBG_FUNC) |
624 bp->dbg_name = vim_strsave(p); | 656 bp->dbg_name = vim_strsave(p); |
625 else if (here) | 657 else if (here) |
626 bp->dbg_name = vim_strsave(curbuf->b_ffname); | 658 bp->dbg_name = vim_strsave(curbuf->b_ffname); |
659 else if (bp->dbg_type == DBG_EXPR) | |
660 { | |
661 bp->dbg_name = vim_strsave(p); | |
662 if (bp->dbg_name != NULL) | |
663 bp->dbg_val = eval_expr(bp->dbg_name, NULL); | |
664 } | |
627 else | 665 else |
628 { | 666 { |
629 /* Expand the file name in the same way as do_source(). This means | 667 /* Expand the file name in the same way as do_source(). This means |
630 * doing it twice, so that $DIR/file gets expanded when $DIR is | 668 * doing it twice, so that $DIR/file gets expanded when $DIR is |
631 * "~/dir". */ | 669 * "~/dir". */ |
669 if (dbg_parsearg(eap->arg, gap) == OK) | 707 if (dbg_parsearg(eap->arg, gap) == OK) |
670 { | 708 { |
671 bp = &DEBUGGY(gap, gap->ga_len); | 709 bp = &DEBUGGY(gap, gap->ga_len); |
672 bp->dbg_forceit = eap->forceit; | 710 bp->dbg_forceit = eap->forceit; |
673 | 711 |
674 pat = file_pat_to_reg_pat(bp->dbg_name, NULL, NULL, FALSE); | 712 if (bp->dbg_type != DBG_EXPR) |
675 if (pat != NULL) | 713 { |
676 { | 714 pat = file_pat_to_reg_pat(bp->dbg_name, NULL, NULL, FALSE); |
677 bp->dbg_prog = vim_regcomp(pat, RE_MAGIC + RE_STRING); | 715 if (pat != NULL) |
678 vim_free(pat); | 716 { |
679 } | 717 bp->dbg_prog = vim_regcomp(pat, RE_MAGIC + RE_STRING); |
680 if (pat == NULL || bp->dbg_prog == NULL) | 718 vim_free(pat); |
681 vim_free(bp->dbg_name); | 719 } |
720 if (pat == NULL || bp->dbg_prog == NULL) | |
721 vim_free(bp->dbg_name); | |
722 else | |
723 { | |
724 if (bp->dbg_lnum == 0) /* default line number is 1 */ | |
725 bp->dbg_lnum = 1; | |
726 #ifdef FEAT_PROFILE | |
727 if (eap->cmdidx != CMD_profile) | |
728 #endif | |
729 { | |
730 DEBUGGY(gap, gap->ga_len).dbg_nr = ++last_breakp; | |
731 ++debug_tick; | |
732 } | |
733 ++gap->ga_len; | |
734 } | |
735 } | |
682 else | 736 else |
683 { | 737 { |
684 if (bp->dbg_lnum == 0) /* default line number is 1 */ | 738 /* DBG_EXPR */ |
685 bp->dbg_lnum = 1; | 739 DEBUGGY(gap, gap->ga_len++).dbg_nr = ++last_breakp; |
686 #ifdef FEAT_PROFILE | 740 ++debug_tick; |
687 if (eap->cmdidx != CMD_profile) | |
688 #endif | |
689 { | |
690 DEBUGGY(gap, gap->ga_len).dbg_nr = ++last_breakp; | |
691 ++debug_tick; | |
692 } | |
693 ++gap->ga_len; | |
694 } | 741 } |
695 } | 742 } |
696 } | 743 } |
697 | 744 |
698 /* | 745 /* |
748 todel = 0; | 795 todel = 0; |
749 del_all = TRUE; | 796 del_all = TRUE; |
750 } | 797 } |
751 else | 798 else |
752 { | 799 { |
753 /* ":breakdel {func|file} [lnum] {name}" */ | 800 /* ":breakdel {func|file|expr} [lnum] {name}" */ |
754 if (dbg_parsearg(eap->arg, gap) == FAIL) | 801 if (dbg_parsearg(eap->arg, gap) == FAIL) |
755 return; | 802 return; |
756 bp = &DEBUGGY(gap, gap->ga_len); | 803 bp = &DEBUGGY(gap, gap->ga_len); |
757 for (i = 0; i < gap->ga_len; ++i) | 804 for (i = 0; i < gap->ga_len; ++i) |
758 { | 805 { |
776 else | 823 else |
777 { | 824 { |
778 while (gap->ga_len > 0) | 825 while (gap->ga_len > 0) |
779 { | 826 { |
780 vim_free(DEBUGGY(gap, todel).dbg_name); | 827 vim_free(DEBUGGY(gap, todel).dbg_name); |
828 #ifdef FEAT_EVAL | |
829 if (DEBUGGY(gap, todel).dbg_type == DBG_EXPR | |
830 && DEBUGGY(gap, todel).dbg_val != NULL) | |
831 free_tv(DEBUGGY(gap, todel).dbg_val); | |
832 #endif | |
781 vim_regfree(DEBUGGY(gap, todel).dbg_prog); | 833 vim_regfree(DEBUGGY(gap, todel).dbg_prog); |
782 --gap->ga_len; | 834 --gap->ga_len; |
783 if (todel < gap->ga_len) | 835 if (todel < gap->ga_len) |
784 mch_memmove(&DEBUGGY(gap, todel), &DEBUGGY(gap, todel + 1), | 836 mch_memmove(&DEBUGGY(gap, todel), &DEBUGGY(gap, todel + 1), |
785 (gap->ga_len - todel) * sizeof(struct debuggy)); | 837 (gap->ga_len - todel) * sizeof(struct debuggy)); |
812 for (i = 0; i < dbg_breakp.ga_len; ++i) | 864 for (i = 0; i < dbg_breakp.ga_len; ++i) |
813 { | 865 { |
814 bp = &BREAKP(i); | 866 bp = &BREAKP(i); |
815 if (bp->dbg_type == DBG_FILE) | 867 if (bp->dbg_type == DBG_FILE) |
816 home_replace(NULL, bp->dbg_name, NameBuff, MAXPATHL, TRUE); | 868 home_replace(NULL, bp->dbg_name, NameBuff, MAXPATHL, TRUE); |
817 smsg((char_u *)_("%3d %s %s line %ld"), | 869 if (bp->dbg_type != DBG_EXPR) |
870 smsg((char_u *)_("%3d %s %s line %ld"), | |
818 bp->dbg_nr, | 871 bp->dbg_nr, |
819 bp->dbg_type == DBG_FUNC ? "func" : "file", | 872 bp->dbg_type == DBG_FUNC ? "func" : "file", |
820 bp->dbg_type == DBG_FUNC ? bp->dbg_name : NameBuff, | 873 bp->dbg_type == DBG_FUNC ? bp->dbg_name : NameBuff, |
821 (long)bp->dbg_lnum); | 874 (long)bp->dbg_lnum); |
875 else | |
876 smsg((char_u *)_("%3d expr %s"), | |
877 bp->dbg_nr, bp->dbg_name); | |
822 } | 878 } |
823 } | 879 } |
824 | 880 |
825 /* | 881 /* |
826 * Find a breakpoint for a function or sourced file. | 882 * Find a breakpoint for a function or sourced file. |
887 for (i = 0; i < gap->ga_len; ++i) | 943 for (i = 0; i < gap->ga_len; ++i) |
888 { | 944 { |
889 /* Skip entries that are not useful or are for a line that is beyond | 945 /* Skip entries that are not useful or are for a line that is beyond |
890 * an already found breakpoint. */ | 946 * an already found breakpoint. */ |
891 bp = &DEBUGGY(gap, i); | 947 bp = &DEBUGGY(gap, i); |
892 if (((bp->dbg_type == DBG_FILE) == file && ( | 948 if (((bp->dbg_type == DBG_FILE) == file && |
949 bp->dbg_type != DBG_EXPR && ( | |
893 #ifdef FEAT_PROFILE | 950 #ifdef FEAT_PROFILE |
894 gap == &prof_ga || | 951 gap == &prof_ga || |
895 #endif | 952 #endif |
896 (bp->dbg_lnum > after && (lnum == 0 || bp->dbg_lnum < lnum))))) | 953 (bp->dbg_lnum > after && (lnum == 0 || bp->dbg_lnum < lnum))))) |
897 { | 954 { |
908 if (fp != NULL) | 965 if (fp != NULL) |
909 *fp = bp->dbg_forceit; | 966 *fp = bp->dbg_forceit; |
910 } | 967 } |
911 got_int |= prev_got_int; | 968 got_int |= prev_got_int; |
912 } | 969 } |
970 #ifdef FEAT_EVAL | |
971 else if (bp->dbg_type == DBG_EXPR) | |
972 { | |
973 typval_T *tv; | |
974 int line = FALSE; | |
975 | |
976 prev_got_int = got_int; | |
977 got_int = FALSE; | |
978 | |
979 tv = eval_expr(bp->dbg_name, NULL); | |
980 if (tv != NULL) | |
981 { | |
982 if (bp->dbg_val == NULL) | |
983 { | |
984 debug_oldval = typval_tostring(NULL); | |
985 bp->dbg_val = tv; | |
986 debug_newval = typval_tostring(bp->dbg_val); | |
987 line = TRUE; | |
988 } | |
989 else | |
990 { | |
991 typval_T val3; | |
992 | |
993 if (typval_copy(bp->dbg_val, &val3) == OK) | |
994 { | |
995 if (typval_compare(tv, &val3, TYPE_EQUAL, | |
996 TRUE, FALSE, TRUE) == OK | |
997 && tv->vval.v_number == FALSE) | |
998 { | |
999 typval_T *v; | |
1000 | |
1001 line = TRUE; | |
1002 debug_oldval = typval_tostring(bp->dbg_val); | |
1003 v = eval_expr(bp->dbg_name, NULL); | |
1004 debug_newval = typval_tostring(v); | |
1005 free_tv(bp->dbg_val); | |
1006 bp->dbg_val = v; | |
1007 } | |
1008 } | |
1009 free_tv(tv); | |
1010 } | |
1011 } | |
1012 else if (bp->dbg_val != NULL) | |
1013 { | |
1014 debug_oldval = typval_tostring(bp->dbg_val); | |
1015 debug_newval = typval_tostring(NULL); | |
1016 free_tv(bp->dbg_val); | |
1017 bp->dbg_val = NULL; | |
1018 line = TRUE; | |
1019 } | |
1020 | |
1021 if (line) | |
1022 { | |
1023 lnum = after > 0 ? after : 1; | |
1024 break; | |
1025 } | |
1026 | |
1027 got_int |= prev_got_int; | |
1028 } | |
1029 #endif | |
913 } | 1030 } |
914 if (name != fname) | 1031 if (name != fname) |
915 vim_free(name); | 1032 vim_free(name); |
916 | 1033 |
917 return lnum; | 1034 return lnum; |