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