diff -r 560f5e777ca4 Modules/readline.c --- a/Modules/readline.c Thu Aug 16 21:52:39 2012 +0200 +++ b/Modules/readline.c Thu Aug 16 22:01:18 2012 +0200 @@ -70,6 +70,55 @@ int num_matches, int max_length); #endif +typedef struct { + PyObject *completion_display_matches_hook; + PyObject *startup_hook; + PyObject *pre_input_hook; + PyObject *completer; + PyObject *begidx; + PyObject *endidx; +} readlinestate; + + +#define readline_state(o) ((readlinestate *)PyModule_GetState(o)) + +static int +readline_clear(PyObject *m) +{ + readlinestate *state = readline_state(m); + Py_CLEAR(state->completion_display_matches_hook); + Py_CLEAR(state->startup_hook); + Py_CLEAR(state->pre_input_hook); + Py_CLEAR(state->completer); + Py_CLEAR(state->begidx); + Py_CLEAR(state->endidx); + return 0; +} + +static int +readline_traverse(PyObject *m, visitproc visit, void *arg) +{ + readlinestate *state = readline_state(m); + Py_VISIT(state->completion_display_matches_hook); + Py_VISIT(state->startup_hook); + Py_VISIT(state->pre_input_hook); + Py_VISIT(state->completer); + Py_VISIT(state->begidx); + Py_VISIT(state->endidx); + return 0; +} + +static void +readline_free(void *m) +{ + readline_clear((PyObject *)m); +} + +static PyModuleDef readlinemodule; + +#define readlinestate_global ((readlinestate *)PyModule_GetState(PyState_FindModule(&readlinemodule))) + + /* Exported function to send one line to readline's init file parser */ static PyObject * @@ -246,23 +295,21 @@ /* Exported functions to specify hook functions in Python */ -static PyObject *completion_display_matches_hook = NULL; -static PyObject *startup_hook = NULL; #ifdef HAVE_RL_PRE_INPUT_HOOK -static PyObject *pre_input_hook = NULL; + #endif static PyObject * set_completion_display_matches_hook(PyObject *self, PyObject *args) { PyObject *result = set_hook("completion_display_matches_hook", - &completion_display_matches_hook, args); + &readlinestate_global->completion_display_matches_hook, args); #ifdef HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK /* We cannot set this hook globally, since it replaces the default completion display. */ rl_completion_display_matches_hook = - completion_display_matches_hook ? + readlinestate_global->completion_display_matches_hook ? #if defined(_RL_FUNCTION_TYPEDEF) (rl_compdisp_func_t *)on_completion_display_matches_hook : 0; #else @@ -283,7 +330,7 @@ static PyObject * set_startup_hook(PyObject *self, PyObject *args) { - return set_hook("startup_hook", &startup_hook, args); + return set_hook("startup_hook", &readlinestate_global->startup_hook, args); } PyDoc_STRVAR(doc_set_startup_hook, @@ -300,7 +347,7 @@ static PyObject * set_pre_input_hook(PyObject *self, PyObject *args) { - return set_hook("pre_input_hook", &pre_input_hook, args); + return set_hook("pre_input_hook", &readlinestate_global->pre_input_hook, args); } PyDoc_STRVAR(doc_set_pre_input_hook, @@ -315,10 +362,10 @@ /* Exported function to specify a word completer in Python */ -static PyObject *completer = NULL; -static PyObject *begidx = NULL; -static PyObject *endidx = NULL; + + + /* Get the completion type for the scope of the tab-completion */ @@ -338,8 +385,8 @@ static PyObject * get_begidx(PyObject *self, PyObject *noarg) { - Py_INCREF(begidx); - return begidx; + Py_INCREF(readlinestate_global->begidx); + return readlinestate_global->begidx; } PyDoc_STRVAR(doc_get_begidx, @@ -352,8 +399,8 @@ static PyObject * get_endidx(PyObject *self, PyObject *noarg) { - Py_INCREF(endidx); - return endidx; + Py_INCREF(readlinestate_global->endidx); + return readlinestate_global->endidx; } PyDoc_STRVAR(doc_get_endidx, @@ -510,7 +557,7 @@ static PyObject * set_completer(PyObject *self, PyObject *args) { - return set_hook("completer", &completer, args); + return set_hook("completer", &readlinestate_global->completer, args); } PyDoc_STRVAR(doc_set_completer, @@ -524,11 +571,11 @@ static PyObject * get_completer(PyObject *self, PyObject *noargs) { - if (completer == NULL) { + if (readlinestate_global->completer == NULL) { Py_RETURN_NONE; } - Py_INCREF(completer); - return completer; + Py_INCREF(readlinestate_global->completer); + return readlinestate_global->completer; } PyDoc_STRVAR(doc_get_completer, @@ -762,14 +809,14 @@ static int on_startup_hook(void) { - return on_hook(startup_hook); + return on_hook(readlinestate_global->startup_hook); } #ifdef HAVE_RL_PRE_INPUT_HOOK static int on_pre_input_hook(void) { - return on_hook(pre_input_hook); + return on_hook(readlinestate_global->pre_input_hook); } #endif @@ -796,7 +843,7 @@ if (PyList_SetItem(m, i, s) == -1) goto error; } - r = PyObject_CallFunction(completion_display_matches_hook, + r = PyObject_CallFunction(readlinestate_global->completion_display_matches_hook, "sOi", matches[0], m, max_length); Py_DECREF(m); m=NULL; @@ -826,13 +873,13 @@ on_completion(const char *text, int state) { char *result = NULL; - if (completer != NULL) { + if (readlinestate_global->completer != NULL) { PyObject *r; #ifdef WITH_THREAD PyGILState_STATE gilstate = PyGILState_Ensure(); #endif rl_attempted_completion_over = 1; - r = PyObject_CallFunction(completer, "si", text, state); + r = PyObject_CallFunction(readlinestate_global->completer, "si", text, state); if (r == NULL) goto error; if (r == Py_None) { @@ -871,10 +918,10 @@ #ifdef HAVE_RL_COMPLETION_SUPPRESS_APPEND rl_completion_suppress_append = 0; #endif - Py_XDECREF(begidx); - Py_XDECREF(endidx); - begidx = PyLong_FromLong((long) start); - endidx = PyLong_FromLong((long) end); + Py_XDECREF(readlinestate_global->begidx); + Py_XDECREF(readlinestate_global->endidx); + readlinestate_global->begidx = PyLong_FromLong((long) start); + readlinestate_global->endidx = PyLong_FromLong((long) end); return completion_matches(text, *on_completion); } @@ -922,8 +969,8 @@ strdup(" \t\n`~!@#$%^&*()-=+[{]}\\|;:'\",<>/?"); /* All nonalphanums except '.' */ - begidx = PyLong_FromLong(0L); - endidx = PyLong_FromLong(0L); + readlinestate_global->begidx = PyLong_FromLong(0L); + readlinestate_global->endidx = PyLong_FromLong(0L); /* Initialize (allows .inputrc to override) * * XXX: A bug in the readline-2.2 library causes a memory leak @@ -1145,12 +1192,12 @@ PyModuleDef_HEAD_INIT, "readline", doc_module, - -1, + sizeof(readlinestate), readline_methods, NULL, - NULL, - NULL, - NULL + readline_traverse, + readline_clear, + readline_free }; @@ -1170,11 +1217,9 @@ #endif /* __APPLE__ */ m = PyModule_Create(&readlinemodule); - if (m == NULL) return NULL; - - + PyState_AddModule(m, &readlinemodule); PyOS_ReadlineFunctionPointer = call_readline; setup_readline();