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