From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 80806 invoked by alias); 1 Feb 2017 17:37:27 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 80508 invoked by uid 89); 1 Feb 2017 17:37:04 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-HELO: relay1.mentorg.com Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 01 Feb 2017 17:37:03 +0000 Received: from svr-orw-mbx-03.mgc.mentorg.com ([147.34.90.203]) by relay1.mentorg.com with esmtp id 1cYyq6-0000r3-2y from Luis_Gustavo@mentor.com ; Wed, 01 Feb 2017 09:37:02 -0800 Received: from [172.30.10.1] (147.34.91.1) by svr-orw-mbx-03.mgc.mentorg.com (147.34.90.203) with Microsoft SMTP Server (TLS) id 15.0.1210.3; Wed, 1 Feb 2017 09:36:57 -0800 Subject: Re: [PATCH v4 2/2] Eliminate make_cleanup_ui_file_delete / make ui_file a class hierarchy References: <1485909045-30285-1-git-send-email-palves@redhat.com> <1485909045-30285-3-git-send-email-palves@redhat.com> To: Pedro Alves , From: Luis Machado Reply-To: Luis Machado Message-ID: Date: Wed, 01 Feb 2017 17:37:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.7.0 MIME-Version: 1.0 In-Reply-To: <1485909045-30285-3-git-send-email-palves@redhat.com> Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit X-ClientProxiedBy: svr-orw-mbx-02.mgc.mentorg.com (147.34.90.202) To svr-orw-mbx-03.mgc.mentorg.com (147.34.90.203) X-IsSubscribed: yes X-SW-Source: 2017-02/txt/msg00034.txt.bz2 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 > > * 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) 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) : > 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) : 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 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 < 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 < - 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) > > /* 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; > -} > > /* 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); > } > > /* (parse-and-eval string) -> > 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_message); > + stb.printf (_(""), 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 () > : "")) > || 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, ")"); > + stb.puts (")"); > 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_message); > + stb.printf (_(""), 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 ()); > } > > > @@ -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 . */ > > #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; > -} > + > > -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. */ > } > > + > + > 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; > -} > + > > -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; > -} > + > > -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); > -} > - > -/* 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; > - } > -} > - > -/* ``struct ui_file'' implementation that maps directly onto > - '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); > -} > + > > -#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; > + > > -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 > > -/* 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_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 '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_up; > + > +/* Like stdio_file, but specifically for stderr. > + > + This exists because there is no real line-buffering on Windows, see > + > + 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!