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 +#include + +#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;