Karsten Hopp 2999ae
To: vim_dev@googlegroups.com
Karsten Hopp 2999ae
Subject: Patch 7.3.1172
Karsten Hopp 2999ae
Fcc: outbox
Karsten Hopp 2999ae
From: Bram Moolenaar <Bram@moolenaar.net>
Karsten Hopp 2999ae
Mime-Version: 1.0
Karsten Hopp 2999ae
Content-Type: text/plain; charset=UTF-8
Karsten Hopp 2999ae
Content-Transfer-Encoding: 8bit
Karsten Hopp 2999ae
------------
Karsten Hopp 2999ae
Karsten Hopp 2999ae
Patch 7.3.1172
Karsten Hopp 2999ae
Problem:    Python 2: loading modules doesn't work well.
Karsten Hopp 2999ae
Solution:   Fix the code. Add more tests. (ZyX)
Karsten Hopp 2999ae
Files:	    runtime/doc/if_pyth.txt, src/if_py_both.h, src/if_python.c,
Karsten Hopp 2999ae
	    src/testdir/python2/module.py, src/testdir/python3/module.py,
Karsten Hopp 2999ae
	    src/testdir/python_after/after.py,
Karsten Hopp 2999ae
	    src/testdir/python_before/before.py, src/testdir/test86.in,
Karsten Hopp 2999ae
	    src/testdir/test86.ok, src/testdir/test87.in,
Karsten Hopp 2999ae
	    src/testdir/test87.ok, Filelist
Karsten Hopp 2999ae
Karsten Hopp 2999ae
Karsten Hopp 2999ae
*** ../vim-7.3.1171/runtime/doc/if_pyth.txt	2013-06-10 21:27:18.000000000 +0200
Karsten Hopp 2999ae
--- runtime/doc/if_pyth.txt	2013-06-12 14:12:13.000000000 +0200
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 315,366 ****
Karsten Hopp 2999ae
  {rtp}/python2 (or python3) and {rtp}/pythonx (for both python versions) for 
Karsten Hopp 2999ae
  each {rtp} found in 'runtimepath'.
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
! Implementation for python 2 is the following: usual importing code with empty 
Karsten Hopp 2999ae
! lists in place of sys.path_hooks and sys.meta_path. Code is similar to the 
Karsten Hopp 2999ae
! below, but written in C: >
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     # Assuming vim variable is already accessible and is set to the current 
Karsten Hopp 2999ae
!     # module
Karsten Hopp 2999ae
      import sys
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     def find_module(fullname):
Karsten Hopp 2999ae
!         return vim
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     def load_module(fullname):
Karsten Hopp 2999ae
!         # see vim._get_paths below
Karsten Hopp 2999ae
!         new_path = _get_paths()
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!         try:         old_path = sys.path
Karsten Hopp 2999ae
!         except: pass
Karsten Hopp 2999ae
!         try:         old_meta_path = sys.meta_path
Karsten Hopp 2999ae
!         except: pass
Karsten Hopp 2999ae
!         try:         old_path_hooks = sys.path_hooks
Karsten Hopp 2999ae
!         except: pass
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!         sys.meta_path = []
Karsten Hopp 2999ae
!         sys.path_hooks = sys.meta_path
Karsten Hopp 2999ae
!         sys.path = new_path
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!         try:
Karsten Hopp 2999ae
!             exec ('import ' + fullname + ' as m')  # No actual exec in C code
Karsten Hopp 2999ae
!             return m
Karsten Hopp 2999ae
!         finally:
Karsten Hopp 2999ae
!             e = None
Karsten Hopp 2999ae
!             try:                        sys.path = old_path
Karsten Hopp 2999ae
!             except Exception as e: pass
Karsten Hopp 2999ae
!             try:                        sys.meta_path = old_meta_path
Karsten Hopp 2999ae
!             except Exception as e: pass
Karsten Hopp 2999ae
!             try:                        sys.path_hooks = old_path_hooks
Karsten Hopp 2999ae
!             except Exception as e: pass
Karsten Hopp 2999ae
!             if e:
Karsten Hopp 2999ae
!                 raise e
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!     def path_hook(d):
Karsten Hopp 2999ae
!         if d == VIM_SPECIAL_PATH:
Karsten Hopp 2999ae
!             return vim
Karsten Hopp 2999ae
!         raise ImportError
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!     sys.path_hooks.append(path_hook)
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
  Implementation for python 3 is cleaner: code is similar to the following, but, 
Karsten Hopp 2999ae
  again, written in C: >
Karsten Hopp 2999ae
--- 315,367 ----
Karsten Hopp 2999ae
  {rtp}/python2 (or python3) and {rtp}/pythonx (for both python versions) for 
