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