[m-rev.] for review: improve `mdb --window'
Simon Taylor
stayl at cs.mu.OZ.AU
Tue Jan 29 05:18:15 AEDT 2002
Estimated hours taken: 10
Improve the handling of the mdb's `--window' option.
`mdb --window' now creates a window for mdb, not the program.
The main advantage of this is that redirection of the program's
input and output now works. The new behaviour should also be
implementable using the Windows API. The old behaviour is still
available with `mdb --program-in-window'.
Unfortunately, the code to open a pseudo-terminal for mdb's I/O
isn't very portable. It works on everything we run nightly tests on,
but isn't likely to work on older systems or BSD systems.
NEWS:
Document the change.
scripts/mdb.in:
Handle the new behaviour of `--window'.
Add `--program-in-window'.
trace/mercury_trace_internal.c:
If `--window' was passed in MERCURY_OPTIONS, redirect
mdb's I/O to a window created using `xterm -S'.
Rename occurrences of `close' to avoid gcc warnings.
runtime/mercury_trace_base.h:
runtime/mercury_trace_base.c:
Kill the mdb window on exit.
runtime/mercury_wrapper.h:
runtime/mercury_wrapper.c:
Add a runtime options `--mdb-in-window' for use by the mdb script.
runtime/mercury_signal.h:
runtime/mercury_signal.c:
Add a version of MR_do_setup_signal which doesn't cause
system calls to be restarted after a signal is received.
This is needed to allow a read() from the mdb window
to timeout if the window failed to start.
configure.in:
runtime/mercury_conf.h.in:
runtime/RESERVED_MACRO_NAMES.
Check for functions open, close, dup, dup2, fdopen, setpgid,
fork, execlp, wait, kill, grantpt, unlockpt, pstname, tcgetattr,
tcsetattr and ioctl.
Check for type pid_t.
Check for header files <fcntl.h>, <termios.h>, <sys/ioctl.h>,
<sys/stropts.h>.
Check for /dev/ptmx, used to open pseudo-terminals.
Index: NEWS
===================================================================
RCS file: /home/mercury1/repository/mercury/NEWS,v
retrieving revision 1.239
diff -u -u -r1.239 NEWS
--- NEWS 25 Jan 2002 05:56:37 -0000 1.239
+++ NEWS 28 Jan 2002 09:01:18 -0000
@@ -186,6 +186,11 @@
requires X11 and a version of `vim' with the `clientserver' feature
enabled.
+* The `--window' mdb option now creates a window for mdb, not
+ the program. The main advantage of the new behaviour is that
+ redirection of the program's input and output works. The old
+ behaviour is still available with `mdb --program-in-window'.
+
* We've fixed a long-standing bug in the handling of module imports.
Previously, if `module1' imported `module2' which imported `module3' in
its interface section, then any types, insts, modes and typeclasses defined
Index: configure.in
===================================================================
RCS file: /home/mercury1/repository/mercury/configure.in,v
retrieving revision 1.291
diff -u -u -r1.291 configure.in
--- configure.in 25 Jan 2002 08:22:20 -0000 1.291
+++ configure.in 28 Jan 2002 15:50:55 -0000
@@ -443,10 +443,13 @@
*-cygwin*)
ac_cv_func_mprotect=no ;;
esac
-AC_HAVE_FUNCS(sysconf getpagesize memalign mprotect sigaction setitimer)
-AC_HAVE_FUNCS(strerror memmove dup fileno fdopen fstat stat isatty)
-AC_HAVE_FUNCS(snprintf vsnprintf _vsnprintf)
-AC_HAVE_FUNCS(gethostname getpid)
+AC_HAVE_FUNCS(sysconf getpagesize gethostname)
+AC_HAVE_FUNCS(mprotect memalign memmove)
+AC_HAVE_FUNCS(sigaction setitimer)
+AC_HAVE_FUNCS(snprintf vsnprintf _vsnprintf strerror)
+AC_HAVE_FUNCS(open close dup dup2 fdopen fileno fstat stat isatty)
+AC_HAVE_FUNCS(getpid setpgid fork execlp wait kill)
+AC_HAVE_FUNCS(grantpt unlockpt ptsname tcgetattr tcsetattr ioctl)
#-----------------------------------------------------------------------------#
AC_CHECK_HEADER(unistd.h, HAVE_UNISTD_H=1)
if test "$HAVE_UNISTD_H" = 1; then
@@ -508,6 +511,31 @@
AC_DEFINE(HAVE_SYS_STAT_H)
fi
#-----------------------------------------------------------------------------#
+AC_CHECK_HEADER(fcntl.h, HAVE_FCNTL_H=1)
+if test "$HAVE_FCNTL_H" = 1; then
+ AC_DEFINE(HAVE_FCNTL_H)
+fi
+#-----------------------------------------------------------------------------#
+AC_CHECK_HEADER(termios.h, HAVE_TERMIOS_H=1)
+if test "$HAVE_TERMIOS_H" = 1; then
+ AC_DEFINE(HAVE_TERMIOS_H)
+fi
+#-----------------------------------------------------------------------------#
+AC_CHECK_HEADER(sys/ioctl.h, HAVE_SYS_IOCTL_H=1)
+if test "$HAVE_SYS_IOCTL_H" = 1; then
+ AC_DEFINE(HAVE_SYS_IOCTL_H)
+fi
+#-----------------------------------------------------------------------------#
+AC_CHECK_HEADER(sys/stropts.h, HAVE_SYS_STROPTS_H=1)
+if test "$HAVE_SYS_STROPTS_H" = 1; then
+ AC_DEFINE(HAVE_SYS_STROPTS_H)
+fi
+#-----------------------------------------------------------------------------#
+AC_CHECK_FILE(/dev/ptmx, HAVE_DEV_PTMX=1)
+if test "$HAVE_DEV_PTMX" = 1; then
+ AC_DEFINE(HAVE_DEV_PTMX)
+fi
+#-----------------------------------------------------------------------------#
#
# check the basics of sigaction
#
@@ -1078,7 +1106,8 @@
fi
AC_SUBST(MR_INT_LEAST32_MAX)
AC_SUBST(MR_UINT_LEAST32_MAX)
-
+#-----------------------------------------------------------------------------#
+AC_TYPE_PID_T
#-----------------------------------------------------------------------------#
AC_MSG_CHECKING(for an integer type of at least 16 bits)
AC_CACHE_VAL(mercury_cv_int_least16_type,
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.286
diff -u -u -r1.286 user_guide.texi
--- doc/user_guide.texi 25 Jan 2002 05:56:40 -0000 1.286
+++ doc/user_guide.texi 26 Jan 2002 13:42:19 -0000
@@ -5905,6 +5905,9 @@
Redirect all three debugger I/O streams -- input, output, and error messages --
to the file or device specified by @var{filename}.
+ at c --mdb-in-window is for use only by the mdb script, so it's
+ at c not documented here.
+
@end table
@end table
Index: runtime/RESERVED_MACRO_NAMES
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/RESERVED_MACRO_NAMES,v
retrieving revision 1.6
diff -u -u -r1.6 RESERVED_MACRO_NAMES
--- runtime/RESERVED_MACRO_NAMES 11 Dec 2001 09:01:18 -0000 1.6
+++ runtime/RESERVED_MACRO_NAMES 28 Jan 2002 15:49:05 -0000
@@ -50,6 +50,7 @@
# but it ought to be defined in mercury_conf_param.h,
# or just deleted, since it is not used at all
# XXX TAG_BITS is defined in mercury_tags.h
+pid_t
BOXED_FLOAT
CONSERVATIVE_GC
LOW_TAG_BITS
@@ -72,23 +73,36 @@
USE_SINGLE_PREC_FLOAT
USE_TYPE_LAYOUT
HAVE_ASM_SIGCONTEXT
+HAVE_CLOSE
+HAVE_DEV_PTMX
HAVE_DLCLOSE
HAVE_DLERROR
HAVE_DLFCN_H
HAVE_DLOPEN
HAVE_DLSYM
+HAVE_DUP
+HAVE_DUP2
+HAVE_EXECLP
+HAVE_FCNTL_H
HAVE_FDOPEN
HAVE_FILENO
+HAVE_FORK
HAVE_FSTAT
HAVE_GETHOSTNAME
HAVE_GETPAGESIZE
+HAVE_GRANTPT
+HAVE_IOCTL
HAVE_ISATTY
+HAVE_KILL
HAVE_MEMALIGN
HAVE_MEMMOVE
HAVE_MPROTECT
HAVE_GETPID
+HAVE_OPEN
+HAVE_PTSNAME
HAVE_READLINE_HISTORY
HAVE_READLINE_READLINE
+HAVE_SETPGID
HAVE_SETITIMER
HAVE_SIGACTION
HAVE_SIGCONTEXT_STRUCT
@@ -96,23 +110,30 @@
HAVE_SIGCONTEXT_STRUCT_3ARG
HAVE_SIGINFO
HAVE_SIGINFO_T
+HAVE_SNPRINTF
HAVE_STAT
HAVE_STRERROR
HAVE_SYSCONF
+HAVE_SYS_IOCTL_H
HAVE_SYS_PARAM
HAVE_SYS_STAT_H
HAVE_SYS_SIGINFO
HAVE_SYS_SIGNAL
+HAVE_SYS_STROPTS_H
HAVE_SYS_TIME
HAVE_SYS_TIMES_H
HAVE_SYS_TYPES_H
HAVE_SYS_UCONTEXT
HAVE_SYS_WAIT
+HAVE_TCGETATTR
+HAVE_TCSETATTR
+HAVE_TERMIOS_H
HAVE_UCONTEXT
HAVE_UNISTD_H
-HAVE_SNPRINTF
+HAVE_UNLOCKPT
HAVE_VSNPRINTF
HAVE__VSNPRINTF
+HAVE_WAIT
#-----------------------------------------------------------------------------#
# These are defined by mercury.h
# Normally macros should start with capital letters,
Index: runtime/mercury_conf.h.in
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf.h.in,v
retrieving revision 1.40
diff -u -u -r1.40 mercury_conf.h.in
--- runtime/mercury_conf.h.in 27 Dec 2001 07:25:22 -0000 1.40
+++ runtime/mercury_conf.h.in 28 Jan 2002 15:48:59 -0000
@@ -121,6 +121,10 @@
** HAVE_SYS_TYPES_H we have <sys/types.h>
** HAVE_SYS_TIMES_H we have <sys/times.h>
** HAVE_DLFCN_H we have <dlfcn.h>
+** HAVE_FCNTL_H we have <fcnt.h>
+** HAVE_TERMIOS_H we have <termios.h>
+** HAVE_SYS_IOCTL_H we have <sys/ioctl.h>
+** HAVE_SYS_STROPTS_H we have <sys/stropts.h>
*/
#undef HAVE_SYS_SIGINFO
#undef HAVE_SYS_SIGNAL
@@ -135,6 +139,16 @@
#undef HAVE_SYS_TIMES_H
#undef HAVE_SYS_TYPES_H
#undef HAVE_DLFCN_H
+#undef HAVE_FCNTL_H
+#undef HAVE_TERMIOS_H
+#undef HAVE_SYS_IOCTL_H
+#undef HAVE_SYS_STROPTS_H
+
+/*
+** HAVE_DEV_PTMX is defined if /dev/ptmx (used to allocate
+** pseudo-terminals) exists.
+*/
+#undef HAVE_DEV_PTMX
/*
** MR_HAVE_POSIX_TIMES is defined if we have the POSIX
@@ -153,10 +167,20 @@
#undef MR_HAVE_INT_LEASTN_T
/*
+** pid_t is defined as `int' iff the system headers don't define it.
+*/
+#undef pid_t
+
+/*
** The following macros are defined iff the corresponding function or
** system call is available:
**
** HAVE_GETPID we have the getpid() function.
+** HAVE_SETPGID we have the setpgid() function.
+** HAVE_FORK we have the fork() function.
+** HAVE_EXECLP we have the execlp() function.
+** HAVE_WAIT we have the wait() function.
+** HAVE_KILL we have the kill() function.
** HAVE_GETHOSTNAME we have the gethostname() function.
** HAVE_SNPRINTF we have the snprintf() function.
** HAVE_VSNPRINTF we have the vsnprintf() function.
@@ -176,13 +200,28 @@
** HAVE_STAT we have the stat() function.
** HAVE_FSTAT we have the fstat() function.
** HAVE_FDOPEN we have the fdopen() function.
+** HAVE_OPEN we have the open() function.
+** HAVE_CLOSE we have the close() function.
+** HAVE_DUP we have the dup() function.
+** HAVE_DUP2 we have the dup2() function.
** HAVE_FILENO we have the fileno() function.
** Note that fileno() may be a macro
** rather than a function, so you should use
** #if defined(fileno) || defined(HAVE_FILENO)
** HAVE_ISATTY we have the isatty() function.
+** HAVE_GRANTPT we have the grantpt() function.
+** HAVE_UNLOCKPT we have the unlockpt() function.
+** HAVE_PTSNAME we have the ptsname() function.
+** HAVE_TCGETATTR we have the tcgetattr() function.
+** HAVE_TCSETATTR we have the tcsetattr() function.
+** HAVE_IOCTL we have the ioctl() function.
*/
#undef HAVE_GETPID
+#undef HAVE_SETPGID
+#undef HAVE_FORK
+#undef HAVE_EXECLP
+#undef HAVE_WAIT
+#undef HAVE_KILL
#undef HAVE_GETHOSTNAME
#undef HAVE_SNPRINTF
#undef HAVE_VSNPRINTF
@@ -202,8 +241,18 @@
#undef HAVE_STAT
#undef HAVE_FSTAT
#undef HAVE_FDOPEN
+#undef HAVE_OPEN
+#undef HAVE_CLOSE
+#undef HAVE_DUP
+#undef HAVE_DUP2
#undef HAVE_FILENO
#undef HAVE_ISATTY
+#undef HAVE_GRANTPT
+#undef HAVE_UNLOCKPT
+#undef HAVE_PTSNAME
+#undef HAVE_TCGETATTR
+#undef HAVE_TCSETATTR
+#undef HAVE_IOCTL
/*
** RETSIGTYPE: the return type of signal handlers.
Index: runtime/mercury_signal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_signal.c,v
retrieving revision 1.9
diff -u -u -r1.9 mercury_signal.c
--- runtime/mercury_signal.c 12 Sep 2000 19:51:07 -0000 1.9
+++ runtime/mercury_signal.c 28 Jan 2002 11:22:59 -0000
@@ -87,14 +87,33 @@
#define SA_SIGINFO 0
#endif
+static void MR_do_setup_signal(int sig, MR_Code *handler, bool need_info,
+ bool restart, const char *error_message);
+
void
MR_setup_signal(int sig, MR_Code *handler, bool need_info,
const char *error_message)
{
+ MR_do_setup_signal(sig, handler, need_info, TRUE, error_message);
+}
+
+void
+MR_setup_signal_no_restart(int sig, MR_Code *handler, bool need_info,
+ const char *error_message)
+{
+ MR_do_setup_signal(sig, handler, need_info, FALSE, error_message);
+}
+
+void
+MR_do_setup_signal(int sig, MR_Code *handler, bool need_info, bool restart,
+ const char *error_message)
+{
#if defined(HAVE_SIGACTION)
struct sigaction act;
+ act.sa_flags = (restart ? SA_RESTART : 0);
+
if (need_info) {
/*
** If we are using sigcontext struct, it means we have
@@ -102,13 +121,9 @@
** request signals, we should not ask for SA_SIGINFO, since our
** handler will not be of the right type.
*/
-#if defined(HAVE_SIGCONTEXT_STRUCT)
- act.sa_flags = SA_RESTART;
-#else /* not HAVE_SIGCONTEXT_STRUCT */
- act.sa_flags = SA_SIGINFO | SA_RESTART;
+#if !defined(HAVE_SIGCONTEXT_STRUCT)
+ act.sa_flags |= SA_SIGINFO;
#endif
- } else {
- act.sa_flags = SA_RESTART;
}
if (sigemptyset(&act.sa_mask) != 0) {
perror("Mercury runtime: cannot set clear signal mask");
Index: runtime/mercury_signal.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_signal.h,v
retrieving revision 1.5
diff -u -u -r1.5 mercury_signal.h
--- runtime/mercury_signal.h 3 Aug 2000 06:18:54 -0000 1.5
+++ runtime/mercury_signal.h 28 Jan 2002 11:04:59 -0000
@@ -30,5 +30,11 @@
extern void MR_setup_signal(int sig, MR_Code *handler, bool need_info,
const char * error_message);
+ /*
+ ** As above, but don't arrange for system calls to be
+ ** restarted if the signal is received.
+ */
+extern void MR_setup_signal_no_restart(int sig, MR_Code *handler,
+ bool need_info, const char * error_message);
#endif /* not MERCURY_SIGNAL_H */
Index: runtime/mercury_trace_base.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_base.c,v
retrieving revision 1.38
diff -u -u -r1.38 mercury_trace_base.c
--- runtime/mercury_trace_base.c 27 Dec 2001 07:08:11 -0000 1.38
+++ runtime/mercury_trace_base.c 28 Jan 2002 08:09:43 -0000
@@ -32,6 +32,10 @@
#include <unistd.h> /* for the write system call */
#endif
+#ifdef HAVE_SYS_WAIT
+ #include <sys/wait.h> /* for the wait system call */
+#endif
+
/*
** Do we want to use the debugger within this process, or do want to use
** the Opium-style trace analyzer debugger implemented by an external process.
@@ -52,6 +56,9 @@
bool MR_trace_enabled = FALSE;
+bool MR_have_mdb_window = FALSE;
+pid_t MR_mdb_window_pid = 0;
+
/*
** MR_trace_call_seqno counts distinct calls. The prologue of every
** procedure assigns the current value of this counter as the sequence number
@@ -210,6 +217,21 @@
MR_address_of_trace_final_external();
} else {
MR_tracing_not_enabled();
+ }
+ }
+#endif
+
+#if defined(HAVE_KILL) && defined(HAVE_WAIT) && defined(SIGTERM)
+ if (MR_have_mdb_window) {
+ int status;
+ status = kill(MR_mdb_window_pid, SIGTERM);
+ if (status != -1) {
+ do {
+ status = wait(NULL);
+ if (status == -1 && errno != EINTR) {
+ break;
+ }
+ } while (status != MR_mdb_window_pid);
}
}
#endif
Index: runtime/mercury_trace_base.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_base.h,v
retrieving revision 1.19
diff -u -u -r1.19 mercury_trace_base.h
--- runtime/mercury_trace_base.h 15 Jun 2001 04:46:23 -0000 1.19
+++ runtime/mercury_trace_base.h 27 Jan 2002 15:15:41 -0000
@@ -19,6 +19,9 @@
#include "mercury_stack_layout.h"
#include "mercury_std.h"
#include "mercury_tabling.h" /* for MR_TableNode */
+#ifdef HAVE_UNISTD_H
+ #include <unistd.h> /* for the write system call and pid_t */
+#endif
/*
** This enum should EXACTLY match the definition of the `trace_port_type'
@@ -93,6 +96,15 @@
extern void MR_trace_start(bool enabled);
extern void MR_trace_end(void);
extern void MR_trace_final(void);
+
+/*
+** MR_have_mdb_window and MR_mdb_window_pid are set by
+** mercury_trace_internal.c after the xterm window for
+** mdb has been spawned. The window process is killed by
+** MR_trace_final().
+*/
+extern bool MR_have_mdb_window;
+extern pid_t MR_mdb_window_pid;
/*
** The globals that define the interface between the tracing subsystem
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.95
diff -u -u -r1.95 mercury_wrapper.c
--- runtime/mercury_wrapper.c 13 Jan 2002 10:13:09 -0000 1.95
+++ runtime/mercury_wrapper.c 26 Jan 2002 16:11:38 -0000
@@ -89,6 +89,7 @@
const char *MR_mdb_in_filename = NULL;
const char *MR_mdb_out_filename = NULL;
const char *MR_mdb_err_filename = NULL;
+bool MR_mdb_in_window = FALSE;
/* other options */
@@ -731,7 +732,8 @@
MR_MDB_TTY,
MR_MDB_IN,
MR_MDB_OUT,
- MR_MDB_ERR
+ MR_MDB_ERR,
+ MR_MDB_IN_WINDOW
};
struct MR_option MR_long_opts[] = {
@@ -748,7 +750,8 @@
{ "mdb-tty", 1, 0, MR_MDB_TTY },
{ "mdb-in", 1, 0, MR_MDB_IN },
{ "mdb-out", 1, 0, MR_MDB_OUT },
- { "mdb-err", 1, 0, MR_MDB_ERR }
+ { "mdb-err", 1, 0, MR_MDB_ERR },
+ { "mdb-in-window", 0, 0, MR_MDB_IN_WINDOW }
};
static void
@@ -854,6 +857,11 @@
MR_mdb_in_filename = MR_copy_string(MR_optarg);
MR_mdb_out_filename = MR_copy_string(MR_optarg);
MR_mdb_err_filename = MR_copy_string(MR_optarg);
+ break;
+
+ case 'w':
+ case MR_MDB_IN_WINDOW:
+ MR_mdb_in_window = TRUE;
break;
case 'a':
Index: runtime/mercury_wrapper.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.h,v
retrieving revision 1.45
diff -u -u -r1.45 mercury_wrapper.h
--- runtime/mercury_wrapper.h 13 Jan 2002 10:13:10 -0000 1.45
+++ runtime/mercury_wrapper.h 26 Jan 2002 12:38:58 -0000
@@ -209,6 +209,9 @@
extern const char *MR_mdb_out_filename;
extern const char *MR_mdb_err_filename;
+/* should mdb be started in a window */
+extern bool MR_mdb_in_window;
+
/* size of the primary cache */
extern size_t MR_pcache_size;
Index: scripts/mdb.in
===================================================================
RCS file: /home/mercury1/repository/mercury/scripts/mdb.in,v
retrieving revision 1.3
diff -u -u -r1.3 mdb.in
--- scripts/mdb.in 21 Dec 1998 04:39:44 -0000 1.3
+++ scripts/mdb.in 27 Jan 2002 07:30:15 -0000
@@ -32,22 +32,32 @@
specified by <file-name>. The I/O for the program
being debugged will not be redirected.
- -w, --window
+ -w, --window, --mdb-in-window
+ Run mdb in a new window, with mdb's I/O going to that
+ window, but with the program's I/O going to the current
+ terminal. Note that this will not work on all systems.
+
+ --program-in-window
Run the program in a new window, with the program's I/O
going to that window, but with mdb's I/O going to the
- current terminal.
+ current terminal. Note that input and output redirection
+ will not work with the \`--program-in-window' option.
+ \`--program-in-window' will work on most UNIX systems
+ running the X Window System, even those for which
+ \`--mdb-in-window' is not supported.
-c <window-command>, --window-command <window-command>
- Specify the command used by the \`--window' option for
- executing a command in a new window. The default such
- command is \`xterm -e'.
+ Specify the command used by the \`--program-in-window'
+ option for executing a command in a new window.
+ The default such command is \`xterm -e'.
Environment variables:
MERCURY_OPTIONS, MERCURY_DEBUGGER_INIT.
"
tty=
-window=false
+# Possible values "none", "program", "mdb".
+window=none
window_cmd="xterm -e"
#-----------------------------------------------------------------------------#
@@ -71,14 +81,20 @@
-t*)
tty="` expr $1 : '-t\(.*\)' `"
shift ;;
- -w|--window)
- window=true
+ -w|--window|--mdb-in-window)
+ window=mdb
+ shift ;;
+ -w-|--no-window|--no-mdb-in-window)
+ window=none
+ shift ;;
+ --program-in-window)
+ window=program
shift ;;
- -w-|--no-window)
- window=false
+ --no-program-in-window)
+ window=none
shift ;;
-c|--window-command)
- window_cmd="$2";
+ window_cmd="$2"
shift; shift ;;
--)
shift; break ;;
@@ -96,8 +112,12 @@
#
invoke_cmd=
-case "$window" in true)
+case "$window" in program)
invoke_cmd="$window_cmd"
+esac
+
+case "$window" in
+ program|mdb)
#
# If windowing is enabled, check that DISPLAY is set, and if not,
# issue a warning message. This is needed because the default error
@@ -113,10 +133,15 @@
# Figure out if/how we should redirect the mdb I/O streams
#
+mdb_in_window_opt=""
+
case "$tty" in
"")
case "$window" in
- true)
+ mdb)
+ mdb_in_window_opt="--mdb-in-window"
+ ;;
+ program)
#
# On Linux, we can use special files in /proc
# that refer to the file descriptors for a
@@ -144,7 +169,7 @@
redirect_opts="--mdb-tty $tty"
fi
;;
- false)
+ none)
redirect_opts=""
;;
esac ;;
@@ -161,7 +186,7 @@
#
enable_mdb_opt="-Di"
-MERCURY_OPTIONS="$MERCURY_OPTIONS $redirect_opts $enable_mdb_opt"
+MERCURY_OPTIONS="$MERCURY_OPTIONS $redirect_opts $enable_mdb_opt $mdb_in_window_opt"
export MERCURY_OPTIONS
MERCURY_DEBUGGER_INIT=${MERCURY_DEBUGGER_INIT- at DEFAULT_MERCURY_DEBUGGER_INIT_DIR@/mdbrc}
export MERCURY_DEBUGGER_INIT
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.111
diff -u -u -r1.111 mercury_trace_internal.c
--- trace/mercury_trace_internal.c 12 Jan 2002 09:08:14 -0000 1.111
+++ trace/mercury_trace_internal.c 28 Jan 2002 18:12:46 -0000
@@ -14,6 +14,7 @@
#include "mercury_layout_util.h"
#include "mercury_array_macros.h"
#include "mercury_getopt.h"
+#include "mercury_signal.h"
#include "mercury_trace.h"
#include "mercury_trace_internal.h"
@@ -37,6 +38,35 @@
#include <string.h>
#include <ctype.h>
#include <errno.h>
+#include <signal.h>
+
+#ifdef HAVE_UNISTD_H
+ #include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+ #include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_WAIT
+ #include <sys/wait.h>
+#endif
+
+#ifdef HAVE_TERMIOS_H
+ #include <termios.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+ #include <fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+ #include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_STROPTS_H
+ #include <sys/stropts.h>
+#endif
/* The initial size of arrays of words. */
#define MR_INIT_WORD_COUNT 20
@@ -167,6 +197,7 @@
} MR_MultiMatch;
static void MR_trace_internal_ensure_init(void);
+static bool MR_trace_internal_create_mdb_window(void);
static void MR_trace_internal_init_from_env(void);
static void MR_trace_internal_init_from_local(void);
static void MR_trace_internal_init_from_home_dir(void);
@@ -217,7 +248,7 @@
static bool MR_trace_options_view(const char **window_cmd,
const char **server_cmd, const char **server_name,
int *timeout, bool *force, bool *verbose, bool *split,
- bool *close, char ***words, int *word_count,
+ bool *close_window, char ***words, int *word_count,
const char *cat, const char*item);
static void MR_trace_usage(const char *cat, const char *item);
static void MR_trace_do_noop(void);
@@ -362,9 +393,23 @@
char *env;
int n;
- MR_mdb_in = MR_try_fopen(MR_mdb_in_filename, "r", stdin);
- MR_mdb_out = MR_try_fopen(MR_mdb_out_filename, "w", stdout);
- MR_mdb_err = MR_try_fopen(MR_mdb_err_filename, "w", stderr);
+ if (MR_mdb_in_window) {
+ MR_mdb_in_window =
+ MR_trace_internal_create_mdb_window();
+ if (! MR_mdb_in_window) {
+ fprintf(stderr,
+ "Try `mdb --program-in-window' instead.\n");
+ }
+ }
+
+ if (! MR_mdb_in_window) {
+ MR_mdb_in = MR_try_fopen(MR_mdb_in_filename,
+ "r", stdin);
+ MR_mdb_out = MR_try_fopen(MR_mdb_out_filename,
+ "w", stdout);
+ MR_mdb_err = MR_try_fopen(MR_mdb_err_filename,
+ "w", stderr);
+ }
/* Ensure that MR_mdb_err is not buffered */
setvbuf(MR_mdb_err, NULL, _IONBF, 0);
@@ -391,6 +436,242 @@
}
}
+static bool MR_got_alarm = FALSE;
+
+static void
+MR_trace_internal_alarm_handler(void)
+{
+ MR_got_alarm = TRUE;
+}
+
+static bool
+MR_trace_internal_create_mdb_window(void)
+{
+ /*
+ ** XXX Add support for MS Windows.
+ */
+#if defined(HAVE_OPEN) && defined(HAVE_FDOPEN) && defined(HAVE_CLOSE) && \
+ defined(HAVE_DUP) && defined(HAVE_DUP2) && defined(HAVE_FORK) && \
+ defined(HAVE_EXECLP)
+
+ int master_fd = -1;
+ int slave_fd = -1;
+ char *slave_name;
+ pid_t child_pid;
+#if defined(HAVE_TERMIOS_H) && defined(HAVE_TCGETATTR) && \
+ defined(HAVE_TCSETATTR)
+ struct termios termio;
+#endif
+
+ /*
+ ** XXX This code to find and open a pseudo-terminal is nowhere
+ ** near as portable as I would like, but given the huge variety
+ ** of methods for allocating pseudo-terminals it will have to do.
+ ** Most systems seem to be standardising on this method (from UNIX98).
+ ** See the xterm or expect source for a more complete version
+ ** (it's a bit too entwined in the rest of the code to just lift
+ ** it out and use it here).
+ */
+#if defined(HAVE_DEV_PTMX) && defined(HAVE_GRANTPT) && \
+ defined(HAVE_UNLOCKPT) && defined(HAVE_PTSNAME)
+ master_fd = open("/dev/ptmx", O_RDWR);
+ if (master_fd == -1 || grantpt(master_fd) == -1
+ || unlockpt(master_fd) == -1) {
+ close(master_fd);
+ perror("error opening master pseudo-terminal for mdb window");
+ return FALSE;
+ }
+ if ((slave_name = ptsname(master_fd)) == NULL) {
+ perror("error getting name of pseudo-terminal for mdb window");
+ close(master_fd);
+ return FALSE;
+ }
+ slave_fd = open(slave_name, O_RDWR);
+ if (slave_fd == -1) {
+ close(master_fd);
+ perror("opening slave pseudo-terminal for mdb window failed");
+ return FALSE;
+ }
+
+#if defined(HAVE_IOCTL) && defined(I_PUSH)
+ /* Magic STREAMS incantations to make this work on Solaris. */
+ ioctl(slave_fd, I_PUSH, "ptem");
+ ioctl(slave_fd, I_PUSH, "ldterm");
+ ioctl(slave_fd, I_PUSH, "ttcompat");
+#endif
+
+#else
+ fprintf(stderr,
+ "Sorry, `mdb --window' not supported on this platform.\n");
+ return FALSE;
+#endif
+
+#if defined(HAVE_TCGETATTR) && defined(HAVE_TCSETATTR)
+ /*
+ ** Turn off echoing before starting the xterm so that
+ ** the user doesn't see the window ID printed by xterm
+ ** on startup (this behaviour is not documented in the
+ ** xterm manual).
+ */
+ tcgetattr(slave_fd, &termio);
+ termio.c_lflag &= ~ECHO;
+ tcsetattr(slave_fd, TCSADRAIN, &termio);
+#endif
+
+ child_pid = fork();
+ if (child_pid == -1) {
+ perror("fork() for mdb window failed");
+ close(master_fd);
+ close(slave_fd);
+ return FALSE;
+ } else if (child_pid == 0) {
+ /*
+ ** Child - exec() the xterm.
+ */
+ char xterm_arg[50];
+
+ close(slave_fd);
+
+#if defined(HAVE_SETPGID)
+ /*
+ ** Put the xterm in a new process group so it won't be
+ ** killed by SIGINT signals sent to the program.
+ */
+ if (setpgid(0, 0) < 0) {
+ perror("setpgid() failed");
+ close(master_fd);
+ exit(EXIT_FAILURE);
+ }
+#endif
+
+ /*
+ ** The XX part is required by xterm, but it's not
+ ** needed for the way we are using xterm (it's meant
+ ** to be an identifier for the pseudo-terminal).
+ ** Different versions of xterm use different
+ ** formats, so it's best to just leave it blank.
+ **
+ ** XXX Some versions of xterm (such as that distributed
+ ** with XFree86 3.3.6) give a warning about this (but it
+ ** still works). The latest version distributed with
+ ** XFree86 4 does not given a warning.
+ */
+ sprintf(xterm_arg, "-SXX%d", master_fd);
+
+ execlp("xterm", "xterm", "-T", "mdb", xterm_arg, NULL);
+ perror("execlp() of xterm failed");
+ exit(EXIT_FAILURE);
+ } else {
+ /*
+ ** Parent - set up the mdb I/O streams to point
+ ** to the pseudo-terminal.
+ */
+ MR_Code *old_alarm_handler;
+ int wait_status;
+ int err_fd = -1;
+ int out_fd = -1;
+
+ MR_mdb_in = MR_mdb_out = MR_mdb_err = NULL;
+
+ close(master_fd);
+
+ /*
+ ** Read the first line of output -- this is a window ID
+ ** written by xterm. The alarm() and associated signal handling
+ ** is to gracefully handle the case where the xterm failed to
+ ** start, for example because the DISPLAY variable was invalid.
+ ** We don't want to restart the read() below if it times out.
+ */
+ old_alarm_handler = (MR_Code *) signal(SIGALRM, NULL);
+ MR_setup_signal_no_restart(SIGALRM,
+ (MR_Code *) MR_trace_internal_alarm_handler, FALSE,
+ "error setting up alarm handler");
+ alarm(10);
+ while (1) {
+ char c;
+ int status;
+ status = read(slave_fd, &c, 1);
+ if (status == -1) {
+ if (errno != EINTR || MR_got_alarm) {
+ perror(
+ "error reading from pseudo-terminal");
+ goto parent_error;
+ }
+ } else if (status == 0 || c == '\n') {
+ break;
+ }
+ }
+
+ /* Reset the alarm handler. */
+ alarm(0);
+ MR_setup_signal(SIGALRM, (MR_Code *) old_alarm_handler,
+ FALSE, "error resetting alarm handler");
+
+#if defined(HAVE_TCGETATTR) && defined(HAVE_TCSETATTR)
+ /* Restore echoing. */
+ termio.c_lflag |= ECHO;
+ tcsetattr(slave_fd, TCSADRAIN, &termio);
+#endif
+
+ if ((out_fd = dup(slave_fd)) == -1) {
+ perror(
+ "opening slave pseudo-terminal for xterm failed");
+ goto parent_error;
+ }
+ if ((err_fd = dup(slave_fd)) == -1) {
+ perror(
+ "opening slave pseudo-terminal for xterm failed");
+ goto parent_error;
+ }
+
+ MR_mdb_in = fdopen(slave_fd, "r");
+ if (MR_mdb_in == NULL) {
+ perror("opening slave pseudo-terminal for xterm failed");
+ goto parent_error;
+ }
+ MR_mdb_out = fdopen(out_fd, "w");
+ if (MR_mdb_out == NULL) {
+ perror("opening slave pseudo-terminal for xterm failed");
+ goto parent_error;
+ }
+ MR_mdb_err = fdopen(err_fd, "w");
+ if (MR_mdb_err == NULL) {
+ perror("opening slave pseudo-terminal for xterm failed");
+ goto parent_error;
+ }
+
+ MR_have_mdb_window = TRUE;
+ MR_mdb_window_pid = child_pid;
+ return TRUE;
+
+parent_error:
+#if defined(HAVE_KILL) && defined(SIGTERM) && defined(HAVE_WAIT)
+ if (kill(child_pid, SIGTERM) != -1) {
+ do {
+ wait_status = wait(NULL);
+ if (wait_status == -1 && errno != EINTR) {
+ break;
+ }
+ } while (wait_status != child_pid);
+ }
+#endif
+ if (MR_mdb_in) fclose(MR_mdb_in);
+ if (MR_mdb_out) fclose(MR_mdb_out);
+ if (MR_mdb_err) fclose(MR_mdb_err);
+ close(slave_fd);
+ close(out_fd);
+ close(err_fd);
+ return FALSE;
+
+ }
+
+#else /* HAVE_OPEN, etc. */
+ fprintf(stderr,
+ "Sorry, `mdb --window' not supported on this platform.\n");
+ return FALSE;
+#endif /* HAVE_OPEN, etc. */
+}
+
static void
MR_trace_internal_init_from_env(void)
{
@@ -1215,18 +1496,18 @@
bool force = FALSE;
bool verbose = FALSE;
bool split = FALSE;
- bool close = FALSE;
+ bool close_window = FALSE;
const char *msg;
if (! MR_trace_options_view(&window_cmd, &server_cmd,
&server_name, &timeout, &force, &verbose,
- &split, &close, &words, &word_count,
+ &split, &close_window, &words, &word_count,
"browsing", "view"))
{
; /* the usage message has already been printed */
} else if (word_count != 1) {
MR_trace_usage("browsing", "view");
- } else if (close) {
+ } else if (close_window) {
MR_trace_maybe_close_source_window(verbose);
} else {
msg = MR_trace_new_source_window(window_cmd,
@@ -3037,7 +3318,7 @@
static bool
MR_trace_options_view(const char **window_cmd, const char **server_cmd,
const char **server_name, int *timeout, bool *force,
- bool *verbose, bool *split, bool *close, char ***words,
+ bool *verbose, bool *split, bool *close_window, char ***words,
int *word_count, const char *cat, const char *item)
{
int c;
@@ -3058,11 +3339,11 @@
MR_trace_usage(cat, item);
return FALSE;
}
- *close = TRUE;
+ *close_window = TRUE;
break;
case 'w':
- if (*close) {
+ if (*close_window) {
MR_trace_usage(cat, item);
return FALSE;
}
@@ -3089,7 +3370,7 @@
break;
case 't':
- if (*close ||
+ if (*close_window ||
sscanf(MR_optarg, "%d", timeout) != 1)
{
MR_trace_usage(cat, item);
@@ -3099,7 +3380,7 @@
break;
case 'f':
- if (*close) {
+ if (*close_window) {
MR_trace_usage(cat, item);
return FALSE;
}
@@ -3112,7 +3393,7 @@
break;
case '2':
- if (*close) {
+ if (*close_window) {
MR_trace_usage(cat, item);
return FALSE;
}
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list