for review: add readline support to mdb

Fergus Henderson fjh at cs.mu.OZ.AU
Mon Mar 22 08:01:14 AEDT 1999


Estimated hours taken: 10

Add GNU readline support to the debugger.

Because GNU readline is licensed under the GPL, not the LGPL,
I was careful to ensure that (1) the readline library is
only linked into your application if it is compiled with
debugging enabled and (2) even in the latter case, the readline
support is disable-able.

Note that the readline headers and libraries get installed in the
standard places, i.e. the headers get installed in $prefix/include
rather than $prefix/lib/mercury/inc, and the readline libraries
get installed in $prefix/lib rather than $prefix/lib/mercury/lib/$fullarch.
We treat the readline library differently than the boehm_gc libgc.a
in this respect, because for libgc.a we use a non-standard version
modified specifically for Mercury (e.g. it is not compiled with
-DALL_INTERIOR_POINTERS), and so we must put it in a non-standard
location, whereas we can use a completely unmodified version of
readline, and so we can safely install it in the standard places.

bindist/bindist.configure.in:
configure.in:
aclocal.m4:
	Add check for libraries needed by readline,
	in particular -l{termcap,curses,ncurses}.
	If they're not found, define MR_NO_USE_READLINE.

Mmakefile:
bindist/Mmakefile:
	Add dependency on new file aclocal.m4.

Mmakefile:
	Add rules to build and install the readline subdirectory.

readline/Mmakefile:
	New file, for building and installing readline.
	This Mmakefile basically just invokes `make' with the appropriate
	arguments -- the Makefile does all the real work.

scripts/mgnuc.in:
	Add the readline header directory to the #include path.

scripts/ml.in:
	If tracing is enabled, then (by default) link in readline
	(and hence also termcap/curses/ncurses).
	Add a new option `--no-readline' to disable this.

trace/mercury_trace_internal.c:
	Delete the FILE * parameter from the MR_getline() function,
	because there are actually two files involved (MR_mdb_in and
	MR_mdb_out), and they are always the same for all calls to this
	function.
	Also change this function so that it calls MR_trace_readline() rather
	than printing the prompt and then calling MR_trace_getline_raw().
	Delete the MR_trace_getline_raw() function -- this has been renamed
	as MR_trace_readline_raw() and moved to mercury_trace_readline.c.

trace/mercury_trace_readline.h:
trace/mercury_trace_readline.c:
	New module containing a new function MR_trace_readline() that prints
	a prompt and reads a line in by calling the readline library.
	I put all this new code inside `#ifndef MR_NO_USE_READLINE' so that
	the use of readline can be disabled.  If that symbol is defined,
	it reverts to the old implementation using MR_trace_readline_raw()
	(formerly called MR_trace_getline_raw()).

runtime/mercury_conf.h.in:
	Define the new configuration parameter `MR_NO_USE_READLINE'.

trace/Mmakefile:
	Add the new files mercury_trace_readline.[ch].
	Ensure that this new module is compiled with warnings disabled,
	to avoid spurious warnings resulting from the readline header files.

Index: Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/mercury/Mmakefile,v
retrieving revision 1.34
diff -u -r1.34 Mmakefile
--- Mmakefile	1999/03/13 01:34:21	1.34
+++ Mmakefile	1999/03/21 20:00:27
@@ -12,6 +12,13 @@
 include Mmake.common
 
 #-----------------------------------------------------------------------------#
+#
+# The following list should list the directories in such a way that no
+# directory in the list depends on any directory following it in the list.
+# It's important that there should not be any cyclic dependencies between
+# different directories, because that would make it building things in the
+# right order much more complicated.
+#
 
 SUBDIRS = \
 		scripts \
@@ -19,8 +26,9 @@
 		boehm_gc \
 		runtime \
 		library \
-		trace \
+		readline \
 		browser \
+		trace \
 		compiler \
 		doc \
 		profiler
