home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / patches / 7.3 / 7.3.1088 < prev    next >
Encoding:
Internet Message Format  |  2013-05-31  |  18.0 KB

  1. To: vim_dev@googlegroups.com
  2. Subject: Patch 7.3.1088
  3. Fcc: outbox
  4. From: Bram Moolenaar <Bram@moolenaar.net>
  5. Mime-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. ------------
  9.  
  10. Patch 7.3.1088
  11. Problem:    New regexp engine: \@<= and \@<! are not implemented.
  12. Solution:   Implement look-behind matching.  Fix off-by-one error in old
  13.         regexp engine.
  14. Files:        src/regexp.c, src/regexp_nfa.c, src/testdir/test64.in,
  15.         src/testdir/test64.ok
  16.  
  17.  
  18. *** ../vim-7.3.1087/src/regexp.c    2013-06-01 14:42:51.000000000 +0200
  19. --- src/regexp.c    2013-06-01 18:55:07.000000000 +0200
  20. ***************
  21. *** 5576,5582 ****
  22.           limit = OPERAND_MIN(rp->rs_scan);
  23.           if (REG_MULTI)
  24.           {
  25. !             if (rp->rs_un.regsave.rs_u.pos.col == 0)
  26.               {
  27.               if (rp->rs_un.regsave.rs_u.pos.lnum
  28.                       < behind_pos.rs_u.pos.lnum
  29. --- 5576,5589 ----
  30.           limit = OPERAND_MIN(rp->rs_scan);
  31.           if (REG_MULTI)
  32.           {
  33. !             if (limit > 0
  34. !                 && ((rp->rs_un.regsave.rs_u.pos.lnum
  35. !                             < behind_pos.rs_u.pos.lnum
  36. !                     ? (colnr_T)STRLEN(regline)
  37. !                     : behind_pos.rs_u.pos.col)
  38. !                 - rp->rs_un.regsave.rs_u.pos.col >= limit))
  39. !             no = FAIL;
  40. !             else if (rp->rs_un.regsave.rs_u.pos.col == 0)
  41.               {
  42.               if (rp->rs_un.regsave.rs_u.pos.lnum
  43.                       < behind_pos.rs_u.pos.lnum
  44. ***************
  45. *** 5601,5613 ****
  46.               else
  47.   #endif
  48.                   --rp->rs_un.regsave.rs_u.pos.col;
  49. -             if (limit > 0
  50. -                 && ((rp->rs_un.regsave.rs_u.pos.lnum
  51. -                             < behind_pos.rs_u.pos.lnum
  52. -                     ? (colnr_T)STRLEN(regline)
  53. -                     : behind_pos.rs_u.pos.col)
  54. -                     - rp->rs_un.regsave.rs_u.pos.col > limit))
  55. -                 no = FAIL;
  56.               }
  57.           }
  58.           else
  59. --- 5608,5613 ----
  60. *** ../vim-7.3.1087/src/regexp_nfa.c    2013-06-01 14:42:51.000000000 +0200
  61. --- src/regexp_nfa.c    2013-06-01 19:42:22.000000000 +0200
  62. ***************
  63. *** 56,61 ****
  64. --- 56,62 ----
  65.       NFA_NOPEN,                /* Start of subexpression marked with \%( */
  66.       NFA_NCLOSE,                /* End of subexpr. marked with \%( ... \) */
  67.       NFA_START_INVISIBLE,
  68. +     NFA_START_INVISIBLE_BEFORE,
  69.       NFA_END_INVISIBLE,
  70.       NFA_COMPOSING,            /* Next nodes in NFA are part of the
  71.                          composing multibyte char */
  72. ***************
  73. *** 1369,1402 ****
  74.           break;
  75.   
  76.       case Magic('@'):
  77.           op = no_Magic(getchr());
  78.           switch(op)
  79.           {
  80.           case '=':
  81. !             EMIT(NFA_PREV_ATOM_NO_WIDTH);
  82.               break;
  83.           case '!':
  84. !             EMIT(NFA_PREV_ATOM_NO_WIDTH_NEG);
  85.               break;
  86. -         case '0':
  87. -         case '1':
  88. -         case '2':
  89. -         case '3':
  90. -         case '4':
  91. -         case '5':
  92. -         case '6':
  93. -         case '7':
  94. -         case '8':
  95. -         case '9':
  96.           case '<':
  97.           case '>':
  98. !             /* Not supported yet */
  99. !             return FAIL;
  100. !         default:
  101. !             syntax_error = TRUE;
  102. !             EMSGN(_("E869: (NFA) Unknown operator '\\@%c'"), op);
  103.               return FAIL;
  104.           }
  105.           break;
  106.   
  107.       case Magic('?'):
  108. --- 1370,1412 ----
  109.           break;
  110.   
  111.       case Magic('@'):
  112. +         c2 = getdecchrs();
  113.           op = no_Magic(getchr());
  114. +         i = 0;
  115.           switch(op)
  116.           {
  117.           case '=':
  118. !             /* \@= */
  119. !             i = NFA_PREV_ATOM_NO_WIDTH;
  120.               break;
  121.           case '!':
  122. !             /* \@! */
  123. !             i = NFA_PREV_ATOM_NO_WIDTH_NEG;
  124.               break;
  125.           case '<':
  126. +             op = no_Magic(getchr());
  127. +             if (op == '=')
  128. +             /* \@<= */
  129. +             i = NFA_PREV_ATOM_JUST_BEFORE;
  130. +             else if (op == '!')
  131. +             /* \@<! */
  132. +             i = NFA_PREV_ATOM_JUST_BEFORE_NEG;
  133. +             break;
  134.           case '>':
  135. !             /* \@> Not supported yet */
  136. !             /* i = NFA_PREV_ATOM_LIKE_PATTERN; */
  137.               return FAIL;
  138.           }
  139. +         if (i == 0)
  140. +         {
  141. +         syntax_error = TRUE;
  142. +         EMSGN(_("E869: (NFA) Unknown operator '\\@%c'"), op);
  143. +         return FAIL;
  144. +         }
  145. +         EMIT(i);
  146. +         if (i == NFA_PREV_ATOM_JUST_BEFORE
  147. +                     || i == NFA_PREV_ATOM_JUST_BEFORE_NEG)
  148. +         EMIT(c2);
  149.           break;
  150.   
  151.       case Magic('?'):
  152. ***************
  153. *** 1734,1742 ****
  154. --- 1744,1758 ----
  155.                   STRCPY(code, "NFA_PREV_ATOM_NO_WIDTH"); break;
  156.       case NFA_PREV_ATOM_NO_WIDTH_NEG:
  157.                   STRCPY(code, "NFA_PREV_ATOM_NO_WIDTH_NEG"); break;
  158. +     case NFA_PREV_ATOM_JUST_BEFORE:
  159. +                 STRCPY(code, "NFA_PREV_ATOM_JUST_BEFORE"); break;
  160. +     case NFA_PREV_ATOM_JUST_BEFORE_NEG:
  161. +              STRCPY(code, "NFA_PREV_ATOM_JUST_BEFORE_NEG"); break;
  162.       case NFA_NOPEN:            STRCPY(code, "NFA_NOPEN"); break;
  163.       case NFA_NCLOSE:        STRCPY(code, "NFA_NCLOSE"); break;
  164.       case NFA_START_INVISIBLE:   STRCPY(code, "NFA_START_INVISIBLE"); break;
  165. +     case NFA_START_INVISIBLE_BEFORE:
  166. +                 STRCPY(code, "NFA_START_INVISIBLE_BEFORE"); break;
  167.       case NFA_END_INVISIBLE:        STRCPY(code, "NFA_END_INVISIBLE"); break;
  168.   
  169.       case NFA_COMPOSING:        STRCPY(code, "NFA_COMPOSING"); break;
  170. ***************
  171. *** 2237,2243 ****
  172.       if (nfa_calc_size == FALSE)
  173.       {
  174.       /* Allocate space for the stack. Max states on the stack : nstate */
  175. !     stack = (Frag_T *) lalloc((nstate + 1) * sizeof(Frag_T), TRUE);
  176.       stackp = stack;
  177.       stack_end = stack + (nstate + 1);
  178.       }
  179. --- 2253,2259 ----
  180.       if (nfa_calc_size == FALSE)
  181.       {
  182.       /* Allocate space for the stack. Max states on the stack : nstate */
  183. !     stack = (Frag_T *)lalloc((nstate + 1) * sizeof(Frag_T), TRUE);
  184.       stackp = stack;
  185.       stack_end = stack + (nstate + 1);
  186.       }
  187. ***************
  188. *** 2370,2377 ****
  189. --- 2386,2397 ----
  190.   
  191.       case NFA_PREV_ATOM_NO_WIDTH:
  192.       case NFA_PREV_ATOM_NO_WIDTH_NEG:
  193. +     case NFA_PREV_ATOM_JUST_BEFORE:
  194. +     case NFA_PREV_ATOM_JUST_BEFORE_NEG:
  195.           /* The \@= operator: match the preceding atom with zero width.
  196.            * The \@! operator: no match for the preceding atom.
  197. +          * The \@<= operator: match for the preceding atom.
  198. +          * The \@<! operator: no match for the preceding atom.
  199.            * Surrounds the preceding atom with START_INVISIBLE and
  200.            * END_INVISIBLE, similarly to MOPEN. */
  201.   
  202. ***************
  203. *** 2389,2399 ****
  204.           s = new_state(NFA_START_INVISIBLE, e.start, s1);
  205.           if (s == NULL)
  206.           goto theend;
  207. !         if (*p == NFA_PREV_ATOM_NO_WIDTH_NEG)
  208.           {
  209.           s->negated = TRUE;
  210.           s1->negated = TRUE;
  211.           }
  212.   
  213.           PUSH(frag(s, list1(&s1->out)));
  214.           break;
  215. --- 2409,2426 ----
  216.           s = new_state(NFA_START_INVISIBLE, e.start, s1);
  217.           if (s == NULL)
  218.           goto theend;
  219. !         if (*p == NFA_PREV_ATOM_NO_WIDTH_NEG
  220. !                        || *p == NFA_PREV_ATOM_JUST_BEFORE_NEG)
  221.           {
  222.           s->negated = TRUE;
  223.           s1->negated = TRUE;
  224.           }
  225. +         if (*p == NFA_PREV_ATOM_JUST_BEFORE
  226. +                        || *p == NFA_PREV_ATOM_JUST_BEFORE_NEG)
  227. +         {
  228. +         s->val = *++p; /* get the count */
  229. +         ++s->c; /* NFA_START_INVISIBLE -> NFA_START_INVISIBLE_BEFORE */
  230. +         }
  231.   
  232.           PUSH(frag(s, list1(&s1->out)));
  233.           break;
  234. ***************
  235. *** 3307,3327 ****
  236.       return val == pos;
  237.   }
  238.   
  239. ! static int nfa_regmatch __ARGS((nfa_state_T *start, regsub_T *submatch, regsub_T *m));
  240.   
  241.   /*
  242.    * Main matching routine.
  243.    *
  244.    * Run NFA to determine whether it matches reginput.
  245.    *
  246.    * Return TRUE if there is a match, FALSE otherwise.
  247.    * Note: Caller must ensure that: start != NULL.
  248.    */
  249.       static int
  250. ! nfa_regmatch(start, submatch, m)
  251.       nfa_state_T        *start;
  252.       regsub_T        *submatch;
  253.       regsub_T        *m;
  254.   {
  255.       int        result;
  256.       int        size = 0;
  257. --- 3334,3357 ----
  258.       return val == pos;
  259.   }
  260.   
  261. ! static int nfa_regmatch __ARGS((nfa_state_T *start, regsub_T *submatch, regsub_T *m, save_se_T *endp));
  262.   
  263.   /*
  264.    * Main matching routine.
  265.    *
  266.    * Run NFA to determine whether it matches reginput.
  267.    *
  268. +  * When "endp" is not NULL it is a required end-of-match position.
  269. +  *
  270.    * Return TRUE if there is a match, FALSE otherwise.
  271.    * Note: Caller must ensure that: start != NULL.
  272.    */
  273.       static int
  274. ! nfa_regmatch(start, submatch, m, endp)
  275.       nfa_state_T        *start;
  276.       regsub_T        *submatch;
  277.       regsub_T        *m;
  278. +     save_se_T        *endp;
  279.   {
  280.       int        result;
  281.       int        size = 0;
  282. ***************
  283. *** 3532,3547 ****
  284.             }
  285.   
  286.           case NFA_END_INVISIBLE:
  287. !         /* This is only encountered after a NFA_START_INVISIBLE node.
  288. !          * They surround a zero-width group, used with "\@=" and "\&".
  289.            * If we got here, it means that the current "invisible" group
  290.            * finished successfully, so return control to the parent
  291.            * nfa_regmatch().  Submatches are stored in *m, and used in
  292.            * the parent call. */
  293.           if (start->c == NFA_MOPEN + 0)
  294.               addstate_here(thislist, t->state->out, &t->sub, &listidx);
  295.           else
  296.           {
  297.               /* do not set submatches for \@! */
  298.               if (!t->state->negated)
  299.               /* TODO: only copy positions in use. */
  300. --- 3562,3603 ----
  301.             }
  302.   
  303.           case NFA_END_INVISIBLE:
  304. !         /* This is only encountered after a NFA_START_INVISIBLE or
  305. !          * NFA_START_INVISIBLE_BEFORE node.
  306. !          * They surround a zero-width group, used with "\@=", "\&",
  307. !          * "\@!", "\@<=" and "\@<!".
  308.            * If we got here, it means that the current "invisible" group
  309.            * finished successfully, so return control to the parent
  310.            * nfa_regmatch().  Submatches are stored in *m, and used in
  311.            * the parent call. */
  312.           if (start->c == NFA_MOPEN + 0)
  313. +             /* TODO: do we ever get here? */
  314.               addstate_here(thislist, t->state->out, &t->sub, &listidx);
  315.           else
  316.           {
  317. + #ifdef ENABLE_LOG
  318. +             if (endp != NULL)
  319. +             {
  320. +             if (REG_MULTI)
  321. +                 fprintf(log_fd, "Current lnum: %d, endp lnum: %d; current col: %d, endp col: %d\n",
  322. +                     (int)reglnum,
  323. +                     (int)endp->se_u.pos.lnum,
  324. +                     (int)(reginput - regline),
  325. +                     endp->se_u.pos.col);
  326. +             else
  327. +                 fprintf(log_fd, "Current col: %d, endp col: %d\n",
  328. +                     (int)(reginput - regline),
  329. +                     (int)(endp->se_u.ptr - reginput));
  330. +             }
  331. + #endif
  332. +             /* It's only a match if it ends at "endp" */
  333. +             if (endp != NULL && (REG_MULTI
  334. +                 ? (reglnum != endp->se_u.pos.lnum
  335. +                 || (int)(reginput - regline)
  336. +                             != endp->se_u.pos.col)
  337. +                 : reginput != endp->se_u.ptr))
  338. +             break;
  339.               /* do not set submatches for \@! */
  340.               if (!t->state->negated)
  341.               /* TODO: only copy positions in use. */
  342. ***************
  343. *** 3551,3561 ****
  344.           break;
  345.   
  346.           case NFA_START_INVISIBLE:
  347.             {
  348. !         char_u    *save_reginput = reginput;
  349. !         char_u    *save_regline = regline;
  350. !         int    save_reglnum = reglnum;
  351. !         int    save_nfa_match = nfa_match;
  352.   
  353.           /* Call nfa_regmatch() to check if the current concat matches
  354.            * at this position. The concat ends with the node
  355. --- 3607,3676 ----
  356.           break;
  357.   
  358.           case NFA_START_INVISIBLE:
  359. +         case NFA_START_INVISIBLE_BEFORE:
  360.             {
  361. !         char_u        *save_reginput = reginput;
  362. !         char_u        *save_regline = regline;
  363. !         int        save_reglnum = reglnum;
  364. !         int        save_nfa_match = nfa_match;
  365. !         save_se_T   endpos;
  366. !         save_se_T   *endposp = NULL;
  367. !         if (t->state->c == NFA_START_INVISIBLE_BEFORE)
  368. !         {
  369. !             /* The recursive match must end at the current position. */
  370. !             endposp = &endpos;
  371. !             if (REG_MULTI)
  372. !             {
  373. !             endpos.se_u.pos.col = (int)(reginput - regline);
  374. !             endpos.se_u.pos.lnum = reglnum;
  375. !             }
  376. !             else
  377. !             endpos.se_u.ptr = reginput;
  378. !             /* Go back the specified number of bytes, or as far as the
  379. !              * start of the previous line, to try matching "\@<=" or
  380. !              * not matching "\@<!". */
  381. !             if (t->state->val <= 0)
  382. !             {
  383. !             if (REG_MULTI)
  384. !             {
  385. !                 regline = reg_getline(--reglnum);
  386. !                 if (regline == NULL)
  387. !                 /* can't go before the first line */
  388. !                 regline = reg_getline(++reglnum);
  389. !             }
  390. !             reginput = regline;
  391. !             }
  392. !             else
  393. !             {
  394. !             if (REG_MULTI
  395. !                 && (int)(reginput - regline) < t->state->val)
  396. !             {
  397. !                 /* Not enough bytes in this line, go to end of
  398. !                  * previous line. */
  399. !                 regline = reg_getline(--reglnum);
  400. !                 if (regline == NULL)
  401. !                 {
  402. !                 /* can't go before the first line */
  403. !                 regline = reg_getline(++reglnum);
  404. !                 reginput = regline;
  405. !                 }
  406. !                 else
  407. !                 reginput = regline + STRLEN(regline);
  408. !             }
  409. !             if ((int)(reginput - regline) >= t->state->val)
  410. !             {
  411. !                 reginput -= t->state->val;
  412. ! #ifdef FEAT_MBYTE
  413. !                 if (has_mbyte)
  414. !                 reginput -= mb_head_off(regline, reginput);
  415. ! #endif
  416. !             }
  417. !             else
  418. !                 reginput = regline;
  419. !             }
  420. !         }
  421.   
  422.           /* Call nfa_regmatch() to check if the current concat matches
  423.            * at this position. The concat ends with the node
  424. ***************
  425. *** 3579,3585 ****
  426.            * recursion. */
  427.           nfa_save_listids(start, listids);
  428.           nfa_set_null_listids(start);
  429. !         result = nfa_regmatch(t->state->out, submatch, m);
  430.           nfa_set_neg_listids(start);
  431.           nfa_restore_listids(start, listids);
  432.   
  433. --- 3694,3700 ----
  434.            * recursion. */
  435.           nfa_save_listids(start, listids);
  436.           nfa_set_null_listids(start);
  437. !         result = nfa_regmatch(t->state->out, submatch, m, endposp);
  438.           nfa_set_neg_listids(start);
  439.           nfa_restore_listids(start, listids);
  440.   
  441. ***************
  442. *** 4120,4130 ****
  443.        * matters!
  444.        * Do not add the start state in recursive calls of nfa_regmatch(),
  445.        * because recursive calls should only start in the first position.
  446.        * Also don't start a match past the first line. */
  447. !     if (nfa_match == FALSE && start->c == NFA_MOPEN + 0
  448. !         && reglnum == 0 && clen != 0
  449. !         && (ireg_maxcol == 0
  450. !                   || (colnr_T)(reginput - regline) < ireg_maxcol))
  451.       {
  452.   #ifdef ENABLE_LOG
  453.           fprintf(log_fd, "(---) STARTSTATE\n");
  454. --- 4235,4255 ----
  455.        * matters!
  456.        * Do not add the start state in recursive calls of nfa_regmatch(),
  457.        * because recursive calls should only start in the first position.
  458. +      * Unless "endp" is not NULL, then we match the end position.
  459.        * Also don't start a match past the first line. */
  460. !     if (nfa_match == FALSE
  461. !         && ((start->c == NFA_MOPEN + 0
  462. !             && reglnum == 0
  463. !             && clen != 0
  464. !             && (ireg_maxcol == 0
  465. !                 || (colnr_T)(reginput - regline) < ireg_maxcol))
  466. !             || (endp != NULL
  467. !             && (REG_MULTI
  468. !                 ? (reglnum < endp->se_u.pos.lnum
  469. !                    || (reglnum == endp->se_u.pos.lnum
  470. !                        && (int)(reginput - regline)
  471. !                                < endp->se_u.pos.col))
  472. !                 : reginput < endp->se_u.ptr))))
  473.       {
  474.   #ifdef ENABLE_LOG
  475.           fprintf(log_fd, "(---) STARTSTATE\n");
  476. ***************
  477. *** 4148,4154 ****
  478.        * finish. */
  479.       if (clen != 0)
  480.           reginput += clen;
  481. !     else if (go_to_nextline)
  482.           reg_nextline();
  483.       else
  484.           break;
  485. --- 4273,4280 ----
  486.        * finish. */
  487.       if (clen != 0)
  488.           reginput += clen;
  489. !     else if (go_to_nextline || (endp != NULL && REG_MULTI
  490. !                         && reglnum < endp->se_u.pos.lnum))
  491.           reg_nextline();
  492.       else
  493.           break;
  494. ***************
  495. *** 4225,4231 ****
  496.       sub.in_use = 0;
  497.       m.in_use = 0;
  498.   
  499. !     if (nfa_regmatch(start, &sub, &m) == FALSE)
  500.       return 0;
  501.   
  502.       cleanup_subexpr();
  503. --- 4351,4357 ----
  504.       sub.in_use = 0;
  505.       m.in_use = 0;
  506.   
  507. !     if (nfa_regmatch(start, &sub, &m, NULL) == FALSE)
  508.       return 0;
  509.   
  510.       cleanup_subexpr();
  511. *** ../vim-7.3.1087/src/testdir/test64.in    2013-06-01 14:42:51.000000000 +0200
  512. --- src/testdir/test64.in    2013-06-01 18:45:09.000000000 +0200
  513. ***************
  514. *** 363,374 ****
  515.   :call add(tl, [2, '\(a\)\(b\)\(c\)\(dd\)\(e\)\(f\)\(g\)\(h\)\(i\)\1\2\3\4\5\6\7\8\9', 'xabcddefghiabcddefghix', 'abcddefghiabcddefghi', 'a', 'b', 'c', 'dd', 'e', 'f', 'g', 'h', 'i'])
  516.   :"
  517.   :"""" Look-behind with limit
  518. ! :call add(tl, [0, '<\@<=span.', 'xxspanxx<spanyyy', 'spany'])
  519. ! :call add(tl, [0, '<\@1<=span.', 'xxspanxx<spanyyy', 'spany'])
  520. ! :call add(tl, [0, '<\@2<=span.', 'xxspanxx<spanyyy', 'spany'])
  521. ! :call add(tl, [0, '\(<<\)\@<=span.', 'xxspanxxxx<spanxx<<spanyyy', 'spany', '<<'])
  522. ! :call add(tl, [0, '\(<<\)\@1<=span.', 'xxspanxxxx<spanxx<<spanyyy'])
  523. ! :call add(tl, [0, '\(<<\)\@2<=span.', 'xxspanxxxx<spanxx<<spanyyy', 'spany', '<<'])
  524.   :"
  525.   :"""" "\_" prepended negated collection matches EOL
  526.   :call add(tl, [2, '\_[^8-9]\+', "asfi\n9888", "asfi\n"])
  527. --- 363,375 ----
  528.   :call add(tl, [2, '\(a\)\(b\)\(c\)\(dd\)\(e\)\(f\)\(g\)\(h\)\(i\)\1\2\3\4\5\6\7\8\9', 'xabcddefghiabcddefghix', 'abcddefghiabcddefghi', 'a', 'b', 'c', 'dd', 'e', 'f', 'g', 'h', 'i'])
  529.   :"
  530.   :"""" Look-behind with limit
  531. ! :call add(tl, [2, '<\@<=span.', 'xxspanxx<spanyyy', 'spany'])
  532. ! :call add(tl, [2, '<\@1<=span.', 'xxspanxx<spanyyy', 'spany'])
  533. ! :call add(tl, [2, '<\@2<=span.', 'xxspanxx<spanyyy', 'spany'])
  534. ! :call add(tl, [2, '\(<<\)\@<=span.', 'xxspanxxxx<spanxx<<spanyyy', 'spany', '<<'])
  535. ! :call add(tl, [2, '\(<<\)\@1<=span.', 'xxspanxxxx<spanxx<<spanyyy'])
  536. ! :call add(tl, [2, '\(<<\)\@2<=span.', 'xxspanxxxx<spanxx<<spanyyy', 'spany', '<<'])
  537. ! :call add(tl, [2, '\(foo\)\@<!bar.', 'xx foobar1 xbar2 xx', 'bar2'])
  538.   :"
  539.   :"""" "\_" prepended negated collection matches EOL
  540.   :call add(tl, [2, '\_[^8-9]\+', "asfi\n9888", "asfi\n"])
  541. ***************
  542. *** 514,521 ****
  543.   asdfasd<yyy
  544.   xxstart1
  545.   asdfasd<yy
  546. ! xxxxstart2
  547.   asdfasd<yy
  548. ! xxxstart3
  549.   
  550.   Results of test64:
  551. --- 515,522 ----
  552.   asdfasd<yyy
  553.   xxstart1
  554.   asdfasd<yy
  555. ! xxxstart2
  556.   asdfasd<yy
  557. ! xxstart3
  558.   
  559.   Results of test64:
  560. *** ../vim-7.3.1087/src/testdir/test64.ok    2013-06-01 14:42:51.000000000 +0200
  561. --- src/testdir/test64.ok    2013-06-01 18:55:43.000000000 +0200
  562. ***************
  563. *** 817,832 ****
  564. --- 817,841 ----
  565.   OK 2 - \(a\)\(b\)\(c\)\(dd\)\(e\)\(f\)\(g\)\(h\)\(i\)\1\2\3\4\5\6\7\8\9
  566.   OK 0 - <\@<=span.
  567.   OK 1 - <\@<=span.
  568. + OK 2 - <\@<=span.
  569.   OK 0 - <\@1<=span.
  570.   OK 1 - <\@1<=span.
  571. + OK 2 - <\@1<=span.
  572.   OK 0 - <\@2<=span.
  573.   OK 1 - <\@2<=span.
  574. + OK 2 - <\@2<=span.
  575.   OK 0 - \(<<\)\@<=span.
  576.   OK 1 - \(<<\)\@<=span.
  577. + OK 2 - \(<<\)\@<=span.
  578.   OK 0 - \(<<\)\@1<=span.
  579.   OK 1 - \(<<\)\@1<=span.
  580. + OK 2 - \(<<\)\@1<=span.
  581.   OK 0 - \(<<\)\@2<=span.
  582.   OK 1 - \(<<\)\@2<=span.
  583. + OK 2 - \(<<\)\@2<=span.
  584. + OK 0 - \(foo\)\@<!bar.
  585. + OK 1 - \(foo\)\@<!bar.
  586. + OK 2 - \(foo\)\@<!bar.
  587.   OK 0 - \_[^8-9]\+
  588.   OK 1 - \_[^8-9]\+
  589.   OK 2 - \_[^8-9]\+
  590. ***************
  591. *** 844,850 ****
  592.   <T="7">Ac 7</Title>
  593.   ghi
  594.   
  595. ! xxxstart3
  596.   -0-
  597.   ffo
  598.   bob
  599. --- 853,859 ----
  600.   <T="7">Ac 7</Title>
  601.   ghi
  602.   
  603. ! xxstart3
  604.   -0-
  605.   ffo
  606.   bob
  607. *** ../vim-7.3.1087/src/version.c    2013-06-01 14:42:51.000000000 +0200
  608. --- src/version.c    2013-06-01 18:37:11.000000000 +0200
  609. ***************
  610. *** 730,731 ****
  611. --- 730,733 ----
  612.   {   /* Add new patch number below this line */
  613. + /**/
  614. +     1088,
  615.   /**/
  616.  
  617. -- 
  618. Seen it all, done it all, can't remember most of it.
  619.  
  620.  /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
  621. ///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
  622. \\\  an exciting new programming language -- http://www.Zimbu.org        ///
  623.  \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///
  624.