/* Prototypes for local utility functions */
-static void ambiguous_line_spec (struct symtabs_and_lines *);
+static void print_sal_location (const symtab_and_line &sal);
-static void filter_sals (struct symtabs_and_lines *);
+static void ambiguous_line_spec (gdb::array_view<const symtab_and_line> sals,
+ const char *format, ...)
+ ATTRIBUTE_PRINTF (2, 3);
+
+static void filter_sals (std::vector<symtab_and_line> &);
\f
/* Limit the call depth of user-defined commands */
/* Found something other than leading repetitions of "/..". */
int found_real_path;
char *p;
- struct cleanup *cleanup;
/* If the new directory is absolute, repeat is a no-op; if relative,
repeat might be useful but is more likely to be a mistake. */
dont_repeat ();
- dir = tilde_expand (dir != NULL ? dir : "~");
- cleanup = make_cleanup (xfree, dir);
+ gdb::unique_xmalloc_ptr<char> dir_holder
+ (tilde_expand (dir != NULL ? dir : "~"));
+ dir = dir_holder.get ();
if (chdir (dir) < 0)
perror_with_name (dir);
len--;
}
- dir = savestring (dir, len);
- if (IS_ABSOLUTE_PATH (dir))
- current_directory = dir;
+ dir_holder.reset (savestring (dir, len));
+ if (IS_ABSOLUTE_PATH (dir_holder.get ()))
+ current_directory = dir_holder.release ();
else
{
if (IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1]))
- current_directory = concat (current_directory, dir, (char *)NULL);
+ current_directory = concat (current_directory, dir_holder.get (),
+ (char *) NULL);
else
current_directory = concat (current_directory, SLASH_STRING,
- dir, (char *)NULL);
- xfree (dir);
+ dir_holder.get (), (char *) NULL);
}
/* Now simplify any occurrences of `.' and `..' in the pathname. */
if (from_tty)
pwd_command ((char *) 0, 1);
-
- do_cleanups (cleanup);
}
\f
/* Show the current value of the 'script-extension' option. */
gdb::optional<open_script>
find_and_open_script (const char *script_file, int search_path)
{
- char *file;
int fd;
- struct cleanup *old_cleanups;
int search_flags = OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH;
gdb::optional<open_script> opened;
- file = tilde_expand (script_file);
- old_cleanups = make_cleanup (xfree, file);
+ gdb::unique_xmalloc_ptr<char> file (tilde_expand (script_file));
if (search_path)
search_flags |= OPF_SEARCH_IN_PATH;
files. Put the full location in *FULL_PATHP. */
char *temp_path;
fd = openp (source_path, search_flags,
- file, O_RDONLY, &temp_path);
+ file.get (), O_RDONLY, &temp_path);
gdb::unique_xmalloc_ptr<char> full_path (temp_path);
if (fd == -1)
- {
- int save_errno = errno;
- do_cleanups (old_cleanups);
- errno = save_errno;
- return opened;
- }
-
- do_cleanups (old_cleanups);
+ return opened;
FILE *result = fdopen (fd, FOPEN_RT);
if (result == NULL)
source_command (char *args, int from_tty)
{
char *file = args;
- int *old_source_verbose = XNEW (int);
int search_path = 0;
scoped_restore save_source_verbose = make_scoped_restore (&source_verbose);
static void
edit_command (char *arg, int from_tty)
{
- struct symtabs_and_lines sals;
struct symtab_and_line sal;
struct symbol *sym;
const char *editor;
arg1 = arg;
event_location_up location = string_to_event_location (&arg1,
current_language);
- sals = decode_line_1 (location.get (), DECODE_LINE_LIST_MODE,
- NULL, NULL, 0);
+ std::vector<symtab_and_line> sals = decode_line_1 (location.get (),
+ DECODE_LINE_LIST_MODE,
+ NULL, NULL, 0);
- filter_sals (&sals);
- if (! sals.nelts)
+ filter_sals (sals);
+ if (sals.empty ())
{
/* C++ */
return;
}
- if (sals.nelts > 1)
+ if (sals.size () > 1)
{
- ambiguous_line_spec (&sals);
- xfree (sals.sals);
+ ambiguous_line_spec (sals,
+ _("Specified line is ambiguous:\n"));
return;
}
- sal = sals.sals[0];
- xfree (sals.sals);
+ sal = sals[0];
if (*arg1)
error (_("Junk at end of line specification."));
static void
list_command (char *arg, int from_tty)
{
- struct symtabs_and_lines sals, sals_end;
- struct symtab_and_line sal = { 0 };
- struct symtab_and_line sal_end = { 0 };
- struct symtab_and_line cursal = { 0 };
struct symbol *sym;
char *arg1;
int no_end = 1;
if (arg == NULL || ((arg[0] == '+' || arg[0] == '-') && arg[1] == '\0'))
{
set_default_source_symtab_and_line ();
- cursal = get_current_source_symtab_and_line ();
+ symtab_and_line cursal = get_current_source_symtab_and_line ();
/* If this is the first "list" since we've set the current
source line, center the listing around that line. */
if (!have_full_symbols () && !have_partial_symbols ())
error (_("No symbol table is loaded. Use the \"file\" command."));
+ std::vector<symtab_and_line> sals;
+ symtab_and_line sal, sal_end;
+
arg1 = arg;
if (*arg1 == ',')
dummy_beg = 1;
current_language);
sals = decode_line_1 (location.get (), DECODE_LINE_LIST_MODE,
NULL, NULL, 0);
-
- filter_sals (&sals);
- if (!sals.nelts)
+ filter_sals (sals);
+ if (sals.empty ())
{
/* C++ */
return;
}
- if (sals.nelts > 1)
- {
- ambiguous_line_spec (&sals);
- xfree (sals.sals);
- return;
- }
- sal = sals.sals[0];
- xfree (sals.sals);
+ sal = sals[0];
}
/* Record whether the BEG arg is all digits. */
for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++);
linenum_beg = (p == arg1);
+ /* Save the range of the first argument, in case we need to let the
+ user know it was ambiguous. */
+ const char *beg = arg;
+ size_t beg_len = arg1 - beg;
+
while (*arg1 == ' ' || *arg1 == '\t')
arg1++;
if (*arg1 == ',')
{
no_end = 0;
+ if (sals.size () > 1)
+ {
+ ambiguous_line_spec (sals,
+ _("Specified first line '%.*s' is ambiguous:\n"),
+ (int) beg_len, beg);
+ return;
+ }
arg1++;
while (*arg1 == ' ' || *arg1 == '\t')
arg1++;
dummy_end = 1;
else
{
+ /* Save the last argument, in case we need to let the user
+ know it was ambiguous. */
+ const char *end_arg = arg1;
+
event_location_up location
= string_to_event_location (&arg1, current_language);
- if (dummy_beg)
- sals_end = decode_line_1 (location.get (),
- DECODE_LINE_LIST_MODE, NULL, NULL, 0);
- else
- sals_end = decode_line_1 (location.get (), DECODE_LINE_LIST_MODE,
- NULL, sal.symtab, sal.line);
- filter_sals (&sals_end);
- if (sals_end.nelts == 0)
+ std::vector<symtab_and_line> sals_end
+ = (dummy_beg
+ ? decode_line_1 (location.get (), DECODE_LINE_LIST_MODE,
+ NULL, NULL, 0)
+ : decode_line_1 (location.get (), DECODE_LINE_LIST_MODE,
+ NULL, sal.symtab, sal.line));
+
+ filter_sals (sals_end);
+ if (sals_end.empty ())
return;
- if (sals_end.nelts > 1)
+ if (sals_end.size () > 1)
{
- ambiguous_line_spec (&sals_end);
- xfree (sals_end.sals);
+ ambiguous_line_spec (sals_end,
+ _("Specified last line '%s' is ambiguous:\n"),
+ end_arg);
return;
}
- sal_end = sals_end.sals[0];
- xfree (sals_end.sals);
+ sal_end = sals_end[0];
}
}
if (!no_end && !dummy_beg && !dummy_end
&& sal.symtab != sal_end.symtab)
- error (_("Specified start and end are in different files."));
+ error (_("Specified first and last lines are in different files."));
if (dummy_beg && dummy_end)
error (_("Two empty args do not say what lines to list."));
error (_("No default source file yet. Do \"help list\"."));
else if (no_end)
{
- int first_line = sal.line - get_lines_to_list () / 2;
-
- if (first_line < 1) first_line = 1;
-
- print_source_lines (sal.symtab,
- first_line,
- first_line + get_lines_to_list (),
- 0);
+ for (int i = 0; i < sals.size (); i++)
+ {
+ sal = sals[i];
+ int first_line = sal.line - get_lines_to_list () / 2;
+ if (first_line < 1)
+ first_line = 1;
+ if (sals.size () > 1)
+ print_sal_location (sal);
+ print_source_lines (sal.symtab,
+ first_line,
+ first_line + get_lines_to_list (),
+ 0);
+ }
}
else
print_source_lines (sal.symtab, sal.line,
static void
print_disassembly (struct gdbarch *gdbarch, const char *name,
- CORE_ADDR low, CORE_ADDR high, int flags)
+ CORE_ADDR low, CORE_ADDR high,
+ gdb_disassembly_flags flags)
{
#if defined(TUI)
if (!tui_is_window_visible (DISASSEM_WIN))
Print a disassembly of the current function according to FLAGS. */
static void
-disassemble_current_function (int flags)
+disassemble_current_function (gdb_disassembly_flags flags)
{
struct frame_info *frame;
struct gdbarch *gdbarch;
CORE_ADDR low, high;
const char *name;
CORE_ADDR pc;
- int flags;
+ gdb_disassembly_flags flags;
const char *p;
p = arg;
}
}
- p = skip_spaces_const (p);
+ p = skip_spaces (p);
}
if ((flags & (DISASSEMBLY_SOURCE_DEPRECATED | DISASSEMBLY_SOURCE))
/* Two arguments. */
int incl_flag = 0;
low = pc;
- p = skip_spaces_const (p);
+ p = skip_spaces (p);
if (p[0] == '+')
{
++p;
{
int i, alias_argc, command_argc;
int abbrev_flag = 0;
- char *args2, *equals;
+ char *equals;
const char *alias, *command;
- char **alias_argv, **command_argv;
- struct cleanup *cleanup;
if (args == NULL || strchr (args, '=') == NULL)
alias_usage_error ();
- args2 = xstrdup (args);
- cleanup = make_cleanup (xfree, args2);
- equals = strchr (args2, '=');
- *equals = '\0';
- alias_argv = gdb_buildargv (args2);
- make_cleanup_freeargv (alias_argv);
- command_argv = gdb_buildargv (equals + 1);
- make_cleanup_freeargv (command_argv);
+ equals = strchr (args, '=');
+ std::string args2 (args, equals - args);
+
+ gdb_argv built_alias_argv (args2.c_str ());
+ gdb_argv command_argv (equals + 1);
- for (i = 0; alias_argv[i] != NULL; )
+ char **alias_argv = built_alias_argv.get ();
+ while (alias_argv[0] != NULL)
{
- if (strcmp (alias_argv[i], "-a") == 0)
+ if (strcmp (alias_argv[0], "-a") == 0)
{
++alias_argv;
abbrev_flag = 1;
}
- else if (strcmp (alias_argv[i], "--") == 0)
+ else if (strcmp (alias_argv[0], "--") == 0)
{
++alias_argv;
break;
}
alias_argc = countargv (alias_argv);
- command_argc = countargv (command_argv);
+ command_argc = command_argv.count ();
/* COMMAND must exist.
Reconstruct the command to remove any extraneous spaces,
for better error messages. */
- std::string command_string (argv_to_string (command_argv, command_argc));
+ std::string command_string (argv_to_string (command_argv.get (),
+ command_argc));
command = command_string.c_str ();
if (! valid_command_p (command))
error (_("Invalid command to alias to: %s"), command);
command_argv[command_argc - 1],
class_alias, abbrev_flag, c_command->prefixlist);
}
-
- do_cleanups (cleanup);
}
\f
+/* Print the file / line number / symbol name of the location
+ specified by SAL. */
+
+static void
+print_sal_location (const symtab_and_line &sal)
+{
+ scoped_restore_current_program_space restore_pspace;
+ set_current_program_space (sal.pspace);
+
+ const char *sym_name = NULL;
+ if (sal.symbol != NULL)
+ sym_name = SYMBOL_PRINT_NAME (sal.symbol);
+ printf_filtered (_("file: \"%s\", line number: %d, symbol: \"%s\"\n"),
+ symtab_to_filename_for_display (sal.symtab),
+ sal.line, sym_name != NULL ? sym_name : "???");
+}
+
/* Print a list of files and line numbers which a user may choose from
in order to list a function which was specified ambiguously (as
- with `list classname::overloadedfuncname', for example). The
- vector in SALS provides the filenames and line numbers. */
+ with `list classname::overloadedfuncname', for example). The SALS
+ array provides the filenames and line numbers. FORMAT is a
+ printf-style format string used to tell the user what was
+ ambiguous. */
static void
-ambiguous_line_spec (struct symtabs_and_lines *sals)
+ambiguous_line_spec (gdb::array_view<const symtab_and_line> sals,
+ const char *format, ...)
{
- int i;
+ va_list ap;
+ va_start (ap, format);
+ vprintf_filtered (format, ap);
+ va_end (ap);
- for (i = 0; i < sals->nelts; ++i)
- printf_filtered (_("file: \"%s\", line number: %d\n"),
- symtab_to_filename_for_display (sals->sals[i].symtab),
- sals->sals[i].line);
+ for (const auto &sal : sals)
+ print_sal_location (sal);
}
-/* Sort function for filter_sals. */
+/* Comparison function for filter_sals. Returns a qsort-style
+ result. */
static int
-compare_symtabs (const void *a, const void *b)
+cmp_symtabs (const symtab_and_line &sala, const symtab_and_line &salb)
{
- const struct symtab_and_line *sala = (const struct symtab_and_line *) a;
- const struct symtab_and_line *salb = (const struct symtab_and_line *) b;
- const char *dira = SYMTAB_DIRNAME (sala->symtab);
- const char *dirb = SYMTAB_DIRNAME (salb->symtab);
+ const char *dira = SYMTAB_DIRNAME (sala.symtab);
+ const char *dirb = SYMTAB_DIRNAME (salb.symtab);
int r;
if (dira == NULL)
return r;
}
- r = filename_cmp (sala->symtab->filename, salb->symtab->filename);
+ r = filename_cmp (sala.symtab->filename, salb.symtab->filename);
if (r)
return r;
- if (sala->line < salb->line)
+ if (sala.line < salb.line)
return -1;
- return sala->line == salb->line ? 0 : 1;
+ return sala.line == salb.line ? 0 : 1;
}
/* Remove any SALs that do not match the current program space, or
which appear to be "file:line" duplicates. */
static void
-filter_sals (struct symtabs_and_lines *sals)
+filter_sals (std::vector<symtab_and_line> &sals)
{
- int i, out, prev;
-
- out = 0;
- for (i = 0; i < sals->nelts; ++i)
- {
- if (sals->sals[i].pspace == current_program_space
- && sals->sals[i].symtab != NULL)
- {
- sals->sals[out] = sals->sals[i];
- ++out;
- }
- }
- sals->nelts = out;
-
- qsort (sals->sals, sals->nelts, sizeof (struct symtab_and_line),
- compare_symtabs);
-
- out = 1;
- prev = 0;
- for (i = 1; i < sals->nelts; ++i)
- {
- if (compare_symtabs (&sals->sals[prev], &sals->sals[i]))
- {
- /* Symtabs differ. */
- sals->sals[out] = sals->sals[i];
- prev = out;
- ++out;
- }
- }
-
- if (sals->nelts == 0)
- {
- xfree (sals->sals);
- sals->sals = NULL;
- }
- else
- sals->nelts = out;
+ /* Remove SALs that do not match. */
+ auto from = std::remove_if (sals.begin (), sals.end (),
+ [&] (const symtab_and_line &sal)
+ { return (sal.pspace != current_program_space || sal.symtab == NULL); });
+
+ /* Remove dups. */
+ std::sort (sals.begin (), from,
+ [] (const symtab_and_line &sala, const symtab_and_line &salb)
+ { return cmp_symtabs (sala, salb) < 0; });
+
+ from = std::unique (sals.begin (), from,
+ [&] (const symtab_and_line &sala,
+ const symtab_and_line &salb)
+ { return cmp_symtabs (sala, salb) == 0; });
+
+ sals.erase (from, sals.end ());
}
static void
value);
}
-\f
-
-initialize_file_ftype _initialize_cli_cmds;
-
void
_initialize_cli_cmds (void)
{