@@ -131,12 +139,16 @@
 library: dep_library scripts util boehm_gc runtime
 	cd library && $(SUBDIR_MMAKE)
 
+.PHONY: readline
+readline:
+	cd readline && $(SUBDIR_MMAKE)
+
 .PHONY: browser
 browser: dep_browser scripts util boehm_gc runtime library
 	cd browser && $(SUBDIR_MMAKE)
 
-.PHONY: runtime
-trace: scripts boehm_gc runtime library browser
+.PHONY: trace
+trace: scripts boehm_gc runtime library readline browser
 	cd trace && $(SUBDIR_MMAKE)
 
 .PHONY: compiler
@@ -174,7 +186,7 @@
 
 #-----------------------------------------------------------------------------#
 
-configure: configure.in
+configure: configure.in aclocal.m4
 	autoconf
 
 config.status: configure VERSION
@@ -285,7 +297,7 @@
 .PHONY: install_main
 install_main: all $(PREINSTALL_HACK) \
 		install_scripts install_util install_runtime install_boehm_gc \
-  		install_library install_browser install_trace \
+  		install_library install_readline install_browser install_trace \
 		install_compiler install_profiler install_doc \
 		$(POSTINSTALL_HACK)
  
@@ -301,10 +313,6 @@
 install_runtime: runtime
 	cd runtime && $(SUBDIR_MMAKE) install
 
-.PHONY: install_trace
-install_trace: trace
-	cd trace && $(SUBDIR_MMAKE) install
-
 .PHONY: install_boehm_gc
 install_boehm_gc: boehm_gc
 	case "$$grade" in \
@@ -321,9 +329,17 @@
 install_library: dep_library library
 	cd library && $(SUBDIR_MMAKE) install
 
+.PHONY: install_readline
+install_readline: readline
+	cd readline && $(SUBDIR_MMAKE) install
+
 .PHONY: install_browser
 install_browser: dep_browser browser
 	cd browser && $(SUBDIR_MMAKE) install
+
+.PHONY: install_trace
+install_trace: trace
+	cd trace && $(SUBDIR_MMAKE) install
 
 .PHONY: install_compiler
 install_compiler: dep_compiler compiler
Index: aclocal.m4
===================================================================
RCS file: aclocal.m4
diff -N aclocal.m4
--- /dev/null	Wed May 28 10:49:58 1997
+++ aclocal.m4	Mon Mar 22 07:19:51 1999
@@ -0,0 +1,30 @@
+dnl----------------------------------------------------------------------------
+dnl
+dnl Mercury specific tests
+dnl
+dnl We ought to move most of code in configure.in and
+dnl bindist/bindist.configure.in into this file...
+dnl
+dnl----------------------------------------------------------------------------
+dnl
+dnl Check which library has the termcap functions.
+dnl
+AC_DEFUN(MERCURY_CHECK_READLINE_LIBS,
+[
+MERCURY_MSG('looking for termcap or curses (needed by readline)...')
+[AC_CHECK_LIB(termcap, tgetent, mercury_cv_termcap_lib=-ltermcap,
+ [AC_CHECK_LIB(curses,  tgetent, mercury_cv_termcap_lib=-lcurses,
+  [AC_CHECK_LIB(ncurses, tgetent, mercury_cv_termcap_lib=-lncurses,
+   mercury_cv_termcap_lib="none")])])]
+if test $mercury_cv_termcap_lib = "none"; then
+	TERMCAP_LIBRARY=
+	READLINE_LIBRARIES=""
+	AC_DEFINE(MR_NO_USE_READLINE)
+else
+	TERMCAP_LIBRARY="$mercury_cv_termcap_lib"
+	READLINE_LIBRARIES="-lreadline $TERMCAP_LIBRARY"
+fi
+AC_SUBST(TERMCAP_LIBRARY)
+AC_SUBST(READLINE_LIBRARIES)
+])
+dnl----------------------------------------------------------------------------
Index: configure.in
===================================================================
RCS file: /home/staff/zs/imp/mercury/configure.in,v
retrieving revision 1.153
diff -u -r1.153 configure.in
--- configure.in	1999/03/18 00:14:00	1.153
+++ configure.in	1999/03/21 18:55:44
@@ -39,6 +39,8 @@
 	exit
 fi
 #-----------------------------------------------------------------------------#
