/* Prototypes for local utility functions */
-static void ambiguous_line_spec (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 (struct symtabs_and_lines *);
+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. */
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."));
- sals.nelts = 0;
- sals.sals = NULL;
+ 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;
}
- sal = sals.sals[0];
+ 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.nelts > 1)
+ if (sals.size () > 1)
{
- ambiguous_line_spec (&sals);
- xfree (sals.sals);
+ ambiguous_line_spec (sals,
+ _("Specified first line '%.*s' is ambiguous:\n"),
+ (int) beg_len, beg);
return;
}
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)
- {
- xfree (sals.sals);
- return;
- }
- if (sals_end.nelts > 1)
+ 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.size () > 1)
{
- ambiguous_line_spec (&sals_end);
- xfree (sals_end.sals);
- xfree (sals.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)
{
- for (int i = 0; i < sals.nelts; i++)
+ for (int i = 0; i < sals.size (); i++)
{
- sal = sals.sals[i];
+ sal = sals[i];
int first_line = sal.line - get_lines_to_list () / 2;
if (first_line < 1)
first_line = 1;
- if (sals.nelts > 1)
+ if (sals.size () > 1)
{
printf_filtered (_("file: \"%s\", line number: %d\n"),
symtab_to_filename_for_display (sal.symtab),
? sal.line + get_lines_to_list ()
: sal_end.line + 1),
0);
- xfree (sals.sals);
}
/* Subroutine of disassemble_command to simplify it.
\f
/* 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)
+ for (const auto &sal : sals)
printf_filtered (_("file: \"%s\", line number: %d\n"),
- symtab_to_filename_for_display (sals->sals[i].symtab),
- sals->sals[i].line);
+ symtab_to_filename_for_display (sal.symtab),
+ sal.line);
}
-/* 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