Karsten Hopp 2999ae
  each {rtp} found in 'runtimepath'.
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
! Implementation for python 2 is similar to the following, but written in C: >
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     from imp import find_module, load_module
Karsten Hopp 2999ae
!     import vim
Karsten Hopp 2999ae
      import sys
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     class VimModuleLoader(object):
Karsten Hopp 2999ae
!         def __init__(self, module):
Karsten Hopp 2999ae
!             self.module = module
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!         def load_module(self, fullname, path=None):
Karsten Hopp 2999ae
!             return self.module
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!     def _find_module(fullname, oldtail, path):
Karsten Hopp 2999ae
!         idx = oldtail.find('.')
Karsten Hopp 2999ae
!         if idx > 0:
Karsten Hopp 2999ae
!             name = oldtail[:idx]
Karsten Hopp 2999ae
!             tail = oldtail[idx+1:]
Karsten Hopp 2999ae
!             fmr = find_module(name, path)
Karsten Hopp 2999ae
!             module = load_module(fullname[:-len(oldtail)] + name, *fmr)
Karsten Hopp 2999ae
!             return _find_module(fullname, tail, module.__path__)
Karsten Hopp 2999ae
!         else:
Karsten Hopp 2999ae
!             fmr = find_module(fullname, path)
Karsten Hopp 2999ae
!             return load_module(fullname, *fmr)
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!     # It uses vim module itself in place of VimPathFinder class: it does not 
Karsten Hopp 2999ae
!     # matter for python which object has find_module function attached to as 
Karsten Hopp 2999ae
!     # an attribute.
Karsten Hopp 2999ae
!     class VimPathFinder(object):
Karsten Hopp 2999ae
!         def find_module(cls, fullname, path=None):
Karsten Hopp 2999ae
!             try:
Karsten Hopp 2999ae
!                 return VimModuleLoader(_find_module(fullname, fullname, path or vim._get_paths()))
Karsten Hopp 2999ae
!             except ImportError:
Karsten Hopp 2999ae
!                 return None
Karsten Hopp 2999ae
!         find_module = classmethod(find_module)
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!         def load_module(cls, fullname, path=None):
Karsten Hopp 2999ae
!             return _find_module(fullname, fullname, path or vim._get_paths())
Karsten Hopp 2999ae
!         load_module = classmethod(load_module)
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!     def hook(path):
Karsten Hopp 2999ae
!         if path == vim.VIM_SPECIAL_PATH:
Karsten Hopp 2999ae
!             return VimPathFinder
Karsten Hopp 2999ae
!         else:
Karsten Hopp 2999ae
!             raise ImportError
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     sys.path_hooks.append(hook)
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
  Implementation for python 3 is cleaner: code is similar to the following, but, 
Karsten Hopp 2999ae
  again, written in C: >
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 395,408 ****
Karsten Hopp 2999ae
  	Note: you must not use value of this constant directly, always use 
Karsten Hopp 2999ae
  	      vim.VIM_SPECIAL_PATH object.
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
- vim.load_module(name)					*python-load_module*
Karsten Hopp 2999ae
  vim.find_module(...)					*python-find_module*
Karsten Hopp 2999ae
  vim.path_hook(path)					*python-path_hook*
Karsten Hopp 2999ae
  	Methods or objects used to implement path loading as described above. 
Karsten Hopp 2999ae
  	You should not be using any of these directly except for vim.path_hook 
Karsten Hopp 2999ae
  	in case you need to do something with sys.meta_path. It is not 
Karsten Hopp 2999ae
  	guaranteed that any of the objects will exist in the future vim 
Karsten Hopp 2999ae
! 	versions. In fact, load_module and find_module methods do not exists 
Karsten Hopp 2999ae
  	in python3.
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
  vim._get_paths						*python-_get_paths*
Karsten Hopp 2999ae
--- 396,408 ----
Karsten Hopp 2999ae
  	Note: you must not use value of this constant directly, always use 
Karsten Hopp 2999ae
  	      vim.VIM_SPECIAL_PATH object.
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
  vim.find_module(...)					*python-find_module*
Karsten Hopp 2999ae
  vim.path_hook(path)					*python-path_hook*
Karsten Hopp 2999ae
  	Methods or objects used to implement path loading as described above. 
Karsten Hopp 2999ae
  	You should not be using any of these directly except for vim.path_hook 
Karsten Hopp 2999ae
  	in case you need to do something with sys.meta_path. It is not 
Karsten Hopp 2999ae
  	guaranteed that any of the objects will exist in the future vim 
Karsten Hopp 2999ae
! 	versions. In fact, find_module methods do not exists 
Karsten Hopp 2999ae
  	in python3.
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
  vim._get_paths						*python-_get_paths*
Karsten Hopp 2999ae
*** ../vim-7.3.1171/src/if_py_both.h	2013-06-10 21:27:18.000000000 +0200
Karsten Hopp 2999ae
--- src/if_py_both.h	2013-06-12 14:12:13.000000000 +0200
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 940,946 ****
Karsten Hopp 2999ae
      {"foreach_rtp", VimForeachRTP,		METH_VARARGS,			"Call given callable for each path in &rtp"},
Karsten Hopp 2999ae
  #if PY_MAJOR_VERSION < 3
Karsten Hopp 2999ae
      {"find_module", FinderFindModule,		METH_VARARGS,			"Internal use only, returns loader object for any input it receives"},
Karsten Hopp 2999ae
-     {"load_module", LoaderLoadModule,		METH_VARARGS,			"Internal use only, tries importing the given module from &rtp by temporary mocking sys.path (to an rtp-based one) and unsetting sys.meta_path and sys.path_hooks"},
Karsten Hopp 2999ae
  #endif
Karsten Hopp 2999ae
      {"path_hook",   VimPathHook,		METH_VARARGS,			"Hook function to install in sys.path_hooks"},
Karsten Hopp 2999ae
      {"_get_paths",  (PyCFunction)Vim_GetPaths,	METH_NOARGS,			"Get &rtp-based additions to sys.path"},
Karsten Hopp 2999ae
--- 940,945 ----
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 5195,5200 ****
Karsten Hopp 2999ae
--- 5194,5206 ----
Karsten Hopp 2999ae
      PyObject_HEAD
