]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/ui-file.c
2011-05-14 Hui Zhu <teawater@gmail.com>
[thirdparty/binutils-gdb.git] / gdb / ui-file.c
CommitLineData
d9fcf2fb 1/* UI_FILE - a generic STDIO like output stream.
349c5d5f 2
7b6bb8da 3 Copyright (C) 1999, 2000, 2001, 2002, 2007, 2008, 2009, 2010, 2011
9b254dd1 4 Free Software Foundation, Inc.
d9fcf2fb
JM
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
d9fcf2fb
JM
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
d9fcf2fb 20
581e13c1 21/* Implement the ``struct ui_file'' object. */
d9fcf2fb
JM
22
23#include "defs.h"
24#include "ui-file.h"
94af9270 25#include "gdb_obstack.h"
1d1358b6 26#include "gdb_string.h"
ad960ed2 27#include "gdb_select.h"
d9fcf2fb 28
449092f6
CV
29#include <errno.h>
30
d9fcf2fb
JM
31static ui_file_isatty_ftype null_file_isatty;
32static ui_file_write_ftype null_file_write;
01124a23 33static ui_file_write_ftype null_file_write_async_safe;
d9fcf2fb 34static ui_file_fputs_ftype null_file_fputs;
449092f6 35static ui_file_read_ftype null_file_read;
d9fcf2fb
JM
36static ui_file_flush_ftype null_file_flush;
37static ui_file_delete_ftype null_file_delete;
38static ui_file_rewind_ftype null_file_rewind;
39static ui_file_put_ftype null_file_put;
40
41struct ui_file
42 {
43 int *magic;
44 ui_file_flush_ftype *to_flush;
45 ui_file_write_ftype *to_write;
01124a23 46 ui_file_write_async_safe_ftype *to_write_async_safe;
d9fcf2fb 47 ui_file_fputs_ftype *to_fputs;
449092f6 48 ui_file_read_ftype *to_read;
d9fcf2fb
JM
49 ui_file_delete_ftype *to_delete;
50 ui_file_isatty_ftype *to_isatty;
51 ui_file_rewind_ftype *to_rewind;
52 ui_file_put_ftype *to_put;
53 void *to_data;
54 };
55int ui_file_magic;
56
57struct ui_file *
fba45db2 58ui_file_new (void)
d9fcf2fb
JM
59{
60 struct ui_file *file = xmalloc (sizeof (struct ui_file));
5d502164 61
d9fcf2fb
JM
62 file->magic = &ui_file_magic;
63 set_ui_file_data (file, NULL, null_file_delete);
64 set_ui_file_flush (file, null_file_flush);
65 set_ui_file_write (file, null_file_write);
01124a23 66 set_ui_file_write_async_safe (file, null_file_write_async_safe);
d9fcf2fb 67 set_ui_file_fputs (file, null_file_fputs);
449092f6 68 set_ui_file_read (file, null_file_read);
d9fcf2fb
JM
69 set_ui_file_isatty (file, null_file_isatty);
70 set_ui_file_rewind (file, null_file_rewind);
71 set_ui_file_put (file, null_file_put);
72 return file;
73}
74
75void
fba45db2 76ui_file_delete (struct ui_file *file)
d9fcf2fb
JM
77{
78 file->to_delete (file);
b8c9b27d 79 xfree (file);
d9fcf2fb
JM
80}
81
82static int
fba45db2 83null_file_isatty (struct ui_file *file)
d9fcf2fb
JM
84{
85 return 0;
86}
87
88static void
fba45db2 89null_file_rewind (struct ui_file *file)
d9fcf2fb
JM
90{
91 return;
92}
93
94static void
95null_file_put (struct ui_file *file,
96 ui_file_put_method_ftype *write,
97 void *dest)
98{
99 return;
100}
101
102static void
fba45db2 103null_file_flush (struct ui_file *file)
d9fcf2fb
JM
104{
105 return;
106}
107
108static void
109null_file_write (struct ui_file *file,
110 const char *buf,
111 long sizeof_buf)
112{
113 if (file->to_fputs == null_file_fputs)
581e13c1
MS
114 /* Both the write and fputs methods are null. Discard the
115 request. */
d9fcf2fb
JM
116 return;
117 else
118 {
119 /* The fputs method isn't null, slowly pass the write request
120 onto that. FYI, this isn't as bad as it may look - the
121 current (as of 1999-11-07) printf_* function calls fputc and
122 fputc does exactly the below. By having a write function it
123 is possible to clean up that code. */
124 int i;
125 char b[2];
5d502164 126
d9fcf2fb
JM
127 b[1] = '\0';
128 for (i = 0; i < sizeof_buf; i++)
129 {
130 b[0] = buf[i];
131 file->to_fputs (b, file);
132 }
133 return;
134 }
135}
136
449092f6
CV
137static long
138null_file_read (struct ui_file *file,
139 char *buf,
140 long sizeof_buf)
141{
142 errno = EBADF;
143 return 0;
144}
145
d9fcf2fb 146static void
fba45db2 147null_file_fputs (const char *buf, struct ui_file *file)
d9fcf2fb
JM
148{
149 if (file->to_write == null_file_write)
581e13c1
MS
150 /* Both the write and fputs methods are null. Discard the
151 request. */
d9fcf2fb
JM
152 return;
153 else
154 {
581e13c1 155 /* The write method was implemented, use that. */
d9fcf2fb
JM
156 file->to_write (file, buf, strlen (buf));
157 }
158}
159
01124a23
DE
160static void
161null_file_write_async_safe (struct ui_file *file,
162 const char *buf,
163 long sizeof_buf)
164{
165 return;
166}
167
d9fcf2fb 168static void
fba45db2 169null_file_delete (struct ui_file *file)
d9fcf2fb
JM
170{
171 return;
172}
173
174void *
fba45db2 175ui_file_data (struct ui_file *file)
d9fcf2fb
JM
176{
177 if (file->magic != &ui_file_magic)
8e65ff28 178 internal_error (__FILE__, __LINE__,
e2e0b3e5 179 _("ui_file_data: bad magic number"));
d9fcf2fb
JM
180 return file->to_data;
181}
182
183void
fba45db2 184gdb_flush (struct ui_file *file)
d9fcf2fb
JM
185{
186 file->to_flush (file);
187}
188
189int
fba45db2 190ui_file_isatty (struct ui_file *file)
d9fcf2fb
JM
191{
192 return file->to_isatty (file);
193}
194
195void
fba45db2 196ui_file_rewind (struct ui_file *file)
d9fcf2fb
JM
197{
198 file->to_rewind (file);
199}
200
201void
202ui_file_put (struct ui_file *file,
203 ui_file_put_method_ftype *write,
204 void *dest)
205{
206 file->to_put (file, write, dest);
207}
208
209void
210ui_file_write (struct ui_file *file,
211 const char *buf,
212 long length_buf)
213{
214 file->to_write (file, buf, length_buf);
215}
216
01124a23
DE
217void
218ui_file_write_async_safe (struct ui_file *file,
219 const char *buf,
220 long length_buf)
221{
222 file->to_write_async_safe (file, buf, length_buf);
223}
224
449092f6
CV
225long
226ui_file_read (struct ui_file *file, char *buf, long length_buf)
227{
228 return file->to_read (file, buf, length_buf);
229}
230
d9fcf2fb 231void
fba45db2 232fputs_unfiltered (const char *buf, struct ui_file *file)
d9fcf2fb
JM
233{
234 file->to_fputs (buf, file);
235}
236
237void
fba45db2 238set_ui_file_flush (struct ui_file *file, ui_file_flush_ftype *flush)
d9fcf2fb
JM
239{
240 file->to_flush = flush;
241}
242
243void
fba45db2 244set_ui_file_isatty (struct ui_file *file, ui_file_isatty_ftype *isatty)
d9fcf2fb
JM
245{
246 file->to_isatty = isatty;
247}
248
249void
fba45db2 250set_ui_file_rewind (struct ui_file *file, ui_file_rewind_ftype *rewind)
d9fcf2fb
JM
251{
252 file->to_rewind = rewind;
253}
254
255void
fba45db2 256set_ui_file_put (struct ui_file *file, ui_file_put_ftype *put)
d9fcf2fb
JM
257{
258 file->to_put = put;
259}
260
261void
262set_ui_file_write (struct ui_file *file,
263 ui_file_write_ftype *write)
264{
265 file->to_write = write;
266}
267
01124a23
DE
268void
269set_ui_file_write_async_safe (struct ui_file *file,
270 ui_file_write_async_safe_ftype *write_async_safe)
271{
272 file->to_write_async_safe = write_async_safe;
273}
274
449092f6
CV
275void
276set_ui_file_read (struct ui_file *file, ui_file_read_ftype *read)
277{
278 file->to_read = read;
279}
280
d9fcf2fb 281void
fba45db2 282set_ui_file_fputs (struct ui_file *file, ui_file_fputs_ftype *fputs)
d9fcf2fb
JM
283{
284 file->to_fputs = fputs;
285}
286
287void
fba45db2
KB
288set_ui_file_data (struct ui_file *file, void *data,
289 ui_file_delete_ftype *delete)
d9fcf2fb
JM
290{
291 file->to_data = data;
292 file->to_delete = delete;
293}
294
295/* ui_file utility function for converting a ``struct ui_file'' into
581e13c1 296 a memory buffer. */
d9fcf2fb
JM
297
298struct accumulated_ui_file
299{
300 char *buffer;
301 long length;
302};
303
304static void
305do_ui_file_xstrdup (void *context, const char *buffer, long length)
306{
307 struct accumulated_ui_file *acc = context;
5d502164 308
d9fcf2fb
JM
309 if (acc->buffer == NULL)
310 acc->buffer = xmalloc (length + 1);
311 else
312 acc->buffer = xrealloc (acc->buffer, acc->length + length + 1);
313 memcpy (acc->buffer + acc->length, buffer, length);
314 acc->length += length;
315 acc->buffer[acc->length] = '\0';
316}
317
318char *
759ef836 319ui_file_xstrdup (struct ui_file *file, long *length)
d9fcf2fb
JM
320{
321 struct accumulated_ui_file acc;
5d502164 322
d9fcf2fb
JM
323 acc.buffer = NULL;
324 acc.length = 0;
325 ui_file_put (file, do_ui_file_xstrdup, &acc);
326 if (acc.buffer == NULL)
327 acc.buffer = xstrdup ("");
759ef836
PA
328 if (length != NULL)
329 *length = acc.length;
d9fcf2fb
JM
330 return acc.buffer;
331}
94af9270
KS
332
333static void
334do_ui_file_obsavestring (void *context, const char *buffer, long length)
335{
336 struct obstack *obstack = (struct obstack *) context;
5d502164 337
94af9270
KS
338 obstack_grow (obstack, buffer, length);
339}
340
341char *
342ui_file_obsavestring (struct ui_file *file, struct obstack *obstack,
343 long *length)
344{
345 ui_file_put (file, do_ui_file_obsavestring, obstack);
346 *length = obstack_object_size (obstack);
347 obstack_1grow (obstack, '\0');
348 return obstack_finish (obstack);
349}
d9fcf2fb
JM
350\f
351/* A pure memory based ``struct ui_file'' that can be used an output
581e13c1
MS
352 buffer. The buffers accumulated contents are available via
353 ui_file_put(). */
d9fcf2fb
JM
354
355struct mem_file
356 {
357 int *magic;
358 char *buffer;
359 int sizeof_buffer;
360 int length_buffer;
361 };
362
363static ui_file_rewind_ftype mem_file_rewind;
364static ui_file_put_ftype mem_file_put;
365static ui_file_write_ftype mem_file_write;
366static ui_file_delete_ftype mem_file_delete;
a14ed312 367static struct ui_file *mem_file_new (void);
d9fcf2fb
JM
368static int mem_file_magic;
369
370static struct ui_file *
371mem_file_new (void)
372{
373 struct mem_file *stream = XMALLOC (struct mem_file);
374 struct ui_file *file = ui_file_new ();
5d502164 375
d9fcf2fb
JM
376 set_ui_file_data (file, stream, mem_file_delete);
377 set_ui_file_rewind (file, mem_file_rewind);
378 set_ui_file_put (file, mem_file_put);
379 set_ui_file_write (file, mem_file_write);
380 stream->magic = &mem_file_magic;
381 stream->buffer = NULL;
382 stream->sizeof_buffer = 0;
383 stream->length_buffer = 0;
384 return file;
385}
386
387static void
388mem_file_delete (struct ui_file *file)
389{
390 struct mem_file *stream = ui_file_data (file);
5d502164 391
d9fcf2fb 392 if (stream->magic != &mem_file_magic)
8e65ff28 393 internal_error (__FILE__, __LINE__,
e2e0b3e5 394 _("mem_file_delete: bad magic number"));
d9fcf2fb 395 if (stream->buffer != NULL)
b8c9b27d
KB
396 xfree (stream->buffer);
397 xfree (stream);
d9fcf2fb
JM
398}
399
400struct ui_file *
401mem_fileopen (void)
402{
403 return mem_file_new ();
404}
405
406static void
407mem_file_rewind (struct ui_file *file)
408{
409 struct mem_file *stream = ui_file_data (file);
5d502164 410
d9fcf2fb 411 if (stream->magic != &mem_file_magic)
8e65ff28 412 internal_error (__FILE__, __LINE__,
e2e0b3e5 413 _("mem_file_rewind: bad magic number"));
d9fcf2fb
JM
414 stream->length_buffer = 0;
415}
416
417static void
418mem_file_put (struct ui_file *file,
419 ui_file_put_method_ftype *write,
420 void *dest)
421{
422 struct mem_file *stream = ui_file_data (file);
5d502164 423
d9fcf2fb 424 if (stream->magic != &mem_file_magic)
8e65ff28 425 internal_error (__FILE__, __LINE__,
e2e0b3e5 426 _("mem_file_put: bad magic number"));
d9fcf2fb
JM
427 if (stream->length_buffer > 0)
428 write (dest, stream->buffer, stream->length_buffer);
429}
430
431void
432mem_file_write (struct ui_file *file,
433 const char *buffer,
434 long length_buffer)
435{
436 struct mem_file *stream = ui_file_data (file);
5d502164 437
d9fcf2fb 438 if (stream->magic != &mem_file_magic)
8e65ff28 439 internal_error (__FILE__, __LINE__,
e2e0b3e5 440 _("mem_file_write: bad magic number"));
d9fcf2fb
JM
441 if (stream->buffer == NULL)
442 {
443 stream->length_buffer = length_buffer;
444 stream->sizeof_buffer = length_buffer;
445 stream->buffer = xmalloc (stream->sizeof_buffer);
446 memcpy (stream->buffer, buffer, length_buffer);
447 }
448 else
449 {
450 int new_length = stream->length_buffer + length_buffer;
5d502164 451
d9fcf2fb
JM
452 if (new_length >= stream->sizeof_buffer)
453 {
454 stream->sizeof_buffer = new_length;
455 stream->buffer = xrealloc (stream->buffer, stream->sizeof_buffer);
456 }
457 memcpy (stream->buffer + stream->length_buffer, buffer, length_buffer);
458 stream->length_buffer = new_length;
459 }
460}
461\f
462/* ``struct ui_file'' implementation that maps directly onto
581e13c1 463 <stdio.h>'s FILE. */
d9fcf2fb
JM
464
465static ui_file_write_ftype stdio_file_write;
01124a23 466static ui_file_write_async_safe_ftype stdio_file_write_async_safe;
d9fcf2fb 467static ui_file_fputs_ftype stdio_file_fputs;
449092f6 468static ui_file_read_ftype stdio_file_read;
d9fcf2fb
JM
469static ui_file_isatty_ftype stdio_file_isatty;
470static ui_file_delete_ftype stdio_file_delete;
3e43a32a 471static struct ui_file *stdio_file_new (FILE *file, int close_p);
d9fcf2fb
JM
472static ui_file_flush_ftype stdio_file_flush;
473
474static int stdio_file_magic;
475
476struct stdio_file
477 {
478 int *magic;
479 FILE *file;
01124a23
DE
480 /* The associated file descriptor is extracted ahead of time for
481 stdio_file_write_async_safe's benefit, in case fileno isn't async-safe. */
482 int fd;
d9fcf2fb
JM
483 int close_p;
484 };
485
486static struct ui_file *
fba45db2 487stdio_file_new (FILE *file, int close_p)
d9fcf2fb
JM
488{
489 struct ui_file *ui_file = ui_file_new ();
490 struct stdio_file *stdio = xmalloc (sizeof (struct stdio_file));
5d502164 491
d9fcf2fb
JM
492 stdio->magic = &stdio_file_magic;
493 stdio->file = file;
01124a23 494 stdio->fd = fileno (file);
d9fcf2fb
JM
495 stdio->close_p = close_p;
496 set_ui_file_data (ui_file, stdio, stdio_file_delete);
497 set_ui_file_flush (ui_file, stdio_file_flush);
498 set_ui_file_write (ui_file, stdio_file_write);
01124a23 499 set_ui_file_write_async_safe (ui_file, stdio_file_write_async_safe);
d9fcf2fb 500 set_ui_file_fputs (ui_file, stdio_file_fputs);
449092f6 501 set_ui_file_read (ui_file, stdio_file_read);
d9fcf2fb
JM
502 set_ui_file_isatty (ui_file, stdio_file_isatty);
503 return ui_file;
504}
505
506static void
fba45db2 507stdio_file_delete (struct ui_file *file)
d9fcf2fb
JM
508{
509 struct stdio_file *stdio = ui_file_data (file);
5d502164 510
d9fcf2fb 511 if (stdio->magic != &stdio_file_magic)
8e65ff28 512 internal_error (__FILE__, __LINE__,
e2e0b3e5 513 _("stdio_file_delete: bad magic number"));
d9fcf2fb
JM
514 if (stdio->close_p)
515 {
516 fclose (stdio->file);
517 }
b8c9b27d 518 xfree (stdio);
d9fcf2fb
JM
519}
520
521static void
fba45db2 522stdio_file_flush (struct ui_file *file)
d9fcf2fb
JM
523{
524 struct stdio_file *stdio = ui_file_data (file);
5d502164 525
d9fcf2fb 526 if (stdio->magic != &stdio_file_magic)
8e65ff28 527 internal_error (__FILE__, __LINE__,
e2e0b3e5 528 _("stdio_file_flush: bad magic number"));
d9fcf2fb
JM
529 fflush (stdio->file);
530}
531
449092f6
CV
532static long
533stdio_file_read (struct ui_file *file, char *buf, long length_buf)
534{
535 struct stdio_file *stdio = ui_file_data (file);
5d502164 536
449092f6
CV
537 if (stdio->magic != &stdio_file_magic)
538 internal_error (__FILE__, __LINE__,
e2e0b3e5 539 _("stdio_file_read: bad magic number"));
ad960ed2
DJ
540
541 /* For the benefit of Windows, call gdb_select before reading from
542 the file. Wait until at least one byte of data is available.
543 Control-C can interrupt gdb_select, but not read. */
544 {
ad960ed2
DJ
545 fd_set readfds;
546 FD_ZERO (&readfds);
01124a23
DE
547 FD_SET (stdio->fd, &readfds);
548 if (gdb_select (stdio->fd + 1, &readfds, NULL, NULL, NULL) == -1)
ad960ed2
DJ
549 return -1;
550 }
551
01124a23 552 return read (stdio->fd, buf, length_buf);
449092f6
CV
553}
554
d9fcf2fb
JM
555static void
556stdio_file_write (struct ui_file *file, const char *buf, long length_buf)
557{
558 struct stdio_file *stdio = ui_file_data (file);
5d502164 559
d9fcf2fb 560 if (stdio->magic != &stdio_file_magic)
8e65ff28 561 internal_error (__FILE__, __LINE__,
e2e0b3e5 562 _("stdio_file_write: bad magic number"));
bf1d7d9c
JB
563 /* Calling error crashes when we are called from the exception framework. */
564 if (fwrite (buf, length_buf, 1, stdio->file))
565 ;
d9fcf2fb
JM
566}
567
01124a23
DE
568static void
569stdio_file_write_async_safe (struct ui_file *file,
570 const char *buf, long length_buf)
571{
572 struct stdio_file *stdio = ui_file_data (file);
573
574 if (stdio->magic != &stdio_file_magic)
575 {
576 /* gettext isn't necessarily async safe, so we can't use _("error message") here.
577 We could extract the correct translation ahead of time, but this is an extremely
578 rare event, and one of the other stdio_file_* routines will presumably catch
579 the problem anyway. For now keep it simple and ignore the error here. */
580 return;
581 }
582
093cee7d
HZ
583 if (write (stdio->fd, buf, length_buf))
584 ;
01124a23
DE
585}
586
d9fcf2fb 587static void
fba45db2 588stdio_file_fputs (const char *linebuffer, struct ui_file *file)
d9fcf2fb
JM
589{
590 struct stdio_file *stdio = ui_file_data (file);
5d502164 591
d9fcf2fb 592 if (stdio->magic != &stdio_file_magic)
8e65ff28 593 internal_error (__FILE__, __LINE__,
e2e0b3e5 594 _("stdio_file_fputs: bad magic number"));
bf1d7d9c
JB
595 /* Calling error crashes when we are called from the exception framework. */
596 if (fputs (linebuffer, stdio->file))
597 ;
d9fcf2fb
JM
598}
599
600static int
fba45db2 601stdio_file_isatty (struct ui_file *file)
d9fcf2fb
JM
602{
603 struct stdio_file *stdio = ui_file_data (file);
5d502164 604
d9fcf2fb 605 if (stdio->magic != &stdio_file_magic)
8e65ff28 606 internal_error (__FILE__, __LINE__,
e2e0b3e5 607 _("stdio_file_isatty: bad magic number"));
01124a23 608 return (isatty (stdio->fd));
d9fcf2fb
JM
609}
610
581e13c1 611/* Like fdopen(). Create a ui_file from a previously opened FILE. */
d9fcf2fb
JM
612
613struct ui_file *
fba45db2 614stdio_fileopen (FILE *file)
d9fcf2fb
JM
615{
616 return stdio_file_new (file, 0);
617}
618
619struct ui_file *
fba45db2 620gdb_fopen (char *name, char *mode)
d9fcf2fb
JM
621{
622 FILE *f = fopen (name, mode);
5d502164 623
d9fcf2fb
JM
624 if (f == NULL)
625 return NULL;
626 return stdio_file_new (f, 1);
627}
e4c242d9
DJ
628
629/* ``struct ui_file'' implementation that maps onto two ui-file objects. */
630
631static ui_file_write_ftype tee_file_write;
632static ui_file_fputs_ftype tee_file_fputs;
633static ui_file_isatty_ftype tee_file_isatty;
634static ui_file_delete_ftype tee_file_delete;
635static ui_file_flush_ftype tee_file_flush;
636
637static int tee_file_magic;
638
639struct tee_file
640 {
641 int *magic;
642 struct ui_file *one, *two;
643 int close_one, close_two;
644 };
645
646struct ui_file *
647tee_file_new (struct ui_file *one, int close_one,
648 struct ui_file *two, int close_two)
649{
650 struct ui_file *ui_file = ui_file_new ();
651 struct tee_file *tee = xmalloc (sizeof (struct tee_file));
5d502164 652
e4c242d9
DJ
653 tee->magic = &tee_file_magic;
654 tee->one = one;
655 tee->two = two;
656 tee->close_one = close_one;
657 tee->close_two = close_two;
658 set_ui_file_data (ui_file, tee, tee_file_delete);
659 set_ui_file_flush (ui_file, tee_file_flush);
660 set_ui_file_write (ui_file, tee_file_write);
661 set_ui_file_fputs (ui_file, tee_file_fputs);
662 set_ui_file_isatty (ui_file, tee_file_isatty);
663 return ui_file;
664}
665
666static void
667tee_file_delete (struct ui_file *file)
668{
669 struct tee_file *tee = ui_file_data (file);
5d502164 670
e4c242d9
DJ
671 if (tee->magic != &tee_file_magic)
672 internal_error (__FILE__, __LINE__,
e2e0b3e5 673 _("tee_file_delete: bad magic number"));
e4c242d9
DJ
674 if (tee->close_one)
675 ui_file_delete (tee->one);
676 if (tee->close_two)
677 ui_file_delete (tee->two);
678
679 xfree (tee);
680}
681
682static void
683tee_file_flush (struct ui_file *file)
684{
685 struct tee_file *tee = ui_file_data (file);
5d502164 686
e4c242d9
DJ
687 if (tee->magic != &tee_file_magic)
688 internal_error (__FILE__, __LINE__,
e2e0b3e5 689 _("tee_file_flush: bad magic number"));
e4c242d9
DJ
690 tee->one->to_flush (tee->one);
691 tee->two->to_flush (tee->two);
692}
693
694static void
695tee_file_write (struct ui_file *file, const char *buf, long length_buf)
696{
697 struct tee_file *tee = ui_file_data (file);
5d502164 698
e4c242d9
DJ
699 if (tee->magic != &tee_file_magic)
700 internal_error (__FILE__, __LINE__,
e2e0b3e5 701 _("tee_file_write: bad magic number"));
e4c242d9
DJ
702 ui_file_write (tee->one, buf, length_buf);
703 ui_file_write (tee->two, buf, length_buf);
704}
705
706static void
707tee_file_fputs (const char *linebuffer, struct ui_file *file)
708{
709 struct tee_file *tee = ui_file_data (file);
5d502164 710
e4c242d9
DJ
711 if (tee->magic != &tee_file_magic)
712 internal_error (__FILE__, __LINE__,
e2e0b3e5 713 _("tee_file_fputs: bad magic number"));
e4c242d9
DJ
714 tee->one->to_fputs (linebuffer, tee->one);
715 tee->two->to_fputs (linebuffer, tee->two);
716}
717
718static int
719tee_file_isatty (struct ui_file *file)
720{
721 struct tee_file *tee = ui_file_data (file);
5d502164 722
e4c242d9
DJ
723 if (tee->magic != &tee_file_magic)
724 internal_error (__FILE__, __LINE__,
e2e0b3e5 725 _("tee_file_isatty: bad magic number"));
172240dd
PA
726
727 return ui_file_isatty (tee->one);
e4c242d9 728}