[m-rev.] for review: add 4 new mdb commands

Julien Fischer juliensf at cs.mu.OZ.AU
Mon Mar 13 12:11:49 AEDT 2006


On Sun, 12 Mar 2006, Ian MacLarty wrote:

> 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.
> Occurances of the strings "$1" through "$9" in the sourced file are replaced

s/Occurances/Ocurrences/

> by the corresponding additional arguments, allowing for parameterised
> scripts.
>
> Use the two new features mentioned above to add three more mdb commands: two
> commands to open a term, goal or exception in vim or emacs and a third
> command to perform a grep on a term, goal or exception (useful for seeing if
> a value occurs in a big map, for example).

Is there any reason why this is limited to vim/emacs?  Perhaps it ought
to look for the environment variable EDITOR first.  Similarly there are
several variants of grep that I might want to use.

> NEWS
> 	Mention the new commands.
>
> doc/mdb_categories:
> doc/user_guide.texi:
> 	Document the new commands.
>
> scripts/Mmakefile:
> scripts/mdb_emacs:
> scripts/mdb_grep:
> scripts/mdb_vim:
> 	Add scripts for the new emacs, grep and vim commands.
>
> scripts/mdbrc.in:
> 	Add aliases for the new shell, emacs, grep and vim commands.
>
> 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_internal.c:
> 	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
> 	occurances of "$[1-9]" with the corresponding value from an array.

s/occurances/occurrences/

