Use ui_file_as_string in gdb/compile/
authorPedro Alves <palves@redhat.com>
Tue, 8 Nov 2016 15:26:46 +0000 (15:26 +0000)
committerPedro Alves <palves@redhat.com>
Tue, 8 Nov 2016 15:26:46 +0000 (15:26 +0000)
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.

gdb/ChangeLog
gdb/c-lang.h
gdb/compile/compile-c-support.c
gdb/compile/compile-internal.h
gdb/compile/compile-object-load.c
gdb/compile/compile-object-load.h
gdb/compile/compile.c
gdb/language.h

index ae21b12..b07e744 100644 (file)
@@ -1,5 +1,26 @@
 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>
+
        * cli/cli-setshow.c (do_show_command): Adjust to use
        ui_file_as_string and std::string.
 
index 12be8bf..8378d4f 100644 (file)
@@ -152,16 +152,16 @@ extern int c_textual_element_type (struct type *, char);
 
 extern struct compile_instance *c_get_compile_context (void);
 
-/* This takes the user-supplied text and returns a newly malloc'd bit
-   of code to compile.
+/* This takes the user-supplied text and returns a new bit of code to
+   compile.
 
    This is used as the la_compute_program language method; see that
    for a description of the arguments.  */
 
-extern char *c_compute_program (struct compile_instance *inst,
-                               const char *input,
-                               struct gdbarch *gdbarch,
-                               const struct block *expr_block,
-                               CORE_ADDR expr_pc);
+extern std::string c_compute_program (struct compile_instance *inst,
+                                     const char *input,
+                                     struct gdbarch *gdbarch,
+                                     const struct block *expr_block,
+                                     CORE_ADDR expr_pc);
 
 #endif /* !defined (C_LANG_H) */
index c42daba..641b0fd 100644 (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
    indicates the value of $PC.  */
 
-char *
+std::string
 c_compute_program (struct compile_instance *inst,
                   const char *input,
                   struct gdbarch *gdbarch,
@@ -334,7 +334,7 @@ c_compute_program (struct compile_instance *inst,
                   CORE_ADDR expr_pc)
 {
   struct ui_file *buf, *var_stream = NULL;
-  char *code;
+  std::string code;
   struct cleanup *cleanup;
   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);
 
   add_code_footer (inst->scope, buf);
-  code = ui_file_xstrdup (buf, NULL);
+  code = ui_file_as_string (buf);
   do_cleanups (cleanup);
   return code;
 }
index 66ea864..5a7bf14 100644 (file)
@@ -152,4 +152,29 @@ extern const char *c_get_mode_for_size (int size);
 struct dynamic_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 */
index 9fc6c02..c08aa2b 100644 (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.
-   Caller must fully dispose the return value by calling compile_object_run.
-   SOURCE_FILE's copy is stored into the returned object.
-   Caller should free both OBJECT_FILE and SOURCE_FILE immediatelly after this
-   function returns.
-   Function returns NULL only for COMPILE_I_PRINT_ADDRESS_SCOPE when
-   COMPILE_I_PRINT_VALUE_SCOPE should have been used instead.  */
+/* Load the object file specified in FILE_NAMES into inferior memory.
+   Throw an error otherwise.  Caller must fully dispose the return
+   value by calling compile_object_run.  Returns NULL only for
+   COMPILE_I_PRINT_ADDRESS_SCOPE when COMPILE_I_PRINT_VALUE_SCOPE
+   should have been used instead.  */
 
 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)
 {
   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 munmap_list *munmap_list_head = NULL;
 
-  filename = tilde_expand (object_file);
+  filename = tilde_expand (file_names.object_file ());
   cleanups = make_cleanup (xfree, filename);
 
   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->objfile = objfile;
-  retval->source_file = xstrdup (source_file);
+  retval->source_file = xstrdup (file_names.source_file ());
   retval->func_sym = func_sym;
   retval->regs_addr = regs_addr;
   retval->scope = scope;
index 39c1a90..b9cf307 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef GDB_COMPILE_OBJECT_LOAD_H
 #define GDB_COMPILE_OBJECT_LOAD_H
 
+#include "compile-internal.h"
+
 struct munmap_list;
 
 struct compile_module
@@ -53,7 +55,7 @@ struct compile_module
 };
 
 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);
 extern void munmap_list_free (struct munmap_list *head);
 
index 73fae22..68353f5 100644 (file)
@@ -248,18 +248,20 @@ get_compile_file_tempdir (void)
   return tempdir_name;
 }
 
-/* Compute the names of source and object files to use.  The names are
-   allocated by malloc and should be freed by the caller.  */
+/* Compute the names of source and object files to use.  */
 
-static void
-get_new_file_names (char **source_file, char **object_file)
+static compile_file_names
+get_new_file_names ()
 {
   static int seq;
   const char *dir = get_compile_file_tempdir ();
 
   ++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.  */
@@ -449,18 +451,13 @@ print_callback (void *ignore, const char *message)
 }
 
 /* Process the compilation request.  On success it returns the object
-   file name and *SOURCE_FILEP is set to source file name.  On an
-   error condition, error () is called.  The caller is responsible for
-   freeing both strings.  */
+   and source file names.  On an error condition, error () is
+   called.  */
 