+AC_CONFIG_SUBDIRS(readline)
+#-----------------------------------------------------------------------------#
 AC_CONFIG_HEADER(runtime/mercury_conf.h)
 AC_PREFIX_DEFAULT(/usr/local/mercury-`. ./VERSION; echo $VERSION`)
 AC_CANONICAL_HOST
@@ -1992,7 +1994,8 @@
 # restore the previous value of LIBS
 #
 LIBS="$save_LIBS"
-
+#-----------------------------------------------------------------------------#
+MERCURY_CHECK_READLINE_LIBS
 #-----------------------------------------------------------------------------#
 AC_OUTPUT(Mmake.common scripts/Mmake.vars scripts/mmc scripts/mprof
 scripts/mercury_update_interface scripts/mgnuc scripts/ml
Index: bindist/Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/mercury/bindist/Mmakefile,v
retrieving revision 1.18
diff -u -r1.18 Mmakefile
--- Mmakefile	1999/03/16 06:11:35	1.18
+++ Mmakefile	1999/03/21 20:00:08
@@ -109,8 +109,8 @@
 	gzip ../$(MERCURY_VERSION).tar
 	rm -rf $(MERCURY_VERSION)
 
-bindist.configure: bindist.configure.in
-	autoconf bindist.configure.in > bindist.configure
+bindist.configure: bindist.configure.in ../aclocal.m4
+	autoconf -l.. bindist.configure.in > bindist.configure
 
 bindist.build_vars: bindist.build_vars.in
 	CONFIG_FILES=bindist.build_vars CONFIG_HEADERS= \
Index: readline/Mmakefile
===================================================================
RCS file: Mmakefile
diff -N Mmakefile
--- /dev/null	Wed May 28 10:49:58 1997
+++ Mmakefile	Mon Mar 22 02:53:30 1999
@@ -0,0 +1,55 @@
+#-----------------------------------------------------------------------------#
+# Copyright (C) 1995-1999 University of Melbourne. 
+# This file may only be copied under the terms of the GNU General
+# Public Licence - see the file COPYING in the Mercury distribution.
+#-----------------------------------------------------------------------------#
+
+# Mmakefile - Mmakefile for installing GNU Readline.
+
+MAIN_TARGET=libreadline
+
+MERCURY_DIR=..
+include $(MERCURY_DIR)/Mmake.common
+
+#-----------------------------------------------------------------------------#
+
+.PHONY: libreadline
+libreadline: libreadline.a libreadline.so
+
+#	We need to export MAKEFLAGS="" to avoid passing the `-r' (suppress
+#	builtin rules) supplied by Mmake to the boehm_gc Makefile, which
+#	needs the builtin rules. 
+#	We don't use `unset', since the Ultrix /bin/sh doesn't have `unset'.
+
+MMAKEFLAGS=
+
+libreadline.a: force
+	MAKEFLAGS=""; export MAKEFLAGS; $(MAKE) $(MMAKEFLAGS) all
+
+.PHONY: libreadline.so
+libreadline.so: force
+	# Try building the shared library.
+	# This is not guaranteed to work on all platforms,
+	# so if this step fails, we just ignore it.
+	-MAKEFLAGS=""; export MAKEFLAGS; $(MAKE) $(MMAKEFLAGS) shared
+
+.PHONY: install
+install:
+	MAKEFLAGS=""; export MAKEFLAGS; $(MAKE) $(MMAKEFLAGS) install
+	# Try installing the shared library.
+	# This is not guaranteed to work on all platforms,
+	# so if this step fails, we just ignore it.
+	-MAKEFLAGS=""; export MAKEFLAGS; $(MAKE) $(MMAKEFLAGS) install-shared
+
+.PHONY: clean
+clean:
+	MAKEFLAGS=""; export MAKEFLAGS; $(MAKE) $(MMAKEFLAGS) clean
+
+.PHONY: realclean
+realclean:
+	MAKEFLAGS=""; export MAKEFLAGS; $(MAKE) $(MMAKEFLAGS) realclean
+
+.PHONY: force
+force:
+
+#-----------------------------------------------------------------------------#
Index: runtime/mercury_conf.h.in
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_conf.h.in,v
retrieving revision 1.11
diff -u -r1.11 mercury_conf.h.in
--- mercury_conf.h.in	1999/03/11 19:18:08	1.11
+++ mercury_conf.h.in	1999/03/21 19:08:40
@@ -260,6 +260,15 @@
 */
 #undef  MR_USE_EXTERNAL_DEBUGGER
 
+/*
+** MR_NO_USE_READLINE
+**	Set this if you want to prevent the debugger from using the GNU
+**	readline library for the command-line prompt.
+**	The autoconfiguration script sets this if it can't find a termcap
+**	library.
+*/
+#undef  MR_NO_USE_READLINE
+
 /*---------------------------------------------------------------------------*/
 
 #include "mercury_conf_param.h"
Index: scripts/mgnuc.in
===================================================================
RCS file: /home/staff/zs/imp/mercury/scripts/mgnuc.in,v
retrieving revision 1.59
diff -u -r1.59 mgnuc.in
--- mgnuc.in	1999/03/12 23:39:43	1.59
+++ mgnuc.in	1999/03/18 10:50:39
@@ -57,8 +57,11 @@
 
 FULLARCH=@FULLARCH@
 NONSHARED_LIB_DIR=${MERCURY_NONSHARED_LIB_DIR=@NONSHARED_LIB_DIR@}
-C_INCL_DIR=${MERCURY_C_INCL_DIR=@LIBDIR@/inc}
-ALL_C_INCL_DIRS=${MERCURY_ALL_C_INCL_DIRS=-I$C_INCL_DIR}
+#we need ${prefix} for @includedir@
+prefix=@prefix@
+RL_C_INCL_DIR=${READLINE_C_INCL_DIR=@includedir@}
+MER_C_INCL_DIR=${MERCURY_C_INCL_DIR=@LIBDIR@/inc}
+ALL_C_INCL_DIRS=${MERCURY_ALL_C_INCL_DIRS=-I$MER_C_INCL_DIR -I$RL_C_INCL_DIR}
 DEFAULT_GRADE=${MERCURY_DEFAULT_GRADE=@DEFAULT_GRADE@}
 CC=${MERCURY_C_COMPILER="@CC@"}
 CFLAGS_FOR_REGS="@CFLAGS_FOR_REGS@"
Index: scripts/ml.in
===================================================================
RCS file: /home/staff/zs/imp/mercury/scripts/ml.in,v
retrieving revision 1.53
diff -u -r1.53 ml.in
--- ml.in	1999/03/18 00:15:14	1.53
+++ ml.in	1999/03/21 19:20:23
@@ -65,6 +65,8 @@
 		then you don't need to explicilty specify \`--trace'.
 		Note that \`--trace' is incompatible with \`--static'
 		on some platforms (e.g. sparc-sun-solaris2.6).
+	-r-, --no-readline
+		Don't link in the GPL'd GNU Readline Library.
 	-g, --c-debug, --no-strip
 		Do not strip C debugging information.
 
@@ -86,6 +88,9 @@
 		See the documentation in the \"Invocation\" section
 		of the Mercury User's Guide."
 
+# libdir is used for readline
+libdir=@libdir@
+
 FULLARCH=@FULLARCH@
 NONSHARED_LIB_DIR=${MERCURY_NONSHARED_LIB_DIR=@NONSHARED_LIB_DIR@}
 DEFAULT_LIBDIR=@LIBDIR@/lib
@@ -111,6 +116,9 @@
 # Likewise for -ldl (libdl.so), which is often needed for dlopen() etc.
 DL_LIBRARY="@DL_LIBRARY@"
 
+# Likewise for -lreadline -l{termcap,curses,ncurses}
+READLINE_LIBRARIES="@READLINE_LIBRARIES@"
+
 # If you change these, you will also need to change Mmake.common.in,
 # scripts/c2init.in, tools/bootcheck, tools/binary, tools/binary_step
 # and tools/linear.
@@ -121,6 +129,7 @@
 
 verbose=false
 trace=false
+readline=true
 case $FULLARCH in
 	*-win95|*-winnt|*-win32|*-cygwin32|*-cygwin)
 		# `gcc -s' is broken in gnu-win32
@@ -161,6 +170,12 @@
 	-t-|--no-trace)
 		trace=false
 		;;
