# HG changeset patch # User Bram Moolenaar # Date 1641574804 -3600 # Node ID 8c0730eca2ce1478f4271d0315f11f5536dc703e # Parent aba0728a28d9e1cf87a56b0fcdf53ef3053c4d65 patch 8.2.4029: debugging NFA regexp my crash, cached indent may be wrong Commit: https://github.com/vim/vim/commit/b2d85e3784ac89f5209489844c1ee0f54d117abb Author: Bram Moolenaar Date: Fri Jan 7 16:55:32 2022 +0000 patch 8.2.4029: debugging NFA regexp my crash, cached indent may be wrong Problem: Debugging NFA regexp my crash, cached indent may be wrong. Solution: Fix some debug warnings in the NFA regexp code. Make sure log_fd is set when used. Fix breakindent and indent caching. (Christian Brabandt, closes #9482) diff --git a/src/indent.c b/src/indent.c --- a/src/indent.c +++ b/src/indent.c @@ -915,13 +915,15 @@ get_breakindent_win( win_T *wp, char_u *line) // start of the line { - static int prev_indent = 0; // cached indent value - static long prev_ts = 0L; // cached tabstop value - static char_u *prev_line = NULL; // cached pointer to line + static int prev_indent = 0; // cached indent value + static long prev_ts = 0L; // cached tabstop value + static char_u *prev_line = NULL; // cached pointer to line static varnumber_T prev_tick = 0; // changedtick of cached value # ifdef FEAT_VARTABS - static int *prev_vts = NULL; // cached vartabs values + static int *prev_vts = NULL; // cached vartabs values # endif + static int prev_list = 0; // cached list value + static int prev_listopt = 0; // cached w_p_briopt_list value int bri = 0; // window width minus window margin space, i.e. what rests for text const int eff_wwidth = wp->w_width @@ -929,9 +931,10 @@ get_breakindent_win( && (vim_strchr(p_cpo, CPO_NUMCOL) == NULL) ? number_width(wp) + 1 : 0); - // used cached indent, unless pointer or 'tabstop' changed + // used cached indent, unless line, 'tabstop' or briopt_list changed if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts || prev_tick != CHANGEDTICK(wp->w_buffer) + || prev_listopt != wp->w_briopt_list # ifdef FEAT_VARTABS || prev_vts != wp->w_buffer->b_p_vts_array # endif @@ -949,6 +952,28 @@ get_breakindent_win( prev_indent = get_indent_str(line, (int)wp->w_buffer->b_p_ts, wp->w_p_list); # endif + prev_listopt = wp->w_briopt_list; + // add additional indent for numbered lists + if (wp->w_briopt_list != 0) + { + regmatch_T regmatch; + + regmatch.regprog = vim_regcomp(curbuf->b_p_flp, + RE_MAGIC + RE_STRING + RE_AUTO + RE_STRICT); + + if (regmatch.regprog != NULL) + { + regmatch.rm_ic = FALSE; + if (vim_regexec(®match, line, 0)) + { + if (wp->w_briopt_list > 0) + prev_list = wp->w_briopt_list; + else + prev_list = (*regmatch.endp - *regmatch.startp); + } + vim_regfree(regmatch.regprog); + } + } } bri = prev_indent + wp->w_briopt_shift; @@ -958,22 +983,10 @@ get_breakindent_win( // add additional indent for numbered lists if (wp->w_briopt_list != 0) { - regmatch_T regmatch; - - regmatch.regprog = vim_regcomp(curbuf->b_p_flp, - RE_MAGIC + RE_STRING + RE_AUTO + RE_STRICT); - if (regmatch.regprog != NULL) - { - regmatch.rm_ic = FALSE; - if (vim_regexec(®match, line, 0)) - { - if (wp->w_briopt_list > 0) - bri += wp->w_briopt_list; - else - bri = (*regmatch.endp - *regmatch.startp); - } - vim_regfree(regmatch.regprog); - } + if (wp->w_briopt_list > 0) + bri += prev_list; + else + bri = prev_list; } // indent minus the length of the showbreak string diff --git a/src/optionstr.c b/src/optionstr.c --- a/src/optionstr.c +++ b/src/optionstr.c @@ -756,6 +756,9 @@ did_set_string_option( { if (briopt_check(curwin) == FAIL) errmsg = e_invalid_argument; + // list setting requires a redraw + if (curwin->w_briopt_list) + redraw_all_later(NOT_VALID); } #endif @@ -2610,6 +2613,14 @@ ambw_end: update_package_paths_in_lua(); #endif +#if defined(FEAT_LINEBREAK) + // Changing Formatlistpattern when briopt includes the list setting: + // redraw + if ((varp == &p_flp || varp == &(curbuf->b_p_flp)) + && curwin->w_briopt_list) + redraw_all_later(NOT_VALID); +#endif + if (curwin->w_curswant != MAXCOL && (get_option_flags(opt_idx) & (P_CURSWANT | P_RALL)) != 0) curwin->w_set_curswant = TRUE; diff --git a/src/regexp_nfa.c b/src/regexp_nfa.c --- a/src/regexp_nfa.c +++ b/src/regexp_nfa.c @@ -2885,7 +2885,7 @@ nfa_print_state2(FILE *debugf, nfa_state char_u save[2]; STRNCPY(save, &p[last], 2); - STRNCPY(&p[last], "+-", 2); + memcpy(&p[last], "+-", 2); fprintf(debugf, " %s", p); STRNCPY(&p[last], save, 2); } @@ -4292,6 +4292,23 @@ sub_equal(regsub_T *sub1, regsub_T *sub2 #ifdef ENABLE_LOG static void +open_debug_log(int result) +{ + log_fd = fopen(NFA_REGEXP_RUN_LOG, "a"); + if (log_fd == NULL) + { + emsg(_(e_log_open_failed)); + log_fd = stderr; + } + + fprintf(log_fd, "****************************\n"); + fprintf(log_fd, "FINISHED RUNNING nfa_regmatch() recursively\n"); + fprintf(log_fd, "MATCH = %s\n", result == TRUE ? "OK" : result == MAYBE + ? "MAYBE" : "FALSE"); + fprintf(log_fd, "****************************\n"); +} + + static void report_state(char *action, regsub_T *sub, nfa_state_T *state, @@ -4307,6 +4324,9 @@ report_state(char *action, else col = (int)(sub->list.line[0].start - rex.line); nfa_set_code(state->c); + if (log_fd == NULL) + open_debug_log(MAYBE); + fprintf(log_fd, "> %s state %d to list %d. char %d: %s (start col %d)%s\n", action, abs(state->id), lid, state->c, code, col, pim_info(pim)); @@ -5430,19 +5450,7 @@ recursive_regmatch( nfa_endp = save_nfa_endp; #ifdef ENABLE_LOG - log_fd = fopen(NFA_REGEXP_RUN_LOG, "a"); - if (log_fd != NULL) - { - fprintf(log_fd, "****************************\n"); - fprintf(log_fd, "FINISHED RUNNING nfa_regmatch() recursively\n"); - fprintf(log_fd, "MATCH = %s\n", result == TRUE ? "OK" : "FALSE"); - fprintf(log_fd, "****************************\n"); - } - else - { - emsg(_(e_log_open_failed)); - log_fd = stderr; - } + open_debug_log(result); #endif return result; @@ -5775,19 +5783,16 @@ nfa_regmatch( #ifdef ENABLE_LOG log_fd = fopen(NFA_REGEXP_RUN_LOG, "a"); - if (log_fd != NULL) - { - fprintf(log_fd, "**********************************\n"); - nfa_set_code(start->c); - fprintf(log_fd, " RUNNING nfa_regmatch() starting with state %d, code %s\n", - abs(start->id), code); - fprintf(log_fd, "**********************************\n"); - } - else + if (log_fd == NULL) { emsg(_(e_log_open_failed)); log_fd = stderr; } + fprintf(log_fd, "**********************************\n"); + nfa_set_code(start->c); + fprintf(log_fd, " RUNNING nfa_regmatch() starting with state %d, code %s\n", + abs(start->id), code); + fprintf(log_fd, "**********************************\n"); #endif thislist = &list[0]; @@ -6919,7 +6924,7 @@ nfa_regmatch( #ifdef DEBUG if (c < 0) - siemsg("INTERNAL: Negative state char: %ld", c); + siemsg("INTERNAL: Negative state char: %ld", (long)c); #endif result = (c == curc); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4029, +/**/ 4028, /**/ 4027,