> 	Delete comments in the .c file that are duplicated in the .h file.
>
> Index: NEWS
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/NEWS,v
> retrieving revision 1.402
> diff -u -r1.402 NEWS
> --- NEWS	8 Mar 2006 02:25:26 -0000	1.402
> +++ NEWS	12 Mar 2006 00:09:13 -0000
> @@ -50,6 +50,12 @@
>    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, goals or exceptions in vim or emacs, or
> +  perform a grep on the term, goal or exception.
>  * The declarative debugger now supports an `undo' command, and allows users to
>    select the search algorithm.
>  * The declarative debugger can now exploit information from the "code

...

> Index: doc/user_guide.texi
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
> retrieving revision 1.470
> diff -u -r1.470 user_guide.texi
> --- doc/user_guide.texi	1 Mar 2006 22:58:44 -0000	1.470
> +++ doc/user_guide.texi	11 Mar 2006 23:43:13 -0000
> @@ -2866,6 +2866,33 @@
>  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.
> + at sp 1
> + at item vim @var{object}
> +Save @var{object} to a temporary file and open the file with the vim
> +editor.
> + at var{object} may be a variable name or number,
> +the word @samp{goal} or
> +the word @samp{exception},
> + at c or the word proc_body,
> +the meanings of which are the same as for the @samp{safe_to_file} command.
> + at sp 1
> + at item emacs @var{object}
> +Save @var{object} to a temporary file and open the file with the emacs
> +editor.

Rather than having separate vim and emacs commands can we not just have
a single edit command that looks up the value of an editor variable somewhere.

> + at var{object} may be a variable name or number,
> +the word @samp{goal} or
> +the word @samp{exception},
> + at c or the word proc_body,
> +the meanings of which are the same as for the @samp{safe_to_file} command.
> + at sp 1
> + at item grep @var{pattern} @var{object}
> +Save the given object to a temporary file and perform a grep on the
> +file using @var{pattern}.
> + at var{object} may be a variable name or number,
> +the word @samp{goal} or
> +the word @samp{exception},
> + at c or the word proc_body,
> +the meanings of which are the same as for the @samp{safe_to_file} command.
>  @c @sp 1
>  @c @item save_to_file [-x] proc_body @var{filename}
>  @c Writes the representation of the body of the current procedure,
> @@ -3737,9 +3764,18 @@
>  In the case that the format itself is being set,
>  these options are ignored.
>  @sp 1
> - at item source [-i] @var{filename}
> + at item shell @var{command}
> + at kindex shell (mdb command)
> +Execute the given command in the system shell.
> + at samp{!} can be used as an alias for @samp{shell}.
> + at sp 1
> + at 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.
> +Occurances of the strings "$1" to "$9" in the sourced file

s/Occurrances/Occurrences/

> +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.


> Index: scripts/mdbrc.in
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/scripts/mdbrc.in,v
> retrieving revision 1.5
> diff -u -r1.5 mdbrc.in
> --- scripts/mdbrc.in	11 Dec 2004 01:59:51 -0000	1.5
> +++ scripts/mdbrc.in	11 Mar 2006 20:52:31 -0000
> @@ -15,5 +15,9 @@
>  alias	e	exception
>  alias	EMPTY	step
>  alias	NUMBER	step
> +alias	!	shell
> +alias	vim	source @DEFAULT_MERCURY_DEBUGGER_INIT_DIR@/mdb_vim
> +alias	emacs	source @DEFAULT_MERCURY_DEBUGGER_INIT_DIR@/mdb_emacs
> +alias	grep	source @DEFAULT_MERCURY_DEBUGGER_INIT_DIR@/mdb_grep
>  set xml_browser_cmd '@DEFAULT_XML_BROWSER_CMD@'
>  set xml_tmp_filename '@DEFAULT_XML_TMP_FILENAME@'
> Index: tests/debugger/Mmakefile
> ===================================================================
> RCS file: /home/mercury1/repository/tests/debugger/Mmakefile,v
> retrieving revision 1.120
> diff -u -r1.120 Mmakefile
> --- tests/debugger/Mmakefile	1 Mar 2006 22:58:47 -0000	1.120
> +++ tests/debugger/Mmakefile	11 Mar 2006 16:47:30 -0000
> @@ -47,6 +47,7 @@
>  	print_table			\
>  	queens_rep			\
>  	resume_typeinfos		\
> +	shell				\
>  	solver_test			\
>  	type_desc_test			\
>  	uci_index
> @@ -477,6 +478,9 @@
>  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
>

...

> RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
> retrieving revision 1.221
> diff -u -r1.221 mercury_trace_internal.c
> --- trace/mercury_trace_internal.c	1 Mar 2006 22:58:50 -0000	1.221
> +++ trace/mercury_trace_internal.c	11 Mar 2006 21:45:44 -0000
> @@ -542,6 +542,7 @@
>  static  MR_TraceCmdFunc MR_trace_cmd_untrust;
>  static  MR_TraceCmdFunc MR_trace_cmd_trusted;
>  static  MR_TraceCmdFunc MR_trace_cmd_dice;
> +static  MR_TraceCmdFunc MR_trace_cmd_shell;
>
>  static  void        MR_maybe_print_spy_point(int slot, const char *problem);
>  static  void        MR_print_unsigned_var(FILE *fp, const char *var,
> @@ -749,8 +750,9 @@
>  static  void        MR_trace_expand_aliases(char ***words,
>                          int *word_max, int *word_count);
>  static  MR_bool     MR_trace_source(const char *filename,
> -                        MR_bool ignore_errors);
> -static  void        MR_trace_source_from_open_file(FILE *fp);
> +                        MR_bool ignore_errors, char **args, int num_args);
> +static  void        MR_trace_source_from_open_file(FILE *fp, char **args,
> +                        int num_args);
>  static  char        *MR_trace_getline_queue(void);
>  static  MR_bool     MR_trace_continue_line(char *ptr, MR_bool *single_quoted,
>                          MR_bool *double_quoted);
> @@ -1209,7 +1211,7 @@
>
>      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. */
>      }
>  }
> @@ -1222,7 +1224,7 @@
>
>      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);
>      }
>  }
> @@ -1246,7 +1248,7 @@
>      (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);
>      }
>
> @@ -5753,17 +5755,24 @@
>      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();
>      }
> @@ -6197,6 +6206,31 @@
>      }
>  }
>
> +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;
> +    int         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, " ");
> +    }
> +
> +    system(command_string);

Shouldn't you check that the call to system succeeds?  e.g. that system
doesn't return -1.  Furthermore I think the mdb should run system(NULL)
somewhere and check that a usable shell exists.

> +    MR_free(command_string);
> +
> +    return KEEP_INTERACTING;
> +}

...

> Index: trace/mercury_trace_readline.c
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_readline.c,v
> retrieving revision 1.9
> diff -u -r1.9 mercury_trace_readline.c
> --- trace/mercury_trace_readline.c	6 Apr 2005 01:11:33 -0000	1.9
> +++ trace/mercury_trace_readline.c	11 Mar 2006 23:58:42 -0000
> @@ -50,13 +50,6 @@
>  static	void	MR_dummy_prep_term_function(int ignored);
>  static	void	MR_dummy_deprep_term_function(void);
>
> +char *
> +MR_trace_readline_expand_args(FILE *fp, char **args, int num_args)
> +{
> +	char	*line;
> +	int	line_length;
> +	int	line_index;
> +	int	expanded_line_length;
> +	char	*expanded_line;
> +	int	expanded_line_index;
> +	int	arg_num;
> +	int	arg_length;
> +	char	*arg;
> +

A lot of these could be of type size_t rather than int (and also above).

> +	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)
>  {
> Index: trace/mercury_trace_readline.h
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_readline.h,v
> retrieving revision 1.2
> diff -u -r1.2 mercury_trace_readline.h
> --- trace/mercury_trace_readline.h	18 Oct 1999 15:47:24 -0000	1.2
> +++ trace/mercury_trace_readline.h	11 Mar 2006 23:55:05 -0000
> @@ -28,3 +28,15 @@
>  ** line, return NULL.  Don't use GNU readline.
>  */
>  char *	MR_trace_readline_raw(FILE *in);
> +
> +/*
> +** Read a line from a file and replace occurances of the strings "$1" to

s/occurances/occurrences/

> +** "$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

s/$n$/$n/ ?

> +** 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.

Why not?

Julien.
--------------------------------------------------------------------------
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