X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fsource.c;h=a1f55b29c4329f7db755d6e140822138063253f7;hb=e26b7e41652e288dfdb4c48121bba470c4774150;hp=4eda082f15d0ad5354bdd8eaf9618a89aa05958b;hpb=82ae4854632a42a7d7d74b6cdb8da9be7890976c;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/source.c b/gdb/source.c index 4eda082f15..a1f55b29c4 100644 --- a/gdb/source.c +++ b/gdb/source.c @@ -1,7 +1,5 @@ /* List lines of source files for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, - 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2016 Free Software Foundation, Inc. This file is part of GDB. @@ -28,11 +26,10 @@ #include "gdbcmd.h" #include "frame.h" #include "value.h" -#include "gdb_assert.h" +#include "filestuff.h" #include -#include "gdb_string.h" -#include "gdb_stat.h" +#include #include #include "gdbcore.h" #include "gdb_regex.h" @@ -45,9 +42,7 @@ #include "completer.h" #include "ui-out.h" #include "readline/readline.h" - -#include "psymtab.h" - +#include "common/enum-flags.h" #define OPEN_MODE (O_RDONLY | O_BINARY) #define FDOPEN_MODE FOPEN_RB @@ -100,7 +95,7 @@ static struct program_space *current_source_pspace; and friends should be rewritten to count characters and see where things are wrapping, but that would be a fair amount of work. */ -int lines_to_list = 10; +static int lines_to_list = 10; static void show_lines_to_list (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) @@ -111,12 +106,35 @@ show_lines_to_list (struct ui_file *file, int from_tty, value); } +/* Possible values of 'set filename-display'. */ +static const char filename_display_basename[] = "basename"; +static const char filename_display_relative[] = "relative"; +static const char filename_display_absolute[] = "absolute"; + +static const char *const filename_display_kind_names[] = { + filename_display_basename, + filename_display_relative, + filename_display_absolute, + NULL +}; + +static const char *filename_display_string = filename_display_relative; + +static void +show_filename_display_string (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Filenames are displayed as \"%s\".\n"), value); +} + /* Line number of last line printed. Default for various commands. current_source_line is usually, but not always, the same as this. */ static int last_line_listed; -/* First line number listed by last listing command. */ +/* First line number listed by last listing command. If 0, then no + source lines have yet been listed since the last time the current + source line was changed. */ static int first_line_listed; @@ -136,6 +154,16 @@ get_first_line_listed (void) return first_line_listed; } +/* Clear line listed range. This makes the next "list" center the + printed source lines around the current source line. */ + +static void +clear_lines_listed_range (void) +{ + first_line_listed = 0; + last_line_listed = 0; +} + /* Return the default number of lines to print with commands like the cli "list". The caller of print_source_lines must use this to calculate the end line and use it in the call to print_source_lines @@ -203,6 +231,9 @@ set_current_source_symtab_and_line (const struct symtab_and_line *sal) current_source_symtab = sal->symtab; current_source_line = sal->line; + /* Force the next "list" to center around the current line. */ + clear_lines_listed_range (); + return cursal; } @@ -229,6 +260,7 @@ select_source_symtab (struct symtab *s) struct symtabs_and_lines sals; struct symtab_and_line sal; struct objfile *ofp; + struct compunit_symtab *cu; if (s) { @@ -243,9 +275,10 @@ select_source_symtab (struct symtab *s) /* Make the default place to list be the function `main' if one exists. */ - if (lookup_symbol (main_name (), 0, VAR_DOMAIN, 0)) + if (lookup_symbol (main_name (), 0, VAR_DOMAIN, 0).symbol) { - sals = decode_line_spec (main_name (), 1); + sals = decode_line_with_current_source (main_name (), + DECODE_LINE_FUNFIRSTLINE); sal = sals.sals[0]; xfree (sals.sals); current_source_pspace = sal.pspace; @@ -260,19 +293,16 @@ select_source_symtab (struct symtab *s) current_source_line = 1; - ALL_OBJFILES (ofp) + ALL_FILETABS (ofp, cu, s) { - for (s = ofp->symtabs; s; s = s->next) - { - const char *name = s->filename; - int len = strlen (name); + const char *name = s->filename; + int len = strlen (name); - if (!(len > 2 && (strcmp (&name[len - 2], ".h") == 0 - || strcmp (name, "<>") == 0))) - { - current_source_pspace = current_program_space; - current_source_symtab = s; - } + if (!(len > 2 && (strcmp (&name[len - 2], ".h") == 0 + || strcmp (name, "<>") == 0))) + { + current_source_pspace = current_program_space; + current_source_symtab = s; } } @@ -335,6 +365,33 @@ show_directories_command (struct ui_file *file, int from_tty, show_directories_1 (NULL, from_tty); } +/* Forget line positions and file names for the symtabs in a + particular objfile. */ + +void +forget_cached_source_info_for_objfile (struct objfile *objfile) +{ + struct compunit_symtab *cu; + struct symtab *s; + + ALL_OBJFILE_FILETABS (objfile, cu, s) + { + if (s->line_charpos != NULL) + { + xfree (s->line_charpos); + s->line_charpos = NULL; + } + if (s->fullname != NULL) + { + xfree (s->fullname); + s->fullname = NULL; + } + } + + if (objfile->sf) + objfile->sf->qf->forget_cached_source_info (objfile); +} + /* Forget what we learned about line positions in source files, and which directories contain them; must check again now since files may be found in a different directory now. */ @@ -343,28 +400,12 @@ void forget_cached_source_info (void) { struct program_space *pspace; - struct symtab *s; struct objfile *objfile; ALL_PSPACES (pspace) ALL_PSPACE_OBJFILES (pspace, objfile) { - for (s = objfile->symtabs; s != NULL; s = s->next) - { - if (s->line_charpos != NULL) - { - xfree (s->line_charpos); - s->line_charpos = NULL; - } - if (s->fullname != NULL) - { - xfree (s->fullname); - s->fullname = NULL; - } - } - - if (objfile->sf) - objfile->sf->qf->forget_cached_source_info (objfile); + forget_cached_source_info_for_objfile (objfile); } last_source_visited = NULL; @@ -375,14 +416,14 @@ init_source_path (void) { char buf[20]; - sprintf (buf, "$cdir%c$cwd", DIRNAME_SEPARATOR); + xsnprintf (buf, sizeof (buf), "$cdir%c$cwd", DIRNAME_SEPARATOR); source_path = xstrdup (buf); forget_cached_source_info (); } /* Add zero or more directories to the front of the source path. */ -void +static void directory_command (char *dirname, int from_tty) { dont_repeat (); @@ -432,62 +473,40 @@ add_path (char *dirname, char **which_path, int parse_separators) { char *old = *which_path; int prefix = 0; - char **argv = NULL; - char *arg; - int argv_index = 0; + VEC (char_ptr) *dir_vec = NULL; + struct cleanup *back_to; + int ix; + char *name; if (dirname == 0) return; if (parse_separators) { + char **argv, **argvp; + /* This will properly parse the space and tab separators - and any quotes that may exist. DIRNAME_SEPARATOR will - be dealt with later. */ + and any quotes that may exist. */ argv = gdb_buildargv (dirname); - make_cleanup_freeargv (argv); - arg = argv[0]; + for (argvp = argv; *argvp; argvp++) + dirnames_to_char_ptr_vec_append (&dir_vec, *argvp); + + freeargv (argv); } else - { - arg = xstrdup (dirname); - make_cleanup (xfree, arg); - } + VEC_safe_push (char_ptr, dir_vec, xstrdup (dirname)); + back_to = make_cleanup_free_char_ptr_vec (dir_vec); - do + for (ix = 0; VEC_iterate (char_ptr, dir_vec, ix, name); ++ix) { - char *name = arg; char *p; struct stat st; - { - char *separator = NULL; - - /* Spaces and tabs will have been removed by buildargv(). - The directories will there be split into a list but - each entry may still contain DIRNAME_SEPARATOR. */ - if (parse_separators) - separator = strchr (name, DIRNAME_SEPARATOR); - - if (separator == 0) - p = arg = name + strlen (name); - else - { - p = separator; - arg = p + 1; - while (*arg == DIRNAME_SEPARATOR) - ++arg; - } - - /* If there are no more directories in this argument then start - on the next argument next time round the loop (if any). */ - if (*arg == '\0') - arg = parse_separators ? argv[++argv_index] : NULL; - } - - /* name is the start of the directory. - p is the separator (or null) following the end. */ + /* Spaces and tabs will have been removed by buildargv(). + NAME is the start of the directory. + P is the '\0' following the end. */ + p = name + strlen (name); while (!(IS_DIR_SEPARATOR (*name) && p <= name + 1) /* "/" */ #ifdef HAVE_DOS_BASED_FILE_SYSTEM @@ -565,27 +584,30 @@ add_path (char *dirname, char **which_path, int parse_separators) append: { unsigned int len = strlen (name); + char tinybuf[2]; 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 + /* 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 (!strncmp (p, name, len) + 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) - p--; /* Back over leading separator. */ + { + /* Back over leading separator. */ + p--; + } if (prefix > p - *which_path) - goto skip_dup; /* Same dir twice in one cmd. */ - strcpy (p, &p[len + 1]); /* Copy from next \0 or : */ + { + /* 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) @@ -593,41 +615,39 @@ add_path (char *dirname, char **which_path, int parse_separators) else break; } - if (p == 0) - { - char tinybuf[2]; - tinybuf[0] = DIRNAME_SEPARATOR; - tinybuf[1] = '\0'; + 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, (char *)NULL); - old[prefix] = c; - *which_path = concat (temp, "", &old[prefix], (char *) NULL); - prefix = strlen (temp); - xfree (temp); - } - else - { - *which_path = concat (name, (old[0] ? tinybuf : old), - old, (char *)NULL); - prefix = strlen (name); - } - xfree (old); - old = *which_path; + /* 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, (char *)NULL); + old[prefix] = c; + *which_path = concat (temp, "", &old[prefix], (char *) NULL); + prefix = strlen (temp); + xfree (temp); + } + else + { + *which_path = concat (name, (old[0] ? tinybuf : old), + old, (char *)NULL); + prefix = strlen (name); } + xfree (old); + old = *which_path; } skip_dup: + ; } - while (arg != NULL); + + do_cleanups (back_to); } @@ -635,15 +655,18 @@ static void source_info (char *ignore, int from_tty) { struct symtab *s = current_source_symtab; + struct compunit_symtab *cust; if (!s) { printf_filtered (_("No current source file.\n")); return; } + + cust = SYMTAB_COMPUNIT (s); printf_filtered (_("Current source file is %s\n"), s->filename); - if (s->dirname) - printf_filtered (_("Compilation directory is %s\n"), s->dirname); + if (SYMTAB_DIRNAME (s) != NULL) + printf_filtered (_("Compilation directory is %s\n"), SYMTAB_DIRNAME (s)); if (s->fullname) printf_filtered (_("Located in %s\n"), s->fullname); if (s->nlines) @@ -651,9 +674,14 @@ source_info (char *ignore, int from_tty) s->nlines == 1 ? "" : "s"); printf_filtered (_("Source language is %s.\n"), language_str (s->language)); - printf_filtered (_("Compiled with %s debugging format.\n"), s->debugformat); + printf_filtered (_("Producer is %s.\n"), + COMPUNIT_PRODUCER (cust) != NULL + ? COMPUNIT_PRODUCER (cust) : _("unknown")); + printf_filtered (_("Compiled with %s debugging format.\n"), + COMPUNIT_DEBUGFORMAT (cust)); printf_filtered (_("%s preprocessor macro info.\n"), - s->macro_table ? "Includes" : "Does not include"); + COMPUNIT_MACRO_TABLE (cust) != NULL + ? "Includes" : "Does not include"); } @@ -683,9 +711,10 @@ is_regular_file (const char *name) 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 @@ -697,6 +726,11 @@ is_regular_file (const char *name) 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. */ @@ -708,10 +742,14 @@ openp (const char *path, int opts, const char *string, { int fd; char *filename; - const char *p; - const char *p1; - int len; int alloclen; + VEC (char_ptr) *dir_vec; + struct cleanup *back_to; + int ix; + char *dir; + /* The errno set for the last name we tried to open (and + failed). */ + int last_errno = 0; /* The open syscall MODE parameter is not specified. */ gdb_assert ((mode & O_CREAT) == 0); @@ -741,9 +779,9 @@ openp (const char *path, int opts, const char *string, if (is_regular_file (string)) { - filename = alloca (strlen (string) + 1); + filename = (char *) alloca (strlen (string) + 1); strcpy (filename, string); - fd = open (filename, mode); + fd = gdb_open_cloexec (filename, mode, 0); if (fd >= 0) goto done; } @@ -752,6 +790,7 @@ openp (const char *path, int opts, const char *string, filename = NULL; fd = -1; } + last_errno = errno; if (!(opts & OPF_SEARCH_IN_PATH)) for (i = 0; string[i]; i++) @@ -772,18 +811,18 @@ openp (const char *path, int opts, const char *string, string += 2; alloclen = strlen (path) + strlen (string) + 2; - filename = alloca (alloclen); + filename = (char *) alloca (alloclen); fd = -1; - for (p = path; p; p = p1 ? p1 + 1 : 0) + last_errno = ENOENT; + + dir_vec = dirnames_to_char_ptr_vec (path); + back_to = make_cleanup_free_char_ptr_vec (dir_vec); + + for (ix = 0; VEC_iterate (char_ptr, dir_vec, ix, dir); ++ix) { - p1 = strchr (p, DIRNAME_SEPARATOR); - if (p1) - len = p1 - p; - else - len = strlen (p); + size_t len = strlen (dir); - if (len == 4 && p[0] == '$' && p[1] == 'c' - && p[2] == 'w' && p[3] == 'd') + if (strcmp (dir, "$cwd") == 0) { /* Name is $cwd -- insert current directory name instead. */ int newlen; @@ -794,15 +833,33 @@ openp (const char *path, int opts, const char *string, if (newlen > alloclen) { alloclen = newlen; - filename = alloca (alloclen); + filename = (char *) alloca (alloclen); } strcpy (filename, current_directory); } + else if (strchr(dir, '~')) + { + /* See whether we need to expand the tilde. */ + int newlen; + char *tilde_expanded; + + tilde_expanded = tilde_expand (dir); + + /* First, realloc the filename buffer if too short. */ + len = strlen (tilde_expanded); + newlen = len + strlen (string) + 2; + if (newlen > alloclen) + { + alloclen = newlen; + filename = (char *) alloca (alloclen); + } + strcpy (filename, tilde_expanded); + xfree (tilde_expanded); + } else { /* Normal file name in path -- just use it. */ - strncpy (filename, p, len); - filename[len] = 0; + strcpy (filename, dir); /* Don't search $cdir. It's also a magic path like $cwd, but we don't have enough information to expand it. The user *could* @@ -811,7 +868,7 @@ openp (const char *path, int opts, const char *string, contexts. If the user really has '$cdir' one can use './$cdir'. We can get $cdir when loading scripts. When loading source files $cdir must have already been expanded to the correct value. */ - if (strcmp (filename, "$cdir") == 0) + if (strcmp (dir, "$cdir") == 0) continue; } @@ -824,38 +881,28 @@ openp (const char *path, int opts, const char *string, if (is_regular_file (filename)) { - fd = open (filename, mode); + fd = gdb_open_cloexec (filename, mode, 0); if (fd >= 0) break; + last_errno = errno; } } + do_cleanups (back_to); + done: if (filename_opened) { - /* If a file was opened, canonicalize its filename. Use xfullpath - rather than gdb_realpath to avoid resolving the basename part - of filenames when the associated file is a symbolic link. This - fixes a potential inconsistency between the filenames known to - GDB and the filenames it prints in the annotations. */ + /* If a file was opened, canonicalize its filename. */ if (fd < 0) *filename_opened = NULL; - else if (IS_ABSOLUTE_PATH (filename)) - *filename_opened = xfullpath (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 = xfullpath (f); - xfree (f); - } + *filename_opened = gdb_abspath (filename); } + errno = last_errno; return fd; } @@ -876,8 +923,9 @@ source_full_path_of (const char *filename, char **full_pathname) { 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; @@ -897,27 +945,20 @@ substitute_path_rule_matches (const struct substitute_path_rule *rule, { const int from_len = strlen (rule->from); const int path_len = strlen (path); - char *path_start; if (path_len < from_len) return 0; /* The substitution rules are anchored at the start of the path, - so the path should start with rule->from. There is no filename - comparison routine, so we need to extract the first FROM_LEN - characters from PATH first and use that to do the comparison. */ - - path_start = alloca (from_len + 1); - strncpy (path_start, path, from_len); - path_start[from_len] = '\0'; + so the path should start with rule->from. */ - if (FILENAME_CMP (path_start, rule->from) != 0) + if (filename_ncmp (path, rule->from, from_len) != 0) return 0; /* Make sure that the region in the path that matches the substitution rule is immediately followed by a directory separator (or the end of string character). */ - + if (path[from_len] != '\0' && !IS_DIR_SEPARATOR (path[from_len])) return 0; @@ -945,7 +986,7 @@ get_substitute_path_rule (const char *path) Return NULL if no substitution rule was specified by the user, or if no rule applied to the given PATH. */ -static char * +char * rewrite_source_path (const char *path) { const struct substitute_path_rule *rule = get_substitute_path_rule (path); @@ -967,26 +1008,6 @@ rewrite_source_path (const char *path) return new_path; } -/* This function is capable of finding the absolute path to a - source file, and opening it, provided you give it a FILENAME. Both the - DIRNAME and FULLNAME are only added suggestions on where to find the file. - - FILENAME should be the filename to open. - DIRNAME is the compilation directory of a particular source file. - Only some debug formats provide this info. - FULLNAME can be the last known absolute path to the file in question. - Space for the path must have been malloc'd. If a path substitution - is applied we free the old value and set a new one. - - On Success - A valid file descriptor is returned (the return value is positive). - FULLNAME is set to the absolute path to the file just opened. - The caller is responsible for freeing FULLNAME. - - On Failure - An invalid file descriptor is returned (the return value is negative). - FULLNAME is set to NULL. */ - int find_and_open_source (const char *filename, const char *dirname, @@ -995,6 +1016,7 @@ find_and_open_source (const char *filename, char *path = source_path; const char *p; int result; + struct cleanup *cleanup; /* Quick way out if we already know its full name. */ @@ -1011,14 +1033,23 @@ find_and_open_source (const char *filename, *fullname = rewritten_fullname; } - result = open (*fullname, OPEN_MODE); + result = gdb_open_cloexec (*fullname, OPEN_MODE, 0); if (result >= 0) - return result; + { + char *lpath = gdb_realpath (*fullname); + + xfree (*fullname); + *fullname = lpath; + return result; + } + /* Didn't work -- free old one, try again. */ xfree (*fullname); *fullname = NULL; } + cleanup = make_cleanup (null_cleanup, NULL); + if (dirname != NULL) { /* If necessary, rewrite the compilation directory name according @@ -1066,15 +1097,18 @@ find_and_open_source (const char *filename, } } - 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; } @@ -1089,35 +1123,69 @@ open_source_file (struct symtab *s) if (!s) return -1; - return find_and_open_source (s->filename, s->dirname, &s->fullname); + return find_and_open_source (s->filename, SYMTAB_DIRNAME (s), &s->fullname); } /* Finds the fullname that a symtab represents. - If this functions finds the fullname, it will save it in s->fullname - and it will also return the value. + This functions finds the fullname and saves it in s->fullname. + It will also return the value. If this function fails to find the file that this symtab represents, - NULL will be returned and s->fullname will be set to NULL. */ -char * + the expected fullname is used. Therefore the files does not have to + exist. */ + +const char * symtab_to_fullname (struct symtab *s) { - int r; + /* Use cached copy if we have it. + We rely on forget_cached_source_info being called appropriately + to handle cases like the file being moved. */ + if (s->fullname == NULL) + { + int fd = find_and_open_source (s->filename, SYMTAB_DIRNAME (s), + &s->fullname); - if (!s) - return NULL; + if (fd >= 0) + close (fd); + else + { + char *fullname; + struct cleanup *back_to; - /* Don't check s->fullname here, the file could have been - deleted/moved/..., look for it again. */ - r = find_and_open_source (s->filename, s->dirname, &s->fullname); + /* rewrite_source_path would be applied by find_and_open_source, we + should report the pathname where GDB tried to find the file. */ - if (r >= 0) - { - close (r); - return s->fullname; - } + if (SYMTAB_DIRNAME (s) == NULL || IS_ABSOLUTE_PATH (s->filename)) + fullname = xstrdup (s->filename); + else + fullname = concat (SYMTAB_DIRNAME (s), SLASH_STRING, s->filename, + NULL); + + back_to = make_cleanup (xfree, fullname); + s->fullname = rewrite_source_path (fullname); + if (s->fullname == NULL) + s->fullname = xstrdup (fullname); + do_cleanups (back_to); + } + } - return NULL; + return s->fullname; +} + +/* See commentary in source.h. */ + +const char * +symtab_to_filename_for_display (struct symtab *symtab) +{ + if (filename_display_string == filename_display_basename) + return lbasename (symtab->filename); + else if (filename_display_string == filename_display_absolute) + return symtab_to_fullname (symtab); + else if (filename_display_string == filename_display_relative) + return symtab->filename; + else + internal_error (__FILE__, __LINE__, _("invalid filename_display_string")); } /* Create and initialize the table S->line_charpos that records @@ -1137,42 +1205,18 @@ find_source_lines (struct symtab *s, int desc) int size; gdb_assert (s); - line_charpos = (int *) xmalloc (lines_allocated * sizeof (int)); + line_charpos = XNEWVEC (int, lines_allocated); if (fstat (desc, &st) < 0) - perror_with_name (s->filename); + perror_with_name (symtab_to_filename_for_display (s)); - if (s->objfile && s->objfile->obfd) - mtime = s->objfile->mtime; + if (SYMTAB_OBJFILE (s) != NULL && SYMTAB_OBJFILE (s)->obfd != NULL) + mtime = SYMTAB_OBJFILE (s)->mtime; else if (exec_bfd) mtime = exec_bfd_mtime; if (mtime && mtime < st.st_mtime) warning (_("Source file is more recent than executable.")); -#ifdef LSEEK_NOT_LINEAR - { - char c; - - /* Have to read it byte by byte to find out where the chars live. */ - - line_charpos[0] = lseek (desc, 0, SEEK_CUR); - nlines = 1; - while (myread (desc, &c, 1) > 0) - { - if (c == '\n') - { - if (nlines == lines_allocated) - { - lines_allocated *= 2; - line_charpos = - (int *) xrealloc ((char *) line_charpos, - sizeof (int) * lines_allocated); - } - line_charpos[nlines++] = lseek (desc, 0, SEEK_CUR); - } - } - } -#else /* lseek linear. */ { struct cleanup *old_cleanups; @@ -1188,7 +1232,7 @@ find_source_lines (struct symtab *s, int desc) /* Reassign `size' to result of read for systems where \r\n -> \n. */ size = myread (desc, data, size); if (size < 0) - perror_with_name (s->filename); + perror_with_name (symtab_to_filename_for_display (s)); end = data + size; p = data; line_charpos[0] = 0; @@ -1211,53 +1255,13 @@ find_source_lines (struct symtab *s, int desc) } do_cleanups (old_cleanups); } -#endif /* lseek linear. */ + s->nlines = nlines; s->line_charpos = (int *) xrealloc ((char *) line_charpos, nlines * sizeof (int)); } -/* Return the character position of a line LINE in symtab S. - Return 0 if anything is invalid. */ - -#if 0 /* Currently unused */ - -int -source_line_charpos (struct symtab *s, int line) -{ - if (!s) - return 0; - if (!s->line_charpos || line <= 0) - return 0; - if (line > s->nlines) - line = s->nlines; - return s->line_charpos[line - 1]; -} - -/* Return the line number of character position POS in symtab S. */ - -int -source_charpos_line (struct symtab *s, int chr) -{ - int line = 0; - int *lnp; - - if (s == 0 || s->line_charpos == 0) - return 0; - lnp = s->line_charpos; - /* Files are usually short, so sequential search is Ok. */ - while (line < s->nlines && *lnp <= chr) - { - line++; - lnp++; - } - if (line >= s->nlines) - line = s->nlines; - return line; -} - -#endif /* 0 */ /* Get full pathname and line number positions for a symtab. @@ -1310,12 +1314,11 @@ identify_source_line (struct symtab *s, int line, int mid_statement, /* Don't index off the end of the line_charpos array. */ return 0; annotate_source (s->fullname, line, s->line_charpos[line - 1], - mid_statement, get_objfile_arch (s->objfile), pc); + mid_statement, get_objfile_arch (SYMTAB_OBJFILE (s)), pc); current_source_line = line; - first_line_listed = line; - last_line_listed = line; current_source_symtab = s; + clear_lines_listed_range (); return 1; } @@ -1323,10 +1326,9 @@ identify_source_line (struct symtab *s, int line, int mid_statement, /* Print source lines from the file of symtab S, starting with line number LINE and stopping before line number STOPLINE. */ -static void print_source_lines_base (struct symtab *s, int line, int stopline, - int noerror); static void -print_source_lines_base (struct symtab *s, int line, int stopline, int noerror) +print_source_lines_base (struct symtab *s, int line, int stopline, + print_source_lines_flags flags) { int c; int desc; @@ -1334,6 +1336,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror) FILE *stream; int nlines = stopline - line; struct cleanup *cleanup; + struct ui_out *uiout = current_uiout; /* Regardless of whether we can open the file, set current_source_symtab. */ current_source_symtab = s; @@ -1353,13 +1356,13 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror) else { desc = last_source_error; - noerror = 1; + flags |= PRINT_SOURCE_LINES_NOERROR; } } else { desc = last_source_error; - noerror = 1; + flags |= PRINT_SOURCE_LINES_NOERROR; noprint = 1; } @@ -1367,17 +1370,45 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror) { last_source_error = desc; - if (!noerror) + if (!(flags & PRINT_SOURCE_LINES_NOERROR)) { - char *name = alloca (strlen (s->filename) + 100); - sprintf (name, "%d\t%s", line, s->filename); + const char *filename = symtab_to_filename_for_display (s); + int len = strlen (filename) + 100; + char *name = (char *) alloca (len); + + xsnprintf (name, len, "%d\t%s", line, filename); print_sys_errmsg (name, errno); } else - ui_out_field_int (uiout, "line", line); - ui_out_text (uiout, "\tin "); - ui_out_field_string (uiout, "file", s->filename); - ui_out_text (uiout, "\n"); + { + ui_out_field_int (uiout, "line", line); + ui_out_text (uiout, "\tin "); + + /* 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 *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 = (char *) alloca (strlen (s_fullname) + 1); + strcpy (local_fullname, s_fullname); + + ui_out_field_string (uiout, "fullname", local_fullname); + } + + ui_out_text (uiout, "\n"); + } return; } @@ -1391,13 +1422,13 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror) { close (desc); error (_("Line number %d out of range; %s has %d lines."), - line, s->filename, s->nlines); + line, symtab_to_filename_for_display (s), s->nlines); } if (lseek (desc, s->line_charpos[line - 1], 0) < 0) { close (desc); - perror_with_name (s->filename); + perror_with_name (symtab_to_filename_for_display (s)); } stream = fdopen (desc, FDOPEN_MODE); @@ -1412,13 +1443,18 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror) if (c == EOF) break; last_line_listed = current_source_line; - sprintf (buf, "%d\t", current_source_line++); + if (flags & PRINT_SOURCE_LINES_FILENAME) + { + ui_out_text (uiout, symtab_to_filename_for_display (s)); + ui_out_text (uiout, ":"); + } + xsnprintf (buf, sizeof (buf), "%d\t", current_source_line++); ui_out_text (uiout, buf); do { if (c < 040 && c != '\t' && c != '\n' && c != '\r') { - sprintf (buf, "^%c", c + 0100); + xsnprintf (buf, sizeof (buf), "^%c", c + 0100); ui_out_text (uiout, buf); } else if (c == 0177) @@ -1435,7 +1471,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror) } else { - sprintf (buf, "%c", c); + xsnprintf (buf, sizeof (buf), "%c", c); ui_out_text (uiout, buf); } } @@ -1451,9 +1487,10 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror) window otherwise it is simply printed. */ void -print_source_lines (struct symtab *s, int line, int stopline, int noerror) +print_source_lines (struct symtab *s, int line, int stopline, + print_source_lines_flags flags) { - print_source_lines_base (s, line, stopline, noerror); + print_source_lines_base (s, line, stopline, flags); } /* Print info on range of pc's in a specified line. */ @@ -1465,30 +1502,39 @@ line_info (char *arg, int from_tty) struct symtab_and_line sal; CORE_ADDR start_pc, end_pc; int i; + struct cleanup *cleanups; init_sal (&sal); /* initialize to zeroes */ if (arg == 0) { sal.symtab = current_source_symtab; - sal.line = last_line_listed; + sal.pspace = current_program_space; + if (last_line_listed != 0) + sal.line = last_line_listed; + else + sal.line = current_source_line; + sals.nelts = 1; - sals.sals = (struct symtab_and_line *) - xmalloc (sizeof (struct symtab_and_line)); + sals.sals = XNEW (struct symtab_and_line); sals.sals[0] = sal; } else { - sals = decode_line_spec_1 (arg, 0); + sals = decode_line_with_last_displayed (arg, DECODE_LINE_LIST_MODE); dont_repeat (); } + cleanups = make_cleanup (xfree, sals.sals); + /* C++ More than one line may have been specified, as when the user specifies an overloaded function name. Print info on them all. */ for (i = 0; i < sals.nelts; i++) { sal = sals.sals[i]; + if (sal.pspace != current_program_space) + continue; if (sal.symtab == 0) { @@ -1511,12 +1557,14 @@ line_info (char *arg, int from_tty) else if (sal.line > 0 && find_line_pc_range (sal, &start_pc, &end_pc)) { - struct gdbarch *gdbarch = get_objfile_arch (sal.symtab->objfile); + struct gdbarch *gdbarch + = get_objfile_arch (SYMTAB_OBJFILE (sal.symtab)); if (start_pc == end_pc) { printf_filtered ("Line %d of \"%s\"", - sal.line, sal.symtab->filename); + sal.line, + symtab_to_filename_for_display (sal.symtab)); wrap_here (" "); printf_filtered (" is at address "); print_address (gdbarch, start_pc, gdb_stdout); @@ -1526,7 +1574,8 @@ line_info (char *arg, int from_tty) else { printf_filtered ("Line %d of \"%s\"", - sal.line, sal.symtab->filename); + sal.line, + symtab_to_filename_for_display (sal.symtab)); wrap_here (" "); printf_filtered (" starts at address "); print_address (gdbarch, start_pc, gdb_stdout); @@ -1552,9 +1601,9 @@ line_info (char *arg, int from_tty) which the user would want to see? If we have debugging symbols and no line numbers? */ printf_filtered (_("Line number %d is out of range for \"%s\".\n"), - sal.line, sal.symtab->filename); + sal.line, symtab_to_filename_for_display (sal.symtab)); } - xfree (sals.sals); + do_cleanups (cleanups); } /* Commands to search the source file for a regexp. */ @@ -1580,7 +1629,7 @@ forward_search_command (char *regex, int from_tty) desc = open_source_file (current_source_symtab); if (desc < 0) - perror_with_name (current_source_symtab->filename); + perror_with_name (symtab_to_filename_for_display (current_source_symtab)); cleanups = make_cleanup_close (desc); if (current_source_symtab->line_charpos == 0) @@ -1590,7 +1639,7 @@ forward_search_command (char *regex, int from_tty) error (_("Expression not found")); if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0) - perror_with_name (current_source_symtab->filename); + perror_with_name (symtab_to_filename_for_display (current_source_symtab)); discard_cleanups (cleanups); stream = fdopen (desc, FDOPEN_MODE); @@ -1603,10 +1652,10 @@ forward_search_command (char *regex, int from_tty) int cursize, newsize; cursize = 256; - buf = xmalloc (cursize); + buf = (char *) xmalloc (cursize); p = buf; - c = getc (stream); + c = fgetc (stream); if (c == EOF) break; do @@ -1615,12 +1664,12 @@ forward_search_command (char *regex, int from_tty) if (p - buf == cursize) { newsize = cursize + cursize / 2; - buf = xrealloc (buf, newsize); + buf = (char *) xrealloc (buf, newsize); p = buf + cursize; 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. */ @@ -1669,7 +1718,7 @@ reverse_search_command (char *regex, int from_tty) desc = open_source_file (current_source_symtab); if (desc < 0) - perror_with_name (current_source_symtab->filename); + perror_with_name (symtab_to_filename_for_display (current_source_symtab)); cleanups = make_cleanup_close (desc); if (current_source_symtab->line_charpos == 0) @@ -1679,7 +1728,7 @@ reverse_search_command (char *regex, int from_tty) error (_("Expression not found")); if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0) - perror_with_name (current_source_symtab->filename); + perror_with_name (symtab_to_filename_for_display (current_source_symtab)); discard_cleanups (cleanups); stream = fdopen (desc, FDOPEN_MODE); @@ -1691,14 +1740,14 @@ reverse_search_command (char *regex, int from_tty) 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. */ @@ -1722,8 +1771,11 @@ reverse_search_command (char *regex, int from_tty) line--; if (fseek (stream, current_source_symtab->line_charpos[line - 1], 0) < 0) { + const char *filename; + do_cleanups (cleanups); - perror_with_name (current_source_symtab->filename); + filename = symtab_to_filename_for_display (current_source_symtab); + perror_with_name (filename); } } @@ -1771,9 +1823,8 @@ void add_substitute_path_rule (char *from, char *to) { struct substitute_path_rule *rule; - struct substitute_path_rule *new_rule; + struct substitute_path_rule *new_rule = XNEW (struct substitute_path_rule); - new_rule = xmalloc (sizeof (struct substitute_path_rule)); new_rule->from = xstrdup (from); new_rule->to = xstrdup (to); new_rule->next = NULL; @@ -1830,9 +1881,10 @@ show_substitute_path_command (char *args, int from_tty) 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. */ @@ -1852,10 +1904,12 @@ show_substitute_path_command (char *args, int from_tty) while (rule != NULL) { - if (from == NULL || FILENAME_CMP (rule->from, from) == 0) + if (from == NULL || substitute_path_rule_matches (rule, from) != 0) printf_filtered (" `%s' -> `%s'.\n", rule->from, rule->to); rule = rule->next; } + + do_cleanups (cleanup); } /* Implement the "unset substitute-path" command. */ @@ -1867,10 +1921,11 @@ unset_substitute_path_command (char *args, int from_tty) 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")); @@ -1908,6 +1963,8 @@ unset_substitute_path_command (char *args, int from_tty) error (_("No substitution rule defined for `%s'"), from); forget_cached_source_info (); + + do_cleanups (cleanup); } /* Add a new source path substitution rule. */ @@ -1917,9 +1974,10 @@ set_substitute_path_command (char *args, int from_tty) { 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")); @@ -1946,6 +2004,8 @@ set_substitute_path_command (char *args, int from_tty) add_substitute_path_rule (argv[0], argv[1]); forget_cached_source_info (); + + do_cleanups (cleanup); } @@ -1993,16 +2053,6 @@ Setting the value to an empty string sets it to $cdir:$cwd, the default."), show_directories_command, &setlist, &showlist); - if (xdb_commands) - { - add_com_alias ("D", "directory", class_files, 0); - add_cmd ("ld", no_class, show_directories_1, _("\ -Current search path for finding source files.\n\ -$cwd in the path means the current working directory.\n\ -$cdir in the path means the compilation directory of the source file."), - &cmdlist); - } - add_info ("source", source_info, _("Information about the current source file.")); @@ -2022,21 +2072,19 @@ The address is also stored as the value of \"$_\".")); Search for regular expression (see regex(3)) from last line listed.\n\ The matching line number is also stored as the value of \"$_\".")); add_com_alias ("search", "forward-search", class_files, 0); + add_com_alias ("fo", "forward-search", class_files, 1); add_com ("reverse-search", class_files, reverse_search_command, _("\ Search backward for regular expression (see regex(3)) from last line listed.\n\ The matching line number is also stored as the value of \"$_\".")); add_com_alias ("rev", "reverse-search", class_files, 1); - if (xdb_commands) - { - add_com_alias ("/", "forward-search", class_files, 0); - add_com_alias ("?", "reverse-search", class_files, 0); - } - 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, +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); @@ -2063,4 +2111,19 @@ Usage: show substitute-path [FROM]\n\ Print the rule for substituting FROM in source file names. If FROM\n\ is not specified, print all substitution rules."), &showlist); + + add_setshow_enum_cmd ("filename-display", class_files, + filename_display_kind_names, + &filename_display_string, _("\ +Set how to display filenames."), _("\ +Show how to display filenames."), _("\ +filename-display can be:\n\ + basename - display only basename of a filename\n\ + relative - display a filename relative to the compilation directory\n\ + absolute - display an absolute filename\n\ +By default, relative filenames are displayed."), + NULL, + show_filename_display_string, + &setlist, &showlist); + }