Use ui_file_as_string in gdb/compile/

Using ui_file_as_string would imply changing a few prototypes to pass
around source and object file names as std::string.  Instead of that,
wrap those two in a new class.  This ends up eliminating a small
wrinkle: get_new_file_names and compile_object_load have swapped
parameters.  The former takes "source, objfile", while the latter
takes "objfile, source".

gdb/ChangeLog:
2016-11-08  Pedro Alves  <palves@redhat.com>

	* c-lang.h (c_compute_program): Now returns std::string.
	* compile/compile-internal.h (class compile_file_names): New
	class.
	* compile/compile-object-load.c (compile_object_load): Replace
	object_file and source_file parameters with a compile_file_names
	parameter.  Adjust.
	* compile-object-load.h: Include "compile-internal.h".
	(compile_object_load): Replace object_file and source_file
	parameters with a compile_file_names parameter.
	* compile/compile-c-support.c (c_compute_program): Now returns a
	std::string.  Use ui_file_as_string.
	* compile/compile.c (get_new_file_names): Remove parameters and
	return a compile_file_names instead.
	(compile_to_object): Now returns a compile_file_names.  Use
	ui_file_as_string.
	(eval_compile_command): Use compile_file_names.
	* language.h (struct language_defn) <la_compute_program>: Now
	returns std::string.
This commit is contained in:
Pedro Alves 2016-11-08 15:26:46 +00:00
parent 3d8b0d9483
commit aaee65aea2
8 changed files with 122 additions and 86 deletions

View file

@ -1,3 +1,24 @@
2016-11-08 Pedro Alves <palves@redhat.com>
* c-lang.h (c_compute_program): Now returns std::string.
* compile/compile-internal.h (class compile_file_names): New
class.
* compile/compile-object-load.c (compile_object_load): Replace
object_file and source_file parameters with a compile_file_names
parameter. Adjust.
* compile-object-load.h: Include "compile-internal.h".
(compile_object_load): Replace object_file and source_file
parameters with a compile_file_names parameter.
* compile/compile-c-support.c (c_compute_program): Now returns a
std::string. Use ui_file_as_string.
* compile/compile.c (get_new_file_names): Remove parameters and
return a compile_file_names instead.
(compile_to_object): Now returns a compile_file_names. Use
ui_file_as_string.
(eval_compile_command): Use compile_file_names.
* language.h (struct language_defn) <la_compute_program>: Now
returns std::string.
2016-11-08 Pedro Alves <palves@redhat.com> 2016-11-08 Pedro Alves <palves@redhat.com>
* cli/cli-setshow.c (do_show_command): Adjust to use * cli/cli-setshow.c (do_show_command): Adjust to use

View file

@ -152,16 +152,16 @@ extern int c_textual_element_type (struct type *, char);
extern struct compile_instance *c_get_compile_context (void); extern struct compile_instance *c_get_compile_context (void);
/* This takes the user-supplied text and returns a newly malloc'd bit /* This takes the user-supplied text and returns a new bit of code to
of code to compile. compile.
This is used as the la_compute_program language method; see that This is used as the la_compute_program language method; see that
for a description of the arguments. */ for a description of the arguments. */
extern char *c_compute_program (struct compile_instance *inst, extern std::string c_compute_program (struct compile_instance *inst,
const char *input, const char *input,
struct gdbarch *gdbarch, struct gdbarch *gdbarch,
const struct block *expr_block, const struct block *expr_block,
CORE_ADDR expr_pc); CORE_ADDR expr_pc);
#endif /* !defined (C_LANG_H) */ #endif /* !defined (C_LANG_H) */

View file