Karsten Hopp 2999ae
  } FinderObject;
Karsten Hopp 2999ae
  static PyTypeObject FinderType;
Karsten Hopp 2999ae
+ #else
Karsten Hopp 2999ae
+ typedef struct
Karsten Hopp 2999ae
+ {
Karsten Hopp 2999ae
+     PyObject_HEAD
Karsten Hopp 2999ae
+     PyObject	*module;
Karsten Hopp 2999ae
+ } LoaderObject;
Karsten Hopp 2999ae
+ static PyTypeObject LoaderType;
Karsten Hopp 2999ae
  #endif
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
      static void
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 5444,5449 ****
Karsten Hopp 2999ae
--- 5450,5457 ----
Karsten Hopp 2999ae
      PYTYPE_READY(OutputType);
Karsten Hopp 2999ae
  #if PY_MAJOR_VERSION >= 3
Karsten Hopp 2999ae
      PYTYPE_READY(FinderType);
Karsten Hopp 2999ae
+ #else
Karsten Hopp 2999ae
+     PYTYPE_READY(LoaderType);
Karsten Hopp 2999ae
  #endif
Karsten Hopp 2999ae
      return 0;
Karsten Hopp 2999ae
  }
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 5570,5575 ****
Karsten Hopp 2999ae
--- 5578,5585 ----
Karsten Hopp 2999ae
      {"Options",    (PyObject *)&OptionsType},
Karsten Hopp 2999ae
  #if PY_MAJOR_VERSION >= 3
Karsten Hopp 2999ae
      {"Finder",     (PyObject *)&FinderType},
Karsten Hopp 2999ae
+ #else
Karsten Hopp 2999ae
+     {"Loader",     (PyObject *)&LoaderType},
Karsten Hopp 2999ae
  #endif
Karsten Hopp 2999ae
  };
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 5666,5671 ****
Karsten Hopp 2999ae
--- 5676,5684 ----
Karsten Hopp 2999ae
      ADD_CHECKED_OBJECT(m, "_find_module",
Karsten Hopp 2999ae
  	    (py_find_module = PyObject_GetAttrString(path_finder,
Karsten Hopp 2999ae
  						     "find_module")));
Karsten Hopp 2999ae
+ #else
Karsten Hopp 2999ae
+     ADD_OBJECT(m, "_find_module", py_find_module);
Karsten Hopp 2999ae
+     ADD_OBJECT(m, "_load_module", py_load_module);
Karsten Hopp 2999ae
  #endif
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
      return 0;
Karsten Hopp 2999ae
*** ../vim-7.3.1171/src/if_python.c	2013-06-10 21:27:18.000000000 +0200
Karsten Hopp 2999ae
--- src/if_python.c	2013-06-12 14:14:27.000000000 +0200
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 150,155 ****
Karsten Hopp 2999ae
--- 150,156 ----
Karsten Hopp 2999ae
  # undef Py_InitModule4
Karsten Hopp 2999ae
  # undef Py_InitModule4_64
Karsten Hopp 2999ae
  # undef PyObject_CallMethod
