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 +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 +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 [ not working. +Solution: Only wait for more characters after [ 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 +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: ++ i2: ++ i: ++ i3: ++ 1:= ++ 6:= ++ 7:= ++ 8:= ++ 4 ++ i4: ++ i4: ++ 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: ++ i2: ++ i: ++ i3: ++ 1:= ++ 6:= ++ 7:= ++ 8:= ++ 4 ++ i4: ++ i4: ++ 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 +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 <>> 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 +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, _(""), (self)); ++ return PyString_FromString(repr); ++ } ++ else ++ { ++ int t = get_tab_number(this->tab); ++ ++ if (t == 0) ++ vim_snprintf(repr, 100, _(""), ++ (self)); ++ else ++ vim_snprintf(repr, 100, _(""), 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, _(""), +--- 1945,1951 ---- + } + else + { +! int w = get_win_number(this->win, firstwin); + + if (w == 0) + vim_snprintf(repr, 100, _(""), +*************** +*** 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 +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 +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 +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 +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 +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 +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 '' ++ 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: + i4: + StopIteration ++ Number of tabs: 4 ++ Current tab pages: ++ (1): 1 windows, current is ++ Windows: ++ (0): displays buffer ; cursor is at (954, 0) ++ (2): 1 windows, current is ++ Windows: ++ (0): displays buffer ; cursor is at (1, 0) ++ (3): 2 windows, current is ++ Windows: ++ (0): displays buffer ; cursor is at (1, 0) ++ (0): displays buffer ; cursor is at (1, 0) ++ (4): 4 windows, current is ++ Windows: ++ (1): displays buffer ; cursor is at (1, 0) ++ (2): displays buffer ; cursor is at (1, 0) ++ (3): displays buffer ; cursor is at (1, 0) ++ (4): displays buffer ; cursor is at (1, 0) ++ Number of windows in current tab page: 4 ++ Current tab page: ++ Current window: : is ++ Current buffer: : is is ++ 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: ++ Current window: ++ Current buffer: ++ 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 '' ++ 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: + i4: + StopIteration ++ Number of tabs: 4 ++ Current tab pages: ++ (1): 1 windows, current is ++ Windows: ++ (0): displays buffer ; cursor is at (929, 0) ++ (2): 1 windows, current is ++ Windows: ++ (0): displays buffer ; cursor is at (1, 0) ++ (3): 2 windows, current is ++ Windows: ++ (0): displays buffer ; cursor is at (1, 0) ++ (0): displays buffer ; cursor is at (1, 0) ++ (4): 4 windows, current is ++ Windows: ++ (1): displays buffer ; cursor is at (1, 0) ++ (2): displays buffer ; cursor is at (1, 0) ++ (3): displays buffer ; cursor is at (1, 0) ++ (4): displays buffer ; cursor is at (1, 0) ++ Number of windows in current tab page: 4 ++ Current tab page: ++ Current window: : is ++ Current buffer: : is is ++ 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: ++ Current window: ++ Current buffer: ++ 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 +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 +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 , 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 +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 +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 +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 +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: + (1): 1 windows, current is + Windows: +! (0): displays buffer ; cursor is at (929, 0) + (2): 1 windows, current is + Windows: + (0): displays buffer ; cursor is at (1, 0) +--- 322,328 ---- + Current tab pages: + (1): 1 windows, current is + Windows: +! (0): displays buffer ; cursor is at (930, 0) + (2): 1 windows, current is + Windows: + (0): displays buffer ; 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 +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: + (1): 1 windows, current is + Windows: +! (0): displays buffer ; cursor is at (954, 0) + (2): 1 windows, current is + Windows: + (0): displays buffer ; cursor is at (1, 0) +--- 333,339 ---- + Current tab pages: + (1): 1 windows, current is + Windows: +! (0): displays buffer ; cursor is at (955, 0) + (2): 1 windows, current is + Windows: + (0): displays buffer ; 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 +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: + (1): 1 windows, current is + Windows: +! (0): displays buffer ; cursor is at (955, 0) + (2): 1 windows, current is + Windows: + (0): displays buffer ; cursor is at (1, 0) +--- 333,339 ---- + Current tab pages: + (1): 1 windows, current is + Windows: +! (0): displays buffer ; cursor is at (954, 0) + (2): 1 windows, current is + Windows: + (0): displays buffer ; 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 +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: + (1): 1 windows, current is + Windows: +! (0): displays buffer ; cursor is at (954, 0) + (2): 1 windows, current is + Windows: +! (0): displays buffer ; cursor is at (1, 0) + (3): 2 windows, current is + Windows: +! (0): displays buffer ; cursor is at (1, 0) +! (0): displays buffer ; cursor is at (1, 0) + (4): 4 windows, current is + Windows: + (1): displays buffer ; cursor is at (1, 0) +--- 333,346 ---- + Current tab pages: + (1): 1 windows, current is + Windows: +! (1): displays buffer ; cursor is at (954, 0) + (2): 1 windows, current is + Windows: +! (1): displays buffer ; cursor is at (1, 0) + (3): 2 windows, current is + Windows: +! (1): displays buffer ; cursor is at (1, 0) +! (2): displays buffer ; cursor is at (1, 0) + (4): 4 windows, current is + Windows: + (1): displays buffer ; 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: + (1): 1 windows, current is + Windows: +! (0): displays buffer ; cursor is at (930, 0) + (2): 1 windows, current is + Windows: +! (0): displays buffer ; cursor is at (1, 0) + (3): 2 windows, current is + Windows: +! (0): displays buffer ; cursor is at (1, 0) +! (0): displays buffer ; cursor is at (1, 0) + (4): 4 windows, current is + Windows: + (1): displays buffer ; cursor is at (1, 0) +--- 322,335 ---- + Current tab pages: + (1): 1 windows, current is + Windows: +! (1): displays buffer ; cursor is at (930, 0) + (2): 1 windows, current is + Windows: +! (1): displays buffer ; cursor is at (1, 0) + (3): 2 windows, current is + Windows: +! (1): displays buffer ; cursor is at (1, 0) +! (2): displays buffer ; cursor is at (1, 0) + (4): 4 windows, current is + Windows: + (1): displays buffer ; 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 +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 +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 , 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 , 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 +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 +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 +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 +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_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(®parse); ++ 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(®parse); ++ } ++ if (*regparse == '-') ++ { ++ startc = '-'; ++ EMIT(startc); ++ TRY_NEG(); ++ EMIT_GLUE(); ++ nfa_inc(®parse); ++ } ++ /* 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(®parse); ++ if (charclass == CLASS_NONE) ++ { ++ equiclass = get_equi_class(®parse); ++ if (equiclass == 0) ++ collclass = get_coll_element(®parse); ++ } ++ ++ /* 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(®parse); ++ 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(®parse); ++ ++ 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(®parse); ++ } ++ 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(®parse); ++ } /* while (p < endp) */ ++ ++ nfa_dec(®parse); ++ if (*regparse == '-') /* if last, '-' is just a char */ ++ { ++ EMIT('-'); ++ TRY_NEG(); ++ EMIT_GLUE(); ++ } ++ nfa_inc(®parse); ++ ++ if (extra == ADD_NL) /* \_[] also matches \n */ ++ { ++ EMIT(reg_string ? NL : NFA_NEWL); ++ TRY_NEG(); ++ EMIT_GLUE(); ++ } ++ ++ /* skip the trailing ] */ ++ regparse = endp; ++ nfa_inc(®parse); ++ 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 ++ * {m,n} is next. */ ++ old_regparse = regparse; ++ /* Save current number of open parenthesis, so we can use it if ++ * {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 + with * ++ */ ++ /* 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")); ++ } ++ /* {0,inf}, {0,} and {} are equivalent to ++ * * */ ++ 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}[/] Search forward for the [count]'th occurrence of +--- 21,27 ---- + 10. Highlighting matches |match-highlight| + + ============================================================================== +! 1. Search commands *search-commands* + + */* + /{pattern}[/] 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\)\@!.*\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 '(? +*** ../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, + # Sandor Kopanyi, + # +! # 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, + # Sandor Kopanyi, + # +! # 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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 [ 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 <%{buildroot}/%{_sysconfdir}/profile.d/vim.sh </dev/null 2>&1 || alias vi=vim fi EOF -cat >$RPM_BUILD_ROOT/%{_sysconfdir}/profile.d/vim.csh <%{buildroot}/%{_sysconfdir}/profile.d/vim.csh < 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 7.3.987-1 +- patchlevel 987 + +* Tue May 21 2013 Karsten Hopp 7.3.944-2 +- consistent use of macros in spec file +- add some links to man pages + * Tue May 14 2013 Karsten Hopp 7.3.944-1 - patchlevel 944