@ -326,7 +326,7 @@ generate_register_struct (struct ui_file *stream, struct gdbarch *gdbarch,
to the inferior when the expression was created, and EXPR_PC to the inferior when the expression was created, and EXPR_PC
indicates the value of $PC. */ indicates the value of $PC. */
char * std::string
c_compute_program (struct compile_instance *inst, c_compute_program (struct compile_instance *inst,
const char *input, const char *input,
struct gdbarch *gdbarch, struct gdbarch *gdbarch,
@ -334,7 +334,7 @@ c_compute_program (struct compile_instance *inst,
CORE_ADDR expr_pc) CORE_ADDR expr_pc)
{ {
struct ui_file *buf, *var_stream = NULL; struct ui_file *buf, *var_stream = NULL;
char *code; std::string code;
struct cleanup *cleanup; struct cleanup *cleanup;
struct compile_c_instance *context = (struct compile_c_instance *) inst; struct compile_c_instance *context = (struct compile_c_instance *) inst;
@ -435,7 +435,7 @@ c_compute_program (struct compile_instance *inst,
fputs_unfiltered ("}\n", buf); fputs_unfiltered ("}\n", buf);
add_code_footer (inst->scope, buf); add_code_footer (inst->scope, buf);
code = ui_file_xstrdup (buf, NULL); code = ui_file_as_string (buf);
do_cleanups (cleanup); do_cleanups (cleanup);
return code; return code;
} }

View file

@ -152,4 +152,29 @@ extern const char *c_get_mode_for_size (int size);
struct dynamic_prop; struct dynamic_prop;
extern char *c_get_range_decl_name (const struct dynamic_prop *prop); extern char *c_get_range_decl_name (const struct dynamic_prop *prop);
/* Type used to hold and pass around the source and object file names
to use for compilation. */
class compile_file_names
{
public:
compile_file_names (std::string source_file, std::string object_file)
: m_source_file (source_file), m_object_file (object_file)
{}
/* Provide read-only views only. Return 'const char *' instead of
std::string to avoid having to use c_str() everywhere in client
code. */
const char *source_file () const
{ return m_source_file.c_str (); }
const char *object_file () const
{ return m_object_file.c_str (); }
private:
/* Storage for the file names. */
std::string m_source_file;
std::string m_object_file;
};
#endif /* GDB_COMPILE_INTERNAL_H */ #endif /* GDB_COMPILE_INTERNAL_H */

View file

@ -601,16 +601,14 @@ store_regs (struct type *regs_type, CORE_ADDR regs_base)
} }
} }
/* Load OBJECT_FILE into inferior memory. Throw an error otherwise. /* Load the object file specified in FILE_NAMES into inferior memory.
Caller must fully dispose the return value by calling compile_object_run. Throw an error otherwise. Caller must fully dispose the return
SOURCE_FILE's copy is stored into the returned object. value by calling compile_object_run. Returns NULL only for
Caller should free both OBJECT_FILE and SOURCE_FILE immediatelly after this COMPILE_I_PRINT_ADDRESS_SCOPE when COMPILE_I_PRINT_VALUE_SCOPE
function returns. should have been used instead. */
Function returns NULL only for COMPILE_I_PRINT_ADDRESS_SCOPE when
COMPILE_I_PRINT_VALUE_SCOPE should have been used instead. */
struct compile_module * struct compile_module *
compile_object_load (const char *object_file, const char *source_file, compile_object_load (const compile_file_names &file_names,
enum compile_i_scope_types scope, void *scope_data) enum compile_i_scope_types scope, void *scope_data)
{ {
struct cleanup *cleanups, *cleanups_free_objfile; struct cleanup *cleanups, *cleanups_free_objfile;
@ -633,7 +631,7 @@ compile_object_load (const char *object_file, const char *source_file,
struct type *expect_return_type; struct type *expect_return_type;
struct munmap_list *munmap_list_head = NULL; struct munmap_list *munmap_list_head = NULL;
filename = tilde_expand (object_file); filename = tilde_expand (file_names.object_file ());
cleanups = make_cleanup (xfree, filename); cleanups = make_cleanup (xfree, filename);
abfd = gdb_bfd_open (filename, gnutarget, -1); abfd = gdb_bfd_open (filename, gnutarget, -1);
@ -824,7 +822,7 @@ compile_object_load (const char *object_file, const char *source_file,
retval = XNEW (struct compile_module); retval = XNEW (struct compile_module);
retval->objfile = objfile; retval->objfile = objfile;
retval->source_file = xstrdup (source_file); retval->source_file = xstrdup (file_names.source_file ());
retval->func_sym = func_sym; retval->func_sym = func_sym;
retval->regs_addr = regs_addr; retval->regs_addr = regs_addr;
retval->scope = scope; retval->scope = scope;

View file

@ -17,6 +17,8 @@
#ifndef GDB_COMPILE_OBJECT_LOAD_H #ifndef GDB_COMPILE_OBJECT_LOAD_H
#define GDB_COMPILE_OBJECT_LOAD_H #define GDB_COMPILE_OBJECT_LOAD_H
#include "compile-internal.h"
struct munmap_list; struct munmap_list;
struct compile_module struct compile_module
@ -53,7 +55,7 @@ struct compile_module
}; };
extern struct compile_module *compile_object_load extern struct compile_module *compile_object_load
(const char *object_file, const char *source_file, (const compile_file_names &fnames,
enum compile_i_scope_types scope, void *scope_data); enum compile_i_scope_types scope, void *scope_data);
extern void munmap_list_free (struct munmap_list *head); extern void munmap_list_free (struct munmap_list *head);

View file

@ -248,18 +248,20 @@ get_compile_file_tempdir (void)
return tempdir_name; return tempdir_name;
} }
/* Compute the names of source and object files to use. The names are /* Compute the names of source and object files to use. */
allocated by malloc and should be freed by the caller. */
static void static compile_file_names
get_new_file_names (char **source_file, char **object_file) get_new_file_names ()
{ {
static int seq; static int seq;
const char *dir = get_compile_file_tempdir (); const char *dir = get_compile_file_tempdir ();
++seq; ++seq;
*source_file = xstrprintf ("%s%sout%d.c", dir, SLASH_STRING, seq);
*object_file = xstrprintf ("%s%sout%d.o", dir, SLASH_STRING, seq); return compile_file_names (string_printf ("%s%sout%d.c",
dir, SLASH_STRING, seq),
string_printf ("%s%sout%d.o",
dir, SLASH_STRING, seq));
} }
/* Get the block and PC at which to evaluate an expression. */ /* Get the block and PC at which to evaluate an expression. */
@ -449,18 +451,13 @@ print_callback (void *ignore, const char *message)
} }
/* Process the compilation request. On success it returns the object /* Process the compilation request. On success it returns the object
file name and *SOURCE_FILEP is set to source file name. On an and source file names. On an error condition, error () is
error condition, error () is called. The caller is responsible for called. */
freeing both strings. */
static char * static compile_file_names
compile_to_object (struct command_line *cmd, const char *cmd_string, compile_to_object (struct command_line *cmd, const char *cmd_string,
enum compile_i_scope_types scope, enum compile_i_scope_types scope)
char **source_filep)
{ {
char *code;
const char *input;
char *source_file, *object_file;
struct compile_instance *compiler; struct compile_instance *compiler;
struct cleanup *cleanup, *inner_cleanup; struct cleanup *cleanup, *inner_cleanup;
const struct block *expr_block; const struct block *expr_block;
@ -496,11 +493,14 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
/* From the provided expression, build a scope to pass to the /* From the provided expression, build a scope to pass to the
compiler. */ compiler. */
std::string input_buf;
const char *input;
if (cmd != NULL) if (cmd != NULL)
{ {
struct ui_file *stream = mem_fileopen (); struct ui_file *stream = mem_fileopen ();
struct command_line *iter; struct command_line *iter;
char *stream_buf;
make_cleanup_ui_file_delete (stream); make_cleanup_ui_file_delete (stream);
for (iter = cmd->body_list[0]; iter; iter = iter->next) for (iter = cmd->body_list[0]; iter; iter = iter->next)
@ -509,20 +509,19 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
fputs_unfiltered ("\n", stream); fputs_unfiltered ("\n", stream);
} }
stream_buf = ui_file_xstrdup (stream, NULL); input_buf = ui_file_as_string (stream);
make_cleanup (xfree, stream_buf); input = input_buf.c_str ();
input = stream_buf;
} }
else if (cmd_string != NULL) else if (cmd_string != NULL)
input = cmd_string; input = cmd_string;
else else
error (_("Neither a simple expression, or a multi-line specified.")); error (_("Neither a simple expression, or a multi-line specified."));
code = current_language->la_compute_program (compiler, input, gdbarch, std::string code
expr_block, expr_pc); = current_language->la_compute_program (compiler, input, gdbarch,
make_cleanup (xfree, code); expr_block, expr_pc);
if (compile_debug) if (compile_debug)
fprintf_unfiltered (gdb_stdlog, "debug output:\n\n%s", code); fprintf_unfiltered (gdb_stdlog, "debug output:\n\n%s", code.c_str ());
os_rx = osabi_triplet_regexp (gdbarch_osabi (gdbarch)); os_rx = osabi_triplet_regexp (gdbarch_osabi (gdbarch));
arch_rx = gdbarch_gnu_triplet_regexp (gdbarch); arch_rx = gdbarch_gnu_triplet_regexp (gdbarch);
@ -553,37 +552,36 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
argi, argv[argi]); argi, argv[argi]);
} }
get_new_file_names (&source_file, &object_file); compile_file_names fnames = get_new_file_names ();
inner_cleanup = make_cleanup (xfree, source_file);
make_cleanup (xfree, object_file);
src = gdb_fopen_cloexec (source_file, "w"); src = gdb_fopen_cloexec (fnames.source_file (), "w");
if (src == NULL) if (src == NULL)
perror_with_name (_("Could not open source file for writing")); perror_with_name (_("Could not open source file for writing"));
make_cleanup (cleanup_unlink_file, source_file); inner_cleanup = make_cleanup (cleanup_unlink_file,
if (fputs (code, src) == EOF) (void *) fnames.source_file ());
if (fputs (code.c_str (), src) == EOF)
perror_with_name (_("Could not write to source file")); perror_with_name (_("Could not write to source file"));
fclose (src); fclose (src);
if (compile_debug) if (compile_debug)
fprintf_unfiltered (gdb_stdlog, "source file produced: %s\n\n", fprintf_unfiltered (gdb_stdlog, "source file produced: %s\n\n",
source_file); fnames.source_file ());
/* Call the compiler and start the compilation process. */ /* Call the compiler and start the compilation process. */
compiler->fe->ops->set_source_file (compiler->fe, source_file); compiler->fe->ops->set_source_file (compiler->fe, fnames.source_file ());
if (!compiler->fe->ops->compile (compiler->fe, object_file, if (!compiler->fe->ops->compile (compiler->fe, fnames.object_file (),
compile_debug)) compile_debug))
error (_("Compilation failed.")); error (_("Compilation failed."));
if (compile_debug) if (compile_debug)
fprintf_unfiltered (gdb_stdlog, "object file produced: %s\n\n", fprintf_unfiltered (gdb_stdlog, "object file produced: %s\n\n",
object_file); fnames.object_file ());
discard_cleanups (inner_cleanup); discard_cleanups (inner_cleanup);
do_cleanups (cleanup); do_cleanups (cleanup);
*source_filep = source_file;
return object_file; return fnames;
} }
/* The "compile" prefix command. */ /* The "compile" prefix command. */
@ -602,32 +600,24 @@ void
eval_compile_command (struct command_line *cmd, const char *cmd_string, eval_compile_command (struct command_line *cmd, const char *cmd_string,
enum compile_i_scope_types scope, void *scope_data) enum compile_i_scope_types scope, void *scope_data)
{ {
char *object_file, *source_file; struct cleanup *cleanup_unlink;
struct compile_module *compile_module;
object_file = compile_to_object (cmd, cmd_string, scope, &source_file); compile_file_names fnames = compile_to_object (cmd, cmd_string, scope);
if (object_file != NULL)
cleanup_unlink = make_cleanup (cleanup_unlink_file,
(void *) fnames.object_file ());
make_cleanup (cleanup_unlink_file, (void *) fnames.source_file ());
compile_module = compile_object_load (fnames, scope, scope_data);
if (compile_module == NULL)
{ {
struct cleanup *cleanup_xfree, *cleanup_unlink; gdb_assert (scope == COMPILE_I_PRINT_ADDRESS_SCOPE);
struct compile_module *compile_module; eval_compile_command (cmd, cmd_string,
COMPILE_I_PRINT_VALUE_SCOPE, scope_data);
cleanup_xfree = make_cleanup (xfree, object_file); return;
make_cleanup (xfree, source_file);
cleanup_unlink = make_cleanup (cleanup_unlink_file, object_file);
make_cleanup (cleanup_unlink_file, source_file);
compile_module = compile_object_load (object_file, source_file,
scope, scope_data);
if (compile_module == NULL)
{
gdb_assert (scope == COMPILE_I_PRINT_ADDRESS_SCOPE);
do_cleanups (cleanup_xfree);
eval_compile_command (cmd, cmd_string,
COMPILE_I_PRINT_VALUE_SCOPE, scope_data);
return;
}
discard_cleanups (cleanup_unlink);
do_cleanups (cleanup_xfree);
compile_object_run (compile_module);
} }
discard_cleanups (cleanup_unlink);
compile_object_run (compile_module);
} }
/* See compile/compile-internal.h. */ /* See compile/compile-internal.h. */

View file

@ -406,8 +406,8 @@ struct language_defn
If 'la_get_gcc_context' is not defined, then this method is If 'la_get_gcc_context' is not defined, then this method is
ignored. ignored.
This takes the user-supplied text and returns a newly malloc'd This takes the user-supplied text and returns a new bit of code
bit of code to compile. The caller owns the result. to compile.
INST is the compiler instance being used. INST is the compiler instance being used.
INPUT is the user's input text. INPUT is the user's input text.
@ -416,11 +416,11 @@ struct language_defn
parsed. parsed.
EXPR_PC is the PC at which the expression is being parsed. */ EXPR_PC is the PC at which the expression is being parsed. */
char *(*la_compute_program) (struct compile_instance *inst, std::string (*la_compute_program) (struct compile_instance *inst,
const char *input, const char *input,
struct gdbarch *gdbarch, struct gdbarch *gdbarch,
const struct block *expr_block, const struct block *expr_block,
CORE_ADDR expr_pc); CORE_ADDR expr_pc);
/* Add fields above this point, so the magic number is always last. */ /* Add fields above this point, so the magic number is always last. */
/* Magic number for compat checking. */ /* Magic number for compat checking. */