1 /* MI Console code. 2 3 Copyright (C) 2000-2019 Free Software Foundation, Inc. 4 5 Contributed by Cygnus Solutions (a Red Hat company). 6 7 This file is part of GDB. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 21 22 /* An MI console is a kind of ui_file stream that sends output to 23 stdout, but encapsulated and prefixed with a distinctive string; 24 for instance, error output is normally identified by a leading 25 "&". */ 26 27 #include "defs.h" 28 #include "mi-console.h" 29 30 /* Create a console that wraps the given output stream RAW with the 31 string PREFIX and quoting it with QUOTE. */ 32 33 mi_console_file::mi_console_file (ui_file *raw, const char *prefix, char quote) 34 : m_raw (raw), 35 m_prefix (prefix), 36 m_quote (quote) 37 {} 38 39 void 40 mi_console_file::write (const char *buf, long length_buf) 41 { 42 size_t prev_size = m_buffer.size (); 43 /* Append the text to our internal buffer. */ 44 m_buffer.write (buf, length_buf); 45 /* Flush when an embedded newline is present anywhere in the 46 buffer. */ 47 if (strchr (m_buffer.c_str () + prev_size, '\n') != NULL) 48 this->flush (); 49 } 50 51 /* Write C to STREAM's in an async-safe way. */ 52 53 static int 54 do_fputc_async_safe (int c, ui_file *stream) 55 { 56 char ch = c; 57 stream->write_async_safe (&ch, 1); 58 return c; 59 } 60 61 void 62 mi_console_file::write_async_safe (const char *buf, long length_buf) 63 { 64 m_raw->write_async_safe (m_prefix, strlen (m_prefix)); 65 if (m_quote) 66 { 67 m_raw->write_async_safe (&m_quote, 1); 68 fputstrn_unfiltered (buf, length_buf, m_quote, do_fputc_async_safe, 69 m_raw); 70 m_raw->write_async_safe (&m_quote, 1); 71 } 72 else 73 fputstrn_unfiltered (buf, length_buf, 0, do_fputc_async_safe, m_raw); 74 75 char nl = '\n'; 76 m_raw->write_async_safe (&nl, 1); 77 } 78 79 void 80 mi_console_file::flush () 81 { 82 const std::string &str = m_buffer.string (); 83 84 /* Transform a byte sequence into a console output packet. */ 85 if (!str.empty ()) 86 { 87 size_t length_buf = str.size (); 88 const char *buf = str.data (); 89 90 fputs_unfiltered (m_prefix, m_raw); 91 if (m_quote) 92 { 93 fputc_unfiltered (m_quote, m_raw); 94 fputstrn_unfiltered (buf, length_buf, m_quote, fputc_unfiltered, 95 m_raw); 96 fputc_unfiltered (m_quote, m_raw); 97 fputc_unfiltered ('\n', m_raw); 98 } 99 else 100 { 101 fputstrn_unfiltered (buf, length_buf, 0, fputc_unfiltered, m_raw); 102 fputc_unfiltered ('\n', m_raw); 103 } 104 gdb_flush (m_raw); 105 } 106 107 m_buffer.clear (); 108 } 109 110 /* Change the underlying stream of the console directly; this is 111 useful as a minimum-impact way to reflect external changes like 112 logging enable/disable. */ 113 114 void 115 mi_console_file::set_raw (ui_file *raw) 116 { 117 m_raw = raw; 118 } 119