1130803Smarcel/* UI_FILE - a generic STDIO like output stream. 2130803Smarcel Copyright 1999, 2000, 2001 Free Software Foundation, Inc. 3130803Smarcel 4130803Smarcel This file is part of GDB. 5130803Smarcel 6130803Smarcel This program is free software; you can redistribute it and/or modify 7130803Smarcel it under the terms of the GNU General Public License as published by 8130803Smarcel the Free Software Foundation; either version 2 of the License, or 9130803Smarcel (at your option) any later version. 10130803Smarcel 11130803Smarcel This program is distributed in the hope that it will be useful, 12130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 13130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14130803Smarcel GNU General Public License for more details. 15130803Smarcel 16130803Smarcel You should have received a copy of the GNU General Public License 17130803Smarcel along with this program; if not, write to the Free Software 18130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 19130803Smarcel Boston, MA 02111-1307, USA. */ 20130803Smarcel 21130803Smarcel#include "defs.h" 22130803Smarcel#include "ui-file.h" 23130803Smarcel#include "tui/tui-file.h" 24130803Smarcel#include "tui/tui-io.h" 25130803Smarcel 26130803Smarcel#include "tui.h" 27130803Smarcel 28130803Smarcel#include "gdb_string.h" 29130803Smarcel 30130803Smarcel/* A ``struct ui_file'' that is compatible with all the legacy 31130803Smarcel code. */ 32130803Smarcel 33130803Smarcel/* new */ 34130803Smarcelenum streamtype 35130803Smarcel{ 36130803Smarcel afile, 37130803Smarcel astring 38130803Smarcel}; 39130803Smarcel 40130803Smarcel/* new */ 41130803Smarcelstruct tui_stream 42130803Smarcel{ 43130803Smarcel int *ts_magic; 44130803Smarcel enum streamtype ts_streamtype; 45130803Smarcel FILE *ts_filestream; 46130803Smarcel char *ts_strbuf; 47130803Smarcel int ts_buflen; 48130803Smarcel}; 49130803Smarcel 50130803Smarcelstatic ui_file_flush_ftype tui_file_flush; 51130803Smarcelextern ui_file_fputs_ftype tui_file_fputs; 52130803Smarcelstatic ui_file_isatty_ftype tui_file_isatty; 53130803Smarcelstatic ui_file_rewind_ftype tui_file_rewind; 54130803Smarcelstatic ui_file_put_ftype tui_file_put; 55130803Smarcelstatic ui_file_delete_ftype tui_file_delete; 56130803Smarcelstatic struct ui_file *tui_file_new (void); 57130803Smarcelstatic int tui_file_magic; 58130803Smarcel 59130803Smarcelstatic struct ui_file * 60130803Smarceltui_file_new (void) 61130803Smarcel{ 62130803Smarcel struct tui_stream *tui = xmalloc (sizeof (struct tui_stream)); 63130803Smarcel struct ui_file *file = ui_file_new (); 64130803Smarcel set_ui_file_data (file, tui, tui_file_delete); 65130803Smarcel set_ui_file_flush (file, tui_file_flush); 66130803Smarcel set_ui_file_fputs (file, tui_file_fputs); 67130803Smarcel set_ui_file_isatty (file, tui_file_isatty); 68130803Smarcel set_ui_file_rewind (file, tui_file_rewind); 69130803Smarcel set_ui_file_put (file, tui_file_put); 70130803Smarcel tui->ts_magic = &tui_file_magic; 71130803Smarcel return file; 72130803Smarcel} 73130803Smarcel 74130803Smarcelstatic void 75130803Smarceltui_file_delete (struct ui_file *file) 76130803Smarcel{ 77130803Smarcel struct tui_stream *tmpstream = ui_file_data (file); 78130803Smarcel if (tmpstream->ts_magic != &tui_file_magic) 79130803Smarcel internal_error (__FILE__, __LINE__, 80130803Smarcel "tui_file_delete: bad magic number"); 81130803Smarcel if ((tmpstream->ts_streamtype == astring) && 82130803Smarcel (tmpstream->ts_strbuf != NULL)) 83130803Smarcel { 84130803Smarcel xfree (tmpstream->ts_strbuf); 85130803Smarcel } 86130803Smarcel xfree (tmpstream); 87130803Smarcel} 88130803Smarcel 89130803Smarcelstruct ui_file * 90130803Smarceltui_fileopen (FILE *stream) 91130803Smarcel{ 92130803Smarcel struct ui_file *file = tui_file_new (); 93130803Smarcel struct tui_stream *tmpstream = ui_file_data (file); 94130803Smarcel tmpstream->ts_streamtype = afile; 95130803Smarcel tmpstream->ts_filestream = stream; 96130803Smarcel tmpstream->ts_strbuf = NULL; 97130803Smarcel tmpstream->ts_buflen = 0; 98130803Smarcel return file; 99130803Smarcel} 100130803Smarcel 101130803Smarcelstruct ui_file * 102130803Smarceltui_sfileopen (int n) 103130803Smarcel{ 104130803Smarcel struct ui_file *file = tui_file_new (); 105130803Smarcel struct tui_stream *tmpstream = ui_file_data (file); 106130803Smarcel tmpstream->ts_streamtype = astring; 107130803Smarcel tmpstream->ts_filestream = NULL; 108130803Smarcel if (n > 0) 109130803Smarcel { 110130803Smarcel tmpstream->ts_strbuf = xmalloc ((n + 1) * sizeof (char)); 111130803Smarcel tmpstream->ts_strbuf[0] = '\0'; 112130803Smarcel } 113130803Smarcel else 114130803Smarcel /* Do not allocate the buffer now. The first time something is printed 115130803Smarcel one will be allocated by tui_file_adjust_strbuf() */ 116130803Smarcel tmpstream->ts_strbuf = NULL; 117130803Smarcel tmpstream->ts_buflen = n; 118130803Smarcel return file; 119130803Smarcel} 120130803Smarcel 121130803Smarcelstatic int 122130803Smarceltui_file_isatty (struct ui_file *file) 123130803Smarcel{ 124130803Smarcel struct tui_stream *stream = ui_file_data (file); 125130803Smarcel if (stream->ts_magic != &tui_file_magic) 126130803Smarcel internal_error (__FILE__, __LINE__, 127130803Smarcel "tui_file_isatty: bad magic number"); 128130803Smarcel if (stream->ts_streamtype == afile) 129130803Smarcel return (isatty (fileno (stream->ts_filestream))); 130130803Smarcel else 131130803Smarcel return 0; 132130803Smarcel} 133130803Smarcel 134130803Smarcelstatic void 135130803Smarceltui_file_rewind (struct ui_file *file) 136130803Smarcel{ 137130803Smarcel struct tui_stream *stream = ui_file_data (file); 138130803Smarcel if (stream->ts_magic != &tui_file_magic) 139130803Smarcel internal_error (__FILE__, __LINE__, 140130803Smarcel "tui_file_rewind: bad magic number"); 141130803Smarcel stream->ts_strbuf[0] = '\0'; 142130803Smarcel} 143130803Smarcel 144130803Smarcelstatic void 145130803Smarceltui_file_put (struct ui_file *file, 146130803Smarcel ui_file_put_method_ftype *write, 147130803Smarcel void *dest) 148130803Smarcel{ 149130803Smarcel struct tui_stream *stream = ui_file_data (file); 150130803Smarcel if (stream->ts_magic != &tui_file_magic) 151130803Smarcel internal_error (__FILE__, __LINE__, 152130803Smarcel "tui_file_put: bad magic number"); 153130803Smarcel if (stream->ts_streamtype == astring) 154130803Smarcel write (dest, stream->ts_strbuf, strlen (stream->ts_strbuf)); 155130803Smarcel} 156130803Smarcel 157130803Smarcel/* All TUI I/O sent to the *_filtered and *_unfiltered functions 158130803Smarcel eventually ends up here. The fputs_unfiltered_hook is primarily 159130803Smarcel used by GUIs to collect all output and send it to the GUI, instead 160130803Smarcel of the controlling terminal. Only output to gdb_stdout and 161130803Smarcel gdb_stderr are sent to the hook. Everything else is sent on to 162130803Smarcel fputs to allow file I/O to be handled appropriately. */ 163130803Smarcel 164130803Smarcel/* FIXME: Should be broken up and moved to a TUI specific file. */ 165130803Smarcel 166130803Smarcelvoid 167130803Smarceltui_file_fputs (const char *linebuffer, struct ui_file *file) 168130803Smarcel{ 169130803Smarcel struct tui_stream *stream = ui_file_data (file); 170130803Smarcel 171130803Smarcel if (stream->ts_streamtype == astring) 172130803Smarcel { 173130803Smarcel tui_file_adjust_strbuf (strlen (linebuffer), file); 174130803Smarcel strcat (stream->ts_strbuf, linebuffer); 175130803Smarcel } 176130803Smarcel else 177130803Smarcel { 178130803Smarcel tui_puts (linebuffer); 179130803Smarcel } 180130803Smarcel} 181130803Smarcel 182130803Smarcelchar * 183130803Smarceltui_file_get_strbuf (struct ui_file *file) 184130803Smarcel{ 185130803Smarcel struct tui_stream *stream = ui_file_data (file); 186130803Smarcel if (stream->ts_magic != &tui_file_magic) 187130803Smarcel internal_error (__FILE__, __LINE__, 188130803Smarcel "tui_file_get_strbuf: bad magic number"); 189130803Smarcel return (stream->ts_strbuf); 190130803Smarcel} 191130803Smarcel 192130803Smarcel/* adjust the length of the buffer by the amount necessary 193130803Smarcel to accomodate appending a string of length N to the buffer contents */ 194130803Smarcelvoid 195130803Smarceltui_file_adjust_strbuf (int n, struct ui_file *file) 196130803Smarcel{ 197130803Smarcel struct tui_stream *stream = ui_file_data (file); 198130803Smarcel int non_null_chars; 199130803Smarcel if (stream->ts_magic != &tui_file_magic) 200130803Smarcel internal_error (__FILE__, __LINE__, 201130803Smarcel "tui_file_adjust_strbuf: bad magic number"); 202130803Smarcel 203130803Smarcel if (stream->ts_streamtype != astring) 204130803Smarcel return; 205130803Smarcel 206130803Smarcel if (stream->ts_strbuf) 207130803Smarcel { 208130803Smarcel /* There is already a buffer allocated */ 209130803Smarcel non_null_chars = strlen (stream->ts_strbuf); 210130803Smarcel 211130803Smarcel if (n > (stream->ts_buflen - non_null_chars - 1)) 212130803Smarcel { 213130803Smarcel stream->ts_buflen = n + non_null_chars + 1; 214130803Smarcel stream->ts_strbuf = xrealloc (stream->ts_strbuf, stream->ts_buflen); 215130803Smarcel } 216130803Smarcel } 217130803Smarcel else 218130803Smarcel /* No buffer yet, so allocate one of the desired size */ 219130803Smarcel stream->ts_strbuf = xmalloc ((n + 1) * sizeof (char)); 220130803Smarcel} 221130803Smarcel 222130803Smarcelstatic void 223130803Smarceltui_file_flush (struct ui_file *file) 224130803Smarcel{ 225130803Smarcel struct tui_stream *stream = ui_file_data (file); 226130803Smarcel if (stream->ts_magic != &tui_file_magic) 227130803Smarcel internal_error (__FILE__, __LINE__, 228130803Smarcel "tui_file_flush: bad magic number"); 229130803Smarcel 230130803Smarcel switch (stream->ts_streamtype) 231130803Smarcel { 232130803Smarcel case astring: 233130803Smarcel break; 234130803Smarcel case afile: 235130803Smarcel fflush (stream->ts_filestream); 236130803Smarcel break; 237130803Smarcel } 238130803Smarcel} 239