diff --git a/7.3.945 b/7.3.945
new file mode 100644
index 0000000..f3bfb2f
--- /dev/null
+++ b/7.3.945
@@ -0,0 +1,648 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.945
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.945
+Problem:    Python: List of buffers is not very useful.
+Solution:   Make vim.buffers a map. No iterator yet. (ZyX)
+Files:	    runtime/doc/if_pyth.txt, src/if_py_both.h, src/if_python3.c,
+	    src/if_python.c, src/testdir/test86.ok, src/testdir/test87.ok
+
+
+*** ../vim-7.3.944/runtime/doc/if_pyth.txt	2013-05-12 19:30:27.000000000 +0200
+--- runtime/doc/if_pyth.txt	2013-05-15 13:34:06.000000000 +0200
+***************
+*** 209,220 ****
+  	to which the variables referred.
+  
+  vim.buffers						*python-buffers*
+! 	A sequence object providing access to the list of vim buffers.  The
+  	object supports the following operations: >
+  	    :py b = vim.buffers[i]	# Indexing (read-only)
+  	    :py b in vim.buffers	# Membership test
+  	    :py n = len(vim.buffers)	# Number of elements
+- 	    :py for b in vim.buffers:	# Sequential access
+  <
+  vim.windows						*python-windows*
+  	A sequence object providing access to the list of vim windows.  The
+--- 209,219 ----
+  	to which the variables referred.
+  
+  vim.buffers						*python-buffers*
+! 	A mapping object providing access to the list of vim buffers.  The
+  	object supports the following operations: >
+  	    :py b = vim.buffers[i]	# Indexing (read-only)
+  	    :py b in vim.buffers	# Membership test
+  	    :py n = len(vim.buffers)	# Number of elements
+  <
+  vim.windows						*python-windows*
+  	A sequence object providing access to the list of vim windows.  The
+*** ../vim-7.3.944/src/if_py_both.h	2013-05-12 21:16:17.000000000 +0200
+--- src/if_py_both.h	2013-05-15 13:34:06.000000000 +0200
+***************
+*** 534,549 ****
+   * Buffer list object - Implementation
+   */
+  
+! static PyTypeObject BufListType;
+! static PySequenceMethods BufListAsSeq;
+  
+  typedef struct
+  {
+      PyObject_HEAD
+! } BufListObject;
+  
+      static PyInt
+! BufListLength(PyObject *self UNUSED)
+  {
+      buf_T	*b = firstbuf;
+      PyInt	n = 0;
+--- 534,548 ----
+   * Buffer list object - Implementation
+   */
+  
+! static PyTypeObject BufMapType;
+  
+  typedef struct
+  {
+      PyObject_HEAD
+! } BufMapObject;
+  
+      static PyInt
+! BufMapLength(PyObject *self UNUSED)
+  {
+      buf_T	*b = firstbuf;
+      PyInt	n = 0;
+***************
+*** 558,577 ****
+  }
+  
+      static PyObject *
+! BufListItem(PyObject *self UNUSED, PyInt n)
+  {
+!     buf_T *b;
+  
+!     for (b = firstbuf; b; b = b->b_next, --n)
+      {
+! 	if (n == 0)
+! 	    return BufferNew(b);
+      }
+  
+!     PyErr_SetString(PyExc_IndexError, _("no such buffer"));
+!     return NULL;
+  }
+  
+  typedef struct pylinkedlist_S {
+      struct pylinkedlist_S	*pll_next;
+      struct pylinkedlist_S	*pll_prev;
+--- 557,597 ----
+  }
+  
+      static PyObject *
+! BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
+  {
+!     buf_T	*b;
+!     int		bnr;
+  
+! #if PY_MAJOR_VERSION < 3
+!     if (PyInt_Check(keyObject))
+! 	bnr = PyInt_AsLong(keyObject);
+!     else
+! #endif
+!     if (PyLong_Check(keyObject))
+! 	bnr = PyLong_AsLong(keyObject);
+!     else
+      {
+! 	PyErr_SetString(PyExc_ValueError, _("key must be integer"));
+! 	return NULL;
+      }
+  
+!     b = buflist_findnr(bnr);
+! 
+!     if (b)
+! 	return BufferNew(b);
+!     else
+!     {
+! 	PyErr_SetString(PyExc_KeyError, _("no such buffer"));
+! 	return NULL;
+!     }
+  }
+  
++ static PyMappingMethods BufMapAsMapping = {
++     (lenfunc)       BufMapLength,
++     (binaryfunc)    BufMapItem,
++     (objobjargproc) 0,
++ };
++ 
+  typedef struct pylinkedlist_S {
+      struct pylinkedlist_S	*pll_next;
+      struct pylinkedlist_S	*pll_prev;
+***************
+*** 3401,3411 ****
+      WindowType.tp_setattr = WindowSetattr;
+  #endif
+  
+!     vim_memset(&BufListType, 0, sizeof(BufListType));
+!     BufListType.tp_name = "vim.bufferlist";
+!     BufListType.tp_basicsize = sizeof(BufListObject);
+!     BufListType.tp_as_sequence = &BufListAsSeq;
+!     BufListType.tp_flags = Py_TPFLAGS_DEFAULT;
+      BufferType.tp_doc = "vim buffer list";
+  
+      vim_memset(&WinListType, 0, sizeof(WinListType));
+--- 3421,3431 ----
+      WindowType.tp_setattr = WindowSetattr;
+  #endif
+  
+!     vim_memset(&BufMapType, 0, sizeof(BufMapType));
+!     BufMapType.tp_name = "vim.bufferlist";
+!     BufMapType.tp_basicsize = sizeof(BufMapObject);
+!     BufMapType.tp_as_mapping = &BufMapAsMapping;
+!     BufMapType.tp_flags = Py_TPFLAGS_DEFAULT;
+      BufferType.tp_doc = "vim buffer list";
+  
+      vim_memset(&WinListType, 0, sizeof(WinListType));
+*** ../vim-7.3.944/src/if_python3.c	2013-05-12 21:16:17.000000000 +0200
+--- src/if_python3.c	2013-05-15 13:34:06.000000000 +0200
+***************
+*** 1272,1293 ****
+      }
+  }
+  
+- /* Buffer list object - Definitions
+-  */
+- 
+- static PySequenceMethods BufListAsSeq = {
+-     (lenfunc)		BufListLength,	    /* sq_length,    len(x)   */
+-     (binaryfunc)	0,		    /* sq_concat,    x+y      */
+-     (ssizeargfunc)	0,		    /* sq_repeat,    x*n      */
+-     (ssizeargfunc)	BufListItem,	    /* sq_item,      x[i]     */
+-     0,					    /* was_sq_slice,	 x[i:j]   */
+-     (ssizeobjargproc)	0,		    /* sq_as_item,  x[i]=v   */
+-     0,					    /* sq_ass_slice, x[i:j]=v */
+-     0,					    /* sq_contains */
+-     0,					    /* sq_inplace_concat */
+-     0,					    /* sq_inplace_repeat */
+- };
+- 
+  /* Window object - Implementation
+   */
+  
+--- 1272,1277 ----
+***************
+*** 1512,1520 ****
+  }
+  #endif
+  
+! static BufListObject TheBufferList =
+  {
+!     PyObject_HEAD_INIT(&BufListType)
+  };
+  
+  static WinListObject TheWindowList =
+--- 1496,1504 ----
+  }
+  #endif
+  
+! static BufMapObject TheBufferMap =
+  {
+!     PyObject_HEAD_INIT(&BufMapType)
+  };
+  
+  static WinListObject TheWindowList =
+***************
+*** 1538,1544 ****
+      PyType_Ready(&BufferType);
+      PyType_Ready(&RangeType);
+      PyType_Ready(&WindowType);
+!     PyType_Ready(&BufListType);
+      PyType_Ready(&WinListType);
+      PyType_Ready(&CurrentType);
+      PyType_Ready(&DictionaryType);
+--- 1522,1528 ----
+      PyType_Ready(&BufferType);
+      PyType_Ready(&RangeType);
+      PyType_Ready(&WindowType);
+!     PyType_Ready(&BufMapType);
+      PyType_Ready(&WinListType);
+      PyType_Ready(&CurrentType);
+      PyType_Ready(&DictionaryType);
+***************
+*** 1557,1564 ****
+      Py_INCREF(VimError);
+  
+      PyModule_AddObject(mod, "error", VimError);
+!     Py_INCREF((PyObject *)(void *)&TheBufferList);
+!     PyModule_AddObject(mod, "buffers", (PyObject *)(void *)&TheBufferList);
+      Py_INCREF((PyObject *)(void *)&TheCurrent);
+      PyModule_AddObject(mod, "current", (PyObject *)(void *)&TheCurrent);
+      Py_INCREF((PyObject *)(void *)&TheWindowList);
+--- 1541,1548 ----
+      Py_INCREF(VimError);
+  
+      PyModule_AddObject(mod, "error", VimError);
+!     Py_INCREF((PyObject *)(void *)&TheBufferMap);
+!     PyModule_AddObject(mod, "buffers", (PyObject *)(void *)&TheBufferMap);
+      Py_INCREF((PyObject *)(void *)&TheCurrent);
+      PyModule_AddObject(mod, "current", (PyObject *)(void *)&TheCurrent);
+      Py_INCREF((PyObject *)(void *)&TheWindowList);
+*** ../vim-7.3.944/src/if_python.c	2013-05-12 20:36:09.000000000 +0200
+--- src/if_python.c	2013-05-15 13:34:06.000000000 +0200
+***************
+*** 1131,1154 ****
+  		      &((RangeObject *)(self))->end);
+  }
+  
+- /* Buffer list object - Definitions
+-  */
+- 
+- static PySequenceMethods BufListAsSeq = {
+-     (PyInquiry)		BufListLength,	    /* sq_length,    len(x)   */
+-     (binaryfunc)	0,		    /* sq_concat,    x+y      */
+-     (PyIntArgFunc)	0,		    /* sq_repeat,    x*n      */
+-     (PyIntArgFunc)	BufListItem,	    /* sq_item,      x[i]     */
+-     (PyIntIntArgFunc)	0,		    /* sq_slice,     x[i:j]   */
+-     (PyIntObjArgProc)	0,		    /* sq_ass_item,  x[i]=v   */
+-     (PyIntIntObjArgProc) 0,		    /* sq_ass_slice, x[i:j]=v */
+-     (objobjproc)	0,
+- #if PY_MAJOR_VERSION >= 2
+-     (binaryfunc)	0,
+-     0,
+- #endif
+- };
+- 
+  /* Window object - Implementation
+   */
+  
+--- 1131,1136 ----
+***************
+*** 1212,1220 ****
+  }
+  #endif
+  
+! static BufListObject TheBufferList =
+  {
+!     PyObject_HEAD_INIT(&BufListType)
+  };
+  
+  static WinListObject TheWindowList =
+--- 1194,1202 ----
+  }
+  #endif
+  
+! static BufMapObject TheBufferMap =
+  {
+!     PyObject_HEAD_INIT(&BufMapType)
+  };
+  
+  static WinListObject TheWindowList =
+***************
+*** 1240,1246 ****
+      PyType_Ready(&BufferType);
+      PyType_Ready(&RangeType);
+      PyType_Ready(&WindowType);
+!     PyType_Ready(&BufListType);
+      PyType_Ready(&WinListType);
+      PyType_Ready(&CurrentType);
+      PyType_Ready(&OptionsType);
+--- 1222,1228 ----
+      PyType_Ready(&BufferType);
+      PyType_Ready(&RangeType);
+      PyType_Ready(&WindowType);
+!     PyType_Ready(&BufMapType);
+      PyType_Ready(&WinListType);
+      PyType_Ready(&CurrentType);
+      PyType_Ready(&OptionsType);
+***************
+*** 1254,1260 ****
+      VimError = Py_BuildValue("s", "vim.error");
+  
+      PyDict_SetItemString(dict, "error", VimError);
+!     PyDict_SetItemString(dict, "buffers", (PyObject *)(void *)&TheBufferList);
+      PyDict_SetItemString(dict, "current", (PyObject *)(void *)&TheCurrent);
+      PyDict_SetItemString(dict, "windows", (PyObject *)(void *)&TheWindowList);
+      tmp = DictionaryNew(&globvardict);
+--- 1236,1242 ----
+      VimError = Py_BuildValue("s", "vim.error");
+  
+      PyDict_SetItemString(dict, "error", VimError);
+!     PyDict_SetItemString(dict, "buffers", (PyObject *)(void *)&TheBufferMap);
+      PyDict_SetItemString(dict, "current", (PyObject *)(void *)&TheCurrent);
+      PyDict_SetItemString(dict, "windows", (PyObject *)(void *)&TheWindowList);
+      tmp = DictionaryNew(&globvardict);
+*** ../vim-7.3.944/src/testdir/test86.ok	2013-05-12 21:16:17.000000000 +0200
+--- src/testdir/test86.ok	2013-05-15 13:34:06.000000000 +0200
+***************
+*** 226,238 ****
+    p/bopts1: False
+    inv: 2! ValueError
+    G: 0
+!   W: 1:1 2:1 3:0 4:0
+!   B: 1:1 2:1 3:0 4:0
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: 0
+!   W: 1:1 2:1 3:0 4:0
+!   B: 1:1 2:1 3:0 4:0
+  >>> iminsert
+    p/gopts1! KeyError
+    inv: 3! KeyError
+--- 226,238 ----
+    p/bopts1: False
+    inv: 2! ValueError
+    G: 0
+!   W: 1:0 2:1 3:0 4:1
+!   B: 1:0 2:1 3:0 4:1
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: 0
+!   W: 1:0 2:1 3:0 4:1
+!   B: 1:0 2:1 3:0 4:1
+  >>> iminsert
+    p/gopts1! KeyError
+    inv: 3! KeyError
+***************
+*** 244,256 ****
+    wopts3! KeyError
+    p/bopts1: 2
+    G: 1
+!   W: 1:2 2:1 3:0 4:2
+!   B: 1:2 2:1 3:0 4:2
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: 1
+!   W: 1:2 2:1 3:0 4:2
+!   B: 1:2 2:1 3:0 4:2
+  >>> omnifunc
+    p/gopts1! KeyError
+    inv: 1! KeyError
+--- 244,256 ----
+    wopts3! KeyError
+    p/bopts1: 2
+    G: 1
+!   W: 1:0 2:2 3:2 4:1
+!   B: 1:0 2:2 3:2 4:1
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: 1
+!   W: 1:0 2:2 3:2 4:1
+!   B: 1:0 2:2 3:2 4:1
+  >>> omnifunc
+    p/gopts1! KeyError
+    inv: 1! KeyError
+***************
+*** 263,275 ****
+    p/bopts1: ''
+    inv: 1! ValueError
+    G: ''
+!   W: 1:'B' 2:'C' 3:'A' 4:''
+!   B: 1:'B' 2:'C' 3:'A' 4:''
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: ''
+!   W: 1:'B' 2:'C' 3:'A' 4:''
+!   B: 1:'B' 2:'C' 3:'A' 4:''
+  >>> preserveindent
+    p/gopts1! KeyError
+    inv: 2! KeyError
+--- 263,275 ----
+    p/bopts1: ''
+    inv: 1! ValueError
+    G: ''
+!   W: 1:'A' 2:'B' 3:'' 4:'C'
+!   B: 1:'A' 2:'B' 3:'' 4:'C'
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: ''
+!   W: 1:'A' 2:'B' 3:'' 4:'C'
+!   B: 1:'A' 2:'B' 3:'' 4:'C'
+  >>> preserveindent
+    p/gopts1! KeyError
+    inv: 2! KeyError
+***************
+*** 282,294 ****
+    p/bopts1: False
+    inv: 2! ValueError
+    G: 0
+!   W: 1:1 2:1 3:0 4:0
+!   B: 1:1 2:1 3:0 4:0
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: 0
+!   W: 1:1 2:1 3:0 4:0
+!   B: 1:1 2:1 3:0 4:0
+  >>> path
+    p/gopts1: '.,/usr/include,,'
+    inv: 0! ValueError
+--- 282,294 ----
+    p/bopts1: False
+    inv: 2! ValueError
+    G: 0
+!   W: 1:0 2:1 3:0 4:1
+!   B: 1:0 2:1 3:0 4:1
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: 0
+!   W: 1:0 2:1 3:0 4:1
+!   B: 1:0 2:1 3:0 4:1
+  >>> path
+    p/gopts1: '.,/usr/include,,'
+    inv: 0! ValueError
+***************
+*** 300,311 ****
+    p/bopts1: None
+    inv: 0! ValueError
+    G: '.,,'
+!   W: 1:',,' 2:'.' 3:'.,,' 4:'.,,'
+!   B: 1:',,' 2:'.' 3:'.,,' 4:'.,,'
+    del wopts3! KeyError
+    G: '.,,'
+!   W: 1:',,' 2:'.,,' 3:'.,,' 4:'.,,'
+!   B: 1:',,' 2:'.,,' 3:'.,,' 4:'.,,'
+  First line
+  First line
+  def
+--- 300,311 ----
+    p/bopts1: None
+    inv: 0! ValueError
+    G: '.,,'
+!   W: 1:'.,,' 2:',,' 3:'.,,' 4:'.'
+!   B: 1:'.,,' 2:',,' 3:'.,,' 4:'.'
+    del wopts3! KeyError
+    G: '.,,'
+!   W: 1:'.,,' 2:',,' 3:'.,,' 4:'.,,'
+!   B: 1:'.,,' 2:',,' 3:'.,,' 4:'.,,'
+  First line
+  First line
+  def
+*** ../vim-7.3.944/src/testdir/test87.ok	2013-05-12 21:16:17.000000000 +0200
+--- src/testdir/test87.ok	2013-05-15 13:34:06.000000000 +0200
+***************
+*** 215,227 ****
+    p/bopts1: False
+    inv: 2! ValueError
+    G: 0
+!   W: 1:1 2:1 3:0 4:0
+!   B: 1:1 2:1 3:0 4:0
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: 0
+!   W: 1:1 2:1 3:0 4:0
+!   B: 1:1 2:1 3:0 4:0
+  >>> iminsert
+    p/gopts1! KeyError
+    inv: 3! KeyError
+--- 215,227 ----
+    p/bopts1: False
+    inv: 2! ValueError
+    G: 0
+!   W: 1:0 2:1 3:0 4:1
+!   B: 1:0 2:1 3:0 4:1
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: 0
+!   W: 1:0 2:1 3:0 4:1
+!   B: 1:0 2:1 3:0 4:1
+  >>> iminsert
+    p/gopts1! KeyError
+    inv: 3! KeyError
+***************
+*** 233,245 ****
+    wopts3! KeyError
+    p/bopts1: 2
+    G: 1
+!   W: 1:2 2:1 3:0 4:2
+!   B: 1:2 2:1 3:0 4:2
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: 1
+!   W: 1:2 2:1 3:0 4:2
+!   B: 1:2 2:1 3:0 4:2
+  >>> omnifunc
+    p/gopts1! KeyError
+    inv: 1! KeyError
+--- 233,245 ----
+    wopts3! KeyError
+    p/bopts1: 2
+    G: 1
+!   W: 1:0 2:2 3:2 4:1
+!   B: 1:0 2:2 3:2 4:1
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: 1
+!   W: 1:0 2:2 3:2 4:1
+!   B: 1:0 2:2 3:2 4:1
+  >>> omnifunc
+    p/gopts1! KeyError
+    inv: 1! KeyError
+***************
+*** 252,264 ****
+    p/bopts1: b''
+    inv: 1! ValueError
+    G: ''
+!   W: 1:'B' 2:'C' 3:'A' 4:''
+!   B: 1:'B' 2:'C' 3:'A' 4:''
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: ''
+!   W: 1:'B' 2:'C' 3:'A' 4:''
+!   B: 1:'B' 2:'C' 3:'A' 4:''
+  >>> preserveindent
+    p/gopts1! KeyError
+    inv: 2! KeyError
+--- 252,264 ----
+    p/bopts1: b''
+    inv: 1! ValueError
+    G: ''
+!   W: 1:'A' 2:'B' 3:'' 4:'C'
+!   B: 1:'A' 2:'B' 3:'' 4:'C'
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: ''
+!   W: 1:'A' 2:'B' 3:'' 4:'C'
+!   B: 1:'A' 2:'B' 3:'' 4:'C'
+  >>> preserveindent
+    p/gopts1! KeyError
+    inv: 2! KeyError
+***************
+*** 271,283 ****
+    p/bopts1: False
+    inv: 2! ValueError
+    G: 0
+!   W: 1:1 2:1 3:0 4:0
+!   B: 1:1 2:1 3:0 4:0
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: 0
+!   W: 1:1 2:1 3:0 4:0
+!   B: 1:1 2:1 3:0 4:0
+  >>> path
+    p/gopts1: b'.,/usr/include,,'
+    inv: 0! ValueError
+--- 271,283 ----
+    p/bopts1: False
+    inv: 2! ValueError
+    G: 0
+!   W: 1:0 2:1 3:0 4:1
+!   B: 1:0 2:1 3:0 4:1
+    del wopts3! KeyError
+    del bopts3! ValueError
+    G: 0
+!   W: 1:0 2:1 3:0 4:1
+!   B: 1:0 2:1 3:0 4:1
+  >>> path
+    p/gopts1: b'.,/usr/include,,'
+    inv: 0! ValueError
+***************
+*** 289,300 ****
+    p/bopts1: None
+    inv: 0! ValueError
+    G: '.,,'
+!   W: 1:',,' 2:'.' 3:'.,,' 4:'.,,'
+!   B: 1:',,' 2:'.' 3:'.,,' 4:'.,,'
+    del wopts3! KeyError
+    G: '.,,'
+!   W: 1:',,' 2:'.,,' 3:'.,,' 4:'.,,'
+!   B: 1:',,' 2:'.,,' 3:'.,,' 4:'.,,'
+  First line
+  First line
+  def
+--- 289,300 ----
+    p/bopts1: None
+    inv: 0! ValueError
+    G: '.,,'
+!   W: 1:'.,,' 2:',,' 3:'.,,' 4:'.'
+!   B: 1:'.,,' 2:',,' 3:'.,,' 4:'.'
+    del wopts3! KeyError
+    G: '.,,'
+!   W: 1:'.,,' 2:',,' 3:'.,,' 4:'.,,'
+!   B: 1:'.,,' 2:',,' 3:'.,,' 4:'.,,'
+  First line
+  First line
+  def
+*** ../vim-7.3.944/src/version.c	2013-05-13 20:26:47.000000000 +0200
+--- src/version.c	2013-05-15 13:37:08.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     945,
+  /**/
+
+-- 
+ARTHUR:        A scratch?  Your arm's off!
+BLACK KNIGHT:  No, it isn't.
+ARTHUR:        Well, what's that then?
+BLACK KNIGHT:  I've had worse.
+                                  The Quest for the Holy Grail (Monty Python)
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.946 b/7.3.946
new file mode 100644
index 0000000..4e42beb
--- /dev/null
+++ b/7.3.946
@@ -0,0 +1,98 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.946
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.946
+Problem:    Sometimes get stuck in waiting for cursor position report,
+	    resulting in keys starting with <Esc>[ not working.
+Solution:   Only wait for more characters after <Esc>[ if followed by '?', '>'
+	    or a digit.
+Files:	    src/term.c
+
+
+*** ../vim-7.3.945/src/term.c	2013-05-13 20:26:47.000000000 +0200
+--- src/term.c	2013-05-15 14:12:43.000000000 +0200
+***************
+*** 4126,4134 ****
+  	     *   The final byte is 'R'. now it is only used for checking for
+  	     *   ambiguous-width character state.
+  	     */
+  	    if ((*T_CRV != NUL || *T_U7 != NUL)
+  			&& ((tp[0] == ESC && tp[1] == '[' && len >= 3)
+! 			    || (tp[0] == CSI && len >= 2)))
+  	    {
+  		j = 0;
+  		extra = 0;
+--- 4126,4136 ----
+  	     *   The final byte is 'R'. now it is only used for checking for
+  	     *   ambiguous-width character state.
+  	     */
++ 	    p = tp[0] == CSI ? tp + 1 : tp + 2;
+  	    if ((*T_CRV != NUL || *T_U7 != NUL)
+  			&& ((tp[0] == ESC && tp[1] == '[' && len >= 3)
+! 			    || (tp[0] == CSI && len >= 2))
+! 			&& (VIM_ISDIGIT(*p) || *p == '>' || *p == '?'))
+  	    {
+  		j = 0;
+  		extra = 0;
+***************
+*** 4136,4142 ****
+  				&& !(tp[i] >= '{' && tp[i] <= '~')
+  				&& !ASCII_ISALPHA(tp[i]); ++i)
+  		    if (tp[i] == ';' && ++j == 1)
+! 			extra = atoi((char *)tp + i + 1);
+  		if (i == len)
+  		    return -1;		/* not enough characters */
+  
+--- 4138,4144 ----
+  				&& !(tp[i] >= '{' && tp[i] <= '~')
+  				&& !ASCII_ISALPHA(tp[i]); ++i)
+  		    if (tp[i] == ';' && ++j == 1)
+! 			extra = i + 1;
+  		if (i == len)
+  		    return -1;		/* not enough characters */
+  
+***************
+*** 4150,4155 ****
+--- 4152,4159 ----
+  # ifdef FEAT_AUTOCMD
+  		    did_cursorhold = TRUE;
+  # endif
++ 		    if (extra > 0)
++ 			extra = atoi((char *)tp + extra);
+  		    if (extra == 2)
+  			aw = "single";
+  		    else if (extra == 3)
+***************
+*** 4178,4183 ****
+--- 4182,4189 ----
+  		    /* rxvt sends its version number: "20703" is 2.7.3.
+  		     * Ignore it for when the user has set 'term' to xterm,
+  		     * even though it's an rxvt. */
++ 		    if (extra > 0)
++ 			extra = atoi((char *)tp + extra);
+  		    if (extra > 20000)
+  			extra = 0;
+  
+*** ../vim-7.3.945/src/version.c	2013-05-15 13:38:41.000000000 +0200
+--- src/version.c	2013-05-15 14:17:51.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     946,
+  /**/
+
+-- 
+No letters of the alphabet were harmed in the creation of this message.
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.947 b/7.3.947
new file mode 100644
index 0000000..2093c9d
--- /dev/null
+++ b/7.3.947
@@ -0,0 +1,703 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.947
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.947
+Problem:    Python: No iterator for vim.list and vim.bufferlist.
+Solution:   Add the iterators. Also fix name of FunctionType. Add tests for
+	    vim.buffers.  (ZyX)
+Files:	    runtime/doc/if_pyth.txt, src/eval.c, src/if_py_both.h,
+	    src/if_python3.c, src/if_python.c, src/proto/eval.pro,
+	    src/testdir/test86.in, src/testdir/test86.ok,
+	    src/testdir/test87.in, src/testdir/test87.ok
+
+
+*** ../vim-7.3.946/runtime/doc/if_pyth.txt	2013-05-15 13:38:41.000000000 +0200
+--- runtime/doc/if_pyth.txt	2013-05-15 14:24:11.000000000 +0200
+***************
+*** 214,219 ****
+--- 214,220 ----
+  	    :py b = vim.buffers[i]	# Indexing (read-only)
+  	    :py b in vim.buffers	# Membership test
+  	    :py n = len(vim.buffers)	# Number of elements
++ 	    :py for b in vim.buffers:	# Iterating over buffer list
+  <
+  vim.windows						*python-windows*
+  	A sequence object providing access to the list of vim windows.  The
+*** ../vim-7.3.946/src/eval.c	2013-05-06 04:50:26.000000000 +0200
+--- src/eval.c	2013-05-15 14:24:11.000000000 +0200
+***************
+*** 390,397 ****
+  static void clear_lval __ARGS((lval_T *lp));
+  static void set_var_lval __ARGS((lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op));
+  static int tv_op __ARGS((typval_T *tv1, typval_T *tv2, char_u  *op));
+- static void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
+- static void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
+  static void list_fix_watch __ARGS((list_T *l, listitem_T *item));
+  static void ex_unletlock __ARGS((exarg_T *eap, char_u *argstart, int deep));
+  static int do_unlet_var __ARGS((lval_T *lp, char_u *name_end, int forceit));
+--- 390,395 ----
+***************
+*** 3106,3112 ****
+  /*
+   * Add a watcher to a list.
+   */
+!     static void
+  list_add_watch(l, lw)
+      list_T	*l;
+      listwatch_T	*lw;
+--- 3104,3110 ----
+  /*
+   * Add a watcher to a list.
+   */
+!     void
+  list_add_watch(l, lw)
+      list_T	*l;
+      listwatch_T	*lw;
+***************
+*** 3119,3125 ****
+   * Remove a watcher from a list.
+   * No warning when it isn't found...
+   */
+!     static void
+  list_rem_watch(l, lwrem)
+      list_T	*l;
+      listwatch_T	*lwrem;
+--- 3117,3123 ----
+   * Remove a watcher from a list.
+   * No warning when it isn't found...
+   */
+!     void
+  list_rem_watch(l, lwrem)
+      list_T	*l;
+      listwatch_T	*lwrem;
+*** ../vim-7.3.946/src/if_py_both.h	2013-05-15 13:38:41.000000000 +0200
+--- src/if_py_both.h	2013-05-15 14:24:11.000000000 +0200
+***************
+*** 531,596 ****
+  };
+  
+  /*
+!  * Buffer list object - Implementation
+   */
+  
+! static PyTypeObject BufMapType;
+  
+  typedef struct
+  {
+      PyObject_HEAD
+! } BufMapObject;
+  
+!     static PyInt
+! BufMapLength(PyObject *self UNUSED)
+  {
+!     buf_T	*b = firstbuf;
+!     PyInt	n = 0;
+  
+!     while (b)
+!     {
+! 	++n;
+! 	b = b->b_next;
+!     }
+  
+!     return n;
+  }
+  
+!     static PyObject *
+! BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
+  {
+!     buf_T	*b;
+!     int		bnr;
+  
+! #if PY_MAJOR_VERSION < 3
+!     if (PyInt_Check(keyObject))
+! 	bnr = PyInt_AsLong(keyObject);
+!     else
+! #endif
+!     if (PyLong_Check(keyObject))
+! 	bnr = PyLong_AsLong(keyObject);
+!     else
+!     {
+! 	PyErr_SetString(PyExc_ValueError, _("key must be integer"));
+! 	return NULL;
+!     }
+  
+!     b = buflist_findnr(bnr);
+  
+!     if (b)
+! 	return BufferNew(b);
+!     else
+!     {
+! 	PyErr_SetString(PyExc_KeyError, _("no such buffer"));
+! 	return NULL;
+!     }
+  }
+  
+! static PyMappingMethods BufMapAsMapping = {
+!     (lenfunc)       BufMapLength,
+!     (binaryfunc)    BufMapItem,
+!     (objobjargproc) 0,
+! };
+  
+  typedef struct pylinkedlist_S {
+      struct pylinkedlist_S	*pll_next;
+--- 531,592 ----
+  };
+  
+  /*
+!  * Generic iterator object
+   */
+  
+! static PyTypeObject IterType;
+! 
+! typedef PyObject *(*nextfun)(void **);
+! typedef void (*destructorfun)(void *);
+! 
+! /* Main purpose of this object is removing the need for do python initialization 
+!  * (i.e. PyType_Ready and setting type attributes) for a big bunch of objects.
+!  */
+  
+  typedef struct
+  {
+      PyObject_HEAD
+!     void *cur;
+!     nextfun next;
+!     destructorfun destruct;
+! } IterObject;
+  
+!     static PyObject *
+! IterNew(void *start, destructorfun destruct, nextfun next)
+  {
+!     IterObject *self;
+  
+!     self = PyObject_NEW(IterObject, &IterType);
+!     self->cur = start;
+!     self->next = next;
+!     self->destruct = destruct;
+  
+!     return (PyObject *)(self);
+  }
+  
+!     static void
+! IterDestructor(PyObject *self)
+  {
+!     IterObject *this = (IterObject *)(self);
+  
+!     this->destruct(this->cur);
+  
+!     DESTRUCTOR_FINISH(self);
+! }
+  
+!     static PyObject *
+! IterNext(PyObject *self)
+! {
+!     IterObject *this = (IterObject *)(self);
+! 
+!     return this->next(&this->cur);
+  }
+  
+!     static PyObject *
+! IterIter(PyObject *self)
+! {
+!     return self;
+! }
+  
+  typedef struct pylinkedlist_S {
+      struct pylinkedlist_S	*pll_next;
+***************
+*** 990,995 ****
+--- 986,1040 ----
+      return list;
+  }
+  
++ typedef struct
++ {
++     listwatch_T	lw;
++     list_T	*list;
++ } listiterinfo_T;
++ 
++     static void
++ ListIterDestruct(listiterinfo_T *lii)
++ {
++     list_rem_watch(lii->list, &lii->lw);
++     PyMem_Free(lii);
++ }
++ 
++     static PyObject *
++ ListIterNext(listiterinfo_T **lii)
++ {
++     PyObject	*r;
++ 
++     if (!((*lii)->lw.lw_item))
++ 	return NULL;
++ 
++     if (!(r = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
++ 	return NULL;
++ 
++     (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
++ 
++     return r;
++ }
++ 
++     static PyObject *
++ ListIter(PyObject *self)
++ {
++     listiterinfo_T	*lii;
++     list_T	*l = ((ListObject *) (self))->list;
++ 
++     if (!(lii = PyMem_New(listiterinfo_T, 1)))
++     {
++ 	PyErr_NoMemory();
++ 	return NULL;
++     }
++ 
++     list_add_watch(l, &lii->lw);
++     lii->lw.lw_item = l->lv_first;
++     lii->list = l;
++ 
++     return IterNew(lii,
++ 	    (destructorfun) ListIterDestruct, (nextfun) ListIterNext);
++ }
++ 
+      static int
+  ListAssItem(PyObject *self, Py_ssize_t index, PyObject *obj)
+  {
+***************
+*** 2869,2874 ****
+--- 2914,3029 ----
+      { NULL,	    NULL,		0,	    NULL }
+  };
+  
++ /*
++  * Buffer list object - Implementation
++  */
++ 
++ static PyTypeObject BufMapType;
++ 
++ typedef struct
++ {
++     PyObject_HEAD
++ } BufMapObject;
++ 
++     static PyInt
++ BufMapLength(PyObject *self UNUSED)
++ {
++     buf_T	*b = firstbuf;
++     PyInt	n = 0;
++ 
++     while (b)
++     {
++ 	++n;
++ 	b = b->b_next;
++     }
++ 
++     return n;
++ }
++ 
++     static PyObject *
++ BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
++ {
++     buf_T	*b;
++     int		bnr;
++ 
++ #if PY_MAJOR_VERSION < 3
++     if (PyInt_Check(keyObject))
++ 	bnr = PyInt_AsLong(keyObject);
++     else
++ #endif
++     if (PyLong_Check(keyObject))
++ 	bnr = PyLong_AsLong(keyObject);
++     else
++     {
++ 	PyErr_SetString(PyExc_ValueError, _("key must be integer"));
++ 	return NULL;
++     }
++ 
++     b = buflist_findnr(bnr);
++ 
++     if (b)
++ 	return BufferNew(b);
++     else
++     {
++ 	PyErr_SetString(PyExc_KeyError, _("no such buffer"));
++ 	return NULL;
++     }
++ }
++ 
++     static void
++ BufMapIterDestruct(PyObject *buffer)
++ {
++     /* Iteration was stopped before all buffers were processed */
++     if (buffer)
++     {
++ 	Py_DECREF(buffer);
++     }
++ }
++ 
++     static PyObject *
++ BufMapIterNext(PyObject **buffer)
++ {
++     PyObject	*next;
++     PyObject	*r;
++ 
++     if (!*buffer)
++ 	return NULL;
++ 
++     r = *buffer;
++ 
++     if (CheckBuffer((BufferObject *)(r)))
++     {
++ 	*buffer = NULL;
++ 	return NULL;
++     }
++ 
++     if (!((BufferObject *)(r))->buf->b_next)
++ 	next = NULL;
++     else if (!(next = BufferNew(((BufferObject *)(r))->buf->b_next)))
++ 	return NULL;
++     *buffer = next;
++     /* Do not increment reference: we no longer hold it (decref), but whoever on 
++      * other side will hold (incref). Decref+incref = nothing.
++      */
++     return r;
++ }
++ 
++     static PyObject *
++ BufMapIter(PyObject *self UNUSED)
++ {
++     PyObject *buffer;
++ 
++     buffer = BufferNew(firstbuf);
++     return IterNew(buffer,
++ 	    (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext);
++ }
++ 
++ static PyMappingMethods BufMapAsMapping = {
++     (lenfunc)       BufMapLength,
++     (binaryfunc)    BufMapItem,
++     (objobjargproc) 0,
++ };
++ 
+  /* Current items object
+   */
+  
+***************
+*** 3383,3388 ****
+--- 3538,3551 ----
+      OutputType.tp_setattr = OutputSetattr;
+  #endif
+  
++     vim_memset(&IterType, 0, sizeof(IterType));
++     IterType.tp_name = "vim.iter";
++     IterType.tp_basicsize = sizeof(IterObject);
++     IterType.tp_flags = Py_TPFLAGS_DEFAULT;
++     IterType.tp_doc = "generic iterator object";
++     IterType.tp_iter = IterIter;
++     IterType.tp_iternext = IterNext;
++ 
+      vim_memset(&BufferType, 0, sizeof(BufferType));
+      BufferType.tp_name = "vim.buffer";
+      BufferType.tp_basicsize = sizeof(BufferType);
+***************
+*** 3426,3431 ****
+--- 3589,3595 ----
+      BufMapType.tp_basicsize = sizeof(BufMapObject);
+      BufMapType.tp_as_mapping = &BufMapAsMapping;
+      BufMapType.tp_flags = Py_TPFLAGS_DEFAULT;
++     BufMapType.tp_iter = BufMapIter;
+      BufferType.tp_doc = "vim buffer list";
+  
+      vim_memset(&WinListType, 0, sizeof(WinListType));
+***************
+*** 3492,3497 ****
+--- 3656,3662 ----
+      ListType.tp_flags = Py_TPFLAGS_DEFAULT;
+      ListType.tp_doc = "list pushing modifications to vim structure";
+      ListType.tp_methods = ListMethods;
++     ListType.tp_iter = ListIter;
+  #if PY_MAJOR_VERSION >= 3
+      ListType.tp_getattro = ListGetattro;
+      ListType.tp_setattro = ListSetattro;
+***************
+*** 3501,3507 ****
+  #endif
+  
+      vim_memset(&FunctionType, 0, sizeof(FunctionType));
+!     FunctionType.tp_name = "vim.list";
+      FunctionType.tp_basicsize = sizeof(FunctionObject);
+      FunctionType.tp_dealloc = FunctionDestructor;
+      FunctionType.tp_call = FunctionCall;
+--- 3666,3672 ----
+  #endif
+  
+      vim_memset(&FunctionType, 0, sizeof(FunctionType));
+!     FunctionType.tp_name = "vim.function";
+      FunctionType.tp_basicsize = sizeof(FunctionObject);
+      FunctionType.tp_dealloc = FunctionDestructor;
+      FunctionType.tp_call = FunctionCall;
+*** ../vim-7.3.946/src/if_python3.c	2013-05-15 13:38:41.000000000 +0200
+--- src/if_python3.c	2013-05-15 14:24:11.000000000 +0200
+***************
+*** 1519,1524 ****
+--- 1519,1525 ----
+      /* The special value is removed from sys.path in Python3_Init(). */
+      static wchar_t *(argv[2]) = {L"/must>not&exist/foo", NULL};
+  
++     PyType_Ready(&IterType);
+      PyType_Ready(&BufferType);
+      PyType_Ready(&RangeType);
+      PyType_Ready(&WindowType);
+*** ../vim-7.3.946/src/if_python.c	2013-05-15 13:38:41.000000000 +0200
+--- src/if_python.c	2013-05-15 14:24:11.000000000 +0200
+***************
+*** 1219,1224 ****
+--- 1219,1225 ----
+      static char *(argv[2]) = {"/must>not&exist/foo", NULL};
+  
+      /* Fixups... */
++     PyType_Ready(&IterType);
+      PyType_Ready(&BufferType);
+      PyType_Ready(&RangeType);
+      PyType_Ready(&WindowType);
+*** ../vim-7.3.946/src/proto/eval.pro	2013-05-06 03:52:44.000000000 +0200
+--- src/proto/eval.pro	2013-05-15 14:24:11.000000000 +0200
+***************
+*** 127,130 ****
+--- 127,132 ----
+  char_u *do_string_sub __ARGS((char_u *str, char_u *pat, char_u *sub, char_u *flags));
+  int switch_win __ARGS((win_T **, tabpage_T **, win_T *, tabpage_T *));
+  void restore_win __ARGS((win_T *, tabpage_T *));
++ void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
++ void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
+  /* vim: set ft=c : */
+*** ../vim-7.3.946/src/testdir/test86.in	2013-05-12 21:16:17.000000000 +0200
+--- src/testdir/test86.in	2013-05-15 14:27:21.000000000 +0200
+***************
+*** 477,482 ****
+--- 477,485 ----
+  :   call RecVars(oname)
+  :endfor
+  :only
++ :for buf in g:bufs[1:]
++ :   execute 'bwipeout!' buf
++ :endfor
+  :"
+  :" Test buffer object
+  :vnew
+***************
+*** 519,524 ****
+--- 522,583 ----
+          # Should not happen in any case
+          cb.append('No exception for ' + expr)
+  EOF
++ :"
++ :" Test vim.buffers object
++ :set hidden
++ :edit a
++ :buffer #
++ :edit b
++ :buffer #
++ :edit c
++ :buffer #
++ py << EOF
++ # Check GCing iterator that was not fully exhausted
++ i = iter(vim.buffers)
++ cb.append('i:' + str(next(i)))
++ # and also check creating more then one iterator at a time
++ i2 = iter(vim.buffers)
++ cb.append('i2:' + str(next(i2)))
++ cb.append('i:' + str(next(i)))
++ # The following should trigger GC and not cause any problems
++ del i
++ del i2
++ i3 = iter(vim.buffers)
++ cb.append('i3:' + str(next(i3)))
++ del i3
++ 
++ prevnum = 0
++ for b in vim.buffers:
++     # Check buffer order
++     if prevnum >= b.number:
++         cb.append('!!! Buffer numbers not in strictly ascending order')
++     # Check indexing: vim.buffers[number].number == number
++     cb.append(str(b.number) + ':' + repr(vim.buffers[b.number]) + '=' + repr(b))
++     prevnum = b.number
++ 
++ cb.append(str(len(vim.buffers)))
++ 
++ bnums = list(map(lambda b: b.number, vim.buffers))[1:]
++ 
++ # Test wiping out buffer with existing iterator
++ i4 = iter(vim.buffers)
++ cb.append('i4:' + str(next(i4)))
++ vim.command('bwipeout! ' + str(bnums.pop(0)))
++ try:
++     next(i4)
++ except vim.error:
++     pass
++ else:
++     cb.append('!!!! No vim.error')
++ i4 = iter(vim.buffers)
++ vim.command('bwipeout! ' + str(bnums.pop(-1)))
++ vim.command('bwipeout! ' + str(bnums.pop(-1)))
++ cb.append('i4:' + str(next(i4)))
++ try:
++     next(i4)
++ except StopIteration:
++     cb.append('StopIteration')
++ EOF
+  :endfun
+  :"
+  :call Test()
+*** ../vim-7.3.946/src/testdir/test86.ok	2013-05-15 13:38:41.000000000 +0200
+--- src/testdir/test86.ok	2013-05-15 14:27:21.000000000 +0200
+***************
+*** 319,321 ****
+--- 319,333 ----
+  Second line
+  Third line
+  foo
++ i:<buffer test86.in>
++ i2:<buffer test86.in>
++ i:<buffer a>
++ i3:<buffer test86.in>
++ 1:<buffer test86.in>=<buffer test86.in>
++ 6:<buffer a>=<buffer a>
++ 7:<buffer b>=<buffer b>
++ 8:<buffer c>=<buffer c>
++ 4
++ i4:<buffer test86.in>
++ i4:<buffer test86.in>
++ StopIteration
+*** ../vim-7.3.946/src/testdir/test87.in	2013-05-12 21:16:17.000000000 +0200
+--- src/testdir/test87.in	2013-05-15 14:27:21.000000000 +0200
+***************
+*** 446,451 ****
+--- 446,454 ----
+  :   call RecVars(oname)
+  :endfor
+  :only
++ :for buf in g:bufs[1:]
++ :   execute 'bwipeout!' buf
++ :endfor
+  :"
+  :" Test buffer object
+  :vnew
+***************
+*** 488,493 ****
+--- 491,552 ----
+          # Should not happen in any case
+          cb.append('No exception for ' + expr)
+  EOF
++ :"
++ :" Test vim.buffers object
++ :set hidden
++ :edit a
++ :buffer #
++ :edit b
++ :buffer #
++ :edit c
++ :buffer #
++ py3 << EOF
++ # Check GCing iterator that was not fully exhausted
++ i = iter(vim.buffers)
++ cb.append('i:' + str(next(i)))
++ # and also check creating more then one iterator at a time
++ i2 = iter(vim.buffers)
++ cb.append('i2:' + str(next(i2)))
++ cb.append('i:' + str(next(i)))
++ # The following should trigger GC and not cause any problems
++ del i
++ del i2
++ i3 = iter(vim.buffers)
++ cb.append('i3:' + str(next(i3)))
++ del i3
++ 
++ prevnum = 0
++ for b in vim.buffers:
++     # Check buffer order
++     if prevnum >= b.number:
++         cb.append('!!! Buffer numbers not in strictly ascending order')
++     # Check indexing: vim.buffers[number].number == number
++     cb.append(str(b.number) + ':' + repr(vim.buffers[b.number]) + '=' + repr(b))
++     prevnum = b.number
++ 
++ cb.append(str(len(vim.buffers)))
++ 
++ bnums = list(map(lambda b: b.number, vim.buffers))[1:]
++ 
++ # Test wiping out buffer with existing iterator
++ i4 = iter(vim.buffers)
++ cb.append('i4:' + str(next(i4)))
++ vim.command('bwipeout! ' + str(bnums.pop(0)))
++ try:
++     next(i4)
++ except vim.error:
++     pass
++ else:
++     cb.append('!!!! No vim.error')
++ i4 = iter(vim.buffers)
++ vim.command('bwipeout! ' + str(bnums.pop(-1)))
++ vim.command('bwipeout! ' + str(bnums.pop(-1)))
++ cb.append('i4:' + str(next(i4)))
++ try:
++     next(i4)
++ except StopIteration:
++     cb.append('StopIteration')
++ EOF
+  :endfun
+  :"
+  :call Test()
+***************
+*** 496,501 ****
+--- 555,561 ----
+  :call garbagecollect(1)
+  :"
+  :/^start:/,$wq! test.out
++ :call getchar()
+  ENDTEST
+  
+  start:
+*** ../vim-7.3.946/src/testdir/test87.ok	2013-05-15 13:38:41.000000000 +0200
+--- src/testdir/test87.ok	2013-05-15 14:27:21.000000000 +0200
+***************
+*** 308,310 ****
+--- 308,322 ----
+  Second line
+  Third line
+  foo
++ i:<buffer test87.in>
++ i2:<buffer test87.in>
++ i:<buffer a>
++ i3:<buffer test87.in>
++ 1:<buffer test87.in>=<buffer test87.in>
++ 6:<buffer a>=<buffer a>
++ 7:<buffer b>=<buffer b>
++ 8:<buffer c>=<buffer c>
++ 4
++ i4:<buffer test87.in>
++ i4:<buffer test87.in>
++ StopIteration
+*** ../vim-7.3.946/src/version.c	2013-05-15 14:22:36.000000000 +0200
+--- src/version.c	2013-05-15 14:25:26.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     947,
+  /**/
+
+-- 
+"It's so simple to be wise.  Just think of something stupid to say
+and then don't say it."        -- Sam Levenson
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.948 b/7.3.948
new file mode 100644
index 0000000..d2d2eb3
--- /dev/null
+++ b/7.3.948
@@ -0,0 +1,423 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.948
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.948
+Problem:    Cannot build with Python 2.2
+Solution:   Make Python interface work with Python 2.2
+	    Make 2.2 the first supported version. (ZyX)
+Files:	    src/if_py_both.h, src/if_python3.c, src/if_python.c,
+	    src/testdir/test86.in, src/testdir/test86.ok,
+	    src/testdir/test87.ok, src/configure.in, src/auto/configure
+
+
+*** ../vim-7.3.947/src/if_py_both.h	2013-05-15 14:39:47.000000000 +0200
+--- src/if_py_both.h	2013-05-15 14:49:11.000000000 +0200
+***************
+*** 564,569 ****
+--- 564,570 ----
+      return (PyObject *)(self);
+  }
+  
++ #if 0 /* unused */
+      static void
+  IterDestructor(PyObject *self)
+  {
+***************
+*** 573,578 ****
+--- 574,580 ----
+  
+      DESTRUCTOR_FINISH(self);
+  }
++ #endif
+  
+      static PyObject *
+  IterNext(PyObject *self)
+***************
+*** 696,708 ****
+  	}
+  	else
+  	{
+! 	    if (!PyBool_Check(val))
+! 	    {
+! 		PyErr_SetString(PyExc_TypeError, _("Only boolean objects are allowed"));
+! 		return -1;
+! 	    }
+! 
+! 	    if (val == Py_True)
+  		this->dict->dv_lock = VAR_LOCKED;
+  	    else
+  		this->dict->dv_lock = 0;
+--- 698,704 ----
+  	}
+  	else
+  	{
+! 	    if (PyObject_IsTrue(val))
+  		this->dict->dv_lock = VAR_LOCKED;
+  	    else
+  		this->dict->dv_lock = 0;
+***************
+*** 1202,1214 ****
+  	}
+  	else
+  	{
+! 	    if (!PyBool_Check(val))
+! 	    {
+! 		PyErr_SetString(PyExc_TypeError, _("Only boolean objects are allowed"));
+! 		return -1;
+! 	    }
+! 
+! 	    if (val == Py_True)
+  		this->list->lv_lock = VAR_LOCKED;
+  	    else
+  		this->list->lv_lock = 0;
+--- 1198,1204 ----
+  	}
+  	else
+  	{
+! 	    if (PyObject_IsTrue(val))
+  		this->list->lv_lock = VAR_LOCKED;
+  	    else
+  		this->list->lv_lock = 0;
+***************
+*** 1484,1497 ****
+  
+      if (flags & SOPT_BOOL)
+      {
+! 	if (!PyBool_Check(valObject))
+! 	{
+! 	    PyErr_SetString(PyExc_ValueError, "Object must be boolean");
+! 	    return -1;
+! 	}
+! 
+! 	r = set_option_value_for(key, (valObject == Py_True), NULL, opt_flags,
+! 				this->opt_type, this->from);
+      }
+      else if (flags & SOPT_NUM)
+      {
+--- 1474,1481 ----
+  
+      if (flags & SOPT_BOOL)
+      {
+! 	r = set_option_value_for(key, PyObject_IsTrue(valObject), NULL,
+! 				opt_flags, this->opt_type, this->from);
+      }
+      else if (flags & SOPT_NUM)
+      {
+*** ../vim-7.3.947/src/if_python3.c	2013-05-15 14:39:47.000000000 +0200
+--- src/if_python3.c	2013-05-15 14:42:21.000000000 +0200
+***************
+*** 156,161 ****
+--- 156,162 ----
+  # define PyMapping_Items py3_PyMapping_Items
+  # define PyIter_Next py3_PyIter_Next
+  # define PyObject_GetIter py3_PyObject_GetIter
++ # define PyObject_IsTrue py3_PyObject_IsTrue
+  # define PyModule_GetDict py3_PyModule_GetDict
+  #undef PyRun_SimpleString
+  # define PyRun_SimpleString py3_PyRun_SimpleString
+***************
+*** 264,269 ****
+--- 265,271 ----
+  static PyObject* (*py3_PyDict_New)(void);
+  static PyObject* (*py3_PyIter_Next)(PyObject *);
+  static PyObject* (*py3_PyObject_GetIter)(PyObject *);
++ static int (*py3_PyObject_IsTrue)(PyObject *);
+  static PyObject* (*py3_Py_BuildValue)(char *, ...);
+  static int (*py3_PyType_Ready)(PyTypeObject *type);
+  static int (*py3_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item);
+***************
+*** 392,397 ****
+--- 394,400 ----
+      {"PyMapping_Items", (PYTHON_PROC*)&py3_PyMapping_Items},
+      {"PyIter_Next", (PYTHON_PROC*)&py3_PyIter_Next},
+      {"PyObject_GetIter", (PYTHON_PROC*)&py3_PyObject_GetIter},
++     {"PyObject_IsTrue", (PYTHON_PROC*)&py3_PyObject_IsTrue},
+      {"PyLong_FromLong", (PYTHON_PROC*)&py3_PyLong_FromLong},
+      {"PyDict_New", (PYTHON_PROC*)&py3_PyDict_New},
+      {"PyType_Ready", (PYTHON_PROC*)&py3_PyType_Ready},
+*** ../vim-7.3.947/src/if_python.c	2013-05-15 14:39:47.000000000 +0200
+--- src/if_python.c	2013-05-15 14:42:21.000000000 +0200
+***************
+*** 229,234 ****
+--- 229,235 ----
+  # define _Py_TrueStruct (*dll__Py_TrueStruct)
+  # define PyObject_Init dll__PyObject_Init
+  # define PyObject_GetIter dll_PyObject_GetIter
++ # define PyObject_IsTrue dll_PyObject_IsTrue
+  # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
+  #  define PyType_IsSubtype dll_PyType_IsSubtype
+  # endif
+***************
+*** 324,329 ****
+--- 325,331 ----
+  static PyObject*(*dll__PyObject_New)(PyTypeObject *, PyObject *);
+  static PyObject*(*dll__PyObject_Init)(PyObject *, PyTypeObject *);
+  static PyObject* (*dll_PyObject_GetIter)(PyObject *);
++ static int (*dll_PyObject_IsTrue)(PyObject *);
+  # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02070000
+  static iternextfunc dll__PyObject_NextNotImplemented;
+  # endif
+***************
+*** 459,464 ****
+--- 461,467 ----
+      {"_PyObject_New", (PYTHON_PROC*)&dll__PyObject_New},
+      {"PyObject_Init", (PYTHON_PROC*)&dll__PyObject_Init},
+      {"PyObject_GetIter", (PYTHON_PROC*)&dll_PyObject_GetIter},
++     {"PyObject_IsTrue", (PYTHON_PROC*)&dll_PyObject_IsTrue},
+  # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02070000
+      {"_PyObject_NextNotImplemented", (PYTHON_PROC*)&dll__PyObject_NextNotImplemented},
+  # endif
+***************
+*** 787,793 ****
+  	 * so the following does both: unlock GIL and save thread state in TLS
+  	 * without deleting thread state
+  	 */
+! 	PyEval_SaveThread();
+  
+  	initialised = 1;
+      }
+--- 790,799 ----
+  	 * so the following does both: unlock GIL and save thread state in TLS
+  	 * without deleting thread state
+  	 */
+! #ifndef PY_CAN_RECURSE
+! 	saved_python_thread =
+! #endif
+! 	    PyEval_SaveThread();
+  
+  	initialised = 1;
+      }
+*** ../vim-7.3.947/src/testdir/test86.in	2013-05-15 14:39:47.000000000 +0200
+--- src/testdir/test86.in	2013-05-15 14:42:21.000000000 +0200
+***************
+*** 183,220 ****
+  :   $put ='[0.0, 0.0]'
+  :endif
+  :let messages=[]
+! :py <<EOF
+  d=vim.bindeval('{}')
+  m=vim.bindeval('messages')
+! try:
+!     d['abc']
+! except Exception as e:
+!     m.extend([e.__class__.__name__])
+! 
+! try:
+!     d['abc']="\0"
+! except Exception as e:
+!     m.extend([e.__class__.__name__])
+! 
+! try:
+!     d['abc']=vim
+! except Exception as e:
+!     m.extend([e.__class__.__name__])
+! 
+! try:
+!     d['']=1
+! except Exception as e:
+!     m.extend([e.__class__.__name__])
+! 
+! try:
+!     d['a\0b']=1
+! except Exception as e:
+!     m.extend([e.__class__.__name__])
+! 
+! try:
+!     d[b'a\0b']=1
+! except Exception as e:
+!     m.extend([e.__class__.__name__])
+  EOF
+  :$put =messages
+  :unlet messages
+--- 183,203 ----
+  :   $put ='[0.0, 0.0]'
+  :endif
+  :let messages=[]
+! py <<EOF
+  d=vim.bindeval('{}')
+  m=vim.bindeval('messages')
+! def em(expr, g=globals(), l=locals()):
+!     try:
+!         exec(expr, g, l)
+!     except:
+!         m.extend([sys.exc_type.__name__])
+! 
+! em('d["abc"]')
+! em('d["abc"]="\\0"')
+! em('d["abc"]=vim')
+! em('d[""]=1')
+! em('d["a\\0b"]=1')
+! em('d[u"a\\0b"]=1')
+  EOF
+  :$put =messages
+  :unlet messages
+***************
+*** 394,407 ****
+  def e(s, g=globals(), l=locals()):
+      try:
+          exec(s, g, l)
+!     except Exception as e:
+!         vim.command('throw ' + repr(e.__class__.__name__))
+  
+  def ev(s, g=globals(), l=locals()):
+      try:
+          return eval(s, g, l)
+!     except Exception as e:
+!         vim.command('throw ' + repr(e.__class__.__name__))
+          return 0
+  EOF
+  :function E(s)
+--- 377,390 ----
+  def e(s, g=globals(), l=locals()):
+      try:
+          exec(s, g, l)
+!     except:
+!         vim.command('throw ' + repr(sys.exc_type.__name__))
+  
+  def ev(s, g=globals(), l=locals()):
+      try:
+          return eval(s, g, l)
+!     except:
+!         vim.command('throw ' + repr(sys.exc_type.__name__))
+          return 0
+  EOF
+  :function E(s)
+*** ../vim-7.3.947/src/testdir/test86.ok	2013-05-15 14:39:47.000000000 +0200
+--- src/testdir/test86.ok	2013-05-15 14:42:21.000000000 +0200
+***************
+*** 82,88 ****
+  bar
+  >>> paste
+    p/gopts1: False
+-   inv: 2! ValueError
+    p/wopts1! KeyError
+    inv: 2! KeyError
+    wopts1! KeyError
+--- 82,87 ----
+***************
+*** 224,230 ****
+    wopts2! KeyError
+    wopts3! KeyError
+    p/bopts1: False
+-   inv: 2! ValueError
+    G: 0
+    W: 1:0 2:1 3:0 4:1
+    B: 1:0 2:1 3:0 4:1
+--- 223,228 ----
+***************
+*** 280,286 ****
+    wopts2! KeyError
+    wopts3! KeyError
+    p/bopts1: False
+-   inv: 2! ValueError
+    G: 0
+    W: 1:0 2:1 3:0 4:1
+    B: 1:0 2:1 3:0 4:1
+--- 278,283 ----
+*** ../vim-7.3.947/src/testdir/test87.ok	2013-05-15 14:39:47.000000000 +0200
+--- src/testdir/test87.ok	2013-05-15 14:42:21.000000000 +0200
+***************
+*** 71,77 ****
+  bar
+  >>> paste
+    p/gopts1: False
+-   inv: 2! ValueError
+    p/wopts1! KeyError
+    inv: 2! KeyError
+    wopts1! KeyError
+--- 71,76 ----
+***************
+*** 213,219 ****
+    wopts2! KeyError
+    wopts3! KeyError
+    p/bopts1: False
+-   inv: 2! ValueError
+    G: 0
+    W: 1:0 2:1 3:0 4:1
+    B: 1:0 2:1 3:0 4:1
+--- 212,217 ----
+***************
+*** 269,275 ****
+    wopts2! KeyError
+    wopts3! KeyError
+    p/bopts1: False
+-   inv: 2! ValueError
+    G: 0
+    W: 1:0 2:1 3:0 4:1
+    B: 1:0 2:1 3:0 4:1
+--- 267,272 ----
+*** ../vim-7.3.947/src/configure.in	2013-05-06 04:21:35.000000000 +0200
+--- src/configure.in	2013-05-15 14:46:11.000000000 +0200
+***************
+*** 863,872 ****
+  	    ${vi_cv_path_python} -c 'import sys; print sys.version[:3]'`
+      ]])
+  
+!     dnl -- it must be at least version 1.4
+!     AC_MSG_CHECKING(Python is 1.4 or better)
+      if ${vi_cv_path_python} -c \
+! 	"import sys; sys.exit(${vi_cv_var_python_version} < 1.4)"
+      then
+        AC_MSG_RESULT(yep)
+  
+--- 863,872 ----
+  	    ${vi_cv_path_python} -c 'import sys; print sys.version[:3]'`
+      ]])
+  
+!     dnl -- it must be at least version 2.2
+!     AC_MSG_CHECKING(Python is 2.2 or better)
+      if ${vi_cv_path_python} -c \
+! 	"import sys; sys.exit(${vi_cv_var_python_version} < 2.2)"
+      then
+        AC_MSG_RESULT(yep)
+  
+*** ../vim-7.3.947/src/auto/configure	2013-05-06 04:21:35.000000000 +0200
+--- src/auto/configure	2013-05-15 14:46:28.000000000 +0200
+***************
+*** 5289,5298 ****
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $vi_cv_var_python_version" >&5
+  $as_echo "$vi_cv_var_python_version" >&6; }
+  
+!         { $as_echo "$as_me:${as_lineno-$LINENO}: checking Python is 1.4 or better" >&5
+! $as_echo_n "checking Python is 1.4 or better... " >&6; }
+      if ${vi_cv_path_python} -c \
+! 	"import sys; sys.exit(${vi_cv_var_python_version} < 1.4)"
+      then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yep" >&5
+  $as_echo "yep" >&6; }
+--- 5289,5298 ----
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $vi_cv_var_python_version" >&5
+  $as_echo "$vi_cv_var_python_version" >&6; }
+  
+!         { $as_echo "$as_me:${as_lineno-$LINENO}: checking Python is 2.2 or better" >&5
+! $as_echo_n "checking Python is 2.2 or better... " >&6; }
+      if ${vi_cv_path_python} -c \
+! 	"import sys; sys.exit(${vi_cv_var_python_version} < 2.2)"
+      then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yep" >&5
+  $as_echo "yep" >&6; }
+*** ../vim-7.3.947/src/version.c	2013-05-15 14:39:47.000000000 +0200
+--- src/version.c	2013-05-15 14:43:39.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     948,
+  /**/
+
+-- 
+MARTHA'S WAY: Don't throw out all that leftover wine. Freeze into ice cubes
+              for future use in casseroles and sauces.
+MY WAY:       What leftover wine?
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.949 b/7.3.949
new file mode 100644
index 0000000..419913a
--- /dev/null
+++ b/7.3.949
@@ -0,0 +1,919 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.949
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.949
+Problem:    Python: no easy access to tabpages.
+Solution:   Add vim.tabpages and vim.current.tabpage. (ZyX)
+Files:	    runtime/doc/if_pyth.txt, src/if_py_both.h, src/if_python3.c,
+	    src/if_python.c, src/proto/if_python3.pro,
+	    src/proto/if_python.pro, src/proto/window.pro, src/structs.h,
+	    src/window.c
+
+
+*** ../vim-7.3.948/runtime/doc/if_pyth.txt	2013-05-15 14:39:47.000000000 +0200
+--- runtime/doc/if_pyth.txt	2013-05-15 15:05:04.000000000 +0200
+***************
+*** 223,228 ****
+--- 223,242 ----
+  	    :py w in vim.windows	# Membership test
+  	    :py n = len(vim.windows)	# Number of elements
+  	    :py for w in vim.windows:	# Sequential access
++ <	Note: vim.windows object always accesses current tab page,. 
++ 	|python-tabpage|.windows objects are bound to parent |python-tabpage| 
++ 	object and always use windows from that tab page (or throw vim.error 
++ 	in case tab page was deleted). You can keep a reference to both 
++ 	without keeping a reference to vim module object or |python-tabpage|, 
++ 	they will not loose their properties in this case.
++ 
++ vim.tabpages						*python-tabpages*
++ 	A sequence object providing access to the list of vim tab pages. The 
++ 	object supports the following operations: >
++ 	    :py t = vim.tabpages[i]	# Indexing (read-only)
++ 	    :py t in vim.tabpages	# Membership test
++ 	    :py n = len(vim.tabpages)	# Number of elements
++ 	    :py for t in vim.tabpages:	# Sequential access
+  <
+  vim.current						*python-current*
+  	An object providing access (via specific attributes) to various
+***************
+*** 230,235 ****
+--- 244,250 ----
+  		vim.current.line	The current line (RW)		String
+  		vim.current.buffer	The current buffer (RO)		Buffer
+  		vim.current.window	The current window (RO)		Window
++ 		vim.current.tabpage	The current tab page (RO)	TabPage
+  		vim.current.range	The current line range (RO)	Range
+  
+  	The last case deserves a little explanation.  When the :python or
+***************
+*** 375,380 ****
+--- 390,397 ----
+  Window objects represent vim windows.  You can obtain them in a number of ways:
+  	- via vim.current.window (|python-current|)
+  	- from indexing vim.windows (|python-windows|)
++ 	- from indexing "windows" attribute of a tab page (|python-tabpage|)
++ 	- from the "window" attribute of a tab page (|python-tabpage|)
+  
+  You can manipulate window objects only through their attributes.  They have no
+  methods, and no sequence or other interface.
+***************
+*** 407,412 ****
+--- 424,447 ----
+  The width attribute is writable only if the screen is split vertically.
+  
+  ==============================================================================
++ 6. Tab page objects					*python-tabpage*
++ 
++ Tab page objects represent vim tab pages. You can obtain them in a number of 
++ ways:
++ 	- via vim.current.tabpage (|python-current|)
++ 	- from indexing vim.tabpages (|python-tabpages|)
++ 
++ You can use this object to access tab page windows. They have no methods and 
++ no sequence or other interfaces.
++ 
++ Tab page attributes are:
++ 	number		The tab page number like the one returned by 
++ 			|tabpagenr()|.
++ 	windows		Like |python-windows|, but for current tab page.
++ 	vars		The tab page |t:| variables.
++ 	window		Current tabpage window.
++ 
++ ==============================================================================
+  6. pyeval() and py3eval() Vim functions			*python-pyeval*
+  
+  To facilitate bi-directional interface, you can use |pyeval()| and |py3eval()| 
+*** ../vim-7.3.948/src/if_py_both.h	2013-05-15 14:51:31.000000000 +0200
+--- src/if_py_both.h	2013-05-15 15:10:16.000000000 +0200
+***************
+*** 27,32 ****
+--- 27,33 ----
+  
+  #define INVALID_BUFFER_VALUE ((buf_T *)(-1))
+  #define INVALID_WINDOW_VALUE ((win_T *)(-1))
++ #define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
+  
+  static int ConvertFromPyObject(PyObject *, typval_T *);
+  static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
+***************
+*** 1579,1584 ****
+--- 1580,1734 ----
+      (objobjargproc) OptionsAssItem,
+  };
+  
++ /* Tabpage object
++  */
++ 
++ typedef struct
++ {
++     PyObject_HEAD
++     tabpage_T	*tab;
++ } TabPageObject;
++ 
++ static PyObject *WinListNew(TabPageObject *tabObject);
++ 
++ static PyTypeObject TabPageType;
++ 
++     static int
++ CheckTabPage(TabPageObject *this)
++ {
++     if (this->tab == INVALID_TABPAGE_VALUE)
++     {
++ 	PyErr_SetVim(_("attempt to refer to deleted tab page"));
++ 	return -1;
++     }
++ 
++     return 0;
++ }
++ 
++     static PyObject *
++ TabPageNew(tabpage_T *tab)
++ {
++     TabPageObject *self;
++ 
++     if (TAB_PYTHON_REF(tab))
++     {
++ 	self = TAB_PYTHON_REF(tab);
++ 	Py_INCREF(self);
++     }
++     else
++     {
++ 	self = PyObject_NEW(TabPageObject, &TabPageType);
++ 	if (self == NULL)
++ 	    return NULL;
++ 	self->tab = tab;
++ 	TAB_PYTHON_REF(tab) = self;
++     }
++ 
++     return (PyObject *)(self);
++ }
++ 
++     static void
++ TabPageDestructor(PyObject *self)
++ {
++     TabPageObject *this = (TabPageObject *)(self);
++ 
++     if (this->tab && this->tab != INVALID_TABPAGE_VALUE)
++ 	TAB_PYTHON_REF(this->tab) = NULL;
++ 
++     DESTRUCTOR_FINISH(self);
++ }
++ 
++     static PyObject *
++ TabPageAttr(TabPageObject *this, char *name)
++ {
++     if (strcmp(name, "windows") == 0)
++ 	return WinListNew(this);
++     else if (strcmp(name, "number") == 0)
++ 	return PyLong_FromLong((long) get_tab_number(this->tab));
++     else if (strcmp(name, "vars") == 0)
++ 	return DictionaryNew(this->tab->tp_vars);
++     else if (strcmp(name, "window") == 0)
++     {
++ 	/* For current tab window.c does not bother to set or update tp_curwin
++ 	 */
++ 	if (this->tab == curtab)
++ 	    return WindowNew(curwin);
++ 	else
++ 	    return WindowNew(this->tab->tp_curwin);
++     }
++     return NULL;
++ }
++ 
++     static PyObject *
++ TabPageRepr(PyObject *self)
++ {
++     static char repr[100];
++     TabPageObject *this = (TabPageObject *)(self);
++ 
++     if (this->tab == INVALID_TABPAGE_VALUE)
++     {
++ 	vim_snprintf(repr, 100, _("<tabpage object (deleted) at %p>"), (self));
++ 	return PyString_FromString(repr);
++     }
++     else
++     {
++ 	int	t = get_tab_number(this->tab);
++ 
++ 	if (t == 0)
++ 	    vim_snprintf(repr, 100, _("<tabpage object (unknown) at %p>"),
++ 								      (self));
++ 	else
++ 	    vim_snprintf(repr, 100, _("<tabpage %d>"), t - 1);
++ 
++ 	return PyString_FromString(repr);
++     }
++ }
++ 
++ static struct PyMethodDef TabPageMethods[] = {
++     /* name,	    function,		calling,    documentation */
++     { NULL,	    NULL,		0,	    NULL }
++ };
++ 
++ /*
++  * Window list object
++  */
++ 
++ static PyTypeObject TabListType;
++ static PySequenceMethods TabListAsSeq;
++ 
++ typedef struct
++ {
++     PyObject_HEAD
++ } TabListObject;
++ 
++     static PyInt
++ TabListLength(PyObject *self UNUSED)
++ {
++     tabpage_T	*tp = first_tabpage;
++     PyInt	n = 0;
++ 
++     while (tp != NULL)
++     {
++ 	++n;
++ 	tp = tp->tp_next;
++     }
++ 
++     return n;
++ }
++ 
++     static PyObject *
++ TabListItem(PyObject *self UNUSED, PyInt n)
++ {
++     tabpage_T	*tp;
++ 
++     for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, --n)
++ 	if (n == 0)
++ 	    return TabPageNew(tp);
++ 
++     PyErr_SetString(PyExc_IndexError, _("no such tab page"));
++     return NULL;
++ }
++ 
+  /* Window object
+   */
+  
+***************
+*** 1588,1595 ****
+      win_T	*win;
+  } WindowObject;
+  
+- static int WindowSetattr(PyObject *, char *, PyObject *);
+- static PyObject *WindowRepr(PyObject *);
+  static PyTypeObject WindowType;
+  
+      static int
+--- 1738,1743 ----
+***************
+*** 1681,1687 ****
+  	return OptionsNew(SREQ_WIN, this->win, (checkfun) CheckWindow,
+  			(PyObject *) this);
+      else if (strcmp(name, "number") == 0)
+! 	return PyLong_FromLong((long) get_win_number(this->win));
+      else if (strcmp(name,"__members__") == 0)
+  	return Py_BuildValue("[ssssssss]", "buffer", "cursor", "height", "vars",
+  		"options", "number", "row", "col");
+--- 1829,1835 ----
+  	return OptionsNew(SREQ_WIN, this->win, (checkfun) CheckWindow,
+  			(PyObject *) this);
+      else if (strcmp(name, "number") == 0)
+! 	return PyLong_FromLong((long) get_win_number(this->win, firstwin));
+      else if (strcmp(name,"__members__") == 0)
+  	return Py_BuildValue("[ssssssss]", "buffer", "cursor", "height", "vars",
+  		"options", "number", "row", "col");
+***************
+*** 1797,1803 ****
+      }
+      else
+      {
+! 	int	w = get_win_number(this->win);
+  
+  	if (w == 0)
+  	    vim_snprintf(repr, 100, _("<window object (unknown) at %p>"),
+--- 1945,1951 ----
+      }
+      else
+      {
+! 	int	w = get_win_number(this->win, firstwin);
+  
+  	if (w == 0)
+  	    vim_snprintf(repr, 100, _("<window object (unknown) at %p>"),
+***************
+*** 1824,1837 ****
+  typedef struct
+  {
+      PyObject_HEAD
+  } WinListObject;
+  
+      static PyInt
+! WinListLength(PyObject *self UNUSED)
+  {
+!     win_T	*w = firstwin;
+      PyInt	n = 0;
+  
+      while (w != NULL)
+      {
+  	++n;
+--- 1972,2030 ----
+  typedef struct
+  {
+      PyObject_HEAD
++     TabPageObject	*tabObject;
+  } WinListObject;
+  
++     static PyObject *
++ WinListNew(TabPageObject *tabObject)
++ {
++     WinListObject	*self;
++ 
++     self = PyObject_NEW(WinListObject, &WinListType);
++     self->tabObject = tabObject;
++     Py_INCREF(tabObject);
++ 
++     return (PyObject *)(self);
++ }
++ 
++     static void
++ WinListDestructor(PyObject *self)
++ {
++     TabPageObject	*tabObject = ((WinListObject *)(self))->tabObject;
++ 
++     if (tabObject)
++ 	Py_DECREF((PyObject *)(tabObject));
++ 
++     DESTRUCTOR_FINISH(self);
++ }
++ 
++     static win_T *
++ get_firstwin(WinListObject *this)
++ {
++     if (this->tabObject)
++     {
++ 	if (CheckTabPage(this->tabObject))
++ 	    return NULL;
++ 	/* For current tab window.c does not bother to set or update tp_firstwin
++ 	 */
++ 	else if (this->tabObject->tab == curtab)
++ 	    return firstwin;
++ 	else
++ 	    return this->tabObject->tab->tp_firstwin;
++     }
++     else
++ 	return firstwin;
++ }
++ 
+      static PyInt
+! WinListLength(PyObject *self)
+  {
+!     win_T	*w;
+      PyInt	n = 0;
+  
++     if (!(w = get_firstwin((WinListObject *)(self))))
++ 	return -1;
++ 
+      while (w != NULL)
+      {
+  	++n;
+***************
+*** 1842,1852 ****
+  }
+  
+      static PyObject *
+! WinListItem(PyObject *self UNUSED, PyInt n)
+  {
+      win_T *w;
+  
+!     for (w = firstwin; w != NULL; w = W_NEXT(w), --n)
+  	if (n == 0)
+  	    return WindowNew(w);
+  
+--- 2035,2048 ----
+  }
+  
+      static PyObject *
+! WinListItem(PyObject *self, PyInt n)
+  {
+      win_T *w;
+  
+!     if (!(w = get_firstwin((WinListObject *)(self))))
+! 	return NULL;
+! 
+!     for (; w != NULL; w = W_NEXT(w), --n)
+  	if (n == 0)
+  	    return WindowNew(w);
+  
+***************
+*** 3018,3029 ****
+  	return (PyObject *)BufferNew(curbuf);
+      else if (strcmp(name, "window") == 0)
+  	return (PyObject *)WindowNew(curwin);
+      else if (strcmp(name, "line") == 0)
+  	return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
+      else if (strcmp(name, "range") == 0)
+  	return RangeNew(curbuf, RangeStart, RangeEnd);
+      else if (strcmp(name,"__members__") == 0)
+! 	return Py_BuildValue("[ssss]", "buffer", "window", "line", "range");
+      else
+      {
+  	PyErr_SetString(PyExc_AttributeError, name);
+--- 3214,3228 ----
+  	return (PyObject *)BufferNew(curbuf);
+      else if (strcmp(name, "window") == 0)
+  	return (PyObject *)WindowNew(curwin);
++     else if (strcmp(name, "tabpage") == 0)
++ 	return (PyObject *)TabPageNew(curtab);
+      else if (strcmp(name, "line") == 0)
+  	return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
+      else if (strcmp(name, "range") == 0)
+  	return RangeNew(curbuf, RangeStart, RangeEnd);
+      else if (strcmp(name,"__members__") == 0)
+! 	return Py_BuildValue("[sssss]", "buffer", "window", "line", "range",
+! 		"tabpage");
+      else
+      {
+  	PyErr_SetString(PyExc_AttributeError, name);
+***************
+*** 3568,3573 ****
+--- 3767,3789 ----
+      WindowType.tp_setattr = WindowSetattr;
+  #endif
+  
++     vim_memset(&TabPageType, 0, sizeof(TabPageType));
++     TabPageType.tp_name = "vim.tabpage";
++     TabPageType.tp_basicsize = sizeof(TabPageObject);
++     TabPageType.tp_dealloc = TabPageDestructor;
++     TabPageType.tp_repr = TabPageRepr;
++     TabPageType.tp_flags = Py_TPFLAGS_DEFAULT;
++     TabPageType.tp_doc = "vim tab page object";
++     TabPageType.tp_methods = TabPageMethods;
++ #if PY_MAJOR_VERSION >= 3
++     TabPageType.tp_getattro = TabPageGetattro;
++     TabPageType.tp_alloc = call_PyType_GenericAlloc;
++     TabPageType.tp_new = call_PyType_GenericNew;
++     TabPageType.tp_free = call_PyObject_Free;
++ #else
++     TabPageType.tp_getattr = TabPageGetattr;
++ #endif
++ 
+      vim_memset(&BufMapType, 0, sizeof(BufMapType));
+      BufMapType.tp_name = "vim.bufferlist";
+      BufMapType.tp_basicsize = sizeof(BufMapObject);
+***************
+*** 3582,3587 ****
+--- 3798,3811 ----
+      WinListType.tp_as_sequence = &WinListAsSeq;
+      WinListType.tp_flags = Py_TPFLAGS_DEFAULT;
+      WinListType.tp_doc = "vim window list";
++     WinListType.tp_dealloc = WinListDestructor;
++ 
++     vim_memset(&TabListType, 0, sizeof(TabListType));
++     TabListType.tp_name = "vim.tabpagelist";
++     TabListType.tp_basicsize = sizeof(TabListType);
++     TabListType.tp_as_sequence = &TabListAsSeq;
++     TabListType.tp_flags = Py_TPFLAGS_DEFAULT;
++     TabListType.tp_doc = "vim tab page list";
+  
+      vim_memset(&RangeType, 0, sizeof(RangeType));
+      RangeType.tp_name = "vim.range";
+*** ../vim-7.3.948/src/if_python3.c	2013-05-15 14:51:31.000000000 +0200
+--- src/if_python3.c	2013-05-15 15:05:04.000000000 +0200
+***************
+*** 626,631 ****
+--- 626,632 ----
+  
+  #define WIN_PYTHON_REF(win) win->w_python3_ref
+  #define BUF_PYTHON_REF(buf) buf->b_python3_ref
++ #define TAB_PYTHON_REF(tab) tab->tp_python3_ref
+  
+      static void
+  call_PyObject_Free(void *p)
+***************
+*** 652,657 ****
+--- 653,659 ----
+  static PyObject *OutputGetattro(PyObject *, PyObject *);
+  static int OutputSetattro(PyObject *, PyObject *, PyObject *);
+  static PyObject *BufferGetattro(PyObject *, PyObject *);
++ static PyObject *TabPageGetattro(PyObject *, PyObject *);
+  static PyObject *WindowGetattro(PyObject *, PyObject *);
+  static int WindowSetattro(PyObject *, PyObject *, PyObject *);
+  static PyObject *RangeGetattro(PyObject *, PyObject *);
+***************
+*** 1275,1280 ****
+--- 1277,1302 ----
+      }
+  }
+  
++ /* TabPage object - Implementation
++  */
++ 
++     static PyObject *
++ TabPageGetattro(PyObject *self, PyObject *nameobj)
++ {
++     PyObject *r;
++ 
++     GET_ATTR_STRING(name, nameobj);
++ 
++     if (CheckTabPage((TabPageObject *)(self)))
++ 	return NULL;
++ 
++     r = TabPageAttr((TabPageObject *)(self), name);
++     if (r || PyErr_Occurred())
++ 	return r;
++     else
++ 	return PyObject_GenericGetAttr(self, nameobj);
++ }
++ 
+  /* Window object - Implementation
+   */
+  
+***************
+*** 1303,1308 ****
+--- 1325,1346 ----
+      return WindowSetattr(self, name, val);
+  }
+  
++ /* Tab page list object - Definitions
++  */
++ 
++ static PySequenceMethods TabListAsSeq = {
++     (lenfunc)	     TabListLength,	    /* sq_length,    len(x)   */
++     (binaryfunc)     0,			    /* sq_concat,    x+y      */
++     (ssizeargfunc)   0,			    /* sq_repeat,    x*n      */
++     (ssizeargfunc)   TabListItem,	    /* sq_item,      x[i]     */
++     0,					    /* sq_slice,     x[i:j]   */
++     (ssizeobjargproc)0,			    /* sq_as_item,  x[i]=v   */
++     0,					    /* sq_ass_slice, x[i:j]=v */
++     0,					    /* sq_contains */
++     0,					    /* sq_inplace_concat */
++     0,					    /* sq_inplace_repeat */
++ };
++ 
+  /* Window list object - Definitions
+   */
+  
+***************
+*** 1497,1502 ****
+--- 1535,1551 ----
+  	WIN_PYTHON_REF(win) = NULL;
+      }
+  }
++ 
++     void
++ python3_tabpage_free(tabpage_T *tab)
++ {
++     if (TAB_PYTHON_REF(tab) != NULL)
++     {
++ 	TabPageObject *tp = TAB_PYTHON_REF(tab);
++ 	tp->tab = INVALID_TABPAGE_VALUE;
++ 	TAB_PYTHON_REF(tab) = NULL;
++     }
++ }
+  #endif
+  
+  static BufMapObject TheBufferMap =
+***************
+*** 1507,1512 ****
+--- 1556,1562 ----
+  static WinListObject TheWindowList =
+  {
+      PyObject_HEAD_INIT(&WinListType)
++     NULL
+  };
+  
+  static CurrentObject TheCurrent =
+***************
+*** 1514,1519 ****
+--- 1564,1574 ----
+      PyObject_HEAD_INIT(&CurrentType)
+  };
+  
++ static TabListObject TheTabPageList =
++ {
++     PyObject_HEAD_INIT(&TabListType)
++ };
++ 
+      static PyObject *
+  Py3Init_vim(void)
+  {
+***************
+*** 1526,1533 ****
+--- 1581,1590 ----
+      PyType_Ready(&BufferType);
+      PyType_Ready(&RangeType);
+      PyType_Ready(&WindowType);
++     PyType_Ready(&TabPageType);
+      PyType_Ready(&BufMapType);
+      PyType_Ready(&WinListType);
++     PyType_Ready(&TabListType);
+      PyType_Ready(&CurrentType);
+      PyType_Ready(&DictionaryType);
+      PyType_Ready(&ListType);
+***************
+*** 1551,1556 ****
+--- 1608,1615 ----
+      PyModule_AddObject(mod, "current", (PyObject *)(void *)&TheCurrent);
+      Py_INCREF((PyObject *)(void *)&TheWindowList);
+      PyModule_AddObject(mod, "windows", (PyObject *)(void *)&TheWindowList);
++     Py_INCREF((PyObject *)(void *)&TheTabPageList);
++     PyModule_AddObject(mod, "tabpages", (PyObject *)(void *)&TheTabPageList);
+  
+      PyModule_AddObject(mod, "vars", DictionaryNew(&globvardict));
+      PyModule_AddObject(mod, "vvars", DictionaryNew(&vimvardict));
+*** ../vim-7.3.948/src/if_python.c	2013-05-15 14:51:31.000000000 +0200
+--- src/if_python.c	2013-05-15 15:05:04.000000000 +0200
+***************
+*** 624,633 ****
+--- 624,635 ----
+  
+  #define WIN_PYTHON_REF(win) win->w_python_ref
+  #define BUF_PYTHON_REF(buf) buf->b_python_ref
++ #define TAB_PYTHON_REF(tab) tab->tp_python_ref
+  
+  static PyObject *OutputGetattr(PyObject *, char *);
+  static PyObject *BufferGetattr(PyObject *, char *);
+  static PyObject *WindowGetattr(PyObject *, char *);
++ static PyObject *TabPageGetattr(PyObject *, char *);
+  static PyObject *RangeGetattr(PyObject *, char *);
+  static PyObject *DictionaryGetattr(PyObject *, char*);
+  static PyObject *ListGetattr(PyObject *, char *);
+***************
+*** 1137,1142 ****
+--- 1139,1162 ----
+  		      &((RangeObject *)(self))->end);
+  }
+  
++ /* TabPage object - Implementation
++  */
++ 
++     static PyObject *
++ TabPageGetattr(PyObject *self, char *name)
++ {
++     PyObject *r;
++ 
++     if (CheckTabPage((TabPageObject *)(self)))
++ 	return NULL;
++ 
++     r = TabPageAttr((TabPageObject *)(self), name);
++     if (r || PyErr_Occurred())
++ 	return r;
++     else
++ 	return Py_FindMethod(TabPageMethods, self, name);
++ }
++ 
+  /* Window object - Implementation
+   */
+  
+***************
+*** 1155,1160 ****
+--- 1175,1198 ----
+  	return Py_FindMethod(WindowMethods, self, name);
+  }
+  
++ /* Tab page list object - Definitions
++  */
++ 
++ static PySequenceMethods TabListAsSeq = {
++     (PyInquiry)		TabListLength,	    /* sq_length,    len(x)   */
++     (binaryfunc)	0,		    /* sq_concat,    x+y      */
++     (PyIntArgFunc)	0,		    /* sq_repeat,    x*n      */
++     (PyIntArgFunc)	TabListItem,	    /* sq_item,      x[i]     */
++     (PyIntIntArgFunc)	0,		    /* sq_slice,     x[i:j]   */
++     (PyIntObjArgProc)	0,		    /* sq_ass_item,  x[i]=v   */
++     (PyIntIntObjArgProc) 0,		    /* sq_ass_slice, x[i:j]=v */
++     (objobjproc)	0,
++ #if PY_MAJOR_VERSION >= 2
++     (binaryfunc)	0,
++     0,
++ #endif
++ };
++ 
+  /* Window list object - Definitions
+   */
+  
+***************
+*** 1198,1203 ****
+--- 1236,1252 ----
+  	WIN_PYTHON_REF(win) = NULL;
+      }
+  }
++ 
++     void
++ python_tabpage_free(tabpage_T *tab)
++ {
++     if (TAB_PYTHON_REF(tab) != NULL)
++     {
++ 	TabPageObject *tp = TAB_PYTHON_REF(tab);
++ 	tp->tab = INVALID_TABPAGE_VALUE;
++ 	TAB_PYTHON_REF(tab) = NULL;
++     }
++ }
+  #endif
+  
+  static BufMapObject TheBufferMap =
+***************
+*** 1208,1213 ****
+--- 1257,1263 ----
+  static WinListObject TheWindowList =
+  {
+      PyObject_HEAD_INIT(&WinListType)
++     NULL
+  };
+  
+  static CurrentObject TheCurrent =
+***************
+*** 1215,1220 ****
+--- 1265,1275 ----
+      PyObject_HEAD_INIT(&CurrentType)
+  };
+  
++ static TabListObject TheTabPageList =
++ {
++     PyObject_HEAD_INIT(&TabListType)
++ };
++ 
+      static int
+  PythonMod_Init(void)
+  {
+***************
+*** 1229,1236 ****
+--- 1284,1293 ----
+      PyType_Ready(&BufferType);
+      PyType_Ready(&RangeType);
+      PyType_Ready(&WindowType);
++     PyType_Ready(&TabPageType);
+      PyType_Ready(&BufMapType);
+      PyType_Ready(&WinListType);
++     PyType_Ready(&TabListType);
+      PyType_Ready(&CurrentType);
+      PyType_Ready(&OptionsType);
+  
+***************
+*** 1246,1251 ****
+--- 1303,1309 ----
+      PyDict_SetItemString(dict, "buffers", (PyObject *)(void *)&TheBufferMap);
+      PyDict_SetItemString(dict, "current", (PyObject *)(void *)&TheCurrent);
+      PyDict_SetItemString(dict, "windows", (PyObject *)(void *)&TheWindowList);
++     PyDict_SetItemString(dict, "tabpages", (PyObject *)(void *)&TheTabPageList);
+      tmp = DictionaryNew(&globvardict);
+      PyDict_SetItemString(dict, "vars",    tmp);
+      Py_DECREF(tmp);
+*** ../vim-7.3.948/src/proto/if_python3.pro	2012-06-29 12:54:32.000000000 +0200
+--- src/proto/if_python3.pro	2013-05-15 15:05:04.000000000 +0200
+***************
+*** 6,11 ****
+--- 6,12 ----
+  void ex_py3file __ARGS((exarg_T *eap));
+  void python3_buffer_free __ARGS((buf_T *buf));
+  void python3_window_free __ARGS((win_T *win));
++ void python3_tabpage_free __ARGS((tabpage_T *tab));
+  void do_py3eval __ARGS((char_u *str, typval_T *rettv));
+  void set_ref_in_python3 __ARGS((int copyID));
+  /* vim: set ft=c : */
+*** ../vim-7.3.948/src/proto/if_python.pro	2012-06-29 12:54:32.000000000 +0200
+--- src/proto/if_python.pro	2013-05-15 15:05:04.000000000 +0200
+***************
+*** 6,11 ****
+--- 6,12 ----
+  void ex_pyfile __ARGS((exarg_T *eap));
+  void python_buffer_free __ARGS((buf_T *buf));
+  void python_window_free __ARGS((win_T *win));
++ void python_tabpage_free __ARGS((tabpage_T *tab));
+  void do_pyeval __ARGS((char_u *str, typval_T *rettv));
+  void set_ref_in_python __ARGS((int copyID));
+  /* vim: set ft=c : */
+*** ../vim-7.3.948/src/proto/window.pro	2013-05-12 19:00:36.000000000 +0200
+--- src/proto/window.pro	2013-05-15 15:05:04.000000000 +0200
+***************
+*** 74,78 ****
+  int match_delete __ARGS((win_T *wp, int id, int perr));
+  void clear_matches __ARGS((win_T *wp));
+  matchitem_T *get_match __ARGS((win_T *wp, int id));
+! int get_win_number __ARGS((win_T *wp));
+  /* vim: set ft=c : */
+--- 74,79 ----
+  int match_delete __ARGS((win_T *wp, int id, int perr));
+  void clear_matches __ARGS((win_T *wp));
+  matchitem_T *get_match __ARGS((win_T *wp, int id));
+! int get_win_number __ARGS((win_T *wp, win_T *first_win));
+! int get_tab_number __ARGS((tabpage_T *tp));
+  /* vim: set ft=c : */
+*** ../vim-7.3.948/src/structs.h	2013-05-06 04:21:35.000000000 +0200
+--- src/structs.h	2013-05-15 15:05:04.000000000 +0200
+***************
+*** 1759,1764 ****
+--- 1759,1772 ----
+      dictitem_T	    tp_winvar;	    /* variable for "t:" Dictionary */
+      dict_T	    *tp_vars;	    /* internal variables, local to tab page */
+  #endif
++ 
++ #ifdef FEAT_PYTHON
++     void	    *tp_python_ref;	/* The Python value for this tab page */
++ #endif
++ 
++ #ifdef FEAT_PYTHON3
++     void	    *tp_python3_ref;	/* The Python value for this tab page */
++ #endif
+  };
+  
+  /*
+*** ../vim-7.3.948/src/window.c	2013-05-12 19:00:36.000000000 +0200
+--- src/window.c	2013-05-15 15:05:04.000000000 +0200
+***************
+*** 3510,3515 ****
+--- 3510,3524 ----
+      hash_init(&tp->tp_vars->dv_hashtab);
+      unref_var_dict(tp->tp_vars);
+  #endif
++ 
++ #ifdef FEAT_PYTHON
++     python_tabpage_free(tp);
++ #endif
++ 
++ #ifdef FEAT_PYTHON3
++     python3_tabpage_free(tp);
++ #endif
++ 
+      vim_free(tp);
+  }
+  
+***************
+*** 6734,6750 ****
+  
+  #if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) || defined(PROTO)
+      int
+! get_win_number(win_T *wp)
+  {
+      int		i = 1;
+      win_T	*w;
+  
+!     for (w = firstwin; w != NULL && w != wp; w = W_NEXT(w))
+  	++i;
+  
+      if (w == NULL)
+  	return 0;
+      else
+  	return i;
+  }
+  #endif
+--- 6743,6774 ----
+  
+  #if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) || defined(PROTO)
+      int
+! get_win_number(win_T *wp, win_T *first_win)
+  {
+      int		i = 1;
+      win_T	*w;
+  
+!     for (w = first_win; w != NULL && w != wp; w = W_NEXT(w))
+  	++i;
+  
+      if (w == NULL)
+  	return 0;
+      else
+  	return i;
++ }
++ 
++     int
++ get_tab_number(tabpage_T *tp)
++ {
++     int		i = 1;
++     tabpage_T	*t;
++ 
++     for (t = first_tabpage; t != NULL && t != tp; t = t->tp_next)
++ 	++i;
++ 
++     if (t == NULL)
++ 	return 0;
++     else
++ 	return i;
+  }
+  #endif
+*** ../vim-7.3.948/src/version.c	2013-05-15 14:51:31.000000000 +0200
+--- src/version.c	2013-05-15 15:06:37.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     949,
+  /**/
+
+-- 
+BLACK KNIGHT:  Come on you pansy!
+    [hah] [parry thrust]
+    [ARTHUR chops the BLACK KNIGHT's right arm off]
+ARTHUR:        Victory is mine!  [kneeling]
+               We thank thee Lord, that in thy merc-
+    [Black Knight kicks Arthur in the head while he is praying]
+                                  The Quest for the Holy Grail (Monty Python)
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.950 b/7.3.950
new file mode 100644
index 0000000..66a0332
--- /dev/null
+++ b/7.3.950
@@ -0,0 +1,185 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.950
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.950
+Problem:    Python: Stack trace printer can't handle messages.
+Solution:   Make KeyErrors use PyErr_SetObject. (ZyX)
+Files:	    src/if_py_both.h, src/if_python3.c, src/if_python.c
+
+
+*** ../vim-7.3.949/src/if_py_both.h	2013-05-15 15:12:25.000000000 +0200
+--- src/if_py_both.h	2013-05-15 15:16:23.000000000 +0200
+***************
+*** 734,740 ****
+  
+      if (di == NULL)
+      {
+! 	PyErr_SetString(PyExc_KeyError, _("no such key in dictionary"));
+  	return NULL;
+      }
+  
+--- 734,740 ----
+  
+      if (di == NULL)
+      {
+! 	PyErr_SetObject(PyExc_KeyError, keyObject);
+  	return NULL;
+      }
+  
+***************
+*** 767,773 ****
+  	if (di == NULL)
+  	{
+  	    DICTKEY_UNREF
+! 	    PyErr_SetString(PyExc_IndexError, _("no such key in dictionary"));
+  	    return -1;
+  	}
+  	hi = hash_find(&d->dv_hashtab, di->di_key);
+--- 767,773 ----
+  	if (di == NULL)
+  	{
+  	    DICTKEY_UNREF
+! 	    PyErr_SetObject(PyExc_KeyError, keyObject);
+  	    return -1;
+  	}
+  	hi = hash_find(&d->dv_hashtab, di->di_key);
+***************
+*** 1353,1359 ****
+  
+      if (flags == 0)
+      {
+! 	PyErr_SetString(PyExc_KeyError, "Option does not exist in given scope");
+  	return NULL;
+      }
+  
+--- 1353,1359 ----
+  
+      if (flags == 0)
+      {
+! 	PyErr_SetObject(PyExc_KeyError, keyObject);
+  	return NULL;
+      }
+  
+***************
+*** 1447,1453 ****
+  
+      if (flags == 0)
+      {
+! 	PyErr_SetString(PyExc_KeyError, "Option does not exist in given scope");
+  	return -1;
+      }
+  
+--- 1447,1453 ----
+  
+      if (flags == 0)
+      {
+! 	PyErr_SetObject(PyExc_KeyError, keyObject);
+  	return -1;
+      }
+  
+***************
+*** 3145,3151 ****
+  	return BufferNew(b);
+      else
+      {
+! 	PyErr_SetString(PyExc_KeyError, _("no such buffer"));
+  	return NULL;
+      }
+  }
+--- 3145,3151 ----
+  	return BufferNew(b);
+      else
+      {
+! 	PyErr_SetObject(PyExc_KeyError, keyObject);
+  	return NULL;
+      }
+  }
+*** ../vim-7.3.949/src/if_python3.c	2013-05-15 15:12:25.000000000 +0200
+--- src/if_python3.c	2013-05-15 15:16:23.000000000 +0200
+***************
+*** 128,133 ****
+--- 128,134 ----
+  # define PyErr_Occurred py3_PyErr_Occurred
+  # define PyErr_SetNone py3_PyErr_SetNone
+  # define PyErr_SetString py3_PyErr_SetString
++ # define PyErr_SetObject py3_PyErr_SetObject
+  # define PyEval_InitThreads py3_PyEval_InitThreads
+  # define PyEval_RestoreThread py3_PyEval_RestoreThread
+  # define PyEval_SaveThread py3_PyEval_SaveThread
+***************
+*** 250,255 ****
+--- 251,257 ----
+  static PyObject* (*py3_PyErr_NoMemory)(void);
+  static void (*py3_Py_Finalize)(void);
+  static void (*py3_PyErr_SetString)(PyObject *, const char *);
++ static void (*py3_PyErr_SetObject)(PyObject *, PyObject *);
+  static int (*py3_PyRun_SimpleString)(char *);
+  static PyObject* (*py3_PyRun_String)(char *, int, PyObject *, PyObject *);
+  static PyObject* (*py3_PyList_GetItem)(PyObject *, Py_ssize_t);
+***************
+*** 379,384 ****
+--- 381,387 ----
+      {"PyErr_NoMemory", (PYTHON_PROC*)&py3_PyErr_NoMemory},
+      {"Py_Finalize", (PYTHON_PROC*)&py3_Py_Finalize},
+      {"PyErr_SetString", (PYTHON_PROC*)&py3_PyErr_SetString},
++     {"PyErr_SetObject", (PYTHON_PROC*)&py3_PyErr_SetObject},
+      {"PyRun_SimpleString", (PYTHON_PROC*)&py3_PyRun_SimpleString},
+      {"PyRun_String", (PYTHON_PROC*)&py3_PyRun_String},
+      {"PyList_GetItem", (PYTHON_PROC*)&py3_PyList_GetItem},
+*** ../vim-7.3.949/src/if_python.c	2013-05-15 15:12:25.000000000 +0200
+--- src/if_python.c	2013-05-15 15:16:23.000000000 +0200
+***************
+*** 155,160 ****
+--- 155,161 ----
+  # define PyErr_Occurred dll_PyErr_Occurred
+  # define PyErr_SetNone dll_PyErr_SetNone
+  # define PyErr_SetString dll_PyErr_SetString
++ # define PyErr_SetObject dll_PyErr_SetObject
+  # define PyEval_InitThreads dll_PyEval_InitThreads
+  # define PyEval_RestoreThread dll_PyEval_RestoreThread
+  # define PyEval_SaveThread dll_PyEval_SaveThread
+***************
+*** 260,265 ****
+--- 261,267 ----
+  static PyObject*(*dll_PyErr_Occurred)(void);
+  static void(*dll_PyErr_SetNone)(PyObject *);
+  static void(*dll_PyErr_SetString)(PyObject *, const char *);
++ static void(*dll_PyErr_SetObject)(PyObject *, PyObject *);
+  static void(*dll_PyEval_InitThreads)(void);
+  static void(*dll_PyEval_RestoreThread)(PyThreadState *);
+  static PyThreadState*(*dll_PyEval_SaveThread)(void);
+***************
+*** 393,398 ****
+--- 395,401 ----
+      {"PyErr_Occurred", (PYTHON_PROC*)&dll_PyErr_Occurred},
+      {"PyErr_SetNone", (PYTHON_PROC*)&dll_PyErr_SetNone},
+      {"PyErr_SetString", (PYTHON_PROC*)&dll_PyErr_SetString},
++     {"PyErr_SetObject", (PYTHON_PROC*)&dll_PyErr_SetObject},
+      {"PyEval_InitThreads", (PYTHON_PROC*)&dll_PyEval_InitThreads},
+      {"PyEval_RestoreThread", (PYTHON_PROC*)&dll_PyEval_RestoreThread},
+      {"PyEval_SaveThread", (PYTHON_PROC*)&dll_PyEval_SaveThread},
+*** ../vim-7.3.949/src/version.c	2013-05-15 15:12:25.000000000 +0200
+--- src/version.c	2013-05-15 15:17:56.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     950,
+  /**/
+
+-- 
+-rwxr-xr-x  1 root          24 Oct 29  1929 /bin/ed
+-rwxr-xr-t  4 root      131720 Jan  1  1970 /usr/ucb/vi
+-rwxr-xr-x  1 root  5.89824e37 Oct 22  1990 /usr/bin/emacs
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.951 b/7.3.951
new file mode 100644
index 0000000..7f1518c
--- /dev/null
+++ b/7.3.951
@@ -0,0 +1,666 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.951
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.951
+Problem:    Python exceptions have problems.
+Solution:   Change some IndexErrors to TypeErrors. Make “line number out of
+	    range” an IndexError.  Make “unable to get option value” a
+	    RuntimeError. Make all PyErr_SetString messages start with
+	    lowercase letter and use _(). (ZyX)
+Files:	    src/if_py_both.h, src/if_python3.c, src/if_python.c,
+	    src/testdir/test86.ok, src/testdir/test87.ok
+
+
+*** ../vim-7.3.950/src/if_py_both.h	2013-05-15 15:35:05.000000000 +0200
+--- src/if_py_both.h	2013-05-15 15:38:57.000000000 +0200
+***************
+*** 71,77 ****
+  {
+      if (val == NULL)
+      {
+! 	PyErr_SetString(PyExc_AttributeError, _("can't delete OutputObject attributes"));
+  	return -1;
+      }
+  
+--- 71,78 ----
+  {
+      if (val == NULL)
+      {
+! 	PyErr_SetString(PyExc_AttributeError,
+! 		_("can't delete OutputObject attributes"));
+  	return -1;
+      }
+  
+***************
+*** 919,925 ****
+  
+      if (index>=ListLength(self))
+      {
+! 	PyErr_SetString(PyExc_IndexError, "list index out of range");
+  	return NULL;
+      }
+      li = list_find(((ListObject *) (self))->list, (long) index);
+--- 920,926 ----
+  
+      if (index>=ListLength(self))
+      {
+! 	PyErr_SetString(PyExc_IndexError, _("list index out of range"));
+  	return NULL;
+      }
+      li = list_find(((ListObject *) (self))->list, (long) index);
+***************
+*** 1047,1053 ****
+      }
+      if (index>length || (index==length && obj==NULL))
+      {
+! 	PyErr_SetString(PyExc_IndexError, "list index out of range");
+  	return -1;
+      }
+  
+--- 1048,1054 ----
+      }
+      if (index>length || (index==length && obj==NULL))
+      {
+! 	PyErr_SetString(PyExc_IndexError, _("list index out of range"));
+  	return -1;
+      }
+  
+***************
+*** 1186,1192 ****
+  
+      if (val == NULL)
+      {
+! 	PyErr_SetString(PyExc_AttributeError, _("Cannot delete DictionaryObject attributes"));
+  	return -1;
+      }
+  
+--- 1187,1194 ----
+  
+      if (val == NULL)
+      {
+! 	PyErr_SetString(PyExc_AttributeError,
+! 		_("cannot delete vim.dictionary attributes"));
+  	return -1;
+      }
+  
+***************
+*** 1194,1200 ****
+      {
+  	if (this->list->lv_lock == VAR_FIXED)
+  	{
+! 	    PyErr_SetString(PyExc_TypeError, _("Cannot modify fixed list"));
+  	    return -1;
+  	}
+  	else
+--- 1196,1202 ----
+      {
+  	if (this->list->lv_lock == VAR_FIXED)
+  	{
+! 	    PyErr_SetString(PyExc_TypeError, _("cannot modify fixed list"));
+  	    return -1;
+  	}
+  	else
+***************
+*** 1208,1214 ****
+      }
+      else
+      {
+! 	PyErr_SetString(PyExc_AttributeError, _("Cannot set this attribute"));
+  	return -1;
+      }
+  }
+--- 1210,1216 ----
+      }
+      else
+      {
+! 	PyErr_SetString(PyExc_AttributeError, _("cannot set this attribute"));
+  	return -1;
+      }
+  }
+***************
+*** 1377,1383 ****
+  	    return PyBytes_FromString((char *) stringval);
+  	else
+  	{
+! 	    PyErr_SetString(PyExc_ValueError, "Unable to get option value");
+  	    return NULL;
+  	}
+      }
+--- 1379,1386 ----
+  	    return PyBytes_FromString((char *) stringval);
+  	else
+  	{
+! 	    PyErr_SetString(PyExc_RuntimeError,
+! 		    _("unable to get option value"));
+  	    return NULL;
+  	}
+      }
+***************
+*** 1455,1467 ****
+      {
+  	if (this->opt_type == SREQ_GLOBAL)
+  	{
+! 	    PyErr_SetString(PyExc_ValueError, "Unable to unset global option");
+  	    return -1;
+  	}
+  	else if (!(flags & SOPT_GLOBAL))
+  	{
+! 	    PyErr_SetString(PyExc_ValueError, "Unable to unset option without "
+! 						"global value");
+  	    return -1;
+  	}
+  	else
+--- 1458,1471 ----
+      {
+  	if (this->opt_type == SREQ_GLOBAL)
+  	{
+! 	    PyErr_SetString(PyExc_ValueError,
+! 		    _("unable to unset global option"));
+  	    return -1;
+  	}
+  	else if (!(flags & SOPT_GLOBAL))
+  	{
+! 	    PyErr_SetString(PyExc_ValueError, _("unable to unset option "
+! 						"without global value"));
+  	    return -1;
+  	}
+  	else
+***************
+*** 1491,1497 ****
+  	    val = PyLong_AsLong(valObject);
+  	else
+  	{
+! 	    PyErr_SetString(PyExc_ValueError, "Object must be integer");
+  	    return -1;
+  	}
+  
+--- 1495,1501 ----
+  	    val = PyLong_AsLong(valObject);
+  	else
+  	{
+! 	    PyErr_SetString(PyExc_TypeError, _("object must be integer"));
+  	    return -1;
+  	}
+  
+***************
+*** 1529,1535 ****
+  	}
+  	else
+  	{
+! 	    PyErr_SetString(PyExc_ValueError, "Object must be string");
+  	    return -1;
+  	}
+  
+--- 1533,1539 ----
+  	}
+  	else
+  	{
+! 	    PyErr_SetString(PyExc_TypeError, _("object must be string"));
+  	    return -1;
+  	}
+  
+***************
+*** 2766,2772 ****
+  
+      if (n < 0 || n > max)
+      {
+! 	PyErr_SetString(PyExc_ValueError, _("line number out of range"));
+  	return NULL;
+      }
+  
+--- 2770,2776 ----
+  
+      if (n < 0 || n > max)
+      {
+! 	PyErr_SetString(PyExc_IndexError, _("line number out of range"));
+  	return NULL;
+      }
+  
+***************
+*** 3135,3141 ****
+  	bnr = PyLong_AsLong(keyObject);
+      else
+      {
+! 	PyErr_SetString(PyExc_ValueError, _("key must be integer"));
+  	return NULL;
+      }
+  
+--- 3139,3145 ----
+  	bnr = PyLong_AsLong(keyObject);
+      else
+      {
+! 	PyErr_SetString(PyExc_TypeError, _("key must be integer"));
+  	return NULL;
+      }
+  
+***************
+*** 3654,3660 ****
+  	return convert_dl(obj, tv, pymap_to_tv, lookupDict);
+      else
+      {
+! 	PyErr_SetString(PyExc_TypeError, _("unable to convert to vim structure"));
+  	return -1;
+      }
+      return 0;
+--- 3658,3665 ----
+  	return convert_dl(obj, tv, pymap_to_tv, lookupDict);
+      else
+      {
+! 	PyErr_SetString(PyExc_TypeError,
+! 		_("unable to convert to vim structure"));
+  	return -1;
+      }
+      return 0;
+*** ../vim-7.3.950/src/if_python3.c	2013-05-15 15:35:05.000000000 +0200
+--- src/if_python3.c	2013-05-15 15:38:57.000000000 +0200
+***************
+*** 336,341 ****
+--- 336,342 ----
+  static PyObject *p3imp_PyExc_KeyboardInterrupt;
+  static PyObject *p3imp_PyExc_TypeError;
+  static PyObject *p3imp_PyExc_ValueError;
++ static PyObject *p3imp_PyExc_RuntimeError;
+  
+  # define PyExc_AttributeError p3imp_PyExc_AttributeError
+  # define PyExc_IndexError p3imp_PyExc_IndexError
+***************
+*** 343,348 ****
+--- 344,350 ----
+  # define PyExc_KeyboardInterrupt p3imp_PyExc_KeyboardInterrupt
+  # define PyExc_TypeError p3imp_PyExc_TypeError
+  # define PyExc_ValueError p3imp_PyExc_ValueError
++ # define PyExc_RuntimeError p3imp_PyExc_RuntimeError
+  
+  /*
+   * Table of name to function pointer of python.
+***************
+*** 580,591 ****
+--- 582,595 ----
+      p3imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt");
+      p3imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError");
+      p3imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError");
++     p3imp_PyExc_RuntimeError = PyDict_GetItemString(exdict, "RuntimeError");
+      Py_XINCREF(p3imp_PyExc_AttributeError);
+      Py_XINCREF(p3imp_PyExc_IndexError);
+      Py_XINCREF(p3imp_PyExc_KeyError);
+      Py_XINCREF(p3imp_PyExc_KeyboardInterrupt);
+      Py_XINCREF(p3imp_PyExc_TypeError);
+      Py_XINCREF(p3imp_PyExc_ValueError);
++     Py_XINCREF(p3imp_PyExc_RuntimeError);
+      Py_XDECREF(exmod);
+  }
+  #endif /* DYNAMIC_PYTHON3 */
+***************
+*** 1132,1138 ****
+      }
+      else
+      {
+! 	PyErr_SetString(PyExc_IndexError, "Index must be int or slice");
+  	return NULL;
+      }
+  }
+--- 1136,1142 ----
+      }
+      else
+      {
+! 	PyErr_SetString(PyExc_TypeError, _("index must be int or slice"));
+  	return NULL;
+      }
+  }
+***************
+*** 1166,1172 ****
+      }
+      else
+      {
+! 	PyErr_SetString(PyExc_IndexError, "Index must be int or slice");
+  	return -1;
+      }
+  }
+--- 1170,1176 ----
+      }
+      else
+      {
+! 	PyErr_SetString(PyExc_TypeError, _("index must be int or slice"));
+  	return -1;
+      }
+  }
+***************
+*** 1248,1254 ****
+      }
+      else
+      {
+! 	PyErr_SetString(PyExc_IndexError, "Index must be int or slice");
+  	return NULL;
+      }
+  }
+--- 1252,1258 ----
+      }
+      else
+      {
+! 	PyErr_SetString(PyExc_TypeError, _("index must be int or slice"));
+  	return NULL;
+      }
+  }
+***************
+*** 1275,1281 ****
+      }
+      else
+      {
+! 	PyErr_SetString(PyExc_IndexError, "Index must be int or slice");
+  	return -1;
+      }
+  }
+--- 1279,1285 ----
+      }
+      else
+      {
+! 	PyErr_SetString(PyExc_TypeError, _("index must be int or slice"));
+  	return -1;
+      }
+  }
+***************
+*** 1450,1456 ****
+      }
+      else
+      {
+! 	PyErr_SetString(PyExc_IndexError, "Index must be int or slice");
+  	return NULL;
+      }
+  }
+--- 1454,1460 ----
+      }
+      else
+      {
+! 	PyErr_SetString(PyExc_TypeError, _("index must be int or slice"));
+  	return NULL;
+      }
+  }
+***************
+*** 1474,1480 ****
+      }
+      else
+      {
+! 	PyErr_SetString(PyExc_IndexError, "Index must be int or slice");
+  	return -1;
+      }
+  }
+--- 1478,1484 ----
+      }
+      else
+      {
+! 	PyErr_SetString(PyExc_TypeError, _("index must be int or slice"));
+  	return -1;
+      }
+  }
+*** ../vim-7.3.950/src/if_python.c	2013-05-15 15:35:05.000000000 +0200
+--- src/if_python.c	2013-05-15 15:38:57.000000000 +0200
+***************
+*** 358,363 ****
+--- 358,364 ----
+  static PyObject *imp_PyExc_KeyboardInterrupt;
+  static PyObject *imp_PyExc_TypeError;
+  static PyObject *imp_PyExc_ValueError;
++ static PyObject *imp_PyExc_RuntimeError;
+  
+  # define PyExc_AttributeError imp_PyExc_AttributeError
+  # define PyExc_IndexError imp_PyExc_IndexError
+***************
+*** 365,370 ****
+--- 366,372 ----
+  # define PyExc_KeyboardInterrupt imp_PyExc_KeyboardInterrupt
+  # define PyExc_TypeError imp_PyExc_TypeError
+  # define PyExc_ValueError imp_PyExc_ValueError
++ # define PyExc_RuntimeError imp_PyExc_RuntimeError
+  
+  /*
+   * Table of name to function pointer of python.
+***************
+*** 593,604 ****
+--- 595,608 ----
+      imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt");
+      imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError");
+      imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError");
++     imp_PyExc_RuntimeError = PyDict_GetItemString(exdict, "RuntimeError");
+      Py_XINCREF(imp_PyExc_AttributeError);
+      Py_XINCREF(imp_PyExc_IndexError);
+      Py_XINCREF(imp_PyExc_KeyError);
+      Py_XINCREF(imp_PyExc_KeyboardInterrupt);
+      Py_XINCREF(imp_PyExc_TypeError);
+      Py_XINCREF(imp_PyExc_ValueError);
++     Py_XINCREF(imp_PyExc_RuntimeError);
+      Py_XDECREF(exmod);
+  }
+  #endif /* DYNAMIC_PYTHON */
+*** ../vim-7.3.950/src/testdir/test86.ok	2013-05-15 14:51:31.000000000 +0200
+--- src/testdir/test86.ok	2013-05-15 15:38:57.000000000 +0200
+***************
+*** 102,108 ****
+    B: 1:1 2:1 3:1 4:1
+  >>> previewheight
+    p/gopts1: 12
+!   inv: 'a'! ValueError
+    p/wopts1! KeyError
+    inv: 'a'! KeyError
+    wopts1! KeyError
+--- 102,108 ----
+    B: 1:1 2:1 3:1 4:1
+  >>> previewheight
+    p/gopts1: 12
+!   inv: 'a'! TypeError
+    p/wopts1! KeyError
+    inv: 'a'! KeyError
+    wopts1! KeyError
+***************
+*** 123,129 ****
+    B: 1:5 2:5 3:5 4:5
+  >>> operatorfunc
+    p/gopts1: ''
+!   inv: 2! ValueError
+    p/wopts1! KeyError
+    inv: 2! KeyError
+    wopts1! KeyError
+--- 123,129 ----
+    B: 1:5 2:5 3:5 4:5
+  >>> operatorfunc
+    p/gopts1: ''
+!   inv: 2! TypeError
+    p/wopts1! KeyError
+    inv: 2! KeyError
+    wopts1! KeyError
+***************
+*** 198,206 ****
+    B: 1:'+2' 2:'+3' 3:'+1' 4:''
+  >>> statusline
+    p/gopts1: ''
+!   inv: 0! ValueError
+    p/wopts1: None
+!   inv: 0! ValueError
+    p/bopts1! KeyError
+    inv: 0! KeyError
+    bopts1! KeyError
+--- 198,206 ----
+    B: 1:'+2' 2:'+3' 3:'+1' 4:''
+  >>> statusline
+    p/gopts1: ''
+!   inv: 0! TypeError
+    p/wopts1: None
+!   inv: 0! TypeError
+    p/bopts1! KeyError
+    inv: 0! KeyError
+    bopts1! KeyError
+***************
+*** 259,265 ****
+    wopts2! KeyError
+    wopts3! KeyError
+    p/bopts1: ''
+!   inv: 1! ValueError
+    G: ''
+    W: 1:'A' 2:'B' 3:'' 4:'C'
+    B: 1:'A' 2:'B' 3:'' 4:'C'
+--- 259,265 ----
+    wopts2! KeyError
+    wopts3! KeyError
+    p/bopts1: ''
+!   inv: 1! TypeError
+    G: ''
+    W: 1:'A' 2:'B' 3:'' 4:'C'
+    B: 1:'A' 2:'B' 3:'' 4:'C'
+***************
+*** 288,301 ****
+    B: 1:0 2:1 3:0 4:1
+  >>> path
+    p/gopts1: '.,/usr/include,,'
+!   inv: 0! ValueError
+    p/wopts1! KeyError
+    inv: 0! KeyError
+    wopts1! KeyError
+    wopts2! KeyError
+    wopts3! KeyError
+    p/bopts1: None
+!   inv: 0! ValueError
+    G: '.,,'
+    W: 1:'.,,' 2:',,' 3:'.,,' 4:'.'
+    B: 1:'.,,' 2:',,' 3:'.,,' 4:'.'
+--- 288,301 ----
+    B: 1:0 2:1 3:0 4:1
+  >>> path
+    p/gopts1: '.,/usr/include,,'
+!   inv: 0! TypeError
+    p/wopts1! KeyError
+    inv: 0! KeyError
+    wopts1! KeyError
+    wopts2! KeyError
+    wopts3! KeyError
+    p/bopts1: None
+!   inv: 0! TypeError
+    G: '.,,'
+    W: 1:'.,,' 2:',,' 3:'.,,' 4:'.'
+    B: 1:'.,,' 2:',,' 3:'.,,' 4:'.'
+*** ../vim-7.3.950/src/testdir/test87.ok	2013-05-15 14:51:31.000000000 +0200
+--- src/testdir/test87.ok	2013-05-15 15:38:57.000000000 +0200
+***************
+*** 91,97 ****
+    B: 1:1 2:1 3:1 4:1
+  >>> previewheight
+    p/gopts1: 12
+!   inv: 'a'! ValueError
+    p/wopts1! KeyError
+    inv: 'a'! KeyError
+    wopts1! KeyError
+--- 91,97 ----
+    B: 1:1 2:1 3:1 4:1
+  >>> previewheight
+    p/gopts1: 12
+!   inv: 'a'! TypeError
+    p/wopts1! KeyError
+    inv: 'a'! KeyError
+    wopts1! KeyError
+***************
+*** 112,118 ****
+    B: 1:5 2:5 3:5 4:5
+  >>> operatorfunc
+    p/gopts1: b''
+!   inv: 2! ValueError
+    p/wopts1! KeyError
+    inv: 2! KeyError
+    wopts1! KeyError
+--- 112,118 ----
+    B: 1:5 2:5 3:5 4:5
+  >>> operatorfunc
+    p/gopts1: b''
+!   inv: 2! TypeError
+    p/wopts1! KeyError
+    inv: 2! KeyError
+    wopts1! KeyError
+***************
+*** 187,195 ****
+    B: 1:'+2' 2:'+3' 3:'+1' 4:''
+  >>> statusline
+    p/gopts1: b''
+!   inv: 0! ValueError
+    p/wopts1: None
+!   inv: 0! ValueError
+    p/bopts1! KeyError
+    inv: 0! KeyError
+    bopts1! KeyError
+--- 187,195 ----
+    B: 1:'+2' 2:'+3' 3:'+1' 4:''
+  >>> statusline
+    p/gopts1: b''
+!   inv: 0! TypeError
+    p/wopts1: None
+!   inv: 0! TypeError
+    p/bopts1! KeyError
+    inv: 0! KeyError
+    bopts1! KeyError
+***************
+*** 248,254 ****
+    wopts2! KeyError
+    wopts3! KeyError
+    p/bopts1: b''
+!   inv: 1! ValueError
+    G: ''
+    W: 1:'A' 2:'B' 3:'' 4:'C'
+    B: 1:'A' 2:'B' 3:'' 4:'C'
+--- 248,254 ----
+    wopts2! KeyError
+    wopts3! KeyError
+    p/bopts1: b''
+!   inv: 1! TypeError
+    G: ''
+    W: 1:'A' 2:'B' 3:'' 4:'C'
+    B: 1:'A' 2:'B' 3:'' 4:'C'
+***************
+*** 277,290 ****
+    B: 1:0 2:1 3:0 4:1
+  >>> path
+    p/gopts1: b'.,/usr/include,,'
+!   inv: 0! ValueError
+    p/wopts1! KeyError
+    inv: 0! KeyError
+    wopts1! KeyError
+    wopts2! KeyError
+    wopts3! KeyError
+    p/bopts1: None
+!   inv: 0! ValueError
+    G: '.,,'
+    W: 1:'.,,' 2:',,' 3:'.,,' 4:'.'
+    B: 1:'.,,' 2:',,' 3:'.,,' 4:'.'
+--- 277,290 ----
+    B: 1:0 2:1 3:0 4:1
+  >>> path
+    p/gopts1: b'.,/usr/include,,'
+!   inv: 0! TypeError
+    p/wopts1! KeyError
+    inv: 0! KeyError
+    wopts1! KeyError
+    wopts2! KeyError
+    wopts3! KeyError
+    p/bopts1: None
+!   inv: 0! TypeError
+    G: '.,,'
+    W: 1:'.,,' 2:',,' 3:'.,,' 4:'.'
+    B: 1:'.,,' 2:',,' 3:'.,,' 4:'.'
+*** ../vim-7.3.950/src/version.c	2013-05-15 15:35:05.000000000 +0200
+--- src/version.c	2013-05-15 15:38:34.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     951,
+  /**/
+
+-- 
+5 out of 4 people have trouble with fractions.
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.952 b/7.3.952
new file mode 100644
index 0000000..297632f
--- /dev/null
+++ b/7.3.952
@@ -0,0 +1,166 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.952
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.952
+Problem:    Python: It's not easy to change window/buffer/tabpage.
+Solution:   Add ability to assign to vim.current.{tabpage,buffer,window}.
+	    (ZyX)
+Files:	    runtime/doc/if_pyth.txt, src/if_py_both.h
+
+
+*** ../vim-7.3.951/runtime/doc/if_pyth.txt	2013-05-15 15:12:25.000000000 +0200
+--- runtime/doc/if_pyth.txt	2013-05-15 15:48:39.000000000 +0200
+***************
+*** 242,250 ****
+  	An object providing access (via specific attributes) to various
+  	"current" objects available in vim:
+  		vim.current.line	The current line (RW)		String
+! 		vim.current.buffer	The current buffer (RO)		Buffer
+! 		vim.current.window	The current window (RO)		Window
+! 		vim.current.tabpage	The current tab page (RO)	TabPage
+  		vim.current.range	The current line range (RO)	Range
+  
+  	The last case deserves a little explanation.  When the :python or
+--- 242,250 ----
+  	An object providing access (via specific attributes) to various
+  	"current" objects available in vim:
+  		vim.current.line	The current line (RW)		String
+! 		vim.current.buffer	The current buffer (RW)		Buffer
+! 		vim.current.window	The current window (RW)		Window
+! 		vim.current.tabpage	The current tab page (RW)	TabPage
+  		vim.current.range	The current line range (RO)	Range
+  
+  	The last case deserves a little explanation.  When the :python or
+***************
+*** 252,257 ****
+--- 252,273 ----
+  	"current range".  A range is a bit like a buffer, but with all access
+  	restricted to a subset of lines.  See |python-range| for more details.
+  
++ 	Note: When assigning to vim.current.{buffer,window,tabpage} it expects 
++ 	valid |python-buffer|, |python-window| or |python-tabpage| objects 
++ 	respectively. Assigning triggers normal (with |autocommand|s) 
++ 	switching to given buffer, window or tab page. It is the only way to 
++ 	switch UI objects in python: you can't assign to 
++ 	|python-tabpage|.window attribute. To switch without triggering 
++ 	autocommands use >
++ 	    py << EOF
++ 	    saved_eventignore = vim.options['eventignore']
++ 	    vim.options['eventignore'] = 'all'
++ 	    try:
++ 	        vim.current.buffer = vim.buffers[2] # Switch to buffer 2
++ 	    finally:
++ 	        vim.options['eventignore'] = saved_eventignore
++ 	    EOF
++ <
+  vim.vars						*python-vars*
+  vim.vvars						*python-vvars*
+  	Dictionary-like objects holding dictionaries with global (|g:|) and 
+*** ../vim-7.3.951/src/if_py_both.h	2013-05-15 15:44:24.000000000 +0200
+--- src/if_py_both.h	2013-05-15 15:48:39.000000000 +0200
+***************
+*** 3244,3249 ****
+--- 3244,3323 ----
+  
+  	return 0;
+      }
++     else if (strcmp(name, "buffer") == 0)
++     {
++ 	int count;
++ 
++ 	if (value->ob_type != &BufferType)
++ 	{
++ 	    PyErr_SetString(PyExc_TypeError, _("expected vim.buffer object"));
++ 	    return -1;
++ 	}
++ 
++ 	if (CheckBuffer((BufferObject *)(value)))
++ 	    return -1;
++ 	count = ((BufferObject *)(value))->buf->b_fnum;
++ 
++ 	if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, count, 0) == FAIL)
++ 	{
++ 	    PyErr_SetVim(_("failed to switch to given buffer"));
++ 	    return -1;
++ 	}
++ 
++ 	return 0;
++     }
++     else if (strcmp(name, "window") == 0)
++     {
++ 	int count;
++ 
++ 	if (value->ob_type != &WindowType)
++ 	{
++ 	    PyErr_SetString(PyExc_TypeError, _("expected vim.window object"));
++ 	    return -1;
++ 	}
++ 
++ 	if (CheckWindow((WindowObject *)(value)))
++ 	    return -1;
++ 	count = get_win_number(((WindowObject *)(value))->win, firstwin);
++ 
++ 	if (!count)
++ 	{
++ 	    PyErr_SetString(PyExc_ValueError,
++ 		    _("failed to find window in the current tab page"));
++ 	    return -1;
++ 	}
++ 
++ 	win_goto(((WindowObject *)(value))->win);
++ 	if (((WindowObject *)(value))->win != curwin)
++ 	{
++ 	    PyErr_SetString(PyExc_RuntimeError,
++ 		    _("did not switch to the specified window"));
++ 	    return -1;
++ 	}
++ 
++ 	return 0;
++     }
++     else if (strcmp(name, "tabpage") == 0)
++     {
++ 	if (value->ob_type != &TabPageType)
++ 	{
++ 	    PyErr_SetString(PyExc_TypeError, _("expected vim.tabpage object"));
++ 	    return -1;
++ 	}
++ 
++ 	if (CheckTabPage((TabPageObject *)(value)))
++ 	    return -1;
++ 
++ 	goto_tabpage_tp(((TabPageObject *)(value))->tab, TRUE, TRUE);
++ 	if (((TabPageObject *)(value))->tab != curtab)
++ 	{
++ 	    PyErr_SetString(PyExc_RuntimeError,
++ 		    _("did not switch to the specified tab page"));
++ 	    return -1;
++ 	}
++ 
++ 	return 0;
++     }
+      else
+      {
+  	PyErr_SetString(PyExc_AttributeError, name);
+*** ../vim-7.3.951/src/version.c	2013-05-15 15:44:24.000000000 +0200
+--- src/version.c	2013-05-15 15:49:12.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     952,
+  /**/
+
+-- 
+Trees moving back and forth is what makes the wind blow.
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.953 b/7.3.953
new file mode 100644
index 0000000..9eb70bd
--- /dev/null
+++ b/7.3.953
@@ -0,0 +1,103 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.953
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.953
+Problem:    Python: string exceptions are deprecated.
+Solution:   Make vim.error an Exception subclass. (ZyX)
+Files:	    src/if_python.c, src/if_python3.c
+
+
+*** ../vim-7.3.952/src/if_python.c	2013-05-15 15:44:24.000000000 +0200
+--- src/if_python.c	2013-05-15 16:02:20.000000000 +0200
+***************
+*** 149,154 ****
+--- 149,155 ----
+  # define PyMem_Malloc dll_PyMem_Malloc
+  # define PyDict_SetItemString dll_PyDict_SetItemString
+  # define PyErr_BadArgument dll_PyErr_BadArgument
++ # define PyErr_NewException dll_PyErr_NewException
+  # define PyErr_Clear dll_PyErr_Clear
+  # define PyErr_PrintEx dll_PyErr_PrintEx
+  # define PyErr_NoMemory dll_PyErr_NoMemory
+***************
+*** 255,260 ****
+--- 256,262 ----
+  static void* (*dll_PyMem_Malloc)(size_t);
+  static int(*dll_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item);
+  static int(*dll_PyErr_BadArgument)(void);
++ static PyObject *(*dll_PyErr_NewException)(char *, PyObject *, PyObject *);
+  static void(*dll_PyErr_Clear)(void);
+  static void(*dll_PyErr_PrintEx)(int);
+  static PyObject*(*dll_PyErr_NoMemory)(void);
+***************
+*** 391,396 ****
+--- 393,399 ----
+      {"PyMem_Malloc", (PYTHON_PROC*)&dll_PyMem_Malloc},
+      {"PyDict_SetItemString", (PYTHON_PROC*)&dll_PyDict_SetItemString},
+      {"PyErr_BadArgument", (PYTHON_PROC*)&dll_PyErr_BadArgument},
++     {"PyErr_NewException", (PYTHON_PROC*)&dll_PyErr_NewException},
+      {"PyErr_Clear", (PYTHON_PROC*)&dll_PyErr_Clear},
+      {"PyErr_PrintEx", (PYTHON_PROC*)&dll_PyErr_PrintEx},
+      {"PyErr_NoMemory", (PYTHON_PROC*)&dll_PyErr_NoMemory},
+***************
+*** 1304,1310 ****
+      mod = Py_InitModule4("vim", VimMethods, (char *)NULL, (PyObject *)NULL, PYTHON_API_VERSION);
+      dict = PyModule_GetDict(mod);
+  
+!     VimError = Py_BuildValue("s", "vim.error");
+  
+      PyDict_SetItemString(dict, "error", VimError);
+      PyDict_SetItemString(dict, "buffers", (PyObject *)(void *)&TheBufferMap);
+--- 1307,1313 ----
+      mod = Py_InitModule4("vim", VimMethods, (char *)NULL, (PyObject *)NULL, PYTHON_API_VERSION);
+      dict = PyModule_GetDict(mod);
+  
+!     VimError = PyErr_NewException("vim.error", NULL, NULL);
+  
+      PyDict_SetItemString(dict, "error", VimError);
+      PyDict_SetItemString(dict, "buffers", (PyObject *)(void *)&TheBufferMap);
+*** ../vim-7.3.952/src/if_python3.c	2013-05-15 15:44:24.000000000 +0200
+--- src/if_python3.c	2013-05-15 16:02:20.000000000 +0200
+***************
+*** 1606,1613 ****
+  	return NULL;
+  
+      VimError = PyErr_NewException("vim.error", NULL, NULL);
+-     Py_INCREF(VimError);
+  
+      PyModule_AddObject(mod, "error", VimError);
+      Py_INCREF((PyObject *)(void *)&TheBufferMap);
+      PyModule_AddObject(mod, "buffers", (PyObject *)(void *)&TheBufferMap);
+--- 1606,1613 ----
+  	return NULL;
+  
+      VimError = PyErr_NewException("vim.error", NULL, NULL);
+  
++     Py_INCREF(VimError);
+      PyModule_AddObject(mod, "error", VimError);
+      Py_INCREF((PyObject *)(void *)&TheBufferMap);
+      PyModule_AddObject(mod, "buffers", (PyObject *)(void *)&TheBufferMap);
+*** ../vim-7.3.952/src/version.c	2013-05-15 15:51:03.000000000 +0200
+--- src/version.c	2013-05-15 16:02:43.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     953,
+  /**/
+
+-- 
+The early bird gets the worm. If you want something else for
+breakfast, get up later.
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.954 b/7.3.954
new file mode 100644
index 0000000..4e37875
--- /dev/null
+++ b/7.3.954
@@ -0,0 +1,94 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.954
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.954
+Problem:    No check if PyObject_IsTrue fails.
+Solution:   Add a check for -1 value. (ZyX)
+Files:	    src/if_py_both.h
+
+
+*** ../vim-7.3.953/src/if_py_both.h	2013-05-15 15:51:03.000000000 +0200
+--- src/if_py_both.h	2013-05-15 16:08:53.000000000 +0200
+***************
+*** 700,706 ****
+  	}
+  	else
+  	{
+! 	    if (PyObject_IsTrue(val))
+  		this->dict->dv_lock = VAR_LOCKED;
+  	    else
+  		this->dict->dv_lock = 0;
+--- 700,709 ----
+  	}
+  	else
+  	{
+! 	    int		istrue = PyObject_IsTrue(val);
+! 	    if (istrue == -1)
+! 		return -1;
+! 	    else if (istrue)
+  		this->dict->dv_lock = VAR_LOCKED;
+  	    else
+  		this->dict->dv_lock = 0;
+***************
+*** 1201,1207 ****
+  	}
+  	else
+  	{
+! 	    if (PyObject_IsTrue(val))
+  		this->list->lv_lock = VAR_LOCKED;
+  	    else
+  		this->list->lv_lock = 0;
+--- 1204,1213 ----
+  	}
+  	else
+  	{
+! 	    int		istrue = PyObject_IsTrue(val);
+! 	    if (istrue == -1)
+! 		return -1;
+! 	    else if (istrue)
+  		this->list->lv_lock = VAR_LOCKED;
+  	    else
+  		this->list->lv_lock = 0;
+***************
+*** 1479,1485 ****
+  
+      if (flags & SOPT_BOOL)
+      {
+! 	r = set_option_value_for(key, PyObject_IsTrue(valObject), NULL,
+  				opt_flags, this->opt_type, this->from);
+      }
+      else if (flags & SOPT_NUM)
+--- 1485,1494 ----
+  
+      if (flags & SOPT_BOOL)
+      {
+! 	int	istrue = PyObject_IsTrue(valObject);
+! 	if (istrue == -1)
+! 	    return -1;
+! 	r = set_option_value_for(key, istrue, NULL,
+  				opt_flags, this->opt_type, this->from);
+      }
+      else if (flags & SOPT_NUM)
+*** ../vim-7.3.953/src/version.c	2013-05-15 16:04:34.000000000 +0200
+--- src/version.c	2013-05-15 16:08:26.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     954,
+  /**/
+
+-- 
+The early bird gets the worm. The second mouse gets the cheese.
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.955 b/7.3.955
new file mode 100644
index 0000000..cccf462
--- /dev/null
+++ b/7.3.955
@@ -0,0 +1,339 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.955
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.955
+Problem:    Python: Not enough tests.
+Solution:   Add tests for vim.{current,window*,tabpage*}. (ZyX)
+Files:	    src/testdir/test86.in, src/testdir/test86.ok,
+	    src/testdir/test87.in, src/testdir/test87.ok
+
+
+*** ../vim-7.3.954/src/testdir/test86.in	2013-05-15 14:51:31.000000000 +0200
+--- src/testdir/test86.in	2013-05-15 16:15:25.000000000 +0200
+***************
+*** 334,339 ****
+--- 334,340 ----
+  :let g:foo = 'bac'
+  :let w:abc = 'def'
+  :let b:baz = 'bar'
++ :let t:bar = 'jkl'
+  :try
+  :  throw "Abc"
+  :catch
+***************
+*** 342,347 ****
+--- 343,349 ----
+  :put =pyeval('vim.vars[''foo'']')
+  :put =pyeval('vim.current.window.vars[''abc'']')
+  :put =pyeval('vim.current.buffer.vars[''baz'']')
++ :put =pyeval('vim.current.tabpage.vars[''bar'']')
+  :"
+  :" Options
+  :" paste:          boolean, global
+***************
+*** 561,566 ****
+--- 563,640 ----
+  except StopIteration:
+      cb.append('StopIteration')
+  EOF
++ :"
++ :" Test vim.{tabpage,window}list and vim.{tabpage,window} objects
++ :tabnew 0
++ :tabnew 1
++ :vnew a.1
++ :tabnew 2
++ :vnew a.2
++ :vnew b.2
++ :vnew c.2
++ py << EOF
++ cb.append('Number of tabs: ' + str(len(vim.tabpages)))
++ cb.append('Current tab pages:')
++ def W(w):
++     if '(unknown)' in repr(w):
++         return '<window object (unknown)>'
++     else:
++         return repr(w)
++ for t in vim.tabpages:
++     cb.append('  ' + repr(t) + '(' + str(t.number) + ')' + ': ' + str(len(t.windows)) + ' windows, current is ' + W(t.window))
++     cb.append('  Windows:')
++     for w in t.windows:
++         cb.append('    ' + W(w) + '(' + str(w.number) + ')' + ': displays buffer ' + repr(w.buffer) + '; cursor is at ' + repr(w.cursor))
++         # Other values depend on the size of the terminal, so they are checked partly:
++         for attr in ('height', 'row', 'width', 'col'):
++             try:
++                 aval = getattr(w, attr)
++                 if type(aval) is not long:
++                     raise TypeError
++                 if aval < 0:
++                     raise ValueError
++             except Exception:
++                 cb.append('!!!!!! Error while getting attribute ' + attr + ': ' + sys.exc_type.__name__)
++         w.cursor = (len(w.buffer), 0)
++ cb.append('Number of windows in current tab page: ' + str(len(vim.windows)))
++ if list(vim.windows) != list(vim.current.tabpage.windows):
++     cb.append('!!!!!! Windows differ')
++ EOF
++ :"
++ :" Test vim.current
++ py << EOF
++ def H(o):
++     return repr(o)
++ cb.append('Current tab page: ' + repr(vim.current.tabpage))
++ cb.append('Current window: ' + repr(vim.current.window) + ': ' + H(vim.current.window) + ' is ' + H(vim.current.tabpage.window))
++ cb.append('Current buffer: ' + repr(vim.current.buffer) + ': ' + H(vim.current.buffer) + ' is ' + H(vim.current.window.buffer)+ ' is ' + H(vim.current.tabpage.window.buffer))
++ # Assigning: fails
++ try:
++     vim.current.window = vim.tabpages[0].window
++ except ValueError:
++     cb.append('ValueError at assigning foreign tab window')
++ 
++ for attr in ('window', 'tabpage', 'buffer'):
++     try:
++         setattr(vim.current, attr, None)
++     except TypeError:
++         cb.append('Type error at assigning None to vim.current.' + attr)
++ 
++ # Assigning: success
++ vim.current.tabpage = vim.tabpages[-2]
++ vim.current.buffer = cb
++ vim.current.window = vim.windows[0]
++ vim.current.window.cursor = (len(vim.current.buffer), 0)
++ cb.append('Current tab page: ' + repr(vim.current.tabpage))
++ cb.append('Current window: ' + repr(vim.current.window))
++ cb.append('Current buffer: ' + repr(vim.current.buffer))
++ cb.append('Current line: ' + repr(vim.current.line))
++ for b in vim.buffers:
++     if b is not cb:
++         vim.command('bwipeout! ' + b.number)
++ EOF
++ :tabonly!
++ :only!
+  :endfun
+  :"
+  :call Test()
+*** ../vim-7.3.954/src/testdir/test86.ok	2013-05-15 15:44:24.000000000 +0200
+--- src/testdir/test86.ok	2013-05-15 16:22:06.000000000 +0200
+***************
+*** 80,85 ****
+--- 80,86 ----
+  bac
+  def
+  bar
++ jkl
+  >>> paste
+    p/gopts1: False
+    p/wopts1! KeyError
+***************
+*** 328,330 ****
+--- 329,361 ----
+  i4:<buffer test86.in>
+  i4:<buffer test86.in>
+  StopIteration
++ Number of tabs: 4
++ Current tab pages:
++   <tabpage 0>(1): 1 windows, current is <window object (unknown)>
++   Windows:
++     <window object (unknown)>(0): displays buffer <buffer test86.in>; cursor is at (954, 0)
++   <tabpage 1>(2): 1 windows, current is <window object (unknown)>
++   Windows:
++     <window object (unknown)>(0): displays buffer <buffer 0>; cursor is at (1, 0)
++   <tabpage 2>(3): 2 windows, current is <window object (unknown)>
++   Windows:
++     <window object (unknown)>(0): displays buffer <buffer a.1>; cursor is at (1, 0)
++     <window object (unknown)>(0): displays buffer <buffer 1>; cursor is at (1, 0)
++   <tabpage 3>(4): 4 windows, current is <window 0>
++   Windows:
++     <window 0>(1): displays buffer <buffer c.2>; cursor is at (1, 0)
++     <window 1>(2): displays buffer <buffer b.2>; cursor is at (1, 0)
++     <window 2>(3): displays buffer <buffer a.2>; cursor is at (1, 0)
++     <window 3>(4): displays buffer <buffer 2>; cursor is at (1, 0)
++ Number of windows in current tab page: 4
++ Current tab page: <tabpage 3>
++ Current window: <window 0>: <window 0> is <window 0>
++ Current buffer: <buffer c.2>: <buffer c.2> is <buffer c.2> is <buffer c.2>
++ ValueError at assigning foreign tab window
++ Type error at assigning None to vim.current.window
++ Type error at assigning None to vim.current.tabpage
++ Type error at assigning None to vim.current.buffer
++ Current tab page: <tabpage 2>
++ Current window: <window 0>
++ Current buffer: <buffer test86.in>
++ Current line: 'Type error at assigning None to vim.current.buffer'
+*** ../vim-7.3.954/src/testdir/test87.in	2013-05-15 14:39:47.000000000 +0200
+--- src/testdir/test87.in	2013-05-15 16:15:25.000000000 +0200
+***************
+*** 320,325 ****
+--- 320,326 ----
+  :let g:foo = 'bac'
+  :let w:abc = 'def'
+  :let b:baz = 'bar'
++ :let t:bar = 'jkl'
+  :try
+  :  throw "Abc"
+  :catch
+***************
+*** 328,333 ****
+--- 329,335 ----
+  :put =py3eval('vim.vars[''foo'']')
+  :put =py3eval('vim.current.window.vars[''abc'']')
+  :put =py3eval('vim.current.buffer.vars[''baz'']')
++ :put =py3eval('vim.current.tabpage.vars[''bar'']')
+  :"
+  :" Options
+  :" paste:          boolean, global
+***************
+*** 547,552 ****
+--- 549,626 ----
+  except StopIteration:
+      cb.append('StopIteration')
+  EOF
++ :"
++ :" Test vim.{tabpage,window}list and vim.{tabpage,window} objects
++ :tabnew 0
++ :tabnew 1
++ :vnew a.1
++ :tabnew 2
++ :vnew a.2
++ :vnew b.2
++ :vnew c.2
++ py3 << EOF
++ def W(w):
++     if '(unknown)' in repr(w):
++         return '<window object (unknown)>'
++     else:
++         return repr(w)
++ cb.append('Number of tabs: ' + str(len(vim.tabpages)))
++ cb.append('Current tab pages:')
++ for t in vim.tabpages:
++     cb.append('  ' + repr(t) + '(' + str(t.number) + ')' + ': ' + str(len(t.windows)) + ' windows, current is ' + W(t.window))
++     cb.append('  Windows:')
++     for w in t.windows:
++         cb.append('    ' + W(w) + '(' + str(w.number) + ')' + ': displays buffer ' + repr(w.buffer) + '; cursor is at ' + repr(w.cursor))
++         # Other values depend on the size of the terminal, so they are checked partly:
++         for attr in ('height', 'row', 'width', 'col'):
++             try:
++                 aval = getattr(w, attr)
++                 if type(aval) is not int:
++                     raise TypeError
++                 if aval < 0:
++                     raise ValueError
++             except Exception as e:
++                 cb.append('!!!!!! Error while getting attribute ' + attr + ': ' + e.__class__.__name__)
++         w.cursor = (len(w.buffer), 0)
++ cb.append('Number of windows in current tab page: ' + str(len(vim.windows)))
++ if list(vim.windows) != list(vim.current.tabpage.windows):
++     cb.append('!!!!!! Windows differ')
++ EOF
++ :"
++ :" Test vim.current
++ py3 << EOF
++ def H(o):
++     return repr(o)
++ cb.append('Current tab page: ' + repr(vim.current.tabpage))
++ cb.append('Current window: ' + repr(vim.current.window) + ': ' + H(vim.current.window) + ' is ' + H(vim.current.tabpage.window))
++ cb.append('Current buffer: ' + repr(vim.current.buffer) + ': ' + H(vim.current.buffer) + ' is ' + H(vim.current.window.buffer)+ ' is ' + H(vim.current.tabpage.window.buffer))
++ # Assigning: fails
++ try:
++     vim.current.window = vim.tabpages[0].window
++ except ValueError:
++     cb.append('ValueError at assigning foreign tab window')
++ 
++ for attr in ('window', 'tabpage', 'buffer'):
++     try:
++         setattr(vim.current, attr, None)
++     except TypeError:
++         cb.append('Type error at assigning None to vim.current.' + attr)
++ 
++ # Assigning: success
++ vim.current.tabpage = vim.tabpages[-2]
++ vim.current.buffer = cb
++ vim.current.window = vim.windows[0]
++ vim.current.window.cursor = (len(vim.current.buffer), 0)
++ cb.append('Current tab page: ' + repr(vim.current.tabpage))
++ cb.append('Current window: ' + repr(vim.current.window))
++ cb.append('Current buffer: ' + repr(vim.current.buffer))
++ cb.append('Current line: ' + repr(vim.current.line))
++ for b in vim.buffers:
++     if b is not cb:
++         vim.command('bwipeout! ' + str(b.number))
++ EOF
++ :tabonly!
++ :only!
+  :endfun
+  :"
+  :call Test()
+*** ../vim-7.3.954/src/testdir/test87.ok	2013-05-15 15:44:24.000000000 +0200
+--- src/testdir/test87.ok	2013-05-15 16:21:39.000000000 +0200
+***************
+*** 69,74 ****
+--- 69,75 ----
+  bac
+  def
+  bar
++ jkl
+  >>> paste
+    p/gopts1: False
+    p/wopts1! KeyError
+***************
+*** 317,319 ****
+--- 318,350 ----
+  i4:<buffer test87.in>
+  i4:<buffer test87.in>
+  StopIteration
++ Number of tabs: 4
++ Current tab pages:
++   <tabpage 0>(1): 1 windows, current is <window object (unknown)>
++   Windows:
++     <window object (unknown)>(0): displays buffer <buffer test87.in>; cursor is at (929, 0)
++   <tabpage 1>(2): 1 windows, current is <window object (unknown)>
++   Windows:
++     <window object (unknown)>(0): displays buffer <buffer 0>; cursor is at (1, 0)
++   <tabpage 2>(3): 2 windows, current is <window object (unknown)>
++   Windows:
++     <window object (unknown)>(0): displays buffer <buffer a.1>; cursor is at (1, 0)
++     <window object (unknown)>(0): displays buffer <buffer 1>; cursor is at (1, 0)
++   <tabpage 3>(4): 4 windows, current is <window 0>
++   Windows:
++     <window 0>(1): displays buffer <buffer c.2>; cursor is at (1, 0)
++     <window 1>(2): displays buffer <buffer b.2>; cursor is at (1, 0)
++     <window 2>(3): displays buffer <buffer a.2>; cursor is at (1, 0)
++     <window 3>(4): displays buffer <buffer 2>; cursor is at (1, 0)
++ Number of windows in current tab page: 4
++ Current tab page: <tabpage 3>
++ Current window: <window 0>: <window 0> is <window 0>
++ Current buffer: <buffer c.2>: <buffer c.2> is <buffer c.2> is <buffer c.2>
++ ValueError at assigning foreign tab window
++ Type error at assigning None to vim.current.window
++ Type error at assigning None to vim.current.tabpage
++ Type error at assigning None to vim.current.buffer
++ Current tab page: <tabpage 2>
++ Current window: <window 0>
++ Current buffer: <buffer test87.in>
++ Current line: 'Type error at assigning None to vim.current.buffer'
+*** ../vim-7.3.954/src/version.c	2013-05-15 16:11:46.000000000 +0200
+--- src/version.c	2013-05-15 16:14:46.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     955,
+  /**/
+
+-- 
+FATHER:    You only killed the bride's father - that's all -
+LAUNCELOT: Oh dear, I didn't really mean to...
+FATHER:    Didn't mean to?  You put your sword right through his head!
+LAUNCELOT: Gosh - Is he all right?
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.956 b/7.3.956
new file mode 100644
index 0000000..d4c1be6
--- /dev/null
+++ b/7.3.956
@@ -0,0 +1,224 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.956
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.956
+Problem:    Python vim.bindeval() causes SIGABRT.
+Solution:   Make pygilstate a local variable. (Yukihiro Nakadaira)
+Files:	    src/if_py_both.h, src/if_python.c, src/if_python3.c
+
+
+*** ../vim-7.3.955/src/if_py_both.h	2013-05-15 16:11:46.000000000 +0200
+--- src/if_py_both.h	2013-05-15 17:37:48.000000000 +0200
+***************
+*** 1298,1304 ****
+--- 1298,1311 ----
+  	}
+      }
+  
++     Py_BEGIN_ALLOW_THREADS
++     Python_Lock_Vim();
++ 
+      error = func_call(name, &args, selfdict, &rettv);
++ 
++     Python_Release_Vim();
++     Py_END_ALLOW_THREADS
++ 
+      if (error != OK)
+      {
+  	result = NULL;
+*** ../vim-7.3.955/src/if_python.c	2013-05-15 16:04:34.000000000 +0200
+--- src/if_python.c	2013-05-15 17:37:48.000000000 +0200
+***************
+*** 676,686 ****
+  typedef PyObject PyThreadState;
+  #endif
+  
+! #ifdef PY_CAN_RECURSE
+! static PyGILState_STATE pygilstate = PyGILState_UNLOCKED;
+! #else
+  static PyThreadState *saved_python_thread = NULL;
+- #endif
+  
+  /*
+   * Suspend a thread of the Python interpreter, other threads are allowed to
+--- 676,683 ----
+  typedef PyObject PyThreadState;
+  #endif
+  
+! #ifndef PY_CAN_RECURSE
+  static PyThreadState *saved_python_thread = NULL;
+  
+  /*
+   * Suspend a thread of the Python interpreter, other threads are allowed to
+***************
+*** 689,699 ****
+      static void
+  Python_SaveThread(void)
+  {
+- #ifdef PY_CAN_RECURSE
+-     PyGILState_Release(pygilstate);
+- #else
+      saved_python_thread = PyEval_SaveThread();
+- #endif
+  }
+  
+  /*
+--- 686,692 ----
+***************
+*** 703,715 ****
+      static void
+  Python_RestoreThread(void)
+  {
+- #ifdef PY_CAN_RECURSE
+-     pygilstate = PyGILState_Ensure();
+- #else
+      PyEval_RestoreThread(saved_python_thread);
+      saved_python_thread = NULL;
+- #endif
+  }
+  
+      void
+  python_end()
+--- 696,705 ----
+      static void
+  Python_RestoreThread(void)
+  {
+      PyEval_RestoreThread(saved_python_thread);
+      saved_python_thread = NULL;
+  }
++ #endif
+  
+      void
+  python_end()
+***************
+*** 725,738 ****
+--- 715,736 ----
+  #ifdef DYNAMIC_PYTHON
+      if (hinstPython && Py_IsInitialized())
+      {
++ # ifdef PY_CAN_RECURSE
++ 	PyGILState_Ensure();
++ # else
+  	Python_RestoreThread();	    /* enter python */
++ # endif
+  	Py_Finalize();
+      }
+      end_dynamic_python();
+  #else
+      if (Py_IsInitialized())
+      {
++ # ifdef PY_CAN_RECURSE
++ 	PyGILState_Ensure();
++ # else
+  	Python_RestoreThread();	    /* enter python */
++ # endif
+  	Py_Finalize();
+      }
+  #endif
+***************
+*** 837,842 ****
+--- 835,843 ----
+  #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+      char		*saved_locale;
+  #endif
++ #ifdef PY_CAN_RECURSE
++     PyGILState_STATE	pygilstate;
++ #endif
+  
+  #ifndef PY_CAN_RECURSE
+      if (recursive)
+***************
+*** 881,887 ****
+--- 882,892 ----
+      }
+  #endif
+  
++ #ifdef PY_CAN_RECURSE
++     pygilstate = PyGILState_Ensure();
++ #else
+      Python_RestoreThread();	    /* enter python */
++ #endif
+  
+      if (rettv == NULL)
+  	PyRun_SimpleString((char *)(cmd));
+***************
+*** 905,911 ****
+--- 910,920 ----
+  	PyErr_Clear();
+      }
+  
++ #ifdef PY_CAN_RECURSE
++     PyGILState_Release(pygilstate);
++ #else
+      Python_SaveThread();	    /* leave python */
++ #endif
+  
+  #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+      if (saved_locale != NULL)
+*** ../vim-7.3.955/src/if_python3.c	2013-05-15 16:04:34.000000000 +0200
+--- src/if_python3.c	2013-05-15 17:37:48.000000000 +0200
+***************
+*** 699,706 ****
+   * 1. Python interpreter main program.
+   */
+  
+- static PyGILState_STATE pygilstate = PyGILState_UNLOCKED;
+- 
+      void
+  python3_end()
+  {
+--- 699,704 ----
+***************
+*** 718,724 ****
+      if (Py_IsInitialized())
+      {
+  	// acquire lock before finalizing
+! 	pygilstate = PyGILState_Ensure();
+  
+  	Py_Finalize();
+      }
+--- 716,722 ----
+      if (Py_IsInitialized())
+      {
+  	// acquire lock before finalizing
+! 	PyGILState_Ensure();
+  
+  	Py_Finalize();
+      }
+***************
+*** 826,831 ****
+--- 824,830 ----
+  #endif
+      PyObject		*cmdstr;
+      PyObject		*cmdbytes;
++     PyGILState_STATE	pygilstate;
+  
+  #if defined(MACOS) && !defined(MACOS_X_UNIX)
+      GetPort(&oldPort);
+*** ../vim-7.3.955/src/version.c	2013-05-15 16:27:33.000000000 +0200
+--- src/version.c	2013-05-15 17:48:15.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     956,
+  /**/
+
+-- 
+GUEST:        He's killed the best man!
+SECOND GUEST: (holding a limp WOMAN) He's killed my auntie.
+FATHER:       No, please!  This is supposed to be a happy occasion!  Let's
+              not bicker and argue about who killed who ...
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.957 b/7.3.957
new file mode 100644
index 0000000..ac684c3
--- /dev/null
+++ b/7.3.957
@@ -0,0 +1,287 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.957
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.957
+Problem:    Python does not have a "do" command like Perl or Lua.
+Solution:   Add the ":py3do" command. (Lilydjwg)
+Files:	    runtime/doc/if_pyth.txt, src/ex_cmds.h, src/ex_docmd.c,
+	    src/if_python3.c, src/proto/if_python3.pro
+
+
+*** ../vim-7.3.956/runtime/doc/if_pyth.txt	2013-05-15 15:51:03.000000000 +0200
+--- runtime/doc/if_pyth.txt	2013-05-15 18:04:17.000000000 +0200
+***************
+*** 490,495 ****
+--- 490,510 ----
+  <							*:py3file*
+  The |:py3file| command works similar to |:pyfile|.
+  
++ 							*:py3do*
++ :[range]py3do {body}	Execute Python function "def _vim_pydo(line, linenr):
++ 			{body}" for each line in the [range], with the
++ 			function arguments being set to the text of each line
++ 			in turn, without a trailing <EOL>, and the current
++ 			line number. The function should return a string or
++ 			None. If a string is returned, it becomes the text of
++ 			the line in the current turn. The default for [range]
++ 			is the whole file: "1,$".
++ 			{not in Vi}
++ 
++ Examples:
++ >
++ 	:py3do return "%s\t%d" % (line[::-1], len(line))
++ 	:py3do if line: return "%4d: %s" % (linenr, line)
+  
+  Vim can be built in four ways (:version output):
+  1. No Python support	    (-python, -python3)
+*** ../vim-7.3.956/src/ex_cmds.h	2012-11-14 20:52:22.000000000 +0100
+--- src/ex_cmds.h	2013-05-15 18:01:55.000000000 +0200
+***************
+*** 743,748 ****
+--- 743,750 ----
+  			RANGE|FILE1|NEEDARG|CMDWIN),
+  EX(CMD_py3,		"py3",		ex_py3,
+  			RANGE|EXTRA|NEEDARG|CMDWIN),
++ EX(CMD_py3do,		"py3do",	ex_py3do,
++ 			RANGE|DFLALL|EXTRA|NEEDARG|CMDWIN),
+  EX(CMD_python3,		"python3",	ex_py3,
+  			RANGE|EXTRA|NEEDARG|CMDWIN),
+  EX(CMD_py3file,		"py3file",	ex_py3file,
+*** ../vim-7.3.956/src/ex_docmd.c	2013-05-07 05:18:15.000000000 +0200
+--- src/ex_docmd.c	2013-05-15 18:01:55.000000000 +0200
+***************
+*** 272,277 ****
+--- 272,278 ----
+  #endif
+  #ifndef FEAT_PYTHON3
+  # define ex_py3			ex_script_ni
++ # define ex_py3do		ex_ni
+  # define ex_py3file		ex_ni
+  #endif
+  #ifndef FEAT_TCL
+*** ../vim-7.3.956/src/if_python3.c	2013-05-15 17:49:00.000000000 +0200
+--- src/if_python3.c	2013-05-15 18:23:30.000000000 +0200
+***************
+*** 76,81 ****
+--- 76,82 ----
+  #else
+  # define CODEC_ERROR_HANDLER NULL
+  #endif
++ #define DOPY_FUNC "_vim_pydo"
+  
+  /* Python 3 does not support CObjects, always use Capsules */
+  #define PY_USE_CAPSULE
+***************
+*** 126,131 ****
+--- 127,133 ----
+  # define PyErr_PrintEx py3_PyErr_PrintEx
+  # define PyErr_NoMemory py3_PyErr_NoMemory
+  # define PyErr_Occurred py3_PyErr_Occurred
++ # define PyErr_PrintEx py3_PyErr_PrintEx
+  # define PyErr_SetNone py3_PyErr_SetNone
+  # define PyErr_SetString py3_PyErr_SetString
+  # define PyErr_SetObject py3_PyErr_SetObject
+***************
+*** 148,154 ****
+  # define PyTuple_GetItem py3_PyTuple_GetItem
+  # define PySlice_GetIndicesEx py3_PySlice_GetIndicesEx
+  # define PyImport_ImportModule py3_PyImport_ImportModule
+- # define PyImport_AddModule py3_PyImport_AddModule
+  # define PyObject_Init py3__PyObject_Init
+  # define PyDict_New py3_PyDict_New
+  # define PyDict_GetItemString py3_PyDict_GetItemString
+--- 150,155 ----
+***************
+*** 163,168 ****
+--- 164,174 ----
+  # define PyRun_SimpleString py3_PyRun_SimpleString
+  #undef PyRun_String
+  # define PyRun_String py3_PyRun_String
++ # define PyObject_GetAttrString py3_PyObject_GetAttrString
++ # define PyObject_SetAttrString py3_PyObject_SetAttrString
++ # define PyObject_CallFunctionObjArgs py3_PyObject_CallFunctionObjArgs
++ # define PyEval_GetLocals py3_PyEval_GetLocals
++ # define PyEval_GetGlobals py3_PyEval_GetGlobals
+  # define PySys_SetObject py3_PySys_SetObject
+  # define PySys_SetArgv py3_PySys_SetArgv
+  # define PyType_Ready py3_PyType_Ready
+***************
+*** 178,183 ****
+--- 184,190 ----
+  # define _PyObject_NextNotImplemented (*py3__PyObject_NextNotImplemented)
+  # define PyModule_AddObject py3_PyModule_AddObject
+  # define PyImport_AppendInittab py3_PyImport_AppendInittab
++ # define PyImport_AddModule py3_PyImport_AddModule
+  # if PY_VERSION_HEX >= 0x030300f0
+  #  undef _PyUnicode_AsString
+  #  define _PyUnicode_AsString py3_PyUnicode_AsUTF8
+***************
+*** 254,259 ****
+--- 261,271 ----
+  static void (*py3_PyErr_SetObject)(PyObject *, PyObject *);
+  static int (*py3_PyRun_SimpleString)(char *);
+  static PyObject* (*py3_PyRun_String)(char *, int, PyObject *, PyObject *);
++ static PyObject* (*py3_PyObject_GetAttrString)(PyObject *, const char *);
++ static PyObject* (*py3_PyObject_SetAttrString)(PyObject *, const char *, PyObject *);
++ static PyObject* (*py3_PyObject_CallFunctionObjArgs)(PyObject *, ...);
++ static PyObject* (*py3_PyEval_GetGlobals)();
++ static PyObject* (*py3_PyEval_GetLocals)();
+  static PyObject* (*py3_PyList_GetItem)(PyObject *, Py_ssize_t);
+  static PyObject* (*py3_PyImport_ImportModule)(const char *);
+  static PyObject* (*py3_PyImport_AddModule)(const char *);
+***************
+*** 386,391 ****
+--- 398,408 ----
+      {"PyErr_SetObject", (PYTHON_PROC*)&py3_PyErr_SetObject},
+      {"PyRun_SimpleString", (PYTHON_PROC*)&py3_PyRun_SimpleString},
+      {"PyRun_String", (PYTHON_PROC*)&py3_PyRun_String},
++     {"PyObject_GetAttrString", (PYTHON_PROC*)&py3_PyObject_GetAttrString},
++     {"PyObject_SetAttrString", (PYTHON_PROC*)&py3_PyObject_SetAttrString},
++     {"PyObject_CallFunctionObjArgs", (PYTHON_PROC*)&py3_PyObject_CallFunctionObjArgs},
++     {"PyEval_GetGlobals", (PYTHON_PROC*)&py3_PyEval_GetGlobals},
++     {"PyEval_GetLocals", (PYTHON_PROC*)&py3_PyEval_GetLocals},
+      {"PyList_GetItem", (PYTHON_PROC*)&py3_PyList_GetItem},
+      {"PyImport_ImportModule", (PYTHON_PROC*)&py3_PyImport_ImportModule},
+      {"PyImport_AddModule", (PYTHON_PROC*)&py3_PyImport_AddModule},
+***************
+*** 990,995 ****
+--- 1007,1106 ----
+      DoPy3Command(eap, buffer, NULL);
+  }
+  
++ void ex_py3do(exarg_T *eap)
++ {
++     linenr_T		i;
++     const char		*code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
++     const char		*s = (const char *) eap->arg;
++     size_t		len;
++     char		*code;
++     int			status;
++     PyObject		*pyfunc, *pymain;
++     PyGILState_STATE	pygilstate;
++ 
++     if (Python3_Init())
++ 	goto theend;
++ 
++     if (u_save(eap->line1 - 1, eap->line2 + 1) != OK)
++     {
++ 	EMSG(_("cannot save undo information"));
++ 	return;
++     }
++     len = strlen(code_hdr) + strlen(s);
++     code = malloc(len + 1);
++     STRCPY(code, code_hdr);
++     STRNCAT(code, s, len + 1);
++     pygilstate = PyGILState_Ensure();
++     status = PyRun_SimpleString(code);
++     vim_free(code);
++     if (status)
++     {
++ 	EMSG(_("failed to run the code"));
++ 	return;
++     }
++     status = 0; /* good */
++     pymain = PyImport_AddModule("__main__");
++     pyfunc = PyObject_GetAttrString(pymain, DOPY_FUNC);
++     PyGILState_Release(pygilstate);
++ 
++     for (i = eap->line1; i <= eap->line2; i++)
++     {
++ 	const char *line;
++ 	PyObject *pyline, *pylinenr, *pyret, *pybytes;
++ 
++ 	line = (char *)ml_get(i);
++ 	pygilstate = PyGILState_Ensure();
++ 	pyline = PyUnicode_Decode(line, strlen(line),
++ 		(char *)ENC_OPT, CODEC_ERROR_HANDLER);
++ 	pylinenr = PyLong_FromLong(i);
++ 	pyret = PyObject_CallFunctionObjArgs(pyfunc, pyline, pylinenr, NULL);
++ 	Py_DECREF(pyline);
++ 	Py_DECREF(pylinenr);
++ 	if (!pyret)
++ 	{
++ 	    PyErr_PrintEx(0);
++ 	    PythonIO_Flush();
++ 	    status = 1;
++ 	    goto out;
++ 	}
++ 
++ 	if (pyret && pyret != Py_None)
++ 	{
++ 	    if (!PyUnicode_Check(pyret))
++ 	    {
++ 		/* TODO: a proper error number */
++ 		EMSG(_("E000: return value must be an instance of str"));
++ 		Py_XDECREF(pyret);
++ 		status = 1;
++ 		goto out;
++ 	    }
++ 	    pybytes = PyUnicode_AsEncodedString(pyret,
++ 		    (char *)ENC_OPT, CODEC_ERROR_HANDLER);
++ 	    ml_replace(i, (char_u *) PyBytes_AsString(pybytes), 1);
++ 	    Py_DECREF(pybytes);
++ 	    changed();
++ #ifdef SYNTAX_HL
++ 	    syn_changed(i); /* recompute syntax hl. for this line */
++ #endif
++ 	}
++ 	Py_XDECREF(pyret);
++ 	PythonIO_Flush();
++ 	PyGILState_Release(pygilstate);
++     }
++     pygilstate = PyGILState_Ensure();
++ out:
++     Py_DECREF(pyfunc);
++     PyObject_SetAttrString(pymain, DOPY_FUNC, NULL);
++     PyGILState_Release(pygilstate);
++     if (status)
++ 	return;
++     check_cursor();
++     update_curbuf(NOT_VALID);
++ 
++ theend:
++     return;
++ }
++ 
+  /******************************************************
+   * 2. Python output stream: writes output via [e]msg().
+   */
+*** ../vim-7.3.956/src/proto/if_python3.pro	2013-05-15 15:12:25.000000000 +0200
+--- src/proto/if_python3.pro	2013-05-15 18:01:55.000000000 +0200
+***************
+*** 3,8 ****
+--- 3,9 ----
+  void python3_end __ARGS((void));
+  int python3_loaded __ARGS((void));
+  void ex_py3 __ARGS((exarg_T *eap));
++ void ex_py3do __ARGS((exarg_T *eap));
+  void ex_py3file __ARGS((exarg_T *eap));
+  void python3_buffer_free __ARGS((buf_T *buf));
+  void python3_window_free __ARGS((win_T *win));
+*** ../vim-7.3.956/src/version.c	2013-05-15 17:49:00.000000000 +0200
+--- src/version.c	2013-05-15 18:16:28.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     957,
+  /**/
+
+-- 
+FATHER: We are here today to witness the union of two young people in the
+        joyful bond of the holy wedlock.  Unfortunately, one of them, my son
+        Herbert, has just fallen to his death.
+   [Murmurs from CROWD;  the BRIDE smiles with relief, coughs.]
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.958 b/7.3.958
new file mode 100644
index 0000000..92aa384
--- /dev/null
+++ b/7.3.958
@@ -0,0 +1,67 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.958
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.958
+Problem:    Python: Iteration destructor not set.
+Solution:   Put IterDestructor to use. (ZyX)
+Files:	    src/if_py_both.c
+
+
+*** ../vim-7.3.957/src/if_py_both.h	2013-05-15 17:49:00.000000000 +0200
+--- src/if_py_both.h	2013-05-15 19:00:19.000000000 +0200
+***************
+*** 566,572 ****
+      return (PyObject *)(self);
+  }
+  
+- #if 0 /* unused */
+      static void
+  IterDestructor(PyObject *self)
+  {
+--- 566,571 ----
+***************
+*** 576,582 ****
+  
+      DESTRUCTOR_FINISH(self);
+  }
+- #endif
+  
+      static PyObject *
+  IterNext(PyObject *self)
+--- 575,580 ----
+***************
+*** 3823,3828 ****
+--- 3821,3827 ----
+      IterType.tp_doc = "generic iterator object";
+      IterType.tp_iter = IterIter;
+      IterType.tp_iternext = IterNext;
++     IterType.tp_dealloc = IterDestructor;
+  
+      vim_memset(&BufferType, 0, sizeof(BufferType));
+      BufferType.tp_name = "vim.buffer";
+*** ../vim-7.3.957/src/version.c	2013-05-15 18:28:08.000000000 +0200
+--- src/version.c	2013-05-15 19:05:28.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     958,
+  /**/
+
+-- 
+Yesterday is history.
+Tomorrow is a mystery.
+Today is a gift.
+That's why it is called 'present'.
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.959 b/7.3.959
new file mode 100644
index 0000000..0435da3
--- /dev/null
+++ b/7.3.959
@@ -0,0 +1,74 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.959
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.959 (after 7.3.957)
+Problem:    Missing error number.
+Solution:   Assign an error number.
+Files:	    src/if_python3.c
+
+
+*** ../vim-7.3.958/src/if_python3.c	2013-05-15 18:28:08.000000000 +0200
+--- src/if_python3.c	2013-05-15 19:41:51.000000000 +0200
+***************
+*** 1007,1013 ****
+      DoPy3Command(eap, buffer, NULL);
+  }
+  
+! void ex_py3do(exarg_T *eap)
+  {
+      linenr_T		i;
+      const char		*code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
+--- 1007,1014 ----
+      DoPy3Command(eap, buffer, NULL);
+  }
+  
+!     void
+! ex_py3do(exarg_T *eap)
+  {
+      linenr_T		i;
+      const char		*code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
+***************
+*** 1068,1075 ****
+  	{
+  	    if (!PyUnicode_Check(pyret))
+  	    {
+! 		/* TODO: a proper error number */
+! 		EMSG(_("E000: return value must be an instance of str"));
+  		Py_XDECREF(pyret);
+  		status = 1;
+  		goto out;
+--- 1069,1075 ----
+  	{
+  	    if (!PyUnicode_Check(pyret))
+  	    {
+! 		EMSG(_("E863: return value must be an instance of str"));
+  		Py_XDECREF(pyret);
+  		status = 1;
+  		goto out;
+*** ../vim-7.3.958/src/version.c	2013-05-15 19:07:03.000000000 +0200
+--- src/version.c	2013-05-15 19:38:05.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     959,
+  /**/
+
+
+-- 
+CRONE:  Who sent you?
+ARTHUR: The Knights Who Say Ni!
+CRONE:  Aaaagh!  (she looks around in rear) No!  We have no shrubberies here.
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.960 b/7.3.960
new file mode 100644
index 0000000..1b4b25c
--- /dev/null
+++ b/7.3.960
@@ -0,0 +1,47 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.960
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.960
+Problem:    Compiler warning for unused variable.
+Solution:   Put declaration in #ifdef.
+Files:	    src/window.c
+
+
+*** ../vim-7.3.959/src/window.c	2013-05-15 15:12:25.000000000 +0200
+--- src/window.c	2013-05-15 23:11:02.000000000 +0200
+***************
+*** 2124,2130 ****
+--- 2124,2132 ----
+  {
+      if (firstwin == lastwin)
+      {
++ #ifdef FEAT_AUTOCMD
+  	buf_T	*old_curbuf = curbuf;
++ #endif
+  
+  	/*
+  	 * Closing the last window in a tab page.  First go to another tab
+*** ../vim-7.3.959/src/version.c	2013-05-15 19:44:35.000000000 +0200
+--- src/version.c	2013-05-15 23:12:12.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     960,
+  /**/
+
+-- 
+Did you ever stop to think...  and forget to start again?
+                                  -- Steven Wright
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.961 b/7.3.961
new file mode 100644
index 0000000..c61ec65
--- /dev/null
+++ b/7.3.961
@@ -0,0 +1,90 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.961
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.961
+Problem:    Tests 86 and 87 fail when using another language than English.
+Solution:   Set the language to C in the test. (Dominique Pelle)
+Files:	    src/testdir/test86.in, src/testdir/test87.in,
+	    src/testdir/test87.ok
+
+
+*** ../vim-7.3.960/src/testdir/test86.in	2013-05-15 16:27:33.000000000 +0200
+--- src/testdir/test86.in	2013-05-16 18:58:46.000000000 +0200
+***************
+*** 5,14 ****
+    ./configure --without-pymalloc
+  See http://svn.python.org/view/python/trunk/Misc/README.valgrind?view=markup
+  
+- 
+  STARTTEST
+  :so small.vim
+  :if !has('python') | e! test.ok | wq! test.out | endif
+  :py import vim
+  :fun Test()
+  :let l = []
+--- 5,14 ----
+    ./configure --without-pymalloc
+  See http://svn.python.org/view/python/trunk/Misc/README.valgrind?view=markup
+  
+  STARTTEST
+  :so small.vim
+  :if !has('python') | e! test.ok | wq! test.out | endif
++ :lang C
+  :py import vim
+  :fun Test()
+  :let l = []
+*** ../vim-7.3.960/src/testdir/test87.in	2013-05-15 16:27:33.000000000 +0200
+--- src/testdir/test87.in	2013-05-16 18:56:21.000000000 +0200
+***************
+*** 3,8 ****
+--- 3,9 ----
+  STARTTEST
+  :so small.vim
+  :if !has('python3') | e! test.ok | wq! test.out | endif
++ :lang C
+  :py3 import vim
+  :fun Test()
+  :let l = []
+*** ../vim-7.3.960/src/testdir/test87.ok	2013-05-15 16:27:33.000000000 +0200
+--- src/testdir/test87.ok	2013-05-16 20:46:05.000000000 +0200
+***************
+*** 322,328 ****
+  Current tab pages:
+    <tabpage 0>(1): 1 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(0): displays buffer <buffer test87.in>; cursor is at (929, 0)
+    <tabpage 1>(2): 1 windows, current is <window object (unknown)>
+    Windows:
+      <window object (unknown)>(0): displays buffer <buffer 0>; cursor is at (1, 0)
+--- 322,328 ----
+  Current tab pages:
+    <tabpage 0>(1): 1 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(0): displays buffer <buffer test87.in>; cursor is at (930, 0)
+    <tabpage 1>(2): 1 windows, current is <window object (unknown)>
+    Windows:
+      <window object (unknown)>(0): displays buffer <buffer 0>; cursor is at (1, 0)
+*** ../vim-7.3.960/src/version.c	2013-05-15 23:13:06.000000000 +0200
+--- src/version.c	2013-05-16 20:47:38.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     961,
+  /**/
+
+-- 
+When I look deep into your eyes, I see JPEG artifacts.
+I can tell by the pixels that we're wrong for each other.  (xkcd)
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.962 b/7.3.962
new file mode 100644
index 0000000..ee39d5e
--- /dev/null
+++ b/7.3.962
@@ -0,0 +1,230 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.962
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.962
+Problem:    Python tests are not portable.
+Solution:   Use shiftwidth instead of iminsert. (ZyX)
+Files:	    src/testdir/test86.in, src/testdir/test86.ok,
+	    src/testdir/test87.in, src/testdir/test87.ok
+
+
+*** ../vim-7.3.961/src/testdir/test86.in	2013-05-16 20:47:51.000000000 +0200
+--- src/testdir/test86.in	2013-05-17 13:34:56.000000000 +0200
+***************
+*** 354,360 ****
+  :" colorcolumn:    string,  window-local
+  :" statusline:     string,  window-local/global
+  :" autoindent:     boolean, buffer-local
+! :" iminsert:       number,  buffer-local
+  :" omnifunc:       string,  buffer-local
+  :" preserveindent: boolean, buffer-local/global
+  :" path:           string,  buffer-local/global
+--- 354,360 ----
+  :" colorcolumn:    string,  window-local
+  :" statusline:     string,  window-local/global
+  :" autoindent:     boolean, buffer-local
+! :" shiftwidth:     number,  buffer-local
+  :" omnifunc:       string,  buffer-local
+  :" preserveindent: boolean, buffer-local/global
+  :" path:           string,  buffer-local/global
+***************
+*** 411,417 ****
+  :let lst+=[['colorcolumn',    '+1',  '+2',  '+3',  'abc',  0,    0,      1    ]]
+  :let lst+=[['statusline',     '1',   '2',   '4',   0,      0,    1,      1    ]]
+  :let lst+=[['autoindent',     0,     1,     1,     2,      1,    0,      2    ]]
+! :let lst+=[['iminsert',       0,     2,     1,     3,      0,    0,      2    ]]
+  :let lst+=[['omnifunc',       'A',   'B',   'C',   1,      0,    0,      2    ]]
+  :let lst+=[['preserveindent', 0,     1,     1,     2,      1,    1,      2    ]]
+  :let lst+=[['path',           '.,,', ',,',  '.',   0,      0,    1,      2    ]]
+--- 411,417 ----
+  :let lst+=[['colorcolumn',    '+1',  '+2',  '+3',  'abc',  0,    0,      1    ]]
+  :let lst+=[['statusline',     '1',   '2',   '4',   0,      0,    1,      1    ]]
+  :let lst+=[['autoindent',     0,     1,     1,     2,      1,    0,      2    ]]
+! :let lst+=[['shiftwidth',     0,     2,     1,     3,      0,    0,      2    ]]
+  :let lst+=[['omnifunc',       'A',   'B',   'C',   1,      0,    0,      2    ]]
+  :let lst+=[['preserveindent', 0,     1,     1,     2,      1,    1,      2    ]]
+  :let lst+=[['path',           '.,,', ',,',  '.',   0,      0,    1,      2    ]]
+*** ../vim-7.3.961/src/testdir/test86.ok	2013-05-15 16:27:33.000000000 +0200
+--- src/testdir/test86.ok	2013-05-17 13:34:56.000000000 +0200
+***************
+*** 232,238 ****
+    G: 0
+    W: 1:0 2:1 3:0 4:1
+    B: 1:0 2:1 3:0 4:1
+! >>> iminsert
+    p/gopts1! KeyError
+    inv: 3! KeyError
+    gopts1! KeyError
+--- 232,238 ----
+    G: 0
+    W: 1:0 2:1 3:0 4:1
+    B: 1:0 2:1 3:0 4:1
+! >>> shiftwidth
+    p/gopts1! KeyError
+    inv: 3! KeyError
+    gopts1! KeyError
+***************
+*** 241,255 ****
+    wopts1! KeyError
+    wopts2! KeyError
+    wopts3! KeyError
+!   p/bopts1: 2
+!   G: 1
+!   W: 1:0 2:2 3:2 4:1
+!   B: 1:0 2:2 3:2 4:1
+    del wopts3! KeyError
+    del bopts3! ValueError
+!   G: 1
+!   W: 1:0 2:2 3:2 4:1
+!   B: 1:0 2:2 3:2 4:1
+  >>> omnifunc
+    p/gopts1! KeyError
+    inv: 1! KeyError
+--- 241,255 ----
+    wopts1! KeyError
+    wopts2! KeyError
+    wopts3! KeyError
+!   p/bopts1: 8
+!   G: 8
+!   W: 1:0 2:2 3:8 4:1
+!   B: 1:0 2:2 3:8 4:1
+    del wopts3! KeyError
+    del bopts3! ValueError
+!   G: 8
+!   W: 1:0 2:2 3:8 4:1
+!   B: 1:0 2:2 3:8 4:1
+  >>> omnifunc
+    p/gopts1! KeyError
+    inv: 1! KeyError
+***************
+*** 333,339 ****
+  Current tab pages:
+    <tabpage 0>(1): 1 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(0): displays buffer <buffer test86.in>; cursor is at (954, 0)
+    <tabpage 1>(2): 1 windows, current is <window object (unknown)>
+    Windows:
+      <window object (unknown)>(0): displays buffer <buffer 0>; cursor is at (1, 0)
+--- 333,339 ----
+  Current tab pages:
+    <tabpage 0>(1): 1 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(0): displays buffer <buffer test86.in>; cursor is at (955, 0)
+    <tabpage 1>(2): 1 windows, current is <window object (unknown)>
+    Windows:
+      <window object (unknown)>(0): displays buffer <buffer 0>; cursor is at (1, 0)
+*** ../vim-7.3.961/src/testdir/test87.in	2013-05-16 20:47:51.000000000 +0200
+--- src/testdir/test87.in	2013-05-17 13:34:56.000000000 +0200
+***************
+*** 341,347 ****
+  :" colorcolumn:    string,  window-local
+  :" statusline:     string,  window-local/global
+  :" autoindent:     boolean, buffer-local
+! :" iminsert:       number,  buffer-local
+  :" omnifunc:       string,  buffer-local
+  :" preserveindent: boolean, buffer-local/global
+  :" path:           string,  buffer-local/global
+--- 341,347 ----
+  :" colorcolumn:    string,  window-local
+  :" statusline:     string,  window-local/global
+  :" autoindent:     boolean, buffer-local
+! :" shiftwidth:     number,  buffer-local
+  :" omnifunc:       string,  buffer-local
+  :" preserveindent: boolean, buffer-local/global
+  :" path:           string,  buffer-local/global
+***************
+*** 398,404 ****
+  :let lst+=[['colorcolumn',    '+1',  '+2',  '+3',  'abc',  0,    0,      1    ]]
+  :let lst+=[['statusline',     '1',   '2',   '4',   0,      0,    1,      1    ]]
+  :let lst+=[['autoindent',     0,     1,     1,     2,      1,    0,      2    ]]
+! :let lst+=[['iminsert',       0,     2,     1,     3,      0,    0,      2    ]]
+  :let lst+=[['omnifunc',       'A',   'B',   'C',   1,      0,    0,      2    ]]
+  :let lst+=[['preserveindent', 0,     1,     1,     2,      1,    1,      2    ]]
+  :let lst+=[['path',           '.,,', ',,',  '.',   0,      0,    1,      2    ]]
+--- 398,404 ----
+  :let lst+=[['colorcolumn',    '+1',  '+2',  '+3',  'abc',  0,    0,      1    ]]
+  :let lst+=[['statusline',     '1',   '2',   '4',   0,      0,    1,      1    ]]
+  :let lst+=[['autoindent',     0,     1,     1,     2,      1,    0,      2    ]]
+! :let lst+=[['shiftwidth',     0,     2,     1,     3,      0,    0,      2    ]]
+  :let lst+=[['omnifunc',       'A',   'B',   'C',   1,      0,    0,      2    ]]
+  :let lst+=[['preserveindent', 0,     1,     1,     2,      1,    1,      2    ]]
+  :let lst+=[['path',           '.,,', ',,',  '.',   0,      0,    1,      2    ]]
+*** ../vim-7.3.961/src/testdir/test87.ok	2013-05-16 20:47:51.000000000 +0200
+--- src/testdir/test87.ok	2013-05-17 13:34:56.000000000 +0200
+***************
+*** 221,227 ****
+    G: 0
+    W: 1:0 2:1 3:0 4:1
+    B: 1:0 2:1 3:0 4:1
+! >>> iminsert
+    p/gopts1! KeyError
+    inv: 3! KeyError
+    gopts1! KeyError
+--- 221,227 ----
+    G: 0
+    W: 1:0 2:1 3:0 4:1
+    B: 1:0 2:1 3:0 4:1
+! >>> shiftwidth
+    p/gopts1! KeyError
+    inv: 3! KeyError
+    gopts1! KeyError
+***************
+*** 230,244 ****
+    wopts1! KeyError
+    wopts2! KeyError
+    wopts3! KeyError
+!   p/bopts1: 2
+!   G: 1
+!   W: 1:0 2:2 3:2 4:1
+!   B: 1:0 2:2 3:2 4:1
+    del wopts3! KeyError
+    del bopts3! ValueError
+!   G: 1
+!   W: 1:0 2:2 3:2 4:1
+!   B: 1:0 2:2 3:2 4:1
+  >>> omnifunc
+    p/gopts1! KeyError
+    inv: 1! KeyError
+--- 230,244 ----
+    wopts1! KeyError
+    wopts2! KeyError
+    wopts3! KeyError
+!   p/bopts1: 8
+!   G: 8
+!   W: 1:0 2:2 3:8 4:1
+!   B: 1:0 2:2 3:8 4:1
+    del wopts3! KeyError
+    del bopts3! ValueError
+!   G: 8
+!   W: 1:0 2:2 3:8 4:1
+!   B: 1:0 2:2 3:8 4:1
+  >>> omnifunc
+    p/gopts1! KeyError
+    inv: 1! KeyError
+*** ../vim-7.3.961/src/version.c	2013-05-16 20:47:51.000000000 +0200
+--- src/version.c	2013-05-17 13:36:36.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     962,
+  /**/
+
+-- 
+TIM: To the north there lies a cave,  the cave of Caerbannog, wherein, carved
+     in mystic runes, upon the very living rock, the last words of Olfin
+     Bedwere of Rheged make plain the last resting place of the most Holy
+     Grail.
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.963 b/7.3.963
new file mode 100644
index 0000000..85c362c
--- /dev/null
+++ b/7.3.963
@@ -0,0 +1,720 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.963
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.963
+Problem:    Setting curbuf without curwin causes trouble.
+Solution:   Add switch_buffer() and restore_buffer().  Block autocommands to
+	    avoid trouble.
+Files:	    src/eval.c, src/proto/eval.pro, src/proto/window.pro,
+	    src/if_py_both.h, src/window.c, src/testdir/test86.ok
+
+
+*** ../vim-7.3.962/src/eval.c	2013-05-15 14:39:47.000000000 +0200
+--- src/eval.c	2013-05-17 14:50:35.000000000 +0200
+***************
+*** 11894,11900 ****
+      win_T	*win, *oldcurwin;
+      char_u	*varname;
+      dictitem_T	*v;
+!     tabpage_T	*tp;
+      int		done = FALSE;
+  
+  #ifdef FEAT_WINDOWS
+--- 11894,11900 ----
+      win_T	*win, *oldcurwin;
+      char_u	*varname;
+      dictitem_T	*v;
+!     tabpage_T	*tp, *oldtabpage;
+      int		done = FALSE;
+  
+  #ifdef FEAT_WINDOWS
+***************
+*** 11912,11922 ****
+  
+      if (win != NULL && varname != NULL)
+      {
+! 	/* Set curwin to be our win, temporarily.  Also set curbuf, so
+! 	 * that we can get buffer-local options. */
+! 	oldcurwin = curwin;
+! 	curwin = win;
+! 	curbuf = win->w_buffer;
+  
+  	if (*varname == '&')	/* window-local-option */
+  	{
+--- 11912,11920 ----
+  
+      if (win != NULL && varname != NULL)
+      {
+! 	/* Set curwin to be our win, temporarily.  Also set the tabpage,
+! 	 * otherwise the window is not valid. */
+! 	switch_win(&oldcurwin, &oldtabpage, win, tp);
+  
+  	if (*varname == '&')	/* window-local-option */
+  	{
+***************
+*** 11936,11943 ****
+  	}
+  
+  	/* restore previous notion of curwin */
+! 	curwin = oldcurwin;
+! 	curbuf = curwin->w_buffer;
+      }
+  
+      if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
+--- 11934,11940 ----
+  	}
+  
+  	/* restore previous notion of curwin */
+! 	restore_win(oldcurwin, oldtabpage);
+      }
+  
+      if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
+***************
+*** 16641,16684 ****
+      setwinvar(argvars, rettv, 0);
+  }
+  
+-     int
+- switch_win(save_curwin, save_curtab, win, tp)
+-     win_T	**save_curwin;
+-     tabpage_T	**save_curtab;
+-     win_T	*win;
+-     tabpage_T	*tp;
+- {
+- #ifdef FEAT_WINDOWS
+-     /* set curwin to be our win, temporarily */
+-     *save_curwin = curwin;
+-     *save_curtab = curtab;
+-     goto_tabpage_tp(tp, FALSE, FALSE);
+-     if (!win_valid(win))
+- 	return FAIL;
+-     curwin = win;
+-     curbuf = curwin->w_buffer;
+- #endif
+-     return OK;
+- }
+- 
+-     void
+- restore_win(save_curwin, save_curtab)
+-     win_T	*save_curwin;
+-     tabpage_T	*save_curtab;
+- {
+- #ifdef FEAT_WINDOWS
+-     /* Restore current tabpage and window, if still valid (autocommands can
+-      * make them invalid). */
+-     if (valid_tabpage(save_curtab))
+- 	goto_tabpage_tp(save_curtab, FALSE, FALSE);
+-     if (win_valid(save_curwin))
+-     {
+- 	curwin = save_curwin;
+- 	curbuf = curwin->w_buffer;
+-     }
+- #endif
+- }
+- 
+  /*
+   * "setwinvar()" and "settabwinvar()" functions
+   */
+--- 16638,16643 ----
+*** ../vim-7.3.962/src/proto/eval.pro	2013-05-15 14:39:47.000000000 +0200
+--- src/proto/eval.pro	2013-05-17 16:01:40.000000000 +0200
+***************
+*** 33,38 ****
+--- 33,40 ----
+  void prof_child_exit __ARGS((proftime_T *tm));
+  int eval_foldexpr __ARGS((char_u *arg, int *cp));
+  void ex_let __ARGS((exarg_T *eap));
++ void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
++ void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
+  void *eval_for_line __ARGS((char_u *arg, int *errp, char_u **nextcmdp, int skip));
+  int next_for_item __ARGS((void *fi_void, char_u *arg));
+  void free_for_info __ARGS((void *fi_void));
+***************
+*** 125,132 ****
+  void ex_oldfiles __ARGS((exarg_T *eap));
+  int modify_fname __ARGS((char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen));
+  char_u *do_string_sub __ARGS((char_u *str, char_u *pat, char_u *sub, char_u *flags));
+- int switch_win __ARGS((win_T **, tabpage_T **, win_T *, tabpage_T *));
+- void restore_win __ARGS((win_T *, tabpage_T *));
+- void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
+- void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
+  /* vim: set ft=c : */
+--- 127,130 ----
+*** ../vim-7.3.962/src/proto/window.pro	2013-05-15 15:12:25.000000000 +0200
+--- src/proto/window.pro	2013-05-17 15:04:14.000000000 +0200
+***************
+*** 32,37 ****
+--- 32,38 ----
+  void tabpage_move __ARGS((int nr));
+  void win_goto __ARGS((win_T *wp));
+  win_T *win_find_nr __ARGS((int winnr));
++ tabpage_T *win_find_tabpage __ARGS((win_T *win));
+  void win_enter __ARGS((win_T *wp, int undo_sync));
+  win_T *buf_jump_open_win __ARGS((buf_T *buf));
+  win_T *buf_jump_open_tab __ARGS((buf_T *buf));
+***************
+*** 69,74 ****
+--- 70,79 ----
+  void check_lnums __ARGS((int do_curwin));
+  void make_snapshot __ARGS((int idx));
+  void restore_snapshot __ARGS((int idx, int close_curwin));
++ int switch_win __ARGS((win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage_T *tp));
++ void restore_win __ARGS((win_T *save_curwin, tabpage_T *save_curtab));
++ void switch_buffer __ARGS((buf_T **save_curbuf, buf_T *buf));
++ void restore_buffer __ARGS((buf_T *save_curbuf));
+  int win_hasvertsplit __ARGS((void));
+  int match_add __ARGS((win_T *wp, char_u *grp, char_u *pat, int prio, int id));
+  int match_delete __ARGS((win_T *wp, int id, int perr));
+*** ../vim-7.3.962/src/if_py_both.h	2013-05-15 19:07:03.000000000 +0200
+--- src/if_py_both.h	2013-05-17 15:57:08.000000000 +0200
+***************
+*** 1413,1426 ****
+  {
+      win_T	*save_curwin;
+      tabpage_T	*save_curtab;
+!     aco_save_T	aco;
+      int		r = 0;
+  
+      switch (opt_type)
+      {
+  	case SREQ_WIN:
+! 	    if (switch_win(&save_curwin, &save_curtab, (win_T *) from, curtab)
+! 								      == FAIL)
+  	    {
+  		PyErr_SetVim("Problem while switching windows.");
+  		return -1;
+--- 1413,1426 ----
+  {
+      win_T	*save_curwin;
+      tabpage_T	*save_curtab;
+!     buf_T	*save_curbuf;
+      int		r = 0;
+  
+      switch (opt_type)
+      {
+  	case SREQ_WIN:
+! 	    if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
+! 				     win_find_tabpage((win_T *)from)) == FAIL)
+  	    {
+  		PyErr_SetVim("Problem while switching windows.");
+  		return -1;
+***************
+*** 1429,1437 ****
+  	    restore_win(save_curwin, save_curtab);
+  	    break;
+  	case SREQ_BUF:
+! 	    aucmd_prepbuf(&aco, (buf_T *) from);
+  	    set_option_value(key, numval, stringval, opt_flags);
+! 	    aucmd_restbuf(&aco);
+  	    break;
+  	case SREQ_GLOBAL:
+  	    set_option_value(key, numval, stringval, opt_flags);
+--- 1429,1437 ----
+  	    restore_win(save_curwin, save_curtab);
+  	    break;
+  	case SREQ_BUF:
+! 	    switch_buffer(&save_curbuf, (buf_T *)from);
+  	    set_option_value(key, numval, stringval, opt_flags);
+! 	    restore_buffer(save_curbuf);
+  	    break;
+  	case SREQ_GLOBAL:
+  	    set_option_value(key, numval, stringval, opt_flags);
+***************
+*** 2240,2249 ****
+       */
+      if (line == Py_None || line == NULL)
+      {
+! 	buf_T *savebuf = curbuf;
+  
+  	PyErr_Clear();
+! 	curbuf = buf;
+  
+  	if (u_savedel((linenr_T)n, 1L) == FAIL)
+  	    PyErr_SetVim(_("cannot save undo information"));
+--- 2240,2249 ----
+       */
+      if (line == Py_None || line == NULL)
+      {
+! 	buf_T *savebuf;
+  
+  	PyErr_Clear();
+! 	switch_buffer(&savebuf, buf);
+  
+  	if (u_savedel((linenr_T)n, 1L) == FAIL)
+  	    PyErr_SetVim(_("cannot save undo information"));
+***************
+*** 2251,2262 ****
+  	    PyErr_SetVim(_("cannot delete line"));
+  	else
+  	{
+! 	    if (buf == curwin->w_buffer)
+  		py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1);
+  	    deleted_lines_mark((linenr_T)n, 1L);
+  	}
+  
+! 	curbuf = savebuf;
+  
+  	if (PyErr_Occurred() || VimErrorCheck())
+  	    return FAIL;
+--- 2251,2262 ----
+  	    PyErr_SetVim(_("cannot delete line"));
+  	else
+  	{
+! 	    if (buf == savebuf)
+  		py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1);
+  	    deleted_lines_mark((linenr_T)n, 1L);
+  	}
+  
+! 	restore_buffer(savebuf);
+  
+  	if (PyErr_Occurred() || VimErrorCheck())
+  	    return FAIL;
+***************
+*** 2269,2282 ****
+      else if (PyString_Check(line))
+      {
+  	char *save = StringToLine(line);
+! 	buf_T *savebuf = curbuf;
+  
+  	if (save == NULL)
+  	    return FAIL;
+  
+  	/* We do not need to free "save" if ml_replace() consumes it. */
+  	PyErr_Clear();
+! 	curbuf = buf;
+  
+  	if (u_savesub((linenr_T)n) == FAIL)
+  	{
+--- 2269,2282 ----
+      else if (PyString_Check(line))
+      {
+  	char *save = StringToLine(line);
+! 	buf_T *savebuf;
+  
+  	if (save == NULL)
+  	    return FAIL;
+  
+  	/* We do not need to free "save" if ml_replace() consumes it. */
+  	PyErr_Clear();
+! 	switch_buffer(&savebuf, buf);
+  
+  	if (u_savesub((linenr_T)n) == FAIL)
+  	{
+***************
+*** 2291,2300 ****
+  	else
+  	    changed_bytes((linenr_T)n, 0);
+  
+! 	curbuf = savebuf;
+  
+  	/* Check that the cursor is not beyond the end of the line now. */
+! 	if (buf == curwin->w_buffer)
+  	    check_cursor_col();
+  
+  	if (PyErr_Occurred() || VimErrorCheck())
+--- 2291,2300 ----
+  	else
+  	    changed_bytes((linenr_T)n, 0);
+  
+! 	restore_buffer(savebuf);
+  
+  	/* Check that the cursor is not beyond the end of the line now. */
+! 	if (buf == savebuf)
+  	    check_cursor_col();
+  
+  	if (PyErr_Occurred() || VimErrorCheck())
+***************
+*** 2333,2342 ****
+      {
+  	PyInt	i;
+  	PyInt	n = (int)(hi - lo);
+! 	buf_T	*savebuf = curbuf;
+  
+  	PyErr_Clear();
+! 	curbuf = buf;
+  
+  	if (u_savedel((linenr_T)lo, (long)n) == FAIL)
+  	    PyErr_SetVim(_("cannot save undo information"));
+--- 2333,2342 ----
+      {
+  	PyInt	i;
+  	PyInt	n = (int)(hi - lo);
+! 	buf_T	*savebuf;
+  
+  	PyErr_Clear();
+! 	switch_buffer(&savebuf, buf);
+  
+  	if (u_savedel((linenr_T)lo, (long)n) == FAIL)
+  	    PyErr_SetVim(_("cannot save undo information"));
+***************
+*** 2350,2361 ****
+  		    break;
+  		}
+  	    }
+! 	    if (buf == curwin->w_buffer)
+  		py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
+  	    deleted_lines_mark((linenr_T)lo, (long)i);
+  	}
+  
+! 	curbuf = savebuf;
+  
+  	if (PyErr_Occurred() || VimErrorCheck())
+  	    return FAIL;
+--- 2350,2361 ----
+  		    break;
+  		}
+  	    }
+! 	    if (buf == savebuf)
+  		py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
+  	    deleted_lines_mark((linenr_T)lo, (long)i);
+  	}
+  
+! 	restore_buffer(savebuf);
+  
+  	if (PyErr_Occurred() || VimErrorCheck())
+  	    return FAIL;
+***************
+*** 2400,2409 ****
+  	    }
+  	}
+  
+- 	savebuf = curbuf;
+- 
+  	PyErr_Clear();
+! 	curbuf = buf;
+  
+  	if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
+  	    PyErr_SetVim(_("cannot save undo information"));
+--- 2400,2409 ----
+  	    }
+  	}
+  
+  	PyErr_Clear();
+! 
+! 	// START of region without "return".  Must call restore_buffer()!
+! 	switch_buffer(&savebuf, buf);
+  
+  	if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
+  	    PyErr_SetVim(_("cannot save undo information"));
+***************
+*** 2480,2489 ****
+  						  (long)MAXLNUM, (long)extra);
+  	changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
+  
+! 	if (buf == curwin->w_buffer)
+  	    py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
+  
+! 	curbuf = savebuf;
+  
+  	if (PyErr_Occurred() || VimErrorCheck())
+  	    return FAIL;
+--- 2480,2490 ----
+  						  (long)MAXLNUM, (long)extra);
+  	changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
+  
+! 	if (buf == savebuf)
+  	    py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
+  
+! 	// END of region without "return".
+! 	restore_buffer(savebuf);
+  
+  	if (PyErr_Occurred() || VimErrorCheck())
+  	    return FAIL;
+***************
+*** 2522,2531 ****
+  	if (str == NULL)
+  	    return FAIL;
+  
+- 	savebuf = curbuf;
+- 
+  	PyErr_Clear();
+! 	curbuf = buf;
+  
+  	if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
+  	    PyErr_SetVim(_("cannot save undo information"));
+--- 2523,2530 ----
+  	if (str == NULL)
+  	    return FAIL;
+  
+  	PyErr_Clear();
+! 	switch_buffer(&savebuf, buf);
+  
+  	if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
+  	    PyErr_SetVim(_("cannot save undo information"));
+***************
+*** 2535,2541 ****
+  	    appended_lines_mark((linenr_T)n, 1L);
+  
+  	vim_free(str);
+! 	curbuf = savebuf;
+  	update_screen(VALID);
+  
+  	if (PyErr_Occurred() || VimErrorCheck())
+--- 2534,2540 ----
+  	    appended_lines_mark((linenr_T)n, 1L);
+  
+  	vim_free(str);
+! 	restore_buffer(savebuf);
+  	update_screen(VALID);
+  
+  	if (PyErr_Occurred() || VimErrorCheck())
+***************
+*** 2574,2583 ****
+  	    }
+  	}
+  
+- 	savebuf = curbuf;
+- 
+  	PyErr_Clear();
+! 	curbuf = buf;
+  
+  	if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
+  	    PyErr_SetVim(_("cannot save undo information"));
+--- 2573,2580 ----
+  	    }
+  	}
+  
+  	PyErr_Clear();
+! 	switch_buffer(&savebuf, buf);
+  
+  	if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
+  	    PyErr_SetVim(_("cannot save undo information"));
+***************
+*** 2607,2613 ****
+  	 */
+  	vim_free(array);
+  
+! 	curbuf = savebuf;
+  	update_screen(VALID);
+  
+  	if (PyErr_Occurred() || VimErrorCheck())
+--- 2604,2610 ----
+  	 */
+  	vim_free(array);
+  
+! 	restore_buffer(savebuf);
+  	update_screen(VALID);
+  
+  	if (PyErr_Occurred() || VimErrorCheck())
+***************
+*** 3023,3029 ****
+      pos_T	*posp;
+      char	*pmark;
+      char	mark;
+!     buf_T	*curbuf_save;
+  
+      if (CheckBuffer((BufferObject *)(self)))
+  	return NULL;
+--- 3020,3026 ----
+      pos_T	*posp;
+      char	*pmark;
+      char	mark;
+!     buf_T	*savebuf;
+  
+      if (CheckBuffer((BufferObject *)(self)))
+  	return NULL;
+***************
+*** 3032,3041 ****
+  	return NULL;
+      mark = *pmark;
+  
+!     curbuf_save = curbuf;
+!     curbuf = ((BufferObject *)(self))->buf;
+      posp = getmark(mark, FALSE);
+!     curbuf = curbuf_save;
+  
+      if (posp == NULL)
+      {
+--- 3029,3037 ----
+  	return NULL;
+      mark = *pmark;
+  
+!     switch_buffer(&savebuf, ((BufferObject *)(self))->buf);
+      posp = getmark(mark, FALSE);
+!     restore_buffer(savebuf);
+  
+      if (posp == NULL)
+      {
+*** ../vim-7.3.962/src/window.c	2013-05-15 23:13:06.000000000 +0200
+--- src/window.c	2013-05-17 15:57:17.000000000 +0200
+***************
+*** 4058,4063 ****
+--- 4058,4082 ----
+  }
+  #endif
+  
++ #if (defined(FEAT_WINDOWS) && defined(FEAT_PYTHON)) || defined(PROTO)
++ /*
++  * Find the tabpage for window "win".
++  */
++     tabpage_T *
++ win_find_tabpage(win)
++     win_T	*win;
++ {
++     win_T	*wp;
++     tabpage_T	*tp;
++ 
++     for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
++ 	for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next)
++ 	    if (wp == win)
++ 		return tp;
++     return NULL;
++ }
++ #endif
++ 
+  #ifdef FEAT_VERTSPLIT
+  /*
+   * Move to window above or below "count" times.
+***************
+*** 6550,6555 ****
+--- 6569,6673 ----
+  
+  #endif
+  
++ #if defined(FEAT_EVAL) || defined(PROTO)
++ /*
++  * Set "win" to be the curwin and "tp" to be the current tab page.
++  * restore_win() MUST be called to undo.
++  * No autocommands will be executed.
++  * Returns FAIL if switching to "win" failed.
++  */
++     int
++ switch_win(save_curwin, save_curtab, win, tp)
++     win_T	**save_curwin;
++     tabpage_T	**save_curtab;
++     win_T	*win;
++     tabpage_T	*tp;
++ {
++ # ifdef FEAT_AUTOCMD
++     block_autocmds();
++ # endif
++ # ifdef FEAT_WINDOWS
++     *save_curwin = curwin;
++     if (tp != NULL)
++     {
++ 	*save_curtab = curtab;
++ 	goto_tabpage_tp(tp, FALSE, FALSE);
++     }
++     if (!win_valid(win))
++     {
++ # ifdef FEAT_AUTOCMD
++ 	unblock_autocmds();
++ # endif
++ 	return FAIL;
++     }
++     curwin = win;
++     curbuf = curwin->w_buffer;
++ # endif
++     return OK;
++ }
++ 
++ /*
++  * Restore current tabpage and window saved by switch_win(), if still valid.
++  */
++     void
++ restore_win(save_curwin, save_curtab)
++     win_T	*save_curwin;
++     tabpage_T	*save_curtab;
++ {
++ # ifdef FEAT_WINDOWS
++     if (save_curtab != NULL && valid_tabpage(save_curtab))
++ 	goto_tabpage_tp(save_curtab, FALSE, FALSE);
++     if (win_valid(save_curwin))
++     {
++ 	curwin = save_curwin;
++ 	curbuf = curwin->w_buffer;
++     }
++ # endif
++ # ifdef FEAT_AUTOCMD
++     unblock_autocmds();
++ # endif
++ }
++ 
++ /*
++  * Make "buf" the current buffer.  restore_buffer() MUST be called to undo.
++  * No autocommands will be executed.  Use aucmd_prepbuf() if there are any.
++  */
++     void
++ switch_buffer(save_curbuf, buf)
++     buf_T *buf;
++     buf_T **save_curbuf;
++ {
++ # ifdef FEAT_AUTOCMD
++     block_autocmds();
++ # endif
++     *save_curbuf = curbuf;
++     --curbuf->b_nwindows;
++     curbuf = buf;
++     curwin->w_buffer = buf;
++     ++curbuf->b_nwindows;
++ }
++ 
++ /*
++  * Restore the current buffer after using switch_buffer().
++  */
++     void
++ restore_buffer(save_curbuf)
++     buf_T *save_curbuf;
++ {
++ # ifdef FEAT_AUTOCMD
++     unblock_autocmds();
++ # endif
++     /* Check for valid buffer, just in case. */
++     if (buf_valid(save_curbuf))
++     {
++ 	--curbuf->b_nwindows;
++ 	curwin->w_buffer = save_curbuf;
++ 	curbuf = save_curbuf;
++ 	++curbuf->b_nwindows;
++     }
++ }
++ #endif
++ 
+  #if (defined(FEAT_GUI) && defined(FEAT_VERTSPLIT)) || defined(PROTO)
+  /*
+   * Return TRUE if there is any vertically split window.
+*** ../vim-7.3.962/src/testdir/test86.ok	2013-05-17 13:37:57.000000000 +0200
+--- src/testdir/test86.ok	2013-05-17 14:48:57.000000000 +0200
+***************
+*** 333,339 ****
+  Current tab pages:
+    <tabpage 0>(1): 1 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(0): displays buffer <buffer test86.in>; cursor is at (955, 0)
+    <tabpage 1>(2): 1 windows, current is <window object (unknown)>
+    Windows:
+      <window object (unknown)>(0): displays buffer <buffer 0>; cursor is at (1, 0)
+--- 333,339 ----
+  Current tab pages:
+    <tabpage 0>(1): 1 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(0): displays buffer <buffer test86.in>; cursor is at (954, 0)
+    <tabpage 1>(2): 1 windows, current is <window object (unknown)>
+    Windows:
+      <window object (unknown)>(0): displays buffer <buffer 0>; cursor is at (1, 0)
+*** ../vim-7.3.962/src/version.c	2013-05-17 13:37:57.000000000 +0200
+--- src/version.c	2013-05-17 15:59:48.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     963,
+  /**/
+
+-- 
+TIM:   That is not an ordinary rabbit ... 'tis the most foul cruel and
+       bad-tempered thing you ever set eyes on.
+ROBIN: You tit.  I soiled my armour I was so scared!
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.964 b/7.3.964
new file mode 100644
index 0000000..e037ad7
--- /dev/null
+++ b/7.3.964
@@ -0,0 +1,405 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.964
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.964
+Problem:    Python: not so easy to access tab pages.
+Solution:   Add window.tabpage, make window.number work with non-current tab
+	    pages. (ZyX)
+Files:	    runtime/doc/if_pyth.txt, src/if_py_both.h, src/if_python3.c,
+	    src/if_python.c, src/testdir/test86.ok, src/testdir/test87.ok
+
+
+*** ../vim-7.3.963/runtime/doc/if_pyth.txt	2013-05-15 18:28:08.000000000 +0200
+--- runtime/doc/if_pyth.txt	2013-05-17 16:07:16.000000000 +0200
+***************
+*** 433,440 ****
+  				This is zero in case it cannot be determined
+  				(e.g. when the window object belongs to other
+  				tab page).
+!  	row, col (read-only)	On-screen window position in display cells.
+  				First position is zero.
+  
+  The height attribute is writable only if the screen is split horizontally.
+  The width attribute is writable only if the screen is split vertically.
+--- 433,441 ----
+  				This is zero in case it cannot be determined
+  				(e.g. when the window object belongs to other
+  				tab page).
+! 	row, col (read-only)	On-screen window position in display cells.
+  				First position is zero.
++ 	tabpage (read-only)	Window tab page.
+  
+  The height attribute is writable only if the screen is split horizontally.
+  The width attribute is writable only if the screen is split vertically.
+***************
+*** 490,496 ****
+  <							*:py3file*
+  The |:py3file| command works similar to |:pyfile|.
+  
+! 							*:py3do*
+  :[range]py3do {body}	Execute Python function "def _vim_pydo(line, linenr):
+  			{body}" for each line in the [range], with the
+  			function arguments being set to the text of each line
+--- 491,497 ----
+  <							*:py3file*
+  The |:py3file| command works similar to |:pyfile|.
+  
+! 							*:py3do* *E863*
+  :[range]py3do {body}	Execute Python function "def _vim_pydo(line, linenr):
+  			{body}" for each line in the [range], with the
+  			function arguments being set to the text of each line
+*** ../vim-7.3.963/src/if_py_both.h	2013-05-17 16:03:53.000000000 +0200
+--- src/if_py_both.h	2013-05-17 16:07:16.000000000 +0200
+***************
+*** 31,36 ****
+--- 31,39 ----
+  
+  static int ConvertFromPyObject(PyObject *, typval_T *);
+  static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
++ static PyObject *WindowNew(win_T *, tabpage_T *);
++ static PyObject *BufferNew (buf_T *);
++ static PyObject *LineToString(const char *);
+  
+  static PyInt RangeStart;
+  static PyInt RangeEnd;
+***************
+*** 1670,1678 ****
+  	/* For current tab window.c does not bother to set or update tp_curwin
+  	 */
+  	if (this->tab == curtab)
+! 	    return WindowNew(curwin);
+  	else
+! 	    return WindowNew(this->tab->tp_curwin);
+      }
+      return NULL;
+  }
+--- 1673,1681 ----
+  	/* For current tab window.c does not bother to set or update tp_curwin
+  	 */
+  	if (this->tab == curtab)
+! 	    return WindowNew(curwin, curtab);
+  	else
+! 	    return WindowNew(this->tab->tp_curwin, this->tab);
+      }
+      return NULL;
+  }
+***************
+*** 1754,1759 ****
+--- 1757,1763 ----
+  {
+      PyObject_HEAD
+      win_T	*win;
++     TabPageObject	*tabObject;
+  } WindowObject;
+  
+  static PyTypeObject WindowType;
+***************
+*** 1771,1777 ****
+  }
+  
+      static PyObject *
+! WindowNew(win_T *win)
+  {
+      /* We need to handle deletion of windows underneath us.
+       * If we add a "w_python*_ref" field to the win_T structure,
+--- 1775,1781 ----
+  }
+  
+      static PyObject *
+! WindowNew(win_T *win, tabpage_T *tab)
+  {
+      /* We need to handle deletion of windows underneath us.
+       * If we add a "w_python*_ref" field to the win_T structure,
+***************
+*** 1804,1809 ****
+--- 1808,1815 ----
+  	WIN_PYTHON_REF(win) = self;
+      }
+  
++     self->tabObject = ((TabPageObject *)(TabPageNew(tab)));
++ 
+      return (PyObject *)(self);
+  }
+  
+***************
+*** 1815,1823 ****
+--- 1821,1849 ----
+      if (this->win && this->win != INVALID_WINDOW_VALUE)
+  	WIN_PYTHON_REF(this->win) = NULL;
+  
++     Py_DECREF(((PyObject *)(this->tabObject)));
++ 
+      DESTRUCTOR_FINISH(self);
+  }
+  
++     static win_T *
++ get_firstwin(TabPageObject *tabObject)
++ {
++     if (tabObject)
++     {
++ 	if (CheckTabPage(tabObject))
++ 	    return NULL;
++ 	/* For current tab window.c does not bother to set or update tp_firstwin
++ 	 */
++ 	else if (tabObject->tab == curtab)
++ 	    return firstwin;
++ 	else
++ 	    return tabObject->tab->tp_firstwin;
++     }
++     else
++ 	return firstwin;
++ }
++ 
+      static PyObject *
+  WindowAttr(WindowObject *this, char *name)
+  {
+***************
+*** 1847,1856 ****
+  	return OptionsNew(SREQ_WIN, this->win, (checkfun) CheckWindow,
+  			(PyObject *) this);
+      else if (strcmp(name, "number") == 0)
+! 	return PyLong_FromLong((long) get_win_number(this->win, firstwin));
+      else if (strcmp(name,"__members__") == 0)
+! 	return Py_BuildValue("[ssssssss]", "buffer", "cursor", "height", "vars",
+! 		"options", "number", "row", "col");
+      else
+  	return NULL;
+  }
+--- 1873,1892 ----
+  	return OptionsNew(SREQ_WIN, this->win, (checkfun) CheckWindow,
+  			(PyObject *) this);
+      else if (strcmp(name, "number") == 0)
+!     {
+! 	if (CheckTabPage(this->tabObject))
+! 	    return NULL;
+! 	return PyLong_FromLong((long)
+! 		get_win_number(this->win, get_firstwin(this->tabObject)));
+!     }
+!     else if (strcmp(name, "tabpage") == 0)
+!     {
+! 	Py_INCREF(this->tabObject);
+! 	return (PyObject *)(this->tabObject);
+!     }
+      else if (strcmp(name,"__members__") == 0)
+! 	return Py_BuildValue("[sssssssss]", "buffer", "cursor", "height",
+! 		"vars", "options", "number", "row", "col", "tabpage");
+      else
+  	return NULL;
+  }
+***************
+*** 2016,2046 ****
+      DESTRUCTOR_FINISH(self);
+  }
+  
+-     static win_T *
+- get_firstwin(WinListObject *this)
+- {
+-     if (this->tabObject)
+-     {
+- 	if (CheckTabPage(this->tabObject))
+- 	    return NULL;
+- 	/* For current tab window.c does not bother to set or update tp_firstwin
+- 	 */
+- 	else if (this->tabObject->tab == curtab)
+- 	    return firstwin;
+- 	else
+- 	    return this->tabObject->tab->tp_firstwin;
+-     }
+-     else
+- 	return firstwin;
+- }
+- 
+      static PyInt
+  WinListLength(PyObject *self)
+  {
+      win_T	*w;
+      PyInt	n = 0;
+  
+!     if (!(w = get_firstwin((WinListObject *)(self))))
+  	return -1;
+  
+      while (w != NULL)
+--- 2052,2064 ----
+      DESTRUCTOR_FINISH(self);
+  }
+  
+      static PyInt
+  WinListLength(PyObject *self)
+  {
+      win_T	*w;
+      PyInt	n = 0;
+  
+!     if (!(w = get_firstwin(((WinListObject *)(self))->tabObject)))
+  	return -1;
+  
+      while (w != NULL)
+***************
+*** 2055,2068 ****
+      static PyObject *
+  WinListItem(PyObject *self, PyInt n)
+  {
+      win_T *w;
+  
+!     if (!(w = get_firstwin((WinListObject *)(self))))
+  	return NULL;
+  
+      for (; w != NULL; w = W_NEXT(w), --n)
+  	if (n == 0)
+! 	    return WindowNew(w);
+  
+      PyErr_SetString(PyExc_IndexError, _("no such window"));
+      return NULL;
+--- 2073,2087 ----
+      static PyObject *
+  WinListItem(PyObject *self, PyInt n)
+  {
++     WinListObject	*this = ((WinListObject *)(self));
+      win_T *w;
+  
+!     if (!(w = get_firstwin(this->tabObject)))
+  	return NULL;
+  
+      for (; w != NULL; w = W_NEXT(w), --n)
+  	if (n == 0)
+! 	    return WindowNew(w, this->tabObject? this->tabObject->tab: curtab);
+  
+      PyErr_SetString(PyExc_IndexError, _("no such window"));
+      return NULL;
+***************
+*** 3227,3233 ****
+      if (strcmp(name, "buffer") == 0)
+  	return (PyObject *)BufferNew(curbuf);
+      else if (strcmp(name, "window") == 0)
+! 	return (PyObject *)WindowNew(curwin);
+      else if (strcmp(name, "tabpage") == 0)
+  	return (PyObject *)TabPageNew(curtab);
+      else if (strcmp(name, "line") == 0)
+--- 3246,3252 ----
+      if (strcmp(name, "buffer") == 0)
+  	return (PyObject *)BufferNew(curbuf);
+      else if (strcmp(name, "window") == 0)
+! 	return (PyObject *)WindowNew(curwin, curtab);
+      else if (strcmp(name, "tabpage") == 0)
+  	return (PyObject *)TabPageNew(curtab);
+      else if (strcmp(name, "line") == 0)
+*** ../vim-7.3.963/src/if_python3.c	2013-05-15 19:44:35.000000000 +0200
+--- src/if_python3.c	2013-05-17 16:07:16.000000000 +0200
+***************
+*** 611,619 ****
+  }
+  #endif /* DYNAMIC_PYTHON3 */
+  
+- static PyObject *BufferNew (buf_T *);
+- static PyObject *WindowNew(win_T *);
+- static PyObject *LineToString(const char *);
+  static PyObject *BufferDir(PyObject *, PyObject *);
+  
+  static int py3initialised = 0;
+--- 611,616 ----
+*** ../vim-7.3.963/src/if_python.c	2013-05-15 17:49:00.000000000 +0200
+--- src/if_python.c	2013-05-17 16:07:16.000000000 +0200
+***************
+*** 610,620 ****
+  }
+  #endif /* DYNAMIC_PYTHON */
+  
+- static PyObject *BufferNew (buf_T *);
+- static PyObject *WindowNew(win_T *);
+- static PyObject *DictionaryNew(dict_T *);
+- static PyObject *LineToString(const char *);
+- 
+  static int initialised = 0;
+  #define PYINITIALISED initialised
+  
+--- 610,615 ----
+*** ../vim-7.3.963/src/testdir/test86.ok	2013-05-17 16:03:53.000000000 +0200
+--- src/testdir/test86.ok	2013-05-17 16:10:26.000000000 +0200
+***************
+*** 333,346 ****
+  Current tab pages:
+    <tabpage 0>(1): 1 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(0): displays buffer <buffer test86.in>; cursor is at (954, 0)
+    <tabpage 1>(2): 1 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(0): displays buffer <buffer 0>; cursor is at (1, 0)
+    <tabpage 2>(3): 2 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(0): displays buffer <buffer a.1>; cursor is at (1, 0)
+!     <window object (unknown)>(0): displays buffer <buffer 1>; cursor is at (1, 0)
+    <tabpage 3>(4): 4 windows, current is <window 0>
+    Windows:
+      <window 0>(1): displays buffer <buffer c.2>; cursor is at (1, 0)
+--- 333,346 ----
+  Current tab pages:
+    <tabpage 0>(1): 1 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(1): displays buffer <buffer test86.in>; cursor is at (954, 0)
+    <tabpage 1>(2): 1 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(1): displays buffer <buffer 0>; cursor is at (1, 0)
+    <tabpage 2>(3): 2 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(1): displays buffer <buffer a.1>; cursor is at (1, 0)
+!     <window object (unknown)>(2): displays buffer <buffer 1>; cursor is at (1, 0)
+    <tabpage 3>(4): 4 windows, current is <window 0>
+    Windows:
+      <window 0>(1): displays buffer <buffer c.2>; cursor is at (1, 0)
+*** ../vim-7.3.963/src/testdir/test87.ok	2013-05-17 13:37:57.000000000 +0200
+--- src/testdir/test87.ok	2013-05-17 16:07:16.000000000 +0200
+***************
+*** 322,335 ****
+  Current tab pages:
+    <tabpage 0>(1): 1 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(0): displays buffer <buffer test87.in>; cursor is at (930, 0)
+    <tabpage 1>(2): 1 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(0): displays buffer <buffer 0>; cursor is at (1, 0)
+    <tabpage 2>(3): 2 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(0): displays buffer <buffer a.1>; cursor is at (1, 0)
+!     <window object (unknown)>(0): displays buffer <buffer 1>; cursor is at (1, 0)
+    <tabpage 3>(4): 4 windows, current is <window 0>
+    Windows:
+      <window 0>(1): displays buffer <buffer c.2>; cursor is at (1, 0)
+--- 322,335 ----
+  Current tab pages:
+    <tabpage 0>(1): 1 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(1): displays buffer <buffer test87.in>; cursor is at (930, 0)
+    <tabpage 1>(2): 1 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(1): displays buffer <buffer 0>; cursor is at (1, 0)
+    <tabpage 2>(3): 2 windows, current is <window object (unknown)>
+    Windows:
+!     <window object (unknown)>(1): displays buffer <buffer a.1>; cursor is at (1, 0)
+!     <window object (unknown)>(2): displays buffer <buffer 1>; cursor is at (1, 0)
+    <tabpage 3>(4): 4 windows, current is <window 0>
+    Windows:
+      <window 0>(1): displays buffer <buffer c.2>; cursor is at (1, 0)
+*** ../vim-7.3.963/src/version.c	2013-05-17 16:03:53.000000000 +0200
+--- src/version.c	2013-05-17 16:11:15.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     964,
+  /**/
+
+-- 
+ARTHUR: Go on, Bors, chop its head off.
+BORS:   Right.  Silly little bleeder.  One rabbit stew coming up.
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.965 b/7.3.965
new file mode 100644
index 0000000..cc2d676
--- /dev/null
+++ b/7.3.965
@@ -0,0 +1,331 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.965
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.965
+Problem:    Python garbage collection not working properly.
+Solution:   Add support for garbage collection. (ZyX)
+Files:	    src/if_py_both.h
+
+
+*** ../vim-7.3.964/src/if_py_both.h	2013-05-17 16:18:27.000000000 +0200
+--- src/if_py_both.h	2013-05-17 16:21:05.000000000 +0200
+***************
+*** 543,548 ****
+--- 543,550 ----
+  
+  typedef PyObject *(*nextfun)(void **);
+  typedef void (*destructorfun)(void *);
++ typedef int (*traversefun)(void *, visitproc, void *);
++ typedef int (*clearfun)(void **);
+  
+  /* Main purpose of this object is removing the need for do python initialization 
+   * (i.e. PyType_Ready and setting type attributes) for a big bunch of objects.
+***************
+*** 554,563 ****
+      void *cur;
+      nextfun next;
+      destructorfun destruct;
+  } IterObject;
+  
+      static PyObject *
+! IterNew(void *start, destructorfun destruct, nextfun next)
+  {
+      IterObject *self;
+  
+--- 556,568 ----
+      void *cur;
+      nextfun next;
+      destructorfun destruct;
++     traversefun traverse;
++     clearfun clear;
+  } IterObject;
+  
+      static PyObject *
+! IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
+! 	clearfun clear)
+  {
+      IterObject *self;
+  
+***************
+*** 565,570 ****
+--- 570,577 ----
+      self->cur = start;
+      self->next = next;
+      self->destruct = destruct;
++     self->traverse = traverse;
++     self->clear = clear;
+  
+      return (PyObject *)(self);
+  }
+***************
+*** 579,584 ****
+--- 586,613 ----
+      DESTRUCTOR_FINISH(self);
+  }
+  
++     static int
++ IterTraverse(PyObject *self, visitproc visit, void *arg)
++ {
++     IterObject *this = (IterObject *)(self);
++ 
++     if (this->traverse != NULL)
++ 	return this->traverse(this->cur, visit, arg);
++     else
++ 	return 0;
++ }
++ 
++     static int
++ IterClear(PyObject *self)
++ {
++     IterObject *this = (IterObject *)(self);
++ 
++     if (this->clear != NULL)
++ 	return this->clear(&this->cur);
++     else
++ 	return 0;
++ }
++ 
+      static PyObject *
+  IterNext(PyObject *self)
+  {
+***************
+*** 1034,1040 ****
+      lii->list = l;
+  
+      return IterNew(lii,
+! 	    (destructorfun) ListIterDestruct, (nextfun) ListIterNext);
+  }
+  
+      static int
+--- 1063,1070 ----
+      lii->list = l;
+  
+      return IterNew(lii,
+! 	    (destructorfun) ListIterDestruct, (nextfun) ListIterNext,
+! 	    NULL, NULL);
+  }
+  
+      static int
+***************
+*** 1348,1353 ****
+--- 1378,1430 ----
+      PyObject *fromObj;
+  } OptionsObject;
+  
++     static int
++ dummy_check(void *arg UNUSED)
++ {
++     return 0;
++ }
++ 
++     static PyObject *
++ OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj)
++ {
++     OptionsObject	*self;
++ 
++     self = PyObject_NEW(OptionsObject, &OptionsType);
++     if (self == NULL)
++ 	return NULL;
++ 
++     self->opt_type = opt_type;
++     self->from = from;
++     self->Check = Check;
++     self->fromObj = fromObj;
++     if (fromObj)
++ 	Py_INCREF(fromObj);
++ 
++     return (PyObject *)(self);
++ }
++ 
++     static void
++ OptionsDestructor(PyObject *self)
++ {
++     if (((OptionsObject *)(self))->fromObj)
++ 	Py_DECREF(((OptionsObject *)(self))->fromObj);
++     DESTRUCTOR_FINISH(self);
++ }
++ 
++     static int
++ OptionsTraverse(PyObject *self, visitproc visit, void *arg)
++ {
++     Py_VISIT(((OptionsObject *)(self))->fromObj);
++     return 0;
++ }
++ 
++     static int
++ OptionsClear(PyObject *self)
++ {
++     Py_CLEAR(((OptionsObject *)(self))->fromObj);
++     return 0;
++ }
++ 
+      static PyObject *
+  OptionsItem(OptionsObject *this, PyObject *keyObject)
+  {
+***************
+*** 1562,1600 ****
+      return r;
+  }
+  
+-     static int
+- dummy_check(void *arg UNUSED)
+- {
+-     return 0;
+- }
+- 
+-     static PyObject *
+- OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj)
+- {
+-     OptionsObject	*self;
+- 
+-     self = PyObject_NEW(OptionsObject, &OptionsType);
+-     if (self == NULL)
+- 	return NULL;
+- 
+-     self->opt_type = opt_type;
+-     self->from = from;
+-     self->Check = Check;
+-     self->fromObj = fromObj;
+-     if (fromObj)
+- 	Py_INCREF(fromObj);
+- 
+-     return (PyObject *)(self);
+- }
+- 
+-     static void
+- OptionsDestructor(PyObject *self)
+- {
+-     if (((OptionsObject *)(self))->fromObj)
+- 	Py_DECREF(((OptionsObject *)(self))->fromObj);
+-     DESTRUCTOR_FINISH(self);
+- }
+- 
+  static PyMappingMethods OptionsAsMapping = {
+      (lenfunc)       NULL,
+      (binaryfunc)    OptionsItem,
+--- 1639,1644 ----
+***************
+*** 1843,1848 ****
+--- 1887,1905 ----
+      else
+  	return firstwin;
+  }
++     static int
++ WindowTraverse(PyObject *self, visitproc visit, void *arg)
++ {
++     Py_VISIT(((PyObject *)(((WindowObject *)(self))->tabObject)));
++     return 0;
++ }
++ 
++     static int
++ WindowClear(PyObject *self)
++ {
++     Py_CLEAR((((WindowObject *)(self))->tabObject));
++     return 0;
++ }
+  
+      static PyObject *
+  WindowAttr(WindowObject *this, char *name)
+***************
+*** 3193,3198 ****
+--- 3250,3269 ----
+      }
+  }
+  
++     static int
++ BufMapIterTraverse(PyObject *buffer, visitproc visit, void *arg)
++ {
++     Py_VISIT(buffer);
++     return 0;
++ }
++ 
++     static int
++ BufMapIterClear(PyObject **buffer)
++ {
++     Py_CLEAR(*buffer);
++     return 0;
++ }
++ 
+      static PyObject *
+  BufMapIterNext(PyObject **buffer)
+  {
+***************
+*** 3228,3234 ****
+  
+      buffer = BufferNew(firstbuf);
+      return IterNew(buffer,
+! 	    (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext);
+  }
+  
+  static PyMappingMethods BufMapAsMapping = {
+--- 3299,3306 ----
+  
+      buffer = BufferNew(firstbuf);
+      return IterNew(buffer,
+! 	    (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext,
+! 	    (traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear);
+  }
+  
+  static PyMappingMethods BufMapAsMapping = {
+***************
+*** 3837,3842 ****
+--- 3909,3916 ----
+      IterType.tp_iter = IterIter;
+      IterType.tp_iternext = IterNext;
+      IterType.tp_dealloc = IterDestructor;
++     IterType.tp_traverse = IterTraverse;
++     IterType.tp_clear = IterClear;
+  
+      vim_memset(&BufferType, 0, sizeof(BufferType));
+      BufferType.tp_name = "vim.buffer";
+***************
+*** 3865,3870 ****
+--- 3939,3946 ----
+      WindowType.tp_flags = Py_TPFLAGS_DEFAULT;
+      WindowType.tp_doc = "vim Window object";
+      WindowType.tp_methods = WindowMethods;
++     WindowType.tp_traverse = WindowTraverse;
++     WindowType.tp_clear = WindowClear;
+  #if PY_MAJOR_VERSION >= 3
+      WindowType.tp_getattro = WindowGetattro;
+      WindowType.tp_setattro = WindowSetattro;
+***************
+*** 4003,4008 ****
+--- 4079,4086 ----
+      OptionsType.tp_doc = "object for manipulating options";
+      OptionsType.tp_as_mapping = &OptionsAsMapping;
+      OptionsType.tp_dealloc = OptionsDestructor;
++     OptionsType.tp_traverse = OptionsTraverse;
++     OptionsType.tp_clear = OptionsClear;
+  
+  #if PY_MAJOR_VERSION >= 3
+      vim_memset(&vimmodule, 0, sizeof(vimmodule));
+*** ../vim-7.3.964/src/version.c	2013-05-17 16:18:27.000000000 +0200
+--- src/version.c	2013-05-17 16:21:24.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     965,
+  /**/
+
+-- 
+ARTHUR: Charge!
+   [They all charge with swords drawn towards the RABBIT.  A tremendous twenty
+   second fight with Peckinpahish shots and borrowing heavily also on the
+   Kung Fu and karate-type films ensues, in which some four KNIGHTS are
+   comprehensively killed.]
+ARTHUR: Run away!  Run away!
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.966 b/7.3.966
new file mode 100644
index 0000000..6dc6950
--- /dev/null
+++ b/7.3.966
@@ -0,0 +1,301 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.966
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.966
+Problem:    There is ":py3do" but no ":pydo".
+Solution:   Add the ":pydo" command. (Lilydjwg)
+Files:	    runtime/doc/if_pyth.txt, src/ex_cmds.h, src/ex_docmd.c,
+	    src/if_py_both.h, src/if_python.c, src/if_python3.c,
+	    src/proto/if_python.pro
+
+
+*** ../vim-7.3.965/runtime/doc/if_pyth.txt	2013-05-17 16:18:27.000000000 +0200
+--- runtime/doc/if_pyth.txt	2013-05-17 16:34:28.000000000 +0200
+***************
+*** 57,62 ****
+--- 57,78 ----
+  Note: Python is very sensitive to the indenting.  Make sure the "class" line
+  and "EOF" do not have any indent.
+  
++ 							*:pydo*
++ :[range]pydo {body}	Execute Python function "def _vim_pydo(line, linenr):
++ 			{body}" for each line in the [range], with the
++ 			function arguments being set to the text of each line
++ 			in turn, without a trailing <EOL>, and the current
++ 			line number. The function should return a string or
++ 			None. If a string is returned, it becomes the text of
++ 			the line in the current turn. The default for [range]
++ 			is the whole file: "1,$".
++ 			{not in Vi}
++ 
++ Examples:
++ >
++ 	:pydo return "%s\t%d" % (line[::-1], len(line))
++ 	:pydo if line: return "%4d: %s" % (linenr, line)
++ <
+  							*:pyfile* *:pyf*
+  :[range]pyf[ile] {file}
+  			Execute the Python script in {file}.  The whole
+***************
+*** 485,511 ****
+  8. Python 3						*python3*
+  
+  							*:py3* *:python3*
+! The |:py3| and |:python3| commands work similar to |:python|.  A simple check
+  if the `:py3` command is working: >
+  	:py3 print("Hello")
+  <							*:py3file*
+! The |:py3file| command works similar to |:pyfile|.
+! 
+  							*:py3do* *E863*
+! :[range]py3do {body}	Execute Python function "def _vim_pydo(line, linenr):
+! 			{body}" for each line in the [range], with the
+! 			function arguments being set to the text of each line
+! 			in turn, without a trailing <EOL>, and the current
+! 			line number. The function should return a string or
+! 			None. If a string is returned, it becomes the text of
+! 			the line in the current turn. The default for [range]
+! 			is the whole file: "1,$".
+! 			{not in Vi}
+  
+- Examples:
+- >
+- 	:py3do return "%s\t%d" % (line[::-1], len(line))
+- 	:py3do if line: return "%4d: %s" % (linenr, line)
+  
+  Vim can be built in four ways (:version output):
+  1. No Python support	    (-python, -python3)
+--- 501,514 ----
+  8. Python 3						*python3*
+  
+  							*:py3* *:python3*
+! The `:py3` and `:python3` commands work similar to `:python`.  A simple check
+  if the `:py3` command is working: >
+  	:py3 print("Hello")
+  <							*:py3file*
+! The `:py3file` command works similar to `:pyfile`.
+  							*:py3do* *E863*
+! The `:py3do` command works similar to `:pydo`.
+  
+  
+  Vim can be built in four ways (:version output):
+  1. No Python support	    (-python, -python3)
+*** ../vim-7.3.965/src/ex_cmds.h	2013-05-15 18:28:08.000000000 +0200
+--- src/ex_cmds.h	2013-05-17 16:29:38.000000000 +0200
+***************
+*** 739,744 ****
+--- 739,746 ----
+  			TRLBAR|CMDWIN),
+  EX(CMD_python,		"python",	ex_python,
+  			RANGE|EXTRA|NEEDARG|CMDWIN),
++ EX(CMD_pydo,		"pydo",		ex_pydo,
++ 			RANGE|DFLALL|EXTRA|NEEDARG|CMDWIN),
+  EX(CMD_pyfile,		"pyfile",	ex_pyfile,
+  			RANGE|FILE1|NEEDARG|CMDWIN),
+  EX(CMD_py3,		"py3",		ex_py3,
+*** ../vim-7.3.965/src/ex_docmd.c	2013-05-15 18:28:08.000000000 +0200
+--- src/ex_docmd.c	2013-05-17 16:29:38.000000000 +0200
+***************
+*** 268,273 ****
+--- 268,274 ----
+  #endif
+  #ifndef FEAT_PYTHON
+  # define ex_python		ex_script_ni
++ # define ex_pydo		ex_ni
+  # define ex_pyfile		ex_ni
+  #endif
+  #ifndef FEAT_PYTHON3
+*** ../vim-7.3.965/src/if_py_both.h	2013-05-17 16:24:27.000000000 +0200
+--- src/if_py_both.h	2013-05-17 16:29:38.000000000 +0200
+***************
+*** 22,27 ****
+--- 22,28 ----
+  #else
+  # define ENC_OPT "latin1"
+  #endif
++ #define DOPY_FUNC "_vim_pydo"
+  
+  #define PyErr_SetVim(str) PyErr_SetString(VimError, str)
+  
+*** ../vim-7.3.965/src/if_python.c	2013-05-17 16:18:27.000000000 +0200
+--- src/if_python.c	2013-05-17 16:29:38.000000000 +0200
+***************
+*** 198,203 ****
+--- 198,206 ----
+  # define PyModule_GetDict dll_PyModule_GetDict
+  # define PyRun_SimpleString dll_PyRun_SimpleString
+  # define PyRun_String dll_PyRun_String
++ # define PyObject_GetAttrString dll_PyObject_GetAttrString
++ # define PyObject_SetAttrString dll_PyObject_SetAttrString
++ # define PyObject_CallFunctionObjArgs dll_PyObject_CallFunctionObjArgs
+  # define PyString_AsString dll_PyString_AsString
+  # define PyString_AsStringAndSize dll_PyString_AsStringAndSize
+  # define PyString_FromString dll_PyString_FromString
+***************
+*** 303,308 ****
+--- 306,314 ----
+  static PyObject*(*dll_PyModule_GetDict)(PyObject *);
+  static int(*dll_PyRun_SimpleString)(char *);
+  static PyObject *(*dll_PyRun_String)(char *, int, PyObject *, PyObject *);
++ static PyObject* (*dll_PyObject_GetAttrString)(PyObject *, const char *);
++ static PyObject* (*dll_PyObject_SetAttrString)(PyObject *, const char *, PyObject *);
++ static PyObject* (*dll_PyObject_CallFunctionObjArgs)(PyObject *, ...);
+  static char*(*dll_PyString_AsString)(PyObject *);
+  static int(*dll_PyString_AsStringAndSize)(PyObject *, char **, int *);
+  static PyObject*(*dll_PyString_FromString)(const char *);
+***************
+*** 440,445 ****
+--- 446,454 ----
+      {"PyModule_GetDict", (PYTHON_PROC*)&dll_PyModule_GetDict},
+      {"PyRun_SimpleString", (PYTHON_PROC*)&dll_PyRun_SimpleString},
+      {"PyRun_String", (PYTHON_PROC*)&dll_PyRun_String},
++     {"PyObject_GetAttrString", (PYTHON_PROC*)&dll_PyObject_GetAttrString},
++     {"PyObject_SetAttrString", (PYTHON_PROC*)&dll_PyObject_SetAttrString},
++     {"PyObject_CallFunctionObjArgs", (PYTHON_PROC*)&dll_PyObject_CallFunctionObjArgs},
+      {"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString},
+      {"PyString_AsStringAndSize", (PYTHON_PROC*)&dll_PyString_AsStringAndSize},
+      {"PyString_FromString", (PYTHON_PROC*)&dll_PyString_FromString},
+***************
+*** 995,1000 ****
+--- 1004,1096 ----
+      DoPythonCommand(eap, buffer, NULL);
+  }
+  
++     void
++ ex_pydo(exarg_T *eap)
++ {
++     linenr_T		i;
++     const char		*code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
++     const char		*s = (const char *) eap->arg;
++     size_t		len;
++     char		*code;
++     int			status;
++     PyObject		*pyfunc, *pymain;
++     PyGILState_STATE	pygilstate;
++ 
++     if (Python_Init())
++         return;
++ 
++     if (u_save(eap->line1 - 1, eap->line2 + 1) != OK)
++     {
++ 	EMSG(_("cannot save undo information"));
++ 	return;
++     }
++     len = strlen(code_hdr) + strlen(s);
++     code = malloc(len + 1);
++     STRCPY(code, code_hdr);
++     STRNCAT(code, s, len + 1);
++     pygilstate = PyGILState_Ensure();
++     status = PyRun_SimpleString(code);
++     vim_free(code);
++     if (status)
++     {
++ 	EMSG(_("failed to run the code"));
++ 	return;
++     }
++     status = 0; /* good */
++     pymain = PyImport_AddModule("__main__");
++     pyfunc = PyObject_GetAttrString(pymain, DOPY_FUNC);
++     PyGILState_Release(pygilstate);
++ 
++     for (i = eap->line1; i <= eap->line2; i++)
++     {
++ 	const char *line;
++ 	PyObject *pyline, *pylinenr, *pyret;
++ 
++ 	line = (char *)ml_get(i);
++ 	pygilstate = PyGILState_Ensure();
++ 	pyline = PyString_FromStringAndSize(line, strlen(line));
++ 	pylinenr = PyLong_FromLong(i);
++ 	pyret = PyObject_CallFunctionObjArgs(pyfunc, pyline, pylinenr, NULL);
++ 	Py_DECREF(pyline);
++ 	Py_DECREF(pylinenr);
++ 	if (!pyret)
++ 	{
++ 	    PyErr_PrintEx(0);
++ 	    PythonIO_Flush();
++ 	    status = 1;
++ 	    goto out;
++ 	}
++ 
++ 	if (pyret && pyret != Py_None)
++ 	{
++ 	    if (!PyString_Check(pyret))
++ 	    {
++ 		EMSG(_("E863: return value must be an instance of str"));
++ 		Py_XDECREF(pyret);
++ 		status = 1;
++ 		goto out;
++ 	    }
++ 	    ml_replace(i, (char_u *) PyString_AsString(pyret), 1);
++ 	    changed();
++ #ifdef SYNTAX_HL
++ 	    syn_changed(i); /* recompute syntax hl. for this line */
++ #endif
++ 	}
++ 	Py_XDECREF(pyret);
++ 	PythonIO_Flush();
++ 	PyGILState_Release(pygilstate);
++     }
++     pygilstate = PyGILState_Ensure();
++ out:
++     Py_DECREF(pyfunc);
++     PyObject_SetAttrString(pymain, DOPY_FUNC, NULL);
++     PyGILState_Release(pygilstate);
++     if (status)
++ 	return;
++     check_cursor();
++     update_curbuf(NOT_VALID);
++ }
++ 
+  /******************************************************
+   * 2. Python output stream: writes output via [e]msg().
+   */
+*** ../vim-7.3.965/src/if_python3.c	2013-05-17 16:18:27.000000000 +0200
+--- src/if_python3.c	2013-05-17 16:29:38.000000000 +0200
+***************
+*** 76,82 ****
+  #else
+  # define CODEC_ERROR_HANDLER NULL
+  #endif
+- #define DOPY_FUNC "_vim_pydo"
+  
+  /* Python 3 does not support CObjects, always use Capsules */
+  #define PY_USE_CAPSULE
+--- 76,81 ----
+*** ../vim-7.3.965/src/proto/if_python.pro	2013-05-15 15:12:25.000000000 +0200
+--- src/proto/if_python.pro	2013-05-17 16:29:38.000000000 +0200
+***************
+*** 3,8 ****
+--- 3,9 ----
+  void python_end __ARGS((void));
+  int python_loaded __ARGS((void));
+  void ex_python __ARGS((exarg_T *eap));
++ void ex_pydo __ARGS((exarg_T *eap));
+  void ex_pyfile __ARGS((exarg_T *eap));
+  void python_buffer_free __ARGS((buf_T *buf));
+  void python_window_free __ARGS((win_T *win));
+*** ../vim-7.3.965/src/version.c	2013-05-17 16:24:27.000000000 +0200
+--- src/version.c	2013-05-17 16:39:19.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     966,
+  /**/
+
+-- 
+A hamburger walks into a bar, and the bartender says: "I'm sorry,
+but we don't serve food here."
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.967 b/7.3.967
new file mode 100644
index 0000000..39c67dd
--- /dev/null
+++ b/7.3.967
@@ -0,0 +1,112 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.9
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.967 (after 7.3.965)
+Problem:    Build fails on Mac OSX. (Greg Novack)
+Solution:   Undefine clear().
+Files:	    src/if_py_both.h
+
+
+*** ../vim-7.3.966/src/if_py_both.h	2013-05-17 16:39:59.000000000 +0200
+--- src/if_py_both.h	2013-05-17 20:40:47.000000000 +0200
+***************
+*** 474,480 ****
+  static PyObject *ConvertToPyObject(typval_T *);
+  
+      static PyObject *
+! VimEvalPy(PyObject *self UNUSED, PyObject *args UNUSED)
+  {
+      char	*expr;
+      typval_T	*our_tv;
+--- 474,480 ----
+  static PyObject *ConvertToPyObject(typval_T *);
+  
+      static PyObject *
+! VimEvalPy(PyObject *self UNUSED, PyObject *args)
+  {
+      char	*expr;
+      typval_T	*our_tv;
+***************
+*** 547,555 ****
+  typedef int (*traversefun)(void *, visitproc, void *);
+  typedef int (*clearfun)(void **);
+  
+! /* Main purpose of this object is removing the need for do python initialization 
+!  * (i.e. PyType_Ready and setting type attributes) for a big bunch of objects.
+!  */
+  
+  typedef struct
+  {
+--- 547,555 ----
+  typedef int (*traversefun)(void *, visitproc, void *);
+  typedef int (*clearfun)(void **);
+  
+! /* Main purpose of this object is removing the need for do python
+!  * initialization (i.e. PyType_Ready and setting type attributes) for a big
+!  * bunch of objects. */
+  
+  typedef struct
+  {
+***************
+*** 598,603 ****
+--- 598,608 ----
+  	return 0;
+  }
+  
++ /* Mac OSX defines clear() somewhere. */
++ #ifdef clear
++ # undef clear
++ #endif
++ 
+      static int
+  IterClear(PyObject *self)
+  {
+***************
+*** 3287,3295 ****
+      else if (!(next = BufferNew(((BufferObject *)(r))->buf->b_next)))
+  	return NULL;
+      *buffer = next;
+!     /* Do not increment reference: we no longer hold it (decref), but whoever on 
+!      * other side will hold (incref). Decref+incref = nothing.
+!      */
+      return r;
+  }
+  
+--- 3292,3299 ----
+      else if (!(next = BufferNew(((BufferObject *)(r))->buf->b_next)))
+  	return NULL;
+      *buffer = next;
+!     /* Do not increment reference: we no longer hold it (decref), but whoever
+!      * on other side will hold (incref). Decref+incref = nothing. */
+      return r;
+  }
+  
+*** ../vim-7.3.966/src/version.c	2013-05-17 16:39:59.000000000 +0200
+--- src/version.c	2013-05-17 21:19:17.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     967,
+  /**/
+
+-- 
+ARTHUR:          What does it say?
+BROTHER MAYNARD: It reads ... "Here may be found the last words of Joseph of
+                 Aramathea." "He who is valorous and pure of heart may find
+                 the Holy Grail in the aaaaarrrrrrggghhh..."
+ARTHUR:          What?
+BROTHER MAYNARD: "The Aaaaarrrrrrggghhh..."
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.968 b/7.3.968
new file mode 100644
index 0000000..be17541
--- /dev/null
+++ b/7.3.968
@@ -0,0 +1,58 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.968
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.968
+Problem:    Multi-byte support is only available when compiled with "big"
+	    features.
+Solution:   Include multi-byte by default, with "normal" features.
+Files:	    src/feature.h
+
+
+*** ../vim-7.3.967/src/feature.h	2013-05-06 04:21:35.000000000 +0200
+--- src/feature.h	2013-05-18 20:18:20.000000000 +0200
+***************
+*** 638,644 ****
+   * Disabled for EBCDIC:
+   * Multibyte support doesn't work on z/OS Unix currently.
+   */
+! #if (defined(FEAT_BIG) || defined(FEAT_GUI_GTK) || defined(FEAT_ARABIC)) \
+  	&& !defined(FEAT_MBYTE) && !defined(WIN16) \
+  	&& SIZEOF_INT >= 4 && !defined(EBCDIC)
+  # define FEAT_MBYTE
+--- 638,644 ----
+   * Disabled for EBCDIC:
+   * Multibyte support doesn't work on z/OS Unix currently.
+   */
+! #if (defined(FEAT_NORMAL) || defined(FEAT_GUI_GTK) || defined(FEAT_ARABIC)) \
+  	&& !defined(FEAT_MBYTE) && !defined(WIN16) \
+  	&& SIZEOF_INT >= 4 && !defined(EBCDIC)
+  # define FEAT_MBYTE
+*** ../vim-7.3.967/src/version.c	2013-05-17 21:20:13.000000000 +0200
+--- src/version.c	2013-05-18 20:21:19.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     968,
+  /**/
+
+-- 
+VOICE OVER: As the horrendous Black Beast lunged forward, escape for Arthur
+            and his knights seemed hopeless,  when, suddenly ... the animator
+            suffered a fatal heart attack.
+ANIMATOR:   Aaaaagh!
+VOICE OVER: The cartoon peril was no more ... The Quest for Holy Grail could
+            continue.
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.969 b/7.3.969
new file mode 100644
index 0000000..8dc47c7
--- /dev/null
+++ b/7.3.969
@@ -0,0 +1,55 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.969
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.969
+Problem:    Can't built with Python 3 and without Python 2.
+Solution:   Adjust #ifdef. (Xavier de Gaye)
+Files:	    src/window.c
+
+
+*** ../vim-7.3.968/src/window.c	2013-05-17 16:03:53.000000000 +0200
+--- src/window.c	2013-05-18 20:53:21.000000000 +0200
+***************
+*** 4058,4064 ****
+  }
+  #endif
+  
+! #if (defined(FEAT_WINDOWS) && defined(FEAT_PYTHON)) || defined(PROTO)
+  /*
+   * Find the tabpage for window "win".
+   */
+--- 4058,4065 ----
+  }
+  #endif
+  
+! #if (defined(FEAT_WINDOWS) && (defined(FEAT_PYTHON) || defined(FEAT_PYTHON3))) \
+! 	|| defined(PROTO)
+  /*
+   * Find the tabpage for window "win".
+   */
+*** ../vim-7.3.968/src/version.c	2013-05-18 20:45:51.000000000 +0200
+--- src/version.c	2013-05-18 20:54:16.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     969,
+  /**/
+
+-- 
+ROBIN:  (warily) And if you get a question wrong?
+ARTHUR: You are cast into the Gorge of Eternal Peril.
+ROBIN:  Oh ... wacho!
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.970 b/7.3.970
new file mode 100644
index 0000000..519138a
--- /dev/null
+++ b/7.3.970
@@ -0,0 +1,6724 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.970
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.970
+Problem:    Syntax highlighting can be slow.
+Solution:   Include the NFA regexp engine.  Add the 'regexpengine' option to
+	    select which one is used. (various authors, including Ken Takata,
+	    Andrei Aiordachioaie, Russ Cox, Xiaozhou Liua, Ian Young)
+Files:	    src/Make_cyg.mak, src/Make_ming.mak, src/Make_mvc.mak,
+	    src/Makefile, src/regexp.c, src/regexp.h, src/regexp_nfa.c,
+	    src/structs.h, src/testdir/Makefile, src/testdir/test64.in,
+	    src/testdir/test64.ok, Filelist, runtime/doc/pattern.txt,
+	    runtime/doc/option.txt, src/option.c, src/option.h,
+	    src/testdir/test95.in, src/testdir/test95.ok,
+	    src/testdir/Make_amiga.mak, src/testdir/Make_dos.mak,
+	    src/testdir/Make_ming.mak, src/testdir/Make_os2.mak,
+	    src/testdir/Make_vms.mms
+
+
+*** ../vim-7.3.969/src/Make_cyg.mak	2013-05-06 04:21:35.000000000 +0200
+--- src/Make_cyg.mak	2013-05-17 18:54:19.000000000 +0200
+***************
+*** 672,677 ****
+--- 672,680 ----
+  $(OUTDIR)/netbeans.o:	netbeans.c $(INCL) $(NBDEBUG_DEP)
+  	$(CC) -c $(CFLAGS) netbeans.c -o $(OUTDIR)/netbeans.o
+  
++ $(OUTDIR)/regexp.o:		regexp.c regexp_nfa.c $(INCL)
++ 	$(CC) -c $(CFLAGS) regexp.c -o $(OUTDIR)/regexp.o
++ 
+  $(OUTDIR)/if_mzsch.o:	if_mzsch.c $(INCL) if_mzsch.h $(MZ_EXTRA_DEP)
+  	$(CC) -c $(CFLAGS) if_mzsch.c -o $(OUTDIR)/if_mzsch.o
+  
+*** ../vim-7.3.969/src/Make_ming.mak	2013-03-07 15:16:16.000000000 +0100
+--- src/Make_ming.mak	2013-05-17 18:54:19.000000000 +0200
+***************
+*** 765,770 ****
+--- 765,773 ----
+  $(OUTDIR)/netbeans.o:	netbeans.c $(INCL) $(NBDEBUG_INCL) $(NBDEBUG_SRC)
+  	$(CC) -c $(CFLAGS) netbeans.c -o $(OUTDIR)/netbeans.o
+  
++ $(OUTDIR)/regexp.o:		regexp.c regexp_nfa.c $(INCL)
++ 	$(CC) -c $(CFLAGS) regexp.c -o $(OUTDIR)/regexp.o
++ 
+  $(OUTDIR)/if_mzsch.o:	if_mzsch.c $(INCL) if_mzsch.h $(MZ_EXTRA_DEP)
+  	$(CC) -c $(CFLAGS) if_mzsch.c -o $(OUTDIR)/if_mzsch.o
+  
+*** ../vim-7.3.969/src/Make_mvc.mak	2013-05-07 05:11:12.000000000 +0200
+--- src/Make_mvc.mak	2013-05-19 16:38:29.000000000 +0200
+***************
+*** 1166,1172 ****
+  
+  $(OUTDIR)/quickfix.obj:	$(OUTDIR) quickfix.c  $(INCL)
+  
+! $(OUTDIR)/regexp.obj:	$(OUTDIR) regexp.c  $(INCL)
+  
+  $(OUTDIR)/screen.obj:	$(OUTDIR) screen.c  $(INCL)
+  
+--- 1173,1179 ----
+  
+  $(OUTDIR)/quickfix.obj:	$(OUTDIR) quickfix.c  $(INCL)
+  
+! $(OUTDIR)/regexp.obj:	$(OUTDIR) regexp.c regexp_nfa.c  $(INCL)
+  
+  $(OUTDIR)/screen.obj:	$(OUTDIR) screen.c  $(INCL)
+  
+*** ../vim-7.3.969/src/Makefile	2013-05-06 04:21:35.000000000 +0200
+--- src/Makefile	2013-05-18 23:42:30.000000000 +0200
+***************
+*** 454,460 ****
+  
+  # MULTIBYTE - To edit multi-byte characters.
+  # Uncomment this when you want to edit a multibyte language.
+! # It's automatically enabled with big features or IME support.
+  # Note: Compile on a machine where setlocale() actually works, otherwise the
+  # configure tests may fail.
+  #CONF_OPT_MULTIBYTE = --enable-multibyte
+--- 454,460 ----
+  
+  # MULTIBYTE - To edit multi-byte characters.
+  # Uncomment this when you want to edit a multibyte language.
+! # It's automatically enabled with normal features, GTK or IME support.
+  # Note: Compile on a machine where setlocale() actually works, otherwise the
+  # configure tests may fail.
+  #CONF_OPT_MULTIBYTE = --enable-multibyte
+***************
+*** 2664,2670 ****
+  objects/quickfix.o: quickfix.c
+  	$(CCC) -o $@ quickfix.c
+  
+! objects/regexp.o: regexp.c
+  	$(CCC) -o $@ regexp.c
+  
+  objects/screen.o: screen.c
+--- 2664,2670 ----
+  objects/quickfix.o: quickfix.c
+  	$(CCC) -o $@ quickfix.c
+  
+! objects/regexp.o: regexp.c regexp_nfa.c
+  	$(CCC) -o $@ regexp.c
+  
+  objects/screen.o: screen.c
+***************
+*** 2938,2947 ****
+   auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
+   regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
+   globals.h farsi.h arabic.h
+! objects/regexp.o: regexp.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
+!  ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
+!  gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
+!  arabic.h
+  objects/screen.o: screen.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
+   ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
+   gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
+--- 2938,2947 ----
+   auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
+   regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
+   globals.h farsi.h arabic.h
+! objects/regexp.o: regexp.c regexp_nfa.c vim.h auto/config.h feature.h os_unix.h \
+!  auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
+!  regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \
+!  globals.h farsi.h arabic.h
+  objects/screen.o: screen.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
+   ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
+   gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \
+*** ../vim-7.3.969/src/regexp.c	2013-03-19 17:42:10.000000000 +0100
+--- src/regexp.c	2013-05-18 19:47:06.000000000 +0200
+***************
+*** 38,46 ****
+   * Named character class support added by Walter Briscoe (1998 Jul 01)
+   */
+  
+  #include "vim.h"
+  
+! #undef DEBUG
+  
+  /*
+   * The "internal use only" fields in regexp.h are present to pass info from
+--- 38,57 ----
+   * Named character class support added by Walter Briscoe (1998 Jul 01)
+   */
+  
++ /* Uncomment the first if you do not want to see debugging logs or files
++  * related to regular expressions, even when compiling with -DDEBUG.
++  * Uncomment the second to get the regexp debugging. */
++ /* #undef DEBUG */
++ /* #define DEBUG */
++ 
+  #include "vim.h"
+  
+! #ifdef DEBUG
+! /* show/save debugging data when BT engine is used */
+! # define BT_REGEXP_DUMP
+! /* save the debugging data to a file instead of displaying it */
+! # define BT_REGEXP_LOG
+! #endif
+  
+  /*
+   * The "internal use only" fields in regexp.h are present to pass info from
+***************
+*** 326,334 ****
+  /* Used for an error (down from) vim_regcomp(): give the error message, set
+   * rc_did_emsg and return NULL */
+  #define EMSG_RET_NULL(m) return (EMSG(m), rc_did_emsg = TRUE, (void *)NULL)
+- #define EMSG_M_RET_NULL(m, c) return (EMSG2((m), (c) ? "" : "\\"), rc_did_emsg = TRUE, (void *)NULL)
+  #define EMSG_RET_FAIL(m) return (EMSG(m), rc_did_emsg = TRUE, FAIL)
+! #define EMSG_ONE_RET_NULL EMSG_M_RET_NULL(_("E369: invalid item in %s%%[]"), reg_magic == MAGIC_ALL)
+  
+  #define MAX_LIMIT	(32767L << 16L)
+  
+--- 337,346 ----
+  /* Used for an error (down from) vim_regcomp(): give the error message, set
+   * rc_did_emsg and return NULL */
+  #define EMSG_RET_NULL(m) return (EMSG(m), rc_did_emsg = TRUE, (void *)NULL)
+  #define EMSG_RET_FAIL(m) return (EMSG(m), rc_did_emsg = TRUE, FAIL)
+! #define EMSG2_RET_NULL(m, c) return (EMSG2((m), (c) ? "" : "\\"), rc_did_emsg = TRUE, (void *)NULL)
+! #define EMSG2_RET_FAIL(m, c) return (EMSG2((m), (c) ? "" : "\\"), rc_did_emsg = TRUE, FAIL)
+! #define EMSG_ONE_RET_NULL EMSG2_RET_NULL(_("E369: invalid item in %s%%[]"), reg_magic == MAGIC_ALL)
+  
+  #define MAX_LIMIT	(32767L << 16L)
+  
+***************
+*** 336,346 ****
+  static int cstrncmp __ARGS((char_u *s1, char_u *s2, int *n));
+  static char_u *cstrchr __ARGS((char_u *, int));
+  
+  #ifdef DEBUG
+- static void	regdump __ARGS((char_u *, regprog_T *));
+  static char_u	*regprop __ARGS((char_u *));
+  #endif
+  
+  #define NOT_MULTI	0
+  #define MULTI_ONE	1
+  #define MULTI_MULT	2
+--- 348,365 ----
+  static int cstrncmp __ARGS((char_u *s1, char_u *s2, int *n));
+  static char_u *cstrchr __ARGS((char_u *, int));
+  
++ #ifdef BT_REGEXP_DUMP
++ static void	regdump __ARGS((char_u *, bt_regprog_T *));
++ #endif
+  #ifdef DEBUG
+  static char_u	*regprop __ARGS((char_u *));
+  #endif
+  
++ static char_u e_missingbracket[] = N_("E769: Missing ] after %s[");
++ static char_u e_unmatchedpp[] = N_("E53: Unmatched %s%%(");
++ static char_u e_unmatchedp[] = N_("E54: Unmatched %s(");
++ static char_u e_unmatchedpar[] = N_("E55: Unmatched %s)");
++ 
+  #define NOT_MULTI	0
+  #define MULTI_ONE	1
+  #define MULTI_MULT	2
+***************
+*** 630,636 ****
+  };
+  #endif
+  
+! static int	curchr;
+  
+  /* arguments for reg() */
+  #define REG_NOPAREN	0	/* toplevel reg() */
+--- 649,661 ----
+  };
+  #endif
+  
+! static int	curchr;		/* currently parsed character */
+! /* Previous character.  Note: prevchr is sometimes -1 when we are not at the
+!  * start, eg in /[ ^I]^ the pattern was never found even if it existed,
+!  * because ^ was taken to be magic -- webb */
+! static int	prevchr;
+! static int	prevprevchr;	/* previous-previous character */
+! static int	nextchr;	/* used for ungetchr() */
+  
+  /* arguments for reg() */
+  #define REG_NOPAREN	0	/* toplevel reg() */
+***************
+*** 680,685 ****
+--- 705,713 ----
+  static void	regtail __ARGS((char_u *, char_u *));
+  static void	regoptail __ARGS((char_u *, char_u *));
+  
++ static regengine_T bt_regengine;
++ static regengine_T nfa_regengine;
++ 
+  /*
+   * Return TRUE if compiled regular expression "prog" can match a line break.
+   */
+***************
+*** 762,767 ****
+--- 790,796 ----
+  /*
+   * Produce the bytes for equivalence class "c".
+   * Currently only handles latin1, latin9 and utf-8.
++  * NOTE: When changing this function, also change nfa_emit_equi_class()
+   */
+      static void
+  reg_equi_class(c)
+***************
+*** 1239,1246 ****
+      return p;
+  }
+  
+  /*
+!  * vim_regcomp() - compile a regular expression into internal code
+   * Returns the program in allocated space.  Returns NULL for an error.
+   *
+   * We can't allocate space until we know how big the compiled form will be,
+--- 1268,1278 ----
+      return p;
+  }
+  
++ static regprog_T    *bt_regcomp __ARGS((char_u *expr, int re_flags));
++ 
+  /*
+!  * bt_regcomp() - compile a regular expression into internal code for the
+!  * traditional back track matcher.
+   * Returns the program in allocated space.  Returns NULL for an error.
+   *
+   * We can't allocate space until we know how big the compiled form will be,
+***************
+*** 1259,1270 ****
+   * of the structure of the compiled regexp.
+   * "re_flags": RE_MAGIC and/or RE_STRING.
+   */
+!     regprog_T *
+! vim_regcomp(expr, re_flags)
+      char_u	*expr;
+      int		re_flags;
+  {
+!     regprog_T	*r;
+      char_u	*scan;
+      char_u	*longest;
+      int		len;
+--- 1291,1302 ----
+   * of the structure of the compiled regexp.
+   * "re_flags": RE_MAGIC and/or RE_STRING.
+   */
+!     static regprog_T *
+! bt_regcomp(expr, re_flags)
+      char_u	*expr;
+      int		re_flags;
+  {
+!     bt_regprog_T    *r;
+      char_u	*scan;
+      char_u	*longest;
+      int		len;
+***************
+*** 1291,1297 ****
+  #endif
+  
+      /* Allocate space. */
+!     r = (regprog_T *)lalloc(sizeof(regprog_T) + regsize, TRUE);
+      if (r == NULL)
+  	return NULL;
+  
+--- 1323,1329 ----
+  #endif
+  
+      /* Allocate space. */
+!     r = (bt_regprog_T *)lalloc(sizeof(bt_regprog_T) + regsize, TRUE);
+      if (r == NULL)
+  	return NULL;
+  
+***************
+*** 1386,1395 ****
+  	    r->regmlen = len;
+  	}
+      }
+! #ifdef DEBUG
+      regdump(expr, r);
+  #endif
+!     return r;
+  }
+  
+  /*
+--- 1418,1428 ----
+  	    r->regmlen = len;
+  	}
+      }
+! #ifdef BT_REGEXP_DUMP
+      regdump(expr, r);
+  #endif
+!     r->engine = &bt_regengine;
+!     return (regprog_T *)r;
+  }
+  
+  /*
+***************
+*** 1436,1442 ****
+  #endif
+  
+  /*
+!  * reg - regular expression, i.e. main body or parenthesized thing
+   *
+   * Caller must absorb opening parenthesis.
+   *
+--- 1469,1475 ----
+  #endif
+  
+  /*
+!  * Parse regular expression, i.e. main body or parenthesized thing.
+   *
+   * Caller must absorb opening parenthesis.
+   *
+***************
+*** 1473,1479 ****
+      {
+  	/* Make a MOPEN node. */
+  	if (regnpar >= NSUBEXP)
+! 	    EMSG_M_RET_NULL(_("E51: Too many %s("), reg_magic == MAGIC_ALL);
+  	parno = regnpar;
+  	++regnpar;
+  	ret = regnode(MOPEN + parno);
+--- 1506,1512 ----
+      {
+  	/* Make a MOPEN node. */
+  	if (regnpar >= NSUBEXP)
+! 	    EMSG2_RET_NULL(_("E51: Too many %s("), reg_magic == MAGIC_ALL);
+  	parno = regnpar;
+  	++regnpar;
+  	ret = regnode(MOPEN + parno);
+***************
+*** 1534,1547 ****
+  	else
+  #endif
+  	    if (paren == REG_NPAREN)
+! 	    EMSG_M_RET_NULL(_("E53: Unmatched %s%%("), reg_magic == MAGIC_ALL);
+  	else
+! 	    EMSG_M_RET_NULL(_("E54: Unmatched %s("), reg_magic == MAGIC_ALL);
+      }
+      else if (paren == REG_NOPAREN && peekchr() != NUL)
+      {
+  	if (curchr == Magic(')'))
+! 	    EMSG_M_RET_NULL(_("E55: Unmatched %s)"), reg_magic == MAGIC_ALL);
+  	else
+  	    EMSG_RET_NULL(_(e_trailing));	/* "Can't happen". */
+  	/* NOTREACHED */
+--- 1567,1580 ----
+  	else
+  #endif
+  	    if (paren == REG_NPAREN)
+! 	    EMSG2_RET_NULL(_(e_unmatchedpp), reg_magic == MAGIC_ALL);
+  	else
+! 	    EMSG2_RET_NULL(_(e_unmatchedp), reg_magic == MAGIC_ALL);
+      }
+      else if (paren == REG_NOPAREN && peekchr() != NUL)
+      {
+  	if (curchr == Magic(')'))
+! 	    EMSG2_RET_NULL(_(e_unmatchedpar), reg_magic == MAGIC_ALL);
+  	else
+  	    EMSG_RET_NULL(_(e_trailing));	/* "Can't happen". */
+  	/* NOTREACHED */
+***************
+*** 1556,1562 ****
+  }
+  
+  /*
+!  * Handle one alternative of an | operator.
+   * Implements the & operator.
+   */
+      static char_u *
+--- 1589,1595 ----
+  }
+  
+  /*
+!  * Parse one alternative of an | operator.
+   * Implements the & operator.
+   */
+      static char_u *
+***************
+*** 1599,1605 ****
+  }
+  
+  /*
+!  * Handle one alternative of an | or & operator.
+   * Implements the concatenation operator.
+   */
+      static char_u *
+--- 1632,1638 ----
+  }
+  
+  /*
+!  * Parse one alternative of an | or & operator.
+   * Implements the concatenation operator.
+   */
+      static char_u *
+***************
+*** 1679,1685 ****
+  }
+  
+  /*
+!  * regpiece - something followed by possible [*+=]
+   *
+   * Note that the branching code sequences used for = and the general cases
+   * of * and + are somewhat optimized:  they use the same NOTHING node as
+--- 1712,1718 ----
+  }
+  
+  /*
+!  * Parse something followed by possible [*+=].
+   *
+   * Note that the branching code sequences used for = and the general cases
+   * of * and + are somewhat optimized:  they use the same NOTHING node as
+***************
+*** 1759,1765 ****
+  			      }
+  		}
+  		if (lop == END)
+! 		    EMSG_M_RET_NULL(_("E59: invalid character after %s@"),
+  						      reg_magic == MAGIC_ALL);
+  		/* Look behind must match with behind_pos. */
+  		if (lop == BEHIND || lop == NOBEHIND)
+--- 1792,1798 ----
+  			      }
+  		}
+  		if (lop == END)
+! 		    EMSG2_RET_NULL(_("E59: invalid character after %s@"),
+  						      reg_magic == MAGIC_ALL);
+  		/* Look behind must match with behind_pos. */
+  		if (lop == BEHIND || lop == NOBEHIND)
+***************
+*** 1793,1799 ****
+  	    else
+  	    {
+  		if (num_complex_braces >= 10)
+! 		    EMSG_M_RET_NULL(_("E60: Too many complex %s{...}s"),
+  						      reg_magic == MAGIC_ALL);
+  		reginsert(BRACE_COMPLEX + num_complex_braces, ret);
+  		regoptail(ret, regnode(BACK));
+--- 1826,1832 ----
+  	    else
+  	    {
+  		if (num_complex_braces >= 10)
+! 		    EMSG2_RET_NULL(_("E60: Too many complex %s{...}s"),
+  						      reg_magic == MAGIC_ALL);
+  		reginsert(BRACE_COMPLEX + num_complex_braces, ret);
+  		regoptail(ret, regnode(BACK));
+***************
+*** 1820,1827 ****
+      return ret;
+  }
+  
+  /*
+!  * regatom - the lowest level
+   *
+   * Optimization:  gobbles an entire sequence of ordinary characters so that
+   * it can turn them into a single node, which is smaller to store and
+--- 1853,1872 ----
+      return ret;
+  }
+  
++ /* When making changes to classchars also change nfa_classcodes. */
++ static char_u	*classchars = (char_u *)".iIkKfFpPsSdDxXoOwWhHaAlLuU";
++ static int	classcodes[] = {
++     ANY, IDENT, SIDENT, KWORD, SKWORD,
++     FNAME, SFNAME, PRINT, SPRINT,
++     WHITE, NWHITE, DIGIT, NDIGIT,
++     HEX, NHEX, OCTAL, NOCTAL,
++     WORD, NWORD, HEAD, NHEAD,
++     ALPHA, NALPHA, LOWER, NLOWER,
++     UPPER, NUPPER
++ };
++ 
+  /*
+!  * Parse the lowest level.
+   *
+   * Optimization:  gobbles an entire sequence of ordinary characters so that
+   * it can turn them into a single node, which is smaller to store and
+***************
+*** 1836,1850 ****
+      int		    cpo_lit;	    /* 'cpoptions' contains 'l' flag */
+      int		    cpo_bsl;	    /* 'cpoptions' contains '\' flag */
+      int		    c;
+-     static char_u   *classchars = (char_u *)".iIkKfFpPsSdDxXoOwWhHaAlLuU";
+-     static int	    classcodes[] = {ANY, IDENT, SIDENT, KWORD, SKWORD,
+- 				    FNAME, SFNAME, PRINT, SPRINT,
+- 				    WHITE, NWHITE, DIGIT, NDIGIT,
+- 				    HEX, NHEX, OCTAL, NOCTAL,
+- 				    WORD, NWORD, HEAD, NHEAD,
+- 				    ALPHA, NALPHA, LOWER, NLOWER,
+- 				    UPPER, NUPPER
+- 				    };
+      char_u	    *p;
+      int		    extra = 0;
+  
+--- 1881,1886 ----
+***************
+*** 2140,2146 ****
+  			      while ((c = getchr()) != ']')
+  			      {
+  				  if (c == NUL)
+! 				      EMSG_M_RET_NULL(_("E69: Missing ] after %s%%["),
+  						      reg_magic == MAGIC_ALL);
+  				  br = regnode(BRANCH);
+  				  if (ret == NULL)
+--- 2176,2182 ----
+  			      while ((c = getchr()) != ']')
+  			      {
+  				  if (c == NUL)
+! 				      EMSG2_RET_NULL(_("E69: Missing ] after %s%%["),
+  						      reg_magic == MAGIC_ALL);
+  				  br = regnode(BRANCH);
+  				  if (ret == NULL)
+***************
+*** 2156,2162 ****
+  				      return NULL;
+  			      }
+  			      if (ret == NULL)
+! 				  EMSG_M_RET_NULL(_("E70: Empty %s%%[]"),
+  						      reg_magic == MAGIC_ALL);
+  			      lastbranch = regnode(BRANCH);
+  			      br = regnode(NOTHING);
+--- 2192,2198 ----
+  				      return NULL;
+  			      }
+  			      if (ret == NULL)
+! 				  EMSG2_RET_NULL(_("E70: Empty %s%%[]"),
+  						      reg_magic == MAGIC_ALL);
+  			      lastbranch = regnode(BRANCH);
+  			      br = regnode(NOTHING);
+***************
+*** 2200,2206 ****
+  			      }
+  
+  			      if (i < 0)
+! 				  EMSG_M_RET_NULL(
+  					_("E678: Invalid character after %s%%[dxouU]"),
+  					reg_magic == MAGIC_ALL);
+  #ifdef FEAT_MBYTE
+--- 2236,2242 ----
+  			      }
+  
+  			      if (i < 0)
+! 				  EMSG2_RET_NULL(
+  					_("E678: Invalid character after %s%%[dxouU]"),
+  					reg_magic == MAGIC_ALL);
+  #ifdef FEAT_MBYTE
+***************
+*** 2272,2278 ****
+  			      }
+  			  }
+  
+! 			  EMSG_M_RET_NULL(_("E71: Invalid character after %s%%"),
+  						      reg_magic == MAGIC_ALL);
+  	    }
+  	}
+--- 2308,2314 ----
+  			      }
+  			  }
+  
+! 			  EMSG2_RET_NULL(_("E71: Invalid character after %s%%"),
+  						      reg_magic == MAGIC_ALL);
+  	    }
+  	}
+***************
+*** 2567,2574 ****
+  		break;
+  	    }
+  	    else if (reg_strict)
+! 		EMSG_M_RET_NULL(_("E769: Missing ] after %s["),
+! 						       reg_magic > MAGIC_OFF);
+  	}
+  	/* FALLTHROUGH */
+  
+--- 2603,2609 ----
+  		break;
+  	    }
+  	    else if (reg_strict)
+! 		EMSG2_RET_NULL(_(e_missingbracket), reg_magic > MAGIC_OFF);
+  	}
+  	/* FALLTHROUGH */
+  
+***************
+*** 2659,2665 ****
+  #endif
+  
+  /*
+!  * emit a node
+   * Return pointer to generated code.
+   */
+      static char_u *
+--- 2694,2700 ----
+  #endif
+  
+  /*
+!  * Emit a node.
+   * Return pointer to generated code.
+   */
+      static char_u *
+***************
+*** 2711,2717 ****
+  #endif
+  
+  /*
+!  * reginsert - insert an operator in front of already-emitted operand
+   *
+   * Means relocating the operand.
+   */
+--- 2746,2752 ----
+  #endif
+  
+  /*
+!  * Insert an operator in front of already-emitted operand
+   *
+   * Means relocating the operand.
+   */
+***************
+*** 2742,2748 ****
+  }
+  
+  /*
+!  * reginsert_limits - insert an operator in front of already-emitted operand.
+   * The operator has the given limit values as operands.  Also set next pointer.
+   *
+   * Means relocating the operand.
+--- 2777,2783 ----
+  }
+  
+  /*
+!  * Insert an operator in front of already-emitted operand.
+   * The operator has the given limit values as operands.  Also set next pointer.
+   *
+   * Means relocating the operand.
+***************
+*** 2794,2800 ****
+  }
+  
+  /*
+!  * regtail - set the next-pointer at the end of a node chain
+   */
+      static void
+  regtail(p, val)
+--- 2829,2835 ----
+  }
+  
+  /*
+!  * Set the next-pointer at the end of a node chain.
+   */
+      static void
+  regtail(p, val)
+***************
+*** 2835,2841 ****
+  }
+  
+  /*
+!  * regoptail - regtail on item after a BRANCH; nop if none
+   */
+      static void
+  regoptail(p, val)
+--- 2870,2876 ----
+  }
+  
+  /*
+!  * Like regtail, on item after a BRANCH; nop if none.
+   */
+      static void
+  regoptail(p, val)
+***************
+*** 2851,2872 ****
+  }
+  
+  /*
+!  * getchr() - get the next character from the pattern. We know about
+!  * magic and such, so therefore we need a lexical analyzer.
+   */
+  
+- /* static int	    curchr; */
+- static int	prevprevchr;
+- static int	prevchr;
+- static int	nextchr;    /* used for ungetchr() */
+- /*
+-  * Note: prevchr is sometimes -1 when we are not at the start,
+-  * eg in /[ ^I]^ the pattern was never found even if it existed, because ^ was
+-  * taken to be magic -- webb
+-  */
+  static int	at_start;	/* True when on the first character */
+  static int	prev_at_start;  /* True when on the second character */
+  
+      static void
+  initchr(str)
+      char_u *str;
+--- 2886,2900 ----
+  }
+  
+  /*
+!  * Functions for getting characters from the regexp input.
+   */
+  
+  static int	at_start;	/* True when on the first character */
+  static int	prev_at_start;  /* True when on the second character */
+  
++ /*
++  * Start parsing at "str".
++  */
+      static void
+  initchr(str)
+      char_u *str;
+***************
+*** 2878,2883 ****
+--- 2906,2914 ----
+      prev_at_start = FALSE;
+  }
+  
++ /*
++  * Get the next character without advancing.
++  */
+      static int
+  peekchr()
+  {
+***************
+*** 3086,3091 ****
+--- 3117,3126 ----
+      prevprevchr = prpr;
+  }
+  
++ /*
++  * Get the next character from the pattern. We know about magic and such, so
++  * therefore we need a lexical analyzer.
++  */
+      static int
+  getchr()
+  {
+***************
+*** 3340,3347 ****
+  } regbehind_T;
+  
+  static char_u	*reg_getline __ARGS((linenr_T lnum));
+! static long	vim_regexec_both __ARGS((char_u *line, colnr_T col, proftime_T *tm));
+! static long	regtry __ARGS((regprog_T *prog, colnr_T col));
+  static void	cleanup_subexpr __ARGS((void));
+  #ifdef FEAT_SYN_HL
+  static void	cleanup_zsubexpr __ARGS((void));
+--- 3375,3382 ----
+  } regbehind_T;
+  
+  static char_u	*reg_getline __ARGS((linenr_T lnum));
+! static long	bt_regexec_both __ARGS((char_u *line, colnr_T col, proftime_T *tm));
+! static long	regtry __ARGS((bt_regprog_T *prog, colnr_T col));
+  static void	cleanup_subexpr __ARGS((void));
+  #ifdef FEAT_SYN_HL
+  static void	cleanup_zsubexpr __ARGS((void));
+***************
+*** 3398,3404 ****
+  /*
+   * Sometimes need to save a copy of a line.  Since alloc()/free() is very
+   * slow, we keep one allocated piece of memory and only re-allocate it when
+!  * it's too small.  It's freed in vim_regexec_both() when finished.
+   */
+  static char_u	*reg_tofree = NULL;
+  static unsigned	reg_tofreelen;
+--- 3433,3439 ----
+  /*
+   * Sometimes need to save a copy of a line.  Since alloc()/free() is very
+   * slow, we keep one allocated piece of memory and only re-allocate it when
+!  * it's too small.  It's freed in bt_regexec_both() when finished.
+   */
+  static char_u	*reg_tofree = NULL;
+  static unsigned	reg_tofreelen;
+***************
+*** 3556,3561 ****
+--- 3591,3598 ----
+  /* TRUE if using multi-line regexp. */
+  #define REG_MULTI	(reg_match == NULL)
+  
++ static int  bt_regexec __ARGS((regmatch_T *rmp, char_u *line, colnr_T col));
++ 
+  /*
+   * Match a regexp against a string.
+   * "rmp->regprog" is a compiled regexp as returned by vim_regcomp().
+***************
+*** 3563,3570 ****
+   *
+   * Return TRUE if there is a match, FALSE if not.
+   */
+!     int
+! vim_regexec(rmp, line, col)
+      regmatch_T	*rmp;
+      char_u	*line;	/* string to match against */
+      colnr_T	col;	/* column to start looking for match */
+--- 3600,3607 ----
+   *
+   * Return TRUE if there is a match, FALSE if not.
+   */
+!     static int
+! bt_regexec(rmp, line, col)
+      regmatch_T	*rmp;
+      char_u	*line;	/* string to match against */
+      colnr_T	col;	/* column to start looking for match */
+***************
+*** 3580,3595 ****
+      ireg_icombine = FALSE;
+  #endif
+      ireg_maxcol = 0;
+!     return (vim_regexec_both(line, col, NULL) != 0);
+  }
+  
+  #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) \
+  	|| defined(FIND_REPLACE_DIALOG) || defined(PROTO)
+  /*
+   * Like vim_regexec(), but consider a "\n" in "line" to be a line break.
+   */
+!     int
+! vim_regexec_nl(rmp, line, col)
+      regmatch_T	*rmp;
+      char_u	*line;	/* string to match against */
+      colnr_T	col;	/* column to start looking for match */
+--- 3617,3635 ----
+      ireg_icombine = FALSE;
+  #endif
+      ireg_maxcol = 0;
+!     return (bt_regexec_both(line, col, NULL) != 0);
+  }
+  
+  #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) \
+  	|| defined(FIND_REPLACE_DIALOG) || defined(PROTO)
++ 
++ static int  bt_regexec_nl __ARGS((regmatch_T *rmp, char_u *line, colnr_T col));
++ 
+  /*
+   * Like vim_regexec(), but consider a "\n" in "line" to be a line break.
+   */
+!     static int
+! bt_regexec_nl(rmp, line, col)
+      regmatch_T	*rmp;
+      char_u	*line;	/* string to match against */
+      colnr_T	col;	/* column to start looking for match */
+***************
+*** 3605,3614 ****
+      ireg_icombine = FALSE;
+  #endif
+      ireg_maxcol = 0;
+!     return (vim_regexec_both(line, col, NULL) != 0);
+  }
+  #endif
+  
+  /*
+   * Match a regexp against multiple lines.
+   * "rmp->regprog" is a compiled regexp as returned by vim_regcomp().
+--- 3645,3656 ----
+      ireg_icombine = FALSE;
+  #endif
+      ireg_maxcol = 0;
+!     return (bt_regexec_both(line, col, NULL) != 0);
+  }
+  #endif
+  
++ static long bt_regexec_multi __ARGS((regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm));
++ 
+  /*
+   * Match a regexp against multiple lines.
+   * "rmp->regprog" is a compiled regexp as returned by vim_regcomp().
+***************
+*** 3617,3624 ****
+   * Return zero if there is no match.  Return number of lines contained in the
+   * match otherwise.
+   */
+!     long
+! vim_regexec_multi(rmp, win, buf, lnum, col, tm)
+      regmmatch_T	*rmp;
+      win_T	*win;		/* window in which to search or NULL */
+      buf_T	*buf;		/* buffer in which to search */
+--- 3659,3666 ----
+   * Return zero if there is no match.  Return number of lines contained in the
+   * match otherwise.
+   */
+!     static long
+! bt_regexec_multi(rmp, win, buf, lnum, col, tm)
+      regmmatch_T	*rmp;
+      win_T	*win;		/* window in which to search or NULL */
+      buf_T	*buf;		/* buffer in which to search */
+***************
+*** 3641,3647 ****
+  #endif
+      ireg_maxcol = rmp->rmm_maxcol;
+  
+!     r = vim_regexec_both(NULL, col, tm);
+  
+      return r;
+  }
+--- 3683,3689 ----
+  #endif
+      ireg_maxcol = rmp->rmm_maxcol;
+  
+!     r = bt_regexec_both(NULL, col, tm);
+  
+      return r;
+  }
+***************
+*** 3651,3662 ****
+   * lines ("line" is NULL, use reg_getline()).
+   */
+      static long
+! vim_regexec_both(line, col, tm)
+      char_u	*line;
+      colnr_T	col;		/* column to start looking for match */
+      proftime_T	*tm UNUSED;	/* timeout limit or NULL */
+  {
+!     regprog_T	*prog;
+      char_u	*s;
+      long	retval = 0L;
+  
+--- 3693,3704 ----
+   * lines ("line" is NULL, use reg_getline()).
+   */
+      static long
+! bt_regexec_both(line, col, tm)
+      char_u	*line;
+      colnr_T	col;		/* column to start looking for match */
+      proftime_T	*tm UNUSED;	/* timeout limit or NULL */
+  {
+!     bt_regprog_T	*prog;
+      char_u	*s;
+      long	retval = 0L;
+  
+***************
+*** 3682,3695 ****
+  
+      if (REG_MULTI)
+      {
+! 	prog = reg_mmatch->regprog;
+  	line = reg_getline((linenr_T)0);
+  	reg_startpos = reg_mmatch->startpos;
+  	reg_endpos = reg_mmatch->endpos;
+      }
+      else
+      {
+! 	prog = reg_match->regprog;
+  	reg_startp = reg_match->startp;
+  	reg_endp = reg_match->endp;
+      }
+--- 3724,3737 ----
+  
+      if (REG_MULTI)
+      {
+! 	prog = (bt_regprog_T *)reg_mmatch->regprog;
+  	line = reg_getline((linenr_T)0);
+  	reg_startpos = reg_mmatch->startpos;
+  	reg_endpos = reg_mmatch->endpos;
+      }
+      else
+      {
+! 	prog = (bt_regprog_T *)reg_match->regprog;
+  	reg_startp = reg_match->startp;
+  	reg_endp = reg_match->endp;
+      }
+***************
+*** 3931,3937 ****
+   */
+      static long
+  regtry(prog, col)
+!     regprog_T	*prog;
+      colnr_T	col;
+  {
+      reginput = regline + col;
+--- 3973,3979 ----
+   */
+      static long
+  regtry(prog, col)
+!     bt_regprog_T    *prog;
+      colnr_T	col;
+  {
+      reginput = regline + col;
+***************
+*** 4063,4069 ****
+  #define RA_NOMATCH	5	/* didn't match */
+  
+    /* Make "regstack" and "backpos" empty.  They are allocated and freed in
+!    * vim_regexec_both() to reduce malloc()/free() calls. */
+    regstack.ga_len = 0;
+    backpos.ga_len = 0;
+  
+--- 4105,4111 ----
+  #define RA_NOMATCH	5	/* didn't match */
+  
+    /* Make "regstack" and "backpos" empty.  They are allocated and freed in
+!    * bt_regexec_both() to reduce malloc()/free() calls. */
+    regstack.ga_len = 0;
+    backpos.ga_len = 0;
+  
+***************
+*** 4072,4085 ****
+     */
+    for (;;)
+    {
+!     /* Some patterns my cause a long time to match, even though they are not
+       * illegal.  E.g., "\([a-z]\+\)\+Q".  Allow breaking them with CTRL-C. */
+      fast_breakcheck();
+  
+  #ifdef DEBUG
+      if (scan != NULL && regnarrate)
+      {
+! 	mch_errmsg(regprop(scan));
+  	mch_errmsg("(\n");
+      }
+  #endif
+--- 4114,4127 ----
+     */
+    for (;;)
+    {
+!     /* Some patterns may cause a long time to match, even though they are not
+       * illegal.  E.g., "\([a-z]\+\)\+Q".  Allow breaking them with CTRL-C. */
+      fast_breakcheck();
+  
+  #ifdef DEBUG
+      if (scan != NULL && regnarrate)
+      {
+! 	mch_errmsg((char *)regprop(scan));
+  	mch_errmsg("(\n");
+      }
+  #endif
+***************
+*** 4100,4106 ****
+  #ifdef DEBUG
+  	if (regnarrate)
+  	{
+! 	    mch_errmsg(regprop(scan));
+  	    mch_errmsg("...\n");
+  # ifdef FEAT_SYN_HL
+  	    if (re_extmatch_in != NULL)
+--- 4142,4148 ----
+  #ifdef DEBUG
+  	if (regnarrate)
+  	{
+! 	    mch_errmsg((char *)regprop(scan));
+  	    mch_errmsg("...\n");
+  # ifdef FEAT_SYN_HL
+  	    if (re_extmatch_in != NULL)
+***************
+*** 4112,4118 ****
+  		{
+  		    mch_errmsg("    \"");
+  		    if (re_extmatch_in->matches[i] != NULL)
+! 			mch_errmsg(re_extmatch_in->matches[i]);
+  		    mch_errmsg("\"\n");
+  		}
+  	    }
+--- 4154,4160 ----
+  		{
+  		    mch_errmsg("    \"");
+  		    if (re_extmatch_in->matches[i] != NULL)
+! 			mch_errmsg((char *)re_extmatch_in->matches[i]);
+  		    mch_errmsg("\"\n");
+  		}
+  	    }
+***************
+*** 6091,6099 ****
+      static int
+  prog_magic_wrong()
+  {
+!     if (UCHARAT(REG_MULTI
+! 		? reg_mmatch->regprog->program
+! 		: reg_match->regprog->program) != REGMAGIC)
+      {
+  	EMSG(_(e_re_corr));
+  	return TRUE;
+--- 6133,6146 ----
+      static int
+  prog_magic_wrong()
+  {
+!     regprog_T	*prog;
+! 
+!     prog = REG_MULTI ? reg_mmatch->regprog : reg_match->regprog;
+!     if (prog->engine == &nfa_regengine)
+! 	/* For NFA matcher we don't check the magic */
+! 	return FALSE;
+! 
+!     if (UCHARAT(((bt_regprog_T *)prog)->program) != REGMAGIC)
+      {
+  	EMSG(_(e_re_corr));
+  	return TRUE;
+***************
+*** 6318,6324 ****
+  }
+  
+  
+! #ifdef DEBUG
+  
+  /*
+   * regdump - dump a regexp onto stdout in vaguely comprehensible form
+--- 6365,6371 ----
+  }
+  
+  
+! #ifdef BT_REGEXP_DUMP
+  
+  /*
+   * regdump - dump a regexp onto stdout in vaguely comprehensible form
+***************
+*** 6326,6339 ****
+      static void
+  regdump(pattern, r)
+      char_u	*pattern;
+!     regprog_T	*r;
+  {
+      char_u  *s;
+      int	    op = EXACTLY;	/* Arbitrary non-END op. */
+      char_u  *next;
+      char_u  *end = NULL;
+  
+!     printf("\r\nregcomp(%s):\r\n", pattern);
+  
+      s = r->program + 1;
+      /*
+--- 6373,6394 ----
+      static void
+  regdump(pattern, r)
+      char_u	*pattern;
+!     bt_regprog_T	*r;
+  {
+      char_u  *s;
+      int	    op = EXACTLY;	/* Arbitrary non-END op. */
+      char_u  *next;
+      char_u  *end = NULL;
++     FILE    *f;
+  
+! #ifdef BT_REGEXP_LOG
+!     f = fopen("bt_regexp_log.log", "a");
+! #else
+!     f = stdout;
+! #endif
+!     if (f == NULL)
+! 	return;
+!     fprintf(f, "-------------------------------------\n\r\nregcomp(%s):\r\n", pattern);
+  
+      s = r->program + 1;
+      /*
+***************
+*** 6343,6360 ****
+      while (op != END || s <= end)
+      {
+  	op = OP(s);
+! 	printf("%2d%s", (int)(s - r->program), regprop(s)); /* Where, what. */
+  	next = regnext(s);
+  	if (next == NULL)	/* Next ptr. */
+! 	    printf("(0)");
+  	else
+! 	    printf("(%d)", (int)((s - r->program) + (next - s)));
+  	if (end < next)
+  	    end = next;
+  	if (op == BRACE_LIMITS)
+  	{
+  	    /* Two short ints */
+! 	    printf(" minval %ld, maxval %ld", OPERAND_MIN(s), OPERAND_MAX(s));
+  	    s += 8;
+  	}
+  	s += 3;
+--- 6398,6415 ----
+      while (op != END || s <= end)
+      {
+  	op = OP(s);
+! 	fprintf(f, "%2d%s", (int)(s - r->program), regprop(s)); /* Where, what. */
+  	next = regnext(s);
+  	if (next == NULL)	/* Next ptr. */
+! 	    fprintf(f, "(0)");
+  	else
+! 	    fprintf(f, "(%d)", (int)((s - r->program) + (next - s)));
+  	if (end < next)
+  	    end = next;
+  	if (op == BRACE_LIMITS)
+  	{
+  	    /* Two short ints */
+! 	    fprintf(f, " minval %ld, maxval %ld", OPERAND_MIN(s), OPERAND_MAX(s));
+  	    s += 8;
+  	}
+  	s += 3;
+***************
+*** 6363,6387 ****
+  		|| op == EXACTLY)
+  	{
+  	    /* Literal string, where present. */
+  	    while (*s != NUL)
+! 		printf("%c", *s++);
+  	    s++;
+  	}
+! 	printf("\r\n");
+      }
+  
+      /* Header fields of interest. */
+      if (r->regstart != NUL)
+! 	printf("start `%s' 0x%x; ", r->regstart < 256
+  		? (char *)transchar(r->regstart)
+  		: "multibyte", r->regstart);
+      if (r->reganch)
+! 	printf("anchored; ");
+      if (r->regmust != NULL)
+! 	printf("must have \"%s\"", r->regmust);
+!     printf("\r\n");
+  }
+  
+  /*
+   * regprop - printable representation of opcode
+   */
+--- 6418,6450 ----
+  		|| op == EXACTLY)
+  	{
+  	    /* Literal string, where present. */
++ 	    fprintf(f, "\nxxxxxxxxx\n");
+  	    while (*s != NUL)
+! 		fprintf(f, "%c", *s++);
+! 	    fprintf(f, "\nxxxxxxxxx\n");
+  	    s++;
+  	}
+! 	fprintf(f, "\r\n");
+      }
+  
+      /* Header fields of interest. */
+      if (r->regstart != NUL)
+! 	fprintf(f, "start `%s' 0x%x; ", r->regstart < 256
+  		? (char *)transchar(r->regstart)
+  		: "multibyte", r->regstart);
+      if (r->reganch)
+! 	fprintf(f, "anchored; ");
+      if (r->regmust != NULL)
+! 	fprintf(f, "must have \"%s\"", r->regmust);
+!     fprintf(f, "\r\n");
+! 
+! #ifdef BT_REGEXP_LOG
+!     fclose(f);
+! #endif
+  }
++ #endif	    /* BT_REGEXP_DUMP */
+  
++ #ifdef DEBUG
+  /*
+   * regprop - printable representation of opcode
+   */
+***************
+*** 6389,6400 ****
+  regprop(op)
+      char_u	   *op;
+  {
+!     char_u	    *p;
+!     static char_u   buf[50];
+  
+!     (void) strcpy(buf, ":");
+  
+!     switch (OP(op))
+      {
+        case BOL:
+  	p = "BOL";
+--- 6452,6463 ----
+  regprop(op)
+      char_u	   *op;
+  {
+!     char	    *p;
+!     static char	    buf[50];
+  
+!     STRCPY(buf, ":");
+  
+!     switch ((int) OP(op))
+      {
+        case BOL:
+  	p = "BOL";
+***************
+*** 6761,6770 ****
+  	break;
+      }
+      if (p != NULL)
+! 	(void) strcat(buf, p);
+!     return buf;
+  }
+! #endif
+  
+  #ifdef FEAT_MBYTE
+  static void mb_decompose __ARGS((int c, int *c1, int *c2, int *c3));
+--- 6824,6833 ----
+  	break;
+      }
+      if (p != NULL)
+! 	STRCAT(buf, p);
+!     return (char_u *)buf;
+  }
+! #endif	    /* DEBUG */
+  
+  #ifdef FEAT_MBYTE
+  static void mb_decompose __ARGS((int c, int *c1, int *c2, int *c3));
+***************
+*** 7667,7669 ****
+--- 7730,7916 ----
+      return retval;
+  }
+  #endif
++ 
++ static regengine_T bt_regengine =
++ {
++     bt_regcomp,
++     bt_regexec,
++ #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) \
++ 	|| defined(FIND_REPLACE_DIALOG) || defined(PROTO)
++     bt_regexec_nl,
++ #endif
++     bt_regexec_multi
++ #ifdef DEBUG
++     ,(char_u *)""
++ #endif
++ };
++ 
++ 
++ #include "regexp_nfa.c"
++ 
++ static regengine_T nfa_regengine =
++ {
++     nfa_regcomp,
++     nfa_regexec,
++ #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) \
++ 	|| defined(FIND_REPLACE_DIALOG) || defined(PROTO)
++     nfa_regexec_nl,
++ #endif
++     nfa_regexec_multi
++ #ifdef DEBUG
++     ,(char_u *)""
++ #endif
++ };
++ 
++ /* Which regexp engine to use? Needed for vim_regcomp().
++  * Must match with 'regexpengine'. */
++ static int regexp_engine = 0;
++ #define	    AUTOMATIC_ENGINE	0
++ #define	    BACKTRACKING_ENGINE	1
++ #define	    NFA_ENGINE		2
++ #ifdef DEBUG
++ static char_u regname[][30] = {
++ 		    "AUTOMATIC Regexp Engine",
++ 		    "BACKTACKING Regexp Engine",
++ 		    "NFA Regexp Engine"
++ 			    };
++ #endif
++ 
++ /*
++  * Compile a regular expression into internal code.
++  * Returns the program in allocated memory.  Returns NULL for an error.
++  */
++     regprog_T *
++ vim_regcomp(expr_arg, re_flags)
++     char_u	*expr_arg;
++     int		re_flags;
++ {
++     regprog_T   *prog = NULL;
++     char_u	*expr = expr_arg;
++ 
++     syntax_error = FALSE;
++     regexp_engine = p_re;
++ 
++     /* Check for prefix "\%#=", that sets the regexp engine */
++     if (STRNCMP(expr, "\\%#=", 4) == 0)
++     {
++ 	int newengine = expr[4] - '0';
++ 
++ 	if (newengine == AUTOMATIC_ENGINE
++ 	    || newengine == BACKTRACKING_ENGINE
++ 	    || newengine == NFA_ENGINE)
++ 	{
++ 	    regexp_engine = expr[4] - '0';
++ 	    expr += 5;
++ #ifdef DEBUG
++ 	    EMSG3("New regexp mode selected (%d): %s", regexp_engine,
++ 						    regname[newengine]);
++ #endif
++ 	}
++ 	else
++ 	{
++ 	    EMSG(_("E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be used "));
++ 	    regexp_engine = AUTOMATIC_ENGINE;
++ 	}
++     }
++ #ifdef DEBUG
++     bt_regengine.expr = expr;
++     nfa_regengine.expr = expr;
++ #endif
++ 
++     /*
++      * First try the NFA engine, unless backtracking was requested.
++      */
++     if (regexp_engine != BACKTRACKING_ENGINE)
++         prog = nfa_regengine.regcomp(expr, re_flags);
++     else
++ 	prog = bt_regengine.regcomp(expr, re_flags);
++ 
++     if (prog == NULL)	    /* error compiling regexp with initial engine */
++     {
++ #ifdef DEBUG
++ 	if (regexp_engine != BACKTRACKING_ENGINE)   /* debugging log for NFA */
++ 	{
++ 	    FILE *f;
++ 	    f = fopen("debug.log", "a");
++ 	    if (f)
++ 	    {
++ 		if (!syntax_error)
++ 		    fprintf(f, "NFA engine could not handle \"%s\"\n", expr);
++ 		else
++ 		    fprintf(f, "Syntax error in \"%s\"\n", expr);
++ 		fclose(f);
++ 	    }
++ 	    else
++ 		EMSG("(NFA) Could not open \"debug.log\" to write !!!");
++ 	    /*
++ 	    if (syntax_error)
++ 		EMSG("NFA Regexp: Syntax Error !");
++ 	    */
++ 	}
++ #endif
++ 	/*
++ 	 * If NFA engine failed, then revert to the backtracking engine.
++ 	 * Except when there was a syntax error, which was properly handled by
++ 	 * NFA engine.
++ 	 */
++ 	if (regexp_engine == AUTOMATIC_ENGINE)
++ 	    if (!syntax_error)
++ 		prog = bt_regengine.regcomp(expr, re_flags);
++ 
++     }	    /* endif prog==NULL */
++ 
++ 
++     return prog;
++ }
++ 
++ /*
++  * Match a regexp against a string.
++  * "rmp->regprog" is a compiled regexp as returned by vim_regcomp().
++  * Uses curbuf for line count and 'iskeyword'.
++  *
++  * Return TRUE if there is a match, FALSE if not.
++  */
++     int
++ vim_regexec(rmp, line, col)
++     regmatch_T *rmp;
++     char_u      *line;  /* string to match against */
++     colnr_T     col;    /* column to start looking for match */
++ {
++     return rmp->regprog->engine->regexec(rmp, line, col);
++ }
++ 
++ #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) \
++ 	|| defined(FIND_REPLACE_DIALOG) || defined(PROTO)
++ /*
++  * Like vim_regexec(), but consider a "\n" in "line" to be a line break.
++  */
++     int
++ vim_regexec_nl(rmp, line, col)
++     regmatch_T *rmp;
++     char_u *line;
++     colnr_T col;
++ {
++     return rmp->regprog->engine->regexec_nl(rmp, line, col);
++ }
++ #endif
++ 
++ /*
++  * Match a regexp against multiple lines.
++  * "rmp->regprog" is a compiled regexp as returned by vim_regcomp().
++  * Uses curbuf for line count and 'iskeyword'.
++  *
++  * Return zero if there is no match.  Return number of lines contained in the
++  * match otherwise.
++  */
++     long
++ vim_regexec_multi(rmp, win, buf, lnum, col, tm)
++     regmmatch_T *rmp;
++     win_T       *win;           /* window in which to search or NULL */
++     buf_T       *buf;           /* buffer in which to search */
++     linenr_T    lnum;           /* nr of line to start looking for match */
++     colnr_T     col;            /* column to start looking for match */
++     proftime_T	*tm;		/* timeout limit or NULL */
++ {
++     return rmp->regprog->engine->regexec_multi(rmp, win, buf, lnum, col, tm);
++ }
+*** ../vim-7.3.969/src/regexp.h	2010-08-15 21:57:27.000000000 +0200
+--- src/regexp.h	2013-05-18 17:24:42.000000000 +0200
+***************
+*** 22,41 ****
+  #define NSUBEXP  10
+  
+  /*
+   * Structure returned by vim_regcomp() to pass on to vim_regexec().
+   * These fields are only to be used in regexp.c!
+!  * See regep.c for an explanation.
+   */
+  typedef struct
+  {
+      int			regstart;
+      char_u		reganch;
+      char_u		*regmust;
+      int			regmlen;
+-     unsigned		regflags;
+      char_u		reghasz;
+!     char_u		program[1];		/* actually longer.. */
+! } regprog_T;
+  
+  /*
+   * Structure to be used for single-line matching.
+--- 22,97 ----
+  #define NSUBEXP  10
+  
+  /*
++  * In the NFA engine: how many braces are allowed.
++  * TODO(RE): Use dynamic memory allocation instead of static, like here
++  */
++ #define NFA_MAX_BRACES 20
++ 
++ typedef struct regengine regengine_T;
++ 
++ typedef struct thread thread_T;
++ 
++ /*
+   * Structure returned by vim_regcomp() to pass on to vim_regexec().
++  * This is the general structure. For the actual matcher, two specific
++  * structures are used. See code below.
++  */
++ typedef struct regprog
++ {
++     regengine_T		*engine;
++     unsigned		regflags;
++ } regprog_T;
++ 
++ /*
++  * Structure used by the back track matcher.
+   * These fields are only to be used in regexp.c!
+!  * See regexp.c for an explanation.
+   */
+  typedef struct
+  {
++     /* These two members implement regprog_T */
++     regengine_T		*engine;
++     unsigned		regflags;
++ 
+      int			regstart;
+      char_u		reganch;
+      char_u		*regmust;
+      int			regmlen;
+      char_u		reghasz;
+!     char_u		program[1];	/* actually longer.. */
+! } bt_regprog_T;
+! 
+! /*
+!  * Structure representing a NFA state.
+!  * A NFA state may have no outgoing edge, when it is a NFA_MATCH state.
+!  */
+! typedef struct nfa_state nfa_state_T;
+! struct nfa_state
+! {
+!     int			c;
+!     nfa_state_T		*out;
+!     nfa_state_T		*out1;
+!     int			id;
+!     int			lastlist;
+!     int			visits;
+!     thread_T		*lastthread;
+!     int			negated;
+! };
+! 
+! /*
+!  * Structure used by the NFA matcher.
+!  */
+! typedef struct
+! {
+!     /* These two members implement regprog_T */
+!     regengine_T		*engine;
+!     unsigned		regflags;
+! 
+!     regprog_T		regprog;
+!     nfa_state_T		*start;
+!     int			nstate;
+!     nfa_state_T		state[0];	/* actually longer.. */
+! } nfa_regprog_T;
+  
+  /*
+   * Structure to be used for single-line matching.
+***************
+*** 78,81 ****
+--- 134,151 ----
+      char_u		*matches[NSUBEXP];
+  } reg_extmatch_T;
+  
++ struct regengine
++ {
++     regprog_T	*(*regcomp)(char_u*, int);
++     int		(*regexec)(regmatch_T*, char_u*, colnr_T);
++ #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) \
++ 	|| defined(FIND_REPLACE_DIALOG) || defined(PROTO)
++     int		(*regexec_nl)(regmatch_T*, char_u*, colnr_T);
++ #endif
++     long	(*regexec_multi)(regmmatch_T*, win_T*, buf_T*, linenr_T, colnr_T, proftime_T*);
++ #ifdef DEBUG
++     char_u	*expr;
++ #endif
++ };
++ 
+  #endif	/* _REGEXP_H */
+*** ../vim-7.3.969/src/regexp_nfa.c	2013-05-19 19:10:10.000000000 +0200
+--- src/regexp_nfa.c	2013-05-19 16:08:09.000000000 +0200
+***************
+*** 0 ****
+--- 1,3819 ----
++ /* vi:set ts=8 sts=4 sw=4:
++  *
++  * NFA regular expression implementation.
++  *
++  * This file is included in "regexp.c".
++  */
++ 
++ #ifdef DEBUG
++ /* Comment this out to disable log files. They can get pretty big */
++ # define ENABLE_LOG
++ # define LOG_NAME "log_nfarun.log"
++ #endif
++ 
++ /* Upper limit allowed for {m,n} repetitions handled by NFA */
++ #define	    NFA_BRACES_MAXLIMIT		    10
++ /* For allocating space for the postfix representation */
++ #define	    NFA_POSTFIX_MULTIPLIER	    (NFA_BRACES_MAXLIMIT + 2)*2
++ /* Size of stack, used when converting the postfix regexp into NFA */
++ #define	    NFA_STACK_SIZE		    1024
++ 
++ enum
++ {
++     NFA_SPLIT = -1024,
++     NFA_MATCH,
++     NFA_SKIP_CHAR,		    /* matches a 0-length char */
++     NFA_END_NEG_RANGE,		    /* Used when expanding [^ab] */
++ 
++     NFA_CONCAT,
++     NFA_OR,
++     NFA_STAR,
++     NFA_PLUS,
++     NFA_QUEST,
++     NFA_QUEST_NONGREEDY,	    /* Non-greedy version of \? */
++     NFA_NOT,			    /* used for [^ab] negated char ranges */
++ 
++     NFA_BOL,			    /* ^    Begin line */
++     NFA_EOL,			    /* $    End line */
++     NFA_BOW,			    /* \<   Begin word */
++     NFA_EOW,			    /* \>   End word */
++     NFA_BOF,			    /* \%^  Begin file */
++     NFA_EOF,			    /* \%$  End file */
++     NFA_NEWL,
++     NFA_ZSTART,			    /* Used for \zs */
++     NFA_ZEND,			    /* Used for \ze */
++     NFA_NOPEN,			    /* Start of subexpression marked with \%( */
++     NFA_NCLOSE,			    /* End of subexpr. marked with \%( ... \) */
++     NFA_START_INVISIBLE,
++     NFA_END_INVISIBLE,
++     NFA_MULTIBYTE,		    /* Next nodes in NFA are part of the same
++ 				       multibyte char */
++     NFA_END_MULTIBYTE,		    /* End of multibyte char in the NFA */
++     NFA_COMPOSING,		    /* Next nodes in NFA are part of the
++ 				       composing multibyte char */
++     NFA_END_COMPOSING,		    /* End of a composing char in the NFA */
++ 
++     /* The following are used only in the postfix form, not in the NFA */
++     NFA_PREV_ATOM_NO_WIDTH,	    /* Used for \@= */
++     NFA_PREV_ATOM_NO_WIDTH_NEG,	    /* Used for \@! */
++     NFA_PREV_ATOM_JUST_BEFORE,	    /* Used for \@<= */
++     NFA_PREV_ATOM_JUST_BEFORE_NEG,  /* Used for \@<! */
++     NFA_PREV_ATOM_LIKE_PATTERN,	    /* Used for \@> */
++ 
++     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 */
++     NFA_SIDENT,		/*	Match identifier char but no digit */
++     NFA_KWORD,		/*	Match keyword char */
++     NFA_SKWORD,		/*	Match word char but no digit */
++     NFA_FNAME,		/*	Match file name char */
++     NFA_SFNAME,		/*	Match file name char but no digit */
++     NFA_PRINT,		/*	Match printable char */
++     NFA_SPRINT,		/*	Match printable char but no digit */
++     NFA_WHITE,		/*	Match whitespace char */
++     NFA_NWHITE,		/*	Match non-whitespace char */
++     NFA_DIGIT,		/*	Match digit char */
++     NFA_NDIGIT,		/*	Match non-digit char */
++     NFA_HEX,		/*	Match hex char */
++     NFA_NHEX,		/*	Match non-hex char */
++     NFA_OCTAL,		/*	Match octal char */
++     NFA_NOCTAL,		/*	Match non-octal char */
++     NFA_WORD,		/*	Match word char */
++     NFA_NWORD,		/*	Match non-word char */
++     NFA_HEAD,		/*	Match head char */
++     NFA_NHEAD,		/*	Match non-head char */
++     NFA_ALPHA,		/*	Match alpha char */
++     NFA_NALPHA,		/*	Match non-alpha char */
++     NFA_LOWER,		/*	Match lowercase char */
++     NFA_NLOWER,		/*	Match non-lowercase char */
++     NFA_UPPER,		/*	Match uppercase char */
++     NFA_NUPPER,		/*	Match non-uppercase char */
++     NFA_FIRST_NL = NFA_ANY + ADD_NL,
++     NFA_LAST_NL = NFA_NUPPER + ADD_NL,
++ 
++     /* Character classes [:alnum:] etc */
++     NFA_CLASS_ALNUM,
++     NFA_CLASS_ALPHA,
++     NFA_CLASS_BLANK,
++     NFA_CLASS_CNTRL,
++     NFA_CLASS_DIGIT,
++     NFA_CLASS_GRAPH,
++     NFA_CLASS_LOWER,
++     NFA_CLASS_PRINT,
++     NFA_CLASS_PUNCT,
++     NFA_CLASS_SPACE,
++     NFA_CLASS_UPPER,
++     NFA_CLASS_XDIGIT,
++     NFA_CLASS_TAB,
++     NFA_CLASS_RETURN,
++     NFA_CLASS_BACKSPACE,
++     NFA_CLASS_ESCAPE
++ };
++ 
++ /* Keep in sync with classchars. */
++ static int nfa_classcodes[] = {
++     NFA_ANY, NFA_IDENT, NFA_SIDENT, NFA_KWORD,NFA_SKWORD,
++     NFA_FNAME, NFA_SFNAME, NFA_PRINT, NFA_SPRINT,
++     NFA_WHITE, NFA_NWHITE, NFA_DIGIT, NFA_NDIGIT,
++     NFA_HEX, NFA_NHEX, NFA_OCTAL, NFA_NOCTAL,
++     NFA_WORD, NFA_NWORD, NFA_HEAD, NFA_NHEAD,
++     NFA_ALPHA, NFA_NALPHA, NFA_LOWER, NFA_NLOWER,
++     NFA_UPPER, NFA_NUPPER
++ };
++ 
++ static char_u e_misplaced[] = N_("E866: (NFA regexp) Misplaced %c");
++ 
++ /*
++  * NFA errors can be of 3 types:
++  * *** NFA runtime errors, when something unknown goes wrong. The NFA fails
++  *     silently and revert the to backtracking engine.
++  *     syntax_error = FALSE;
++  * *** Regexp syntax errors, when the input regexp is not syntactically correct.
++  *     The NFA engine displays an error message, and nothing else happens.
++  *     syntax_error = TRUE
++  * *** Unsupported features, when the input regexp uses an operator that is not
++  *     implemented in the NFA. The NFA engine fails silently, and reverts to the
++  *     old backtracking engine.
++  *     syntax_error = FALSE
++  * "The NFA fails" means that "compiling the regexp with the NFA fails":
++  * nfa_regcomp() returns FAIL.
++  */
++ static int syntax_error = FALSE;
++ 
++ /* NFA regexp \ze operator encountered. */
++ static int nfa_has_zend = FALSE;
++ 
++ static int *post_start;  /* holds the postfix form of r.e. */
++ static int *post_end;
++ static int *post_ptr;
++ 
++ static int nstate;	/* Number of states in the NFA. */
++ static int istate;	/* Index in the state vector, used in new_state() */
++ static int nstate_max;	/* Upper bound of estimated number of states. */
++ 
++ 
++ static int nfa_regcomp_start __ARGS((char_u*expr, int re_flags));
++ static int nfa_recognize_char_class __ARGS((char_u *start, char_u *end, int extra_newl));
++ static int nfa_emit_equi_class __ARGS((int c, int neg));
++ static void nfa_inc __ARGS((char_u **p));
++ static void nfa_dec __ARGS((char_u **p));
++ static int nfa_regatom __ARGS((void));
++ static int nfa_regpiece __ARGS((void));
++ static int nfa_regconcat __ARGS((void));
++ static int nfa_regbranch __ARGS((void));
++ static int nfa_reg __ARGS((int paren));
++ #ifdef DEBUG
++ static void nfa_set_code __ARGS((int c));
++ static void nfa_postfix_dump __ARGS((char_u *expr, int retval));
++ static void nfa_print_state __ARGS((FILE *debugf, nfa_state_T *state, int ident));
++ static void nfa_dump __ARGS((nfa_regprog_T *prog));
++ #endif
++ static int *re2post __ARGS((void));
++ static nfa_state_T *new_state __ARGS((int c, nfa_state_T *out, nfa_state_T *out1));
++ static nfa_state_T *post2nfa __ARGS((int *postfix, int *end, int nfa_calc_size));
++ static int check_char_class __ARGS((int class, int c));
++ static void st_error __ARGS((int *postfix, int *end, int *p));
++ 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 void nfa_set_null_listids __ARGS((nfa_state_T *start));
++ static void nfa_set_neg_listids __ARGS((nfa_state_T *start));
++ 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));
++ static long nfa_regexec_multi __ARGS((regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm));
++ 
++ /* helper functions used when doing re2post() ... regatom() parsing */
++ #define EMIT(c)	do {				\
++ 		    if (post_ptr >= post_end)	\
++ 			return FAIL;		\
++ 		    *post_ptr++ = c;		\
++ 		} while (0)
++ 
++ #define EMIT_MBYTE(c)					    \
++ 			len = (*mb_char2bytes)(c, buf);	    \
++ 			EMIT(buf[0]);			    \
++ 			for (i = 1; i < len; i++)	    \
++ 			{				    \
++ 			    EMIT(buf[i]);		    \
++ 			    EMIT(NFA_CONCAT);		    \
++ 			}				    \
++ 			EMIT(NFA_MULTIBYTE);
++ 
++ #define EMIT_COMPOSING_UTF(input)			    \
++ 			len = utfc_ptr2len(input);	    \
++ 			EMIT(input[0]);			    \
++ 			for (i = 1; i < len; i++)	    \
++ 			{				    \
++ 			    EMIT(input[i]);		    \
++ 			    EMIT(NFA_CONCAT);		    \
++ 			}				    \
++ 			EMIT(NFA_COMPOSING);
++ 
++ /*
++  * Initialize internal variables before NFA compilation.
++  * Return OK on success, FAIL otherwise.
++  */
++     static int
++ nfa_regcomp_start(expr, re_flags)
++     char_u	*expr;
++     int		re_flags;	    /* see vim_regcomp() */
++ {
++     int		postfix_size;
++ 
++     nstate = 0;
++     istate = 0;
++     /* A reasonable estimation for size */
++     nstate_max = (STRLEN(expr) + 1) * NFA_POSTFIX_MULTIPLIER;
++ 
++     /* Size for postfix representation of expr */
++     postfix_size = sizeof(*post_start) * nstate_max;
++     post_start = (int *)lalloc(postfix_size, TRUE);
++     if (post_start == NULL)
++ 	return FAIL;
++     vim_memset(post_start, 0, postfix_size);
++     post_ptr = post_start;
++     post_end = post_start + postfix_size;
++     nfa_has_zend = FALSE;
++ 
++     regcomp_start(expr, re_flags);
++ 
++     return OK;
++ }
++ 
++ /*
++  * Search between "start" and "end" and try to recognize a
++  * character class in expanded form. For example [0-9].
++  * On success, return the id the character class to be emitted.
++  * On failure, return 0 (=FAIL)
++  * Start points to the first char of the range, while end should point
++  * to the closing brace.
++  */
++     static int
++ nfa_recognize_char_class(start, end, extra_newl)
++     char_u  *start;
++     char_u  *end;
++     int	    extra_newl;
++ {
++     int		i;
++     /* Each of these variables takes up a char in "config[]",
++      * in the order they are here. */
++     int		not = FALSE, af = FALSE, AF = FALSE, az = FALSE, AZ = FALSE,
++ 		o7 = FALSE, o9 = FALSE, underscore = FALSE, newl = FALSE;
++     char_u	*p;
++ #define NCONFIGS 16
++     int		classid[NCONFIGS] = {
++ 	NFA_DIGIT, NFA_NDIGIT, NFA_HEX, NFA_NHEX,
++ 	NFA_OCTAL, NFA_NOCTAL, NFA_WORD, NFA_NWORD,
++ 	NFA_HEAD, NFA_NHEAD, NFA_ALPHA, NFA_NALPHA,
++ 	NFA_LOWER, NFA_NLOWER, NFA_UPPER, NFA_NUPPER
++     };
++     char_u	myconfig[9];
++     char_u	config[NCONFIGS][9] = {
++ 	"000000100",	/* digit */
++ 	"100000100",	/* non digit */
++ 	"011000100",	/* hex-digit */
++ 	"111000100",	/* non hex-digit */
++ 	"000001000",	/* octal-digit */
++ 	"100001000",	/* [^0-7] */
++ 	"000110110",	/* [0-9A-Za-z_]	*/
++ 	"100110110",	/* [^0-9A-Za-z_] */
++ 	"000110010",	/* head of word */
++ 	"100110010",	/* not head of word */
++ 	"000110000",	/* alphabetic char a-z */
++ 	"100110000",	/* non alphabetic char */
++ 	"000100000",	/* lowercase letter */
++ 	"100100000",	/* non lowercase */
++ 	"000010000",	/* uppercase */
++ 	"100010000"	/* non uppercase */
++     };
++ 
++     if (extra_newl == TRUE)
++ 	newl = TRUE;
++ 
++     if (*end != ']')
++ 	return FAIL;
++     p = start;
++     if (*p == '^')
++     {
++ 	not = TRUE;
++ 	p ++;
++     }
++ 
++     while (p < end)
++     {
++ 	if (p + 2 < end && *(p + 1) == '-')
++ 	{
++ 	    switch (*p)
++ 	    {
++ 		case '0':
++ 		    if (*(p + 2) == '9')
++ 		    {
++ 			o9 = TRUE;
++ 			break;
++ 		    }
++ 		    else
++ 		    if (*(p + 2) == '7')
++ 		    {
++ 			o7 = TRUE;
++ 			break;
++ 		    }
++ 		case 'a':
++ 		    if (*(p + 2) == 'z')
++ 		    {
++ 			az = TRUE;
++ 			break;
++ 		    }
++ 		    else
++ 		    if (*(p + 2) == 'f')
++ 		    {
++ 			af = TRUE;
++ 			break;
++ 		    }
++ 		case 'A':
++ 		    if (*(p + 2) == 'Z')
++ 		    {
++ 			AZ = TRUE;
++ 			break;
++ 		    }
++ 		    else
++ 		    if (*(p + 2) == 'F')
++ 		    {
++ 			AF = TRUE;
++ 			break;
++ 		    }
++ 		/* FALLTHROUGH */
++ 		default:
++ 		    return FAIL;
++ 	    }
++ 	    p += 3;
++ 	}
++ 	else if (p + 1 < end && *p == '\\' && *(p + 1) == 'n')
++ 	{
++ 	    newl = TRUE;
++ 	    p += 2;
++ 	}
++ 	else if (*p == '_')
++ 	{
++ 	    underscore = TRUE;
++ 	    p ++;
++ 	}
++ 	else if (*p == '\n')
++ 	{
++ 	    newl = TRUE;
++ 	    p ++;
++ 	}
++ 	else
++ 	    return FAIL;
++     } /* while (p < end) */
++ 
++     if (p != end)
++ 	return FAIL;
++ 
++     /* build the config that represents the ranges we gathered */
++     STRCPY(myconfig, "000000000");
++     if (not == TRUE)
++ 	myconfig[0] = '1';
++     if (af == TRUE)
++ 	myconfig[1] = '1';
++     if (AF == TRUE)
++ 	myconfig[2] = '1';
++     if (az == TRUE)
++ 	myconfig[3] = '1';
++     if (AZ == TRUE)
++ 	myconfig[4] = '1';
++     if (o7 == TRUE)
++ 	myconfig[5] = '1';
++     if (o9 == TRUE)
++ 	myconfig[6] = '1';
++     if (underscore == TRUE)
++ 	myconfig[7] = '1';
++     if (newl == TRUE)
++     {
++ 	myconfig[8] = '1';
++ 	extra_newl = ADD_NL;
++     }
++     /* try to recognize character classes */
++     for (i = 0; i < NCONFIGS; i++)
++ 	if (STRNCMP(myconfig, config[i],8) == 0)
++ 	    return classid[i] + extra_newl;
++ 
++     /* fallthrough => no success so far */
++     return FAIL;
++ 
++ #undef NCONFIGS
++ }
++ 
++ /*
++  * Produce the bytes for equivalence class "c".
++  * Currently only handles latin1, latin9 and utf-8.
++  * Emits bytes in postfix notation: 'a,b,NFA_OR,c,NFA_OR' is
++  * equivalent to 'a OR b OR c'
++  *
++  * NOTE! When changing this function, also update reg_equi_class()
++  */
++     static int
++ nfa_emit_equi_class(c, neg)
++     int	    c;
++     int	    neg;
++ {
++     int	first = TRUE;
++     int	glue = neg == TRUE ? NFA_CONCAT : NFA_OR;
++ #define EMIT2(c)		\
++ 	EMIT(c);		\
++ 	if (neg == TRUE) {	\
++ 	    EMIT(NFA_NOT);	\
++ 	}			\
++ 	if (first == FALSE)	\
++ 	    EMIT(glue);		\
++ 	else			\
++ 	    first = FALSE;	\
++ 
++ #ifdef FEAT_MBYTE
++     if (enc_utf8 || STRCMP(p_enc, "latin1") == 0
++ 					 || STRCMP(p_enc, "iso-8859-15") == 0)
++ #endif
++     {
++ 	switch (c)
++ 	{
++ 	    case 'A': case '\300': case '\301': case '\302':
++ 	    case '\303': case '\304': case '\305':
++ 		    EMIT2('A');	    EMIT2('\300');  EMIT2('\301');
++ 		    EMIT2('\302');  EMIT2('\303');  EMIT2('\304');
++ 		    EMIT2('\305');
++ 		    return OK;
++ 
++ 	    case 'C': case '\307':
++ 		    EMIT2('C');	    EMIT2('\307');
++ 		    return OK;
++ 
++ 	    case 'E': case '\310': case '\311': case '\312': case '\313':
++ 		    EMIT2('E');	    EMIT2('\310');  EMIT2('\311');
++ 		    EMIT2('\312');  EMIT2('\313');
++ 		    return OK;
++ 
++ 	    case 'I': case '\314': case '\315': case '\316': case '\317':
++ 		    EMIT2('I');	    EMIT2('\314');  EMIT2('\315');
++ 		    EMIT2('\316');  EMIT2('\317');
++ 		    return OK;
++ 
++ 	    case 'N': case '\321':
++ 		    EMIT2('N');	    EMIT2('\321');
++ 		    return OK;
++ 
++ 	    case 'O': case '\322': case '\323': case '\324': case '\325':
++ 	    case '\326':
++ 		    EMIT2('O');	    EMIT2('\322');  EMIT2('\323');
++ 		    EMIT2('\324');  EMIT2('\325');  EMIT2('\326');
++ 		    return OK;
++ 
++ 	    case 'U': case '\331': case '\332': case '\333': case '\334':
++ 		    EMIT2('U');	    EMIT2('\331');  EMIT2('\332');
++ 		    EMIT2('\333');  EMIT2('\334');
++ 		    return OK;
++ 
++ 	    case 'Y': case '\335':
++ 		    EMIT2('Y');	    EMIT2('\335');
++ 		    return OK;
++ 
++ 	    case 'a': case '\340': case '\341': case '\342':
++ 	    case '\343': case '\344': case '\345':
++ 		    EMIT2('a');	    EMIT2('\340');  EMIT2('\341');
++ 		    EMIT2('\342');  EMIT2('\343');  EMIT2('\344');
++ 		    EMIT2('\345');
++ 		    return OK;
++ 
++ 	    case 'c': case '\347':
++ 		    EMIT2('c');	    EMIT2('\347');
++ 		    return OK;
++ 
++ 	    case 'e': case '\350': case '\351': case '\352': case '\353':
++ 		    EMIT2('e');	    EMIT2('\350');  EMIT2('\351');
++ 		    EMIT2('\352');  EMIT2('\353');
++ 		    return OK;
++ 
++ 	    case 'i': case '\354': case '\355': case '\356': case '\357':
++ 		    EMIT2('i');	    EMIT2('\354');  EMIT2('\355');
++ 		    EMIT2('\356');  EMIT2('\357');
++ 		    return OK;
++ 
++ 	    case 'n': case '\361':
++ 		    EMIT2('n');	    EMIT2('\361');
++ 		    return OK;
++ 
++ 	    case 'o': case '\362': case '\363': case '\364': case '\365':
++ 	    case '\366':
++ 		    EMIT2('o');	    EMIT2('\362');  EMIT2('\363');
++ 		    EMIT2('\364');  EMIT2('\365');  EMIT2('\366');
++ 		    return OK;
++ 
++ 	    case 'u': case '\371': case '\372': case '\373': case '\374':
++ 		    EMIT2('u');	    EMIT2('\371');  EMIT2('\372');
++ 		    EMIT2('\373');  EMIT2('\374');
++ 		    return OK;
++ 
++ 	    case 'y': case '\375': case '\377':
++ 		    EMIT2('y');	    EMIT2('\375');  EMIT2('\377');
++ 		    return OK;
++ 
++ 	    default:
++ 		    return FAIL;
++ 	}
++     }
++ 
++     EMIT(c);
++     return OK;
++ #undef EMIT2
++ }
++ 
++ /*
++  * Code to parse regular expression.
++  *
++  * We try to reuse parsing functions in regexp.c to
++  * minimize surprise and keep the syntax consistent.
++  */
++ 
++ /*
++  * Increments the pointer "p" by one (multi-byte) character.
++  */
++     static void
++ nfa_inc(p)
++     char_u **p;
++ {
++ #ifdef FEAT_MBYTE
++     if (has_mbyte)
++ 	mb_ptr2char_adv(p);
++     else
++ #endif
++ 	*p = *p + 1;
++ }
++ 
++ /*
++  * Decrements the pointer "p" by one (multi-byte) character.
++  */
++     static void
++ nfa_dec(p)
++     char_u **p;
++ {
++ #ifdef FEAT_MBYTE
++     char_u *p2, *oldp;
++ 
++     if (has_mbyte)
++     {
++ 	oldp = *p;
++ 	/* Try to find the multibyte char that advances to the current
++ 	 * position. */
++ 	do
++ 	{
++ 	    *p = *p - 1;
++ 	    p2 = *p;
++ 	    mb_ptr2char_adv(&p2);
++ 	} while (p2 != oldp);
++     }
++ #else
++     *p = *p - 1;
++ #endif
++ }
++ 
++ /*
++  * Parse the lowest level.
++  *
++  * An atom can be one of a long list of items.  Many atoms match one character
++  * in the text.  It is often an ordinary character or a character class.
++  * Braces can be used to make a pattern into an atom.  The "\z(\)" construct
++  * is only for syntax highlighting.
++  *
++  * atom    ::=     ordinary-atom
++  *     or  \( pattern \)
++  *     or  \%( pattern \)
++  *     or  \z( pattern \)
++  */
++     static int
++ nfa_regatom()
++ {
++     int		c;
++     int		charclass;
++     int		equiclass;
++     int		collclass;
++     int		got_coll_char;
++     char_u	*p;
++     char_u	*endp;
++ #ifdef FEAT_MBYTE
++     char_u	*old_regparse = regparse;
++     int		clen;
++     int		len;
++     static char_u	buf[30];
++     int		i;
++ #endif
++     int		extra = 0;
++     int		first;
++     int		emit_range;
++     int		negated;
++     int		result;
++     int		startc = -1;
++     int		endc = -1;
++     int		oldstartc = -1;
++     int		cpo_lit;	/* 'cpoptions' contains 'l' flag */
++     int		cpo_bsl;	/* 'cpoptions' contains '\' flag */
++     int		glue;		/* ID that will "glue" nodes together */
++ 
++     cpo_lit = vim_strchr(p_cpo, CPO_LITERAL) != NULL;
++     cpo_bsl = vim_strchr(p_cpo, CPO_BACKSL) != NULL;
++ 
++     c = getchr();
++ 
++ #ifdef FEAT_MBYTE
++     /* clen has the length of the current char, without composing chars */
++     clen = (*mb_char2len)(c);
++     if (has_mbyte && clen > 1)
++ 	goto nfa_do_multibyte;
++ #endif
++     switch (c)
++     {
++ 	case Magic('^'):
++ 	    EMIT(NFA_BOL);
++ 	    break;
++ 
++ 	case Magic('$'):
++ 	    EMIT(NFA_EOL);
++ #if defined(FEAT_SYN_HL) || defined(PROTO)
++ 	    had_eol = TRUE;
++ #endif
++ 	    break;
++ 
++ 	case Magic('<'):
++ 	    EMIT(NFA_BOW);
++ 	    break;
++ 
++ 	case Magic('>'):
++ 	    EMIT(NFA_EOW);
++ 	    break;
++ 
++ 	case Magic('_'):
++ 	    c = no_Magic(getchr());
++ 	    if (c == '^')	/* "\_^" is start-of-line */
++ 	    {
++ 		EMIT(NFA_BOL);
++ 		break;
++ 	    }
++ 	    if (c == '$')	/* "\_$" is end-of-line */
++ 	    {
++ 		EMIT(NFA_EOL);
++ #if defined(FEAT_SYN_HL) || defined(PROTO)
++ 		had_eol = TRUE;
++ #endif
++ 		break;
++ 	    }
++ 
++ 	    extra = ADD_NL;
++ 
++ 	    /* "\_[" is collection plus newline */
++ 	    if (c == '[')
++ 		/* TODO: make this work
++ 		 * goto collection; */
++ 		return FAIL;
++ 
++ 	/* "\_x" is character class plus newline */
++ 	/*FALLTHROUGH*/
++ 
++ 	/*
++ 	 * Character classes.
++ 	 */
++ 	case Magic('.'):
++ 	case Magic('i'):
++ 	case Magic('I'):
++ 	case Magic('k'):
++ 	case Magic('K'):
++ 	case Magic('f'):
++ 	case Magic('F'):
++ 	case Magic('p'):
++ 	case Magic('P'):
++ 	case Magic('s'):
++ 	case Magic('S'):
++ 	case Magic('d'):
++ 	case Magic('D'):
++ 	case Magic('x'):
++ 	case Magic('X'):
++ 	case Magic('o'):
++ 	case Magic('O'):
++ 	case Magic('w'):
++ 	case Magic('W'):
++ 	case Magic('h'):
++ 	case Magic('H'):
++ 	case Magic('a'):
++ 	case Magic('A'):
++ 	case Magic('l'):
++ 	case Magic('L'):
++ 	case Magic('u'):
++ 	case Magic('U'):
++ 	    p = vim_strchr(classchars, no_Magic(c));
++ 	    if (p == NULL)
++ 	    {
++ 		return FAIL;	    /* runtime error */
++ 	    }
++ #ifdef FEAT_MBYTE
++ 	    /* When '.' is followed by a composing char ignore the dot, so that
++ 	     * the composing char is matched here. */
++ 	    if (enc_utf8 && c == Magic('.') && utf_iscomposing(peekchr()))
++ 	    {
++ 		c = getchr();
++ 		goto nfa_do_multibyte;
++ 	    }
++ #endif
++ 	    EMIT(nfa_classcodes[p - classchars]);
++ 	    if (extra == ADD_NL)
++ 	    {
++ 		EMIT(NFA_NEWL);
++ 		EMIT(NFA_OR);
++ 		regflags |= RF_HASNL;
++ 	    }
++ 	    break;
++ 
++ 	case Magic('n'):
++ 	    if (reg_string)
++ 	    /* In a string "\n" matches a newline character. */
++ 	    EMIT(NL);
++ 	    else
++ 	    {
++ 		/* In buffer text "\n" matches the end of a line. */
++ 		EMIT(NFA_NEWL);
++ 		regflags |= RF_HASNL;
++ 	    }
++ 	    break;
++ 
++ 	case Magic('('):
++ 	    if (nfa_reg(REG_PAREN) == FAIL)
++ 		return FAIL;	    /* cascaded error */
++ 	    break;
++ 
++ 	case NUL:
++ 	    syntax_error = TRUE;
++ 	    EMSG_RET_FAIL(_("E865: (NFA) Regexp end encountered prematurely"));
++ 
++ 	case Magic('|'):
++ 	case Magic('&'):
++ 	case Magic(')'):
++ 	    syntax_error = TRUE;
++ 	    EMSG2(_(e_misplaced), no_Magic(c));
++ 	    return FAIL;
++ 
++ 	case Magic('='):
++ 	case Magic('?'):
++ 	case Magic('+'):
++ 	case Magic('@'):
++ 	case Magic('*'):
++ 	case Magic('{'):
++ 	    /* these should follow an atom, not form an atom */
++ 	    syntax_error = TRUE;
++ 	    EMSG2(_(e_misplaced), no_Magic(c));
++ 	    return FAIL;
++ 
++ 	case Magic('~'):		/* previous substitute pattern */
++ 	    /* Not supported yet */
++ 	    return FAIL;
++ 
++ 	case Magic('1'):
++ 	case Magic('2'):
++ 	case Magic('3'):
++ 	case Magic('4'):
++ 	case Magic('5'):
++ 	case Magic('6'):
++ 	case Magic('7'):
++ 	case Magic('8'):
++ 	case Magic('9'):
++ 	    /* not supported yet */
++ 	    return FAIL;
++ 
++ 	case Magic('z'):
++ 	    c = no_Magic(getchr());
++ 	    switch (c)
++ 	    {
++ 		case 's':
++ 		    EMIT(NFA_ZSTART);
++ 		    break;
++ 		case 'e':
++ 		    EMIT(NFA_ZEND);
++ 		    nfa_has_zend = TRUE;
++ 		    /* TODO: Currently \ze does not work properly. */
++ 		    return FAIL;
++ 		    /* break; */
++ 		case '1':
++ 		case '2':
++ 		case '3':
++ 		case '4':
++ 		case '5':
++ 		case '6':
++ 		case '7':
++ 		case '8':
++ 		case '9':
++ 		case '(':
++ 		    /* \z1...\z9 and \z( not yet supported */
++ 		    return FAIL;
++ 		default:
++ 		    syntax_error = TRUE;
++ 		    EMSG2(_("E867: (NFA) Unknown operator '\\z%c'"),
++ 								 no_Magic(c));
++ 		    return FAIL;
++ 	    }
++ 	    break;
++ 
++ 	case Magic('%'):
++ 	    c = no_Magic(getchr());
++ 	    switch (c)
++ 	    {
++ 		/* () without a back reference */
++ 		case '(':
++ 		    if (nfa_reg(REG_NPAREN) == FAIL)
++ 			return FAIL;
++ 		    EMIT(NFA_NOPEN);
++ 		    break;
++ 
++ 		case 'd':   /* %d123 decimal */
++ 		case 'o':   /* %o123 octal */
++ 		case 'x':   /* %xab hex 2 */
++ 		case 'u':   /* %uabcd hex 4 */
++ 		case 'U':   /* %U1234abcd hex 8 */
++ 		    /* Not yet supported */
++ 		    return FAIL;
++ 
++ 		    c = coll_get_char();
++ #ifdef FEAT_MBYTE
++ 		    if ((*mb_char2len)(c) > 1)
++ 		    {
++ 			EMIT_MBYTE(c);
++ 		    }
++ 		    else
++ #endif
++ 			EMIT(c);
++ 		    break;
++ 
++ 		/* Catch \%^ and \%$ regardless of where they appear in the
++ 		 * pattern -- regardless of whether or not it makes sense. */
++ 		case '^':
++ 		    EMIT(NFA_BOF);
++ 		    /* Not yet supported */
++ 		    return FAIL;
++ 		    break;
++ 
++ 		case '$':
++ 		    EMIT(NFA_EOF);
++ 		    /* Not yet supported */
++ 		    return FAIL;
++ 		    break;
++ 
++ 		case '#':
++ 		    /* not supported yet */
++ 		    return FAIL;
++ 		    break;
++ 
++ 		case 'V':
++ 		    /* not supported yet */
++ 		    return FAIL;
++ 		    break;
++ 
++ 		case '[':
++ 		    /* \%[abc] not supported yet */
++ 		    return FAIL;
++ 
++ 		default:
++ 		    /* not supported yet */
++ 		    return FAIL;
++ 	    }
++ 	    break;
++ 
++ /* collection: */
++ 	case Magic('['):
++ 	    /*
++ 	     * Glue is emitted between several atoms from the [].
++ 	     * It is either NFA_OR, or NFA_CONCAT.
++ 	     *
++ 	     * [abc] expands to 'a b NFA_OR c NFA_OR' (in postfix notation)
++ 	     * [^abc] expands to 'a NFA_NOT b NFA_NOT NFA_CONCAT c NFA_NOT
++ 	     *		NFA_CONCAT NFA_END_NEG_RANGE NFA_CONCAT' (in postfix
++ 	     *		notation)
++ 	     *
++ 	     */
++ 
++ 
++ /* Emit negation atoms, if needed.
++  * The CONCAT below merges the NOT with the previous node. */
++ #define TRY_NEG()		    \
++ 	    if (negated == TRUE)    \
++ 	    {			    \
++ 		EMIT(NFA_NOT);	    \
++ 	    }
++ 
++ /* Emit glue between important nodes : CONCAT or OR. */
++ #define EMIT_GLUE()		    \
++ 	    if (first == FALSE)	    \
++ 		EMIT(glue);	    \
++ 	    else		    \
++ 		first = FALSE;
++ 
++ 	    p = regparse;
++ 	    endp = skip_anyof(p);
++ 	    if (*endp == ']')
++ 	    {
++ 		/*
++ 		 * Try to reverse engineer character classes. For example,
++ 		 * recognize that [0-9] stands for  \d and [A-Za-z_] with \h,
++ 		 * and perform the necessary substitutions in the NFA.
++ 		 */
++ 		result = nfa_recognize_char_class(regparse, endp,
++ 							    extra == ADD_NL);
++ 		if (result != FAIL)
++ 		{
++ 		    if (result >= NFA_DIGIT && result <= NFA_NUPPER)
++ 			EMIT(result);
++ 		    else	/* must be char class + newline */
++ 		    {
++ 			EMIT(result - ADD_NL);
++ 			EMIT(NFA_NEWL);
++ 			EMIT(NFA_OR);
++ 		    }
++ 		    regparse = endp;
++ 		    nfa_inc(&regparse);
++ 		    return OK;
++ 		}
++ 		/*
++ 		 * Failed to recognize a character class. Use the simple
++ 		 * version that turns [abc] into 'a' OR 'b' OR 'c'
++ 		 */
++ 		startc = endc = oldstartc = -1;
++ 		first = TRUE;	    /* Emitting first atom in this sequence? */
++ 		negated = FALSE;
++ 		glue = NFA_OR;
++ 		if (*regparse == '^')			/* negated range */
++ 		{
++ 		    negated = TRUE;
++ 		    glue = NFA_CONCAT;
++ 		    nfa_inc(&regparse);
++ 		}
++ 		if (*regparse == '-')
++ 		{
++ 		    startc = '-';
++ 		    EMIT(startc);
++ 		    TRY_NEG();
++ 		    EMIT_GLUE();
++ 		    nfa_inc(&regparse);
++ 		}
++ 		/* Emit the OR branches for each character in the [] */
++ 		emit_range = FALSE;
++ 		while (regparse < endp)
++ 		{
++ 		    oldstartc = startc;
++ 		    startc = -1;
++ 		    got_coll_char = FALSE;
++ 		    if (*regparse == '[')
++ 		    {
++ 			/* Check for [: :], [= =], [. .] */
++ 			equiclass = collclass = 0;
++ 			charclass = get_char_class(&regparse);
++ 			if (charclass == CLASS_NONE)
++ 			{
++ 			    equiclass = get_equi_class(&regparse);
++ 			    if (equiclass == 0)
++ 				collclass = get_coll_element(&regparse);
++ 			}
++ 
++ 			/* Character class like [:alpha:]  */
++ 			if (charclass != CLASS_NONE)
++ 			{
++ 			    switch (charclass)
++ 			    {
++ 				case CLASS_ALNUM:
++ 				    EMIT(NFA_CLASS_ALNUM);
++ 				    break;
++ 				case CLASS_ALPHA:
++ 				    EMIT(NFA_CLASS_ALPHA);
++ 				    break;
++ 				case CLASS_BLANK:
++ 				    EMIT(NFA_CLASS_BLANK);
++ 				    break;
++ 				case CLASS_CNTRL:
++ 				    EMIT(NFA_CLASS_CNTRL);
++ 				    break;
++ 				case CLASS_DIGIT:
++ 				    EMIT(NFA_CLASS_DIGIT);
++ 				    break;
++ 				case CLASS_GRAPH:
++ 				    EMIT(NFA_CLASS_GRAPH);
++ 				    break;
++ 				case CLASS_LOWER:
++ 				    EMIT(NFA_CLASS_LOWER);
++ 				    break;
++ 				case CLASS_PRINT:
++ 				    EMIT(NFA_CLASS_PRINT);
++ 				    break;
++ 				case CLASS_PUNCT:
++ 				    EMIT(NFA_CLASS_PUNCT);
++ 				    break;
++ 				case CLASS_SPACE:
++ 				    EMIT(NFA_CLASS_SPACE);
++ 				    break;
++ 				case CLASS_UPPER:
++ 				    EMIT(NFA_CLASS_UPPER);
++ 				    break;
++ 				case CLASS_XDIGIT:
++ 				    EMIT(NFA_CLASS_XDIGIT);
++ 				    break;
++ 				case CLASS_TAB:
++ 				    EMIT(NFA_CLASS_TAB);
++ 				    break;
++ 				case CLASS_RETURN:
++ 				    EMIT(NFA_CLASS_RETURN);
++ 				    break;
++ 				case CLASS_BACKSPACE:
++ 				    EMIT(NFA_CLASS_BACKSPACE);
++ 				    break;
++ 				case CLASS_ESCAPE:
++ 				    EMIT(NFA_CLASS_ESCAPE);
++ 				    break;
++ 			    }
++ 			    TRY_NEG();
++ 			    EMIT_GLUE();
++ 			    continue;
++ 			}
++ 			/* Try equivalence class [=a=] and the like */
++ 			if (equiclass != 0)
++ 			{
++ 			    result = nfa_emit_equi_class(equiclass, negated);
++ 			    if (result == FAIL)
++ 			    {
++ 				/* should never happen */
++ 				EMSG_RET_FAIL(_("E868: Error building NFA with equivalence class!"));
++ 			    }
++ 			    EMIT_GLUE();
++ 			    continue;
++ 			}
++ 			/* Try collating class like [. .]  */
++ 			if (collclass != 0)
++ 			{
++ 			    startc = collclass;	 /* allow [.a.]-x as a range */
++ 			    /* Will emit the proper atom at the end of the
++ 			     * while loop. */
++ 			}
++ 		    }
++ 		    /* Try a range like 'a-x' or '\t-z' */
++ 		    if (*regparse == '-')
++ 		    {
++ 			emit_range = TRUE;
++ 			startc = oldstartc;
++ 			nfa_inc(&regparse);
++ 			continue;	    /* reading the end of the range */
++ 		    }
++ 
++ 		    /* Now handle simple and escaped characters.
++ 		     * Only "\]", "\^", "\]" and "\\" are special in Vi.  Vim
++ 		     * accepts "\t", "\e", etc., but only when the 'l' flag in
++ 		     * 'cpoptions' is not included.
++ 		     * Posix doesn't recognize backslash at all.
++ 		     */
++ 		    if (*regparse == '\\'
++ 			    && !cpo_bsl
++ 			    && regparse + 1 <= endp
++ 			    && (vim_strchr(REGEXP_INRANGE, regparse[1]) != NULL
++ 				|| (!cpo_lit
++ 				    && vim_strchr(REGEXP_ABBR, regparse[1])
++ 								      != NULL)
++ 			    )
++ 			)
++ 		    {
++ 			nfa_inc(&regparse);
++ 
++ 			if (*regparse == 'n' || *regparse == 'n')
++ 			    startc = reg_string ? NL : NFA_NEWL;
++ 			else
++ 			    if  (*regparse == 'd'
++ 				    || *regparse == 'o'
++ 				    || *regparse == 'x'
++ 				    || *regparse == 'u'
++ 				    || *regparse == 'U'
++ 				)
++ 			    {
++ 				/* TODO(RE) This needs more testing */
++ 				startc = coll_get_char();
++ 				got_coll_char = TRUE;
++ 				nfa_dec(&regparse);
++ 			    }
++ 			    else
++ 			    {
++ 				/* \r,\t,\e,\b */
++ 				startc = backslash_trans(*regparse);
++ 			    }
++ 		    }
++ 
++ 		    /* Normal printable char */
++ 		    if (startc == -1)
++ #ifdef FEAT_MBYTE
++ 			startc = (*mb_ptr2char)(regparse);
++ #else
++ 		    startc = *regparse;
++ #endif
++ 
++ 		    /* Previous char was '-', so this char is end of range. */
++ 		    if (emit_range)
++ 		    {
++ 			endc = startc; startc = oldstartc;
++ 			if (startc > endc)
++ 			    EMSG_RET_FAIL(_(e_invrange));
++ #ifdef FEAT_MBYTE
++ 			if (has_mbyte && ((*mb_char2len)(startc) > 1
++ 				    || (*mb_char2len)(endc) > 1))
++ 			{
++ 			    if (endc > startc + 256)
++ 				EMSG_RET_FAIL(_(e_invrange));
++ 			    /* Emit the range. "startc" was already emitted, so
++ 			     * skip it. */
++ 			    for (c = startc + 1; c <= endc; c++)
++ 			    {
++ 				if ((*mb_char2len)(c) > 1)
++ 				{
++ 				    EMIT_MBYTE(c);
++ 				}
++ 				else
++ 				    EMIT(c);
++ 				TRY_NEG();
++ 				EMIT_GLUE();
++ 			    }
++ 			    emit_range = FALSE;
++ 			}
++ 			else
++ #endif
++ 			{
++ #ifdef EBCDIC
++ 			    int alpha_only = FALSE;
++ 
++ 			    /* for alphabetical range skip the gaps
++ 			     * 'i'-'j', 'r'-'s', 'I'-'J' and 'R'-'S'. */
++ 			    if (isalpha(startc) && isalpha(endc))
++ 				alpha_only = TRUE;
++ #endif
++ 			    /* Emit the range. "startc" was already emitted, so
++ 			     * skip it. */
++ 			    for (c = startc + 1; c <= endc; c++)
++ #ifdef EBCDIC
++ 				if (!alpha_only || isalpha(startc))
++ #endif
++ 				{
++ 				    EMIT(c);
++ 				    TRY_NEG();
++ 				    EMIT_GLUE();
++ 				}
++ 			    emit_range = FALSE;
++ 			}
++ 		    }
++ 		    else
++ 		    {
++ 			/*
++ 			 * This char (startc) is not part of a range. Just
++ 			 * emit it.
++ 			 *
++ 			 * Normally, simply emit startc. But if we get char
++ 			 * code=0 from a collating char, then replace it with
++ 			 * 0x0a.
++ 			 *
++ 			 * This is needed to completely mimic the behaviour of
++ 			 * the backtracking engine.
++ 			 */
++ 			if (got_coll_char == TRUE && startc == 0)
++ 			    EMIT(0x0a);
++ 			else
++ #ifdef FEAT_MBYTE
++ 			    if ((*mb_char2len)(startc) > 1)
++ 			    {
++ 				EMIT_MBYTE(startc);
++ 			    }
++ 			    else
++ #endif
++ 				EMIT(startc);
++ 			TRY_NEG();
++ 			EMIT_GLUE();
++ 		    }
++ 
++ 		    nfa_inc(&regparse);
++ 		} /* while (p < endp) */
++ 
++ 		nfa_dec(&regparse);
++ 		if (*regparse == '-')	    /* if last, '-' is just a char */
++ 		{
++ 		    EMIT('-');
++ 		    TRY_NEG();
++ 		    EMIT_GLUE();
++ 		}
++ 		nfa_inc(&regparse);
++ 
++ 		if (extra == ADD_NL)	    /* \_[] also matches \n */
++ 		{
++ 		    EMIT(reg_string ? NL : NFA_NEWL);
++ 		    TRY_NEG();
++ 		    EMIT_GLUE();
++ 		}
++ 
++ 		/* skip the trailing ] */
++ 		regparse = endp;
++ 		nfa_inc(&regparse);
++ 		if (negated == TRUE)
++ 		{
++ 		    /* Mark end of negated char range */
++ 		    EMIT(NFA_END_NEG_RANGE);
++ 		    EMIT(NFA_CONCAT);
++ 		}
++ 		return OK;
++ 	    }		/* if exists closing ] */
++ 	    else if (reg_strict)
++ 	    {
++ 		syntax_error = TRUE;
++ 		EMSG_RET_FAIL(_(e_missingbracket));
++ 	    }
++ 
++ 	/* FALLTHROUGH */
++ 	default:
++ 	    {
++ #ifdef FEAT_MBYTE
++ 		int	plen;
++ 
++ nfa_do_multibyte:
++ 		/* length of current char, with composing chars,
++ 		 * from pointer */
++ 		plen = (*mb_ptr2len)(old_regparse);
++ 		if (enc_utf8 && clen != plen)
++ 		{
++ 		    /* A composing character is always handled as a
++ 		     * separate atom, surrounded by NFA_COMPOSING and
++ 		     * NFA_END_COMPOSING. Note that right now we are
++ 		     * building the postfix form, not the NFA itself;
++ 		     * a composing char could be: a, b, c, NFA_COMPOSING
++ 		     * where 'a', 'b', 'c' are chars with codes > 256.
++ 		     */
++ 		    EMIT_COMPOSING_UTF(old_regparse);
++ 		    regparse = old_regparse + plen;
++ 		}
++ 		else
++ 		    /* A multi-byte character is always handled as a
++ 		     * separate atom, surrounded by NFA_MULTIBYTE and
++ 		     * NFA_END_MULTIBYTE */
++ 		    if (plen > 1)
++ 		    {
++ 			EMIT_MBYTE(c);
++ 		    }
++ 		    else
++ #endif
++ 		{
++ 		    c = no_Magic(c);
++ 		    EMIT(c);
++ 		}
++ 		return OK;
++ 	    }
++     }
++ 
++ #undef TRY_NEG
++ #undef EMIT_GLUE
++ 
++     return OK;
++ }
++ 
++ /*
++  * Parse something followed by possible [*+=].
++  *
++  * A piece is an atom, possibly followed by a multi, an indication of how many
++  * times the atom can be matched.  Example: "a*" matches any sequence of "a"
++  * characters: "", "a", "aa", etc.
++  *
++  * piece   ::=	    atom
++  *	or  atom  multi
++  */
++     static int
++ nfa_regpiece()
++ {
++     int		i;
++     int		op;
++     int		ret;
++     long	minval, maxval;
++     int		greedy = TRUE;      /* Braces are prefixed with '-' ? */
++     char_u	*old_regparse, *new_regparse;
++     int		c2;
++     int		*old_post_ptr, *my_post_start;
++     int		old_regnpar;
++     int		quest;
++ 
++     /* Save the current position in the regexp, so that we can use it if
++      * <atom>{m,n} is next. */
++     old_regparse = regparse;
++     /* Save current number of open parenthesis, so we can use it if
++      * <atom>{m,n} is next */
++     old_regnpar = regnpar;
++     /* store current pos in the postfix form, for \{m,n} involving 0s */
++     my_post_start = post_ptr;
++ 
++     ret = nfa_regatom();
++     if (ret == FAIL)
++ 	return FAIL;	    /* cascaded error */
++ 
++     op = peekchr();
++     if (re_multi_type(op) == NOT_MULTI)
++ 	return OK;
++ 
++     skipchr();
++     switch (op)
++     {
++ 	case Magic('*'):
++ 	    EMIT(NFA_STAR);
++ 	    break;
++ 
++ 	case Magic('+'):
++ 	    /*
++ 	     * Trick: Normally, (a*)\+ would match the whole input "aaa".  The
++ 	     * first and only submatch would be "aaa". But the backtracking
++ 	     * engine interprets the plus as "try matching one more time", and
++ 	     * a* matches a second time at the end of the input, the empty
++ 	     * string.
++ 	     * The submatch will the empty string.
++ 	     *
++ 	     * In order to be consistent with the old engine, we disable
++ 	     * NFA_PLUS, and replace <atom>+ with <atom><atom>*
++ 	     */
++ 	    /*	EMIT(NFA_PLUS);	 */
++ 	    regnpar = old_regnpar;
++ 	    regparse = old_regparse;
++ 	    curchr = -1;
++ 	    if (nfa_regatom() == FAIL)
++ 		return FAIL;
++ 	    EMIT(NFA_STAR);
++ 	    EMIT(NFA_CONCAT);
++ 	    skipchr();		/* skip the \+	*/
++ 	    break;
++ 
++ 	case Magic('@'):
++ 	    op = no_Magic(getchr());
++ 	    switch(op)
++ 	    {
++ 		case '=':
++ 		    EMIT(NFA_PREV_ATOM_NO_WIDTH);
++ 		    break;
++ 		case '!':
++ 		case '<':
++ 		case '>':
++ 		    /* Not supported yet */
++ 		    return FAIL;
++ 		default:
++ 		    syntax_error = TRUE;
++ 		    EMSG2(_("E869: (NFA) Unknown operator '\\@%c'"), op);
++ 		    return FAIL;
++ 	    }
++ 	    break;
++ 
++ 	case Magic('?'):
++ 	case Magic('='):
++ 	    EMIT(NFA_QUEST);
++ 	    break;
++ 
++ 	case Magic('{'):
++ 	    /* a{2,5} will expand to 'aaa?a?a?'
++ 	     * a{-1,3} will expand to 'aa??a??', where ?? is the nongreedy
++ 	     * version of '?'
++ 	     * \v(ab){2,3} will expand to '(ab)(ab)(ab)?', where all the
++ 	     * parenthesis have the same id
++ 	     */
++ 
++ 	    greedy = TRUE;
++ 	    c2 = peekchr();
++ 	    if (c2 == '-' || c2 == Magic('-'))
++ 	    {
++ 		skipchr();
++ 		greedy = FALSE;
++ 	    }
++ 	    if (!read_limits(&minval, &maxval))
++ 	    {
++ 		syntax_error = TRUE;
++ 		EMSG_RET_FAIL(_("E870: (NFA regexp) Error reading repetition limits"));
++ 	    }
++ 	    /*  <atom>{0,inf}, <atom>{0,} and <atom>{}  are equivalent to
++ 	     *  <atom>*  */
++ 	    if (minval == 0 && maxval == MAX_LIMIT && greedy)
++ 	    {
++ 		EMIT(NFA_STAR);
++ 		break;
++ 	    }
++ 
++ 	    if (maxval > NFA_BRACES_MAXLIMIT)
++ 	    {
++ 		/* This would yield a huge automaton and use too much memory.
++ 		 * Revert to old engine */
++ 		return FAIL;
++ 	    }
++ 
++ 	    /* Special case: x{0} or x{-0} */
++ 	    if (maxval == 0)
++ 	    {
++ 		/* Ignore result of previous call to nfa_regatom() */
++ 		post_ptr = my_post_start;
++ 		/* NFA_SKIP_CHAR has 0-length and works everywhere */
++ 		EMIT(NFA_SKIP_CHAR);
++ 		return OK;
++ 	    }
++ 
++ 	    /* Ignore previous call to nfa_regatom() */
++ 	    post_ptr = my_post_start;
++ 	    /* Save pos after the repeated atom and the \{} */
++ 	    new_regparse = regparse;
++ 
++ 	    new_regparse = regparse;
++ 	    quest = (greedy == TRUE? NFA_QUEST : NFA_QUEST_NONGREEDY);
++ 	    for (i = 0; i < maxval; i++)
++ 	    {
++ 		/* Goto beginning of the repeated atom */
++ 		regparse = old_regparse;
++ 		curchr = -1;
++ 		/* Restore count of parenthesis */
++ 		regnpar = old_regnpar;
++ 		old_post_ptr = post_ptr;
++ 		if (nfa_regatom() == FAIL)
++ 		    return FAIL;
++ 		/* after "minval" times, atoms are optional */
++ 		if (i + 1 > minval)
++ 		    EMIT(quest);
++ 		if (old_post_ptr != my_post_start)
++ 		    EMIT(NFA_CONCAT);
++ 	    }
++ 
++ 	    /* Go to just after the repeated atom and the \{} */
++ 	    regparse = new_regparse;
++ 	    curchr = -1;
++ 
++ 	    break;
++ 
++ 
++ 	default:
++ 	    break;
++     }	/* end switch */
++ 
++     if (re_multi_type(peekchr()) != NOT_MULTI)
++     {
++ 	/* Can't have a multi follow a multi. */
++ 	syntax_error = TRUE;
++ 	EMSG_RET_FAIL(_("E871: (NFA regexp) Can't have a multi follow a multi !"));
++     }
++ 
++     return OK;
++ }
++ 
++ /*
++  * Parse one or more pieces, concatenated.  It matches a match for the
++  * first piece, followed by a match for the second piece, etc.  Example:
++  * "f[0-9]b", first matches "f", then a digit and then "b".
++  *
++  * concat  ::=	    piece
++  *	or  piece piece
++  *	or  piece piece piece
++  *	etc.
++  */
++     static int
++ nfa_regconcat()
++ {
++     int		cont = TRUE;
++     int		first = TRUE;
++ 
++     while (cont)
++     {
++ 	switch (peekchr())
++ 	{
++ 	    case NUL:
++ 	    case Magic('|'):
++ 	    case Magic('&'):
++ 	    case Magic(')'):
++ 		cont = FALSE;
++ 		break;
++ 
++ 	    case Magic('Z'):
++ #ifdef FEAT_MBYTE
++ 		regflags |= RF_ICOMBINE;
++ #endif
++ 		skipchr_keepstart();
++ 		break;
++ 	    case Magic('c'):
++ 		regflags |= RF_ICASE;
++ 		skipchr_keepstart();
++ 		break;
++ 	    case Magic('C'):
++ 		regflags |= RF_NOICASE;
++ 		skipchr_keepstart();
++ 		break;
++ 	    case Magic('v'):
++ 		reg_magic = MAGIC_ALL;
++ 		skipchr_keepstart();
++ 		curchr = -1;
++ 		break;
++ 	    case Magic('m'):
++ 		reg_magic = MAGIC_ON;
++ 		skipchr_keepstart();
++ 		curchr = -1;
++ 		break;
++ 	    case Magic('M'):
++ 		reg_magic = MAGIC_OFF;
++ 		skipchr_keepstart();
++ 		curchr = -1;
++ 		break;
++ 	    case Magic('V'):
++ 		reg_magic = MAGIC_NONE;
++ 		skipchr_keepstart();
++ 		curchr = -1;
++ 		break;
++ 
++ 	    default:
++ 		if (nfa_regpiece() == FAIL)
++ 		    return FAIL;
++ 		if (first == FALSE)
++ 		    EMIT(NFA_CONCAT);
++ 		else
++ 		    first = FALSE;
++ 		break;
++ 	}
++     }
++ 
++     return OK;
++ }
++ 
++ /*
++  * Parse a branch, one or more concats, separated by "\&".  It matches the
++  * last concat, but only if all the preceding concats also match at the same
++  * position.  Examples:
++  *      "foobeep\&..." matches "foo" in "foobeep".
++  *      ".*Peter\&.*Bob" matches in a line containing both "Peter" and "Bob"
++  *
++  * branch ::=	    concat
++  *		or  concat \& concat
++  *		or  concat \& concat \& concat
++  *		etc.
++  */
++     static int
++ nfa_regbranch()
++ {
++     int		ch;
++     int		*old_post_ptr;
++ 
++     old_post_ptr = post_ptr;
++ 
++     /* First branch, possibly the only one */
++     if (nfa_regconcat() == FAIL)
++ 	return FAIL;
++ 
++     ch = peekchr();
++     /* Try next concats */
++     while (ch == Magic('&'))
++     {
++ 	skipchr();
++ 	EMIT(NFA_NOPEN);
++ 	EMIT(NFA_PREV_ATOM_NO_WIDTH);
++ 	old_post_ptr = post_ptr;
++ 	if (nfa_regconcat() == FAIL)
++ 	    return FAIL;
++ 	/* if concat is empty, skip a input char. But do emit a node */
++ 	if (old_post_ptr == post_ptr)
++ 	    EMIT(NFA_SKIP_CHAR);
++ 	EMIT(NFA_CONCAT);
++ 	ch = peekchr();
++     }
++ 
++     /* Even if a branch is empty, emit one node for it */
++     if (old_post_ptr == post_ptr)
++ 	EMIT(NFA_SKIP_CHAR);
++ 
++     return OK;
++ }
++ 
++ /*
++  *  Parse a pattern, one or more branches, separated by "\|".  It matches
++  *  anything that matches one of the branches.  Example: "foo\|beep" matches
++  *  "foo" and matches "beep".  If more than one branch matches, the first one
++  *  is used.
++  *
++  *  pattern ::=	    branch
++  *	or  branch \| branch
++  *	or  branch \| branch \| branch
++  *	etc.
++  */
++     static int
++ nfa_reg(paren)
++     int		paren;	/* REG_NOPAREN, REG_PAREN, REG_NPAREN or REG_ZPAREN */
++ {
++     int		parno = 0;
++ 
++ #ifdef FEAT_SYN_HL
++ #endif
++     if (paren == REG_PAREN)
++     {
++ 	if (regnpar >= NSUBEXP) /* Too many `(' */
++ 	{
++ 	    syntax_error = TRUE;
++ 	    EMSG_RET_FAIL(_("E872: (NFA regexp) Too many '('"));
++ 	}
++ 	parno = regnpar++;
++     }
++ 
++     if (nfa_regbranch() == FAIL)
++ 	return FAIL;	    /* cascaded error */
++ 
++     while (peekchr() == Magic('|'))
++     {
++ 	skipchr();
++ 	if (nfa_regbranch() == FAIL)
++ 	    return FAIL;    /* cascaded error */
++ 	EMIT(NFA_OR);
++     }
++ 
++     /* Check for proper termination. */
++     if (paren != REG_NOPAREN && getchr() != Magic(')'))
++     {
++ 	syntax_error = TRUE;
++ 	if (paren == REG_NPAREN)
++ 	    EMSG2_RET_FAIL(_(e_unmatchedpp), reg_magic == MAGIC_ALL);
++ 	else
++ 	    EMSG2_RET_FAIL(_(e_unmatchedp), reg_magic == MAGIC_ALL);
++     }
++     else if (paren == REG_NOPAREN && peekchr() != NUL)
++     {
++ 	syntax_error = TRUE;
++ 	if (peekchr() == Magic(')'))
++ 	    EMSG2_RET_FAIL(_(e_unmatchedpar), reg_magic == MAGIC_ALL);
++ 	else
++ 	    EMSG_RET_FAIL(_("E873: (NFA regexp) proper termination error"));
++     }
++     /*
++      * Here we set the flag allowing back references to this set of
++      * parentheses.
++      */
++     if (paren == REG_PAREN)
++     {
++ 	had_endbrace[parno] = TRUE;     /* have seen the close paren */
++ 	EMIT(NFA_MOPEN + parno);
++     }
++ 
++     return OK;
++ }
++ 
++ typedef struct
++ {
++     char_u	*start[NSUBEXP];
++     char_u	*end[NSUBEXP];
++     lpos_T	startpos[NSUBEXP];
++     lpos_T	endpos[NSUBEXP];
++ } regsub_T;
++ 
++ static int nfa_regmatch __ARGS((nfa_state_T *start, regsub_T *submatch, regsub_T *m));
++ 
++ #ifdef DEBUG
++ static char_u code[50];
++ 
++     static void
++ nfa_set_code(c)
++     int	    c;
++ {
++     int	    addnl = FALSE;
++ 
++     if (c >= NFA_FIRST_NL && c <= NFA_LAST_NL)
++     {
++ 	addnl = TRUE;
++ 	c -= ADD_NL;
++     }
++ 
++     STRCPY(code, "");
++     switch (c)
++     {
++ 	case NFA_MATCH:	    STRCPY(code, "NFA_MATCH "); break;
++ 	case NFA_SPLIT:	    STRCPY(code, "NFA_SPLIT "); break;
++ 	case NFA_CONCAT:    STRCPY(code, "NFA_CONCAT "); break;
++ 	case NFA_NEWL:	    STRCPY(code, "NFA_NEWL "); break;
++ 	case NFA_ZSTART:    STRCPY(code, "NFA_ZSTART"); break;
++ 	case NFA_ZEND:	    STRCPY(code, "NFA_ZEND"); break;
++ 
++ 	case NFA_PREV_ATOM_NO_WIDTH:
++ 			    STRCPY(code, "NFA_PREV_ATOM_NO_WIDTH"); break;
++ 	case NFA_NOPEN:		    STRCPY(code, "NFA_MOPEN_INVISIBLE"); break;
++ 	case NFA_NCLOSE:	    STRCPY(code, "NFA_MCLOSE_INVISIBLE"); break;
++ 	case NFA_START_INVISIBLE:   STRCPY(code, "NFA_START_INVISIBLE"); break;
++ 	case NFA_END_INVISIBLE:	    STRCPY(code, "NFA_END_INVISIBLE"); break;
++ 
++ 	case NFA_MULTIBYTE:	    STRCPY(code, "NFA_MULTIBYTE"); break;
++ 	case NFA_END_MULTIBYTE:	    STRCPY(code, "NFA_END_MULTIBYTE"); break;
++ 
++ 	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;
++ 	case NFA_BOW:		STRCPY(code, "NFA_BOW "); break;
++ 	case NFA_STAR:		STRCPY(code, "NFA_STAR "); break;
++ 	case NFA_PLUS:		STRCPY(code, "NFA_PLUS "); break;
++ 	case NFA_NOT:		STRCPY(code, "NFA_NOT "); break;
++ 	case NFA_SKIP_CHAR:	STRCPY(code, "NFA_SKIP_CHAR"); break;
++ 	case NFA_OR:		STRCPY(code, "NFA_OR"); break;
++ 	case NFA_QUEST:		STRCPY(code, "NFA_QUEST"); break;
++ 	case NFA_QUEST_NONGREEDY: STRCPY(code, "NFA_QUEST_NON_GREEDY"); break;
++ 	case NFA_END_NEG_RANGE:	STRCPY(code, "NFA_END_NEG_RANGE"); break;
++ 	case NFA_CLASS_ALNUM:	STRCPY(code, "NFA_CLASS_ALNUM"); break;
++ 	case NFA_CLASS_ALPHA:	STRCPY(code, "NFA_CLASS_ALPHA"); break;
++ 	case NFA_CLASS_BLANK:	STRCPY(code, "NFA_CLASS_BLANK"); break;
++ 	case NFA_CLASS_CNTRL:	STRCPY(code, "NFA_CLASS_CNTRL"); break;
++ 	case NFA_CLASS_DIGIT:	STRCPY(code, "NFA_CLASS_DIGIT"); break;
++ 	case NFA_CLASS_GRAPH:	STRCPY(code, "NFA_CLASS_GRAPH"); break;
++ 	case NFA_CLASS_LOWER:	STRCPY(code, "NFA_CLASS_LOWER"); break;
++ 	case NFA_CLASS_PRINT:	STRCPY(code, "NFA_CLASS_PRINT"); break;
++ 	case NFA_CLASS_PUNCT:	STRCPY(code, "NFA_CLASS_PUNCT"); break;
++ 	case NFA_CLASS_SPACE:	STRCPY(code, "NFA_CLASS_SPACE"); break;
++ 	case NFA_CLASS_UPPER:	STRCPY(code, "NFA_CLASS_UPPER"); break;
++ 	case NFA_CLASS_XDIGIT:	STRCPY(code, "NFA_CLASS_XDIGIT"); break;
++ 	case NFA_CLASS_TAB:	STRCPY(code, "NFA_CLASS_TAB"); break;
++ 	case NFA_CLASS_RETURN:	STRCPY(code, "NFA_CLASS_RETURN"); break;
++ 	case NFA_CLASS_BACKSPACE:   STRCPY(code, "NFA_CLASS_BACKSPACE"); break;
++ 	case NFA_CLASS_ESCAPE:	STRCPY(code, "NFA_CLASS_ESCAPE"); break;
++ 
++ 	case NFA_ANY:	STRCPY(code, "NFA_ANY"); break;
++ 	case NFA_IDENT:	STRCPY(code, "NFA_IDENT"); break;
++ 	case NFA_SIDENT:STRCPY(code, "NFA_SIDENT"); break;
++ 	case NFA_KWORD:	STRCPY(code, "NFA_KWORD"); break;
++ 	case NFA_SKWORD:STRCPY(code, "NFA_SKWORD"); break;
++ 	case NFA_FNAME:	STRCPY(code, "NFA_FNAME"); break;
++ 	case NFA_SFNAME:STRCPY(code, "NFA_SFNAME"); break;
++ 	case NFA_PRINT:	STRCPY(code, "NFA_PRINT"); break;
++ 	case NFA_SPRINT:STRCPY(code, "NFA_SPRINT"); break;
++ 	case NFA_WHITE:	STRCPY(code, "NFA_WHITE"); break;
++ 	case NFA_NWHITE:STRCPY(code, "NFA_NWHITE"); break;
++ 	case NFA_DIGIT:	STRCPY(code, "NFA_DIGIT"); break;
++ 	case NFA_NDIGIT:STRCPY(code, "NFA_NDIGIT"); break;
++ 	case NFA_HEX:	STRCPY(code, "NFA_HEX"); break;
++ 	case NFA_NHEX:	STRCPY(code, "NFA_NHEX"); break;
++ 	case NFA_OCTAL:	STRCPY(code, "NFA_OCTAL"); break;
++ 	case NFA_NOCTAL:STRCPY(code, "NFA_NOCTAL"); break;
++ 	case NFA_WORD:	STRCPY(code, "NFA_WORD"); break;
++ 	case NFA_NWORD:	STRCPY(code, "NFA_NWORD"); break;
++ 	case NFA_HEAD:	STRCPY(code, "NFA_HEAD"); break;
++ 	case NFA_NHEAD:	STRCPY(code, "NFA_NHEAD"); break;
++ 	case NFA_ALPHA:	STRCPY(code, "NFA_ALPHA"); break;
++ 	case NFA_NALPHA:STRCPY(code, "NFA_NALPHA"); break;
++ 	case NFA_LOWER:	STRCPY(code, "NFA_LOWER"); break;
++ 	case NFA_NLOWER:STRCPY(code, "NFA_NLOWER"); break;
++ 	case NFA_UPPER:	STRCPY(code, "NFA_UPPER"); break;
++ 	case NFA_NUPPER:STRCPY(code, "NFA_NUPPER"); break;
++ 
++ 	default:
++ 	    STRCPY(code, "CHAR(x)");
++ 	    code[5] = c;
++     }
++ 
++     if (addnl == TRUE)
++ 	STRCAT(code, " + NEWLINE ");
++ 
++ }
++ 
++ #ifdef ENABLE_LOG
++ static FILE *log_fd;
++ 
++ /*
++  * Print the postfix notation of the current regexp.
++  */
++     static void
++ nfa_postfix_dump(expr, retval)
++     char_u  *expr;
++     int	    retval;
++ {
++     int *p;
++     FILE *f;
++ 
++     f = fopen("LOG.log", "a");
++     if (f != NULL)
++     {
++ 	fprintf(f, "\n-------------------------\n");
++ 	if (retval == FAIL)
++ 	    fprintf(f, ">>> NFA engine failed ... \n");
++ 	else if (retval == OK)
++ 	    fprintf(f, ">>> NFA engine succeeded !\n");
++ 	fprintf(f, "Regexp: \"%s\"\nPostfix notation (char): \"", expr);
++ 	for (p=post_start; *p; p++)
++ 	{
++ 	    nfa_set_code(*p);
++ 	    fprintf(f, "%s, ", code);
++ 	}
++ 	fprintf(f, "\"\nPostfix notation (int): ");
++ 	for (p=post_start; *p; p++)
++ 		fprintf(f, "%d ", *p);
++ 	fprintf(f, "\n\n");
++ 	fclose(f);
++     }
++ }
++ 
++ /*
++  * Print the NFA starting with a root node "state".
++  */
++     static void
++ nfa_print_state(debugf, state, ident)
++     FILE *debugf;
++     nfa_state_T *state;
++     int ident;
++ {
++     int i;
++ 
++     if (state == NULL)
++ 	return;
++ 
++     fprintf(debugf, "(%2d)", abs(state->id));
++     for (i = 0; i < ident; i++)
++ 	fprintf(debugf, "%c", ' ');
++ 
++     nfa_set_code(state->c);
++     fprintf(debugf, "%s %s (%d) (id=%d)\n",
++ 		 state->negated ? "NOT" : "", code, state->c, abs(state->id));
++     if (state->id < 0)
++ 	return;
++ 
++     state->id = abs(state->id) * -1;
++     nfa_print_state(debugf, state->out, ident + 4);
++     nfa_print_state(debugf, state->out1, ident + 4);
++ }
++ 
++ /*
++  * Print the NFA state machine.
++  */
++     static void
++ nfa_dump(prog)
++     nfa_regprog_T *prog;
++ {
++     FILE *debugf = fopen("LOG.log", "a");
++ 
++     if (debugf != NULL)
++     {
++ 	nfa_print_state(debugf, prog->start, 0);
++ 	fclose(debugf);
++     }
++ }
++ #endif	    /* ENABLE_LOG */
++ #endif	    /* DEBUG */
++ 
++ /*
++  * Parse r.e. @expr and convert it into postfix form.
++  * Return the postfix string on success, NULL otherwise.
++  */
++     static int *
++ re2post()
++ {
++     if (nfa_reg(REG_NOPAREN) == FAIL)
++ 	return NULL;
++     EMIT(NFA_MOPEN);
++     return post_start;
++ }
++ 
++ /* NB. Some of the code below is inspired by Russ's. */
++ 
++ /*
++  * Represents an NFA state plus zero or one or two arrows exiting.
++  * if c == MATCH, no arrows out; matching state.
++  * If c == SPLIT, unlabeled arrows to out and out1 (if != NULL).
++  * If c < 256, labeled arrow with character c to out.
++  */
++ 
++ static nfa_state_T	*state_ptr; /* points to nfa_prog->state */
++ 
++ /*
++  * Allocate and initialize nfa_state_T.
++  */
++     static nfa_state_T *
++ new_state(c, out, out1)
++     int		c;
++     nfa_state_T	*out;
++     nfa_state_T	*out1;
++ {
++     nfa_state_T *s;
++ 
++     if (istate >= nstate)
++ 	return NULL;
++ 
++     s = &state_ptr[istate++];
++ 
++     s->c    = c;
++     s->out  = out;
++     s->out1 = out1;
++ 
++     s->id   = istate;
++     s->lastlist = 0;
++     s->lastthread = NULL;
++     s->visits = 0;
++     s->negated = FALSE;
++ 
++     return s;
++ }
++ 
++ /*
++  * A partially built NFA without the matching state filled in.
++  * Frag_T.start points at the start state.
++  * Frag_T.out is a list of places that need to be set to the
++  * next state for this fragment.
++  */
++ typedef union Ptrlist Ptrlist;
++ struct Frag
++ {
++     nfa_state_T   *start;
++     Ptrlist	*out;
++ };
++ typedef struct Frag Frag_T;
++ 
++ static Frag_T frag __ARGS((nfa_state_T *start, Ptrlist *out));
++ static Ptrlist *list1 __ARGS((nfa_state_T **outp));
++ static void patch __ARGS((Ptrlist *l, nfa_state_T *s));
++ static Ptrlist *append __ARGS((Ptrlist *l1, Ptrlist *l2));
++ static void st_push __ARGS((Frag_T s, Frag_T **p, Frag_T *stack_end));
++ static Frag_T st_pop __ARGS((Frag_T **p, Frag_T *stack));
++ 
++ /*
++  * Initialize Frag_T struct.
++  */
++     static Frag_T
++ frag(start, out)
++     nfa_state_T	*start;
++     Ptrlist	*out;
++ {
++     Frag_T n = { start, out };
++     return n;
++ }
++ 
++ /*
++  * Since the out pointers in the list are always
++  * uninitialized, we use the pointers themselves
++  * as storage for the Ptrlists.
++  */
++ union Ptrlist
++ {
++     Ptrlist	*next;
++     nfa_state_T	*s;
++ };
++ 
++ /*
++  * Create singleton list containing just outp.
++  */
++     static Ptrlist *
++ list1(outp)
++     nfa_state_T	**outp;
++ {
++     Ptrlist *l;
++ 
++     l = (Ptrlist *)outp;
++     l->next = NULL;
++     return l;
++ }
++ 
++ /*
++  * Patch the list of states at out to point to start.
++  */
++     static void
++ patch(l, s)
++     Ptrlist	*l;
++     nfa_state_T	*s;
++ {
++     Ptrlist *next;
++ 
++     for (; l; l = next)
++     {
++ 	next = l->next;
++ 	l->s = s;
++     }
++ }
++ 
++ 
++ /*
++  * Join the two lists l1 and l2, returning the combination.
++  */
++     static Ptrlist *
++ append(l1, l2)
++     Ptrlist *l1;
++     Ptrlist *l2;
++ {
++     Ptrlist *oldl1;
++ 
++     oldl1 = l1;
++     while (l1->next)
++ 	l1 = l1->next;
++     l1->next = l2;
++     return oldl1;
++ }
++ 
++ /*
++  * Stack used for transforming postfix form into NFA.
++  */
++ static Frag_T empty;
++ 
++     static void
++ st_error(postfix, end, p)
++     int *postfix;
++     int *end;
++     int *p;
++ {
++     FILE *df;
++     int *p2;
++ 
++     df = fopen("stack.err", "a");
++     if (df)
++     {
++ 	fprintf(df, "Error popping the stack!\n");
++ #ifdef DEBUG
++ 	fprintf(df, "Current regexp is \"%s\"\n", nfa_regengine.expr);
++ #endif
++ 	fprintf(df, "Postfix form is: ");
++ #ifdef DEBUG
++ 	for (p2 = postfix; p2 < end; p2++)
++ 	{
++ 	    nfa_set_code(*p2);
++ 	    fprintf(df, "%s, ", code);
++ 	}
++ 	nfa_set_code(*p);
++ 	fprintf(df, "\nCurrent position is: ");
++ 	for (p2 = postfix; p2 <= p; p2 ++)
++ 	{
++ 	    nfa_set_code(*p2);
++ 	    fprintf(df, "%s, ", code);
++ 	}
++ #else
++ 	for (p2 = postfix; p2 < end; p2++)
++ 	{
++ 	    fprintf(df, "%d, ", *p2);
++ 	}
++ 	fprintf(df, "\nCurrent position is: ");
++ 	for (p2 = postfix; p2 <= p; p2 ++)
++ 	{
++ 	    fprintf(df, "%d, ", *p2);
++ 	}
++ #endif
++ 	fprintf(df, "\n--------------------------\n");
++ 	fclose(df);
++     }
++     EMSG(_("E874: (NFA) Could not pop the stack !"));
++ }
++ 
++ /*
++  * Push an item onto the stack.
++  */
++     static void
++ st_push(s, p, stack_end)
++     Frag_T s;
++     Frag_T **p;
++     Frag_T *stack_end;
++ {
++     Frag_T *stackp = *p;
++ 
++     if (stackp >= stack_end)
++ 	return;
++     *stackp = s;
++     *p = *p + 1;
++ }
++ 
++ /*
++  * Pop an item from the stack.
++  */
++     static Frag_T
++ st_pop(p, stack)
++     Frag_T **p;
++     Frag_T *stack;
++ {
++     Frag_T *stackp;
++ 
++     *p = *p - 1;
++     stackp = *p;
++     if (stackp < stack)
++ 	return empty;
++     return **p;
++ }
++ 
++ /*
++  * Convert a postfix form into its equivalent NFA.
++  * Return the NFA start state on success, NULL otherwise.
++  */
++     static nfa_state_T *
++ post2nfa(postfix, end, nfa_calc_size)
++     int		*postfix;
++     int		*end;
++     int		nfa_calc_size;
++ {
++     int		*p;
++     int		mopen;
++     int		mclose;
++     Frag_T	*stack = NULL;
++     Frag_T	*stackp = NULL;
++     Frag_T	*stack_end = NULL;
++     Frag_T	e1;
++     Frag_T	e2;
++     Frag_T	e;
++     nfa_state_T	*s;
++     nfa_state_T	*s1;
++     nfa_state_T	*matchstate;
++ 
++     if (postfix == NULL)
++ 	return NULL;
++ 
++ #define PUSH(s)	    st_push ((s), &stackp, stack_end)
++ #define POP()	    st_pop(&stackp, stack);		\
++ 		    if (stackp < stack)			\
++ 		    {					\
++ 			st_error(postfix, end, p);	\
++ 			return NULL;			\
++ 		    }
++ 
++     if (nfa_calc_size == FALSE)
++     {
++ 	/* Allocate space for the stack. Max states on the stack : nstate */
++ 	stack = (Frag_T *) lalloc((nstate + 1)*sizeof(Frag_T), TRUE);
++ 	stackp = stack;
++ 	stack_end = stack + NFA_STACK_SIZE;
++     }
++ 
++     for (p = postfix; p < end; ++p)
++     {
++ 	switch (*p)
++ 	{
++ 	case NFA_CONCAT:
++ 	    /* Catenation.
++ 	     * Pay attention: this operator does not exist
++ 	     * in the r.e. itself (it is implicit, really).
++ 	     * It is added when r.e. is translated to postfix
++ 	     * form in re2post().
++ 	     *
++ 	     * No new state added here. */
++ 	    if (nfa_calc_size == TRUE)
++ 	    {
++ 		nstate += 0;
++ 		break;
++ 	    }
++ 	    e2 = POP();
++ 	    e1 = POP();
++ 	    patch(e1.out, e2.start);
++ 	    PUSH(frag(e1.start, e2.out));
++ 	    break;
++ 
++ 	case NFA_NOT:
++ 	    /* Negation of a character */
++ 	    if (nfa_calc_size == TRUE)
++ 	    {
++ 		nstate += 0;
++ 		break;
++ 	    }
++ 	    e1 = POP();
++ 	    e1.start->negated = TRUE;
++ 	    if (e1.start->c == NFA_MULTIBYTE || e1.start->c == NFA_COMPOSING)
++ 		e1.start->out1->negated = TRUE;
++ 	    PUSH(e1);
++ 	    break;
++ 
++ 	case NFA_OR:
++ 	    /* Alternation */
++ 	    if (nfa_calc_size == TRUE)
++ 	    {
++ 		nstate ++;
++ 		break;
++ 	    }
++ 	    e2 = POP();
++ 	    e1 = POP();
++ 	    s = new_state(NFA_SPLIT, e1.start, e2.start);
++ 	    if (s == NULL)
++ 		return NULL;
++ 	    PUSH(frag(s, append(e1.out, e2.out)));
++ 	    break;
++ 
++ 	case NFA_STAR:
++ 	    /* Zero or more */
++ 	    if (nfa_calc_size == TRUE)
++ 	    {
++ 		nstate ++;
++ 		break;
++ 	    }
++ 	    e = POP();
++ 	    s = new_state(NFA_SPLIT, e.start, NULL);
++ 	    if (s == NULL)
++ 		return NULL;
++ 	    patch(e.out, s);
++ 	    PUSH(frag(s, list1(&s->out1)));
++ 	    break;
++ 
++ 	case NFA_QUEST:
++ 	    /* one or zero atoms=> greedy match */
++ 	    if (nfa_calc_size == TRUE)
++ 	    {
++ 		nstate ++;
++ 		break;
++ 	    }
++ 	    e = POP();
++ 	    s = new_state(NFA_SPLIT, e.start, NULL);
++ 	    if (s == NULL)
++ 		return NULL;
++ 	    PUSH(frag(s, append(e.out, list1(&s->out1))));
++ 	    break;
++ 
++ 	case NFA_QUEST_NONGREEDY:
++ 	    /* zero or one atoms => non-greedy match */
++ 	    if (nfa_calc_size == TRUE)
++ 	    {
++ 		nstate ++;
++ 		break;
++ 	    }
++ 	    e = POP();
++ 	    s = new_state(NFA_SPLIT, NULL, e.start);
++ 	    if (s == NULL)
++ 		return NULL;
++ 	    PUSH(frag(s, append(e.out, list1(&s->out))));
++ 	    break;
++ 
++ 	case NFA_PLUS:
++ 	    /* One or more */
++ 	    if (nfa_calc_size == TRUE)
++ 	    {
++ 		nstate ++;
++ 		break;
++ 	    }
++ 	    e = POP();
++ 	    s = new_state(NFA_SPLIT, e.start, NULL);
++ 	    if (s == NULL)
++ 		return NULL;
++ 	    patch(e.out, s);
++ 	    PUSH(frag(e.start, list1(&s->out1)));
++ 	    break;
++ 
++ 	case NFA_SKIP_CHAR:
++ 	    /* Symbol of 0-length, Used in a repetition
++ 	     * with max/min count of 0 */
++ 	    if (nfa_calc_size == TRUE)
++ 	    {
++ 		nstate ++;
++ 		break;
++ 	    }
++ 	    s = new_state(NFA_SKIP_CHAR, NULL, NULL);
++ 	    if (s == NULL)
++ 		return NULL;
++ 	    PUSH(frag(s, list1(&s->out)));
++ 	    break;
++ 
++ 	case NFA_PREV_ATOM_NO_WIDTH:
++ 	    /* The \@= operator: match the preceding atom with 0 width.
++ 	     * Surrounds the preceding atom with START_INVISIBLE and
++ 	     * END_INVISIBLE, similarly to MOPEN.
++ 	     */
++ 	    /* TODO: Maybe this drops the speed? */
++ 	    return NULL;
++ 
++ 	    if (nfa_calc_size == TRUE)
++ 	    {
++ 		nstate += 2;
++ 		break;
++ 	    }
++ 	    e = POP();
++ 	    s1 = new_state(NFA_END_INVISIBLE, NULL, NULL);
++ 	    if (s1 == NULL)
++ 		return NULL;
++ 	    patch(e.out, s1);
++ 
++ 	    s = new_state(NFA_START_INVISIBLE, e.start, s1);
++ 	    if (s == NULL)
++ 		return NULL;
++ 	    PUSH(frag(s, list1(&s1->out)));
++ 	    break;
++ 
++ 	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" */
++ 	case NFA_MULTIBYTE:	/* mbyte char */
++ 	case NFA_COMPOSING:	/* composing char */
++ 	    if (nfa_calc_size == TRUE)
++ 	    {
++ 		nstate += 2;
++ 		break;
++ 	    }
++ 
++ 	    mopen = *p;
++ 	    switch (*p)
++ 	    {
++ 		case NFA_NOPEN:
++ 		    mclose = NFA_NCLOSE;
++ 		    break;
++ 		case NFA_MULTIBYTE:
++ 		    mclose = NFA_END_MULTIBYTE;
++ 		    break;
++ 		case NFA_COMPOSING:
++ 		    mclose = NFA_END_COMPOSING;
++ 		    break;
++ 		default:
++ 		    /* NFA_MOPEN(0) ... NFA_MOPEN(9) */
++ 		    mclose = *p + NSUBEXP;
++ 		    break;
++ 	    }
++ 
++ 	    /* Allow "NFA_MOPEN" as a valid postfix representation for
++ 	     * the empty regexp "". In this case, the NFA will be
++ 	     * NFA_MOPEN -> NFA_MCLOSE. Note that this also allows
++ 	     * empty groups of parenthesis, and empty mbyte chars */
++ 	    if (stackp == stack)
++ 	    {
++ 		s = new_state(mopen, NULL, NULL);
++ 		if (s == NULL)
++ 		    return NULL;
++ 		s1 = new_state(mclose, NULL, NULL);
++ 		if (s1 == NULL)
++ 		    return NULL;
++ 		patch(list1(&s->out), s1);
++ 		PUSH(frag(s, list1(&s1->out)));
++ 		break;
++ 	    }
++ 
++ 	    /* At least one node was emitted before NFA_MOPEN, so
++ 	     * at least one node will be between NFA_MOPEN and NFA_MCLOSE */
++ 	    e = POP();
++ 	    s = new_state(mopen, e.start, NULL);   /* `(' */
++ 	    if (s == NULL)
++ 		return NULL;
++ 
++ 	    s1 = new_state(mclose, NULL, NULL);   /* `)' */
++ 	    if (s1 == NULL)
++ 		return NULL;
++ 	    patch(e.out, s1);
++ 
++ 	    if (mopen == NFA_MULTIBYTE || mopen == NFA_COMPOSING)
++ 		/* MULTIBYTE->out1 = END_MULTIBYTE
++ 		* COMPOSING->out1 = END_COMPOSING */
++ 		patch(list1(&s->out1), s1);
++ 
++ 	    PUSH(frag(s, list1(&s1->out)));
++ 	    break;
++ 
++ 	case NFA_ZSTART:
++ 	case NFA_ZEND:
++ 	default:
++ 	    /* Operands */
++ 	    if (nfa_calc_size == TRUE)
++ 	    {
++ 		nstate ++;
++ 		break;
++ 	    }
++ 	    s = new_state(*p, NULL, NULL);
++ 	    if (s == NULL)
++ 		return NULL;
++ 	    PUSH(frag(s, list1(&s->out)));
++ 	    break;
++ 
++ 	} /* switch(*p) */
++ 
++     } /* for(p = postfix; *p; ++p) */
++ 
++     if (nfa_calc_size == TRUE)
++     {
++ 	nstate ++;
++ 	return NULL;	/* Return value when counting size is ignored anyway */
++     }
++ 
++     e = POP();
++     if (stackp != stack)
++ 	EMSG_RET_NULL(_("E875: (NFA regexp) (While converting from postfix to NFA), too many states left on stack"));
++ 
++     if (istate >= nstate)
++ 	EMSG_RET_NULL(_("E876: (NFA regexp) Not enough space to store the whole NFA "));
++ 
++     vim_free(stack);
++ 
++     matchstate = &state_ptr[istate++]; /* the match state */
++     matchstate->c = NFA_MATCH;
++     matchstate->out = matchstate->out1 = NULL;
++ 
++     patch(e.out, matchstate);
++     return e.start;
++ 
++ #undef POP1
++ #undef PUSH1
++ #undef POP2
++ #undef PUSH2
++ #undef POP
++ #undef PUSH
++ }
++ 
++ /****************************************************************
++  * NFA execution code.
++  ****************************************************************/
++ 
++ /* thread_T contains runtime information of a NFA state */
++ struct thread
++ {
++     nfa_state_T	*state;
++     regsub_T	sub;		/* submatch info */
++ };
++ 
++ typedef struct
++ {
++     thread_T	*t;
++     int		n;
++ } List;
++ 
++ static void addstate __ARGS((List *l, nfa_state_T *state, regsub_T *m, int off, int lid, int *match));
++ 
++     static void
++ addstate(l, state, m, off, lid, match)
++     List		*l;	/* runtime state list */
++     nfa_state_T		*state;	/* state to update */
++     regsub_T		*m;	/* pointers to subexpressions */
++     int			off;
++     int			lid;
++     int			*match;	/* found match? */
++ {
++     regsub_T		save;
++     int			subidx = 0;
++ 
++     if (l == NULL || state == NULL)
++ 	return;
++ 
++     switch (state->c)
++     {
++ 	case NFA_SPLIT:
++ 	case NFA_NOT:
++ 	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:
++ 	    /* Do not remember these nodes in list "thislist" or "nextlist" */
++ 	    break;
++ 
++ 	default:
++ 	    if (state->lastlist == lid)
++ 	    {
++ 		if (++state->visits > 2)
++ 		    return;
++ 	    }
++ 	    else
++ 	    {
++ 		/* add the state to the list */
++ 		state->lastlist = lid;
++ 		state->lastthread = &l->t[l->n++];
++ 		state->lastthread->state = state;
++ 		state->lastthread->sub = *m;
++ 	    }
++     }
++ 
++ #ifdef ENABLE_LOG
++     nfa_set_code(state->c);
++     fprintf(log_fd, "> Adding state %d to list. Character %s, code %d\n",
++ 	abs(state->id), code, state->c);
++ #endif
++     switch (state->c)
++     {
++ 	case NFA_MATCH:
++ 	    *match = TRUE;
++ 	    break;
++ 
++ 	case NFA_SPLIT:
++ 	    addstate(l, state->out, m, off, lid, match);
++ 	    addstate(l, state->out1, m, off, lid, match);
++ 	    break;
++ 
++ 	case NFA_SKIP_CHAR:
++ 	    addstate(l, state->out, m, off, lid, match);
++ 	    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;
++ 
++ 	case NFA_MULTIBYTE:
++ 	    /* nfa_regmatch() will match all the bytes of this multibyte char. */
++ 	    break;
++ #endif
++ 
++ 	case NFA_END_MULTIBYTE:
++ 	    /* Successfully matched this mbyte char */
++ 	    addstate(l, state->out, m, off, lid, match);
++ 	    break;
++ 
++ 	case NFA_NOPEN:
++ 	case NFA_NCLOSE:
++ 	    addstate(l, state->out, m, off, lid, match);
++ 	    break;
++ 
++ 	/* If this state is reached, then a recursive call of nfa_regmatch()
++ 	 * succeeded. the next call saves the found submatches in the
++ 	 * first state after the "invisible" branch. */
++ #if 0
++ 	case NFA_END_INVISIBLE:
++ 	    break;
++ #endif
++ 
++ 	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:
++ 	    subidx = state->c - NFA_MOPEN;
++ 	    if (state->c == NFA_ZSTART)
++ 		subidx = 0;
++ 
++ 	    if (REG_MULTI)
++ 	    {
++ 		save.startpos[subidx] = m->startpos[subidx];
++ 		save.endpos[subidx] = m->endpos[subidx];
++ 		m->startpos[subidx].lnum = reglnum;
++ 		m->startpos[subidx].col = reginput - regline + off;
++ 	    }
++ 	    else
++ 	    {
++ 		save.start[subidx] = m->start[subidx];
++ 		save.end[subidx] = m->end[subidx];
++ 		m->start[subidx] = reginput + off;
++ 	    }
++ 
++ 	    addstate(l, state->out, m, off, lid, match);
++ 
++ 	    if (REG_MULTI)
++ 	    {
++ 		m->startpos[subidx] = save.startpos[subidx];
++ 		m->endpos[subidx] = save.endpos[subidx];
++ 	    }
++ 	    else
++ 	    {
++ 		m->start[subidx] = save.start[subidx];
++ 		m->end[subidx] = save.end[subidx];
++ 	    }
++ 	    break;
++ 
++ 	case NFA_MCLOSE + 0:
++ 	    if (nfa_has_zend == TRUE)
++ 	    {
++ 		addstate(l, state->out, m, off, lid, match);
++ 		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:
++ 	    subidx = state->c - NFA_MCLOSE;
++ 	    if (state->c == NFA_ZEND)
++ 		subidx = 0;
++ 
++ 	    if (REG_MULTI)
++ 	    {
++ 		save.startpos[subidx] = m->startpos[subidx];
++ 		save.endpos[subidx] = m->endpos[subidx];
++ 		m->endpos[subidx].lnum = reglnum;
++ 		m->endpos[subidx].col = reginput - regline + off;
++ 	    }
++ 	    else
++ 	    {
++ 		save.start[subidx] = m->start[subidx];
++ 		save.end[subidx] = m->end[subidx];
++ 		m->end[subidx] = reginput + off;
++ 	    }
++ 
++ 	    addstate(l, state->out, m, off, lid, match);
++ 
++ 	    if (REG_MULTI)
++ 	    {
++ 		m->startpos[subidx] = save.startpos[subidx];
++ 		m->endpos[subidx] = save.endpos[subidx];
++ 	    }
++ 	    else
++ 	    {
++ 		m->start[subidx] = save.start[subidx];
++ 		m->end[subidx] = save.end[subidx];
++ 	    }
++ 	    break;
++     }
++ }
++ 
++ /*
++  * Check character class "class" against current character c.
++  */
++     static int
++ check_char_class(class, c)
++     int		class;
++     int		c;
++ {
++     switch (class)
++     {
++ 	case NFA_CLASS_ALNUM:
++ 	    if (isalnum(c))
++ 		return OK;
++ 	    break;
++ 	case NFA_CLASS_ALPHA:
++ 	    if (isalpha(c))
++ 		return OK;
++ 	    break;
++ 	case NFA_CLASS_BLANK:
++ 	    if (c == ' ' || c == '\t')
++ 		return OK;
++ 	    break;
++ 	case NFA_CLASS_CNTRL:
++ 	    if (iscntrl(c))
++ 		return OK;
++ 	    break;
++ 	case NFA_CLASS_DIGIT:
++ 	    if (VIM_ISDIGIT(c))
++ 		return OK;
++ 	    break;
++ 	case NFA_CLASS_GRAPH:
++ 	    if (isgraph(c))
++ 		return OK;
++ 	    break;
++ 	case NFA_CLASS_LOWER:
++ 	    if (MB_ISLOWER(c))
++ 		return OK;
++ 	    break;
++ 	case NFA_CLASS_PRINT:
++ 	    if (vim_isprintc(c))
++ 		return OK;
++ 	    break;
++ 	case NFA_CLASS_PUNCT:
++ 	    if (ispunct(c))
++ 		return OK;
++ 	    break;
++ 	case NFA_CLASS_SPACE:
++ 	    if ((c >=9 && c <= 13) || (c == ' '))
++ 		return OK;
++ 	    break;
++ 	case NFA_CLASS_UPPER:
++ 	    if (MB_ISUPPER(c))
++ 		return OK;
++ 	    break;
++ 	case NFA_CLASS_XDIGIT:
++ 	    if (vim_isxdigit(c))
++ 		return OK;
++ 	    break;
++ 	case NFA_CLASS_TAB:
++ 	    if (c == '\t')
++ 		return OK;
++ 	    break;
++ 	case NFA_CLASS_RETURN:
++ 	    if (c == '\r')
++ 		return OK;
++ 	    break;
++ 	case NFA_CLASS_BACKSPACE:
++ 	    if (c == '\b')
++ 		return OK;
++ 	    break;
++ 	case NFA_CLASS_ESCAPE:
++ 	    if (c == '\033')
++ 		return OK;
++ 	    break;
++ 
++ 	default:
++ 	    /* should not be here :P */
++ 	    EMSG_RET_FAIL(_("E877: (NFA regexp) Invalid character class "));
++     }
++     return FAIL;
++ }
++ 
++ /*
++  * Set all NFA nodes' list ID equal to -1.
++  */
++     static void
++ nfa_set_neg_listids(start)
++     nfa_state_T	    *start;
++ {
++     if (start == NULL)
++ 	return;
++     if (start->lastlist >= 0)
++     {
++ 	start->lastlist = -1;
++ 	nfa_set_neg_listids(start->out);
++ 	nfa_set_neg_listids(start->out1);
++     }
++ }
++ 
++ /*
++  * Set all NFA nodes' list ID equal to 0.
++  */
++     static void
++ nfa_set_null_listids(start)
++     nfa_state_T	    *start;
++ {
++     if (start == NULL)
++ 	return;
++     if (start->lastlist == -1)
++     {
++ 	start->lastlist = 0;
++ 	nfa_set_null_listids(start->out);
++ 	nfa_set_null_listids(start->out1);
++     }
++ }
++ 
++ /*
++  * Save list IDs for all NFA states in "list".
++  */
++     static void
++ nfa_save_listids(start, list)
++     nfa_state_T	    *start;
++     int		    *list;
++ {
++     if (start == NULL)
++ 	return;
++     if (start->lastlist != -1)
++     {
++ 	list[abs(start->id)] = start->lastlist;
++ 	start->lastlist = -1;
++ 	nfa_save_listids(start->out, list);
++ 	nfa_save_listids(start->out1, list);
++     }
++ }
++ 
++ /*
++  * Restore list IDs from "list" to all NFA states.
++  */
++     static void
++ nfa_restore_listids(start, list)
++     nfa_state_T	    *start;
++     int		    *list;
++ {
++     if (start == NULL)
++ 	return;
++     if (start->lastlist == -1)
++     {
++ 	start->lastlist = list[abs(start->id)];
++ 	nfa_restore_listids(start->out, list);
++ 	nfa_restore_listids(start->out1, list);
++     }
++ }
++ 
++ /*
++  * Main matching routine.
++  *
++  * Run NFA to determine whether it matches reginput.
++  *
++  * Return TRUE if there is a match, FALSE otherwise.
++  * Note: Caller must ensure that: start != NULL.
++  */
++     static int
++ nfa_regmatch(start, submatch, m)
++     nfa_state_T		*start;
++     regsub_T		*submatch;
++     regsub_T		*m;
++ {
++     int		c = -1;
++     int		n;
++     int		i = 0;
++     int		result;
++     int		size = 0;
++     int		match = FALSE;
++     int		flag = 0;
++     int		old_reglnum = -1;
++     int		reginput_updated = FALSE;
++     thread_T	*t;
++     char_u	*cc;
++     char_u	*old_reginput = NULL;
++     char_u	*old_regline = NULL;
++     nfa_state_T	*sta;
++     nfa_state_T *end;
++     List	list[3];
++     List	*listtbl[2][2];
++     List	*ll;
++     int		listid = 1;
++     int		endnode = 0;
++     List	*thislist;
++     List	*nextlist;
++     List	*neglist;
++     int		*listids = NULL;
++     int		j = 0;
++     int		len = 0;
++ #ifdef DEBUG
++     FILE	*debug = fopen("list.log", "a");
++ 
++     if (debug == NULL)
++     {
++ 	EMSG(_("(NFA) COULD NOT OPEN list.log !"));
++ 	return FALSE;
++     }
++ #endif
++ 
++     /* Allocate memory for the lists of nodes */
++     size = (nstate + 1) * sizeof(thread_T);
++     list[0].t = (thread_T *)lalloc(size, TRUE);
++     list[1].t = (thread_T *)lalloc(size, TRUE);
++     list[2].t = (thread_T *)lalloc(size, TRUE);
++     if (list[0].t == NULL || list[1].t == NULL || list[2].t == NULL)
++ 	goto theend;
++     vim_memset(list[0].t, 0, size);
++     vim_memset(list[1].t, 0, size);
++     vim_memset(list[2].t, 0, size);
++ 
++ #ifdef ENABLE_LOG
++     log_fd = fopen(LOG_NAME, "a");
++     if (log_fd != NULL)
++     {
++ 	fprintf(log_fd, "**********************************\n");
++ 	nfa_set_code(start->c);
++ 	fprintf(log_fd, " RUNNING nfa_regmatch() starting with state %d, code %s\n",
++ 	abs(start->id), code);
++ 	fprintf(log_fd, "**********************************\n");
++     }
++     else
++     {
++ 	EMSG(_("Could not open temporary log file for writing, displaying on stderr ... "));
++ 	log_fd = stderr;
++     }
++ #endif
++ 
++     thislist = &list[0];
++     thislist->n = 0;
++     nextlist = &list[1];
++     nextlist->n = 0;
++     neglist = &list[2];
++     neglist->n = 0;
++ #ifdef ENABLE_LOG
++     fprintf(log_fd, "(---) STARTSTATE\n");
++ #endif
++     addstate(thislist, start, m, 0, listid, &match);
++ 
++     /* There are two cases when the NFA advances: 1. input char matches the
++      * NFA node and 2. input char does not match the NFA node, but the next
++      * node is NFA_NOT. The following macro calls addstate() according to
++      * these rules. It is used A LOT, so use the "listtbl" table for speed */
++     listtbl[0][0] = NULL;
++     listtbl[0][1] = neglist;
++     listtbl[1][0] = nextlist;
++     listtbl[1][1] = NULL;
++ #define	ADD_POS_NEG_STATE(node)						    \
++     ll = listtbl[result ? 1 : 0][node->negated];			    \
++     if (ll != NULL)							    \
++ 	addstate(ll, node->out , &t->sub, n, listid + 1, &match);
++ 
++ 
++     /*
++      * Run for each character.
++      */
++     do {
++ again:
++ #ifdef FEAT_MBYTE
++ 	if (has_mbyte)
++ 	{
++ 	    c = (*mb_ptr2char)(reginput);
++ 	    n = (*mb_ptr2len)(reginput);
++ 	}
++ 	else
++ #endif
++ 	{
++ 	    c = *reginput;
++ 	    n = 1;
++ 	}
++ 	if (c == NUL)
++ 	    n = 0;
++ 	cc = (char_u *)&c;
++ 
++ 	/* swap lists */
++ 	thislist = &list[flag];
++ 	nextlist = &list[flag ^= 1];
++ 	nextlist->n = 0;	    /* `clear' nextlist */
++ 	listtbl[1][0] = nextlist;
++ 	++listid;
++ 
++ #ifdef ENABLE_LOG
++ 	fprintf(log_fd, "------------------------------------------\n");
++ 	fprintf(log_fd, ">>> Reginput is \"%s\"\n", reginput);
++ 	fprintf(log_fd, ">>> Advanced one character ... Current char is %c (code %d) \n", c, (int)c);
++ 	fprintf(log_fd, ">>> Thislist has %d states available: ", thislist->n);
++ 	for (i = 0; i< thislist->n; i++)
++ 	    fprintf(log_fd, "%d  ", abs(thislist->t[i].state->id));
++ 	fprintf(log_fd, "\n");
++ #endif
++ 
++ #ifdef DEBUG
++ 	fprintf(debug, "\n-------------------\n");
++ #endif
++ 
++ 	/* compute nextlist */
++ 	for (i = 0; i < thislist->n || neglist->n > 0; ++i)
++ 	{
++ 	    if (neglist->n > 0)
++ 	    {
++ 		t = &neglist->t[0];
++ 		neglist->n --;
++ 		i--;
++ 	    }
++ 	    else
++ 		t = &thislist->t[i];
++ 
++ #ifdef DEBUG
++ 	    nfa_set_code(t->state->c);
++ 	    fprintf(debug, "%s, ", code);
++ #endif
++ #ifdef ENABLE_LOG
++ 	    nfa_set_code(t->state->c);
++ 	    fprintf(log_fd, "(%d) %s, code %d ... \n", abs(t->state->id),
++ 						      code, (int)t->state->c);
++ #endif
++ 
++ 	    /*
++ 	     * Handle the possible codes of the current state.
++ 	     * The most important is NFA_MATCH.
++ 	     */
++ 	    switch (t->state->c)
++ 	    {
++ 	    case NFA_MATCH:
++ 		match = TRUE;
++ 		*submatch = t->sub;
++ #ifdef ENABLE_LOG
++ 		for (j = 0; j < 4; j++)
++ 		    if (REG_MULTI)
++ 			fprintf(log_fd, "\n *** group %d, start: c=%d, l=%d, end: c=%d, l=%d",
++ 				j,
++ 				t->sub.startpos[j].col,
++ 				(int)t->sub.startpos[j].lnum,
++ 				t->sub.endpos[j].col,
++ 				(int)t->sub.endpos[j].lnum);
++ 		    else
++ 			fprintf(log_fd, "\n *** group %d, start: \"%s\", end: \"%s\"",
++ 				j,
++ 				(char *)t->sub.start[j],
++ 				(char *)t->sub.end[j]);
++ 		fprintf(log_fd, "\n");
++ #endif
++ 		goto nextchar;		/* found the left-most longest match */
++ 
++ 	    case NFA_END_INVISIBLE:
++ 		/* This is only encountered after a NFA_START_INVISIBLE node.
++ 		 * They surround a zero-width group, used with "\@=" and "\&".
++ 		 * If we got here, it means that the current "invisible" group
++ 		 * 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)
++ 		    addstate(thislist, t->state->out, &t->sub, 0, listid,
++ 								      &match);
++ 		else
++ 		{
++ 		    *m = t->sub;
++ 		    match = TRUE;
++ 		}
++ 		break;
++ 
++ 	    case NFA_START_INVISIBLE:
++ 		/* Save global variables, and call nfa_regmatch() to check if
++ 		 * the current concat matches at this position. The concat
++ 		 * ends with the node NFA_END_INVISIBLE */
++ 		old_reginput = reginput;
++ 		old_regline = regline;
++ 		old_reglnum = reglnum;
++ 		if (listids == NULL)
++ 		{
++ 		    listids = (int *) lalloc(sizeof(int) * nstate, TRUE);
++ 		    if (listids == NULL)
++ 		    {
++ 			EMSG(_("E878: (NFA) Could not allocate memory for branch traversal!"));
++ 			return 0;
++ 		    }
++ 		}
++ #ifdef ENABLE_LOG
++ 		if (log_fd != stderr)
++ 		    fclose(log_fd);
++ 		log_fd = NULL;
++ #endif
++ 		/* Have to clear the listid field of the NFA nodes, so that
++ 		 * nfa_regmatch() and addstate() can run properly after
++ 		 * recursion. */
++ 		nfa_save_listids(start, listids);
++ 		nfa_set_null_listids(start);
++ 		result = nfa_regmatch(t->state->out, submatch, m);
++ 		nfa_set_neg_listids(start);
++ 		nfa_restore_listids(start, listids);
++ 
++ #ifdef ENABLE_LOG
++ 		log_fd = fopen(LOG_NAME, "a");
++ 		if (log_fd != NULL)
++ 		{
++ 		    fprintf(log_fd, "****************************\n");
++ 		    fprintf(log_fd, "FINISHED RUNNING nfa_regmatch() recursively\n");
++ 		    fprintf(log_fd, "MATCH = %s\n", result == TRUE ? "OK" : "FALSE");
++ 		    fprintf(log_fd, "****************************\n");
++ 		}
++ 		else
++ 		{
++ 		    EMSG(_("Could not open temporary log file for writing, displaying on stderr ... "));
++ 		    log_fd = stderr;
++ 		}
++ #endif
++ 		if (result == TRUE)
++ 		{
++ 		    /* Restore position in input text */
++ 		    reginput = old_reginput;
++ 		    regline = old_regline;
++ 		    reglnum = old_reglnum;
++ 		    /* Copy submatch info from the recursive call */
++ 		    if (REG_MULTI)
++ 			for (j = 1; j < NSUBEXP; j++)
++ 			{
++ 			    t->sub.startpos[j] = m->startpos[j];
++ 			    t->sub.endpos[j] = m->endpos[j];
++ 			}
++ 		    else
++ 			for (j = 1; j < NSUBEXP; j++)
++ 			{
++ 			    t->sub.start[j] = m->start[j];
++ 			    t->sub.end[j] = m->end[j];
++ 			}
++ 		    /* t->state->out1 is the corresponding END_INVISIBLE node */
++ 		    addstate(thislist, t->state->out1->out, &t->sub, 0, listid,
++ 								    &match);
++ 		}
++ 		else
++ 		{
++ 		    /* continue with next input char */
++ 		    reginput = old_reginput;
++ 		}
++ 		break;
++ 
++ 	    case NFA_BOL:
++ 		if (reginput == regline)
++ 		    addstate(thislist, t->state->out, &t->sub, 0, listid,
++ 								    &match);
++ 		break;
++ 
++ 	    case NFA_EOL:
++ 		if (c == NUL)
++ 		    addstate(thislist, t->state->out, &t->sub, 0, listid,
++ 								    &match);
++ 		break;
++ 
++ 	    case NFA_BOW:
++ 	    {
++ 		int bow = TRUE;
++ 
++ 		if (c == NUL)
++ 		    bow = FALSE;
++ #ifdef FEAT_MBYTE
++ 		else if (has_mbyte)
++ 		{
++ 		    int this_class;
++ 
++ 		    /* Get class of current and previous char (if it exists). */
++ 		    this_class = mb_get_class(reginput);
++ 		    if (this_class <= 1)
++ 			bow = FALSE;
++ 		    else if (reg_prev_class() == this_class)
++ 			bow = FALSE;
++ 		}
++ #endif
++ 		else if (!vim_iswordc(c)
++ 			|| (reginput > regline && vim_iswordc(reginput[-1])))
++ 		    bow = FALSE;
++ 		if (bow)
++ 		    addstate(thislist, t->state->out, &t->sub, 0, listid,
++ 								    &match);
++ 		break;
++ 	    }
++ 
++ 	    case NFA_EOW:
++ 	    {
++ 		int eow = TRUE;
++ 
++ 		if (reginput == regline)
++ 		    eow = FALSE;
++ #ifdef FEAT_MBYTE
++ 		else if (has_mbyte)
++ 		{
++ 		    int this_class, prev_class;
++ 
++ 		    /* Get class of current and previous char (if it exists). */
++ 		    this_class = mb_get_class(reginput);
++ 		    prev_class = reg_prev_class();
++ 		    if (this_class == prev_class
++ 					|| prev_class == 0 || prev_class == 1)
++ 			eow = FALSE;
++ 		}
++ #endif
++ 		else if (!vim_iswordc(reginput[-1])
++ 				    || (reginput[0] != NUL && vim_iswordc(c)))
++ 		    eow = FALSE;
++ 		if (eow)
++ 		    addstate(thislist, t->state->out, &t->sub, 0, listid,
++ 								    &match);
++ 		break;
++ 	    }
++ 
++ 	    case NFA_MULTIBYTE:
++ 	    case NFA_COMPOSING:
++ 		switch (t->state->c)
++ 		{
++ 		    case NFA_MULTIBYTE:	    endnode = NFA_END_MULTIBYTE; break;
++ 		    case NFA_COMPOSING:	    endnode = NFA_END_COMPOSING; break;
++ 		    default:		    endnode = 0;
++ 		}
++ 
++ 		result = OK;
++ 		sta = t->state->out;
++ 		len = 1;
++ 		while (sta->c != endnode && len <= n)
++ 		{
++ 		    if (reginput[len-1] != sta->c)
++ 		    {
++ 			result = OK - 1;
++ 			break;
++ 		    }
++ 		    len++;
++ 		    sta = sta->out;
++ 		}
++ 
++ 		/* if input char length doesn't match regexp char length */
++ 		if (len -1 < n || sta->c != endnode)
++ 		    result = OK - 1;
++ 		end = t->state->out1;	    /* NFA_END_MULTIBYTE or
++ 					       NFA_END_COMPOSING */
++ 		/* If \Z was present, then ignore composing characters */
++ 		if (regflags & RF_ICOMBINE)
++ 		    result = 1 ^ sta->negated;
++ 		ADD_POS_NEG_STATE(end);
++ 		break;
++ 
++ 	    case NFA_NEWL:
++ 		if (!reg_line_lbr && REG_MULTI
++ 				&& c == NUL && reglnum <= reg_maxline)
++ 		{
++ 		    if (reginput_updated == FALSE)
++ 		    {
++ 			reg_nextline();
++ 			reginput_updated = TRUE;
++ 		    }
++ 		    addstate(nextlist, t->state->out, &t->sub, n, listid + 1,
++ 								    &match);
++ 		}
++ 		break;
++ 
++ 	    case NFA_CLASS_ALNUM:
++ 	    case NFA_CLASS_ALPHA:
++ 	    case NFA_CLASS_BLANK:
++ 	    case NFA_CLASS_CNTRL:
++ 	    case NFA_CLASS_DIGIT:
++ 	    case NFA_CLASS_GRAPH:
++ 	    case NFA_CLASS_LOWER:
++ 	    case NFA_CLASS_PRINT:
++ 	    case NFA_CLASS_PUNCT:
++ 	    case NFA_CLASS_SPACE:
++ 	    case NFA_CLASS_UPPER:
++ 	    case NFA_CLASS_XDIGIT:
++ 	    case NFA_CLASS_TAB:
++ 	    case NFA_CLASS_RETURN:
++ 	    case NFA_CLASS_BACKSPACE:
++ 	    case NFA_CLASS_ESCAPE:
++ 		result = check_char_class(t->state->c, c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_END_NEG_RANGE:
++ 		/* This follows a series of negated nodes, like:
++ 		 * CHAR(x), NFA_NOT, CHAR(y), NFA_NOT etc. */
++ 		if (c > 0)
++ 		    addstate(nextlist, t->state->out, &t->sub, n, listid + 1,
++ 								    &match);
++ 		break;
++ 
++ 	    case NFA_ANY:
++ 		/* Any printable char, not just any char. '\0' (end of input)
++ 		 * must not match */
++ 		if (c > 0)
++ 		    addstate(nextlist, t->state->out, &t->sub, n, listid + 1,
++ 								    &match);
++ 		break;
++ 
++ 	    /*
++ 	     * Character classes like \a for alpha, \d for digit etc.
++ 	     */
++ 	    case NFA_IDENT:	/*  \i	*/
++ 		result = vim_isIDc(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_SIDENT:	/*  \I	*/
++ 		result = !VIM_ISDIGIT(c) && vim_isIDc(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_KWORD:	/*  \k	*/
++ 		result = vim_iswordp(cc);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_SKWORD:	/*  \K	*/
++ 		result = !VIM_ISDIGIT(c) && vim_iswordp(cc);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_FNAME:	/*  \f	*/
++ 		result = vim_isfilec(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_SFNAME:	/*  \F	*/
++ 		result = !VIM_ISDIGIT(c) && vim_isfilec(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_PRINT:	/*  \p	*/
++ 		result = ptr2cells(cc) == 1;
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_SPRINT:	/*  \P	*/
++ 		result = !VIM_ISDIGIT(c) && ptr2cells(cc) == 1;
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_WHITE:	/*  \s	*/
++ 		result = vim_iswhite(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_NWHITE:	/*  \S	*/
++ 		result = c != NUL && !vim_iswhite(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_DIGIT:	/*  \d	*/
++ 		result = ri_digit(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_NDIGIT:	/*  \D	*/
++ 		result = c != NUL && !ri_digit(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_HEX:	/*  \x	*/
++ 		result = ri_hex(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_NHEX:	/*  \X	*/
++ 		result = c != NUL && !ri_hex(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_OCTAL:	/*  \o	*/
++ 		result = ri_octal(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_NOCTAL:	/*  \O	*/
++ 		result = c != NUL && !ri_octal(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_WORD:	/*  \w	*/
++ 		result = ri_word(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_NWORD:	/*  \W	*/
++ 		result = c != NUL && !ri_word(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_HEAD:	/*  \h	*/
++ 		result = ri_head(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_NHEAD:	/*  \H	*/
++ 		result = c != NUL && !ri_head(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_ALPHA:	/*  \a	*/
++ 		result = ri_alpha(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_NALPHA:	/*  \A	*/
++ 		result = c != NUL && !ri_alpha(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_LOWER:	/*  \l	*/
++ 		result = ri_lower(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_NLOWER:	/*  \L	*/
++ 		result = c != NUL && !ri_lower(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_UPPER:	/*  \u	*/
++ 		result = ri_upper(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    case NFA_NUPPER:	/* \U	*/
++ 		result = c != NUL && !ri_upper(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 
++ 	    default:	/* regular character */
++ 		result = (no_Magic(t->state->c) == c);
++ 		if (!result)
++ 		    result = ireg_ic == TRUE
++ 				&& MB_TOLOWER(t->state->c) == MB_TOLOWER(c);
++ 		ADD_POS_NEG_STATE(t->state);
++ 		break;
++ 	    }
++ 
++ 	} /* for (thislist = thislist; thislist->state; thislist++) */
++ 
++ 	/* The first found match is the leftmost one, but there may be a
++ 	 * longer one. Keep running the NFA, but don't start from the
++ 	 * beginning. Also, do not add the start state in recursive calls of
++ 	 * nfa_regmatch(), because recursive calls should only start in the
++ 	 * first position. */
++ 	if (match == FALSE && start->c == NFA_MOPEN + 0)
++ 	{
++ #ifdef ENABLE_LOG
++ 	    fprintf(log_fd, "(---) STARTSTATE\n");
++ #endif
++ 	    addstate(nextlist, start, m, n, listid + 1, &match);
++ 	}
++ 
++ 	if (reginput_updated)
++ 	{
++ 	    reginput_updated = FALSE;
++ 	    goto again;
++ 	}
++ 
++ #ifdef ENABLE_LOG
++ 	fprintf(log_fd, ">>> Thislist had %d states available: ", thislist->n);
++ 	for (i = 0; i< thislist->n; i++)
++ 	    fprintf(log_fd, "%d  ", abs(thislist->t[i].state->id));
++ 	fprintf(log_fd, "\n");
++ #endif
++ 
++ nextchar:
++ 	reginput += n;
++     } while (c || reginput_updated);
++ 
++ #ifdef ENABLE_LOG
++     if (log_fd != stderr)
++ 	fclose(log_fd);
++     log_fd = NULL;
++ #endif
++ 
++ theend:
++     /* Free memory */
++     vim_free(list[0].t);
++     vim_free(list[1].t);
++     vim_free(list[2].t);
++     list[0].t = list[1].t = list[2].t = NULL;
++     if (listids != NULL)
++ 	vim_free(listids);
++ #undef ADD_POS_NEG_STATE
++ #ifdef DEBUG
++     fclose(debug);
++ #endif
++ 
++     return match;
++ }
++ 
++ /*
++  * Try match of "prog" with at regline["col"].
++  * 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(LOG_NAME, "a");
++     if (f != NULL)
++     {
++ 	fprintf(f, "\n\n\n\n\n\n\t\t=======================================================\n");
++ 	fprintf(f, "		=======================================================\n");
++ #ifdef DEBUG
++ 	fprintf(f, "\tRegexp is \"%s\"\n", nfa_regengine.expr);
++ #endif
++ 	fprintf(f, "\tInput text is \"%s\" \n", reginput);
++ 	fprintf(f, "		=======================================================\n\n\n\n\n\n\n");
++ 	nfa_print_state(f, start, 0);
++ 	fprintf(f, "\n\n");
++ 	fclose(f);
++     }
++     else
++ 	EMSG(_("Could not open temporary log file for writing "));
++ #endif
++ 
++     if (REG_MULTI)
++     {
++ 	/* Use 0xff to set lnum to -1 */
++ 	vim_memset(sub.startpos, 0xff, sizeof(lpos_T) * NSUBEXP);
++ 	vim_memset(sub.endpos, 0xff, sizeof(lpos_T) * NSUBEXP);
++ 	vim_memset(m.startpos, 0xff, sizeof(lpos_T) * NSUBEXP);
++ 	vim_memset(m.endpos, 0xff, sizeof(lpos_T) * NSUBEXP);
++     }
++     else
++     {
++ 	vim_memset(sub.start, 0, sizeof(char_u *) * NSUBEXP);
++ 	vim_memset(sub.end, 0, sizeof(char_u *) * NSUBEXP);
++ 	vim_memset(m.start, 0, sizeof(char_u *) * NSUBEXP);
++ 	vim_memset(m.end, 0, sizeof(char_u *) * NSUBEXP);
++     }
++ 
++     if (nfa_regmatch(start, &sub, &m) == FALSE)
++ 	return 0;
++ 
++     cleanup_subexpr();
++     if (REG_MULTI)
++     {
++ 	for (i = 0; i < NSUBEXP; i++)
++ 	{
++ 	    reg_startpos[i] = sub.startpos[i];
++ 	    reg_endpos[i] = sub.endpos[i];
++ 	}
++ 
++ 	if (reg_startpos[0].lnum < 0)
++ 	{
++ 	    reg_startpos[0].lnum = 0;
++ 	    reg_startpos[0].col = col;
++ 	}
++ 	if (reg_endpos[0].lnum < 0)
++ 	{
++ 	    reg_endpos[0].lnum = reglnum;
++ 	    reg_endpos[0].col = (int)(reginput - regline);
++ 	}
++ 	else
++ 	    /* Use line number of "\ze". */
++ 	    reglnum = reg_endpos[0].lnum;
++     }
++     else
++     {
++ 	for (i = 0; i < NSUBEXP; i++)
++ 	{
++ 	    reg_startp[i] = sub.start[i];
++ 	    reg_endp[i] = sub.end[i];
++ 	}
++ 
++ 	if (reg_startp[0] == NULL)
++ 	    reg_startp[0] = regline + col;
++ 	if (reg_endp[0] == NULL)
++ 	    reg_endp[0] = reginput;
++     }
++ 
++     return 1 + reglnum;
++ }
++ 
++ /*
++  * Match a regexp against a string ("line" points to the string) or multiple
++  * lines ("line" is NULL, use reg_getline()).
++  *
++  * Returns 0 for failure, number of lines contained in the match otherwise.
++  */
++     static long
++ nfa_regexec_both(line, col)
++     char_u	*line;
++     colnr_T	col;		/* column to start looking for match */
++ {
++     nfa_regprog_T   *prog;
++     long	    retval = 0L;
++     int		    i;
++ 
++     if (REG_MULTI)
++     {
++ 	prog = (nfa_regprog_T *)reg_mmatch->regprog;
++ 	line = reg_getline((linenr_T)0);    /* relative to the cursor */
++ 	reg_startpos = reg_mmatch->startpos;
++ 	reg_endpos = reg_mmatch->endpos;
++     }
++     else
++     {
++ 	prog = (nfa_regprog_T *)reg_match->regprog;
++ 	reg_startp = reg_match->startp;
++ 	reg_endp = reg_match->endp;
++     }
++ 
++     /* Be paranoid... */
++     if (prog == NULL || line == NULL)
++     {
++ 	EMSG(_(e_null));
++ 	goto theend;
++     }
++ 
++     /* If the start column is past the maximum column: no need to try. */
++     if (ireg_maxcol > 0 && col >= ireg_maxcol)
++ 	goto theend;
++ 
++     /* If pattern contains "\c" or "\C": overrule value of ireg_ic */
++     if (prog->regflags & RF_ICASE)
++ 	ireg_ic = TRUE;
++     else if (prog->regflags & RF_NOICASE)
++ 	ireg_ic = FALSE;
++ 
++ #ifdef FEAT_MBYTE
++     /* If pattern contains "\Z" overrule value of ireg_icombine */
++     if (prog->regflags & RF_ICOMBINE)
++ 	ireg_icombine = TRUE;
++ #endif
++ 
++     regline = line;
++     reglnum = 0;    /* relative to line */
++ 
++     nstate = prog->nstate;
++ 
++     for (i = 0; i < nstate; ++i)
++     {
++ 	prog->state[i].id = i;
++ 	prog->state[i].lastlist = 0;
++ 	prog->state[i].visits = 0;
++ 	prog->state[i].lastthread = NULL;
++     }
++ 
++     retval = nfa_regtry(prog->start, col);
++ 
++ theend:
++     return retval;
++ }
++ 
++ /*
++  * Compile a regular expression into internal code for the NFA matcher.
++  * Returns the program in allocated space.  Returns NULL for an error.
++  */
++     static regprog_T *
++ nfa_regcomp(expr, re_flags)
++     char_u	*expr;
++     int		re_flags;
++ {
++     nfa_regprog_T	*prog;
++     int			prog_size;
++     int			*postfix;
++ 
++     if (expr == NULL)
++ 	return NULL;
++ 
++ #ifdef DEBUG
++     nfa_regengine.expr = expr;
++ #endif
++ 
++     init_class_tab();
++ 
++     if (nfa_regcomp_start(expr, re_flags) == FAIL)
++ 	return NULL;
++ 
++     /* Space for compiled regexp */
++     prog_size = sizeof(nfa_regprog_T) + sizeof(nfa_state_T) * nstate_max;
++     prog = (nfa_regprog_T *)lalloc(prog_size, TRUE);
++     if (prog == NULL)
++ 	goto fail;
++     vim_memset(prog, 0, prog_size);
++ 
++     /* Build postfix form of the regexp. Needed to build the NFA
++      * (and count its size) */
++     postfix = re2post();
++     if (postfix == NULL)
++ 	goto fail;	    /* Cascaded (syntax?) error */
++ 
++     /*
++      * In order to build the NFA, we parse the input regexp twice:
++      * 1. first pass to count size (so we can allocate space)
++      * 2. second to emit code
++      */
++ #ifdef ENABLE_LOG
++     {
++ 	FILE *f = fopen(LOG_NAME, "a");
++ 
++ 	if (f != NULL)
++ 	{
++ 	    fprintf(f, "\n*****************************\n\n\n\n\tCompiling regexp \"%s\" ... hold on !\n", expr);
++ 	    fclose(f);
++ 	}
++     }
++ #endif
++ 
++     /*
++      * PASS 1
++      * Count number of NFA states in "nstate". Do not build the NFA.
++      */
++     post2nfa(postfix, post_ptr, TRUE);
++     state_ptr = prog->state;
++ 
++     /*
++      * PASS 2
++      * Build the NFA
++      */
++     prog->start = post2nfa(postfix, post_ptr, FALSE);
++     if (prog->start == NULL)
++ 	goto fail;
++ 
++     prog->regflags = regflags;
++     prog->engine = &nfa_regengine;
++     prog->nstate = nstate;
++ #ifdef ENABLE_LOG
++     nfa_postfix_dump(expr, OK);
++     nfa_dump(prog);
++ #endif
++ 
++ out:
++     vim_free(post_start);
++     post_start = post_ptr = post_end = NULL;
++     state_ptr = NULL;
++     return (regprog_T *)prog;
++ 
++ fail:
++     vim_free(prog);
++     prog = NULL;
++ #ifdef ENABLE_LOG
++     nfa_postfix_dump(expr, FAIL);
++ #endif
++ #ifdef DEBUG
++     nfa_regengine.expr = NULL;
++ #endif
++     goto out;
++ }
++ 
++ 
++ /*
++  * Match a regexp against a string.
++  * "rmp->regprog" is a compiled regexp as returned by nfa_regcomp().
++  * Uses curbuf for line count and 'iskeyword'.
++  *
++  * Return TRUE if there is a match, FALSE if not.
++  */
++     static int
++ nfa_regexec(rmp, line, col)
++     regmatch_T	*rmp;
++     char_u	*line;	/* string to match against */
++     colnr_T	col;	/* column to start looking for match */
++ {
++     reg_match = rmp;
++     reg_mmatch = NULL;
++     reg_maxline = 0;
++     reg_line_lbr = FALSE;
++     reg_buf = curbuf;
++     reg_win = NULL;
++     ireg_ic = rmp->rm_ic;
++ #ifdef FEAT_MBYTE
++     ireg_icombine = FALSE;
++ #endif
++     ireg_maxcol = 0;
++     return (nfa_regexec_both(line, col) != 0);
++ }
++ 
++ #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) \
++ 	|| defined(FIND_REPLACE_DIALOG) || defined(PROTO)
++ 
++ static int  nfa_regexec_nl __ARGS((regmatch_T *rmp, char_u *line, colnr_T col));
++ 
++ /*
++  * Like nfa_regexec(), but consider a "\n" in "line" to be a line break.
++  */
++     static int
++ nfa_regexec_nl(rmp, line, col)
++     regmatch_T	*rmp;
++     char_u	*line;	/* string to match against */
++     colnr_T	col;	/* column to start looking for match */
++ {
++     reg_match = rmp;
++     reg_mmatch = NULL;
++     reg_maxline = 0;
++     reg_line_lbr = TRUE;
++     reg_buf = curbuf;
++     reg_win = NULL;
++     ireg_ic = rmp->rm_ic;
++ #ifdef FEAT_MBYTE
++     ireg_icombine = FALSE;
++ #endif
++     ireg_maxcol = 0;
++     return (nfa_regexec_both(line, col) != 0);
++ }
++ #endif
++ 
++ 
++ /*
++  * Match a regexp against multiple lines.
++  * "rmp->regprog" is a compiled regexp as returned by vim_regcomp().
++  * Uses curbuf for line count and 'iskeyword'.
++  *
++  * Return zero if there is no match.  Return number of lines contained in the
++  * match otherwise.
++  *
++  * Note: the body is the same as bt_regexec() except for nfa_regexec_both()
++  *
++  * ! Also NOTE : match may actually be in another line. e.g.:
++  * when r.e. is \nc, cursor is at 'a' and the text buffer looks like
++  *
++  * +-------------------------+
++  * |a                        |
++  * |b                        |
++  * |c                        |
++  * |                         |
++  * +-------------------------+
++  *
++  * then nfa_regexec_multi() returns 3. while the original
++  * vim_regexec_multi() returns 0 and a second call at line 2 will return 2.
++  *
++  * FIXME if this behavior is not compatible.
++  */
++     static long
++ nfa_regexec_multi(rmp, win, buf, lnum, col, tm)
++     regmmatch_T	*rmp;
++     win_T	*win;		/* window in which to search or NULL */
++     buf_T	*buf;		/* buffer in which to search */
++     linenr_T	lnum;		/* nr of line to start looking for match */
++     colnr_T	col;		/* column to start looking for match */
++     proftime_T	*tm UNUSED;	/* timeout limit or NULL */
++ {
++     long	r;
++     buf_T	*save_curbuf = curbuf;
++ 
++     reg_match = NULL;
++     reg_mmatch = rmp;
++     reg_buf = buf;
++     reg_win = win;
++     reg_firstlnum = lnum;
++     reg_maxline = reg_buf->b_ml.ml_line_count - lnum;
++     reg_line_lbr = FALSE;
++     ireg_ic = rmp->rmm_ic;
++ #ifdef FEAT_MBYTE
++     ireg_icombine = FALSE;
++ #endif
++     ireg_maxcol = rmp->rmm_maxcol;
++ 
++     /* Need to switch to buffer "buf" to make vim_iswordc() work. */
++     curbuf = buf;
++     r = nfa_regexec_both(NULL, col);
++     curbuf = save_curbuf;
++ 
++     return r;
++ }
++ 
++ #ifdef DEBUG
++ # undef ENABLE_LOG
++ #endif
+*** ../vim-7.3.969/src/structs.h	2013-05-15 15:12:25.000000000 +0200
+--- src/structs.h	2013-05-17 18:54:19.000000000 +0200
+***************
+*** 63,77 ****
+  
+  #define GA_EMPTY    {0, 0, 0, 0, NULL}
+  
+- /*
+-  * This is here because regexp.h needs pos_T and below regprog_T is used.
+-  */
+- #include "regexp.h"
+- 
+  typedef struct window_S		win_T;
+  typedef struct wininfo_S	wininfo_T;
+  typedef struct frame_S		frame_T;
+  typedef int			scid_T;		/* script ID */
+  
+  /*
+   * This is here because gui.h needs the pos_T and win_T, and win_T needs gui.h
+--- 63,78 ----
+  
+  #define GA_EMPTY    {0, 0, 0, 0, NULL}
+  
+  typedef struct window_S		win_T;
+  typedef struct wininfo_S	wininfo_T;
+  typedef struct frame_S		frame_T;
+  typedef int			scid_T;		/* script ID */
++ typedef struct file_buffer	buf_T;  /* forward declaration */
++ 
++ /*
++  * This is here because regexp.h needs pos_T and below regprog_T is used.
++  */
++ #include "regexp.h"
+  
+  /*
+   * This is here because gui.h needs the pos_T and win_T, and win_T needs gui.h
+***************
+*** 526,533 ****
+  # endif
+  } cmdmod_T;
+  
+- typedef struct file_buffer buf_T;  /* forward declaration */
+- 
+  #define MF_SEED_LEN	8
+  
+  struct memfile
+--- 527,532 ----
+*** ../vim-7.3.969/src/testdir/Makefile	2013-04-24 12:56:13.000000000 +0200
+--- src/testdir/Makefile	2013-05-18 14:22:50.000000000 +0200
+***************
+*** 29,35 ****
+  		test79.out test80.out test81.out test82.out test83.out \
+  		test84.out test85.out test86.out test87.out test88.out \
+  		test89.out test90.out test91.out test92.out test93.out \
+! 		test94.out
+  
+  SCRIPTS_GUI = test16.out
+  
+--- 29,35 ----
+  		test79.out test80.out test81.out test82.out test83.out \
+  		test84.out test85.out test86.out test87.out test88.out \
+  		test89.out test90.out test91.out test92.out test93.out \
+! 		test94.out test95.out
+  
+  SCRIPTS_GUI = test16.out
+  
+***************
+*** 85,97 ****
+  		fi"
+  
+  	# Check if the test.out file matches test.ok.
+! 	@/bin/sh -c "if test -f test.out; then\
+  		  if diff test.out $*.ok; \
+  		  then mv -f test.out $*.out; \
+  		  else echo $* FAILED >>test.log; mv -f test.out $*.failed; \
+  		  fi \
+  		else echo $* NO OUTPUT >>test.log; \
+  		fi"
+  	-rm -rf X* test.ok viminfo
+  
+  test49.out: test49.vim
+--- 85,100 ----
+  		fi"
+  
+  	# Check if the test.out file matches test.ok.
+! 	@/bin/sh -c "if test -f test.out; then \
+  		  if diff test.out $*.ok; \
+  		  then mv -f test.out $*.out; \
+  		  else echo $* FAILED >>test.log; mv -f test.out $*.failed; \
+  		  fi \
+  		else echo $* NO OUTPUT >>test.log; \
+  		fi"
++ 	@/bin/sh -c "if test -f valgrind; then\
++ 		  mv -f valgrind valgrind.$*; \
++ 		fi"
+  	-rm -rf X* test.ok viminfo
+  
+  test49.out: test49.vim
+*** ../vim-7.3.969/src/testdir/test64.in	2010-08-15 21:57:29.000000000 +0200
+--- src/testdir/test64.in	2013-05-19 16:05:36.000000000 +0200
+***************
+*** 1,4 ****
+! Test for regexp patterns.
+  
+  A pattern that gives the expected result produces OK, so that we know it was
+  actually tried.
+--- 1,5 ----
+! Test for regexp patterns without multi-byte support.
+! See test95 for multi-byte tests.
+  
+  A pattern that gives the expected result produces OK, so that we know it was
+  actually tried.
+***************
+*** 14,19 ****
+--- 15,25 ----
+  :"    etc.
+  :"  When there is no match use only the first two items.
+  :let tl = []
++ 
++ :""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
++ :"""" Previously written tests """"""""""""""""""""""""""""""""
++ :""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
++ 
+  :call add(tl, ['ab', 'aab', 'ab'])
+  :call add(tl, ['b', 'abcdef', 'b'])
+  :call add(tl, ['bc*', 'abccccdef', 'bcccc'])
+***************
+*** 132,137 ****
+--- 138,301 ----
+  :"
+  :call add(tl, ['\v(a*)+', 'aaaa', 'aaaa', ''])
+  :call add(tl, ['x', 'abcdef'])
++ 
++ :""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
++ :""""" Simple tests """""""""""""""""""""""""""""""""""""""""""
++ :""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
++ 
++ :" Search single groups
++ :call add(tl, ['ab', 'aab', 'ab'])
++ :call add(tl, ['ab', 'baced'])
++ :call add(tl, ['ab', '                    ab           ', 'ab'])
++ 
++ :" Search multi-modifiers
++ :call add(tl, ['x*', 'xcd', 'x'])
++ :call add(tl, ['x*', 'xxxxxxxxxxxxxxxxsofijiojgf', 'xxxxxxxxxxxxxxxx'])
++ :call add(tl, ['x*', 'abcdoij', ''])                    " empty match is good
++ :call add(tl, ['x\+', 'abcdoin'])                       " no match here
++ :call add(tl, ['x\+', 'abcdeoijdfxxiuhfij', 'xx'])
++ :call add(tl, ['x\+', 'xxxxx', 'xxxxx'])
++ :call add(tl, ['x\+', 'abc x siufhiush xxxxxxxxx', 'x'])
++ :call add(tl, ['x\=', 'x sdfoij', 'x'])
++ :call add(tl, ['x\=', 'abc sfoij', '']) " empty match is good
++ :call add(tl, ['x\=', 'xxxxxxxxx c', 'x'])
++ :call add(tl, ['x\?', 'x sdfoij', 'x'])
++ :call add(tl, ['x\?', 'abc sfoij', ''])                 " empty match is good
++ :call add(tl, ['x\?', 'xxxxxxxxxx c', 'x'])
++ 
++ :call add(tl, ['a\{0,0}', 'abcdfdoij', ''])
++ :call add(tl, ['a\{0,1}', 'asiubid axxxaaa', 'a'])      " same thing as 'a?'
++ :call add(tl, ['a\{1,0}', 'asiubid axxxaaa', 'a'])      " same thing as 'a\{0,1}'
++ :call add(tl, ['a\{3,6}', 'aa siofuh'])
++ :call add(tl, ['a\{3,6}', 'aaaaa asfoij afaa', 'aaaaa'])
++ :call add(tl, ['a\{3,6}', 'aaaaaaaa', 'aaaaaa'])
++ :call add(tl, ['a\{0}', 'asoiuj', ''])
++ :call add(tl, ['a\{2}', 'aaaa', 'aa'])
++ :call add(tl, ['a\{2}', 'iuash fiusahfliusah fiushfilushfi uhsaifuh askfj nasfvius afg aaaa sfiuhuhiushf', 'aa'])
++ :call add(tl, ['a\{2}', 'abcdefghijklmnopqrestuvwxyz1234567890'])
++ :call add(tl, ['a\{0,}', 'oij sdigfusnf', ''])          " same thing as 'a*'
++ :call add(tl, ['a\{0,}', 'aaaaa aa', 'aaaaa'])
++ :call add(tl, ['a\{2,}', 'sdfiougjdsafg'])
++ :call add(tl, ['a\{2,}', 'aaaaasfoij ', 'aaaaa'])
++ :call add(tl, ['a\{,0}', 'oidfguih iuhi hiu aaaa', ''])
++ :call add(tl, ['a\{,5}', 'abcd', 'a'])
++ :call add(tl, ['a\{,5}', 'aaaaaaaaaa', 'aaaaa'])
++ :call add(tl, ['a\{}', 'bbbcddiuhfcd', ''])                 " same thing as 'a*'
++ :call add(tl, ['a\{}', 'aaaaioudfh coisf jda', 'aaaa'])
++ 
++ :call add(tl, ['a\{-0,0}', 'abcdfdoij', ''])
++ :call add(tl, ['a\{-0,1}', 'asiubid axxxaaa', ''])      " anti-greedy version of 'a?'
++ :call add(tl, ['a\{-3,6}', 'aa siofuh'])
++ :call add(tl, ['a\{-3,6}', 'aaaaa asfoij afaa', 'aaa'])
++ :call add(tl, ['a\{-3,6}', 'aaaaaaaa', 'aaa'])
++ :call add(tl, ['a\{-0}', 'asoiuj', ''])
++ :call add(tl, ['a\{-2}', 'aaaa', 'aa'])
++ :call add(tl, ['a\{-2}', 'abcdefghijklmnopqrestuvwxyz1234567890'])
++ :call add(tl, ['a\{-0,}', 'oij sdigfusnf', ''])
++ :call add(tl, ['a\{-0,}', 'aaaaa aa', ''])
++ :call add(tl, ['a\{-2,}', 'sdfiougjdsafg'])
++ :call add(tl, ['a\{-2,}', 'aaaaasfoij ', 'aa'])
++ :call add(tl, ['a\{-,0}', 'oidfguih iuhi hiu aaaa', ''])
++ :call add(tl, ['a\{-,5}', 'abcd', ''])
++ :call add(tl, ['a\{-,5}', 'aaaaaaaaaa', ''])
++ :call add(tl, ['a\{-}', 'bbbcddiuhfcd', ''])            " anti-greedy version of 'a*'
++ :call add(tl, ['a\{-}', 'aaaaioudfh coisf jda', ''])
++ 
++ :" Test groups of characters and submatches
++ :call add(tl, ['\(abc\)*', 'abcabcabc', 'abcabcabc', 'abc'])
++ :call add(tl, ['\(ab\)\+', 'abababaaaaa', 'ababab', 'ab'])
++ :call add(tl, ['\(abaaaaa\)*cd', 'cd', 'cd', ''])
++ :call add(tl, ['\(test1\)\? \(test2\)\?', 'test1 test3', 'test1 ', 'test1', ''])
++ :call add(tl, ['\(test1\)\= \(test2\) \(test4443\)\=', ' test2 test4443 yupiiiiiiiiiii', ' test2 test4443', '', 'test2', 'test4443'])
++ :call add(tl, ['\(\(sub1\) hello \(sub 2\)\)', 'asterix sub1 hello sub 2 obelix', 'sub1 hello sub 2', 'sub1 hello sub 2', 'sub1', 'sub 2'])
++ :call add(tl, ['\(\(\(yyxxzz\)\)\)', 'abcdddsfiusfyyzzxxyyxxzz', 'yyxxzz', 'yyxxzz', 'yyxxzz', 'yyxxzz'])
++ :call add(tl, ['\v((ab)+|c+)+', 'abcccaba', 'abcccab', 'ab', 'ab'])
++ :call add(tl, ['\v((ab)|c*)+', 'abcccaba', 'abcccab', '', 'ab'])
++ :call add(tl, ['\v(a(c*)+b)+', 'acbababaaa', 'acbabab', 'ab', ''])
++ :call add(tl, ['\v(a|b*)+', 'aaaa', 'aaaa', ''])
++ 
++ :" Test greedy-ness and lazy-ness
++ :call add(tl, ['a\{-2,7}','aaaaaaaaaaaaa', 'aa'])
++ :call add(tl, ['a\{2,7}','aaaaaaaaaaaaaaaaaaaa', 'aaaaaaa'])
++ :call add(tl, ['\vx(.{-,8})yz(.*)','xayxayzxayzxayz','xayxayzxayzxayz','ayxa','xayzxayz'])
++ :call add(tl, ['\vx(.*)yz(.*)','xayxayzxayzxayz','xayxayzxayzxayz', 'ayxayzxayzxa',''])
++ :call add(tl, ['\v(a{1,2}){-2,3}','aaaaaaa','aaaa','aa'])
++ :call add(tl, ['\v(a{-1,3})+','aa','aa','a'])
++ 
++ :" Test Character classes
++ :call add(tl, ['\d\+e\d\d','test 10e23 fd','10e23'])
++ 
++ :" Test collections and character range []
++ :call add(tl, ['\v[a]', 'abcd', 'a'])
++ :call add(tl, ['a[bcd]', 'abcd', 'ab'])
++ :call add(tl, ['a[b-d]', 'acbd', 'ac'])
++ :call add(tl, ['[a-d][e-f][x-x]d', 'cexdxx', 'cexd'])
++ :call add(tl, ['\v[[:alpha:]]+', 'abcdefghijklmnopqrstuvwxyz6','abcdefghijklmnopqrstuvwxyz'])
++ :call add(tl, ['[[:alpha:]\+]', '6x8','x'])
++ :call add(tl, ['[^abc]\+','abcabcabc'])
++ :call add(tl, ['[^abc]','defghiasijvoinasoiunbvb','d'])
++ :call add(tl, ['[^abc]\+','ddddddda','ddddddd'])
++ :call add(tl, ['[^a-d]\+','aaaAAAZIHFNCddd','AAAZIHFNC'])
++ :call add(tl, ['[a-f]*','iiiiiiii',''])
++ :call add(tl, ['[a-f]*','abcdefgh','abcdef'])
++ :call add(tl, ['[^a-f]\+','abcdefgh','gh'])
++ :call add(tl, ['[a-c]\{-3,6}','abcabc','abc'])
++ :call add(tl, ['[^[:alpha:]]\+','abcccadfoij7787ysf287yrnccdu','7787'])
++ :call add(tl, ['[-a]', '-', '-'])
++ :call add(tl, ['[a-]', '-', '-'])
++ :call add(tl, ['[-./[:alnum:]_~]\+', 'log13.file', 'log13.file'])		" filename regexp
++ :call add(tl, ['[\]\^\-\\]\+', '\^\\\-\---^', '\^\\\-\---^'])			" special chars
++ :call add(tl, ['[[.a.]]\+', 'aa', 'aa'])								" collation elem
++ :call add(tl, ['abc[0-9]*ddd', 'siuhabc ii'])							" middle of regexp
++ :call add(tl, ['abc[0-9]*ddd', 'adf abc44482ddd oijs', 'abc44482ddd'])
++ :call add(tl, ['\_[0-9]\+', 'asfi9888u', '9888'])
++ :call add(tl, ['[0-9\n]\+', 'asfi9888u', '9888'])
++ 
++ 
++ :"""" Test recognition of some character classes
++ :call add(tl, ['[0-9]', '8', '8'])
++ :call add(tl, ['[^0-9]', '8'])
++ :call add(tl, ['[0-9a-fA-F]*', '0a7', '0a7'])
++ :call add(tl, ['[^0-9A-Fa-f]\+', '0a7'])
++ :call add(tl, ['[a-z_A-Z0-9]\+', 'aso_sfoij', 'aso_sfoij'])
++ :call add(tl, ['[a-z]', 'a', 'a'])
++ :call add(tl, ['[a-zA-Z]', 'a', 'a'])
++ :call add(tl, ['[A-Z]', 'a'])
++ :call add(tl, ['\C[^A-Z]\+', 'ABCOIJDEOIFNSD jsfoij sa', ' jsfoij sa'])
++ 
++ :"""" Tests for \z features
++ :call add(tl, ['xx \ze test', 'xx '])					" must match after \ze
++ :call add(tl, ['abc\zeend', 'oij abcend', 'abc'])
++ :call add(tl, ['abc\zsdd', 'ddabcddxyzt', 'dd'])
++ :call add(tl, ['aa \zsax', ' ax'])						" must match before \zs
++ :call add(tl, ['abc \zsmatch\ze abc', 'abc abc abc match abc abc', 'match'])
++ :call add(tl, ['\v(a \zsif .*){2}', 'a if then a if last', 'if last', 'a if last'])
++ 
++ :"""" Tests for \@ features
++ :call add(tl, ['abc\@=', 'abc', 'ab'])
++ :call add(tl, ['abc\@=cd', 'abcd', 'abcd'])
++ :call add(tl, ['abc\@=', 'ababc', 'ab'])
++ :call add(tl, ['abcd\@=e', 'abcd'])                     " will never match, no matter the input text
++ :call add(tl, ['abcd\@=e', 'any text in here ... '])    " will never match
++ :call add(tl, ['\v(abc)@=..', 'xabcd', 'ab', 'abc'])
++ :call add(tl, ['\(.*John\)\@=.*Bob', 'here is John, and here is B'])	" no match
++ :call add(tl, ['\(John.*\)\@=.*Bob', 'John is Bobs friend', 'John is Bob', 'John is Bobs friend'])
++ :call add(tl, ['.*John\&.*Bob', 'here is John, and here is B'])	" no match
++ :call add(tl, ['.*John\&.*Bob', 'John is Bobs friend', 'John is Bob'])
++ :call add(tl, ['\v(test1)@=.*yep', 'this is a test1, yep it is', 'test1, yep', 'test1'])
++ 
++ :"""" Combining different tests and features
++ :call add(tl, ['[[:alpha:]]\{-2,6}', '787abcdiuhsasiuhb4', 'ab'])
++ :call add(tl, ['[^[=a=]]\+', 'ddaãâbcd', 'dd'])
++ :call add(tl, ['', 'abcd', ''])
++ :call add(tl, ['\v(())', 'any possible text', ''])
++ :call add(tl, ['\v%(ab(xyz)c)', '   abxyzc ', 'abxyzc', 'xyz'])
++ :call add(tl, ['\v(test|)empty', 'tesempty', 'empty', ''])
++ :call add(tl, ['\v(a|aa)(a|aa)', 'aaa', 'aa', 'a', 'a'])
++ 
++ 
++ :"""" Run the tests
++ 
+  :"
+  :for t in tl
+  :  let l = matchlist(t[1], t[0])
+***************
+*** 143,149 ****
+  :  elseif len(t) > 2 && l[0] != t[2]
+  :    $put ='ERROR: pat: \"' . t[0] . '\", text: \"' . t[1] . '\", match: \"' . l[0] . '\", expected: \"' . t[2] . '\"'
+  :  else
+! :    $put ='OK'
+  :  endif
+  :  if len(l) > 0
+  :"   check all the nine submatches
+--- 307,313 ----
+  :  elseif len(t) > 2 && l[0] != t[2]
+  :    $put ='ERROR: pat: \"' . t[0] . '\", text: \"' . t[1] . '\", match: \"' . l[0] . '\", expected: \"' . t[2] . '\"'
+  :  else
+! :    $put ='OK - ' . t[0]
+  :  endif
+  :  if len(l) > 0
+  :"   check all the nine submatches
+***************
+*** 161,167 ****
+  :  endif
+  :endfor
+  :unlet t tl e l
+! :/^Results/,$wq! test.out
+  ENDTEST
+  
+  Results of test64:
+--- 325,341 ----
+  :  endif
+  :endfor
+  :unlet t tl e l
+! 
+! :" Check that \_[0-9] matching EOL does not break a following \>
+! :" This only works on a buffer line, not with expression evaluation
+! /^Find this
+! /\<\(\(25\_[0-5]\|2\_[0-4]\_[0-9]\|\_[01]\?\_[0-9]\_[0-9]\?\)\.\)\{3\}\(25\_[0-5]\|2\_[0-4]\_[0-9]\|\_[01]\?\_[0-9]\_[0-9]\?\)\>
+! y$Gop:"
+! 
+! :/\%#=1^Results/,$wq! test.out
+  ENDTEST
+  
++ Find this:
++ localnet/192.168.0.1
++ 
+  Results of test64:
+*** ../vim-7.3.969/src/testdir/test64.ok	2010-08-15 21:57:29.000000000 +0200
+--- src/testdir/test64.ok	2013-05-19 16:05:16.000000000 +0200
+***************
+*** 1,102 ****
+  Results of test64:
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+! OK
+--- 1,230 ----
+  Results of test64:
+! OK - ab
+! OK - b
+! OK - bc*
+! OK - bc\{-}
+! OK - bc\{-}\(d\)
+! OK - bc*
+! OK - c*
+! OK - bc*
+! OK - c*
+! OK - bc\+
+! OK - bc\+
+! OK - a\|ab
+! OK - c\?
+! OK - bc\?
+! OK - bc\?
+! OK - \va{1}
+! OK - \va{2}
+! OK - \va{2}
+! OK - \va{2}
+! OK - \va{2}
+! OK - \va{2}
+! OK - \va{2}
+! OK - \vb{1}
+! OK - \vba{2}
+! OK - \vba{3}
+! OK - \v(ab){1}
+! OK - \v(ab){1}
+! OK - \v(ab){1}
+! OK - \v(ab){0,2}
+! OK - \v(ab){0,2}
+! OK - \v(ab){1,2}
+! OK - \v(ab){1,2}
+! OK - \v(ab){2,4}
+! OK - \v(ab){2,4}
+! OK - \v(ab){2}
+! OK - \v(ab){2}
+! OK - \v(ab){2}
+! OK - \v(ab){2}
+! OK - \v((ab){2}){2}
+! OK - \v((ab){2}){2}
+! OK - \v(a{1}){1}
+! OK - \v(a{2}){1}
+! OK - \v(a{2}){1}
+! OK - \v(a{2}){1}
+! OK - \v(a{1}){2}
+! OK - \v(a{1}){2}
+! OK - \v(a{2})+
+! OK - \v(a{2})+
+! OK - \v(a{2}){1}
+! OK - \v(a{1}){2}
+! OK - \v(a{1}){1}
+! OK - \v(a{2}){2}
+! OK - \v(a{2}){2}
+! OK - \v(a+){2}
+! OK - \v(a{3}){2}
+! OK - \v(a{1,2}){2}
+! OK - \v(a{1,3}){2}
+! OK - \v(a{1,3}){2}
+! OK - \v(a{1,3}){3}
+! OK - \v(a{1,2}){2}
+! OK - \v(a+)+
+! OK - \v(a+)+
+! OK - \v(a+){1,2}
+! OK - \v(a+)(a+)
+! OK - \v(a{3})+
+! OK - \v(a|b|c)+
+! OK - \v(a|b|c){2}
+! OK - \v(abc){2}
+! OK - \v(abc){2}
+! OK - a*
+! OK - \v(a*)+
+! OK - \v((ab)+)+
+! OK - \v(((ab)+)+)+
+! OK - \v(((ab)+)+)+
+! OK - \v(a{0,2})+
+! OK - \v(a*)+
+! OK - \v((a*)+)+
+! OK - \v((ab)*)+
+! OK - \va{1,3}
+! OK - \va{2,3}
+! OK - \v((ab)+|c*)+
+! OK - \v(a{2})|(b{3})
+! OK - \va{2}|b{2}
+! OK - \v(a)+|(c)+
+! OK - \vab{2,3}c
+! OK - \vab{2,3}c
+! OK - \vab{2,3}cd{2,3}e
+! OK - \va(bc){2}d
+! OK - \va*a{2}
+! OK - \va*a{2}
+! OK - \va*a{2}
+! OK - \va*a{2}
+! OK - \va*b*|a*c*
+! OK - \va{1}b{1}|a{1}b{1}
+! OK - \v(a)
+! OK - \v(a)(b)
+! OK - \v(ab)(b)(c)
+! OK - \v((a)(b))
+! OK - \v(a)|(b)
+! OK - \v(a*)+
+! OK - x
+! OK - ab
+! OK - ab
+! OK - ab
+! OK - x*
+! OK - x*
+! OK - x*
+! OK - x\+
+! OK - x\+
+! OK - x\+
+! OK - x\+
+! OK - x\=
+! OK - x\=
+! OK - x\=
+! OK - x\?
+! OK - x\?
+! OK - x\?
+! OK - a\{0,0}
+! OK - a\{0,1}
+! OK - a\{1,0}
+! OK - a\{3,6}
+! OK - a\{3,6}
+! OK - a\{3,6}
+! OK - a\{0}
+! OK - a\{2}
+! OK - a\{2}
+! OK - a\{2}
+! OK - a\{0,}
+! OK - a\{0,}
+! OK - a\{2,}
+! OK - a\{2,}
+! OK - a\{,0}
+! OK - a\{,5}
+! OK - a\{,5}
+! OK - a\{}
+! OK - a\{}
+! OK - a\{-0,0}
+! OK - a\{-0,1}
+! OK - a\{-3,6}
+! OK - a\{-3,6}
+! OK - a\{-3,6}
+! OK - a\{-0}
+! OK - a\{-2}
+! OK - a\{-2}
+! OK - a\{-0,}
+! OK - a\{-0,}
+! OK - a\{-2,}
+! OK - a\{-2,}
+! OK - a\{-,0}
+! OK - a\{-,5}
+! OK - a\{-,5}
+! OK - a\{-}
+! OK - a\{-}
+! OK - \(abc\)*
+! OK - \(ab\)\+
+! OK - \(abaaaaa\)*cd
+! OK - \(test1\)\? \(test2\)\?
+! OK - \(test1\)\= \(test2\) \(test4443\)\=
+! OK - \(\(sub1\) hello \(sub 2\)\)
+! OK - \(\(\(yyxxzz\)\)\)
+! OK - \v((ab)+|c+)+
+! OK - \v((ab)|c*)+
+! OK - \v(a(c*)+b)+
+! OK - \v(a|b*)+
+! OK - a\{-2,7}
+! OK - a\{2,7}
+! OK - \vx(.{-,8})yz(.*)
+! OK - \vx(.*)yz(.*)
+! OK - \v(a{1,2}){-2,3}
+! OK - \v(a{-1,3})+
+! OK - \d\+e\d\d
+! OK - \v[a]
+! OK - a[bcd]
+! OK - a[b-d]
+! OK - [a-d][e-f][x-x]d
+! OK - \v[[:alpha:]]+
+! OK - [[:alpha:]\+]
+! OK - [^abc]\+
+! OK - [^abc]
+! OK - [^abc]\+
+! OK - [^a-d]\+
+! OK - [a-f]*
+! OK - [a-f]*
+! OK - [^a-f]\+
+! OK - [a-c]\{-3,6}
+! OK - [^[:alpha:]]\+
+! OK - [-a]
+! OK - [a-]
+! OK - [-./[:alnum:]_~]\+
+! OK - [\]\^\-\\]\+
+! OK - [[.a.]]\+
+! OK - abc[0-9]*ddd
+! OK - abc[0-9]*ddd
+! OK - \_[0-9]\+
+! OK - [0-9\n]\+
+! OK - [0-9]
+! OK - [^0-9]
+! OK - [0-9a-fA-F]*
+! OK - [^0-9A-Fa-f]\+
+! OK - [a-z_A-Z0-9]\+
+! OK - [a-z]
+! OK - [a-zA-Z]
+! OK - [A-Z]
+! OK - \C[^A-Z]\+
+! OK - xx \ze test
+! OK - abc\zeend
+! OK - abc\zsdd
+! OK - aa \zsax
+! OK - abc \zsmatch\ze abc
+! OK - \v(a \zsif .*){2}
+! OK - abc\@=
+! OK - abc\@=cd
+! OK - abc\@=
+! OK - abcd\@=e
+! OK - abcd\@=e
+! OK - \v(abc)@=..
+! OK - \(.*John\)\@=.*Bob
+! OK - \(John.*\)\@=.*Bob
+! OK - .*John\&.*Bob
+! OK - .*John\&.*Bob
+! OK - \v(test1)@=.*yep
+! OK - [[:alpha:]]\{-2,6}
+! OK - [^[=a=]]\+
+! OK - 
+! OK - \v(())
+! OK - \v%(ab(xyz)c)
+! OK - \v(test|)empty
+! OK - \v(a|aa)(a|aa)
+! 192.168.0.1
+*** ../vim-7.3.969/Filelist	2013-03-07 13:32:03.000000000 +0100
+--- Filelist	2013-05-17 19:25:39.000000000 +0200
+***************
+*** 57,62 ****
+--- 57,63 ----
+  		src/popupmnu.c \
+  		src/quickfix.c \
+  		src/regexp.c \
++ 		src/regexp_nfa.c \
+  		src/regexp.h \
+  		src/screen.c \
+  		src/search.c \
+*** ../vim-7.3.969/runtime/doc/pattern.txt	2011-07-20 17:58:14.000000000 +0200
+--- runtime/doc/pattern.txt	2013-05-17 22:57:02.000000000 +0200
+***************
+*** 21,27 ****
+  10. Highlighting matches	|match-highlight|
+  
+  ==============================================================================
+! 1. Search commands				*search-commands* *E486*
+  
+  							*/*
+  /{pattern}[/]<CR>	Search forward for the [count]'th occurrence of
+--- 21,27 ----
+  10. Highlighting matches	|match-highlight|
+  
+  ==============================================================================
+! 1. Search commands				*search-commands*
+  
+  							*/*
+  /{pattern}[/]<CR>	Search forward for the [count]'th occurrence of
+***************
+*** 150,155 ****
+--- 150,160 ----
+  All matches for the last used search pattern will be highlighted if you set
+  the 'hlsearch' option.  This can be suspended with the |:nohlsearch| command.
+  
++ When no match is found you get the error: *E486* Pattern not found
++ Note that for the |:global| command this behaves like a normal message, for Vi
++ compatibility.  For the |:s| command the "e" flag can be used to avoid the
++ error message |:s_flags|.
++ 
+  					*search-offset* *{offset}*
+  These commands search for the specified pattern.  With "/" and "?" an
+  additional offset may be given.  There are two types of offsets: line offsets
+***************
+*** 214,220 ****
+  the search, possibly in another direction or with another count.  Note that
+  two patterns are remembered: One for 'normal' search commands and one for the
+  substitute command ":s".  Each time an empty pattern is given, the previously
+! used pattern is used.
+  
+  The 'magic' option sticks with the last used pattern.  If you change 'magic',
+  this will not change how the last used pattern will be interpreted.
+--- 219,226 ----
+  the search, possibly in another direction or with another count.  Note that
+  two patterns are remembered: One for 'normal' search commands and one for the
+  substitute command ":s".  Each time an empty pattern is given, the previously
+! used pattern is used.  However, if there is no previous search command, a
+! previous substitute pattern is used, if possible.
+  
+  The 'magic' option sticks with the last used pattern.  If you change 'magic',
+  this will not change how the last used pattern will be interpreted.
+***************
+*** 344,349 ****
+--- 350,376 ----
+  		or  \z( pattern \)		|/\z(|
+  
+  
++ 				*/\%#=* *two-engines*
++ Vim includes two regexp engines:
++ 1. An old, backtracking engine that supports everything.
++ 2. A new, NFA engine that works much faster on some patterns, but does not
++    support everything.
++ 
++ Vim will automatically select the right engine for you.  However, if you run
++ into a problem or want to specifically select one engine or the other, you can
++ prepend one of the following to the pattern:
++ 
++ 	\%#=0	Force automatic selection.  Only has an effect when
++ 	        'regexpengine' has been set to a non-zero value.
++ 	\%#=1	Force using the old engine.
++ 	\%#=2	Force using the NFA engine.
++ 
++ You can also use the 'regexpengine' option to change the default.
++ 
++ 			 *E864* *E868* *E874* *E875* *E876* *E877* *E878*
++ If selecting the NFA engine and it runs into something that is not implemented
++ the pattern will not match.  This is only useful when debugging Vim.
++ 
+  ==============================================================================
+  3. Magic							*/magic*
+  
+***************
+*** 390,398 ****
+  
+  ==============================================================================
+  4. Overview of pattern items				*pattern-overview*
+  
+  Overview of multi items.				*/multi* *E61* *E62*
+! More explanation and examples below, follow the links.			*E64*
+  
+  	  multi ~
+       'magic' 'nomagic'	matches of the preceding atom ~
+--- 417,426 ----
+  
+  ==============================================================================
+  4. Overview of pattern items				*pattern-overview*
++ 						*E865* *E866* *E867* *E869*
+  
+  Overview of multi items.				*/multi* *E61* *E62*
+! More explanation and examples below, follow the links.		*E64* *E871*
+  
+  	  multi ~
+       'magic' 'nomagic'	matches of the preceding atom ~
+***************
+*** 498,513 ****
+  	x	x	a character with no special meaning matches itself
+  
+  |/[]|	[]	\[]	any character specified inside the []
+! |/\%[]| \%[]	\%[]	a sequence of optionally matched atoms
+  
+  |/\c|	\c	\c	ignore case, do not use the 'ignorecase' option
+  |/\C|	\C	\C	match case, do not use the 'ignorecase' option
+  |/\m|	\m	\m	'magic' on for the following chars in the pattern
+  |/\M|	\M	\M	'magic' off for the following chars in the pattern
+  |/\v|	\v	\v	the following chars in the pattern are "very magic"
+  |/\V|	\V	\V	the following chars in the pattern are "very nomagic"
+! |/\Z|	\Z	\Z	ignore differences in Unicode "combining characters".
+! 			Useful when searching voweled Hebrew or Arabic text.
+  
+  |/\%d|	\%d	\%d	match specified decimal character (eg \%d123)
+  |/\%x|	\%x	\%x	match specified hex character (eg \%x2a)
+--- 526,543 ----
+  	x	x	a character with no special meaning matches itself
+  
+  |/[]|	[]	\[]	any character specified inside the []
+! |/\%[]|	\%[]	\%[]	a sequence of optionally matched atoms
+  
+  |/\c|	\c	\c	ignore case, do not use the 'ignorecase' option
+  |/\C|	\C	\C	match case, do not use the 'ignorecase' option
++ |/\Z|	\Z	\Z	ignore differences in Unicode "combining characters".
++ 			Useful when searching voweled Hebrew or Arabic text.
++ 
+  |/\m|	\m	\m	'magic' on for the following chars in the pattern
+  |/\M|	\M	\M	'magic' off for the following chars in the pattern
+  |/\v|	\v	\v	the following chars in the pattern are "very magic"
+  |/\V|	\V	\V	the following chars in the pattern are "very nomagic"
+! |/\%#=|   \%#=1   \%#=1   select regexp engine |/zero-width|
+  
+  |/\%d|	\%d	\%d	match specified decimal character (eg \%d123)
+  |/\%x|	\%x	\%x	match specified hex character (eg \%x2a)
+***************
+*** 575,581 ****
+  \?	Just like \=.  Cannot be used when searching backwards with the "?"
+  	command. {not in Vi}
+  
+! 						*/\{* *E58* *E60* *E554*
+  \{n,m}	Matches n to m of the preceding atom, as many as possible
+  \{n}	Matches n of the preceding atom
+  \{n,}	Matches at least n of the preceding atom, as many as possible
+--- 605,611 ----
+  \?	Just like \=.  Cannot be used when searching backwards with the "?"
+  	command. {not in Vi}
+  
+! 					*/\{* *E58* *E60* *E554* *E870*
+  \{n,m}	Matches n to m of the preceding atom, as many as possible
+  \{n}	Matches n of the preceding atom
+  \{n,}	Matches at least n of the preceding atom, as many as possible
+***************
+*** 631,647 ****
+  							*/\@!*
+  \@!	Matches with zero width if the preceding atom does NOT match at the
+  	current position. |/zero-width| {not in Vi}
+! 	Like '(?!pattern)" in Perl.
+  	Example			matches ~
+  	foo\(bar\)\@!		any "foo" not followed by "bar"
+! 	a.\{-}p\@!		"a", "ap", "app", etc. not followed by a "p"
+  	if \(\(then\)\@!.\)*$	"if " not followed by "then"
+  
+  	Using "\@!" is tricky, because there are many places where a pattern
+  	does not match.  "a.*p\@!" will match from an "a" to the end of the
+  	line, because ".*" can match all characters in the line and the "p"
+  	doesn't match at the end of the line.  "a.\{-}p\@!" will match any
+! 	"a", "ap", "aap", etc. that isn't followed by a "p", because the "."
+  	can match a "p" and "p\@!" doesn't match after that.
+  
+  	You can't use "\@!" to look for a non-match before the matching
+--- 661,678 ----
+  							*/\@!*
+  \@!	Matches with zero width if the preceding atom does NOT match at the
+  	current position. |/zero-width| {not in Vi}
+! 	Like "(?!pattern)" in Perl.
+  	Example			matches ~
+  	foo\(bar\)\@!		any "foo" not followed by "bar"
+! 	a.\{-}p\@!		"a", "ap", "app", "appp", etc. not immediately
+! 				followed by a "p"
+  	if \(\(then\)\@!.\)*$	"if " not followed by "then"
+  
+  	Using "\@!" is tricky, because there are many places where a pattern
+  	does not match.  "a.*p\@!" will match from an "a" to the end of the
+  	line, because ".*" can match all characters in the line and the "p"
+  	doesn't match at the end of the line.  "a.\{-}p\@!" will match any
+! 	"a", "ap", "app", etc. that isn't followed by a "p", because the "."
+  	can match a "p" and "p\@!" doesn't match after that.
+  
+  	You can't use "\@!" to look for a non-match before the matching
+***************
+*** 650,659 ****
+  	"foobar" you could use "\(foo\)\@!...bar", but that doesn't match a
+  	bar at the start of a line.  Use "\(foo\)\@<!bar".
+  
+  							*/\@<=*
+  \@<=	Matches with zero width if the preceding atom matches just before what
+  	follows. |/zero-width| {not in Vi}
+! 	Like '(?<=pattern)" in Perl, but Vim allows non-fixed-width patterns.
+  	Example			matches ~
+  	\(an\_s\+\)\@<=file	"file" after "an" and white space or an
+  				end-of-line
+--- 681,697 ----
+  	"foobar" you could use "\(foo\)\@!...bar", but that doesn't match a
+  	bar at the start of a line.  Use "\(foo\)\@<!bar".
+  
++ 	Useful example: to find "foo" in a line that does not contain "bar": >
++ 		/^\%(.*bar\)\@!.*\zsfoo
++ <	This pattern first checks that there is not a single position in the
++ 	line where "bar" matches.  If ".*bar" matches somewhere the \@! will
++ 	reject the pattern.  When there is no match any "foo" will be found.
++ 	The "\zs" is to have the match start just before "foo".
++ 
+  							*/\@<=*
+  \@<=	Matches with zero width if the preceding atom matches just before what
+  	follows. |/zero-width| {not in Vi}
+! 	Like "(?<=pattern)" in Perl, but Vim allows non-fixed-width patterns.
+  	Example			matches ~
+  	\(an\_s\+\)\@<=file	"file" after "an" and white space or an
+  				end-of-line
+***************
+*** 677,683 ****
+  	before what follows.  Thus this matches if there is no position in the
+  	current or previous line where the atom matches such that it ends just
+  	before what follows.  |/zero-width| {not in Vi}
+! 	Like '(?<!pattern)" in Perl, but Vim allows non-fixed-width patterns.
+  	The match with the preceding atom is made to end just before the match
+  	with what follows, thus an atom that ends in ".*" will work.
+  	Warning: This can be slow (because many positions need to be checked
+--- 715,721 ----
+  	before what follows.  Thus this matches if there is no position in the
+  	current or previous line where the atom matches such that it ends just
+  	before what follows.  |/zero-width| {not in Vi}
+! 	Like "(?<!pattern)" in Perl, but Vim allows non-fixed-width patterns.
+  	The match with the preceding atom is made to end just before the match
+  	with what follows, thus an atom that ends in ".*" will work.
+  	Warning: This can be slow (because many positions need to be checked
+***************
+*** 923,929 ****
+  \l	lowercase character:		[a-z]		*/\l*
+  \L	non-lowercase character:	[^a-z]		*/\L*
+  \u	uppercase character:		[A-Z]		*/\u*
+! \U	non-uppercase character		[^A-Z]		*/\U*
+  
+  	NOTE: Using the atom is faster than the [] form.
+  
+--- 961,967 ----
+  \l	lowercase character:		[a-z]		*/\l*
+  \L	non-lowercase character:	[^a-z]		*/\L*
+  \u	uppercase character:		[A-Z]		*/\u*
+! \U	non-uppercase character:	[^A-Z]		*/\U*
+  
+  	NOTE: Using the atom is faster than the [] form.
+  
+***************
+*** 948,954 ****
+  ~	matches the last given substitute string	*/~* */\~*
+  
+  \(\)	A pattern enclosed by escaped parentheses.	*/\(* */\(\)* */\)*
+! 	E.g., "\(^a\)" matches 'a' at the start of a line.  *E51* *E54* *E55*
+  
+  \1      Matches the same string that was matched by	*/\1* *E65*
+  	the first sub-expression in \( and \). {not in Vi}
+--- 986,993 ----
+  ~	matches the last given substitute string	*/~* */\~*
+  
+  \(\)	A pattern enclosed by escaped parentheses.	*/\(* */\(\)* */\)*
+! 	E.g., "\(^a\)" matches 'a' at the start of a line.
+! 	*E51* *E54* *E55* *E872* *E873*
+  
+  \1      Matches the same string that was matched by	*/\1* *E65*
+  	the first sub-expression in \( and \). {not in Vi}
+***************
+*** 979,984 ****
+--- 1018,1025 ----
+  	[xyz]		any 'x', 'y' or 'z'
+  	[a-zA-Z]$	any alphabetic character at the end of a line
+  	\c[a-z]$	same
++ 	[А-яЁё]		Russian alphabet (with utf-8 and cp1251)
++ 
+  								*/[\n]*
+  	With "\_" prepended the collection also includes the end-of-line.
+  	The same can be done by including "\n" in the collection.  The
+***************
+*** 1045,1050 ****
+--- 1086,1093 ----
+  	  any character that's not in "^]-\bdertnoUux".  "[\xyz]" matches '\',
+  	  'x', 'y' and 'z'.  It's better to use "\\" though, future expansions
+  	  may use other characters after '\'.
++ 	- Omitting the trailing ] is not considered an error. "[]" works like
++ 	  "[]]", it matches the ']' character.
+  	- The following translations are accepted when the 'l' flag is not
+  	  included in 'cpoptions' {not in Vi}:
+  		\e	<Esc>
+*** ../vim-7.3.969/src/option.c	2013-05-11 13:45:00.000000000 +0200
+--- src/option.c	2013-05-17 22:23:14.000000000 +0200
+***************
+*** 2077,2082 ****
+--- 2077,2085 ----
+  			    (char_u *)NULL, PV_NONE,
+  #endif
+  			    {(char_u *)2000L, (char_u *)0L} SCRIPTID_INIT},
++     {"regexpengine", "re",  P_NUM|P_VI_DEF,
++ 			    (char_u *)&p_re, PV_NONE,
++ 			    {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT},
+      {"relativenumber", "rnu", P_BOOL|P_VI_DEF|P_RWIN,
+  			    (char_u *)VAR_WIN, PV_RNU,
+  			    {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
+***************
+*** 8604,8609 ****
+--- 8607,8617 ----
+  	errmsg = e_positive;
+  	p_hi = 0;
+      }
++     if (p_re < 0 || p_re > 2)
++     {
++ 	errmsg = e_invarg;
++ 	p_re = 0;
++     }
+      if (p_report < 0)
+      {
+  	errmsg = e_positive;
+*** ../vim-7.3.969/src/option.h	2013-03-19 16:46:59.000000000 +0100
+--- src/option.h	2013-05-17 22:23:39.000000000 +0200
+***************
+*** 653,658 ****
+--- 653,659 ----
+  EXTERN long	p_rdt;		/* 'redrawtime' */
+  #endif
+  EXTERN int	p_remap;	/* 'remap' */
++ EXTERN long	p_re;		/* 'regexpengine' */
+  EXTERN long	p_report;	/* 'report' */
+  #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+  EXTERN long	p_pvh;		/* 'previewheight' */
+*** ../vim-7.3.969/src/testdir/test95.in	2013-05-19 19:10:10.000000000 +0200
+--- src/testdir/test95.in	2013-05-18 15:11:43.000000000 +0200
+***************
+*** 0 ****
+--- 1,63 ----
++ Test for regexp patterns with multi-byte support.
++ See test64 for the non-multi-byte tests.
++ 
++ A pattern that gives the expected result produces OK, so that we know it was
++ actually tried.
++ 
++ STARTTEST
++ :so small.vim
++ :so mbyte.vim
++ :" tl is a List of Lists with:
++ :"    regexp pattern
++ :"    text to test the pattern on
++ :"    expected match (optional)
++ :"    expected submatch 1 (optional)
++ :"    expected submatch 2 (optional)
++ :"    etc.
++ :"  When there is no match use only the first two items.
++ :let tl = []
++ 
++ :"""" Multi-byte character tests. These will fail unless vim is compiled
++ :"""" with Multibyte (FEAT_MBYTE) or BIG/HUGE features.
++ :call add(tl, ['[[:alpha:][=a=]]\+', '879 aiaãâaiuvna ', 'aiaãâaiuvna'])
++ :call add(tl, ['[[=a=]]\+', 'ddaãâbcd', 'aãâ'])								" equivalence classes
++ :call add(tl, ['[^ม ]\+', 'มม oijasoifjos ifjoisj f osij j มมมมม abcd', 'oijasoifjos'])
++ :call add(tl, [' [^ ]\+', 'start มabcdม ', ' มabcdม'])
++ :call add(tl, ['[ม[:alpha:][=a=]]\+', '879 aiaãมâมaiuvna ', 'aiaãมâมaiuvna'])
++ 
++ :"""" Run the tests
++ 
++ :"
++ :for t in tl
++ :  let l = matchlist(t[1], t[0])
++ :" check the match itself
++ :  if len(l) == 0 && len(t) > 2
++ :    $put ='ERROR: pat: \"' . t[0] . '\", text: \"' . t[1] . '\", did not match, expected: \"' . t[2] . '\"'
++ :  elseif len(l) > 0 && len(t) == 2
++ :    $put ='ERROR: pat: \"' . t[0] . '\", text: \"' . t[1] . '\", match: \"' . l[0] . '\", expected no match'
++ :  elseif len(t) > 2 && l[0] != t[2]
++ :    $put ='ERROR: pat: \"' . t[0] . '\", text: \"' . t[1] . '\", match: \"' . l[0] . '\", expected: \"' . t[2] . '\"'
++ :  else
++ :    $put ='OK - ' . t[0]
++ :  endif
++ :  if len(l) > 0
++ :"   check all the nine submatches
++ :    for i in range(1, 9)
++ :      if len(t) <= i + 2
++ :        let e = ''
++ :      else
++ :        let e = t[i + 2]
++ :      endif
++ :      if l[i] != e
++ :        $put ='ERROR: pat: \"' . t[0] . '\", text: \"' . t[1] . '\", submatch ' . i . ': \"' . l[i] . '\", expected: \"' . e . '\"'
++ :      endif
++ :    endfor
++ :    unlet i
++ :  endif
++ :endfor
++ :unlet t tl e l
++ 
++ :/\%#=1^Results/,$wq! test.out
++ ENDTEST
++ 
++ Results of test95:
+*** ../vim-7.3.969/src/testdir/test95.ok	2013-05-19 19:10:10.000000000 +0200
+--- src/testdir/test95.ok	2013-05-18 14:30:49.000000000 +0200
+***************
+*** 0 ****
+--- 1,6 ----
++ Results of test95:
++ OK - [[:alpha:][=a=]]\+
++ OK - [[=a=]]\+
++ OK - [^ม ]\+
++ OK -  [^ ]\+
++ OK - [ม[:alpha:][=a=]]\+
+*** ../vim-7.3.969/src/testdir/Make_amiga.mak	2013-04-12 13:44:49.000000000 +0200
+--- src/testdir/Make_amiga.mak	2013-05-18 14:21:35.000000000 +0200
+***************
+*** 33,39 ****
+  		test76.out test77.out test78.out test79.out test80.out \
+  		test81.out test82.out test83.out test84.out test88.out \
+  		test89.out test90.out test91.out test92.out test93.out \
+! 		test94.out
+  
+  .SUFFIXES: .in .out
+  
+--- 33,39 ----
+  		test76.out test77.out test78.out test79.out test80.out \
+  		test81.out test82.out test83.out test84.out test88.out \
+  		test89.out test90.out test91.out test92.out test93.out \
+! 		test94.out test95.out
+  
+  .SUFFIXES: .in .out
+  
+***************
+*** 144,146 ****
+--- 144,147 ----
+  test92.out: test92.in
+  test93.out: test93.in
+  test94.out: test94.in
++ test95.out: test95.in
+*** ../vim-7.3.969/src/testdir/Make_dos.mak	2013-04-12 13:44:49.000000000 +0200
+--- src/testdir/Make_dos.mak	2013-05-18 14:21:47.000000000 +0200
+***************
+*** 32,38 ****
+  		test79.out test80.out test81.out test82.out test83.out \
+  		test84.out test85.out test86.out test87.out test88.out \
+  		test89.out test90.out test91.out test92.out test93.out \
+! 		test94.out
+  
+  SCRIPTS32 =	test50.out test70.out
+  
+--- 32,38 ----
+  		test79.out test80.out test81.out test82.out test83.out \
+  		test84.out test85.out test86.out test87.out test88.out \
+  		test89.out test90.out test91.out test92.out test93.out \
+! 		test94.out test95.out
+  
+  SCRIPTS32 =	test50.out test70.out
+  
+*** ../vim-7.3.969/src/testdir/Make_ming.mak	2013-04-12 13:44:49.000000000 +0200
+--- src/testdir/Make_ming.mak	2013-05-18 14:21:56.000000000 +0200
+***************
+*** 52,58 ****
+  		test79.out test80.out test81.out test82.out test83.out \
+  		test84.out test85.out test86.out test87.out test88.out \
+  		test89.out test90.out test91.out test92.out test93.out \
+! 		test94.out
+  
+  SCRIPTS32 =	test50.out test70.out
+  
+--- 52,58 ----
+  		test79.out test80.out test81.out test82.out test83.out \
+  		test84.out test85.out test86.out test87.out test88.out \
+  		test89.out test90.out test91.out test92.out test93.out \
+! 		test94.out test95.out
+  
+  SCRIPTS32 =	test50.out test70.out
+  
+*** ../vim-7.3.969/src/testdir/Make_os2.mak	2013-04-12 13:44:49.000000000 +0200
+--- src/testdir/Make_os2.mak	2013-05-18 14:22:00.000000000 +0200
+***************
+*** 33,39 ****
+  		test76.out test77.out test78.out test79.out test80.out \
+  		test81.out test82.out test83.out test84.out test88.out \
+  		test89.out test90.out test91.out test92.out test93.out \
+! 		test94.out
+  
+  .SUFFIXES: .in .out
+  
+--- 33,39 ----
+  		test76.out test77.out test78.out test79.out test80.out \
+  		test81.out test82.out test83.out test84.out test88.out \
+  		test89.out test90.out test91.out test92.out test93.out \
+! 		test94.out test95.out
+  
+  .SUFFIXES: .in .out
+  
+*** ../vim-7.3.969/src/testdir/Make_vms.mms	2013-04-12 13:44:49.000000000 +0200
+--- src/testdir/Make_vms.mms	2013-05-18 14:22:11.000000000 +0200
+***************
+*** 4,10 ****
+  # Authors:	Zoltan Arpadffy, <arpadffy@polarhome.com>
+  #		Sandor Kopanyi,  <sandor.kopanyi@mailbox.hu>
+  #
+! # Last change:  2013 Apr 12
+  #
+  # This has been tested on VMS 6.2 to 8.3 on DEC Alpha, VAX and IA64.
+  # Edit the lines in the Configuration section below to select.
+--- 4,10 ----
+  # Authors:	Zoltan Arpadffy, <arpadffy@polarhome.com>
+  #		Sandor Kopanyi,  <sandor.kopanyi@mailbox.hu>
+  #
+! # Last change:  2013 May 18
+  #
+  # This has been tested on VMS 6.2 to 8.3 on DEC Alpha, VAX and IA64.
+  # Edit the lines in the Configuration section below to select.
+***************
+*** 77,83 ****
+  	 test71.out test72.out test74.out test75.out test76.out \
+  	 test77.out test78.out test79.out test80.out test81.out \
+  	 test82.out test83.out test84.out test88.out test89.out \
+! 	 test90.out test91.out test92.out test93.out test94.out
+  
+  # Known problems:
+  # Test 30: a problem around mac format - unknown reason
+--- 77,84 ----
+  	 test71.out test72.out test74.out test75.out test76.out \
+  	 test77.out test78.out test79.out test80.out test81.out \
+  	 test82.out test83.out test84.out test88.out test89.out \
+! 	 test90.out test91.out test92.out test93.out test94.out \
+! 	 test95.out
+  
+  # Known problems:
+  # Test 30: a problem around mac format - unknown reason
+*** ../vim-7.3.969/src/version.c	2013-05-18 20:55:31.000000000 +0200
+--- src/version.c	2013-05-19 19:10:25.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     970,
+  /**/
+
+-- 
+BRIDGEKEEPER: What is the air-speed velocity of an unladen swallow?
+ARTHUR:       What do you mean?  An African or European swallow?
+BRIDGEKEEPER: Er ...  I don't know that ... Aaaaarrrrrrggghhh!
+   BRIDGEKEEPER is cast into the gorge.
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.971 b/7.3.971
new file mode 100644
index 0000000..9cf92cd
--- /dev/null
+++ b/7.3.971
@@ -0,0 +1,135 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.971
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.971
+Problem:    No support for VS2012 static code analysis.
+Solution:   Add the ANALYZE option. (Mike Williams)
+Files:	    src/Make_mvc.mak
+
+
+*** ../vim-7.3.970/src/Make_mvc.mak	2013-05-19 19:16:25.000000000 +0200
+--- src/Make_mvc.mak	2013-05-19 16:38:29.000000000 +0200
+***************
+*** 20,26 ****
+  #
+  #	!!!!  After changing features do "nmake clean" first  !!!!
+  #
+! #       Feature Set: FEATURES=[TINY, SMALL, NORMAL, BIG, HUGE] (default is BIG)
+  #
+  #	GUI interface: GUI=yes (default is no)
+  #
+--- 20,26 ----
+  #
+  #	!!!!  After changing features do "nmake clean" first  !!!!
+  #
+! #	Feature Set: FEATURES=[TINY, SMALL, NORMAL, BIG, HUGE] (default is BIG)
+  #
+  #	GUI interface: GUI=yes (default is no)
+  #
+***************
+*** 87,106 ****
+  #	  GETTEXT=[yes or no]  (default is yes)
+  #	See http://sourceforge.net/projects/gettext/
+  #
+! #       PostScript printing: POSTSCRIPT=yes (default is no)
+  #
+! #       Netbeans Support: NETBEANS=[yes or no] (default is yes if GUI is yes)
+  #
+! #       XPM Image Support: XPM=[path to XPM directory]
+! #       Default is "xpm", using the files included in the distribution.
+! #       Use "no" to disable this feature.
+  #
+! #       Optimization: OPTIMIZE=[SPACE, SPEED, MAXSPEED] (default is MAXSPEED)
+  #
+! #       Processor Version: CPUNR=[i386, i486, i586, i686, pentium4] (default is
+! #       i386)
+  #
+! #       Version Support: WINVER=[0x0400, 0x0500] (default is 0x0400)
+  #
+  #	Debug version: DEBUG=yes
+  #	Mapfile: MAP=[no, yes or lines] (default is yes)
+--- 87,106 ----
+  #	  GETTEXT=[yes or no]  (default is yes)
+  #	See http://sourceforge.net/projects/gettext/
+  #
+! #	PostScript printing: POSTSCRIPT=yes (default is no)
+  #
+! #	Netbeans Support: NETBEANS=[yes or no] (default is yes if GUI is yes)
+  #
+! #	XPM Image Support: XPM=[path to XPM directory]
+! #	Default is "xpm", using the files included in the distribution.
+! #	Use "no" to disable this feature.
+  #
+! #	Optimization: OPTIMIZE=[SPACE, SPEED, MAXSPEED] (default is MAXSPEED)
+  #
+! #	Processor Version: CPUNR=[i386, i486, i586, i686, pentium4] (default is
+! #	i386)
+  #
+! #	Version Support: WINVER=[0x0400, 0x0500] (default is 0x0400)
+  #
+  #	Debug version: DEBUG=yes
+  #	Mapfile: MAP=[no, yes or lines] (default is yes)
+***************
+*** 108,117 ****
+  #	  yes:   Write a normal mapfile.
+  #	  lines: Write a mapfile with line numbers (only for VC6 and later)
+  #
+! #       Netbeans Debugging Support: NBDEBUG=[yes or no] (should be no, yes
+! #       doesn't work)
+  #
+! #       Visual C Version: MSVCVER=m.n (default derived from nmake if undefined)
+  #
+  # You can combine any of these interfaces
+  #
+--- 108,119 ----
+  #	  yes:   Write a normal mapfile.
+  #	  lines: Write a mapfile with line numbers (only for VC6 and later)
+  #
+! #	Netbeans Debugging Support: NBDEBUG=[yes or no] (should be no, yes
+! #	doesn't work)
+  #
+! #	Visual C Version: MSVCVER=m.n (default derived from nmake if undefined)
+! #
+! #	Static Code Analysis: ANALYZE=yes (works with VS2012 only)
+  #
+  # You can combine any of these interfaces
+  #
+***************
+*** 479,484 ****
+--- 481,491 ----
+  CFLAGS=$(CFLAGS) $(WP64CHECK)
+  !endif
+  
++ # Static code analysis generally available starting with VS2012
++ !if ("$(ANALYZE)" == "yes") && ("$(MSVCVER)" == "11.0")
++ CFLAGS=$(CFLAGS) /analyze
++ !endif
++ 
+  CFLAGS = $(CFLAGS) $(OPTFLAG) -DNDEBUG $(CPUARG)
+  RCFLAGS = $(rcflags) $(rcvars) -DNDEBUG
+  ! ifdef USE_MSVCRT
+*** ../vim-7.3.970/src/version.c	2013-05-19 19:16:25.000000000 +0200
+--- src/version.c	2013-05-19 21:03:34.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     971,
+  /**/
+
+
+-- 
+It is illegal for a driver to be blindfolded while operating a vehicle.
+		[real standing law in Alabama, United States of America]
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.972 b/7.3.972
new file mode 100644
index 0000000..725f23b
--- /dev/null
+++ b/7.3.972
@@ -0,0 +1,99 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.972
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.972
+Problem:    Cursor not restored after InsertEnter autocommand if it moved to
+	    another line.
+Solution:   Also restore if the saved line number is still valid.  Allow
+	    setting v:char to skip restoring.
+Files:	    src/edit.c, runtime/doc/autocmd.txt
+
+
+*** ../vim-7.3.971/src/edit.c	2013-05-06 04:21:35.000000000 +0200
+--- src/edit.c	2013-05-19 21:09:37.000000000 +0200
+***************
+*** 382,394 ****
+  	else
+  	    ptr = (char_u *)"i";
+  	set_vim_var_string(VV_INSERTMODE, ptr, 1);
+  # endif
+  	apply_autocmds(EVENT_INSERTENTER, NULL, NULL, FALSE, curbuf);
+  
+! 	/* Since Insert mode was not started yet a call to check_cursor_col()
+! 	 * may have moved the cursor, especially with the "A" command. */
+! 	if (curwin->w_cursor.col != save_cursor.col
+! 		&& curwin->w_cursor.lnum == save_cursor.lnum)
+  	{
+  	    int save_state = State;
+  
+--- 382,402 ----
+  	else
+  	    ptr = (char_u *)"i";
+  	set_vim_var_string(VV_INSERTMODE, ptr, 1);
++ 	set_vim_var_string(VV_CHAR, NULL, -1);  /* clear v:char */
+  # endif
+  	apply_autocmds(EVENT_INSERTENTER, NULL, NULL, FALSE, curbuf);
+  
+! 	/* Make sure the cursor didn't move.  Do call check_cursor_col() in
+! 	 * case the text was modified.  Since Insert mode was not started yet
+! 	 * a call to check_cursor_col() may move the cursor, especially with
+! 	 * the "A" command, thus set State to avoid that. Also check that the
+! 	 * line number is still valid (lines may have been deleted).
+! 	 * Do not restore if v:char was set to a non-empty string. */
+! 	if (!equalpos(curwin->w_cursor, save_cursor)
+! # ifdef FEAT_EVAL
+! 		&& *get_vim_var_str(VV_CHAR) == NUL
+! # endif
+! 		&& save_cursor.lnum <= curbuf->b_ml.ml_line_count)
+  	{
+  	    int save_state = State;
+  
+*** ../vim-7.3.971/runtime/doc/autocmd.txt	2013-03-19 13:33:18.000000000 +0100
+--- runtime/doc/autocmd.txt	2013-05-19 21:05:59.000000000 +0200
+***************
+*** 674,681 ****
+  InsertEnter			Just before starting Insert mode.  Also for
+  				Replace mode and Virtual Replace mode.  The
+  				|v:insertmode| variable indicates the mode.
+! 				Be careful not to move the cursor or do
+! 				anything else that the user does not expect.
+  							*InsertLeave*
+  InsertLeave			When leaving Insert mode.  Also when using
+  				CTRL-O |i_CTRL-O|.  But not for |i_CTRL-C|.
+--- 691,701 ----
+  InsertEnter			Just before starting Insert mode.  Also for
+  				Replace mode and Virtual Replace mode.  The
+  				|v:insertmode| variable indicates the mode.
+! 				Be careful not to do anything else that the
+! 				user does not expect.
+! 				The cursor is restored afterwards.  If you do
+! 				not want that set |v:char| to a non-empty
+! 				string.
+  							*InsertLeave*
+  InsertLeave			When leaving Insert mode.  Also when using
+  				CTRL-O |i_CTRL-O|.  But not for |i_CTRL-C|.
+*** ../vim-7.3.971/src/version.c	2013-05-19 21:03:50.000000000 +0200
+--- src/version.c	2013-05-19 21:13:10.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     972,
+  /**/
+
+-- 
+It is illegal for anyone to try and stop a child from playfully jumping over
+puddles of water.
+		[real standing law in California, United States of America]
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.973 b/7.3.973
new file mode 100644
index 0000000..6a4ac10
--- /dev/null
+++ b/7.3.973
@@ -0,0 +1,137 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.973
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.973
+Problem:    Compiler warnings. Crash on startup. (Tony Mechelynck)
+Solution:   Change EMSG2 to EMSGN. Make array one character longer.
+Files:	    src/regexp_nfa.c
+
+
+*** ../vim-7.3.972/src/regexp_nfa.c	2013-05-19 19:16:25.000000000 +0200
+--- src/regexp_nfa.c	2013-05-19 21:56:31.000000000 +0200
+***************
+*** 273,279 ****
+  	NFA_HEAD, NFA_NHEAD, NFA_ALPHA, NFA_NALPHA,
+  	NFA_LOWER, NFA_NLOWER, NFA_UPPER, NFA_NUPPER
+      };
+!     char_u	myconfig[9];
+      char_u	config[NCONFIGS][9] = {
+  	"000000100",	/* digit */
+  	"100000100",	/* non digit */
+--- 273,279 ----
+  	NFA_HEAD, NFA_NHEAD, NFA_ALPHA, NFA_NALPHA,
+  	NFA_LOWER, NFA_NLOWER, NFA_UPPER, NFA_NUPPER
+      };
+!     char_u	myconfig[10];
+      char_u	config[NCONFIGS][9] = {
+  	"000000100",	/* digit */
+  	"100000100",	/* non digit */
+***************
+*** 400,406 ****
+      }
+      /* try to recognize character classes */
+      for (i = 0; i < NCONFIGS; i++)
+! 	if (STRNCMP(myconfig, config[i],8) == 0)
+  	    return classid[i] + extra_newl;
+  
+      /* fallthrough => no success so far */
+--- 400,406 ----
+      }
+      /* try to recognize character classes */
+      for (i = 0; i < NCONFIGS; i++)
+! 	if (STRNCMP(myconfig, config[i], 8) == 0)
+  	    return classid[i] + extra_newl;
+  
+      /* fallthrough => no success so far */
+***************
+*** 759,765 ****
+  	case Magic('&'):
+  	case Magic(')'):
+  	    syntax_error = TRUE;
+! 	    EMSG2(_(e_misplaced), no_Magic(c));
+  	    return FAIL;
+  
+  	case Magic('='):
+--- 759,765 ----
+  	case Magic('&'):
+  	case Magic(')'):
+  	    syntax_error = TRUE;
+! 	    EMSGN(_(e_misplaced), no_Magic(c));
+  	    return FAIL;
+  
+  	case Magic('='):
+***************
+*** 770,776 ****
+  	case Magic('{'):
+  	    /* these should follow an atom, not form an atom */
+  	    syntax_error = TRUE;
+! 	    EMSG2(_(e_misplaced), no_Magic(c));
+  	    return FAIL;
+  
+  	case Magic('~'):		/* previous substitute pattern */
+--- 770,776 ----
+  	case Magic('{'):
+  	    /* these should follow an atom, not form an atom */
+  	    syntax_error = TRUE;
+! 	    EMSGN(_(e_misplaced), no_Magic(c));
+  	    return FAIL;
+  
+  	case Magic('~'):		/* previous substitute pattern */
+***************
+*** 816,822 ****
+  		    return FAIL;
+  		default:
+  		    syntax_error = TRUE;
+! 		    EMSG2(_("E867: (NFA) Unknown operator '\\z%c'"),
+  								 no_Magic(c));
+  		    return FAIL;
+  	    }
+--- 816,822 ----
+  		    return FAIL;
+  		default:
+  		    syntax_error = TRUE;
+! 		    EMSGN(_("E867: (NFA) Unknown operator '\\z%c'"),
+  								 no_Magic(c));
+  		    return FAIL;
+  	    }
+***************
+*** 1363,1369 ****
+  		    return FAIL;
+  		default:
+  		    syntax_error = TRUE;
+! 		    EMSG2(_("E869: (NFA) Unknown operator '\\@%c'"), op);
+  		    return FAIL;
+  	    }
+  	    break;
+--- 1363,1369 ----
+  		    return FAIL;
+  		default:
+  		    syntax_error = TRUE;
+! 		    EMSGN(_("E869: (NFA) Unknown operator '\\@%c'"), op);
+  		    return FAIL;
+  	    }
+  	    break;
+*** ../vim-7.3.972/src/version.c	2013-05-19 21:15:08.000000000 +0200
+--- src/version.c	2013-05-19 22:29:03.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     973,
+  /**/
+
+-- 
+Sometimes I think the surest sign that intelligent life exists elsewhere
+in the universe is that none of it has tried to contact us.     (Calvin)
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.974 b/7.3.974
new file mode 100644
index 0000000..97f7e52
--- /dev/null
+++ b/7.3.974
@@ -0,0 +1,158 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.974
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.974
+Problem:    Can't build with ruby 1.8.5.
+Solution:   Only use ruby_init_stack() when RUBY_INIT_STACK is defined.
+	    (Yukihiro Nakadaira)
+Files:	    src/if_ruby.c
+
+
+*** ../vim-7.3.973/src/if_ruby.c	2013-05-12 14:10:41.000000000 +0200
+--- src/if_ruby.c	2013-05-20 12:47:48.000000000 +0200
+***************
+*** 158,165 ****
+  static void ruby_io_init(void);
+  static void ruby_vim_init(void);
+  
+! #if defined(__ia64) && !defined(ruby_init_stack)
+! # define ruby_init_stack(addr) ruby_init_stack((addr), rb_ia64_bsp())
+  #endif
+  
+  #if defined(DYNAMIC_RUBY) || defined(PROTO)
+--- 158,167 ----
+  static void ruby_io_init(void);
+  static void ruby_vim_init(void);
+  
+! #if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
+! # if defined(__ia64) && !defined(ruby_init_stack)
+! #  define ruby_init_stack(addr) ruby_init_stack((addr), rb_ia64_bsp())
+! # endif
+  #endif
+  
+  #if defined(DYNAMIC_RUBY) || defined(PROTO)
+***************
+*** 231,242 ****
+  #  define rb_float_new			dll_rb_float_new
+  #  define rb_ary_new			dll_rb_ary_new
+  #  define rb_ary_push			dll_rb_ary_push
+! #  ifdef __ia64
+! #   define rb_ia64_bsp		dll_rb_ia64_bsp
+! #   undef ruby_init_stack
+! #   define ruby_init_stack(addr)	dll_ruby_init_stack((addr), rb_ia64_bsp())
+! #  else
+! #   define ruby_init_stack	dll_ruby_init_stack
+  #  endif
+  # else
+  #  define rb_str2cstr			dll_rb_str2cstr
+--- 233,246 ----
+  #  define rb_float_new			dll_rb_float_new
+  #  define rb_ary_new			dll_rb_ary_new
+  #  define rb_ary_push			dll_rb_ary_push
+! #  if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
+! #   ifdef __ia64
+! #    define rb_ia64_bsp			dll_rb_ia64_bsp
+! #    undef ruby_init_stack
+! #    define ruby_init_stack(addr)	dll_ruby_init_stack((addr), rb_ia64_bsp())
+! #   else
+! #    define ruby_init_stack		dll_ruby_init_stack
+! #   endif
+  #  endif
+  # else
+  #  define rb_str2cstr			dll_rb_str2cstr
+***************
+*** 346,356 ****
+  static VALUE (*dll_rb_float_new) (double);
+  static VALUE (*dll_rb_ary_new) (void);
+  static VALUE (*dll_rb_ary_push) (VALUE, VALUE);
+! #  ifdef __ia64
+  static void * (*dll_rb_ia64_bsp) (void);
+  static void (*dll_ruby_init_stack)(VALUE*, void*);
+! #  else
+  static void (*dll_ruby_init_stack)(VALUE*);
+  #  endif
+  # endif
+  # ifdef RUBY19_OR_LATER
+--- 350,362 ----
+  static VALUE (*dll_rb_float_new) (double);
+  static VALUE (*dll_rb_ary_new) (void);
+  static VALUE (*dll_rb_ary_push) (VALUE, VALUE);
+! #  if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
+! #   ifdef __ia64
+  static void * (*dll_rb_ia64_bsp) (void);
+  static void (*dll_ruby_init_stack)(VALUE*, void*);
+! #   else
+  static void (*dll_ruby_init_stack)(VALUE*);
++ #   endif
+  #  endif
+  # endif
+  # ifdef RUBY19_OR_LATER
+***************
+*** 491,500 ****
+  # endif
+  # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18
+      {"rb_string_value_ptr", (RUBY_PROC*)&dll_rb_string_value_ptr},
+- #  ifdef __ia64
+-     {"rb_ia64_bsp", (RUBY_PROC*)&dll_rb_ia64_bsp},
+- #  endif
+-     {"ruby_init_stack", (RUBY_PROC*)&dll_ruby_init_stack},
+  #  if DYNAMIC_RUBY_VER <= 19
+      {"rb_float_new", (RUBY_PROC*)&dll_rb_float_new},
+  #  else
+--- 497,502 ----
+***************
+*** 513,518 ****
+--- 515,526 ----
+      {"rb_require", (RUBY_PROC*)&dll_rb_require},
+      {"ruby_process_options", (RUBY_PROC*)&dll_ruby_process_options},
+  # endif
++ # if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
++ #  ifdef __ia64
++     {"rb_ia64_bsp", (RUBY_PROC*)&dll_rb_ia64_bsp},
++ #  endif
++     {"ruby_init_stack", (RUBY_PROC*)&dll_ruby_init_stack},
++ # endif
+      {"", NULL},
+  };
+  
+***************
+*** 735,741 ****
+  	    NtInitialize(&argc, &argv);
+  #endif
+  	    {
+! #if defined(RUBY_VERSION) && RUBY_VERSION >= 18
+  		ruby_init_stack(ruby_stack_start);
+  #endif
+  		ruby_init();
+--- 743,749 ----
+  	    NtInitialize(&argc, &argv);
+  #endif
+  	    {
+! #if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
+  		ruby_init_stack(ruby_stack_start);
+  #endif
+  		ruby_init();
+*** ../vim-7.3.973/src/version.c	2013-05-19 22:31:13.000000000 +0200
+--- src/version.c	2013-05-20 12:51:22.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     974,
+  /**/
+
+-- 
+bashian roulette:
+$ ((RANDOM%6)) || rm -rf ~
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.975 b/7.3.975
new file mode 100644
index 0000000..d4b97ac
--- /dev/null
+++ b/7.3.975
@@ -0,0 +1,70 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.975
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.975
+Problem:    Crash in regexp parsing.
+Solution:   Correctly compute the end of allocated memory.
+Files:	    src/regexp_nfa.c
+
+
+*** ../vim-7.3.974/src/regexp_nfa.c	2013-05-19 22:31:13.000000000 +0200
+--- src/regexp_nfa.c	2013-05-20 13:43:37.000000000 +0200
+***************
+*** 231,244 ****
+      /* A reasonable estimation for size */
+      nstate_max = (STRLEN(expr) + 1) * NFA_POSTFIX_MULTIPLIER;
+  
+!     /* Size for postfix representation of expr */
+      postfix_size = sizeof(*post_start) * nstate_max;
+      post_start = (int *)lalloc(postfix_size, TRUE);
+      if (post_start == NULL)
+  	return FAIL;
+      vim_memset(post_start, 0, postfix_size);
+      post_ptr = post_start;
+!     post_end = post_start + postfix_size;
+      nfa_has_zend = FALSE;
+  
+      regcomp_start(expr, re_flags);
+--- 231,249 ----
+      /* A reasonable estimation for size */
+      nstate_max = (STRLEN(expr) + 1) * NFA_POSTFIX_MULTIPLIER;
+  
+!     /* Some items blow up in size, such as [A-z].  Add more space for that.
+!      * TODO: some patterns may still fail. */
+! //    nstate_max += 1000;
+! 
+!     /* Size for postfix representation of expr. */
+      postfix_size = sizeof(*post_start) * nstate_max;
++ 
+      post_start = (int *)lalloc(postfix_size, TRUE);
+      if (post_start == NULL)
+  	return FAIL;
+      vim_memset(post_start, 0, postfix_size);
+      post_ptr = post_start;
+!     post_end = post_start + nstate_max;
+      nfa_has_zend = FALSE;
+  
+      regcomp_start(expr, re_flags);
+*** ../vim-7.3.974/src/version.c	2013-05-20 12:52:23.000000000 +0200
+--- src/version.c	2013-05-20 13:42:10.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     975,
+  /**/
+
+-- 
+My Go, this amn keyboar oesn't have a .
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.976 b/7.3.976
new file mode 100644
index 0000000..1012e73
--- /dev/null
+++ b/7.3.976
@@ -0,0 +1,87 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.976
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.976
+Problem:    Can't build on HP-UX.
+Solution:   Remove modern initialization. (John Marriott)
+Files:	    src/regexp_nfa.c
+
+
+*** ../vim-7.3.975/src/regexp_nfa.c	2013-05-20 13:44:24.000000000 +0200
+--- src/regexp_nfa.c	2013-05-20 13:51:07.000000000 +0200
+***************
+*** 1961,1974 ****
+  static Frag_T st_pop __ARGS((Frag_T **p, Frag_T *stack));
+  
+  /*
+!  * Initialize Frag_T struct.
+   */
+      static Frag_T
+  frag(start, out)
+      nfa_state_T	*start;
+      Ptrlist	*out;
+  {
+!     Frag_T n = { start, out };
+      return n;
+  }
+  
+--- 1961,1977 ----
+  static Frag_T st_pop __ARGS((Frag_T **p, Frag_T *stack));
+  
+  /*
+!  * Initialize a Frag_T struct and return it.
+   */
+      static Frag_T
+  frag(start, out)
+      nfa_state_T	*start;
+      Ptrlist	*out;
+  {
+!     Frag_T n;
+! 
+!     n.start = start;
+!     n.out = out;
+      return n;
+  }
+  
+***************
+*** 2144,2150 ****
+      if (postfix == NULL)
+  	return NULL;
+  
+! #define PUSH(s)	    st_push ((s), &stackp, stack_end)
+  #define POP()	    st_pop(&stackp, stack);		\
+  		    if (stackp < stack)			\
+  		    {					\
+--- 2147,2153 ----
+      if (postfix == NULL)
+  	return NULL;
+  
+! #define PUSH(s)	    st_push((s), &stackp, stack_end)
+  #define POP()	    st_pop(&stackp, stack);		\
+  		    if (stackp < stack)			\
+  		    {					\
+*** ../vim-7.3.975/src/version.c	2013-05-20 13:44:24.000000000 +0200
+--- src/version.c	2013-05-20 13:54:56.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     976,
+  /**/
+
+-- 
+Dogs must have a permit signed by the mayor in order to congregate in groups
+of three or more on private property.
+		[real standing law in Oklahoma, United States of America]
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.977 b/7.3.977
new file mode 100644
index 0000000..d6a3097
--- /dev/null
+++ b/7.3.977
@@ -0,0 +1,294 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.977
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.977
+Problem:    Compiler warnings on 64 bit Windows.
+Solution:   Add type casts. (Mike Williams)  Also fix some white space and
+	    uncomment what was commented-out for testing.
+Files:	    src/regexp_nfa.c
+
+
+*** ../vim-7.3.976/src/regexp_nfa.c	2013-05-20 13:55:17.000000000 +0200
+--- src/regexp_nfa.c	2013-05-20 14:24:44.000000000 +0200
+***************
+*** 224,239 ****
+      char_u	*expr;
+      int		re_flags;	    /* see vim_regcomp() */
+  {
+!     int		postfix_size;
+  
+      nstate = 0;
+      istate = 0;
+      /* A reasonable estimation for size */
+!     nstate_max = (STRLEN(expr) + 1) * NFA_POSTFIX_MULTIPLIER;
+  
+      /* Some items blow up in size, such as [A-z].  Add more space for that.
+       * TODO: some patterns may still fail. */
+! //    nstate_max += 1000;
+  
+      /* Size for postfix representation of expr. */
+      postfix_size = sizeof(*post_start) * nstate_max;
+--- 224,239 ----
+      char_u	*expr;
+      int		re_flags;	    /* see vim_regcomp() */
+  {
+!     size_t	postfix_size;
+  
+      nstate = 0;
+      istate = 0;
+      /* A reasonable estimation for size */
+!     nstate_max = (int)(STRLEN(expr) + 1) * NFA_POSTFIX_MULTIPLIER;
+  
+      /* Some items blow up in size, such as [A-z].  Add more space for that.
+       * TODO: some patterns may still fail. */
+!     nstate_max += 1000;
+  
+      /* Size for postfix representation of expr. */
+      postfix_size = sizeof(*post_start) * nstate_max;
+***************
+*** 2177,2183 ****
+  	     * No new state added here. */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate += 0;
+  		break;
+  	    }
+  	    e2 = POP();
+--- 2177,2183 ----
+  	     * No new state added here. */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		/* nstate += 0; */
+  		break;
+  	    }
+  	    e2 = POP();
+***************
+*** 2190,2196 ****
+  	    /* Negation of a character */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate += 0;
+  		break;
+  	    }
+  	    e1 = POP();
+--- 2190,2196 ----
+  	    /* Negation of a character */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		/* nstate += 0; */
+  		break;
+  	    }
+  	    e1 = POP();
+***************
+*** 2204,2210 ****
+  	    /* Alternation */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate ++;
+  		break;
+  	    }
+  	    e2 = POP();
+--- 2204,2210 ----
+  	    /* Alternation */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate++;
+  		break;
+  	    }
+  	    e2 = POP();
+***************
+*** 2219,2225 ****
+  	    /* Zero or more */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate ++;
+  		break;
+  	    }
+  	    e = POP();
+--- 2219,2225 ----
+  	    /* Zero or more */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate++;
+  		break;
+  	    }
+  	    e = POP();
+***************
+*** 2234,2240 ****
+  	    /* one or zero atoms=> greedy match */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate ++;
+  		break;
+  	    }
+  	    e = POP();
+--- 2234,2240 ----
+  	    /* one or zero atoms=> greedy match */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate++;
+  		break;
+  	    }
+  	    e = POP();
+***************
+*** 2248,2254 ****
+  	    /* zero or one atoms => non-greedy match */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate ++;
+  		break;
+  	    }
+  	    e = POP();
+--- 2248,2254 ----
+  	    /* zero or one atoms => non-greedy match */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate++;
+  		break;
+  	    }
+  	    e = POP();
+***************
+*** 2262,2268 ****
+  	    /* One or more */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate ++;
+  		break;
+  	    }
+  	    e = POP();
+--- 2262,2268 ----
+  	    /* One or more */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate++;
+  		break;
+  	    }
+  	    e = POP();
+***************
+*** 2278,2284 ****
+  	     * with max/min count of 0 */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate ++;
+  		break;
+  	    }
+  	    s = new_state(NFA_SKIP_CHAR, NULL, NULL);
+--- 2278,2284 ----
+  	     * with max/min count of 0 */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate++;
+  		break;
+  	    }
+  	    s = new_state(NFA_SKIP_CHAR, NULL, NULL);
+***************
+*** 2392,2398 ****
+  	    /* Operands */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate ++;
+  		break;
+  	    }
+  	    s = new_state(*p, NULL, NULL);
+--- 2392,2398 ----
+  	    /* Operands */
+  	    if (nfa_calc_size == TRUE)
+  	    {
+! 		nstate++;
+  		break;
+  	    }
+  	    s = new_state(*p, NULL, NULL);
+***************
+*** 2407,2413 ****
+  
+      if (nfa_calc_size == TRUE)
+      {
+! 	nstate ++;
+  	return NULL;	/* Return value when counting size is ignored anyway */
+      }
+  
+--- 2407,2413 ----
+  
+      if (nfa_calc_size == TRUE)
+      {
+! 	nstate++;
+  	return NULL;	/* Return value when counting size is ignored anyway */
+      }
+  
+***************
+*** 2583,2589 ****
+  		save.startpos[subidx] = m->startpos[subidx];
+  		save.endpos[subidx] = m->endpos[subidx];
+  		m->startpos[subidx].lnum = reglnum;
+! 		m->startpos[subidx].col = reginput - regline + off;
+  	    }
+  	    else
+  	    {
+--- 2583,2589 ----
+  		save.startpos[subidx] = m->startpos[subidx];
+  		save.endpos[subidx] = m->endpos[subidx];
+  		m->startpos[subidx].lnum = reglnum;
+! 		m->startpos[subidx].col = (colnr_T)(reginput - regline + off);
+  	    }
+  	    else
+  	    {
+***************
+*** 2631,2637 ****
+  		save.startpos[subidx] = m->startpos[subidx];
+  		save.endpos[subidx] = m->endpos[subidx];
+  		m->endpos[subidx].lnum = reglnum;
+! 		m->endpos[subidx].col = reginput - regline + off;
+  	    }
+  	    else
+  	    {
+--- 2631,2637 ----
+  		save.startpos[subidx] = m->startpos[subidx];
+  		save.endpos[subidx] = m->endpos[subidx];
+  		m->endpos[subidx].lnum = reglnum;
+! 		m->endpos[subidx].col = (colnr_T)(reginput - regline + off);
+  	    }
+  	    else
+  	    {
+***************
+*** 3620,3626 ****
+      int		re_flags;
+  {
+      nfa_regprog_T	*prog;
+!     int			prog_size;
+      int			*postfix;
+  
+      if (expr == NULL)
+--- 3620,3626 ----
+      int		re_flags;
+  {
+      nfa_regprog_T	*prog;
+!     size_t		prog_size;
+      int			*postfix;
+  
+      if (expr == NULL)
+*** ../vim-7.3.976/src/version.c	2013-05-20 13:55:17.000000000 +0200
+--- src/version.c	2013-05-20 21:24:28.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     977,
+  /**/
+
+-- 
+A law to reduce crime states: "It is mandatory for a motorist with criminal
+intentions to stop at the city limits and telephone the chief of police as he
+is entering the town.
+		[real standing law in Washington, United States of America]
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.978 b/7.3.978
new file mode 100644
index 0000000..168596d
--- /dev/null
+++ b/7.3.978
@@ -0,0 +1,180 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.978
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.978
+Problem:    Regexp debug logs don't have a good name.
+Solution:   Use clear names and make it possible to write logs for the old and
+	    new engines separately. (Taro Muraoka)
+Files:	    src/regexp.c, src/regexp_nfa.c
+
+
+*** ../vim-7.3.977/src/regexp.c	2013-05-19 19:16:25.000000000 +0200
+--- src/regexp.c	2013-05-20 21:41:19.000000000 +0200
+***************
+*** 51,56 ****
+--- 51,58 ----
+  # define BT_REGEXP_DUMP
+  /* save the debugging data to a file instead of displaying it */
+  # define BT_REGEXP_LOG
++ # define BT_REGEXP_DEBUG_LOG
++ # define BT_REGEXP_DEBUG_LOG_NAME	"bt_regexp_debug.log"
+  #endif
+  
+  /*
+***************
+*** 7828,7838 ****
+  
+      if (prog == NULL)	    /* error compiling regexp with initial engine */
+      {
+! #ifdef DEBUG
+  	if (regexp_engine != BACKTRACKING_ENGINE)   /* debugging log for NFA */
+  	{
+  	    FILE *f;
+! 	    f = fopen("debug.log", "a");
+  	    if (f)
+  	    {
+  		if (!syntax_error)
+--- 7830,7840 ----
+  
+      if (prog == NULL)	    /* error compiling regexp with initial engine */
+      {
+! #ifdef BT_REGEXP_DEBUG_LOG
+  	if (regexp_engine != BACKTRACKING_ENGINE)   /* debugging log for NFA */
+  	{
+  	    FILE *f;
+! 	    f = fopen(BT_REGEXP_DEBUG_LOG_NAME, "a");
+  	    if (f)
+  	    {
+  		if (!syntax_error)
+***************
+*** 7842,7848 ****
+  		fclose(f);
+  	    }
+  	    else
+! 		EMSG("(NFA) Could not open \"debug.log\" to write !!!");
+  	    /*
+  	    if (syntax_error)
+  		EMSG("NFA Regexp: Syntax Error !");
+--- 7844,7851 ----
+  		fclose(f);
+  	    }
+  	    else
+! 		EMSG2("(NFA) Could not open \"%s\" to write !!!",
+!                         BT_REGEXP_DEBUG_LOG_NAME);
+  	    /*
+  	    if (syntax_error)
+  		EMSG("NFA Regexp: Syntax Error !");
+*** ../vim-7.3.977/src/regexp_nfa.c	2013-05-20 21:26:26.000000000 +0200
+--- src/regexp_nfa.c	2013-05-20 21:41:19.000000000 +0200
+***************
+*** 9,14 ****
+--- 9,16 ----
+  /* Comment this out to disable log files. They can get pretty big */
+  # define ENABLE_LOG
+  # define LOG_NAME "log_nfarun.log"
++ # define NFA_REGEXP_DEBUG_LOG
++ # define NFA_REGEXP_DEBUG_LOG_NAME	"nfa_regexp_debug.log"
+  #endif
+  
+  /* Upper limit allowed for {m,n} repetitions handled by NFA */
+***************
+*** 2849,2860 ****
+      int		*listids = NULL;
+      int		j = 0;
+      int		len = 0;
+! #ifdef DEBUG
+!     FILE	*debug = fopen("list.log", "a");
+  
+      if (debug == NULL)
+      {
+! 	EMSG(_("(NFA) COULD NOT OPEN list.log !"));
+  	return FALSE;
+      }
+  #endif
+--- 2851,2862 ----
+      int		*listids = NULL;
+      int		j = 0;
+      int		len = 0;
+! #ifdef NFA_REGEXP_DEBUG_LOG
+!     FILE	*debug = fopen(NFA_REGEXP_DEBUG_LOG_NAME, "a");
+  
+      if (debug == NULL)
+      {
+! 	EMSG2(_("(NFA) COULD NOT OPEN %s !"), NFA_REGEXP_DEBUG_LOG_NAME);
+  	return FALSE;
+      }
+  #endif
+***************
+*** 2950,2956 ****
+  	fprintf(log_fd, "\n");
+  #endif
+  
+! #ifdef DEBUG
+  	fprintf(debug, "\n-------------------\n");
+  #endif
+  
+--- 2952,2958 ----
+  	fprintf(log_fd, "\n");
+  #endif
+  
+! #ifdef NFA_REGEXP_DEBUG_LOG
+  	fprintf(debug, "\n-------------------\n");
+  #endif
+  
+***************
+*** 2966,2972 ****
+  	    else
+  		t = &thislist->t[i];
+  
+! #ifdef DEBUG
+  	    nfa_set_code(t->state->c);
+  	    fprintf(debug, "%s, ", code);
+  #endif
+--- 2968,2974 ----
+  	    else
+  		t = &thislist->t[i];
+  
+! #ifdef NFA_REGEXP_DEBUG_LOG
+  	    nfa_set_code(t->state->c);
+  	    fprintf(debug, "%s, ", code);
+  #endif
+***************
+*** 3436,3442 ****
+      if (listids != NULL)
+  	vim_free(listids);
+  #undef ADD_POS_NEG_STATE
+! #ifdef DEBUG
+      fclose(debug);
+  #endif
+  
+--- 3438,3444 ----
+      if (listids != NULL)
+  	vim_free(listids);
+  #undef ADD_POS_NEG_STATE
+! #ifdef NFA_REGEXP_DEBUG_LOG
+      fclose(debug);
+  #endif
+  
+*** ../vim-7.3.977/src/version.c	2013-05-20 21:26:26.000000000 +0200
+--- src/version.c	2013-05-20 21:48:27.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     978,
+  /**/
+
+-- 
+SIGIRO -- irony detected (iron core dumped)
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.979 b/7.3.979
new file mode 100644
index 0000000..e7ca5de
--- /dev/null
+++ b/7.3.979
@@ -0,0 +1,69 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.979
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.979
+Problem:    Complex NFA regexp doesn't work.
+Solution:   Set actual state stack end instead of using an arbitrary number.
+	    (Yasuhiro Matsumoto)
+Files:	    src/regexp_nfa.c
+
+
+*** ../vim-7.3.978/src/regexp_nfa.c	2013-05-20 21:49:08.000000000 +0200
+--- src/regexp_nfa.c	2013-05-20 21:53:24.000000000 +0200
+***************
+*** 17,24 ****
+  #define	    NFA_BRACES_MAXLIMIT		    10
+  /* For allocating space for the postfix representation */
+  #define	    NFA_POSTFIX_MULTIPLIER	    (NFA_BRACES_MAXLIMIT + 2)*2
+- /* Size of stack, used when converting the postfix regexp into NFA */
+- #define	    NFA_STACK_SIZE		    1024
+  
+  enum
+  {
+--- 17,22 ----
+***************
+*** 2160,2168 ****
+      if (nfa_calc_size == FALSE)
+      {
+  	/* Allocate space for the stack. Max states on the stack : nstate */
+! 	stack = (Frag_T *) lalloc((nstate + 1)*sizeof(Frag_T), TRUE);
+  	stackp = stack;
+! 	stack_end = stack + NFA_STACK_SIZE;
+      }
+  
+      for (p = postfix; p < end; ++p)
+--- 2158,2166 ----
+      if (nfa_calc_size == FALSE)
+      {
+  	/* Allocate space for the stack. Max states on the stack : nstate */
+! 	stack = (Frag_T *) lalloc((nstate + 1) * sizeof(Frag_T), TRUE);
+  	stackp = stack;
+! 	stack_end = stack + (nstate + 1);
+      }
+  
+      for (p = postfix; p < end; ++p)
+*** ../vim-7.3.978/src/version.c	2013-05-20 21:49:08.000000000 +0200
+--- src/version.c	2013-05-20 21:55:37.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     979,
+  /**/
+
+-- 
+   Another bucket of what can only be described as human ordure hits ARTHUR.
+ARTHUR: ... Right!  (to the KNIGHTS) That settles it!
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.980 b/7.3.980
new file mode 100644
index 0000000..f57d5f7
--- /dev/null
+++ b/7.3.980
@@ -0,0 +1,141 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.980
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.980
+Problem:    Regexp logs may contain garbage. Character classes don't work
+	    correctly for multi-byte characters.
+Solution:   Check for end of post list.  Only use "is" functions for
+	    characters up to 255. (Ken Takata)
+Files:	    src/regexp_nfa.c
+
+
+*** ../vim-7.3.979/src/regexp_nfa.c	2013-05-20 21:56:53.000000000 +0200
+--- src/regexp_nfa.c	2013-05-20 22:09:01.000000000 +0200
+***************
+*** 1826,1838 ****
+  	else if (retval == OK)
+  	    fprintf(f, ">>> NFA engine succeeded !\n");
+  	fprintf(f, "Regexp: \"%s\"\nPostfix notation (char): \"", expr);
+! 	for (p=post_start; *p; p++)
+  	{
+  	    nfa_set_code(*p);
+  	    fprintf(f, "%s, ", code);
+  	}
+  	fprintf(f, "\"\nPostfix notation (int): ");
+! 	for (p=post_start; *p; p++)
+  		fprintf(f, "%d ", *p);
+  	fprintf(f, "\n\n");
+  	fclose(f);
+--- 1826,1838 ----
+  	else if (retval == OK)
+  	    fprintf(f, ">>> NFA engine succeeded !\n");
+  	fprintf(f, "Regexp: \"%s\"\nPostfix notation (char): \"", expr);
+! 	for (p = post_start; *p && p < post_end; p++)
+  	{
+  	    nfa_set_code(*p);
+  	    fprintf(f, "%s, ", code);
+  	}
+  	fprintf(f, "\"\nPostfix notation (int): ");
+! 	for (p = post_start; *p && p < post_end; p++)
+  		fprintf(f, "%d ", *p);
+  	fprintf(f, "\n\n");
+  	fclose(f);
+***************
+*** 2667,2677 ****
+      switch (class)
+      {
+  	case NFA_CLASS_ALNUM:
+! 	    if (isalnum(c))
+  		return OK;
+  	    break;
+  	case NFA_CLASS_ALPHA:
+! 	    if (isalpha(c))
+  		return OK;
+  	    break;
+  	case NFA_CLASS_BLANK:
+--- 2667,2677 ----
+      switch (class)
+      {
+  	case NFA_CLASS_ALNUM:
+! 	    if (c >= 1 && c <= 255 && isalnum(c))
+  		return OK;
+  	    break;
+  	case NFA_CLASS_ALPHA:
+! 	    if (c >= 1 && c <= 255 && isalpha(c))
+  		return OK;
+  	    break;
+  	case NFA_CLASS_BLANK:
+***************
+*** 2679,2685 ****
+  		return OK;
+  	    break;
+  	case NFA_CLASS_CNTRL:
+! 	    if (iscntrl(c))
+  		return OK;
+  	    break;
+  	case NFA_CLASS_DIGIT:
+--- 2679,2685 ----
+  		return OK;
+  	    break;
+  	case NFA_CLASS_CNTRL:
+! 	    if (c >= 1 && c <= 255 && iscntrl(c))
+  		return OK;
+  	    break;
+  	case NFA_CLASS_DIGIT:
+***************
+*** 2687,2693 ****
+  		return OK;
+  	    break;
+  	case NFA_CLASS_GRAPH:
+! 	    if (isgraph(c))
+  		return OK;
+  	    break;
+  	case NFA_CLASS_LOWER:
+--- 2687,2693 ----
+  		return OK;
+  	    break;
+  	case NFA_CLASS_GRAPH:
+! 	    if (c >= 1 && c <= 255 && isgraph(c))
+  		return OK;
+  	    break;
+  	case NFA_CLASS_LOWER:
+***************
+*** 2699,2705 ****
+  		return OK;
+  	    break;
+  	case NFA_CLASS_PUNCT:
+! 	    if (ispunct(c))
+  		return OK;
+  	    break;
+  	case NFA_CLASS_SPACE:
+--- 2699,2705 ----
+  		return OK;
+  	    break;
+  	case NFA_CLASS_PUNCT:
+! 	    if (c >= 1 && c <= 255 && ispunct(c))
+  		return OK;
+  	    break;
+  	case NFA_CLASS_SPACE:
+*** ../vim-7.3.979/src/version.c	2013-05-20 21:56:53.000000000 +0200
+--- src/version.c	2013-05-20 22:10:54.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     980,
+  /**/
+
+-- 
+Why is "abbreviation" such a long word?
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.981 b/7.3.981
new file mode 100644
index 0000000..d118585
--- /dev/null
+++ b/7.3.981
@@ -0,0 +1,101 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.981
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.981
+Problem:    In the old regexp engine \i, \I, \f and \F don't work on
+	    multi-byte characters.
+Solution:   Dereference pointer properly.
+Files:      src/regexp.c, src/testdir/test64.in, src/testdir/test64.ok
+
+
+*** ../vim-7.3.980/src/regexp.c	2013-05-20 21:49:08.000000000 +0200
+--- src/regexp.c	2013-05-20 23:58:32.000000000 +0200
+***************
+*** 5758,5764 ****
+        case SIDENT + ADD_NL:
+  	while (count < maxcount)
+  	{
+! 	    if (vim_isIDc(*scan) && (testval || !VIM_ISDIGIT(*scan)))
+  	    {
+  		mb_ptr_adv(scan);
+  	    }
+--- 5758,5764 ----
+        case SIDENT + ADD_NL:
+  	while (count < maxcount)
+  	{
+! 	    if (vim_isIDc(PTR2CHAR(scan)) && (testval || !VIM_ISDIGIT(*scan)))
+  	    {
+  		mb_ptr_adv(scan);
+  	    }
+***************
+*** 5819,5825 ****
+        case SFNAME + ADD_NL:
+  	while (count < maxcount)
+  	{
+! 	    if (vim_isfilec(*scan) && (testval || !VIM_ISDIGIT(*scan)))
+  	    {
+  		mb_ptr_adv(scan);
+  	    }
+--- 5819,5825 ----
+        case SFNAME + ADD_NL:
+  	while (count < maxcount)
+  	{
+! 	    if (vim_isfilec(PTR2CHAR(scan)) && (testval || !VIM_ISDIGIT(*scan)))
+  	    {
+  		mb_ptr_adv(scan);
+  	    }
+*** ../vim-7.3.980/src/testdir/test64.in	2013-05-19 19:16:25.000000000 +0200
+--- src/testdir/test64.in	2013-05-20 23:58:09.000000000 +0200
+***************
+*** 262,267 ****
+--- 262,271 ----
+  :call add(tl, ['[a-zA-Z]', 'a', 'a'])
+  :call add(tl, ['[A-Z]', 'a'])
+  :call add(tl, ['\C[^A-Z]\+', 'ABCOIJDEOIFNSD jsfoij sa', ' jsfoij sa'])
++ :call add(tl, ['\i\+', '&*§xx ', 'xx'])
++ :call add(tl, ['\%#=1\i\+', '&*§xx ', 'xx'])
++ :call add(tl, ['\f\+', '&*Ÿfname ', 'fname'])
++ :call add(tl, ['\%#=1\i\+', '&*Ÿfname ', 'fname'])
+  
+  :"""" Tests for \z features
+  :call add(tl, ['xx \ze test', 'xx '])					" must match after \ze
+*** ../vim-7.3.980/src/testdir/test64.ok	2013-05-19 19:16:25.000000000 +0200
+--- src/testdir/test64.ok	2013-05-21 00:00:08.000000000 +0200
+***************
+*** 203,208 ****
+--- 203,212 ----
+  OK - [a-zA-Z]
+  OK - [A-Z]
+  OK - \C[^A-Z]\+
++ OK - \i\+
++ OK - \%#=1\i\+
++ OK - \f\+
++ OK - \%#=1\i\+
+  OK - xx \ze test
+  OK - abc\zeend
+  OK - abc\zsdd
+*** ../vim-7.3.980/src/version.c	2013-05-20 22:19:58.000000000 +0200
+--- src/version.c	2013-05-21 00:01:30.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     981,
+  /**/
+
+-- 
+   [The rest of the ARMY stand around looking at a loss.]
+INSPECTOR END OF FILM: (picks up megaphone) All right!  Clear off!  Go on!
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.982 b/7.3.982
new file mode 100644
index 0000000..3e8b94f
--- /dev/null
+++ b/7.3.982
@@ -0,0 +1,97 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.982
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.982
+Problem:    In the new regexp engine \p does not work on multi-byte
+	    characters.
+Solution:   Don't point to an integer but the characters.
+Files:	    src/regexp_nfa.c, src/testdir/test95.in, src/testdir/test95.ok
+
+
+*** ../vim-7.3.981/src/regexp_nfa.c	2013-05-20 22:19:58.000000000 +0200
+--- src/regexp_nfa.c	2013-05-21 12:34:02.000000000 +0200
+***************
+*** 2931,2937 ****
+  	}
+  	if (c == NUL)
+  	    n = 0;
+! 	cc = (char_u *)&c;
+  
+  	/* swap lists */
+  	thislist = &list[flag];
+--- 2931,2937 ----
+  	}
+  	if (c == NUL)
+  	    n = 0;
+! 	cc = reginput;
+  
+  	/* swap lists */
+  	thislist = &list[flag];
+***************
+*** 2960,2966 ****
+  	    if (neglist->n > 0)
+  	    {
+  		t = &neglist->t[0];
+! 		neglist->n --;
+  		i--;
+  	    }
+  	    else
+--- 2960,2966 ----
+  	    if (neglist->n > 0)
+  	    {
+  		t = &neglist->t[0];
+! 		neglist->n--;
+  		i--;
+  	    }
+  	    else
+*** ../vim-7.3.981/src/testdir/test95.in	2013-05-19 19:16:25.000000000 +0200
+--- src/testdir/test95.in	2013-05-21 12:24:56.000000000 +0200
+***************
+*** 25,30 ****
+--- 25,33 ----
+  :call add(tl, [' [^ ]\+', 'start มabcdม ', ' มabcdม'])
+  :call add(tl, ['[ม[:alpha:][=a=]]\+', '879 aiaãมâมaiuvna ', 'aiaãมâมaiuvna'])
+  
++ :" this is not a normal "i" but 0xec
++ :call add(tl, ['\p\+', 'ìa', 'ìa'])
++ 
+  :"""" Run the tests
+  
+  :"
+*** ../vim-7.3.981/src/testdir/test95.ok	2013-05-19 19:16:25.000000000 +0200
+--- src/testdir/test95.ok	2013-05-21 12:31:00.000000000 +0200
+***************
+*** 4,6 ****
+--- 4,7 ----
+  OK - [^ม ]\+
+  OK -  [^ ]\+
+  OK - [ม[:alpha:][=a=]]\+
++ OK - \p\+
+*** ../vim-7.3.981/src/version.c	2013-05-21 00:02:54.000000000 +0200
+--- src/version.c	2013-05-21 12:32:41.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     982,
+  /**/
+
+-- 
+ERIC IDLE PLAYED: THE DEAD COLLECTOR, MR BINT (A VILLAGE NE'ER-DO -WELL VERY
+                  KEEN ON BURNING WITCHES), SIR ROBIN, THE GUARD WHO DOESN'T
+                  HICOUGH BUT TRIES TO GET THINGS STRAIGHT, CONCORDE (SIR
+                  LAUNCELOT'S TRUSTY STEED), ROGER THE SHRUBBER (A SHRUBBER),
+                  BROTHER MAYNARD
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.983 b/7.3.983
new file mode 100644
index 0000000..19b4a9c
--- /dev/null
+++ b/7.3.983
@@ -0,0 +1,109 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.983
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.983
+Problem:    Uneccessary temp variable.
+Solution:   Remove the variable.
+Files:	    src/regexp_nfa.c
+
+
+*** ../vim-7.3.982/src/regexp_nfa.c	2013-05-21 12:34:13.000000000 +0200
+--- src/regexp_nfa.c	2013-05-21 12:35:37.000000000 +0200
+***************
+*** 2833,2839 ****
+      int		old_reglnum = -1;
+      int		reginput_updated = FALSE;
+      thread_T	*t;
+-     char_u	*cc;
+      char_u	*old_reginput = NULL;
+      char_u	*old_regline = NULL;
+      nfa_state_T	*sta;
+--- 2833,2838 ----
+***************
+*** 2931,2937 ****
+  	}
+  	if (c == NUL)
+  	    n = 0;
+- 	cc = reginput;
+  
+  	/* swap lists */
+  	thislist = &list[flag];
+--- 2930,2935 ----
+***************
+*** 3261,3272 ****
+  		break;
+  
+  	    case NFA_KWORD:	/*  \k	*/
+! 		result = vim_iswordp(cc);
+  		ADD_POS_NEG_STATE(t->state);
+  		break;
+  
+  	    case NFA_SKWORD:	/*  \K	*/
+! 		result = !VIM_ISDIGIT(c) && vim_iswordp(cc);
+  		ADD_POS_NEG_STATE(t->state);
+  		break;
+  
+--- 3259,3270 ----
+  		break;
+  
+  	    case NFA_KWORD:	/*  \k	*/
+! 		result = vim_iswordp(reginput);
+  		ADD_POS_NEG_STATE(t->state);
+  		break;
+  
+  	    case NFA_SKWORD:	/*  \K	*/
+! 		result = !VIM_ISDIGIT(c) && vim_iswordp(reginput);
+  		ADD_POS_NEG_STATE(t->state);
+  		break;
+  
+***************
+*** 3281,3292 ****
+  		break;
+  
+  	    case NFA_PRINT:	/*  \p	*/
+! 		result = ptr2cells(cc) == 1;
+  		ADD_POS_NEG_STATE(t->state);
+  		break;
+  
+  	    case NFA_SPRINT:	/*  \P	*/
+! 		result = !VIM_ISDIGIT(c) && ptr2cells(cc) == 1;
+  		ADD_POS_NEG_STATE(t->state);
+  		break;
+  
+--- 3279,3290 ----
+  		break;
+  
+  	    case NFA_PRINT:	/*  \p	*/
+! 		result = ptr2cells(reginput) == 1;
+  		ADD_POS_NEG_STATE(t->state);
+  		break;
+  
+  	    case NFA_SPRINT:	/*  \P	*/
+! 		result = !VIM_ISDIGIT(c) && ptr2cells(reginput) == 1;
+  		ADD_POS_NEG_STATE(t->state);
+  		break;
+  
+*** ../vim-7.3.982/src/version.c	2013-05-21 12:34:13.000000000 +0200
+--- src/version.c	2013-05-21 12:41:58.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     983,
+  /**/
+
+-- 
+Communication is one of the most compli..., eh, well, it's hard.
+You know what I mean.  Not?
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.984 b/7.3.984
new file mode 100644
index 0000000..c767638
--- /dev/null
+++ b/7.3.984
@@ -0,0 +1,49 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.984
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.984
+Problem:    A Visual mapping that uses CTRL-G works differently when started
+	    from Insert mode. (Ein Brown)
+Solution:   Reset old_mapped_len when handling typed text in Select mode.
+Files:	    src/normal.c
+
+
+*** ../vim-7.3.983/src/normal.c	2013-05-06 04:21:35.000000000 +0200
+--- src/normal.c	2013-05-20 21:11:55.000000000 +0200
+***************
+*** 701,706 ****
+--- 701,707 ----
+  	else
+  	    c = 'c';
+  	msg_nowait = TRUE;	/* don't delay going to insert mode */
++ 	old_mapped_len = 0;	/* do go to Insert mode */
+      }
+  #endif
+  
+*** ../vim-7.3.983/src/version.c	2013-05-21 12:43:52.000000000 +0200
+--- src/version.c	2013-05-21 12:45:02.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     984,
+  /**/
+
+-- 
+MICHAEL PALIN PLAYED: 1ST SOLDIER WITH A KEEN INTEREST IN BIRDS, DENNIS, MR
+                      DUCK (A VILLAGE CARPENTER WHO IS ALMOST KEENER THAN
+                      ANYONE ELSE TO BURN WITCHES), THREE-HEADED KNIGHT, SIR
+                      GALAHAD, KING OF SWAMP CASTLE, BROTHER MAYNARD'S ROOMATE
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.985 b/7.3.985
new file mode 100644
index 0000000..9772951
--- /dev/null
+++ b/7.3.985
@@ -0,0 +1,51 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.985
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.985
+Problem:    GTK vim not started as gvim doesn't set WM_CLASS property to a
+            useful value.
+Solution:   Call g_set_prgname() on startup. (James McCoy)
+Files:      src/gui_gtk_x11.c
+
+
+*** ../vim-7.3.984/src/gui_gtk_x11.c	2013-05-06 04:21:35.000000000 +0200
+--- src/gui_gtk_x11.c	2013-05-21 12:48:16.000000000 +0200
+***************
+*** 1447,1452 ****
+--- 1447,1457 ----
+  	using_gnome = 1;
+  #endif
+  
++     /* This defaults to argv[0], but we want it to match the name of the
++      * shipped gvim.desktop so that Vim's windows can be associated with this
++      * file. */
++     g_set_prgname("gvim");
++ 
+      /* Don't use gtk_init() or gnome_init(), it exits on failure. */
+      if (!gtk_init_check(&gui_argc, &gui_argv))
+      {
+*** ../vim-7.3.984/src/version.c	2013-05-21 12:45:54.000000000 +0200
+--- src/version.c	2013-05-21 12:50:04.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     985,
+  /**/
+
+-- 
+A disclaimer for the disclaimer:
+"and before I get a huge amount of complaints , I have no control over the
+disclaimer at the end of this mail :-)" (Timothy Aldrich)
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.986 b/7.3.986
new file mode 100644
index 0000000..f6fc773
--- /dev/null
+++ b/7.3.986
@@ -0,0 +1,61 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.986
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.986
+Problem:    Test 95 doesn't pass when 'encoding' isn't utf-8. (Yasuhiro
+	    Matsumoto)
+Solution:   Force 'encoding' to be utf-8.
+Files:	    src/testdir/test95.in
+
+
+*** ../vim-7.3.985/src/testdir/test95.in	2013-05-21 12:34:13.000000000 +0200
+--- src/testdir/test95.in	2013-05-21 12:58:09.000000000 +0200
+***************
+*** 1,4 ****
+! Test for regexp patterns with multi-byte support.
+  See test64 for the non-multi-byte tests.
+  
+  A pattern that gives the expected result produces OK, so that we know it was
+--- 1,4 ----
+! Test for regexp patterns with multi-byte support, using utf-8.
+  See test64 for the non-multi-byte tests.
+  
+  A pattern that gives the expected result produces OK, so that we know it was
+***************
+*** 7,12 ****
+--- 7,13 ----
+  STARTTEST
+  :so small.vim
+  :so mbyte.vim
++ :set encoding=utf-8 viminfo+=nviminfo
+  :" tl is a List of Lists with:
+  :"    regexp pattern
+  :"    text to test the pattern on
+*** ../vim-7.3.985/src/version.c	2013-05-21 12:52:00.000000000 +0200
+--- src/version.c	2013-05-21 12:59:32.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     986,
+  /**/
+
+-- 
+(letter from Mark to Mike, about the film's probable certificate)
+      For an 'A' we would have to: Lose as many shits as possible; Take Jesus
+      Christ out, if possible; Loose "I fart in your general direction"; Lose
+      "the oral sex"; Lose "oh, fuck off"; Lose "We make castanets out of your
+      testicles"
+                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/7.3.987 b/7.3.987
new file mode 100644
index 0000000..543c40b
--- /dev/null
+++ b/7.3.987
@@ -0,0 +1,201 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 7.3.987
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 7.3.987
+Problem:    No easy to run an individual test.  Tests 64 fails when
+	    'encoding' is not utf-8.
+Solution:   Add individual test targets to the Makefile.  Move some lines from
+	    test 64 to 95.
+Files:	    src/Makefile, src/testdir/test64.in, src/testdir/test64.ok,
+	    src/testdir/test95.in, src/testdir/test95.ok
+
+
+*** ../vim-7.3.986/src/Makefile	2013-05-19 19:16:25.000000000 +0200
+--- src/Makefile	2013-05-21 13:18:04.000000000 +0200
+***************
+*** 1861,1866 ****
+--- 1861,1879 ----
+  		./$$t || exit 1; echo $$t passed; \
+  	done
+  
++ # Run individual test, assuming that Vim was already compiled.
++ test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 \
++ 	test11 test12 test13 test14 test15 test16 test17 test18 test19 \
++ 	test21 test22 test23 test24 test25 test26 test27 test28 test29 \
++ 	test31 test32 test33 test34 test35 test36 test37 test38 test39 \
++ 	test41 test42 test43 test44 test45 test46 test47 test48 test49 \
++ 	test51 test52 test53 test54 test55 test56 test57 test58 test59 \
++ 	test61 test62 test63 test64 test65 test66 test67 test68 test69 \
++ 	test71 test72 test73 test74 test75 test76 test77 test78 test79 \
++ 	test81 test82 test83 test84 test85 test86 test87 test88 test89 \
++ 	test91 test92 test93 test94 test95 test96 test97 test98 test99:
++ 	cd testdir; rm $@.out; $(MAKE) -f Makefile $@.out VIMPROG=../$(VIMTARGET)
++ 
+  testclean:
+  	cd testdir; $(MAKE) -f Makefile clean
+  	if test -d $(PODIR); then \
+*** ../vim-7.3.986/src/testdir/test64.in	2013-05-21 00:02:54.000000000 +0200
+--- src/testdir/test64.in	2013-05-21 13:23:27.000000000 +0200
+***************
+*** 262,271 ****
+  :call add(tl, ['[a-zA-Z]', 'a', 'a'])
+  :call add(tl, ['[A-Z]', 'a'])
+  :call add(tl, ['\C[^A-Z]\+', 'ABCOIJDEOIFNSD jsfoij sa', ' jsfoij sa'])
+- :call add(tl, ['\i\+', '&*§xx ', 'xx'])
+- :call add(tl, ['\%#=1\i\+', '&*§xx ', 'xx'])
+- :call add(tl, ['\f\+', '&*Ÿfname ', 'fname'])
+- :call add(tl, ['\%#=1\i\+', '&*Ÿfname ', 'fname'])
+  
+  :"""" Tests for \z features
+  :call add(tl, ['xx \ze test', 'xx '])					" must match after \ze
+--- 262,267 ----
+***************
+*** 290,302 ****
+  
+  :"""" Combining different tests and features
+  :call add(tl, ['[[:alpha:]]\{-2,6}', '787abcdiuhsasiuhb4', 'ab'])
+- :call add(tl, ['[^[=a=]]\+', 'ddaãâbcd', 'dd'])
+  :call add(tl, ['', 'abcd', ''])
+  :call add(tl, ['\v(())', 'any possible text', ''])
+  :call add(tl, ['\v%(ab(xyz)c)', '   abxyzc ', 'abxyzc', 'xyz'])
+  :call add(tl, ['\v(test|)empty', 'tesempty', 'empty', ''])
+  :call add(tl, ['\v(a|aa)(a|aa)', 'aaa', 'aa', 'a', 'a'])
+  
+  
+  :"""" Run the tests
+  
+--- 286,303 ----
+  
+  :"""" Combining different tests and features
+  :call add(tl, ['[[:alpha:]]\{-2,6}', '787abcdiuhsasiuhb4', 'ab'])
+  :call add(tl, ['', 'abcd', ''])
+  :call add(tl, ['\v(())', 'any possible text', ''])
+  :call add(tl, ['\v%(ab(xyz)c)', '   abxyzc ', 'abxyzc', 'xyz'])
+  :call add(tl, ['\v(test|)empty', 'tesempty', 'empty', ''])
+  :call add(tl, ['\v(a|aa)(a|aa)', 'aaa', 'aa', 'a', 'a'])
+  
++ :"""" \%u and friends
++ :call add(tl, ['\%d32', 'yes no', ' '])
++ :call add(tl, ['\%o40', 'yes no', ' '])
++ :call add(tl, ['\%x20', 'yes no', ' '])
++ :call add(tl, ['\%u0020', 'yes no', ' '])
++ :call add(tl, ['\%U00000020', 'yes no', ' '])
+  
+  :"""" Run the tests
+  
+*** ../vim-7.3.986/src/testdir/test64.ok	2013-05-21 00:02:54.000000000 +0200
+--- src/testdir/test64.ok	2013-05-21 13:23:37.000000000 +0200
+***************
+*** 203,212 ****
+  OK - [a-zA-Z]
+  OK - [A-Z]
+  OK - \C[^A-Z]\+
+- OK - \i\+
+- OK - \%#=1\i\+
+- OK - \f\+
+- OK - \%#=1\i\+
+  OK - xx \ze test
+  OK - abc\zeend
+  OK - abc\zsdd
+--- 203,208 ----
+***************
+*** 225,234 ****
+  OK - .*John\&.*Bob
+  OK - \v(test1)@=.*yep
+  OK - [[:alpha:]]\{-2,6}
+- OK - [^[=a=]]\+
+  OK - 
+  OK - \v(())
+  OK - \v%(ab(xyz)c)
+  OK - \v(test|)empty
+  OK - \v(a|aa)(a|aa)
+  192.168.0.1
+--- 221,234 ----
+  OK - .*John\&.*Bob
+  OK - \v(test1)@=.*yep
+  OK - [[:alpha:]]\{-2,6}
+  OK - 
+  OK - \v(())
+  OK - \v%(ab(xyz)c)
+  OK - \v(test|)empty
+  OK - \v(a|aa)(a|aa)
++ OK - \%d32
++ OK - \%o40
++ OK - \%x20
++ OK - \%u0020
++ OK - \%U00000020
+  192.168.0.1
+*** ../vim-7.3.986/src/testdir/test95.in	2013-05-21 13:05:05.000000000 +0200
+--- src/testdir/test95.in	2013-05-21 13:24:19.000000000 +0200
+***************
+*** 7,13 ****
+  STARTTEST
+  :so small.vim
+  :so mbyte.vim
+! :set encoding=utf-8 viminfo+=nviminfo
+  :" tl is a List of Lists with:
+  :"    regexp pattern
+  :"    text to test the pattern on
+--- 7,13 ----
+  STARTTEST
+  :so small.vim
+  :so mbyte.vim
+! :set nocp encoding=utf-8 viminfo+=nviminfo
+  :" tl is a List of Lists with:
+  :"    regexp pattern
+  :"    text to test the pattern on
+***************
+*** 29,34 ****
+--- 29,43 ----
+  :" this is not a normal "i" but 0xec
+  :call add(tl, ['\p\+', 'ìa', 'ìa'])
+  
++ :"""" Test recognition of some character classes
++ :call add(tl, ['\i\+', '&*§xx ', 'xx'])
++ :call add(tl, ['\%#=1\i\+', '&*§xx ', 'xx'])
++ :call add(tl, ['\f\+', '&*Ÿfname ', 'fname'])
++ :call add(tl, ['\%#=1\i\+', '&*Ÿfname ', 'fname'])
++ 
++ :"""" Combining different tests and features
++ :call add(tl, ['[^[=a=]]\+', 'ddaãâbcd', 'dd'])
++ 
+  :"""" Run the tests
+  
+  :"
+*** ../vim-7.3.986/src/testdir/test95.ok	2013-05-21 12:34:13.000000000 +0200
+--- src/testdir/test95.ok	2013-05-21 13:24:23.000000000 +0200
+***************
+*** 5,7 ****
+--- 5,12 ----
+  OK -  [^ ]\+
+  OK - [ม[:alpha:][=a=]]\+
+  OK - \p\+
++ OK - \i\+
++ OK - \%#=1\i\+
++ OK - \f\+
++ OK - \%#=1\i\+
++ OK - [^[=a=]]\+
+*** ../vim-7.3.986/src/version.c	2013-05-21 13:05:05.000000000 +0200
+--- src/version.c	2013-05-21 13:27:12.000000000 +0200
+***************
+*** 730,731 ****
+--- 730,733 ----
+  {   /* Add new patch number below this line */
++ /**/
++     987,
+  /**/
+
+-- 
+An SQL statement walks into a bar.  He approaches two tables
+and says, "Mind if I join you?"
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- 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    ///
diff --git a/README.patches b/README.patches
index ad55b60..287479e 100644
--- a/README.patches
+++ b/README.patches
@@ -976,3 +976,46 @@ Individual patches for Vim 7.3:
   5470  7.3.942  Python: SEGV in Buffer functions
   6867  7.3.943  Python: Negative indices were failing
   2283  7.3.944  external program receives the termrespone
+ 16738  7.3.945  Python: List of buffers is not very useful
+  3029  7.3.946  sometimes keys starting with <Esc>[ ar not working
+ 17613  7.3.947  Python: No iterator for vim.list and vim.bufferlist
+ 11841  7.3.948  cannot build with Python 2.2
+ 25668  7.3.949  Python: no easy access to tabpages
+  5750  7.3.950  Python: Stack trace printer can't handle messages
+ 15906  7.3.951  Python exceptions have problems
+  5245  7.3.952  Python: It's not easy to change window/buffer/tabpage
+  3924  7.3.953  Python: string exceptions are deprecated
+  2374  7.3.954  No check if PyObject_IsTrue fails
+ 12291  7.3.955  Python: Not enough tests
+  5261  7.3.956  Python vim.bindeval() causes SIGABRT
+  9959  7.3.957  Python does not have a "do" command like Perl or Lua
+  1772  7.3.958  Python: Iteration destructor not set
+  2058  7.3.959  (after 7.3.957) missing error number
+  1366  7.3.960  compiler warning for unused variable
+  3054  7.3.961  tests 86 and 87 fail when using another language than English
+  8389  7.3.962  Python tests are not portable
+ 18867  7.3.963  setting curbuf without curwin causes trouble
+ 13179  7.3.964  Python: not so easy to access tab pages
+  8088  7.3.965  Python garbage collection not working properly
+ 10038  7.3.966  there is ":py3do" but no ":pydo"
+  3304  7.3.967  (after 7.3.965) build fails on Mac OSX
+  2100  7.3.968  multi-byte support is only available with "big" features
+  1603  7.3.969  can't built with Python 3 and without Python 2
+184170  7.3.970  pattern matching is slow, include the NFA engine
+  4337  7.3.971  no support for VS2012 static code analysis
+  3720  7.3.972  cursor not restored properly after InsertEnter autocommand
+  3881  7.3.973  (after 7.3.970) compiler warnings, crash on startup
+  4775  7.3.974  can't build with ruby 1.8.5
+  2301  7.3.975  (after 7.3.970) crash in regexp parsing
+  2254  7.3.976  (after 7.3.970) can't build with HP-UX
+  7028  7.3.977  compiler warnings, white space, uncommented for testing
+  4535  7.3.978  regexp debug logs don't have a good name
+  2268  7.3.979  complex NFA regexp doesn't work
+  3597  7.3.980  regexp logs contain garbage; character classes don't work
+  3105  7.3.981  old regexp engine fails on \i, \I, \f and \F with mbyte chars
+  2800  7.3.982  \p does not work on multi-byte chars in new regexp engine
+  2675  7.3.983  uneccessary temp variable
+  1706  7.3.984  Visual mapping using CTRL-G works differently from Insert mode
+  1691  7.3.985  GTK vim not started as gvim has WM_CLASS property wrong
+  2113  7.3.986  test 95 doesn't pass when 'encoding' isn't utf-8
+  6338  7.3.987  no easy to run an individual test; test 64 may fail
diff --git a/vim.spec b/vim.spec
index 1aff1e7..13484e1 100644
--- a/vim.spec
+++ b/vim.spec
@@ -18,7 +18,7 @@
 #used for pre-releases:
 %define beta %{nil}
 %define vimdir vim73%{?beta}
-%define patchlevel 944
+%define patchlevel 987
 
 Summary: The VIM editor
 URL:     http://www.vim.org/
@@ -1000,6 +1000,49 @@ Patch941: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.941
 Patch942: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.942
 Patch943: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.943
 Patch944: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.944
+Patch945: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.945
+Patch946: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.946
+Patch947: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.947
+Patch948: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.948
+Patch949: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.949
+Patch950: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.950
+Patch951: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.951
+Patch952: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.952
+Patch953: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.953
+Patch954: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.954
+Patch955: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.955
+Patch956: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.956
+Patch957: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.957
+Patch958: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.958
+Patch959: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.959
+Patch960: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.960
+Patch961: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.961
+Patch962: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.962
+Patch963: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.963
+Patch964: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.964
+Patch965: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.965
+Patch966: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.966
+Patch967: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.967
+Patch968: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.968
+Patch969: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.969
+Patch970: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.970
+Patch971: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.971
+Patch972: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.972
+Patch973: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.973
+Patch974: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.974
+Patch975: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.975
+Patch976: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.976
+Patch977: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.977
+Patch978: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.978
+Patch979: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.979
+Patch980: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.980
+Patch981: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.981
+Patch982: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.982
+Patch983: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.983
+Patch984: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.984
+Patch985: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.985
+Patch986: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.986
+Patch987: ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.987
 
 Patch3000: vim-7.3-syntax.patch
 Patch3002: vim-7.1-nowarnings.patch
@@ -2090,6 +2133,49 @@ perl -pi -e "s,bin/nawk,bin/awk,g" runtime/tools/mve.awk
 %patch942 -p0
 %patch943 -p0
 %patch944 -p0
+%patch945 -p0
+%patch946 -p0
+%patch947 -p0
+%patch948 -p0
+%patch949 -p0
+%patch950 -p0
+%patch951 -p0
+%patch952 -p0
+%patch953 -p0
+%patch954 -p0
+%patch955 -p0
+%patch956 -p0
+%patch957 -p0
+%patch958 -p0
+%patch959 -p0
+%patch960 -p0
+%patch961 -p0
+%patch962 -p0
+%patch963 -p0
+%patch964 -p0
+%patch965 -p0
+%patch966 -p0
+%patch967 -p0
+%patch968 -p0
+%patch969 -p0
+%patch970 -p0
+%patch971 -p0
+%patch972 -p0
+%patch973 -p0
+%patch974 -p0
+%patch975 -p0
+%patch976 -p0
+%patch977 -p0
+%patch978 -p0
+%patch979 -p0
+%patch980 -p0
+%patch981 -p0
+%patch982 -p0
+%patch983 -p0
+%patch984 -p0
+%patch985 -p0
+%patch986 -p0
+%patch987 -p0
 
 
 # install spell files
@@ -2119,8 +2205,8 @@ autoconf
 sed -e "s+VIMRCLOC	= \$(VIMLOC)+VIMRCLOC	= /etc+" Makefile > Makefile.tmp
 mv -f Makefile.tmp Makefile
 
-export CFLAGS="$RPM_OPT_FLAGS -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2"
-export CXXFLAGS="$RPM_OPT_FLAGS -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2"
+export CFLAGS="%{optflags} -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2"
+export CXXFLAGS="%{optflags} -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2"
 
 %configure --with-features=huge \
   --enable-pythoninterp=dynamic \
@@ -2198,15 +2284,15 @@ perl -pi -e "s/\/etc\/vimrc/\/etc\/virc/"  os_unix.h
 make VIMRCLOC=/etc VIMRUNTIMEDIR=/usr/share/vim/%{vimdir} %{?_smp_mflags}
 
 %install
-rm -rf $RPM_BUILD_ROOT
-mkdir -p $RPM_BUILD_ROOT/%{_bindir}
-mkdir -p $RPM_BUILD_ROOT/%{_datadir}/%{name}/vimfiles/{after,autoload,colors,compiler,doc,ftdetect,ftplugin,indent,keymap,lang,plugin,print,spell,syntax,tutor}
-mkdir -p $RPM_BUILD_ROOT/%{_datadir}/%{name}/vimfiles/after/{autoload,colors,compiler,doc,ftdetect,ftplugin,indent,keymap,lang,plugin,print,spell,syntax,tutor}
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/%{_bindir}
+mkdir -p %{buildroot}/%{_datadir}/%{name}/vimfiles/{after,autoload,colors,compiler,doc,ftdetect,ftplugin,indent,keymap,lang,plugin,print,spell,syntax,tutor}
+mkdir -p %{buildroot}/%{_datadir}/%{name}/vimfiles/after/{autoload,colors,compiler,doc,ftdetect,ftplugin,indent,keymap,lang,plugin,print,spell,syntax,tutor}
 cp -f %{SOURCE11} .
 %if %{?fedora}%{!?fedora:0} >= 16 || %{?rhel}%{!?rhel:0} >= 6
-cp -f %{SOURCE15} $RPM_BUILD_ROOT/%{_datadir}/%{name}/vimfiles/template.spec
+cp -f %{SOURCE15} %{buildroot}/%{_datadir}/%{name}/vimfiles/template.spec
 %else
-cp -f %{SOURCE14} $RPM_BUILD_ROOT/%{_datadir}/%{name}/vimfiles/template.spec
+cp -f %{SOURCE14} %{buildroot}/%{_datadir}/%{name}/vimfiles/template.spec
 %endif
 cp runtime/doc/uganda.txt LICENSE
 # Those aren't Linux info files but some binary files for Amiga:
@@ -2214,29 +2300,29 @@ rm -f README*.info
 
 
 cd src
-make install DESTDIR=$RPM_BUILD_ROOT BINDIR=%{_bindir} VIMRCLOC=/etc VIMRUNTIMEDIR=/usr/share/vim/%{vimdir}
-make installgtutorbin  DESTDIR=$RPM_BUILD_ROOT BINDIR=%{_bindir} VIMRCLOC=/etc VIMRUNTIMEDIR=/usr/share/vim/%{vimdir}
-mkdir -p $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/{16x16,32x32,48x48,64x64}/apps
-install -m755 vim $RPM_BUILD_ROOT%{_bindir}/vi
-install -m755 enhanced-vim $RPM_BUILD_ROOT%{_bindir}/vim
-install -m755 gvim $RPM_BUILD_ROOT%{_bindir}/gvim
+make install DESTDIR=%{buildroot} BINDIR=%{_bindir} VIMRCLOC=/etc VIMRUNTIMEDIR=/usr/share/vim/%{vimdir}
+make installgtutorbin  DESTDIR=%{buildroot} BINDIR=%{_bindir} VIMRCLOC=/etc VIMRUNTIMEDIR=/usr/share/vim/%{vimdir}
+mkdir -p %{buildroot}%{_datadir}/icons/hicolor/{16x16,32x32,48x48,64x64}/apps
+install -m755 vim %{buildroot}%{_bindir}/vi
+install -m755 enhanced-vim %{buildroot}%{_bindir}/vim
+install -m755 gvim %{buildroot}%{_bindir}/gvim
 install -p -m644 %{SOURCE7} \
-   $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/16x16/apps/gvim.png
+   %{buildroot}%{_datadir}/icons/hicolor/16x16/apps/gvim.png
 install -p -m644 %{SOURCE8} \
-   $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/32x32/apps/gvim.png
+   %{buildroot}%{_datadir}/icons/hicolor/32x32/apps/gvim.png
 install -p -m644 %{SOURCE9} \
-   $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/48x48/apps/gvim.png
+   %{buildroot}%{_datadir}/icons/hicolor/48x48/apps/gvim.png
 install -p -m644 %{SOURCE10} \
-   $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/64x64/apps/gvim.png
+   %{buildroot}%{_datadir}/icons/hicolor/64x64/apps/gvim.png
 
-( cd $RPM_BUILD_ROOT
+( cd %{buildroot}
   ln -sf vi ./%{_bindir}/rvi
   ln -sf vi ./%{_bindir}/rview
   ln -sf vi ./%{_bindir}/view
   ln -sf vi ./%{_bindir}/ex
   ln -sf vim ./%{_bindir}/rvim
   ln -sf vim ./%{_bindir}/vimdiff
-  perl -pi -e "s,$RPM_BUILD_ROOT,," .%{_mandir}/man1/vim.1 .%{_mandir}/man1/vimtutor.1
+  perl -pi -e "s,%{buildroot},," .%{_mandir}/man1/vim.1 .%{_mandir}/man1/vimtutor.1
   rm -f .%{_mandir}/man1/rvim.1
   ln -sf vim.1.gz .%{_mandir}/man1/vi.1.gz
   ln -sf vim.1.gz .%{_mandir}/man1/rvi.1.gz
@@ -2247,12 +2333,12 @@ install -p -m644 %{SOURCE10} \
   ln -sf gvim ./%{_bindir}/gvimdiff
   ln -sf gvim ./%{_bindir}/vimx
   %if "%{desktop_file}" == "1"
-    mkdir -p $RPM_BUILD_ROOT/%{_datadir}/applications
+    mkdir -p %{buildroot}/%{_datadir}/applications
     desktop-file-install \
     %if 0%{?fedora} && 0%{?fedora} < 19
         --vendor fedora \
     %endif
-        --dir $RPM_BUILD_ROOT/%{_datadir}/applications \
+        --dir %{buildroot}/%{_datadir}/applications \
         %{SOURCE3}
         # --add-category "Development;TextEditor;X-Red-Hat-Base" D\
   %else
@@ -2264,7 +2350,7 @@ install -p -m644 %{SOURCE10} \
     ln -sf menu_ja_jp.ujis.vim menu_ja_jp.eucjp.vim )
 )
 
-pushd $RPM_BUILD_ROOT/%{_datadir}/%{name}/%{vimdir}/tutor
+pushd %{buildroot}/%{_datadir}/%{name}/%{vimdir}/tutor
 mkdir conv
    iconv -f CP1252 -t UTF8 tutor.ca > conv/tutor.ca
    iconv -f CP1252 -t UTF8 tutor.it > conv/tutor.it
@@ -2289,13 +2375,13 @@ rmdir conv
 popd
 
 # Dependency cleanups
-chmod 644 $RPM_BUILD_ROOT/%{_datadir}/%{name}/%{vimdir}/doc/vim2html.pl \
- $RPM_BUILD_ROOT/%{_datadir}/%{name}/%{vimdir}/tools/*.pl \
- $RPM_BUILD_ROOT/%{_datadir}/%{name}/%{vimdir}/tools/vim132
+chmod 644 %{buildroot}/%{_datadir}/%{name}/%{vimdir}/doc/vim2html.pl \
+ %{buildroot}/%{_datadir}/%{name}/%{vimdir}/tools/*.pl \
+ %{buildroot}/%{_datadir}/%{name}/%{vimdir}/tools/vim132
 chmod 644 ../runtime/doc/vim2html.pl
 
-mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/profile.d
-cat >$RPM_BUILD_ROOT/%{_sysconfdir}/profile.d/vim.sh <<EOF
+mkdir -p %{buildroot}/%{_sysconfdir}/profile.d
+cat >%{buildroot}/%{_sysconfdir}/profile.d/vim.sh <<EOF
 if [ -n "\$BASH_VERSION" -o -n "\$KSH_VERSION" -o -n "\$ZSH_VERSION" ]; then
   [ -x /%{_bindir}/id ] || return
   [ \`/%{_bindir}/id -u\` -le 200 ] && return
@@ -2303,17 +2389,17 @@ if [ -n "\$BASH_VERSION" -o -n "\$KSH_VERSION" -o -n "\$ZSH_VERSION" ]; then
   alias vi >/dev/null 2>&1 || alias vi=vim
 fi
 EOF
-cat >$RPM_BUILD_ROOT/%{_sysconfdir}/profile.d/vim.csh <<EOF
+cat >%{buildroot}/%{_sysconfdir}/profile.d/vim.csh <<EOF
 if ( -x /usr/bin/id ) then
     if ( "\`/usr/bin/id -u\`" > 100 ) then
         alias vi vim
     endif
 endif
 EOF
-chmod 0644 $RPM_BUILD_ROOT/%{_sysconfdir}/profile.d/*
-install -p -m644 %{SOURCE4} $RPM_BUILD_ROOT/%{_sysconfdir}/vimrc
-install -p -m644 %{SOURCE4} $RPM_BUILD_ROOT/%{_sysconfdir}/virc
-(cd $RPM_BUILD_ROOT/%{_datadir}/%{name}/%{vimdir}/doc;
+chmod 0644 %{buildroot}/%{_sysconfdir}/profile.d/*
+install -p -m644 %{SOURCE4} %{buildroot}/%{_sysconfdir}/vimrc
+install -p -m644 %{SOURCE4} %{buildroot}/%{_sysconfdir}/virc
+(cd %{buildroot}/%{_datadir}/%{name}/%{vimdir}/doc;
  gzip -9 *.txt
  gzip -d help.txt.gz version7.txt.gz sponsor.txt.gz
  cp %{SOURCE12} .
@@ -2328,35 +2414,39 @@ EOF
 LANG=C sort tags > tags.tmp; mv tags.tmp tags
  )
 (cd ../runtime; rm -rf doc; ln -svf ../../vim/%{vimdir}/doc docs;) 
-rm -f $RPM_BUILD_ROOT/%{_datadir}/vim/%{vimdir}/macros/maze/maze*.c
-rm -rf $RPM_BUILD_ROOT/%{_datadir}/vim/%{vimdir}/tools
-rm -rf $RPM_BUILD_ROOT/%{_datadir}/vim/%{vimdir}/doc/vim2html.pl
-rm -f $RPM_BUILD_ROOT/%{_datadir}/vim/%{vimdir}/tutor/tutor.gr.utf-8~
-( cd $RPM_BUILD_ROOT/%{_mandir}
+rm -f %{buildroot}/%{_datadir}/vim/%{vimdir}/macros/maze/maze*.c
+rm -rf %{buildroot}/%{_datadir}/vim/%{vimdir}/tools
+rm -rf %{buildroot}/%{_datadir}/vim/%{vimdir}/doc/vim2html.pl
+rm -f %{buildroot}/%{_datadir}/vim/%{vimdir}/tutor/tutor.gr.utf-8~
+( cd %{buildroot}/%{_mandir}
   for i in `find ??/ -type f`; do
     bi=`basename $i`
-    iconv -f latin1 -t UTF8 $i > $RPM_BUILD_ROOT/$bi
-    mv -f $RPM_BUILD_ROOT/$bi $i
+    iconv -f latin1 -t UTF8 $i > %{buildroot}/$bi
+    mv -f %{buildroot}/$bi $i
   done
 )
 
 # Remove not UTF-8 manpages
 for i in pl.ISO8859-2 it.ISO8859-1 ru.KOI8-R fr.ISO8859-1; do
-  rm -rf $RPM_BUILD_ROOT/%{_mandir}/$i
+  rm -rf %{buildroot}/%{_mandir}/$i
 done
 
 # use common man1/ru directory
-mv $RPM_BUILD_ROOT/%{_mandir}/ru.UTF-8 $RPM_BUILD_ROOT/%{_mandir}/ru
+mv %{buildroot}/%{_mandir}/ru.UTF-8 %{buildroot}/%{_mandir}/ru
 
 # Remove duplicate man pages
 for i in fr.UTF-8 it.UTF-8 pl.UTF-8; do
-  rm -rf $RPM_BUILD_ROOT/%{_mandir}/$i
+  rm -rf %{buildroot}/%{_mandir}/$i
 done
 
-for i in rvim.1 gvim.1 gvimdiff.1; do 
-  echo ".so man1/vim.1" > $RPM_BUILD_ROOT/%{_mandir}/man1/$i
+for i in rvim.1 gvim.1 gvimdiff.1 gex.1 gview.1 gvimtutor.1 vimx.1; do 
+  echo ".so man1/vim.1" > %{buildroot}/%{_mandir}/man1/$i
 done
-touch $RPM_BUILD_ROOT/%{_datadir}/%{name}/vimfiles/doc/tags
+mkdir -p %{buildroot}/%{_mandir}/man5
+for i in virc.5 vimrc.5; do 
+  echo ".so man1/vim.1" > %{buildroot}/%{_mandir}/man5/$i
+done
+touch %{buildroot}/%{_datadir}/%{name}/vimfiles/doc/tags
 
 %post X11
 touch --no-create %{_datadir}/icons/hicolor
@@ -2373,7 +2463,7 @@ fi
 update-desktop-database &> /dev/null ||:
 
 %clean
-rm -rf $RPM_BUILD_ROOT
+rm -rf %{buildroot}
 
 %files common
 %defattr(-,root,root)
@@ -2440,13 +2530,21 @@ rm -rf $RPM_BUILD_ROOT
 %lang(zh_CN.UTF-8) %{_datadir}/%{name}/%{vimdir}/lang/zh_CN.UTF-8
 %lang(zh_TW.UTF-8) %{_datadir}/%{name}/%{vimdir}/lang/zh_TW.UTF-8
 /%{_bindir}/xxd
-%{_mandir}/man1/vim.*
 %{_mandir}/man1/ex.*
-%{_mandir}/man1/vi.*
-%{_mandir}/man1/view.*
+%{_mandir}/man1/gex.*
+%{_mandir}/man1/gview.*
+%{_mandir}/man1/gvim*
 %{_mandir}/man1/rvi.*
 %{_mandir}/man1/rview.*
+%{_mandir}/man1/rvim.*
+%{_mandir}/man1/vi.*
+%{_mandir}/man1/view.*
+%{_mandir}/man1/vim.*
+%{_mandir}/man1/vimdiff.*
+%{_mandir}/man1/vimtutor.*
+%{_mandir}/man1/vimx.*
 %{_mandir}/man1/xxd.*
+%{_mandir}/man5/vimrc.*
 %lang(fr) %{_mandir}/fr/man1/*
 %lang(it) %{_mandir}/it/man1/*
 %lang(pl) %{_mandir}/pl/man1/*
@@ -2517,6 +2615,13 @@ rm -rf $RPM_BUILD_ROOT
 %{_bindir}/view
 %{_bindir}/rvi
 %{_bindir}/rview
+%{_mandir}/man1/vim.*
+%{_mandir}/man1/vi.*
+%{_mandir}/man1/ex.*
+%{_mandir}/man1/rvi.*
+%{_mandir}/man1/rview.*
+%{_mandir}/man1/view.*
+%{_mandir}/man5/virc.*
 
 %files enhanced
 %defattr(-,root,root)
@@ -2525,9 +2630,6 @@ rm -rf $RPM_BUILD_ROOT
 %{_bindir}/vimdiff
 %{_bindir}/vimtutor
 %config(noreplace) %{_sysconfdir}/profile.d/vim.*
-%{_mandir}/man1/rvim.*
-%{_mandir}/man1/vimdiff.*
-%{_mandir}/man1/vimtutor.*
 
 %files filesystem
 %defattr(-,root,root)
@@ -2565,10 +2667,16 @@ rm -rf $RPM_BUILD_ROOT
 %{_bindir}/vimx
 %{_bindir}/evim
 %{_mandir}/man1/evim.*
-%{_mandir}/man1/gvim*
 %{_datadir}/icons/hicolor/*/apps/*
 
 %changelog
+* Tue May 21 2013 Karsten Hopp <karsten@redhat.com> 7.3.987-1
+- patchlevel 987
+
+* Tue May 21 2013 Karsten Hopp <karsten@redhat.com> 7.3.944-2
+- consistent use of macros in spec file
+- add some links to man pages
+
 * Tue May 14 2013 Karsten Hopp <karsten@redhat.com> 7.3.944-1
 - patchlevel 944