Karsten Hopp 2999ae
+ # undef PyObject_CallFunction
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
  /*
Karsten Hopp 2999ae
   * Wrapper defines
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 219,224 ****
Karsten Hopp 2999ae
--- 220,226 ----
Karsten Hopp 2999ae
  # define PyObject_HasAttrString dll_PyObject_HasAttrString
Karsten Hopp 2999ae
  # define PyObject_SetAttrString dll_PyObject_SetAttrString
Karsten Hopp 2999ae
  # define PyObject_CallFunctionObjArgs dll_PyObject_CallFunctionObjArgs
Karsten Hopp 2999ae
+ # define PyObject_CallFunction dll_PyObject_CallFunction
Karsten Hopp 2999ae
  # define PyObject_Call dll_PyObject_Call
Karsten Hopp 2999ae
  # define PyString_AsString dll_PyString_AsString
Karsten Hopp 2999ae
  # define PyString_AsStringAndSize dll_PyString_AsStringAndSize
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 357,362 ****
Karsten Hopp 2999ae
--- 359,365 ----
Karsten Hopp 2999ae
  static int (*dll_PyObject_HasAttrString)(PyObject *, const char *);
Karsten Hopp 2999ae
  static PyObject* (*dll_PyObject_SetAttrString)(PyObject *, const char *, PyObject *);
Karsten Hopp 2999ae
  static PyObject* (*dll_PyObject_CallFunctionObjArgs)(PyObject *, ...);
Karsten Hopp 2999ae
+ static PyObject* (*dll_PyObject_CallFunction)(PyObject *, char *, ...);
Karsten Hopp 2999ae
  static PyObject* (*dll_PyObject_Call)(PyObject *, PyObject *, PyObject *);
Karsten Hopp 2999ae
  static char*(*dll_PyString_AsString)(PyObject *);
Karsten Hopp 2999ae
  static int(*dll_PyString_AsStringAndSize)(PyObject *, char **, int *);
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 528,533 ****
Karsten Hopp 2999ae
--- 531,537 ----
Karsten Hopp 2999ae
      {"PyObject_HasAttrString", (PYTHON_PROC*)&dll_PyObject_HasAttrString},
Karsten Hopp 2999ae
      {"PyObject_SetAttrString", (PYTHON_PROC*)&dll_PyObject_SetAttrString},
Karsten Hopp 2999ae
      {"PyObject_CallFunctionObjArgs", (PYTHON_PROC*)&dll_PyObject_CallFunctionObjArgs},
Karsten Hopp 2999ae
+     {"PyObject_CallFunction", (PYTHON_PROC*)&dll_PyObject_CallFunction},
Karsten Hopp 2999ae
      {"PyObject_Call", (PYTHON_PROC*)&dll_PyObject_Call},
Karsten Hopp 2999ae
      {"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString},
Karsten Hopp 2999ae
      {"PyString_AsStringAndSize", (PYTHON_PROC*)&dll_PyString_AsStringAndSize},
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 748,757 ****
Karsten Hopp 2999ae
  static PyObject *ListGetattr(PyObject *, char *);
Karsten Hopp 2999ae
  static PyObject *FunctionGetattr(PyObject *, char *);
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
- static PyObject *LoaderLoadModule(PyObject *, PyObject *);
Karsten Hopp 2999ae
  static PyObject *FinderFindModule(PyObject *, PyObject *);
Karsten Hopp 2999ae
  static PyObject *VimPathHook(PyObject *, PyObject *);
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
  #ifndef Py_VISIT
Karsten Hopp 2999ae
  # define Py_VISIT(obj) visit(obj, arg)
Karsten Hopp 2999ae
  #endif
Karsten Hopp 2999ae
--- 752,763 ----
Karsten Hopp 2999ae
  static PyObject *ListGetattr(PyObject *, char *);
Karsten Hopp 2999ae
  static PyObject *FunctionGetattr(PyObject *, char *);
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
  static PyObject *FinderFindModule(PyObject *, PyObject *);
Karsten Hopp 2999ae
  static PyObject *VimPathHook(PyObject *, PyObject *);
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
+ static PyObject *py_find_module;
Karsten Hopp 2999ae
+ static PyObject *py_load_module;
Karsten Hopp 2999ae
+ 
Karsten Hopp 2999ae
  #ifndef Py_VISIT
Karsten Hopp 2999ae
  # define Py_VISIT(obj) visit(obj, arg)
Karsten Hopp 2999ae
  #endif
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 1376,1465 ****
Karsten Hopp 2999ae
  }
Karsten Hopp 2999ae
  #endif
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
      static PyObject *
Karsten Hopp 2999ae
! LoaderLoadModule(PyObject *self, PyObject *args)
Karsten Hopp 2999ae
  {
Karsten Hopp 2999ae
!     char	*fullname;
Karsten Hopp 2999ae
!     PyObject	*path;
Karsten Hopp 2999ae
!     PyObject	*meta_path;
Karsten Hopp 2999ae
!     PyObject	*path_hooks;
Karsten Hopp 2999ae
!     PyObject	*new_path;
Karsten Hopp 2999ae
!     PyObject	*r;
Karsten Hopp 2999ae
!     PyObject	*new_list;
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     if (!PyArg_ParseTuple(args, "s", &fullname))
Karsten Hopp 2999ae
! 	return NULL;
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     if (!(new_path = Vim_GetPaths(self)))
Karsten Hopp 2999ae
  	return NULL;
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     if (!(new_list = PyList_New(0)))
Karsten Hopp 2999ae
  	return NULL;
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
! #define GET_SYS_OBJECT(objstr, obj) \
Karsten Hopp 2999ae
!     obj = PySys_GetObject(objstr); \
Karsten Hopp 2999ae
!     PyErr_Clear(); \
Karsten Hopp 2999ae
!     Py_XINCREF(obj);
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     GET_SYS_OBJECT("meta_path", meta_path);
Karsten Hopp 2999ae
!     if (PySys_SetObject("meta_path", new_list))
Karsten Hopp 2999ae
      {
Karsten Hopp 2999ae
! 	Py_XDECREF(meta_path);
Karsten Hopp 2999ae
! 	Py_DECREF(new_list);
Karsten Hopp 2999ae
! 	return NULL;
Karsten Hopp 2999ae
      }
Karsten Hopp 2999ae
!     Py_DECREF(new_list); /* Now it becomes a reference borrowed from
Karsten Hopp 2999ae
! 			    sys.meta_path */
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
! #define RESTORE_SYS_OBJECT(objstr, obj) \
Karsten Hopp 2999ae
!     if (obj) \
Karsten Hopp 2999ae
!     { \
Karsten Hopp 2999ae
! 	PySys_SetObject(objstr, obj); \
Karsten Hopp 2999ae
! 	Py_DECREF(obj); \
Karsten Hopp 2999ae
      }
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     GET_SYS_OBJECT("path_hooks", path_hooks);
Karsten Hopp 2999ae
!     if (PySys_SetObject("path_hooks", new_list))
Karsten Hopp 2999ae
!     {
Karsten Hopp 2999ae
! 	RESTORE_SYS_OBJECT("meta_path", meta_path);
Karsten Hopp 2999ae
! 	Py_XDECREF(path_hooks);
Karsten Hopp 2999ae
  	return NULL;
Karsten Hopp 2999ae
-     }
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     GET_SYS_OBJECT("path", path);
Karsten Hopp 2999ae
!     if (PySys_SetObject("path", new_path))
Karsten Hopp 2999ae
!     {
Karsten Hopp 2999ae
! 	RESTORE_SYS_OBJECT("meta_path", meta_path);
Karsten Hopp 2999ae
! 	RESTORE_SYS_OBJECT("path_hooks", path_hooks);
Karsten Hopp 2999ae
! 	Py_XDECREF(path);
Karsten Hopp 2999ae
  	return NULL;
Karsten Hopp 2999ae
-     }
Karsten Hopp 2999ae
-     Py_DECREF(new_path);
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     r = PyImport_ImportModule(fullname);
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     RESTORE_SYS_OBJECT("meta_path", meta_path);
Karsten Hopp 2999ae
!     RESTORE_SYS_OBJECT("path_hooks", path_hooks);
Karsten Hopp 2999ae
!     RESTORE_SYS_OBJECT("path", path);
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     if (PyErr_Occurred())
Karsten Hopp 2999ae
      {
Karsten Hopp 2999ae
! 	Py_XDECREF(r);
Karsten Hopp 2999ae
  	return NULL;
Karsten Hopp 2999ae
      }
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     return r;
Karsten Hopp 2999ae
! }
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     static PyObject *
Karsten Hopp 2999ae
! FinderFindModule(PyObject *self UNUSED, PyObject *args UNUSED)
Karsten Hopp 2999ae
! {
Karsten Hopp 2999ae
!     /*
Karsten Hopp 2999ae
!      * Don't bother actually finding the module, it is delegated to the "loader"
Karsten Hopp 2999ae
!      * object (which is basically the same object: vim module).
Karsten Hopp 2999ae
!      */
Karsten Hopp 2999ae
!     Py_INCREF(vim_module);
Karsten Hopp 2999ae
!     return vim_module;
Karsten Hopp 2999ae
  }
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
      static PyObject *