+	-r|--readline)
+		readline=true
+		;;
+	-r-|--no-readline)
+		readline=false
+		;;
 	-g-|--no-c-debug|--strip)
 		strip=true
 		;;
@@ -365,13 +380,19 @@
 		;;
 esac
 
+case $readline in
+	true)	;;
+	false)	READLINE_LIBRARIES=
+		;;
+esac
+
 case $trace in
 	true)	TRACE_LIBS="-l$TRACE_LIB_NAME -l$BROWSER_LIB_NAME \
-			$SOCKET_LIBRARY $DL_LIB"
+			$SOCKET_LIBRARY $DL_LIBRARY $READLINE_LIBRARIES"
 		TRACE_STATIC_LIBS="\
 			$LIBDIR/$GRADE/$FULLARCH/lib$TRACE_LIB_NAME.a \
 			$LIBDIR/$GRADE/$FULLARCH/lib$BROWSER_LIB_NAME.a \
-			$SOCKET_LIBRARY $DL_LIB"
+			$SOCKET_LIBRARY $DL_LIBRARY $READLINE_LIBRARIES"
 		;;
 	false)	TRACE_LIBS=
 		TRACE_STATIC_LIBS=
@@ -415,6 +436,7 @@
 merc_libdir_opts="\
 	-L$LIBDIR/$GRADE/$FULLARCH
 	-L$LIBDIR/$FULLARCH
