diff options
Diffstat (limited to 'gdb/cli/cli-cmds.c')
-rw-r--r-- | gdb/cli/cli-cmds.c | 178 |
1 files changed, 120 insertions, 58 deletions
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index aaf0586..dcb8ece 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -470,62 +470,59 @@ Script filename extension recognition is \"%s\".\n"), value); } +/* Try to open SCRIPT_FILE. + If successful, the full path name is stored in *FULL_PATHP, + the stream is stored in *STREAMP, and return 1. + The caller is responsible for freeing *FULL_PATHP. + If not successful, return 0; errno is set for the last file + we tried to open. + + If SEARCH_PATH is non-zero, and the file isn't found in cwd, + search for it in the source search path. + + NOTE: This calls openp which uses xfullpath to compute the full path + instead of gdb_realpath. Symbolic links are not resolved. */ + static int -find_and_open_script (int from_tty, char **filep, FILE **streamp, - struct cleanup **cleanupp) +find_and_open_script (const char *script_file, int search_path, + FILE **streamp, char **full_pathp) { - char *file = *filep; - char *full_pathname = NULL; + char *file; int fd; struct cleanup *old_cleanups; + int search_flags = OPF_TRY_CWD_FIRST; - file = tilde_expand (file); + file = tilde_expand (script_file); old_cleanups = make_cleanup (xfree, file); - /* Search for and open 'file' on the search path used for source - files. Put the full location in 'full_pathname'. */ - fd = openp (source_path, OPF_TRY_CWD_FIRST, - file, O_RDONLY, &full_pathname); - make_cleanup (xfree, full_pathname); + if (search_path) + search_flags |= OPF_SEARCH_IN_PATH; - /* Use the full path name, if it is found. */ - if (full_pathname != NULL && fd != -1) - { - file = full_pathname; - } + /* Search for and open 'file' on the search path used for source + files. Put the full location in *FULL_PATHP. */ + fd = openp (source_path, search_flags, + file, O_RDONLY, full_pathp); if (fd == -1) { - if (from_tty) - perror_with_name (file); - else - { - do_cleanups (old_cleanups); - return 0; - } + int save_errno = errno; + do_cleanups (old_cleanups); + errno = save_errno; + return 0; } - *streamp = fdopen (fd, FOPEN_RT); - *filep = file; - *cleanupp = old_cleanups; + do_cleanups (old_cleanups); + *streamp = fdopen (fd, FOPEN_RT); return 1; } -void -source_script (char *file, int from_tty) -{ - FILE *stream; - struct cleanup *old_cleanups; - - if (file == NULL || *file == 0) - { - error (_("source command requires file name of file to source.")); - } - - if (!find_and_open_script (from_tty, &file, &stream, &old_cleanups)) - return; +/* Load script FILE, which has already been opened as STREAM. + STREAM is closed before we return. */ +static void +source_script_from_stream (FILE *stream, const char *file) +{ if (script_ext_mode != script_ext_off && strlen (file) > 3 && !strcmp (&file[strlen (file) - 3], ".py")) { @@ -541,22 +538,64 @@ source_script (char *file, int from_tty) if (script_ext_mode == script_ext_soft && e.reason == RETURN_ERROR && e.error == UNSUPPORTED_ERROR) { - if (!find_and_open_script (from_tty, &file, &stream, &old_cleanups)) - return; - - script_from_file (stream, file); + fseek (stream, 0, SEEK_SET); + script_from_file (stream, (char*) file); } else - /* Nope, just punt. */ - throw_exception (e); + { + /* Nope, just punt. */ + fclose (stream); + throw_exception (e); + } } + else + fclose (stream); } else script_from_file (stream, file); +} +/* Worker to perform the "source" command. + Load script FILE. + If SEARCH_PATH is non-zero, and the file isn't found in cwd, + search for it in the source search path. */ + +static void +source_script_with_search (const char *file, int from_tty, int search_path) +{ + FILE *stream; + char *full_path; + struct cleanup *old_cleanups; + + if (file == NULL || *file == 0) + error (_("source command requires file name of file to source.")); + + if (!find_and_open_script (file, search_path, &stream, &full_path)) + { + /* The script wasn't found, or was otherwise inaccessible. + If the source command was invoked interactively, throw an error. + Otherwise (e.g. if it was invoked by a script), silently ignore + the error. */ + if (from_tty) + perror_with_name (file); + else + return; + } + + old_cleanups = make_cleanup (xfree, full_path); + source_script_from_stream (stream, file); do_cleanups (old_cleanups); } +/* Wrapper around source_script_with_search to export it to main.c + for use in loading .gdbinit scripts. */ + +void +source_script (char *file, int from_tty) +{ + source_script_with_search (file, from_tty, 0); +} + /* Return the source_verbose global variable to its previous state on exit from the source command, by whatever means. */ static void @@ -572,33 +611,52 @@ source_command (char *args, int from_tty) struct cleanup *old_cleanups; char *file = args; int *old_source_verbose = xmalloc (sizeof(int)); + int search_path = 0; *old_source_verbose = source_verbose; old_cleanups = make_cleanup (source_verbose_cleanup, old_source_verbose); /* -v causes the source command to run in verbose mode. + -s causes the file to be searched in the source search path, + even if the file name contains a '/'. We still have to be able to handle filenames with spaces in a backward compatible way, so buildargv is not appropriate. */ if (args) { - /* Make sure leading white space does not break the comparisons. */ - while (isspace(args[0])) - args++; - - /* Is -v the first thing in the string? */ - if (args[0] == '-' && args[1] == 'v' && isspace (args[2])) + while (args[0] != '\0') { - source_verbose = 1; + /* Make sure leading white space does not break the comparisons. */ + while (isspace(args[0])) + args++; + + if (args[0] != '-') + break; + + if (args[1] == 'v' && isspace (args[2])) + { + source_verbose = 1; + + /* Skip passed -v. */ + args = &args[3]; + } + else if (args[1] == 's' && isspace (args[2])) + { + search_path = 1; - /* Trim -v and whitespace from the filename. */ - file = &args[3]; - while (isspace (file[0])) - file++; + /* Skip passed -s. */ + args = &args[3]; + } + else + break; } + + while (isspace (args[0])) + args++; + file = args; } - source_script (file, from_tty); + source_script_with_search (file, from_tty, search_path); do_cleanups (old_cleanups); } @@ -1379,8 +1437,12 @@ Commands defined in this way may have up to ten arguments.")); source_help_text = xstrprintf (_("\ Read commands from a file named FILE.\n\ -Optional -v switch (before the filename) causes each command in\n\ -FILE to be echoed as it is executed.\n\ +\n\ +Usage: source [-s] [-v] FILE\n\ +-s: search for the script in the source search path,\n\ + even if FILE contains directories.\n\ +-v: each command in FILE is echoed as it is executed.\n\ +\n\ Note that the file \"%s\" is read automatically in this way\n\ when GDB is started."), gdbinit); c = add_cmd ("source", class_support, source_command, |