Proposed patch for gdb/mi 741

Elena Zannoni ezannoni@redhat.com
Tue Oct 22 09:08:00 GMT 2002


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



More information about the Gdb-patches mailing list