From: Luis Machado <lgustavo@codesourcery.com>
To: Pedro Alves <palves@redhat.com>, <gdb-patches@sourceware.org>
Subject: Re: [PATCH v4 2/2] Eliminate make_cleanup_ui_file_delete / make ui_file a class hierarchy
Date: Wed, 01 Feb 2017 17:37:00 -0000 [thread overview]
Message-ID: <a1194bed-b33a-d874-2fa2-b0a1ff793eea@codesourcery.com> (raw)
In-Reply-To: <1485909045-30285-3-git-send-email-palves@redhat.com>
Two comments close to the end.
On 01/31/2017 06:30 PM, Pedro Alves wrote:
> This patch starts from the desire to eliminate
> make_cleanup_ui_file_delete, but then goes beyond. It makes ui_file &
> friends a real C++ class hierarchy, and switches temporary
> ui_file-like objects to stack-based allocation.
>
> - mem_fileopen -> string_file
>
> mem_fileopen is replaced with a new string_file class that is treated
> as a value class created on the stack. This alone eliminates most
> make_cleanup_ui_file_delete calls, and, simplifies code a whole lot
> (diffstat shows around 1k loc dropped.)
>
> string_file's internal buffer is a std::string, thus the "string" in
> the name. This simplifies the implementation much, compared to
> mem_fileopen, which managed growing its internal buffer manually.
>
> - ui_file_as_string, ui_file_strdup, ui_file_obsavestring all gone
>
> The new string_file class has a string() method that provides direct
> writable access to the internal std::string buffer. This replaced
> ui_file_as_string, which forced a copy of the same data the stream had
> inside. With direct access via a writable reference, we can instead
> move the string out of the string_stream, avoiding deep string
> copying.
>
> Related, ui_file_xstrdup calls are replaced with xstrdup'ping the
> stream's string, and ui_file_obsavestring is replaced by
> obstack_copy0.
>
> With all those out of the way, getting rid of the weird ui_file_put
> mechanism was possible.
>
> - New ui_file::printf, ui_file::puts, etc. methods
>
> These simplify / clarify client code. I considered splitting
> client-code changes, like these, e.g.:
>
> - stb = mem_fileopen ();
> - fprintf_unfiltered (stb, "%s%s%s",
> - _("The valid values are:\n"),
> - regdesc,
> - _("The default is \"std\"."));
> + string_file stb;
> + stb.printf ("%s%s%s",
> + _("The valid values are:\n"),
> + regdesc,
> + _("The default is \"std\"."));
>
> In two steps, with the first step leaving fprintf_unfiltered (etc.)
> calls in place, and only afterwards do a pass to change all those to
> call stb.printf etc.. I didn't do that split, because (when I tried),
> it turned out to be pointless make-work: the first pass would have to
> touch the fprintf_unfiltered line anyway, to replace "stb" with
> "&stb".
>
> - gdb_fopen replaced with stack-based objects
>
> This avoids the need for cleanups or unique_ptr's. I.e., this:
>
> struct ui_file *file = gdb_fopen (filename, "w");
> if (filename == NULL)
> perror_with_name (filename);
> cleanups = make_cleanup_ui_file_delete (file);
> // use file.
> do_cleanups (cleanups);
>
> is replaced with this:
>
> stdio_file file;
> if (!file.open (filename, "w"))
> perror_with_name (filename);
> // use file.
>
> - odd contorsions in null_file_write / null_file_fputs around when to
> call to_fputs / to_write eliminated.
>
> - Global null_stream object
>
> A few places that were allocating a ui_file in order to print to
> "nowhere" are adjusted to instead refer to a new 'null_stream' global
> stream.
>
> - TUI's tui_sfileopen eliminated. TUI's ui_file much simplified
>
> The TUI's ui_file was serving a dual purpose. It supported being used
> as string buffer, and supported being backed by a stdio FILE. The
> string buffer part is gone, replaced by using of string_file. The
> 'FILE *' support is now much simplified, by making the TUI's ui_file
> inherit from stdio_file.
>
> gdb/ChangeLog:
> yyyy-mm-dd Pedro Alves <palves@redhat.com>
>
> * ada-lang.c (type_as_string): Use string_file.
> * ada-valprint.c (ada_print_floating): Use string_file.
> * ada-varobj.c (ada_varobj_scalar_image)
> (ada_varobj_get_value_image): Use string_file.
> * aix-thread.c (aix_thread_extra_thread_info): Use string_file.
> * arm-tdep.c (_initialize_arm_tdep): Use string_printf.
> * breakpoint.c (update_inserted_breakpoint_locations)
> (insert_breakpoint_locations, reattach_breakpoints)
> (print_breakpoint_location, print_one_detail_ranged_breakpoint)
> (print_it_watchpoint): Use string_file.
> (save_breakpoints): Use stdio_file.
> * c-exp.y (oper): Use string_file.
> * cli/cli-logging.c (set_logging_redirect): Use ui_file_up and
> tee_file.
> (pop_output_files): Use delete.
> (handle_redirections): Use stdio_file and tee_file.
> * cli/cli-setshow.c (do_show_command): Use string_file.
> * compile/compile-c-support.c (c_compute_program): Use
> string_file.
> * compile/compile-c-symbols.c (generate_vla_size): Take a
> 'string_file &' instead of a 'ui_file *'.
> (generate_c_for_for_one_variable): Take a 'string_file &' instead
> of a 'ui_file *'. Use string_file.
> (generate_c_for_variable_locations): Take a 'string_file &'
> instead of a 'ui_file *'.
> * compile/compile-internal.h (generate_c_for_for_one_variable):
> Take a 'string_file &' instead of a 'ui_file *'.
> * compile/compile-loc2c.c (push, pushf, unary, binary)
> (print_label, pushf_register_address, pushf_register)
> (do_compile_dwarf_expr_to_c): Take a 'string_file &' instead of a
> 'ui_file *'. Adjust.
> * compile/compile.c (compile_to_object): Use string_file.
> * compile/compile.h (compile_dwarf_expr_to_c)
> (compile_dwarf_bounds_to_c): Take a 'string_file &' instead of a
> 'ui_file *'.
> * cp-support.c (inspect_type): Use string_file and obstack_copy0.
> (replace_typedefs_qualified_name): Use string_file and
> obstack_copy0.
> * disasm.c (gdb_pretty_print_insn): Use string_file.
> (gdb_disassembly): Adjust reference the null_stream global.
> (do_ui_file_delete): Delete.
> (gdb_insn_length): Use null_stream.
> * dummy-frame.c (maintenance_print_dummy_frames): Use stdio_file.
> * dwarf2loc.c (dwarf2_compile_property_to_c)
> (locexpr_generate_c_location, loclist_generate_c_location): Take a
> 'string_file &' instead of a 'ui_file *'.
> * dwarf2loc.h (dwarf2_compile_property_to_c): Likewise.
> * dwarf2read.c (do_ui_file_peek_last): Delete.
> (dwarf2_compute_name): Use string_file.
> * event-top.c (gdb_setup_readline): Use stdio_file.
> * gdbarch.sh (verify_gdbarch): Use string_file.
> * gdbtypes.c (safe_parse_type): Use null_stream.
> * guile/scm-breakpoint.c (gdbscm_breakpoint_commands): Use
> string_file.
> * guile/scm-disasm.c (gdbscm_print_insn_from_port): Take a
> 'string_file *' instead of a 'ui_file *'.
> (gdbscm_arch_disassemble): Use string_file.
> * guile/scm-frame.c (frscm_print_frame_smob): Use string_file.
> * guile/scm-ports.c (class ioscm_file_port): Now a class that
> inherits from ui_file.
> (ioscm_file_port_delete, ioscm_file_port_rewind)
> (ioscm_file_port_put): Delete.
> (ioscm_file_port_write): Rename to ...
> (ioscm_file_port::write): ... this. Remove file_port_magic
> checks.
> (ioscm_file_port_new): Delete.
> (ioscm_with_output_to_port_worker): Use ioscm_file_port and
> ui_file_up.
> * guile/scm-type.c (tyscm_type_name): Use string_file.
> * guile/scm-value.c (vlscm_print_value_smob, gdbscm_value_print):
> Use string_file.
> * infcmd.c (print_return_value_1): Use string_file.
> * infrun.c (print_target_wait_results): Use string_file.
> * language.c (add_language): Use string_file.
> * location.c (explicit_to_string_internal): Use string_file.
> * main.c (captured_main_1): Use null_file.
> * maint.c (maintenance_print_architecture): Use stdio_file.
> * mi/mi-cmd-stack.c (list_arg_or_local): Use string_file.
> * mi/mi-common.h (struct mi_interp) <out, err, log, targ,
> event_channel>: Change type to mi_console_file pointer.
> * mi/mi-console.c (mi_console_file_fputs, mi_console_file_flush)
> (mi_console_file_delete): Delete.
> (struct mi_console_file): Delete.
> (mi_console_file_magic): Delete.
> (mi_console_file_new): Delete.
> (mi_console_file::mi_console_file): New.
> (mi_console_file_delete): Delete.
> (mi_console_file_fputs): Delete.
> (mi_console_file::write): New.
> (mi_console_raw_packet): Delete.
> (mi_console_file::flush): New.
> (mi_console_file_flush): Delete.
> (mi_console_set_raw): Rename to ...
> (mi_console_file::set_raw): ... this.
> * mi/mi-console.h (class mi_console_file): New class.
> (mi_console_file_new, mi_console_set_raw): Delete.
> * mi/mi-interp.c (mi_interpreter_init): Use mi_console_file.
> (mi_set_logging): Use delete and tee_file. Adjust.
> * mi/mi-main.c (output_register): Use string_file.
> (mi_cmd_data_evaluate_expression): Use string_file.
> (mi_cmd_data_read_memory): Use string_file.
> (mi_cmd_execute, print_variable_or_computed): Use string_file.
> * mi/mi-out.c (mi_ui_out::main_stream): New.
> (mi_ui_out::rewind): Use main_stream and
> string_file.
> (mi_ui_out::put): Use main_stream and string_file.
> (mi_ui_out::mi_ui_out): Remove 'stream' parameter.
> Allocate a 'string_file' instead.
> (mi_out_new): Don't allocate a mem_fileopen stream here.
> * mi/mi-out.h (mi_ui_out::mi_ui_out): Remove 'stream' parameter.
> (mi_ui_out::main_stream): Declare method.
> * printcmd.c (eval_command): Use string_file.
> * psymtab.c (maintenance_print_psymbols): Use stdio_file.
> * python/py-arch.c (archpy_disassemble): Use string_file.
> * python/py-breakpoint.c (bppy_get_commands): Use string_file.
> * python/py-frame.c (frapy_str): Use string_file.
> * python/py-framefilter.c (py_print_type, py_print_single_arg):
> Use string_file.
> * python/py-type.c (typy_str): Use string_file.
> * python/py-unwind.c (unwind_infopy_str): Use string_file.
> * python/py-value.c (valpy_str): Use string_file.
> * record-btrace.c (btrace_insn_history): Use string_file.
> * regcache.c (regcache_print): Use stdio_file.
> * reggroups.c (maintenance_print_reggroups): Use stdio_file.
> * remote.c (escape_buffer): Use string_file.
> * rust-lang.c (rust_get_disr_info): Use string_file.
> * serial.c (serial_open_ops_1): Use stdio_file.
> (do_serial_close): Use delete.
> * stack.c (print_frame_arg): Use string_file.
> (print_frame_args): Remove local mem_fileopen stream, not used.
> (print_frame): Use string_file.
> * symmisc.c (maintenance_print_symbols): Use stdio_file.
> * symtab.h (struct symbol_computed_ops) <generate_c_location>:
> Take a 'string_file *' instead of a 'ui_file *'.
> * top.c (new_ui): Use stdio_file and stderr_file.
> (free_ui): Use delete.
> (execute_command_to_string): Use string_file.
> (quit_confirm): Use string_file.
> * tracepoint.c (collection_list::append_exp): Use string_file.
> * tui/tui-disasm.c (tui_disassemble): Use string_file.
> * tui/tui-file.c: Don't include "ui-file.h".
> (enum streamtype, struct tui_stream): Delete.
> (tui_file_new, tui_file_delete, tui_fileopen, tui_sfileopen)
> (tui_file_isatty, tui_file_rewind, tui_file_put): Delete.
> (tui_file::tui_file): New method.
> (tui_file_fputs): Delete.
> (tui_file_get_strbuf): Delete.
> (tui_file::puts): New method.
> (tui_file_adjust_strbuf): Delete.
> (tui_file_flush): Delete.
> (tui_file::flush): New method.
> * tui/tui-file.h: Tweak intro comment.
> Include ui-file.h.
> (tui_fileopen, tui_sfileopen, tui_file_get_strbuf)
> (tui_file_adjust_strbuf): Delete declarations.
> (class tui_file): New class.
> * tui/tui-io.c (tui_initialize_io): Use tui_file.
> * tui/tui-regs.c (tui_restore_gdbout): Use delete.
> (tui_register_format): Use string_stream.
> * tui/tui-stack.c (tui_make_status_line): Use string_file.
> (tui_get_function_from_frame): Use string_file.
> * typeprint.c (type_to_string): Use string_file.
> * ui-file.c (struct ui_file, ui_file_magic, ui_file_new): Delete.
> (null_stream): New global.
> (ui_file_delete): Delete.
> (ui_file::ui_file): New.
> (null_file_isatty): Delete.
> (ui_file::~ui_file): New.
> (null_file_rewind): Delete.
> (ui_file::printf): New.
> (null_file_put): Delete.
> (null_file_flush): Delete.
> (ui_file::putstr): New.
> (null_file_write): Delete.
> (ui_file::putstrn): New.
> (null_file_read): Delete.
> (ui_file::putc): New.
> (null_file_fputs): Delete.
> (null_file_write_async_safe): Delete.
> (ui_file::vprintf): New.
> (null_file_delete): Delete.
> (null_file::write): New.
> (null_file_fseek): Delete.
> (null_file::puts): New.
> (ui_file_data): Delete.
> (null_file::write_async_safe): New.
> (gdb_flush, ui_file_isatty): Adjust.
> (ui_file_put, ui_file_rewind): Delete.
> (ui_file_write): Adjust.
> (ui_file_write_for_put): Delete.
> (ui_file_write_async_safe, ui_file_read): Adjust.
> (ui_file_fseek): Delete.
> (fputs_unfiltered): Adjust.
> (set_ui_file_flush, set_ui_file_isatty, set_ui_file_rewind)
> (set_ui_file_put, set_ui_file_write, set_ui_file_write_async_safe)
> (set_ui_file_read, set_ui_file_fputs, set_ui_file_fseek)
> (set_ui_file_data): Delete.
> (string_file::~string_file, string_file::write)
> (struct accumulated_ui_file, do_ui_file_xstrdup, ui_file_xstrdup)
> (do_ui_file_as_string, ui_file_as_string): Delete.
> (do_ui_file_obsavestring, ui_file_obsavestring): Delete.
> (struct mem_file): Delete.
> (mem_file_new): Delete.
> (stdio_file::stdio_file): New.
> (mem_file_delete): Delete.
> (stdio_file::stdio_file): New.
> (mem_fileopen): Delete.
> (stdio_file::~stdio_file): New.
> (mem_file_rewind): Delete.
> (stdio_file::set_stream): New.
> (mem_file_put): Delete.
> (stdio_file::open): New.
> (mem_file_write): Delete.
> (stdio_file_magic, struct stdio_file): Delete.
> (stdio_file_new, stdio_file_delete, stdio_file_flush): Delete.
> (stdio_file::flush): New.
> (stdio_file_read): Rename to ...
> (stdio_file::read): ... this. Adjust.
> (stdio_file_write): Rename to ...
> (stdio_file::write): ... this. Adjust.
> (stdio_file_write_async_safe): Rename to ...
> (stdio_file::write_async_safe) ... this. Adjust.
> (stdio_file_fputs): Rename to ...
> (stdio_file::puts) ... this. Adjust.
> (stdio_file_isatty): Delete.
> (stdio_file_fseek): Delete.
> (stdio_file::isatty): New.
> (stderr_file_write): Rename to ...
> (stderr_file::write) ... this. Adjust.
> (stderr_file_fputs): Rename to ...
> (stderr_file::puts) ... this. Adjust.
> (stderr_fileopen, stdio_fileopen, gdb_fopen): Delete.
> (stderr_file::stderr_file): New.
> (tee_file_magic): Delete.
> (struct tee_file): Delete.
> (tee_file::tee_file): New.
> (tee_file_new): Delete.
> (tee_file::~tee_file): New.
> (tee_file_delete): Delete.
> (tee_file_flush): Rename to ...
> (tee_file::flush): ... this. Adjust.
> (tee_file_write): Rename to ...
> (tee_file::write): ... this. Adjust.
> (tee_file::write_async_safe): New.
> (tee_file_fputs): Rename to ...
> (tee_file::puts): ... this. Adjust.
> (tee_file_isatty): Rename to ...
> (tee_file::isatty): ... this. Adjust.
> * ui-file.h (struct obstack, struct ui_file): Don't
> forward-declare.
> (ui_file_new, ui_file_flush_ftype, set_ui_file_flush)
> (ui_file_write_ftype)
> (set_ui_file_write, ui_file_fputs_ftype, set_ui_file_fputs)
> (ui_file_write_async_safe_ftype, set_ui_file_write_async_safe)
> (ui_file_read_ftype, set_ui_file_read, ui_file_isatty_ftype)
> (set_ui_file_isatty, ui_file_rewind_ftype, set_ui_file_rewind)
> (ui_file_put_method_ftype, ui_file_put_ftype, set_ui_file_put)
> (ui_file_delete_ftype, set_ui_file_data, ui_file_fseek_ftype)
> (set_ui_file_fseek): Delete.
> (ui_file_data, ui_file_delete, ui_file_rewind)
> (struct ui_file): New.
> (ui_file_up): New.
> (class null_file): New.
> (null_stream): Declare.
> (ui_file_write_for_put, ui_file_put): Delete.
> (ui_file_xstrdup, ui_file_as_string, ui_file_obsavestring):
> Delete.
> (ui_file_fseek, mem_fileopen, stdio_fileopen, stderr_fileopen)
> (gdb_fopen, tee_file_new): Delete.
> (struct string_file): New.
> (struct stdio_file): New.
> (stdio_file_up): New.
> (struct stderr_file): New.
> (class tee_file): New.
> * ui-out.c (ui_out::field_stream): Take a 'string_file &' instead
> of a 'ui_file *'. Adjust.
> * ui-out.h (class ui_out) <field_stream>: Likewise.
> * utils.c (do_ui_file_delete, make_cleanup_ui_file_delete)
> (null_stream): Delete.
> (error_stream): Take a 'string_file &' instead of a 'ui_file *'.
> Adjust.
> * utils.h (struct ui_file): Delete forward declaration..
> (make_cleanup_ui_file_delete, null_stream): Delete declarations.
> (error_stream): Take a 'string_file &' instead of a
> 'ui_file *'.
> * varobj.c (varobj_value_get_print_value): Use string_file.
> * xtensa-tdep.c (xtensa_verify_config): Use string_file.
> * gdbarch.c: Regenerate.
> ---
> gdb/ada-lang.c | 12 +-
> gdb/ada-valprint.c | 9 +-
> gdb/ada-varobj.c | 23 +-
> gdb/aix-thread.c | 18 +-
> gdb/arm-tdep.c | 13 +-
> gdb/breakpoint.c | 97 +++--
> gdb/c-exp.y | 8 +-
> gdb/cli/cli-logging.c | 55 ++-
> gdb/cli/cli-setshow.c | 36 +-
> gdb/compile/compile-c-support.c | 62 ++--
> gdb/compile/compile-c-symbols.c | 21 +-
> gdb/compile/compile-internal.h | 2 +-
> gdb/compile/compile-loc2c.c | 107 +++---
> gdb/compile/compile.c | 9 +-
> gdb/compile/compile.h | 4 +-
> gdb/cp-support.c | 38 +-
> gdb/disasm-selftests.c | 4 +-
> gdb/disasm.c | 18 +-
> gdb/dummy-frame.c | 9 +-
> gdb/dwarf2loc.c | 6 +-
> gdb/dwarf2loc.h | 2 +-
> gdb/dwarf2read.c | 48 +--
> gdb/event-top.c | 4 +-
> gdb/gdbarch.c | 32 +-
> gdb/gdbarch.sh | 20 +-
> gdb/gdbtypes.c | 3 +-
> gdb/guile/scm-breakpoint.c | 12 +-
> gdb/guile/scm-disasm.c | 16 +-
> gdb/guile/scm-frame.c | 9 +-
> gdb/guile/scm-ports.c | 95 ++---
> gdb/guile/scm-type.c | 14 +-
> gdb/guile/scm-value.c | 29 +-
> gdb/infcmd.c | 12 +-
> gdb/infrun.c | 36 +-
> gdb/language.c | 38 +-
> gdb/location.c | 43 +--
> gdb/main.c | 2 +-
> gdb/maint.c | 9 +-
> gdb/mi/mi-cmd-stack.c | 17 +-
> gdb/mi/mi-common.h | 12 +-
> gdb/mi/mi-console.c | 135 ++-----
> gdb/mi/mi-console.h | 36 +-
> gdb/mi/mi-interp.c | 22 +-
> gdb/mi/mi-main.c | 61 ++-
> gdb/mi/mi-out.c | 27 +-
> gdb/mi/mi-out.h | 7 +-
> gdb/printcmd.c | 11 +-
> gdb/psymtab.c | 19 +-
> gdb/python/py-arch.c | 30 +-
> gdb/python/py-breakpoint.c | 13 +-
> gdb/python/py-frame.c | 9 +-
> gdb/python/py-framefilter.c | 32 +-
> gdb/python/py-type.c | 19 +-
> gdb/python/py-unwind.c | 24 +-
> gdb/python/py-value.c | 16 +-
> gdb/regcache.c | 9 +-
> gdb/reggroups.c | 9 +-
> gdb/remote.c | 12 +-
> gdb/rust-lang.c | 9 +-
> gdb/serial.c | 9 +-
> gdb/stack.c | 28 +-
> gdb/symmisc.c | 14 +-
> gdb/symtab.h | 2 +-
> gdb/top.c | 51 +--
> gdb/tracepoint.c | 7 +-
> gdb/tui/tui-disasm.c | 18 +-
> gdb/tui/tui-file.c | 230 +-----------
> gdb/tui/tui-file.h | 18 +-
> gdb/tui/tui-io.c | 4 +-
> gdb/tui/tui-regs.c | 21 +-
> gdb/tui/tui-stack.c | 33 +-
> gdb/typeprint.c | 17 +-
> gdb/ui-file.c | 802 +++++++---------------------------------
> gdb/ui-file.h | 295 ++++++++++-----
> gdb/ui-out.c | 10 +-
> gdb/ui-out.h | 2 +-
> gdb/utils.c | 33 +-
> gdb/utils.h | 8 +-
> gdb/varobj.c | 29 +-
> gdb/xtensa-tdep.c | 31 +-
> 80 files changed, 1058 insertions(+), 2108 deletions(-)
>
> diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
> index 381752b..502710a 100644
> --- a/gdb/ada-lang.c
> +++ b/gdb/ada-lang.c
> @@ -7602,17 +7602,11 @@ ada_value_struct_elt (struct value *arg, char *name, int no_err)
> static std::string
> type_as_string (struct type *type)
> {
> - struct ui_file *tmp_stream = mem_fileopen ();
> - struct cleanup *old_chain;
> -
> - tmp_stream = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (tmp_stream);
> + string_file tmp_stream;
>
> - type_print (type, "", tmp_stream, -1);
> - std::string str = ui_file_as_string (tmp_stream);
> + type_print (type, "", &tmp_stream, -1);
>
> - do_cleanups (old_chain);
> - return str;
> + return std::move (tmp_stream.string ());
> }
>
> /* Given a type TYPE, look up the type of the component of type named NAME.
> diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c
> index 0a9e325..804cf40 100644
> --- a/gdb/ada-valprint.c
> +++ b/gdb/ada-valprint.c
> @@ -298,12 +298,11 @@ static void
> ada_print_floating (const gdb_byte *valaddr, struct type *type,
> struct ui_file *stream)
> {
> - struct ui_file *tmp_stream = mem_fileopen ();
> - struct cleanup *cleanups = make_cleanup_ui_file_delete (tmp_stream);
> + string_file tmp_stream;
>
> - print_floating (valaddr, type, tmp_stream);
> + print_floating (valaddr, type, &tmp_stream);
>
> - std::string s = ui_file_as_string (tmp_stream);
> + std::string &s = tmp_stream.string ();
> size_t skip_count = 0;
>
> /* Modify for Ada rules. */
> @@ -342,8 +341,6 @@ ada_print_floating (const gdb_byte *valaddr, struct type *type,
> }
> else
> fprintf_filtered (stream, "%s", &s[skip_count]);
> -
> - do_cleanups (cleanups);
> }
>
> void
> diff --git a/gdb/ada-varobj.c b/gdb/ada-varobj.c
> index 52e3247..34d9c7b 100644
> --- a/gdb/ada-varobj.c
> +++ b/gdb/ada-varobj.c
> @@ -79,14 +79,10 @@ ada_varobj_decode_var (struct value **value_ptr, struct type **type_ptr)
> static std::string
> ada_varobj_scalar_image (struct type *type, LONGEST val)
> {
> - struct ui_file *buf = mem_fileopen ();
> - struct cleanup *cleanups = make_cleanup_ui_file_delete (buf);
> + string_file buf;
>
> - ada_print_scalar (type, val, buf);
> - std::string result = ui_file_as_string (buf);
> - do_cleanups (cleanups);
> -
> - return result;
> + ada_print_scalar (type, val, &buf);
> + return std::move (buf.string ());
> }
>
> /* Assuming that the (PARENT_VALUE, PARENT_TYPE) pair designates
> @@ -808,17 +804,10 @@ static std::string
> ada_varobj_get_value_image (struct value *value,
> struct value_print_options *opts)
> {
> - struct ui_file *buffer;
> - struct cleanup *old_chain;
> -
> - buffer = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (buffer);
> -
> - common_val_print (value, buffer, 0, opts, current_language);
> - std::string result = ui_file_as_string (buffer);
> + string_file buffer;
>
> - do_cleanups (old_chain);
> - return result;
> + common_val_print (value, &buffer, 0, opts, current_language);
> + return std::move (buffer.string ());
> }
>
> /* Assuming that the (VALUE, TYPE) pair designates an array varobj,
> diff --git a/gdb/aix-thread.c b/gdb/aix-thread.c
> index ea64220..cf1a462 100644
> --- a/gdb/aix-thread.c
> +++ b/gdb/aix-thread.c
> @@ -1749,7 +1749,6 @@ static char *
> aix_thread_extra_thread_info (struct target_ops *self,
> struct thread_info *thread)
> {
> - struct ui_file *buf;
> int status;
> pthdb_pthread_t pdtid;
> pthdb_tid_t tid;
> @@ -1762,43 +1761,42 @@ aix_thread_extra_thread_info (struct target_ops *self,
> if (!PD_TID (thread->ptid))
> return NULL;
>
> - buf = mem_fileopen ();
> + string_file buf;
>
> pdtid = thread->priv->pdtid;
> tid = thread->priv->tid;
>
> if (tid != PTHDB_INVALID_TID)
> /* i18n: Like "thread-identifier %d, [state] running, suspended" */
> - fprintf_unfiltered (buf, _("tid %d"), (int)tid);
> + buf.printf (_("tid %d"), (int)tid);
>
> status = pthdb_pthread_state (pd_session, pdtid, &state);
> if (status != PTHDB_SUCCESS)
> state = PST_NOTSUP;
> - fprintf_unfiltered (buf, ", %s", state2str (state));
> + buf.printf (", %s", state2str (state));
>
> status = pthdb_pthread_suspendstate (pd_session, pdtid,
> &suspendstate);
> if (status == PTHDB_SUCCESS && suspendstate == PSS_SUSPENDED)
> /* i18n: Like "Thread-Id %d, [state] running, suspended" */
> - fprintf_unfiltered (buf, _(", suspended"));
> + buf.printf (_(", suspended"));
>
> status = pthdb_pthread_detachstate (pd_session, pdtid,
> &detachstate);
> if (status == PTHDB_SUCCESS && detachstate == PDS_DETACHED)
> /* i18n: Like "Thread-Id %d, [state] running, detached" */
> - fprintf_unfiltered (buf, _(", detached"));
> + buf.printf (_(", detached"));
>
> pthdb_pthread_cancelpend (pd_session, pdtid, &cancelpend);
> if (status == PTHDB_SUCCESS && cancelpend)
> /* i18n: Like "Thread-Id %d, [state] running, cancel pending" */
> - fprintf_unfiltered (buf, _(", cancel pending"));
> + buf.printf (_(", cancel pending"));
>
> - ui_file_write (buf, "", 1);
> + buf.write ("", 1);
>
> xfree (ret); /* Free old buffer. */
>
> - ret = ui_file_xstrdup (buf, NULL);
> - ui_file_delete (buf);
> + ret = xstrdup (buf.c_str ());
>
> return ret;
> }
> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
> index 0ae311f..88ed391 100644
> --- a/gdb/arm-tdep.c
> +++ b/gdb/arm-tdep.c
> @@ -9576,13 +9576,11 @@ extern initialize_file_ftype _initialize_arm_tdep; /* -Wmissing-prototypes */
> void
> _initialize_arm_tdep (void)
> {
> - struct ui_file *stb;
> long length;
> const char *setname;
> const char *setdesc;
> const char *const *regnames;
> int i;
> - static std::string helptext;
> char regdesc[1024], *rdptr = regdesc;
> size_t rest = sizeof (regdesc);
>
> @@ -9648,13 +9646,10 @@ _initialize_arm_tdep (void)
> valid_disassembly_styles[num_disassembly_options] = NULL;
>
> /* Create the help text. */
> - stb = mem_fileopen ();
> - fprintf_unfiltered (stb, "%s%s%s",
> - _("The valid values are:\n"),
> - regdesc,
> - _("The default is \"std\"."));
> - helptext = ui_file_as_string (stb);
> - ui_file_delete (stb);
> + std::string helptext = string_printf ("%s%s%s",
> + _("The valid values are:\n"),
> + regdesc,
> + _("The default is \"std\"."));
>
> add_setshow_enum_cmd("disassembler", no_class,
> valid_disassembly_styles, &disassembly_style,
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index 867dbb9..a76b3e4 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -3061,14 +3061,13 @@ update_inserted_breakpoint_locations (void)
> int hw_breakpoint_error = 0;
> int hw_bp_details_reported = 0;
>
> - struct ui_file *tmp_error_stream = mem_fileopen ();
> - struct cleanup *cleanups = make_cleanup_ui_file_delete (tmp_error_stream);
> + string_file tmp_error_stream;
>
> /* Explicitly mark the warning -- this will only be printed if
> there was an error. */
> - fprintf_unfiltered (tmp_error_stream, "Warning:\n");
> + tmp_error_stream.puts ("Warning:\n");
>
> - save_current_space_and_thread ();
> + struct cleanup *cleanups = save_current_space_and_thread ();
>
> ALL_BP_LOCATIONS (bl, blp_tmp)
> {
> @@ -3093,7 +3092,7 @@ update_inserted_breakpoint_locations (void)
> && ptid_equal (inferior_ptid, null_ptid))
> continue;
>
> - val = insert_bp_location (bl, tmp_error_stream, &disabled_breaks,
> + val = insert_bp_location (bl, &tmp_error_stream, &disabled_breaks,
> &hw_breakpoint_error, &hw_bp_details_reported);
> if (val)
> error_flag = val;
> @@ -3121,14 +3120,13 @@ insert_breakpoint_locations (void)
> int hw_breakpoint_error = 0;
> int hw_bp_error_explained_already = 0;
>
> - struct ui_file *tmp_error_stream = mem_fileopen ();
> - struct cleanup *cleanups = make_cleanup_ui_file_delete (tmp_error_stream);
> -
> + string_file tmp_error_stream;
> +
> /* Explicitly mark the warning -- this will only be printed if
> there was an error. */
> - fprintf_unfiltered (tmp_error_stream, "Warning:\n");
> + tmp_error_stream.puts ("Warning:\n");
>
> - save_current_space_and_thread ();
> + struct cleanup *cleanups = save_current_space_and_thread ();
>
> ALL_BP_LOCATIONS (bl, blp_tmp)
> {
> @@ -3152,7 +3150,7 @@ insert_breakpoint_locations (void)
> && ptid_equal (inferior_ptid, null_ptid))
> continue;
>
> - val = insert_bp_location (bl, tmp_error_stream, &disabled_breaks,
> + val = insert_bp_location (bl, &tmp_error_stream, &disabled_breaks,
> &hw_breakpoint_error, &hw_bp_error_explained_already);
> if (val)
> error_flag = val;
> @@ -3187,9 +3185,9 @@ insert_breakpoint_locations (void)
> remove_breakpoint (loc);
>
> hw_breakpoint_error = 1;
> - fprintf_unfiltered (tmp_error_stream,
> - "Could not insert hardware watchpoint %d.\n",
> - bpt->number);
> + tmp_error_stream.printf ("Could not insert "
> + "hardware watchpoint %d.\n",
> + bpt->number);
> error_flag = -1;
> }
> }
> @@ -3200,8 +3198,7 @@ insert_breakpoint_locations (void)
> message about possibly exhausted resources. */
> if (hw_breakpoint_error && !hw_bp_error_explained_already)
> {
> - fprintf_unfiltered (tmp_error_stream,
> - "Could not insert hardware breakpoints:\n\
> + tmp_error_stream.printf ("Could not insert hardware breakpoints:\n\
> You may have requested too many hardware breakpoints/watchpoints.\n");
> }
> target_terminal_ours_for_output ();
> @@ -3283,7 +3280,6 @@ reattach_breakpoints (int pid)
> struct cleanup *old_chain;
> struct bp_location *bl, **blp_tmp;
> int val;
> - struct ui_file *tmp_error_stream;
> int dummy1 = 0, dummy2 = 0, dummy3 = 0;
> struct inferior *inf;
> struct thread_info *tp;
> @@ -3297,8 +3293,7 @@ reattach_breakpoints (int pid)
>
> inferior_ptid = tp->ptid;
>
> - tmp_error_stream = mem_fileopen ();
> - make_cleanup_ui_file_delete (tmp_error_stream);
> + string_file tmp_error_stream;
>
> ALL_BP_LOCATIONS (bl, blp_tmp)
> {
> @@ -3308,7 +3303,7 @@ reattach_breakpoints (int pid)
> if (bl->inserted)
> {
> bl->inserted = 0;
> - val = insert_bp_location (bl, tmp_error_stream, &dummy1, &dummy2, &dummy3);
> + val = insert_bp_location (bl, &tmp_error_stream, &dummy1, &dummy2, &dummy3);
> if (val != 0)
> {
> do_cleanups (old_chain);
> @@ -6179,14 +6174,11 @@ print_breakpoint_location (struct breakpoint *b,
> }
> else if (loc)
> {
> - struct ui_file *stb = mem_fileopen ();
> - struct cleanup *stb_chain = make_cleanup_ui_file_delete (stb);
> + string_file stb;
>
> - print_address_symbolic (loc->gdbarch, loc->address, stb,
> + print_address_symbolic (loc->gdbarch, loc->address, &stb,
> demangle, "");
> uiout->field_stream ("at", stb);
> -
> - do_cleanups (stb_chain);
> }
> else
> {
> @@ -10293,8 +10285,7 @@ print_one_detail_ranged_breakpoint (const struct breakpoint *b,
> {
> CORE_ADDR address_start, address_end;
> struct bp_location *bl = b->loc;
> - struct ui_file *stb = mem_fileopen ();
> - struct cleanup *cleanup = make_cleanup_ui_file_delete (stb);
> + string_file stb;
>
> gdb_assert (bl);
>
> @@ -10302,13 +10293,11 @@ print_one_detail_ranged_breakpoint (const struct breakpoint *b,
> address_end = address_start + bl->length - 1;
>
> uiout->text ("\taddress range: ");
> - fprintf_unfiltered (stb, "[%s, %s]",
> - print_core_address (bl->gdbarch, address_start),
> - print_core_address (bl->gdbarch, address_end));
> + stb.printf ("[%s, %s]",
> + print_core_address (bl->gdbarch, address_start),
> + print_core_address (bl->gdbarch, address_end));
> uiout->field_stream ("addr", stb);
> uiout->text ("\n");
> -
> - do_cleanups (cleanup);
> }
>
> /* Implement the "print_mention" breakpoint_ops method for
> @@ -10740,7 +10729,6 @@ print_it_watchpoint (bpstat bs)
> {
> struct cleanup *old_chain;
> struct breakpoint *b;
> - struct ui_file *stb;
> enum print_stop_action result;
> struct watchpoint *w;
> struct ui_out *uiout = current_uiout;
> @@ -10750,12 +10738,13 @@ print_it_watchpoint (bpstat bs)
> b = bs->breakpoint_at;
> w = (struct watchpoint *) b;
>
> - stb = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (stb);
> + old_chain = make_cleanup (null_cleanup, NULL);
>
> annotate_watchpoint (b->number);
> maybe_print_thread_hit_breakpoint (uiout);
>
> + string_file stb;
> +
> switch (b->type)
> {
> case bp_watchpoint:
> @@ -10766,10 +10755,10 @@ print_it_watchpoint (bpstat bs)
> mention (b);
> make_cleanup_ui_out_tuple_begin_end (uiout, "value");
> uiout->text ("\nOld value = ");
> - watchpoint_value_print (bs->old_val, stb);
> + watchpoint_value_print (bs->old_val, &stb);
> uiout->field_stream ("old", stb);
> uiout->text ("\nNew value = ");
> - watchpoint_value_print (w->val, stb);
> + watchpoint_value_print (w->val, &stb);
> uiout->field_stream ("new", stb);
> uiout->text ("\n");
> /* More than one watchpoint may have been triggered. */
> @@ -10783,7 +10772,7 @@ print_it_watchpoint (bpstat bs)
> mention (b);
> make_cleanup_ui_out_tuple_begin_end (uiout, "value");
> uiout->text ("\nValue = ");
> - watchpoint_value_print (w->val, stb);
> + watchpoint_value_print (w->val, &stb);
> uiout->field_stream ("value", stb);
> uiout->text ("\n");
> result = PRINT_UNKNOWN;
> @@ -10799,7 +10788,7 @@ print_it_watchpoint (bpstat bs)
> mention (b);
> make_cleanup_ui_out_tuple_begin_end (uiout, "value");
> uiout->text ("\nOld value = ");
> - watchpoint_value_print (bs->old_val, stb);
> + watchpoint_value_print (bs->old_val, &stb);
> uiout->field_stream ("old", stb);
> uiout->text ("\nNew value = ");
> }
> @@ -10813,7 +10802,7 @@ print_it_watchpoint (bpstat bs)
> make_cleanup_ui_out_tuple_begin_end (uiout, "value");
> uiout->text ("\nValue = ");
> }
> - watchpoint_value_print (w->val, stb);
> + watchpoint_value_print (w->val, &stb);
> uiout->field_stream ("new", stb);
> uiout->text ("\n");
> result = PRINT_UNKNOWN;
> @@ -15669,7 +15658,6 @@ save_breakpoints (char *filename, int from_tty,
> struct breakpoint *tp;
> int any = 0;
> struct cleanup *cleanup;
> - struct ui_file *fp;
> int extra_trace_bits = 0;
>
> if (filename == 0 || *filename == 0)
> @@ -15705,14 +15693,15 @@ save_breakpoints (char *filename, int from_tty,
>
> filename = tilde_expand (filename);
> cleanup = make_cleanup (xfree, filename);
> - fp = gdb_fopen (filename, "w");
> - if (!fp)
> +
> + stdio_file fp;
> +
> + if (!fp.open (filename, "w"))
> error (_("Unable to open file '%s' for saving (%s)"),
> filename, safe_strerror (errno));
> - make_cleanup_ui_file_delete (fp);
>
> if (extra_trace_bits)
> - save_trace_state_variables (fp);
> + save_trace_state_variables (&fp);
>
> ALL_BREAKPOINTS (tp)
> {
> @@ -15724,23 +15713,23 @@ save_breakpoints (char *filename, int from_tty,
> if (filter && !filter (tp))
> continue;
>
> - tp->ops->print_recreate (tp, fp);
> + tp->ops->print_recreate (tp, &fp);
>
> /* Note, we can't rely on tp->number for anything, as we can't
> assume the recreated breakpoint numbers will match. Use $bpnum
> instead. */
>
> if (tp->cond_string)
> - fprintf_unfiltered (fp, " condition $bpnum %s\n", tp->cond_string);
> + fp.printf (" condition $bpnum %s\n", tp->cond_string);
>
> if (tp->ignore_count)
> - fprintf_unfiltered (fp, " ignore $bpnum %d\n", tp->ignore_count);
> + fp.printf (" ignore $bpnum %d\n", tp->ignore_count);
>
> if (tp->type != bp_dprintf && tp->commands)
> {
> - fprintf_unfiltered (fp, " commands\n");
> + fp.puts (" commands\n");
>
> - current_uiout->redirect (fp);
> + current_uiout->redirect (&fp);
> TRY
> {
> print_command_lines (current_uiout, tp->commands->commands, 2);
> @@ -15753,11 +15742,11 @@ save_breakpoints (char *filename, int from_tty,
> END_CATCH
>
> current_uiout->redirect (NULL);
> - fprintf_unfiltered (fp, " end\n");
> + fp.puts (" end\n");
> }
>
> if (tp->enable_state == bp_disabled)
> - fprintf_unfiltered (fp, "disable $bpnum\n");
> + fp.puts ("disable $bpnum\n");
>
> /* If this is a multi-location breakpoint, check if the locations
> should be individually disabled. Watchpoint locations are
> @@ -15769,12 +15758,12 @@ save_breakpoints (char *filename, int from_tty,
>
> for (loc = tp->loc; loc != NULL; loc = loc->next, n++)
> if (!loc->enabled)
> - fprintf_unfiltered (fp, "disable $bpnum.%d\n", n);
> + fp.printf ("disable $bpnum.%d\n", n);
> }
> }
>
> if (extra_trace_bits && *default_collect)
> - fprintf_unfiltered (fp, "set default-collect %s\n", default_collect);
> + fp.printf ("set default-collect %s\n", default_collect);
>
> if (from_tty)
> printf_filtered (_("Saved to file '%s'.\n"), filename);
> diff --git a/gdb/c-exp.y b/gdb/c-exp.y
> index 8a92cce..2753c6e 100644
> --- a/gdb/c-exp.y
> +++ b/gdb/c-exp.y
> @@ -1555,13 +1555,11 @@ oper: OPERATOR NEW
> | OPERATOR OBJC_LBRAC ']'
> { $$ = operator_stoken ("[]"); }
> | OPERATOR conversion_type_id
> - { struct ui_file *buf = mem_fileopen ();
> + { string_file buf;
>
> - c_print_type ($2, NULL, buf, -1, 0,
> + c_print_type ($2, NULL, &buf, -1, 0,
> &type_print_raw_options);
> - std::string name = ui_file_as_string (buf);
> - ui_file_delete (buf);
> - $$ = operator_stoken (name.c_str ());
> + $$ = operator_stoken (buf.c_str ());
> }
> ;
>
> diff --git a/gdb/cli/cli-logging.c b/gdb/cli/cli-logging.c
> index 9428624..f165896 100644
> --- a/gdb/cli/cli-logging.c
> +++ b/gdb/cli/cli-logging.c
> @@ -76,7 +76,7 @@ static struct ui_file *logging_no_redirect_file;
> static void
> set_logging_redirect (char *args, int from_tty, struct cmd_list_element *c)
> {
> - struct cleanup *cleanups;
> + ui_file_up destroy_old_stdout;
> struct ui_file *output, *new_logging_no_redirect_file;
> struct ui_out *uiout = current_uiout;
>
> @@ -85,15 +85,13 @@ set_logging_redirect (char *args, int from_tty, struct cmd_list_element *c)
> || (logging_redirect == 0 && logging_no_redirect_file != NULL))
> return;
>
> - cleanups = make_cleanup (null_cleanup, NULL);
> -
> if (logging_redirect != 0)
> {
> gdb_assert (logging_no_redirect_file != NULL);
>
> /* ui_out_redirect still has not been called for next
> gdb_stdout. */
> - make_cleanup_ui_file_delete (gdb_stdout);
> + destroy_old_stdout.reset (gdb_stdout);
>
> output = logging_no_redirect_file;
> new_logging_no_redirect_file = NULL;
> @@ -105,9 +103,7 @@ set_logging_redirect (char *args, int from_tty, struct cmd_list_element *c)
> else
> {
> gdb_assert (logging_no_redirect_file == NULL);
> - output = tee_file_new (saved_output.out, 0, gdb_stdout, 0);
> - if (output == NULL)
> - perror_with_name (_("set logging"));
> + output = new tee_file (saved_output.out, 0, gdb_stdout, 0);
> new_logging_no_redirect_file = gdb_stdout;
>
> if (from_tty)
> @@ -135,8 +131,6 @@ set_logging_redirect (char *args, int from_tty, struct cmd_list_element *c)
>
> uiout->redirect (NULL);
> uiout->redirect (output);
> -
> - do_cleanups (cleanups);
> }
>
> static void
> @@ -152,7 +146,7 @@ pop_output_files (void)
> {
> if (logging_no_redirect_file)
> {
> - ui_file_delete (logging_no_redirect_file);
> + delete logging_no_redirect_file;
> logging_no_redirect_file = NULL;
> }
>
> @@ -160,7 +154,7 @@ pop_output_files (void)
> {
> /* Only delete one of the files -- they are all set to the same
> value. */
> - ui_file_delete (gdb_stdout);
> + delete gdb_stdout;
>
> gdb_stdout = saved_output.out;
> gdb_stderr = saved_output.err;
> @@ -184,9 +178,8 @@ pop_output_files (void)
> static void
> handle_redirections (int from_tty)
> {
> - struct cleanup *cleanups;
> - struct ui_file *output;
> - struct ui_file *no_redirect_file = NULL;
> + ui_file_up output;
> + ui_file_up no_redirect_file;
>
> if (saved_filename != NULL)
> {
> @@ -195,36 +188,30 @@ handle_redirections (int from_tty)
> return;
> }
>
> - output = gdb_fopen (logging_filename, logging_overwrite ? "w" : "a");
> - if (output == NULL)
> + stdio_file_up log (new stdio_file ());
> + if (!log->open (logging_filename, logging_overwrite ? "w" : "a"))
> perror_with_name (_("set logging"));
> - cleanups = make_cleanup_ui_file_delete (output);
>
> /* Redirects everything to gdb_stdout while this is running. */
> if (!logging_redirect)
> {
> - no_redirect_file = output;
> + no_redirect_file = std::move (log);
> + output.reset (new tee_file (gdb_stdout, 0, no_redirect_file.get (), 0));
>
> - output = tee_file_new (gdb_stdout, 0, no_redirect_file, 0);
> - if (output == NULL)
> - perror_with_name (_("set logging"));
> - make_cleanup_ui_file_delete (output);
> if (from_tty)
> fprintf_unfiltered (gdb_stdout, "Copying output to %s.\n",
> logging_filename);
> - logging_no_redirect_file = no_redirect_file;
> }
> else
> {
> gdb_assert (logging_no_redirect_file == NULL);
> + output = std::move (log);
>
> if (from_tty)
> fprintf_unfiltered (gdb_stdout, "Redirecting output to %s.\n",
> logging_filename);
> }
>
> - discard_cleanups (cleanups);
> -
> saved_filename = xstrdup (logging_filename);
> saved_output.out = gdb_stdout;
> saved_output.err = gdb_stderr;
> @@ -233,18 +220,22 @@ handle_redirections (int from_tty)
> saved_output.targerr = gdb_stdtargerr;
>
> /* Let the interpreter do anything it needs. */
> - if (current_interp_set_logging (1, output, no_redirect_file) == 0)
> + if (current_interp_set_logging (1, output.get (),
> + no_redirect_file.get ()) == 0)
> {
> - gdb_stdout = output;
> - gdb_stdlog = output;
> - gdb_stderr = output;
> - gdb_stdtarg = output;
> - gdb_stdtargerr = output;
> + gdb_stdout = output.get ();
> + gdb_stdlog = output.get ();
> + gdb_stderr = output.get ();
> + gdb_stdtarg = output.get ();
> + gdb_stdtargerr = output.get ();
> }
>
> + output.release ();
> + logging_no_redirect_file = no_redirect_file.release ();
> +
> /* Don't do the redirect for MI, it confuses MI's ui-out scheme. */
> if (!current_uiout->is_mi_like_p ())
> - current_uiout->redirect (output);
> + current_uiout->redirect (gdb_stdout);
> }
>
> static void
> diff --git a/gdb/cli/cli-setshow.c b/gdb/cli/cli-setshow.c
> index 9298665..218e1f3 100644
> --- a/gdb/cli/cli-setshow.c
> +++ b/gdb/cli/cli-setshow.c
> @@ -568,13 +568,10 @@ void
> do_show_command (const char *arg, int from_tty, struct cmd_list_element *c)
> {
> struct ui_out *uiout = current_uiout;
> - struct cleanup *old_chain;
> - struct ui_file *stb;
>
> gdb_assert (c->type == show_cmd);
>
> - stb = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (stb);
> + string_file stb;
>
> /* Possibly call the pre hook. */
> if (c->pre_show_hook)
> @@ -584,29 +581,29 @@ do_show_command (const char *arg, int from_tty, struct cmd_list_element *c)
> {
> case var_string:
> if (*(char **) c->var)
> - fputstr_filtered (*(char **) c->var, '"', stb);
> + stb.putstr (*(char **) c->var, '"');
> break;
> case var_string_noescape:
> case var_optional_filename:
> case var_filename:
> case var_enum:
> if (*(char **) c->var)
> - fputs_filtered (*(char **) c->var, stb);
> + stb.puts (*(char **) c->var);
> break;
> case var_boolean:
> - fputs_filtered (*(int *) c->var ? "on" : "off", stb);
> + stb.puts (*(int *) c->var ? "on" : "off");
> break;
> case var_auto_boolean:
> switch (*(enum auto_boolean*) c->var)
> {
> case AUTO_BOOLEAN_TRUE:
> - fputs_filtered ("on", stb);
> + stb.puts ("on");
> break;
> case AUTO_BOOLEAN_FALSE:
> - fputs_filtered ("off", stb);
> + stb.puts ("off");
> break;
> case AUTO_BOOLEAN_AUTO:
> - fputs_filtered ("auto", stb);
> + stb.puts ("auto");
> break;
> default:
> internal_error (__FILE__, __LINE__,
> @@ -619,24 +616,24 @@ do_show_command (const char *arg, int from_tty, struct cmd_list_element *c)
> case var_zuinteger:
> if (c->var_type == var_uinteger
> && *(unsigned int *) c->var == UINT_MAX)
> - fputs_filtered ("unlimited", stb);
> + stb.puts ("unlimited");
> else
> - fprintf_filtered (stb, "%u", *(unsigned int *) c->var);
> + stb.printf ("%u", *(unsigned int *) c->var);
> break;
> case var_integer:
> case var_zinteger:
> if (c->var_type == var_integer
> && *(int *) c->var == INT_MAX)
> - fputs_filtered ("unlimited", stb);
> + stb.puts ("unlimited");
> else
> - fprintf_filtered (stb, "%d", *(int *) c->var);
> + stb.printf ("%d", *(int *) c->var);
> break;
> case var_zuinteger_unlimited:
> {
> if (*(int *) c->var == -1)
> - fputs_filtered ("unlimited", stb);
> + stb.puts ("unlimited");
> else
> - fprintf_filtered (stb, "%d", *(int *) c->var);
> + stb.printf ("%d", *(int *) c->var);
> }
> break;
> default:
> @@ -653,14 +650,11 @@ do_show_command (const char *arg, int from_tty, struct cmd_list_element *c)
> uiout->field_stream ("value", stb);
> else
> {
> - std::string value = ui_file_as_string (stb);
> -
> if (c->show_value_func != NULL)
> - c->show_value_func (gdb_stdout, from_tty, c, value.c_str ());
> + c->show_value_func (gdb_stdout, from_tty, c, stb.c_str ());
> else
> - deprecated_show_value_hack (gdb_stdout, from_tty, c, value.c_str ());
> + deprecated_show_value_hack (gdb_stdout, from_tty, c, stb.c_str ());
> }
> - do_cleanups (old_chain);
>
> c->func (c, NULL, from_tty);
> }
> diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c
> index 877bfb7..7ad0a87 100644
> --- a/gdb/compile/compile-c-support.c
> +++ b/gdb/compile/compile-c-support.c
> @@ -333,15 +333,12 @@ c_compute_program (struct compile_instance *inst,
> const struct block *expr_block,
> CORE_ADDR expr_pc)
> {
> - struct ui_file *buf, *var_stream = NULL;
> - std::string code;
> - struct cleanup *cleanup;
> struct compile_c_instance *context = (struct compile_c_instance *) inst;
>
> - buf = mem_fileopen ();
> - cleanup = make_cleanup_ui_file_delete (buf);
> + string_file buf;
> + string_file var_stream;
>
> - write_macro_definitions (expr_block, expr_pc, buf);
> + write_macro_definitions (expr_block, expr_pc, &buf);
>
> /* Do not generate local variable information for "raw"
> compilations. In this case we aren't emitting our own function
> @@ -355,21 +352,17 @@ c_compute_program (struct compile_instance *inst,
> before generating the function header, so we can define the
> register struct before the function body. This requires a
> temporary stream. */
> - var_stream = mem_fileopen ();
> - make_cleanup_ui_file_delete (var_stream);
> registers_used = generate_c_for_variable_locations (context,
> var_stream, gdbarch,
> expr_block, expr_pc);
> make_cleanup (xfree, registers_used);
>
> - fputs_unfiltered ("typedef unsigned int"
> - " __attribute__ ((__mode__(__pointer__)))"
> - " __gdb_uintptr;\n",
> - buf);
> - fputs_unfiltered ("typedef int"
> - " __attribute__ ((__mode__(__pointer__)))"
> - " __gdb_intptr;\n",
> - buf);
> + buf.puts ("typedef unsigned int"
> + " __attribute__ ((__mode__(__pointer__)))"
> + " __gdb_uintptr;\n");
> + buf.puts ("typedef int"
> + " __attribute__ ((__mode__(__pointer__)))"
> + " __gdb_intptr;\n");
>
> /* Iterate all log2 sizes in bytes supported by c_get_mode_for_size. */
> for (i = 0; i < 4; ++i)
> @@ -377,24 +370,23 @@ c_compute_program (struct compile_instance *inst,
> const char *mode = c_get_mode_for_size (1 << i);
>
> gdb_assert (mode != NULL);
> - fprintf_unfiltered (buf,
> - "typedef int"
> - " __attribute__ ((__mode__(__%s__)))"
> - " __gdb_int_%s;\n",
> - mode, mode);
> + buf.printf ("typedef int"
> + " __attribute__ ((__mode__(__%s__)))"
> + " __gdb_int_%s;\n",
> + mode, mode);
> }
>
> - generate_register_struct (buf, gdbarch, registers_used);
> + generate_register_struct (&buf, gdbarch, registers_used);
> }
>
> - add_code_header (inst->scope, buf);
> + add_code_header (inst->scope, &buf);
>
> if (inst->scope == COMPILE_I_SIMPLE_SCOPE
> || inst->scope == COMPILE_I_PRINT_ADDRESS_SCOPE
> || inst->scope == COMPILE_I_PRINT_VALUE_SCOPE)
> {
> - ui_file_put (var_stream, ui_file_write_for_put, buf);
> - fputs_unfiltered ("#pragma GCC user_expression\n", buf);
> + buf.write (var_stream.c_str (), var_stream.size ());
> + buf.puts ("#pragma GCC user_expression\n");
> }
>
> /* The user expression has to be in its own scope, so that "extern"
> @@ -402,15 +394,15 @@ c_compute_program (struct compile_instance *inst,
> declaration is in the same scope as the declaration provided by
> gdb. */
> if (inst->scope != COMPILE_I_RAW_SCOPE)
> - fputs_unfiltered ("{\n", buf);
> + buf.puts ("{\n");
>
> - fputs_unfiltered ("#line 1 \"gdb command line\"\n", buf);
> + buf.puts ("#line 1 \"gdb command line\"\n");
>
> switch (inst->scope)
> {
> case COMPILE_I_PRINT_ADDRESS_SCOPE:
> case COMPILE_I_PRINT_VALUE_SCOPE:
> - fprintf_unfiltered (buf,
> + buf.printf (
> "__auto_type " COMPILE_I_EXPR_VAL " = %s;\n"
> "typeof (%s) *" COMPILE_I_EXPR_PTR_TYPE ";\n"
> "memcpy (" COMPILE_I_PRINT_OUT_ARG ", %s" COMPILE_I_EXPR_VAL ",\n"
> @@ -420,22 +412,20 @@ c_compute_program (struct compile_instance *inst,
> ? "&" : ""));
> break;
> default:
> - fputs_unfiltered (input, buf);
> + buf.puts (input);
> break;
> }
>
> - fputs_unfiltered ("\n", buf);
> + buf.puts ("\n");
>
> /* For larger user expressions the automatic semicolons may be
> confusing. */
> if (strchr (input, '\n') == NULL)
> - fputs_unfiltered (";\n", buf);
> + buf.puts (";\n");
>
> if (inst->scope != COMPILE_I_RAW_SCOPE)
> - fputs_unfiltered ("}\n", buf);
> + buf.puts ("}\n");
>
> - add_code_footer (inst->scope, buf);
> - code = ui_file_as_string (buf);
> - do_cleanups (cleanup);
> - return code;
> + add_code_footer (inst->scope, &buf);
> + return std::move (buf.string ());
> }
> diff --git a/gdb/compile/compile-c-symbols.c b/gdb/compile/compile-c-symbols.c
> index 6010006..9282cfc 100644
> --- a/gdb/compile/compile-c-symbols.c
> +++ b/gdb/compile/compile-c-symbols.c
> @@ -584,7 +584,7 @@ symbol_seen (htab_t hashtab, struct symbol *sym)
>
> static void
> generate_vla_size (struct compile_c_instance *compiler,
> - struct ui_file *stream,
> + string_file &stream,
> struct gdbarch *gdbarch,
> unsigned char *registers_used,
> CORE_ADDR pc,
> @@ -640,7 +640,7 @@ generate_vla_size (struct compile_c_instance *compiler,
>
> static void
> generate_c_for_for_one_variable (struct compile_c_instance *compiler,
> - struct ui_file *stream,
> + string_file &stream,
> struct gdbarch *gdbarch,
> unsigned char *registers_used,
> CORE_ADDR pc,
> @@ -651,14 +651,14 @@ generate_c_for_for_one_variable (struct compile_c_instance *compiler,
> {
> if (is_dynamic_type (SYMBOL_TYPE (sym)))
> {
> - struct ui_file *size_file = mem_fileopen ();
> - struct cleanup *cleanup = make_cleanup_ui_file_delete (size_file);
> + /* We need to emit to a temporary buffer in case an error
> + occurs in the middle. */
> + string_file local_file;
>
> - generate_vla_size (compiler, size_file, gdbarch, registers_used, pc,
> + generate_vla_size (compiler, local_file, gdbarch, registers_used, pc,
> SYMBOL_TYPE (sym), sym);
> - ui_file_put (size_file, ui_file_write_for_put, stream);
>
> - do_cleanups (cleanup);
> + stream.write (local_file.c_str (), local_file.size ());
> }
>
> if (SYMBOL_COMPUTED_OPS (sym) != NULL)
> @@ -667,14 +667,13 @@ generate_c_for_for_one_variable (struct compile_c_instance *compiler,
> struct cleanup *cleanup = make_cleanup (xfree, generated_name);
> /* We need to emit to a temporary buffer in case an error
> occurs in the middle. */
> - struct ui_file *local_file = mem_fileopen ();
> + string_file local_file;
>
> - make_cleanup_ui_file_delete (local_file);
> SYMBOL_COMPUTED_OPS (sym)->generate_c_location (sym, local_file,
> gdbarch,
> registers_used,
> pc, generated_name);
> - ui_file_put (local_file, ui_file_write_for_put, stream);
> + stream.write (local_file.c_str (), local_file.size ());
>
> do_cleanups (cleanup);
> }
> @@ -719,7 +718,7 @@ generate_c_for_for_one_variable (struct compile_c_instance *compiler,
>
> unsigned char *
> generate_c_for_variable_locations (struct compile_c_instance *compiler,
> - struct ui_file *stream,
> + string_file &stream,
> struct gdbarch *gdbarch,
> const struct block *block,
> CORE_ADDR pc)
> diff --git a/gdb/compile/compile-internal.h b/gdb/compile/compile-internal.h
> index 4bf5bf9..0c53f8c 100644
> --- a/gdb/compile/compile-internal.h
> +++ b/gdb/compile/compile-internal.h
> @@ -135,7 +135,7 @@ extern struct compile_instance *new_compile_instance (struct gcc_c_context *fe);
>
> extern unsigned char *generate_c_for_variable_locations
> (struct compile_c_instance *compiler,
> - struct ui_file *stream,
> + string_file &stream,
> struct gdbarch *gdbarch,
> const struct block *block,
> CORE_ADDR pc);
> diff --git a/gdb/compile/compile-loc2c.c b/gdb/compile/compile-loc2c.c
> index 81684d1..f1296e8 100644
> --- a/gdb/compile/compile-loc2c.c
> +++ b/gdb/compile/compile-loc2c.c
> @@ -435,9 +435,9 @@ compute_stack_depth (enum bfd_endian byte_order, unsigned int addr_size,
> /* Emit code to push a constant. */
>
> static void
> -push (int indent, struct ui_file *stream, ULONGEST l)
> +push (int indent, string_file &stream, ULONGEST l)
> {
> - fprintfi_filtered (indent, stream,
> + fprintfi_filtered (indent, &stream,
> "__gdb_stack[++__gdb_tos] = (" GCC_UINTPTR ") %s;\n",
> hex_string (l));
> }
> @@ -445,57 +445,57 @@ push (int indent, struct ui_file *stream, ULONGEST l)
> /* Emit code to push an arbitrary expression. This works like
> printf. */
>
> -static void pushf (int indent, struct ui_file *stream, const char *format, ...)
> +static void pushf (int indent, string_file &stream, const char *format, ...)
> ATTRIBUTE_PRINTF (3, 4);
>
> static void
> -pushf (int indent, struct ui_file *stream, const char *format, ...)
> +pushf (int indent, string_file &stream, const char *format, ...)
> {
> va_list args;
>
> - fprintfi_filtered (indent, stream, "__gdb_stack[__gdb_tos + 1] = ");
> + fprintfi_filtered (indent, &stream, "__gdb_stack[__gdb_tos + 1] = ");
> va_start (args, format);
> - vfprintf_filtered (stream, format, args);
> + stream.vprintf (format, args);
> va_end (args);
> - fprintf_filtered (stream, ";\n");
> + stream.puts (";\n");
>
> - fprintfi_filtered (indent, stream, "++__gdb_tos;\n");
> + fprintfi_filtered (indent, &stream, "++__gdb_tos;\n");
> }
>
> /* Emit code for a unary expression -- one which operates in-place on
> the top-of-stack. This works like printf. */
>
> -static void unary (int indent, struct ui_file *stream, const char *format, ...)
> +static void unary (int indent, string_file &stream, const char *format, ...)
> ATTRIBUTE_PRINTF (3, 4);
>
> static void
> -unary (int indent, struct ui_file *stream, const char *format, ...)
> +unary (int indent, string_file &stream, const char *format, ...)
> {
> va_list args;
>
> - fprintfi_filtered (indent, stream, "__gdb_stack[__gdb_tos] = ");
> + fprintfi_filtered (indent, &stream, "__gdb_stack[__gdb_tos] = ");
> va_start (args, format);
> - vfprintf_filtered (stream, format, args);
> + stream.vprintf (format, args);
> va_end (args);
> - fprintf_filtered (stream, ";\n");
> + stream.puts (";\n");
> }
>
> /* Emit code for a unary expression -- one which uses the top two
> stack items, popping the topmost one. This works like printf. */
> -static void binary (int indent, struct ui_file *stream, const char *format, ...)
> +static void binary (int indent, string_file &stream, const char *format, ...)
> ATTRIBUTE_PRINTF (3, 4);
>
> static void
> -binary (int indent, struct ui_file *stream, const char *format, ...)
> +binary (int indent, string_file &stream, const char *format, ...)
> {
> va_list args;
>
> - fprintfi_filtered (indent, stream, "__gdb_stack[__gdb_tos - 1] = ");
> + fprintfi_filtered (indent, &stream, "__gdb_stack[__gdb_tos - 1] = ");
> va_start (args, format);
> - vfprintf_filtered (stream, format, args);
> + stream.vprintf (format, args);
> va_end (args);
> - fprintf_filtered (stream, ";\n");
> - fprintfi_filtered (indent, stream, "--__gdb_tos;\n");
> + stream.puts (";\n");
> + fprintfi_filtered (indent, &stream, "--__gdb_tos;\n");
> }
>
> /* Print the name of a label given its "SCOPE", an arbitrary integer
> @@ -503,10 +503,9 @@ binary (int indent, struct ui_file *stream, const char *format, ...)
> corresponding to the label's point of definition. */
>
> static void
> -print_label (struct ui_file *stream, unsigned int scope, int target)
> +print_label (string_file &stream, unsigned int scope, int target)
> {
> - fprintf_filtered (stream, "__label_%u_%s",
> - scope, pulongest (target));
> + stream.printf ("__label_%u_%s", scope, pulongest (target));
> }
>
> /* Emit code that pushes a register's address on the stack.
> @@ -514,7 +513,7 @@ print_label (struct ui_file *stream, unsigned int scope, int target)
> register was needed by this expression. */
>
> static void
> -pushf_register_address (int indent, struct ui_file *stream,
> +pushf_register_address (int indent, string_file &stream,
> unsigned char *registers_used,
> struct gdbarch *gdbarch, int regnum)
> {
> @@ -535,7 +534,7 @@ pushf_register_address (int indent, struct ui_file *stream,
> register's value before it is pushed. */
>
> static void
> -pushf_register (int indent, struct ui_file *stream,
> +pushf_register (int indent, string_file &stream,
> unsigned char *registers_used,
> struct gdbarch *gdbarch, int regnum, uint64_t offset)
> {
> @@ -584,7 +583,7 @@ pushf_register (int indent, struct ui_file *stream,
> things. */
>
> static void
> -do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream,
> +do_compile_dwarf_expr_to_c (int indent, string_file &stream,
> const char *type_name,
> const char *result_name,
> struct symbol *sym, CORE_ADDR pc,
> @@ -609,9 +608,9 @@ do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream,
>
> ++scope;
>
> - fprintfi_filtered (indent, stream, "__attribute__ ((unused)) %s %s;\n",
> + fprintfi_filtered (indent, &stream, "__attribute__ ((unused)) %s %s;\n",
> type_name, result_name);
> - fprintfi_filtered (indent, stream, "{\n");
> + fprintfi_filtered (indent, &stream, "{\n");
> indent += 2;
>
> stack_depth = compute_stack_depth (byte_order, addr_size,
> @@ -648,20 +647,20 @@ do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream,
> "compiled code."),
> SYMBOL_PRINT_NAME (sym));
>
> - fprintfi_filtered (indent, stream, "%s = %s;\n",
> + fprintfi_filtered (indent, &stream, "%s = %s;\n",
> result_name,
> core_addr_to_string (value_address (val)));
> - fprintfi_filtered (indent - 2, stream, "}\n");
> + fprintfi_filtered (indent - 2, &stream, "}\n");
> do_cleanups (cleanup);
> return;
> }
>
> - fprintfi_filtered (indent, stream, GCC_UINTPTR " __gdb_stack[%d];\n",
> + fprintfi_filtered (indent, &stream, GCC_UINTPTR " __gdb_stack[%d];\n",
> stack_depth);
>
> if (need_tempvar)
> - fprintfi_filtered (indent, stream, GCC_UINTPTR " __gdb_tmp;\n");
> - fprintfi_filtered (indent, stream, "int __gdb_tos = -1;\n");
> + fprintfi_filtered (indent, &stream, GCC_UINTPTR " __gdb_tmp;\n");
> + fprintfi_filtered (indent, &stream, "int __gdb_tos = -1;\n");
>
> if (initial != NULL)
> pushf (indent, stream, "%s", core_addr_to_string (*initial));
> @@ -672,13 +671,13 @@ do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream,
> uint64_t uoffset, reg;
> int64_t offset;
>
> - print_spaces (indent - 2, stream);
> + print_spaces (indent - 2, &stream);
> if (info[op_ptr - base].label)
> {
> print_label (stream, scope, op_ptr - base);
> - fprintf_filtered (stream, ":;");
> + stream.puts (":;");
> }
> - fprintf_filtered (stream, "/* %s */\n", get_DW_OP_name (op));
> + stream.printf ("/* %s */\n", get_DW_OP_name (op));
>
> /* This is handy for debugging the generated code:
> fprintf_filtered (stream, "if (__gdb_tos != %d) abort ();\n",
> @@ -919,7 +918,7 @@ do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream,
> break;
>
> case DW_OP_drop:
> - fprintfi_filtered (indent, stream, "--__gdb_tos;\n");
> + fprintfi_filtered (indent, &stream, "--__gdb_tos;\n");
> break;
>
> case DW_OP_pick:
> @@ -929,13 +928,13 @@ do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream,
> break;
>
> case DW_OP_swap:
> - fprintfi_filtered (indent, stream,
> + fprintfi_filtered (indent, &stream,
> "__gdb_tmp = __gdb_stack[__gdb_tos - 1];\n");
> - fprintfi_filtered (indent, stream,
> + fprintfi_filtered (indent, &stream,
> "__gdb_stack[__gdb_tos - 1] = "
> "__gdb_stack[__gdb_tos];\n");
> - fprintfi_filtered (indent, stream, ("__gdb_stack[__gdb_tos] = "
> - "__gdb_tmp;\n"));
> + fprintfi_filtered (indent, &stream, ("__gdb_stack[__gdb_tos] = "
> + "__gdb_tmp;\n"));
> break;
>
> case DW_OP_over:
> @@ -943,15 +942,15 @@ do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream,
> break;
>
> case DW_OP_rot:
> - fprintfi_filtered (indent, stream, ("__gdb_tmp = "
> - "__gdb_stack[__gdb_tos];\n"));
> - fprintfi_filtered (indent, stream,
> + fprintfi_filtered (indent, &stream, ("__gdb_tmp = "
> + "__gdb_stack[__gdb_tos];\n"));
> + fprintfi_filtered (indent, &stream,
> "__gdb_stack[__gdb_tos] = "
> "__gdb_stack[__gdb_tos - 1];\n");
> - fprintfi_filtered (indent, stream,
> + fprintfi_filtered (indent, &stream,
> "__gdb_stack[__gdb_tos - 1] = "
> "__gdb_stack[__gdb_tos -2];\n");
> - fprintfi_filtered (indent, stream, "__gdb_stack[__gdb_tos - 2] = "
> + fprintfi_filtered (indent, &stream, "__gdb_stack[__gdb_tos - 2] = "
> "__gdb_tmp;\n");
> break;
>
> @@ -973,7 +972,7 @@ do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream,
>
> /* Cast to a pointer of the desired type, then
> dereference. */
> - fprintfi_filtered (indent, stream,
> + fprintfi_filtered (indent, &stream,
> "__gdb_stack[__gdb_tos] = "
> "*((__gdb_int_%s *) "
> "__gdb_stack[__gdb_tos]);\n",
> @@ -1099,19 +1098,19 @@ do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream,
> case DW_OP_skip:
> offset = extract_signed_integer (op_ptr, 2, byte_order);
> op_ptr += 2;
> - fprintfi_filtered (indent, stream, "goto ");
> + fprintfi_filtered (indent, &stream, "goto ");
> print_label (stream, scope, op_ptr + offset - base);
> - fprintf_filtered (stream, ";\n");
> + stream.puts (";\n");
> break;
>
> case DW_OP_bra:
> offset = extract_signed_integer (op_ptr, 2, byte_order);
> op_ptr += 2;
> - fprintfi_filtered (indent, stream,
> + fprintfi_filtered (indent, &stream,
> "if ((( " GCC_INTPTR
> ") __gdb_stack[__gdb_tos--]) != 0) goto ");
> print_label (stream, scope, op_ptr + offset - base);
> - fprintf_filtered (stream, ";\n");
> + stream.puts (";\n");
> break;
>
> case DW_OP_nop:
> @@ -1122,9 +1121,9 @@ do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream,
> }
> }
>
> - fprintfi_filtered (indent, stream, "%s = __gdb_stack[__gdb_tos];\n",
> + fprintfi_filtered (indent, &stream, "%s = __gdb_stack[__gdb_tos];\n",
> result_name);
> - fprintfi_filtered (indent - 2, stream, "}\n");
> + fprintfi_filtered (indent - 2, &stream, "}\n");
>
> do_cleanups (cleanup);
> }
> @@ -1132,7 +1131,7 @@ do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream,
> /* See compile.h. */
>
> void
> -compile_dwarf_expr_to_c (struct ui_file *stream, const char *result_name,
> +compile_dwarf_expr_to_c (string_file &stream, const char *result_name,
> struct symbol *sym, CORE_ADDR pc,
> struct gdbarch *arch, unsigned char *registers_used,
> unsigned int addr_size,
> @@ -1147,7 +1146,7 @@ compile_dwarf_expr_to_c (struct ui_file *stream, const char *result_name,
> /* See compile.h. */
>
> void
> -compile_dwarf_bounds_to_c (struct ui_file *stream,
> +compile_dwarf_bounds_to_c (string_file &stream,
> const char *result_name,
> const struct dynamic_prop *prop,
> struct symbol *sym, CORE_ADDR pc,
> diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
> index 0ae2125..b525f61 100644
> --- a/gdb/compile/compile.c
> +++ b/gdb/compile/compile.c
> @@ -494,22 +494,19 @@ 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;
> + string_file input_buf;
> const char *input;
>
> if (cmd != NULL)
> {
> - struct ui_file *stream = mem_fileopen ();
> struct command_line *iter;
>
> - make_cleanup_ui_file_delete (stream);
> for (iter = cmd->body_list[0]; iter; iter = iter->next)
> {
> - fputs_unfiltered (iter->line, stream);
> - fputs_unfiltered ("\n", stream);
> + input_buf.puts (iter->line);
> + input_buf.puts ("\n");
> }
>
> - input_buf = ui_file_as_string (stream);
> input = input_buf.c_str ();
> }
> else if (cmd_string != NULL)
> diff --git a/gdb/compile/compile.h b/gdb/compile/compile.h
> index a46ee6d..7438599 100644
> --- a/gdb/compile/compile.h
> +++ b/gdb/compile/compile.h
> @@ -55,7 +55,7 @@ extern void eval_compile_command (struct command_line *cmd,
> PER_CU is the per-CU object used for looking up various other
> things. */
>
> -extern void compile_dwarf_expr_to_c (struct ui_file *stream,
> +extern void compile_dwarf_expr_to_c (string_file &stream,
> const char *result_name,
> struct symbol *sym,
> CORE_ADDR pc,
> @@ -90,7 +90,7 @@ extern void compile_dwarf_expr_to_c (struct ui_file *stream,
> PER_CU is the per-CU object used for looking up various other
> things. */
>
> -extern void compile_dwarf_bounds_to_c (struct ui_file *stream,
> +extern void compile_dwarf_bounds_to_c (string_file &stream,
> const char *result_name,
> const struct dynamic_prop *prop,
> struct symbol *sym, CORE_ADDR pc,
> diff --git a/gdb/cp-support.c b/gdb/cp-support.c
> index f4498f1..1b0900e 100644
> --- a/gdb/cp-support.c
> +++ b/gdb/cp-support.c
> @@ -192,7 +192,6 @@ inspect_type (struct demangle_parse_info *info,
> int is_anon;
> struct type *type;
> std::unique_ptr<demangle_parse_info> i;
> - struct ui_file *buf;
>
> /* Get the real type of the typedef. */
> type = check_typedef (otype);
> @@ -228,23 +227,21 @@ inspect_type (struct demangle_parse_info *info,
> type = last;
> }
>
> - buf = mem_fileopen ();
> + string_file buf;
> TRY
> - {
> - type_print (type, "", buf, -1);
> - }
> -
> + {
> + type_print (type, "", &buf, -1);
> + }
> /* If type_print threw an exception, there is little point
> in continuing, so just bow out gracefully. */
> CATCH (except, RETURN_MASK_ERROR)
> {
> - ui_file_delete (buf);
> return 0;
> }
> END_CATCH
>
> - name = ui_file_obsavestring (buf, &info->obstack, &len);
> - ui_file_delete (buf);
> + len = buf.size ();
> + name = (char *) obstack_copy0 (&info->obstack, buf.c_str (), len);
>
> /* Turn the result into a new tree. Note that this
> tree will contain pointers into NAME, so NAME cannot
> @@ -301,7 +298,7 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info,
> {
> long len;
> char *name;
> - struct ui_file *buf = mem_fileopen ();
> + string_file buf;
> struct demangle_component *comp = ret_comp;
>
> /* Walk each node of the qualified name, reconstructing the name of
> @@ -315,9 +312,9 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info,
> {
> struct demangle_component newobj;
>
> - ui_file_write (buf, d_left (comp)->u.s_name.s,
> - d_left (comp)->u.s_name.len);
> - name = ui_file_obsavestring (buf, &info->obstack, &len);
> + buf.write (d_left (comp)->u.s_name.s, d_left (comp)->u.s_name.len);
> + len = buf.size ();
> + name = (char *) obstack_copy0 (&info->obstack, buf.c_str (), len);
> newobj.type = DEMANGLE_COMPONENT_NAME;
> newobj.u.s_name.s = name;
> newobj.u.s_name.len = len;
> @@ -330,12 +327,11 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info,
> string and replace the top DEMANGLE_COMPONENT_QUAL_NAME
> node. */
>
> - ui_file_rewind (buf);
> + buf.clear ();
> n = cp_comp_to_string (&newobj, 100);
> if (n == NULL)
> {
> /* If something went astray, abort typedef substitutions. */
> - ui_file_delete (buf);
> return;
> }
>
> @@ -360,14 +356,13 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info,
> if (name == NULL)
> {
> /* If something went astray, abort typedef substitutions. */
> - ui_file_delete (buf);
> return;
> }
> - fputs_unfiltered (name, buf);
> + buf.puts (name);
> xfree (name);
> }
>
> - ui_file_write (buf, "::", 2);
> + buf.write ("::", 2);
> comp = d_right (comp);
> }
>
> @@ -377,8 +372,9 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info,
>
> if (comp->type == DEMANGLE_COMPONENT_NAME)
> {
> - ui_file_write (buf, comp->u.s_name.s, comp->u.s_name.len);
> - name = ui_file_obsavestring (buf, &info->obstack, &len);
> + buf.write (comp->u.s_name.s, comp->u.s_name.len);
> + len = buf.size ();
> + name = (char *) obstack_copy0 (&info->obstack, buf.c_str (), len);
>
> /* Replace the top (DEMANGLE_COMPONENT_QUAL_NAME) node
> with a DEMANGLE_COMPONENT_NAME node containing the whole
> @@ -390,8 +386,6 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info,
> }
> else
> replace_typedefs (info, comp, finder, data);
> -
> - ui_file_delete (buf);
> }
>
>
> diff --git a/gdb/disasm-selftests.c b/gdb/disasm-selftests.c
> index c89c5ed..7d0b006 100644
> --- a/gdb/disasm-selftests.c
> +++ b/gdb/disasm-selftests.c
> @@ -113,7 +113,7 @@ print_one_insn_test (struct gdbarch *gdbarch)
> const gdb_byte *insn,
> size_t len)
> : gdb_disassembler (gdbarch,
> - (verbose ? gdb_stdout : null_stream ()),
> + (verbose ? gdb_stdout : &null_stream),
> gdb_disassembler_test::read_memory),
> m_insn (insn), m_len (len)
> {
> @@ -173,7 +173,7 @@ memory_error_test (struct gdbarch *gdbarch)
> {
> public:
> gdb_disassembler_test (struct gdbarch *gdbarch)
> - : gdb_disassembler (gdbarch, null_stream (),
> + : gdb_disassembler (gdbarch, &null_stream,
> gdb_disassembler_test::read_memory)
> {
> }
> diff --git a/gdb/disasm.c b/gdb/disasm.c
> index 59ebef0..92bca99 100644
> --- a/gdb/disasm.c
> +++ b/gdb/disasm.c
> @@ -248,8 +248,7 @@ gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
> if (name != NULL)
> xfree (name);
>
> - struct ui_file *stb = mem_fileopen ();
> - make_cleanup_ui_file_delete (stb);
> + string_file stb;
>
> if (flags & DISASSEMBLY_RAW_INSN)
> {
> @@ -260,28 +259,23 @@ gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
>
> /* Build the opcodes using a temporary stream so we can
> write them out in a single go for the MI. */
> - struct ui_file *opcode_stream = mem_fileopen ();
> - struct cleanup *cleanups =
> - make_cleanup_ui_file_delete (opcode_stream);
> + string_file opcode_stream;
>
> - size = gdb_print_insn (gdbarch, pc, stb, NULL);
> + size = gdb_print_insn (gdbarch, pc, &stb, NULL);
> end_pc = pc + size;
>
> for (;pc < end_pc; ++pc)
> {
> read_code (pc, &data, 1);
> - fprintf_filtered (opcode_stream, "%s%02x",
> - spacer, (unsigned) data);
> + opcode_stream.printf ("%s%02x", spacer, (unsigned) data);
> spacer = " ";
> }
>
> uiout->field_stream ("opcodes", opcode_stream);
> uiout->text ("\t");
> -
> - do_cleanups (cleanups);
> }
> else
> - size = gdb_print_insn (gdbarch, pc, stb, NULL);
> + size = gdb_print_insn (gdbarch, pc, &stb, NULL);
>
> uiout->field_stream ("inst", stb);
> do_cleanups (ui_out_chain);
> @@ -856,7 +850,7 @@ gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
> int
> gdb_insn_length (struct gdbarch *gdbarch, CORE_ADDR addr)
> {
> - return gdb_print_insn (gdbarch, addr, null_stream (), NULL);
> + return gdb_print_insn (gdbarch, addr, &null_stream, NULL);
> }
>
> /* fprintf-function for gdb_buffered_insn_length. This function is a
> diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c
> index e81d8e9..2a84b28 100644
> --- a/gdb/dummy-frame.c
> +++ b/gdb/dummy-frame.c
> @@ -409,14 +409,11 @@ maintenance_print_dummy_frames (char *args, int from_tty)
> fprint_dummy_frames (gdb_stdout);
> else
> {
> - struct cleanup *cleanups;
> - struct ui_file *file = gdb_fopen (args, "w");
> + stdio_file file;
>
> - if (file == NULL)
> + if (!file.open (args, "w"))
> perror_with_name (_("maintenance print dummy-frames"));
> - cleanups = make_cleanup_ui_file_delete (file);
> - fprint_dummy_frames (file);
> - do_cleanups (cleanups);
> + fprint_dummy_frames (&file);
> }
> }
>
> diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
> index 7fca76b..0357e51 100644
> --- a/gdb/dwarf2loc.c
> +++ b/gdb/dwarf2loc.c
> @@ -2645,7 +2645,7 @@ dwarf2_evaluate_property (const struct dynamic_prop *prop,
> /* See dwarf2loc.h. */
>
> void
> -dwarf2_compile_property_to_c (struct ui_file *stream,
> +dwarf2_compile_property_to_c (string_file &stream,
> const char *result_name,
> struct gdbarch *gdbarch,
> unsigned char *registers_used,
> @@ -4361,7 +4361,7 @@ locexpr_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
> /* symbol_computed_ops 'generate_c_location' method. */
>
> static void
> -locexpr_generate_c_location (struct symbol *sym, struct ui_file *stream,
> +locexpr_generate_c_location (struct symbol *sym, string_file &stream,
> struct gdbarch *gdbarch,
> unsigned char *registers_used,
> CORE_ADDR pc, const char *result_name)
> @@ -4571,7 +4571,7 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
> /* symbol_computed_ops 'generate_c_location' method. */
>
> static void
> -loclist_generate_c_location (struct symbol *sym, struct ui_file *stream,
> +loclist_generate_c_location (struct symbol *sym, string_file &stream,
> struct gdbarch *gdbarch,
> unsigned char *registers_used,
> CORE_ADDR pc, const char *result_name)
> diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h
> index 24e660c..d6cdbd2 100644
> --- a/gdb/dwarf2loc.h
> +++ b/gdb/dwarf2loc.h
> @@ -151,7 +151,7 @@ int dwarf2_evaluate_property (const struct dynamic_prop *prop,
> evaluated.
> SYM the originating symbol, used for error reporting. */
>
> -void dwarf2_compile_property_to_c (struct ui_file *stream,
> +void dwarf2_compile_property_to_c (string_file &stream,
> const char *result_name,
> struct gdbarch *gdbarch,
> unsigned char *registers_used,
> diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
> index b5dc510..774ed73 100644
> --- a/gdb/dwarf2read.c
> +++ b/gdb/dwarf2read.c
> @@ -8409,17 +8409,6 @@ die_needs_namespace (struct die_info *die, struct dwarf2_cu *cu)
> }
> }
>
> -/* Retrieve the last character from a mem_file. */
> -
> -static void
> -do_ui_file_peek_last (void *object, const char *buffer, long length)
> -{
> - char *last_char_p = (char *) object;
> -
> - if (length > 0)
> - *last_char_p = buffer[length - 1];
> -}
> -
> /* Compute the fully qualified name of DIE in CU. If PHYSNAME is nonzero,
> compute the physname for the object, which include a method's:
> - formal parameters (C++),
> @@ -8478,21 +8467,21 @@ dwarf2_compute_name (const char *name,
> {
> long length;
> const char *prefix;
> - struct ui_file *buf;
> const char *canonical_name = NULL;
>
> + string_file buf;
> +
> prefix = determine_prefix (die, cu);
> - buf = mem_fileopen ();
> if (*prefix != '\0')
> {
> char *prefixed_name = typename_concat (NULL, prefix, name,
> physname, cu);
>
> - fputs_unfiltered (prefixed_name, buf);
> + buf.puts (prefixed_name);
> xfree (prefixed_name);
> }
> else
> - fputs_unfiltered (name, buf);
> + buf.puts (name);
>
> /* Template parameters may be specified in the DIE's DW_AT_name, or
> as children with DW_TAG_template_type_param or
> @@ -8537,25 +8526,25 @@ dwarf2_compute_name (const char *name,
>
> if (first)
> {
> - fputs_unfiltered ("<", buf);
> + buf.puts ("<");
> first = 0;
> }
> else
> - fputs_unfiltered (", ", buf);
> + buf.puts (", ");
>
> attr = dwarf2_attr (child, DW_AT_type, cu);
> if (attr == NULL)
> {
> complaint (&symfile_complaints,
> _("template parameter missing DW_AT_type"));
> - fputs_unfiltered ("UNKNOWN_TYPE", buf);
> + buf.puts ("UNKNOWN_TYPE");
> continue;
> }
> type = die_type (child, cu);
>
> if (child->tag == DW_TAG_template_type_param)
> {
> - c_print_type (type, "", buf, -1, 0, &type_print_raw_options);
> + c_print_type (type, "", &buf, -1, 0, &type_print_raw_options);
> continue;
> }
>
> @@ -8565,7 +8554,7 @@ dwarf2_compute_name (const char *name,
> complaint (&symfile_complaints,
> _("template parameter missing "
> "DW_AT_const_value"));
> - fputs_unfiltered ("UNKNOWN_VALUE", buf);
> + buf.puts ("UNKNOWN_VALUE");
> continue;
> }
>
> @@ -8576,7 +8565,7 @@ dwarf2_compute_name (const char *name,
> if (TYPE_NOSIGN (type))
> /* GDB prints characters as NUMBER 'CHAR'. If that's
> changed, this can use value_print instead. */
> - c_printchar (value, type, buf);
> + c_printchar (value, type, &buf);
> else
> {
> struct value_print_options opts;
> @@ -8599,7 +8588,7 @@ dwarf2_compute_name (const char *name,
> the radix. */
> get_formatted_print_options (&opts, 'd');
> opts.raw = 1;
> - value_print (v, buf, &opts);
> + value_print (v, &buf, &opts);
> release_value (v);
> value_free (v);
> }
> @@ -8611,12 +8600,10 @@ dwarf2_compute_name (const char *name,
> {
> /* Close the argument list, with a space if necessary
> (nested templates). */
> - char last_char = '\0';
> - ui_file_put (buf, do_ui_file_peek_last, &last_char);
> - if (last_char == '>')
> - fputs_unfiltered (" >", buf);
> + if (!buf.empty () && buf.string ().back () == '>')
> + buf.puts (" >");
> else
> - fputs_unfiltered (">", buf);
> + buf.puts (">");
> }
> }
>
> @@ -8628,7 +8615,7 @@ dwarf2_compute_name (const char *name,
> {
> struct type *type = read_type_die (die, cu);
>
> - c_type_print_args (type, buf, 1, cu->language,
> + c_type_print_args (type, &buf, 1, cu->language,
> &type_print_raw_options);
>
> if (cu->language == language_cplus)
> @@ -8643,12 +8630,11 @@ dwarf2_compute_name (const char *name,
> && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_PTR
> && TYPE_CONST (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type,
> 0))))
> - fputs_unfiltered (" const", buf);
> + buf.puts (" const");
> }
> }
>
> - std::string intermediate_name = ui_file_as_string (buf);
> - ui_file_delete (buf);
> + const std::string &intermediate_name = buf.string ();
>
> if (cu->language == language_cplus)
> canonical_name
> diff --git a/gdb/event-top.c b/gdb/event-top.c
> index ae4f704..5d8d077 100644
> --- a/gdb/event-top.c
> +++ b/gdb/event-top.c
> @@ -1237,8 +1237,8 @@ gdb_setup_readline (int editing)
> mess it up here. The sync stuff should really go away over
> time. */
> if (!batch_silent)
> - gdb_stdout = stdio_fileopen (ui->outstream);
> - gdb_stderr = stderr_fileopen (ui->errstream);
> + gdb_stdout = new stdio_file (ui->outstream);
> + gdb_stderr = new stderr_file (ui->errstream);
> gdb_stdlog = gdb_stderr; /* for moment */
> gdb_stdtarg = gdb_stderr; /* for moment */
> gdb_stdtargerr = gdb_stderr; /* for moment */
> diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
> index 8bd0c19..266f2e9 100644
> --- a/gdb/gdbarch.c
> +++ b/gdb/gdbarch.c
> @@ -497,17 +497,13 @@ gdbarch_free (struct gdbarch *arch)
> static void
> verify_gdbarch (struct gdbarch *gdbarch)
> {
> - struct ui_file *log;
> - struct cleanup *cleanups;
> - long length;
> + string_file log;
>
> - log = mem_fileopen ();
> - cleanups = make_cleanup_ui_file_delete (log);
> /* fundamental */
> if (gdbarch->byte_order == BFD_ENDIAN_UNKNOWN)
> - fprintf_unfiltered (log, "\n\tbyte-order");
> + log.puts ("\n\tbyte-order");
> if (gdbarch->bfd_arch_info == NULL)
> - fprintf_unfiltered (log, "\n\tbfd_arch_info");
> + log.puts ("\n\tbfd_arch_info");
> /* Check those that need to be defined for the given multi-arch level. */
> /* Skip verify of bits_big_endian, invalid_p == 0 */
> /* Skip verify of short_bit, invalid_p == 0 */
> @@ -542,7 +538,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
> /* Skip verify of pseudo_register_read_value, has predicate. */
> /* Skip verify of pseudo_register_write, has predicate. */
> if (gdbarch->num_regs == -1)
> - fprintf_unfiltered (log, "\n\tnum_regs");
> + log.puts ("\n\tnum_regs");
> /* Skip verify of num_pseudo_regs, invalid_p == 0 */
> /* Skip verify of ax_pseudo_register_collect, has predicate. */
> /* Skip verify of ax_pseudo_register_push_stack, has predicate. */
> @@ -556,7 +552,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
> /* Skip verify of sdb_reg_to_regnum, invalid_p == 0 */
> /* Skip verify of dwarf2_reg_to_regnum, invalid_p == 0 */
> if (gdbarch->register_name == 0)
> - fprintf_unfiltered (log, "\n\tregister_name");
> + log.puts ("\n\tregister_name");
> /* Skip verify of register_type, has predicate. */
> /* Skip verify of dummy_id, has predicate. */
> /* Skip verify of deprecated_fp_regnum, invalid_p == 0 */
> @@ -579,14 +575,14 @@ verify_gdbarch (struct gdbarch *gdbarch)
> /* Skip verify of return_value, has predicate. */
> /* Skip verify of return_in_first_hidden_param_p, invalid_p == 0 */
> if (gdbarch->skip_prologue == 0)
> - fprintf_unfiltered (log, "\n\tskip_prologue");
> + log.puts ("\n\tskip_prologue");
> /* Skip verify of skip_main_prologue, has predicate. */
> /* Skip verify of skip_entrypoint, has predicate. */
> if (gdbarch->inner_than == 0)
> - fprintf_unfiltered (log, "\n\tinner_than");
> + log.puts ("\n\tinner_than");
> /* Skip verify of breakpoint_from_pc, invalid_p == 0 */
> if (gdbarch->breakpoint_kind_from_pc == 0)
> - fprintf_unfiltered (log, "\n\tbreakpoint_kind_from_pc");
> + log.puts ("\n\tbreakpoint_kind_from_pc");
> /* Skip verify of sw_breakpoint_from_kind, invalid_p == 0 */
> /* Skip verify of breakpoint_kind_from_current_state, invalid_p == 0 */
> /* Skip verify of adjust_breakpoint_address, has predicate. */
> @@ -607,7 +603,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
> /* Skip verify of software_single_step, has predicate. */
> /* Skip verify of single_step_through_delay, has predicate. */
> if (gdbarch->print_insn == 0)
> - fprintf_unfiltered (log, "\n\tprint_insn");
> + log.puts ("\n\tprint_insn");
> /* Skip verify of skip_trampoline_code, invalid_p == 0 */
> /* Skip verify of skip_solib_resolver, invalid_p == 0 */
> /* Skip verify of in_solib_return_trampoline, invalid_p == 0 */
> @@ -641,9 +637,9 @@ verify_gdbarch (struct gdbarch *gdbarch)
> /* Skip verify of displaced_step_hw_singlestep, invalid_p == 0 */
> /* Skip verify of displaced_step_fixup, has predicate. */
> if ((! gdbarch->displaced_step_free_closure) != (! gdbarch->displaced_step_copy_insn))
> - fprintf_unfiltered (log, "\n\tdisplaced_step_free_closure");
> + log.puts ("\n\tdisplaced_step_free_closure");
> if ((! gdbarch->displaced_step_location) != (! gdbarch->displaced_step_copy_insn))
> - fprintf_unfiltered (log, "\n\tdisplaced_step_location");
> + log.puts ("\n\tdisplaced_step_location");
> /* Skip verify of relocate_instruction, has predicate. */
> /* Skip verify of overlay_update, has predicate. */
> /* Skip verify of core_read_description, has predicate. */
> @@ -696,12 +692,10 @@ verify_gdbarch (struct gdbarch *gdbarch)
> /* Skip verify of gcc_target_options, invalid_p == 0 */
> /* Skip verify of gnu_triplet_regexp, invalid_p == 0 */
> /* Skip verify of addressable_memory_unit_size, invalid_p == 0 */
> - std::string buf = ui_file_as_string (log);
> - if (!buf.empty ())
> + if (!log.empty ())
> internal_error (__FILE__, __LINE__,
> _("verify_gdbarch: the following are invalid ...%s"),
> - buf.c_str ());
> - do_cleanups (cleanups);
> + log.c_str ());
> }
>
>
> diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
> index 2958cab..54549b6 100755
> --- a/gdb/gdbarch.sh
> +++ b/gdb/gdbarch.sh
> @@ -1875,17 +1875,13 @@ cat <<EOF
> static void
> verify_gdbarch (struct gdbarch *gdbarch)
> {
> - struct ui_file *log;
> - struct cleanup *cleanups;
> - long length;
> + string_file log;
>
> - log = mem_fileopen ();
> - cleanups = make_cleanup_ui_file_delete (log);
> /* fundamental */
> if (gdbarch->byte_order == BFD_ENDIAN_UNKNOWN)
> - fprintf_unfiltered (log, "\n\tbyte-order");
> + log.puts ("\n\tbyte-order");
> if (gdbarch->bfd_arch_info == NULL)
> - fprintf_unfiltered (log, "\n\tbfd_arch_info");
> + log.puts ("\n\tbfd_arch_info");
> /* Check those that need to be defined for the given multi-arch level. */
> EOF
> function_list | while do_read
> @@ -1914,21 +1910,19 @@ do
> elif [ -n "${invalid_p}" ]
> then
> printf " if (${invalid_p})\n"
> - printf " fprintf_unfiltered (log, \"\\\\n\\\\t${function}\");\n"
> + printf " log.puts (\"\\\\n\\\\t${function}\");\n"
> elif [ -n "${predefault}" ]
> then
> printf " if (gdbarch->${function} == ${predefault})\n"
> - printf " fprintf_unfiltered (log, \"\\\\n\\\\t${function}\");\n"
> + printf " log.puts (\"\\\\n\\\\t${function}\");\n"
> fi
> fi
> done
> cat <<EOF
> - std::string buf = ui_file_as_string (log);
> - if (!buf.empty ())
> + if (!log.empty ())
> internal_error (__FILE__, __LINE__,
> _("verify_gdbarch: the following are invalid ...%s"),
> - buf.c_str ());
> - do_cleanups (cleanups);
> + log.c_str ());
> }
> EOF
>
> diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
> index 21cc005..5e5db27 100644
> --- a/gdb/gdbtypes.c
> +++ b/gdb/gdbtypes.c
> @@ -2459,7 +2459,7 @@ safe_parse_type (struct gdbarch *gdbarch, char *p, int length)
>
> /* Suppress error messages. */
> saved_gdb_stderr = gdb_stderr;
> - gdb_stderr = ui_file_new ();
> + gdb_stderr = &null_stream;
>
> /* Call parse_and_eval_type() without fear of longjmp()s. */
> TRY
> @@ -2473,7 +2473,6 @@ safe_parse_type (struct gdbarch *gdbarch, char *p, int length)
> END_CATCH
>
> /* Stop suppressing error messages. */
> - ui_file_delete (gdb_stderr);
> gdb_stderr = saved_gdb_stderr;
>
> return type;
> diff --git a/gdb/guile/scm-breakpoint.c b/gdb/guile/scm-breakpoint.c
> index b2e7c96..71cffbb 100644
> --- a/gdb/guile/scm-breakpoint.c
> +++ b/gdb/guile/scm-breakpoint.c
> @@ -978,8 +978,6 @@ gdbscm_breakpoint_commands (SCM self)
> = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
> struct breakpoint *bp;
> long length;
> - struct ui_file *string_file;
> - struct cleanup *chain;
> SCM result;
>
> bp = bp_smob->bp;
> @@ -987,10 +985,9 @@ gdbscm_breakpoint_commands (SCM self)
> if (bp->commands == NULL)
> return SCM_BOOL_F;
>
> - string_file = mem_fileopen ();
> - chain = make_cleanup_ui_file_delete (string_file);
> + string_file buf;
>
> - current_uiout->redirect (string_file);
> + current_uiout->redirect (&buf);
> TRY
> {
> print_command_lines (current_uiout, breakpoint_commands (bp), 0);
> @@ -998,15 +995,12 @@ gdbscm_breakpoint_commands (SCM self)
> current_uiout->redirect (NULL);
> CATCH (except, RETURN_MASK_ALL)
> {
> - do_cleanups (chain);
> gdbscm_throw_gdb_exception (except);
> }
> END_CATCH
>
> - std::string cmdstr = ui_file_as_string (string_file);
> - result = gdbscm_scm_from_c_string (cmdstr.c_str ());
> + result = gdbscm_scm_from_c_string (buf.c_str ());
>
> - do_cleanups (chain);
> return result;
> }
>
> diff --git a/gdb/guile/scm-disasm.c b/gdb/guile/scm-disasm.c
> index 25cae5a..f8cbad6 100644
> --- a/gdb/guile/scm-disasm.c
> +++ b/gdb/guile/scm-disasm.c
> @@ -146,7 +146,7 @@ gdbscm_disassembler::gdbscm_disassembler (struct gdbarch *gdbarch,
> static int
> gdbscm_print_insn_from_port (struct gdbarch *gdbarch,
> SCM port, ULONGEST offset, CORE_ADDR memaddr,
> - struct ui_file *stream, int *branch_delay_insns)
> + string_file *stream, int *branch_delay_insns)
> {
> gdbscm_disassembler di (gdbarch, stream, port, offset);
>
> @@ -245,33 +245,29 @@ gdbscm_arch_disassemble (SCM self, SCM start_scm, SCM rest)
> for (pc = start, i = 0; pc <= end && i < count; )
> {
> int insn_len = 0;
> - struct ui_file *memfile = mem_fileopen ();
> - struct cleanup *cleanups = make_cleanup_ui_file_delete (memfile);
> + string_file buf;
>
> TRY
> {
> if (using_port)
> {
> insn_len = gdbscm_print_insn_from_port (gdbarch, port, offset,
> - pc, memfile, NULL);
> + pc, &buf, NULL);
> }
> else
> - insn_len = gdb_print_insn (gdbarch, pc, memfile, NULL);
> + insn_len = gdb_print_insn (gdbarch, pc, &buf, NULL);
> }
> CATCH (except, RETURN_MASK_ALL)
> {
> - GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS (except, cleanups);
> + GDBSCM_HANDLE_GDB_EXCEPTION (except);
> }
> END_CATCH
>
> - std::string as = ui_file_as_string (memfile);
> -
> - result = scm_cons (dascm_make_insn (pc, as.c_str (), insn_len),
> + result = scm_cons (dascm_make_insn (pc, buf.c_str (), insn_len),
> result);
>
> pc += insn_len;
> i++;
> - do_cleanups (cleanups);
> }
>
> return scm_reverse_x (result, SCM_EOL);
> diff --git a/gdb/guile/scm-frame.c b/gdb/guile/scm-frame.c
> index 9b5159e..994f92d 100644
> --- a/gdb/guile/scm-frame.c
> +++ b/gdb/guile/scm-frame.c
> @@ -156,15 +156,12 @@ static int
> frscm_print_frame_smob (SCM self, SCM port, scm_print_state *pstate)
> {
> frame_smob *f_smob = (frame_smob *) SCM_SMOB_DATA (self);
> - struct ui_file *strfile;
>
> gdbscm_printf (port, "#<%s ", frame_smob_name);
>
> - strfile = mem_fileopen ();
> - fprint_frame_id (strfile, f_smob->frame_id);
> - std::string s = ui_file_as_string (strfile);
> - gdbscm_printf (port, "%s", s.c_str ());
> - ui_file_delete (strfile);
> + string_file strfile;
> + fprint_frame_id (&strfile, f_smob->frame_id);
> + gdbscm_printf (port, "%s", strfile.c_str ());
>
> scm_puts (">", port);
>
> diff --git a/gdb/guile/scm-ports.c b/gdb/guile/scm-ports.c
> index 4a1c864..fb3a47b 100644
> --- a/gdb/guile/scm-ports.c
> +++ b/gdb/guile/scm-ports.c
> @@ -37,11 +37,18 @@
>
> /* A ui-file for sending output to Guile. */
>
> -typedef struct
> +class ioscm_file_port : public ui_file
> {
> - int *magic;
> - SCM port;
> -} ioscm_file_port;
> +public:
> + /* Return a ui_file that writes to PORT. */
> + explicit ioscm_file_port (SCM port);
> +
> + void flush () override;
> + void write (const char *buf, long length_buf) override;
> +
> +private:
> + SCM m_port;
> +};
>
> /* Data for a memory port. */
>
> @@ -431,74 +438,21 @@ gdbscm_error_port (void)
> \f
> /* Support for sending GDB I/O to Guile ports. */
>
> -static void
> -ioscm_file_port_delete (struct ui_file *file)
> -{
> - ioscm_file_port *stream = (ioscm_file_port *) ui_file_data (file);
> -
> - if (stream->magic != &file_port_magic)
> - internal_error (__FILE__, __LINE__,
> - _("ioscm_file_port_delete: bad magic number"));
> - xfree (stream);
> -}
> -
> -static void
> -ioscm_file_port_rewind (struct ui_file *file)
> -{
> - ioscm_file_port *stream = (ioscm_file_port *) ui_file_data (file);
> -
> - if (stream->magic != &file_port_magic)
> - internal_error (__FILE__, __LINE__,
> - _("ioscm_file_port_rewind: bad magic number"));
> -
> - scm_truncate_file (stream->port, 0);
> -}
> +ioscm_file_port::ioscm_file_port (SCM port)
> + : m_port (port)
> +{}
>
> -static void
> -ioscm_file_port_put (struct ui_file *file,
> - ui_file_put_method_ftype *write,
> - void *dest)
> +void
> +ioscm_file_port::flush ()
> {
> - ioscm_file_port *stream = (ioscm_file_port *) ui_file_data (file);
> -
> - if (stream->magic != &file_port_magic)
> - internal_error (__FILE__, __LINE__,
> - _("ioscm_file_port_put: bad magic number"));
> -
> - /* This function doesn't meld with ports very well. */
> }
>
> -static void
> -ioscm_file_port_write (struct ui_file *file,
> - const char *buffer,
> - long length_buffer)
> +void
> +ioscm_file_port::write (const char *buffer, long length_buffer)
> {
> - ioscm_file_port *stream = (ioscm_file_port *) ui_file_data (file);
> -
> - if (stream->magic != &file_port_magic)
> - internal_error (__FILE__, __LINE__,
> - _("ioscm_pot_file_write: bad magic number"));
> -
> - scm_c_write (stream->port, buffer, length_buffer);
> + scm_c_write (m_port, buffer, length_buffer);
> }
>
> -/* Return a ui_file that writes to PORT. */
> -
> -static struct ui_file *
> -ioscm_file_port_new (SCM port)
> -{
> - ioscm_file_port *stream = XCNEW (ioscm_file_port);
> - struct ui_file *file = ui_file_new ();
> -
> - set_ui_file_data (file, stream, ioscm_file_port_delete);
> - set_ui_file_rewind (file, ioscm_file_port_rewind);
> - set_ui_file_put (file, ioscm_file_port_put);
> - set_ui_file_write (file, ioscm_file_port_write);
> - stream->magic = &file_port_magic;
> - stream->port = port;
> -
> - return file;
> -}
> \f
> /* Helper routine for with-{output,error}-to-port. */
>
> @@ -506,7 +460,6 @@ static SCM
> ioscm_with_output_to_port_worker (SCM port, SCM thunk, enum oport oport,
> const char *func_name)
> {
> - struct ui_file *port_file;
> struct cleanup *cleanups;
> SCM result;
>
> @@ -520,21 +473,19 @@ ioscm_with_output_to_port_worker (SCM port, SCM thunk, enum oport oport,
> make_cleanup_restore_integer (¤t_ui->async);
> current_ui->async = 0;
>
> - port_file = ioscm_file_port_new (port);
> -
> - make_cleanup_ui_file_delete (port_file);
> + ui_file_up port_file (new ioscm_file_port (port));
>
> scoped_restore save_file = make_scoped_restore (oport == GDB_STDERR
> ? &gdb_stderr : &gdb_stdout);
>
> if (oport == GDB_STDERR)
> - gdb_stderr = port_file;
> + gdb_stderr = port_file.get ();
> else
> {
> - current_uiout->redirect (port_file);
> + current_uiout->redirect (port_file.get ());
> make_cleanup_ui_out_redirect_pop (current_uiout);
>
> - gdb_stdout = port_file;
> + gdb_stdout = port_file.get ();
> }
>
> result = gdbscm_safe_call_0 (thunk, NULL);
> diff --git a/gdb/guile/scm-type.c b/gdb/guile/scm-type.c
> index f5de011..42a8ad2 100644
> --- a/gdb/guile/scm-type.c
> +++ b/gdb/guile/scm-type.c
> @@ -107,18 +107,10 @@ tyscm_type_name (struct type *type)
> {
> TRY
> {
> - struct cleanup *old_chain;
> - struct ui_file *stb;
> + string_file stb;
>
> - stb = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (stb);
> -
> - LA_PRINT_TYPE (type, "", stb, -1, 0, &type_print_raw_options);
> -
> - std::string name = ui_file_as_string (stb);
> - do_cleanups (old_chain);
> -
> - return name;
> + LA_PRINT_TYPE (type, "", &stb, -1, 0, &type_print_raw_options);
> + return std::move (stb.string ());
> }
> CATCH (except, RETURN_MASK_ALL)
> {
> diff --git a/gdb/guile/scm-value.c b/gdb/guile/scm-value.c
> index b4f32b6..ebccfb6 100644
> --- a/gdb/guile/scm-value.c
> +++ b/gdb/guile/scm-value.c
> @@ -157,15 +157,10 @@ vlscm_print_value_smob (SCM self, SCM port, scm_print_state *pstate)
>
> TRY
> {
> - struct ui_file *stb = mem_fileopen ();
> - struct cleanup *old_chain = make_cleanup_ui_file_delete (stb);
> + string_file stb;
>
> - common_val_print (v_smob->value, stb, 0, &opts, current_language);
> -
> - std::string s = ui_file_as_string (stb);
> - scm_puts (s.c_str (), port);
> -
> - do_cleanups (old_chain);
> + common_val_print (v_smob->value, &stb, 0, &opts, current_language);
> + scm_puts (stb.c_str (), port);
> }
> CATCH (except, RETURN_MASK_ALL)
> {
> @@ -1277,21 +1272,15 @@ gdbscm_value_print (SCM self)
> = vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
> struct value *value = v_smob->value;
> struct value_print_options opts;
> - std::string s;
> - SCM result;
>
> get_user_print_options (&opts);
> opts.deref_ref = 0;
>
> + string_file stb;
> +
> TRY
> {
> - struct ui_file *stb = mem_fileopen ();
> - struct cleanup *old_chain = make_cleanup_ui_file_delete (stb);
> -
> - common_val_print (value, stb, 0, &opts, current_language);
> - s = ui_file_as_string (stb);
> -
> - do_cleanups (old_chain);
> + common_val_print (value, &stb, 0, &opts, current_language);
> }
> CATCH (except, RETURN_MASK_ALL)
> {
> @@ -1304,10 +1293,8 @@ gdbscm_value_print (SCM self)
> IWBN to use scm_take_locale_string here, but we'd have to temporarily
> override the default port conversion handler because contrary to
> documentation it doesn't necessarily free the input string. */
> - result = scm_from_stringn (s.c_str (), s.size (), host_charset (),
> - SCM_FAILED_CONVERSION_QUESTION_MARK);
> -
> - return result;
> + return scm_from_stringn (stb.c_str (), stb.size (), host_charset (),
> + SCM_FAILED_CONVERSION_QUESTION_MARK);
> }
> \f
> /* (parse-and-eval string) -> <gdb:value>
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index d761117..d836162 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -1670,21 +1670,19 @@ print_return_value_1 (struct ui_out *uiout, struct return_value_info *rv)
> if (rv->value != NULL)
> {
> struct value_print_options opts;
> - struct ui_file *stb;
> - struct cleanup *old_chain;
>
> /* Print it. */
> - stb = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (stb);
> uiout->text ("Value returned is ");
> uiout->field_fmt ("gdb-result-var", "$%d",
> - rv->value_history_index);
> + rv->value_history_index);
> uiout->text (" = ");
> get_no_prettyformat_print_options (&opts);
> - value_print (rv->value, stb, &opts);
> +
> + string_file stb;
> +
> + value_print (rv->value, &stb, &opts);
> uiout->field_stream ("return-value", stb);
> uiout->text ("\n");
> - do_cleanups (old_chain);
> }
> else
> {
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index 41f1fdd..1e5e9f1 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -3438,40 +3438,32 @@ print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
> const struct target_waitstatus *ws)
> {
> char *status_string = target_waitstatus_to_string (ws);
> - struct ui_file *tmp_stream = mem_fileopen ();
> + string_file stb;
>
> /* The text is split over several lines because it was getting too long.
> Call fprintf_unfiltered (gdb_stdlog) once so that the text is still
> output as a unit; we want only one timestamp printed if debug_timestamp
> is set. */
>
> - fprintf_unfiltered (tmp_stream,
> - "infrun: target_wait (%d.%ld.%ld",
> - ptid_get_pid (waiton_ptid),
> - ptid_get_lwp (waiton_ptid),
> - ptid_get_tid (waiton_ptid));
> + stb.printf ("infrun: target_wait (%d.%ld.%ld",
> + ptid_get_pid (waiton_ptid),
> + ptid_get_lwp (waiton_ptid),
> + ptid_get_tid (waiton_ptid));
> if (ptid_get_pid (waiton_ptid) != -1)
> - fprintf_unfiltered (tmp_stream,
> - " [%s]", target_pid_to_str (waiton_ptid));
> - fprintf_unfiltered (tmp_stream, ", status) =\n");
> - fprintf_unfiltered (tmp_stream,
> - "infrun: %d.%ld.%ld [%s],\n",
> - ptid_get_pid (result_ptid),
> - ptid_get_lwp (result_ptid),
> - ptid_get_tid (result_ptid),
> - target_pid_to_str (result_ptid));
> - fprintf_unfiltered (tmp_stream,
> - "infrun: %s\n",
> - status_string);
> -
> - std::string text = ui_file_as_string (tmp_stream);
> + stb.printf (" [%s]", target_pid_to_str (waiton_ptid));
> + stb.printf (", status) =\n");
> + stb.printf ("infrun: %d.%ld.%ld [%s],\n",
> + ptid_get_pid (result_ptid),
> + ptid_get_lwp (result_ptid),
> + ptid_get_tid (result_ptid),
> + target_pid_to_str (result_ptid));
> + stb.printf ("infrun: %s\n", status_string);
>
> /* This uses %s in part to handle %'s in the text, but also to avoid
> a gcc error: the format attribute requires a string literal. */
> - fprintf_unfiltered (gdb_stdlog, "%s", text.c_str ());
> + fprintf_unfiltered (gdb_stdlog, "%s", stb.c_str ());
>
> xfree (status_string);
> - ui_file_delete (tmp_stream);
> }
>
> /* Select a thread at random, out of those which are resumed and have
> diff --git a/gdb/language.c b/gdb/language.c
> index a40eb87..31c5c59 100644
> --- a/gdb/language.c
> +++ b/gdb/language.c
> @@ -539,9 +539,6 @@ add_language (const struct language_defn *lang)
> static const char **language_names = NULL;
> /* For the "help set language" command. */
>
> - int i;
> - struct ui_file *tmp_stream;
> -
> if (lang->la_magic != LANG_MAGIC)
> {
> fprintf_unfiltered (gdb_stderr,
> @@ -569,9 +566,9 @@ add_language (const struct language_defn *lang)
> language_names = XRESIZEVEC (const char *, language_names,
> languages_size + 1);
>
> - for (i = 0; i < languages_size; ++i)
> + for (int i = 0; i < languages_size; ++i)
> language_names[i] = languages[i]->la_name;
> - language_names[i] = NULL;
> + language_names[languages_size] = NULL;
>
> /* Add the filename extensions. */
> if (lang->la_filename_extensions != NULL)
> @@ -584,37 +581,32 @@ add_language (const struct language_defn *lang)
> }
>
> /* Build the "help set language" docs. */
> - tmp_stream = mem_fileopen ();
> + string_file doc;
>
> - fprintf_unfiltered (tmp_stream,
> - _("Set the current source language.\n"
> - "The currently understood settings are:\n\nlocal or "
> - "auto Automatic setting based on source file\n"));
> + doc.printf (_("Set the current source language.\n"
> + "The currently understood settings are:\n\nlocal or "
> + "auto Automatic setting based on source file\n"));
>
> - for (i = 0; i < languages_size; ++i)
> + for (int i = 0; i < languages_size; ++i)
> {
> /* Already dealt with these above. */
> if (languages[i]->la_language == language_unknown
> || languages[i]->la_language == language_auto)
> continue;
>
> - /* FIXME: i18n: for now assume that the human-readable name
> - is just a capitalization of the internal name. */
> - fprintf_unfiltered (tmp_stream, "%-16s Use the %c%s language\n",
> - languages[i]->la_name,
> - /* Capitalize first letter of language
> - name. */
> - toupper (languages[i]->la_name[0]),
> - languages[i]->la_name + 1);
> + /* FIXME: i18n: for now assume that the human-readable name is
> + just a capitalization of the internal name. */
> + doc.printf ("%-16s Use the %c%s language\n",
> + languages[i]->la_name,
> + /* Capitalize first letter of language name. */
> + toupper (languages[i]->la_name[0]),
> + languages[i]->la_name + 1);
> }
>
> - std::string language_set_doc = ui_file_as_string (tmp_stream);
> - ui_file_delete (tmp_stream);
> -
> add_setshow_enum_cmd ("language", class_support,
> (const char **) language_names,
> &language,
> - language_set_doc.c_str (),
> + doc.c_str (),
> _("Show the current source language."),
> NULL, set_language_command,
> show_language_command,
> diff --git a/gdb/location.c b/gdb/location.c
> index 37da6df..fbd09e2 100644
> --- a/gdb/location.c
> +++ b/gdb/location.c
> @@ -227,59 +227,52 @@ static char *
> explicit_to_string_internal (int as_linespec,
> const struct explicit_location *explicit_loc)
> {
> - struct ui_file *buf;
> - char space, *result;
> int need_space = 0;
> - struct cleanup *cleanup;
> -
> - space = as_linespec ? ':' : ' ';
> - buf = mem_fileopen ();
> - cleanup = make_cleanup_ui_file_delete (buf);
> + char space = as_linespec ? ':' : ' ';
> + string_file buf;
>
> if (explicit_loc->source_filename != NULL)
> {
> if (!as_linespec)
> - fputs_unfiltered ("-source ", buf);
> - fputs_unfiltered (explicit_loc->source_filename, buf);
> + buf.puts ("-source ");
> + buf.puts (explicit_loc->source_filename);
> need_space = 1;
> }
>
> if (explicit_loc->function_name != NULL)
> {
> if (need_space)
> - fputc_unfiltered (space, buf);
> + buf.putc (space);
> if (!as_linespec)
> - fputs_unfiltered ("-function ", buf);
> - fputs_unfiltered (explicit_loc->function_name, buf);
> + buf.puts ("-function ");
> + buf.puts (explicit_loc->function_name);
> need_space = 1;
> }
>
> if (explicit_loc->label_name != NULL)
> {
> if (need_space)
> - fputc_unfiltered (space, buf);
> + buf.putc (space);
> if (!as_linespec)
> - fputs_unfiltered ("-label ", buf);
> - fputs_unfiltered (explicit_loc->label_name, buf);
> + buf.puts ("-label ");
> + buf.puts (explicit_loc->label_name);
> need_space = 1;
> }
>
> if (explicit_loc->line_offset.sign != LINE_OFFSET_UNKNOWN)
> {
> if (need_space)
> - fputc_unfiltered (space, buf);
> + buf.putc (space);
> if (!as_linespec)
> - fputs_unfiltered ("-line ", buf);
> - fprintf_filtered (buf, "%s%d",
> - (explicit_loc->line_offset.sign == LINE_OFFSET_NONE ? ""
> - : (explicit_loc->line_offset.sign
> - == LINE_OFFSET_PLUS ? "+" : "-")),
> - explicit_loc->line_offset.offset);
> + buf.puts ("-line ");
> + buf.printf ("%s%d",
> + (explicit_loc->line_offset.sign == LINE_OFFSET_NONE ? ""
> + : (explicit_loc->line_offset.sign
> + == LINE_OFFSET_PLUS ? "+" : "-")),
> + explicit_loc->line_offset.offset);
> }
>
> - result = ui_file_xstrdup (buf, NULL);
> - do_cleanups (cleanup);
> - return result;
> + return xstrdup (buf.c_str ());
> }
>
> /* See description in location.h. */
> diff --git a/gdb/main.c b/gdb/main.c
> index f5387b6..30e27c2 100644
> --- a/gdb/main.c
> +++ b/gdb/main.c
> @@ -763,7 +763,7 @@ captured_main_1 (struct captured_main_args *context)
> break;
> case 'B':
> batch_flag = batch_silent = 1;
> - gdb_stdout = ui_file_new();
> + gdb_stdout = new null_file ();
> break;
> case 'D':
> if (optarg[0] == '\0')
> diff --git a/gdb/maint.c b/gdb/maint.c
> index 77b56af..d95f658 100644
> --- a/gdb/maint.c
> +++ b/gdb/maint.c
> @@ -403,14 +403,11 @@ maintenance_print_architecture (char *args, int from_tty)
> gdbarch_dump (gdbarch, gdb_stdout);
> else
> {
> - struct cleanup *cleanups;
> - struct ui_file *file = gdb_fopen (args, "w");
> + stdio_file file;
>
> - if (file == NULL)
> + if (!file.open (args, "w"))
> perror_with_name (_("maintenance print architecture"));
> - cleanups = make_cleanup_ui_file_delete (file);
> - gdbarch_dump (gdbarch, file);
> - do_cleanups (cleanups);
> + gdbarch_dump (gdbarch, &file);
> }
> }
>
> diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
> index efaf49d..acb44a2 100644
> --- a/gdb/mi/mi-cmd-stack.c
> +++ b/gdb/mi/mi-cmd-stack.c
> @@ -488,7 +488,6 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
> {
> struct cleanup *old_chain;
> struct ui_out *uiout = current_uiout;
> - struct ui_file *stb;
>
> gdb_assert (!arg->val || !arg->error);
> gdb_assert ((values == PRINT_NO_VALUES && arg->val == NULL
> @@ -511,15 +510,16 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
> TYPE_LENGTH (value_type (arg->val))))))
> return;
>
> - stb = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (stb);
> + old_chain = make_cleanup (null_cleanup, NULL);
>
> if (values != PRINT_NO_VALUES || what == all)
> make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
>
> - fputs_filtered (SYMBOL_PRINT_NAME (arg->sym), stb);
> + string_file stb;
> +
> + stb.puts (SYMBOL_PRINT_NAME (arg->sym));
> if (arg->entry_kind == print_entry_values_only)
> - fputs_filtered ("@entry", stb);
> + stb.puts ("@entry");
> uiout->field_stream ("name", stb);
>
> if (what == all && SYMBOL_IS_ARGUMENT (arg->sym))
> @@ -528,7 +528,7 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
> if (values == PRINT_SIMPLE_VALUES)
> {
> check_typedef (arg->sym->type);
> - type_print (arg->sym->type, "", stb, -1);
> + type_print (arg->sym->type, "", &stb, -1);
> uiout->field_stream ("type", stb);
> }
>
> @@ -546,7 +546,7 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
>
> get_no_prettyformat_print_options (&opts);
> opts.deref_ref = 1;
> - common_val_print (arg->val, stb, 0, &opts,
> + common_val_print (arg->val, &stb, 0, &opts,
> language_def (SYMBOL_LANGUAGE (arg->sym)));
> }
> CATCH (except, RETURN_MASK_ERROR)
> @@ -556,8 +556,7 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
> END_CATCH
> }
> if (error_message != NULL)
> - fprintf_filtered (stb, _("<error reading variable: %s>"),
> - error_message);
> + stb.printf (_("<error reading variable: %s>"), error_message);
> uiout->field_stream ("value", stb);
> }
>
> diff --git a/gdb/mi/mi-common.h b/gdb/mi/mi-common.h
> index 0d39cb7..e82b4a3 100644
> --- a/gdb/mi/mi-common.h
> +++ b/gdb/mi/mi-common.h
> @@ -19,6 +19,8 @@
> #ifndef MI_COMMON_H
> #define MI_COMMON_H
>
> +struct mi_console_file;
> +
> /* Represents the reason why GDB is sending an asynchronous command to
> the front end. NOTE: When modifing this, don't forget to update
> gdb.texinfo! */
> @@ -51,11 +53,11 @@ const char *async_reason_lookup (enum async_reply_reason reason);
> struct mi_interp
> {
> /* MI's output channels */
> - struct ui_file *out;
> - struct ui_file *err;
> - struct ui_file *log;
> - struct ui_file *targ;
> - struct ui_file *event_channel;
> + mi_console_file *out;
> + mi_console_file *err;
> + mi_console_file *log;
> + mi_console_file *targ;
> + mi_console_file *event_channel;
>
> /* Raw console output. */
> struct ui_file *raw_stdout;
> diff --git a/gdb/mi/mi-console.c b/gdb/mi/mi-console.c
> index afb5e94..7c1c2ac 100644
> --- a/gdb/mi/mi-console.c
> +++ b/gdb/mi/mi-console.c
> @@ -26,118 +26,56 @@
>
> #include "defs.h"
> #include "mi-console.h"
> -static ui_file_fputs_ftype mi_console_file_fputs;
> -static ui_file_flush_ftype mi_console_file_flush;
> -static ui_file_delete_ftype mi_console_file_delete;
> -
> -struct mi_console_file
> - {
> - int *magic;
> - struct ui_file *raw;
> - struct ui_file *buffer;
> - const char *prefix;
> - char quote;
> - };
> -
> -/* Use the address of this otherwise-unused global as a magic number
> - identifying this class of ui_file objects. */
> -static int mi_console_file_magic;
>
> /* Create a console that wraps the given output stream RAW with the
> string PREFIX and quoting it with QUOTE. */
>
> -struct ui_file *
> -mi_console_file_new (struct ui_file *raw, const char *prefix, char quote)
> -{
> - struct ui_file *ui_file = ui_file_new ();
> - struct mi_console_file *mi_console = XNEW (struct mi_console_file);
> -
> - mi_console->magic = &mi_console_file_magic;
> - mi_console->raw = raw;
> - mi_console->buffer = mem_fileopen ();
> - mi_console->prefix = prefix;
> - mi_console->quote = quote;
> - set_ui_file_fputs (ui_file, mi_console_file_fputs);
> - set_ui_file_flush (ui_file, mi_console_file_flush);
> - set_ui_file_data (ui_file, mi_console, mi_console_file_delete);
> -
> - return ui_file;
> -}
> -
> -static void
> -mi_console_file_delete (struct ui_file *file)
> -{
> - struct mi_console_file *mi_console
> - = (struct mi_console_file *) ui_file_data (file);
> -
> - if (mi_console->magic != &mi_console_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("mi_console_file_delete: bad magic number"));
> +mi_console_file::mi_console_file (ui_file *raw, const char *prefix, char quote)
> + : m_raw (raw),
> + m_prefix (prefix),
> + m_quote (quote)
> +{}
>
> - xfree (mi_console);
> -}
> -
> -static void
> -mi_console_file_fputs (const char *buf, struct ui_file *file)
> +void
> +mi_console_file::write (const char *buf, long length_buf)
> {
> - struct mi_console_file *mi_console
> - = (struct mi_console_file *) ui_file_data (file);
> -
> - if (mi_console->magic != &mi_console_file_magic)
> - internal_error (__FILE__, __LINE__,
> - "mi_console_file_fputs: bad magic number");
> -
> + size_t prev_size = m_buffer.size ();
> /* Append the text to our internal buffer. */
> - fputs_unfiltered (buf, mi_console->buffer);
> - /* Flush when an embedded newline is present anywhere in the buffer. */
> - if (strchr (buf, '\n') != NULL)
> - gdb_flush (file);
> + m_buffer.write (buf, length_buf);
> + /* Flush when an embedded newline is present anywhere in the
> + buffer. */
> + if (strchr (m_buffer.c_str () + prev_size, '\n') != NULL)
> + this->flush ();
> }
>
> -/* Transform a byte sequence into a console output packet. */
> -
> -static void
> -mi_console_raw_packet (void *data, const char *buf, long length_buf)
> +void
> +mi_console_file::flush ()
> {
> - struct mi_console_file *mi_console = (struct mi_console_file *) data;
> -
> - if (mi_console->magic != &mi_console_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("mi_console_raw_packet: bad magic number"));
> + const std::string &str = m_buffer.string ();
>
> - if (length_buf > 0)
> + /* Transform a byte sequence into a console output packet. */
> + if (!str.empty ())
> {
> - fputs_unfiltered (mi_console->prefix, mi_console->raw);
> - if (mi_console->quote)
> + size_t length_buf = str.size ();
> + const char *buf = str.data ();
> +
> + fputs_unfiltered (m_prefix, m_raw);
> + if (m_quote)
> {
> - fputc_unfiltered (mi_console->quote, mi_console->raw);
> - fputstrn_unfiltered (buf, length_buf,
> - mi_console->quote, mi_console->raw);
> - fputc_unfiltered (mi_console->quote, mi_console->raw);
> - fputc_unfiltered ('\n', mi_console->raw);
> + fputc_unfiltered (m_quote, m_raw);
> + fputstrn_unfiltered (buf, length_buf, m_quote, m_raw);
> + fputc_unfiltered (m_quote, m_raw);
> + fputc_unfiltered ('\n', m_raw);
> }
> else
> {
> - fputstrn_unfiltered (buf, length_buf, 0, mi_console->raw);
> - fputc_unfiltered ('\n', mi_console->raw);
> + fputstrn_unfiltered (buf, length_buf, 0, m_raw);
> + fputc_unfiltered ('\n', m_raw);
> }
> - gdb_flush (mi_console->raw);
> + gdb_flush (m_raw);
> }
> -}
> -
> -static void
> -mi_console_file_flush (struct ui_file *file)
> -{
> - struct mi_console_file *mi_console
> - = (struct mi_console_file *) ui_file_data (file);
> -
> - if (mi_console->magic != &mi_console_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("mi_console_file_flush: bad magic number"));
> -
> - ui_file_put (mi_console->buffer, mi_console_raw_packet, mi_console);
> - ui_file_rewind (mi_console->buffer);
>
> + m_buffer.clear ();
> }
>
> /* Change the underlying stream of the console directly; this is
> @@ -145,14 +83,7 @@ mi_console_file_flush (struct ui_file *file)
> logging enable/disable. */
>
> void
> -mi_console_set_raw (struct ui_file *file, struct ui_file *raw)
> +mi_console_file::set_raw (ui_file *raw)
> {
> - struct mi_console_file *mi_console
> - = (struct mi_console_file *) ui_file_data (file);
> -
> - if (mi_console->magic != &mi_console_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("mi_console_file_set_raw: bad magic number"));
> -
> - mi_console->raw = raw;
> + m_raw = raw;
> }
> diff --git a/gdb/mi/mi-console.h b/gdb/mi/mi-console.h
> index 64355a7..289013f 100644
> --- a/gdb/mi/mi-console.h
> +++ b/gdb/mi/mi-console.h
> @@ -20,11 +20,37 @@
> #ifndef MI_CONSOLE_H
> #define MI_CONSOLE_H
>
> -extern struct ui_file *mi_console_file_new (struct ui_file *raw,
> - const char *prefix,
> - char quote);
> +/* An output stream for MI. Wraps a given output stream with a prefix
> + and handles quoting. This stream is locally buffered. */
>
> -extern void mi_console_set_raw (struct ui_file *console,
> - struct ui_file *raw);
> +class mi_console_file : public ui_file
> +{
> +public:
> + /* Create a console that wraps the given output stream RAW with the
> + string PREFIX and quoting it with QUOTE. */
> + mi_console_file (ui_file *raw, const char *prefix, char quote);
> +
> + /* MI-specific API. */
> + void set_raw (ui_file *raw);
> +
> + /* ui_file-specific methods. */
> +
> + void flush () override;
> +
> + void write (const char *buf, long length_buf) override;
> +
> +private:
> + /* The wrapped raw output stream. */
> + ui_file *m_raw;
> +
> + /* The local buffer. */
> + string_file m_buffer;
> +
> + /* The prefix. */
> + const char *m_prefix;
> +
> + /* The quote char. */
> + char m_quote;
> +};
>
> #endif
> diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
> index 76f4f8c..f167a53 100644
> --- a/gdb/mi/mi-interp.c
> +++ b/gdb/mi/mi-interp.c
> @@ -126,11 +126,11 @@ mi_interpreter_init (struct interp *interp, int top_level)
>
> /* Create MI console channels, each with a different prefix so they
> can be distinguished. */
> - mi->out = mi_console_file_new (mi->raw_stdout, "~", '"');
> - mi->err = mi_console_file_new (mi->raw_stdout, "&", '"');
> + mi->out = new mi_console_file (mi->raw_stdout, "~", '"');
> + mi->err = new mi_console_file (mi->raw_stdout, "&", '"');
> mi->log = mi->err;
> - mi->targ = mi_console_file_new (mi->raw_stdout, "@", '"');
> - mi->event_channel = mi_console_file_new (mi->raw_stdout, "=", 0);
> + mi->targ = new mi_console_file (mi->raw_stdout, "@", '"');
> + mi->event_channel = new mi_console_file (mi->raw_stdout, "=", 0);
>
> name = interp_name (interp);
> /* INTERP_MI selects the most recent released version. "mi2" was
> @@ -1391,8 +1391,8 @@ mi_set_logging (struct interp *interp, int start_log,
> it), and create one based on raw_stdout instead. */
> if (logfile)
> {
> - ui_file_delete (out);
> - out = tee_file_new (mi->raw_stdout, 0, logfile, 0);
> + delete out;
> + out = new tee_file (mi->raw_stdout, false, logfile, false);
> }
>
> mi->saved_raw_stdout = mi->raw_stdout;
> @@ -1404,11 +1404,11 @@ mi_set_logging (struct interp *interp, int start_log,
> mi->saved_raw_stdout = NULL;
> }
>
> - mi_console_set_raw (mi->out, mi->raw_stdout);
> - mi_console_set_raw (mi->err, mi->raw_stdout);
> - mi_console_set_raw (mi->log, mi->raw_stdout);
> - mi_console_set_raw (mi->targ, mi->raw_stdout);
> - mi_console_set_raw (mi->event_channel, mi->raw_stdout);
> + mi->out->set_raw (mi->raw_stdout);
> + mi->err->set_raw (mi->raw_stdout);
> + mi->log->set_raw (mi->raw_stdout);
> + mi->targ->set_raw (mi->raw_stdout);
> + mi->event_channel->set_raw (mi->raw_stdout);
>
> return 1;
> }
> diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
> index 57c23eb..b249f2d 100644
> --- a/gdb/mi/mi-main.c
> +++ b/gdb/mi/mi-main.c
> @@ -1267,7 +1267,6 @@ output_register (struct frame_info *frame, int regnum, int format,
> struct value *val = value_of_register (regnum, frame);
> struct cleanup *tuple_cleanup;
> struct value_print_options opts;
> - struct ui_file *stb;
>
> if (skip_unavailable && !value_entirely_available (val))
> return;
> @@ -1281,14 +1280,13 @@ output_register (struct frame_info *frame, int regnum, int format,
> if (format == 'r')
> format = 'z';
>
> - stb = mem_fileopen ();
> - make_cleanup_ui_file_delete (stb);
> + string_file stb;
>
> get_formatted_print_options (&opts, format);
> opts.deref_ref = 1;
> val_print (value_type (val),
> value_embedded_offset (val), 0,
> - stb, 0, val, &opts, current_language);
> + &stb, 0, val, &opts, current_language);
> uiout->field_stream ("value", stb);
>
> do_cleanups (tuple_cleanup);
> @@ -1358,15 +1356,10 @@ mi_cmd_data_write_register_values (char *command, char **argv, int argc)
> void
> mi_cmd_data_evaluate_expression (char *command, char **argv, int argc)
> {
> - struct cleanup *old_chain;
> struct value *val;
> - struct ui_file *stb;
> struct value_print_options opts;
> struct ui_out *uiout = current_uiout;
>
> - stb = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (stb);
> -
> if (argc != 1)
> error (_("-data-evaluate-expression: "
> "Usage: -data-evaluate-expression expression"));
> @@ -1375,14 +1368,14 @@ mi_cmd_data_evaluate_expression (char *command, char **argv, int argc)
>
> val = evaluate_expression (expr.get ());
>
> + string_file stb;
> +
> /* Print the result of the expression evaluation. */
> get_user_print_options (&opts);
> opts.deref_ref = 0;
> - common_val_print (val, stb, 0, &opts, current_language);
> + common_val_print (val, &stb, 0, &opts, current_language);
>
> uiout->field_stream ("value", stb);
> -
> - do_cleanups (old_chain);
> }
>
> /* This is the -data-read-memory command.
> @@ -1522,15 +1515,13 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
>
> /* Build the result as a two dimentional table. */
> {
> - struct ui_file *stream;
> - struct cleanup *cleanup_stream;
> int row;
> int row_byte;
> + struct cleanup *cleanup_list;
>
> - stream = mem_fileopen ();
> - cleanup_stream = make_cleanup_ui_file_delete (stream);
> + string_file stream;
>
> - make_cleanup_ui_out_list_begin_end (uiout, "memory");
> + cleanup_list = make_cleanup_ui_out_list_begin_end (uiout, "memory");
> for (row = 0, row_byte = 0;
> row < nr_rows;
> row++, row_byte += nr_cols * word_size)
> @@ -1557,9 +1548,9 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
> }
> else
> {
> - ui_file_rewind (stream);
> + stream.clear ();
> print_scalar_formatted (&mbuf[col_byte], word_type, &opts,
> - word_asize, stream);
> + word_asize, &stream);
> uiout->field_stream (NULL, stream);
> }
> }
> @@ -1568,22 +1559,22 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
> {
> int byte;
>
> - ui_file_rewind (stream);
> + stream.clear ();
> for (byte = row_byte;
> byte < row_byte + word_size * nr_cols; byte++)
> {
> if (byte >= nr_bytes)
> - fputc_unfiltered ('X', stream);
> + stream.putc ('X');
> else if (mbuf[byte] < 32 || mbuf[byte] > 126)
> - fputc_unfiltered (aschar, stream);
> + stream.putc (aschar);
> else
> - fputc_unfiltered (mbuf[byte], stream);
> + stream.putc (mbuf[byte]);
> }
> uiout->field_stream ("ascii", stream);
> }
> do_cleanups (cleanup_tuple);
> }
> - do_cleanups (cleanup_stream);
> + do_cleanups (cleanup_list);
> }
> }
>
> @@ -2317,15 +2308,12 @@ mi_cmd_execute (struct mi_parse *parse)
> else
> {
> /* FIXME: DELETE THIS. */
> - struct ui_file *stb;
> -
> - stb = mem_fileopen ();
> + string_file stb;
>
> - fputs_unfiltered ("Undefined mi command: ", stb);
> - fputstr_unfiltered (parse->command, '"', stb);
> - fputs_unfiltered (" (missing implementation)", stb);
> + stb.puts ("Undefined mi command: ");
> + stb.putstr (parse->command, '"');
> + stb.puts (" (missing implementation)");
>
> - make_cleanup_ui_file_delete (stb);
> error_stream (stb);
> }
> do_cleanups (cleanup);
> @@ -2705,12 +2693,10 @@ print_variable_or_computed (const char *expression, enum print_values values)
> {
> struct cleanup *old_chain;
> struct value *val;
> - struct ui_file *stb;
> struct type *type;
> struct ui_out *uiout = current_uiout;
>
> - stb = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (stb);
> + string_file stb;
>
> expression_up expr = parse_expression (expression);
>
> @@ -2719,6 +2705,7 @@ print_variable_or_computed (const char *expression, enum print_values values)
> else
> val = evaluate_expression (expr.get ());
>
> + old_chain = make_cleanup (null_cleanup, NULL);
> if (values != PRINT_NO_VALUES)
> make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
> uiout->field_string ("name", expression);
> @@ -2727,7 +2714,7 @@ print_variable_or_computed (const char *expression, enum print_values values)
> {
> case PRINT_SIMPLE_VALUES:
> type = check_typedef (value_type (val));
> - type_print (value_type (val), "", stb, -1);
> + type_print (value_type (val), "", &stb, -1);
> uiout->field_stream ("type", stb);
> if (TYPE_CODE (type) != TYPE_CODE_ARRAY
> && TYPE_CODE (type) != TYPE_CODE_STRUCT
> @@ -2737,7 +2724,7 @@ print_variable_or_computed (const char *expression, enum print_values values)
>
> get_no_prettyformat_print_options (&opts);
> opts.deref_ref = 1;
> - common_val_print (val, stb, 0, &opts, current_language);
> + common_val_print (val, &stb, 0, &opts, current_language);
> uiout->field_stream ("value", stb);
> }
> break;
> @@ -2747,7 +2734,7 @@ print_variable_or_computed (const char *expression, enum print_values values)
>
> get_no_prettyformat_print_options (&opts);
> opts.deref_ref = 1;
> - common_val_print (val, stb, 0, &opts, current_language);
> + common_val_print (val, &stb, 0, &opts, current_language);
> uiout->field_stream ("value", stb);
> }
> break;
> diff --git a/gdb/mi/mi-out.c b/gdb/mi/mi-out.c
> index 5a5aef9..6181140 100644
> --- a/gdb/mi/mi-out.c
> +++ b/gdb/mi/mi-out.c
> @@ -236,23 +236,31 @@ mi_ui_out::close (ui_out_type type)
> m_suppress_field_separator = false;
> }
>
> +string_file *
> +mi_ui_out::main_stream ()
> +{
> + gdb_assert (m_streams.size () == 1);
> +
> + return (string_file *) m_streams.back ();
> +}
> +
> /* Clear the buffer. */
>
> void
> mi_ui_out::rewind ()
> {
> - ui_file_rewind (m_streams.back ());
> + main_stream ()->clear ();
> }
>
> /* Dump the buffer onto the specified stream. */
>
> void
> -mi_ui_out::put (ui_file *stream)
> +mi_ui_out::put (ui_file *where)
> {
> - ui_file *outstream = m_streams.back ();
> + string_file *mi_stream = main_stream ();
>
> - ui_file_put (outstream, ui_file_write_for_put, stream);
> - ui_file_rewind (outstream);
> + where->write (mi_stream->data (), mi_stream->size ());
> + mi_stream->clear ();
> }
>
> /* Return the current MI version. */
> @@ -265,13 +273,12 @@ mi_ui_out::version ()
>
> /* Constructor for an `mi_out_data' object. */
>
> -mi_ui_out::mi_ui_out (int mi_version, ui_file *stream)
> +mi_ui_out::mi_ui_out (int mi_version)
> : m_suppress_field_separator (false),
> m_suppress_output (false),
> m_mi_version (mi_version)
> {
> - gdb_assert (stream != NULL);
> -
> + string_file *stream = new string_file ();
> m_streams.push_back (stream);
> }
>
> @@ -284,9 +291,7 @@ mi_ui_out::~mi_ui_out ()
> mi_ui_out *
> mi_out_new (int mi_version)
> {
> - ui_file *stream = mem_fileopen ();
> -
> - return new mi_ui_out (mi_version, stream);
> + return new mi_ui_out (mi_version);
> }
>
> /* Helper function to return the given UIOUT as an mi_ui_out. It is an error
> diff --git a/gdb/mi/mi-out.h b/gdb/mi/mi-out.h
> index e82d44d..fea94f2 100644
> --- a/gdb/mi/mi-out.h
> +++ b/gdb/mi/mi-out.h
> @@ -30,7 +30,7 @@ class mi_ui_out : public ui_out
> {
> public:
>
> - explicit mi_ui_out (int mi_version, ui_file *stream);
> + explicit mi_ui_out (int mi_version);
> virtual ~mi_ui_out ();
>
> /* MI-specific */
> @@ -78,6 +78,11 @@ private:
> void open (const char *name, ui_out_type type);
> void close (ui_out_type type);
>
> + /* Convenience method that returns the MI out's string stream cast
> + to its appropriate type. Assumes/asserts that output was not
> + redirected. */
> + string_file *main_stream ();
> +
> bool m_suppress_field_separator;
> bool m_suppress_output;
> int m_mi_version;
> diff --git a/gdb/printcmd.c b/gdb/printcmd.c
> index e4711e9..dab4f53 100644
> --- a/gdb/printcmd.c
> +++ b/gdb/printcmd.c
> @@ -2717,18 +2717,13 @@ printf_command (char *arg, int from_tty)
> static void
> eval_command (char *arg, int from_tty)
> {
> - struct ui_file *ui_out = mem_fileopen ();
> - struct cleanup *cleanups = make_cleanup_ui_file_delete (ui_out);
> + string_file stb;
>
> - ui_printf (arg, ui_out);
> + ui_printf (arg, &stb);
>
> - std::string expanded = ui_file_as_string (ui_out);
> -
> - expanded = insert_user_defined_cmd_args (expanded.c_str ());
> + std::string expanded = insert_user_defined_cmd_args (stb.c_str ());
>
> execute_command (&expanded[0], from_tty);
> -
> - do_cleanups (cleanups);
> }
>
> void
> diff --git a/gdb/psymtab.c b/gdb/psymtab.c
> index 3acc226..1fad8a0 100644
> --- a/gdb/psymtab.c
> +++ b/gdb/psymtab.c
> @@ -1965,6 +1965,8 @@ maintenance_print_psymbols (char *args, int from_tty)
> if (address_arg != NULL && source_arg != NULL)
> error (_("Must specify at most one of -pc and -source"));
>
> + stdio_file arg_outfile;
> +
> if (argv[outfile_idx] != NULL)
> {
> char *outfile_name;
> @@ -1973,10 +1975,9 @@ maintenance_print_psymbols (char *args, int from_tty)
> error (_("Junk at end of command"));
> outfile_name = tilde_expand (argv[outfile_idx]);
> make_cleanup (xfree, outfile_name);
> - outfile = gdb_fopen (outfile_name, FOPEN_WT);
> - if (outfile == NULL)
> + if (!arg_outfile.open (outfile_name, FOPEN_WT))
> perror_with_name (outfile_name);
> - make_cleanup_ui_file_delete (outfile);
> + outfile = &arg_outfile;
> }
>
> if (address_arg != NULL)
> @@ -2011,9 +2012,8 @@ maintenance_print_psymbols (char *args, int from_tty)
> {
> if (!printed_objfile_header)
> {
> - fprintf_filtered (outfile,
> - "\nPartial symtabs for objfile %s\n",
> - objfile_name (objfile));
> + outfile->printf ("\nPartial symtabs for objfile %s\n",
> + objfile_name (objfile));
> printed_objfile_header = 1;
> }
> dump_psymtab (objfile, ps, outfile);
> @@ -2039,9 +2039,8 @@ maintenance_print_psymbols (char *args, int from_tty)
> {
> if (!printed_objfile_header)
> {
> - fprintf_filtered (outfile,
> - "\nPartial symtabs for objfile %s\n",
> - objfile_name (objfile));
> + outfile->printf ("\nPartial symtabs for objfile %s\n",
> + objfile_name (objfile));
> printed_objfile_header = 1;
> }
> dump_psymtab (objfile, ps, outfile);
> @@ -2056,7 +2055,7 @@ maintenance_print_psymbols (char *args, int from_tty)
> && source_arg == NULL
> && objfile->psymtabs_addrmap != NULL)
> {
> - fprintf_filtered (outfile, "\n");
> + outfile->puts ("\n");
> dump_psymtab_addrmap (objfile, NULL, outfile);
> }
> }
> diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c
> index 13cc9ba..8d0ec33 100644
> --- a/gdb/python/py-arch.c
> +++ b/gdb/python/py-arch.c
> @@ -193,54 +193,38 @@ archpy_disassemble (PyObject *self, PyObject *args, PyObject *kw)
> || (end_obj == NULL && count_obj == NULL && pc == start);)
> {
> int insn_len = 0;
> - struct ui_file *memfile = mem_fileopen ();
> gdbpy_ref insn_dict (PyDict_New ());
>
> if (insn_dict == NULL)
> - {
> - ui_file_delete (memfile);
> -
> - return NULL;
> - }
> + return NULL;
> if (PyList_Append (result_list.get (), insn_dict.get ()))
> - {
> - ui_file_delete (memfile);
> + return NULL; /* PyList_Append Sets the exception. */
>
> - return NULL; /* PyList_Append Sets the exception. */
> - }
> + string_file stb;
>
> TRY
> {
> - insn_len = gdb_print_insn (gdbarch, pc, memfile, NULL);
> + insn_len = gdb_print_insn (gdbarch, pc, &stb, NULL);
> }
> CATCH (except, RETURN_MASK_ALL)
> {
> - ui_file_delete (memfile);
> -
> gdbpy_convert_exception (except);
> return NULL;
> }
> END_CATCH
>
> - std::string as = ui_file_as_string (memfile);
> -
> if (PyDict_SetItemString (insn_dict.get (), "addr",
> gdb_py_long_from_ulongest (pc))
> || PyDict_SetItemString (insn_dict.get (), "asm",
> - PyString_FromString (!as.empty ()
> - ? as.c_str ()
> + PyString_FromString (!stb.empty ()
> + ? stb.c_str ()
> : "<unknown>"))
> || PyDict_SetItemString (insn_dict.get (), "length",
> PyInt_FromLong (insn_len)))
> - {
> - ui_file_delete (memfile);
> -
> - return NULL;
> - }
> + return NULL;
>
> pc += insn_len;
> i++;
> - ui_file_delete (memfile);
> }
>
> return result_list.release ();
> diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
> index f268b2b..ac64900 100644
> --- a/gdb/python/py-breakpoint.c
> +++ b/gdb/python/py-breakpoint.c
> @@ -485,19 +485,16 @@ bppy_get_commands (PyObject *self, void *closure)
> gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
> struct breakpoint *bp = self_bp->bp;
> long length;
> - struct ui_file *string_file;
> PyObject *result;
> - struct cleanup *chain;
>
> BPPY_REQUIRE_VALID (self_bp);
>
> if (! self_bp->bp->commands)
> Py_RETURN_NONE;
>
> - string_file = mem_fileopen ();
> - chain = make_cleanup_ui_file_delete (string_file);
> + string_file stb;
>
> - current_uiout->redirect (string_file);
> + current_uiout->redirect (&stb);
> TRY
> {
> print_command_lines (current_uiout, breakpoint_commands (bp), 0);
> @@ -505,17 +502,13 @@ bppy_get_commands (PyObject *self, void *closure)
> CATCH (except, RETURN_MASK_ALL)
> {
> current_uiout->redirect (NULL);
> - do_cleanups (chain);
> gdbpy_convert_exception (except);
> return NULL;
> }
> END_CATCH
>
> current_uiout->redirect (NULL);
> - std::string cmdstr = ui_file_as_string (string_file);
> - result = host_string_to_python_string (cmdstr.c_str ());
> - do_cleanups (chain);
> - return result;
> + return host_string_to_python_string (stb.c_str ());
> }
>
> /* Python function to get the breakpoint type. */
> diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
> index 048e7c1..8f5ddd0 100644
> --- a/gdb/python/py-frame.c
> +++ b/gdb/python/py-frame.c
> @@ -80,13 +80,10 @@ frame_object_to_frame_info (PyObject *obj)
> static PyObject *
> frapy_str (PyObject *self)
> {
> - PyObject *result;
> - struct ui_file *strfile;
> + string_file strfile;
>
> - strfile = mem_fileopen ();
> - fprint_frame_id (strfile, ((frame_object *) self)->frame_id);
> - std::string s = ui_file_as_string (strfile);
> - return PyString_FromString (s.c_str ());
> + fprint_frame_id (&strfile, ((frame_object *) self)->frame_id);
> + return PyString_FromString (strfile.c_str ());
> }
>
> /* Implementation of gdb.Frame.is_valid (self) -> Boolean.
> diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c
> index bdd9911..9dc01ba 100644
> --- a/gdb/python/py-framefilter.c
> +++ b/gdb/python/py-framefilter.c
> @@ -208,15 +208,11 @@ py_print_type (struct ui_out *out, struct value *val)
>
> TRY
> {
> - struct ui_file *stb;
> - struct cleanup *cleanup;
> -
> - stb = mem_fileopen ();
> - cleanup = make_cleanup_ui_file_delete (stb);
> check_typedef (value_type (val));
> - type_print (value_type (val), "", stb, -1);
> +
> + string_file stb;
> + type_print (value_type (val), "", &stb, -1);
> out->field_stream ("type", stb);
> - do_cleanups (cleanup);
> }
> CATCH (except, RETURN_MASK_ALL)
> {
> @@ -280,14 +276,10 @@ py_print_value (struct ui_out *out, struct value *val,
> {
> TRY
> {
> - struct ui_file *stb;
> - struct cleanup *cleanup;
> + string_file stb;
>
> - stb = mem_fileopen ();
> - cleanup = make_cleanup_ui_file_delete (stb);
> - common_val_print (val, stb, indent, opts, language);
> + common_val_print (val, &stb, indent, opts, language);
> out->field_stream ("value", stb);
> - do_cleanups (cleanup);
> }
> CATCH (except, RETURN_MASK_ALL)
> {
> @@ -393,26 +385,22 @@ py_print_single_arg (struct ui_out *out,
> entry value options. */
> if (fa != NULL)
> {
> - struct ui_file *stb;
> + string_file stb;
>
> - stb = mem_fileopen ();
> - make_cleanup_ui_file_delete (stb);
> - fprintf_symbol_filtered (stb, SYMBOL_PRINT_NAME (fa->sym),
> + fprintf_symbol_filtered (&stb, SYMBOL_PRINT_NAME (fa->sym),
> SYMBOL_LANGUAGE (fa->sym),
> DMGL_PARAMS | DMGL_ANSI);
> if (fa->entry_kind == print_entry_values_compact)
> {
> - fputs_filtered ("=", stb);
> + stb.puts ("=");
>
> - fprintf_symbol_filtered (stb, SYMBOL_PRINT_NAME (fa->sym),
> + fprintf_symbol_filtered (&stb, SYMBOL_PRINT_NAME (fa->sym),
> SYMBOL_LANGUAGE (fa->sym),
> DMGL_PARAMS | DMGL_ANSI);
> }
> if (fa->entry_kind == print_entry_values_only
> || fa->entry_kind == print_entry_values_compact)
> - {
> - fputs_filtered ("@entry", stb);
> - }
> + stb.puts ("@entry");
> out->field_stream ("name", stb);
> }
> else
> diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
> index 7862829..f6e8dd6 100644
> --- a/gdb/python/py-type.c
> +++ b/gdb/python/py-type.c
> @@ -967,22 +967,13 @@ typy_template_argument (PyObject *self, PyObject *args)
> static PyObject *
> typy_str (PyObject *self)
> {
> - std::string thetype;
> + string_file thetype;
> PyObject *result;
>
> TRY
> {
> - struct cleanup *old_chain;
> - struct ui_file *stb;
> -
> - stb = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (stb);
> -
> - LA_PRINT_TYPE (type_object_to_type (self), "", stb, -1, 0,
> + LA_PRINT_TYPE (type_object_to_type (self), "", &thetype, -1, 0,
> &type_print_raw_options);
> -
> - thetype = ui_file_as_string (stb);
> - do_cleanups (old_chain);
> }
> CATCH (except, RETURN_MASK_ALL)
> {
> @@ -990,10 +981,8 @@ typy_str (PyObject *self)
> }
> END_CATCH
>
> - result = PyUnicode_Decode (thetype.c_str (), thetype.length (),
> - host_charset (), NULL);
> -
> - return result;
> + return PyUnicode_Decode (thetype.c_str (), thetype.size (),
> + host_charset (), NULL);
> }
>
> /* Implement the richcompare method. */
> diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
> index 690412a..d1b63ad 100644
> --- a/gdb/python/py-unwind.c
> +++ b/gdb/python/py-unwind.c
> @@ -198,12 +198,11 @@ pyuw_object_attribute_to_pointer (PyObject *pyo, const char *attr_name,
> static PyObject *
> unwind_infopy_str (PyObject *self)
> {
> - struct ui_file *strfile = mem_fileopen ();
> unwind_info_object *unwind_info = (unwind_info_object *) self;
> - PyObject *result;
> + string_file stb;
>
> - fprintf_unfiltered (strfile, "Frame ID: ");
> - fprint_frame_id (strfile, unwind_info->frame_id);
> + stb.puts ("Frame ID: ");
> + fprint_frame_id (&stb, unwind_info->frame_id);
> {
> char *sep = "";
> int i;
> @@ -211,18 +210,18 @@ unwind_infopy_str (PyObject *self)
> saved_reg *reg;
>
> get_user_print_options (&opts);
> - fprintf_unfiltered (strfile, "\nSaved registers: (");
> + stb.printf ("\nSaved registers: (");
> for (i = 0; VEC_iterate (saved_reg, unwind_info->saved_regs, i, reg); i++)
> {
> struct value *value = value_object_to_value (reg->value);
>
> - fprintf_unfiltered (strfile, "%s(%d, ", sep, reg->number);
> + stb.printf ("%s(%d, ", sep, reg->number);
> if (value != NULL)
> {
> TRY
> {
> - value_print (value, strfile, &opts);
> - fprintf_unfiltered (strfile, ")");
> + value_print (value, &stb, &opts);
> + stb.puts (")");
> }
> CATCH (except, RETURN_MASK_ALL)
> {
> @@ -231,16 +230,13 @@ unwind_infopy_str (PyObject *self)
> END_CATCH
> }
> else
> - fprintf_unfiltered (strfile, "<BAD>)");
> + stb.puts ("<BAD>)");
> sep = ", ";
> }
> - fprintf_unfiltered (strfile, ")");
> + stb.puts (")");
> }
>
> - std::string s = ui_file_as_string (strfile);
> - result = PyString_FromString (s.c_str ());
> - ui_file_delete (strfile);
> - return result;
> + return PyString_FromString (stb.c_str ());
> }
>
> /* Create UnwindInfo instance for given PendingFrame and frame ID.
> diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
> index 8f3164b..8e4d06d 100644
> --- a/gdb/python/py-value.c
> +++ b/gdb/python/py-value.c
> @@ -867,23 +867,17 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
> static PyObject *
> valpy_str (PyObject *self)
> {
> - std::string s;
> - PyObject *result;
> struct value_print_options opts;
>
> get_user_print_options (&opts);
> opts.deref_ref = 0;
>
> + string_file stb;
> +
> TRY
> {
> - struct ui_file *stb = mem_fileopen ();
> - struct cleanup *old_chain = make_cleanup_ui_file_delete (stb);
> -
> - common_val_print (((value_object *) self)->value, stb, 0,
> + common_val_print (((value_object *) self)->value, &stb, 0,
> &opts, python_language);
> - s = ui_file_as_string (stb);
> -
> - do_cleanups (old_chain);
> }
> CATCH (except, RETURN_MASK_ALL)
> {
> @@ -891,9 +885,7 @@ valpy_str (PyObject *self)
> }
> END_CATCH
>
> - result = PyUnicode_Decode (s.c_str (), s.length (), host_charset (), NULL);
> -
> - return result;
> + return PyUnicode_Decode (stb.c_str (), stb.size (), host_charset (), NULL);
> }
>
> /* Implements gdb.Value.is_optimized_out. */
> diff --git a/gdb/regcache.c b/gdb/regcache.c
> index 9d28aa2..eed1bd8 100644
> --- a/gdb/regcache.c
> +++ b/gdb/regcache.c
> @@ -1498,14 +1498,11 @@ regcache_print (char *args, enum regcache_dump_what what_to_dump)
> regcache_dump (get_current_regcache (), gdb_stdout, what_to_dump);
> else
> {
> - struct cleanup *cleanups;
> - struct ui_file *file = gdb_fopen (args, "w");
> + stdio_file file;
>
> - if (file == NULL)
> + if (!file.open (args, "w"))
> perror_with_name (_("maintenance print architecture"));
> - cleanups = make_cleanup_ui_file_delete (file);
> - regcache_dump (get_current_regcache (), file, what_to_dump);
> - do_cleanups (cleanups);
> + regcache_dump (get_current_regcache (), &file, what_to_dump);
> }
> }
>
> diff --git a/gdb/reggroups.c b/gdb/reggroups.c
> index 693b378..ae7d4ce 100644
> --- a/gdb/reggroups.c
> +++ b/gdb/reggroups.c
> @@ -270,14 +270,11 @@ maintenance_print_reggroups (char *args, int from_tty)
> reggroups_dump (gdbarch, gdb_stdout);
> else
> {
> - struct cleanup *cleanups;
> - struct ui_file *file = gdb_fopen (args, "w");
> + stdio_file file;
>
> - if (file == NULL)
> + if (!file.open (args, "w"))
> perror_with_name (_("maintenance print reggroups"));
> - cleanups = make_cleanup_ui_file_delete (file);
> - reggroups_dump (gdbarch, file);
> - do_cleanups (cleanups);
> + reggroups_dump (gdbarch, &file);
> }
> }
>
> diff --git a/gdb/remote.c b/gdb/remote.c
> index c4cec91..3befbd3 100644
> --- a/gdb/remote.c
> +++ b/gdb/remote.c
> @@ -8674,16 +8674,10 @@ remote_send (char **buf,
> static std::string
> escape_buffer (const char *buf, int n)
> {
> - struct cleanup *old_chain;
> - struct ui_file *stb;
> -
> - stb = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (stb);
> + string_file stb;
>
> - fputstrn_unfiltered (buf, n, '\\', stb);
> - std::string str = ui_file_as_string (stb);
> - do_cleanups (old_chain);
> - return str;
> + stb.putstrn (buf, n, '\\');
> + return std::move (stb.string ());
> }
>
> /* Display a null-terminated packet on stdout, for debugging, using C
> diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
> index 4445812..dd72cd9 100644
> --- a/gdb/rust-lang.c
> +++ b/gdb/rust-lang.c
> @@ -125,7 +125,6 @@ rust_get_disr_info (struct type *type, const gdb_byte *valaddr,
> int i;
> struct disr_info ret;
> struct type *disr_type;
> - struct ui_file *temp_file;
> struct value_print_options opts;
> struct cleanup *cleanup;
> const char *name_segment;
> @@ -229,17 +228,16 @@ rust_get_disr_info (struct type *type, const gdb_byte *valaddr,
> if (strcmp (TYPE_FIELD_NAME (disr_type, 0), "RUST$ENUM$DISR") != 0)
> error (_("Rust debug format has changed"));
>
> - temp_file = mem_fileopen ();
> - cleanup = make_cleanup_ui_file_delete (temp_file);
> + string_file temp_file;
> /* The first value of the first field (or any field)
> is the discriminant value. */
> c_val_print (TYPE_FIELD_TYPE (disr_type, 0),
> (embedded_offset + TYPE_FIELD_BITPOS (type, 0) / 8
> + TYPE_FIELD_BITPOS (disr_type, 0) / 8),
> - address, temp_file,
> + address, &temp_file,
> 0, val, &opts);
>
> - ret.name = ui_file_as_string (temp_file);
> + ret.name = std::move (temp_file.string ());
> name_segment = rust_last_path_segment (ret.name.c_str ());
> if (name_segment != NULL)
> {
> @@ -271,7 +269,6 @@ rust_get_disr_info (struct type *type, const gdb_byte *valaddr,
> TYPE_TAG_NAME (type), ret.name.c_str ());
> }
>
> - do_cleanups (cleanup);
> return ret;
> }
>
> diff --git a/gdb/serial.c b/gdb/serial.c
> index afb7075..b48b977 100644
> --- a/gdb/serial.c
> +++ b/gdb/serial.c
> @@ -251,9 +251,12 @@ serial_open_ops_1 (const struct serial_ops *ops, const char *open_name)
>
> if (serial_logfile != NULL)
> {
> - serial_logfp = gdb_fopen (serial_logfile, "w");
> - if (serial_logfp == NULL)
> + stdio_file_up file (new stdio_file ());
> +
> + if (!file->open (serial_logfile, "w"))
> perror_with_name (serial_logfile);
> +
> + serial_logfp = file.release ();
> }
>
> return scb;
> @@ -315,7 +318,7 @@ do_serial_close (struct serial *scb, int really_close)
> serial_current_type = 0;
>
> /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr? */
> - ui_file_delete (serial_logfp);
> + delete serial_logfp;
> serial_logfp = NULL;
> }
>
> diff --git a/gdb/stack.c b/gdb/stack.c
> index 4c9e14e..e24aaf3 100644
> --- a/gdb/stack.c
> +++ b/gdb/stack.c
> @@ -225,11 +225,9 @@ print_frame_arg (const struct frame_arg *arg)
> {
> struct ui_out *uiout = current_uiout;
> struct cleanup *old_chain;
> - struct ui_file *stb;
> const char *error_message = NULL;
>
> - stb = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (stb);
> + string_file stb;
>
> gdb_assert (!arg->val || !arg->error);
> gdb_assert (arg->entry_kind == print_entry_values_no
> @@ -239,22 +237,22 @@ print_frame_arg (const struct frame_arg *arg)
>
> annotate_arg_begin ();
>
> - make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
> - fprintf_symbol_filtered (stb, SYMBOL_PRINT_NAME (arg->sym),
> + old_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
> + fprintf_symbol_filtered (&stb, SYMBOL_PRINT_NAME (arg->sym),
> SYMBOL_LANGUAGE (arg->sym), DMGL_PARAMS | DMGL_ANSI);
> if (arg->entry_kind == print_entry_values_compact)
> {
> /* It is OK to provide invalid MI-like stream as with
> PRINT_ENTRY_VALUE_COMPACT we never use MI. */
> - fputs_filtered ("=", stb);
> + stb.puts ("=");
>
> - fprintf_symbol_filtered (stb, SYMBOL_PRINT_NAME (arg->sym),
> + fprintf_symbol_filtered (&stb, SYMBOL_PRINT_NAME (arg->sym),
> SYMBOL_LANGUAGE (arg->sym),
> DMGL_PARAMS | DMGL_ANSI);
> }
> if (arg->entry_kind == print_entry_values_only
> || arg->entry_kind == print_entry_values_compact)
> - fputs_filtered ("@entry", stb);
> + stb.puts ("@entry");
> uiout->field_stream ("name", stb);
> annotate_arg_name_end ();
> uiout->text ("=");
> @@ -294,7 +292,7 @@ print_frame_arg (const struct frame_arg *arg)
> /* True in "summary" mode, false otherwise. */
> opts.summary = !strcmp (print_frame_arguments, "scalars");
>
> - common_val_print (arg->val, stb, 2, &opts, language);
> + common_val_print (arg->val, &stb, 2, &opts, language);
> }
> CATCH (except, RETURN_MASK_ERROR)
> {
> @@ -303,8 +301,7 @@ print_frame_arg (const struct frame_arg *arg)
> END_CATCH
> }
> if (error_message != NULL)
> - fprintf_filtered (stb, _("<error reading variable: %s>"),
> - error_message);
> + stb.printf (_("<error reading variable: %s>"), error_message);
> }
>
> uiout->field_stream ("value", stb);
> @@ -1158,7 +1155,6 @@ print_frame (struct frame_info *frame, int print_level,
> struct ui_out *uiout = current_uiout;
> char *funname = NULL;
> enum language funlang = language_unknown;
> - struct ui_file *stb;
> struct cleanup *old_chain, *list_chain;
> struct value_print_options opts;
> struct symbol *func;
> @@ -1167,11 +1163,9 @@ print_frame (struct frame_info *frame, int print_level,
>
> pc_p = get_frame_pc_if_available (frame, &pc);
>
> - stb = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (stb);
>
> find_frame_funname (frame, &funname, &funlang, &func);
> - make_cleanup (xfree, funname);
> + old_chain = make_cleanup (xfree, funname);
>
> annotate_frame_begin (print_level ? frame_relative_level (frame) : 0,
> gdbarch, pc);
> @@ -1199,7 +1193,9 @@ print_frame (struct frame_info *frame, int print_level,
> uiout->text (" in ");
> }
> annotate_frame_function_name ();
> - fprintf_symbol_filtered (stb, funname ? funname : "??",
> +
> + string_file stb;
> + fprintf_symbol_filtered (&stb, funname ? funname : "??",
> funlang, DMGL_ANSI);
> uiout->field_stream ("func", stb);
> uiout->wrap_hint (" ");
> diff --git a/gdb/symmisc.c b/gdb/symmisc.c
> index 811183c..07d571a 100644
> --- a/gdb/symmisc.c
> +++ b/gdb/symmisc.c
> @@ -457,6 +457,8 @@ maintenance_print_symbols (char *args, int from_tty)
> if (address_arg != NULL && source_arg != NULL)
> error (_("Must specify at most one of -pc and -source"));
>
> + stdio_file arg_outfile;
> +
> if (argv[outfile_idx] != NULL)
> {
> char *outfile_name;
> @@ -465,10 +467,9 @@ maintenance_print_symbols (char *args, int from_tty)
> error (_("Junk at end of command"));
> outfile_name = tilde_expand (argv[outfile_idx]);
> make_cleanup (xfree, outfile_name);
> - outfile = gdb_fopen (outfile_name, FOPEN_WT);
> - if (outfile == NULL)
> + if (!arg_outfile.open (outfile_name, FOPEN_WT))
> perror_with_name (outfile_name);
> - make_cleanup_ui_file_delete (outfile);
> + outfile = &arg_outfile;
> }
>
> if (address_arg != NULL)
> @@ -744,6 +745,8 @@ maintenance_print_msymbols (char *args, int from_tty)
> }
> outfile_idx = i;
>
> + stdio_file arg_outfile;
> +
> if (argv[outfile_idx] != NULL)
> {
> char *outfile_name;
> @@ -752,10 +755,9 @@ maintenance_print_msymbols (char *args, int from_tty)
> error (_("Junk at end of command"));
> outfile_name = tilde_expand (argv[outfile_idx]);
> make_cleanup (xfree, outfile_name);
> - outfile = gdb_fopen (outfile_name, FOPEN_WT);
> - if (outfile == NULL)
> + if (!arg_outfile.open (outfile_name, FOPEN_WT))
> perror_with_name (outfile_name);
> - make_cleanup_ui_file_delete (outfile);
> + outfile = &arg_outfile;
> }
>
> ALL_OBJFILES (objfile)
> diff --git a/gdb/symtab.h b/gdb/symtab.h
> index f4cfdf6..88bdd27 100644
> --- a/gdb/symtab.h
> +++ b/gdb/symtab.h
> @@ -674,7 +674,7 @@ struct symbol_computed_ops
> The generated C code must assign the location to a local
> variable; this variable's name is RESULT_NAME. */
>
> - void (*generate_c_location) (struct symbol *symbol, struct ui_file *stream,
> + void (*generate_c_location) (struct symbol *symbol, string_file &stream,
> struct gdbarch *gdbarch,
> unsigned char *registers_used,
> CORE_ADDR pc, const char *result_name);
> diff --git a/gdb/top.c b/gdb/top.c
> index f712bea..6bf9d8c0 100644
> --- a/gdb/top.c
> +++ b/gdb/top.c
> @@ -272,9 +272,9 @@ new_ui (FILE *instream, FILE *outstream, FILE *errstream)
>
> ui->input_interactive_p = ISATTY (ui->instream);
>
> - ui->m_gdb_stdin = stdio_fileopen (ui->instream);
> - ui->m_gdb_stdout = stdio_fileopen (ui->outstream);
> - ui->m_gdb_stderr = stderr_fileopen (ui->errstream);
> + ui->m_gdb_stdin = new stdio_file (ui->instream);
> + ui->m_gdb_stdout = new stdio_file (ui->outstream);
> + ui->m_gdb_stderr = new stderr_file (ui->errstream);
> ui->m_gdb_stdlog = ui->m_gdb_stderr;
>
> ui->prompt_state = PROMPT_NEEDED;
> @@ -296,9 +296,9 @@ new_ui (FILE *instream, FILE *outstream, FILE *errstream)
> static void
> free_ui (struct ui *ui)
> {
> - ui_file_delete (ui->m_gdb_stdin);
> - ui_file_delete (ui->m_gdb_stdout);
> - ui_file_delete (ui->m_gdb_stderr);
> + delete ui->m_gdb_stdin;
> + delete ui->m_gdb_stdout;
> + delete ui->m_gdb_stderr;
>
> xfree (ui);
> }
> @@ -693,7 +693,6 @@ execute_command (char *p, int from_tty)
> std::string
> execute_command_to_string (char *p, int from_tty)
> {
> - struct ui_file *str_file;
> struct cleanup *cleanup;
>
> /* GDB_STDOUT should be better already restored during these
> @@ -702,31 +701,27 @@ execute_command_to_string (char *p, int from_tty)
>
> scoped_restore save_async = make_scoped_restore (¤t_ui->async, 0);
>
> - str_file = mem_fileopen ();
> + string_file str_file;
>
> - make_cleanup_ui_file_delete (str_file);
> -
> - current_uiout->redirect (str_file);
> + current_uiout->redirect (&str_file);
> make_cleanup_ui_out_redirect_pop (current_uiout);
>
> scoped_restore save_stdout
> - = make_scoped_restore (&gdb_stdout, str_file);
> + = make_scoped_restore (&gdb_stdout, &str_file);
> scoped_restore save_stderr
> - = make_scoped_restore (&gdb_stderr, str_file);
> + = make_scoped_restore (&gdb_stderr, &str_file);
> scoped_restore save_stdlog
> - = make_scoped_restore (&gdb_stdlog, str_file);
> + = make_scoped_restore (&gdb_stdlog, &str_file);
> scoped_restore save_stdtarg
> - = make_scoped_restore (&gdb_stdtarg, str_file);
> + = make_scoped_restore (&gdb_stdtarg, &str_file);
> scoped_restore save_stdtargerr
> - = make_scoped_restore (&gdb_stdtargerr, str_file);
> + = make_scoped_restore (&gdb_stdtargerr, &str_file);
>
> execute_command (p, from_tty);
>
> - std::string retval = ui_file_as_string (str_file);
> -
> do_cleanups (cleanup);
>
> - return retval;
> + return std::move (str_file.string ());
> }
>
> \f
> @@ -1569,26 +1564,18 @@ print_inferior_quit_action (struct inferior *inf, void *arg)
> int
> quit_confirm (void)
> {
> - struct ui_file *stb;
> - struct cleanup *old_chain;
> -
> /* Don't even ask if we're only debugging a core file inferior. */
> if (!have_live_inferiors ())
> return 1;
>
> /* Build the query string as a single string. */
> - stb = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (stb);
> -
> - fprintf_filtered (stb, _("A debugging session is active.\n\n"));
> - iterate_over_inferiors (print_inferior_quit_action, stb);
> - fprintf_filtered (stb, _("\nQuit anyway? "));
> + string_file stb;
>
> - std::string str = ui_file_as_string (stb);
> -
> - do_cleanups (old_chain);
> + stb.puts (_("A debugging session is active.\n\n"));
> + iterate_over_inferiors (print_inferior_quit_action, &stb);
> + stb.puts (_("\nQuit anyway? "));
>
> - return query ("%s", str.c_str ());
> + return query ("%s", stb.c_str ());
> }
>
> /* Prepare to exit GDB cleanly by undoing any changes made to the
> diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
> index 18b569e..2da6fdd 100644
> --- a/gdb/tracepoint.c
> +++ b/gdb/tracepoint.c
> @@ -1304,12 +1304,11 @@ collection_list::stringify ()
> void
> collection_list::append_exp (struct expression *exp)
> {
> - struct ui_file *tmp_stream = mem_fileopen ();
> + string_file tmp_stream;
>
> - print_expression (exp, tmp_stream);
> + print_expression (exp, &tmp_stream);
>
> - m_computed.push_back (ui_file_as_string (tmp_stream));
> - ui_file_delete (tmp_stream);
> + m_computed.push_back (std::move (tmp_stream.string ()));
> }
>
> void
> diff --git a/gdb/tui/tui-disasm.c b/gdb/tui/tui-disasm.c
> index 2d1cadd..123a906 100644
> --- a/gdb/tui/tui-disasm.c
> +++ b/gdb/tui/tui-disasm.c
> @@ -54,10 +54,7 @@ static CORE_ADDR
> tui_disassemble (struct gdbarch *gdbarch, struct tui_asm_line *asm_lines,
> CORE_ADDR pc, int count)
> {
> - struct ui_file *gdb_dis_out;
> -
> - /* Now init the ui_file structure. */
> - gdb_dis_out = tui_sfileopen (256);
> + string_file gdb_dis_out;
>
> /* Now construct each line. */
> for (; count > 0; count--, asm_lines++)
> @@ -67,20 +64,19 @@ tui_disassemble (struct gdbarch *gdbarch, struct tui_asm_line *asm_lines,
> if (asm_lines->insn)
> xfree (asm_lines->insn);
>
> - print_address (gdbarch, pc, gdb_dis_out);
> + print_address (gdbarch, pc, &gdb_dis_out);
> asm_lines->addr = pc;
> - asm_lines->addr_string = xstrdup (tui_file_get_strbuf (gdb_dis_out));
> + asm_lines->addr_string = xstrdup (gdb_dis_out.c_str ());
>
> - ui_file_rewind (gdb_dis_out);
> + gdb_dis_out.clear ();
>
> - pc = pc + gdb_print_insn (gdbarch, pc, gdb_dis_out, NULL);
> + pc = pc + gdb_print_insn (gdbarch, pc, &gdb_dis_out, NULL);
>
> - asm_lines->insn = xstrdup (tui_file_get_strbuf (gdb_dis_out));
> + asm_lines->insn = xstrdup (gdb_dis_out.c_str ());
>
> /* Reset the buffer to empty. */
> - ui_file_rewind (gdb_dis_out);
> + gdb_dis_out.clear ();
> }
> - ui_file_delete (gdb_dis_out);
> return pc;
> }
>
> diff --git a/gdb/tui/tui-file.c b/gdb/tui/tui-file.c
> index 4dc6370..2f895b7 100644
> --- a/gdb/tui/tui-file.c
> +++ b/gdb/tui/tui-file.c
> @@ -17,145 +17,14 @@
> along with this program. If not, see <http://www.gnu.org/licenses/>. */
>
> #include "defs.h"
> -#include "ui-file.h"
> #include "tui/tui-file.h"
> #include "tui/tui-io.h"
> #include "tui/tui-command.h"
> #include "tui.h"
>
> -/* A ``struct ui_file'' that is compatible with all the legacy
> - code. */
> -
> -/* new */
> -enum streamtype
> -{
> - afile,
> - astring
> -};
> -
> -/* new */
> -struct tui_stream
> -{
> - int *ts_magic;
> - enum streamtype ts_streamtype;
> - FILE *ts_filestream;
> - char *ts_strbuf;
> - int ts_buflen;
> -};
> -
> -static ui_file_flush_ftype tui_file_flush;
> -extern ui_file_fputs_ftype tui_file_fputs;
> -static ui_file_isatty_ftype tui_file_isatty;
> -static ui_file_rewind_ftype tui_file_rewind;
> -static ui_file_put_ftype tui_file_put;
> -static ui_file_delete_ftype tui_file_delete;
> -static struct ui_file *tui_file_new (void);
> -static int tui_file_magic;
> -
> -static struct ui_file *
> -tui_file_new (void)
> -{
> - struct tui_stream *tui = XNEW (struct tui_stream);
> - struct ui_file *file = ui_file_new ();
> -
> - set_ui_file_data (file, tui, tui_file_delete);
> - set_ui_file_flush (file, tui_file_flush);
> - set_ui_file_fputs (file, tui_file_fputs);
> - set_ui_file_isatty (file, tui_file_isatty);
> - set_ui_file_rewind (file, tui_file_rewind);
> - set_ui_file_put (file, tui_file_put);
> - tui->ts_magic = &tui_file_magic;
> - return file;
> -}
> -
> -static void
> -tui_file_delete (struct ui_file *file)
> -{
> - struct tui_stream *tmpstream = (struct tui_stream *) ui_file_data (file);
> -
> - if (tmpstream->ts_magic != &tui_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("tui_file_delete: bad magic number"));
> - if ((tmpstream->ts_streamtype == astring)
> - && (tmpstream->ts_strbuf != NULL))
> - {
> - xfree (tmpstream->ts_strbuf);
> - }
> - xfree (tmpstream);
> -}
> -
> -struct ui_file *
> -tui_fileopen (FILE *stream)
> -{
> - struct ui_file *file = tui_file_new ();
> - struct tui_stream *tmpstream = (struct tui_stream *) ui_file_data (file);
> -
> - tmpstream->ts_streamtype = afile;
> - tmpstream->ts_filestream = stream;
> - tmpstream->ts_strbuf = NULL;
> - tmpstream->ts_buflen = 0;
> - return file;
> -}
> -
> -struct ui_file *
> -tui_sfileopen (int n)
> -{
> - struct ui_file *file = tui_file_new ();
> - struct tui_stream *tmpstream = (struct tui_stream *) ui_file_data (file);
> -
> - tmpstream->ts_streamtype = astring;
> - tmpstream->ts_filestream = NULL;
> - if (n > 0)
> - {
> - tmpstream->ts_strbuf = XNEWVEC (char, n + 1);
> - tmpstream->ts_strbuf[0] = '\0';
> - }
> - else
> - /* Do not allocate the buffer now. The first time something is
> - printed one will be allocated by tui_file_adjust_strbuf(). */
> - tmpstream->ts_strbuf = NULL;
> - tmpstream->ts_buflen = n;
> - return file;
> -}
> -
> -static int
> -tui_file_isatty (struct ui_file *file)
> -{
> - struct tui_stream *stream = (struct tui_stream *) ui_file_data (file);
> -
> - if (stream->ts_magic != &tui_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("tui_file_isatty: bad magic number"));
> - if (stream->ts_streamtype == afile)
> - return (isatty (fileno (stream->ts_filestream)));
> - else
> - return 0;
> -}
> -
> -static void
> -tui_file_rewind (struct ui_file *file)
> -{
> - struct tui_stream *stream = (struct tui_stream *) ui_file_data (file);
> -
> - if (stream->ts_magic != &tui_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("tui_file_rewind: bad magic number"));
> - stream->ts_strbuf[0] = '\0';
> -}
> -
> -static void
> -tui_file_put (struct ui_file *file,
> - ui_file_put_method_ftype *write,
> - void *dest)
> -{
> - struct tui_stream *stream = (struct tui_stream *) ui_file_data (file);
> -
> - if (stream->ts_magic != &tui_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("tui_file_put: bad magic number"));
> - if (stream->ts_streamtype == astring)
> - write (dest, stream->ts_strbuf, strlen (stream->ts_strbuf));
> -}
> +tui_file::tui_file (FILE *stream)
> + : stdio_file (stream)
> +{}
>
> /* All TUI I/O sent to the *_filtered and *_unfiltered functions
> eventually ends up here. The fputs_unfiltered_hook is primarily
> @@ -164,91 +33,22 @@ tui_file_put (struct ui_file *file,
> gdb_stderr are sent to the hook. Everything else is sent on to
> fputs to allow file I/O to be handled appropriately. */
>
> -/* FIXME: Should be broken up and moved to a TUI specific file. */
> -
> void
> -tui_file_fputs (const char *linebuffer, struct ui_file *file)
> -{
> - struct tui_stream *stream = (struct tui_stream *) ui_file_data (file);
> -
> - if (stream->ts_streamtype == astring)
> - {
> - tui_file_adjust_strbuf (strlen (linebuffer), file);
> - strcat (stream->ts_strbuf, linebuffer);
> - }
> - else
> - {
> - tui_puts (linebuffer);
> - /* gdb_stdout is buffered, and the caller must gdb_flush it at
> - appropriate times. Other streams are not so buffered. */
> - if (file != gdb_stdout)
> - tui_refresh_cmd_win ();
> - }
> -}
> -
> -char *
> -tui_file_get_strbuf (struct ui_file *file)
> +tui_file::puts (const char *linebuffer)
> {
> - struct tui_stream *stream = (struct tui_stream *) ui_file_data (file);
> -
> - if (stream->ts_magic != &tui_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("tui_file_get_strbuf: bad magic number"));
> - return (stream->ts_strbuf);
> + tui_puts (linebuffer);
> + /* gdb_stdout is buffered, and the caller must gdb_flush it at
> + appropriate times. Other streams are not so buffered. */
> + if (this != gdb_stdout)
> + tui_refresh_cmd_win ();
> }
>
> -/* Adjust the length of the buffer by the amount necessary to
> - accomodate appending a string of length N to the buffer
> - contents. */
> void
> -tui_file_adjust_strbuf (int n, struct ui_file *file)
> -{
> - struct tui_stream *stream = (struct tui_stream *) ui_file_data (file);
> - int non_null_chars;
> -
> - if (stream->ts_magic != &tui_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("tui_file_adjust_strbuf: bad magic number"));
> -
> - if (stream->ts_streamtype != astring)
> - return;
> -
> - if (stream->ts_strbuf)
> - {
> - /* There is already a buffer allocated. */
> - non_null_chars = strlen (stream->ts_strbuf);
> -
> - if (n > (stream->ts_buflen - non_null_chars - 1))
> - {
> - stream->ts_buflen = n + non_null_chars + 1;
> - stream->ts_strbuf
> - = XRESIZEVEC (char, stream->ts_strbuf, stream->ts_buflen);
> - }
> - }
> - else
> - /* No buffer yet, so allocate one of the desired size. */
> - stream->ts_strbuf = XNEWVEC (char, n + 1);
> -}
> -
> -static void
> -tui_file_flush (struct ui_file *file)
> +tui_file::flush ()
> {
> - struct tui_stream *stream = (struct tui_stream *) ui_file_data (file);
> -
> - if (stream->ts_magic != &tui_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("tui_file_flush: bad magic number"));
> -
> - switch (stream->ts_streamtype)
> - {
> - case astring:
> - break;
> - case afile:
> - /* gdb_stdout is buffered. Other files are always flushed on
> - every write. */
> - if (file == gdb_stdout)
> - tui_refresh_cmd_win ();
> - fflush (stream->ts_filestream);
> - break;
> - }
> + /* gdb_stdout is buffered. Other files are always flushed on
> + every write. */
> + if (this == gdb_stdout)
> + tui_refresh_cmd_win ();
> + stdio_file::flush ();
> }
> diff --git a/gdb/tui/tui-file.h b/gdb/tui/tui-file.h
> index 0e90cdf..aceaab6 100644
> --- a/gdb/tui/tui-file.h
> +++ b/gdb/tui/tui-file.h
> @@ -1,4 +1,4 @@
> -/* UI_FILE - a generic STDIO like output stream.
> +/* TUI_FILE - a STDIO-like output stream for the TUI.
> Copyright (C) 1999-2017 Free Software Foundation, Inc.
>
> This file is part of GDB.
> @@ -19,9 +19,17 @@
> #ifndef TUI_FILE_H
> #define TUI_FILE_H
>
> -extern struct ui_file *tui_fileopen (FILE *);
> -extern struct ui_file *tui_sfileopen (int);
> -extern char *tui_file_get_strbuf (struct ui_file *);
> -extern void tui_file_adjust_strbuf (int, struct ui_file *);
> +#include "ui-file.h"
> +
> +/* A STDIO-like output stream for the TUI. */
> +
> +class tui_file : public stdio_file
> +{
> +public:
> + explicit tui_file (FILE *stream);
> +
> + void flush () override;
> + void puts (const char *) override;
> +};
>
> #endif
> diff --git a/gdb/tui/tui-io.c b/gdb/tui/tui-io.c
> index 6f00f84..433762b 100644
> --- a/gdb/tui/tui-io.c
> +++ b/gdb/tui/tui-io.c
> @@ -528,8 +528,8 @@ tui_initialize_io (void)
> #endif
>
> /* Create tui output streams. */
> - tui_stdout = tui_fileopen (stdout);
> - tui_stderr = tui_fileopen (stderr);
> + tui_stdout = new tui_file (stdout);
> + tui_stderr = new tui_file (stderr);
> tui_out = tui_out_new (tui_stdout);
>
> /* Create the default UI. */
> diff --git a/gdb/tui/tui-regs.c b/gdb/tui/tui-regs.c
> index fc7913b..7d116ee8 100644
> --- a/gdb/tui/tui-regs.c
> +++ b/gdb/tui/tui-regs.c
> @@ -711,7 +711,7 @@ TUI command to control the register window."), tuicmd);
> static void
> tui_restore_gdbout (void *ui)
> {
> - ui_file_delete (gdb_stdout);
> + delete gdb_stdout;
> gdb_stdout = (struct ui_file*) ui;
> pagination_enabled = 1;
> }
> @@ -723,29 +723,26 @@ static char *
> tui_register_format (struct frame_info *frame, int regnum)
> {
> struct gdbarch *gdbarch = get_frame_arch (frame);
> - struct ui_file *stream;
> struct ui_file *old_stdout;
> struct cleanup *cleanups;
> char *p, *s;
> char *ret;
>
> + string_file stream;
> +
> pagination_enabled = 0;
> old_stdout = gdb_stdout;
> - stream = tui_sfileopen (256);
> - gdb_stdout = stream;
> + gdb_stdout = &stream;
> cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
> - gdbarch_print_registers_info (gdbarch, stream, frame, regnum, 1);
> -
> - /* Save formatted output in the buffer. */
> - p = tui_file_get_strbuf (stream);
> + gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
>
> /* Remove the possible \n. */
> - s = strrchr (p, '\n');
> - if (s && s[1] == 0)
> - *s = 0;
> + std::string &str = stream.string ();
> + if (!str.empty () && str.back () == '\n')
> + str.resize (str.size () - 1);
>
> /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
> - ret = tui_expand_tabs (p, 0);
> + ret = tui_expand_tabs (str.c_str (), 0);
>
> do_cleanups (cleanups);
>
> diff --git a/gdb/tui/tui-stack.c b/gdb/tui/tui-stack.c
> index 945a716..21a8bac 100644
> --- a/gdb/tui/tui-stack.c
> +++ b/gdb/tui/tui-stack.c
> @@ -68,12 +68,9 @@ tui_make_status_line (struct tui_locator_element *loc)
> int status_size;
> int i, proc_width;
> const char *pid_name;
> - const char *pc_buf;
> int target_width;
> int pid_width;
> int line_width;
> - int pc_width;
> - struct ui_file *pc_out;
>
> if (ptid_equal (inferior_ptid, null_ptid))
> pid_name = "No process";
> @@ -102,12 +99,14 @@ tui_make_status_line (struct tui_locator_element *loc)
> line_width = MIN_LINE_WIDTH;
>
> /* Translate PC address. */
> - pc_out = tui_sfileopen (128);
> + string_file pc_out;
> +
> fputs_filtered (loc->gdbarch? paddress (loc->gdbarch, loc->addr) : "??",
> - pc_out);
> - pc_buf = tui_file_get_strbuf (pc_out);
> - pc_width = strlen (pc_buf);
> -
> + &pc_out);
> +
> + const char *pc_buf = pc_out.c_str ();
> + int pc_width = pc_out.size ();
> +
> /* First determine the amount of proc name width we have available.
> The +1 are for a space separator between fields.
> The -1 are to take into account the \0 counted by sizeof. */
> @@ -204,7 +203,6 @@ tui_make_status_line (struct tui_locator_element *loc)
> string[i] = ' ';
> string[status_size] = (char) 0;
>
> - ui_file_delete (pc_out);
> return string;
> }
>
> @@ -215,21 +213,21 @@ static char*
> tui_get_function_from_frame (struct frame_info *fi)
> {
> static char name[256];
> - struct ui_file *stream = tui_sfileopen (256);
> - char *p;
> + string_file stream;
>
> print_address_symbolic (get_frame_arch (fi), get_frame_pc (fi),
> - stream, demangle, "");
> - p = tui_file_get_strbuf (stream);
> + &stream, demangle, "");
>
> /* Use simple heuristics to isolate the function name. The symbol
> can be demangled and we can have function parameters. Remove
> them because the status line is too short to display them. */
> - if (*p == '<')
> - p++;
> - strncpy (name, p, sizeof (name) - 1);
> + const char *d = stream.c_str ();
> + if (*d == '<')
> + d++;
> + strncpy (name, d, sizeof (name) - 1);
> name[sizeof (name) - 1] = 0;
> - p = strchr (name, '(');
> +
> + char *p = strchr (name, '(');
> if (!p)
> p = strchr (name, '>');
> if (p)
> @@ -237,7 +235,6 @@ tui_get_function_from_frame (struct frame_info *fi)
> p = strchr (name, '+');
> if (p)
> *p = 0;
> - ui_file_delete (stream);
> return name;
> }
>
> diff --git a/gdb/typeprint.c b/gdb/typeprint.c
> index 56e993e..a22c6fb 100644
> --- a/gdb/typeprint.c
> +++ b/gdb/typeprint.c
> @@ -371,26 +371,19 @@ type_print (struct type *type, const char *varstring, struct ui_file *stream,
> std::string
> type_to_string (struct type *type)
> {
> - std::string s;
> - struct ui_file *stb;
> - struct cleanup *old_chain;
> -
> - stb = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (stb);
> -
> TRY
> {
> - type_print (type, "", stb, -1);
> - s = ui_file_as_string (stb);
> + string_file stb;
> +
> + type_print (type, "", &stb, -1);
> + return std::move (stb.string ());
> }
> CATCH (except, RETURN_MASK_ALL)
> {
> }
> END_CATCH
>
> - do_cleanups (old_chain);
> -
> - return s;
> + return {};
> }
>
> /* Print type of EXP, or last thing in value history if EXP == NULL.
> diff --git a/gdb/ui-file.c b/gdb/ui-file.c
> index 3dce511..60e3274 100644
> --- a/gdb/ui-file.c
> +++ b/gdb/ui-file.c
> @@ -25,193 +25,80 @@
> #include "gdb_select.h"
> #include "filestuff.h"
>
> -static ui_file_isatty_ftype null_file_isatty;
> -static ui_file_write_ftype null_file_write;
> -static ui_file_write_ftype null_file_write_async_safe;
> -static ui_file_fputs_ftype null_file_fputs;
> -static ui_file_read_ftype null_file_read;
> -static ui_file_flush_ftype null_file_flush;
> -static ui_file_delete_ftype null_file_delete;
> -static ui_file_rewind_ftype null_file_rewind;
> -static ui_file_put_ftype null_file_put;
> -static ui_file_fseek_ftype null_file_fseek;
> -
> -struct ui_file
> - {
> - int *magic;
> - ui_file_flush_ftype *to_flush;
> - ui_file_write_ftype *to_write;
> - ui_file_write_async_safe_ftype *to_write_async_safe;
> - ui_file_fputs_ftype *to_fputs;
> - ui_file_read_ftype *to_read;
> - ui_file_delete_ftype *to_delete;
> - ui_file_isatty_ftype *to_isatty;
> - ui_file_rewind_ftype *to_rewind;
> - ui_file_put_ftype *to_put;
> - ui_file_fseek_ftype *to_fseek;
> - void *to_data;
> - };
> -int ui_file_magic;
> -
> -struct ui_file *
> -ui_file_new (void)
> -{
> - struct ui_file *file = XNEW (struct ui_file);
> -
> - file->magic = &ui_file_magic;
> - set_ui_file_data (file, NULL, null_file_delete);
> - set_ui_file_flush (file, null_file_flush);
> - set_ui_file_write (file, null_file_write);
> - set_ui_file_write_async_safe (file, null_file_write_async_safe);
> - set_ui_file_fputs (file, null_file_fputs);
> - set_ui_file_read (file, null_file_read);
> - set_ui_file_isatty (file, null_file_isatty);
> - set_ui_file_rewind (file, null_file_rewind);
> - set_ui_file_put (file, null_file_put);
> - set_ui_file_fseek (file, null_file_fseek);
> - return file;
> -}
> +null_file null_stream;
>
> -void
> -ui_file_delete (struct ui_file *file)
> -{
> - file->to_delete (file);
> - xfree (file);
> -}
> +ui_file::ui_file ()
> +{}
>
> -static int
> -null_file_isatty (struct ui_file *file)
> -{
> - return 0;
> -}
> +ui_file::~ui_file ()
> +{}
>
> -static void
> -null_file_rewind (struct ui_file *file)
> +void
> +ui_file::printf (const char *format, ...)
> {
> - return;
> -}
> + va_list args;
>
> -static void
> -null_file_put (struct ui_file *file,
> - ui_file_put_method_ftype *write,
> - void *dest)
> -{
> - return;
> + va_start (args, format);
> + vfprintf_unfiltered (this, format, args);
> + va_end (args);
> }
>
> -static void
> -null_file_flush (struct ui_file *file)
> +void
> +ui_file::putstr (const char *str, int quoter)
> {
> - return;
> + fputstr_unfiltered (str, quoter, this);
> }
>
> -static void
> -null_file_write (struct ui_file *file,
> - const char *buf,
> - long sizeof_buf)
> +void
> +ui_file::putstrn (const char *str, int n, int quoter)
> {
> - if (file->to_fputs == null_file_fputs)
> - /* Both the write and fputs methods are null. Discard the
> - request. */
> - return;
> - else
> - {
> - /* The fputs method isn't null, slowly pass the write request
> - onto that. FYI, this isn't as bad as it may look - the
> - current (as of 1999-11-07) printf_* function calls fputc and
> - fputc does exactly the below. By having a write function it
> - is possible to clean up that code. */
> - int i;
> - char b[2];
> -
> - b[1] = '\0';
> - for (i = 0; i < sizeof_buf; i++)
> - {
> - b[0] = buf[i];
> - file->to_fputs (b, file);
> - }
> - return;
> - }
> + fputstrn_unfiltered (str, n, quoter, this);
> }
>
> -static long
> -null_file_read (struct ui_file *file,
> - char *buf,
> - long sizeof_buf)
> +int
> +ui_file::putc (int c)
> {
> - errno = EBADF;
> - return 0;
> + return fputc_unfiltered (c, this);
> }
>
> -static void
> -null_file_fputs (const char *buf, struct ui_file *file)
> +void
> +ui_file::vprintf (const char *format, va_list args)
> {
> - if (file->to_write == null_file_write)
> - /* Both the write and fputs methods are null. Discard the
> - request. */
> - return;
> - else
> - {
> - /* The write method was implemented, use that. */
> - file->to_write (file, buf, strlen (buf));
> - }
> + vfprintf_unfiltered (this, format, args);
> }
>
> -static void
> -null_file_write_async_safe (struct ui_file *file,
> - const char *buf,
> - long sizeof_buf)
> -{
> - return;
> -}
> +\f
>
> -static void
> -null_file_delete (struct ui_file *file)
> +void
> +null_file::write (const char *buf, long sizeof_buf)
> {
> - return;
> + /* Discard the request. */
> }
>
> -static int
> -null_file_fseek (struct ui_file *stream, long offset, int whence)
> +void
> +null_file::puts (const char *)
> {
> - errno = EBADF;
> -
> - return -1;
> + /* Discard the request. */
> }
>
> -void *
> -ui_file_data (struct ui_file *file)
> +void
> +null_file::write_async_safe (const char *buf, long sizeof_buf)
> {
> - if (file->magic != &ui_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("ui_file_data: bad magic number"));
> - return file->to_data;
> + /* Discard the request. */
> }
>
> +\f
> +
> void
> gdb_flush (struct ui_file *file)
> {
> - file->to_flush (file);
> + file->flush ();
> }
>
> int
> ui_file_isatty (struct ui_file *file)
> {
> - return file->to_isatty (file);
> -}
> -
> -void
> -ui_file_rewind (struct ui_file *file)
> -{
> - file->to_rewind (file);
> -}
> -
> -void
> -ui_file_put (struct ui_file *file,
> - ui_file_put_method_ftype *write,
> - void *dest)
> -{
> - file->to_put (file, write, dest);
> + return file->isatty ();
> }
>
> void
> @@ -219,13 +106,7 @@ ui_file_write (struct ui_file *file,
> const char *buf,
> long length_buf)
> {
> - file->to_write (file, buf, length_buf);
> -}
> -
> -void
> -ui_file_write_for_put (void *data, const char *buffer, long length_buffer)
> -{
> - ui_file_write ((struct ui_file *) data, buffer, length_buffer);
> + file->write (buf, length_buf);
> }
>
> void
> @@ -233,622 +114,215 @@ ui_file_write_async_safe (struct ui_file *file,
> const char *buf,
> long length_buf)
> {
> - file->to_write_async_safe (file, buf, length_buf);
> + file->write_async_safe (buf, length_buf);
> }
>
> long
> ui_file_read (struct ui_file *file, char *buf, long length_buf)
> {
> - return file->to_read (file, buf, length_buf);
> -}
> -
> -int
> -ui_file_fseek (struct ui_file *file, long offset, int whence)
> -{
> - return file->to_fseek (file, offset, whence);
> + return file->read (buf, length_buf);
> }
>
> void
> fputs_unfiltered (const char *buf, struct ui_file *file)
> {
> - file->to_fputs (buf, file);
> + file->puts (buf);
> }
>
> -void
> -set_ui_file_flush (struct ui_file *file, ui_file_flush_ftype *flush_ptr)
> -{
> - file->to_flush = flush_ptr;
> -}
> -
> -void
> -set_ui_file_isatty (struct ui_file *file, ui_file_isatty_ftype *isatty_ptr)
> -{
> - file->to_isatty = isatty_ptr;
> -}
> -
> -void
> -set_ui_file_rewind (struct ui_file *file, ui_file_rewind_ftype *rewind_ptr)
> -{
> - file->to_rewind = rewind_ptr;
> -}
> +\f
>
> -void
> -set_ui_file_put (struct ui_file *file, ui_file_put_ftype *put_ptr)
> -{
> - file->to_put = put_ptr;
> -}
> +string_file::~string_file ()
> +{}
>
> void
> -set_ui_file_write (struct ui_file *file,
> - ui_file_write_ftype *write_ptr)
> +string_file::write (const char *buf, long length_buf)
> {
> - file->to_write = write_ptr;
> + m_string.append (buf, length_buf);
> }
>
> -void
> -set_ui_file_write_async_safe (struct ui_file *file,
> - ui_file_write_async_safe_ftype *write_async_safe_ptr)
> -{
> - file->to_write_async_safe = write_async_safe_ptr;
> -}
> +\f
>
> -void
> -set_ui_file_read (struct ui_file *file, ui_file_read_ftype *read_ptr)
> +stdio_file::stdio_file (FILE *file, bool close_p)
> {
> - file->to_read = read_ptr;
> + set_stream (file);
> + m_close_p = close_p;
> }
>
> -void
> -set_ui_file_fputs (struct ui_file *file, ui_file_fputs_ftype *fputs_ptr)
> -{
> - file->to_fputs = fputs_ptr;
> -}
> +stdio_file::stdio_file ()
> + : m_file (NULL),
> + m_fd (-1),
> + m_close_p (false)
> +{}
>
> -void
> -set_ui_file_fseek (struct ui_file *file, ui_file_fseek_ftype *fseek_ptr)
> +stdio_file::~stdio_file ()
> {
> - file->to_fseek = fseek_ptr;
> + if (m_close_p)
> + fclose (m_file);
> }
>
> void
> -set_ui_file_data (struct ui_file *file, void *data,
> - ui_file_delete_ftype *delete_ptr)
> +stdio_file::set_stream (FILE *file)
> {
> - file->to_data = data;
> - file->to_delete = delete_ptr;
> + m_file = file;
> + m_fd = fileno (file);
> }
>
> -/* ui_file utility function for converting a ``struct ui_file'' into
> - a memory buffer. */
> -
> -struct accumulated_ui_file
> +bool
> +stdio_file::open (const char *name, const char *mode)
> {
> - char *buffer;
> - long length;
> -};
> -
> -static void
> -do_ui_file_xstrdup (void *context, const char *buffer, long length)
> -{
> - struct accumulated_ui_file *acc = (struct accumulated_ui_file *) context;
> -
> - if (acc->buffer == NULL)
> - acc->buffer = (char *) xmalloc (length + 1);
> - else
> - acc->buffer = (char *) xrealloc (acc->buffer, acc->length + length + 1);
> - memcpy (acc->buffer + acc->length, buffer, length);
> - acc->length += length;
> - acc->buffer[acc->length] = '\0';
> -}
> -
> -char *
> -ui_file_xstrdup (struct ui_file *file, long *length)
> -{
> - struct accumulated_ui_file acc;
> -
> - acc.buffer = NULL;
> - acc.length = 0;
> - ui_file_put (file, do_ui_file_xstrdup, &acc);
> - if (acc.buffer == NULL)
> - acc.buffer = xstrdup ("");
> - if (length != NULL)
> - *length = acc.length;
> - return acc.buffer;
> -}
> -
> -/* ui_file utility function for converting a ``struct ui_file'' into a
> - std:string. */
> -
> -static void
> -do_ui_file_as_string (void *context, const char *buffer, long length)
> -{
> - std::string *str = (std::string *) context;
> -
> - *str = std::string (buffer, length);
> -}
> -
> -/* See ui-file.h. */
> -
> -std::string
> -ui_file_as_string (struct ui_file *file)
> -{
> - std::string str;
> -
> - ui_file_put (file, do_ui_file_as_string, &str);
> - return str;
> -}
> -
> -static void
> -do_ui_file_obsavestring (void *context, const char *buffer, long length)
> -{
> - struct obstack *obstack = (struct obstack *) context;
> -
> - obstack_grow (obstack, buffer, length);
> -}
> -
> -char *
> -ui_file_obsavestring (struct ui_file *file, struct obstack *obstack,
> - long *length)
> -{
> - ui_file_put (file, do_ui_file_obsavestring, obstack);
> - *length = obstack_object_size (obstack);
> - obstack_1grow (obstack, '\0');
> - return (char *) obstack_finish (obstack);
> -}
> -\f
> -/* A pure memory based ``struct ui_file'' that can be used an output
> - buffer. The buffers accumulated contents are available via
> - ui_file_put(). */
> -
> -struct mem_file
> - {
> - int *magic;
> - char *buffer;
> - int sizeof_buffer;
> - int length_buffer;
> - };
> -
> -static ui_file_rewind_ftype mem_file_rewind;
> -static ui_file_put_ftype mem_file_put;
> -static ui_file_write_ftype mem_file_write;
> -static ui_file_delete_ftype mem_file_delete;
> -static struct ui_file *mem_file_new (void);
> -static int mem_file_magic;
> -
> -static struct ui_file *
> -mem_file_new (void)
> -{
> - struct mem_file *stream = XNEW (struct mem_file);
> - struct ui_file *file = ui_file_new ();
> -
> - set_ui_file_data (file, stream, mem_file_delete);
> - set_ui_file_rewind (file, mem_file_rewind);
> - set_ui_file_put (file, mem_file_put);
> - set_ui_file_write (file, mem_file_write);
> - stream->magic = &mem_file_magic;
> - stream->buffer = NULL;
> - stream->sizeof_buffer = 0;
> - stream->length_buffer = 0;
> - return file;
> -}
> -
> -static void
> -mem_file_delete (struct ui_file *file)
> -{
> - struct mem_file *stream = (struct mem_file *) ui_file_data (file);
> + /* Close the previous stream, if we own it. */
> + if (m_close_p)
> + {
> + fclose (m_file);
> + m_close_p = false;
> + }
>
> - if (stream->magic != &mem_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("mem_file_delete: bad magic number"));
> - if (stream->buffer != NULL)
> - xfree (stream->buffer);
> - xfree (stream);
> -}
> + FILE *f = gdb_fopen_cloexec (name, mode);
>
> -struct ui_file *
> -mem_fileopen (void)
> -{
> - return mem_file_new ();
> -}
> + if (f == NULL)
> + return false;
>
> -static void
> -mem_file_rewind (struct ui_file *file)
> -{
> - struct mem_file *stream = (struct mem_file *) ui_file_data (file);
> + set_stream (f);
> + m_close_p = true;
>
> - if (stream->magic != &mem_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("mem_file_rewind: bad magic number"));
> - stream->length_buffer = 0;
> -}
> -
> -static void
> -mem_file_put (struct ui_file *file,
> - ui_file_put_method_ftype *write,
> - void *dest)
> -{
> - struct mem_file *stream = (struct mem_file *) ui_file_data (file);
> -
> - if (stream->magic != &mem_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("mem_file_put: bad magic number"));
> - if (stream->length_buffer > 0)
> - write (dest, stream->buffer, stream->length_buffer);
> + return true;
> }
>
> void
> -mem_file_write (struct ui_file *file,
> - const char *buffer,
> - long length_buffer)
> -{
> - struct mem_file *stream = (struct mem_file *) ui_file_data (file);
> -
> - if (stream->magic != &mem_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("mem_file_write: bad magic number"));
> - if (stream->buffer == NULL)
> - {
> - stream->length_buffer = length_buffer;
> - stream->sizeof_buffer = length_buffer;
> - stream->buffer = (char *) xmalloc (stream->sizeof_buffer);
> - memcpy (stream->buffer, buffer, length_buffer);
> - }
> - else
> - {
> - int new_length = stream->length_buffer + length_buffer;
> -
> - if (new_length >= stream->sizeof_buffer)
> - {
> - stream->sizeof_buffer = new_length;
> - stream->buffer
> - = (char *) xrealloc (stream->buffer, stream->sizeof_buffer);
> - }
> - memcpy (stream->buffer + stream->length_buffer, buffer, length_buffer);
> - stream->length_buffer = new_length;
> - }
> -}
> -\f
> -/* ``struct ui_file'' implementation that maps directly onto
> - <stdio.h>'s FILE. */
> -
> -static ui_file_write_ftype stdio_file_write;
> -static ui_file_write_async_safe_ftype stdio_file_write_async_safe;
> -static ui_file_fputs_ftype stdio_file_fputs;
> -static ui_file_read_ftype stdio_file_read;
> -static ui_file_isatty_ftype stdio_file_isatty;
> -static ui_file_delete_ftype stdio_file_delete;
> -static struct ui_file *stdio_file_new (FILE *file, int close_p);
> -static ui_file_flush_ftype stdio_file_flush;
> -static ui_file_fseek_ftype stdio_file_fseek;
> -
> -static int stdio_file_magic;
> -
> -struct stdio_file
> - {
> - int *magic;
> - FILE *file;
> - /* The associated file descriptor is extracted ahead of time for
> - stdio_file_write_async_safe's benefit, in case fileno isn't async-safe. */
> - int fd;
> - int close_p;
> - };
> -
> -static struct ui_file *
> -stdio_file_new (FILE *file, int close_p)
> -{
> - struct ui_file *ui_file = ui_file_new ();
> - struct stdio_file *stdio = XNEW (struct stdio_file);
> -
> - stdio->magic = &stdio_file_magic;
> - stdio->file = file;
> - stdio->fd = fileno (file);
> - stdio->close_p = close_p;
> - set_ui_file_data (ui_file, stdio, stdio_file_delete);
> - set_ui_file_flush (ui_file, stdio_file_flush);
> - set_ui_file_write (ui_file, stdio_file_write);
> - set_ui_file_write_async_safe (ui_file, stdio_file_write_async_safe);
> - set_ui_file_fputs (ui_file, stdio_file_fputs);
> - set_ui_file_read (ui_file, stdio_file_read);
> - set_ui_file_isatty (ui_file, stdio_file_isatty);
> - set_ui_file_fseek (ui_file, stdio_file_fseek);
> - return ui_file;
> -}
> -
> -static void
> -stdio_file_delete (struct ui_file *file)
> -{
> - struct stdio_file *stdio = (struct stdio_file *) ui_file_data (file);
> -
> - if (stdio->magic != &stdio_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("stdio_file_delete: bad magic number"));
> - if (stdio->close_p)
> - {
> - fclose (stdio->file);
> - }
> - xfree (stdio);
> -}
> -
> -static void
> -stdio_file_flush (struct ui_file *file)
> +stdio_file::flush ()
> {
> - struct stdio_file *stdio = (struct stdio_file *) ui_file_data (file);
> -
> - if (stdio->magic != &stdio_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("stdio_file_flush: bad magic number"));
> - fflush (stdio->file);
> + fflush (m_file);
> }
>
> -static long
> -stdio_file_read (struct ui_file *file, char *buf, long length_buf)
> +long
> +stdio_file::read (char *buf, long length_buf)
> {
> - struct stdio_file *stdio = (struct stdio_file *) ui_file_data (file);
> -
> - if (stdio->magic != &stdio_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("stdio_file_read: bad magic number"));
> -
> /* Wait until at least one byte of data is available, or we get
> interrupted with Control-C. */
> {
> fd_set readfds;
>
> FD_ZERO (&readfds);
> - FD_SET (stdio->fd, &readfds);
> - if (interruptible_select (stdio->fd + 1, &readfds, NULL, NULL, NULL) == -1)
> + FD_SET (m_fd, &readfds);
> + if (interruptible_select (m_fd + 1, &readfds, NULL, NULL, NULL) == -1)
> return -1;
> }
>
> - return read (stdio->fd, buf, length_buf);
> + return ::read (m_fd, buf, length_buf);
> }
>
> -static void
> -stdio_file_write (struct ui_file *file, const char *buf, long length_buf)
> +void
> +stdio_file::write (const char *buf, long length_buf)
> {
> - struct stdio_file *stdio = (struct stdio_file *) ui_file_data (file);
> -
> - if (stdio->magic != &stdio_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("stdio_file_write: bad magic number"));
> /* Calling error crashes when we are called from the exception framework. */
> - if (fwrite (buf, length_buf, 1, stdio->file))
> + if (fwrite (buf, length_buf, 1, m_file))
> {
> /* Nothing. */
> }
> }
>
> -static void
> -stdio_file_write_async_safe (struct ui_file *file,
> - const char *buf, long length_buf)
> +void
> +stdio_file::write_async_safe (const char *buf, long length_buf)
> {
> - struct stdio_file *stdio = (struct stdio_file *) ui_file_data (file);
> -
> - if (stdio->magic != &stdio_file_magic)
> - {
> - /* gettext isn't necessarily async safe, so we can't use _("error message") here.
> - We could extract the correct translation ahead of time, but this is an extremely
> - rare event, and one of the other stdio_file_* routines will presumably catch
> - the problem anyway. For now keep it simple and ignore the error here. */
> - return;
> - }
> -
> /* This is written the way it is to avoid a warning from gcc about not using the
> result of write (since it can be declared with attribute warn_unused_result).
> Alas casting to void doesn't work for this. */
> - if (write (stdio->fd, buf, length_buf))
> + if (::write (m_fd, buf, length_buf))
> {
> /* Nothing. */
> }
> }
>
> -static void
> -stdio_file_fputs (const char *linebuffer, struct ui_file *file)
> +void
> +stdio_file::puts (const char *linebuffer)
> {
> - struct stdio_file *stdio = (struct stdio_file *) ui_file_data (file);
> -
> - if (stdio->magic != &stdio_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("stdio_file_fputs: bad magic number"));
> /* Calling error crashes when we are called from the exception framework. */
> - if (fputs (linebuffer, stdio->file))
> + if (fputs (linebuffer, m_file))
> {
> /* Nothing. */
> }
> }
>
> -static int
> -stdio_file_isatty (struct ui_file *file)
> +bool
> +stdio_file::isatty ()
> {
> - struct stdio_file *stdio = (struct stdio_file *) ui_file_data (file);
> -
> - if (stdio->magic != &stdio_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("stdio_file_isatty: bad magic number"));
> - return (isatty (stdio->fd));
> + return ::isatty (m_fd);
> }
>
> -static int
> -stdio_file_fseek (struct ui_file *file, long offset, int whence)
> -{
> - struct stdio_file *stdio = (struct stdio_file *) ui_file_data (file);
> -
> - if (stdio->magic != &stdio_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("stdio_file_fseek: bad magic number"));
> -
> - return fseek (stdio->file, offset, whence);
> -}
> +\f
>
> -#ifdef __MINGW32__
> -/* This is the implementation of ui_file method to_write for stderr.
> +/* This is the implementation of ui_file method 'write' for stderr.
> gdb_stdout is flushed before writing to gdb_stderr. */
>
> -static void
> -stderr_file_write (struct ui_file *file, const char *buf, long length_buf)
> +void
> +stderr_file::write (const char *buf, long length_buf)
> {
> gdb_flush (gdb_stdout);
> - stdio_file_write (file, buf, length_buf);
> + stdio_file::write (buf, length_buf);
> }
>
> -/* This is the implementation of ui_file method to_fputs for stderr.
> +/* This is the implementation of ui_file method 'puts' for stderr.
> gdb_stdout is flushed before writing to gdb_stderr. */
>
> -static void
> -stderr_file_fputs (const char *linebuffer, struct ui_file *file)
> +void
> +stderr_file::puts (const char *linebuffer)
> {
> gdb_flush (gdb_stdout);
> - stdio_file_fputs (linebuffer, file);
> + stdio_file::puts (linebuffer);
> }
> -#endif
> -
> -struct ui_file *
> -stderr_fileopen (FILE *stream)
> -{
> - struct ui_file *ui_file = stdio_fileopen (stream);
> -
> -#ifdef __MINGW32__
> - /* There is no real line-buffering on Windows, see
> - http://msdn.microsoft.com/en-us/library/86cebhfs%28v=vs.71%29.aspx
> - so the stdout is either fully-buffered or non-buffered. We can't
> - make stdout non-buffered, because of two concerns,
> - 1. non-buffering hurts performance,
> - 2. non-buffering may change GDB's behavior when it is interacting
> - with front-end, such as Emacs.
> -
> - We decided to leave stdout as fully buffered, but flush it first
> - when something is written to stderr. */
> -
> - /* Method 'to_write_async_safe' is not overwritten, because there's
> - no way to flush a stream in an async-safe manner. Fortunately,
> - it doesn't really matter, because:
> - - that method is only used for printing internal debug output
> - from signal handlers.
> - - Windows hosts don't have a concept of async-safeness. Signal
> - handlers run in a separate thread, so they can call
> - the regular non-async-safe output routines freely. */
> - set_ui_file_write (ui_file, stderr_file_write);
> - set_ui_file_fputs (ui_file, stderr_file_fputs);
> -#endif
>
> - return ui_file;
> -}
> -
> -/* Like fdopen(). Create a ui_file from a previously opened FILE. */
> -
> -struct ui_file *
> -stdio_fileopen (FILE *file)
> -{
> - return stdio_file_new (file, 0);
> -}
> +stderr_file::stderr_file (FILE *stream)
> + : stdio_file (stream)
> +{}
>
> -struct ui_file *
> -gdb_fopen (const char *name, const char *mode)
> -{
> - FILE *f = gdb_fopen_cloexec (name, mode);
> -
> - if (f == NULL)
> - return NULL;
> - return stdio_file_new (f, 1);
> -}
> -
> -/* ``struct ui_file'' implementation that maps onto two ui-file objects. */
> -
> -static ui_file_write_ftype tee_file_write;
> -static ui_file_fputs_ftype tee_file_fputs;
> -static ui_file_isatty_ftype tee_file_isatty;
> -static ui_file_delete_ftype tee_file_delete;
> -static ui_file_flush_ftype tee_file_flush;
> +\f
>
> -static int tee_file_magic;
> +tee_file::tee_file (ui_file *one, bool close_one,
> + ui_file *two, bool close_two)
> + : m_one (one),
> + m_two (two),
> + m_close_one (close_one),
> + m_close_two (close_two)
> +{}
>
> -struct tee_file
> - {
> - int *magic;
> - struct ui_file *one, *two;
> - int close_one, close_two;
> - };
> -
> -struct ui_file *
> -tee_file_new (struct ui_file *one, int close_one,
> - struct ui_file *two, int close_two)
> +tee_file::~tee_file ()
> {
> - struct ui_file *ui_file = ui_file_new ();
> - struct tee_file *tee = XNEW (struct tee_file);
> -
> - tee->magic = &tee_file_magic;
> - tee->one = one;
> - tee->two = two;
> - tee->close_one = close_one;
> - tee->close_two = close_two;
> - set_ui_file_data (ui_file, tee, tee_file_delete);
> - set_ui_file_flush (ui_file, tee_file_flush);
> - set_ui_file_write (ui_file, tee_file_write);
> - set_ui_file_fputs (ui_file, tee_file_fputs);
> - set_ui_file_isatty (ui_file, tee_file_isatty);
> - return ui_file;
> + if (m_close_one)
> + delete m_one;
> + if (m_close_two)
> + delete m_two;
> }
>
> -static void
> -tee_file_delete (struct ui_file *file)
> +void
> +tee_file::flush ()
> {
> - struct tee_file *tee = (struct tee_file *) ui_file_data (file);
> -
> - if (tee->magic != &tee_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("tee_file_delete: bad magic number"));
> - if (tee->close_one)
> - ui_file_delete (tee->one);
> - if (tee->close_two)
> - ui_file_delete (tee->two);
> -
> - xfree (tee);
> + m_one->flush ();
> + m_two->flush ();
> }
>
> -static void
> -tee_file_flush (struct ui_file *file)
> +void
> +tee_file::write (const char *buf, long length_buf)
> {
> - struct tee_file *tee = (struct tee_file *) ui_file_data (file);
> -
> - if (tee->magic != &tee_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("tee_file_flush: bad magic number"));
> - tee->one->to_flush (tee->one);
> - tee->two->to_flush (tee->two);
> + m_one->write (buf, length_buf);
> + m_two->write (buf, length_buf);
> }
>
> -static void
> -tee_file_write (struct ui_file *file, const char *buf, long length_buf)
> +void
> +tee_file::write_async_safe (const char *buf, long length_buf)
> {
> - struct tee_file *tee = (struct tee_file *) ui_file_data (file);
> -
> - if (tee->magic != &tee_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("tee_file_write: bad magic number"));
> - ui_file_write (tee->one, buf, length_buf);
> - ui_file_write (tee->two, buf, length_buf);
> + m_one->write_async_safe (buf, length_buf);
> + m_two->write_async_safe (buf, length_buf);
> }
>
> -static void
> -tee_file_fputs (const char *linebuffer, struct ui_file *file)
> +void
> +tee_file::puts (const char *linebuffer)
> {
> - struct tee_file *tee = (struct tee_file *) ui_file_data (file);
> -
> - if (tee->magic != &tee_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("tee_file_fputs: bad magic number"));
> - tee->one->to_fputs (linebuffer, tee->one);
> - tee->two->to_fputs (linebuffer, tee->two);
> + m_one->puts (linebuffer);
> + m_two->puts (linebuffer);
> }
>
> -static int
> -tee_file_isatty (struct ui_file *file)
> +bool
> +tee_file::isatty ()
> {
> - struct tee_file *tee = (struct tee_file *) ui_file_data (file);
> -
> - if (tee->magic != &tee_file_magic)
> - internal_error (__FILE__, __LINE__,
> - _("tee_file_isatty: bad magic number"));
> -
> - return ui_file_isatty (tee->one);
> + return m_one->isatty ();
> }
> diff --git a/gdb/ui-file.h b/gdb/ui-file.h
> index 4ad3940..1cb9693 100644
> --- a/gdb/ui-file.h
> +++ b/gdb/ui-file.h
> @@ -19,140 +19,245 @@
> #ifndef UI_FILE_H
> #define UI_FILE_H
>
> -struct obstack;
> -struct ui_file;
> -
> #include <string>
>
> -/* Create a generic ui_file object with null methods. */
> +/* The abstract ui_file base class. */
> +
> +class ui_file
> +{
> +public:
> + ui_file ();
> + virtual ~ui_file () = 0;
> +
> + /* Public non-virtual API. */
>
> -extern struct ui_file *ui_file_new (void);
> + void printf (const char *, ...) ATTRIBUTE_PRINTF (2, 3);
>
> -/* Override methods used by specific implementations of a UI_FILE
> - object. */
> + /* Print a string whose delimiter is QUOTER. Note that these
> + routines should only be called for printing things which are
> + independent of the language of the program being debugged. */
> + void putstr (const char *str, int quoter);
>
> -typedef void (ui_file_flush_ftype) (struct ui_file *stream);
> -extern void set_ui_file_flush (struct ui_file *stream,
> - ui_file_flush_ftype *flush);
> + void putstrn (const char *str, int n, int quoter);
>
> -/* NOTE: Both fputs and write methods are available. Default
> - implementations that mapping one onto the other are included. */
> -typedef void (ui_file_write_ftype) (struct ui_file *stream,
> - const char *buf, long length_buf);
> -extern void set_ui_file_write (struct ui_file *stream,
> - ui_file_write_ftype *fputs);
> + int putc (int c);
>
> -typedef void (ui_file_fputs_ftype) (const char *, struct ui_file *stream);
> -extern void set_ui_file_fputs (struct ui_file *stream,
> - ui_file_fputs_ftype *fputs);
> + void vprintf (const char *, va_list) ATTRIBUTE_PRINTF (2, 0);
>
> -/* This version of "write" is safe for use in signal handlers.
> - It's not guaranteed that all existing output will have been
> - flushed first.
> - Implementations are also free to ignore some or all of the request.
> - fputs_async is not provided as the async versions are rarely used,
> - no point in having both for a rarely used interface. */
> -typedef void (ui_file_write_async_safe_ftype)
> - (struct ui_file *stream, const char *buf, long length_buf);
> -extern void set_ui_file_write_async_safe
> - (struct ui_file *stream, ui_file_write_async_safe_ftype *write_async_safe);
> + /* Methods below are both public, and overridable by ui_file
> + subclasses. */
>
> -typedef long (ui_file_read_ftype) (struct ui_file *stream,
> - char *buf, long length_buf);
> -extern void set_ui_file_read (struct ui_file *stream,
> - ui_file_read_ftype *fread);
> + virtual void write (const char *buf, long length_buf) = 0;
>
> -typedef int (ui_file_isatty_ftype) (struct ui_file *stream);
> -extern void set_ui_file_isatty (struct ui_file *stream,
> - ui_file_isatty_ftype *isatty);
> + /* This version of "write" is safe for use in signal handlers. It's
> + not guaranteed that all existing output will have been flushed
> + first. Implementations are also free to ignore some or all of
> + the request. puts_async is not provided as the async versions
> + are rarely used, no point in having both for a rarely used
> + interface. */
> + virtual void write_async_safe (const char *buf, long length_buf)
> + { gdb_assert_not_reached ("write_async_safe"); }
>
> -typedef void (ui_file_rewind_ftype) (struct ui_file *stream);
> -extern void set_ui_file_rewind (struct ui_file *stream,
> - ui_file_rewind_ftype *rewind);
> + virtual void puts (const char *str)
> + { this->write (str, strlen (str)); }
>
> -typedef void (ui_file_put_method_ftype) (void *object, const char *buffer,
> - long length_buffer);
> -typedef void (ui_file_put_ftype) (struct ui_file *stream,
> - ui_file_put_method_ftype *method,
> - void *context);
> -extern void set_ui_file_put (struct ui_file *stream, ui_file_put_ftype *put);
> + virtual long read (char *buf, long length_buf)
> + { gdb_assert_not_reached ("can't read from this file type"); }
>
> -typedef void (ui_file_delete_ftype) (struct ui_file * stream);
> -extern void set_ui_file_data (struct ui_file *stream, void *data,
> - ui_file_delete_ftype *to_delete);
> + virtual bool isatty ()
> + { return false; }
>
> -typedef int (ui_file_fseek_ftype) (struct ui_file *stream, long offset,
> - int whence);
> -extern void set_ui_file_fseek (struct ui_file *stream,
> - ui_file_fseek_ftype *fseek_ptr);
> + virtual void flush ()
> + {}
> +};
>
> -extern void *ui_file_data (struct ui_file *file);
> +typedef std::unique_ptr<ui_file> ui_file_up;
>
> +/* A ui_file that writes to nowhere. */
>
> -extern void gdb_flush (struct ui_file *);
> +class null_file : public ui_file
> +{
> +public:
> + void write (const char *buf, long length_buf) override;
> + void write_async_safe (const char *buf, long sizeof_buf) override;
> + void puts (const char *str) override;
> +};
>
> -extern void ui_file_delete (struct ui_file *stream);
> +/* A preallocated null_file stream. */
> +extern null_file null_stream;
>
> -extern void ui_file_rewind (struct ui_file *stream);
> +extern void gdb_flush (ui_file *);
>
> extern int ui_file_isatty (struct ui_file *);
>
> extern void ui_file_write (struct ui_file *file, const char *buf,
> long length_buf);
>
> -/* A wrapper for ui_file_write that is suitable for use by
> - ui_file_put. */
> -
> -extern void ui_file_write_for_put (void *data, const char *buffer,
> - long length_buffer);
> -
> extern void ui_file_write_async_safe (struct ui_file *file, const char *buf,
> long length_buf);
>
> -/* NOTE: copies left to right. */
> -extern void ui_file_put (struct ui_file *src,
> - ui_file_put_method_ftype *write, void *dest);
> +extern long ui_file_read (struct ui_file *file, char *buf, long length_buf);
>
> -/* Returns a freshly allocated buffer containing the entire contents
> - of FILE (as determined by ui_file_put()) with a NUL character
> - appended. LENGTH, if not NULL, is set to the size of the buffer
> - minus that appended NUL. */
> -extern char *ui_file_xstrdup (struct ui_file *file, long *length);
> +/* A std::string-based ui_file. Can be used as a scratch buffer for
> + collecting output. */
>
> -/* Returns a std::string containing the entire contents of FILE (as
> - determined by ui_file_put()). */
> -extern std::string ui_file_as_string (struct ui_file *file);
> +class string_file : public ui_file
> +{
> +public:
> + string_file () {}
> + ~string_file () override;
>
> -/* Similar to ui_file_xstrdup, but return a new string allocated on
> - OBSTACK. */
> -extern char *ui_file_obsavestring (struct ui_file *file,
> - struct obstack *obstack, long *length);
> + /* Override ui_file methods. */
>
> -extern long ui_file_read (struct ui_file *file, char *buf, long length_buf);
> + void write (const char *buf, long length_buf) override;
> +
> + long read (char *buf, long length_buf) override
> + { gdb_assert_not_reached ("a string_file is not readable"); }
> +
> + /* string_file-specific public API. */
> +
> + /* Accesses the std::string containing the entire output collected
> + so far.
> +
> + Returns a non-const reference so that it's easy to move the
> + string contents out of the string_file. E.g.:
> +
> + string_file buf;
> + buf.printf (....);
> + buf.printf (....);
> + return std::move (buf.string ());
> + */
> + std::string &string () { return m_string; }
> +
> + /* Provide a few convenience methods with the same API as the
> + underlying std::string. */
> + const char *data () const { return m_string.data (); }
> + const char *c_str () const { return m_string.c_str (); }
> + size_t size () const { return m_string.size (); }
> + bool empty () const { return m_string.empty (); }
> + void clear () { return m_string.clear (); }
> +
> +private:
> + /* The internal buffer. */
> + std::string m_string;
> +};
> +
> +/* A ui_file implementation that maps directly onto <stdio.h>'s FILE.
> + A stdio_file can either own its underlying file, or not. If it
> + owns the file, then destroying the stdio_file closes the underlying
> + file, otherwise it is left open. */
> +
> +class stdio_file : public ui_file
> +{
> +public:
> + /* Create a ui_file from a previously opened FILE. CLOSE_P
> + indicates whether the underlying file should be closed when the
> + stdio_file is destroyed. */
> + explicit stdio_file (FILE *file, bool close_p = false);
> +
> + /* Create an stdio_file that is not managing any file yet. Call
> + open to actually open something. */
> + stdio_file ();
> +
> + ~stdio_file () override;
> +
> + /* Open NAME in mode MODE, and own the resulting file. Returns true
> + on success, false otherwise. If the stdio_file previously owned
> + a file, it is closed. */
> + bool open (const char *name, const char *mode);
> +
> + void flush () override;
> +
> + void write (const char *buf, long length_buf) override;
> +
> + void write_async_safe (const char *buf, long length_buf) override;
> +
> + void puts (const char *) override;
> +
> + long read (char *buf, long length_buf) override;
> +
> + bool isatty () override;
> +
> +private:
> + /* Sets the internal stream to FILE, and saves the FILE's file
> + descriptor in M_FD. */
> + void set_stream (FILE *file);
> +
> + /* The file. */
> + FILE *m_file;
> +
> + /* The associated file descriptor is extracted ahead of time for
> + stdio_file::write_async_safe's benefit, in case fileno isn't
> + async-safe. */
> + int m_fd;
> +
> + /* If true, M_FILE is closed on destruction. */
> + bool m_close_p;
> +};
> +
> +typedef std::unique_ptr<stdio_file> stdio_file_up;
> +
> +/* Like stdio_file, but specifically for stderr.
> +
> + This exists because there is no real line-buffering on Windows, see
> + <http://msdn.microsoft.com/en-us/library/86cebhfs%28v=vs.71%29.aspx>
> + so the stdout is either fully-buffered or non-buffered. We can't
> + make stdout non-buffered, because of two concerns:
> +
> + 1. Non-buffering hurts performance.
> + 2. Non-buffering may change GDB's behavior when it is interacting
> + with a front-end, such as Emacs.
> +
> + We leave stdout as fully buffered, but flush it first when
> + something is written to stderr.
> +
> + Note the the 'write_async_safe' method is not overwritten, because
Extra "the".
Did you mean overridden instead of overwritten?
> + there's no way to flush a stream in an async-safe manner.
> + Fortunately, it doesn't really matter, because:
> +
> + 1. That method is only used for printing internal debug output
> + from signal handlers.
>
> -extern int ui_file_fseek (struct ui_file *file, long offset, int whence);
> + 2. Windows hosts don't have a concept of async-safeness. Signal
> + handlers run in a separate thread, so they can call the regular
> + non-async-safe output routines freely.
> +*/
> +class stderr_file : public stdio_file
> +{
> +public:
> + explicit stderr_file (FILE *stream);
>
> -/* Create/open a memory based file. Can be used as a scratch buffer
> - for collecting output. */
> -extern struct ui_file *mem_fileopen (void);
> + /* Flushes gdb_stdout before writing to the underlying stream. */
> + void write (const char *buf, long length_buf) override;
>
I noticed the above declaration and ...
> + /* Flushes gdb_stdout before writing to the underlying stream. */
> + void puts (const char *linebuffer) override;
... the above declaration both have the same documentation. Do they
accomplish the same?
> +};
>
> +/* A ui_file implementation that maps onto two ui-file objects. */
>
> -/* Open/create a STDIO based UI_FILE using the already open FILE. */
> -extern struct ui_file *stdio_fileopen (FILE *file);
> +class tee_file : public ui_file
> +{
> +public:
> + /* Create a file which writes to both ONE and TWO. CLOSE_ONE and
> + CLOSE_TWO indicate whether the original files should be closed
> + when the new file is closed. */
> + tee_file (ui_file *one, bool close_one,
> + ui_file *two, bool close_two);
> + ~tee_file () override;
>
> -/* Likewise, for stderr-like streams. */
> -extern struct ui_file *stderr_fileopen (FILE *file);
> + void write (const char *buf, long length_buf) override;
> + void write_async_safe (const char *buf, long length_buf) override;
> + void puts (const char *) override;
>
> + bool isatty () override;
> + void flush () override;
>
> -/* Open NAME returning an STDIO based UI_FILE. */
> -extern struct ui_file *gdb_fopen (const char *name, const char *mode);
> +private:
> + /* The two underlying ui_files, and whether they should each be
> + closed on destruction. */
> + ui_file *m_one, *m_two;
> + bool m_close_one, m_close_two;
> +};
>
> -/* Create a file which writes to both ONE and TWO. CLOSE_ONE
> - and CLOSE_TWO indicate whether the original files should be
> - closed when the new file is closed. */
> -extern struct ui_file *tee_file_new (struct ui_file *one,
> - int close_one,
> - struct ui_file *two,
> - int close_two);
> #endif
> diff --git a/gdb/ui-out.c b/gdb/ui-out.c
> index fdcd454..42cffbe 100644
> --- a/gdb/ui-out.c
> +++ b/gdb/ui-out.c
> @@ -529,15 +529,13 @@ ui_out::field_core_addr (const char *fldname, struct gdbarch *gdbarch,
> }
>
> void
> -ui_out::field_stream (const char *fldname, ui_file *stream)
> +ui_out::field_stream (const char *fldname, string_file &stream)
> {
> - std::string buffer = ui_file_as_string (stream);
> -
> - if (!buffer.empty ())
> - field_string (fldname, buffer.c_str ());
> + if (!stream.empty ())
> + field_string (fldname, stream.c_str ());
> else
> field_skip (fldname);
> - ui_file_rewind (stream);
> + stream.clear ();
> }
>
> /* Used to omit a field. */
> diff --git a/gdb/ui-out.h b/gdb/ui-out.h
> index b8bea97..d54843d 100644
> --- a/gdb/ui-out.h
> +++ b/gdb/ui-out.h
> @@ -108,7 +108,7 @@ class ui_out
> void field_core_addr (const char *fldname, struct gdbarch *gdbarch,
> CORE_ADDR address);
> void field_string (const char *fldname, const char *string);
> - void field_stream (const char *fldname, ui_file *stream);
> + void field_stream (const char *fldname, string_file &stream);
> void field_skip (const char *fldname);
> void field_fmt (const char *fldname, const char *format, ...)
> ATTRIBUTE_PRINTF (3, 4);
> diff --git a/gdb/utils.c b/gdb/utils.c
> index ab87143..3dc2f03 100644
> --- a/gdb/utils.c
> +++ b/gdb/utils.c
> @@ -187,33 +187,6 @@ make_cleanup_obstack_free (struct obstack *obstack)
> return make_cleanup (do_obstack_free, obstack);
> }
>
> -static void
> -do_ui_file_delete (void *arg)
> -{
> - ui_file_delete ((struct ui_file *) arg);
> -}
> -
> -struct cleanup *
> -make_cleanup_ui_file_delete (struct ui_file *arg)
> -{
> - return make_cleanup (do_ui_file_delete, arg);
> -}
> -
> -struct ui_file *
> -null_stream (void)
> -{
> - /* A simple implementation of singleton pattern. */
> - static struct ui_file *stream = NULL;
> -
> - if (stream == NULL)
> - {
> - stream = ui_file_new ();
> - /* Delete it on gdb exit. */
> - make_final_cleanup (do_ui_file_delete, stream);
> - }
> - return stream;
> -}
> -
> /* Helper function for make_cleanup_ui_out_redirect_pop. */
>
> static void
> @@ -460,11 +433,9 @@ verror (const char *string, va_list args)
> }
>
> void
> -error_stream (struct ui_file *stream)
> +error_stream (const string_file &stream)
> {
> - std::string message = ui_file_as_string (stream);
> -
> - error (("%s"), message.c_str ());
> + error (("%s"), stream.c_str ());
> }
>
> /* Emit a message and abort. */
> diff --git a/gdb/utils.h b/gdb/utils.h
> index 9e71cc2..f138702 100644
> --- a/gdb/utils.h
> +++ b/gdb/utils.h
> @@ -66,9 +66,6 @@ char **gdb_buildargv (const char *);
>
> extern struct cleanup *make_cleanup_freeargv (char **);
>
> -struct ui_file;
> -extern struct cleanup *make_cleanup_ui_file_delete (struct ui_file *);
> -
> struct ui_out;
> extern struct cleanup *
> make_cleanup_ui_out_redirect_pop (struct ui_out *uiout);
> @@ -189,9 +186,6 @@ extern struct ui_file *gdb_stdtarg;
> extern struct ui_file *gdb_stdtargerr;
> extern struct ui_file *gdb_stdtargin;
>
> -/* Return a null stream. */
> -extern struct ui_file *null_stream (void);
> -
> /* Set the screen dimensions to WIDTH and HEIGHT. */
>
> extern void set_screen_width_and_height (int width, int height);
> @@ -306,7 +300,7 @@ extern void (*deprecated_error_begin_hook) (void);
>
> extern char *warning_pre_print;
>
> -extern void error_stream (struct ui_file *) ATTRIBUTE_NORETURN;
> +extern void error_stream (const string_file &) ATTRIBUTE_NORETURN;
>
> extern void demangler_vwarning (const char *file, int line,
> const char *, va_list ap)
> diff --git a/gdb/varobj.c b/gdb/varobj.c
> index bcca6c6..3b2771f5 100644
> --- a/gdb/varobj.c
> +++ b/gdb/varobj.c
> @@ -2400,8 +2400,6 @@ varobj_value_get_print_value (struct value *value,
> enum varobj_display_formats format,
> const struct varobj *var)
> {
> - struct ui_file *stb;
> - struct cleanup *old_chain;
> struct value_print_options opts;
> struct type *type = NULL;
> long len = 0;
> @@ -2413,9 +2411,7 @@ varobj_value_get_print_value (struct value *value,
> if (value == NULL)
> return std::string ();
>
> - stb = mem_fileopen ();
> - old_chain = make_cleanup_ui_file_delete (stb);
> -
> + string_file stb;
> std::string thevalue;
>
> #if HAVE_PYTHON
> @@ -2430,10 +2426,7 @@ varobj_value_get_print_value (struct value *value,
> /* First check to see if we have any children at all. If so,
> we simply return {...}. */
> if (dynamic_varobj_has_child_method (var))
> - {
> - do_cleanups (old_chain);
> - return "{...}";
> - }
> + return "{...}";
>
> if (PyObject_HasAttr (value_formatter, gdbpy_to_string_cst))
> {
> @@ -2441,7 +2434,7 @@ varobj_value_get_print_value (struct value *value,
>
> gdbpy_ref output (apply_varobj_pretty_printer (value_formatter,
> &replacement,
> - stb));
> + &stb));
>
> /* If we have string like output ... */
> if (output != NULL)
> @@ -2484,10 +2477,7 @@ varobj_value_get_print_value (struct value *value,
> type = builtin_type (gdbarch)->builtin_char;
>
> if (!string_print)
> - {
> - do_cleanups (old_chain);
> - return thevalue;
> - }
> + return thevalue;
> }
> else
> gdbpy_print_stack ();
> @@ -2507,20 +2497,17 @@ varobj_value_get_print_value (struct value *value,
>
> /* If the THEVALUE has contents, it is a regular string. */
> if (!thevalue.empty ())
> - LA_PRINT_STRING (stb, type, (gdb_byte *) thevalue.c_str (),
> + LA_PRINT_STRING (&stb, type, (gdb_byte *) thevalue.c_str (),
> len, encoding.get (), 0, &opts);
> else if (string_print)
> /* Otherwise, if string_print is set, and it is not a regular
> string, it is a lazy string. */
> - val_print_string (type, encoding.get (), str_addr, len, stb, &opts);
> + val_print_string (type, encoding.get (), str_addr, len, &stb, &opts);
> else
> /* All other cases. */
> - common_val_print (value, stb, 0, &opts, current_language);
> -
> - thevalue = ui_file_as_string (stb);
> + common_val_print (value, &stb, 0, &opts, current_language);
>
> - do_cleanups (old_chain);
> - return thevalue;
> + return std::move (stb.string ());
> }
>
> int
> diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c
> index 978b13a..376f4c7 100644
> --- a/gdb/xtensa-tdep.c
> +++ b/gdb/xtensa-tdep.c
> @@ -3063,45 +3063,38 @@ xtensa_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
> static void
> xtensa_verify_config (struct gdbarch *gdbarch)
> {
> - struct ui_file *log;
> - struct cleanup *cleanups;
> - struct gdbarch_tdep *tdep;
> -
> - tdep = gdbarch_tdep (gdbarch);
> - log = mem_fileopen ();
> - cleanups = make_cleanup_ui_file_delete (log);
> + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> + string_file log;
>
> /* Verify that we got a reasonable number of AREGS. */
> if ((tdep->num_aregs & -tdep->num_aregs) != tdep->num_aregs)
> - fprintf_unfiltered (log, _("\
> + log.printf (_("\
> \n\tnum_aregs: Number of AR registers (%d) is not a power of two!"),
> - tdep->num_aregs);
> + tdep->num_aregs);
>
> /* Verify that certain registers exist. */
>
> if (tdep->pc_regnum == -1)
> - fprintf_unfiltered (log, _("\n\tpc_regnum: No PC register"));
> + log.printf (_("\n\tpc_regnum: No PC register"));
> if (tdep->isa_use_exceptions && tdep->ps_regnum == -1)
> - fprintf_unfiltered (log, _("\n\tps_regnum: No PS register"));
> + log.printf (_("\n\tps_regnum: No PS register"));
>
> if (tdep->isa_use_windowed_registers)
> {
> if (tdep->wb_regnum == -1)
> - fprintf_unfiltered (log, _("\n\twb_regnum: No WB register"));
> + log.printf (_("\n\twb_regnum: No WB register"));
> if (tdep->ws_regnum == -1)
> - fprintf_unfiltered (log, _("\n\tws_regnum: No WS register"));
> + log.printf (_("\n\tws_regnum: No WS register"));
> if (tdep->ar_base == -1)
> - fprintf_unfiltered (log, _("\n\tar_base: No AR registers"));
> + log.printf (_("\n\tar_base: No AR registers"));
> }
>
> if (tdep->a0_base == -1)
> - fprintf_unfiltered (log, _("\n\ta0_base: No Ax registers"));
> + log.printf (_("\n\ta0_base: No Ax registers"));
>
> - std::string buf = ui_file_as_string (log);
> - if (!buf.empty ())
> + if (!log.empty ())
> internal_error (__FILE__, __LINE__,
> - _("the following are invalid: %s"), buf.c_str ());
> - do_cleanups (cleanups);
> + _("the following are invalid: %s"), log.c_str ());
> }
>
>
>
Otherwise looks good to me.
Great cleanup. Thanks!
next prev parent reply other threads:[~2017-02-01 17:37 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-02-01 0:30 [PATCH v4 0/2] Eliminate cleanups & make ui_file a C++ " Pedro Alves
2017-02-01 0:30 ` [PATCH v4 1/2] Add back gdb_pretty_print_insn Pedro Alves
2017-02-01 17:01 ` Luis Machado
2017-02-01 18:10 ` Simon Marchi
2017-02-01 18:26 ` Simon Marchi
2017-02-02 0:00 ` Pedro Alves
2017-02-01 20:02 ` Pedro Alves
2017-02-01 20:31 ` Pedro Alves
2017-02-01 23:50 ` Pedro Alves
2017-02-02 1:20 ` Simon Marchi
2017-02-02 11:37 ` [pushed] Reuse buffers across gdb_pretty_print_insn calls (Re: [PATCH v4 1/2] Add back gdb_pretty_print_insn) Pedro Alves
2017-02-01 0:31 ` [PATCH v4 2/2] Eliminate make_cleanup_ui_file_delete / make ui_file a class hierarchy Pedro Alves
2017-02-01 17:37 ` Luis Machado [this message]
2017-02-01 22:49 ` Pedro Alves
2017-02-01 23:24 ` Luis Machado
2017-02-02 0:02 ` Pedro Alves
2017-02-27 19:43 ` Edjunior Barbosa Machado
2017-03-07 14:02 ` Pedro Alves
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=a1194bed-b33a-d874-2fa2-b0a1ff793eea@codesourcery.com \
--to=lgustavo@codesourcery.com \
--cc=gdb-patches@sourceware.org \
--cc=palves@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).