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;