diff -r 2df7c958974e Modules/readline.c
--- a/Modules/readline.c Sat May 23 18:08:55 2015 -0700
+++ b/Modules/readline.c Sun May 24 09:16:23 2015 +0000
@@ -27,10 +27,14 @@
# define RESTORE_LOCALE(sl)
#endif
+#ifdef HAVE_EDITLINE_READLINE_H
+# 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
#ifdef HAVE_RL_COMPLETION_MATCHES
#define completion_matches(x, y) \
@@ -40,32 +44,25 @@
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__
+#ifdef HAVE_EDITLINE
/*
* 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,
- * hence we use a runtime check to detect if we're using libedit
- *
* Currently there is one known API incompatibility:
* - '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 /* HAVE_EDITLINE */
#ifdef HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK
static void
@@ -642,15 +639,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 */
@@ -663,27 +652,27 @@
if (!PyArg_ParseTuple(args, "i:index", &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();
+#ifdef HAVE_EDITLINE
+ /* Older versions of libedit's readline emulation
+ * use 0-based indexes, while readline and newer
+ * versions of libedit use 1-based indexes.
+ */
+ idx = idx - 1 + libedit_history_start;
- idx = idx - 1 + libedit_history_start;
+#ifdef __APPLE__
+ /*
+ * Apple's readline emulation crashes when
+ * the index is out of range, therefore
+ * test for that and fail gracefully.
+ */
+ int length = _py_get_history_length();
- /*
- * 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;
- }
+ if (idx < (0 + libedit_history_start)
+ || idx >= (length + libedit_history_start)) {
+ Py_RETURN_NONE;
}
-#endif /* __APPLE__ */
+#endif
+#endif /* HAVE_EDITLINE */
if ((hist_ent = history_get(idx)))
return PyUnicode_FromString(hist_ent->line);
else {
@@ -1018,12 +1007,11 @@
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();
+ rl_initialize();
/* Detect if libedit's readline emulation uses 0-based
* indexing or 1-based indexing.
@@ -1035,7 +1023,7 @@
libedit_history_start = 1;
}
clear_history();
-#endif /* __APPLE__ */
+#endif /* HAVE_EDITLINE */
using_history();
@@ -1080,12 +1068,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)
}
@@ -1249,15 +1236,24 @@
if (n > 0) {
const char *line;
int length = _py_get_history_length();
- if (length > 0)
-#ifdef __APPLE__
- if (using_libedit_emulation) {
- /* handle older 0-based or newer 1-based indexing */
- line = (const char *)history_get(length + libedit_history_start - 1)->line;
- } else
-#endif /* __APPLE__ */
- line = (const char *)history_get(length)->line;
- else
+ if (length > 0) {
+ HIST_ENTRY *entry;
+#ifdef HAVE_EDITLINE
+ /* handle older 0-based or newer 1-based indexing */
+ entry = history_get(length + libedit_history_start - 1);
+#else
+ entry = 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 doesn't really have one.
+ */
+ if (entry == NULL)
+ line = "";
+ else
+ line = (const char *)entry->line;
+ } else
line = "";
if (strcmp(p, line))
add_history(p);
@@ -1279,13 +1275,13 @@
/* 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
static struct PyModuleDef readlinemodule = {
PyModuleDef_HEAD_INIT,
@@ -1306,16 +1302,6 @@
PyObject *m;
readlinestate *mod_state;
-#ifdef __APPLE__
- 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__ */
-
m = PyModule_Create(&readlinemodule);
if (m == NULL)
diff -r 2df7c958974e configure.ac
--- a/configure.ac Sat May 23 18:08:55 2015 -0700
+++ b/configure.ac Sun May 24 09:16:23 2015 +0000
@@ -1289,6 +1289,8 @@
UNIVERSAL_ARCH_FLAGS=
AC_SUBST(UNIVERSAL_ARCH_FLAGS)
+DEFAULT_LIBREADLINE=readline
+
# tweak BASECFLAGS based on compiler and platform
case $GCC in
yes)
@@ -1448,6 +1450,7 @@
;;
esac
AC_MSG_RESULT($CC)
+ DEFAULT_LIBREADLINE=editline
fi
if test "${enable_universalsdk}"
@@ -4371,93 +4374,157 @@
[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 "" tinfo 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
+ AC_CHECK_HEADERS(editline/readline.h)
+ 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 "" 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_PROGRAM([
+#include /* Must be first for Gnu Readline */
+#ifdef HAVE_EDITLINE_READLINE_H
+# include
+#else
+# include
+#endif
+],[
+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,
+
+ fi
+
+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 /* Must be first for Gnu Readline */
+#ifdef HAVE_EDITLINE_READLINE_H
+# include
+#else
+# include
+#endif
+],[
+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 /* Must be first for Gnu Readline */
+#ifdef HAVE_EDITLINE_READLINE_H
+# include
+#else
+# include
+#endif
+],[
+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.]), )
-fi
-
-AC_CHECK_LIB(readline, append_history,
+ [Define if you have readline 4.2]),,$READLINE_LIBS)
+
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
+#include /* Must be first for Gnu Readline */
+#ifdef HAVE_EDITLINE_READLINE_H
+# include
+#else
+# include
+#endif
+],[
+int i = 0;
+rl_catch_signals = i;
+])],[
+ AC_DEFINE(HAVE_RL_CATCH_SIGNAL,1,
+ [Define if you can turn off readline's signal handling.])
+])
+
+ 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 -r 2df7c958974e setup.py
--- a/setup.py Sat May 23 18:08:55 2015 -0700
+++ b/setup.py Sun May 24 09:16:23 2015 +0000
@@ -678,7 +678,12 @@
exts.append( Extension('audioop', ['audioop.c']) )
# readline
- do_readline = self.compiler.find_library_file(lib_dirs, 'readline')
+ if sysconfig.get_config_var('HAVE_LIBREADLINE'):
+ readline_lib = 'readline'
+ elif sysconfig.get_config_var('HAVE_EDITLINE'):
+ readline_lib = 'edit'
+ else:
+ readline_lib = None
readline_termcap_library = ""
curses_library = ""
# Cannot use os.popen here in py3k.
@@ -686,7 +691,9 @@
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 readline_lib:
+ 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'),
@@ -709,6 +716,8 @@
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:
@@ -744,7 +753,7 @@
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: