15796c8dcSSimon Schubert /* UI_FILE - a generic STDIO like output stream.
2*ef5ccd6cSJohn Marino Copyright (C) 1999-2013 Free Software Foundation, Inc.
35796c8dcSSimon Schubert
45796c8dcSSimon Schubert This file is part of GDB.
55796c8dcSSimon Schubert
65796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
75796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
85796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
95796c8dcSSimon Schubert (at your option) any later version.
105796c8dcSSimon Schubert
115796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
125796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
135796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
145796c8dcSSimon Schubert GNU General Public License for more details.
155796c8dcSSimon Schubert
165796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
175796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */
185796c8dcSSimon Schubert
195796c8dcSSimon Schubert #include "defs.h"
205796c8dcSSimon Schubert #include "ui-file.h"
215796c8dcSSimon Schubert #include "tui/tui-file.h"
225796c8dcSSimon Schubert #include "tui/tui-io.h"
235796c8dcSSimon Schubert
245796c8dcSSimon Schubert #include "tui.h"
255796c8dcSSimon Schubert
265796c8dcSSimon Schubert #include "gdb_string.h"
275796c8dcSSimon Schubert
285796c8dcSSimon Schubert /* A ``struct ui_file'' that is compatible with all the legacy
295796c8dcSSimon Schubert code. */
305796c8dcSSimon Schubert
315796c8dcSSimon Schubert /* new */
325796c8dcSSimon Schubert enum streamtype
335796c8dcSSimon Schubert {
345796c8dcSSimon Schubert afile,
355796c8dcSSimon Schubert astring
365796c8dcSSimon Schubert };
375796c8dcSSimon Schubert
385796c8dcSSimon Schubert /* new */
395796c8dcSSimon Schubert struct tui_stream
405796c8dcSSimon Schubert {
415796c8dcSSimon Schubert int *ts_magic;
425796c8dcSSimon Schubert enum streamtype ts_streamtype;
435796c8dcSSimon Schubert FILE *ts_filestream;
445796c8dcSSimon Schubert char *ts_strbuf;
455796c8dcSSimon Schubert int ts_buflen;
465796c8dcSSimon Schubert };
475796c8dcSSimon Schubert
485796c8dcSSimon Schubert static ui_file_flush_ftype tui_file_flush;
495796c8dcSSimon Schubert extern ui_file_fputs_ftype tui_file_fputs;
505796c8dcSSimon Schubert static ui_file_isatty_ftype tui_file_isatty;
515796c8dcSSimon Schubert static ui_file_rewind_ftype tui_file_rewind;
525796c8dcSSimon Schubert static ui_file_put_ftype tui_file_put;
535796c8dcSSimon Schubert static ui_file_delete_ftype tui_file_delete;
545796c8dcSSimon Schubert static struct ui_file *tui_file_new (void);
555796c8dcSSimon Schubert static int tui_file_magic;
565796c8dcSSimon Schubert
575796c8dcSSimon Schubert static struct ui_file *
tui_file_new(void)585796c8dcSSimon Schubert tui_file_new (void)
595796c8dcSSimon Schubert {
605796c8dcSSimon Schubert struct tui_stream *tui = XMALLOC (struct tui_stream);
615796c8dcSSimon Schubert struct ui_file *file = ui_file_new ();
62cf7f2e2dSJohn Marino
635796c8dcSSimon Schubert set_ui_file_data (file, tui, tui_file_delete);
645796c8dcSSimon Schubert set_ui_file_flush (file, tui_file_flush);
655796c8dcSSimon Schubert set_ui_file_fputs (file, tui_file_fputs);
665796c8dcSSimon Schubert set_ui_file_isatty (file, tui_file_isatty);
675796c8dcSSimon Schubert set_ui_file_rewind (file, tui_file_rewind);
685796c8dcSSimon Schubert set_ui_file_put (file, tui_file_put);
695796c8dcSSimon Schubert tui->ts_magic = &tui_file_magic;
705796c8dcSSimon Schubert return file;
715796c8dcSSimon Schubert }
725796c8dcSSimon Schubert
735796c8dcSSimon Schubert static void
tui_file_delete(struct ui_file * file)745796c8dcSSimon Schubert tui_file_delete (struct ui_file *file)
755796c8dcSSimon Schubert {
765796c8dcSSimon Schubert struct tui_stream *tmpstream = ui_file_data (file);
77cf7f2e2dSJohn Marino
785796c8dcSSimon Schubert if (tmpstream->ts_magic != &tui_file_magic)
795796c8dcSSimon Schubert internal_error (__FILE__, __LINE__,
805796c8dcSSimon Schubert _("tui_file_delete: bad magic number"));
815796c8dcSSimon Schubert if ((tmpstream->ts_streamtype == astring)
825796c8dcSSimon Schubert && (tmpstream->ts_strbuf != NULL))
835796c8dcSSimon Schubert {
845796c8dcSSimon Schubert xfree (tmpstream->ts_strbuf);
855796c8dcSSimon Schubert }
865796c8dcSSimon Schubert xfree (tmpstream);
875796c8dcSSimon Schubert }
885796c8dcSSimon Schubert
895796c8dcSSimon Schubert struct ui_file *
tui_fileopen(FILE * stream)905796c8dcSSimon Schubert tui_fileopen (FILE *stream)
915796c8dcSSimon Schubert {
925796c8dcSSimon Schubert struct ui_file *file = tui_file_new ();
935796c8dcSSimon Schubert struct tui_stream *tmpstream = ui_file_data (file);
94cf7f2e2dSJohn Marino
955796c8dcSSimon Schubert tmpstream->ts_streamtype = afile;
965796c8dcSSimon Schubert tmpstream->ts_filestream = stream;
975796c8dcSSimon Schubert tmpstream->ts_strbuf = NULL;
985796c8dcSSimon Schubert tmpstream->ts_buflen = 0;
995796c8dcSSimon Schubert return file;
1005796c8dcSSimon Schubert }
1015796c8dcSSimon Schubert
1025796c8dcSSimon Schubert struct ui_file *
tui_sfileopen(int n)1035796c8dcSSimon Schubert tui_sfileopen (int n)
1045796c8dcSSimon Schubert {
1055796c8dcSSimon Schubert struct ui_file *file = tui_file_new ();
1065796c8dcSSimon Schubert struct tui_stream *tmpstream = ui_file_data (file);
107cf7f2e2dSJohn Marino
1085796c8dcSSimon Schubert tmpstream->ts_streamtype = astring;
1095796c8dcSSimon Schubert tmpstream->ts_filestream = NULL;
1105796c8dcSSimon Schubert if (n > 0)
1115796c8dcSSimon Schubert {
1125796c8dcSSimon Schubert tmpstream->ts_strbuf = xmalloc ((n + 1) * sizeof (char));
1135796c8dcSSimon Schubert tmpstream->ts_strbuf[0] = '\0';
1145796c8dcSSimon Schubert }
1155796c8dcSSimon Schubert else
1165796c8dcSSimon Schubert /* Do not allocate the buffer now. The first time something is
1175796c8dcSSimon Schubert printed one will be allocated by tui_file_adjust_strbuf(). */
1185796c8dcSSimon Schubert tmpstream->ts_strbuf = NULL;
1195796c8dcSSimon Schubert tmpstream->ts_buflen = n;
1205796c8dcSSimon Schubert return file;
1215796c8dcSSimon Schubert }
1225796c8dcSSimon Schubert
1235796c8dcSSimon Schubert static int
tui_file_isatty(struct ui_file * file)1245796c8dcSSimon Schubert tui_file_isatty (struct ui_file *file)
1255796c8dcSSimon Schubert {
1265796c8dcSSimon Schubert struct tui_stream *stream = ui_file_data (file);
127cf7f2e2dSJohn Marino
1285796c8dcSSimon Schubert if (stream->ts_magic != &tui_file_magic)
1295796c8dcSSimon Schubert internal_error (__FILE__, __LINE__,
1305796c8dcSSimon Schubert _("tui_file_isatty: bad magic number"));
1315796c8dcSSimon Schubert if (stream->ts_streamtype == afile)
1325796c8dcSSimon Schubert return (isatty (fileno (stream->ts_filestream)));
1335796c8dcSSimon Schubert else
1345796c8dcSSimon Schubert return 0;
1355796c8dcSSimon Schubert }
1365796c8dcSSimon Schubert
1375796c8dcSSimon Schubert static void
tui_file_rewind(struct ui_file * file)1385796c8dcSSimon Schubert tui_file_rewind (struct ui_file *file)
1395796c8dcSSimon Schubert {
1405796c8dcSSimon Schubert struct tui_stream *stream = ui_file_data (file);
141cf7f2e2dSJohn Marino
1425796c8dcSSimon Schubert if (stream->ts_magic != &tui_file_magic)
1435796c8dcSSimon Schubert internal_error (__FILE__, __LINE__,
1445796c8dcSSimon Schubert _("tui_file_rewind: bad magic number"));
1455796c8dcSSimon Schubert stream->ts_strbuf[0] = '\0';
1465796c8dcSSimon Schubert }
1475796c8dcSSimon Schubert
1485796c8dcSSimon Schubert static void
tui_file_put(struct ui_file * file,ui_file_put_method_ftype * write,void * dest)1495796c8dcSSimon Schubert tui_file_put (struct ui_file *file,
1505796c8dcSSimon Schubert ui_file_put_method_ftype *write,
1515796c8dcSSimon Schubert void *dest)
1525796c8dcSSimon Schubert {
1535796c8dcSSimon Schubert struct tui_stream *stream = ui_file_data (file);
154cf7f2e2dSJohn Marino
1555796c8dcSSimon Schubert if (stream->ts_magic != &tui_file_magic)
1565796c8dcSSimon Schubert internal_error (__FILE__, __LINE__,
1575796c8dcSSimon Schubert _("tui_file_put: bad magic number"));
1585796c8dcSSimon Schubert if (stream->ts_streamtype == astring)
1595796c8dcSSimon Schubert write (dest, stream->ts_strbuf, strlen (stream->ts_strbuf));
1605796c8dcSSimon Schubert }
1615796c8dcSSimon Schubert
1625796c8dcSSimon Schubert /* All TUI I/O sent to the *_filtered and *_unfiltered functions
1635796c8dcSSimon Schubert eventually ends up here. The fputs_unfiltered_hook is primarily
1645796c8dcSSimon Schubert used by GUIs to collect all output and send it to the GUI, instead
1655796c8dcSSimon Schubert of the controlling terminal. Only output to gdb_stdout and
1665796c8dcSSimon Schubert gdb_stderr are sent to the hook. Everything else is sent on to
1675796c8dcSSimon Schubert fputs to allow file I/O to be handled appropriately. */
1685796c8dcSSimon Schubert
1695796c8dcSSimon Schubert /* FIXME: Should be broken up and moved to a TUI specific file. */
1705796c8dcSSimon Schubert
1715796c8dcSSimon Schubert void
tui_file_fputs(const char * linebuffer,struct ui_file * file)1725796c8dcSSimon Schubert tui_file_fputs (const char *linebuffer, struct ui_file *file)
1735796c8dcSSimon Schubert {
1745796c8dcSSimon Schubert struct tui_stream *stream = ui_file_data (file);
1755796c8dcSSimon Schubert
1765796c8dcSSimon Schubert if (stream->ts_streamtype == astring)
1775796c8dcSSimon Schubert {
1785796c8dcSSimon Schubert tui_file_adjust_strbuf (strlen (linebuffer), file);
1795796c8dcSSimon Schubert strcat (stream->ts_strbuf, linebuffer);
1805796c8dcSSimon Schubert }
1815796c8dcSSimon Schubert else
1825796c8dcSSimon Schubert {
1835796c8dcSSimon Schubert tui_puts (linebuffer);
1845796c8dcSSimon Schubert }
1855796c8dcSSimon Schubert }
1865796c8dcSSimon Schubert
1875796c8dcSSimon Schubert char *
tui_file_get_strbuf(struct ui_file * file)1885796c8dcSSimon Schubert tui_file_get_strbuf (struct ui_file *file)
1895796c8dcSSimon Schubert {
1905796c8dcSSimon Schubert struct tui_stream *stream = ui_file_data (file);
191cf7f2e2dSJohn Marino
1925796c8dcSSimon Schubert if (stream->ts_magic != &tui_file_magic)
1935796c8dcSSimon Schubert internal_error (__FILE__, __LINE__,
1945796c8dcSSimon Schubert _("tui_file_get_strbuf: bad magic number"));
1955796c8dcSSimon Schubert return (stream->ts_strbuf);
1965796c8dcSSimon Schubert }
1975796c8dcSSimon Schubert
1985796c8dcSSimon Schubert /* Adjust the length of the buffer by the amount necessary to
1995796c8dcSSimon Schubert accomodate appending a string of length N to the buffer
2005796c8dcSSimon Schubert contents. */
2015796c8dcSSimon Schubert void
tui_file_adjust_strbuf(int n,struct ui_file * file)2025796c8dcSSimon Schubert tui_file_adjust_strbuf (int n, struct ui_file *file)
2035796c8dcSSimon Schubert {
2045796c8dcSSimon Schubert struct tui_stream *stream = ui_file_data (file);
2055796c8dcSSimon Schubert int non_null_chars;
206cf7f2e2dSJohn Marino
2075796c8dcSSimon Schubert if (stream->ts_magic != &tui_file_magic)
2085796c8dcSSimon Schubert internal_error (__FILE__, __LINE__,
2095796c8dcSSimon Schubert _("tui_file_adjust_strbuf: bad magic number"));
2105796c8dcSSimon Schubert
2115796c8dcSSimon Schubert if (stream->ts_streamtype != astring)
2125796c8dcSSimon Schubert return;
2135796c8dcSSimon Schubert
2145796c8dcSSimon Schubert if (stream->ts_strbuf)
2155796c8dcSSimon Schubert {
2165796c8dcSSimon Schubert /* There is already a buffer allocated. */
2175796c8dcSSimon Schubert non_null_chars = strlen (stream->ts_strbuf);
2185796c8dcSSimon Schubert
2195796c8dcSSimon Schubert if (n > (stream->ts_buflen - non_null_chars - 1))
2205796c8dcSSimon Schubert {
2215796c8dcSSimon Schubert stream->ts_buflen = n + non_null_chars + 1;
2225796c8dcSSimon Schubert stream->ts_strbuf = xrealloc (stream->ts_strbuf, stream->ts_buflen);
2235796c8dcSSimon Schubert }
2245796c8dcSSimon Schubert }
2255796c8dcSSimon Schubert else
2265796c8dcSSimon Schubert /* No buffer yet, so allocate one of the desired size. */
2275796c8dcSSimon Schubert stream->ts_strbuf = xmalloc ((n + 1) * sizeof (char));
2285796c8dcSSimon Schubert }
2295796c8dcSSimon Schubert
2305796c8dcSSimon Schubert static void
tui_file_flush(struct ui_file * file)2315796c8dcSSimon Schubert tui_file_flush (struct ui_file *file)
2325796c8dcSSimon Schubert {
2335796c8dcSSimon Schubert struct tui_stream *stream = ui_file_data (file);
234cf7f2e2dSJohn Marino
2355796c8dcSSimon Schubert if (stream->ts_magic != &tui_file_magic)
2365796c8dcSSimon Schubert internal_error (__FILE__, __LINE__,
2375796c8dcSSimon Schubert _("tui_file_flush: bad magic number"));
2385796c8dcSSimon Schubert
2395796c8dcSSimon Schubert switch (stream->ts_streamtype)
2405796c8dcSSimon Schubert {
2415796c8dcSSimon Schubert case astring:
2425796c8dcSSimon Schubert break;
2435796c8dcSSimon Schubert case afile:
2445796c8dcSSimon Schubert fflush (stream->ts_filestream);
2455796c8dcSSimon Schubert break;
2465796c8dcSSimon Schubert }
2475796c8dcSSimon Schubert }
248