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