/* List lines of source files for GDB, the GNU debugger.
- Copyright (C) 1986-2013 Free Software Foundation, Inc.
+ Copyright (C) 1986-2014 Free Software Foundation, Inc.
This file is part of GDB.
#include "frame.h"
#include "value.h"
#include "gdb_assert.h"
+#include "filestuff.h"
#include <sys/types.h>
-#include "gdb_string.h"
-#include "gdb_stat.h"
+#include <string.h>
+#include <sys/stat.h>
#include <fcntl.h>
#include "gdbcore.h"
#include "gdb_regex.h"
#include "ui-out.h"
#include "readline/readline.h"
-#include "psymtab.h"
-
-
#define OPEN_MODE (O_RDONLY | O_BINARY)
#define FDOPEN_MODE FOPEN_RB
char tinybuf[2];
p = *which_path;
- /* FIXME: we should use realpath() or its work-alike
- before comparing. Then all the code above which
- removes excess slashes and dots could simply go away. */
- if (!filename_cmp (p, name))
+ while (1)
{
- /* 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. */
- memmove (p, &p[len + 1], strlen (&p[len + 1]) + 1); /* Copy from next \0 or : */
+ /* FIXME: we should use realpath() or its work-alike
+ before comparing. Then all the code above which
+ removes excess slashes and dots could simply go away. */
+ if (!filename_ncmp (p, name, len)
+ && (p[len] == '\0' || p[len] == DIRNAME_SEPARATOR))
+ {
+ /* Found it in the search path, remove old copy. */
+ if (p > *which_path)
+ {
+ /* Back over leading separator. */
+ p--;
+ }
+ if (prefix > p - *which_path)
+ {
+ /* Same dir twice in one cmd. */
+ goto skip_dup;
+ }
+ /* Copy from next '\0' or ':'. */
+ memmove (p, &p[len + 1], strlen (&p[len + 1]) + 1);
+ }
+ p = strchr (p, DIRNAME_SEPARATOR);
+ if (p != 0)
+ ++p;
+ else
+ break;
}
tinybuf[0] = DIRNAME_SEPARATOR;
If OPF_TRY_CWD_FIRST, try to open ./STRING before searching PATH.
(ie pretend the first element of PATH is "."). This also indicates
- that a slash in STRING disables searching of the path (this is
- so that "exec-file ./foo" or "symbol-file ./foo" insures that you
- get that particular version of foo or an error message).
+ that, unless OPF_SEARCH_IN_PATH is also specified, a slash in STRING
+ disables searching of the path (this is so that "exec-file ./foo" or
+ "symbol-file ./foo" insures that you get that particular version of
+ foo or an error message).
If OPTS has OPF_SEARCH_IN_PATH set, absolute names will also be
searched in path (we usually want this for source files but not for
and the file, sigh! Emacs gets confuzzed by this when we print the
source file name!!!
+ If OPTS has OPF_RETURN_REALPATH set return FILENAME_OPENED resolved by
+ gdb_realpath. Even without OPF_RETURN_REALPATH this function still returns
+ filename starting with "/". If FILENAME_OPENED is NULL this option has no
+ effect.
+
If a file is found, return the descriptor.
Otherwise, return -1, with errno set for the last name we tried to open. */
{
filename = alloca (strlen (string) + 1);
strcpy (filename, string);
- fd = open (filename, mode);
+ fd = gdb_open_cloexec (filename, mode, 0);
if (fd >= 0)
goto done;
}
if (is_regular_file (filename))
{
- fd = open (filename, mode);
+ fd = gdb_open_cloexec (filename, mode, 0);
if (fd >= 0)
break;
}
/* If a file was opened, canonicalize its filename. */
if (fd < 0)
*filename_opened = NULL;
- else if (IS_ABSOLUTE_PATH (filename))
+ else if ((opts & OPF_RETURN_REALPATH) != 0)
*filename_opened = gdb_realpath (filename);
else
- {
- /* Beware the // my son, the Emacs barfs, the botch that catch... */
-
- char *f = concat (current_directory,
- IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])
- ? "" : SLASH_STRING,
- filename, (char *)NULL);
-
- *filename_opened = gdb_realpath (f);
- xfree (f);
- }
+ *filename_opened = gdb_abspath (filename);
}
return fd;
{
int fd;
- fd = openp (source_path, OPF_TRY_CWD_FIRST | OPF_SEARCH_IN_PATH, filename,
- O_RDONLY, full_pathname);
+ fd = openp (source_path,
+ OPF_TRY_CWD_FIRST | OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH,
+ filename, O_RDONLY, full_pathname);
if (fd < 0)
{
*full_pathname = NULL;
char *path = source_path;
const char *p;
int result;
+ struct cleanup *cleanup;
/* Quick way out if we already know its full name. */
*fullname = rewritten_fullname;
}
- result = open (*fullname, OPEN_MODE);
+ result = gdb_open_cloexec (*fullname, OPEN_MODE, 0);
if (result >= 0)
{
char *lpath = gdb_realpath (*fullname);
*fullname = NULL;
}
+ cleanup = make_cleanup (null_cleanup, NULL);
+
if (dirname != NULL)
{
/* If necessary, rewrite the compilation directory name according
}
}
- result = openp (path, OPF_SEARCH_IN_PATH, filename, OPEN_MODE, fullname);
+ result = openp (path, OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH, filename,
+ OPEN_MODE, fullname);
if (result < 0)
{
/* Didn't work. Try using just the basename. */
p = lbasename (filename);
if (p != filename)
- result = openp (path, OPF_SEARCH_IN_PATH, p, OPEN_MODE, fullname);
+ result = openp (path, OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH, p,
+ OPEN_MODE, fullname);
}
+ do_cleanups (cleanup);
return result;
}
{
ui_out_field_int (uiout, "line", line);
ui_out_text (uiout, "\tin ");
- ui_out_field_string (uiout, "file",
- symtab_to_filename_for_display (s));
- /* TUI expects the "fullname" field. While it is
- !ui_out_is_mi_like_p compared to CLI it is !ui_source_list. */
+ /* CLI expects only the "file" field. TUI expects only the
+ "fullname" field (and TUI does break if "file" is printed).
+ MI expects both fields. ui_source_list is set only for CLI,
+ not for TUI. */
+ if (ui_out_is_mi_like_p (uiout)
+ || ui_out_test_flags (uiout, ui_source_list))
+ ui_out_field_string (uiout, "file",
+ symtab_to_filename_for_display (s));
if (ui_out_is_mi_like_p (uiout)
|| !ui_out_test_flags (uiout, ui_source_list))
- {
- const char *fullname = symtab_to_fullname (s);
+ {
+ const char *s_fullname = symtab_to_fullname (s);
+ char *local_fullname;
+
+ /* ui_out_field_string may free S_FULLNAME by calling
+ open_source_file for it again. See e.g.,
+ tui_field_string->tui_show_source. */
+ local_fullname = alloca (strlen (s_fullname) + 1);
+ strcpy (local_fullname, s_fullname);
+
+ ui_out_field_string (uiout, "fullname", local_fullname);
+ }
- ui_out_field_string (uiout, "fullname", fullname);
- }
ui_out_text (uiout, "\n");
}
buf = xmalloc (cursize);
p = buf;
- c = getc (stream);
+ c = fgetc (stream);
if (c == EOF)
break;
do
cursize = newsize;
}
}
- while (c != '\n' && (c = getc (stream)) >= 0);
+ while (c != '\n' && (c = fgetc (stream)) >= 0);
/* Remove the \r, if any, at the end of the line, otherwise
regular expressions that end with $ or \n won't work. */
char buf[4096]; /* Should be reasonable??? */
char *p = buf;
- c = getc (stream);
+ c = fgetc (stream);
if (c == EOF)
break;
do
{
*p++ = c;
}
- while (c != '\n' && (c = getc (stream)) >= 0);
+ while (c != '\n' && (c = fgetc (stream)) >= 0);
/* Remove the \r, if any, at the end of the line, otherwise
regular expressions that end with $ or \n won't work. */
struct substitute_path_rule *rule = substitute_path_rules;
char **argv;
char *from = NULL;
+ struct cleanup *cleanup;
argv = gdb_buildargv (args);
- make_cleanup_freeargv (argv);
+ cleanup = make_cleanup_freeargv (argv);
/* We expect zero or one argument. */
printf_filtered (" `%s' -> `%s'.\n", rule->from, rule->to);
rule = rule->next;
}
+
+ do_cleanups (cleanup);
}
/* Implement the "unset substitute-path" command. */
char **argv = gdb_buildargv (args);
char *from = NULL;
int rule_found = 0;
+ struct cleanup *cleanup;
/* This function takes either 0 or 1 argument. */
- make_cleanup_freeargv (argv);
+ cleanup = make_cleanup_freeargv (argv);
if (argv != NULL && argv[0] != NULL && argv[1] != NULL)
error (_("Incorrect usage, too many arguments in command"));
error (_("No substitution rule defined for `%s'"), from);
forget_cached_source_info ();
+
+ do_cleanups (cleanup);
}
/* Add a new source path substitution rule. */
{
char **argv;
struct substitute_path_rule *rule;
+ struct cleanup *cleanup;
argv = gdb_buildargv (args);
- make_cleanup_freeargv (argv);
+ cleanup = make_cleanup_freeargv (argv);
if (argv == NULL || argv[0] == NULL || argv [1] == NULL)
error (_("Incorrect usage, too few arguments in command"));
add_substitute_path_rule (argv[0], argv[1]);
forget_cached_source_info ();
+
+ do_cleanups (cleanup);
}
\f
add_com_alias ("?", "reverse-search", class_files, 0);
}
- add_setshow_zuinteger_unlimited_cmd ("listsize", class_support,
- &lines_to_list, _("\
+ add_setshow_integer_cmd ("listsize", class_support, &lines_to_list, _("\
Set number of source lines gdb will list by default."), _("\
-Show number of source lines gdb will list by default."), NULL,
- NULL, show_lines_to_list,
- &setlist, &showlist);
+Show number of source lines gdb will list by default."), _("\
+Use this to choose how many source lines the \"list\" displays (unless\n\
+the \"list\" argument explicitly specifies some other number).\n\
+A value of \"unlimited\", or zero, means there's no limit."),
+ NULL,
+ show_lines_to_list,
+ &setlist, &showlist);
add_cmd ("substitute-path", class_files, set_substitute_path_command,
_("\