198944Sobrien/* UI_FILE - a generic STDIO like output stream. 298944Sobrien 3130803Smarcel Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 4130803Smarcel 598944Sobrien This file is part of GDB. 698944Sobrien 798944Sobrien This program is free software; you can redistribute it and/or modify 898944Sobrien it under the terms of the GNU General Public License as published by 998944Sobrien the Free Software Foundation; either version 2 of the License, or 1098944Sobrien (at your option) any later version. 1198944Sobrien 1298944Sobrien This program is distributed in the hope that it will be useful, 1398944Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1498944Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1598944Sobrien GNU General Public License for more details. 1698944Sobrien 1798944Sobrien You should have received a copy of the GNU General Public License 1898944Sobrien along with this program; if not, write to the Free Software 1998944Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 2098944Sobrien Boston, MA 02111-1307, USA. */ 2198944Sobrien 2298944Sobrien/* Implement the ``struct ui_file'' object. */ 2398944Sobrien 2498944Sobrien#include "defs.h" 2598944Sobrien#include "ui-file.h" 2698944Sobrien#include "gdb_string.h" 2798944Sobrien 28130803Smarcel#include <errno.h> 2998944Sobrien 3098944Sobrienstatic ui_file_isatty_ftype null_file_isatty; 3198944Sobrienstatic ui_file_write_ftype null_file_write; 3298944Sobrienstatic ui_file_fputs_ftype null_file_fputs; 33130803Smarcelstatic ui_file_read_ftype null_file_read; 3498944Sobrienstatic ui_file_flush_ftype null_file_flush; 3598944Sobrienstatic ui_file_delete_ftype null_file_delete; 3698944Sobrienstatic ui_file_rewind_ftype null_file_rewind; 3798944Sobrienstatic ui_file_put_ftype null_file_put; 3898944Sobrien 3998944Sobrienstruct ui_file 4098944Sobrien { 4198944Sobrien int *magic; 4298944Sobrien ui_file_flush_ftype *to_flush; 4398944Sobrien ui_file_write_ftype *to_write; 4498944Sobrien ui_file_fputs_ftype *to_fputs; 45130803Smarcel ui_file_read_ftype *to_read; 4698944Sobrien ui_file_delete_ftype *to_delete; 4798944Sobrien ui_file_isatty_ftype *to_isatty; 4898944Sobrien ui_file_rewind_ftype *to_rewind; 4998944Sobrien ui_file_put_ftype *to_put; 5098944Sobrien void *to_data; 5198944Sobrien }; 5298944Sobrienint ui_file_magic; 5398944Sobrien 5498944Sobrienstruct ui_file * 5598944Sobrienui_file_new (void) 5698944Sobrien{ 5798944Sobrien struct ui_file *file = xmalloc (sizeof (struct ui_file)); 5898944Sobrien file->magic = &ui_file_magic; 5998944Sobrien set_ui_file_data (file, NULL, null_file_delete); 6098944Sobrien set_ui_file_flush (file, null_file_flush); 6198944Sobrien set_ui_file_write (file, null_file_write); 6298944Sobrien set_ui_file_fputs (file, null_file_fputs); 63130803Smarcel set_ui_file_read (file, null_file_read); 6498944Sobrien set_ui_file_isatty (file, null_file_isatty); 6598944Sobrien set_ui_file_rewind (file, null_file_rewind); 6698944Sobrien set_ui_file_put (file, null_file_put); 6798944Sobrien return file; 6898944Sobrien} 6998944Sobrien 7098944Sobrienvoid 7198944Sobrienui_file_delete (struct ui_file *file) 7298944Sobrien{ 7398944Sobrien file->to_delete (file); 7498944Sobrien xfree (file); 7598944Sobrien} 7698944Sobrien 7798944Sobrienstatic int 7898944Sobriennull_file_isatty (struct ui_file *file) 7998944Sobrien{ 8098944Sobrien return 0; 8198944Sobrien} 8298944Sobrien 8398944Sobrienstatic void 8498944Sobriennull_file_rewind (struct ui_file *file) 8598944Sobrien{ 8698944Sobrien return; 8798944Sobrien} 8898944Sobrien 8998944Sobrienstatic void 9098944Sobriennull_file_put (struct ui_file *file, 9198944Sobrien ui_file_put_method_ftype *write, 9298944Sobrien void *dest) 9398944Sobrien{ 9498944Sobrien return; 9598944Sobrien} 9698944Sobrien 9798944Sobrienstatic void 9898944Sobriennull_file_flush (struct ui_file *file) 9998944Sobrien{ 10098944Sobrien return; 10198944Sobrien} 10298944Sobrien 10398944Sobrienstatic void 10498944Sobriennull_file_write (struct ui_file *file, 10598944Sobrien const char *buf, 10698944Sobrien long sizeof_buf) 10798944Sobrien{ 10898944Sobrien if (file->to_fputs == null_file_fputs) 10998944Sobrien /* Both the write and fputs methods are null. Discard the 11098944Sobrien request. */ 11198944Sobrien return; 11298944Sobrien else 11398944Sobrien { 11498944Sobrien /* The fputs method isn't null, slowly pass the write request 11598944Sobrien onto that. FYI, this isn't as bad as it may look - the 11698944Sobrien current (as of 1999-11-07) printf_* function calls fputc and 11798944Sobrien fputc does exactly the below. By having a write function it 11898944Sobrien is possible to clean up that code. */ 11998944Sobrien int i; 12098944Sobrien char b[2]; 12198944Sobrien b[1] = '\0'; 12298944Sobrien for (i = 0; i < sizeof_buf; i++) 12398944Sobrien { 12498944Sobrien b[0] = buf[i]; 12598944Sobrien file->to_fputs (b, file); 12698944Sobrien } 12798944Sobrien return; 12898944Sobrien } 12998944Sobrien} 13098944Sobrien 131130803Smarcelstatic long 132130803Smarcelnull_file_read (struct ui_file *file, 133130803Smarcel char *buf, 134130803Smarcel long sizeof_buf) 135130803Smarcel{ 136130803Smarcel errno = EBADF; 137130803Smarcel return 0; 138130803Smarcel} 139130803Smarcel 14098944Sobrienstatic void 14198944Sobriennull_file_fputs (const char *buf, struct ui_file *file) 14298944Sobrien{ 14398944Sobrien if (file->to_write == null_file_write) 14498944Sobrien /* Both the write and fputs methods are null. Discard the 14598944Sobrien request. */ 14698944Sobrien return; 14798944Sobrien else 14898944Sobrien { 14998944Sobrien /* The write method was implemented, use that. */ 15098944Sobrien file->to_write (file, buf, strlen (buf)); 15198944Sobrien } 15298944Sobrien} 15398944Sobrien 15498944Sobrienstatic void 15598944Sobriennull_file_delete (struct ui_file *file) 15698944Sobrien{ 15798944Sobrien return; 15898944Sobrien} 15998944Sobrien 16098944Sobrienvoid * 16198944Sobrienui_file_data (struct ui_file *file) 16298944Sobrien{ 16398944Sobrien if (file->magic != &ui_file_magic) 16498944Sobrien internal_error (__FILE__, __LINE__, 16598944Sobrien "ui_file_data: bad magic number"); 16698944Sobrien return file->to_data; 16798944Sobrien} 16898944Sobrien 16998944Sobrienvoid 17098944Sobriengdb_flush (struct ui_file *file) 17198944Sobrien{ 17298944Sobrien file->to_flush (file); 17398944Sobrien} 17498944Sobrien 17598944Sobrienint 17698944Sobrienui_file_isatty (struct ui_file *file) 17798944Sobrien{ 17898944Sobrien return file->to_isatty (file); 17998944Sobrien} 18098944Sobrien 18198944Sobrienvoid 18298944Sobrienui_file_rewind (struct ui_file *file) 18398944Sobrien{ 18498944Sobrien file->to_rewind (file); 18598944Sobrien} 18698944Sobrien 18798944Sobrienvoid 18898944Sobrienui_file_put (struct ui_file *file, 18998944Sobrien ui_file_put_method_ftype *write, 19098944Sobrien void *dest) 19198944Sobrien{ 19298944Sobrien file->to_put (file, write, dest); 19398944Sobrien} 19498944Sobrien 19598944Sobrienvoid 19698944Sobrienui_file_write (struct ui_file *file, 19798944Sobrien const char *buf, 19898944Sobrien long length_buf) 19998944Sobrien{ 20098944Sobrien file->to_write (file, buf, length_buf); 20198944Sobrien} 20298944Sobrien 203130803Smarcellong 204130803Smarcelui_file_read (struct ui_file *file, char *buf, long length_buf) 205130803Smarcel{ 206130803Smarcel return file->to_read (file, buf, length_buf); 207130803Smarcel} 208130803Smarcel 20998944Sobrienvoid 21098944Sobrienfputs_unfiltered (const char *buf, struct ui_file *file) 21198944Sobrien{ 21298944Sobrien file->to_fputs (buf, file); 21398944Sobrien} 21498944Sobrien 21598944Sobrienvoid 21698944Sobrienset_ui_file_flush (struct ui_file *file, ui_file_flush_ftype *flush) 21798944Sobrien{ 21898944Sobrien file->to_flush = flush; 21998944Sobrien} 22098944Sobrien 22198944Sobrienvoid 22298944Sobrienset_ui_file_isatty (struct ui_file *file, ui_file_isatty_ftype *isatty) 22398944Sobrien{ 22498944Sobrien file->to_isatty = isatty; 22598944Sobrien} 22698944Sobrien 22798944Sobrienvoid 22898944Sobrienset_ui_file_rewind (struct ui_file *file, ui_file_rewind_ftype *rewind) 22998944Sobrien{ 23098944Sobrien file->to_rewind = rewind; 23198944Sobrien} 23298944Sobrien 23398944Sobrienvoid 23498944Sobrienset_ui_file_put (struct ui_file *file, ui_file_put_ftype *put) 23598944Sobrien{ 23698944Sobrien file->to_put = put; 23798944Sobrien} 23898944Sobrien 23998944Sobrienvoid 24098944Sobrienset_ui_file_write (struct ui_file *file, 24198944Sobrien ui_file_write_ftype *write) 24298944Sobrien{ 24398944Sobrien file->to_write = write; 24498944Sobrien} 24598944Sobrien 24698944Sobrienvoid 247130803Smarcelset_ui_file_read (struct ui_file *file, ui_file_read_ftype *read) 248130803Smarcel{ 249130803Smarcel file->to_read = read; 250130803Smarcel} 251130803Smarcel 252130803Smarcelvoid 25398944Sobrienset_ui_file_fputs (struct ui_file *file, ui_file_fputs_ftype *fputs) 25498944Sobrien{ 25598944Sobrien file->to_fputs = fputs; 25698944Sobrien} 25798944Sobrien 25898944Sobrienvoid 25998944Sobrienset_ui_file_data (struct ui_file *file, void *data, 26098944Sobrien ui_file_delete_ftype *delete) 26198944Sobrien{ 26298944Sobrien file->to_data = data; 26398944Sobrien file->to_delete = delete; 26498944Sobrien} 26598944Sobrien 26698944Sobrien/* ui_file utility function for converting a ``struct ui_file'' into 26798944Sobrien a memory buffer''. */ 26898944Sobrien 26998944Sobrienstruct accumulated_ui_file 27098944Sobrien{ 27198944Sobrien char *buffer; 27298944Sobrien long length; 27398944Sobrien}; 27498944Sobrien 27598944Sobrienstatic void 27698944Sobriendo_ui_file_xstrdup (void *context, const char *buffer, long length) 27798944Sobrien{ 27898944Sobrien struct accumulated_ui_file *acc = context; 27998944Sobrien if (acc->buffer == NULL) 28098944Sobrien acc->buffer = xmalloc (length + 1); 28198944Sobrien else 28298944Sobrien acc->buffer = xrealloc (acc->buffer, acc->length + length + 1); 28398944Sobrien memcpy (acc->buffer + acc->length, buffer, length); 28498944Sobrien acc->length += length; 28598944Sobrien acc->buffer[acc->length] = '\0'; 28698944Sobrien} 28798944Sobrien 28898944Sobrienchar * 28998944Sobrienui_file_xstrdup (struct ui_file *file, 29098944Sobrien long *length) 29198944Sobrien{ 29298944Sobrien struct accumulated_ui_file acc; 29398944Sobrien acc.buffer = NULL; 29498944Sobrien acc.length = 0; 29598944Sobrien ui_file_put (file, do_ui_file_xstrdup, &acc); 29698944Sobrien if (acc.buffer == NULL) 29798944Sobrien acc.buffer = xstrdup (""); 29898944Sobrien *length = acc.length; 29998944Sobrien return acc.buffer; 30098944Sobrien} 30198944Sobrien 30298944Sobrien/* A pure memory based ``struct ui_file'' that can be used an output 30398944Sobrien buffer. The buffers accumulated contents are available via 30498944Sobrien ui_file_put(). */ 30598944Sobrien 30698944Sobrienstruct mem_file 30798944Sobrien { 30898944Sobrien int *magic; 30998944Sobrien char *buffer; 31098944Sobrien int sizeof_buffer; 31198944Sobrien int length_buffer; 31298944Sobrien }; 31398944Sobrien 31498944Sobrienstatic ui_file_rewind_ftype mem_file_rewind; 31598944Sobrienstatic ui_file_put_ftype mem_file_put; 31698944Sobrienstatic ui_file_write_ftype mem_file_write; 31798944Sobrienstatic ui_file_delete_ftype mem_file_delete; 31898944Sobrienstatic struct ui_file *mem_file_new (void); 31998944Sobrienstatic int mem_file_magic; 32098944Sobrien 32198944Sobrienstatic struct ui_file * 32298944Sobrienmem_file_new (void) 32398944Sobrien{ 32498944Sobrien struct mem_file *stream = XMALLOC (struct mem_file); 32598944Sobrien struct ui_file *file = ui_file_new (); 32698944Sobrien set_ui_file_data (file, stream, mem_file_delete); 32798944Sobrien set_ui_file_rewind (file, mem_file_rewind); 32898944Sobrien set_ui_file_put (file, mem_file_put); 32998944Sobrien set_ui_file_write (file, mem_file_write); 33098944Sobrien stream->magic = &mem_file_magic; 33198944Sobrien stream->buffer = NULL; 33298944Sobrien stream->sizeof_buffer = 0; 33398944Sobrien stream->length_buffer = 0; 33498944Sobrien return file; 33598944Sobrien} 33698944Sobrien 33798944Sobrienstatic void 33898944Sobrienmem_file_delete (struct ui_file *file) 33998944Sobrien{ 34098944Sobrien struct mem_file *stream = ui_file_data (file); 34198944Sobrien if (stream->magic != &mem_file_magic) 34298944Sobrien internal_error (__FILE__, __LINE__, 34398944Sobrien "mem_file_delete: bad magic number"); 34498944Sobrien if (stream->buffer != NULL) 34598944Sobrien xfree (stream->buffer); 34698944Sobrien xfree (stream); 34798944Sobrien} 34898944Sobrien 34998944Sobrienstruct ui_file * 35098944Sobrienmem_fileopen (void) 35198944Sobrien{ 35298944Sobrien return mem_file_new (); 35398944Sobrien} 35498944Sobrien 35598944Sobrienstatic void 35698944Sobrienmem_file_rewind (struct ui_file *file) 35798944Sobrien{ 35898944Sobrien struct mem_file *stream = ui_file_data (file); 35998944Sobrien if (stream->magic != &mem_file_magic) 36098944Sobrien internal_error (__FILE__, __LINE__, 36198944Sobrien "mem_file_rewind: bad magic number"); 36298944Sobrien stream->length_buffer = 0; 36398944Sobrien} 36498944Sobrien 36598944Sobrienstatic void 36698944Sobrienmem_file_put (struct ui_file *file, 36798944Sobrien ui_file_put_method_ftype *write, 36898944Sobrien void *dest) 36998944Sobrien{ 37098944Sobrien struct mem_file *stream = ui_file_data (file); 37198944Sobrien if (stream->magic != &mem_file_magic) 37298944Sobrien internal_error (__FILE__, __LINE__, 37398944Sobrien "mem_file_put: bad magic number"); 37498944Sobrien if (stream->length_buffer > 0) 37598944Sobrien write (dest, stream->buffer, stream->length_buffer); 37698944Sobrien} 37798944Sobrien 37898944Sobrienvoid 37998944Sobrienmem_file_write (struct ui_file *file, 38098944Sobrien const char *buffer, 38198944Sobrien long length_buffer) 38298944Sobrien{ 38398944Sobrien struct mem_file *stream = ui_file_data (file); 38498944Sobrien if (stream->magic != &mem_file_magic) 38598944Sobrien internal_error (__FILE__, __LINE__, 38698944Sobrien "mem_file_write: bad magic number"); 38798944Sobrien if (stream->buffer == NULL) 38898944Sobrien { 38998944Sobrien stream->length_buffer = length_buffer; 39098944Sobrien stream->sizeof_buffer = length_buffer; 39198944Sobrien stream->buffer = xmalloc (stream->sizeof_buffer); 39298944Sobrien memcpy (stream->buffer, buffer, length_buffer); 39398944Sobrien } 39498944Sobrien else 39598944Sobrien { 39698944Sobrien int new_length = stream->length_buffer + length_buffer; 39798944Sobrien if (new_length >= stream->sizeof_buffer) 39898944Sobrien { 39998944Sobrien stream->sizeof_buffer = new_length; 40098944Sobrien stream->buffer = xrealloc (stream->buffer, stream->sizeof_buffer); 40198944Sobrien } 40298944Sobrien memcpy (stream->buffer + stream->length_buffer, buffer, length_buffer); 40398944Sobrien stream->length_buffer = new_length; 40498944Sobrien } 40598944Sobrien} 40698944Sobrien 40798944Sobrien/* ``struct ui_file'' implementation that maps directly onto 40898944Sobrien <stdio.h>'s FILE. */ 40998944Sobrien 41098944Sobrienstatic ui_file_write_ftype stdio_file_write; 41198944Sobrienstatic ui_file_fputs_ftype stdio_file_fputs; 412130803Smarcelstatic ui_file_read_ftype stdio_file_read; 41398944Sobrienstatic ui_file_isatty_ftype stdio_file_isatty; 41498944Sobrienstatic ui_file_delete_ftype stdio_file_delete; 41598944Sobrienstatic struct ui_file *stdio_file_new (FILE * file, int close_p); 41698944Sobrienstatic ui_file_flush_ftype stdio_file_flush; 41798944Sobrien 41898944Sobrienstatic int stdio_file_magic; 41998944Sobrien 42098944Sobrienstruct stdio_file 42198944Sobrien { 42298944Sobrien int *magic; 42398944Sobrien FILE *file; 42498944Sobrien int close_p; 42598944Sobrien }; 42698944Sobrien 42798944Sobrienstatic struct ui_file * 42898944Sobrienstdio_file_new (FILE *file, int close_p) 42998944Sobrien{ 43098944Sobrien struct ui_file *ui_file = ui_file_new (); 43198944Sobrien struct stdio_file *stdio = xmalloc (sizeof (struct stdio_file)); 43298944Sobrien stdio->magic = &stdio_file_magic; 43398944Sobrien stdio->file = file; 43498944Sobrien stdio->close_p = close_p; 43598944Sobrien set_ui_file_data (ui_file, stdio, stdio_file_delete); 43698944Sobrien set_ui_file_flush (ui_file, stdio_file_flush); 43798944Sobrien set_ui_file_write (ui_file, stdio_file_write); 43898944Sobrien set_ui_file_fputs (ui_file, stdio_file_fputs); 439130803Smarcel set_ui_file_read (ui_file, stdio_file_read); 44098944Sobrien set_ui_file_isatty (ui_file, stdio_file_isatty); 44198944Sobrien return ui_file; 44298944Sobrien} 44398944Sobrien 44498944Sobrienstatic void 44598944Sobrienstdio_file_delete (struct ui_file *file) 44698944Sobrien{ 44798944Sobrien struct stdio_file *stdio = ui_file_data (file); 44898944Sobrien if (stdio->magic != &stdio_file_magic) 44998944Sobrien internal_error (__FILE__, __LINE__, 45098944Sobrien "stdio_file_delete: bad magic number"); 45198944Sobrien if (stdio->close_p) 45298944Sobrien { 45398944Sobrien fclose (stdio->file); 45498944Sobrien } 45598944Sobrien xfree (stdio); 45698944Sobrien} 45798944Sobrien 45898944Sobrienstatic void 45998944Sobrienstdio_file_flush (struct ui_file *file) 46098944Sobrien{ 46198944Sobrien struct stdio_file *stdio = ui_file_data (file); 46298944Sobrien if (stdio->magic != &stdio_file_magic) 46398944Sobrien internal_error (__FILE__, __LINE__, 46498944Sobrien "stdio_file_flush: bad magic number"); 46598944Sobrien fflush (stdio->file); 46698944Sobrien} 46798944Sobrien 468130803Smarcelstatic long 469130803Smarcelstdio_file_read (struct ui_file *file, char *buf, long length_buf) 470130803Smarcel{ 471130803Smarcel struct stdio_file *stdio = ui_file_data (file); 472130803Smarcel if (stdio->magic != &stdio_file_magic) 473130803Smarcel internal_error (__FILE__, __LINE__, 474130803Smarcel "stdio_file_read: bad magic number"); 475130803Smarcel return read (fileno (stdio->file), buf, length_buf); 476130803Smarcel} 477130803Smarcel 47898944Sobrienstatic void 47998944Sobrienstdio_file_write (struct ui_file *file, const char *buf, long length_buf) 48098944Sobrien{ 48198944Sobrien struct stdio_file *stdio = ui_file_data (file); 48298944Sobrien if (stdio->magic != &stdio_file_magic) 48398944Sobrien internal_error (__FILE__, __LINE__, 48498944Sobrien "stdio_file_write: bad magic number"); 48598944Sobrien fwrite (buf, length_buf, 1, stdio->file); 48698944Sobrien} 48798944Sobrien 48898944Sobrienstatic void 48998944Sobrienstdio_file_fputs (const char *linebuffer, struct ui_file *file) 49098944Sobrien{ 49198944Sobrien struct stdio_file *stdio = ui_file_data (file); 49298944Sobrien if (stdio->magic != &stdio_file_magic) 49398944Sobrien internal_error (__FILE__, __LINE__, 49498944Sobrien "stdio_file_fputs: bad magic number"); 49598944Sobrien fputs (linebuffer, stdio->file); 49698944Sobrien} 49798944Sobrien 49898944Sobrienstatic int 49998944Sobrienstdio_file_isatty (struct ui_file *file) 50098944Sobrien{ 50198944Sobrien struct stdio_file *stdio = ui_file_data (file); 50298944Sobrien if (stdio->magic != &stdio_file_magic) 50398944Sobrien internal_error (__FILE__, __LINE__, 50498944Sobrien "stdio_file_isatty: bad magic number"); 50598944Sobrien return (isatty (fileno (stdio->file))); 50698944Sobrien} 50798944Sobrien 50898944Sobrien/* Like fdopen(). Create a ui_file from a previously opened FILE. */ 50998944Sobrien 51098944Sobrienstruct ui_file * 51198944Sobrienstdio_fileopen (FILE *file) 51298944Sobrien{ 51398944Sobrien return stdio_file_new (file, 0); 51498944Sobrien} 51598944Sobrien 51698944Sobrienstruct ui_file * 51798944Sobriengdb_fopen (char *name, char *mode) 51898944Sobrien{ 51998944Sobrien FILE *f = fopen (name, mode); 52098944Sobrien if (f == NULL) 52198944Sobrien return NULL; 52298944Sobrien return stdio_file_new (f, 1); 52398944Sobrien} 524130803Smarcel 525130803Smarcel/* ``struct ui_file'' implementation that maps onto two ui-file objects. */ 526130803Smarcel 527130803Smarcelstatic ui_file_write_ftype tee_file_write; 528130803Smarcelstatic ui_file_fputs_ftype tee_file_fputs; 529130803Smarcelstatic ui_file_isatty_ftype tee_file_isatty; 530130803Smarcelstatic ui_file_delete_ftype tee_file_delete; 531130803Smarcelstatic ui_file_flush_ftype tee_file_flush; 532130803Smarcel 533130803Smarcelstatic int tee_file_magic; 534130803Smarcel 535130803Smarcelstruct tee_file 536130803Smarcel { 537130803Smarcel int *magic; 538130803Smarcel struct ui_file *one, *two; 539130803Smarcel int close_one, close_two; 540130803Smarcel }; 541130803Smarcel 542130803Smarcelstruct ui_file * 543130803Smarceltee_file_new (struct ui_file *one, int close_one, 544130803Smarcel struct ui_file *two, int close_two) 545130803Smarcel{ 546130803Smarcel struct ui_file *ui_file = ui_file_new (); 547130803Smarcel struct tee_file *tee = xmalloc (sizeof (struct tee_file)); 548130803Smarcel tee->magic = &tee_file_magic; 549130803Smarcel tee->one = one; 550130803Smarcel tee->two = two; 551130803Smarcel tee->close_one = close_one; 552130803Smarcel tee->close_two = close_two; 553130803Smarcel set_ui_file_data (ui_file, tee, tee_file_delete); 554130803Smarcel set_ui_file_flush (ui_file, tee_file_flush); 555130803Smarcel set_ui_file_write (ui_file, tee_file_write); 556130803Smarcel set_ui_file_fputs (ui_file, tee_file_fputs); 557130803Smarcel set_ui_file_isatty (ui_file, tee_file_isatty); 558130803Smarcel return ui_file; 559130803Smarcel} 560130803Smarcel 561130803Smarcelstatic void 562130803Smarceltee_file_delete (struct ui_file *file) 563130803Smarcel{ 564130803Smarcel struct tee_file *tee = ui_file_data (file); 565130803Smarcel if (tee->magic != &tee_file_magic) 566130803Smarcel internal_error (__FILE__, __LINE__, 567130803Smarcel "tee_file_delete: bad magic number"); 568130803Smarcel if (tee->close_one) 569130803Smarcel ui_file_delete (tee->one); 570130803Smarcel if (tee->close_two) 571130803Smarcel ui_file_delete (tee->two); 572130803Smarcel 573130803Smarcel xfree (tee); 574130803Smarcel} 575130803Smarcel 576130803Smarcelstatic void 577130803Smarceltee_file_flush (struct ui_file *file) 578130803Smarcel{ 579130803Smarcel struct tee_file *tee = ui_file_data (file); 580130803Smarcel if (tee->magic != &tee_file_magic) 581130803Smarcel internal_error (__FILE__, __LINE__, 582130803Smarcel "tee_file_flush: bad magic number"); 583130803Smarcel tee->one->to_flush (tee->one); 584130803Smarcel tee->two->to_flush (tee->two); 585130803Smarcel} 586130803Smarcel 587130803Smarcelstatic void 588130803Smarceltee_file_write (struct ui_file *file, const char *buf, long length_buf) 589130803Smarcel{ 590130803Smarcel struct tee_file *tee = ui_file_data (file); 591130803Smarcel if (tee->magic != &tee_file_magic) 592130803Smarcel internal_error (__FILE__, __LINE__, 593130803Smarcel "tee_file_write: bad magic number"); 594130803Smarcel ui_file_write (tee->one, buf, length_buf); 595130803Smarcel ui_file_write (tee->two, buf, length_buf); 596130803Smarcel} 597130803Smarcel 598130803Smarcelstatic void 599130803Smarceltee_file_fputs (const char *linebuffer, struct ui_file *file) 600130803Smarcel{ 601130803Smarcel struct tee_file *tee = ui_file_data (file); 602130803Smarcel if (tee->magic != &tee_file_magic) 603130803Smarcel internal_error (__FILE__, __LINE__, 604130803Smarcel "tee_file_fputs: bad magic number"); 605130803Smarcel tee->one->to_fputs (linebuffer, tee->one); 606130803Smarcel tee->two->to_fputs (linebuffer, tee->two); 607130803Smarcel} 608130803Smarcel 609130803Smarcelstatic int 610130803Smarceltee_file_isatty (struct ui_file *file) 611130803Smarcel{ 612130803Smarcel struct tee_file *tee = ui_file_data (file); 613130803Smarcel if (tee->magic != &tee_file_magic) 614130803Smarcel internal_error (__FILE__, __LINE__, 615130803Smarcel "tee_file_isatty: bad magic number"); 616130803Smarcel return (0); 617130803Smarcel} 618