+	-L$libdir
 "
 LIBDIR_OPTS="$user_libdir_opts $merc_libdir_opts"
 
@@ -423,6 +445,7 @@
 		LIBS=${MERCURY_LIBS="$TRACE_LIBS -l$STD_LIB_NAME -l$RT_LIB_NAME $LIBGC $STDLIBS"}
 		merc_shlib_dirs="$merc_shlib_dirs $LIBDIR/$GRADE/$FULLARCH"
 		merc_shlib_dirs="$merc_shlib_dirs $LIBDIR/$FULLARCH"
+		merc_shlib_dirs="$merc_shlib_dirs $libdir"
 		;;
 	static)
 		LIBS=${MERCURY_LIBS="$TRACE_STATIC_LIBS
@@ -430,7 +453,7 @@
 			$LIBDIR/$GRADE/$FULLARCH/lib$RT_LIB_NAME.a \
 			$LIBGC_STATIC \
 			$STDLIBS"}
-		merc_shlib_dirs=""
+		merc_shlib_dirs="$libdir"
 		;;
 	none)	LIBS="$STDLIBS"
 		LIBDIR_OPTS="$user_libdir_opts"
Index: trace/Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/mercury/trace/Mmakefile,v
retrieving revision 1.6
diff -u -r1.6 Mmakefile
--- Mmakefile	1999/01/11 03:52:30	1.6
+++ Mmakefile	1999/03/21 17:55:50
@@ -16,13 +16,20 @@
 
 CFLAGS		= -I$(MERCURY_DIR)/browser -I$(MERCURY_DIR)/library \
 		  -I$(MERCURY_DIR)/runtime -I$(MERCURY_DIR)/boehm_gc \
