1 /* UI_FILE - a generic STDIO like output stream. 2 Copyright (C) 1999, 2000, 2001, 2007, 2008, 2009 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 set_ui_file_data (file, tui, tui_file_delete); 64 set_ui_file_flush (file, tui_file_flush); 65 set_ui_file_fputs (file, tui_file_fputs); 66 set_ui_file_isatty (file, tui_file_isatty); 67 set_ui_file_rewind (file, tui_file_rewind); 68 set_ui_file_put (file, tui_file_put); 69 tui->ts_magic = &tui_file_magic; 70 return file; 71 } 72 73 static void 74 tui_file_delete (struct ui_file *file) 75 { 76 struct tui_stream *tmpstream = ui_file_data (file); 77 if (tmpstream->ts_magic != &tui_file_magic) 78 internal_error (__FILE__, __LINE__, 79 _("tui_file_delete: bad magic number")); 80 if ((tmpstream->ts_streamtype == astring) 81 && (tmpstream->ts_strbuf != NULL)) 82 { 83 xfree (tmpstream->ts_strbuf); 84 } 85 xfree (tmpstream); 86 } 87 88 struct ui_file * 89 tui_fileopen (FILE *stream) 90 { 91 struct ui_file *file = tui_file_new (); 92 struct tui_stream *tmpstream = ui_file_data (file); 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 100 struct ui_file * 101 tui_sfileopen (int n) 102 { 103 struct ui_file *file = tui_file_new (); 104 struct tui_stream *tmpstream = ui_file_data (file); 105 tmpstream->ts_streamtype = astring; 106 tmpstream->ts_filestream = NULL; 107 if (n > 0) 108 { 109 tmpstream->ts_strbuf = xmalloc ((n + 1) * sizeof (char)); 110 tmpstream->ts_strbuf[0] = '\0'; 111 } 112 else 113 /* Do not allocate the buffer now. The first time something is 114 printed one will be allocated by tui_file_adjust_strbuf(). */ 115 tmpstream->ts_strbuf = NULL; 116 tmpstream->ts_buflen = n; 117 return file; 118 } 119 120 static int 121 tui_file_isatty (struct ui_file *file) 122 { 123 struct tui_stream *stream = ui_file_data (file); 124 if (stream->ts_magic != &tui_file_magic) 125 internal_error (__FILE__, __LINE__, 126 _("tui_file_isatty: bad magic number")); 127 if (stream->ts_streamtype == afile) 128 return (isatty (fileno (stream->ts_filestream))); 129 else 130 return 0; 131 } 132 133 static void 134 tui_file_rewind (struct ui_file *file) 135 { 136 struct tui_stream *stream = ui_file_data (file); 137 if (stream->ts_magic != &tui_file_magic) 138 internal_error (__FILE__, __LINE__, 139 _("tui_file_rewind: bad magic number")); 140 stream->ts_strbuf[0] = '\0'; 141 } 142 143 static void 144 tui_file_put (struct ui_file *file, 145 ui_file_put_method_ftype *write, 146 void *dest) 147 { 148 struct tui_stream *stream = ui_file_data (file); 149 if (stream->ts_magic != &tui_file_magic) 150 internal_error (__FILE__, __LINE__, 151 _("tui_file_put: bad magic number")); 152 if (stream->ts_streamtype == astring) 153 write (dest, stream->ts_strbuf, strlen (stream->ts_strbuf)); 154 } 155 156 /* All TUI I/O sent to the *_filtered and *_unfiltered functions 157 eventually ends up here. The fputs_unfiltered_hook is primarily 158 used by GUIs to collect all output and send it to the GUI, instead 159 of the controlling terminal. Only output to gdb_stdout and 160 gdb_stderr are sent to the hook. Everything else is sent on to 161 fputs to allow file I/O to be handled appropriately. */ 162 163 /* FIXME: Should be broken up and moved to a TUI specific file. */ 164 165 void 166 tui_file_fputs (const char *linebuffer, struct ui_file *file) 167 { 168 struct tui_stream *stream = ui_file_data (file); 169 170 if (stream->ts_streamtype == astring) 171 { 172 tui_file_adjust_strbuf (strlen (linebuffer), file); 173 strcat (stream->ts_strbuf, linebuffer); 174 } 175 else 176 { 177 tui_puts (linebuffer); 178 } 179 } 180 181 char * 182 tui_file_get_strbuf (struct ui_file *file) 183 { 184 struct tui_stream *stream = ui_file_data (file); 185 if (stream->ts_magic != &tui_file_magic) 186 internal_error (__FILE__, __LINE__, 187 _("tui_file_get_strbuf: bad magic number")); 188 return (stream->ts_strbuf); 189 } 190 191 /* Adjust the length of the buffer by the amount necessary to 192 accomodate appending a string of length N to the buffer 193 contents. */ 194 void 195 tui_file_adjust_strbuf (int n, struct ui_file *file) 196 { 197 struct tui_stream *stream = ui_file_data (file); 198 int non_null_chars; 199 if (stream->ts_magic != &tui_file_magic) 200 internal_error (__FILE__, __LINE__, 201 _("tui_file_adjust_strbuf: bad magic number")); 202 203 if (stream->ts_streamtype != astring) 204 return; 205 206 if (stream->ts_strbuf) 207 { 208 /* There is already a buffer allocated. */ 209 non_null_chars = strlen (stream->ts_strbuf); 210 211 if (n > (stream->ts_buflen - non_null_chars - 1)) 212 { 213 stream->ts_buflen = n + non_null_chars + 1; 214 stream->ts_strbuf = xrealloc (stream->ts_strbuf, stream->ts_buflen); 215 } 216 } 217 else 218 /* No buffer yet, so allocate one of the desired size. */ 219 stream->ts_strbuf = xmalloc ((n + 1) * sizeof (char)); 220 } 221 222 static void 223 tui_file_flush (struct ui_file *file) 224 { 225 struct tui_stream *stream = ui_file_data (file); 226 if (stream->ts_magic != &tui_file_magic) 227 internal_error (__FILE__, __LINE__, 228 _("tui_file_flush: bad magic number")); 229 230 switch (stream->ts_streamtype) 231 { 232 case astring: 233 break; 234 case afile: 235 fflush (stream->ts_filestream); 236 break; 237 } 238 } 239