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