Patch 8.0.0020
Problem:    The regexp engines are not reentrant.
Solution:   Add regexec_T and save/restore the state when needed.
Files:      src/regexp.c, src/regexp_nfa.c, src/testdir/test_expr.vim,
            runtime/doc/eval.txt, runtime/doc/change.txt


*** ../vim-8.0.0019/src/regexp.c        2016-09-09 20:20:20.000000000 +0200
--- src/regexp.c        2016-10-02 16:21:22.709068952 +0200
***************
*** 3509,3535 ****
  #endif
  
  /*
-  * Internal copy of 'ignorecase'.  It is set at each call to vim_regexec().
-  * Normally it gets the value of "rm_ic" or "rmm_ic", but when the pattern
-  * contains '\c' or '\C' the value is overruled.
-  */
- static int    ireg_ic;
- 
- #ifdef FEAT_MBYTE
- /*
-  * Similar to ireg_ic, but only for 'combining' characters.  Set with \Z flag
-  * in the regexp.  Defaults to false, always.
-  */
- static int    ireg_icombine;
- #endif
- 
- /*
-  * Copy of "rmm_maxcol": maximum column to search for a match.  Zero when
-  * there is no maximum.
-  */
- static colnr_T        ireg_maxcol;
- 
- /*
   * Sometimes need to save a copy of a line.  Since alloc()/free() is very
   * slow, we keep one allocated piece of memory and only re-allocate it when
   * it's too small.  It's freed in bt_regexec_both() when finished.
--- 3509,3514 ----
***************
*** 3538,3544 ****
  static unsigned       reg_tofreelen;
  
  /*
!  * These variables are set when executing a regexp to speed up the execution.
   * Which ones are set depends on whether a single-line or multi-line match is
   * done:
   *                    single-line             multi-line
--- 3517,3523 ----
  static unsigned       reg_tofreelen;
  
  /*
!  * Structure used to store the execution state of the regex engine.
   * Which ones are set depends on whether a single-line or multi-line match is
   * done:
   *                    single-line             multi-line
***************
*** 3554,3570 ****
   * reg_maxline                0                       last line nr
   * reg_line_lbr               FALSE or TRUE           FALSE
   */
! static regmatch_T     *reg_match;
! static regmmatch_T    *reg_mmatch;
! static char_u         **reg_startp = NULL;
! static char_u         **reg_endp = NULL;
! static lpos_T         *reg_startpos = NULL;
! static lpos_T         *reg_endpos = NULL;
! static win_T          *reg_win;
! static buf_T          *reg_buf;
! static linenr_T               reg_firstlnum;
! static linenr_T               reg_maxline;
! static int            reg_line_lbr;       /* "\n" in string is line break */
  
  /* Values for rs_state in regitem_T. */
  typedef enum regstate_E
--- 3533,3570 ----
   * reg_maxline                0                       last line nr
   * reg_line_lbr               FALSE or TRUE           FALSE
   */
! typedef struct {
!     regmatch_T                *reg_match;
!     regmmatch_T               *reg_mmatch;
!     char_u            **reg_startp;
!     char_u            **reg_endp;
!     lpos_T            *reg_startpos;
!     lpos_T            *reg_endpos;
!     win_T             *reg_win;
!     buf_T             *reg_buf;
!     linenr_T          reg_firstlnum;
!     linenr_T          reg_maxline;
!     int                       reg_line_lbr;   /* "\n" in string is line break 
*/
! 
!     /* Internal copy of 'ignorecase'.  It is set at each call to 
vim_regexec().
!      * Normally it gets the value of "rm_ic" or "rmm_ic", but when the pattern
!      * contains '\c' or '\C' the value is overruled. */
!     int                       reg_ic;
! 
! #ifdef FEAT_MBYTE
!     /* Similar to rex.reg_ic, but only for 'combining' characters.  Set with 
\Z
!      * flag in the regexp.  Defaults to false, always. */
!     int                       reg_icombine;
! #endif
! 
!     /* Copy of "rmm_maxcol": maximum column to search for a match.  Zero when
!      * there is no maximum. */
!     colnr_T           reg_maxcol;
! } regexec_T;
! 
! static regexec_T      rex;
! static int            rex_in_use = FALSE;
! 
  
  /* Values for rs_state in regitem_T. */
  typedef enum regstate_E
***************
*** 3669,3680 ****
  {
      /* when looking behind for a match/no-match lnum is negative.  But we
       * can't go before line 1 */
!     if (reg_firstlnum + lnum < 1)
        return NULL;
!     if (lnum > reg_maxline)
        /* Must have matched the "\n" in the last line. */
        return (char_u *)"";
!     return ml_get_buf(reg_buf, reg_firstlnum + lnum, FALSE);
  }
  
  static regsave_T behind_pos;
--- 3669,3680 ----
  {
      /* when looking behind for a match/no-match lnum is negative.  But we
       * can't go before line 1 */
!     if (rex.reg_firstlnum + lnum < 1)
        return NULL;
!     if (lnum > rex.reg_maxline)
        /* Must have matched the "\n" in the last line. */
        return (char_u *)"";
!     return ml_get_buf(rex.reg_buf, rex.reg_firstlnum + lnum, FALSE);
  }
  
  static regsave_T behind_pos;
***************
*** 3687,3696 ****
  #endif
  
  /* TRUE if using multi-line regexp. */
! #define REG_MULTI     (reg_match == NULL)
! 
! static int  bt_regexec_nl(regmatch_T *rmp, char_u *line, colnr_T col, int 
line_lbr);
! 
  
  /*
   * Match a regexp against a string.
--- 3687,3693 ----
  #endif
  
  /* TRUE if using multi-line regexp. */
! #define REG_MULTI     (rex.reg_match == NULL)
  
  /*
   * Match a regexp against a string.
***************
*** 3707,3729 ****
      colnr_T   col,    /* column to start looking for match */
      int               line_lbr)
  {
!     reg_match = rmp;
!     reg_mmatch = NULL;
!     reg_maxline = 0;
!     reg_line_lbr = line_lbr;
!     reg_buf = curbuf;
!     reg_win = NULL;
!     ireg_ic = rmp->rm_ic;
  #ifdef FEAT_MBYTE
!     ireg_icombine = FALSE;
  #endif
!     ireg_maxcol = 0;
  
      return bt_regexec_both(line, col, NULL);
  }
  
- static long bt_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, 
linenr_T lnum, colnr_T col, proftime_T *tm);
- 
  /*
   * Match a regexp against multiple lines.
   * "rmp->regprog" is a compiled regexp as returned by vim_regcomp().
--- 3704,3724 ----
      colnr_T   col,    /* column to start looking for match */
      int               line_lbr)
  {
!     rex.reg_match = rmp;
!     rex.reg_mmatch = NULL;
!     rex.reg_maxline = 0;
!     rex.reg_line_lbr = line_lbr;
!     rex.reg_buf = curbuf;
!     rex.reg_win = NULL;
!     rex.reg_ic = rmp->rm_ic;
  #ifdef FEAT_MBYTE
!     rex.reg_icombine = FALSE;
  #endif
!     rex.reg_maxcol = 0;
  
      return bt_regexec_both(line, col, NULL);
  }
  
  /*
   * Match a regexp against multiple lines.
   * "rmp->regprog" is a compiled regexp as returned by vim_regcomp().
***************
*** 3741,3758 ****
      colnr_T   col,            /* column to start looking for match */
      proftime_T        *tm)            /* timeout limit or NULL */
  {
!     reg_match = NULL;
!     reg_mmatch = rmp;
!     reg_buf = buf;
!     reg_win = win;
!     reg_firstlnum = lnum;
!     reg_maxline = reg_buf->b_ml.ml_line_count - lnum;
!     reg_line_lbr = FALSE;
!     ireg_ic = rmp->rmm_ic;
  #ifdef FEAT_MBYTE
!     ireg_icombine = FALSE;
  #endif
!     ireg_maxcol = rmp->rmm_maxcol;
  
      return bt_regexec_both(NULL, col, tm);
  }
--- 3736,3753 ----
      colnr_T   col,            /* column to start looking for match */
      proftime_T        *tm)            /* timeout limit or NULL */
  {
!     rex.reg_match = NULL;
!     rex.reg_mmatch = rmp;
!     rex.reg_buf = buf;
!     rex.reg_win = win;
!     rex.reg_firstlnum = lnum;
!     rex.reg_maxline = rex.reg_buf->b_ml.ml_line_count - lnum;
!     rex.reg_line_lbr = FALSE;
!     rex.reg_ic = rmp->rmm_ic;
  #ifdef FEAT_MBYTE
!     rex.reg_icombine = FALSE;
  #endif
!     rex.reg_maxcol = rmp->rmm_maxcol;
  
      return bt_regexec_both(NULL, col, tm);
  }
***************
*** 3794,3809 ****
  
      if (REG_MULTI)
      {
!       prog = (bt_regprog_T *)reg_mmatch->regprog;
        line = reg_getline((linenr_T)0);
!       reg_startpos = reg_mmatch->startpos;
!       reg_endpos = reg_mmatch->endpos;
      }
      else
      {
!       prog = (bt_regprog_T *)reg_match->regprog;
!       reg_startp = reg_match->startp;
!       reg_endp = reg_match->endp;
      }
  
      /* Be paranoid... */
--- 3789,3804 ----
  
      if (REG_MULTI)
      {
!       prog = (bt_regprog_T *)rex.reg_mmatch->regprog;
        line = reg_getline((linenr_T)0);
!       rex.reg_startpos = rex.reg_mmatch->startpos;
!       rex.reg_endpos = rex.reg_mmatch->endpos;
      }
      else
      {
!       prog = (bt_regprog_T *)rex.reg_match->regprog;
!       rex.reg_startp = rex.reg_match->startp;
!       rex.reg_endp = rex.reg_match->endp;
      }
  
      /* Be paranoid... */
***************
*** 3818,3836 ****
        goto theend;
  
      /* If the start column is past the maximum column: no need to try. */
!     if (ireg_maxcol > 0 && col >= ireg_maxcol)
        goto theend;
  
!     /* If pattern contains "\c" or "\C": overrule value of ireg_ic */
      if (prog->regflags & RF_ICASE)
!       ireg_ic = TRUE;
      else if (prog->regflags & RF_NOICASE)
!       ireg_ic = FALSE;
  
  #ifdef FEAT_MBYTE
!     /* If pattern contains "\Z" overrule value of ireg_icombine */
      if (prog->regflags & RF_ICOMBINE)
!       ireg_icombine = TRUE;
  #endif
  
      /* If there is a "must appear" string, look for it. */
--- 3813,3831 ----
        goto theend;
  
      /* If the start column is past the maximum column: no need to try. */
!     if (rex.reg_maxcol > 0 && col >= rex.reg_maxcol)
        goto theend;
  
!     /* If pattern contains "\c" or "\C": overrule value of rex.reg_ic */
      if (prog->regflags & RF_ICASE)
!       rex.reg_ic = TRUE;
      else if (prog->regflags & RF_NOICASE)
!       rex.reg_ic = FALSE;
  
  #ifdef FEAT_MBYTE
!     /* If pattern contains "\Z" overrule value of rex.reg_icombine */
      if (prog->regflags & RF_ICOMBINE)
!       rex.reg_icombine = TRUE;
  #endif
  
      /* If there is a "must appear" string, look for it. */
***************
*** 3850,3856 ****
         * This is used very often, esp. for ":global".  Use three versions of
         * the loop to avoid overhead of conditions.
         */
!       if (!ireg_ic
  #ifdef FEAT_MBYTE
                && !has_mbyte
  #endif
--- 3845,3851 ----
         * This is used very often, esp. for ":global".  Use three versions of
         * the loop to avoid overhead of conditions.
         */
!       if (!rex.reg_ic
  #ifdef FEAT_MBYTE
                && !has_mbyte
  #endif
***************
*** 3862,3868 ****
                ++s;
            }
  #ifdef FEAT_MBYTE
!       else if (!ireg_ic || (!enc_utf8 && mb_char2len(c) > 1))
            while ((s = vim_strchr(s, c)) != NULL)
            {
                if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0)
--- 3857,3863 ----
                ++s;
            }
  #ifdef FEAT_MBYTE
!       else if (!rex.reg_ic || (!enc_utf8 && mb_char2len(c) > 1))
            while ((s = vim_strchr(s, c)) != NULL)
            {
                if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0)
***************
*** 3898,3904 ****
            c = regline[col];
        if (prog->regstart == NUL
                || prog->regstart == c
!               || (ireg_ic && ((
  #ifdef FEAT_MBYTE
                        (enc_utf8 && utf_fold(prog->regstart) == utf_fold(c)))
                        || (c < 255 && prog->regstart < 255 &&
--- 3893,3899 ----
            c = regline[col];
        if (prog->regstart == NUL
                || prog->regstart == c
!               || (rex.reg_ic && ((
  #ifdef FEAT_MBYTE
                        (enc_utf8 && utf_fold(prog->regstart) == utf_fold(c)))
                        || (c < 255 && prog->regstart < 255 &&
***************
*** 3920,3926 ****
            {
                /* Skip until the char we know it must start with.
                 * Used often, do some work to avoid call overhead. */
!               if (!ireg_ic
  #ifdef FEAT_MBYTE
                            && !has_mbyte
  #endif
--- 3915,3921 ----
            {
                /* Skip until the char we know it must start with.
                 * Used often, do some work to avoid call overhead. */
!               if (!rex.reg_ic
  #ifdef FEAT_MBYTE
                            && !has_mbyte
  #endif
***************
*** 3937,3943 ****
            }
  
            /* Check for maximum column to try. */
!           if (ireg_maxcol > 0 && col >= ireg_maxcol)
            {
                retval = 0;
                break;
--- 3932,3938 ----
            }
  
            /* Check for maximum column to try. */
!           if (rex.reg_maxcol > 0 && col >= rex.reg_maxcol)
            {
                retval = 0;
                break;
***************
*** 4056,4081 ****
      cleanup_subexpr();
      if (REG_MULTI)
      {
!       if (reg_startpos[0].lnum < 0)
        {
!           reg_startpos[0].lnum = 0;
!           reg_startpos[0].col = col;
        }
!       if (reg_endpos[0].lnum < 0)
        {
!           reg_endpos[0].lnum = reglnum;
!           reg_endpos[0].col = (int)(reginput - regline);
        }
        else
            /* Use line number of "\ze". */
!           reglnum = reg_endpos[0].lnum;
      }
      else
      {
!       if (reg_startp[0] == NULL)
!           reg_startp[0] = regline + col;
!       if (reg_endp[0] == NULL)
!           reg_endp[0] = reginput;
      }
  #ifdef FEAT_SYN_HL
      /* Package any found \z(...\) matches for export. Default is none. */
--- 4051,4076 ----
      cleanup_subexpr();
      if (REG_MULTI)
      {
!       if (rex.reg_startpos[0].lnum < 0)
        {
!           rex.reg_startpos[0].lnum = 0;
!           rex.reg_startpos[0].col = col;
        }
!       if (rex.reg_endpos[0].lnum < 0)
        {
!           rex.reg_endpos[0].lnum = reglnum;
!           rex.reg_endpos[0].col = (int)(reginput - regline);
        }
        else
            /* Use line number of "\ze". */
!           reglnum = rex.reg_endpos[0].lnum;
      }
      else
      {
!       if (rex.reg_startp[0] == NULL)
!           rex.reg_startp[0] = regline + col;
!       if (rex.reg_endp[0] == NULL)
!           rex.reg_endp[0] = reginput;
      }
  #ifdef FEAT_SYN_HL
      /* Package any found \z(...\) matches for export. Default is none. */
***************
*** 4125,4131 ****
  {
      if (reginput > regline)
        return mb_get_class_buf(reginput - 1
!                           - (*mb_head_off)(regline, reginput - 1), reg_buf);
      return -1;
  }
  #endif
--- 4120,4126 ----
  {
      if (reginput > regline)
        return mb_get_class_buf(reginput - 1
!                        - (*mb_head_off)(regline, reginput - 1), rex.reg_buf);
      return -1;
  }
  #endif
***************
*** 4141,4154 ****
      pos_T     top, bot;
      linenr_T    lnum;
      colnr_T   col;
!     win_T     *wp = reg_win == NULL ? curwin : reg_win;
      int               mode;
      colnr_T   start, end;
      colnr_T   start2, end2;
      colnr_T   cols;
  
      /* Check if the buffer is the current buffer. */
!     if (reg_buf != curbuf || VIsual.lnum == 0)
        return FALSE;
  
      if (VIsual_active)
--- 4136,4149 ----
      pos_T     top, bot;
      linenr_T    lnum;
      colnr_T   col;
!     win_T     *wp = rex.reg_win == NULL ? curwin : rex.reg_win;
      int               mode;
      colnr_T   start, end;
      colnr_T   start2, end2;
      colnr_T   cols;
  
      /* Check if the buffer is the current buffer. */
!     if (rex.reg_buf != curbuf || VIsual.lnum == 0)
        return FALSE;
  
      if (VIsual_active)
***************
*** 4179,4185 ****
        }
        mode = curbuf->b_visual.vi_mode;
      }
!     lnum = reglnum + reg_firstlnum;
      if (lnum < top.lnum || lnum > bot.lnum)
        return FALSE;
  
--- 4174,4180 ----
        }
        mode = curbuf->b_visual.vi_mode;
      }
!     lnum = reglnum + rex.reg_firstlnum;
      if (lnum < top.lnum || lnum > bot.lnum)
        return FALSE;
  
***************
*** 4309,4320 ****
  
        op = OP(scan);
        /* Check for character class with NL added. */
!       if (!reg_line_lbr && WITH_NL(op) && REG_MULTI
!                               && *reginput == NUL && reglnum <= reg_maxline)
        {
            reg_nextline();
        }
!       else if (reg_line_lbr && WITH_NL(op) && *reginput == '\n')
        {
            ADVANCE_REGINPUT();
        }
--- 4304,4315 ----
  
        op = OP(scan);
        /* Check for character class with NL added. */
!       if (!rex.reg_line_lbr && WITH_NL(op) && REG_MULTI
!                            && *reginput == NUL && reglnum <= rex.reg_maxline)
        {
            reg_nextline();
        }
!       else if (rex.reg_line_lbr && WITH_NL(op) && *reginput == '\n')
        {
            ADVANCE_REGINPUT();
        }
***************
*** 4345,4365 ****
             * line where we started, not at the start of the line or we
             * didn't start at the first line of the buffer. */
            if (reglnum != 0 || reginput != regline
!                                         || (REG_MULTI && reg_firstlnum > 1))
                status = RA_NOMATCH;
            break;
  
          case RE_EOF:
!           if (reglnum != reg_maxline || c != NUL)
                status = RA_NOMATCH;
            break;
  
          case CURSOR:
            /* Check if the buffer is in a window and compare the
!            * reg_win->w_cursor position to the match position. */
!           if (reg_win == NULL
!                   || (reglnum + reg_firstlnum != reg_win->w_cursor.lnum)
!                   || ((colnr_T)(reginput - regline) != reg_win->w_cursor.col))
                status = RA_NOMATCH;
            break;
  
--- 4340,4362 ----
             * line where we started, not at the start of the line or we
             * didn't start at the first line of the buffer. */
            if (reglnum != 0 || reginput != regline
!                                      || (REG_MULTI && rex.reg_firstlnum > 1))
                status = RA_NOMATCH;
            break;
  
          case RE_EOF:
!           if (reglnum != rex.reg_maxline || c != NUL)
                status = RA_NOMATCH;
            break;
  
          case CURSOR:
            /* Check if the buffer is in a window and compare the
!            * rex.reg_win->w_cursor position to the match position. */
!           if (rex.reg_win == NULL
!                   || (reglnum + rex.reg_firstlnum
!                                                != rex.reg_win->w_cursor.lnum)
!                   || ((colnr_T)(reginput - regline)
!                                                != rex.reg_win->w_cursor.col))
                status = RA_NOMATCH;
            break;
  
***************
*** 4370,4385 ****
                int     cmp = OPERAND(scan)[1];
                pos_T   *pos;
  
!               pos = getmark_buf(reg_buf, mark, FALSE);
                if (pos == NULL              /* mark doesn't exist */
                        || pos->lnum <= 0    /* mark isn't set in reg_buf */
!                       || (pos->lnum == reglnum + reg_firstlnum
                                ? (pos->col == (colnr_T)(reginput - regline)
                                    ? (cmp == '<' || cmp == '>')
                                    : (pos->col < (colnr_T)(reginput - regline)
                                        ? cmp != '>'
                                        : cmp != '<'))
!                               : (pos->lnum < reglnum + reg_firstlnum
                                    ? cmp != '>'
                                    : cmp != '<')))
                    status = RA_NOMATCH;
--- 4367,4382 ----
                int     cmp = OPERAND(scan)[1];
                pos_T   *pos;
  
!               pos = getmark_buf(rex.reg_buf, mark, FALSE);
                if (pos == NULL              /* mark doesn't exist */
                        || pos->lnum <= 0    /* mark isn't set in reg_buf */
!                       || (pos->lnum == reglnum + rex.reg_firstlnum
                                ? (pos->col == (colnr_T)(reginput - regline)
                                    ? (cmp == '<' || cmp == '>')
                                    : (pos->col < (colnr_T)(reginput - regline)
                                        ? cmp != '>'
                                        : cmp != '<'))
!                               : (pos->lnum < reglnum + rex.reg_firstlnum
                                    ? cmp != '>'
                                    : cmp != '<')))
                    status = RA_NOMATCH;
***************
*** 4392,4398 ****
            break;
  
          case RE_LNUM:
!           if (!REG_MULTI || !re_num_cmp((long_u)(reglnum + reg_firstlnum),
                                                                        scan))
                status = RA_NOMATCH;
            break;
--- 4389,4395 ----
            break;
  
          case RE_LNUM:
!           if (!REG_MULTI || !re_num_cmp((long_u)(reglnum + rex.reg_firstlnum),
                                                                        scan))
                status = RA_NOMATCH;
            break;
***************
*** 4404,4410 ****
  
          case RE_VCOL:
            if (!re_num_cmp((long_u)win_linetabsize(
!                           reg_win == NULL ? curwin : reg_win,
                            regline, (colnr_T)(reginput - regline)) + 1, scan))
                status = RA_NOMATCH;
            break;
--- 4401,4407 ----
  
          case RE_VCOL:
            if (!re_num_cmp((long_u)win_linetabsize(
!                           rex.reg_win == NULL ? curwin : rex.reg_win,
                            regline, (colnr_T)(reginput - regline)) + 1, scan))
                status = RA_NOMATCH;
            break;
***************
*** 4418,4424 ****
                int this_class;
  
                /* Get class of current and previous char (if it exists). */
!               this_class = mb_get_class_buf(reginput, reg_buf);
                if (this_class <= 1)
                    status = RA_NOMATCH;  /* not on a word at all */
                else if (reg_prev_class() == this_class)
--- 4415,4421 ----
                int this_class;
  
                /* Get class of current and previous char (if it exists). */
!               this_class = mb_get_class_buf(reginput, rex.reg_buf);
                if (this_class <= 1)
                    status = RA_NOMATCH;  /* not on a word at all */
                else if (reg_prev_class() == this_class)
***************
*** 4427,4434 ****
  #endif
            else
            {
!               if (!vim_iswordc_buf(c, reg_buf) || (reginput > regline
!                                  && vim_iswordc_buf(reginput[-1], reg_buf)))
                    status = RA_NOMATCH;
            }
            break;
--- 4424,4431 ----
  #endif
            else
            {
!               if (!vim_iswordc_buf(c, rex.reg_buf) || (reginput > regline
!                               && vim_iswordc_buf(reginput[-1], rex.reg_buf)))
                    status = RA_NOMATCH;
            }
            break;
***************
*** 4442,4448 ****
                int this_class, prev_class;
  
                /* Get class of current and previous char (if it exists). */
!               this_class = mb_get_class_buf(reginput, reg_buf);
                prev_class = reg_prev_class();
                if (this_class == prev_class
                        || prev_class == 0 || prev_class == 1)
--- 4439,4445 ----
                int this_class, prev_class;
  
                /* Get class of current and previous char (if it exists). */
!               this_class = mb_get_class_buf(reginput, rex.reg_buf);
                prev_class = reg_prev_class();
                if (this_class == prev_class
                        || prev_class == 0 || prev_class == 1)
***************
*** 4451,4458 ****
  #endif
            else
            {
!               if (!vim_iswordc_buf(reginput[-1], reg_buf)
!                       || (reginput[0] != NUL && vim_iswordc_buf(c, reg_buf)))
                    status = RA_NOMATCH;
            }
            break; /* Matched with EOW */
--- 4448,4456 ----
  #endif
            else
            {
!               if (!vim_iswordc_buf(reginput[-1], rex.reg_buf)
!                       || (reginput[0] != NUL
!                                          && vim_iswordc_buf(c, rex.reg_buf)))
                    status = RA_NOMATCH;
            }
            break; /* Matched with EOW */
***************
*** 4480,4493 ****
            break;
  
          case KWORD:
!           if (!vim_iswordp_buf(reginput, reg_buf))
                status = RA_NOMATCH;
            else
                ADVANCE_REGINPUT();
            break;
  
          case SKWORD:
!           if (VIM_ISDIGIT(*reginput) || !vim_iswordp_buf(reginput, reg_buf))
                status = RA_NOMATCH;
            else
                ADVANCE_REGINPUT();
--- 4478,4492 ----
            break;
  
          case KWORD:
!           if (!vim_iswordp_buf(reginput, rex.reg_buf))
                status = RA_NOMATCH;
            else
                ADVANCE_REGINPUT();
            break;
  
          case SKWORD:
!           if (VIM_ISDIGIT(*reginput)
!                                   || !vim_iswordp_buf(reginput, rex.reg_buf))
                status = RA_NOMATCH;
            else
                ADVANCE_REGINPUT();
***************
*** 4655,4661 ****
                opnd = OPERAND(scan);
                /* Inline the first byte, for speed. */
                if (*opnd != *reginput
!                       && (!ireg_ic || (
  #ifdef FEAT_MBYTE
                            !enc_utf8 &&
  #endif
--- 4654,4660 ----
                opnd = OPERAND(scan);
                /* Inline the first byte, for speed. */
                if (*opnd != *reginput
!                       && (!rex.reg_ic || (
  #ifdef FEAT_MBYTE
                            !enc_utf8 &&
  #endif
***************
*** 4670,4676 ****
                {
                    if (opnd[1] == NUL
  #ifdef FEAT_MBYTE
!                           && !(enc_utf8 && ireg_ic)
  #endif
                        )
                    {
--- 4669,4675 ----
                {
                    if (opnd[1] == NUL
  #ifdef FEAT_MBYTE
!                           && !(enc_utf8 && rex.reg_ic)
  #endif
                        )
                    {
***************
*** 4689,4695 ****
                    if (status != RA_NOMATCH
                            && enc_utf8
                            && UTF_COMPOSINGLIKE(reginput, reginput + len)
!                           && !ireg_icombine
                            && OP(next) != RE_COMPOSING)
                    {
                        /* raaron: This code makes a composing character get
--- 4688,4694 ----
                    if (status != RA_NOMATCH
                            && enc_utf8
                            && UTF_COMPOSINGLIKE(reginput, reginput + len)
!                           && !rex.reg_icombine
                            && OP(next) != RE_COMPOSING)
                    {
                        /* raaron: This code makes a composing character get
***************
*** 4840,4847 ****
                else
                {
                    rp->rs_no = no;
!                   save_se(&rp->rs_un.sesave, &reg_startpos[no],
!                                                            &reg_startp[no]);
                    /* We simply continue and handle the result when done. */
                }
            }
--- 4839,4846 ----
                else
                {
                    rp->rs_no = no;
!                   save_se(&rp->rs_un.sesave, &rex.reg_startpos[no],
!                                                         &rex.reg_startp[no]);
                    /* We simply continue and handle the result when done. */
                }
            }
***************
*** 4900,4906 ****
                else
                {
                    rp->rs_no = no;
!                   save_se(&rp->rs_un.sesave, &reg_endpos[no], &reg_endp[no]);
                    /* We simply continue and handle the result when done. */
                }
            }
--- 4899,4906 ----
                else
                {
                    rp->rs_no = no;
!                   save_se(&rp->rs_un.sesave, &rex.reg_endpos[no],
!                                                           &rex.reg_endp[no]);
                    /* We simply continue and handle the result when done. */
                }
            }
***************
*** 4949,4955 ****
                cleanup_subexpr();
                if (!REG_MULTI)         /* Single-line regexp */
                {
!                   if (reg_startp[no] == NULL || reg_endp[no] == NULL)
                    {
                        /* Backref was not set: Match an empty string. */
                        len = 0;
--- 4949,4955 ----
                cleanup_subexpr();
                if (!REG_MULTI)         /* Single-line regexp */
                {
!                   if (rex.reg_startp[no] == NULL || rex.reg_endp[no] == NULL)
                    {
                        /* Backref was not set: Match an empty string. */
                        len = 0;
***************
*** 4958,4983 ****
                    {
                        /* Compare current input with back-ref in the same
                         * line. */
!                       len = (int)(reg_endp[no] - reg_startp[no]);
!                       if (cstrncmp(reg_startp[no], reginput, &len) != 0)
                            status = RA_NOMATCH;
                    }
                }
                else                            /* Multi-line regexp */
                {
!                   if (reg_startpos[no].lnum < 0 || reg_endpos[no].lnum < 0)
                    {
                        /* Backref was not set: Match an empty string. */
                        len = 0;
                    }
                    else
                    {
!                       if (reg_startpos[no].lnum == reglnum
!                               && reg_endpos[no].lnum == reglnum)
                        {
                            /* Compare back-ref within the current line. */
!                           len = reg_endpos[no].col - reg_startpos[no].col;
!                           if (cstrncmp(regline + reg_startpos[no].col,
                                                          reginput, &len) != 0)
                                status = RA_NOMATCH;
                        }
--- 4958,4985 ----
                    {
                        /* Compare current input with back-ref in the same
                         * line. */
!                       len = (int)(rex.reg_endp[no] - rex.reg_startp[no]);
!                       if (cstrncmp(rex.reg_startp[no], reginput, &len) != 0)
                            status = RA_NOMATCH;
                    }
                }
                else                            /* Multi-line regexp */
                {
!                   if (rex.reg_startpos[no].lnum < 0
!                                               || rex.reg_endpos[no].lnum < 0)
                    {
                        /* Backref was not set: Match an empty string. */
                        len = 0;
                    }
                    else
                    {
!                       if (rex.reg_startpos[no].lnum == reglnum
!                               && rex.reg_endpos[no].lnum == reglnum)
                        {
                            /* Compare back-ref within the current line. */
!                           len = rex.reg_endpos[no].col
!                                                   - rex.reg_startpos[no].col;
!                           if (cstrncmp(regline + rex.reg_startpos[no].col,
                                                          reginput, &len) != 0)
                                status = RA_NOMATCH;
                        }
***************
*** 4986,4995 ****
                            /* Messy situation: Need to compare between two
                             * lines. */
                            int r = match_with_backref(
!                                           reg_startpos[no].lnum,
!                                           reg_startpos[no].col,
!                                           reg_endpos[no].lnum,
!                                           reg_endpos[no].col,
                                            &len);
  
                            if (r != RA_MATCH)
--- 4988,4997 ----
                            /* Messy situation: Need to compare between two
                             * lines. */
                            int r = match_with_backref(
!                                           rex.reg_startpos[no].lnum,
!                                           rex.reg_startpos[no].col,
!                                           rex.reg_endpos[no].lnum,
!                                           rex.reg_endpos[no].col,
                                            &len);
  
                            if (r != RA_MATCH)
***************
*** 5154,5160 ****
                if (OP(next) == EXACTLY)
                {
                    rst.nextb = *OPERAND(next);
!                   if (ireg_ic)
                    {
                        if (MB_ISUPPER(rst.nextb))
                            rst.nextb_ic = MB_TOLOWER(rst.nextb);
--- 5156,5162 ----
                if (OP(next) == EXACTLY)
                {
                    rst.nextb = *OPERAND(next);
!                   if (rex.reg_ic)
                    {
                        if (MB_ISUPPER(rst.nextb))
                            rst.nextb_ic = MB_TOLOWER(rst.nextb);
***************
*** 5282,5291 ****
            break;
  
          case NEWL:
!           if ((c != NUL || !REG_MULTI || reglnum > reg_maxline
!                            || reg_line_lbr) && (c != '\n' || !reg_line_lbr))
                status = RA_NOMATCH;
!           else if (reg_line_lbr)
                ADVANCE_REGINPUT();
            else
                reg_nextline();
--- 5284,5294 ----
            break;
  
          case NEWL:
!           if ((c != NUL || !REG_MULTI || reglnum > rex.reg_maxline
!                            || rex.reg_line_lbr)
!                                          && (c != '\n' || !rex.reg_line_lbr))
                status = RA_NOMATCH;
!           else if (rex.reg_line_lbr)
                ADVANCE_REGINPUT();
            else
                reg_nextline();
***************
*** 5331,5338 ****
          case RS_MOPEN:
            /* Pop the state.  Restore pointers when there is no match. */
            if (status == RA_NOMATCH)
!               restore_se(&rp->rs_un.sesave, &reg_startpos[rp->rs_no],
!                                                 &reg_startp[rp->rs_no]);
            regstack_pop(&scan);
            break;
  
--- 5334,5341 ----
          case RS_MOPEN:
            /* Pop the state.  Restore pointers when there is no match. */
            if (status == RA_NOMATCH)
!               restore_se(&rp->rs_un.sesave, &rex.reg_startpos[rp->rs_no],
!                                                 &rex.reg_startp[rp->rs_no]);
            regstack_pop(&scan);
            break;
  
***************
*** 5349,5356 ****
          case RS_MCLOSE:
            /* Pop the state.  Restore pointers when there is no match. */
            if (status == RA_NOMATCH)
!               restore_se(&rp->rs_un.sesave, &reg_endpos[rp->rs_no],
!                                                   &reg_endp[rp->rs_no]);
            regstack_pop(&scan);
            break;
  
--- 5352,5359 ----
          case RS_MCLOSE:
            /* Pop the state.  Restore pointers when there is no match. */
            if (status == RA_NOMATCH)
!               restore_se(&rp->rs_un.sesave, &rex.reg_endpos[rp->rs_no],
!                                                   &rex.reg_endp[rp->rs_no]);
            regstack_pop(&scan);
            break;
  
***************
*** 5785,5792 ****
                ++count;
                mb_ptr_adv(scan);
            }
!           if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline
!                                        || reg_line_lbr || count == maxcount)
                break;
            ++count;            /* count the line-break */
            reg_nextline();
--- 5788,5795 ----
                ++count;
                mb_ptr_adv(scan);
            }
!           if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline
!                                     || rex.reg_line_lbr || count == maxcount)
                break;
            ++count;            /* count the line-break */
            reg_nextline();
***************
*** 5810,5824 ****
            }
            else if (*scan == NUL)
            {
!               if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline
!                                                             || reg_line_lbr)
                    break;
                reg_nextline();
                scan = reginput;
                if (got_int)
                    break;
            }
!           else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
                ++scan;
            else
                break;
--- 5813,5827 ----
            }
            else if (*scan == NUL)
            {
!               if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline
!                                                          || rex.reg_line_lbr)
                    break;
                reg_nextline();
                scan = reginput;
                if (got_int)
                    break;
            }
!           else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
                ++scan;
            else
                break;
***************
*** 5834,5855 ****
        case SKWORD + ADD_NL:
        while (count < maxcount)
        {
!           if (vim_iswordp_buf(scan, reg_buf)
                                          && (testval || !VIM_ISDIGIT(*scan)))
            {
                mb_ptr_adv(scan);
            }
            else if (*scan == NUL)
            {
!               if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline
!                                                             || reg_line_lbr)
                    break;
                reg_nextline();
                scan = reginput;
                if (got_int)
                    break;
            }
!           else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
                ++scan;
            else
                break;
--- 5837,5858 ----
        case SKWORD + ADD_NL:
        while (count < maxcount)
        {
!           if (vim_iswordp_buf(scan, rex.reg_buf)
                                          && (testval || !VIM_ISDIGIT(*scan)))
            {
                mb_ptr_adv(scan);
            }
            else if (*scan == NUL)
            {
!               if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline
!                                                          || rex.reg_line_lbr)
                    break;
                reg_nextline();
                scan = reginput;
                if (got_int)
                    break;
            }
!           else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
                ++scan;
            else
                break;
***************
*** 5871,5885 ****
            }
            else if (*scan == NUL)
            {
!               if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline
!                                                             || reg_line_lbr)
                    break;
                reg_nextline();
                scan = reginput;
                if (got_int)
                    break;
            }
!           else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
                ++scan;
            else
                break;
--- 5874,5888 ----
            }
            else if (*scan == NUL)
            {
!               if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline
!                                                          || rex.reg_line_lbr)
                    break;
                reg_nextline();
                scan = reginput;
                if (got_int)
                    break;
            }
!           else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
                ++scan;
            else
                break;
***************
*** 5897,5904 ****
        {
            if (*scan == NUL)
            {
!               if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline
!                                                             || reg_line_lbr)
                    break;
                reg_nextline();
                scan = reginput;
--- 5900,5907 ----
        {
            if (*scan == NUL)
            {
!               if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline
!                                                          || rex.reg_line_lbr)
                    break;
                reg_nextline();
                scan = reginput;
***************
*** 5910,5916 ****
            {
                mb_ptr_adv(scan);
            }
!           else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
                ++scan;
            else
                break;
--- 5913,5919 ----
            {
                mb_ptr_adv(scan);
            }
!           else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
                ++scan;
            else
                break;
***************
*** 5929,5936 ****
  #endif
            if (*scan == NUL)
            {
!               if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline
!                                                             || reg_line_lbr)
                    break;
                reg_nextline();
                scan = reginput;
--- 5932,5939 ----
  #endif
            if (*scan == NUL)
            {
!               if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline
!                                                          || rex.reg_line_lbr)
                    break;
                reg_nextline();
                scan = reginput;
***************
*** 5947,5953 ****
  #endif
            else if ((class_tab[*scan] & mask) == testval)
                ++scan;
!           else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
                ++scan;
            else
                break;
--- 5950,5956 ----
  #endif
            else if ((class_tab[*scan] & mask) == testval)
                ++scan;
!           else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
                ++scan;
            else
                break;
***************
*** 6031,6037 ****
            /* This doesn't do a multi-byte character, because a MULTIBYTECODE
             * would have been used for it.  It does handle single-byte
             * characters, such as latin1. */
!           if (ireg_ic)
            {
                cu = MB_TOUPPER(*opnd);
                cl = MB_TOLOWER(*opnd);
--- 6034,6040 ----
            /* This doesn't do a multi-byte character, because a MULTIBYTECODE
             * would have been used for it.  It does handle single-byte
             * characters, such as latin1. */
!           if (rex.reg_ic)
            {
                cu = MB_TOUPPER(*opnd);
                cl = MB_TOLOWER(*opnd);
***************
*** 6062,6075 ****
             * compiling the program). */
            if ((len = (*mb_ptr2len)(opnd)) > 1)
            {
!               if (ireg_ic && enc_utf8)
                    cf = utf_fold(utf_ptr2char(opnd));
                while (count < maxcount && (*mb_ptr2len)(scan) >= len)
                {
                    for (i = 0; i < len; ++i)
                        if (opnd[i] != scan[i])
                            break;
!                   if (i < len && (!ireg_ic || !enc_utf8
                                        || utf_fold(utf_ptr2char(scan)) != cf))
                        break;
                    scan += len;
--- 6065,6078 ----
             * compiling the program). */
            if ((len = (*mb_ptr2len)(opnd)) > 1)
            {
!               if (rex.reg_ic && enc_utf8)
                    cf = utf_fold(utf_ptr2char(opnd));
                while (count < maxcount && (*mb_ptr2len)(scan) >= len)
                {
                    for (i = 0; i < len; ++i)
                        if (opnd[i] != scan[i])
                            break;
!                   if (i < len && (!rex.reg_ic || !enc_utf8
                                        || utf_fold(utf_ptr2char(scan)) != cf))
                        break;
                    scan += len;
***************
*** 6094,6108 ****
  #endif
            if (*scan == NUL)
            {
!               if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline
!                                                             || reg_line_lbr)
                    break;
                reg_nextline();
                scan = reginput;
                if (got_int)
                    break;
            }
!           else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
                ++scan;
  #ifdef FEAT_MBYTE
            else if (has_mbyte && (len = (*mb_ptr2len)(scan)) > 1)
--- 6097,6111 ----
  #endif
            if (*scan == NUL)
            {
!               if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline
!                                                          || rex.reg_line_lbr)
                    break;
                reg_nextline();
                scan = reginput;
                if (got_int)
                    break;
            }
!           else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p)))
                ++scan;
  #ifdef FEAT_MBYTE
            else if (has_mbyte && (len = (*mb_ptr2len)(scan)) > 1)
***************
*** 6124,6134 ****
  
        case NEWL:
        while (count < maxcount
!               && ((*scan == NUL && reglnum <= reg_maxline && !reg_line_lbr
!                           && REG_MULTI) || (*scan == '\n' && reg_line_lbr)))
        {
            count++;
!           if (reg_line_lbr)
                ADVANCE_REGINPUT();
            else
                reg_nextline();
--- 6127,6138 ----
  
        case NEWL:
        while (count < maxcount
!               && ((*scan == NUL && reglnum <= rex.reg_maxline
!                                      && !rex.reg_line_lbr && REG_MULTI)
!                   || (*scan == '\n' && rex.reg_line_lbr)))
        {
            count++;
!           if (rex.reg_line_lbr)
                ADVANCE_REGINPUT();
            else
                reg_nextline();
***************
*** 6183,6189 ****
  {
      regprog_T *prog;
  
!     prog = REG_MULTI ? reg_mmatch->regprog : reg_match->regprog;
      if (prog->engine == &nfa_regengine)
        /* For NFA matcher we don't check the magic */
        return FALSE;
--- 6187,6193 ----
  {
      regprog_T *prog;
  
!     prog = REG_MULTI ? rex.reg_mmatch->regprog : rex.reg_match->regprog;
      if (prog->engine == &nfa_regengine)
        /* For NFA matcher we don't check the magic */
        return FALSE;
***************
*** 6209,6221 ****
        if (REG_MULTI)
        {
            /* Use 0xff to set lnum to -1 */
!           vim_memset(reg_startpos, 0xff, sizeof(lpos_T) * NSUBEXP);
!           vim_memset(reg_endpos, 0xff, sizeof(lpos_T) * NSUBEXP);
        }
        else
        {
!           vim_memset(reg_startp, 0, sizeof(char_u *) * NSUBEXP);
!           vim_memset(reg_endp, 0, sizeof(char_u *) * NSUBEXP);
        }
        need_clear_subexpr = FALSE;
      }
--- 6213,6225 ----
        if (REG_MULTI)
        {
            /* Use 0xff to set lnum to -1 */
!           vim_memset(rex.reg_startpos, 0xff, sizeof(lpos_T) * NSUBEXP);
!           vim_memset(rex.reg_endpos, 0xff, sizeof(lpos_T) * NSUBEXP);
        }
        else
        {
!           vim_memset(rex.reg_startp, 0, sizeof(char_u *) * NSUBEXP);
!           vim_memset(rex.reg_endp, 0, sizeof(char_u *) * NSUBEXP);
        }
        need_clear_subexpr = FALSE;
      }
***************
*** 6261,6273 ****
        {
            if (REG_MULTI)
            {
!               bp->save_start[i].se_u.pos = reg_startpos[i];
!               bp->save_end[i].se_u.pos = reg_endpos[i];
            }
            else
            {
!               bp->save_start[i].se_u.ptr = reg_startp[i];
!               bp->save_end[i].se_u.ptr = reg_endp[i];
            }
        }
      }
--- 6265,6277 ----
        {
            if (REG_MULTI)
            {
!               bp->save_start[i].se_u.pos = rex.reg_startpos[i];
!               bp->save_end[i].se_u.pos = rex.reg_endpos[i];
            }
            else
            {
!               bp->save_start[i].se_u.ptr = rex.reg_startp[i];
!               bp->save_end[i].se_u.ptr = rex.reg_endp[i];
            }
        }
      }
***************
*** 6289,6301 ****
        {
            if (REG_MULTI)
            {
!               reg_startpos[i] = bp->save_start[i].se_u.pos;
!               reg_endpos[i] = bp->save_end[i].se_u.pos;
            }
            else
            {
!               reg_startp[i] = bp->save_start[i].se_u.ptr;
!               reg_endp[i] = bp->save_end[i].se_u.ptr;
            }
        }
      }
--- 6293,6305 ----
        {
            if (REG_MULTI)
            {
!               rex.reg_startpos[i] = bp->save_start[i].se_u.pos;
!               rex.reg_endpos[i] = bp->save_end[i].se_u.pos;
            }
            else
            {
!               rex.reg_startp[i] = bp->save_start[i].se_u.ptr;
!               rex.reg_endp[i] = bp->save_end[i].se_u.ptr;
            }
        }
      }
***************
*** 6454,6460 ****
            *bytelen += len;
        if (clnum == end_lnum)
            break;              /* match and at end! */
!       if (reglnum >= reg_maxline)
            return RA_NOMATCH;  /* text too short */
  
        /* Advance to next line. */
--- 6458,6464 ----
            *bytelen += len;
        if (clnum == end_lnum)
            break;              /* match and at end! */
!       if (reglnum >= rex.reg_maxline)
            return RA_NOMATCH;  /* text too short */
  
        /* Advance to next line. */
***************
*** 7039,7045 ****
  #endif
  
  /*
!  * Compare two strings, ignore case if ireg_ic set.
   * Return 0 if strings match, non-zero otherwise.
   * Correct the length "*n" when composing characters are ignored.
   */
--- 7043,7049 ----
  #endif
  
  /*
!  * Compare two strings, ignore case if rex.reg_ic set.
   * Return 0 if strings match, non-zero otherwise.
   * Correct the length "*n" when composing characters are ignored.
   */
***************
*** 7048,7061 ****
  {
      int               result;
  
!     if (!ireg_ic)
        result = STRNCMP(s1, s2, *n);
      else
        result = MB_STRNICMP(s1, s2, *n);
  
  #ifdef FEAT_MBYTE
      /* if it failed and it's utf8 and we want to combineignore: */
!     if (result != 0 && enc_utf8 && ireg_icombine)
      {
        char_u  *str1, *str2;
        int     c1, c2, c11, c12;
--- 7052,7065 ----
  {
      int               result;
  
!     if (!rex.reg_ic)
        result = STRNCMP(s1, s2, *n);
      else
        result = MB_STRNICMP(s1, s2, *n);
  
  #ifdef FEAT_MBYTE
      /* if it failed and it's utf8 and we want to combineignore: */
!     if (result != 0 && enc_utf8 && rex.reg_icombine)
      {
        char_u  *str1, *str2;
        int     c1, c2, c11, c12;
***************
*** 7074,7087 ****
            /* decompose the character if necessary, into 'base' characters
             * because I don't care about Arabic, I will hard-code the Hebrew
             * which I *do* care about!  So sue me... */
!           if (c1 != c2 && (!ireg_ic || utf_fold(c1) != utf_fold(c2)))
            {
                /* decomposition necessary? */
                mb_decompose(c1, &c11, &junk, &junk);
                mb_decompose(c2, &c12, &junk, &junk);
                c1 = c11;
                c2 = c12;
!               if (c11 != c12 && (!ireg_ic || utf_fold(c11) != utf_fold(c12)))
                    break;
            }
        }
--- 7078,7092 ----
            /* decompose the character if necessary, into 'base' characters
             * because I don't care about Arabic, I will hard-code the Hebrew
             * which I *do* care about!  So sue me... */
!           if (c1 != c2 && (!rex.reg_ic || utf_fold(c1) != utf_fold(c2)))
            {
                /* decomposition necessary? */
                mb_decompose(c1, &c11, &junk, &junk);
                mb_decompose(c2, &c12, &junk, &junk);
                c1 = c11;
                c2 = c12;
!               if (c11 != c12
!                           && (!rex.reg_ic || utf_fold(c11) != utf_fold(c12)))
                    break;
            }
        }
***************
*** 7103,7109 ****
      char_u    *p;
      int               cc;
  
!     if (!ireg_ic
  #ifdef FEAT_MBYTE
            || (!enc_utf8 && mb_char2len(c) > 1)
  #endif
--- 7108,7114 ----
      char_u    *p;
      int               cc;
  
!     if (!rex.reg_ic
  #ifdef FEAT_MBYTE
            || (!enc_utf8 && mb_char2len(c) > 1)
  #endif
***************
*** 7276,7289 ****
  #ifdef FEAT_EVAL
  static int can_f_submatch = FALSE;    /* TRUE when submatch() can be used */
  
! /* These pointers are used instead of reg_match and reg_mmatch for
!  * reg_submatch().  Needed for when the substitution string is an expression
!  * that contains a call to substitute() and submatch(). */
! static regmatch_T     *submatch_match;
! static regmmatch_T    *submatch_mmatch;
! static linenr_T               submatch_firstlnum;
! static linenr_T               submatch_maxline;
! static int            submatch_line_lbr;
  #endif
  
  #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
--- 7281,7298 ----
  #ifdef FEAT_EVAL
  static int can_f_submatch = FALSE;    /* TRUE when submatch() can be used */
  
! /* These pointers are used for reg_submatch().  Needed for when the
!  * substitution string is an expression that contains a call to substitute()
!  * and submatch(). */
! typedef struct {
!     regmatch_T        *sm_match;
!     regmmatch_T       *sm_mmatch;
!     linenr_T  sm_firstlnum;
!     linenr_T  sm_maxline;
!     int               sm_line_lbr;
! } regsubmatch_T;
! 
! static regsubmatch_T rsm;  /* can only be used when can_f_submatch is TRUE */
  #endif
  
  #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
***************
*** 7310,7320 ****
      li = argv->vval.v_list->lv_first;
      for (i = 0; i < 10; ++i)
      {
!       s = submatch_match->startp[i];
!       if (s == NULL || submatch_match->endp[i] == NULL)
            s = NULL;
        else
!           s = vim_strnsave(s, (int)(submatch_match->endp[i] - s));
        li->li_tv.v_type = VAR_STRING;
        li->li_tv.vval.v_string = s;
        li = li->li_next;
--- 7319,7329 ----
      li = argv->vval.v_list->lv_first;
      for (i = 0; i < 10; ++i)
      {
!       s = rsm.sm_match->startp[i];
!       if (s == NULL || rsm.sm_match->endp[i] == NULL)
            s = NULL;
        else
!           s = vim_strnsave(s, (int)(rsm.sm_match->endp[i] - s));
        li->li_tv.v_type = VAR_STRING;
        li->li_tv.vval.v_string = s;
        li = li->li_next;
***************
*** 7359,7370 ****
      int               magic,
      int               backslash)
  {
!     reg_match = rmp;
!     reg_mmatch = NULL;
!     reg_maxline = 0;
!     reg_buf = curbuf;
!     reg_line_lbr = TRUE;
!     return vim_regsub_both(source, expr, dest, copy, magic, backslash);
  }
  #endif
  
--- 7368,7394 ----
      int               magic,
      int               backslash)
  {
!     int               result;
!     regexec_T rex_save;
!     int               rex_in_use_save = rex_in_use;
! 
!     if (rex_in_use)
!       /* Being called recursively, save the state. */
!       rex_save = rex;
!     rex_in_use = TRUE;
! 
!     rex.reg_match = rmp;
!     rex.reg_mmatch = NULL;
!     rex.reg_maxline = 0;
!     rex.reg_buf = curbuf;
!     rex.reg_line_lbr = TRUE;
!     result = vim_regsub_both(source, expr, dest, copy, magic, backslash);
! 
!     rex_in_use = rex_in_use_save;
!     if (rex_in_use)
!       rex = rex_save;
! 
!     return result;
  }
  #endif
  
***************
*** 7378,7390 ****
      int               magic,
      int               backslash)
  {
!     reg_match = NULL;
!     reg_mmatch = rmp;
!     reg_buf = curbuf;         /* always works on the current buffer! */
!     reg_firstlnum = lnum;
!     reg_maxline = curbuf->b_ml.ml_line_count - lnum;
!     reg_line_lbr = FALSE;
!     return vim_regsub_both(source, NULL, dest, copy, magic, backslash);
  }
  
      static int
--- 7402,7429 ----
      int               magic,
      int               backslash)
  {
!     int               result;
!     regexec_T rex_save;
!     int               rex_in_use_save = rex_in_use;
! 
!     if (rex_in_use)
!       /* Being called recursively, save the state. */
!       rex_save = rex;
!     rex_in_use = TRUE;
! 
!     rex.reg_match = NULL;
!     rex.reg_mmatch = rmp;
!     rex.reg_buf = curbuf;     /* always works on the current buffer! */
!     rex.reg_firstlnum = lnum;
!     rex.reg_maxline = curbuf->b_ml.ml_line_count - lnum;
!     rex.reg_line_lbr = FALSE;
!     result = vim_regsub_both(source, NULL, dest, copy, magic, backslash);
! 
!     rex_in_use = rex_in_use_save;
!     if (rex_in_use)
!       rex = rex_save;
! 
!     return result;
  }
  
      static int
***************
*** 7424,7434 ****
      /*
       * When the substitute part starts with "\=" evaluate it as an expression.
       */
!     if (expr != NULL || (source[0] == '\\' && source[1] == '='
! #ifdef FEAT_EVAL
!           && !can_f_submatch      /* can't do this recursively */
! #endif
!           ))
      {
  #ifdef FEAT_EVAL
        /* To make sure that the length doesn't change between checking the
--- 7463,7469 ----
      /*
       * When the substitute part starts with "\=" evaluate it as an expression.
       */
!     if (expr != NULL || (source[0] == '\\' && source[1] == '='))
      {
  #ifdef FEAT_EVAL
        /* To make sure that the length doesn't change between checking the
***************
*** 7447,7470 ****
        }
        else
        {
!           win_T       *save_reg_win;
!           int         save_ireg_ic;
!           int         prev_can_f_submatch = can_f_submatch;
  
            vim_free(eval_result);
  
            /* The expression may contain substitute(), which calls us
             * recursively.  Make sure submatch() gets the text from the first
!            * level.  Don't need to save "reg_buf", because
!            * vim_regexec_multi() can't be called recursively. */
!           submatch_match = reg_match;
!           submatch_mmatch = reg_mmatch;
!           submatch_firstlnum = reg_firstlnum;
!           submatch_maxline = reg_maxline;
!           submatch_line_lbr = reg_line_lbr;
!           save_reg_win = reg_win;
!           save_ireg_ic = ireg_ic;
            can_f_submatch = TRUE;
  
            if (expr != NULL)
            {
--- 7482,7503 ----
        }
        else
        {
!           int             prev_can_f_submatch = can_f_submatch;
!           regsubmatch_T   rsm_save;
  
            vim_free(eval_result);
  
            /* The expression may contain substitute(), which calls us
             * recursively.  Make sure submatch() gets the text from the first
!            * level. */
!           if (can_f_submatch)
!               rsm_save = rsm;
            can_f_submatch = TRUE;
+           rsm.sm_match = rex.reg_match;
+           rsm.sm_mmatch = rex.reg_mmatch;
+           rsm.sm_firstlnum = rex.reg_firstlnum;
+           rsm.sm_maxline = rex.reg_maxline;
+           rsm.sm_line_lbr = rex.reg_line_lbr;
  
            if (expr != NULL)
            {
***************
*** 7476,7510 ****
  
                rettv.v_type = VAR_STRING;
                rettv.vval.v_string = NULL;
!               if (prev_can_f_submatch)
!               {
!                   /* can't do this recursively */
!               }
!               else
!               {
!                   argv[0].v_type = VAR_LIST;
!                   argv[0].vval.v_list = &matchList.sl_list;
!                   matchList.sl_list.lv_len = 0;
!                   if (expr->v_type == VAR_FUNC)
!                   {
!                       s = expr->vval.v_string;
!                       call_func(s, (int)STRLEN(s), &rettv,
!                                       1, argv, fill_submatch_list,
!                                            0L, 0L, &dummy, TRUE, NULL, NULL);
!                   }
!                   else if (expr->v_type == VAR_PARTIAL)
!                   {
!                       partial_T   *partial = expr->vval.v_partial;
  
-                       s = partial_name(partial);
-                       call_func(s, (int)STRLEN(s), &rettv,
-                                       1, argv, fill_submatch_list,
-                                         0L, 0L, &dummy, TRUE, partial, NULL);
-                   }
-                   if (matchList.sl_list.lv_len > 0)
-                       /* fill_submatch_list() was called */
-                       clear_submatch_list(&matchList);
-               }
                eval_result = get_tv_string_buf_chk(&rettv, buf);
                if (eval_result != NULL)
                    eval_result = vim_strsave(eval_result);
--- 7509,7537 ----
  
                rettv.v_type = VAR_STRING;
                rettv.vval.v_string = NULL;
!               argv[0].v_type = VAR_LIST;
!               argv[0].vval.v_list = &matchList.sl_list;
!               matchList.sl_list.lv_len = 0;
!               if (expr->v_type == VAR_FUNC)
!               {
!                   s = expr->vval.v_string;
!                   call_func(s, (int)STRLEN(s), &rettv,
!                                   1, argv, fill_submatch_list,
!                                        0L, 0L, &dummy, TRUE, NULL, NULL);
!               }
!               else if (expr->v_type == VAR_PARTIAL)
!               {
!                   partial_T   *partial = expr->vval.v_partial;
! 
!                   s = partial_name(partial);
!                   call_func(s, (int)STRLEN(s), &rettv,
!                                   1, argv, fill_submatch_list,
!                                     0L, 0L, &dummy, TRUE, partial, NULL);
!               }
!               if (matchList.sl_list.lv_len > 0)
!                   /* fill_submatch_list() was called */
!                   clear_submatch_list(&matchList);
  
                eval_result = get_tv_string_buf_chk(&rettv, buf);
                if (eval_result != NULL)
                    eval_result = vim_strsave(eval_result);
***************
*** 7522,7528 ****
                    /* Change NL to CR, so that it becomes a line break,
                     * unless called from vim_regexec_nl().
                     * Skip over a backslashed character. */
!                   if (*s == NL && !submatch_line_lbr)
                        *s = CAR;
                    else if (*s == '\\' && s[1] != NUL)
                    {
--- 7549,7555 ----
                    /* Change NL to CR, so that it becomes a line break,
                     * unless called from vim_regexec_nl().
                     * Skip over a backslashed character. */
!                   if (*s == NL && !rsm.sm_line_lbr)
                        *s = CAR;
                    else if (*s == '\\' && s[1] != NUL)
                    {
***************
*** 7533,7539 ****
                         *   def
                         * Not when called from vim_regexec_nl().
                         */
!                       if (*s == NL && !submatch_line_lbr)
                            *s = CAR;
                        had_backslash = TRUE;
                    }
--- 7560,7566 ----
                         *   def
                         * Not when called from vim_regexec_nl().
                         */
!                       if (*s == NL && !rsm.sm_line_lbr)
                            *s = CAR;
                        had_backslash = TRUE;
                    }
***************
*** 7552,7565 ****
                dst += STRLEN(eval_result);
            }
  
!           reg_match = submatch_match;
!           reg_mmatch = submatch_mmatch;
!           reg_firstlnum = submatch_firstlnum;
!           reg_maxline = submatch_maxline;
!           reg_line_lbr = submatch_line_lbr;
!           reg_win = save_reg_win;
!           ireg_ic = save_ireg_ic;
!           can_f_submatch = FALSE;
        }
  #endif
      }
--- 7579,7587 ----
                dst += STRLEN(eval_result);
            }
  
!           can_f_submatch = prev_can_f_submatch;
!           if (can_f_submatch)
!               rsm = rsm_save;
        }
  #endif
      }
***************
*** 7688,7713 ****
        {
            if (REG_MULTI)
            {
!               clnum = reg_mmatch->startpos[no].lnum;
!               if (clnum < 0 || reg_mmatch->endpos[no].lnum < 0)
                    s = NULL;
                else
                {
!                   s = reg_getline(clnum) + reg_mmatch->startpos[no].col;
!                   if (reg_mmatch->endpos[no].lnum == clnum)
!                       len = reg_mmatch->endpos[no].col
!                                              - reg_mmatch->startpos[no].col;
                    else
                        len = (int)STRLEN(s);
                }
            }
            else
            {
!               s = reg_match->startp[no];
!               if (reg_match->endp[no] == NULL)
                    s = NULL;
                else
!                   len = (int)(reg_match->endp[no] - s);
            }
            if (s != NULL)
            {
--- 7710,7735 ----
        {
            if (REG_MULTI)
            {
!               clnum = rex.reg_mmatch->startpos[no].lnum;
!               if (clnum < 0 || rex.reg_mmatch->endpos[no].lnum < 0)
                    s = NULL;
                else
                {
!                   s = reg_getline(clnum) + rex.reg_mmatch->startpos[no].col;
!                   if (rex.reg_mmatch->endpos[no].lnum == clnum)
!                       len = rex.reg_mmatch->endpos[no].col
!                                           - rex.reg_mmatch->startpos[no].col;
                    else
                        len = (int)STRLEN(s);
                }
            }
            else
            {
!               s = rex.reg_match->startp[no];
!               if (rex.reg_match->endp[no] == NULL)
                    s = NULL;
                else
!                   len = (int)(rex.reg_match->endp[no] - s);
            }
            if (s != NULL)
            {
***************
*** 7717,7730 ****
                    {
                        if (REG_MULTI)
                        {
!                           if (reg_mmatch->endpos[no].lnum == clnum)
                                break;
                            if (copy)
                                *dst = CAR;
                            ++dst;
                            s = reg_getline(++clnum);
!                           if (reg_mmatch->endpos[no].lnum == clnum)
!                               len = reg_mmatch->endpos[no].col;
                            else
                                len = (int)STRLEN(s);
                        }
--- 7739,7752 ----
                    {
                        if (REG_MULTI)
                        {
!                           if (rex.reg_mmatch->endpos[no].lnum == clnum)
                                break;
                            if (copy)
                                *dst = CAR;
                            ++dst;
                            s = reg_getline(++clnum);
!                           if (rex.reg_mmatch->endpos[no].lnum == clnum)
!                               len = rex.reg_mmatch->endpos[no].col;
                            else
                                len = (int)STRLEN(s);
                        }
***************
*** 7824,7839 ****
  reg_getline_submatch(linenr_T lnum)
  {
      char_u *s;
!     linenr_T save_first = reg_firstlnum;
!     linenr_T save_max = reg_maxline;
  
!     reg_firstlnum = submatch_firstlnum;
!     reg_maxline = submatch_maxline;
  
      s = reg_getline(lnum);
  
!     reg_firstlnum = save_first;
!     reg_maxline = save_max;
      return s;
  }
  
--- 7846,7861 ----
  reg_getline_submatch(linenr_T lnum)
  {
      char_u *s;
!     linenr_T save_first = rex.reg_firstlnum;
!     linenr_T save_max = rex.reg_maxline;
  
!     rex.reg_firstlnum = rsm.sm_firstlnum;
!     rex.reg_maxline = rsm.sm_maxline;
  
      s = reg_getline(lnum);
  
!     rex.reg_firstlnum = save_first;
!     rex.reg_maxline = save_max;
      return s;
  }
  
***************
*** 7854,7860 ****
      if (!can_f_submatch || no < 0)
        return NULL;
  
!     if (submatch_match == NULL)
      {
        /*
         * First round: compute the length and allocate memory.
--- 7876,7882 ----
      if (!can_f_submatch || no < 0)
        return NULL;
  
!     if (rsm.sm_match == NULL)
      {
        /*
         * First round: compute the length and allocate memory.
***************
*** 7862,7879 ****
         */
        for (round = 1; round <= 2; ++round)
        {
!           lnum = submatch_mmatch->startpos[no].lnum;
!           if (lnum < 0 || submatch_mmatch->endpos[no].lnum < 0)
                return NULL;
  
!           s = reg_getline_submatch(lnum) + submatch_mmatch->startpos[no].col;
            if (s == NULL)  /* anti-crash check, cannot happen? */
                break;
!           if (submatch_mmatch->endpos[no].lnum == lnum)
            {
                /* Within one line: take form start to end col. */
!               len = submatch_mmatch->endpos[no].col
!                                         - submatch_mmatch->startpos[no].col;
                if (round == 2)
                    vim_strncpy(retval, s, len);
                ++len;
--- 7884,7901 ----
         */
        for (round = 1; round <= 2; ++round)
        {
!           lnum = rsm.sm_mmatch->startpos[no].lnum;
!           if (lnum < 0 || rsm.sm_mmatch->endpos[no].lnum < 0)
                return NULL;
  
!           s = reg_getline_submatch(lnum) + rsm.sm_mmatch->startpos[no].col;
            if (s == NULL)  /* anti-crash check, cannot happen? */
                break;
!           if (rsm.sm_mmatch->endpos[no].lnum == lnum)
            {
                /* Within one line: take form start to end col. */
!               len = rsm.sm_mmatch->endpos[no].col
!                                         - rsm.sm_mmatch->startpos[no].col;
                if (round == 2)
                    vim_strncpy(retval, s, len);
                ++len;
***************
*** 7890,7896 ****
                }
                ++len;
                ++lnum;
!               while (lnum < submatch_mmatch->endpos[no].lnum)
                {
                    s = reg_getline_submatch(lnum++);
                    if (round == 2)
--- 7912,7918 ----
                }
                ++len;
                ++lnum;
!               while (lnum < rsm.sm_mmatch->endpos[no].lnum)
                {
                    s = reg_getline_submatch(lnum++);
                    if (round == 2)
***************
*** 7902,7909 ****
                }
                if (round == 2)
                    STRNCPY(retval + len, reg_getline_submatch(lnum),
!                                            submatch_mmatch->endpos[no].col);
!               len += submatch_mmatch->endpos[no].col;
                if (round == 2)
                    retval[len] = NUL;
                ++len;
--- 7924,7931 ----
                }
                if (round == 2)
                    STRNCPY(retval + len, reg_getline_submatch(lnum),
!                                            rsm.sm_mmatch->endpos[no].col);
!               len += rsm.sm_mmatch->endpos[no].col;
                if (round == 2)
                    retval[len] = NUL;
                ++len;
***************
*** 7919,7929 ****
      }
      else
      {
!       s = submatch_match->startp[no];
!       if (s == NULL || submatch_match->endp[no] == NULL)
            retval = NULL;
        else
!           retval = vim_strnsave(s, (int)(submatch_match->endp[no] - s));
      }
  
      return retval;
--- 7941,7951 ----
      }
      else
      {
!       s = rsm.sm_match->startp[no];
!       if (s == NULL || rsm.sm_match->endp[no] == NULL)
            retval = NULL;
        else
!           retval = vim_strnsave(s, (int)(rsm.sm_match->endp[no] - s));
      }
  
      return retval;
***************
*** 7951,7965 ****
      if (!can_f_submatch || no < 0)
        return NULL;
  
!     if (submatch_match == NULL)
      {
!       slnum = submatch_mmatch->startpos[no].lnum;
!       elnum = submatch_mmatch->endpos[no].lnum;
        if (slnum < 0 || elnum < 0)
            return NULL;
  
!       scol = submatch_mmatch->startpos[no].col;
!       ecol = submatch_mmatch->endpos[no].col;
  
        list = list_alloc();
        if (list == NULL)
--- 7973,7987 ----
      if (!can_f_submatch || no < 0)
        return NULL;
  
!     if (rsm.sm_match == NULL)
      {
!       slnum = rsm.sm_mmatch->startpos[no].lnum;
!       elnum = rsm.sm_mmatch->endpos[no].lnum;
        if (slnum < 0 || elnum < 0)
            return NULL;
  
!       scol = rsm.sm_mmatch->startpos[no].col;
!       ecol = rsm.sm_mmatch->endpos[no].col;
  
        list = list_alloc();
        if (list == NULL)
***************
*** 7988,8001 ****
      }
      else
      {
!       s = submatch_match->startp[no];
!       if (s == NULL || submatch_match->endp[no] == NULL)
            return NULL;
        list = list_alloc();
        if (list == NULL)
            return NULL;
        if (list_append_string(list, s,
!                                (int)(submatch_match->endp[no] - s)) == FAIL)
            error = TRUE;
      }
  
--- 8010,8023 ----
      }
      else
      {
!       s = rsm.sm_match->startp[no];
!       if (s == NULL || rsm.sm_match->endp[no] == NULL)
            return NULL;
        list = list_alloc();
        if (list == NULL)
            return NULL;
        if (list_append_string(list, s,
!                                (int)(rsm.sm_match->endp[no] - s)) == FAIL)
            error = TRUE;
      }
  
***************
*** 8173,8179 ****
      colnr_T   col,    /* column to start looking for match */
      int               nl)
  {
!     int result = rmp->regprog->engine->regexec_nl(rmp, line, col, nl);
  
      /* NFA engine aborted because it's very slow. */
      if (rmp->regprog->re_engine == AUTOMATIC_ENGINE
--- 8195,8214 ----
      colnr_T   col,    /* column to start looking for match */
      int               nl)
  {
!     int               result;
!     regexec_T rex_save;
!     int               rex_in_use_save = rex_in_use;
! 
!     if (rex_in_use)
!       /* Being called recursively, save the state. */
!       rex_save = rex;
!     rex_in_use = TRUE;
!     rex.reg_startp = NULL;
!     rex.reg_endp = NULL;
!     rex.reg_startpos = NULL;
!     rex.reg_endpos = NULL;
! 
!     result = rmp->regprog->engine->regexec_nl(rmp, line, col, nl);
  
      /* NFA engine aborted because it's very slow. */
      if (rmp->regprog->re_engine == AUTOMATIC_ENGINE
***************
*** 8198,8203 ****
--- 8233,8243 ----
  
        p_re = save_p_re;
      }
+ 
+     rex_in_use = rex_in_use_save;
+     if (rex_in_use)
+       rex = rex_save;
+ 
      return result > 0;
  }
  
***************
*** 8264,8271 ****
      colnr_T     col,            /* column to start looking for match */
      proftime_T        *tm)            /* timeout limit or NULL */
  {
!     int result = rmp->regprog->engine->regexec_multi(
!                                               rmp, win, buf, lnum, col, tm);
  
      /* NFA engine aborted because it's very slow. */
      if (rmp->regprog->re_engine == AUTOMATIC_ENGINE
--- 8304,8319 ----
      colnr_T     col,            /* column to start looking for match */
      proftime_T        *tm)            /* timeout limit or NULL */
  {
!     int               result;
!     regexec_T rex_save;
!     int               rex_in_use_save = rex_in_use;
! 
!     if (rex_in_use)
!       /* Being called recursively, save the state. */
!       rex_save = rex;
!     rex_in_use = TRUE;
! 
!     result = rmp->regprog->engine->regexec_multi(rmp, win, buf, lnum, col, 
tm);
  
      /* NFA engine aborted because it's very slow. */
      if (rmp->regprog->re_engine == AUTOMATIC_ENGINE
***************
*** 8291,8295 ****
--- 8339,8347 ----
        p_re = save_p_re;
      }
  
+     rex_in_use = rex_in_use_save;
+     if (rex_in_use)
+       rex = rex_save;
+ 
      return result <= 0 ? 0 : result;
  }
*** ../vim-8.0.0019/src/regexp_nfa.c    2016-09-09 20:26:46.000000000 +0200
--- src/regexp_nfa.c    2016-10-02 15:51:12.173504331 +0200
***************
*** 5432,5438 ****
      char_u *s;
  
      /* Used often, do some work to avoid call overhead. */
!     if (!ireg_ic
  #ifdef FEAT_MBYTE
                && !has_mbyte
  #endif
--- 5432,5438 ----
      char_u *s;
  
      /* Used often, do some work to avoid call overhead. */
!     if (!rex.reg_ic
  #ifdef FEAT_MBYTE
                && !has_mbyte
  #endif
***************
*** 5467,5473 ****
        {
            c1 = PTR2CHAR(match_text + len1);
            c2 = PTR2CHAR(regline + col + len2);
!           if (c1 != c2 && (!ireg_ic || MB_TOLOWER(c1) != MB_TOLOWER(c2)))
            {
                match = FALSE;
                break;
--- 5467,5473 ----
        {
            c1 = PTR2CHAR(match_text + len1);
            c2 = PTR2CHAR(regline + col + len2);
!           if (c1 != c2 && (!rex.reg_ic || MB_TOLOWER(c1) != MB_TOLOWER(c2)))
            {
                match = FALSE;
                break;
***************
*** 5485,5499 ****
            cleanup_subexpr();
            if (REG_MULTI)
            {
!               reg_startpos[0].lnum = reglnum;
!               reg_startpos[0].col = col;
!               reg_endpos[0].lnum = reglnum;
!               reg_endpos[0].col = col + len2;
            }
            else
            {
!               reg_startp[0] = regline + col;
!               reg_endp[0] = regline + col + len2;
            }
            return 1L;
        }
--- 5485,5499 ----
            cleanup_subexpr();
            if (REG_MULTI)
            {
!               rex.reg_startpos[0].lnum = reglnum;
!               rex.reg_startpos[0].col = col;
!               rex.reg_endpos[0].lnum = reglnum;
!               rex.reg_endpos[0].col = col + len2;
            }
            else
            {
!               rex.reg_startp[0] = regline + col;
!               rex.reg_endp[0] = regline + col + len2;
            }
            return 1L;
        }
***************
*** 5728,5735 ****
              {
  #ifdef FEAT_MBYTE
                /* If the match ends before a composing characters and
!                * ireg_icombine is not set, that is not really a match. */
!               if (enc_utf8 && !ireg_icombine && utf_iscomposing(curc))
                    break;
  #endif
                nfa_match = TRUE;
--- 5728,5735 ----
              {
  #ifdef FEAT_MBYTE
                /* If the match ends before a composing characters and
!                * rex.reg_icombine is not set, that is not really a match. */
!               if (enc_utf8 && !rex.reg_icombine && utf_iscomposing(curc))
                    break;
  #endif
                nfa_match = TRUE;
***************
*** 6048,6063 ****
                    int this_class;
  
                    /* Get class of current and previous char (if it exists). */
!                   this_class = mb_get_class_buf(reginput, reg_buf);
                    if (this_class <= 1)
                        result = FALSE;
                    else if (reg_prev_class() == this_class)
                        result = FALSE;
                }
  #endif
!               else if (!vim_iswordc_buf(curc, reg_buf)
                           || (reginput > regline
!                                  && vim_iswordc_buf(reginput[-1], reg_buf)))
                    result = FALSE;
                if (result)
                {
--- 6048,6063 ----
                    int this_class;
  
                    /* Get class of current and previous char (if it exists). */
!                   this_class = mb_get_class_buf(reginput, rex.reg_buf);
                    if (this_class <= 1)
                        result = FALSE;
                    else if (reg_prev_class() == this_class)
                        result = FALSE;
                }
  #endif
!               else if (!vim_iswordc_buf(curc, rex.reg_buf)
                           || (reginput > regline
!                               && vim_iswordc_buf(reginput[-1], rex.reg_buf)))
                    result = FALSE;
                if (result)
                {
***************
*** 6076,6091 ****
                    int this_class, prev_class;
  
                    /* Get class of current and previous char (if it exists). */
!                   this_class = mb_get_class_buf(reginput, reg_buf);
                    prev_class = reg_prev_class();
                    if (this_class == prev_class
                                        || prev_class == 0 || prev_class == 1)
                        result = FALSE;
                }
  #endif
!               else if (!vim_iswordc_buf(reginput[-1], reg_buf)
                        || (reginput[0] != NUL
!                                          && vim_iswordc_buf(curc, reg_buf)))
                    result = FALSE;
                if (result)
                {
--- 6076,6091 ----
                    int this_class, prev_class;
  
                    /* Get class of current and previous char (if it exists). */
!                   this_class = mb_get_class_buf(reginput, rex.reg_buf);
                    prev_class = reg_prev_class();
                    if (this_class == prev_class
                                        || prev_class == 0 || prev_class == 1)
                        result = FALSE;
                }
  #endif
!               else if (!vim_iswordc_buf(reginput[-1], rex.reg_buf)
                        || (reginput[0] != NUL
!                                       && vim_iswordc_buf(curc, rex.reg_buf)))
                    result = FALSE;
                if (result)
                {
***************
*** 6096,6102 ****
  
            case NFA_BOF:
                if (reglnum == 0 && reginput == regline
!                                       && (!REG_MULTI || reg_firstlnum == 1))
                {
                    add_here = TRUE;
                    add_state = t->state->out;
--- 6096,6102 ----
  
            case NFA_BOF:
                if (reglnum == 0 && reginput == regline
!                                    && (!REG_MULTI || rex.reg_firstlnum == 1))
                {
                    add_here = TRUE;
                    add_state = t->state->out;
***************
*** 6104,6110 ****
                break;
  
            case NFA_EOF:
!               if (reglnum == reg_maxline && curc == NUL)
                {
                    add_here = TRUE;
                    add_state = t->state->out;
--- 6104,6110 ----
                break;
  
            case NFA_EOF:
!               if (reglnum == rex.reg_maxline && curc == NUL)
                {
                    add_here = TRUE;
                    add_state = t->state->out;
***************
*** 6131,6137 ****
                     * (no preceding character). */
                    len += mb_char2len(mc);
                }
!               if (ireg_icombine && len == 0)
                {
                    /* If \Z was present, then ignore composing characters.
                     * When ignoring the base character this always matches. */
--- 6131,6137 ----
                     * (no preceding character). */
                    len += mb_char2len(mc);
                }
!               if (rex.reg_icombine && len == 0)
                {
                    /* If \Z was present, then ignore composing characters.
                     * When ignoring the base character this always matches. */
***************
*** 6190,6197 ****
  #endif
  
            case NFA_NEWL:
!               if (curc == NUL && !reg_line_lbr && REG_MULTI
!                                                   && reglnum <= reg_maxline)
                {
                    go_to_nextline = TRUE;
                    /* Pass -1 for the offset, which means taking the position
--- 6190,6197 ----
  #endif
  
            case NFA_NEWL:
!               if (curc == NUL && !rex.reg_line_lbr && REG_MULTI
!                                                && reglnum <= rex.reg_maxline)
                {
                    go_to_nextline = TRUE;
                    /* Pass -1 for the offset, which means taking the position
***************
*** 6199,6205 ****
                    add_state = t->state->out;
                    add_off = -1;
                }
!               else if (curc == '\n' && reg_line_lbr)
                {
                    /* match \n as if it is an ordinary character */
                    add_state = t->state->out;
--- 6199,6205 ----
                    add_state = t->state->out;
                    add_off = -1;
                }
!               else if (curc == '\n' && rex.reg_line_lbr)
                {
                    /* match \n as if it is an ordinary character */
                    add_state = t->state->out;
***************
*** 6244,6250 ****
                            result = result_if_matched;
                            break;
                        }
!                       if (ireg_ic)
                        {
                            int curc_low = MB_TOLOWER(curc);
                            int done = FALSE;
--- 6244,6250 ----
                            result = result_if_matched;
                            break;
                        }
!                       if (rex.reg_ic)
                        {
                            int curc_low = MB_TOLOWER(curc);
                            int done = FALSE;
***************
*** 6262,6268 ****
                    }
                    else if (state->c < 0 ? check_char_class(state->c, curc)
                                : (curc == state->c
!                                  || (ireg_ic && MB_TOLOWER(curc)
                                                    == MB_TOLOWER(state->c))))
                    {
                        result = result_if_matched;
--- 6262,6268 ----
                    }
                    else if (state->c < 0 ? check_char_class(state->c, curc)
                                : (curc == state->c
!                                  || (rex.reg_ic && MB_TOLOWER(curc)
                                                    == MB_TOLOWER(state->c))))
                    {
                        result = result_if_matched;
***************
*** 6320,6332 ****
                break;
  
            case NFA_KWORD:     /*  \k  */
!               result = vim_iswordp_buf(reginput, reg_buf);
                ADD_STATE_IF_MATCH(t->state);
                break;
  
            case NFA_SKWORD:    /*  \K  */
                result = !VIM_ISDIGIT(curc)
!                                       && vim_iswordp_buf(reginput, reg_buf);
                ADD_STATE_IF_MATCH(t->state);
                break;
  
--- 6320,6332 ----
                break;
  
            case NFA_KWORD:     /*  \k  */
!               result = vim_iswordp_buf(reginput, rex.reg_buf);
                ADD_STATE_IF_MATCH(t->state);
                break;
  
            case NFA_SKWORD:    /*  \K  */
                result = !VIM_ISDIGIT(curc)
!                                    && vim_iswordp_buf(reginput, rex.reg_buf);
                ADD_STATE_IF_MATCH(t->state);
                break;
  
***************
*** 6441,6464 ****
                break;
  
            case NFA_LOWER_IC:  /* [a-z] */
!               result = ri_lower(curc) || (ireg_ic && ri_upper(curc));
                ADD_STATE_IF_MATCH(t->state);
                break;
  
            case NFA_NLOWER_IC: /* [^a-z] */
                result = curc != NUL
!                         && !(ri_lower(curc) || (ireg_ic && ri_upper(curc)));
                ADD_STATE_IF_MATCH(t->state);
                break;
  
            case NFA_UPPER_IC:  /* [A-Z] */
!               result = ri_upper(curc) || (ireg_ic && ri_lower(curc));
                ADD_STATE_IF_MATCH(t->state);
                break;
  
            case NFA_NUPPER_IC: /* ^[A-Z] */
                result = curc != NUL
!                         && !(ri_upper(curc) || (ireg_ic && ri_lower(curc)));
                ADD_STATE_IF_MATCH(t->state);
                break;
  
--- 6441,6464 ----
                break;
  
            case NFA_LOWER_IC:  /* [a-z] */
!               result = ri_lower(curc) || (rex.reg_ic && ri_upper(curc));
                ADD_STATE_IF_MATCH(t->state);
                break;
  
            case NFA_NLOWER_IC: /* [^a-z] */
                result = curc != NUL
!                       && !(ri_lower(curc) || (rex.reg_ic && ri_upper(curc)));
                ADD_STATE_IF_MATCH(t->state);
                break;
  
            case NFA_UPPER_IC:  /* [A-Z] */
!               result = ri_upper(curc) || (rex.reg_ic && ri_lower(curc));
                ADD_STATE_IF_MATCH(t->state);
                break;
  
            case NFA_NUPPER_IC: /* ^[A-Z] */
                result = curc != NUL
!                       && !(ri_upper(curc) || (rex.reg_ic && ri_lower(curc)));
                ADD_STATE_IF_MATCH(t->state);
                break;
  
***************
*** 6549,6555 ****
            case NFA_LNUM_LT:
                result = (REG_MULTI &&
                        nfa_re_num_cmp(t->state->val, t->state->c - NFA_LNUM,
!                           (long_u)(reglnum + reg_firstlnum)));
                if (result)
                {
                    add_here = TRUE;
--- 6549,6555 ----
            case NFA_LNUM_LT:
                result = (REG_MULTI &&
                        nfa_re_num_cmp(t->state->val, t->state->c - NFA_LNUM,
!                           (long_u)(reglnum + rex.reg_firstlnum)));
                if (result)
                {
                    add_here = TRUE;
***************
*** 6575,6581 ****
                {
                    int     op = t->state->c - NFA_VCOL;
                    colnr_T col = (colnr_T)(reginput - regline);
!                   win_T   *wp = reg_win == NULL ? curwin : reg_win;
  
                    /* Bail out quickly when there can't be a match, avoid the
                     * overhead of win_linetabsize() on long lines. */
--- 6575,6581 ----
                {
                    int     op = t->state->c - NFA_VCOL;
                    colnr_T col = (colnr_T)(reginput - regline);
!                   win_T   *wp = rex.reg_win == NULL ? curwin : rex.reg_win;
  
                    /* Bail out quickly when there can't be a match, avoid the
                     * overhead of win_linetabsize() on long lines. */
***************
*** 6611,6628 ****
            case NFA_MARK_GT:
            case NFA_MARK_LT:
              {
!               pos_T   *pos = getmark_buf(reg_buf, t->state->val, FALSE);
  
                /* Compare the mark position to the match position. */
                result = (pos != NULL                /* mark doesn't exist */
                        && pos->lnum > 0    /* mark isn't set in reg_buf */
!                       && (pos->lnum == reglnum + reg_firstlnum
                                ? (pos->col == (colnr_T)(reginput - regline)
                                    ? t->state->c == NFA_MARK
                                    : (pos->col < (colnr_T)(reginput - regline)
                                        ? t->state->c == NFA_MARK_GT
                                        : t->state->c == NFA_MARK_LT))
!                               : (pos->lnum < reglnum + reg_firstlnum
                                    ? t->state->c == NFA_MARK_GT
                                    : t->state->c == NFA_MARK_LT)));
                if (result)
--- 6611,6628 ----
            case NFA_MARK_GT:
            case NFA_MARK_LT:
              {
!               pos_T   *pos = getmark_buf(rex.reg_buf, t->state->val, FALSE);
  
                /* Compare the mark position to the match position. */
                result = (pos != NULL                /* mark doesn't exist */
                        && pos->lnum > 0    /* mark isn't set in reg_buf */
!                       && (pos->lnum == reglnum + rex.reg_firstlnum
                                ? (pos->col == (colnr_T)(reginput - regline)
                                    ? t->state->c == NFA_MARK
                                    : (pos->col < (colnr_T)(reginput - regline)
                                        ? t->state->c == NFA_MARK_GT
                                        : t->state->c == NFA_MARK_LT))
!                               : (pos->lnum < reglnum + rex.reg_firstlnum
                                    ? t->state->c == NFA_MARK_GT
                                    : t->state->c == NFA_MARK_LT)));
                if (result)
***************
*** 6634,6643 ****
              }
  
            case NFA_CURSOR:
!               result = (reg_win != NULL
!                       && (reglnum + reg_firstlnum == reg_win->w_cursor.lnum)
                        && ((colnr_T)(reginput - regline)
!                                                  == reg_win->w_cursor.col));
                if (result)
                {
                    add_here = TRUE;
--- 6634,6644 ----
              }
  
            case NFA_CURSOR:
!               result = (rex.reg_win != NULL
!                       && (reglnum + rex.reg_firstlnum
!                                                == rex.reg_win->w_cursor.lnum)
                        && ((colnr_T)(reginput - regline)
!                                               == rex.reg_win->w_cursor.col));
                if (result)
                {
                    add_here = TRUE;
***************
*** 6691,6702 ****
  #endif
                result = (c == curc);
  
!               if (!result && ireg_ic)
                    result = MB_TOLOWER(c) == MB_TOLOWER(curc);
  #ifdef FEAT_MBYTE
!               /* If ireg_icombine is not set only skip over the character
                 * itself.  When it is set skip over composing characters. */
!               if (result && enc_utf8 && !ireg_icombine)
                    clen = utf_ptr2len(reginput);
  #endif
                ADD_STATE_IF_MATCH(t->state);
--- 6692,6703 ----
  #endif
                result = (c == curc);
  
!               if (!result && rex.reg_ic)
                    result = MB_TOLOWER(c) == MB_TOLOWER(curc);
  #ifdef FEAT_MBYTE
!               /* If rex.reg_icombine is not set only skip over the character
                 * itself.  When it is set skip over composing characters. */
!               if (result && enc_utf8 && !rex.reg_icombine)
                    clen = utf_ptr2len(reginput);
  #endif
                ADD_STATE_IF_MATCH(t->state);
***************
*** 6815,6822 ****
                && ((toplevel
                        && reglnum == 0
                        && clen != 0
!                       && (ireg_maxcol == 0
!                           || (colnr_T)(reginput - regline) < ireg_maxcol))
                    || (nfa_endp != NULL
                        && (REG_MULTI
                            ? (reglnum < nfa_endp->se_u.pos.lnum
--- 6816,6823 ----
                && ((toplevel
                        && reglnum == 0
                        && clen != 0
!                       && (rex.reg_maxcol == 0
!                           || (colnr_T)(reginput - regline) < rex.reg_maxcol))
                    || (nfa_endp != NULL
                        && (REG_MULTI
                            ? (reglnum < nfa_endp->se_u.pos.lnum
***************
*** 6856,6863 ****
                        /* Checking if the required start character matches is
                         * cheaper than adding a state that won't match. */
                        c = PTR2CHAR(reginput + clen);
!                       if (c != prog->regstart && (!ireg_ic || MB_TOLOWER(c)
!                                              != MB_TOLOWER(prog->regstart)))
                        {
  #ifdef ENABLE_LOG
                            fprintf(log_fd, "  Skipping start state, regstart 
does not match\n");
--- 6857,6864 ----
                        /* Checking if the required start character matches is
                         * cheaper than adding a state that won't match. */
                        c = PTR2CHAR(reginput + clen);
!                       if (c != prog->regstart && (!rex.reg_ic
!                              || MB_TOLOWER(c) != MB_TOLOWER(prog->regstart)))
                        {
  #ifdef ENABLE_LOG
                            fprintf(log_fd, "  Skipping start state, regstart 
does not match\n");
***************
*** 6997,7036 ****
      {
        for (i = 0; i < subs.norm.in_use; i++)
        {
!           reg_startpos[i].lnum = subs.norm.list.multi[i].start_lnum;
!           reg_startpos[i].col = subs.norm.list.multi[i].start_col;
  
!           reg_endpos[i].lnum = subs.norm.list.multi[i].end_lnum;
!           reg_endpos[i].col = subs.norm.list.multi[i].end_col;
        }
  
!       if (reg_startpos[0].lnum < 0)
        {
!           reg_startpos[0].lnum = 0;
!           reg_startpos[0].col = col;
        }
!       if (reg_endpos[0].lnum < 0)
        {
            /* pattern has a \ze but it didn't match, use current end */
!           reg_endpos[0].lnum = reglnum;
!           reg_endpos[0].col = (int)(reginput - regline);
        }
        else
            /* Use line number of "\ze". */
!           reglnum = reg_endpos[0].lnum;
      }
      else
      {
        for (i = 0; i < subs.norm.in_use; i++)
        {
!           reg_startp[i] = subs.norm.list.line[i].start;
!           reg_endp[i] = subs.norm.list.line[i].end;
        }
  
!       if (reg_startp[0] == NULL)
!           reg_startp[0] = regline + col;
!       if (reg_endp[0] == NULL)
!           reg_endp[0] = reginput;
      }
  
  #ifdef FEAT_SYN_HL
--- 6998,7037 ----
      {
        for (i = 0; i < subs.norm.in_use; i++)
        {
!           rex.reg_startpos[i].lnum = subs.norm.list.multi[i].start_lnum;
!           rex.reg_startpos[i].col = subs.norm.list.multi[i].start_col;
  
!           rex.reg_endpos[i].lnum = subs.norm.list.multi[i].end_lnum;
!           rex.reg_endpos[i].col = subs.norm.list.multi[i].end_col;
        }
  
!       if (rex.reg_startpos[0].lnum < 0)
        {
!           rex.reg_startpos[0].lnum = 0;
!           rex.reg_startpos[0].col = col;
        }
!       if (rex.reg_endpos[0].lnum < 0)
        {
            /* pattern has a \ze but it didn't match, use current end */
!           rex.reg_endpos[0].lnum = reglnum;
!           rex.reg_endpos[0].col = (int)(reginput - regline);
        }
        else
            /* Use line number of "\ze". */
!           reglnum = rex.reg_endpos[0].lnum;
      }
      else
      {
        for (i = 0; i < subs.norm.in_use; i++)
        {
!           rex.reg_startp[i] = subs.norm.list.line[i].start;
!           rex.reg_endp[i] = subs.norm.list.line[i].end;
        }
  
!       if (rex.reg_startp[0] == NULL)
!           rex.reg_startp[0] = regline + col;
!       if (rex.reg_endp[0] == NULL)
!           rex.reg_endp[0] = reginput;
      }
  
  #ifdef FEAT_SYN_HL
***************
*** 7093,7108 ****
  
      if (REG_MULTI)
      {
!       prog = (nfa_regprog_T *)reg_mmatch->regprog;
        line = reg_getline((linenr_T)0);    /* relative to the cursor */
!       reg_startpos = reg_mmatch->startpos;
!       reg_endpos = reg_mmatch->endpos;
      }
      else
      {
!       prog = (nfa_regprog_T *)reg_match->regprog;
!       reg_startp = reg_match->startp;
!       reg_endp = reg_match->endp;
      }
  
      /* Be paranoid... */
--- 7094,7109 ----
  
      if (REG_MULTI)
      {
!       prog = (nfa_regprog_T *)rex.reg_mmatch->regprog;
        line = reg_getline((linenr_T)0);    /* relative to the cursor */
!       rex.reg_startpos = rex.reg_mmatch->startpos;
!       rex.reg_endpos = rex.reg_mmatch->endpos;
      }
      else
      {
!       prog = (nfa_regprog_T *)rex.reg_match->regprog;
!       rex.reg_startp = rex.reg_match->startp;
!       rex.reg_endp = rex.reg_match->endp;
      }
  
      /* Be paranoid... */
***************
*** 7112,7127 ****
        goto theend;
      }
  
!     /* If pattern contains "\c" or "\C": overrule value of ireg_ic */
      if (prog->regflags & RF_ICASE)
!       ireg_ic = TRUE;
      else if (prog->regflags & RF_NOICASE)
!       ireg_ic = FALSE;
  
  #ifdef FEAT_MBYTE
!     /* If pattern contains "\Z" overrule value of ireg_icombine */
      if (prog->regflags & RF_ICOMBINE)
!       ireg_icombine = TRUE;
  #endif
  
      regline = line;
--- 7113,7128 ----
        goto theend;
      }
  
!     /* If pattern contains "\c" or "\C": overrule value of rex.reg_ic */
      if (prog->regflags & RF_ICASE)
!       rex.reg_ic = TRUE;
      else if (prog->regflags & RF_NOICASE)
!       rex.reg_ic = FALSE;
  
  #ifdef FEAT_MBYTE
!     /* If pattern contains "\Z" overrule value of rex.reg_icombine */
      if (prog->regflags & RF_ICOMBINE)
!       rex.reg_icombine = TRUE;
  #endif
  
      regline = line;
***************
*** 7160,7173 ****
         * Nothing else to try. Doesn't handle combining chars well. */
        if (prog->match_text != NULL
  #ifdef FEAT_MBYTE
!                   && !ireg_icombine
  #endif
                )
            return find_match_text(col, prog->regstart, prog->match_text);
      }
  
      /* If the start column is past the maximum column: no need to try. */
!     if (ireg_maxcol > 0 && col >= ireg_maxcol)
        goto theend;
  
      nstate = prog->nstate;
--- 7161,7174 ----
         * Nothing else to try. Doesn't handle combining chars well. */
        if (prog->match_text != NULL
  #ifdef FEAT_MBYTE
!                   && !rex.reg_icombine
  #endif
                )
            return find_match_text(col, prog->regstart, prog->match_text);
      }
  
      /* If the start column is past the maximum column: no need to try. */
!     if (rex.reg_maxcol > 0 && col >= rex.reg_maxcol)
        goto theend;
  
      nstate = prog->nstate;
***************
*** 7326,7342 ****
      colnr_T   col,    /* column to start looking for match */
      int               line_lbr)
  {
!     reg_match = rmp;
!     reg_mmatch = NULL;
!     reg_maxline = 0;
!     reg_line_lbr = line_lbr;
!     reg_buf = curbuf;
!     reg_win = NULL;
!     ireg_ic = rmp->rm_ic;
  #ifdef FEAT_MBYTE
!     ireg_icombine = FALSE;
  #endif
!     ireg_maxcol = 0;
      return nfa_regexec_both(line, col, NULL);
  }
  
--- 7327,7343 ----
      colnr_T   col,    /* column to start looking for match */
      int               line_lbr)
  {
!     rex.reg_match = rmp;
!     rex.reg_mmatch = NULL;
!     rex.reg_maxline = 0;
!     rex.reg_line_lbr = line_lbr;
!     rex.reg_buf = curbuf;
!     rex.reg_win = NULL;
!     rex.reg_ic = rmp->rm_ic;
  #ifdef FEAT_MBYTE
!     rex.reg_icombine = FALSE;
  #endif
!     rex.reg_maxcol = 0;
      return nfa_regexec_both(line, col, NULL);
  }
  
***************
*** 7375,7392 ****
      colnr_T   col,            /* column to start looking for match */
      proftime_T        *tm)            /* timeout limit or NULL */
  {
!     reg_match = NULL;
!     reg_mmatch = rmp;
!     reg_buf = buf;
!     reg_win = win;
!     reg_firstlnum = lnum;
!     reg_maxline = reg_buf->b_ml.ml_line_count - lnum;
!     reg_line_lbr = FALSE;
!     ireg_ic = rmp->rmm_ic;
  #ifdef FEAT_MBYTE
!     ireg_icombine = FALSE;
  #endif
!     ireg_maxcol = rmp->rmm_maxcol;
  
      return nfa_regexec_both(NULL, col, tm);
  }
--- 7376,7393 ----
      colnr_T   col,            /* column to start looking for match */
      proftime_T        *tm)            /* timeout limit or NULL */
  {
!     rex.reg_match = NULL;
!     rex.reg_mmatch = rmp;
!     rex.reg_buf = buf;
!     rex.reg_win = win;
!     rex.reg_firstlnum = lnum;
!     rex.reg_maxline = rex.reg_buf->b_ml.ml_line_count - lnum;
!     rex.reg_line_lbr = FALSE;
!     rex.reg_ic = rmp->rmm_ic;
  #ifdef FEAT_MBYTE
!     rex.reg_icombine = FALSE;
  #endif
!     rex.reg_maxcol = rmp->rmm_maxcol;
  
      return nfa_regexec_both(NULL, col, tm);
  }
*** ../vim-8.0.0019/src/testdir/test_expr.vim   2016-09-14 22:16:09.863803610 
+0200
--- src/testdir/test_expr.vim   2016-10-02 16:29:45.285611327 +0200
***************
*** 405,413 ****
        \ {-> submatch(2) . submatch(3) . submatch(1)}, ''))
  
    func Recurse()
!     return substitute('yyy', 'y*', {-> g:val}, '')
    endfunc
!   call assert_equal('--', substitute('xxx', 'x*', {-> '-' . Recurse() . '-'}, 
''))
  endfunc
  
  func Test_invalid_submatch()
--- 405,414 ----
        \ {-> submatch(2) . submatch(3) . submatch(1)}, ''))
  
    func Recurse()
!     return substitute('yyy', 'y\(.\)y', {-> submatch(1)}, '')
    endfunc
!   " recursive call works
!   call assert_equal('-y-x-', substitute('xxx', 'x\(.\)x', {-> '-' . Recurse() 
. '-' . submatch(1) . '-'}, ''))
  endfunc
  
  func Test_invalid_submatch()
*** ../vim-8.0.0019/runtime/doc/eval.txt        2016-09-27 21:28:52.905342034 
+0200
--- runtime/doc/eval.txt        2016-10-02 16:39:09.841721025 +0200
***************
*** 7379,7384 ****
--- 7390,7398 ----
                |substitute()| this list will always contain one or zero
                items, since there are no real line breaks.
  
+               When substitute() is used recursively only the submatches in
+               the current (deepest) call can be obtained.
+ 
                Example: >
                        :s/\d\+/\=submatch(0) + 1/
  <             This finds the first number in the line and adds one to it.
*** ../vim-8.0.0019/runtime/doc/change.txt      2016-09-12 12:45:25.000000000 
+0200
--- runtime/doc/change.txt      2016-10-02 16:37:35.170373987 +0200
***************
*** 1,4 ****
! *change.txt*    For Vim version 8.0.  Last change: 2016 Sep 11
  
  
                  VIM REFERENCE MANUAL    by Bram Moolenaar
--- 1,4 ----
! *change.txt*    For Vim version 8.0.  Last change: 2016 Oct 02
  
  
                  VIM REFERENCE MANUAL    by Bram Moolenaar
***************
*** 913,920 ****
  Substitute with an expression                 *sub-replace-expression*
                                                *sub-replace-\=* *s/\=*
  When the substitute string starts with "\=" the remainder is interpreted as an
! expression.  This does not work recursively: a |substitute()| function inside
! the expression cannot use "\=" for the substitute string.
  
  The special meaning for characters as mentioned at |sub-replace-special| does
  not apply except for "<CR>".  A <NL> character is used as a line break, you
--- 913,919 ----
  Substitute with an expression                 *sub-replace-expression*
                                                *sub-replace-\=* *s/\=*
  When the substitute string starts with "\=" the remainder is interpreted as an
! expression.
  
  The special meaning for characters as mentioned at |sub-replace-special| does
  not apply except for "<CR>".  A <NL> character is used as a line break, you
*** ../vim-8.0.0019/src/version.c       2016-09-29 20:54:42.407110721 +0200
--- src/version.c       2016-10-02 15:27:58.639175908 +0200
***************
*** 766,767 ****
--- 766,769 ----
  {   /* Add new patch number below this line */
+ /**/
+     20,
  /**/

-- 
    With sufficient thrust, pigs fly just fine.
                   -- RFC 1925

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui