[m-rev.] for review: mdb command line completion
Simon Taylor
stayl at cs.mu.OZ.AU
Wed Mar 6 21:47:22 AEDT 2002
On 04-Mar-2002, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> On 04-Mar-2002, Simon Taylor <stayl at cs.mu.OZ.AU> wrote:
> >
> > Add support for command line completion to mdb.
>
> One thing I noticed is that there are no test cases.
>
> I know we have had some issues with different versions of readline
> behaving differently, but even if we can't easily get the tests to work
> on all our machines, I think it is worth setting up some tests on at
> least one machine.
>
> One way to make it testable, without affecting any of the
> existing debugger test cases, would be to add a new runtime option
> `--force-readline', which would cause MR_trace_readline() to use
> readline() even if the input file was a tty.
Done.
> > runtime/mercury_array_macros.h:
> > Define a macro MR_find_first_match, which is like MR_bsearch
> > except that it finds the first match, not an arbitary match.
>
> s/arbitary/arbitrary/
>
> > Index: runtime/mercury_array_macros.h
> > /*
> > +** MR_find_first_match(int next, int& element, MR_bool& found, COMPARE)
> > +**
> > +** Given a sorted array, this macro finds the first element in the array
> > +** for which `COMPARE' is zero (MR_bsearch finds an arbitrary element).
> > +** Otherwise, the parameters and behaviour are the same as for MR_bsearch.
>
> The parameter `next' is poorly named.
> I suggest s/next/num_elements/
> (both here and in MR_bsearch()).
Done.
> > +#define MR_find_first_match(next, element, found, COMPARE) \
> > + do { \
> > + MR_bsearch((next), (element), (found), (COMPARE)); \
> > + if (found) { \
> > + while ((element) > 0) { \
> > + int diff; \
>
> `diff' is unused here.
> That line should be deleted.
Done.
> > Index: trace/mercury_trace_alias.c
> ...
> > +static MR_bool
> > +MR_trace_filter_alias_completions(const char *word, MR_Completer_Data *data)
>
> Why not `const MR_Completer_Data *data'?
Because the address of that function is passed to a function which expects
a function taking a non-const MR_Completer_Data.
> > Index: trace/mercury_trace_completion.c
> ...
> > +#define MR_MAX_COMMAND_LEN 32
>
> You should document
> - what this is used for
> - what the units are
>
> Also, 32 is probably too small.
I've moved this #define to where it is used so that the
meaning is obvious without documentation.
> > +typedef struct MR_String_Array_Completer_Data_struct {
> > + int offset;
> > + char **strings;
> > +} MR_String_Array_Completer_Data;
>
> What does the `offset' field represent?
> Some comments here might help.
I've used more descriptive names, and move the typedef closer to
where it is used.
> > +char *MR_trace_line_completer(const char *passed_word, int state)
> > +{
> > +#ifndef MR_NO_USE_READLINE
> ... 150 lines of code ...
> > +#else
> > + return NULL;
> > +#endif
>
> You should add comments after the #else and #endif.
>
> It would IMHO also be clearer to use `#ifdef' rather than `#ifndef' here,
> swapping the `then' and the `else' parts. Then you won't need a comment
> on the #else.
Done.
> > +++ trace/mercury_trace_internal.c 4 Mar 2002 07:25:14 -0000
> > + /*
> > + ** Some commands take set strings as arguments.
> > + ** This field is a NULL terminated array of those strings.
> > + */
> > + const char *const *MR_trace_command_arg_strings;
>
> What is this field set to for commands which don't take strings as arguments?
> The comment should document that.
Done.
> > +static const char *const MR_trace_print_cmd_args[] =
> > + {"exception", "goal", NULL};
>
> For use with filename completion, it might be worth making
> "print variables" have the same effect as "print".
"print goal" has the same effect as "print" (did you mean "print *"?).
I've added "*" to the list of completions.
> > + ** XXX Should we allow completion of options of comands?
>
> s/comands/commands/
>
> The answer to the XXX question is yes ;-)
> So I'd write that as
>
> ** XXX We should allow completion of options of commands.
I've added the options to the arrays of completions.
> > + { "queries", "query", NULL, MR_trace_null_completer },
> > + { "queries", "cc_query", NULL, MR_trace_null_completer },
> > + { "queries", "io_query", NULL, MR_trace_null_completer },
>
> These should be using a module-name completer.
> An XXX comment is warranted.
>
> (Ideally the completer would be one that included all the modules
> in the program, not just those compiled with tracing enabled, so
> maybe this is not the same completer as for the `procedures' command.)
Done.
> > Index: trace/mercury_trace_tables.c
> > +/*
> > +** Convert all occurrences of `__' to `:'.
>
> Since we're planning to eventually change the module qualifier
> from `:' to `.', it might be a good idea to use a macro
> MR_MODULE_SEPARATOR_CHAR instead of the various different
> hard-coded occurrences of `:'.
Separate change.
> > +*/
> > +static char *
> > +MR_translate_double_underscores(char *start)
> ...
> > + return start;
> > +}
>
> The return type for that should be `void *'.
>
> (Whoever designed C's string handling routines has a lot to answer for ;-)
Sorry, you'll have to explain that.
Simon.
diff -u runtime/mercury_array_macros.h runtime/mercury_array_macros.h
--- runtime/mercury_array_macros.h
+++ runtime/mercury_array_macros.h
@@ -123,7 +123,7 @@
} while(0)
/*
-** MR_bsearch(int next, int& element, MR_bool& found, COMPARE)
+** MR_bsearch(int num_elements, int& element, MR_bool& found, COMPARE)
**
** Given a sorted array, this macro performs a binary search.
** If the search is successful, MR_bsearch sets the `found' parameter
@@ -131,7 +131,8 @@
** If the search is unsuccessful, MR_bsearch sets `found' to MR_FALSE;
** `element' will be clobbered.
**
-** The number of the elements in the array is given by the `next' parameter.
+** The number of the elements in the array is given by the `num_elements'
+** parameter.
** The `COMPARE' parameter should be an expression of type int which compares
** the value at the index specified by the current value of `element'
** with the desired value, and returns <0, 0, or >0 according to whether
@@ -142,7 +143,7 @@
** parameter.
*/
-#define MR_bsearch(next, element, found, COMPARE) \
+#define MR_bsearch(num_elements, element, found, COMPARE) \
do { \
int lo; \
int hi; \
@@ -155,7 +156,7 @@
*/ \
(element) = 0; \
lo = 0; \
- hi = (next) - 1; \
+ hi = (num_elements) - 1; \
(found) = MR_FALSE; \
while (lo <= hi) { \
(element) = (lo + hi) / 2; \
@@ -172,19 +173,18 @@
} while(0)
/*
-** MR_find_first_match(int next, int& element, MR_bool& found, COMPARE)
+** MR_find_first_match(int num_elements, int& element, MR_bool& found, COMPARE)
**
** Given a sorted array, this macro finds the first element in the array
** for which `COMPARE' is zero (MR_bsearch finds an arbitrary element).
** Otherwise, the parameters and behaviour are the same as for MR_bsearch.
*/
-#define MR_find_first_match(next, element, found, COMPARE) \
+#define MR_find_first_match(num_elements, element, found, COMPARE) \
do { \
- MR_bsearch((next), (element), (found), (COMPARE)); \
+ MR_bsearch((num_elements), (element), (found), (COMPARE)); \
if (found) { \
while ((element) > 0) { \
- int diff; \
(element)--; \
if ((COMPARE) != 0) { \
(element)++; \
diff -u trace/mercury_trace_completion.c trace/mercury_trace_completion.c
--- trace/mercury_trace_completion.c
+++ trace/mercury_trace_completion.c
@@ -33,33 +33,6 @@
#endif
#endif
-#define MR_MAX_COMMAND_LEN 32
-
-typedef struct MR_String_Array_Completer_Data_struct {
- int offset;
- char **strings;
-} MR_String_Array_Completer_Data;
-
-typedef struct {
- MR_Get_Slot_Name MR_sorted_array_get_slot_name;
- int MR_sorted_array_offset;
- int MR_sorted_array_size;
-} MR_Sorted_Array_Completer_Data;
-
-typedef struct {
- MR_Completer_Filter MR_filter_func;
- MR_Completer_Data MR_filter_data;
- MR_Free_Completer_Data MR_filter_free_data;
- MR_Completer_List * MR_filter_list;
-} MR_Filter_Completer_Data;
-
-typedef struct {
- MR_Completer_Map MR_map_func;
- MR_Completer_Data MR_map_data;
- MR_Free_Completer_Data MR_map_free_data;
- MR_Completer_List * MR_map_list;
-} MR_Map_Completer_Data;
-
/*
** Complete on NULL terminated array of strings.
** The strings will not be `free'd.
@@ -71,28 +44,22 @@
size_t word_len, MR_Completer_List **list);
static void MR_trace_free_completer_list(MR_Completer_List *completer_list);
-static char *MR_trace_sorted_array_completer_next(const char *word,
- size_t word_length, MR_Completer_Data *data);
-
-static char *MR_trace_filter_completer_next(const char *word,
- size_t word_len, MR_Completer_Data *);
-static void MR_trace_free_filter_completer_data(MR_Completer_Data data);
-
-static char *MR_trace_map_completer_next(const char *word,
- size_t word_len, MR_Completer_Data *);
-static void MR_trace_free_map_completer_data(MR_Completer_Data data);
-
-static char *MR_trace_string_array_completer_next(const char *word,
- size_t word_len, MR_Completer_Data *data);
-
-static char *MR_trace_filename_completer_next(const char *word,
- size_t word_len, MR_Completer_Data *);
-
static char *MR_prepend_string(char *completion, MR_Completer_Data *data);
+/*---------------------------------------------------------------------------*/
+/*
+** Called by Readline when the user requests completion.
+** Examine Readline's input buffer to work out which completers
+** should be used, then apply them.
+** Readline passes zero for `state' on the first call, and non-zero
+** on subsequent calls.
+*/
+
char *MR_trace_line_completer(const char *passed_word, int state)
{
-#ifndef MR_NO_USE_READLINE
+#ifdef MR_NO_USE_READLINE
+ return NULL;
+#else
static MR_Completer_List *completer_list;
static char *word;
static size_t word_len;
@@ -187,8 +154,8 @@
/*
** We're completing an argument of the command.
*/
-
- char command[MR_MAX_COMMAND_LEN];
+ #define MR_MAX_COMMAND_NAME_LEN 32
+ char command[MR_MAX_COMMAND_NAME_LEN];
char *expanded_command;
int command_len;
char **words;
@@ -198,7 +165,7 @@
MR_Completer_List *arg_completer;
command_len = command_end - command_start;
- if (command_len >= MR_MAX_COMMAND_LEN) {
+ if (command_len >= MR_MAX_COMMAND_NAME_LEN) {
/* The string is too long to be a command. */
return NULL;
} else {
@@ -249,9 +216,7 @@
word = NULL;
}
return completion;
-#else
- return NULL;
-#endif
+#endif /* ! MR_NO_USE_READLINE */
}
static char *
@@ -270,6 +235,8 @@
return result;
}
+/*---------------------------------------------------------------------------*/
+
static char *
MR_trace_completer_list_next(const char *word, size_t word_len,
MR_Completer_List **list)
@@ -312,12 +279,27 @@
}
}
+/*---------------------------------------------------------------------------*/
+/* No completions. */
+
MR_Completer_List *
MR_trace_null_completer(const char *word, size_t word_len)
{
return NULL;
}
+/*---------------------------------------------------------------------------*/
+/* Complete on the labels of a sorted array. */
+
+typedef struct {
+ MR_Get_Slot_Name MR_sorted_array_get_slot_name;
+ int MR_sorted_array_current_offset;
+ int MR_sorted_array_size;
+} MR_Sorted_Array_Completer_Data;
+
+static char *MR_trace_sorted_array_completer_next(const char *word,
+ size_t word_length, MR_Completer_Data *data);
+
MR_Completer_List *
MR_trace_sorted_array_completer(const char *word, size_t word_length,
int array_size, MR_Get_Slot_Name get_slot_name)
@@ -343,7 +325,7 @@
if (found) {
data = MR_NEW(MR_Sorted_Array_Completer_Data);
data->MR_sorted_array_get_slot_name = get_slot_name;
- data->MR_sorted_array_offset = slot;
+ data->MR_sorted_array_current_offset = slot;
data->MR_sorted_array_size = array_size;
(completer) = MR_new_completer_elem(
MR_trace_sorted_array_completer_next,
@@ -363,11 +345,13 @@
data = (MR_Sorted_Array_Completer_Data *) *completer_data;
- if (data->MR_sorted_array_offset < data->MR_sorted_array_size) {
+ if (data->MR_sorted_array_current_offset
+ < data->MR_sorted_array_size)
+ {
completion = data->MR_sorted_array_get_slot_name(
- data->MR_sorted_array_offset);
+ data->MR_sorted_array_current_offset);
if (MR_strneq(completion, word, word_length)) {
- data->MR_sorted_array_offset++;
+ data->MR_sorted_array_current_offset++;
return MR_copy_string(completion);
} else {
return NULL;
@@ -377,13 +361,24 @@
}
}
+/*---------------------------------------------------------------------------*/
+/* Complete on the elements of an unsorted array of strings. */
+
+typedef struct MR_String_Array_Completer_Data_struct {
+ char **MR_string_array;
+ int MR_string_array_current_offset;
+} MR_String_Array_Completer_Data;
+
+static char *MR_trace_string_array_completer_next(const char *word,
+ size_t word_len, MR_Completer_Data *data);
+
static MR_Completer_List *
MR_trace_string_array_completer(const char *const *strings)
{
MR_String_Array_Completer_Data *data;
data = MR_NEW(MR_String_Array_Completer_Data);
- data->offset = 0;
- data->strings = (char **) strings;
+ data->MR_string_array = (char **) strings;
+ data->MR_string_array_current_offset = 0;
return MR_new_completer_elem(&MR_trace_string_array_completer_next,
(MR_Completer_Data) data, MR_free_func);
}
@@ -398,8 +393,9 @@
completer_data = (MR_String_Array_Completer_Data *) *data;
while (1) {
- result = completer_data->strings[completer_data->offset];
- completer_data->offset++;
+ result = completer_data->MR_string_array[
+ completer_data->MR_string_array_current_offset];
+ completer_data->MR_string_array_current_offset++;
if (result == NULL) {
return NULL;
} else {
@@ -410,6 +406,12 @@
}
}
+/*---------------------------------------------------------------------------*/
+/* Use Readline's filename completer. */
+
+static char *MR_trace_filename_completer_next(const char *word,
+ size_t word_len, MR_Completer_Data *);
+
MR_Completer_List *
MR_trace_filename_completer(const char *word, size_t word_len)
{
@@ -417,7 +419,6 @@
(MR_Completer_Data) 0, MR_trace_no_free);
}
-
static char *
MR_trace_filename_completer_next(const char *word, size_t word_len,
MR_Completer_Data *data)
@@ -428,6 +429,20 @@
return filename_completion_function((char *) word, state);
}
+/*---------------------------------------------------------------------------*/
+/* Apply a filter to the output of a completer. */
+
+typedef struct {
+ MR_Completer_Filter MR_filter_func;
+ MR_Completer_Data MR_filter_data;
+ MR_Free_Completer_Data MR_filter_free_data;
+ MR_Completer_List * MR_filter_list;
+} MR_Filter_Completer_Data;
+
+static char *MR_trace_filter_completer_next(const char *word,
+ size_t word_len, MR_Completer_Data *);
+static void MR_trace_free_filter_completer_data(MR_Completer_Data data);
+
MR_Completer_List *
MR_trace_filter_completer(MR_Completer_Filter filter,
MR_Completer_Data filter_data,
@@ -479,6 +494,20 @@
MR_free(data);
}
+/*---------------------------------------------------------------------------*/
+/* Apply a mapping function to the output of a completer. */
+
+typedef struct {
+ MR_Completer_Map MR_map_func;
+ MR_Completer_Data MR_map_data;
+ MR_Free_Completer_Data MR_map_free_data;
+ MR_Completer_List * MR_map_list;
+} MR_Map_Completer_Data;
+
+static char *MR_trace_map_completer_next(const char *word,
+ size_t word_len, MR_Completer_Data *);
+static void MR_trace_free_map_completer_data(MR_Completer_Data data);
+
MR_Completer_List *
MR_trace_map_completer(MR_Completer_Map map, MR_Completer_Data map_data,
MR_Free_Completer_Data free_data,
@@ -522,6 +551,8 @@
MR_trace_free_completer_list(data->MR_map_list);
MR_free(data);
}
+
+/*---------------------------------------------------------------------------*/
MR_Completer_List *
MR_new_completer_elem(MR_Completer completer, MR_Completer_Data data,
diff -u trace/mercury_trace_completion.h trace/mercury_trace_completion.h
--- trace/mercury_trace_completion.h
+++ trace/mercury_trace_completion.h
@@ -13,6 +13,9 @@
#ifndef MR_TRACE_COMPLETION_H
#define MR_TRACE_COMPLETION_H
+#include "mercury_std.h" /* for MR_bool */
+#include <stdlib.h> /* for size_t */
+
/*
** Called by Readline when the user requests completion.
** Examine Readline's input buffer to work out which completers
diff -u trace/mercury_trace_internal.c trace/mercury_trace_internal.c
--- trace/mercury_trace_internal.c
+++ trace/mercury_trace_internal.c
@@ -227,8 +227,9 @@
const char *MR_trace_command_name;
/*
- ** Some commands take set strings as arguments.
- ** This field is a NULL terminated array of those strings.
+ ** Some commands take fixed strings as arguments.
+ ** This field is a NULL terminated array of those strings,
+ ** or NULL if there are no fixed strings.
*/
const char *const *MR_trace_command_arg_strings;
@@ -4131,15 +4132,42 @@
parent_filename, parent_lineno, indent);
}
+static const char *const MR_trace_movement_cmd_args[] =
+ {"-N", "-S", "-a", "-n", "-s",
+ "--none", "--some", "--all", "--strict", "--no-strict", NULL};
+
static const char *const MR_trace_print_cmd_args[] =
- {"exception", "goal", NULL};
+ {"-f", "-p", "-v", "--flat", "--pretty", "--verbose",
+ "exception", "goal", "*", NULL};
+
+ /*
+ ** It's better to have a single completion where possible,
+ ** so don't include `-d' here.
+ */
+static const char *const MR_trace_stack_cmd_args[] =
+ {"--detailed", NULL};
static const char *const MR_trace_set_cmd_args[] =
- {"format", "depth", "size", "width", "lines",
+ {"-A", "-B", "-P", "-f", "-p", "-v",
+ "--print-all", "--print", "--browse",
+ "--flat", "--pretty", "--verbose",
+ "format", "depth", "size", "width", "lines",
"flat", "pretty", "verbose", NULL};
+static const char *const MR_trace_view_cmd_args[] =
+ {"-c", "-f", "-n", "-s", "-t", "-v", "-w", "-2",
+ "--close", "--verbose", "--force", "--split-screen",
+ "--window-command", "--server-command", "--server-name",
+ "--timeout", NULL};
+
static const char *const MR_trace_break_cmd_args[] =
- {"here", "info", NULL};
+ {"-A", "-E", "-I", "-O", "-P", "-S", "-a", "-e", "-i",
+ "--all", "--entry", "--ignore-entry", "--ignore-interface",
+ "--interface", "--print", "--select-all", "--select-one",
+ "--stop", "here", "info", NULL};
+
+static const char *const MR_trace_ignore_cmd_args[] =
+ {"-E", "-I", "--ignore-entry", "--ignore-interface", NULL};
static const char *const MR_trace_printlevel_cmd_args[] =
{"none", "some", "all", NULL};
@@ -4156,43 +4184,72 @@
static const char *const MR_trace_table_io_cmd_args[] =
{"stats", "start", "end", NULL};
+ /*
+ ** It's better to have a single completion where possible,
+ ** so don't include `-i' here.
+ */
+static const char *const MR_trace_source_cmd_args[] =
+ {"--ignore-errors", NULL};
+
+static const char *const MR_trace_quit_cmd_args[] =
+ {"-y", NULL};
+
static const MR_Trace_Command_Info MR_trace_valid_command_list[] =
{
/*
** The first two fields of this block should be the same
** as in the file doc/mdb_command_list.
- ** XXX Should we allow completion of options of comands?
*/
- { "queries", "query", NULL, MR_trace_null_completer },
- { "queries", "cc_query", NULL, MR_trace_null_completer },
- { "queries", "io_query", NULL, MR_trace_null_completer },
- { "forward", "step", NULL, MR_trace_null_completer },
- { "forward", "goto", NULL, MR_trace_null_completer },
- { "forward", "next", NULL, MR_trace_null_completer },
- { "forward", "finish", NULL, MR_trace_null_completer },
- { "forward", "exception", NULL, MR_trace_null_completer },
- { "forward", "return", NULL, MR_trace_null_completer },
- { "forward", "forward", NULL, MR_trace_null_completer },
- { "forward", "mindepth", NULL, MR_trace_null_completer },
- { "forward", "maxdepth", NULL, MR_trace_null_completer },
- { "forward", "continue", NULL, MR_trace_null_completer },
+ /*
+ ** XXX For queries we should complete on all modules, not
+ ** just those that were compiled with tracing enabled.
+ */
+ { "queries", "query", NULL, MR_trace_module_completer },
+ { "queries", "cc_query", NULL, MR_trace_module_completer },
+ { "queries", "io_query", NULL, MR_trace_module_completer },
+ { "forward", "step", MR_trace_movement_cmd_args,
+ MR_trace_null_completer },
+ { "forward", "goto", MR_trace_movement_cmd_args,
+ MR_trace_null_completer },
+ { "forward", "next", MR_trace_movement_cmd_args,
+ MR_trace_null_completer },
+ { "forward", "finish", MR_trace_movement_cmd_args,
+ MR_trace_null_completer },
+ { "forward", "exception", MR_trace_movement_cmd_args,
+ MR_trace_null_completer },
+ { "forward", "return", MR_trace_movement_cmd_args,
+ MR_trace_null_completer },
+ { "forward", "forward", MR_trace_movement_cmd_args,
+ MR_trace_null_completer },
+ { "forward", "mindepth", MR_trace_movement_cmd_args,
+ MR_trace_null_completer },
+ { "forward", "maxdepth", MR_trace_movement_cmd_args,
+ MR_trace_null_completer },
+ { "forward", "continue", MR_trace_movement_cmd_args,
+ MR_trace_null_completer },
{ "backward", "retry", NULL, MR_trace_null_completer },
{ "browsing", "vars", NULL, MR_trace_null_completer },
{ "browsing", "print", MR_trace_print_cmd_args,
MR_trace_var_completer },
{ "browsing", "browse", MR_trace_print_cmd_args,
MR_trace_var_completer },
- { "browsing", "stack", NULL, MR_trace_null_completer },
- { "browsing", "up", NULL, MR_trace_null_completer },
- { "browsing", "down", NULL, MR_trace_null_completer },
- { "browsing", "level", NULL, MR_trace_null_completer },
+ { "browsing", "stack", MR_trace_stack_cmd_args,
+ MR_trace_null_completer },
+ { "browsing", "up", MR_trace_stack_cmd_args,
+ MR_trace_null_completer },
+ { "browsing", "down", MR_trace_stack_cmd_args,
+ MR_trace_null_completer },
+ { "browsing", "level", MR_trace_stack_cmd_args,
+ MR_trace_null_completer },
{ "browsing", "current", NULL, MR_trace_null_completer },
{ "browsing", "set", MR_trace_set_cmd_args, MR_trace_null_completer },
- { "browsing", "view", NULL, MR_trace_null_completer },
+ { "browsing", "view", MR_trace_view_cmd_args,
+ MR_trace_null_completer },
{ "breakpoint", "break", MR_trace_break_cmd_args,
MR_trace_breakpoint_completer },
- { "breakpoint", "ignore", NULL, MR_trace_null_completer },
+ { "breakpoint", "ignore", MR_trace_ignore_cmd_args,
+ MR_trace_null_completer },
{ "breakpoint", "enable", NULL, MR_trace_null_completer },
{ "breakpoint", "disable", NULL, MR_trace_null_completer },
{ "breakpoint", "delete", NULL, MR_trace_null_completer },
@@ -4215,11 +4272,12 @@
{ "help", "document", NULL, MR_trace_null_completer },
{ "help", "help", NULL, MR_trace_help_completer },
#ifdef MR_TRACE_HISTOGRAM
- { "exp", "histogram_all", NULL, MR_trace_null_completer },
- { "exp", "histogram_exp", NULL, MR_trace_null_completer },
+ { "exp", "histogram_all", NULL, MR_trace_filename_completer },
+ { "exp", "histogram_exp", NULL, MR_trace_filename_completer },
{ "exp", "clear_histogram", NULL, MR_trace_null_completer },
#endif
- { "developer", "nondet_stack", NULL, MR_trace_null_completer },
+ { "developer", "nondet_stack", MR_trace_stack_cmd_args,
+ MR_trace_null_completer },
#ifdef MR_USE_MINIMAL_MODEL
{ "developer", "gen_stack", NULL, MR_trace_null_completer },
#endif
@@ -4227,13 +4285,14 @@
{ "developer", "all_regs", NULL, MR_trace_null_completer },
{ "developer", "table_io", MR_trace_table_io_cmd_args,
MR_trace_null_completer },
- { "developer", "proc_stats", NULL, MR_trace_null_completer },
- { "developer", "label_stats", NULL, MR_trace_null_completer },
+ { "developer", "proc_stats", NULL, MR_trace_filename_completer },
+ { "developer", "label_stats", NULL, MR_trace_filename_completer },
{ "developer", "print_optionals", MR_trace_on_off_args,
MR_trace_null_completer },
- { "misc", "source", NULL, MR_trace_filename_completer },
+ { "misc", "source", MR_trace_source_cmd_args,
+ MR_trace_filename_completer },
{ "misc", "save", NULL, MR_trace_filename_completer },
- { "misc", "quit", NULL, NULL},
+ { "misc", "quit", MR_trace_quit_cmd_args, NULL},
/* End of doc/mdb_command_list. */
{ NULL, "NUMBER", NULL, MR_trace_null_completer },
{ NULL, "EMPTY", NULL, MR_trace_null_completer },
diff -u trace/mercury_trace_readline.c trace/mercury_trace_readline.c
--- trace/mercury_trace_readline.c
+++ trace/mercury_trace_readline.c
@@ -17,6 +17,7 @@
#include "mercury_array_macros.h"
#include "mercury_memory.h"
#include "mercury_std.h"
+#include "mercury_wrapper.h"
#include "mercury_trace_readline.h"
#include "mercury_trace_completion.h"
@@ -29,6 +30,8 @@
extern FILE *rl_outstream;
extern char (*rl_completion_entry_function)(const char *, int);
extern const char *rl_readline_name;
+ extern void (*rl_prep_term_function)(int);
+ extern void (*rl_deprep_term_function)(void);
#endif
#ifdef MR_HAVE_READLINE_HISTORY_H
#include "readline/history.h"
@@ -44,6 +47,9 @@
/* The initial size of the array of characters used to hold the line. */
#define MR_INIT_BUF_LEN 80
+static void MR_dummy_prep_term_function(int ignored);
+static void MR_dummy_deprep_term_function(void);
+
/*
** Print the prompt to the `out' file, read a line from the `in' file,
** and return it in a MR_malloc'd buffer holding the line (without the
@@ -57,9 +63,11 @@
#if (defined(isatty) || defined(MR_HAVE_ISATTY)) \
&& (defined(fileno) || defined(MR_HAVE_FILENO)) \
&& !defined(MR_NO_USE_READLINE)
- /* use readline, if the input file is a terminal */
- if (isatty(fileno(in))) {
- char *line;
+ char *line;
+ MR_bool in_isatty;
+
+ in_isatty = isatty(fileno(in));
+ if (in_isatty || MR_force_readline) {
rl_instream = in;
rl_outstream = out;
@@ -71,9 +79,23 @@
** function pointers).
*/
rl_completion_entry_function =
- (void *) &MR_trace_line_completer;
+ (void *) &MR_trace_line_completer;
rl_readline_name = "mdb";
+ if (!in_isatty) {
+ /*
+ ** This is necessary for tests/debugger/completion,
+ ** otherwise we get lots of messages about readline
+ ** not being able to get the terminal settings.
+ ** This is possibly a bit flaky, but it's only
+ ** used by our tests.
+ */
+ rl_prep_term_function =
+ (void *) MR_dummy_prep_term_function;
+ rl_deprep_term_function =
+ (void *) MR_dummy_deprep_term_function;
+ }
+
line = readline((char *) prompt);
/*
@@ -136,4 +158,14 @@
MR_free(contents);
return NULL;
}
+}
+
+static void
+MR_dummy_prep_term_function(int ignored)
+{
+}
+
+static void
+MR_dummy_deprep_term_function(void)
+{
}
diff -u trace/mercury_trace_tables.c trace/mercury_trace_tables.c
--- trace/mercury_trace_tables.c
+++ trace/mercury_trace_tables.c
@@ -370,7 +370,7 @@
str = start;
while (*str) {
- if (*str == '_' && *(str+ 1) == '_') {
+ if (*str == '_' && *(str + 1) == '_') {
*(str - double_underscores) = ':';
double_underscores++;
str++;
only in patch2:
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/debugger/completion.sub2.sub3.m 5 Mar 2002 15:13:02 -0000
@@ -0,0 +1,9 @@
+:- module completion__sub2__sub3.
+
+:- interface.
+
+:- func zabc3 = int.
+
+:- implementation.
+
+zabc3 = 3.
only in patch2:
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/debugger/completion.sub2.m 5 Mar 2002 15:15:59 -0000
@@ -0,0 +1,11 @@
+:- module completion__sub2.
+
+:- interface.
+
+:- include_module completion__sub2__sub3.
+
+:- func z2 = int.
+
+:- implementation.
+
+z2 = 2.
only in patch2:
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/debugger/completion.sub1.m 5 Mar 2002 15:10:56 -0000
@@ -0,0 +1,13 @@
+:- module completion__sub1.
+
+:- interface.
+
+:- func z1 = int.
+
+:- pred zp(int::out) is det.
+
+:- implementation.
+
+z1 = 1.
+
+zp(1).
only in patch2:
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/debugger/completion.m 5 Mar 2002 15:13:43 -0000
@@ -0,0 +1,20 @@
+:- module completion.
+
+:- interface.
+
+:- import_module io.
+
+:- include_module completion__sub1, completion__sub2.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+main -->
+ io__write_string("ok\n").
+
+:- func z = int.
+z = 0.
+
+:- func zz = int.
+zz = 0.
only in patch2:
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/debugger/completion.inputrc 5 Mar 2002 08:23:54 -0000
@@ -0,0 +1,9 @@
+# Don't query the user if there are too many completions.
+set completion-query-items 100000
+
+# Display all completions immediately, without
+# requiring multiple `complete' commands.
+set show-all-if-ambiguous on
+
+# Make the completion requests show up in the input file.
+@: complete
only in patch2:
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/debugger/completion.inp 6 Mar 2002 10:41:14 -0000
@@ -0,0 +1,13 @@
+echo on
+ at h@e at v@a@
+p --f@@H@
+sta@ @
+proc at e@compl@:@1
+set --f at fo@p@
+un at ex@
+b z at a@
+b pred*@z@
+b compl at s@1 at 1
+b compl at s@2 at s@
+2d at e@
+c
only in patch2:
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/debugger/completion.exp 6 Mar 2002 10:42:00 -0000
@@ -0,0 +1,96 @@
+Melbourne Mercury Debugger, mdb version DEV.
+Copyright 1998 The University of Melbourne, Australia.
+mdb is free software, covered by the GNU General Public License.
+There is absolutely no warranty for mdb.
+ 1: 1 1 CALL pred completion:main/2-0 (det) completion.m:13
+mdb> echo on
+Command echo enabled.
+mdb>
+? down maxdepth return
+P e mindepth s
+alias echo mmc_options save
+all_regs enable modules scope
+b exception next scroll
+break excp nondet_stack set
+browse f p source
+c finish print stack
+cc_query forward print_optionals stack_regs
+context g printlevel step
+continue goto proc_stats table_io
+current h procedures unalias
+d help query up
+delete ignore quit v
+disable io_query r vars
+document label_stats register view
+document_category level retry
+
+h help
+
+vars view
+help vars
+vars
+ Prints the names of all the known variables in the current
+ environment, together with an ordinal number for each variable.
+
+
+mdb>
+* --pretty -f -v exception
+--flat --verbose -p HeadVar__1 goal
+p --flat HeadVar__1
+ HeadVar__1 state('<<c_pointer>>')
+mdb>
+stack stack_regs
+stack --detailed
+ 0 1 1 1 pred completion:main/2-0 (det) (completion.m:13) (empty)
+mdb>
+proc_stats procedures
+
+completion completion:sub2
+completion:sub1 completion:sub2:sub3
+
+completion:sub1 completion:sub2 completion:sub2:sub3
+procedures completion:sub1
+Registering debuggable procedures... done.
+There are 4 debuggable modules, with a total of 7 procedures.
+List of procedures in module `completion:sub1'
+
+pred completion:sub1:zp/1-0 (det)
+func completion:sub1:z1/0-0 (det)
+mdb> set --flat format pretty
+mdb> unalias excp
+Alias `excp' removed.
+mdb>
+z z1 z2 zabc3 zp zz
+b zabc3
+ 0: + stop interface func completion:sub2:sub3:zabc3/0-0 (det)
+mdb>
+pred*completion: pred*completion:sub2:sub3:
+pred*completion:sub1: pred*main
+pred*completion:sub2: pred*zp
+b pred*zp
+ 1: + stop interface pred completion:sub1:zp/1-0 (det)
+mdb>
+completion: completion:sub2:
+completion:sub1: completion:sub2:sub3:
+
+completion:sub1: completion:sub2: completion:sub2:sub3:
+
+completion:sub1:z1 completion:sub1:zp
+b completion:sub1:z1
+ 2: + stop interface func completion:sub1:z1/0-0 (det)
+mdb>
+completion: completion:sub2:
+completion:sub1: completion:sub2:sub3:
+
+completion:sub1: completion:sub2: completion:sub2:sub3:
+
+completion:sub2: completion:sub2:sub3:
+b completion:sub2:sub3:zabc3
+ 3: + stop interface func completion:sub2:sub3:zabc3/0-0 (det)
+mdb>
+2d 2disable 2document_category
+2delete 2document 2down
+2delete
+ 2: E stop interface func completion:sub1:z1/0-0 (det)
+mdb> c
+ok
only in patch2:
--- tests/debugger/Mmakefile 2 Mar 2002 10:22:05 -0000 1.66
+++ tests/debugger/Mmakefile 5 Mar 2002 14:57:11 -0000
@@ -28,6 +28,7 @@
breakpoints \
browse_pretty \
cmd_quote \
+ completion \
debugger_regs \
exception_cmd \
exception_value \
@@ -46,6 +47,10 @@
resume_typeinfos \
shallow
+# The completion test requires mdb to use readline, even though
+# the input is not a terminal.
+MLFLAGS-completion = --runtime-flags --force-readline
+
MCFLAGS-shallow = --trace shallow
MCFLAGS-tabled_read = --trace-table-io
MCFLAGS-tabled_read_decl = --trace-table-io-decl
@@ -128,6 +133,11 @@
cmd_quote.out: cmd_quote cmd_quote.inp
$(MDB) ./cmd_quote < cmd_quote.inp 2>&1 | \
sed 's/io.m:[0-9]*/io.m:NNNN/g' > cmd_quote.out 2>&1
+
+# Set up readline to make it easier to use completion non-interactively.
+completion.out: completion completion.inp
+ INPUTRC=completion.inputrc $(MDB) ./completion \
+ < completion.inp > completion.out 2>&1
debugger_regs.out: debugger_regs debugger_regs.inp
$(MDB) ./debugger_regs < debugger_regs.inp > debugger_regs.out 2>&1
only in patch2:
--- runtime/mercury_wrapper.h 24 Feb 2002 11:53:37 -0000 1.51
+++ runtime/mercury_wrapper.h 4 Mar 2002 13:40:39 -0000
@@ -220,6 +220,9 @@
/* should mdb be started in a window */
extern MR_bool MR_mdb_in_window;
+/* use readline() in the debugger even if the input stream is not a tty */
+extern MR_bool MR_force_readline;
+
/* size of the primary cache */
extern size_t MR_pcache_size;
only in patch2:
--- runtime/mercury_wrapper.c 24 Feb 2002 11:53:36 -0000 1.102
+++ runtime/mercury_wrapper.c 5 Mar 2002 14:53:44 -0000
@@ -103,6 +103,9 @@
const char *MR_mdb_err_filename = NULL;
MR_bool MR_mdb_in_window = MR_FALSE;
+/* use readline() in the debugger even if the input stream is not a tty */
+MR_bool MR_force_readline = MR_FALSE;
+
/* other options */
MR_bool MR_check_space = MR_FALSE;
@@ -753,6 +756,7 @@
MR_MDB_OUT,
MR_MDB_ERR,
MR_MDB_IN_WINDOW,
+ MR_FORCE_READLINE,
MR_NUM_OUTPUT_ARGS
};
@@ -773,6 +777,7 @@
{ "mdb-out", 1, 0, MR_MDB_OUT },
{ "mdb-err", 1, 0, MR_MDB_ERR },
{ "mdb-in-window", 0, 0, MR_MDB_IN_WINDOW },
+ { "force-readline", 0, 0, MR_FORCE_READLINE },
{ "num-output-args", 1, 0, MR_NUM_OUTPUT_ARGS }
};
@@ -901,6 +906,18 @@
MR_mdb_in_window = MR_TRUE;
break;
+ case MR_FORCE_READLINE:
+ MR_force_readline = MR_TRUE;
+#ifdef MR_NO_USE_READLINE
+ printf(
+"Mercury runtime: `--force-readline' is specified in MERCURY_OPTIONS\n");
+ printf(
+"but readline() is not available.\n");
+ fflush(stdout);
+ exit(1);
+#endif
+ break;
+
case 'a':
benchmark_all_solns = MR_TRUE;
break;
@@ -1092,7 +1109,7 @@
"the word `%s'\n"
"which is not an option. Please refer to the "
"Environment Variables section\n"
- "of the Mercury user's guide for details.\n",
+ "of the Mercury User's Guide for details.\n",
argv[MR_optind]);
fflush(stdout);
exit(1);
@@ -1105,7 +1122,7 @@
printf("The MERCURY_OPTIONS environment variable "
"contains an invalid option.\n"
"Please refer to the Environment Variables section of "
- "the Mercury\nuser's guide for details.\n");
+ "the Mercury\nUser's Guide for details.\n");
fflush(stdout);
exit(1);
} /* end usage() */
--------------------------------------------------------------------------
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