mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-14 05:12:33 +00:00
Add a new mdb command, 'shell', that allows users to execute shell commands
Estimated hours taken: 5 Branches: main Add a new mdb command, 'shell', that allows users to execute shell commands from within the debugger. Allow the user to give up to nine additional arguments to the 'source' command. Occurrences of the strings "$1" through "$9" in the sourced file are replaced by the corresponding additional arguments, allowing for parameterised scripts. Use the two new features mentioned above to add two more mdb commands: one to open a term, goal or exception in an external editor another command to perform a grep on a term, goal or exception (useful for seeing if a value occurs in a big map, for example). NEWS Mention the new commands. doc/mdb_categories: doc/user_guide.texi: Document the new commands. scripts/Mmakefile: scripts/mdb_open: scripts/mdb_vim: Add scripts for the new commands. scripts/mdbrc.in: Add aliases for the new shell, emacs, grep and vim commands. tests/debugger/completion.exp: tests/debugger/mdb_command_test.inp: Adjust for new commands. tests/debugger/save.exp: tests/debugger/save.exp2: Adjust for new commands. Replace system dependent strings with ZZZ instead of XXX. tests/debugger/Mmakefile: tests/debugger/shell.exp: tests/debugger/shell.inp: tests/debugger/shell.m: tests/debugger/shell_test_script: Test the shell and source commands. trace/mercury_trace_cmd_misc.c: Check if there are extra arguments to the source mdb command and pass them to MR_trace_source if there are. trace/mercury_trace_cmd_misc.h: Add shell command handling function prototype. trace/mercury_trace_declarative.c: Call MR_trace_call_system_display_error_on_failure instead of system when displaying benchmarking statistics for the declarative debugger. trace/mercury_trace_internal.c: trace/mercury_trace_internal.h: Implement the shell command and extend the source command to handle the optional extra arguments. trace/mercury_trace_readline.c: trace/mercury_trace_readline.h: Add a new function to read a line and replace all the occurrences of "$[1-9]" with the corresponding value from an array. Delete comments in the .c file that are duplicated in the .h file. trace/mercury_trace_util.c: trace/mercury_trace_util.h: Implement MR_trace_call_system_display_error_on_failure that executes a system call and displays an error message if the system call terminates abnormally.
This commit is contained in:
51
NEWS
51
NEWS
@@ -69,6 +69,12 @@ Changes to the Mercury debugger:
|
||||
left the goal at which the term was available as the value of a program
|
||||
variable.
|
||||
* Users can now see the set of places where two terms differ from each other.
|
||||
* Users can now execute system shell commands from within the debugger.
|
||||
* The source command now accepts optional additional arguments which
|
||||
are substituted into the sourced file, allowing for parameterised
|
||||
scripts.
|
||||
* Users can now open terms in their favorite editor, or
|
||||
perform a grep on a term.
|
||||
* The `set' command has been replaced by several other commands: the `format',
|
||||
`format_param', `list_context_lines', `list_path', `xml_browser_cmd',
|
||||
`xml_tmp_filename', `fail_trace_counts', `pass_trace_counts' and
|
||||
@@ -77,8 +83,9 @@ Changes to the Mercury debugger:
|
||||
* The `save' command now saves the entire persistent state of the debugger
|
||||
(with one small exception that cannot be reestablished by an mdb command from
|
||||
an arbitrary point of execution).
|
||||
* The declarative debugger now supports an `undo' command, and allows users to
|
||||
select the search algorithm.
|
||||
* The declarative debugger now supports an `undo' command.
|
||||
* The declarative debugger now allows users to
|
||||
change the search algorithm mid-session.
|
||||
* The declarative debugger can now exploit information from the "code
|
||||
footprints" of passed and failed test cases to find bugs with fewer
|
||||
questions. We have also added two tools, mslice and mdice, to manipulate
|
||||
@@ -314,6 +321,46 @@ Changes to the Mercury compiler:
|
||||
in which the format string or the structure of the list of values to be
|
||||
printed are not statically available.
|
||||
|
||||
Changes to the Mercury debugger:
|
||||
|
||||
* A `list' command has ben added that displays a listing of the source code
|
||||
lines referred to by the current environment. To supporting commands
|
||||
`pop_list_dir' and `push_list_dir' have also been added.
|
||||
|
||||
* Users can now keep hold of a term, referring to it even when execution has
|
||||
left the goal at which the term was available as the value of a program
|
||||
variable. The name of the new command is `hold'.
|
||||
|
||||
* A `diff' command has been added that allows users to see the set of places
|
||||
where two terms differ from each other.
|
||||
|
||||
* A `shell' (or `!' for short) command has been added that allows users to
|
||||
execute system shell commands from within the debugger.
|
||||
|
||||
* The `source' command now accepts optional additional arguments which
|
||||
are substituted into the sourced file, allowing for parameterised
|
||||
scripts. The strings "$1" through "$9" in the sourced file are replaced with
|
||||
the corresponding argument of the `source' command.
|
||||
|
||||
* The above two features have been used to create two additional commands: an
|
||||
`open' command that lets users open a term in their favorite editor for
|
||||
browsing and a `grep' command that can be used to check if a term contains
|
||||
a particular pattern.
|
||||
|
||||
* The declarative debugger now allows users to take back answers they gave
|
||||
by means of an multi-level `undo' command.
|
||||
|
||||
* The declarative debugger now allows users to change the search algorithm
|
||||
mid-session by means of a `mode' command.
|
||||
|
||||
* The declarative debugger can now exploit information from the "code
|
||||
footprints" of passed and failed test cases to find bugs with fewer
|
||||
questions. We have also added two tools, mslice and mdice, to manipulate
|
||||
files containing such footprints.
|
||||
|
||||
* Subterm dependency tracking in the declarative debugger is now significantly
|
||||
faster.
|
||||
|
||||
Changes to the extras distribution:
|
||||
|
||||
* We've added a library of data structures designed to work for solver types.
|
||||
|
||||
@@ -27,7 +27,7 @@ document_category 400 browsing
|
||||
browsing - Commands that let users explore the state of the computation.
|
||||
The browsing commands are `vars', `held_vars', `print', `browse',
|
||||
`stack', `up', `down', `level', `current', `view', `hold',
|
||||
`diff', `dump', and `list'.
|
||||
`diff', `dump', `grep', `list' and `open'.
|
||||
|
||||
end
|
||||
document_category 500 breakpoint
|
||||
@@ -70,8 +70,8 @@ decl - Commands available from within the declarative debugger. These
|
||||
end
|
||||
document_category 900 misc
|
||||
misc - Commands that are of interest to most users but do not fit into
|
||||
other categories. The misc commands are `source', `save' and
|
||||
`quit'.
|
||||
other categories. The misc commands are `source', `save', `shell'
|
||||
and `quit'.
|
||||
|
||||
end
|
||||
document_category 1000 exp
|
||||
|
||||
@@ -2870,6 +2870,22 @@ Writes the value of the variable in the current environment
|
||||
with the given ordinal number or with the given name
|
||||
to the specified file. The option @samp{-x} (or @samp{--xml}) causes the
|
||||
output to be in XML.
|
||||
@sp 1
|
||||
@item open @var{term}
|
||||
Save @var{term} to a temporary file and open the file in an editor.
|
||||
The environment variable EDITOR is consulted to determine what editor to
|
||||
use.
|
||||
If this environment variable is not set then @samp{vi} is used.
|
||||
@var{term} may be any term that can be saved to a file with the
|
||||
@samp{save_to_file} command.
|
||||
@sp 1
|
||||
@item grep @var{pattern} @var{term}
|
||||
Save the given term to a temporary file and perform a grep on the
|
||||
file using @var{pattern}.
|
||||
@var{term} may be any term that can be saved to a file with the
|
||||
@samp{save_to_file} command.
|
||||
The unix `grep' command must be available from the shell for this command
|
||||
to work.
|
||||
@c @sp 1
|
||||
@c @item dump [-x] proc_body @var{filename}
|
||||
@c Writes the representation of the body of the current procedure,
|
||||
@@ -3799,9 +3815,13 @@ and its submodules, if any.
|
||||
|
||||
@sp 1
|
||||
@table @code
|
||||
@item source [-i] @var{filename}
|
||||
@item source [-i] @var{filename} [@var{args}]
|
||||
@kindex source (mdb command)
|
||||
Executes the commands in the file named @var{filename}.
|
||||
Optionally a list of at most nine arguments can be given.
|
||||
Occurrences of the strings "$1" to "$9" in the sourced file
|
||||
will be replaced by the corresponding arguments given in the source
|
||||
command before the commands in the sourced file are executed.
|
||||
@sp 1
|
||||
The option @samp{-i} or @samp{--ignore-errors} tells @samp{mdb}
|
||||
not to complain if the named file does not exist or is not readable.
|
||||
|
||||
@@ -48,7 +48,11 @@ CONF_FILES = \
|
||||
CONF_DEBUG_SCRIPTS = \
|
||||
mdbrc
|
||||
|
||||
DEBUGGER_SCRIPTS = $(CONF_DEBUG_SCRIPTS) xul_tree.xsl
|
||||
DEBUGGER_SCRIPTS = $(CONF_DEBUG_SCRIPTS) \
|
||||
xul_tree.xsl \
|
||||
mdb_open \
|
||||
mdb_grep
|
||||
|
||||
EMACS_SCRIPTS = gud.el
|
||||
|
||||
#-----------------------------------------------------------------------------#
|
||||
|
||||
3
scripts/mdb_grep
Normal file
3
scripts/mdb_grep
Normal file
@@ -0,0 +1,3 @@
|
||||
save_to_file $2 .mdb_grep_tmp
|
||||
shell grep $1 .mdb_grep_tmp
|
||||
shell rm .mdb_grep_tmp
|
||||
3
scripts/mdb_open
Normal file
3
scripts/mdb_open
Normal file
@@ -0,0 +1,3 @@
|
||||
save_to_file $1 .mdb_open_tmp
|
||||
shell ${EDITOR-vi} .mdb_open_tmp
|
||||
shell rm .mdb_open_tmp
|
||||
@@ -15,5 +15,8 @@ alias excp exception
|
||||
alias e exception
|
||||
alias EMPTY step
|
||||
alias NUMBER step
|
||||
alias ! shell
|
||||
alias open source @DEFAULT_MERCURY_DEBUGGER_INIT_DIR@/mdb_open
|
||||
alias grep source @DEFAULT_MERCURY_DEBUGGER_INIT_DIR@/mdb_grep
|
||||
xml_browser_cmd '@DEFAULT_XML_BROWSER_CMD@'
|
||||
xml_tmp_filename '@DEFAULT_XML_TMP_FILENAME@'
|
||||
|
||||
@@ -47,6 +47,7 @@ NONRETRY_PROGS = \
|
||||
print_table \
|
||||
queens_rep \
|
||||
resume_typeinfos \
|
||||
shell \
|
||||
save \
|
||||
solver_test \
|
||||
type_desc_test \
|
||||
@@ -469,13 +470,18 @@ retry.out: retry retry.inp
|
||||
# with a known character sequence.
|
||||
save.out: save save.inp
|
||||
$(MDB) ./save < save.inp 2>&1 | \
|
||||
sed 's/xml_browser_cmd.*/xml_browser_cmd XXX/g' | \
|
||||
sed 's/xml_tmp_filename.*/xml_tmp_filename XXX/g' \
|
||||
sed 's/xml_browser_cmd.*/xml_browser_cmd ZZZ/g' | \
|
||||
sed 's/xml_tmp_filename.*/xml_tmp_filename ZZZ/g' | \
|
||||
sed 's/^alias grep source.*$$/alias grep source ZZZ\/mdb_grep/' | \
|
||||
sed 's/^alias open source.*$$/alias open source ZZZ\/mdb_open/' \
|
||||
> save.out 2>&1
|
||||
|
||||
shallow.out: shallow shallow.inp
|
||||
$(MDB) ./shallow < shallow.inp > shallow.out 2>&1
|
||||
|
||||
shell.out: shell shell.inp
|
||||
$(MDB_STD) ./shell < shell.inp > shell.out 2>&1
|
||||
|
||||
solver_test.out: solver_test solver_test.inp
|
||||
$(MDB_STD) ./solver_test < solver_test.inp > solver_test.out 2>&1
|
||||
|
||||
|
||||
@@ -3,43 +3,45 @@ mdb> echo on
|
||||
Command echo enabled.
|
||||
mdb> register --quiet
|
||||
mdb>
|
||||
? excp print_optionals
|
||||
P f printlevel
|
||||
alias fail_trace_counts procedures
|
||||
all_class_decls finish push_list_dir
|
||||
all_procedures flag query
|
||||
all_regs format quit
|
||||
all_type_ctors format_param r
|
||||
ambiguity forward register
|
||||
b g retry
|
||||
break gen_stack return
|
||||
break_print goal_paths s
|
||||
browse goto save
|
||||
c h scope
|
||||
cc_query held_vars scroll
|
||||
class_decl help source
|
||||
clear_histogram histogram_all stack
|
||||
condition histogram_exp stack_default_limit
|
||||
consumer hold stack_regs
|
||||
context ignore stats
|
||||
continue io_query step
|
||||
current level subgoal
|
||||
cut_stack list table
|
||||
d list_context_lines table_io
|
||||
dd list_path term_size
|
||||
debug_vars max_io_actions trust
|
||||
delete maxdepth trusted
|
||||
dice mindepth type_ctor
|
||||
diff mm_stacks unalias
|
||||
disable mmc_options unhide_events
|
||||
document modules untrust
|
||||
document_category next up
|
||||
down nondet_stack v
|
||||
dump p var_details
|
||||
e pass_trace_counts vars
|
||||
echo pneg_stack view
|
||||
enable pop_list_dir xml_browser_cmd
|
||||
exception print xml_tmp_filename
|
||||
! f printlevel
|
||||
? fail_trace_counts procedures
|
||||
P finish push_list_dir
|
||||
alias flag query
|
||||
all_class_decls format quit
|
||||
all_procedures format_param r
|
||||
all_regs forward register
|
||||
all_type_ctors g retry
|
||||
ambiguity gen_stack return
|
||||
b goal_paths s
|
||||
break goto save
|
||||
break_print grep scope
|
||||
browse h scroll
|
||||
c held_vars shell
|
||||
cc_query help source
|
||||
class_decl histogram_all stack
|
||||
clear_histogram histogram_exp stack_default_limit
|
||||
condition hold stack_regs
|
||||
consumer ignore stats
|
||||
context io_query step
|
||||
continue level subgoal
|
||||
current list table
|
||||
cut_stack list_context_lines table_io
|
||||
d list_path term_size
|
||||
dd max_io_actions trust
|
||||
debug_vars maxdepth trusted
|
||||
delete mindepth type_ctor
|
||||
dice mm_stacks unalias
|
||||
diff mmc_options unhide_events
|
||||
disable modules untrust
|
||||
document next up
|
||||
document_category nondet_stack v
|
||||
down open var_details
|
||||
dump p vars
|
||||
e pass_trace_counts view
|
||||
echo pneg_stack xml_browser_cmd
|
||||
enable pop_list_dir xml_tmp_filename
|
||||
exception print
|
||||
excp print_optionals
|
||||
h help histogram_exp
|
||||
held_vars histogram_all hold
|
||||
var_details vars view
|
||||
|
||||
@@ -46,6 +46,8 @@ view xyzzy xyzzy xyzzy xyzzy xyzzy
|
||||
hold xyzzy xyzzy xyzzy xyzzy xyzzy
|
||||
diff xyzzy xyzzy xyzzy xyzzy xyzzy
|
||||
dump xyzzy xyzzy xyzzy xyzzy xyzzy
|
||||
open xyzzy xyzzy xyzzy xyzzy xyzzy
|
||||
grep xyzzy xyzzy xyzzy xyzzy xyzzy
|
||||
list xyzzy xyzzy xyzzy xyzzy xyzzy
|
||||
break xyzzy xyzzy xyzzy xyzzy xyzzy
|
||||
condition xyzzy xyzzy xyzzy xyzzy xyzzy
|
||||
|
||||
@@ -21,6 +21,7 @@ mdb> save save_file
|
||||
Debugger state saved to save_file.
|
||||
mdb> continue -n -S
|
||||
[1, 3, 5, 2, 4]
|
||||
alias ! shell
|
||||
alias ? help
|
||||
alias EMPTY step
|
||||
alias NUMBER step
|
||||
@@ -32,7 +33,9 @@ alias e exception
|
||||
alias excp exception
|
||||
alias f finish
|
||||
alias g goto
|
||||
alias grep source ZZZ/mdb_grep
|
||||
alias h help
|
||||
alias open source ZZZ/mdb_open
|
||||
alias p print
|
||||
alias r retry
|
||||
alias s step
|
||||
|
||||
@@ -21,6 +21,7 @@ mdb> save save_file
|
||||
Debugger state saved to save_file.
|
||||
mdb> continue -n -S
|
||||
[1, 3, 5, 2, 4]
|
||||
alias ! shell
|
||||
alias ? help
|
||||
alias EMPTY step
|
||||
alias NUMBER step
|
||||
@@ -32,7 +33,9 @@ alias e exception
|
||||
alias excp exception
|
||||
alias f finish
|
||||
alias g goto
|
||||
alias grep source ZZZ/mdb_grep
|
||||
alias h help
|
||||
alias open source ZZZ/mdb_open
|
||||
alias p print
|
||||
alias r retry
|
||||
alias s step
|
||||
@@ -101,8 +104,8 @@ format_param -A -p size 10
|
||||
format_param -A -p width 80
|
||||
format_param -A -p lines 2
|
||||
max_io_actions 20
|
||||
xml_browser_cmd XXX
|
||||
xml_tmp_filename XXX
|
||||
xml_browser_cmd ZZZ
|
||||
xml_tmp_filename ZZZ
|
||||
trust save
|
||||
trust std lib
|
||||
list_context_lines 2
|
||||
|
||||
16
tests/debugger/shell.exp
Normal file
16
tests/debugger/shell.exp
Normal file
@@ -0,0 +1,16 @@
|
||||
E1: C1 CALL pred shell.main/2-0 (det) shell.m:11
|
||||
mdb> echo on
|
||||
Command echo enabled.
|
||||
mdb> shell echo hello
|
||||
hello
|
||||
mdb> alias test source shell_test_script
|
||||
test => source shell_test_script
|
||||
mdb> test value1 value2 3 'value 4' "a" '' 'b' file_name.ext 9
|
||||
value1 value2
|
||||
value2 value1
|
||||
value1 value2 $ $abc 3 value 4 a b file_name.ext 9 $0 $b $
|
||||
mdb> test only_one_value
|
||||
only_one_value
|
||||
only_one_value
|
||||
only_one_value $ $abc $0 $b $
|
||||
mdb> quit -y
|
||||
6
tests/debugger/shell.inp
Normal file
6
tests/debugger/shell.inp
Normal file
@@ -0,0 +1,6 @@
|
||||
echo on
|
||||
shell echo hello
|
||||
alias test source shell_test_script
|
||||
test value1 value2 3 'value 4' "a" '' 'b' file_name.ext 9
|
||||
test only_one_value
|
||||
quit -y
|
||||
12
tests/debugger/shell.m
Normal file
12
tests/debugger/shell.m
Normal file
@@ -0,0 +1,12 @@
|
||||
:- module shell.
|
||||
|
||||
:- interface.
|
||||
|
||||
:- import_module io.
|
||||
|
||||
:- pred main(io::di, io::uo) is det.
|
||||
|
||||
:- implementation.
|
||||
|
||||
main(!IO) :-
|
||||
nl(!IO).
|
||||
3
tests/debugger/shell_test_script
Normal file
3
tests/debugger/shell_test_script
Normal file
@@ -0,0 +1,3 @@
|
||||
shell echo $1 $2
|
||||
shell echo $2 $1
|
||||
shell echo $1 $2 $ \\$abc $3 $4 $5 $6 $7 $8 $9 \\$0 \\$b $
|
||||
@@ -47,17 +47,24 @@ MR_trace_cmd_source(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
|
||||
MR_Event_Info *event_info, MR_Code **jumpaddr)
|
||||
{
|
||||
MR_bool ignore_errors;
|
||||
char **args;
|
||||
|
||||
ignore_errors = MR_FALSE;
|
||||
if (! MR_trace_options_ignore(&ignore_errors, &words, &word_count)) {
|
||||
; /* the usage message has already been printed */
|
||||
} else if (word_count == 2) {
|
||||
} else if (word_count >= 2) {
|
||||
/*
|
||||
** If the source fails, the error message
|
||||
** will have already been printed by MR_trace_source
|
||||
** (unless ignore_errors suppresses the message).
|
||||
*/
|
||||
(void) MR_trace_source(words[1], ignore_errors);
|
||||
if (word_count == 2) {
|
||||
args = NULL;
|
||||
} else {
|
||||
args = &words[2];
|
||||
}
|
||||
(void) MR_trace_source(words[1], ignore_errors, args,
|
||||
word_count - 2);
|
||||
} else {
|
||||
MR_trace_usage_cur_cmd();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
extern MR_TraceCmdFunc MR_trace_cmd_source;
|
||||
extern MR_TraceCmdFunc MR_trace_cmd_save;
|
||||
extern MR_TraceCmdFunc MR_trace_cmd_shell;
|
||||
extern MR_TraceCmdFunc MR_trace_cmd_quit;
|
||||
|
||||
extern const char *const MR_trace_source_cmd_args[];
|
||||
|
||||
@@ -2434,7 +2434,7 @@ MR_decl_print_edt_stats(void)
|
||||
pid = getpid();
|
||||
sprintf(cmdstr, "ps -p %i -o rss,vsz | tail -1 |"
|
||||
"awk '{print \"RSS = \" $1 \"\\nVSZ = \" $2}' 1>&2", pid);
|
||||
system(cmdstr);
|
||||
MR_trace_call_system_display_error_on_failure(stderr, cmdstr);
|
||||
|
||||
MR_debug_enabled = MR_FALSE;
|
||||
MR_update_trace_func_enabled();
|
||||
|
||||
@@ -634,7 +634,7 @@ MR_trace_internal_init_from_env(void)
|
||||
|
||||
init = getenv("MERCURY_DEBUGGER_INIT");
|
||||
if (init != NULL) {
|
||||
(void) MR_trace_source(init, MR_FALSE);
|
||||
(void) MR_trace_source(init, MR_FALSE, NULL, 0);
|
||||
/* If the source failed, the error message has been printed. */
|
||||
}
|
||||
}
|
||||
@@ -647,7 +647,7 @@ MR_trace_internal_init_from_local(void)
|
||||
|
||||
init = MDBRC_FILENAME;
|
||||
if ((fp = fopen(init, "r")) != NULL) {
|
||||
MR_trace_source_from_open_file(fp);
|
||||
MR_trace_source_from_open_file(fp, NULL, 0);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
@@ -671,7 +671,7 @@ MR_trace_internal_init_from_home_dir(void)
|
||||
(void) strcat(buf, "/");
|
||||
(void) strcat(buf, MDBRC_FILENAME);
|
||||
if ((fp = fopen(buf, "r")) != NULL) {
|
||||
MR_trace_source_from_open_file(fp);
|
||||
MR_trace_source_from_open_file(fp, NULL, 0);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
@@ -679,12 +679,13 @@ MR_trace_internal_init_from_home_dir(void)
|
||||
}
|
||||
|
||||
MR_bool
|
||||
MR_trace_source(const char *filename, MR_bool ignore_errors)
|
||||
MR_trace_source(const char *filename, MR_bool ignore_errors,
|
||||
char** args, int num_args)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen(filename, "r")) != NULL) {
|
||||
MR_trace_source_from_open_file(fp);
|
||||
MR_trace_source_from_open_file(fp, args, num_args);
|
||||
fclose(fp);
|
||||
return MR_TRUE;
|
||||
}
|
||||
@@ -698,7 +699,7 @@ MR_trace_source(const char *filename, MR_bool ignore_errors)
|
||||
}
|
||||
|
||||
void
|
||||
MR_trace_source_from_open_file(FILE *fp)
|
||||
MR_trace_source_from_open_file(FILE *fp, char **args, int num_args)
|
||||
{
|
||||
char *contents;
|
||||
MR_Line *line;
|
||||
@@ -713,7 +714,9 @@ MR_trace_source_from_open_file(FILE *fp)
|
||||
** preserving their order in the sourced file.
|
||||
*/
|
||||
|
||||
while ((contents = MR_trace_readline_raw(fp)) != NULL) {
|
||||
while ((contents = MR_trace_readline_expand_args(fp, args, num_args))
|
||||
!= NULL)
|
||||
{
|
||||
line = MR_NEW(MR_Line);
|
||||
line->MR_line_contents = MR_copy_string(contents);
|
||||
|
||||
@@ -751,6 +754,31 @@ MR_trace_do_noop(void)
|
||||
** MR_process_matching_procedures().
|
||||
*/
|
||||
|
||||
static MR_Next
|
||||
MR_trace_cmd_shell(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
|
||||
MR_Event_Info *event_info, MR_Code **jumpaddr)
|
||||
{
|
||||
char* command_string;
|
||||
size_t command_string_length;
|
||||
int word_num;
|
||||
|
||||
command_string_length = 1;
|
||||
for (word_num = 1; word_num < word_count; word_num++) {
|
||||
command_string_length += strlen(words[word_num]) + 1;
|
||||
}
|
||||
command_string = (char*) MR_malloc(sizeof(char) * command_string_length);
|
||||
command_string[0] = '\0';
|
||||
for (word_num = 1; word_num < word_count; word_num++) {
|
||||
strcat(command_string, words[word_num]);
|
||||
strcat(command_string, " ");
|
||||
}
|
||||
|
||||
MR_trace_call_system_display_error_on_failure(MR_mdb_err, command_string);
|
||||
MR_free(command_string);
|
||||
|
||||
return KEEP_INTERACTING;
|
||||
}
|
||||
|
||||
static void
|
||||
MR_mdb_print_proc_id_and_nl(void *data, const MR_Proc_Layout *entry_layout)
|
||||
{
|
||||
@@ -1628,6 +1656,8 @@ static const MR_Trace_Command_Info MR_trace_command_infos[] =
|
||||
NULL, MR_trace_filename_completer },
|
||||
{ "misc", "quit", MR_trace_cmd_quit,
|
||||
MR_trace_quit_cmd_args, MR_trace_null_completer },
|
||||
{ "misc", "shell", MR_trace_cmd_shell,
|
||||
NULL, MR_trace_null_completer },
|
||||
|
||||
{ "exp", "histogram_all", MR_trace_cmd_histogram_all,
|
||||
NULL, MR_trace_filename_completer },
|
||||
|
||||
@@ -83,13 +83,14 @@ extern MR_Trace_Source_Server MR_trace_source_server;
|
||||
*/
|
||||
|
||||
extern MR_bool MR_trace_source(const char *filename,
|
||||
MR_bool ignore_errors);
|
||||
MR_bool ignore_errors, char** args, int num_args);
|
||||
|
||||
/*
|
||||
** Source commands from the given file.
|
||||
*/
|
||||
|
||||
extern void MR_trace_source_from_open_file(FILE *fp);
|
||||
extern void MR_trace_source_from_open_file(FILE *fp,
|
||||
char **args, int num_args);
|
||||
|
||||
/*
|
||||
** Print a usage message for the currently executing command.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1998-2002, 2005 The University of Melbourne.
|
||||
** Copyright (C) 1998-2002, 2005-2006 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.
|
||||
*/
|
||||
@@ -50,13 +50,6 @@
|
||||
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
|
||||
** 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)
|
||||
{
|
||||
@@ -147,12 +140,6 @@ MR_trace_readline(const char *prompt, FILE *in, FILE *out)
|
||||
return MR_trace_readline_raw(in);
|
||||
}
|
||||
|
||||
/*
|
||||
** Read a line from a file, and return a pointer to a MR_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)
|
||||
{
|
||||
@@ -180,6 +167,65 @@ MR_trace_readline_raw(FILE *fp)
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
MR_trace_readline_expand_args(FILE *fp, char **args, int num_args)
|
||||
{
|
||||
char *line;
|
||||
size_t line_length;
|
||||
int line_index;
|
||||
size_t expanded_line_length;
|
||||
char *expanded_line;
|
||||
int expanded_line_index;
|
||||
int arg_num;
|
||||
size_t arg_length;
|
||||
char *arg;
|
||||
|
||||
line = MR_trace_readline_raw(fp);
|
||||
if (line == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
line_length = strlen(line);
|
||||
|
||||
expanded_line_length = line_length;
|
||||
expanded_line = (char*) MR_malloc(line_length + 1);
|
||||
expanded_line[0] = '\0';
|
||||
expanded_line_index = 0;
|
||||
|
||||
for (line_index = 0; line_index < line_length; line_index++) {
|
||||
if ((line[line_index] == '$') &&
|
||||
(line_index < (line_length - 1)) &&
|
||||
(line[line_index + 1] >= '1') &&
|
||||
(line[line_index + 1] <= '9'))
|
||||
{
|
||||
arg_num = (int)(line[line_index + 1] - '1');
|
||||
if (arg_num < num_args) {
|
||||
arg = args[arg_num];
|
||||
arg_length = strlen(arg);
|
||||
/*
|
||||
** Subtract 2 for the "$n" which will
|
||||
** not occur in the expanded string.
|
||||
*/
|
||||
expanded_line_length += arg_length - 2;
|
||||
expanded_line = MR_realloc(expanded_line,
|
||||
expanded_line_length + 1);
|
||||
expanded_line[expanded_line_index] = '\0';
|
||||
strcat(expanded_line, arg);
|
||||
expanded_line_index += arg_length;
|
||||
}
|
||||
/* Skip the digit after the '$'. */
|
||||
line_index++;
|
||||
} else {
|
||||
expanded_line[expanded_line_index] = line[line_index];
|
||||
expanded_line_index++;
|
||||
}
|
||||
}
|
||||
|
||||
MR_free(line);
|
||||
expanded_line[expanded_line_index] = '\0';
|
||||
|
||||
return expanded_line;
|
||||
}
|
||||
|
||||
static void
|
||||
MR_dummy_prep_term_function(int ignored)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1998-1999 The University of Melbourne.
|
||||
** Copyright (C) 1998-1999, 2006 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.
|
||||
*/
|
||||
@@ -28,3 +28,15 @@ char * MR_trace_readline(const char *prompt, FILE *in, FILE *out);
|
||||
** line, return NULL. Don't use GNU readline.
|
||||
*/
|
||||
char * MR_trace_readline_raw(FILE *in);
|
||||
|
||||
/*
|
||||
** Read a line from a file and replace occurrences of the strings "$1" to
|
||||
** "$9" with the corresponding values in the args array. If there is no
|
||||
** value in the args array, then the "$n" string is replaced by the empty
|
||||
** string.
|
||||
** Return a pointer to a MR_malloc'd buffer holding the new string (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_expand_args(FILE *fp, char **args, int num_args);
|
||||
|
||||
@@ -207,3 +207,21 @@ MR_trace_proc_layout_is_builtin_catch(const MR_Proc_Layout *layout)
|
||||
}
|
||||
return MR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
MR_trace_call_system_display_error_on_failure(FILE *err_stream, char *command)
|
||||
{
|
||||
int system_rv;
|
||||
|
||||
if (system(NULL)) {
|
||||
system_rv = system(command);
|
||||
if (system_rv != 0) {
|
||||
fprintf(err_stream,
|
||||
"mdb: the shell command returned a non-zero exit code or was"
|
||||
" terminated abnormally.\n",
|
||||
system_rv);
|
||||
}
|
||||
} else {
|
||||
fprintf(err_stream, "mdb: no shell found.\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,4 +78,13 @@ extern void MR_print_debug_vars(FILE *fp, MR_Event_Info *event_info);
|
||||
extern MR_bool MR_trace_proc_layout_is_builtin_catch(
|
||||
const MR_Proc_Layout *layout);
|
||||
|
||||
/*
|
||||
** MR_trace_call_system_display_error_on_failure executes the given command
|
||||
** and displays an error message if the command returned a non-zero exit
|
||||
** status, there was a problem executing the command, or no usable shell was
|
||||
** available.
|
||||
*/
|
||||
extern void MR_trace_call_system_display_error_on_failure(
|
||||
FILE *err_stream, char *command);
|
||||
|
||||
#endif /* MERCURY_TRACE_UTIL_H */
|
||||
|
||||
Reference in New Issue
Block a user