diff -r 3ecddf168f1f Modules/readline.c --- a/Modules/readline.c Tue Nov 29 00:53:09 2011 +0100 +++ b/Modules/readline.c Tue Nov 29 07:11:28 2011 -0800 @@ -39,13 +39,12 @@ extern char **completion_matches(char *, rl_compentry_func_t *); #else -#if !defined(__APPLE__) +#ifndef HAVE_EDITLINE extern char **completion_matches(char *, CPFunction *); #endif #endif #endif -#ifdef __APPLE__ /* * It is possible to link the readline module to the readline * emulation library of editline/libedit. @@ -60,9 +59,6 @@ * - Note that replace_history and remove_history use a 0-based index * with both implementation. */ -static int using_libedit_emulation = 0; -static const char libedit_version_tag[] = "EditLine wrapper"; -#endif /* __APPLE__ */ static void on_completion_display_matches_hook(char **matches, @@ -520,15 +516,7 @@ static int _py_get_history_length(void) { - HISTORY_STATE *hist_st = history_get_history_state(); - int length = hist_st->length; - /* the history docs don't say so, but the address of hist_st changes each - time history_get_history_state is called which makes me think it's - freshly malloc'd memory... on the other hand, the address of the last - line stays the same as long as history isn't extended, so it appears to - be malloc'd but managed by the history package... */ - free(hist_st); - return length; + return history_length; } /* Exported function to get any element of history */ @@ -541,27 +529,27 @@ if (!PyArg_ParseTuple(args, "i:index", &idx)) return NULL; -#ifdef __APPLE__ - if (using_libedit_emulation) { - /* Libedit emulation uses 0-based indexes, - * the real one uses 1-based indexes, - * adjust the index to ensure that Python - * code doesn't have to worry about the - * difference. - */ - int length = _py_get_history_length(); - idx --; +#ifdef HAVE_EDITLINE + /* Libedit emulation uses 0-based indexes, + * the real one uses 1-based indexes, + * adjust the index to ensure that Python + * code doesn't have to worry about the + * difference. + */ + int length = _py_get_history_length(); + idx --; - /* - * Apple's readline emulation crashes when - * the index is out of range, therefore - * test for that and fail gracefully. - */ - if (idx < 0 || idx >= length) { - Py_RETURN_NONE; - } +#if __APPLE__ + /* + * Apple's readline emulation crashes when + * the index is out of range, therefore + * test for that and fail gracefully. + */ + if (idx < 0 || idx >= length) { + Py_RETURN_NONE; } -#endif /* __APPLE__ */ +#endif +#endif /* HAVE_EDITLINE */ if ((hist_ent = history_get(idx))) return PyString_FromString(hist_ent->line); else { @@ -865,13 +853,12 @@ Py_FatalError("not enough memory to save locale"); #endif -#ifdef __APPLE__ +#ifdef HAVE_EDITLINE /* the libedit readline emulation resets key bindings etc * when calling rl_initialize. So call it upfront */ - if (using_libedit_emulation) - rl_initialize(); -#endif /* __APPLE__ */ + rl_initialize(); +#endif /* HAVE_EDITLINE */ using_history(); @@ -904,12 +891,11 @@ * XXX: A bug in the readline-2.2 library causes a memory leak * inside this function. Nothing we can do about it. */ -#ifdef __APPLE__ - if (using_libedit_emulation) - rl_read_init_file(NULL); - else -#endif /* __APPLE__ */ - rl_initialize(); +#ifdef HAVE_EDITLINE + rl_read_init_file(NULL); +#else + rl_initialize(); +#endif /* __HAVE_EDITLINE__ */ RESTORE_LOCALE(saved_locale) } @@ -1074,18 +1060,28 @@ if (n > 0) { const char *line; int length = _py_get_history_length(); - if (length > 0) -#ifdef __APPLE__ - if (using_libedit_emulation) { - /* - * Libedit's emulation uses 0-based indexes, - * the real readline uses 1-based indexes. - */ - line = history_get(length - 1)->line; - } else -#endif /* __APPLE__ */ - line = history_get(length)->line; - else + if (length > 0) { +#ifdef HAVE_EDITLINE + /* + * Libedit's emulation uses 0-based indexes, + * the real readline uses 1-based indexes. + */ + HIST_ENTRY *hs; + hs = history_get(length); +#else + HISTORY_STATE *hs; + hs = history_get(length); +#endif /* HAVE_EDITLINE */ + /* + * FreeBSD's libedit implementation returns NULL on out of bound + * accesses. For whatever reason it incorrectly claims that it has + * an element when it really doesn't really have one. + */ + if (hs == NULL) + line = ""; + else + line = hs->line; + } else line = ""; if (strcmp(p, line)) add_history(p); @@ -1107,31 +1103,19 @@ /* Initialize the module */ +#ifdef HAVE_EDITLINE +PyDoc_STRVAR(doc_module, +"Importing this module enables command line editing using libedit readline."); +#else PyDoc_STRVAR(doc_module, "Importing this module enables command line editing using GNU readline."); - -#ifdef __APPLE__ -PyDoc_STRVAR(doc_module_le, -"Importing this module enables command line editing using libedit readline."); -#endif /* __APPLE__ */ +#endif PyMODINIT_FUNC initreadline(void) { PyObject *m; -#ifdef __APPLE__ - if (strncmp(rl_library_version, libedit_version_tag, strlen(libedit_version_tag)) == 0) { - using_libedit_emulation = 1; - } - - if (using_libedit_emulation) - m = Py_InitModule4("readline", readline_methods, doc_module_le, - (PyObject *)NULL, PYTHON_API_VERSION); - else - -#endif /* __APPLE__ */ - m = Py_InitModule4("readline", readline_methods, doc_module, (PyObject *)NULL, PYTHON_API_VERSION); if (m == NULL) diff -r 3ecddf168f1f configure.in --- a/configure.in Tue Nov 29 00:53:09 2011 +0100 +++ b/configure.in Tue Nov 29 07:11:28 2011 -0800 @@ -970,6 +970,8 @@ UNIVERSAL_ARCH_FLAGS= AC_SUBST(UNIVERSAL_ARCH_FLAGS) +DEFAULT_LIBREADLINE=readline + # tweak BASECFLAGS based on compiler and platform case $GCC in yes) @@ -1021,6 +1023,7 @@ ;; esac AC_MSG_RESULT($CC) + DEFAULT_LIBREADLINE=editline fi # Calculate the right deployment target for this build. @@ -3855,87 +3858,128 @@ [Define this if you have flockfile(), getc_unlocked(), and funlockfile()]) fi +AC_ARG_WITH([readline], + [AS_HELP_STRING([--with-readline], + [enable support for the readline module. You can also specify readline, editline, etc, or no to disable detection. Defaults to $DEFAULT_LIBREADLINE])], + [], + [with_readline=$DEFAULT_LIBREADLINE]) + # check where readline lives # save the value of LIBS so we don't actually link Python with readline LIBS_no_readline=$LIBS -# On some systems we need to link readline to a termcap compatible -# library. NOTE: Keep the precedence of listed libraries synchronised -# with setup.py. -py_cv_lib_readline=no -AC_MSG_CHECKING([how to link readline libs]) -for py_libtermcap in "" ncursesw ncurses curses termcap; do - if test -z "$py_libtermcap"; then - READLINE_LIBS="-lreadline" +if test "x$with_readline" != "xno" +then + + if test "x$with_readline" = xeditline + then + LIBREADLINE=edit + elif test "x$with_readline" = xreadline + then + LIBREADLINE=readline else - READLINE_LIBS="-lreadline -l$py_libtermcap" + LIBREADLINE=$DEFAULT_LIBREADLINE fi - LIBS="$READLINE_LIBS $LIBS_no_readline" - AC_LINK_IFELSE( - [AC_LANG_CALL([],[readline])], - [py_cv_lib_readline=yes]) - if test $py_cv_lib_readline = yes; then - break + + # On some systems we need to link readline to a termcap compatible + # library. NOTE: Keep the precedence of listed libraries synchronised + # with setup.py. + py_cv_lib_readline=no + AC_MSG_CHECKING([how to link readline libs]) + for py_libtermcap in "" ncursesw ncurses curses termcap; do + if test -z "$py_libtermcap"; then + READLINE_LIBS="-l$LIBREADLINE" + else + READLINE_LIBS="-l$LIBREADLINE -l$py_libtermcap" + fi + LIBS="$READLINE_LIBS $LIBS_no_readline" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([#include ],[ +readline("this is a prompt"); +])],[py_cv_lib_readline=yes]) + if test $py_cv_lib_readline = yes; then + break + fi + done + + # Uncomment this line if you want to use READINE_LIBS in Makefile or scripts + #AC_SUBST([READLINE_LIBS]) + if test $py_cv_lib_readline = no; then + AC_MSG_RESULT([none]) + else + AC_MSG_RESULT([$READLINE_LIBS]) + if test "x$LIBREADLINE" = xedit + then + AC_DEFINE(HAVE_EDITLINE, 1, + [Define if you have the editline library (-ledit).]) + else + AC_DEFINE(HAVE_LIBREADLINE, 1, + [Define if you have the readline library (-lreadline).]) + fi fi -done -# Uncomment this line if you want to use READINE_LIBS in Makefile or scripts -#AC_SUBST([READLINE_LIBS]) -if test $py_cv_lib_readline = no; then - AC_MSG_RESULT([none]) -else - AC_MSG_RESULT([$READLINE_LIBS]) - AC_DEFINE(HAVE_LIBREADLINE, 1, - [Define if you have the readline library (-lreadline).]) + fi -# check for readline 2.1 -AC_CHECK_LIB(readline, rl_callback_handler_install, +if test "x$py_cv_lib_readline" = "xyes" +then + + # check for readline 2.1 + AC_CHECK_LIB($LIBREADLINE, rl_callback_handler_install, AC_DEFINE(HAVE_RL_CALLBACK, 1, [Define if you have readline 2.1]), ,$READLINE_LIBS) -# check for readline 2.2 -AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])], - [have_readline=yes], - [have_readline=no] -) -if test $have_readline = yes + # check for readline 2.2 + AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])], + [have_readline=yes], + [have_readline=no] + ) +fi + +if test "x$have_readline" = xyes then - AC_EGREP_HEADER([extern int rl_completion_append_character;], - [readline/readline.h], - AC_DEFINE(HAVE_RL_COMPLETION_APPEND_CHARACTER, 1, - [Define if you have readline 2.2]), ) - AC_EGREP_HEADER([extern int rl_completion_suppress_append;], - [readline/readline.h], - AC_DEFINE(HAVE_RL_COMPLETION_SUPPRESS_APPEND, 1, - [Define if you have rl_completion_suppress_append]), ) -fi - -# check for readline 4.0 -AC_CHECK_LIB(readline, rl_pre_input_hook, + AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#include +],[ +int i = 0; +rl_completion_append_character = i; +])],[ + AC_DEFINE(HAVE_RL_COMPLETION_APPEND_CHARACTER,1, + [Define if you have readline 2.2]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#include +],[ +int i = 0; +rl_completion_suppress_append = i; +])],[ + AC_DEFINE(HAVE_RL_COMPLETION_SUPPRESS_APPEND,1, + [Define if you have rl_completion_suppress_append]) +])]) + + # check for readline 4.0 + AC_CHECK_LIB($LIBREADLINE, rl_pre_input_hook, AC_DEFINE(HAVE_RL_PRE_INPUT_HOOK, 1, - [Define if you have readline 4.0]), ,$READLINE_LIBS) - -# also in 4.0 -AC_CHECK_LIB(readline, rl_completion_display_matches_hook, + [Define if you have readline 4.0]),,$READLINE_LIBS) + + # also in 4.0 + AC_CHECK_LIB($LIBREADLINE, rl_completion_display_matches_hook, AC_DEFINE(HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK, 1, - [Define if you have readline 4.0]), ,$READLINE_LIBS) - -# check for readline 4.2 -AC_CHECK_LIB(readline, rl_completion_matches, + [Define if you have readline 4.0]),,$READLINE_LIBS) + + # check for readline 4.2 + AC_CHECK_LIB($LIBREADLINE, rl_completion_matches, AC_DEFINE(HAVE_RL_COMPLETION_MATCHES, 1, - [Define if you have readline 4.2]), ,$READLINE_LIBS) - -# also in readline 4.2 -AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])], - [have_readline=yes], - [have_readline=no] -) -if test $have_readline = yes -then - AC_EGREP_HEADER([extern int rl_catch_signals;], - [readline/readline.h], - AC_DEFINE(HAVE_RL_CATCH_SIGNAL, 1, - [Define if you can turn off readline's signal handling.]), ) + [Define if you have readline 4.2]),,$READLINE_LIBS) + +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ +#include +],[ +int i = 0; +rl_catch_signals = i; +])],[ + AC_DEFINE(HAVE_RL_CATCH_SIGNAL,1, + [Define if you can turn off readline''s signal handling.]) +]) + fi # End of readline checks: restore LIBS