-		  -g $(DLL_CFLAGS) $(EXTRA_CFLAGS)
+		  -g $(DLL_CFLAGS)
 MGNUC		= MERCURY_C_INCL_DIR=. $(SCRIPTS_DIR)/mgnuc
-MGNUCFLAGS	= --no-ansi $(EXTRA_MGNUCFLAGS) $(CFLAGS)
+MGNUCFLAGS	= --no-ansi
 MOD2C		= $(SCRIPTS_DIR)/mod2c
 
 #-----------------------------------------------------------------------------#
 
+# mercury_readline.c #includes the GNU readline headers, which
+# lack prototypes and `const', so we need to disable warnings
+# when compiling that file.
+MGNUCFLAGS-mercury_trace_readline = --no-check
+
+#-----------------------------------------------------------------------------#
+
 # keep this list in alphabetical order, please
 HDRS		=	\
 			mercury_trace.h			\
@@ -32,6 +39,7 @@
 			mercury_trace_external.h 	\
 			mercury_trace_help.h		\
 			mercury_trace_internal.h	\
+			mercury_trace_readline.h	\
 			mercury_trace_spy.h		\
 			mercury_trace_tables.h		\
 			mercury_trace_util.h
@@ -45,6 +53,7 @@
 			mercury_trace_external.c 	\
 			mercury_trace_help.c		\
 			mercury_trace_internal.c	\
+			mercury_trace_readline.c	\
 			mercury_trace_spy.c		\
 			mercury_trace_tables.c
 
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.33
diff -u -r1.33 mercury_trace_internal.c
--- mercury_trace_internal.c	1999/03/18 08:19:17	1.33
+++ mercury_trace_internal.c	1999/03/21 17:47:29
@@ -20,10 +20,13 @@
 #include "mercury_trace_spy.h"
 #include "mercury_trace_tables.h"
 #include "mercury_trace_util.h"
+#include "mercury_trace_readline.h"
 #include "mercury_layout_util.h"
 #include "mercury_array_macros.h"
 #include "mercury_getopt.h"
+
 #include "browse.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -36,9 +39,6 @@
 /* The initial size of arrays of words. */
 #define	MR_INIT_WORD_COUNT	20
 
-/* The initial size of arrays of characters. */
-#define	MR_INIT_BUF_LEN		80
-
 /* The initial number of lines in documentation entries. */
 #define	MR_INIT_DOC_CHARS	800
 
@@ -202,9 +202,8 @@
 			int *word_max, int *word_count);
 static	bool	MR_trace_source(const char *filename);
 static	void	MR_trace_source_from_open_file(FILE *fp);
-static	char	*MR_trace_getline(const char *prompt, FILE *fp);
+static	char	*MR_trace_getline(const char *prompt);
 static	char	*MR_trace_getline_queue(void);
-static	char	*MR_trace_getline_raw(FILE *fp);
 static	void	MR_insert_line_at_head(const char *line);
 static	void	MR_insert_line_at_tail(const char *line);
 
@@ -262,7 +261,7 @@
 	jumpaddr = NULL;
 
 	do {
-		line = MR_trace_getline("mdb> ", MR_mdb_in);
+		line = MR_trace_getline("mdb> ");
 		res = MR_trace_debug_cmd(line, cmd, event_info, &event_details,
 				&ancestor_level, &jumpaddr);
 	} while (res == KEEP_INTERACTING);
