1/* UI_FILE - a generic STDIO like output stream.
2
3   Copyright (C) 1999, 2000, 2001, 2002, 2007 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/* Implement the ``struct ui_file'' object. */
21
22#include "defs.h"
23#include "ui-file.h"
24#include "gdb_string.h"
25
26#include <errno.h>
27
28static ui_file_isatty_ftype null_file_isatty;
29static ui_file_write_ftype null_file_write;
30static ui_file_fputs_ftype null_file_fputs;
31static ui_file_read_ftype null_file_read;
32static ui_file_flush_ftype null_file_flush;
33static ui_file_delete_ftype null_file_delete;
34static ui_file_rewind_ftype null_file_rewind;
35static ui_file_put_ftype null_file_put;
36
37struct ui_file
38  {
39    int *magic;
40    ui_file_flush_ftype *to_flush;
41    ui_file_write_ftype *to_write;
42    ui_file_fputs_ftype *to_fputs;
43    ui_file_read_ftype *to_read;
44    ui_file_delete_ftype *to_delete;
45    ui_file_isatty_ftype *to_isatty;
46    ui_file_rewind_ftype *to_rewind;
47    ui_file_put_ftype *to_put;
48    void *to_data;
49  };
50int ui_file_magic;
51
52struct ui_file *
53ui_file_new (void)
54{
55  struct ui_file *file = xmalloc (sizeof (struct ui_file));
56  file->magic = &ui_file_magic;
57  set_ui_file_data (file, NULL, null_file_delete);
58  set_ui_file_flush (file, null_file_flush);
59  set_ui_file_write (file, null_file_write);
60  set_ui_file_fputs (file, null_file_fputs);
61  set_ui_file_read (file, null_file_read);
62  set_ui_file_isatty (file, null_file_isatty);
63  set_ui_file_rewind (file, null_file_rewind);
64  set_ui_file_put (file, null_file_put);
65  return file;
66}
67
68void
69ui_file_delete (struct ui_file *file)
70{
71  file->to_delete (file);
72  xfree (file);
73}
74
75static int
76null_file_isatty (struct ui_file *file)
77{
78  return 0;
79}
80
81static void
82null_file_rewind (struct ui_file *file)
83{
84  return;
85}
86
87static void
88null_file_put (struct ui_file *file,
89	       ui_file_put_method_ftype *write,
90	       void *dest)
91{
92  return;
93}
94
95static void
96null_file_flush (struct ui_file *file)
97{
98  return;
99}
100
101static void
102null_file_write (struct ui_file *file,
103		 const char *buf,
104		 long sizeof_buf)
105{
106  if (file->to_fputs == null_file_fputs)
107    /* Both the write and fputs methods are null. Discard the
108       request. */
109    return;
110  else
111    {
112      /* The fputs method isn't null, slowly pass the write request
113         onto that.  FYI, this isn't as bad as it may look - the
114         current (as of 1999-11-07) printf_* function calls fputc and
115         fputc does exactly the below.  By having a write function it
116         is possible to clean up that code.  */
117      int i;
118      char b[2];
119      b[1] = '\0';
120      for (i = 0; i < sizeof_buf; i++)
121	{
122	  b[0] = buf[i];
123	  file->to_fputs (b, file);
124	}
125      return;
126    }
127}
128
129static long
130null_file_read (struct ui_file *file,
131		char *buf,
132		long sizeof_buf)
133{
134  errno = EBADF;
135  return 0;
136}
137
138static void
139null_file_fputs (const char *buf, struct ui_file *file)
140{
141  if (file->to_write == null_file_write)
142    /* Both the write and fputs methods are null. Discard the
143       request. */
144    return;
145  else
146    {
147      /* The write method was implemented, use that. */
148      file->to_write (file, buf, strlen (buf));
149    }
150}
151
152static void
153null_file_delete (struct ui_file *file)
154{
155  return;
156}
157
158void *
159ui_file_data (struct ui_file *file)
160{
161  if (file->magic != &ui_file_magic)
162    internal_error (__FILE__, __LINE__,
163		    _("ui_file_data: bad magic number"));
164  return file->to_data;
165}
166
167void
168gdb_flush (struct ui_file *file)
169{
170  file->to_flush (file);
171}
172
173int
174ui_file_isatty (struct ui_file *file)
175{
176  return file->to_isatty (file);
177}
178
179void
180ui_file_rewind (struct ui_file *file)
181{
182  file->to_rewind (file);
183}
184
185void
186ui_file_put (struct ui_file *file,
187	      ui_file_put_method_ftype *write,
188	      void *dest)
189{
190  file->to_put (file, write, dest);
191}
192
193void
194ui_file_write (struct ui_file *file,
195		const char *buf,
196		long length_buf)
197{
198  file->to_write (file, buf, length_buf);
199}
200
201long
202ui_file_read (struct ui_file *file, char *buf, long length_buf)
203{
204  return file->to_read (file, buf, length_buf);
205}
206
207void
208fputs_unfiltered (const char *buf, struct ui_file *file)
209{
210  file->to_fputs (buf, file);
211}
212
213void
214set_ui_file_flush (struct ui_file *file, ui_file_flush_ftype *flush)
215{
216  file->to_flush = flush;
217}
218
219void
220set_ui_file_isatty (struct ui_file *file, ui_file_isatty_ftype *isatty)
221{
222  file->to_isatty = isatty;
223}
224
225void
226set_ui_file_rewind (struct ui_file *file, ui_file_rewind_ftype *rewind)
227{
228  file->to_rewind = rewind;
229}
230
231void
232set_ui_file_put (struct ui_file *file, ui_file_put_ftype *put)
233{
234  file->to_put = put;
235}
236
237void
238set_ui_file_write (struct ui_file *file,
239		    ui_file_write_ftype *write)
240{
241  file->to_write = write;
242}
243
244void
245set_ui_file_read (struct ui_file *file, ui_file_read_ftype *read)
246{
247  file->to_read = read;
248}
249
250void
251set_ui_file_fputs (struct ui_file *file, ui_file_fputs_ftype *fputs)
252{
253  file->to_fputs = fputs;
254}
255
256void
257set_ui_file_data (struct ui_file *file, void *data,
258		  ui_file_delete_ftype *delete)
259{
260  file->to_data = data;
261  file->to_delete = delete;
262}
263
264/* ui_file utility function for converting a ``struct ui_file'' into
265   a memory buffer''. */
266
267struct accumulated_ui_file
268{
269  char *buffer;
270  long length;
271};
272
273static void
274do_ui_file_xstrdup (void *context, const char *buffer, long length)
275{
276  struct accumulated_ui_file *acc = context;
277  if (acc->buffer == NULL)
278    acc->buffer = xmalloc (length + 1);
279  else
280    acc->buffer = xrealloc (acc->buffer, acc->length + length + 1);
281  memcpy (acc->buffer + acc->length, buffer, length);
282  acc->length += length;
283  acc->buffer[acc->length] = '\0';
284}
285
286char *
287ui_file_xstrdup (struct ui_file *file,
288		  long *length)
289{
290  struct accumulated_ui_file acc;
291  acc.buffer = NULL;
292  acc.length = 0;
293  ui_file_put (file, do_ui_file_xstrdup, &acc);
294  if (acc.buffer == NULL)
295    acc.buffer = xstrdup ("");
296  *length = acc.length;
297  return acc.buffer;
298}
299
300/* A pure memory based ``struct ui_file'' that can be used an output
301   buffer. The buffers accumulated contents are available via
302   ui_file_put(). */
303
304struct mem_file
305  {
306    int *magic;
307    char *buffer;
308    int sizeof_buffer;
309    int length_buffer;
310  };
311
312static ui_file_rewind_ftype mem_file_rewind;
313static ui_file_put_ftype mem_file_put;
314static ui_file_write_ftype mem_file_write;
315static ui_file_delete_ftype mem_file_delete;
316static struct ui_file *mem_file_new (void);
317static int mem_file_magic;
318
319static struct ui_file *
320mem_file_new (void)
321{
322  struct mem_file *stream = XMALLOC (struct mem_file);
323  struct ui_file *file = ui_file_new ();
324  set_ui_file_data (file, stream, mem_file_delete);
325  set_ui_file_rewind (file, mem_file_rewind);
326  set_ui_file_put (file, mem_file_put);
327  set_ui_file_write (file, mem_file_write);
328  stream->magic = &mem_file_magic;
329  stream->buffer = NULL;
330  stream->sizeof_buffer = 0;
331  stream->length_buffer = 0;
332  return file;
333}
334
335static void
336mem_file_delete (struct ui_file *file)
337{
338  struct mem_file *stream = ui_file_data (file);
339  if (stream->magic != &mem_file_magic)
340    internal_error (__FILE__, __LINE__,
341		    _("mem_file_delete: bad magic number"));
342  if (stream->buffer != NULL)
343    xfree (stream->buffer);
344  xfree (stream);
345}
346
347struct ui_file *
348mem_fileopen (void)
349{
350  return mem_file_new ();
351}
352
353static void
354mem_file_rewind (struct ui_file *file)
355{
356  struct mem_file *stream = ui_file_data (file);
357  if (stream->magic != &mem_file_magic)
358    internal_error (__FILE__, __LINE__,
359		    _("mem_file_rewind: bad magic number"));
360  stream->length_buffer = 0;
361}
362
363static void
364mem_file_put (struct ui_file *file,
365	      ui_file_put_method_ftype *write,
366	      void *dest)
367{
368  struct mem_file *stream = ui_file_data (file);
369  if (stream->magic != &mem_file_magic)
370    internal_error (__FILE__, __LINE__,
371		    _("mem_file_put: bad magic number"));
372  if (stream->length_buffer > 0)
373    write (dest, stream->buffer, stream->length_buffer);
374}
375
376void
377mem_file_write (struct ui_file *file,
378		const char *buffer,
379		long length_buffer)
380{
381  struct mem_file *stream = ui_file_data (file);
382  if (stream->magic != &mem_file_magic)
383    internal_error (__FILE__, __LINE__,
384		    _("mem_file_write: bad magic number"));
385  if (stream->buffer == NULL)
386    {
387      stream->length_buffer = length_buffer;
388      stream->sizeof_buffer = length_buffer;
389      stream->buffer = xmalloc (stream->sizeof_buffer);
390      memcpy (stream->buffer, buffer, length_buffer);
391    }
392  else
393    {
394      int new_length = stream->length_buffer + length_buffer;
395      if (new_length >= stream->sizeof_buffer)
396	{
397	  stream->sizeof_buffer = new_length;
398	  stream->buffer = xrealloc (stream->buffer, stream->sizeof_buffer);
399	}
400      memcpy (stream->buffer + stream->length_buffer, buffer, length_buffer);
401      stream->length_buffer = new_length;
402    }
403}
404
405/* ``struct ui_file'' implementation that maps directly onto
406   <stdio.h>'s FILE. */
407
408static ui_file_write_ftype stdio_file_write;
409static ui_file_fputs_ftype stdio_file_fputs;
410static ui_file_read_ftype stdio_file_read;
411static ui_file_isatty_ftype stdio_file_isatty;
412static ui_file_delete_ftype stdio_file_delete;
413static struct ui_file *stdio_file_new (FILE * file, int close_p);
414static ui_file_flush_ftype stdio_file_flush;
415
416static int stdio_file_magic;
417
418struct stdio_file
419  {
420    int *magic;
421    FILE *file;
422    int close_p;
423  };
424
425static struct ui_file *
426stdio_file_new (FILE *file, int close_p)
427{
428  struct ui_file *ui_file = ui_file_new ();
429  struct stdio_file *stdio = xmalloc (sizeof (struct stdio_file));
430  stdio->magic = &stdio_file_magic;
431  stdio->file = file;
432  stdio->close_p = close_p;
433  set_ui_file_data (ui_file, stdio, stdio_file_delete);
434  set_ui_file_flush (ui_file, stdio_file_flush);
435  set_ui_file_write (ui_file, stdio_file_write);
436  set_ui_file_fputs (ui_file, stdio_file_fputs);
437  set_ui_file_read (ui_file, stdio_file_read);
438  set_ui_file_isatty (ui_file, stdio_file_isatty);
439  return ui_file;
440}
441
442static void
443stdio_file_delete (struct ui_file *file)
444{
445  struct stdio_file *stdio = ui_file_data (file);
446  if (stdio->magic != &stdio_file_magic)
447    internal_error (__FILE__, __LINE__,
448		    _("stdio_file_delete: bad magic number"));
449  if (stdio->close_p)
450    {
451      fclose (stdio->file);
452    }
453  xfree (stdio);
454}
455
456static void
457stdio_file_flush (struct ui_file *file)
458{
459  struct stdio_file *stdio = ui_file_data (file);
460  if (stdio->magic != &stdio_file_magic)
461    internal_error (__FILE__, __LINE__,
462		    _("stdio_file_flush: bad magic number"));
463  fflush (stdio->file);
464}
465
466static long
467stdio_file_read (struct ui_file *file, char *buf, long length_buf)
468{
469  struct stdio_file *stdio = ui_file_data (file);
470  if (stdio->magic != &stdio_file_magic)
471    internal_error (__FILE__, __LINE__,
472		    _("stdio_file_read: bad magic number"));
473  return read (fileno (stdio->file), buf, length_buf);
474}
475
476static void
477stdio_file_write (struct ui_file *file, const char *buf, long length_buf)
478{
479  struct stdio_file *stdio = ui_file_data (file);
480  if (stdio->magic != &stdio_file_magic)
481    internal_error (__FILE__, __LINE__,
482		    _("stdio_file_write: bad magic number"));
483  fwrite (buf, length_buf, 1, stdio->file);
484}
485
486static void
487stdio_file_fputs (const char *linebuffer, struct ui_file *file)
488{
489  struct stdio_file *stdio = ui_file_data (file);
490  if (stdio->magic != &stdio_file_magic)
491    internal_error (__FILE__, __LINE__,
492		    _("stdio_file_fputs: bad magic number"));
493  fputs (linebuffer, stdio->file);
494}
495
496static int
497stdio_file_isatty (struct ui_file *file)
498{
499  struct stdio_file *stdio = ui_file_data (file);
500  if (stdio->magic != &stdio_file_magic)
501    internal_error (__FILE__, __LINE__,
502		    _("stdio_file_isatty: bad magic number"));
503  return (isatty (fileno (stdio->file)));
504}
505
506/* Like fdopen().  Create a ui_file from a previously opened FILE. */
507
508struct ui_file *
509stdio_fileopen (FILE *file)
510{
511  return stdio_file_new (file, 0);
512}
513
514struct ui_file *
515gdb_fopen (char *name, char *mode)
516{
517  FILE *f = fopen (name, mode);
518  if (f == NULL)
519    return NULL;
520  return stdio_file_new (f, 1);
521}
522
523/* ``struct ui_file'' implementation that maps onto two ui-file objects.  */
524
525static ui_file_write_ftype tee_file_write;
526static ui_file_fputs_ftype tee_file_fputs;
527static ui_file_isatty_ftype tee_file_isatty;
528static ui_file_delete_ftype tee_file_delete;
529static ui_file_flush_ftype tee_file_flush;
530
531static int tee_file_magic;
532
533struct tee_file
534  {
535    int *magic;
536    struct ui_file *one, *two;
537    int close_one, close_two;
538  };
539
540struct ui_file *
541tee_file_new (struct ui_file *one, int close_one,
542	      struct ui_file *two, int close_two)
543{
544  struct ui_file *ui_file = ui_file_new ();
545  struct tee_file *tee = xmalloc (sizeof (struct tee_file));
546  tee->magic = &tee_file_magic;
547  tee->one = one;
548  tee->two = two;
549  tee->close_one = close_one;
550  tee->close_two = close_two;
551  set_ui_file_data (ui_file, tee, tee_file_delete);
552  set_ui_file_flush (ui_file, tee_file_flush);
553  set_ui_file_write (ui_file, tee_file_write);
554  set_ui_file_fputs (ui_file, tee_file_fputs);
555  set_ui_file_isatty (ui_file, tee_file_isatty);
556  return ui_file;
557}
558
559static void
560tee_file_delete (struct ui_file *file)
561{
562  struct tee_file *tee = ui_file_data (file);
563  if (tee->magic != &tee_file_magic)
564    internal_error (__FILE__, __LINE__,
565		    _("tee_file_delete: bad magic number"));
566  if (tee->close_one)
567    ui_file_delete (tee->one);
568  if (tee->close_two)
569    ui_file_delete (tee->two);
570
571  xfree (tee);
572}
573
574static void
575tee_file_flush (struct ui_file *file)
576{
577  struct tee_file *tee = ui_file_data (file);
578  if (tee->magic != &tee_file_magic)
579    internal_error (__FILE__, __LINE__,
580		    _("tee_file_flush: bad magic number"));
581  tee->one->to_flush (tee->one);
582  tee->two->to_flush (tee->two);
583}
584
585static void
586tee_file_write (struct ui_file *file, const char *buf, long length_buf)
587{
588  struct tee_file *tee = ui_file_data (file);
589  if (tee->magic != &tee_file_magic)
590    internal_error (__FILE__, __LINE__,
591		    _("tee_file_write: bad magic number"));
592  ui_file_write (tee->one, buf, length_buf);
593  ui_file_write (tee->two, buf, length_buf);
594}
595
596static void
597tee_file_fputs (const char *linebuffer, struct ui_file *file)
598{
599  struct tee_file *tee = ui_file_data (file);
600  if (tee->magic != &tee_file_magic)
601    internal_error (__FILE__, __LINE__,
602		    _("tee_file_fputs: bad magic number"));
603  tee->one->to_fputs (linebuffer, tee->one);
604  tee->two->to_fputs (linebuffer, tee->two);
605}
606
607static int
608tee_file_isatty (struct ui_file *file)
609{
610  struct tee_file *tee = ui_file_data (file);
611  if (tee->magic != &tee_file_magic)
612    internal_error (__FILE__, __LINE__,
613		    _("tee_file_isatty: bad magic number"));
614  return (0);
615}
616