static void pwd_command (char *, int);
-static void show_version (char *, int);
-
static void help_command (char *, int);
static void show_command (char *, int);
static void set_debug (char *, int);
-static void show_user (char *, int);
-
static void make_command (char *, int);
static void shell_escape (const char *, int);
/* 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 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 */
}
static void
-show_version (char *args, int from_tty)
+show_version (const char *args, int from_tty)
{
print_gdb_version (gdb_stdout);
printf_filtered ("\n");
}
static void
-show_configuration (char *args, int from_tty)
+show_configuration (const char *args, int from_tty)
{
print_gdb_configuration (gdb_stdout);
}
{
if (args)
error (_("The \"pwd\" command does not take an argument: %s"), args);
- if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
+
+ gdb::unique_xmalloc_ptr<char> cwd (getcwd (NULL, 0));
+
+ if (cwd == NULL)
error (_("Error finding name of working directory: %s"),
safe_strerror (errno));
- if (strcmp (gdb_dirbuf, current_directory) != 0)
+ if (strcmp (cwd.get (), current_directory) != 0)
printf_unfiltered (_("Working directory %s\n (canonically %s).\n"),
- current_directory, gdb_dirbuf);
+ current_directory, cwd.get ());
else
printf_unfiltered (_("Working directory %s.\n"), current_directory);
}
void
-cd_command (char *dir, int from_tty)
+cd_command (const char *dir, int from_tty)
{
int len;
/* Found something other than leading repetitions of "/..". */
/* There's too much mess with DOSish names like "d:", "d:.",
"d:./foo" etc. Instead of having lots of special #ifdef'ed code,
simply get the canonicalized name of the current directory. */
- dir = getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
+ gdb::unique_xmalloc_ptr<char> cwd (getcwd (NULL, 0));
+ dir = cwd.get ();
#endif
len = strlen (dir);
dir_holder.reset (savestring (dir, len));
if (IS_ABSOLUTE_PATH (dir_holder.get ()))
- current_directory = dir_holder.release ();
+ {
+ xfree (current_directory);
+ current_directory = dir_holder.release ();
+ }
else
{
if (IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1]))
}
static void
-source_command (char *args, int from_tty)
+source_command (const char *args, int from_tty)
{
- char *file = args;
+ const char *file = args;
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;
}
else
{
- char *arg1;
+ const char *arg1;
/* Now should only be one argument -- decode it in SAL. */
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;
+ const char *arg1;
int no_end = 1;
int dummy_end = 0;
int dummy_beg = 0;
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)
- {
- printf_filtered (_("file: \"%s\", line number: %d\n"),
- symtab_to_filename_for_display (sal.symtab),
- sal.line);
- }
+ if (sals.size () > 1)
+ print_sal_location (sal);
print_source_lines (sal.symtab,
first_line,
first_line + get_lines_to_list (),
? sal.line + get_lines_to_list ()
: sal_end.line + 1),
0);
- xfree (sals.sals);
}
/* Subroutine of disassemble_command to simplify it.
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;
}
static void
-show_user (char *args, int from_tty)
+show_user (const char *args, int from_tty)
{
struct cmd_list_element *c;
extern struct cmd_list_element *cmdlist;
}
}
\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)
{
/* Define the classes of commands.
They will appear in the help list in alphabetical order. */
- add_cmd ("internals", class_maintenance, NULL, _("\
+ add_cmd ("internals", class_maintenance, _("\
Maintenance commands.\n\
Some gdb commands are provided just for use by gdb maintainers.\n\
These commands are subject to frequent change, and may not be as\n\
well documented as user commands."),
&cmdlist);
- add_cmd ("obscure", class_obscure, NULL, _("Obscure features."), &cmdlist);
- add_cmd ("aliases", class_alias, NULL,
+ add_cmd ("obscure", class_obscure, _("Obscure features."), &cmdlist);
+ add_cmd ("aliases", class_alias,
_("Aliases of other commands."), &cmdlist);
- add_cmd ("user-defined", class_user, NULL, _("\
+ add_cmd ("user-defined", class_user, _("\
User-defined commands.\n\
The commands in this class are those defined by the user.\n\
Use the \"define\" command to define a command."), &cmdlist);
- add_cmd ("support", class_support, NULL, _("Support facilities."), &cmdlist);
+ add_cmd ("support", class_support, _("Support facilities."), &cmdlist);
if (!dbx_commands)
- add_cmd ("status", class_info, NULL, _("Status inquiries."), &cmdlist);
- add_cmd ("files", class_files, NULL, _("Specifying and examining files."),
+ add_cmd ("status", class_info, _("Status inquiries."), &cmdlist);
+ add_cmd ("files", class_files, _("Specifying and examining files."),
&cmdlist);
- add_cmd ("breakpoints", class_breakpoint, NULL,
+ add_cmd ("breakpoints", class_breakpoint,
_("Making program stop at certain points."), &cmdlist);
- add_cmd ("data", class_vars, NULL, _("Examining data."), &cmdlist);
- add_cmd ("stack", class_stack, NULL, _("\
+ add_cmd ("data", class_vars, _("Examining data."), &cmdlist);
+ add_cmd ("stack", class_stack, _("\
Examining the stack.\n\
The stack is made up of stack frames. Gdb assigns numbers to stack frames\n\
counting from zero for the innermost (currently executing) frame.\n\n\
When the program being debugged stops, gdb selects the innermost frame.\n\
The commands below can be used to select other frames by number or address."),
&cmdlist);
- add_cmd ("running", class_run, NULL, _("Running the program."), &cmdlist);
+ add_cmd ("running", class_run, _("Running the program."), &cmdlist);
/* Define general commands. */
Print working directory. This is used for your program as well."));
c = add_cmd ("cd", class_files, cd_command, _("\
-Set working directory to DIR for debugger and program being debugged.\n\
-The change does not take effect for the program being debugged\n\
-until the next time it is started."), &cmdlist);
+Set working directory to DIR for debugger.\n\
+The debugger's current working directory specifies where scripts and other\n\
+files that can be loaded by GDB are located.\n\
+In order to change the inferior's current working directory, the recommended\n\
+way is to use the \"set cwd\" command."), &cmdlist);
set_cmd_completer (c, filename_completer);
add_com ("echo", class_support, echo_command, _("\