From 67164d72c3c12b1165f93f9d51994bacc6052254 Mon Sep 17 00:00:00 2001 From: Robert Marshall Date: Wed, 27 Feb 2019 01:45:42 -0500 Subject: [PATCH] Build or disable readline module with Editline I have ported the work done by martin.panter to latest master. * Include if Editline is configured * Redefine HAVE_LIBREADLINE to also indicate if -ledit is used * New flag WITH_EDITLINE to differentiate between -lreadline and -ledit * Remove conditional completion_matches() declarations; use the declaration from the library rather than trying to guess it Resolves #13501 Signed-off-by: Robert Marshall --- Modules/readline.c | 153 ++++++++++++------------- configure | 270 ++++++++++++++++++++++++--------------------- configure.ac | 186 ++++++++++++++++++------------- pyconfig.h.in | 5 +- setup.py | 13 ++- 5 files changed, 339 insertions(+), 288 deletions(-) diff --git a/Modules/readline.c b/Modules/readline.c index 57335fe911..735cc194b8 100644 --- a/Modules/readline.c +++ b/Modules/readline.c @@ -26,45 +26,47 @@ # define RESTORE_LOCALE(sl) #endif +#ifdef WITH_EDITLINE +# include +#else /* GNU readline definitions */ -#undef HAVE_CONFIG_H /* Else readline/chardefs.h includes strings.h */ -#include -#include +# undef HAVE_CONFIG_H /* Else readline/chardefs.h includes strings.h */ +# include +# include +#endif +/* Readline 4.2 deprecated completion_matches() in favour of ++rl_completion_matches() */ #ifdef HAVE_RL_COMPLETION_MATCHES #define completion_matches(x, y) \ rl_completion_matches((x), ((rl_compentry_func_t *)(y))) -#else -#if defined(_RL_FUNCTION_TYPEDEF) -extern char **completion_matches(char *, rl_compentry_func_t *); -#else - -#if !defined(__APPLE__) -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. * * On OSX this emulation library is not 100% API compatible - * with the "real" readline and cannot be detected at compile-time, + * with the "real" readline and if WITH_EDITLINE + * was not specified, cannot be detected at compile-time, * hence we use a runtime check to detect if we're using libedit - * - * Currently there is one known API incompatibility: + */ +#if defined(__APPLE__) && !defined(WITH_EDITLINE) +# define DETECT_EDITLINE +static int using_libedit_emulation = 0; +static const char libedit_version_tag[] = "EditLine wrapper"; +#endif + +#if defined(WITH_EDITLINE) || defined(__APPLE__) +# define SUPPORT_EDITLINE +/* One incompatibility of Editline: * - 'get_history' has a 1-based index with GNU readline, and a 0-based * index with older versions of libedit's emulation. * - Note that replace_history and remove_history use a 0-based index * with both implementations. */ -static int using_libedit_emulation = 0; -static const char libedit_version_tag[] = "EditLine wrapper"; - static int libedit_history_start = 0; -#endif /* __APPLE__ */ +#endif #ifdef HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK static void @@ -664,25 +666,6 @@ PyDoc_STRVAR(doc_get_completer, \n\ Returns current completer function."); -/* Private function to get current length of history. XXX It may be - * possible to replace this with a direct use of history_length instead, - * but it's not clear whether BSD's libedit keeps history_length up to date. - * See issue #8065.*/ - -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; -} - /* Exported function to get any element of history */ static PyObject * @@ -693,27 +676,25 @@ get_history_item(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "i:get_history_item", &idx)) return NULL; -#ifdef __APPLE__ - if (using_libedit_emulation) { - /* Older versions of libedit's readline emulation - * use 0-based indexes, while readline and newer - * versions of libedit use 1-based indexes. - */ - int length = _py_get_history_length(); - - idx = idx - 1 + libedit_history_start; - - /* - * Apple's readline emulation crashes when - * the index is out of range, therefore - * test for that and fail gracefully. - */ - if (idx < (0 + libedit_history_start) - || idx >= (length + libedit_history_start)) { - Py_RETURN_NONE; - } + +#ifdef SUPPORT_EDITLINE + idx = idx - 1 + libedit_history_start; + + /* + * Apple's readline emulation crashes when + * the index is out of range, therefore + * test for that and fail gracefully. + */ + /* KELLIN NOTE: + * The initial patch removed the 0 for some unknown to me reason + * + * if (idx < (0 + libedit_history_start) + */ + if (idx < libedit_history_start + || idx >= (history_length + libedit_history_start)) { + Py_RETURN_NONE; } -#endif /* __APPLE__ */ +#endif /* SUPPORT_EDITLINE */ if ((hist_ent = history_get(idx))) return decode(hist_ent->line); else { @@ -731,7 +712,7 @@ return the current contents of history item at index."); static PyObject * get_current_history_length(PyObject *self, PyObject *noarg) { - return PyLong_FromLong((long)_py_get_history_length()); + return PyLong_FromLong(history_length); } PyDoc_STRVAR(doc_get_current_history_length, @@ -1080,14 +1061,16 @@ setup_readline(readlinestate *mod_state) /* The name must be defined before initialization */ rl_readline_name = "python"; -#ifdef __APPLE__ +#ifdef SUPPORT_EDITLINE /* the libedit readline emulation resets key bindings etc - * when calling rl_initialize. So call it upfront + * when calling rl_initialize. So call it before making those settings. */ +# ifdef DETECT_EDITLINE if (using_libedit_emulation) +# endif rl_initialize(); - /* Detect if libedit's readline emulation uses 0-based + /* Detect if the backend library uses 0-based * indexing or 1-based indexing. */ add_history("1"); @@ -1097,7 +1080,7 @@ setup_readline(readlinestate *mod_state) libedit_history_start = 1; } clear_history(); -#endif /* __APPLE__ */ +#endif /* SUPPORT_EDITLINE */ using_history(); @@ -1126,7 +1109,7 @@ setup_readline(readlinestate *mod_state) mod_state->begidx = PyLong_FromLong(0L); mod_state->endidx = PyLong_FromLong(0L); -#ifdef __APPLE__ +#ifdef SUPPORT_EDITLINE if (!using_libedit_emulation) #endif { @@ -1147,13 +1130,20 @@ setup_readline(readlinestate *mod_state) * * XXX: A bug in the readline-2.2 library causes a memory leak * inside this function. Nothing we can do about it. + * + * For Editline, just invoke the user configuration; initialization was + * already done above. */ -#ifdef __APPLE__ +#ifdef DETECT_EDITLINE if (using_libedit_emulation) rl_read_init_file(NULL); else -#endif /* __APPLE__ */ rl_initialize(); +#elif defined(WITH_EDITLINE) + rl_read_init_file(NULL); +#else + rl_initialize(); +#endif RESTORE_LOCALE(saved_locale) } @@ -1278,16 +1268,13 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt) n = strlen(p); if (should_auto_add_history && n > 0) { const char *line; - int length = _py_get_history_length(); - if (length > 0) { + if (history_length > 0) { HIST_ENTRY *hist_ent; -#ifdef __APPLE__ - if (using_libedit_emulation) { - /* handle older 0-based or newer 1-based indexing */ - hist_ent = history_get(length + libedit_history_start - 1); - } else -#endif /* __APPLE__ */ - hist_ent = history_get(length); +#ifdef SUPPORT_EDITLINE + hist_ent = history_get(history_length + libedit_history_start - 1); +#else + hist_ent = history_get(history_length); +#endif line = hist_ent ? hist_ent->line : ""; } else line = ""; @@ -1312,12 +1299,15 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt) /* Initialize the module */ PyDoc_STRVAR(doc_module, +#ifndef WITH_EDITLINE "Importing this module enables command line editing using GNU readline."); - -#ifdef __APPLE__ +#endif +#ifdef DETECT_EDITLINE PyDoc_STRVAR(doc_module_le, +#endif +#ifdef SUPPORT_EDITLINE "Importing this module enables command line editing using libedit readline."); -#endif /* __APPLE__ */ +#endif static struct PyModuleDef readlinemodule = { PyModuleDef_HEAD_INIT, @@ -1338,15 +1328,14 @@ PyInit_readline(void) PyObject *m; readlinestate *mod_state; -#ifdef __APPLE__ +#ifdef DETECT_EDITLINE if (strncmp(rl_library_version, libedit_version_tag, strlen(libedit_version_tag)) == 0) { using_libedit_emulation = 1; } if (using_libedit_emulation) readlinemodule.m_doc = doc_module_le; - -#endif /* __APPLE__ */ +#endif /* DETECT_EDITLINE */ m = PyModule_Create(&readlinemodule); diff --git a/configure b/configure index d98d14ab63..0ef3e68fb0 100755 --- a/configure +++ b/configure @@ -839,6 +839,7 @@ with_dtrace with_libm with_libc enable_big_digits +with_readline with_computed_gotos with_ensurepip with_openssl @@ -1545,6 +1546,8 @@ Optional Packages: --with(out)-dtrace disable/enable DTrace support --with-libm=STRING math library --with-libc=STRING C library + --with(out)-readline[=editline] + use Editline for backend or disable readline module --with(out)-computed-gotos Use computed gotos in evaluation loop (enabled by default on supported compilers) @@ -15180,24 +15183,49 @@ $as_echo "#define HAVE_GETC_UNLOCKED 1" >>confdefs.h fi + +# Check whether --with-readline was given. +if test "${with_readline+set}" = set; then : + withval=$with_readline; +else + with_readline=yes +fi + + # check where readline lives +py_cv_lib_readline=no # 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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link readline libs" >&5 +if test "$with_readline" != no; then + case "$with_readline" in + editline|edit) + LIBREADLINE=edit + +$as_echo "#define WITH_EDITLINE 1" >>confdefs.h + + ;; + yes|readline) + LIBREADLINE=readline + ;; + *) + as_fn_error $? "proper usage is --with(out)-readline[=editline]" "$LINENO" 5 + ;; + esac + + # On some systems we need to link readline to a termcap compatible + # library. NOTE: Keep the precedence of listed libraries synchronised + # with setup.py. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link readline libs" >&5 $as_echo_n "checking how to link readline libs... " >&6; } -for py_libtermcap in "" tinfo ncursesw ncurses curses termcap; do - if test -z "$py_libtermcap"; then - READLINE_LIBS="-lreadline" - else - READLINE_LIBS="-lreadline -l$py_libtermcap" - fi - LIBS="$READLINE_LIBS $LIBS_no_readline" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + for py_libtermcap in "" tinfo 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" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. @@ -15220,73 +15248,67 @@ if ac_fn_c_try_link "$LINENO"; then : fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - 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 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 + if test $py_cv_lib_readline = yes; then + break + fi + done + + # Uncomment this line if you want to use READLINE_LIBS in Makefile or scripts + #AC_SUBST([READLINE_LIBS]) + if test $py_cv_lib_readline = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $READLINE_LIBS" >&5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $READLINE_LIBS" >&5 $as_echo "$READLINE_LIBS" >&6; } $as_echo "#define HAVE_LIBREADLINE 1" >>confdefs.h + fi fi -# check for readline 2.2 -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - have_readline=yes -else - have_readline=no - -fi -rm -f conftest.err conftest.i conftest.$ac_ext -if test $have_readline = yes -then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include +if test "$py_cv_lib_readline" = yes; then + # check for readline 2.2 + ac_fn_c_check_decl "$LINENO" "rl_completion_append_character" "ac_cv_have_decl_rl_completion_append_character" " +#include /* Must be first for Gnu Readline */ +#ifdef WITH_EDITLINE +# include +#else +# include +#endif -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "extern int rl_completion_append_character;" >/dev/null 2>&1; then : +" +if test "x$ac_cv_have_decl_rl_completion_append_character" = xyes; then : -$as_echo "#define HAVE_RL_COMPLETION_APPEND_CHARACTER 1" >>confdefs.h + $as_echo "#define HAVE_RL_COMPLETION_APPEND_CHARACTER 1" >>confdefs.h -fi -rm -f conftest* + fi - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "extern int rl_completion_suppress_append;" >/dev/null 2>&1; then : + ac_fn_c_check_decl "$LINENO" "rl_completion_suppress_append" "ac_cv_have_decl_rl_completion_suppress_append" " +#include /* Must be first for Gnu Readline */ +#ifdef WITH_EDITLINE +# include +#else +# include +#endif +" +if test "x$ac_cv_have_decl_rl_completion_suppress_append" = xyes; then : $as_echo "#define HAVE_RL_COMPLETION_SUPPRESS_APPEND 1" >>confdefs.h fi -rm -f conftest* -fi -# check for readline 4.0 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_pre_input_hook in -lreadline" >&5 -$as_echo_n "checking for rl_pre_input_hook in -lreadline... " >&6; } -if ${ac_cv_lib_readline_rl_pre_input_hook+:} false; then : + # check for readline 4.0 + as_ac_Lib=`$as_echo "ac_cv_lib_$LIBREADLINE''_rl_pre_input_hook" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_pre_input_hook in -l$LIBREADLINE" >&5 +$as_echo_n "checking for rl_pre_input_hook in -l$LIBREADLINE... " >&6; } +if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lreadline $READLINE_LIBS $LIBS" +LIBS="-l$LIBREADLINE $READLINE_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -15306,31 +15328,33 @@ return rl_pre_input_hook (); } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_readline_rl_pre_input_hook=yes + eval "$as_ac_Lib=yes" else - ac_cv_lib_readline_rl_pre_input_hook=no + eval "$as_ac_Lib=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_rl_pre_input_hook" >&5 -$as_echo "$ac_cv_lib_readline_rl_pre_input_hook" >&6; } -if test "x$ac_cv_lib_readline_rl_pre_input_hook" = xyes; then : +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : $as_echo "#define HAVE_RL_PRE_INPUT_HOOK 1" >>confdefs.h fi -# also in 4.0 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_completion_display_matches_hook in -lreadline" >&5 -$as_echo_n "checking for rl_completion_display_matches_hook in -lreadline... " >&6; } -if ${ac_cv_lib_readline_rl_completion_display_matches_hook+:} false; then : + # also in 4.0 + as_ac_Lib=`$as_echo "ac_cv_lib_$LIBREADLINE''_rl_completion_display_matches_hook" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_completion_display_matches_hook in -l$LIBREADLINE" >&5 +$as_echo_n "checking for rl_completion_display_matches_hook in -l$LIBREADLINE... " >&6; } +if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lreadline $READLINE_LIBS $LIBS" +LIBS="-l$LIBREADLINE $READLINE_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -15350,31 +15374,33 @@ return rl_completion_display_matches_hook (); } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_readline_rl_completion_display_matches_hook=yes + eval "$as_ac_Lib=yes" else - ac_cv_lib_readline_rl_completion_display_matches_hook=no + eval "$as_ac_Lib=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_rl_completion_display_matches_hook" >&5 -$as_echo "$ac_cv_lib_readline_rl_completion_display_matches_hook" >&6; } -if test "x$ac_cv_lib_readline_rl_completion_display_matches_hook" = xyes; then : +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : $as_echo "#define HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK 1" >>confdefs.h fi -# also in 4.0, but not in editline -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_resize_terminal in -lreadline" >&5 -$as_echo_n "checking for rl_resize_terminal in -lreadline... " >&6; } -if ${ac_cv_lib_readline_rl_resize_terminal+:} false; then : + # also in 4.0, but not in editline + as_ac_Lib=`$as_echo "ac_cv_lib_$LIBREADLINE''_rl_resize_terminal" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_resize_terminal in -l$LIBREADLINE" >&5 +$as_echo_n "checking for rl_resize_terminal in -l$LIBREADLINE... " >&6; } +if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lreadline $READLINE_LIBS $LIBS" +LIBS="-l$LIBREADLINE $READLINE_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -15394,31 +15420,33 @@ return rl_resize_terminal (); } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_readline_rl_resize_terminal=yes + eval "$as_ac_Lib=yes" else - ac_cv_lib_readline_rl_resize_terminal=no + eval "$as_ac_Lib=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_rl_resize_terminal" >&5 -$as_echo "$ac_cv_lib_readline_rl_resize_terminal" >&6; } -if test "x$ac_cv_lib_readline_rl_resize_terminal" = xyes; then : +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : $as_echo "#define HAVE_RL_RESIZE_TERMINAL 1" >>confdefs.h fi -# check for readline 4.2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_completion_matches in -lreadline" >&5 -$as_echo_n "checking for rl_completion_matches in -lreadline... " >&6; } -if ${ac_cv_lib_readline_rl_completion_matches+:} false; then : + # check for readline 4.2 + as_ac_Lib=`$as_echo "ac_cv_lib_$LIBREADLINE''_rl_completion_matches" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_completion_matches in -l$LIBREADLINE" >&5 +$as_echo_n "checking for rl_completion_matches in -l$LIBREADLINE... " >&6; } +if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lreadline $READLINE_LIBS $LIBS" +LIBS="-l$LIBREADLINE $READLINE_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -15438,59 +15466,49 @@ return rl_completion_matches (); } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_readline_rl_completion_matches=yes + eval "$as_ac_Lib=yes" else - ac_cv_lib_readline_rl_completion_matches=no + eval "$as_ac_Lib=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_rl_completion_matches" >&5 -$as_echo "$ac_cv_lib_readline_rl_completion_matches" >&6; } -if test "x$ac_cv_lib_readline_rl_completion_matches" = xyes; then : +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : $as_echo "#define HAVE_RL_COMPLETION_MATCHES 1" >>confdefs.h fi -# also in readline 4.2 -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - have_readline=yes -else - have_readline=no - -fi -rm -f conftest.err conftest.i conftest.$ac_ext -if test $have_readline = yes -then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include + # also in readline 4.2 + ac_fn_c_check_decl "$LINENO" "rl_catch_signals" "ac_cv_have_decl_rl_catch_signals" " +#include /* Must be first for Gnu Readline */ +#ifdef WITH_EDITLINE +# include +#else +# include +#endif -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "extern int rl_catch_signals;" >/dev/null 2>&1; then : +" +if test "x$ac_cv_have_decl_rl_catch_signals" = xyes; then : $as_echo "#define HAVE_RL_CATCH_SIGNAL 1" >>confdefs.h fi -rm -f conftest* -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for append_history in -lreadline" >&5 -$as_echo_n "checking for append_history in -lreadline... " >&6; } -if ${ac_cv_lib_readline_append_history+:} false; then : + as_ac_Lib=`$as_echo "ac_cv_lib_$LIBREADLINE''_append_history" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for append_history in -l$LIBREADLINE" >&5 +$as_echo_n "checking for append_history in -l$LIBREADLINE... " >&6; } +if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lreadline $READLINE_LIBS $LIBS" +LIBS="-l$LIBREADLINE $READLINE_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -15510,22 +15528,24 @@ return append_history (); } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_readline_append_history=yes + eval "$as_ac_Lib=yes" else - ac_cv_lib_readline_append_history=no + eval "$as_ac_Lib=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_append_history" >&5 -$as_echo "$ac_cv_lib_readline_append_history" >&6; } -if test "x$ac_cv_lib_readline_append_history" = xyes; then : +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : $as_echo "#define HAVE_RL_APPEND_HISTORY 1" >>confdefs.h fi +fi # End of readline checks: restore LIBS LIBS=$LIBS_no_readline diff --git a/configure.ac b/configure.ac index c7380caa19..0ba425bc95 100644 --- a/configure.ac +++ b/configure.ac @@ -4634,92 +4634,124 @@ then [Define this if you have flockfile(), getc_unlocked(), and funlockfile()]) fi +AC_ARG_WITH([readline], + [AS_HELP_STRING([--with(out)-readline@<:@=editline@:>@], + [use Editline for backend or disable readline module])], + [], + [with_readline=yes]) + # check where readline lives +py_cv_lib_readline=no # 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 "" tinfo ncursesw ncurses curses termcap; do - if test -z "$py_libtermcap"; then - READLINE_LIBS="-lreadline" +if test "$with_readline" != no; then + case "$with_readline" in + editline|edit) + LIBREADLINE=edit + AC_DEFINE(WITH_EDITLINE, 1, + [Define to build the readline module against Editline.]) + ;; + yes|readline) + LIBREADLINE=readline + ;; + *) + AC_MSG_ERROR([proper usage is --with(out)-readline@<:@=editline@:>@]) + ;; + esac + + # On some systems we need to link readline to a termcap compatible + # library. NOTE: Keep the precedence of listed libraries synchronised + # with setup.py. + AC_MSG_CHECKING([how to link readline libs]) + for py_libtermcap in "" tinfo 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_CALL([],[readline])], + [py_cv_lib_readline=yes]) + if test $py_cv_lib_readline = yes; then + break + fi + done + + # Uncomment this line if you want to use READLINE_LIBS in Makefile or scripts + #AC_SUBST([READLINE_LIBS]) + if test $py_cv_lib_readline = no; then + AC_MSG_RESULT([none]) else - READLINE_LIBS="-lreadline -l$py_libtermcap" + AC_MSG_RESULT([$READLINE_LIBS]) + AC_DEFINE(HAVE_LIBREADLINE, 1, + [Define to build the readline module.]) 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 - 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.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_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_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, - AC_DEFINE(HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK, 1, - [Define if you have readline 4.0]), ,$READLINE_LIBS) - -# also in 4.0, but not in editline -AC_CHECK_LIB(readline, rl_resize_terminal, - AC_DEFINE(HAVE_RL_RESIZE_TERMINAL, 1, - [Define if you have readline 4.0]), ,$READLINE_LIBS) - -# check for readline 4.2 -AC_CHECK_LIB(readline, 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.]), ) -fi +if test "$py_cv_lib_readline" = yes; then + # check for readline 2.2 + AC_CHECK_DECL(rl_completion_append_character, + AC_DEFINE(HAVE_RL_COMPLETION_APPEND_CHARACTER, 1, + [Define if you have readline 2.2]),, + [ +#include /* Must be first for Gnu Readline */ +#ifdef WITH_EDITLINE +# include +#else +# include +#endif + ]) + AC_CHECK_DECL(rl_completion_suppress_append, + AC_DEFINE(HAVE_RL_COMPLETION_SUPPRESS_APPEND, 1, + [Define if you have rl_completion_suppress_append]),, + [ +#include /* Must be first for Gnu Readline */ +#ifdef WITH_EDITLINE +# include +#else +# include +#endif + ]) -AC_CHECK_LIB(readline, append_history, - AC_DEFINE(HAVE_RL_APPEND_HISTORY, 1, - [Define if readline supports append_history]), ,$READLINE_LIBS) + # 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($LIBREADLINE, rl_completion_display_matches_hook, + AC_DEFINE(HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK, 1, + [Define if you have readline 4.0]),,$READLINE_LIBS) + + # also in 4.0, but not in editline + AC_CHECK_LIB($LIBREADLINE, rl_resize_terminal, + AC_DEFINE(HAVE_RL_RESIZE_TERMINAL, 1, + [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_CHECK_DECL(rl_catch_signals, + AC_DEFINE(HAVE_RL_CATCH_SIGNAL, 1, + [Define if you can turn off readline's signal handling.]),, + [ +#include /* Must be first for Gnu Readline */ +#ifdef WITH_EDITLINE +# include +#else +# include +#endif + ]) + + AC_CHECK_LIB($LIBREADLINE, append_history, + AC_DEFINE(HAVE_RL_APPEND_HISTORY, 1, + [Define if readline supports append_history]),,$READLINE_LIBS) +fi # End of readline checks: restore LIBS LIBS=$LIBS_no_readline diff --git a/pyconfig.h.in b/pyconfig.h.in index d41d579327..d12e3ead03 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -585,7 +585,7 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBINTL_H -/* Define if you have the readline library (-lreadline). */ +/* Define to build the readline module. */ #undef HAVE_LIBREADLINE /* Define to 1 if you have the `resolv' library (-lresolv). */ @@ -1495,6 +1495,9 @@ Dyld is necessary to support frameworks. */ #undef WITH_DYLD +/* Define to build the readline module against Editline. */ +#undef WITH_EDITLINE + /* Define to 1 if libintl is needed for locale functions. */ #undef WITH_LIBINTL diff --git a/setup.py b/setup.py index 3310654945..f43e395e42 100644 --- a/setup.py +++ b/setup.py @@ -771,7 +771,6 @@ class PyBuildExt(build_ext): libraries=['m']) ) # readline - do_readline = self.compiler.find_library_file(lib_dirs, 'readline') readline_termcap_library = "" curses_library = "" # Cannot use os.popen here in py3k. @@ -779,7 +778,13 @@ class PyBuildExt(build_ext): if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) # Determine if readline is already linked against curses or tinfo. - if do_readline: + if sysconfig.get_config_var('HAVE_LIBREADLINE'): + if sysconfig.get_config_var('WITH_EDITLINE'): + readline_lib = 'edit' + else: + readline_lib = 'readline' + do_readline = self.compiler.find_library_file(lib_dirs, + readline_lib) if cross_compiling: ret = os.system("%s -d %s | grep '(NEEDED)' > %s" \ % (sysconfig.get_config_var('READELF'), @@ -802,6 +807,8 @@ class PyBuildExt(build_ext): break if os.path.exists(tmpfile): os.unlink(tmpfile) + else: + do_readline = False # Issue 7384: If readline is already linked against curses, # use the same library for the readline and curses modules. if 'curses' in readline_termcap_library: @@ -837,7 +844,7 @@ class PyBuildExt(build_ext): else: readline_extra_link_args = () - readline_libs = ['readline'] + readline_libs = ['readline_lib'] if readline_termcap_library: pass # Issue 7384: Already linked against curses or tinfo. elif curses_library: -- 2.17.2 (Apple Git-113)