[RFA 22/23] Make gdb_buildargv return a unique pointer

Tom Tromey
2017-05-03T22:46:56Z

This introduces gdb_argv_up, a unique pointer wrapping an "argv"
pointer; that is, a pointer to a NULL-terminated array of char*, where
both the array and each non-NULL element in the array are xmalloc'd.

This patch then changes gdb_buildargv to return a gdb_argv_up and
fixes all the users. It also changes skip.c to use gdb_buildargv
(previously it was the only direct caller of buildargv, other than
gdb_buildargv itself).

One future change that might make sense would be to add begin and end
functions, so that an argv could be iterated over. I didn't look into
this too much; and perhaps replacing some uses with
std::vector<std::string> would be even better.

2017-05-02 Tom Tromey <tom@tromey.com>

* utils.h (struct gdb_argv_deleter): New.
(gdb_argv_up): New typedef.
(gdb_buildargv): Change return type.
* utils.c (gdb_buildargv): Return gdb_argv_up.
* tracepoint.c (delete_trace_variable_command): Update.
* tracefile.c (tsave_command): Update.
* top.c (new_ui_command): Update.
* symmisc.c (maintenance_print_symbols)
(maintenance_print_msymbols, maintenance_expand_symtabs): Update.
* symfile.c (symbol_file_command, generic_load)
(remove_symbol_file_command): Update.
* stack.c (backtrace_command): Update.
* source.c (add_path, show_substitute_path_command)
(unset_substitute_path_command, set_substitute_path_command):
Update.
* skip.c (skip_command): Update. Use gdb_buildargv.
* ser-mingw.c (pipe_windows_open): Update.
* remote.c (extended_remote_run, remote_put_command)
(remote_get_command, remote_delete_command): Update.
* remote-sim.c (gdbsim_load, gdbsim_create_inferior)
(gdbsim_open): Update.
* python/py-cmd.c (gdbpy_string_to_argv): Update.
* psymtab.c (maintenance_print_psymbols): Update.
* procfs.c (procfs_info_proc): Update.
* interps.c (interpreter_exec_cmd): Update.
* infrun.c (handle_command): Update.
* inferior.c (add_inferior_command, clone_inferior_command):
Update.
* guile/scm-string.c (gdbscm_string_to_argv): Update.
* exec.c (exec_file_command): Update.
* compile/compile.c (build_argc_argv): Update.
* cli/cli-cmds.c (alias_command): Update.
---
gdb/ChangeLog | 35 +++++++++++++++++++++++++++++++++++
gdb/cli/cli-cmds.c | 31 +++++++++++++------------------
gdb/compile/compile.c | 2 +-
gdb/exec.c | 14 ++++----------
gdb/guile/scm-string.c | 4 +---
gdb/inferior.c | 26 ++++++++------------------
gdb/infrun.c | 8 ++------
gdb/interps.c | 13 ++-----------
gdb/procfs.c | 5 +++--
gdb/psymtab.c | 5 ++---
gdb/python/py-cmd.c | 9 ++-------
gdb/remote-sim.c | 10 +++++-----
gdb/remote.c | 30 ++++--------------------------
gdb/ser-mingw.c | 2 +-
gdb/skip.c | 8 +-------
gdb/source.c | 28 ++++++----------------------
gdb/stack.c | 2 +-
gdb/symfile.c | 22 ++++++++--------------
gdb/symmisc.c | 17 +++++------------
gdb/top.c | 10 ++--------
gdb/tracefile.c | 6 +++---
gdb/tracepoint.c | 7 +------
gdb/utils.c | 4 ++--
gdb/utils.h | 19 ++++++++++++++++++-
24 files changed, 130 insertions(+), 187 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 286d414..4dc3bb4 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,40 @@
2017-05-02 Tom Tromey <tom@tromey.com>

