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:
parent
3d8b0d9483
commit
aaee65aea2
8 changed files with 122 additions and 86 deletions
|
@ -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
|
||||||
|
|
14
gdb/c-lang.h
14
gdb/c-lang.h
|
@ -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) */
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue