This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: Proposed patch for gdb/mi 741
- From: Elena Zannoni <ezannoni at redhat dot com>
- To: "J. Johnston" <jjohnstn at redhat dot com>
- Cc: gdb-patches at sources dot redhat dot com
- Date: Tue, 22 Oct 2002 12:05:51 -0400
- Subject: Re: Proposed patch for gdb/mi 741
- References: <3DA4886F.194D484D@redhat.com>
J. Johnston writes:
> The following solves a number of problems with the mi -environment commands.
> For starters, each command now has an mi cmd wrapper so arguments may use the
> syntax of adding double-quotes to handle extraneous characters such as spaces.
>
> The -environment-pwd command now lists the output in mi syntax:
>
> e.g.
> -environment-pwd
> ^done,cwd="...."
>
> The -environment-directory command has been changed to output in mi format.
> It also has been changed to allow for no arguments being passed.
> If no arguments are passed, it behaves like the gdb dir command and resets the
> source search path to the default, however, no confirmation query is performed. If an empty
> string "" is passed, it is ignored so this can be used to display the current
> search path without modifying it.
>
> e.g.
> -environment-directory /usr/bin /usr/local/bin
> ^done,source-path="/usr/bin:/usr/local/bin:$cdir:$cwd"
>
> The -environment-path command has been changed to output in mi format.
> It also has been changed to allow for no arguments being passed. When
> no arguments are passed, the current object search path is displayed.
>
> e.g.
> -environment-path
> ^done,path="....."
>
> For mi1 or below, the previous behavior is preserved by rerouting the commands
> to their old cli counterparts.
Hmmm, I think the testsuite changes are ok. Also the addition of the
new file is fine. However I don't think we should be duplicating the
mod_path() code. Would it be possible to maybe split mod_path() in 2
or more functions, and have MI call one of them?
I mean
mod_path()
{
do_cli_specific_stuff;
call add_path(args1);
....
}
mi_env_path()
{
do_mi_specific_stuff;
call add_path(args2);
.....
}
similarly for other code that may have been duplicated.
Thanks
Elena
>
> Eli, I have split the doc changes into 741doc.patch for your convenience. Let me know
> if there are any problems.
>
> gdb/mi/ChangeLog:
>
> 2002-10-09 Jeff Johnston <jjohnstn@redhat.com>
>
> * mi-cmds.c (-environment-directory) Change to use mi_cmd_env_dir,
> (-environment-cd): Change to use mi_cmd_env_cd,.
> (-environment-pwd): Change to use mi_cmd_env_pwd.
> (-environment-path): Change to use mi_cmd_env_path.
> * mi-cmds.h (mi_cmd_env_cd, mi_cmd_env_dir): New prototypes.
> (mi_cmd_env_path, mi_cmd_env_pwd): Ditto.
> * mi-cmd-env.c: New file. Part of fix for PR gdb/741.
> * gdbmi.texinfo (environment-cd): Update output and example.
> (environment-pwd): Ditto.
> (environment-dir): Update output, description, and examples.
> (environment-path): Ditto.
>
> gdb/testsuite/gdb.mi/ChangeLog:
>
> 2002-10-09 Jeff Johnston <jjohnstn@redhat.com>
>
> * mi-basics.exp: Change tests for -environment-directory. Also add
> tests for -environment-cd and -environment-pwd. Part of fix for
> PR gdb/741.
>
> Approved, comments?
>
> -- Jeff J.Index: mi/mi-cmd-env.c
> ===================================================================
> RCS file: mi/mi-cmd-env.c
> diff -N mi/mi-cmd-env.c
> --- mi/mi-cmd-env.c 1 Jan 1970 00:00:00 -0000
> +++ mi/mi-cmd-env.c 9 Oct 2002 18:15:59 -0000
> @@ -0,0 +1,320 @@
> +/* MI Command Set - environment commands.
> + Copyright 2002 Free Software Foundation, Inc.
> + Contributed by Red Hat Inc.
> +
> + This file is part of GDB.
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 2 of the License, or
> + (at your option) any later version.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program; if not, write to the Free Software
> + Foundation, Inc., 59 Temple Place - Suite 330,
> + Boston, MA 02111-1307, USA. */
> +
> +#include <string.h>
> +#include <sys/stat.h>
> +
> +#include "defs.h"
> +#include "target.h"
> +#include "frame.h"
> +#include "value.h"
> +#include "mi-cmds.h"
> +#include "mi-out.h"
> +#include "ui-out.h"
> +#include "symtab.h"
> +#include "filenames.h"
> +#include "environ.h"
> +#include "command.h"
> +#include "top.h"
> +
> +extern struct environ *inferior_environ;
> +extern char *source_path;
> +
> +static void env_cli_command (const char *cli, char *args);
> +static void env_mod_path (char *dirname, char **which_path);
> +
> +static const char path_var_name[] = "PATH";
> +
> +/* the following is copied from mi-main.c so for m1 and below we
> + can perform old behavior and use cli commands */
> +static void
> +env_execute_cli_command (const char *cli, char *args)
> +{
> + if (cli != 0)
> + {
> + struct cleanup *old_cleanups;
> + char *run;
> + xasprintf (&run, cli, args);
> + old_cleanups = make_cleanup (xfree, run);
> + execute_command ( /*ui */ run, 0 /*from_tty */ );
> + do_cleanups (old_cleanups);
> + return;
> + }
> +}
> +
> +
> +/* Print working directory. */
> +enum mi_cmd_result
> +mi_cmd_env_pwd (char *command, char **argv, int argc)
> +{
> + if (argc > 0)
> + error ("mi_cmd_env_pwd: No arguments required");
> +
> + if (mi_version (uiout) < 2)
> + {
> + env_execute_cli_command ("pwd", NULL);
> + return MI_CMD_DONE;
> + }
> +
> + /* otherwise mi level 2 or higher */
> +
> + getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
> + ui_out_field_string (uiout, "cwd", gdb_dirbuf);
> +
> + return MI_CMD_DONE;
> +}
> +
> +/* Change working directory. */
> +enum mi_cmd_result
> +mi_cmd_env_cd (char *command, char **argv, int argc)
> +{
> + if (argc == 0 || argc > 1)
> + error ("mi_cmd_env_cd: Usage DIRECTORY");
> +
> + env_execute_cli_command ("cd %s", argv[0]);
> +
> + return MI_CMD_DONE;
> +}
> +
> +static void
> +env_mod_path (char *dirname, char **which_path)
> +{
> + char *old = *which_path;
> + int prefix = 0;
> + char *name = dirname;
> + register char *p;
> + struct stat st;
> +
> + if (dirname == 0 || dirname[0] == '\0')
> + return;
> +
> + dirname = xstrdup (dirname);
> + make_cleanup (xfree, dirname);
> +
> +
> + p = dirname = name + strlen (name);
> +
> + if (!(IS_DIR_SEPARATOR (*name) && p <= name + 1) /* "/" */
> +#ifdef HAVE_DOS_BASED_FILE_SYSTEM
> + /* On MS-DOS and MS-Windows, h:\ is different from h: */
> + && !(p == name + 3 && name[1] == ':') /* "d:/" */
> +#endif
> + && IS_DIR_SEPARATOR (p[-1]))
> + /* Sigh. "foo/" => "foo" */
> + --p;
> + *p = '\0';
> +
> + while (p > name && p[-1] == '.')
> + {
> + if (p - name == 1)
> + {
> + /* "." => getwd (). */
> + name = current_directory;
> + goto append;
> + }
> + else if (p > name + 1 && IS_DIR_SEPARATOR (p[-2]))
> + {
> + if (p - name == 2)
> + {
> + /* "/." => "/". */
> + *--p = '\0';
> + goto append;
> + }
> + else
> + {
> + /* "...foo/." => "...foo". */
> + p -= 2;
> + *p = '\0';
> + continue;
> + }
> + }
> + else
> + break;
> + }
> +
> + if (name[0] == '~')
> + name = tilde_expand (name);
> +#ifdef HAVE_DOS_BASED_FILE_SYSTEM
> + else if (IS_ABSOLUTE_PATH (name) && p == name + 2) /* "d:" => "d:." */
> + name = concat (name, ".", NULL);
> +#endif
> + else if (!IS_ABSOLUTE_PATH (name) && name[0] != '$')
> + name = concat (current_directory, SLASH_STRING, name, NULL);
> + else
> + name = savestring (name, p - name);
> + make_cleanup (xfree, name);
> +
> + /* Unless it's a variable, check existence. */
> + if (name[0] != '$')
> + {
> + /* These are warnings, not errors, since we don't want a
> + non-existent directory in a .gdbinit file to stop processing
> + of the .gdbinit file.
> +
> + Whether they get added to the path is more debatable. Current
> + answer is yes, in case the user wants to go make the directory
> + or whatever. If the directory continues to not exist/not be
> + a directory/etc, then having them in the path should be
> + harmless. */
> + if (stat (name, &st) < 0)
> + {
> + int save_errno = errno;
> + fprintf_unfiltered (gdb_stderr, "Warning: ");
> + print_sys_errmsg (name, save_errno);
> + }
> + else if ((st.st_mode & S_IFMT) != S_IFDIR)
> + warning ("%s is not a directory.", name);
> + }
> +
> + append:
> + {
> + register unsigned int len = strlen (name);
> +
> + p = *which_path;
> + while (1)
> + {
> + /* FIXME: strncmp loses in interesting ways on MS-DOS and
> + MS-Windows because of case-insensitivity and two different
> + but functionally identical slash characters. We need a
> + special filesystem-dependent file-name comparison function.
> +
> + Actually, even on Unix I would use realpath() or its work-
> + alike before comparing. Then all the code above which
> + removes excess slashes and dots could simply go away. */
> + if (!strncmp (p, name, len)
> + && (p[len] == '\0' || p[len] == DIRNAME_SEPARATOR))
> + {
> + /* Found it in the search path, remove old copy */
> + if (p > *which_path)
> + p--; /* Back over leading separator */
> + if (prefix > p - *which_path)
> + goto skip_dup; /* Same dir twice in one cmd */
> + strcpy (p, &p[len + 1]); /* Copy from next \0 or : */
> + }
> + p = strchr (p, DIRNAME_SEPARATOR);
> + if (p != 0)
> + ++p;
> + else
> + break;
> + }
> + if (p == 0)
> + {
> + char tinybuf[2];
> +
> + tinybuf[0] = DIRNAME_SEPARATOR;
> + tinybuf[1] = '\0';
> +
> + /* If we have already tacked on a name(s) in this command,
> + be sure they stay on the front as we tack on some more. */
> + if (prefix)
> + {
> + char *temp, c;
> +
> + c = old[prefix];
> + old[prefix] = '\0';
> + temp = concat (old, tinybuf, name, NULL);
> + old[prefix] = c;
> + *which_path = concat (temp, "", &old[prefix], NULL);
> + prefix = strlen (temp);
> + xfree (temp);
> + }
> + else
> + {
> + *which_path = concat (name, (old[0] ? tinybuf : old), old, NULL);
> + prefix = strlen (name);
> + }
> + xfree (old);
> + old = *which_path;
> + }
> + }
> + skip_dup:;
> +}
> +
> +/* Add one or more directories to start of executable search path */
> +enum mi_cmd_result
> +mi_cmd_env_path (char *command, char **argv, int argc)
> +{
> + char *exec_path;
> + char *env;
> + int i;
> + if (argc == 0)
> + error ("mi_cmd_env_path: Usage [DIR1 DIR2 ... DIRn]");
> +
> + if (mi_version (uiout) < 2)
> + {
> + for (i = argc - 1; i >= 0; --i)
> + env_execute_cli_command ("path %s", argv[i]);
> + return MI_CMD_DONE;
> + }
> +
> + /* otherwise mi level 2 or higher */
> + dont_repeat ();
> + env = get_in_environ (inferior_environ, path_var_name);
> +
> + /* Can be null if path is not set */
> + if (!env)
> + env = "";
> + exec_path = xstrdup (env);
> +
> + for (i = argc - 1; i >= 0; --i)
> + env_mod_path (argv[i], &exec_path);
> +
> + set_in_environ (inferior_environ, path_var_name, exec_path);
> + xfree (exec_path);
> + env = get_in_environ (inferior_environ, path_var_name);
> + ui_out_field_string (uiout, "path", env);
> +
> + return MI_CMD_DONE;
> +}
> +
> +/* Add zero or more directories to the front of the source path. */
> +enum mi_cmd_result
> +mi_cmd_env_dir (char *command, char **argv, int argc)
> +{
> + int i;
> +
> + dont_repeat ();
> +
> + if (mi_version (uiout) < 2)
> + {
> + for (i = argc - 1; i >= 0; --i)
> + env_execute_cli_command ("dir %s", argv[i]);
> + return MI_CMD_DONE;
> + }
> +
> + /* otherwise mi 2 or higher */
> + if (argc == 0)
> + {
> + /* no args implies reset to default path */
> + xfree (source_path);
> + init_source_path ();
> + }
> + else
> + {
> + for (i = argc - 1; i >= 0; --i)
> + env_mod_path (argv[i], &source_path);
> + init_last_source_visited ();
> + }
> +
> + ui_out_field_string (uiout, "source-path", source_path);
> + forget_cached_source_info ();
> +}
> +
> Index: mi/mi-cmds.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/mi/mi-cmds.c,v
> retrieving revision 1.8
> diff -u -r1.8 mi-cmds.c
> --- mi/mi-cmds.c 6 Mar 2001 08:21:45 -0000 1.8
> +++ mi/mi-cmds.c 9 Oct 2002 18:15:59 -0000
> @@ -56,10 +56,10 @@
> {"display-enable", 0, 0},
> {"display-insert", 0, 0},
> {"display-list", 0, 0},
> - {"environment-cd", "cd %s", 0},
> - {"environment-directory", "dir %s", 0},
> - {"environment-path", "path %s", 0},
> - {"environment-pwd", "pwd", 0},
> + {"environment-cd", 0, 0, mi_cmd_env_cd},
> + {"environment-directory", 0, 0, mi_cmd_env_dir},
> + {"environment-path", 0, 0, mi_cmd_env_path},
> + {"environment-pwd", 0, 0, mi_cmd_env_pwd},
> {"exec-abort", 0, 0},
> {"exec-arguments", "set args %s", 0},
> {"exec-continue", 0, mi_cmd_exec_continue},
> Index: mi/mi-cmds.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/mi/mi-cmds.h,v
> retrieving revision 1.5
> diff -u -r1.5 mi-cmds.h
> --- mi/mi-cmds.h 6 Mar 2001 08:21:45 -0000 1.5
> +++ mi/mi-cmds.h 9 Oct 2002 18:15:59 -0000
> @@ -64,6 +64,10 @@
> extern mi_cmd_argv_ftype mi_cmd_data_read_memory;
> extern mi_cmd_argv_ftype mi_cmd_data_write_memory;
> extern mi_cmd_argv_ftype mi_cmd_data_write_register_values;
> +extern mi_cmd_argv_ftype mi_cmd_env_cd;
> +extern mi_cmd_argv_ftype mi_cmd_env_dir;
> +extern mi_cmd_argv_ftype mi_cmd_env_path;
> +extern mi_cmd_argv_ftype mi_cmd_env_pwd;
> extern mi_cmd_args_ftype mi_cmd_exec_continue;
> extern mi_cmd_args_ftype mi_cmd_exec_finish;
> extern mi_cmd_args_ftype mi_cmd_exec_next;
> Index: mi/gdbmi.texinfo
> ===================================================================
> RCS file: /cvs/src/src/gdb/mi/gdbmi.texinfo,v
> retrieving revision 1.29
> diff -u -r1.29 gdbmi.texinfo
> --- mi/gdbmi.texinfo 3 Oct 2002 22:31:31 -0000 1.29
> +++ mi/gdbmi.texinfo 9 Oct 2002 18:28:04 -0000
> @@ -1665,10 +1665,12 @@
> @subsubheading Synopsis
>
> @example
> - -environment-directory @var{pathdir}
> + -environment-directory [ @var{pathdir} ]+
> @end example
>
> -Add directory @var{pathdir} to beginning of search path for source files.
> +Add directories @var{pathdir} to beginning of search path for source files.
> +If no argument is given, reset search path to default. An empty string for
> +@var{pathdir} is ignored so it may be used to display the current search path.
>
> @subsubheading @value{GDBN} Command
>
> @@ -1679,7 +1681,13 @@
> @smallexample
> (@value{GDBP})
> -environment-directory /kwikemart/marge/ezannoni/flathead-dev/devo/gdb
> -^done
> +^done,source-path="/kwikemart/marge/ezannoni/flathead-dev/devo/gdb:$cdir:$cwd"
> +(@value{GDBP})
> +-environment-directory ""
> +^done,source-path="/kwikemart/marge/ezannoni/flathead-dev/devo/gdb:$cdir:$cwd"
> +(@value{GDBP})
> +-environment-directory
> +^done,source-path="$cdir:$cwd"
> (@value{GDBP})
> @end smallexample
>
> @@ -1690,10 +1698,12 @@
> @subsubheading Synopsis
>
> @example
> - -environment-path ( @var{pathdir} )+
> + -environment-path [ @var{pathdir} ]+
> @end example
>
> Add directories @var{pathdir} to beginning of search path for object files.
> +If no paths or an empty path is specified, the current object search path
> +is displayed with no modification.
>
> @subsubheading @value{GDBN} Command
>
> @@ -1704,7 +1714,10 @@
> @smallexample
> (@value{GDBP})
> -environment-path /kwikemart/marge/ezannoni/flathead-dev/ppc-eabi/gdb
> -^done
> +^done,path="/kwikemart/marge/ezannoni/flathead-dev/ppc-eabi/gdb:/usr/bin"
> +(@value{GDBP})
> +-environment-path
> +^done,path="/kwikemart/marge/ezannoni/flathead-dev/ppc-eabi/gdb:/usr/bin"
> (@value{GDBP})
> @end smallexample
>
> @@ -1729,8 +1742,7 @@
> @smallexample
> (@value{GDBP})
> -environment-pwd
> -~Working directory /kwikemart/marge/ezannoni/flathead-dev/devo/gdb.
> -^done
> +^done,cwd="/kwikemart/marge/ezannoni/flathead-dev/devo/gdb"
> (@value{GDBP})
> @end smallexample
>
> Index: testsuite/gdb.mi/mi-basics.exp
> ===================================================================
> RCS file: /cvs/src/src/gdb/testsuite/gdb.mi/mi-basics.exp,v
> retrieving revision 1.6
> diff -u -r1.6 mi-basics.exp
> --- testsuite/gdb.mi/mi-basics.exp 27 Jun 2001 17:27:07 -0000 1.6
> +++ testsuite/gdb.mi/mi-basics.exp 9 Oct 2002 18:18:17 -0000
> @@ -150,24 +150,50 @@
>
> # Clear the search directories, then specify one to be searched
> # Tests:
> - # -environment-directory
> # -environment-directory arg
> + # -environment-directory empty-string
> + # -environment-directory
>
> #exp_internal 1
> - mi_gdb_test "202-environment-directory" \
> - "\\\^done" \
> + mi_gdb_test "202-environment-directory ${srcdir}/${subdir}" \
> + "\\\^done,source-path=\"${srcdir}/${subdir}:\\\$cdir:\\\$cwd\"" \
> + "environment-directory arg operation"
> +
> + mi_gdb_test "203-environment-directory \"\"" \
> + "\\\^done,source-path=\"${srcdir}/${subdir}:\\\$cdir:\\\$cwd\"" \
> + "environment-directory empty-string operation"
> +
> + mi_gdb_test "204-environment-directory" \
> + "\\\^done,source-path=\"\\\$cdir:\\\$cwd\"" \
> "environment-directory operation"
>
> - mi_gdb_test "203-environment-directory ${srcdir}/${subdir}" \
> - "\\\^done" \
> - "environment-directory arg operation"
> #exp_internal 0
> }
>
> +proc test_cwd_specification {} {
> + global mi_gdb_prompt
> + global objdir
> + global subdir
> +
> + # Change the working directory, then print the current working directory
> + # Tests:
> + # -environment-cd ${objdir}
> + # -environment-pwd
> +
> + mi_gdb_test "205-environment-cd ${objdir}" \
> + "\\\^done" \
> + "environment-cd arg operation"
> +
> + mi_gdb_test "206-environment-pwd" \
> + "\\\^done,cwd=\"${objdir}\"" \
> + "environment-pwd operation"
> +}
> +
> if [test_mi_interpreter_selection] {
> test_exec_and_symbol_mi_operatons
> test_breakpoints_deletion
> test_dir_specification
> + test_cwd_specification
> }
>
> mi_gdb_exit