+ * utils.h (struct gdb_argv_deleter): New.
+ (gdb_argv_up): New typedef.
+ (gdb_buildargv): Change return type.
+ * utils.c (gdb_buildargv): Return gdb_argv_up.
+ * tracepoint.c (delete_trace_variable_command): Update.
+ * tracefile.c (tsave_command): Update.
+ * top.c (new_ui_command): Update.
+ * symmisc.c (maintenance_print_symbols)
+ (maintenance_print_msymbols, maintenance_expand_symtabs): Update.
+ * symfile.c (symbol_file_command, generic_load)
+ (remove_symbol_file_command): Update.
+ * stack.c (backtrace_command): Update.
+ * source.c (add_path, show_substitute_path_command)
+ (unset_substitute_path_command, set_substitute_path_command):
+ Update.
+ * skip.c (skip_command): Update. Use gdb_buildargv.
+ * ser-mingw.c (pipe_windows_open): Update.
+ * remote.c (extended_remote_run, remote_put_command)
+ (remote_get_command, remote_delete_command): Update.
+ * remote-sim.c (gdbsim_load, gdbsim_create_inferior)
+ (gdbsim_open): Update.
+ * python/py-cmd.c (gdbpy_string_to_argv): Update.
+ * psymtab.c (maintenance_print_psymbols): Update.
+ * procfs.c (procfs_info_proc): Update.
+ * interps.c (interpreter_exec_cmd): Update.
+ * infrun.c (handle_command): Update.
+ * inferior.c (add_inferior_command, clone_inferior_command):
+ Update.
+ * guile/scm-string.c (gdbscm_string_to_argv): Update.
+ * exec.c (exec_file_command): Update.
+ * compile/compile.c (build_argc_argv): Update.
+ * cli/cli-cmds.c (alias_command): Update.
+
+2017-05-02 Tom Tromey <tom@tromey.com>
+
* python/python.c (gdbpy_decode_line): Use unique_xmalloc_ptr.

2017-05-02 Tom Tromey <tom@tromey.com>
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 3dc8b9c..5ba0922 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -1403,31 +1403,27 @@ alias_command (char *args, int from_tty)
{
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_up built_alias_argv = gdb_buildargv (args2.c_str ());
+ gdb_argv_up command_argv = gdb_buildargv (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;
@@ -1452,12 +1448,13 @@ alias_command (char *args, int from_tty)
}

alias_argc = countargv (alias_argv);
- command_argc = countargv (command_argv);
+ command_argc = countargv (command_argv.get ());

/* 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);
@@ -1514,8 +1511,6 @@ alias_command (char *args, int from_tty)
command_argv[command_argc - 1],
class_alias, abbrev_flag, c_command->prefixlist);
}
-
- do_cleanups (cleanup);
}
\f
/* Print a list of files and line numbers which a user may choose from
diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
index 5269aaf..4994219 100644
--- a/gdb/compile/compile.c
+++ b/gdb/compile/compile.c
@@ -292,7 +292,7 @@ get_expr_block_and_pc (CORE_ADDR *pc)
static void
build_argc_argv (const char *s, int *argcp, char ***argvp)
{
- *argvp = gdb_buildargv (s);
+ *argvp = gdb_buildargv (s).release ();
*argcp = countargv (*argvp);
}

diff --git a/gdb/exec.c b/gdb/exec.c
index 2c9a74b..8fba0a1 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -410,7 +410,6 @@ exec_file_attach (const char *filename, int from_tty)
static void
exec_file_command (char *args, int from_tty)
{
- char **argv;
char *filename;

if (from_tty && target_has_execution
@@ -420,13 +419,11 @@ exec_file_command (char *args, int from_tty)

if (args)
{
- struct cleanup *cleanups;
-
/* Scan through the args and pick up the first non option arg
as the filename. */

- argv = gdb_buildargv (args);
- cleanups = make_cleanup_freeargv (argv);
+ gdb_argv_up built_argv = gdb_buildargv (args);
+ char **argv = built_argv.get ();

for (; (*argv != NULL) && (**argv == '-'); argv++)
{;
@@ -434,11 +431,8 @@ exec_file_command (char *args, int from_tty)
if (*argv == NULL)
error (_("No executable file name was specified"));

- filename = tilde_expand (*argv);
- make_cleanup (xfree, filename);
- exec_file_attach (filename, from_tty);
-
- do_cleanups (cleanups);
+ gdb::unique_xmalloc_ptr<char> filename (tilde_expand (*argv));
+ exec_file_attach (filename.get (), from_tty);
}
else
exec_file_attach (NULL, from_tty);
diff --git a/gdb/guile/scm-string.c b/gdb/guile/scm-string.c
index d97f583..c6432c1 100644
--- a/gdb/guile/scm-string.c
+++ b/gdb/guile/scm-string.c
@@ -241,7 +241,6 @@ static SCM
gdbscm_string_to_argv (SCM string_scm)
{
char *string;
- char **c_argv;
int i;
SCM result = SCM_EOL;

@@ -254,11 +253,10 @@ gdbscm_string_to_argv (SCM string_scm)
return SCM_EOL;
}

- c_argv = gdb_buildargv (string);
+ gdb_argv_up c_argv = gdb_buildargv (string);
for (i = 0; c_argv[i] != NULL; ++i)
result = scm_cons (gdbscm_scm_from_c_string (c_argv[i]), result);

- freeargv (c_argv);
xfree (string);

return scm_reverse_x (result, SCM_EOL);
diff --git a/gdb/inferior.c b/gdb/inferior.c
index 002296f..1b467884 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -820,20 +820,17 @@ static void
add_inferior_command (char *args, int from_tty)
{
int i, copies = 1;
- char *exec = NULL;
- char **argv;
+ gdb::unique_xmalloc_ptr<char> exec;
symfile_add_flags add_flags = 0;
- struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);

if (from_tty)
add_flags |= SYMFILE_VERBOSE;

if (args)
{
- argv = gdb_buildargv (args);
- make_cleanup_freeargv (argv);
+ gdb_argv_up built_argv = gdb_buildargv (args);

- for (; *argv != NULL; argv++)
+ for (char **argv = built_argv.get (); *argv != NULL; argv++)
{
if (**argv == '-')
{
@@ -849,8 +846,7 @@ add_inferior_command (char *args, int from_tty)
++argv;
if (!*argv)
error (_("No argument to -exec"));
- exec = tilde_expand (*argv);
- make_cleanup (xfree, exec);
+ exec.reset (tilde_expand (*argv));
}
}
else
@@ -874,12 +870,10 @@ add_inferior_command (char *args, int from_tty)
set_current_inferior (inf);
switch_to_thread (null_ptid);

- exec_file_attach (exec, from_tty);
- symbol_file_add_main (exec, add_flags);
+ exec_file_attach (exec.get (), from_tty);
+ symbol_file_add_main (exec.get (), add_flags);
}
}
-
- do_cleanups (old_chain);
}

