X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fsource.c;h=e77789c0dbab8b9d0d7a118e44c91d33a065c2ba;hb=62ea19c1000856c2633a952c52269fca4143931a;hp=14b1f71c855344781153c7d3fda64d294df670c5;hpb=1e2ccb612d2b61014bb7e9fef3eb58e4947b9d2b;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/source.c b/gdb/source.c index 14b1f71c85..e77789c0db 100644 --- a/gdb/source.c +++ b/gdb/source.c @@ -1,5 +1,5 @@ /* List lines of source files for GDB, the GNU debugger. - Copyright (C) 1986-2014 Free Software Foundation, Inc. + Copyright (C) 1986-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -26,12 +26,9 @@ #include "gdbcmd.h" #include "frame.h" #include "value.h" -#include "gdb_assert.h" #include "filestuff.h" #include -#include -#include #include #include "gdbcore.h" #include "gdb_regex.h" @@ -44,26 +41,15 @@ #include "completer.h" #include "ui-out.h" #include "readline/readline.h" +#include "common/enum-flags.h" +#include "common/scoped_fd.h" +#include +#include "common/pathstuff.h" +#include "source-cache.h" #define OPEN_MODE (O_RDONLY | O_BINARY) #define FDOPEN_MODE FOPEN_RB -/* Prototypes for exported functions. */ - -void _initialize_source (void); - -/* Prototypes for local functions. */ - -static int get_filename_and_charpos (struct symtab *, char **); - -static void reverse_search_command (char *, int); - -static void forward_search_command (char *, int); - -static void line_info (char *, int); - -static void source_info (char *, int); - /* Path of directories to search for source files. Same format as the PATH environment variable's value. */ @@ -96,7 +82,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) @@ -182,7 +168,7 @@ get_lines_to_list (void) struct symtab_and_line get_current_source_symtab_and_line (void) { - struct symtab_and_line cursal = { 0 }; + symtab_and_line cursal; cursal.pspace = current_source_pspace; cursal.symtab = current_source_symtab; @@ -218,9 +204,9 @@ set_default_source_symtab_and_line (void) NOTE: The returned sal pc and end fields are not valid. */ struct symtab_and_line -set_current_source_symtab_and_line (const struct symtab_and_line *sal) +set_current_source_symtab_and_line (const symtab_and_line &sal) { - struct symtab_and_line cursal = { 0 }; + symtab_and_line cursal; cursal.pspace = current_source_pspace; cursal.symtab = current_source_symtab; @@ -228,9 +214,9 @@ set_current_source_symtab_and_line (const struct symtab_and_line *sal) cursal.pc = 0; cursal.end = 0; - current_source_pspace = sal->pspace; - current_source_symtab = sal->symtab; - current_source_line = sal->line; + current_source_pspace = sal.pspace; + current_source_symtab = sal.symtab; + current_source_line = sal.line; /* Force the next "list" to center around the current line. */ clear_lines_listed_range (); @@ -258,9 +244,8 @@ clear_current_source_symtab_and_line (void) void 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) { @@ -275,15 +260,15 @@ 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_with_current_source (main_name (), - DECODE_LINE_FUNFIRSTLINE); - sal = sals.sals[0]; - xfree (sals.sals); + std::vector sals + = decode_line_with_current_source (main_name (), + DECODE_LINE_FUNFIRSTLINE); + const symtab_and_line &sal = sals[0]; current_source_pspace = sal.pspace; current_source_symtab = sal.symtab; - current_source_line = max (sal.line - (lines_to_list - 1), 1); + current_source_line = std::max (sal.line - (lines_to_list - 1), 1); if (current_source_symtab) return; } @@ -293,19 +278,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; } } @@ -330,7 +312,8 @@ select_source_symtab (struct symtab *s) path list. The theory is that set(show(dir)) should be a no-op. */ static void -set_directories_command (char *args, int from_tty, struct cmd_list_element *c) +set_directories_command (const char *args, + int from_tty, struct cmd_list_element *c) { /* This is the value that was set. It needs to be processed to maintain $cdir:$cwd and remove dups. */ @@ -374,9 +357,10 @@ show_directories_command (struct ui_file *file, int from_tty, void forget_cached_source_info_for_objfile (struct objfile *objfile) { + struct compunit_symtab *cu; struct symtab *s; - ALL_OBJFILE_SYMTABS (objfile, s) + ALL_OBJFILE_FILETABS (objfile, cu, s) { if (s->line_charpos != NULL) { @@ -410,6 +394,7 @@ forget_cached_source_info (void) forget_cached_source_info_for_objfile (objfile); } + g_source_cache.clear (); last_source_visited = NULL; } @@ -426,7 +411,7 @@ init_source_path (void) /* Add zero or more directories to the front of the source path. */ static void -directory_command (char *dirname, int from_tty) +directory_command (const char *dirname, int from_tty) { dont_repeat (); /* FIXME, this goes to "delete dir"... */ @@ -451,7 +436,7 @@ directory_command (char *dirname, int from_tty) This will not be quoted so we must not treat spaces as separators. */ void -directory_switch (char *dirname, int from_tty) +directory_switch (const char *dirname, int from_tty) { add_path (dirname, &source_path, 0); } @@ -459,7 +444,7 @@ directory_switch (char *dirname, int from_tty) /* Add zero or more directories to the front of an arbitrary path. */ void -mod_path (char *dirname, char **which_path) +mod_path (const char *dirname, char **which_path) { add_path (dirname, which_path, 1); } @@ -471,39 +456,33 @@ mod_path (char *dirname, char **which_path) as space or tab. */ void -add_path (char *dirname, char **which_path, int parse_separators) +add_path (const char *dirname, char **which_path, int parse_separators) { char *old = *which_path; int prefix = 0; - VEC (char_ptr) *dir_vec = NULL; - struct cleanup *back_to; - int ix; - char *name; + std::vector> dir_vec; 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. */ - argv = gdb_buildargv (dirname); + gdb_argv argv (dirname); - for (argvp = argv; *argvp; argvp++) - dirnames_to_char_ptr_vec_append (&dir_vec, *argvp); - - freeargv (argv); + for (char *arg : argv) + dirnames_to_char_ptr_vec_append (&dir_vec, arg); } else - VEC_safe_push (char_ptr, dir_vec, xstrdup (dirname)); - back_to = make_cleanup_free_char_ptr_vec (dir_vec); + dir_vec.emplace_back (xstrdup (dirname)); - for (ix = 0; VEC_iterate (char_ptr, dir_vec, ix, name); ++ix) + for (const gdb::unique_xmalloc_ptr &name_up : dir_vec) { + char *name = name_up.get (); char *p; struct stat st; + gdb::unique_xmalloc_ptr new_name_holder; /* Spaces and tabs will have been removed by buildargv(). NAME is the start of the directory. @@ -549,16 +528,17 @@ add_path (char *dirname, char **which_path, int parse_separators) } if (name[0] == '~') - name = tilde_expand (name); + new_name_holder.reset (tilde_expand (name)); #ifdef HAVE_DOS_BASED_FILE_SYSTEM else if (IS_ABSOLUTE_PATH (name) && p == name + 2) /* "d:" => "d:." */ - name = concat (name, ".", (char *)NULL); + new_name_holder.reset (concat (name, ".", (char *) NULL)); #endif else if (!IS_ABSOLUTE_PATH (name) && name[0] != '$') - name = concat (current_directory, SLASH_STRING, name, (char *)NULL); + new_name_holder.reset (concat (current_directory, SLASH_STRING, name, + (char *) NULL)); else - name = savestring (name, p - name); - make_cleanup (xfree, name); + new_name_holder.reset (savestring (name, p - name)); + name = new_name_holder.get (); /* Unless it's a variable, check existence. */ if (name[0] != '$') @@ -648,24 +628,25 @@ add_path (char *dirname, char **which_path, int parse_separators) skip_dup: ; } - - do_cleanups (back_to); } static void -source_info (char *ignore, int from_tty) +info_source_command (const 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) @@ -673,30 +654,17 @@ 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"); } -/* Return True if the file NAME exists and is a regular file. */ -static int -is_regular_file (const char *name) -{ - struct stat st; - const int status = stat (name, &st); - - /* Stat should never fail except when the file does not exist. - If stat fails, analyze the source of error and return True - unless the file does not exist, to avoid returning false results - on obscure systems where stat does not work as expected. */ - - if (status != 0) - return (errno != ENOENT); - - return S_ISREG (st.st_mode); -} - /* Open a file named STRING, searching path PATH (dir names sep by some char) using mode MODE in the calls to open. You cannot use this function to create files (O_CREAT). @@ -731,16 +699,16 @@ is_regular_file (const char *name) /* >>>> This should only allow files of certain types, >>>> eg executable, non-directory. */ int -openp (const char *path, int opts, const char *string, - int mode, char **filename_opened) +openp (const char *path, openp_flags opts, const char *string, + int mode, gdb::unique_xmalloc_ptr *filename_opened) { int fd; char *filename; 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; + std::vector> dir_vec; /* The open syscall MODE parameter is not specified. */ gdb_assert ((mode & O_CREAT) == 0); @@ -766,20 +734,22 @@ openp (const char *path, int opts, const char *string, if ((opts & OPF_TRY_CWD_FIRST) || IS_ABSOLUTE_PATH (string)) { - int i; + int i, reg_file_errno; - if (is_regular_file (string)) + if (is_regular_file (string, ®_file_errno)) { - filename = alloca (strlen (string) + 1); + filename = (char *) alloca (strlen (string) + 1); strcpy (filename, string); fd = gdb_open_cloexec (filename, mode, 0); if (fd >= 0) goto done; + last_errno = errno; } else { filename = NULL; fd = -1; + last_errno = reg_file_errno; } if (!(opts & OPF_SEARCH_IN_PATH)) @@ -801,15 +771,17 @@ 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; + 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) + for (const gdb::unique_xmalloc_ptr &dir_up : dir_vec) { + char *dir = dir_up.get (); size_t len = strlen (dir); + int reg_file_errno; if (strcmp (dir, "$cwd") == 0) { @@ -822,7 +794,7 @@ 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); } @@ -830,20 +802,18 @@ openp (const char *path, int opts, const char *string, { /* See whether we need to expand the tilde. */ int newlen; - char *tilde_expanded; - tilde_expanded = tilde_expand (dir); + gdb::unique_xmalloc_ptr tilde_expanded (tilde_expand (dir)); /* First, realloc the filename buffer if too short. */ - len = strlen (tilde_expanded); + len = strlen (tilde_expanded.get ()); newlen = len + strlen (string) + 2; if (newlen > alloclen) { alloclen = newlen; - filename = alloca (alloclen); + filename = (char *) alloca (alloclen); } - strcpy (filename, tilde_expanded); - xfree (tilde_expanded); + strcpy (filename, tilde_expanded.get ()); } else { @@ -868,28 +838,30 @@ openp (const char *path, int opts, const char *string, strcat (filename + len, SLASH_STRING); strcat (filename, string); - if (is_regular_file (filename)) + if (is_regular_file (filename, ®_file_errno)) { fd = gdb_open_cloexec (filename, mode, 0); if (fd >= 0) break; + last_errno = errno; } + else + last_errno = reg_file_errno; } - do_cleanups (back_to); - done: if (filename_opened) { /* If a file was opened, canonicalize its filename. */ if (fd < 0) - *filename_opened = NULL; + filename_opened->reset (NULL); else if ((opts & OPF_RETURN_REALPATH) != 0) *filename_opened = gdb_realpath (filename); else *filename_opened = gdb_abspath (filename); } + errno = last_errno; return fd; } @@ -906,7 +878,8 @@ done: Else, this functions returns 0, and FULL_PATHNAME is set to NULL. */ int -source_full_path_of (const char *filename, char **full_pathname) +source_full_path_of (const char *filename, + gdb::unique_xmalloc_ptr *full_pathname) { int fd; @@ -915,7 +888,7 @@ source_full_path_of (const char *filename, char **full_pathname) filename, O_RDONLY, full_pathname); if (fd < 0) { - *full_pathname = NULL; + full_pathname->reset (NULL); return 0; } @@ -967,13 +940,12 @@ get_substitute_path_rule (const char *path) } /* If the user specified a source path substitution rule that applies - to PATH, then apply it and return the new path. This new path must - be deallocated afterwards. - + to PATH, then apply it and return the new path. + Return NULL if no substitution rule was specified by the user, or if no rule applied to the given PATH. */ - -char * + +gdb::unique_xmalloc_ptr rewrite_source_path (const char *path) { const struct substitute_path_rule *rule = get_substitute_path_rule (path); @@ -992,18 +964,19 @@ rewrite_source_path (const char *path) strcpy (new_path, rule->to); strcat (new_path, path + from_len); - return new_path; + return gdb::unique_xmalloc_ptr (new_path); } -int +/* See source.h. */ + +scoped_fd find_and_open_source (const char *filename, const char *dirname, - char **fullname) + gdb::unique_xmalloc_ptr *fullname) { char *path = source_path; const char *p; int result; - struct cleanup *cleanup; /* Quick way out if we already know its full name. */ @@ -1012,44 +985,34 @@ find_and_open_source (const char *filename, /* The user may have requested that source paths be rewritten according to substitution rules he provided. If a substitution rule applies to this path, then apply it. */ - char *rewritten_fullname = rewrite_source_path (*fullname); + gdb::unique_xmalloc_ptr rewritten_fullname + = rewrite_source_path (fullname->get ()); if (rewritten_fullname != NULL) - { - xfree (*fullname); - *fullname = rewritten_fullname; - } + *fullname = std::move (rewritten_fullname); - result = gdb_open_cloexec (*fullname, OPEN_MODE, 0); + result = gdb_open_cloexec (fullname->get (), OPEN_MODE, 0); if (result >= 0) { - char *lpath = gdb_realpath (*fullname); - - xfree (*fullname); - *fullname = lpath; - return result; + *fullname = gdb_realpath (fullname->get ()); + return scoped_fd (result); } /* Didn't work -- free old one, try again. */ - xfree (*fullname); - *fullname = NULL; + fullname->reset (NULL); } - cleanup = make_cleanup (null_cleanup, NULL); - + gdb::unique_xmalloc_ptr rewritten_dirname; if (dirname != NULL) { /* If necessary, rewrite the compilation directory name according to the source path substitution rules specified by the user. */ - char *rewritten_dirname = rewrite_source_path (dirname); + rewritten_dirname = rewrite_source_path (dirname); if (rewritten_dirname != NULL) - { - make_cleanup (xfree, rewritten_dirname); - dirname = rewritten_dirname; - } - + dirname = rewritten_dirname.get (); + /* Replace a path entry of $cdir with the compilation directory name. */ #define cdir_len 5 @@ -1071,17 +1034,15 @@ find_and_open_source (const char *filename, } } + gdb::unique_xmalloc_ptr rewritten_filename; if (IS_ABSOLUTE_PATH (filename)) { /* If filename is absolute path, try the source path substitution on it. */ - char *rewritten_filename = rewrite_source_path (filename); + rewritten_filename = rewrite_source_path (filename); if (rewritten_filename != NULL) - { - make_cleanup (xfree, rewritten_filename); - filename = rewritten_filename; - } + filename = rewritten_filename.get (); } result = openp (path, OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH, filename, @@ -1095,8 +1056,7 @@ find_and_open_source (const char *filename, OPEN_MODE, fullname); } - do_cleanups (cleanup); - return result; + return scoped_fd (result); } /* Open a source file given a symtab S. Returns a file descriptor or @@ -1104,13 +1064,18 @@ find_and_open_source (const char *filename, This function is a convience function to find_and_open_source. */ -int +scoped_fd open_source_file (struct symtab *s) { if (!s) - return -1; + return scoped_fd (-1); - return find_and_open_source (s->filename, s->dirname, &s->fullname); + gdb::unique_xmalloc_ptr fullname (s->fullname); + s->fullname = NULL; + scoped_fd fd = find_and_open_source (s->filename, SYMTAB_DIRNAME (s), + &fullname); + s->fullname = fullname.release (); + return fd; } /* Finds the fullname that a symtab represents. @@ -1130,28 +1095,24 @@ symtab_to_fullname (struct symtab *s) to handle cases like the file being moved. */ if (s->fullname == NULL) { - int fd = find_and_open_source (s->filename, s->dirname, &s->fullname); + scoped_fd fd = open_source_file (s); - if (fd >= 0) - close (fd); - else + if (fd.get () < 0) { - char *fullname; - struct cleanup *back_to; + gdb::unique_xmalloc_ptr 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 (s->dirname == NULL || IS_ABSOLUTE_PATH (s->filename)) - fullname = xstrdup (s->filename); + if (SYMTAB_DIRNAME (s) == NULL || IS_ABSOLUTE_PATH (s->filename)) + fullname.reset (xstrdup (s->filename)); else - fullname = concat (s->dirname, SLASH_STRING, s->filename, NULL); + fullname.reset (concat (SYMTAB_DIRNAME (s), SLASH_STRING, + s->filename, (char *) NULL)); - back_to = make_cleanup (xfree, fullname); - s->fullname = rewrite_source_path (fullname); + s->fullname = rewrite_source_path (fullname.get ()).release (); if (s->fullname == NULL) - s->fullname = xstrdup (fullname); - do_cleanups (back_to); + s->fullname = fullname.release (); } } @@ -1182,7 +1143,7 @@ void find_source_lines (struct symtab *s, int desc) { struct stat st; - char *data, *p, *end; + char *p, *end; int nlines = 0; int lines_allocated = 1000; int *line_charpos; @@ -1190,12 +1151,12 @@ 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 (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; @@ -1203,23 +1164,20 @@ find_source_lines (struct symtab *s, int desc) warning (_("Source file is more recent than executable.")); { - struct cleanup *old_cleanups; - /* st_size might be a large type, but we only support source files whose size fits in an int. */ size = (int) st.st_size; - /* Use malloc, not alloca, because this may be pretty large, and we may - run into various kinds of limits on stack size. */ - data = (char *) xmalloc (size); - old_cleanups = make_cleanup (xfree, data); + /* Use the heap, not the stack, because this may be pretty large, + and we may run into various kinds of limits on stack size. */ + gdb::def_vector data (size); /* Reassign `size' to result of read for systems where \r\n -> \n. */ - size = myread (desc, data, size); + size = myread (desc, data.data (), size); if (size < 0) perror_with_name (symtab_to_filename_for_display (s)); - end = data + size; - p = data; + end = data.data () + size; + p = &data[0]; line_charpos[0] = 0; nlines = 1; while (p != end) @@ -1235,10 +1193,9 @@ find_source_lines (struct symtab *s, int desc) (int *) xrealloc ((char *) line_charpos, sizeof (int) * lines_allocated); } - line_charpos[nlines++] = p - data; + line_charpos[nlines++] = p - data.data (); } } - do_cleanups (old_cleanups); } s->nlines = nlines; @@ -1250,32 +1207,23 @@ find_source_lines (struct symtab *s, int desc) /* Get full pathname and line number positions for a symtab. - Return nonzero if line numbers may have changed. Set *FULLNAME to actual name of the file as found by `openp', or to 0 if the file is not found. */ -static int +static void get_filename_and_charpos (struct symtab *s, char **fullname) { - int desc, linenums_changed = 0; - struct cleanup *cleanups; - - desc = open_source_file (s); - if (desc < 0) + scoped_fd desc = open_source_file (s); + if (desc.get () < 0) { if (fullname) *fullname = NULL; - return 0; + return; } - cleanups = make_cleanup_close (desc); if (fullname) *fullname = s->fullname; if (s->line_charpos == 0) - linenums_changed = 1; - if (linenums_changed) - find_source_lines (s, desc); - do_cleanups (cleanups); - return linenums_changed; + find_source_lines (s, desc.get ()); } /* Print text describing the full name of the source file S @@ -1299,7 +1247,7 @@ 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; current_source_symtab = s; @@ -1313,14 +1261,12 @@ identify_source_line (struct symtab *s, int line, int mid_statement, static void print_source_lines_base (struct symtab *s, int line, int stopline, - enum print_source_lines_flags flags) + print_source_lines_flags flags) { int c; - int desc; + scoped_fd desc; int noprint = 0; - 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. */ @@ -1330,55 +1276,55 @@ print_source_lines_base (struct symtab *s, int line, int stopline, /* If printing of source lines is disabled, just print file and line number. */ - if (ui_out_test_flags (uiout, ui_source_list)) + if (uiout->test_flags (ui_source_list)) { /* Only prints "No such file or directory" once. */ if ((s != last_source_visited) || (!last_source_error)) { last_source_visited = s; desc = open_source_file (s); + if (desc.get () < 0) + { + last_source_error = desc.get (); + noprint = 1; + } } else { - desc = last_source_error; flags |= PRINT_SOURCE_LINES_NOERROR; + noprint = 1; } } else { - desc = last_source_error; - flags |= PRINT_SOURCE_LINES_NOERROR; + flags |= PRINT_SOURCE_LINES_NOERROR; noprint = 1; } - if (desc < 0 || noprint) + if (noprint) { - last_source_error = desc; - if (!(flags & PRINT_SOURCE_LINES_NOERROR)) { const char *filename = symtab_to_filename_for_display (s); int len = strlen (filename) + 100; - char *name = alloca (len); + 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 "); + uiout->field_int ("line", line); + uiout->text ("\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)) + if (uiout->is_mi_like_p () || uiout->test_flags (ui_source_list)) + uiout->field_string ("file", symtab_to_filename_for_display (s), + ui_out_style_kind::FILE); + if (uiout->is_mi_like_p () || !uiout->test_flags (ui_source_list)) { const char *s_fullname = symtab_to_fullname (s); char *local_fullname; @@ -1386,13 +1332,13 @@ print_source_lines_base (struct symtab *s, int line, int stopline, /* 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); + local_fullname = (char *) alloca (strlen (s_fullname) + 1); strcpy (local_fullname, s_fullname); - ui_out_field_string (uiout, "fullname", local_fullname); + uiout->field_string ("fullname", local_fullname); } - ui_out_text (uiout, "\n"); + uiout->text ("\n"); } return; @@ -1400,70 +1346,54 @@ print_source_lines_base (struct symtab *s, int line, int stopline, last_source_error = 0; - if (s->line_charpos == 0) - find_source_lines (s, desc); - - if (line < 1 || line > s->nlines) - { - close (desc); - error (_("Line number %d out of range; %s has %d lines."), - line, symtab_to_filename_for_display (s), s->nlines); - } - - if (lseek (desc, s->line_charpos[line - 1], 0) < 0) - { - close (desc); - perror_with_name (symtab_to_filename_for_display (s)); - } - - stream = fdopen (desc, FDOPEN_MODE); - clearerr (stream); - cleanup = make_cleanup_fclose (stream); + std::string lines; + if (!g_source_cache.get_source_lines (s, line, stopline - 1, &lines)) + error (_("Line number %d out of range; %s has %d lines."), + line, symtab_to_filename_for_display (s), s->nlines); + const char *iter = lines.c_str (); while (nlines-- > 0) { char buf[20]; - c = fgetc (stream); - if (c == EOF) + c = *iter++; + if (c == '\0') break; last_line_listed = current_source_line; if (flags & PRINT_SOURCE_LINES_FILENAME) { - ui_out_text (uiout, symtab_to_filename_for_display (s)); - ui_out_text (uiout, ":"); + uiout->text (symtab_to_filename_for_display (s)); + uiout->text (":"); } xsnprintf (buf, sizeof (buf), "%d\t", current_source_line++); - ui_out_text (uiout, buf); + uiout->text (buf); do { - if (c < 040 && c != '\t' && c != '\n' && c != '\r') + if (c < 040 && c != '\t' && c != '\n' && c != '\r' && c != '\033') { xsnprintf (buf, sizeof (buf), "^%c", c + 0100); - ui_out_text (uiout, buf); + uiout->text (buf); } else if (c == 0177) - ui_out_text (uiout, "^?"); + uiout->text ("^?"); else if (c == '\r') { /* Skip a \r character, but only before a \n. */ - int c1 = fgetc (stream); - - if (c1 != '\n') + if (*iter != '\n') printf_filtered ("^%c", c + 0100); - if (c1 != EOF) - ungetc (c1, stream); } else { xsnprintf (buf, sizeof (buf), "%c", c); - ui_out_text (uiout, buf); + uiout->text (buf); } } - while (c != '\n' && (c = fgetc (stream)) >= 0); + while (c != '\n' && (c = *iter++) != '\0'); + if (c == '\0') + break; } - - do_cleanups (cleanup); + if (lines.back () != '\n') + uiout->text ("\n"); } /* Show source lines from the file of symtab S, starting with line @@ -1473,7 +1403,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline, void print_source_lines (struct symtab *s, int line, int stopline, - enum print_source_lines_flags flags) + print_source_lines_flags flags) { print_source_lines_base (s, line, stopline, flags); } @@ -1481,44 +1411,38 @@ print_source_lines (struct symtab *s, int line, int stopline, /* Print info on range of pc's in a specified line. */ static void -line_info (char *arg, int from_tty) +info_line_command (const char *arg, int from_tty) { - struct symtabs_and_lines sals; - struct symtab_and_line sal; CORE_ADDR start_pc, end_pc; - int i; - struct cleanup *cleanups; - init_sal (&sal); /* initialize to zeroes */ + std::vector decoded_sals; + symtab_and_line curr_sal; + gdb::array_view sals; if (arg == 0) { - sal.symtab = current_source_symtab; - sal.pspace = current_program_space; + curr_sal.symtab = current_source_symtab; + curr_sal.pspace = current_program_space; if (last_line_listed != 0) - sal.line = last_line_listed; + curr_sal.line = last_line_listed; else - sal.line = current_source_line; + curr_sal.line = current_source_line; - sals.nelts = 1; - sals.sals = (struct symtab_and_line *) - xmalloc (sizeof (struct symtab_and_line)); - sals.sals[0] = sal; + sals = curr_sal; } else { - sals = decode_line_with_last_displayed (arg, DECODE_LINE_LIST_MODE); + decoded_sals = decode_line_with_last_displayed (arg, + DECODE_LINE_LIST_MODE); + sals = decoded_sals; 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++) + for (const auto &sal : sals) { - sal = sals.sals[i]; if (sal.pspace != current_program_space) continue; @@ -1543,7 +1467,8 @@ 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) { @@ -1578,7 +1503,7 @@ line_info (char *arg, int from_tty) /* If this is the only line, show the source code. If it could not find the file, don't do anything special. */ - if (annotation_level && sals.nelts == 1) + if (annotation_level && sals.size () == 1) identify_source_line (sal.symtab, sal.line, 0, start_pc); } else @@ -1588,185 +1513,111 @@ line_info (char *arg, int from_tty) printf_filtered (_("Line number %d is out of range for \"%s\".\n"), sal.line, symtab_to_filename_for_display (sal.symtab)); } - do_cleanups (cleanups); } /* Commands to search the source file for a regexp. */ +/* Helper for forward_search_command/reverse_search_command. FORWARD + indicates direction: true for forward, false for + backward/reverse. */ + static void -forward_search_command (char *regex, int from_tty) +search_command_helper (const char *regex, int from_tty, bool forward) { - int c; - int desc; - FILE *stream; - int line; - char *msg; - struct cleanup *cleanups; - - line = last_line_listed + 1; - - msg = (char *) re_comp (regex); + const char *msg = re_comp (regex); if (msg) error (("%s"), msg); if (current_source_symtab == 0) select_source_symtab (0); - desc = open_source_file (current_source_symtab); - if (desc < 0) + scoped_fd desc = open_source_file (current_source_symtab); + if (desc.get () < 0) perror_with_name (symtab_to_filename_for_display (current_source_symtab)); - cleanups = make_cleanup_close (desc); if (current_source_symtab->line_charpos == 0) - find_source_lines (current_source_symtab, desc); + find_source_lines (current_source_symtab, desc.get ()); + + int line = (forward + ? last_line_listed + 1 + : last_line_listed - 1); if (line < 1 || line > current_source_symtab->nlines) error (_("Expression not found")); - if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0) + if (lseek (desc.get (), current_source_symtab->line_charpos[line - 1], 0) + < 0) perror_with_name (symtab_to_filename_for_display (current_source_symtab)); - discard_cleanups (cleanups); - stream = fdopen (desc, FDOPEN_MODE); - clearerr (stream); - cleanups = make_cleanup_fclose (stream); + gdb_file_up stream = desc.to_file (FDOPEN_MODE); + clearerr (stream.get ()); + + gdb::def_vector buf; + buf.reserve (256); + while (1) { - static char *buf = NULL; - char *p; - int cursize, newsize; - - cursize = 256; - buf = xmalloc (cursize); - p = buf; + buf.resize (0); - c = fgetc (stream); + int c = fgetc (stream.get ()); if (c == EOF) break; do { - *p++ = c; - if (p - buf == cursize) - { - newsize = cursize + cursize / 2; - buf = xrealloc (buf, newsize); - p = buf + cursize; - cursize = newsize; - } + buf.push_back (c); } - while (c != '\n' && (c = fgetc (stream)) >= 0); + while (c != '\n' && (c = fgetc (stream.get ())) >= 0); /* Remove the \r, if any, at the end of the line, otherwise regular expressions that end with $ or \n won't work. */ - if (p - buf > 1 && p[-2] == '\r') + size_t sz = buf.size (); + if (sz >= 2 && buf[sz - 2] == '\r') { - p--; - p[-1] = '\n'; + buf[sz - 2] = '\n'; + buf.resize (sz - 1); } /* We now have a source line in buf, null terminate and match. */ - *p = 0; - if (re_exec (buf) > 0) + buf.push_back ('\0'); + if (re_exec (buf.data ()) > 0) { /* Match! */ - do_cleanups (cleanups); print_source_lines (current_source_symtab, line, line + 1, 0); set_internalvar_integer (lookup_internalvar ("_"), line); - current_source_line = max (line - lines_to_list / 2, 1); + current_source_line = std::max (line - lines_to_list / 2, 1); return; } - line++; + + if (forward) + line++; + else + { + line--; + if (line < 1) + break; + if (fseek (stream.get (), + current_source_symtab->line_charpos[line - 1], 0) < 0) + { + const char *filename + = symtab_to_filename_for_display (current_source_symtab); + perror_with_name (filename); + } + } } printf_filtered (_("Expression not found\n")); - do_cleanups (cleanups); } static void -reverse_search_command (char *regex, int from_tty) +forward_search_command (const char *regex, int from_tty) { - int c; - int desc; - FILE *stream; - int line; - char *msg; - struct cleanup *cleanups; - - line = last_line_listed - 1; - - msg = (char *) re_comp (regex); - if (msg) - error (("%s"), msg); - - if (current_source_symtab == 0) - select_source_symtab (0); - - desc = open_source_file (current_source_symtab); - if (desc < 0) - perror_with_name (symtab_to_filename_for_display (current_source_symtab)); - cleanups = make_cleanup_close (desc); - - if (current_source_symtab->line_charpos == 0) - find_source_lines (current_source_symtab, desc); - - if (line < 1 || line > current_source_symtab->nlines) - error (_("Expression not found")); - - if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0) - perror_with_name (symtab_to_filename_for_display (current_source_symtab)); - - discard_cleanups (cleanups); - stream = fdopen (desc, FDOPEN_MODE); - clearerr (stream); - cleanups = make_cleanup_fclose (stream); - while (line > 1) - { -/* FIXME!!! We walk right off the end of buf if we get a long line!!! */ - char buf[4096]; /* Should be reasonable??? */ - char *p = buf; - - c = fgetc (stream); - if (c == EOF) - break; - do - { - *p++ = c; - } - 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. */ - if (p - buf > 1 && p[-2] == '\r') - { - p--; - p[-1] = '\n'; - } - - /* We now have a source line in buf; null terminate and match. */ - *p = 0; - if (re_exec (buf) > 0) - { - /* Match! */ - do_cleanups (cleanups); - print_source_lines (current_source_symtab, line, line + 1, 0); - set_internalvar_integer (lookup_internalvar ("_"), line); - current_source_line = max (line - lines_to_list / 2, 1); - return; - } - line--; - if (fseek (stream, current_source_symtab->line_charpos[line - 1], 0) < 0) - { - const char *filename; - - do_cleanups (cleanups); - filename = symtab_to_filename_for_display (current_source_symtab); - perror_with_name (filename); - } - } + search_command_helper (regex, from_tty, true); +} - printf_filtered (_("Expression not found\n")); - do_cleanups (cleanups); - return; +static void +reverse_search_command (const char *regex, int from_tty) +{ + search_command_helper (regex, from_tty, false); } /* If the last character of PATH is a directory separator, then strip it. */ @@ -1808,9 +1659,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; @@ -1862,15 +1712,12 @@ delete_substitute_path_rule (struct substitute_path_rule *rule) /* Implement the "show substitute-path" command. */ static void -show_substitute_path_command (char *args, int from_tty) +show_substitute_path_command (const 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); - cleanup = make_cleanup_freeargv (argv); + gdb_argv argv (args); /* We expect zero or one argument. */ @@ -1894,24 +1741,20 @@ show_substitute_path_command (char *args, int from_tty) printf_filtered (" `%s' -> `%s'.\n", rule->from, rule->to); rule = rule->next; } - - do_cleanups (cleanup); } /* Implement the "unset substitute-path" command. */ static void -unset_substitute_path_command (char *args, int from_tty) +unset_substitute_path_command (const char *args, int from_tty) { struct substitute_path_rule *rule = substitute_path_rules; - char **argv = gdb_buildargv (args); + gdb_argv argv (args); char *from = NULL; int rule_found = 0; - struct cleanup *cleanup; /* This function takes either 0 or 1 argument. */ - cleanup = make_cleanup_freeargv (argv); if (argv != NULL && argv[0] != NULL && argv[1] != NULL) error (_("Incorrect usage, too many arguments in command")); @@ -1949,21 +1792,16 @@ 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. */ static void -set_substitute_path_command (char *args, int from_tty) +set_substitute_path_command (const char *args, int from_tty) { - char **argv; struct substitute_path_rule *rule; - struct cleanup *cleanup; - argv = gdb_buildargv (args); - cleanup = make_cleanup_freeargv (argv); + gdb_argv argv (args); if (argv == NULL || argv[0] == NULL || argv [1] == NULL) error (_("Incorrect usage, too few arguments in command")); @@ -1990,8 +1828,6 @@ set_substitute_path_command (char *args, int from_tty) add_substitute_path_rule (argv[0], argv[1]); forget_cached_source_info (); - - do_cleanups (cleanup); } @@ -2039,20 +1875,10 @@ 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, + add_info ("source", info_source_command, _("Information about the current source file.")); - add_info ("line", line_info, _("\ + add_info ("line", info_line_command, _("\ Core addresses of the code for a source line.\n\ Line can be specified as\n\ LINENUM, to list around that line in current file,\n\ @@ -2075,12 +1901,6 @@ 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."), _("\