@@ -1302,9 +1301,8 @@
 			if (! confirmed) {
 				char	*line2;
 
-				line2 = MR_trace_getline(
-					"mdb: are you sure you want to quit? ",
-					MR_mdb_in);
+				line2 = MR_trace_getline("mdb: "
+					"are you sure you want to quit? ");
 				if (line2 == NULL) {
 					/* This means the user input EOF. */
 					confirmed = TRUE;
@@ -1929,7 +1927,7 @@
 	int	i;
 
 	next_char_slot = 0;
-	while ((text = MR_trace_getline("cat> ", MR_mdb_in)) != NULL) {
+	while ((text = MR_trace_getline("cat> ")) != NULL) {
 		if (streq(text, "end")) {
 			free(text);
 			break;
@@ -2180,7 +2178,7 @@
 {
 	char	*line;
 
-	while ((line = MR_trace_getline_raw(fp)) != NULL) {
+	while ((line = MR_trace_readline_raw(fp)) != NULL) {
 		MR_insert_line_at_tail(line);
 	}
 
@@ -2189,14 +2187,15 @@
 
 /*
 ** If there any lines waiting in the queue, return the first of these.
-** If not, print the prompt, read a line from the given file, and return it
-** in a malloc'd buffer holding the line (without the final newline).
+** If not, print the prompt to MR_mdb_out, read a line from MR_mdb_in,
+** and return it in a malloc'd buffer holding the line (without the final
+** newline).
 ** If EOF occurs on a nonempty line, treat the EOF as a newline; if EOF
 ** occurs on an empty line, return NULL.
 */
 
 static char *
-MR_trace_getline(const char *prompt, FILE *fp)
+MR_trace_getline(const char *prompt)
 {
 	char	*line;
 
@@ -2206,10 +2205,8 @@
 	}
 
 	MR_trace_internal_interacting = TRUE;
-	fprintf(MR_mdb_out, "%s", prompt);
-	fflush(MR_mdb_out);
 
-	return MR_trace_getline_raw(fp);
+	return MR_trace_readline(prompt, MR_mdb_in, MR_mdb_out);
 }
 
 /*
@@ -2237,40 +2234,6 @@
 	}
 }
 
-/*
-**	Read a line from a file, and return a pointer to a malloc'd buffer
-**	holding the line (without the final newline). If EOF occurs on a
-**	nonempty line, treat the EOF as a newline; if EOF occurs on an empty
-**	line, return NULL.
-*/
-
-static char *
-MR_trace_getline_raw(FILE *fp)
-{
-	char	*contents;
-	int	content_max;
-	int	c;
-	int	i;
-
-	contents = NULL;
-	content_max = 0;
-
-	i = 0;
-	while ((c = getc(fp)) != EOF && c != '\n') {
-		MR_ensure_big_enough(i, content, char, MR_INIT_BUF_LEN);
-		contents[i++] = c;
-	}
-
-	if (c == '\n' || i > 0) {
-		MR_ensure_big_enough(i, content, char, MR_INIT_BUF_LEN);
-		contents[i] = '\0';
-		return contents;
-	} else {
-		free(contents);
-		return NULL;
-	}
-}
-
 static void
 MR_insert_line_at_head(const char *contents)
 {
@@ -2320,7 +2283,7 @@
 	/* We try to leave one line for the prompt itself. */
 	if (MR_scroll_control && MR_scroll_next >= MR_scroll_limit - 1) {
 	try_again:
-		buf = MR_trace_getline("--more-- ", MR_mdb_in);
+		buf = MR_trace_getline("--more-- ");
 		if (buf != NULL) {
 			for (i = 0; buf[i] != '\0' && MR_isspace(buf[i]); i++)
 				;
Index: trace/mercury_trace_readline.c
===================================================================
RCS file: mercury_trace_readline.c
diff -N mercury_trace_readline.c
--- /dev/null	Wed May 28 10:49:58 1997
+++ mercury_trace_readline.c	Mon Mar 22 04:56:48 1999
@@ -0,0 +1,100 @@
+/*
+** Copyright (C) 1998-1999 The University of Melbourne.
+** This file may only be copied under the terms of the GNU Library General
+** Public License - see the file COPYING.LIB in the Mercury distribution.
+*/
+
+/*
+** A simple interface to read a line, normally done using GNU readline.
+**
+** This module is compiled with warnings disabled (mgnuc --no-check),
+** since the GNU readline headers don't use prototypes, const, etc.
+**
+** Main authors: fjh, zs.
+*/
+
+#include "mercury_imp.h"
+#include "mercury_trace_readline.h"
+#include "mercury_array_macros.h"
+#include "mercury_memory.h"
+#include "mercury_std.h"
+
+#ifndef MR_NO_USE_READLINE
+#include "readline/readline.h"
+#include "readline/history.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* The initial size of the array of characters used to hold the line. */
+#define	MR_INIT_BUF_LEN		80
+
+/*
+** Print the prompt to the `out' file, read a line from the `in' file,
+** and return it in a malloc'd buffer holding the line (without the final
+** newline).
+** If EOF occurs on a nonempty line, treat the EOF as a newline; if EOF
+** occurs on an empty line, return NULL.
+*/
+char *
+MR_trace_readline(const char *prompt, FILE *in, FILE *out)
+{
+	char	*line;
+
+#ifdef MR_NO_USE_READLINE
+
+	fprintf(out, "%s", prompt);
+	fflush(out);
+	line = MR_trace_getline_raw(in);
+
+#else /* use readline */
+
+	size_t	len;
+
+	rl_instream = in;
+	rl_outstream = out;
+
+	line = readline((char *) prompt);
+
+	if (line != NULL && line[0] != '\0') {
+		add_history(line);
+	}
+
+#endif
+
+	return line;
+}
+
+/*
+** Read a line from a file, and return a pointer to a malloc'd buffer
+** holding the line (without the final newline). If EOF occurs on a
+** nonempty line, treat the EOF as a newline; if EOF occurs on an empty
+** line, return NULL.
+*/
+char *
+MR_trace_readline_raw(FILE *fp)
+{
+	char	*contents;
+	int	content_max;
+	int	c;
+	int	i;
+
+	contents = NULL;
+	content_max = 0;
+
+	i = 0;
+	while ((c = getc(fp)) != EOF && c != '\n') {
+		MR_ensure_big_enough(i, content, char, MR_INIT_BUF_LEN);
+		contents[i++] = c;
+	}
+
+	if (c == '\n' || i > 0) {
+		MR_ensure_big_enough(i, content, char, MR_INIT_BUF_LEN);
+		contents[i] = '\0';
+		return contents;
+	} else {
+		free(contents);
+		return NULL;
+	}
+}
Index: trace/mercury_trace_readline.h
===================================================================
RCS file: mercury_trace_readline.h
diff -N mercury_trace_readline.h
--- /dev/null	Wed May 28 10:49:58 1997
+++ mercury_trace_readline.h	Mon Mar 22 04:36:02 1999
@@ -0,0 +1,30 @@
+/*
+** Copyright (C) 1998-1999 The University of Melbourne.
+** This file may only be copied under the terms of the GNU Library General
+** Public License - see the file COPYING.LIB in the Mercury distribution.
+*/
+
+/*
+** mercury_trace_readline.h: simple interface functions to read a line.
+**
+** Main authors: fjh, zs.
+*/
+
+#include <stdio.h>	/* for FILE */
+
+/*
+** Print the prompt to the `out' file, read a line from the `in' file,
+** possibly using GNU readline for command-line editing, and return it
+** in a malloc'd buffer holding the line (without the final newline).
+** If EOF occurs on a nonempty line, treat the EOF as a newline; if EOF
+** occurs on an empty line, return NULL.
+*/
+char *	MR_trace_readline(const char *prompt, FILE *in, FILE *out);
+
+/*
+** Read a line from a file, and return a pointer to a malloc'd buffer
+** holding the line (without the final newline). If EOF occurs on a
+** nonempty line, treat the EOF as a newline; if EOF occurs on an empty
+** line, return NULL.  Don't use GNU readline.
+*/
+char *	MR_trace_readline_raw(FILE *in);
-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3        |     -- the last words of T. S. Garp.



More information about the developers mailing list