Loading ...
Sorry, an error occurred while loading the content.

Patch 7.3.10

Expand Messages
  • Bram Moolenaar
    Patch 7.3.1090 Problem: New regexp engine does not support z1 .. z9 and z(. Solution: Implement the syntax submatches. Files: src/regexp.h,
    Message 1 of 8 , Jun 1, 2013
    • 0 Attachment
      Patch 7.3.1090
      Problem: New regexp engine does not support \z1 .. \z9 and \z(.
      Solution: Implement the syntax submatches.
      Files: src/regexp.h, src/regexp_nfa.c


      *** ../vim-7.3.1089/src/regexp.h 2013-05-30 17:05:34.000000000 +0200
      --- src/regexp.h 2013-06-01 22:18:07.000000000 +0200
      ***************
      *** 55,61 ****
      --- 55,63 ----
      char_u reganch;
      char_u *regmust;
      int regmlen;
      + #ifdef FEAT_SYN_HL
      char_u reghasz;
      + #endif
      char_u program[1]; /* actually longer.. */
      } bt_regprog_T;

      ***************
      *** 88,93 ****
      --- 90,98 ----
      nfa_state_T *start;
      int has_zend; /* pattern contains \ze */
      int has_backref; /* pattern contains \1 .. \9 */
      + #ifdef FEAT_SYN_HL
      + int reghasz;
      + #endif
      int nsubexp; /* number of () */
      int nstate;
      nfa_state_T state[0]; /* actually longer.. */
      *** ../vim-7.3.1089/src/regexp_nfa.c 2013-06-01 19:54:39.000000000 +0200
      --- src/regexp_nfa.c 2013-06-01 22:54:08.000000000 +0200
      ***************
      *** 78,90 ****
      NFA_BACKREF7, /* \7 */
      NFA_BACKREF8, /* \8 */
      NFA_BACKREF9, /* \9 */
      NFA_SKIP, /* Skip characters */

      NFA_MOPEN,
      ! NFA_MCLOSE = NFA_MOPEN + NSUBEXP,

      /* NFA_FIRST_NL */
      ! NFA_ANY = NFA_MCLOSE + NSUBEXP, /* Match any one character. */
      NFA_ANYOF, /* Match any character in this string. */
      NFA_ANYBUT, /* Match any character not in this string. */
      NFA_IDENT, /* Match identifier char */
      --- 78,144 ----
      NFA_BACKREF7, /* \7 */
      NFA_BACKREF8, /* \8 */
      NFA_BACKREF9, /* \9 */
      + #ifdef FEAT_SYN_HL
      + NFA_ZREF1, /* \z1 */
      + NFA_ZREF2, /* \z2 */
      + NFA_ZREF3, /* \z3 */
      + NFA_ZREF4, /* \z4 */
      + NFA_ZREF5, /* \z5 */
      + NFA_ZREF6, /* \z6 */
      + NFA_ZREF7, /* \z7 */
      + NFA_ZREF8, /* \z8 */
      + NFA_ZREF9, /* \z9 */
      + #endif
      NFA_SKIP, /* Skip characters */

      NFA_MOPEN,
      ! NFA_MOPEN1,
      ! NFA_MOPEN2,
      ! NFA_MOPEN3,
      ! NFA_MOPEN4,
      ! NFA_MOPEN5,
      ! NFA_MOPEN6,
      ! NFA_MOPEN7,
      ! NFA_MOPEN8,
      ! NFA_MOPEN9,
      !
      ! NFA_MCLOSE,
      ! NFA_MCLOSE1,
      ! NFA_MCLOSE2,
      ! NFA_MCLOSE3,
      ! NFA_MCLOSE4,
      ! NFA_MCLOSE5,
      ! NFA_MCLOSE6,
      ! NFA_MCLOSE7,
      ! NFA_MCLOSE8,
      ! NFA_MCLOSE9,
      !
      ! #ifdef FEAT_SYN_HL
      ! NFA_ZOPEN,
      ! NFA_ZOPEN1,
      ! NFA_ZOPEN2,
      ! NFA_ZOPEN3,
      ! NFA_ZOPEN4,
      ! NFA_ZOPEN5,
      ! NFA_ZOPEN6,
      ! NFA_ZOPEN7,
      ! NFA_ZOPEN8,
      ! NFA_ZOPEN9,
      !
      ! NFA_ZCLOSE,
      ! NFA_ZCLOSE1,
      ! NFA_ZCLOSE2,
      ! NFA_ZCLOSE3,
      ! NFA_ZCLOSE4,
      ! NFA_ZCLOSE5,
      ! NFA_ZCLOSE6,
      ! NFA_ZCLOSE7,
      ! NFA_ZCLOSE8,
      ! NFA_ZCLOSE9,
      ! #endif

      /* NFA_FIRST_NL */
      ! NFA_ANY, /* Match any one character. */
      NFA_ANYOF, /* Match any character in this string. */
      NFA_ANYBUT, /* Match any character not in this string. */
      NFA_IDENT, /* Match identifier char */
      ***************
      *** 221,227 ****
      static void nfa_save_listids __ARGS((nfa_state_T *start, int *list));
      static void nfa_restore_listids __ARGS((nfa_state_T *start, int *list));
      static int nfa_re_num_cmp __ARGS((long_u val, int op, long_u pos));
      ! static long nfa_regtry __ARGS((nfa_state_T *start, colnr_T col));
      static long nfa_regexec_both __ARGS((char_u *line, colnr_T col));
      static regprog_T *nfa_regcomp __ARGS((char_u *expr, int re_flags));
      static int nfa_regexec __ARGS((regmatch_T *rmp, char_u *line, colnr_T col));
      --- 275,281 ----
      static void nfa_save_listids __ARGS((nfa_state_T *start, int *list));
      static void nfa_restore_listids __ARGS((nfa_state_T *start, int *list));
      static int nfa_re_num_cmp __ARGS((long_u val, int op, long_u pos));
      ! static long nfa_regtry __ARGS((nfa_regprog_T *prog, colnr_T col));
      static long nfa_regexec_both __ARGS((char_u *line, colnr_T col));
      static regprog_T *nfa_regcomp __ARGS((char_u *expr, int re_flags));
      static int nfa_regexec __ARGS((regmatch_T *rmp, char_u *line, colnr_T col));
      ***************
      *** 267,272 ****
      --- 321,327 ----
      nfa_has_zend = FALSE;
      nfa_has_backref = FALSE;

      + /* shared with BT engine */
      regcomp_start(expr, re_flags);

      return OK;
      ***************
      *** 799,804 ****
      --- 854,860 ----
      EMIT(NFA_ZEND);
      nfa_has_zend = TRUE;
      break;
      + #ifdef FEAT_SYN_HL
      case '1':
      case '2':
      case '3':
      ***************
      *** 808,816 ****
      case '7':
      case '8':
      case '9':
      case '(':
      ! /* TODO: \z1...\z9 and \z( not yet supported */
      ! return FAIL;
      default:
      syntax_error = TRUE;
      EMSGN(_("E867: (NFA) Unknown operator '\\z%c'"),
      --- 864,882 ----
      case '7':
      case '8':
      case '9':
      + /* \z1...\z9 */
      + EMIT(NFA_ZREF1 + (no_Magic(c) - '1'));
      + /* No need to set nfa_has_backref, the sub-matches don't
      + * change when \z1 .. \z9 maches or not. */
      + re_has_z = REX_USE;
      + break;
      case '(':
      ! /* \z( */
      ! if (nfa_reg(REG_ZPAREN) == FAIL)
      ! return FAIL; /* cascaded error */
      ! re_has_z = REX_SET;
      ! break;
      ! #endif
      default:
      syntax_error = TRUE;
      EMSGN(_("E867: (NFA) Unknown operator '\\z%c'"),
      ***************
      *** 1651,1658 ****
      {
      int parno = 0;

      - #ifdef FEAT_SYN_HL
      - #endif
      if (paren == REG_PAREN)
      {
      if (regnpar >= NSUBEXP) /* Too many `(' */
      --- 1717,1722 ----
      ***************
      *** 1662,1667 ****
      --- 1726,1743 ----
      }
      parno = regnpar++;
      }
      + #ifdef FEAT_SYN_HL
      + else if (paren == REG_ZPAREN)
      + {
      + /* Make a ZOPEN node. */
      + if (regnzpar >= NSUBEXP)
      + {
      + syntax_error = TRUE;
      + EMSG_RET_FAIL(_("E879: (NFA regexp) Too many \\z("));
      + }
      + parno = regnzpar++;
      + }
      + #endif

      if (nfa_regbranch() == FAIL)
      return FAIL; /* cascaded error */
      ***************
      *** 1700,1705 ****
      --- 1776,1785 ----
      had_endbrace[parno] = TRUE; /* have seen the close paren */
      EMIT(NFA_MOPEN + parno);
      }
      + #ifdef FEAT_SYN_HL
      + else if (paren == REG_ZPAREN)
      + EMIT(NFA_ZOPEN + parno);
      + #endif

      return OK;
      }
      ***************
      *** 1738,1743 ****
      --- 1818,1834 ----
      case NFA_BACKREF7: STRCPY(code, "NFA_BACKREF7"); break;
      case NFA_BACKREF8: STRCPY(code, "NFA_BACKREF8"); break;
      case NFA_BACKREF9: STRCPY(code, "NFA_BACKREF9"); break;
      + #ifdef FEAT_SYN_HL
      + case NFA_ZREF1: STRCPY(code, "NFA_ZREF1"); break;
      + case NFA_ZREF2: STRCPY(code, "NFA_ZREF2"); break;
      + case NFA_ZREF3: STRCPY(code, "NFA_ZREF3"); break;
      + case NFA_ZREF4: STRCPY(code, "NFA_ZREF4"); break;
      + case NFA_ZREF5: STRCPY(code, "NFA_ZREF5"); break;
      + case NFA_ZREF6: STRCPY(code, "NFA_ZREF6"); break;
      + case NFA_ZREF7: STRCPY(code, "NFA_ZREF7"); break;
      + case NFA_ZREF8: STRCPY(code, "NFA_ZREF8"); break;
      + case NFA_ZREF9: STRCPY(code, "NFA_ZREF9"); break;
      + #endif
      case NFA_SKIP: STRCPY(code, "NFA_SKIP"); break;

      case NFA_PREV_ATOM_NO_WIDTH:
      ***************
      *** 1758,1789 ****
      case NFA_COMPOSING: STRCPY(code, "NFA_COMPOSING"); break;
      case NFA_END_COMPOSING: STRCPY(code, "NFA_END_COMPOSING"); break;

      ! case NFA_MOPEN + 0:
      ! case NFA_MOPEN + 1:
      ! case NFA_MOPEN + 2:
      ! case NFA_MOPEN + 3:
      ! case NFA_MOPEN + 4:
      ! case NFA_MOPEN + 5:
      ! case NFA_MOPEN + 6:
      ! case NFA_MOPEN + 7:
      ! case NFA_MOPEN + 8:
      ! case NFA_MOPEN + 9:
      STRCPY(code, "NFA_MOPEN(x)");
      code[10] = c - NFA_MOPEN + '0';
      break;
      ! case NFA_MCLOSE + 0:
      ! case NFA_MCLOSE + 1:
      ! case NFA_MCLOSE + 2:
      ! case NFA_MCLOSE + 3:
      ! case NFA_MCLOSE + 4:
      ! case NFA_MCLOSE + 5:
      ! case NFA_MCLOSE + 6:
      ! case NFA_MCLOSE + 7:
      ! case NFA_MCLOSE + 8:
      ! case NFA_MCLOSE + 9:
      STRCPY(code, "NFA_MCLOSE(x)");
      code[11] = c - NFA_MCLOSE + '0';
      break;
      case NFA_EOL: STRCPY(code, "NFA_EOL "); break;
      case NFA_BOL: STRCPY(code, "NFA_BOL "); break;
      case NFA_EOW: STRCPY(code, "NFA_EOW "); break;
      --- 1849,1908 ----
      case NFA_COMPOSING: STRCPY(code, "NFA_COMPOSING"); break;
      case NFA_END_COMPOSING: STRCPY(code, "NFA_END_COMPOSING"); break;

      ! case NFA_MOPEN:
      ! case NFA_MOPEN1:
      ! case NFA_MOPEN2:
      ! case NFA_MOPEN3:
      ! case NFA_MOPEN4:
      ! case NFA_MOPEN5:
      ! case NFA_MOPEN6:
      ! case NFA_MOPEN7:
      ! case NFA_MOPEN8:
      ! case NFA_MOPEN9:
      STRCPY(code, "NFA_MOPEN(x)");
      code[10] = c - NFA_MOPEN + '0';
      break;
      ! case NFA_MCLOSE:
      ! case NFA_MCLOSE1:
      ! case NFA_MCLOSE2:
      ! case NFA_MCLOSE3:
      ! case NFA_MCLOSE4:
      ! case NFA_MCLOSE5:
      ! case NFA_MCLOSE6:
      ! case NFA_MCLOSE7:
      ! case NFA_MCLOSE8:
      ! case NFA_MCLOSE9:
      STRCPY(code, "NFA_MCLOSE(x)");
      code[11] = c - NFA_MCLOSE + '0';
      break;
      + #ifdef FEAT_SYN_HL
      + case NFA_ZOPEN:
      + case NFA_ZOPEN1:
      + case NFA_ZOPEN2:
      + case NFA_ZOPEN3:
      + case NFA_ZOPEN4:
      + case NFA_ZOPEN5:
      + case NFA_ZOPEN6:
      + case NFA_ZOPEN7:
      + case NFA_ZOPEN8:
      + case NFA_ZOPEN9:
      + STRCPY(code, "NFA_ZOPEN(x)");
      + code[10] = c - NFA_ZOPEN + '0';
      + break;
      + case NFA_ZCLOSE:
      + case NFA_ZCLOSE1:
      + case NFA_ZCLOSE2:
      + case NFA_ZCLOSE3:
      + case NFA_ZCLOSE4:
      + case NFA_ZCLOSE5:
      + case NFA_ZCLOSE6:
      + case NFA_ZCLOSE7:
      + case NFA_ZCLOSE8:
      + case NFA_ZCLOSE9:
      + STRCPY(code, "NFA_ZCLOSE(x)");
      + code[11] = c - NFA_ZCLOSE + '0';
      + break;
      + #endif
      case NFA_EOL: STRCPY(code, "NFA_EOL "); break;
      case NFA_BOL: STRCPY(code, "NFA_BOL "); break;
      case NFA_EOW: STRCPY(code, "NFA_EOW "); break;
      ***************
      *** 2437,2453 ****
      /* FALLTHROUGH */
      #endif

      ! case NFA_MOPEN + 0: /* Submatch */
      ! case NFA_MOPEN + 1:
      ! case NFA_MOPEN + 2:
      ! case NFA_MOPEN + 3:
      ! case NFA_MOPEN + 4:
      ! case NFA_MOPEN + 5:
      ! case NFA_MOPEN + 6:
      ! case NFA_MOPEN + 7:
      ! case NFA_MOPEN + 8:
      ! case NFA_MOPEN + 9:
      ! case NFA_NOPEN: /* \%( "Invisible Submatch" */
      if (nfa_calc_size == TRUE)
      {
      nstate += 2;
      --- 2556,2584 ----
      /* FALLTHROUGH */
      #endif

      ! case NFA_MOPEN: /* \( \) Submatch */
      ! case NFA_MOPEN1:
      ! case NFA_MOPEN2:
      ! case NFA_MOPEN3:
      ! case NFA_MOPEN4:
      ! case NFA_MOPEN5:
      ! case NFA_MOPEN6:
      ! case NFA_MOPEN7:
      ! case NFA_MOPEN8:
      ! case NFA_MOPEN9:
      ! #ifdef FEAT_SYN_HL
      ! case NFA_ZOPEN: /* \z( \) Submatch */
      ! case NFA_ZOPEN1:
      ! case NFA_ZOPEN2:
      ! case NFA_ZOPEN3:
      ! case NFA_ZOPEN4:
      ! case NFA_ZOPEN5:
      ! case NFA_ZOPEN6:
      ! case NFA_ZOPEN7:
      ! case NFA_ZOPEN8:
      ! case NFA_ZOPEN9:
      ! #endif
      ! case NFA_NOPEN: /* \%( \) "Invisible Submatch" */
      if (nfa_calc_size == TRUE)
      {
      nstate += 2;
      ***************
      *** 2457,2472 ****
      mopen = *p;
      switch (*p)
      {
      ! case NFA_NOPEN:
      ! mclose = NFA_NCLOSE;
      ! break;
      #ifdef FEAT_MBYTE
      ! case NFA_COMPOSING:
      ! mclose = NFA_END_COMPOSING;
      ! break;
      #endif
      default:
      ! /* NFA_MOPEN(0) ... NFA_MOPEN(9) */
      mclose = *p + NSUBEXP;
      break;
      }
      --- 2588,2611 ----
      mopen = *p;
      switch (*p)
      {
      ! case NFA_NOPEN: mclose = NFA_NCLOSE; break;
      ! #ifdef FEAT_SYN_HL
      ! case NFA_ZOPEN: mclose = NFA_ZCLOSE; break;
      ! case NFA_ZOPEN1: mclose = NFA_ZCLOSE1; break;
      ! case NFA_ZOPEN2: mclose = NFA_ZCLOSE2; break;
      ! case NFA_ZOPEN3: mclose = NFA_ZCLOSE3; break;
      ! case NFA_ZOPEN4: mclose = NFA_ZCLOSE4; break;
      ! case NFA_ZOPEN5: mclose = NFA_ZCLOSE5; break;
      ! case NFA_ZOPEN6: mclose = NFA_ZCLOSE6; break;
      ! case NFA_ZOPEN7: mclose = NFA_ZCLOSE7; break;
      ! case NFA_ZOPEN8: mclose = NFA_ZCLOSE8; break;
      ! case NFA_ZOPEN9: mclose = NFA_ZCLOSE9; break;
      ! #endif
      #ifdef FEAT_MBYTE
      ! case NFA_COMPOSING: mclose = NFA_END_COMPOSING; break;
      #endif
      default:
      ! /* NFA_MOPEN, NFA_MOPEN1 .. NFA_MOPEN9 */
      mclose = *p + NSUBEXP;
      break;
      }
      ***************
      *** 2518,2523 ****
      --- 2657,2673 ----
      case NFA_BACKREF7:
      case NFA_BACKREF8:
      case NFA_BACKREF9:
      + #ifdef FEAT_SYN_HL
      + case NFA_ZREF1:
      + case NFA_ZREF2:
      + case NFA_ZREF3:
      + case NFA_ZREF4:
      + case NFA_ZREF5:
      + case NFA_ZREF6:
      + case NFA_ZREF7:
      + case NFA_ZREF8:
      + case NFA_ZREF9:
      + #endif
      if (nfa_calc_size == TRUE)
      {
      nstate += 2;
      ***************
      *** 2630,2641 ****
      } list;
      } regsub_T;

      /* nfa_thread_T contains execution information of a NFA state */
      typedef struct
      {
      nfa_state_T *state;
      int count;
      ! regsub_T sub; /* submatch info, only party used */
      } nfa_thread_T;

      /* nfa_list_T contains the alternative NFA execution states. */
      --- 2780,2799 ----
      } list;
      } regsub_T;

      + typedef struct
      + {
      + regsub_T norm; /* \( .. \) matches */
      + #ifdef FEAT_SYN_HL
      + regsub_T synt; /* \z( .. \) matches */
      + #endif
      + } regsubs_T;
      +
      /* nfa_thread_T contains execution information of a NFA state */
      typedef struct
      {
      nfa_state_T *state;
      int count;
      ! regsubs_T subs; /* submatch info, only party used */
      } nfa_thread_T;

      /* nfa_list_T contains the alternative NFA execution states. */
      ***************
      *** 2648,2653 ****
      --- 2806,2824 ----
      } nfa_list_T;

      #ifdef ENABLE_LOG
      + static void log_subsexpr __ARGS((regsubs_T *subs));
      + static void log_subexpr __ARGS((regsub_T *sub));
      +
      + static void
      + log_subsexpr(subs)
      + regsubs_T *subs;
      + {
      + log_subexpr(&subs->norm);
      + # ifdef FEAT_SYN_HL
      + log_subexpr(&subs->synt);
      + # endif
      + }
      +
      static void
      log_subexpr(sub)
      regsub_T *sub;
      ***************
      *** 2674,2682 ****
      /* Used during execution: whether a match has been found. */
      static int nfa_match;

      static int sub_equal __ARGS((regsub_T *sub1, regsub_T *sub2));
      ! static void addstate __ARGS((nfa_list_T *l, nfa_state_T *state, regsub_T *sub, int off));
      ! static void addstate_here __ARGS((nfa_list_T *l, nfa_state_T *state, regsub_T *sub, int *ip));

      /*
      * Return TRUE if "sub1" and "sub2" have the same positions.
      --- 2845,2916 ----
      /* Used during execution: whether a match has been found. */
      static int nfa_match;

      + static void clear_sub __ARGS((regsub_T *sub));
      + static void copy_sub __ARGS((regsub_T *to, regsub_T *from));
      + static void copy_sub_off __ARGS((regsub_T *to, regsub_T *from));
      static int sub_equal __ARGS((regsub_T *sub1, regsub_T *sub2));
      ! static void addstate __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, int off));
      ! static void addstate_here __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, int *ip));
      !
      ! static void
      ! clear_sub(sub)
      ! regsub_T *sub;
      ! {
      ! if (REG_MULTI)
      ! /* Use 0xff to set lnum to -1 */
      ! vim_memset(sub->list.multi, 0xff,
      ! sizeof(struct multipos) * nfa_nsubexpr);
      ! else
      ! vim_memset(sub->list.line, 0, sizeof(struct linepos) * nfa_nsubexpr);
      ! sub->in_use = 0;
      ! }
      !
      ! /*
      ! * Copy the submatches from "from" to "to".
      ! */
      ! static void
      ! copy_sub(to, from)
      ! regsub_T *to;
      ! regsub_T *from;
      ! {
      ! to->in_use = from->in_use;
      ! if (from->in_use > 0)
      ! {
      ! /* Copy the match start and end positions. */
      ! if (REG_MULTI)
      ! mch_memmove(&to->list.multi[0],
      ! &from->list.multi[0],
      ! sizeof(struct multipos) * from->in_use);
      ! else
      ! mch_memmove(&to->list.line[0],
      ! &from->list.line[0],
      ! sizeof(struct linepos) * from->in_use);
      ! }
      ! }
      !
      ! /*
      ! * Like copy_sub() but exclude the main match.
      ! */
      ! static void
      ! copy_sub_off(to, from)
      ! regsub_T *to;
      ! regsub_T *from;
      ! {
      ! if (to->in_use < from->in_use)
      ! to->in_use = from->in_use;
      ! if (from->in_use > 1)
      ! {
      ! /* Copy the match start and end positions. */
      ! if (REG_MULTI)
      ! mch_memmove(&to->list.multi[1],
      ! &from->list.multi[1],
      ! sizeof(struct multipos) * (from->in_use - 1));
      ! else
      ! mch_memmove(&to->list.line[1],
      ! &from->list.line[1],
      ! sizeof(struct linepos) * (from->in_use - 1));
      ! }
      ! }

      /*
      * Return TRUE if "sub1" and "sub2" have the same positions.
      ***************
      *** 2761,2770 ****
      }

      static void
      ! addstate(l, state, sub, off)
      nfa_list_T *l; /* runtime state list */
      nfa_state_T *state; /* state to update */
      ! regsub_T *sub; /* pointers to subexpressions */
      int off; /* byte offset, when -1 go to next line */
      {
      int subidx;
      --- 2995,3004 ----
      }

      static void
      ! addstate(l, state, subs, off)
      nfa_list_T *l; /* runtime state list */
      nfa_state_T *state; /* state to update */
      ! regsubs_T *subs; /* pointers to subexpressions */
      int off; /* byte offset, when -1 go to next line */
      {
      int subidx;
      ***************
      *** 2773,2778 ****
      --- 3007,3013 ----
      int save_in_use;
      char_u *save_ptr;
      int i;
      + regsub_T *sub;
      #ifdef ENABLE_LOG
      int did_print = FALSE;
      #endif
      ***************
      *** 2787,2815 ****
      case NFA_NOPEN:
      case NFA_NCLOSE:
      case NFA_MCLOSE:
      ! case NFA_MCLOSE + 1:
      ! case NFA_MCLOSE + 2:
      ! case NFA_MCLOSE + 3:
      ! case NFA_MCLOSE + 4:
      ! case NFA_MCLOSE + 5:
      ! case NFA_MCLOSE + 6:
      ! case NFA_MCLOSE + 7:
      ! case NFA_MCLOSE + 8:
      ! case NFA_MCLOSE + 9:
      /* These nodes are not added themselves but their "out" and/or
      * "out1" may be added below. */
      break;

      case NFA_MOPEN:
      ! case NFA_MOPEN + 1:
      ! case NFA_MOPEN + 2:
      ! case NFA_MOPEN + 3:
      ! case NFA_MOPEN + 4:
      ! case NFA_MOPEN + 5:
      ! case NFA_MOPEN + 6:
      ! case NFA_MOPEN + 7:
      ! case NFA_MOPEN + 8:
      ! case NFA_MOPEN + 9:
      /* These nodes do not need to be added, but we need to bail out
      * when it was tried to be added to this list before. */
      if (state->lastlist == l->id)
      --- 3022,3074 ----
      case NFA_NOPEN:
      case NFA_NCLOSE:
      case NFA_MCLOSE:
      ! case NFA_MCLOSE1:
      ! case NFA_MCLOSE2:
      ! case NFA_MCLOSE3:
      ! case NFA_MCLOSE4:
      ! case NFA_MCLOSE5:
      ! case NFA_MCLOSE6:
      ! case NFA_MCLOSE7:
      ! case NFA_MCLOSE8:
      ! case NFA_MCLOSE9:
      ! #ifdef FEAT_SYN_HL
      ! case NFA_ZCLOSE:
      ! case NFA_ZCLOSE1:
      ! case NFA_ZCLOSE2:
      ! case NFA_ZCLOSE3:
      ! case NFA_ZCLOSE4:
      ! case NFA_ZCLOSE5:
      ! case NFA_ZCLOSE6:
      ! case NFA_ZCLOSE7:
      ! case NFA_ZCLOSE8:
      ! case NFA_ZCLOSE9:
      ! #endif
      /* These nodes are not added themselves but their "out" and/or
      * "out1" may be added below. */
      break;

      case NFA_MOPEN:
      ! case NFA_MOPEN1:
      ! case NFA_MOPEN2:
      ! case NFA_MOPEN3:
      ! case NFA_MOPEN4:
      ! case NFA_MOPEN5:
      ! case NFA_MOPEN6:
      ! case NFA_MOPEN7:
      ! case NFA_MOPEN8:
      ! case NFA_MOPEN9:
      ! #ifdef FEAT_SYN_HL
      ! case NFA_ZOPEN:
      ! case NFA_ZOPEN1:
      ! case NFA_ZOPEN2:
      ! case NFA_ZOPEN3:
      ! case NFA_ZOPEN4:
      ! case NFA_ZOPEN5:
      ! case NFA_ZOPEN6:
      ! case NFA_ZOPEN7:
      ! case NFA_ZOPEN8:
      ! case NFA_ZOPEN9:
      ! #endif
      /* These nodes do not need to be added, but we need to bail out
      * when it was tried to be added to this list before. */
      if (state->lastlist == l->id)
      ***************
      *** 2839,2845 ****
      {
      thread = &l->t[i];
      if (thread->state->id == state->id
      ! && sub_equal(&thread->sub, sub))
      goto skip_add;
      }
      }
      --- 3098,3108 ----
      {
      thread = &l->t[i];
      if (thread->state->id == state->id
      ! && sub_equal(&thread->subs.norm, &subs->norm)
      ! #ifdef FEAT_SYN_HL
      ! && sub_equal(&thread->subs.synt, &subs->synt)
      ! #endif
      ! )
      goto skip_add;
      }
      }
      ***************
      *** 2858,2876 ****
      state->lastlist = l->id;
      thread = &l->t[l->n++];
      thread->state = state;
      ! thread->sub.in_use = sub->in_use;
      ! if (sub->in_use > 0)
      ! {
      ! /* Copy the match start and end positions. */
      ! if (REG_MULTI)
      ! mch_memmove(&thread->sub.list.multi[0],
      ! &sub->list.multi[0],
      ! sizeof(struct multipos) * sub->in_use);
      ! else
      ! mch_memmove(&thread->sub.list.line[0],
      ! &sub->list.line[0],
      ! sizeof(struct linepos) * sub->in_use);
      ! }
      #ifdef ENABLE_LOG
      {
      int col;
      --- 3121,3130 ----
      state->lastlist = l->id;
      thread = &l->t[l->n++];
      thread->state = state;
      ! copy_sub(&thread->subs.norm, &subs->norm);
      ! #ifdef FEAT_SYN_HL
      ! copy_sub(&thread->subs.synt, &subs->synt);
      ! #endif
      #ifdef ENABLE_LOG
      {
      int col;
      ***************
      *** 2912,2959 ****
      break;

      case NFA_SPLIT:
      ! addstate(l, state->out, sub, off);
      ! addstate(l, state->out1, sub, off);
      break;

      - #if 0
      - case NFA_END_NEG_RANGE:
      - /* Nothing to handle here. nfa_regmatch() will take care of it */
      - break;
      -
      - case NFA_NOT:
      - EMSG(_("E999: (NFA regexp internal error) Should not process NOT node !"));
      - #ifdef ENABLE_LOG
      - fprintf(f, "\n\n>>> E999: Added state NFA_NOT to a list ... Something went wrong ! Why wasn't it processed already? \n\n");
      - #endif
      - break;
      -
      - case NFA_COMPOSING:
      - /* nfa_regmatch() will match all the bytes of this composing char. */
      - break;
      - #endif
      -
      case NFA_SKIP_CHAR:
      case NFA_NOPEN:
      case NFA_NCLOSE:
      ! addstate(l, state->out, sub, off);
      break;

      ! case NFA_MOPEN + 0:
      ! case NFA_MOPEN + 1:
      ! case NFA_MOPEN + 2:
      ! case NFA_MOPEN + 3:
      ! case NFA_MOPEN + 4:
      ! case NFA_MOPEN + 5:
      ! case NFA_MOPEN + 6:
      ! case NFA_MOPEN + 7:
      ! case NFA_MOPEN + 8:
      ! case NFA_MOPEN + 9:
      case NFA_ZSTART:
      if (state->c == NFA_ZSTART)
      subidx = 0;
      else
      subidx = state->c - NFA_MOPEN;

      /* Set the position (with "off") in the subexpression. Save and
      * restore it when it was in use. Otherwise fill any gap. */
      --- 3166,3222 ----
      break;

      case NFA_SPLIT:
      ! /* order matters here */
      ! addstate(l, state->out, subs, off);
      ! addstate(l, state->out1, subs, off);
      break;

      case NFA_SKIP_CHAR:
      case NFA_NOPEN:
      case NFA_NCLOSE:
      ! addstate(l, state->out, subs, off);
      break;

      ! case NFA_MOPEN:
      ! case NFA_MOPEN1:
      ! case NFA_MOPEN2:
      ! case NFA_MOPEN3:
      ! case NFA_MOPEN4:
      ! case NFA_MOPEN5:
      ! case NFA_MOPEN6:
      ! case NFA_MOPEN7:
      ! case NFA_MOPEN8:
      ! case NFA_MOPEN9:
      ! #ifdef FEAT_SYN_HL
      ! case NFA_ZOPEN:
      ! case NFA_ZOPEN1:
      ! case NFA_ZOPEN2:
      ! case NFA_ZOPEN3:
      ! case NFA_ZOPEN4:
      ! case NFA_ZOPEN5:
      ! case NFA_ZOPEN6:
      ! case NFA_ZOPEN7:
      ! case NFA_ZOPEN8:
      ! case NFA_ZOPEN9:
      ! #endif
      case NFA_ZSTART:
      if (state->c == NFA_ZSTART)
      + {
      subidx = 0;
      + sub = &subs->norm;
      + }
      + #ifdef FEAT_SYN_HL
      + else if (state->c >= NFA_ZOPEN)
      + {
      + subidx = state->c - NFA_ZOPEN;
      + sub = &subs->synt;
      + }
      + #endif
      else
      + {
      subidx = state->c - NFA_MOPEN;
      + sub = &subs->norm;
      + }

      /* Set the position (with "off") in the subexpression. Save and
      * restore it when it was in use. Otherwise fill any gap. */
      ***************
      *** 3007,3013 ****
      sub->list.line[subidx].start = reginput + off;
      }

      ! addstate(l, state->out, sub, off);

      if (save_in_use == -1)
      {
      --- 3270,3276 ----
      sub->list.line[subidx].start = reginput + off;
      }

      ! addstate(l, state->out, subs, off);

      if (save_in_use == -1)
      {
      ***************
      *** 3020,3047 ****
      sub->in_use = save_in_use;
      break;

      ! case NFA_MCLOSE + 0:
      if (nfa_has_zend)
      {
      /* Do not overwrite the position set by \ze. If no \ze
      * encountered end will be set in nfa_regtry(). */
      ! addstate(l, state->out, sub, off);
      break;
      }
      ! case NFA_MCLOSE + 1:
      ! case NFA_MCLOSE + 2:
      ! case NFA_MCLOSE + 3:
      ! case NFA_MCLOSE + 4:
      ! case NFA_MCLOSE + 5:
      ! case NFA_MCLOSE + 6:
      ! case NFA_MCLOSE + 7:
      ! case NFA_MCLOSE + 8:
      ! case NFA_MCLOSE + 9:
      case NFA_ZEND:
      if (state->c == NFA_ZEND)
      subidx = 0;
      else
      subidx = state->c - NFA_MCLOSE;

      /* We don't fill in gaps here, there must have been an MOPEN that
      * has done that. */
      --- 3283,3335 ----
      sub->in_use = save_in_use;
      break;

      ! case NFA_MCLOSE:
      if (nfa_has_zend)
      {
      /* Do not overwrite the position set by \ze. If no \ze
      * encountered end will be set in nfa_regtry(). */
      ! addstate(l, state->out, subs, off);
      break;
      }
      ! case NFA_MCLOSE1:
      ! case NFA_MCLOSE2:
      ! case NFA_MCLOSE3:
      ! case NFA_MCLOSE4:
      ! case NFA_MCLOSE5:
      ! case NFA_MCLOSE6:
      ! case NFA_MCLOSE7:
      ! case NFA_MCLOSE8:
      ! case NFA_MCLOSE9:
      ! #ifdef FEAT_SYN_HL
      ! case NFA_ZCLOSE:
      ! case NFA_ZCLOSE1:
      ! case NFA_ZCLOSE2:
      ! case NFA_ZCLOSE3:
      ! case NFA_ZCLOSE4:
      ! case NFA_ZCLOSE5:
      ! case NFA_ZCLOSE6:
      ! case NFA_ZCLOSE7:
      ! case NFA_ZCLOSE8:
      ! case NFA_ZCLOSE9:
      ! #endif
      case NFA_ZEND:
      if (state->c == NFA_ZEND)
      + {
      subidx = 0;
      + sub = &subs->norm;
      + }
      + #ifdef FEAT_SYN_HL
      + else if (state->c >= NFA_ZCLOSE)
      + {
      + subidx = state->c - NFA_ZCLOSE;
      + sub = &subs->synt;
      + }
      + #endif
      else
      + {
      subidx = state->c - NFA_MCLOSE;
      + sub = &subs->norm;
      + }

      /* We don't fill in gaps here, there must have been an MOPEN that
      * has done that. */
      ***************
      *** 3069,3075 ****
      sub->list.line[subidx].end = reginput + off;
      }

      ! addstate(l, state->out, sub, off);

      if (REG_MULTI)
      sub->list.multi[subidx].end = save_lpos;
      --- 3357,3363 ----
      sub->list.line[subidx].end = reginput + off;
      }

      ! addstate(l, state->out, subs, off);

      if (REG_MULTI)
      sub->list.multi[subidx].end = save_lpos;
      ***************
      *** 3087,3096 ****
      * matters for alternatives.
      */
      static void
      ! addstate_here(l, state, sub, ip)
      nfa_list_T *l; /* runtime state list */
      nfa_state_T *state; /* state to update */
      ! regsub_T *sub; /* pointers to subexpressions */
      int *ip;
      {
      int tlen = l->n;
      --- 3375,3384 ----
      * matters for alternatives.
      */
      static void
      ! addstate_here(l, state, subs, ip)
      nfa_list_T *l; /* runtime state list */
      nfa_state_T *state; /* state to update */
      ! regsubs_T *subs; /* pointers to subexpressions */
      int *ip;
      {
      int tlen = l->n;
      ***************
      *** 3098,3104 ****
      int i = *ip;

      /* first add the state(s) at the end, so that we know how many there are */
      ! addstate(l, state, sub, 0);

      /* when "*ip" was at the end of the list, nothing to do */
      if (i + 1 == tlen)
      --- 3386,3392 ----
      int i = *ip;

      /* first add the state(s) at the end, so that we know how many there are */
      ! addstate(l, state, subs, 0);

      /* when "*ip" was at the end of the list, nothing to do */
      if (i + 1 == tlen)
      ***************
      *** 3212,3218 ****

      /*
      * Check for a match with subexpression "subidx".
      ! * return TRUE if it matches.
      */
      static int
      match_backref(sub, subidx, bytelen)
      --- 3500,3506 ----

      /*
      * Check for a match with subexpression "subidx".
      ! * Return TRUE if it matches.
      */
      static int
      match_backref(sub, subidx, bytelen)
      ***************
      *** 3260,3265 ****
      --- 3548,3586 ----
      return FALSE;
      }

      + #ifdef FEAT_SYN_HL
      +
      + static int match_zref __ARGS((int subidx, int *bytelen));
      +
      + /*
      + * Check for a match with \z subexpression "subidx".
      + * Return TRUE if it matches.
      + */
      + static int
      + match_zref(subidx, bytelen)
      + int subidx;
      + int *bytelen; /* out: length of match in bytes */
      + {
      + int len;
      +
      + cleanup_zsubexpr();
      + if (re_extmatch_in == NULL || re_extmatch_in->matches[subidx] == NULL)
      + {
      + /* backref was not set, match an empty string */
      + *bytelen = 0;
      + return TRUE;
      + }
      +
      + len = (int)STRLEN(re_extmatch_in->matches[subidx]);
      + if (cstrncmp(re_extmatch_in->matches[subidx], reginput, &len) == 0)
      + {
      + *bytelen = len;
      + return TRUE;
      + }
      + return FALSE;
      + }
      + #endif
      +
      /*
      * Set all NFA nodes' list ID equal to -1.
      */
      ***************
      *** 3334,3340 ****
      return val == pos;
      }

      ! static int nfa_regmatch __ARGS((nfa_state_T *start, regsub_T *submatch, regsub_T *m, save_se_T *endp));

      /*
      * Main matching routine.
      --- 3655,3661 ----
      return val == pos;
      }

      ! static int nfa_regmatch __ARGS((nfa_state_T *start, regsubs_T *submatch, regsubs_T *m, save_se_T *endp));

      /*
      * Main matching routine.
      ***************
      *** 3349,3356 ****
      static int
      nfa_regmatch(start, submatch, m, endp)
      nfa_state_T *start;
      ! regsub_T *submatch;
      ! regsub_T *m;
      save_se_T *endp;
      {
      int result;
      --- 3670,3677 ----
      static int
      nfa_regmatch(start, submatch, m, endp)
      nfa_state_T *start;
      ! regsubs_T *submatch;
      ! regsubs_T *m;
      save_se_T *endp;
      {
      int result;
      ***************
      *** 3429,3435 ****
      #define ADD_POS_NEG_STATE(node) \
      ll = listtbl[result ? 1 : 0][node->negated]; \
      if (ll != NULL) \
      ! addstate(ll, node->out , &t->sub, clen);


      /*
      --- 3750,3756 ----
      #define ADD_POS_NEG_STATE(node) \
      ll = listtbl[result ? 1 : 0][node->negated]; \
      if (ll != NULL) \
      ! addstate(ll, node->out , &t->subs, clen);


      /*
      ***************
      *** 3531,3556 ****
      {
      case NFA_MATCH:
      {
      - int j;
      -
      nfa_match = TRUE;
      ! submatch->in_use = t->sub.in_use;
      ! if (REG_MULTI)
      ! for (j = 0; j < submatch->in_use; j++)
      ! {
      ! submatch->list.multi[j].start =
      ! t->sub.list.multi[j].start;
      ! submatch->list.multi[j].end = t->sub.list.multi[j].end;
      ! }
      ! else
      ! for (j = 0; j < submatch->in_use; j++)
      ! {
      ! submatch->list.line[j].start =
      ! t->sub.list.line[j].start;
      ! submatch->list.line[j].end = t->sub.list.line[j].end;
      ! }
      #ifdef ENABLE_LOG
      ! log_subexpr(&t->sub);
      #endif
      /* Found the left-most longest match, do not look at any other
      * states at this position. When the list of states is going
      --- 3852,3864 ----
      {
      case NFA_MATCH:
      {
      nfa_match = TRUE;
      ! copy_sub(&submatch->norm, &t->subs.norm);
      ! #ifdef FEAT_SYN_HL
      ! copy_sub(&submatch->synt, &t->subs.synt);
      ! #endif
      #ifdef ENABLE_LOG
      ! log_subsexpr(&t->subs);
      #endif
      /* Found the left-most longest match, do not look at any other
      * states at this position. When the list of states is going
      ***************
      *** 3570,3578 ****
      * finished successfully, so return control to the parent
      * nfa_regmatch(). Submatches are stored in *m, and used in
      * the parent call. */
      ! if (start->c == NFA_MOPEN + 0)
      /* TODO: do we ever get here? */
      ! addstate_here(thislist, t->state->out, &t->sub, &listidx);
      else
      {
      #ifdef ENABLE_LOG
      --- 3878,3886 ----
      * finished successfully, so return control to the parent
      * nfa_regmatch(). Submatches are stored in *m, and used in
      * the parent call. */
      ! if (start->c == NFA_MOPEN)
      /* TODO: do we ever get here? */
      ! addstate_here(thislist, t->state->out, &t->subs, &listidx);
      else
      {
      #ifdef ENABLE_LOG
      ***************
      *** 3600,3607 ****

      /* do not set submatches for \@! */
      if (!t->state->negated)
      ! /* TODO: only copy positions in use. */
      ! *m = t->sub;
      nfa_match = TRUE;
      }
      break;
      --- 3908,3919 ----

      /* do not set submatches for \@! */
      if (!t->state->negated)
      ! {
      ! copy_sub(&m->norm, &t->subs.norm);
      ! #ifdef FEAT_SYN_HL
      ! copy_sub(&m->synt, &t->subs.synt);
      ! #endif
      ! }
      nfa_match = TRUE;
      }
      break;
      ***************
      *** 3630,3636 ****

      /* Go back the specified number of bytes, or as far as the
      * start of the previous line, to try matching "\@<=" or
      ! * not matching "\@<!". */
      if (t->state->val <= 0)
      {
      if (REG_MULTI)
      --- 3942,3950 ----

      /* Go back the specified number of bytes, or as far as the
      * start of the previous line, to try matching "\@<=" or
      ! * not matching "\@<!".
      ! * TODO: This is very inefficient! Would be better to
      ! * first check for a match with what follows. */
      if (t->state->val <= 0)
      {
      if (REG_MULTI)
      ***************
      *** 3722,3748 ****
      /* for \@! it is a match when result is FALSE */
      if (result != t->state->negated)
      {
      - int j;
      -
      /* Copy submatch info from the recursive call */
      ! if (REG_MULTI)
      ! for (j = 1; j < m->in_use; j++)
      ! {
      ! t->sub.list.multi[j].start = m->list.multi[j].start;
      ! t->sub.list.multi[j].end = m->list.multi[j].end;
      ! }
      ! else
      ! for (j = 1; j < m->in_use; j++)
      ! {
      ! t->sub.list.line[j].start = m->list.line[j].start;
      ! t->sub.list.line[j].end = m->list.line[j].end;
      ! }
      ! if (m->in_use > t->sub.in_use)
      ! t->sub.in_use = m->in_use;

      /* t->state->out1 is the corresponding END_INVISIBLE node;
      * Add it to the current list (zero-width match). */
      ! addstate_here(thislist, t->state->out1->out, &t->sub,
      &listidx);
      }
      break;
      --- 4036,4050 ----
      /* for \@! it is a match when result is FALSE */
      if (result != t->state->negated)
      {
      /* Copy submatch info from the recursive call */
      ! copy_sub_off(&t->subs.norm, &m->norm);
      ! #ifdef FEAT_SYN_HL
      ! copy_sub_off(&t->subs.synt, &m->synt);
      ! #endif

      /* t->state->out1 is the corresponding END_INVISIBLE node;
      * Add it to the current list (zero-width match). */
      ! addstate_here(thislist, t->state->out1->out, &t->subs,
      &listidx);
      }
      break;
      ***************
      *** 3750,3761 ****

      case NFA_BOL:
      if (reginput == regline)
      ! addstate_here(thislist, t->state->out, &t->sub, &listidx);
      break;

      case NFA_EOL:
      if (curc == NUL)
      ! addstate_here(thislist, t->state->out, &t->sub, &listidx);
      break;

      case NFA_BOW:
      --- 4052,4063 ----

      case NFA_BOL:
      if (reginput == regline)
      ! addstate_here(thislist, t->state->out, &t->subs, &listidx);
      break;

      case NFA_EOL:
      if (curc == NUL)
      ! addstate_here(thislist, t->state->out, &t->subs, &listidx);
      break;

      case NFA_BOW:
      ***************
      *** 3782,3788 ****
      && vim_iswordc_buf(reginput[-1], reg_buf)))
      bow = FALSE;
      if (bow)
      ! addstate_here(thislist, t->state->out, &t->sub, &listidx);
      break;
      }

      --- 4084,4090 ----
      && vim_iswordc_buf(reginput[-1], reg_buf)))
      bow = FALSE;
      if (bow)
      ! addstate_here(thislist, t->state->out, &t->subs, &listidx);
      break;
      }

      ***************
      *** 3810,3828 ****
      && vim_iswordc_buf(curc, reg_buf)))
      eow = FALSE;
      if (eow)
      ! addstate_here(thislist, t->state->out, &t->sub, &listidx);
      break;
      }

      case NFA_BOF:
      if (reglnum == 0 && reginput == regline
      && (!REG_MULTI || reg_firstlnum == 1))
      ! addstate_here(thislist, t->state->out, &t->sub, &listidx);
      break;

      case NFA_EOF:
      if (reglnum == reg_maxline && curc == NUL)
      ! addstate_here(thislist, t->state->out, &t->sub, &listidx);
      break;

      #ifdef FEAT_MBYTE
      --- 4112,4130 ----
      && vim_iswordc_buf(curc, reg_buf)))
      eow = FALSE;
      if (eow)
      ! addstate_here(thislist, t->state->out, &t->subs, &listidx);
      break;
      }

      case NFA_BOF:
      if (reglnum == 0 && reginput == regline
      && (!REG_MULTI || reg_firstlnum == 1))
      ! addstate_here(thislist, t->state->out, &t->subs, &listidx);
      break;

      case NFA_EOF:
      if (reglnum == reg_maxline && curc == NUL)
      ! addstate_here(thislist, t->state->out, &t->subs, &listidx);
      break;

      #ifdef FEAT_MBYTE
      ***************
      *** 3911,3922 ****
      go_to_nextline = TRUE;
      /* Pass -1 for the offset, which means taking the position
      * at the start of the next line. */
      ! addstate(nextlist, t->state->out, &t->sub, -1);
      }
      else if (curc == '\n' && reg_line_lbr)
      {
      /* match \n as if it is an ordinary character */
      ! addstate(nextlist, t->state->out, &t->sub, 1);
      }
      break;

      --- 4213,4224 ----
      go_to_nextline = TRUE;
      /* Pass -1 for the offset, which means taking the position
      * at the start of the next line. */
      ! addstate(nextlist, t->state->out, &t->subs, -1);
      }
      else if (curc == '\n' && reg_line_lbr)
      {
      /* match \n as if it is an ordinary character */
      ! addstate(nextlist, t->state->out, &t->subs, 1);
      }
      break;

      ***************
      *** 3944,3956 ****
      /* This follows a series of negated nodes, like:
      * CHAR(x), NFA_NOT, CHAR(y), NFA_NOT etc. */
      if (curc > 0)
      ! addstate(nextlist, t->state->out, &t->sub, clen);
      break;

      case NFA_ANY:
      /* Any char except '\0', (end of input) does not match. */
      if (curc > 0)
      ! addstate(nextlist, t->state->out, &t->sub, clen);
      break;

      /*
      --- 4246,4258 ----
      /* This follows a series of negated nodes, like:
      * CHAR(x), NFA_NOT, CHAR(y), NFA_NOT etc. */
      if (curc > 0)
      ! addstate(nextlist, t->state->out, &t->subs, clen);
      break;

      case NFA_ANY:
      /* Any char except '\0', (end of input) does not match. */
      if (curc > 0)
      ! addstate(nextlist, t->state->out, &t->subs, clen);
      break;

      /*
      ***************
      *** 4096,4114 ****
      case NFA_BACKREF7:
      case NFA_BACKREF8:
      case NFA_BACKREF9:
      ! /* \1 .. \9 */
      {
      ! int subidx = t->state->c - NFA_BACKREF1 + 1;
      int bytelen;

      ! result = match_backref(&t->sub, subidx, &bytelen);
      if (result)
      {
      if (bytelen == 0)
      {
      /* empty match always works, add NFA_SKIP with zero to
      * be used next */
      ! addstate_here(thislist, t->state->out, &t->sub,
      &listidx);
      thislist->t[listidx + 1].count = 0;
      }
      --- 4398,4439 ----
      case NFA_BACKREF7:
      case NFA_BACKREF8:
      case NFA_BACKREF9:
      ! #ifdef FEAT_SYN_HL
      ! case NFA_ZREF1:
      ! case NFA_ZREF2:
      ! case NFA_ZREF3:
      ! case NFA_ZREF4:
      ! case NFA_ZREF5:
      ! case NFA_ZREF6:
      ! case NFA_ZREF7:
      ! case NFA_ZREF8:
      ! case NFA_ZREF9:
      ! #endif
      ! /* \1 .. \9 \z1 .. \z9 */
      {
      ! int subidx;
      int bytelen;

      ! if (t->state->c <= NFA_BACKREF9)
      ! {
      ! subidx = t->state->c - NFA_BACKREF1 + 1;
      ! result = match_backref(&t->subs.norm, subidx, &bytelen);
      ! }
      ! #ifdef FEAT_SYN_HL
      ! else
      ! {
      ! subidx = t->state->c - NFA_ZREF1 + 1;
      ! result = match_zref(subidx, &bytelen);
      ! }
      ! #endif
      !
      if (result)
      {
      if (bytelen == 0)
      {
      /* empty match always works, add NFA_SKIP with zero to
      * be used next */
      ! addstate_here(thislist, t->state->out, &t->subs,
      &listidx);
      thislist->t[listidx + 1].count = 0;
      }
      ***************
      *** 4116,4134 ****
      {
      /* match current character, jump ahead to out of
      * NFA_SKIP */
      ! addstate(nextlist, t->state->out->out, &t->sub, clen);
      #ifdef ENABLE_LOG
      ! log_subexpr(&nextlist->t[nextlist->n - 1].sub);
      #endif
      }
      else
      {
      /* skip ofer the matched characters, set character
      * count in NFA_SKIP */
      ! addstate(nextlist, t->state->out, &t->sub, bytelen);
      nextlist->t[nextlist->n - 1].count = bytelen - clen;
      #ifdef ENABLE_LOG
      ! log_subexpr(&nextlist->t[nextlist->n - 1].sub);
      #endif
      }

      --- 4441,4459 ----
      {
      /* match current character, jump ahead to out of
      * NFA_SKIP */
      ! addstate(nextlist, t->state->out->out, &t->subs, clen);
      #ifdef ENABLE_LOG
      ! log_subsexpr(&nextlist->t[nextlist->n - 1].subs);
      #endif
      }
      else
      {
      /* skip ofer the matched characters, set character
      * count in NFA_SKIP */
      ! addstate(nextlist, t->state->out, &t->subs, bytelen);
      nextlist->t[nextlist->n - 1].count = bytelen - clen;
      #ifdef ENABLE_LOG
      ! log_subsexpr(&nextlist->t[nextlist->n - 1].subs);
      #endif
      }

      ***************
      *** 4140,4157 ****
      if (t->count - clen <= 0)
      {
      /* end of match, go to what follows */
      ! addstate(nextlist, t->state->out, &t->sub, clen);
      #ifdef ENABLE_LOG
      ! log_subexpr(&nextlist->t[nextlist->n - 1].sub);
      #endif
      }
      else
      {
      /* add state again with decremented count */
      ! addstate(nextlist, t->state, &t->sub, 0);
      nextlist->t[nextlist->n - 1].count = t->count - clen;
      #ifdef ENABLE_LOG
      ! log_subexpr(&nextlist->t[nextlist->n - 1].sub);
      #endif
      }
      break;
      --- 4465,4482 ----
      if (t->count - clen <= 0)
      {
      /* end of match, go to what follows */
      ! addstate(nextlist, t->state->out, &t->subs, clen);
      #ifdef ENABLE_LOG
      ! log_subsexpr(&nextlist->t[nextlist->n - 1].subs);
      #endif
      }
      else
      {
      /* add state again with decremented count */
      ! addstate(nextlist, t->state, &t->subs, 0);
      nextlist->t[nextlist->n - 1].count = t->count - clen;
      #ifdef ENABLE_LOG
      ! log_subsexpr(&nextlist->t[nextlist->n - 1].subs);
      #endif
      }
      break;
      ***************
      *** 4169,4175 ****
      nfa_re_num_cmp(t->state->val, t->state->c - NFA_LNUM,
      (long_u)(reglnum + reg_firstlnum)));
      if (result)
      ! addstate_here(thislist, t->state->out, &t->sub, &listidx);
      break;

      case NFA_COL:
      --- 4494,4500 ----
      nfa_re_num_cmp(t->state->val, t->state->c - NFA_LNUM,
      (long_u)(reglnum + reg_firstlnum)));
      if (result)
      ! addstate_here(thislist, t->state->out, &t->subs, &listidx);
      break;

      case NFA_COL:
      ***************
      *** 4178,4184 ****
      result = nfa_re_num_cmp(t->state->val, t->state->c - NFA_COL,
      (long_u)(reginput - regline) + 1);
      if (result)
      ! addstate_here(thislist, t->state->out, &t->sub, &listidx);
      break;

      case NFA_VCOL:
      --- 4503,4509 ----
      result = nfa_re_num_cmp(t->state->val, t->state->c - NFA_COL,
      (long_u)(reginput - regline) + 1);
      if (result)
      ! addstate_here(thislist, t->state->out, &t->subs, &listidx);
      break;

      case NFA_VCOL:
      ***************
      *** 4189,4195 ****
      reg_win == NULL ? curwin : reg_win,
      regline, (colnr_T)(reginput - regline)) + 1);
      if (result)
      ! addstate_here(thislist, t->state->out, &t->sub, &listidx);
      break;

      case NFA_CURSOR:
      --- 4514,4520 ----
      reg_win == NULL ? curwin : reg_win,
      regline, (colnr_T)(reginput - regline)) + 1);
      if (result)
      ! addstate_here(thislist, t->state->out, &t->subs, &listidx);
      break;

      case NFA_CURSOR:
      ***************
      *** 4198,4204 ****
      && ((colnr_T)(reginput - regline)
      == reg_win->w_cursor.col));
      if (result)
      ! addstate_here(thislist, t->state->out, &t->sub, &listidx);
      break;

      default: /* regular character */
      --- 4523,4529 ----
      && ((colnr_T)(reginput - regline)
      == reg_win->w_cursor.col));
      if (result)
      ! addstate_here(thislist, t->state->out, &t->subs, &listidx);
      break;

      default: /* regular character */
      ***************
      *** 4238,4244 ****
      * Unless "endp" is not NULL, then we match the end position.
      * Also don't start a match past the first line. */
      if (nfa_match == FALSE
      ! && ((start->c == NFA_MOPEN + 0
      && reglnum == 0
      && clen != 0
      && (ireg_maxcol == 0
      --- 4563,4569 ----
      * Unless "endp" is not NULL, then we match the end position.
      * Also don't start a match past the first line. */
      if (nfa_match == FALSE
      ! && ((start->c == NFA_MOPEN
      && reglnum == 0
      && clen != 0
      && (ireg_maxcol == 0
      ***************
      *** 4305,4322 ****
      * Returns 0 for failure, number of lines contained in the match otherwise.
      */
      static long
      ! nfa_regtry(start, col)
      ! nfa_state_T *start;
      ! colnr_T col;
      {
      int i;
      ! regsub_T sub, m;
      #ifdef ENABLE_LOG
      FILE *f;
      #endif

      reginput = regline + col;
      need_clear_subexpr = TRUE;

      #ifdef ENABLE_LOG
      f = fopen(NFA_REGEXP_RUN_LOG, "a");
      --- 4630,4653 ----
      * Returns 0 for failure, number of lines contained in the match otherwise.
      */
      static long
      ! nfa_regtry(prog, col)
      ! nfa_regprog_T *prog;
      ! colnr_T col;
      {
      int i;
      ! regsubs_T subs, m;
      ! nfa_state_T *start = prog->start;
      #ifdef ENABLE_LOG
      FILE *f;
      #endif

      reginput = regline + col;
      need_clear_subexpr = TRUE;
      + #ifdef FEAT_SYN_HL
      + /* Clear the external match subpointers if necessary. */
      + if (prog->reghasz == REX_SET)
      + need_clear_zsubexpr = TRUE;
      + #endif

      #ifdef ENABLE_LOG
      f = fopen(NFA_REGEXP_RUN_LOG, "a");
      ***************
      *** 4337,4366 ****
      EMSG(_("Could not open temporary log file for writing "));
      #endif

      ! if (REG_MULTI)
      ! {
      ! /* Use 0xff to set lnum to -1 */
      ! vim_memset(sub.list.multi, 0xff, sizeof(struct multipos) * nfa_nsubexpr);
      ! vim_memset(m.list.multi, 0xff, sizeof(struct multipos) * nfa_nsubexpr);
      ! }
      ! else
      ! {
      ! vim_memset(sub.list.line, 0, sizeof(struct linepos) * nfa_nsubexpr);
      ! vim_memset(m.list.line, 0, sizeof(struct linepos) * nfa_nsubexpr);
      ! }
      ! sub.in_use = 0;
      ! m.in_use = 0;

      ! if (nfa_regmatch(start, &sub, &m, NULL) == FALSE)
      return 0;

      cleanup_subexpr();
      if (REG_MULTI)
      {
      ! for (i = 0; i < sub.in_use; i++)
      {
      ! reg_startpos[i] = sub.list.multi[i].start;
      ! reg_endpos[i] = sub.list.multi[i].end;
      }

      if (reg_startpos[0].lnum < 0)
      --- 4668,4690 ----
      EMSG(_("Could not open temporary log file for writing "));
      #endif

      ! clear_sub(&subs.norm);
      ! clear_sub(&m.norm);
      ! #ifdef FEAT_SYN_HL
      ! clear_sub(&subs.synt);
      ! clear_sub(&m.synt);
      ! #endif

      ! if (nfa_regmatch(start, &subs, &m, NULL) == FALSE)
      return 0;

      cleanup_subexpr();
      if (REG_MULTI)
      {
      ! for (i = 0; i < subs.norm.in_use; i++)
      {
      ! reg_startpos[i] = subs.norm.list.multi[i].start;
      ! reg_endpos[i] = subs.norm.list.multi[i].end;
      }

      if (reg_startpos[0].lnum < 0)
      ***************
      *** 4380,4389 ****
      }
      else
      {
      ! for (i = 0; i < sub.in_use; i++)
      {
      ! reg_startp[i] = sub.list.line[i].start;
      ! reg_endp[i] = sub.list.line[i].end;
      }

      if (reg_startp[0] == NULL)
      --- 4704,4713 ----
      }
      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)
      ***************
      *** 4392,4397 ****
      --- 4716,4758 ----
      reg_endp[0] = reginput;
      }

      + #ifdef FEAT_SYN_HL
      + /* Package any found \z(...\) matches for export. Default is none. */
      + unref_extmatch(re_extmatch_out);
      + re_extmatch_out = NULL;
      +
      + if (prog->reghasz == REX_SET)
      + {
      + int i;
      +
      + cleanup_zsubexpr();
      + re_extmatch_out = make_extmatch();
      + for (i = 0; i < subs.synt.in_use; i++)
      + {
      + if (REG_MULTI)
      + {
      + struct multipos *mpos = &subs.synt.list.multi[i];
      +
      + /* Only accept single line matches. */
      + if (mpos->start.lnum >= 0 && mpos->start.lnum == mpos->end.lnum)
      + re_extmatch_out->matches[i] =
      + vim_strnsave(reg_getline(mpos->start.lnum)
      + + mpos->start.col,
      + mpos->end.col - mpos->start.col);
      + }
      + else
      + {
      + struct linepos *lpos = &subs.synt.list.line[i];
      +
      + if (lpos->start != NULL && lpos->end != NULL)
      + re_extmatch_out->matches[i] =
      + vim_strnsave(lpos->start,
      + (int)(lpos->end - lpos->start));
      + }
      + }
      + }
      + #endif
      +
      return 1 + reglnum;
      }

      ***************
      *** 4461,4467 ****
      prog->state[i].lastlist = 0;
      }

      ! retval = nfa_regtry(prog->start, col);

      theend:
      return retval;
      --- 4822,4828 ----
      prog->state[i].lastlist = 0;
      }

      ! retval = nfa_regtry(prog, col);

      theend:
      return retval;
      ***************
      *** 4552,4557 ****
      --- 4913,4922 ----
      nfa_postfix_dump(expr, OK);
      nfa_dump(prog);
      #endif
      + #ifdef FEAT_SYN_HL
      + /* Remember whether this pattern has any \z specials in it. */
      + prog->reghasz = re_has_z;
      + #endif

      out:
      vim_free(post_start);
      *** ../vim-7.3.1089/src/version.c 2013-06-01 20:32:09.000000000 +0200
      --- src/version.c 2013-06-01 22:29:51.000000000 +0200
      ***************
      *** 730,731 ****
      --- 730,733 ----
      { /* Add new patch number below this line */
      + /**/
      + 1090,
      /**/

      --
      Despite the cost of living, have you noticed how it remains so popular?

      /// Bram Moolenaar -- Bram@... -- 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 vim_dev+unsubscribe@....
      For more options, visit https://groups.google.com/groups/opt_out.
    • Bram Moolenaar
      ... Sorry for the unfinished subject... Syntax highlighting of XML with long lines is a lot faster now. -- Nothing is fool-proof to a sufficiently talented
      Message 2 of 8 , Jun 1, 2013
      • 0 Attachment
        I wrote:

        > Patch 7.3.1090
        > Problem: New regexp engine does not support \z1 .. \z9 and \z(.
        > Solution: Implement the syntax submatches.
        > Files: src/regexp.h, src/regexp_nfa.c

        Sorry for the unfinished subject...

        Syntax highlighting of XML with long lines is a lot faster now.

        --
        Nothing is fool-proof to a sufficiently talented fool.

        /// Bram Moolenaar -- Bram@... -- 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 vim_dev+unsubscribe@....
        For more options, visit https://groups.google.com/groups/opt_out.
      • Dominique PellĂ©
        ... Hi I was hoping for faster xml syntax highlighting after reading the above comment, but using :set regexpengine=1 (old engine) is much faster than :set
        Message 3 of 8 , Jun 2, 2013
        • 0 Attachment
          Bram Moolenaar wrote:

          > Syntax highlighting of XML with long lines is a lot faster now.

          Hi

          I was hoping for faster xml syntax highlighting after reading
          the above comment, but using :set regexpengine=1 (old engine)
          is much faster than :set regexpengine=0 (automatic engine).

          Here is a comparison using vim-7.3.1090 (big) on Linux x86_64:

          1/ download this xml file:

          $ wget http://svn.code.sf.net/p/languagetool/code/trunk/languagetool/languagetool-language-modules/fr/src/main/resources/org/languagetool/rules/fr/grammar.xml

          2/ create a simple ~/.vimrc

          $ cat ~/.vimrc
          set nocompatible
          set regexpengine=1
          filetype on
          filetype plugin on
          syntax on

          3/ measure (using old regexp engine):

          $ time vim -c ':norm G' -c ':redraw|q' grammar.xml
          real 0m3.511s
          user 0m3.444s
          sys 0m0.052s


          4/ change "set regexpengine=1" into "set regexpengine=0" in ~/.vimrc

          5/ measure the same command again (using new regexp engine):

          $ time vim -c ':norm G' -c ':redraw|q' grammar.xml

          real 0m16.429s
          user 0m16.117s
          sys 0m0.256s

          So in this xml example, it's x4.7 slower with the new
          regexp engine. Is this expected?

          The grammar.xml file contains a few long lines. Here is the
          length of the 5 longest lines:

          $ perl -ne 'print length($_), "\n"' < grammar.xml | sort -n | tail -5
          812
          924
          1217
          1343
          2312

          Regards
          Dominique

          --
          --
          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 vim_dev+unsubscribe@....
          For more options, visit https://groups.google.com/groups/opt_out.
        • Bram Moolenaar
          ... Did you do this with an older xml syntax file, or the one recently committed? ... I have an XML file where the old engine basically gets stuck and I have
          Message 4 of 8 , Jun 2, 2013
          • 0 Attachment
            Dominique Pelle wrote:

            > Bram Moolenaar wrote:
            >
            > > Syntax highlighting of XML with long lines is a lot faster now.
            >
            > Hi
            >
            > I was hoping for faster xml syntax highlighting after reading
            > the above comment, but using :set regexpengine=1 (old engine)
            > is much faster than :set regexpengine=0 (automatic engine).
            >
            > Here is a comparison using vim-7.3.1090 (big) on Linux x86_64:
            >
            > 1/ download this xml file:
            >
            > $ wget http://svn.code.sf.net/p/languagetool/code/trunk/languagetool/languagetool-language-modules/fr/src/main/resources/org/languagetool/rules/fr/grammar.xml
            >
            > 2/ create a simple ~/.vimrc
            >
            > $ cat ~/.vimrc
            > set nocompatible
            > set regexpengine=1
            > filetype on
            > filetype plugin on
            > syntax on
            >
            > 3/ measure (using old regexp engine):
            >
            > $ time vim -c ':norm G' -c ':redraw|q' grammar.xml
            > real 0m3.511s
            > user 0m3.444s
            > sys 0m0.052s

            Did you do this with an older xml syntax file, or the one recently
            committed?

            > 4/ change "set regexpengine=1" into "set regexpengine=0" in ~/.vimrc
            >
            > 5/ measure the same command again (using new regexp engine):
            >
            > $ time vim -c ':norm G' -c ':redraw|q' grammar.xml
            >
            > real 0m16.429s
            > user 0m16.117s
            > sys 0m0.256s
            >
            > So in this xml example, it's x4.7 slower with the new
            > regexp engine. Is this expected?
            >
            > The grammar.xml file contains a few long lines. Here is the
            > length of the 5 longest lines:
            >
            > $ perl -ne 'print length($_), "\n"' < grammar.xml | sort -n | tail -5
            > 812
            > 924
            > 1217
            > 1343
            > 2312

            I have an XML file where the old engine basically gets stuck and I have
            to press CTRL-C to get back control. With the new engine it now does
            show up.

            The new engine is slower on normal patterns. I first want to make the
            new engine work with all possible regexp features. Then I want to
            automatically fall back to the old engine for patterns where it should
            be faster.

            Also, we should start using the limit on the look-behind matching. The
            XML syntax contains items like this:

            [<]\@<=[^ /!?<>"']\+

            Clearly the look-behind will only work when going back one or two
            characters, going back further won't work. But the engine doesn't know
            that, it goes back to the start of the previous line before it gives up.

            This is much faster:

            [<]\@2<=[^ /!?<>"']\+

            Then the engine give up two bytes before where the match needs to end.

            Another difference between the old and the new engine is that the new
            engine first finds a match with the look-behind. The old engine first
            finds a match with what follows. I'm not sure what works best.

            There is still a lot of speed optimizing to do, but I first want to make
            it work and fix any bugs. It doesn't make sense to optimize something
            that doesn't work.

            --
            The 50-50-90 rule: Anytime you have a 50-50 chance of getting
            something right, there's a 90% probability you'll get it wrong.

            /// Bram Moolenaar -- Bram@... -- 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 vim_dev+unsubscribe@....
            For more options, visit https://groups.google.com/groups/opt_out.
          • Ben Fritz
            ... I didn t know you could do that! I have an older Vim installed on this computer currently...is this a new feature, or just undocumented? -- -- You received
            Message 5 of 8 , Jun 2, 2013
            • 0 Attachment
              On Sunday, June 2, 2013 7:27:57 AM UTC-5, Bram Moolenaar wrote:
              >
              >
              > This is much faster:
              >
              >
              >
              > [<]\@2<=[^ /!?<>"']\+
              >

              I didn't know you could do that! I have an older Vim installed on this computer currently...is this a new feature, or just undocumented?

              --
              --
              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 vim_dev+unsubscribe@....
              For more options, visit https://groups.google.com/groups/opt_out.
            • Andy Wokula
              ... See Patch 7.3.1037 -- Andy -- -- You received this message from the vim_dev maillist. Do not top-post! Type your reply below the text you are replying
              Message 6 of 8 , Jun 2, 2013
              • 0 Attachment
                Am 02.06.2013 21:38, schrieb Ben Fritz:
                > On Sunday, June 2, 2013 7:27:57 AM UTC-5, Bram Moolenaar wrote:
                >>
                >>
                >> This is much faster:
                >>
                >> [<]\@2<=[^ /!?<>"']\+
                >>
                >
                > I didn't know you could do that! I have an older Vim installed on this
                > computer currently...is this a new feature, or just undocumented?

                See Patch 7.3.1037

                --
                Andy

                --
                --
                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 vim_dev+unsubscribe@....
                For more options, visit https://groups.google.com/groups/opt_out.
              • Bram Moolenaar
                ... Introduced in patch 7.3.1037. Thus it can only be used in runtime files included with the upcoming Vim 7.4. Look-behind matches are still slow, because of
                Message 7 of 8 , Jun 2, 2013
                • 0 Attachment
                  Ben Fritz wrote:

                  > On Sunday, June 2, 2013 7:27:57 AM UTC-5, Bram Moolenaar wrote:
                  > >
                  > >
                  > > This is much faster:
                  > >
                  > >
                  > >
                  > > [<]\@2<=[^ /!?<>"']\+
                  > >
                  >
                  > I didn't know you could do that! I have an older Vim installed on this
                  > computer currently...is this a new feature, or just undocumented?

                  Introduced in patch 7.3.1037. Thus it can only be used in runtime files
                  included with the upcoming Vim 7.4.

                  Look-behind matches are still slow, because of all the overhead, but
                  with this limit it's at least somewhat less slow.

                  --
                  ERROR 047: Keyboard not found. Press RETURN to continue.

                  /// Bram Moolenaar -- Bram@... -- 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 vim_dev+unsubscribe@....
                  For more options, visit https://groups.google.com/groups/opt_out.
                Your message has been successfully submitted and would be delivered to recipients shortly.