tui-file.c revision 1.3
1/* UI_FILE - a generic STDIO like output stream. 2 Copyright (C) 1999-2015 Free Software Foundation, Inc. 3 4 This file is part of GDB. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 19#include "defs.h" 20#include "ui-file.h" 21#include "tui/tui-file.h" 22#include "tui/tui-io.h" 23#include "tui/tui-command.h" 24#include "tui.h" 25 26/* A ``struct ui_file'' that is compatible with all the legacy 27 code. */ 28 29/* new */ 30enum streamtype 31{ 32 afile, 33 astring 34}; 35 36/* new */ 37struct tui_stream 38{ 39 int *ts_magic; 40 enum streamtype ts_streamtype; 41 FILE *ts_filestream; 42 char *ts_strbuf; 43 int ts_buflen; 44}; 45 46static ui_file_flush_ftype tui_file_flush; 47extern ui_file_fputs_ftype tui_file_fputs; 48static ui_file_isatty_ftype tui_file_isatty; 49static ui_file_rewind_ftype tui_file_rewind; 50static ui_file_put_ftype tui_file_put; 51static ui_file_delete_ftype tui_file_delete; 52static struct ui_file *tui_file_new (void); 53static int tui_file_magic; 54 55static struct ui_file * 56tui_file_new (void) 57{ 58 struct tui_stream *tui = XNEW (struct tui_stream); 59 struct ui_file *file = ui_file_new (); 60 61 set_ui_file_data (file, tui, tui_file_delete); 62 set_ui_file_flush (file, tui_file_flush); 63 set_ui_file_fputs (file, tui_file_fputs); 64 set_ui_file_isatty (file, tui_file_isatty); 65 set_ui_file_rewind (file, tui_file_rewind); 66 set_ui_file_put (file, tui_file_put); 67 tui->ts_magic = &tui_file_magic; 68 return file; 69} 70 71static void 72tui_file_delete (struct ui_file *file) 73{ 74 struct tui_stream *tmpstream = ui_file_data (file); 75 76 if (tmpstream->ts_magic != &tui_file_magic) 77 internal_error (__FILE__, __LINE__, 78 _("tui_file_delete: bad magic number")); 79 if ((tmpstream->ts_streamtype == astring) 80 && (tmpstream->ts_strbuf != NULL)) 81 { 82 xfree (tmpstream->ts_strbuf); 83 } 84 xfree (tmpstream); 85} 86 87struct ui_file * 88tui_fileopen (FILE *stream) 89{ 90 struct ui_file *file = tui_file_new (); 91 struct tui_stream *tmpstream = ui_file_data (file); 92 93 tmpstream->ts_streamtype = afile; 94 tmpstream->ts_filestream = stream; 95 tmpstream->ts_strbuf = NULL; 96 tmpstream->ts_buflen = 0; 97 return file; 98} 99 100struct ui_file * 101tui_sfileopen (int n) 102{ 103 struct ui_file *file = tui_file_new (); 104 struct tui_stream *tmpstream = ui_file_data (file); 105 106 tmpstream->ts_streamtype = astring; 107 tmpstream->ts_filestream = NULL; 108 if (n > 0) 109 { 110 tmpstream->ts_strbuf = xmalloc ((n + 1) * sizeof (char)); 111 tmpstream->ts_strbuf[0] = '\0'; 112 } 113 else 114 /* Do not allocate the buffer now. The first time something is 115 printed one will be allocated by tui_file_adjust_strbuf(). */ 116 tmpstream->ts_strbuf = NULL; 117 tmpstream->ts_buflen = n; 118 return file; 119} 120 121static int 122tui_file_isatty (struct ui_file *file) 123{ 124 struct tui_stream *stream = ui_file_data (file); 125 126 if (stream->ts_magic != &tui_file_magic) 127 internal_error (__FILE__, __LINE__, 128 _("tui_file_isatty: bad magic number")); 129 if (stream->ts_streamtype == afile) 130 return (isatty (fileno (stream->ts_filestream))); 131 else 132 return 0; 133} 134 135static void 136tui_file_rewind (struct ui_file *file) 137{ 138 struct tui_stream *stream = ui_file_data (file); 139 140 if (stream->ts_magic != &tui_file_magic) 141 internal_error (__FILE__, __LINE__, 142 _("tui_file_rewind: bad magic number")); 143 stream->ts_strbuf[0] = '\0'; 144} 145 146static void 147tui_file_put (struct ui_file *file, 148 ui_file_put_method_ftype *write, 149 void *dest) 150{ 151 struct tui_stream *stream = ui_file_data (file); 152 153 if (stream->ts_magic != &tui_file_magic) 154 internal_error (__FILE__, __LINE__, 155 _("tui_file_put: bad magic number")); 156 if (stream->ts_streamtype == astring) 157 write (dest, stream->ts_strbuf, strlen (stream->ts_strbuf)); 158} 159 160/* All TUI I/O sent to the *_filtered and *_unfiltered functions 161 eventually ends up here. The fputs_unfiltered_hook is primarily 162 used by GUIs to collect all output and send it to the GUI, instead 163 of the controlling terminal. Only output to gdb_stdout and 164 gdb_stderr are sent to the hook. Everything else is sent on to 165 fputs to allow file I/O to be handled appropriately. */ 166 167/* FIXME: Should be broken up and moved to a TUI specific file. */ 168 169void 170tui_file_fputs (const char *linebuffer, struct ui_file *file) 171{ 172 struct tui_stream *stream = ui_file_data (file); 173 174 if (stream->ts_streamtype == astring) 175 { 176 tui_file_adjust_strbuf (strlen (linebuffer), file); 177 strcat (stream->ts_strbuf, linebuffer); 178 } 179 else 180 { 181 tui_puts (linebuffer); 182 /* gdb_stdout is buffered, and the caller must gdb_flush it at 183 appropriate times. Other streams are not so buffered. */ 184 if (file != gdb_stdout) 185 tui_refresh_cmd_win (); 186 } 187} 188 189char * 190tui_file_get_strbuf (struct ui_file *file) 191{ 192 struct tui_stream *stream = ui_file_data (file); 193 194 if (stream->ts_magic != &tui_file_magic) 195 internal_error (__FILE__, __LINE__, 196 _("tui_file_get_strbuf: bad magic number")); 197 return (stream->ts_strbuf); 198} 199 200/* Adjust the length of the buffer by the amount necessary to 201 accomodate appending a string of length N to the buffer 202 contents. */ 203void 204tui_file_adjust_strbuf (int n, struct ui_file *file) 205{ 206 struct tui_stream *stream = ui_file_data (file); 207 int non_null_chars; 208 209 if (stream->ts_magic != &tui_file_magic) 210 internal_error (__FILE__, __LINE__, 211 _("tui_file_adjust_strbuf: bad magic number")); 212 213 if (stream->ts_streamtype != astring) 214 return; 215 216 if (stream->ts_strbuf) 217 { 218 /* There is already a buffer allocated. */ 219 non_null_chars = strlen (stream->ts_strbuf); 220 221 if (n > (stream->ts_buflen - non_null_chars - 1)) 222 { 223 stream->ts_buflen = n + non_null_chars + 1; 224 stream->ts_strbuf = xrealloc (stream->ts_strbuf, stream->ts_buflen); 225 } 226 } 227 else 228 /* No buffer yet, so allocate one of the desired size. */ 229 stream->ts_strbuf = xmalloc ((n + 1) * sizeof (char)); 230} 231 232static void 233tui_file_flush (struct ui_file *file) 234{ 235 struct tui_stream *stream = ui_file_data (file); 236 237 if (stream->ts_magic != &tui_file_magic) 238 internal_error (__FILE__, __LINE__, 239 _("tui_file_flush: bad magic number")); 240 241 switch (stream->ts_streamtype) 242 { 243 case astring: 244 break; 245 case afile: 246 /* gdb_stdout is buffered. Other files are always flushed on 247 every write. */ 248 if (file == gdb_stdout) 249 tui_refresh_cmd_win (); 250 fflush (stream->ts_filestream); 251 break; 252 } 253} 254