/* clone-inferior [-copies N] [ID] */
@@ -888,15 +882,13 @@ static void
clone_inferior_command (char *args, int from_tty)
{
int i, copies = 1;
- char **argv;
struct inferior *orginf = NULL;
- struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);

if (args)
{
- argv = gdb_buildargv (args);
- make_cleanup_freeargv (argv);
+ gdb_argv_up built_argv = gdb_buildargv (args);

+ char **argv = built_argv.get ();
for (; *argv != NULL; argv++)
{
if (**argv == '-')
@@ -967,8 +959,6 @@ clone_inferior_command (char *args, int from_tty)
switch_to_thread (null_ptid);
clone_program_space (pspace, orginf->pspace);
}
-
- do_cleanups (old_chain);
}

/* Print notices when new inferiors are created and die. */
diff --git a/gdb/infrun.c b/gdb/infrun.c
index fcafdc1..03aad38 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -8506,14 +8506,12 @@ sig_print_info (enum gdb_signal oursig)
static void
handle_command (char *args, int from_tty)
{
- char **argv;
int digits, wordlen;
int sigfirst, signum, siglast;
enum gdb_signal oursig;
int allsigs;
int nsigs;
unsigned char *sigs;
- struct cleanup *old_chain;

if (args == NULL)
{
@@ -8528,8 +8526,8 @@ handle_command (char *args, int from_tty)

/* Break the command line up into args. */

- argv = gdb_buildargv (args);
- old_chain = make_cleanup_freeargv (argv);
+ gdb_argv_up built_argv = gdb_buildargv (args);
+ char **argv = built_argv.get ();

/* Walk through the args, looking for signal oursigs, signal names, and
actions. Signal numbers and signal names may be interspersed with
@@ -8680,8 +8678,6 @@ Are you sure you want to change it? "),

break;
}
-
- do_cleanups (old_chain);
}

/* Complete the "handle" command. */
diff --git a/gdb/interps.c b/gdb/interps.c
index af86390..0512b38 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -407,21 +407,14 @@ interpreter_exec_cmd (char *args, int from_tty)
{
struct ui_interp_info *ui_interp = get_current_interp_info ();
struct interp *old_interp, *interp_to_use;
- char **prules = NULL;
- char **trule = NULL;
unsigned int nrules;
unsigned int i;
- struct cleanup *cleanup;

if (args == NULL)
error_no_arg (_("interpreter-exec command"));

- prules = gdb_buildargv (args);
- cleanup = make_cleanup_freeargv (prules);
-
- nrules = 0;
- for (trule = prules; *trule != NULL; trule++)
- nrules++;
+ gdb_argv_up prules = gdb_buildargv (args);
+ nrules = countargv (prules.get ());

if (nrules < 2)
error (_("usage: interpreter-exec <interpreter> [ <command> ... ]"));
@@ -446,8 +439,6 @@ interpreter_exec_cmd (char *args, int from_tty)
}

interp_set (old_interp, 0);
-
- do_cleanups (cleanup);
}

/* See interps.h. */
diff --git a/gdb/procfs.c b/gdb/procfs.c
index 2aaee07..fa4fa1a 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -5108,10 +5108,11 @@ procfs_info_proc (struct target_ops *ops, const char *args,
}

old_chain = make_cleanup (null_cleanup, 0);
+ gdb_argv_up built_argv;
if (args)
{
- argv = gdb_buildargv (args);
- make_cleanup_freeargv (argv);
+ built_argv.reset (gdb_buildargv (args));
+ argv = built_argv.get ();
}
while (argv != NULL && *argv != NULL)
{
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index bb482ee..a85e512 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -1905,7 +1905,6 @@ dump_psymtab_addrmap (struct objfile *objfile, struct partial_symtab *psymtab,
static void
maintenance_print_psymbols (char *args, int from_tty)
{
- char **argv;
struct ui_file *outfile = gdb_stdout;
struct cleanup *cleanups;
char *address_arg = NULL, *source_arg = NULL, *objfile_arg = NULL;
@@ -1917,8 +1916,8 @@ maintenance_print_psymbols (char *args, int from_tty)

dont_repeat ();

- argv = gdb_buildargv (args);
- cleanups = make_cleanup_freeargv (argv);
+ gdb_argv_up argv = gdb_buildargv (args);
+ cleanups = make_cleanup (null_cleanup, NULL);

for (i = 0; argv != NULL && argv[i] != NULL; ++i)
{
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index 6203211..7bd25b4 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -763,7 +763,7 @@ gdbpy_string_to_argv (PyObject *self, PyObject *args)

if (*input != '\0')
{
- char **c_argv = gdb_buildargv (input);
+ gdb_argv_up c_argv = gdb_buildargv (input);
int i;

for (i = 0; c_argv[i] != NULL; ++i)
@@ -772,13 +772,8 @@ gdbpy_string_to_argv (PyObject *self, PyObject *args)

if (argp == NULL
|| PyList_Append (py_argv.get (), argp.get ()) < 0)
- {
- freeargv (c_argv);
- return NULL;
- }
+ return NULL;
}
-
- freeargv (c_argv);
}

return py_argv.release ();
diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
index fd1bc66..e932e87 100644
--- a/gdb/remote-sim.c
+++ b/gdb/remote-sim.c
@@ -574,8 +574,7 @@ gdbsim_load (struct target_ops *self, const char *args, int fromtty)
if (args == NULL)
error_no_arg (_("program to load"));

- argv = gdb_buildargv (args);
- make_cleanup_freeargv (argv);
+ gdb_argv_up argv = gdb_buildargv (args);

prog = tilde_expand (argv[0]);

@@ -632,6 +631,7 @@ gdbsim_create_inferior (struct target_ops *target, const char *exec_file,
remove_breakpoints ();
init_wait_for_inferior ();

+ gdb_argv_up built_argv;
if (exec_file != NULL)
{
len = strlen (exec_file) + 1 + allargs.size () + 1 + /*slop */ 10;
@@ -640,8 +640,8 @@ gdbsim_create_inferior (struct target_ops *target, const char *exec_file,
strcat (arg_buf, exec_file);
strcat (arg_buf, " ");
strcat (arg_buf, args);
- argv = gdb_buildargv (arg_buf);
- make_cleanup_freeargv (argv);
+ built_argv.reset (gdb_buildargv (arg_buf));
+ argv = built_argv.get ();
}
else
argv = NULL;
@@ -732,7 +732,7 @@ gdbsim_open (const char *args, int from_tty)
strcat (arg_buf, " "); /* 1 */
strcat (arg_buf, args);
}
- sim_argv = gdb_buildargv (arg_buf);
+ sim_argv = gdb_buildargv (arg_buf).release ();

init_callbacks ();
gdbsim_desc = sim_open (SIM_OPEN_DEBUG, &gdb_callback, exec_bfd, sim_argv);
diff --git a/gdb/remote.c b/gdb/remote.c
index ecd0ce0..a699387 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -9525,12 +9525,9 @@ extended_remote_run (const std::string &args)

if (!args.empty ())
{
- struct cleanup *back_to;
int i;
- char **argv;

- argv = gdb_buildargv (args.c_str ());
- back_to = make_cleanup_freeargv (argv);
+ gdb_argv_up argv = gdb_buildargv (args.c_str ());
for (i = 0; argv[i] != NULL; i++)
{
if (strlen (argv[i]) * 2 + 1 + len >= get_remote_packet_size ())
@@ -9539,7 +9536,6 @@ extended_remote_run (const std::string &args)
len += 2 * bin2hex ((gdb_byte *) argv[i], rs->buf + len,
strlen (argv[i]));
}
- do_cleanups (back_to);
}

rs->buf[len++] = '\0';
@@ -12035,58 +12031,40 @@ remote_file_delete (const char *remote_file, int from_tty)
static void
remote_put_command (char *args, int from_tty)
{
- struct cleanup *back_to;
- char **argv;
-
if (args == NULL)
error_no_arg (_("file to put"));

- argv = gdb_buildargv (args);
- back_to = make_cleanup_freeargv (argv);
+ gdb_argv_up argv = gdb_buildargv (args);
if (argv[0] == NULL || argv[1] == NULL || argv[2] != NULL)
error (_("Invalid parameters to remote put"));

remote_file_put (argv[0], argv[1], from_tty);
-
- do_cleanups (back_to);
}

static void
remote_get_command (char *args, int from_tty)
{
- struct cleanup *back_to;
- char **argv;
-
if (args == NULL)
error_no_arg (_("file to get"));

- argv = gdb_buildargv (args);
- back_to = make_cleanup_freeargv (argv);
+ gdb_argv_up argv = gdb_buildargv (args);
if (argv[0] == NULL || argv[1] == NULL || argv[2] != NULL)
error (_("Invalid parameters to remote get"));

remote_file_get (argv[0], argv[1], from_tty);
-
- do_cleanups (back_to);
}

static void
remote_delete_command (char *args, int from_tty)
{
- struct cleanup *back_to;
- char **argv;
-
if (args == NULL)
error_no_arg (_("file to delete"));

- argv = gdb_buildargv (args);
- back_to = make_cleanup_freeargv (argv);
+ gdb_argv_up argv = gdb_buildargv (args);
if (argv[0] == NULL || argv[1] != NULL)
error (_("Invalid parameters to remote delete"));

remote_file_delete (argv[0], from_tty);
-
- do_cleanups (back_to);
}

static void
diff --git a/gdb/ser-mingw.c b/gdb/ser-mingw.c
index 3f12458..429f89f 100644
--- a/gdb/ser-mingw.c
+++ b/gdb/ser-mingw.c
@@ -869,7 +869,7 @@ pipe_windows_open (struct serial *scb, const char *name)
if (name == NULL)
error_no_arg (_("child command"));

- argv = gdb_buildargv (name);
+ argv = gdb_buildargv (name).release ();
back_to = make_cleanup_freeargv (argv);

if (! argv[0] || argv[0][0] == '\0')
diff --git a/gdb/skip.c b/gdb/skip.c
index 33ed8d8..b830c6f 100644
--- a/gdb/skip.c
+++ b/gdb/skip.c
@@ -231,8 +231,6 @@ skip_command (char *arg, int from_tty)
const char *gfile = NULL;
const char *function = NULL;
const char *rfunction = NULL;
- char **argv;
- struct cleanup *cleanups;
struct skiplist_entry *e;
int i;

@@ -242,8 +240,7 @@ skip_command (char *arg, int from_tty)
return;
}

- argv = buildargv (arg);
- cleanups = make_cleanup_freeargv (argv);
+ gdb_argv_up argv = gdb_buildargv (arg);

for (i = 0; argv[i] != NULL; ++i)
{
@@ -290,7 +287,6 @@ skip_command (char *arg, int from_tty)
FUNCTION-NAME may be `foo (int)', and therefore we pass the
complete original arg to skip_function command as if the user
typed "skip function arg". */
- do_cleanups (cleanups);
skip_function_command (arg, from_tty);
return;
}
@@ -350,8 +346,6 @@ skip_command (char *arg, int from_tty)
lower_file_text, file_to_print);
}
}
-
- do_cleanups (cleanups);
}

static void
diff --git a/gdb/source.c b/gdb/source.c
index 3d477ad..7eef86c 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -484,16 +484,14 @@ add_path (char *dirname, char **which_path, int parse_separators)

if (parse_separators)
{
- char **argv, **argvp;
+ char **argvp;

/* This will properly parse the space and tab separators
and any quotes that may exist. */
- argv = gdb_buildargv (dirname);
+ gdb_argv_up argv = gdb_buildargv (dirname);

- for (argvp = argv; *argvp; argvp++)
+ for (argvp = argv.get (); *argvp; argvp++)
dirnames_to_char_ptr_vec_append (&dir_vec, *argvp);
-
- freeargv (argv);
}
else
VEC_safe_push (char_ptr, dir_vec, xstrdup (dirname));
@@ -1882,12 +1880,9 @@ static void
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);
- cleanup = make_cleanup_freeargv (argv);
+ gdb_argv_up argv = gdb_buildargv (args);

/* We expect zero or one argument. */

@@ -1911,8 +1906,6 @@ 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. */
@@ -1921,14 +1914,12 @@ static void
unset_substitute_path_command (char *args, int from_tty)
{
struct substitute_path_rule *rule = substitute_path_rules;
- char **argv = gdb_buildargv (args);
+ gdb_argv_up argv = gdb_buildargv (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"));

@@ -1966,8 +1957,6 @@ 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. */
@@ -1975,12 +1964,9 @@ unset_substitute_path_command (char *args, int from_tty)
static void
set_substitute_path_command (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_up argv = gdb_buildargv (args);

if (argv == NULL || argv[0] == NULL || argv [1] == NULL)
error (_("Incorrect usage, too few arguments in command"));
@@ -2007,8 +1993,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);
}

\f
diff --git a/gdb/stack.c b/gdb/stack.c
index 7f8a51c..34e8aa5 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1877,7 +1877,7 @@ backtrace_command (char *arg, int from_tty)
char **argv;
int i;

- argv = gdb_buildargv (arg);
+ argv = gdb_buildargv (arg).release ();
make_cleanup_freeargv (argv);
argc = 0;
for (i = 0; argv[i]; i++)
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 846aabe..9482ddc 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -1628,7 +1628,7 @@ symbol_file_command (char *args, int from_tty)
}
else
{
- char **argv = gdb_buildargv (args);
+ char **argv;
objfile_flags flags = OBJF_USERLOADED;
symfile_add_flags add_flags = 0;
struct cleanup *cleanups;
@@ -1637,7 +1637,8 @@ symbol_file_command (char *args, int from_tty)
if (from_tty)
add_flags |= SYMFILE_VERBOSE;

- cleanups = make_cleanup_freeargv (argv);
+ gdb_argv_up built_argv = gdb_buildargv (args);
+ argv = built_argv.get ();
while (*argv != NULL)
{
if (strcmp (*argv, "-readnow") == 0)
@@ -1655,8 +1656,6 @@ symbol_file_command (char *args, int from_tty)

if (name == NULL)
error (_("no symbol file name was specified"));
-
- do_cleanups (cleanups);
}
}

@@ -2050,25 +2049,23 @@ void
generic_load (const char *args, int from_tty)
{
char *filename;
- struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
+ struct cleanup *old_cleanups;
struct load_section_data cbdata;
struct load_progress_data total_progress;
struct ui_out *uiout = current_uiout;

CORE_ADDR entry;
- char **argv;

memset (&cbdata, 0, sizeof (cbdata));
memset (&total_progress, 0, sizeof (total_progress));
cbdata.progress_data = &total_progress;

- make_cleanup (clear_memory_write_data, &cbdata.requests);
+ old_cleanups = make_cleanup (clear_memory_write_data, &cbdata.requests);

if (args == NULL)
error_no_arg (_("file to load"));

- argv = gdb_buildargv (args);
- make_cleanup_freeargv (argv);
+ gdb_argv_up argv = gdb_buildargv (args);

filename = tilde_expand (argv[0]);
make_cleanup (xfree, filename);
@@ -2216,7 +2213,6 @@ add_symbol_file_command (char *args, int from_tty)
int i;
int expecting_sec_name = 0;
int expecting_sec_addr = 0;
- char **argv;
struct objfile *objf;
objfile_flags flags = OBJF_USERLOADED | OBJF_SHARED;
symfile_add_flags add_flags = 0;
@@ -2243,8 +2239,7 @@ add_symbol_file_command (char *args, int from_tty)
if (args == NULL)
error (_("add-symbol-file takes a file name and an address"));

- argv = gdb_buildargv (args);
- make_cleanup_freeargv (argv);
+ gdb_argv_up argv = gdb_buildargv (args);

for (arg = argv[0], argcnt = 0; arg != NULL; arg = argv[++argcnt])
{
@@ -2364,7 +2359,6 @@ add_symbol_file_command (char *args, int from_tty)
static void
remove_symbol_file_command (char *args, int from_tty)
{
- char **argv;
struct objfile *objf = NULL;
struct cleanup *my_cleanups;
struct program_space *pspace = current_program_space;
@@ -2376,7 +2370,7 @@ remove_symbol_file_command (char *args, int from_tty)

my_cleanups = make_cleanup (null_cleanup, NULL);

- argv = gdb_buildargv (args);
+ gdb_argv_up argv = gdb_buildargv (args);

if (strcmp (argv[0], "-a") == 0)
{
diff --git a/gdb/symmisc.c b/gdb/symmisc.c
index 32a5331..e3a512e 100644
--- a/gdb/symmisc.c
+++ b/gdb/symmisc.c
@@ -407,7 +407,6 @@ dump_symtab (struct symtab *symtab, struct ui_file *outfile)
static void
maintenance_print_symbols (char *args, int from_tty)
{
- char **argv;
struct ui_file *outfile = gdb_stdout;
struct cleanup *cleanups;
char *address_arg = NULL, *source_arg = NULL, *objfile_arg = NULL;
@@ -415,8 +414,8 @@ maintenance_print_symbols (char *args, int from_tty)

dont_repeat ();

- argv = gdb_buildargv (args);
- cleanups = make_cleanup_freeargv (argv);
+ gdb_argv_up argv = gdb_buildargv (args);
+ cleanups = make_cleanup (null_cleanup, NULL);

for (i = 0; argv != NULL && argv[i] != NULL; ++i)
{
@@ -709,7 +708,6 @@ print_symbol (void *args)
static void
maintenance_print_msymbols (char *args, int from_tty)
{
- char **argv;
struct ui_file *outfile = gdb_stdout;
struct cleanup *cleanups;
char *objfile_arg = NULL;
@@ -718,8 +716,8 @@ maintenance_print_msymbols (char *args, int from_tty)

dont_repeat ();

- argv = gdb_buildargv (args);
- cleanups = make_cleanup_freeargv (argv);
+ gdb_argv_up argv = gdb_buildargv (args);
+ cleanups = make_cleanup (null_cleanup, NULL);

for (i = 0; argv != NULL && argv[i] != NULL; ++i)
{
@@ -944,14 +942,11 @@ maintenance_expand_symtabs (char *args, int from_tty)
{
struct program_space *pspace;
struct objfile *objfile;
- struct cleanup *cleanups;
- char **argv;
char *regexp = NULL;

/* We use buildargv here so that we handle spaces in the regexp
in a way that allows adding more arguments later. */
- argv = gdb_buildargv (args);
- cleanups = make_cleanup_freeargv (argv);
+ gdb_argv_up argv = gdb_buildargv (args);

if (argv != NULL)
{
@@ -988,8 +983,6 @@ maintenance_expand_symtabs (char *args, int from_tty)
ALL_DOMAIN);
}
}
-
- do_cleanups (cleanups);
}
\f

diff --git a/gdb/top.c b/gdb/top.c
index 6038366..a51b59f 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -364,17 +364,14 @@ new_ui_command (char *args, int from_tty)
int i;
int res;
int argc;
- char **argv;
const char *interpreter_name;
const char *tty_name;
- struct cleanup *success_chain;
struct cleanup *failure_chain;

dont_repeat ();

- argv = gdb_buildargv (args);
- success_chain = make_cleanup_freeargv (argv);
- argc = countargv (argv);
+ gdb_argv_up argv = gdb_buildargv (args);
+ argc = countargv (argv.get ());

if (argc < 2)
error (_("usage: new-ui <interpreter> <tty>"));
@@ -407,9 +404,6 @@ new_ui_command (char *args, int from_tty)
stream[2].release ();

discard_cleanups (failure_chain);
-
- /* This restores the previous UI and frees argv. */
- do_cleanups (success_chain);
}

printf_unfiltered ("New UI allocated\n");
diff --git a/gdb/tracefile.c b/gdb/tracefile.c
index cc90945..2dce0d9 100644
--- a/gdb/tracefile.c
+++ b/gdb/tracefile.c
@@ -318,8 +318,8 @@ tsave_command (char *args, int from_tty)
if (args == NULL)
error_no_arg (_("file in which to save trace data"));

- argv = gdb_buildargv (args);
- back_to = make_cleanup_freeargv (argv);
+ gdb_argv_up built_argv = gdb_buildargv (args);
+ argv = built_argv.get ();

for (; *argv; ++argv)
{
@@ -341,7 +341,7 @@ tsave_command (char *args, int from_tty)
else
writer = tfile_trace_file_writer_new ();

- make_cleanup (trace_file_writer_xfree, writer);
+ back_to = make_cleanup (trace_file_writer_xfree, writer);

trace_save (filename, writer, target_does_save);

diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 3a39ebc..f569c86 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -448,8 +448,6 @@ static void
delete_trace_variable_command (char *args, int from_tty)
{
int ix;
- char **argv;
- struct cleanup *back_to;

if (args == NULL)
{
@@ -460,8 +458,7 @@ delete_trace_variable_command (char *args, int from_tty)
return;
}

- argv = gdb_buildargv (args);
- back_to = make_cleanup_freeargv (argv);
+ gdb_argv_up argv = gdb_buildargv (args);

for (ix = 0; argv[ix] != NULL; ix++)
{
@@ -471,8 +468,6 @@ delete_trace_variable_command (char *args, int from_tty)
warning (_("Name \"%s\" not prefixed with '$', ignoring"), argv[ix]);
}

- do_cleanups (back_to);
-
dont_repeat ();
}

diff --git a/gdb/utils.c b/gdb/utils.c
index 7d0b5f4..b631ed0 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -2914,14 +2914,14 @@ ldirname (const char *filename)
Therefore, the returned value is guaranteed to be non-NULL,
unless the parameter itself is NULL. */

-char **
+gdb_argv_up
gdb_buildargv (const char *s)
{
char **argv = buildargv (s);

if (s != NULL && argv == NULL)
malloc_failure (0);
- return argv;
+ return gdb_argv_up (argv);
}

int
diff --git a/gdb/utils.h b/gdb/utils.h
index 8f545c6..dd7c75e7 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -60,7 +60,24 @@ extern int parse_pid_to_attach (const char *args);

extern int parse_escape (struct gdbarch *, const char **);

-char **gdb_buildargv (const char *);
+/* A deleter for an argv array. This is an array where each element,
+ up to the first NULL, is xmalloc'd, and the array itself is
+ xmalloc'd. */
+struct gdb_argv_deleter
+{
+ void operator() (char **argv) const
+ {
+ freeargv (argv);
+ }
+};
+
+/* A unique pointer to an argv array. */
+typedef std::unique_ptr<char *[], gdb_argv_deleter> gdb_argv_up;
+
+/* A wrapper for libiberty's buildargv that handles memory allocation
+ failures in the gdb style. */
+gdb_argv_up gdb_buildargv (const char *);
+
\f
/* Cleanup utilities. */

--
2.9.3