-static char *
+static compile_file_names
 compile_to_object (struct command_line *cmd, const char *cmd_string,
-                  enum compile_i_scope_types scope,
-                  char **source_filep)
+                  enum compile_i_scope_types scope)
 {
-  char *code;
-  const char *input;
-  char *source_file, *object_file;
   struct compile_instance *compiler;
   struct cleanup *cleanup, *inner_cleanup;
   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
      compiler.  */
+
+  std::string input_buf;
+  const char *input;
+
   if (cmd != NULL)
     {
       struct ui_file *stream = mem_fileopen ();
       struct command_line *iter;
-      char *stream_buf;
 
       make_cleanup_ui_file_delete (stream);
       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);
        }
 
-      stream_buf = ui_file_xstrdup (stream, NULL);
-      make_cleanup (xfree, stream_buf);
-      input = stream_buf;
+      input_buf = ui_file_as_string (stream);
+      input = input_buf.c_str ();
     }
   else if (cmd_string != NULL)
     input = cmd_string;
   else
     error (_("Neither a simple expression, or a multi-line specified."));
 
-  code = current_language->la_compute_program (compiler, input, gdbarch,
-                                              expr_block, expr_pc);
-  make_cleanup (xfree, code);
+  std::string code
+    = current_language->la_compute_program (compiler, input, gdbarch,
+                                           expr_block, expr_pc);
   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));
   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]);
     }
 
-  get_new_file_names (&source_file, &object_file);
-  inner_cleanup = make_cleanup (xfree, source_file);
-  make_cleanup (xfree, object_file);
+  compile_file_names fnames = get_new_file_names ();
 
-  src = gdb_fopen_cloexec (source_file, "w");
+  src = gdb_fopen_cloexec (fnames.source_file (), "w");
   if (src == NULL)
     perror_with_name (_("Could not open source file for writing"));
-  make_cleanup (cleanup_unlink_file, source_file);
-  if (fputs (code, src) == EOF)
+  inner_cleanup = make_cleanup (cleanup_unlink_file,
+                               (void *) fnames.source_file ());
+  if (fputs (code.c_str (), src) == EOF)
     perror_with_name (_("Could not write to source file"));
   fclose (src);
 
   if (compile_debug)
     fprintf_unfiltered (gdb_stdlog, "source file produced: %s\n\n",
-                       source_file);
+                       fnames.source_file ());
 
   /* 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))
     error (_("Compilation failed."));
 
   if (compile_debug)
     fprintf_unfiltered (gdb_stdlog, "object file produced: %s\n\n",
-                       object_file);
+                       fnames.object_file ());
 
   discard_cleanups (inner_cleanup);
   do_cleanups (cleanup);
-  *source_filep = source_file;
-  return object_file;
+
+  return fnames;
 }
 
 /* The "compile" prefix command.  */
@@ -602,32 +600,24 @@ void
 eval_compile_command (struct command_line *cmd, const char *cmd_string,
                      enum compile_i_scope_types scope, void *scope_data)
 {
-  char *object_file, *source_file;
+  struct cleanup *cleanup_unlink;
+  struct compile_module *compile_module;
+
+  compile_file_names fnames = compile_to_object (cmd, cmd_string, scope);
 
-  object_file = compile_to_object (cmd, cmd_string, scope, &source_file);
-  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;
-      struct compile_module *compile_module;
-
-      cleanup_xfree = make_cleanup (xfree, object_file);
-      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);
+      gdb_assert (scope == COMPILE_I_PRINT_ADDRESS_SCOPE);
+      eval_compile_command (cmd, cmd_string,
+                           COMPILE_I_PRINT_VALUE_SCOPE, scope_data);
+      return;
     }
+  discard_cleanups (cleanup_unlink);
+  compile_object_run (compile_module);
 }
 
 /* See compile/compile-internal.h.  */
index d6f932e..758f265 100644 (file)
@@ -406,8 +406,8 @@ struct language_defn
        If 'la_get_gcc_context' is not defined, then this method is
        ignored.
 
-       This takes the user-supplied text and returns a newly malloc'd
-       bit of code to compile.  The caller owns the result.
+       This takes the user-supplied text and returns a new bit of code
+       to compile.
 
        INST is the compiler instance being used.
        INPUT is the user's input text.
@@ -416,11 +416,11 @@ struct language_defn
        parsed.
        EXPR_PC is the PC at which the expression is being parsed.  */
 
-    char *(*la_compute_program) (struct compile_instance *inst,
-                                const char *input,
-                                struct gdbarch *gdbarch,
-                                const struct block *expr_block,
-                                CORE_ADDR expr_pc);
+    std::string (*la_compute_program) (struct compile_instance *inst,
+                                      const char *input,
+                                      struct gdbarch *gdbarch,
+                                      const struct block *expr_block,
+                                      CORE_ADDR expr_pc);
 
     /* Add fields above this point, so the magic number is always last.  */
     /* Magic number for compat checking.  */