for review: add mdb support for interactive queries
Fergus Henderson
fjh at cs.mu.OZ.AU
Thu Mar 4 10:50:57 AEDT 1999
Anyone care to review this?
Estimated hours taken: 14
Add support for invoking interactive queries to mdb.
browser/interactive_query.m:
New module, to implement interactive queries.
browser/dl.m:
browser/name_mangle.m:
Copy these files from extras/dynamic_linking, since
they are needed by browser/interactive_query.m.
configure.in:
runtime/mercury_conf.h.in:
Autodetect the presence of support for dlopen() etc.
browser/dl.m:
Add #ifdefs so that the code will compile (but report
an error at runtime) if dlopen() etc. are not supported.
browser/browser_library.m:
Add interface_query, dl, and name_mangle to the list of
modules in this library.
trace/mercury_trace_browse.h:
trace/mercury_trace_browse.c:
Add a new function MR_trace_query() to interface to the ML_query()
function defined by browser/interfactive_query.m.
trace/mercury_trace_internal.c:
Add code to implement new commands `query', `cc_query', `io_query',
and `mmc_options', using the MR_trace_query() function defined by
trace/mercury_trace_browse.h.
runtime/mercury_grade.h:
Add code to define MR_GRADE_OPT, so that browser/interactive_query.m
can use this to invoke mmc with the same grade that the executable
being debugged was built with.
doc/mdb_categories:
doc/user_guide.texi:
Document the new commands `query', `cc_query', `io_query',
and `mmc_options'.
Index: browser/browser_library.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/browser_library.m,v
retrieving revision 1.2
diff -u -r1.2 browser_library.m
--- browser_library.m 1998/10/25 07:16:39 1.2
+++ browser_library.m 1999/03/03 14:50:16
@@ -14,10 +14,8 @@
:- import_module help.
:- import_module debugger_interface.
-:- import_module browse.
-:- import_module frame.
-:- import_module parse.
-:- import_module util.
+:- import_module browse, frame, parse, util.
+:- import_module interactive_query, dl, name_mangle.
% See library/library.m for why we implement this predicate this way.
cvs diff: browser/dl.m is a new entry, no comparison available
cvs diff: browser/interactive_query.m is a new entry, no comparison available
cvs diff: browser/name_mangle.m is a new entry, no comparison available
Index: configure.in
===================================================================
RCS file: /home/mercury1/repository/mercury/configure.in,v
retrieving revision 1.148
diff -u -r1.148 configure.in
--- configure.in 1999/02/01 02:02:26 1.148
+++ configure.in 1999/03/03 17:54:42
@@ -279,6 +279,12 @@
AC_DEFINE(HAVE_SYS_TIME)
fi
#-----------------------------------------------------------------------------#
+AC_CHECK_HEADER(dlfcn.h, HAVE_DLFCN_H=1)
+if test "$HAVE_DLFCN_H" = 1; then
+ AC_DEFINE(HAVE_DLFCN_H)
+fi
+AC_HAVE_FUNCS(dlopen dlclose dlsym dlerror)
+#-----------------------------------------------------------------------------#
#
# check the basics of sigaction
#
Index: doc/mdb_categories
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/mdb_categories,v
retrieving revision 1.3
diff -u -r1.3 mdb_categories
--- mdb_categories 1998/11/15 14:00:23 1.3
+++ mdb_categories 1999/03/03 23:44:22
@@ -2,6 +2,11 @@
concepts - The concepts on which the Mercury debugger is based.
end
+document_category 150 queries
+queries - Commands for invoking goals interactively.
+ The commands for queries are
+ `query', `cc_query', and `io_query'.
+end
document_category 200 forward
forward - Commands that move execution forward.
The forward commands are `step', `goto', `finish', `forward',
@@ -28,7 +33,7 @@
document_category 600 parameter
parameter - Commands that let users access debugger parameters.
The parameter commands are `printlevel', `echo', `scroll',
- `alias' and `unalias'.
+ `mmc_options', `alias' and `unalias'.
end
document_category 700 help
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.157
diff -u -r1.157 user_guide.texi
--- user_guide.texi 1999/02/21 10:09:43 1.157
+++ user_guide.texi 1999/03/03 23:27:34
@@ -1327,6 +1327,7 @@
even if the number and the command are not separated by white space.
@menu
+* Interactive query commands::
* Forward movement commands::
* Backward movement commands::
* Browsing commands::
@@ -1338,6 +1339,53 @@
* Miscellaneous commands::
@end menu
+ at node Interactive query commands
+ at subsection Interactive query commands
+
+ at table @code
+ at item query @var{module1} @var{module2} @dots{}
+ at itemx cc_query @var{module1} @var{module2} @dots{}
+ at itemx io_query @var{module1} @var{module2} @dots{}
+These commands allow you to type in queries (goals) interactively
+in the debugger. When you use one of these commands, the debugger
+will respond with a query prompt (@samp{?-} or @samp{run <--}),
+at which you can type in a goal; the debugger will the compile
+and execute the goal and display the answer(s).
+You can return from the query prompt to the @samp{mdb>} prompt
+by typing the end-of-file indicator (typically control-D or control-Z),
+or by typing @samp{quit.}.
+
+The module names @var{module1}, @var{module2}, @dots{} specify
+which modules will be imported. You need to import all the modules
+that define symbols used in your query. Note that you can also
+add new modules to the list of imports directly at the query prompt,
+by using a command of the form @samp{["@var{module}"]}, e.g. @samp{["int"]}.
+
+The three variants differ in what kind of goals they allow.
+For goals which perform I/O, you need to use @samp{io_query};
+this lets you type in the goal using DCG syntax.
+For goals which don't do I/O, but which have determinism
+ at samp{cc_nondet} or @samp{cc_multi}, you you need to use @samp{cc_query};
+this finds only one solution to the specified goal.
+For all other goals, you can use plain @samp{query}, which
+finds all the solutions to the goal.
+
+For @samp{query} and @samp{cc_query}, the debugger will print
+out all the variables in the goal using @samp{io__write}.
+The goal must bind all of its variables to ground terms,
+otherwise you will get a mode error.
+
+The current implementation works by compiling the queries on-the-fly
+and then dynamically linking them into the program being debugged.
+Thus it make take a little while for your query to be executed.
+Each query will be written to a file named @file{query.m} in the current
+directory, so make sure you don't name your source file @file{query.m}.
+Note that dynamic linking may not be supported on some systems;
+if your using a system for which dynamic linking is not supported,
+you will get an error message when you try to run these commands.
+
+ at end table
+
@node Forward movement commands
@subsection Forward movement commands
@@ -1673,6 +1721,13 @@
@subsection Parameter commands
@sp 1
@table @code
+ at item mmc_options @var{option1} @var{option2} @dots{}
+This command sets the options that will be passed to @samp{mmc}
+to compile your query when you use one of the query commands
+(@samp{query}, @samp{cc_query}, or @samp{io_query}.
+For example, if a query results in a compile error,
+it may sometimes be helpful to use @samp{mmc_options --verbose-errors}.
+ at sp 1
@item printlevel none
Sets the default print level to @samp{none}.
@sp 1
Index: runtime/mercury_conf.h.in
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf.h.in,v
retrieving revision 1.9
diff -u -r1.9 mercury_conf.h.in
--- mercury_conf.h.in 1998/12/15 00:22:11 1.9
+++ mercury_conf.h.in 1999/03/03 17:54:55
@@ -72,6 +72,7 @@
** HAVE_SYS_TIME we have <sys/time.h>
** HAVE_SYS_PARAM we have <sys/param.h>
** HAVE_SYS_WAIT we have <sys/wait.h>
+** HAVE_DLFCN_H we have <dlfcn.h>
*/
#undef HAVE_SYS_SIGINFO
#undef HAVE_UCONTEXT
@@ -80,19 +81,24 @@
#undef HAVE_SYS_TIME
#undef HAVE_SYS_PARAM
#undef HAVE_SYS_WAIT
+#undef HAVE_DLFCN_H
/*
** The following macros are defined iff the corresponding function or
** system call is available:
**
** HAVE_SYSCONF we have the sysconf() system call.
-** HAVE_SIGACTION we have the sigaction() sysstem call.
+** HAVE_SIGACTION we have the sigaction() system call.
** HAVE_GETPAGESIZE we have the getpagesize() system call.
** HAVE_MPROTECT we have the mprotect() system call.
** HAVE_MEMALIGN we have the memalign() function.
** HAVE_STRERROR we have the strerror() function.
** HAVE_SETITIMER we have the setitimer() function.
** HAVE_MEMMOVE we have the memmove() function.
+** HAVE_DLOPEN we have the dlopen() function.
+** HAVE_DLCLOSE we have the dlclose() function.
+** HAVE_DLSYM we have the dlsym() function.
+** HAVE_DLERROR we have the dlerror() function.
*/
#undef HAVE_SYSCONF
#undef HAVE_SIGACTION
@@ -102,6 +108,10 @@
#undef HAVE_STRERROR
#undef HAVE_SETITIMER
#undef HAVE_MEMMOVE
+#undef HAVE_DLOPEN
+#undef HAVE_DLCLOSE
+#undef HAVE_DLSYM
+#undef HAVE_DLERROR
/*
** RETSIGTYPE: the return type of signal handlers.
Index: runtime/mercury_grade.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_grade.h,v
retrieving revision 1.15
diff -u -r1.15 mercury_grade.h
--- mercury_grade.h 1998/11/11 01:53:06 1.15
+++ mercury_grade.h 1999/03/03 15:26:06
@@ -191,4 +191,123 @@
extern const char MR_GRADE_VAR;
+/*
+** Here we do the same thing as above, but this time we build up a string
+** containing the options to pass to the compiler to select this grade.
+*/
+
+#ifdef USE_ASM_LABELS
+ #define MR_GRADE_OPT_PART_1 "asm_"
+#else
+ #define MR_GRADE_OPT_PART_1 ""
+#endif
+
+#ifdef USE_GCC_NONLOCAL_GOTOS
+ #ifdef USE_GCC_GLOBAL_REGISTERS
+ #define MR_GRADE_OPT_PART_2 MR_GRADE_OPT_PART_1 "fast"
+ #else
+ #define MR_GRADE_OPT_PART_2 MR_GRADE_OPT_PART_1 "jump"
+ #endif
+#else
+ #ifdef USE_GCC_GLOBAL_REGISTERS
+ #define MR_GRADE_OPT_PART_2 MR_GRADE_OPT_PART_1 "reg"
+ #else
+ #define MR_GRADE_OPT_PART_2 MR_GRADE_OPT_PART_1 "none"
+ #endif
+#endif
+
+#ifdef MR_THREAD_SAFE
+ #define MR_GRADE_OPT_PART_3 MR_GRADE_OPT_PART_2 ".par"
+#else
+ #define MR_GRADE_OPT_PART_3 MR_GRADE_OPT_PART_2
+#endif
+#ifdef CONSERVATIVE_GC
+ #define MR_GRADE_OPT_PART_4 MR_GRADE_OPT_PART_3 ".gc"
+#elif defined(NATIVE_GC)
+ #define MR_GRADE_OPT_PART_4 MR_GRADE_OPT_PART_3 ".agc"
+#else
+ #define MR_GRADE_OPT_PART_4 MR_GRADE_OPT_PART_3
+#endif
+
+#ifdef PROFILE_TIME
+ #ifdef PROFILE_CALLS
+ #ifdef PROFILE_MEMORY
+ #define MR_GRADE_OPT_PART_5 MR_GRADE_OPT_PART_4 ".profall"
+ #else
+ #define MR_GRADE_OPT_PART_5 MR_GRADE_OPT_PART_4 ".prof"
+ #endif
+ #else
+ #ifdef PROFILE_MEMORY
+ /*
+ ** Memory profiling interferes with time profiling,
+ ** so there's no point in allowing this.
+ */
+ #error "Invalid combination of profiling options"
+ #else
+ /* Currently useless "but... */
+ #define MR_GRADE_OPT_PART_5 MR_GRADE_OPT_PART_4 ".proftime"
+ #endif
+ #endif
+#else
+ #ifdef PROFILE_CALLS
+ #ifdef PROFILE_MEMORY
+ #define MR_GRADE_OPT_PART_5 MR_GRADE_OPT_PART_4 ".memprof"
+ #else
+ #define MR_GRADE_OPT_PART_5 MR_GRADE_OPT_PART_4 ".profcalls"
+ #endif
+ #else
+ #ifdef PROFILE_MEMORY
+ /*
+ ** Call-graph memory profiling requires call profiling,
+ ** and call profiling is reasonably cheap "so there's
+ ** no point in allowing this.
+ */
+ #error "Invalid combination of profiling options"
+ #else
+ #define MR_GRADE_OPT_PART_5 MR_GRADE_OPT_PART_4
+ #endif
+ #endif
+#endif
+
+#ifdef MR_USE_TRAIL
+ #define MR_GRADE_OPT_PART_6 MR_GRADE_OPT_PART_5 ".tr"
+#else
+ #define MR_GRADE_OPT_PART_6 MR_GRADE_OPT_PART_5
+#endif
+
+/*
+** Parts 7-10 above (i.e. tag bits, compact args, (un)boxed float, and
+** debugging of the nondet stack) are documented as "not for general use",
+** and can't be set via the `--grade' option; we don't bother to pass them on.
+*/
+
+#if defined(PIC_REG) && defined(USE_GCC_GLOBAL_REGISTERS) && defined(__i386__)
+ #define MR_GRADE_OPT_PART_11 MR_GRADE_OPT_PART_6 ".picreg"
+#else
+ #define MR_GRADE_OPT_PART_11 MR_GRADE_OPT_PART_6
+#endif
+
+/*
+** Stack traces aren't strictly binary incompatible - but if you
+** try to do a stack trace you might find it doesn't work very
+** well unless all modules are compiled in with --stack-trace.
+** Hence we consider it effectively binary incompatible.
+** Similar considerations apply to procedure call tracing.
+*/
+#if defined(MR_STACK_TRACE)
+ #if defined(MR_REQUIRE_TRACING)
+ #define MR_GRADE_OPT_PART_12 MR_GRADE_OPT_PART_11 ".debug"
+ #else
+ #define MR_GRADE_OPT_PART_12 MR_GRADE_OPT_PART_11 ".strce"
+ #endif
+#else
+ #if defined(MR_REQUIRE_TRACING)
+ #define MR_GRADE_OPT_PART_12 MR_GRADE_OPT_PART_11 ".trace"
+ #else
+ #define MR_GRADE_OPT_PART_12 MR_GRADE_OPT_PART_11
+ #endif
+#endif
+
+#define MR_GRADE_OPT MR_GRADE_OPT_PART_12
+
#endif /* MERCURY_GRADES_H */
Index: trace/mercury_trace_browse.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_browse.c,v
retrieving revision 1.2
diff -u -r1.2 mercury_trace_browse.c
--- mercury_trace_browse.c 1998/12/28 03:38:53 1.2
+++ mercury_trace_browse.c 1999/03/03 18:01:27
@@ -9,7 +9,8 @@
**
** Main author: fjh
**
-** This file provides the C interface to browser/browse.m.
+** This file provides the C interface to browser/browse.m
+** and browser/interactive_query.m.
*/
/*
@@ -26,6 +27,7 @@
#include "mercury_trace_internal.h"
#include "mercury_deep_copy.h"
#include "browse.h"
+#include "interactive_query.h"
#include "std_util.h"
#include <stdio.h>
@@ -97,4 +99,35 @@
(Word *) MR_trace_browser_state_type);
done = TRUE;
}
+}
+
+void
+MR_trace_query(MR_Query_Type type, const char *options, int num_imports,
+ char *imports[])
+{
+ ConstString options_on_heap;
+ Word imports_list;
+ MercuryFile mdb_in, mdb_out;
+ int i;
+
+ MR_c_file_to_mercury_file(MR_mdb_in, &mdb_in);
+ MR_c_file_to_mercury_file(MR_mdb_out, &mdb_out);
+
+ if (options == NULL) options = "";
+
+ MR_TRACE_USE_HP(
+ make_aligned_string(options_on_heap, options);
+
+ imports_list = list_empty();
+ for (i = num_imports; i > 0; i--) {
+ ConstString this_import;
+ make_aligned_string(this_import, imports[i - 1]);
+ imports_list = list_cons(this_import, imports_list);
+ }
+ );
+
+ MR_TRACE_CALL_MERCURY(
+ ML_query(type, imports_list, (String) options_on_heap,
+ (Word) &mdb_in, (Word) &mdb_out);
+ );
}
Index: trace/mercury_trace_browse.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_browse.h,v
retrieving revision 1.1
diff -u -r1.1 mercury_trace_browse.h
--- mercury_trace_browse.h 1998/11/15 16:47:51 1.1
+++ mercury_trace_browse.h 1999/03/03 19:18:22
@@ -7,7 +7,8 @@
/*
** mercury_trace_browse.h
**
-** Defines the interface of the term browser for the internal debugger.
+** Defines the interface of the term browser and the interactive query
+** facility for the internal debugger.
*/
#ifndef MERCURY_TRACE_BROWSE_H
@@ -22,5 +23,16 @@
** Display a term (non-interactively).
*/
extern void MR_trace_print(Word type_info, Word value);
+
+
+/*
+** Invoke an interactive query.
+*/
+
+/* This must kept in sync with query_type in browser/interactive.m. */
+typedef enum { MR_NORMAL_QUERY, MR_CC_QUERY, MR_IO_QUERY } MR_Query_Type;
+
+extern void MR_trace_query(MR_Query_Type type, const char *options,
+ int num_imports, /* const */ char *imports[]);
#endif /* MERCURY_TRACE_BROWSE_H */
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.29
diff -u -r1.29 mercury_trace_internal.c
--- mercury_trace_internal.c 1999/02/23 08:06:50 1.29
+++ mercury_trace_internal.c 1999/03/03 19:18:55
@@ -403,6 +403,8 @@
MR_print_proc_id_for_debugger(fp, entry_layout);
}
+/* Options to pass to mmc when compiling queries. */
+static char *MR_mmc_options = NULL;
static MR_Next
MR_trace_debug_cmd(char *line, MR_Trace_Cmd_Info *cmd,
@@ -976,6 +978,33 @@
} else {
MR_trace_usage("parameter", "printlevel");
}
+ } else if (streq(words[0], "query")) {
+ MR_trace_query(MR_NORMAL_QUERY, MR_mmc_options,
+ word_count - 1, words + 1);
+ } else if (streq(words[0], "cc_query")) {
+ MR_trace_query(MR_CC_QUERY, MR_mmc_options,
+ word_count - 1, words + 1);
+ } else if (streq(words[0], "io_query")) {
+ MR_trace_query(MR_IO_QUERY, MR_mmc_options,
+ word_count - 1, words + 1);
+ } else if (streq(words[0], "mmc_options")) {
+ size_t len;
+
+ /* allocate the right amount of space */
+ len = 0;
+ for (i = 1; i < word_count; i++) {
+ len += strlen(words[i]) + 1;
+ }
+ MR_mmc_options = realloc(MR_mmc_options, len);
+
+ /* copy the arguments to MR_mmc_options */
+ MR_mmc_options[0] = '\0';
+ for (i = 1; i < word_count; i++) {
+ strcat(MR_mmc_options, words[i]);
+ strcat(MR_mmc_options, " ");
+ }
+ MR_mmc_options[len] = '\0';
+
} else if (streq(words[0], "scroll")) {
if (word_count == 2) {
if (streq(words[1], "off")) {
--- ../extras/dynamic_linking/dl.m Thu Mar 4 02:51:40 1999
+++ ./dl.m Thu Mar 4 10:47:40 1999
@@ -55,8 +55,13 @@
:- implementation.
:- import_module std_util, require, string, list.
-:- pragma c_header_code("#include <stdio.h>").
-:- pragma c_header_code("#include <dlfcn.h>").
+:- pragma c_header_code("
+ #include <stdio.h>
+ #include ""mercury_conf.h""
+#ifdef HAVE_DLFCN_H
+ #include <dlfcn.h>
+#endif
+").
:- type handle ---> handle(c_pointer).
@@ -79,17 +84,23 @@
** variables in C++) which may end up calling Mercury, so it's not safe
** to declare this as `will_not_call_mercury'.
*/
+
:- pred dlopen(string::in, (mode)::in, scope::in, c_pointer::out,
io__state::di, io__state::uo) is det.
:- pragma c_code(dlopen(FileName::in, Mode::in, Scope::in, Result::out,
_IO0::di, _IO::uo), [], "
{
+#if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN) \
+ && defined(RTLD_NOW) && defined(RTLD_LAZY)
int mode = (Mode ? RTLD_NOW : RTLD_LAZY);
/* not all systems have RTLD_GLOBAL */
#ifdef RTLD_GLOBAL
if (Scope) mode |= RTLD_GLOBAL;
#endif
Result = (Word) dlopen(FileName, mode);
+#else
+ Result = (Word) NULL;
+#endif
}").
:- type closure ---> closure(int, c_pointer).
@@ -175,15 +186,27 @@
:- pragma c_code(dlsym(Handle::in, Name::in, Pointer::out,
_IO0::di, _IO::uo), [will_not_call_mercury], "
{
+#if defined(HAVE_DLFCN_H) && defined(HAVE_DLSYM)
Pointer = (Word) dlsym((void *) Handle, Name);
+#else
+ Pointer = (Word) NULL;
+#endif
}").
:- pred dlerror(string::out, io__state::di, io__state::uo) is det.
:- pragma c_code(dlerror(ErrorMsg::out, _IO0::di, _IO::uo),
[will_not_call_mercury], "
{
- const char *msg = dlerror();
+ const char *msg;
+
+#if defined(HAVE_DLFCN_H) && defined(HAVE_DLERROR)
+ msg = dlerror();
if (msg == NULL) msg = """";
+#else
+ make_aligned_string(msg, ""sorry, not implemented: ""
+ ""dynamic linking not supported on this platform"");
+#endif
+
make_aligned_string_copy(ErrorMsg, msg);
}").
@@ -198,5 +221,8 @@
** to declare this as `will_not_call_mercury'.
*/
:- pred dlclose(c_pointer::in, io__state::di, io__state::uo) is det.
-:- pragma c_code(dlclose(Handle::in, _IO0::di, _IO::uo),
- [], "dlclose((void *)Handle)").
+:- pragma c_code(dlclose(Handle::in, _IO0::di, _IO::uo), [], "
+#if defined(HAVE_DLFCN_H) && defined(HAVE_DLCLOSE)
+ dlclose((void *)Handle)
+#endif
+").
--
Fergus Henderson <fjh at cs.mu.oz.au> | "Binaries may die
WWW: <http://www.cs.mu.oz.au/~fjh> | but source code lives forever"
PGP: finger fjh at 128.250.37.3 | -- leaked Microsoft memo.
More information about the developers
mailing list