Karsten Hopp 2999ae
--- 1382,1534 ----
Karsten Hopp 2999ae
  }
Karsten Hopp 2999ae
  #endif
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
+     static void
Karsten Hopp 2999ae
+ LoaderDestructor(LoaderObject *self)
Karsten Hopp 2999ae
+ {
Karsten Hopp 2999ae
+     Py_DECREF(self->module);
Karsten Hopp 2999ae
+     DESTRUCTOR_FINISH(self);
Karsten Hopp 2999ae
+ }
Karsten Hopp 2999ae
+ 
Karsten Hopp 2999ae
      static PyObject *
Karsten Hopp 2999ae
! LoaderLoadModule(LoaderObject *self, PyObject *args UNUSED)
Karsten Hopp 2999ae
  {
Karsten Hopp 2999ae
!     PyObject	*r = self->module;
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     Py_INCREF(r);
Karsten Hopp 2999ae
!     return r;
Karsten Hopp 2999ae
! }
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
! static struct PyMethodDef LoaderMethods[] = {
Karsten Hopp 2999ae
!     /* name,	    function,				calling,	doc */
Karsten Hopp 2999ae
!     {"load_module", (PyCFunction)LoaderLoadModule,	METH_VARARGS,	""},
Karsten Hopp 2999ae
!     { NULL,	    NULL,				0,		NULL}
Karsten Hopp 2999ae
! };
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!     static PyObject *
Karsten Hopp 2999ae
! call_load_module(char *name, int len, PyObject *find_module_result)
Karsten Hopp 2999ae
! {
Karsten Hopp 2999ae
!     PyObject	*fd, *pathname, *description;
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!     if (!PyTuple_Check(find_module_result)
Karsten Hopp 2999ae
! 	    || PyTuple_GET_SIZE(find_module_result) != 3)
Karsten Hopp 2999ae
!     {
Karsten Hopp 2999ae
! 	PyErr_SetString(PyExc_TypeError,
Karsten Hopp 2999ae
! 		_("expected 3-tuple as imp.find_module() result"));
Karsten Hopp 2999ae
  	return NULL;
Karsten Hopp 2999ae
+     }
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     if (!(fd = PyTuple_GET_ITEM(find_module_result, 0))
Karsten Hopp 2999ae
! 	    || !(pathname = PyTuple_GET_ITEM(find_module_result, 1))
Karsten Hopp 2999ae
! 	    || !(description = PyTuple_GET_ITEM(find_module_result, 2)))
Karsten Hopp 2999ae
!     {
Karsten Hopp 2999ae
! 	PyErr_SetString(PyExc_RuntimeError,
Karsten Hopp 2999ae
! 		_("internal error: imp.find_module returned tuple with NULL"));
Karsten Hopp 2999ae
  	return NULL;
Karsten Hopp 2999ae
+     }
Karsten Hopp 2999ae
+ 
Karsten Hopp 2999ae
+     return PyObject_CallFunction(py_load_module,
Karsten Hopp 2999ae
+ 	    "s#OOO", name, len, fd, pathname, description);
Karsten Hopp 2999ae
+ }
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     static PyObject *
Karsten Hopp 2999ae
! find_module(char *fullname, char *tail, PyObject *new_path)
Karsten Hopp 2999ae
! {
Karsten Hopp 2999ae
!     PyObject	*find_module_result;
Karsten Hopp 2999ae
!     PyObject	*module;
Karsten Hopp 2999ae
!     char	*dot;
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     if ((dot = (char *) vim_strchr((char_u *) tail, '.')))
Karsten Hopp 2999ae
      {
Karsten Hopp 2999ae
! 	/*
Karsten Hopp 2999ae
! 	 * There is a dot in the name: call find_module recursively without the 
Karsten Hopp 2999ae
! 	 * first component
Karsten Hopp 2999ae
! 	 */
Karsten Hopp 2999ae
! 	PyObject	*newest_path;
Karsten Hopp 2999ae
! 	int		partlen = (int) (dot - 1 - tail);
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
! 	if (!(find_module_result = PyObject_CallFunction(py_find_module,
Karsten Hopp 2999ae
! 			"s#O", tail, partlen, new_path)))
Karsten Hopp 2999ae
! 	    return NULL;
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
! 	if (!(module = call_load_module(
Karsten Hopp 2999ae
! 			fullname,
Karsten Hopp 2999ae
! 			((int) (tail - fullname)) + partlen,
Karsten Hopp 2999ae
! 			find_module_result)))
Karsten Hopp 2999ae
! 	{
Karsten Hopp 2999ae
! 	    Py_DECREF(find_module_result);
Karsten Hopp 2999ae
! 	    return NULL;
Karsten Hopp 2999ae
! 	}
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
! 	Py_DECREF(find_module_result);
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
! 	if (!(newest_path = PyObject_GetAttrString(module, "__path__")))
Karsten Hopp 2999ae
! 	{
Karsten Hopp 2999ae
! 	    Py_DECREF(module);
Karsten Hopp 2999ae
! 	    return NULL;
Karsten Hopp 2999ae
! 	}
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
! 	Py_DECREF(module);
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
! 	module = find_module(fullname, dot + 1, newest_path);
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
! 	Py_DECREF(newest_path);
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
! 	return module;
Karsten Hopp 2999ae
      }
Karsten Hopp 2999ae
!     else
Karsten Hopp 2999ae
!     {
Karsten Hopp 2999ae
! 	if (!(find_module_result = PyObject_CallFunction(py_find_module,
Karsten Hopp 2999ae
! 			"sO", tail, new_path)))
Karsten Hopp 2999ae
! 	    return NULL;
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
! 	if (!(module = call_load_module(
Karsten Hopp 2999ae
! 			fullname,
Karsten Hopp 2999ae
! 			STRLEN(fullname),
Karsten Hopp 2999ae
! 			find_module_result)))
Karsten Hopp 2999ae
! 	{
Karsten Hopp 2999ae
! 	    Py_DECREF(find_module_result);
Karsten Hopp 2999ae
! 	    return NULL;
Karsten Hopp 2999ae
! 	}
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
! 	Py_DECREF(find_module_result);
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
! 	return module;
Karsten Hopp 2999ae
      }
Karsten Hopp 2999ae
+ }
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     static PyObject *
Karsten Hopp 2999ae
! FinderFindModule(PyObject *self, PyObject *args)
Karsten Hopp 2999ae
! {
Karsten Hopp 2999ae
!     char	*fullname;
Karsten Hopp 2999ae
!     PyObject	*module;
Karsten Hopp 2999ae
!     PyObject	*new_path;
Karsten Hopp 2999ae
!     LoaderObject	*loader;
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!     if (!PyArg_ParseTuple(args, "s", &fullname))
Karsten Hopp 2999ae
  	return NULL;
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     if (!(new_path = Vim_GetPaths(self)))
Karsten Hopp 2999ae
  	return NULL;
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     module = find_module(fullname, fullname, new_path);
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     Py_DECREF(new_path);
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     if (!module)
Karsten Hopp 2999ae
      {
Karsten Hopp 2999ae
! 	Py_INCREF(Py_None);
Karsten Hopp 2999ae
! 	return Py_None;
Karsten Hopp 2999ae
!     }
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!     if (!(loader = PyObject_NEW(LoaderObject, &LoaderType)))
Karsten Hopp 2999ae
!     {
Karsten Hopp 2999ae
! 	Py_DECREF(module);
Karsten Hopp 2999ae
  	return NULL;
Karsten Hopp 2999ae
      }
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     loader->module = module;
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
!     return (PyObject *) loader;
Karsten Hopp 2999ae
  }
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
      static PyObject *
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 1483,1489 ****
Karsten Hopp 2999ae
  PythonMod_Init(void)
