tui-file.c revision 130803
1/* UI_FILE - a generic STDIO like output stream.
2   Copyright 1999, 2000, 2001 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 2 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, write to the Free Software
18   Foundation, Inc., 59 Temple Place - Suite 330,
19   Boston, MA 02111-1307, USA.  */
20
21#include "defs.h"
22#include "ui-file.h"
23#include "tui/tui-file.h"
24#include "tui/tui-io.h"
25
26#include "tui.h"
27
28#include "gdb_string.h"
29
30/* A ``struct ui_file'' that is compatible with all the legacy
31   code. */
32
33/* new */
34enum streamtype
35{
36  afile,
37  astring
38};
39
40/* new */
41struct tui_stream
42{
43  int *ts_magic;
44  enum streamtype ts_streamtype;
45  FILE *ts_filestream;
46  char *ts_strbuf;
47  int ts_buflen;
48};
49
50static ui_file_flush_ftype tui_file_flush;
51extern ui_file_fputs_ftype tui_file_fputs;
52static ui_file_isatty_ftype tui_file_isatty;
53static ui_file_rewind_ftype tui_file_rewind;
54static ui_file_put_ftype tui_file_put;
55static ui_file_delete_ftype tui_file_delete;
56static struct ui_file *tui_file_new (void);
57static int tui_file_magic;
58
59static struct ui_file *
60tui_file_new (void)
61{
62  struct tui_stream *tui = xmalloc (sizeof (struct tui_stream));
63  struct ui_file *file = ui_file_new ();
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
74static void
75tui_file_delete (struct ui_file *file)
76{
77  struct tui_stream *tmpstream = ui_file_data (file);
78  if (tmpstream->ts_magic != &tui_file_magic)
79    internal_error (__FILE__, __LINE__,
80		    "tui_file_delete: bad magic number");
81  if ((tmpstream->ts_streamtype == astring) &&
82      (tmpstream->ts_strbuf != NULL))
83    {
84      xfree (tmpstream->ts_strbuf);
85    }
86  xfree (tmpstream);
87}
88
89struct ui_file *
90tui_fileopen (FILE *stream)
91{
92  struct ui_file *file = tui_file_new ();
93  struct tui_stream *tmpstream = ui_file_data (file);
94  tmpstream->ts_streamtype = afile;
95  tmpstream->ts_filestream = stream;
96  tmpstream->ts_strbuf = NULL;
97  tmpstream->ts_buflen = 0;
98  return file;
99}
100
101struct ui_file *
102tui_sfileopen (int n)
103{
104  struct ui_file *file = tui_file_new ();
105  struct tui_stream *tmpstream = ui_file_data (file);
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 printed
115       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  if (stream->ts_magic != &tui_file_magic)
126    internal_error (__FILE__, __LINE__,
127		    "tui_file_isatty: bad magic number");
128  if (stream->ts_streamtype == afile)
129    return (isatty (fileno (stream->ts_filestream)));
130  else
131    return 0;
132}
133
134static void
135tui_file_rewind (struct ui_file *file)
136{
137  struct tui_stream *stream = ui_file_data (file);
138  if (stream->ts_magic != &tui_file_magic)
139    internal_error (__FILE__, __LINE__,
140		    "tui_file_rewind: bad magic number");
141  stream->ts_strbuf[0] = '\0';
142}
143
144static void
145tui_file_put (struct ui_file *file,
146	      ui_file_put_method_ftype *write,
147	      void *dest)
148{
149  struct tui_stream *stream = ui_file_data (file);
150  if (stream->ts_magic != &tui_file_magic)
151    internal_error (__FILE__, __LINE__,
152		    "tui_file_put: bad magic number");
153  if (stream->ts_streamtype == astring)
154    write (dest, stream->ts_strbuf, strlen (stream->ts_strbuf));
155}
156
157/* All TUI I/O sent to the *_filtered and *_unfiltered functions
158   eventually ends up here.  The fputs_unfiltered_hook is primarily
159   used by GUIs to collect all output and send it to the GUI, instead
160   of the controlling terminal.  Only output to gdb_stdout and
161   gdb_stderr are sent to the hook.  Everything else is sent on to
162   fputs to allow file I/O to be handled appropriately.  */
163
164/* FIXME: Should be broken up and moved to a TUI specific file. */
165
166void
167tui_file_fputs (const char *linebuffer, struct ui_file *file)
168{
169  struct tui_stream *stream = ui_file_data (file);
170
171  if (stream->ts_streamtype == astring)
172    {
173      tui_file_adjust_strbuf (strlen (linebuffer), file);
174      strcat (stream->ts_strbuf, linebuffer);
175    }
176  else
177    {
178      tui_puts (linebuffer);
179    }
180}
181
182char *
183tui_file_get_strbuf (struct ui_file *file)
184{
185  struct tui_stream *stream = ui_file_data (file);
186  if (stream->ts_magic != &tui_file_magic)
187    internal_error (__FILE__, __LINE__,
188		    "tui_file_get_strbuf: bad magic number");
189  return (stream->ts_strbuf);
190}
191
192/* adjust the length of the buffer by the amount necessary
193   to accomodate appending a string of length N to the buffer contents */
194void
195tui_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
222static void
223tui_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