Karsten Hopp 2999ae
  {
Karsten Hopp 2999ae
      /* The special value is removed from sys.path in Python_Init(). */
Karsten Hopp 2999ae
!     static char *(argv[2]) = {"/must>not&exist/foo", NULL};
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
      if (init_types())
Karsten Hopp 2999ae
  	return -1;
Karsten Hopp 2999ae
--- 1552,1585 ----
Karsten Hopp 2999ae
  PythonMod_Init(void)
Karsten Hopp 2999ae
  {
Karsten Hopp 2999ae
      /* The special value is removed from sys.path in Python_Init(). */
Karsten Hopp 2999ae
!     static char	*(argv[2]) = {"/must>not&exist/foo", NULL};
Karsten Hopp 2999ae
!     PyObject	*imp;
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!     if (!(imp = PyImport_ImportModule("imp")))
Karsten Hopp 2999ae
! 	return -1;
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!     if (!(py_find_module = PyObject_GetAttrString(imp, "find_module")))
Karsten Hopp 2999ae
!     {
Karsten Hopp 2999ae
! 	Py_DECREF(imp);
Karsten Hopp 2999ae
! 	return -1;
Karsten Hopp 2999ae
!     }
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!     if (!(py_load_module = PyObject_GetAttrString(imp, "load_module")))
Karsten Hopp 2999ae
!     {
Karsten Hopp 2999ae
! 	Py_DECREF(py_find_module);
Karsten Hopp 2999ae
! 	Py_DECREF(imp);
Karsten Hopp 2999ae
! 	return -1;
Karsten Hopp 2999ae
!     }
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!     Py_DECREF(imp);
Karsten Hopp 2999ae
! 
Karsten Hopp 2999ae
!     vim_memset(&LoaderType, 0, sizeof(LoaderType));
Karsten Hopp 2999ae
!     LoaderType.tp_name = "vim.Loader";
Karsten Hopp 2999ae
!     LoaderType.tp_basicsize = sizeof(LoaderObject);
Karsten Hopp 2999ae
!     LoaderType.tp_flags = Py_TPFLAGS_DEFAULT;
Karsten Hopp 2999ae
!     LoaderType.tp_doc = "vim message object";
Karsten Hopp 2999ae
!     LoaderType.tp_methods = LoaderMethods;
Karsten Hopp 2999ae
!     LoaderType.tp_dealloc = (destructor)LoaderDestructor;
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
      if (init_types())
Karsten Hopp 2999ae
  	return -1;
Karsten Hopp 2999ae
*** ../vim-7.3.1171/src/testdir/python2/module.py	2013-06-11 18:47:37.000000000 +0200
Karsten Hopp 2999ae
--- src/testdir/python2/module.py	2013-06-12 14:12:13.000000000 +0200
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 1 ****
Karsten Hopp 2999ae
--- 1,2 ----
Karsten Hopp 2999ae
+ import before_1
Karsten Hopp 2999ae
  dir = '2'
Karsten Hopp 2999ae
*** ../vim-7.3.1171/src/testdir/python3/module.py	2013-06-11 18:47:37.000000000 +0200
Karsten Hopp 2999ae
--- src/testdir/python3/module.py	2013-06-12 14:12:13.000000000 +0200
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 1 ****
Karsten Hopp 2999ae
--- 1,2 ----
Karsten Hopp 2999ae
+ import before_1
Karsten Hopp 2999ae
  dir = '3'
Karsten Hopp 2999ae
*** ../vim-7.3.1171/src/testdir/python_after/after.py	1970-01-01 01:00:00.000000000 +0100
Karsten Hopp 2999ae
--- src/testdir/python_after/after.py	2013-06-12 14:12:13.000000000 +0200
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 0 ****
Karsten Hopp 2999ae
--- 1,2 ----
Karsten Hopp 2999ae
+ import before_2
Karsten Hopp 2999ae
+ dir = "after"
Karsten Hopp 2999ae
*** ../vim-7.3.1171/src/testdir/python_before/before.py	1970-01-01 01:00:00.000000000 +0100
Karsten Hopp 2999ae
--- src/testdir/python_before/before.py	2013-06-12 14:12:13.000000000 +0200
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 0 ****
Karsten Hopp 2999ae
--- 1 ----
Karsten Hopp 2999ae
+ dir = "before"
Karsten Hopp 2999ae
*** ../vim-7.3.1171/src/testdir/test86.in	2013-06-11 18:47:37.000000000 +0200
Karsten Hopp 2999ae
--- src/testdir/test86.in	2013-06-12 14:12:13.000000000 +0200
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 8,13 ****
Karsten Hopp 2999ae
--- 8,14 ----
Karsten Hopp 2999ae
  STARTTEST
Karsten Hopp 2999ae
  :so small.vim
Karsten Hopp 2999ae
  :set encoding=latin1
Karsten Hopp 2999ae
+ :set noswapfile
Karsten Hopp 2999ae
  :if !has('python') | e! test.ok | wq! test.out | endif
Karsten Hopp 2999ae
  :lang C
Karsten Hopp 2999ae
  :py import vim
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 1071,1080 ****
Karsten Hopp 2999ae
--- 1072,1087 ----
Karsten Hopp 2999ae
  :"
Karsten Hopp 2999ae
  :" Test import
Karsten Hopp 2999ae
  py << EOF
Karsten Hopp 2999ae
+ sys.path.insert(0, os.path.join(os.getcwd(), 'python_before'))
Karsten Hopp 2999ae
+ sys.path.append(os.path.join(os.getcwd(), 'python_after'))
Karsten Hopp 2999ae
  vim.options['rtp'] = os.getcwd().replace(',', '\\,').replace('\\', '\\\\')
Karsten Hopp 2999ae
  from module import dir as d
Karsten Hopp 2999ae
  from modulex import ddir
Karsten Hopp 2999ae
  cb.append(d + ',' + ddir)
Karsten Hopp 2999ae
+ import before
Karsten Hopp 2999ae
+ cb.append(before.dir)
Karsten Hopp 2999ae
+ import after
Karsten Hopp 2999ae
+ cb.append(after.dir)
Karsten Hopp 2999ae
  EOF
Karsten Hopp 2999ae
  :"
Karsten Hopp 2999ae
  :" Test exceptions
Karsten Hopp 2999ae
*** ../vim-7.3.1171/src/testdir/test86.ok	2013-06-11 18:47:37.000000000 +0200
Karsten Hopp 2999ae
--- src/testdir/test86.ok	2013-06-12 14:12:13.000000000 +0200
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 1084,1089 ****
Karsten Hopp 2999ae
--- 1084,1091 ----
Karsten Hopp 2999ae
  vim.current.tabpage = True:(<type 'exceptions.TypeError'>, TypeError('expected vim.TabPage object',))
Karsten Hopp 2999ae
  vim.current.xxx = True:(<type 'exceptions.AttributeError'>, AttributeError('xxx',))
Karsten Hopp 2999ae
  2,xx
Karsten Hopp 2999ae
+ before
Karsten Hopp 2999ae
+ after
Karsten Hopp 2999ae
  vim.command("throw 'abc'"):(<class 'vim.error'>, error('abc',))
Karsten Hopp 2999ae
  Exe("throw 'def'"):(<class 'vim.error'>, error('def',))
Karsten Hopp 2999ae
  vim.eval("Exe('throw ''ghi''')"):(<class 'vim.error'>, error('ghi',))
Karsten Hopp 2999ae
*** ../vim-7.3.1171/src/testdir/test87.in	2013-06-11 18:47:37.000000000 +0200
Karsten Hopp 2999ae
--- src/testdir/test87.in	2013-06-12 14:12:13.000000000 +0200
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 2,7 ****
Karsten Hopp 2999ae
--- 2,8 ----
Karsten Hopp 2999ae
  
Karsten Hopp 2999ae
  STARTTEST
Karsten Hopp 2999ae
  :so small.vim
Karsten Hopp 2999ae
+ :set noswapfile
Karsten Hopp 2999ae
  :if !has('python3') | e! test.ok | wq! test.out | endif
Karsten Hopp 2999ae
  :lang C
Karsten Hopp 2999ae
  :py3 import vim
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 1038,1047 ****
Karsten Hopp 2999ae
--- 1039,1054 ----
Karsten Hopp 2999ae
  :"
Karsten Hopp 2999ae
  :" Test import
Karsten Hopp 2999ae
  py3 << EOF
Karsten Hopp 2999ae
+ sys.path.insert(0, os.path.join(os.getcwd(), 'python_before'))
Karsten Hopp 2999ae
+ sys.path.append(os.path.join(os.getcwd(), 'python_after'))
Karsten Hopp 2999ae
  vim.options['rtp'] = os.getcwd().replace(',', '\\,').replace('\\', '\\\\')
Karsten Hopp 2999ae
  from module import dir as d
Karsten Hopp 2999ae
  from modulex import ddir
Karsten Hopp 2999ae
  cb.append(d + ',' + ddir)
Karsten Hopp 2999ae
+ import before
Karsten Hopp 2999ae
+ cb.append(before.dir)
Karsten Hopp 2999ae
+ import after
Karsten Hopp 2999ae
+ cb.append(after.dir)
Karsten Hopp 2999ae
  EOF
Karsten Hopp 2999ae
  :"
Karsten Hopp 2999ae
  :" Test exceptions
Karsten Hopp 2999ae
*** ../vim-7.3.1171/src/testdir/test87.ok	2013-06-11 18:47:37.000000000 +0200
Karsten Hopp 2999ae
--- src/testdir/test87.ok	2013-06-12 14:12:13.000000000 +0200
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 1093,1098 ****
Karsten Hopp 2999ae
--- 1093,1100 ----
Karsten Hopp 2999ae
  vim.current.tabpage = True:(<class 'TypeError'>, TypeError('expected vim.TabPage object',))
Karsten Hopp 2999ae
  vim.current.xxx = True:(<class 'AttributeError'>, AttributeError('xxx',))
Karsten Hopp 2999ae
  3,xx
Karsten Hopp 2999ae
+ before
Karsten Hopp 2999ae
+ after
Karsten Hopp 2999ae
  vim.command("throw 'abc'"):(<class 'vim.error'>, error('abc',))
Karsten Hopp 2999ae
  Exe("throw 'def'"):(<class 'vim.error'>, error('def',))
Karsten Hopp 2999ae
  vim.eval("Exe('throw ''ghi''')"):(<class 'vim.error'>, error('ghi',))
Karsten Hopp 2999ae
*** ../vim-7.3.1171/Filelist	2013-06-11 18:47:37.000000000 +0200
Karsten Hopp 2999ae
--- Filelist	2013-06-12 14:13:57.000000000 +0200
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 87,92 ****
Karsten Hopp 2999ae
--- 87,94 ----
Karsten Hopp 2999ae
  		src/testdir/python2/*.py \
Karsten Hopp 2999ae
  		src/testdir/python3/*.py \
Karsten Hopp 2999ae
  		src/testdir/pythonx/*.py \
Karsten Hopp 2999ae
+ 		src/testdir/python_after/*.py \
Karsten Hopp 2999ae
+ 		src/testdir/python_before/*.py \
Karsten Hopp 2999ae
  		src/proto.h \
Karsten Hopp 2999ae
  		src/proto/blowfish.pro \
Karsten Hopp 2999ae
  		src/proto/buffer.pro \
Karsten Hopp 2999ae
*** ../vim-7.3.1171/src/version.c	2013-06-12 14:10:23.000000000 +0200
Karsten Hopp 2999ae
--- src/version.c	2013-06-12 14:14:12.000000000 +0200
Karsten Hopp 2999ae
***************
Karsten Hopp 2999ae
*** 730,731 ****
Karsten Hopp 2999ae
--- 730,733 ----
Karsten Hopp 2999ae
  {   /* Add new patch number below this line */
Karsten Hopp 2999ae
+ /**/
Karsten Hopp 2999ae
+     1172,
Karsten Hopp 2999ae
  /**/
Karsten Hopp 2999ae
Karsten Hopp 2999ae
-- 
Karsten Hopp 2999ae
Microsoft says that MS-Windows is much better for you than Linux.
Karsten Hopp 2999ae
That's like the Pope saying that catholicism is much better for
Karsten Hopp 2999ae
you than protestantism.
Karsten Hopp 2999ae
Karsten Hopp 2999ae
 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
Karsten Hopp 2999ae
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
Karsten Hopp 2999ae
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
Karsten Hopp 2999ae
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///