1/* 2 * bz2.c -- 3 * 4 * Implements and registers compressor based on bzip2. 5 * 6 * 7 * Copyright (c) 1996 Andreas Kupries (a.kupries@westend.com) 8 * All rights reserved. 9 * 10 * Permission is hereby granted, without written agreement and without 11 * license or royalty fees, to use, copy, modify, and distribute this 12 * software and its documentation for any purpose, provided that the 13 * above copyright notice and the following two paragraphs appear in 14 * all copies of this software. 15 * 16 * IN NO EVENT SHALL I LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, 17 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS 18 * SOFTWARE AND ITS DOCUMENTATION, EVEN IF I HAVE BEEN ADVISED OF THE 19 * POSSIBILITY OF SUCH DAMAGE. 20 * 21 * I SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND 24 * I HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 25 * ENHANCEMENTS, OR MODIFICATIONS. 26 * 27 * CVS: $Id: bz2.c,v 1.8 2009/05/07 04:57:27 andreas_kupries Exp $ 28 */ 29 30#include "transformInt.h" 31 32/* 33 * Declarations of internal procedures. 34 */ 35 36static Trf_ControlBlock CreateEncoder _ANSI_ARGS_ ((ClientData writeClientData, 37 Trf_WriteProc *fun, 38 Trf_Options optInfo, 39 Tcl_Interp* interp, 40 ClientData clientData)); 41static void DeleteEncoder _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock, 42 ClientData clientData)); 43static int Encode _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock, 44 unsigned int character, 45 Tcl_Interp* interp, 46 ClientData clientData)); 47static int EncodeBuffer _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock, 48 unsigned char* buffer, int bufLen, 49 Tcl_Interp* interp, 50 ClientData clientData)); 51static int FlushEncoder _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock, 52 Tcl_Interp* interp, 53 ClientData clientData)); 54static void ClearEncoder _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock, 55 ClientData clientData)); 56 57static Trf_ControlBlock CreateDecoder _ANSI_ARGS_ ((ClientData writeClientData, 58 Trf_WriteProc *fun, 59 Trf_Options optInfo, 60 Tcl_Interp* interp, 61 ClientData clientData)); 62static void DeleteDecoder _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock, 63 ClientData clientData)); 64static int Decode _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock, 65 unsigned int character, 66 Tcl_Interp* interp, 67 ClientData clientData)); 68static int DecodeBuffer _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock, 69 unsigned char* buffer, int bufLen, 70 Tcl_Interp* interp, 71 ClientData clientData)); 72static int FlushDecoder _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock, 73 Tcl_Interp* interp, 74 ClientData clientData)); 75static void ClearDecoder _ANSI_ARGS_ ((Trf_ControlBlock ctrlBlock, 76 ClientData clientData)); 77 78static void Bz2libError _ANSI_ARGS_ ((Tcl_Interp* interp, 79 bz_stream* state, 80 int errcode, 81 CONST char* prefix)); 82 83 84/* 85 * Converter definition. 86 */ 87 88static Trf_TypeDefinition convDefinition = 89{ 90 "bz2", 91 NULL, /* client data not used */ 92 NULL, /* filled by TrfInit_ZB2, THREADING: serialize initialization */ 93 { 94 CreateEncoder, 95 DeleteEncoder, 96 Encode, 97 EncodeBuffer, 98 FlushEncoder, 99 ClearEncoder, 100 NULL /* no MaxRead */ 101 }, { 102 CreateDecoder, 103 DeleteDecoder, 104 Decode, 105 DecodeBuffer, 106 FlushDecoder, 107 ClearDecoder, 108 NULL /* no MaxRead */ 109 }, 110 TRF_UNSEEKABLE 111}; 112 113/* 114 * Definition of the control blocks for en- and decoder. 115 */ 116 117typedef struct _EncoderControl_ { 118 Trf_WriteProc* write; 119 ClientData writeClientData; 120 121 /* add conversion specific items here (BZ2) */ 122 123 bz_stream state; /* compressor state */ 124 125 char* output_buffer; 126 127} EncoderControl; 128 129 130typedef struct _DecoderControl_ { 131 Trf_WriteProc* write; 132 ClientData writeClientData; 133 134 /* add conversion specific items here (BZ2) */ 135 136 bz_stream state; /* decompressor state */ 137 138 char* output_buffer; 139 140 int lastRes; 141 142} DecoderControl; 143 144#define KILO (1024) 145#define OUT_SIZE (32 * KILO) 146 147 148/* 149 *------------------------------------------------------* 150 * 151 * TrfInit_BZ2 -- 152 * 153 * ------------------------------------------------* 154 * Register the compressor implemented in this file. 155 * ------------------------------------------------* 156 * 157 * Sideeffects: 158 * As of 'Trf_Register'. 159 * 160 * Result: 161 * A standard Tcl error code. 162 * 163 *------------------------------------------------------* 164 */ 165 166int 167TrfInit_BZ2 (interp) 168Tcl_Interp* interp; 169{ 170 TrfLock; /* THREADING: serialize initialization */ 171 convDefinition.options = TrfBZ2Options (); 172 TrfUnlock; 173 174 return Trf_Register (interp, &convDefinition); 175} 176 177/* 178 *------------------------------------------------------* 179 * 180 * CreateEncoder -- 181 * 182 * ------------------------------------------------* 183 * Allocate and initialize the control block of a 184 * data encoder. 185 * ------------------------------------------------* 186 * 187 * Sideeffects: 188 * Allocates memory. 189 * 190 * Result: 191 * An opaque reference to the control block. 192 * 193 *------------------------------------------------------* 194 */ 195 196static Trf_ControlBlock 197CreateEncoder (writeClientData, fun, optInfo, interp, clientData) 198ClientData writeClientData; 199Trf_WriteProc* fun; 200Trf_Options optInfo; 201Tcl_Interp* interp; 202ClientData clientData; 203{ 204 EncoderControl* c; 205 TrfBz2OptionBlock* o = (TrfBz2OptionBlock*) optInfo; 206 int res; 207 208 c = (EncoderControl*) ckalloc (sizeof (EncoderControl)); 209 c->write = fun; 210 c->writeClientData = writeClientData; 211 212 /* initialize conversion specific items here (BZ2) */ 213 214 c->state.bzalloc = NULL; 215 c->state.bzfree = NULL; 216 c->state.opaque = NULL; 217 218 c->output_buffer = (char*) ckalloc (OUT_SIZE); 219 220 if (c->output_buffer == (char*) NULL) { 221 ckfree ((VOID*) c); 222 return (ClientData) NULL; 223 } 224 225 res = bz.bcompressInit (&c->state, o->level, 0, 0); 226 227 if (res != BZ_OK) { 228 if (interp) { 229 Bz2libError (interp, &c->state, res, "compressor/init"); 230 } 231 232 ckfree ((VOID*) c->output_buffer); 233 ckfree ((VOID*) c); 234 return (ClientData) NULL; 235 } 236 237 return (ClientData) c; 238} 239 240/* 241 *------------------------------------------------------* 242 * 243 * DeleteEncoder -- 244 * 245 * ------------------------------------------------* 246 * Destroy the control block of an encoder. 247 * ------------------------------------------------* 248 * 249 * Sideeffects: 250 * Releases the memory allocated by 'CreateEncoder' 251 * 252 * Result: 253 * None. 254 * 255 *------------------------------------------------------* 256 */ 257 258static void 259DeleteEncoder (ctrlBlock, clientData) 260Trf_ControlBlock ctrlBlock; 261ClientData clientData; 262{ 263 EncoderControl* c = (EncoderControl*) ctrlBlock; 264 265 /* release conversion specific items here (BZ2) */ 266 267 bz.bcompressEnd (&c->state); 268 ckfree ((char*) c->output_buffer); 269 ckfree ((char*) c); 270} 271 272/* 273 *------------------------------------------------------* 274 * 275 * Encode -- 276 * 277 * ------------------------------------------------* 278 * Encode the given character and write the result. 279 * ------------------------------------------------* 280 * 281 * Sideeffects: 282 * As of the called WriteFun. 283 * 284 * Result: 285 * Generated bytes implicitly via WriteFun. 286 * A standard Tcl error code. 287 * 288 *------------------------------------------------------* 289 */ 290 291static int 292Encode (ctrlBlock, character, interp, clientData) 293Trf_ControlBlock ctrlBlock; 294unsigned int character; 295Tcl_Interp* interp; 296ClientData clientData; 297{ 298 EncoderControl* c = (EncoderControl*) ctrlBlock; 299 300 /* execute conversion specific code here (BZ2) */ 301 302 char in; 303 int res; 304 305 in = character; 306 307 c->state.next_in = (unsigned char*) (Bytef*) ∈ 308 c->state.avail_in = 1; 309 310 for (;;) { 311 c->state.next_out = (unsigned char*) (Bytef*) c->output_buffer; 312 c->state.avail_out = OUT_SIZE; 313 314 res = bz.bcompress (&c->state, BZ_RUN); 315 316 if (res < BZ_OK) { 317 if (interp) { 318 Bz2libError (interp, &c->state, res, "compressor"); 319 } 320 return TCL_ERROR; 321 } 322 323 if (c->state.avail_out < OUT_SIZE) { 324 res = c->write (c->writeClientData, (unsigned char*) c->output_buffer, 325 OUT_SIZE - c->state.avail_out, interp); 326 if (res != TCL_OK) { 327 return res; 328 } 329 } 330 331 if (c->state.avail_in > 0) 332 continue; 333 334 if ((c->state.avail_out == 0) && (res == BZ_OK)) 335 continue; 336 337 break; 338 } 339 340 return TCL_OK; 341} 342 343/* 344 *------------------------------------------------------* 345 * 346 * EncodeBuffer -- 347 * 348 * ------------------------------------------------* 349 * Encode the given buffer and write the result. 350 * ------------------------------------------------* 351 * 352 * Sideeffects: 353 * As of the called WriteFun. 354 * 355 * Result: 356 * Generated bytes implicitly via WriteFun. 357 * A standard Tcl error code. 358 * 359 *------------------------------------------------------* 360 */ 361 362static int 363EncodeBuffer (ctrlBlock, buffer, bufLen, interp, clientData) 364Trf_ControlBlock ctrlBlock; 365unsigned char* buffer; 366int bufLen; 367Tcl_Interp* interp; 368ClientData clientData; 369{ 370 EncoderControl* c = (EncoderControl*) ctrlBlock; 371 372 /* execute conversion specific code here (BZ2) */ 373 int res; 374 375 c->state.next_in = (unsigned char*) (Bytef*) buffer; 376 c->state.avail_in = bufLen; 377 378 for (;;) { 379 c->state.next_out = (unsigned char*) (Bytef*) c->output_buffer; 380 c->state.avail_out = OUT_SIZE; 381 382 res = bz.bcompress (&c->state, BZ_RUN); 383 384 if (res < BZ_OK) { 385 if (interp) { 386 Bz2libError (interp, &c->state, res, "compressor"); 387 } 388 return TCL_ERROR; 389 } 390 391 if (c->state.avail_out < OUT_SIZE) { 392 res = c->write (c->writeClientData, (unsigned char*) c->output_buffer, 393 OUT_SIZE - c->state.avail_out, interp); 394 if (res != TCL_OK) { 395 return res; 396 } 397 } 398 399 if (c->state.avail_in > 0) 400 continue; 401 402 if ((c->state.avail_out == 0) && (res == BZ_OK)) 403 continue; 404 405 break; 406 } 407 408 return TCL_OK; 409} 410 411/* 412 *------------------------------------------------------* 413 * 414 * FlushEncoder -- 415 * 416 * ------------------------------------------------* 417 * Encode an incomplete character sequence (if possible). 418 * ------------------------------------------------* 419 * 420 * Sideeffects: 421 * As of the called WriteFun. 422 * 423 * Result: 424 * Generated bytes implicitly via WriteFun. 425 * A standard Tcl error code. 426 * 427 *------------------------------------------------------* 428 */ 429 430static int 431FlushEncoder (ctrlBlock, interp, clientData) 432Trf_ControlBlock ctrlBlock; 433Tcl_Interp* interp; 434ClientData clientData; 435{ 436 EncoderControl* c = (EncoderControl*) ctrlBlock; 437 438 /* execute conversion specific code here (BZ2) */ 439 int res; 440 441 c->state.next_in = (unsigned char*) (Bytef*) NULL; 442 c->state.avail_in = 0; 443 444 for (;;) { 445 c->state.next_out = (unsigned char*) (Bytef*) c->output_buffer; 446 c->state.avail_out = OUT_SIZE; 447 448 res = bz.bcompress (&c->state, BZ_FINISH); 449 450 if (res < BZ_OK) { 451 if (interp) { 452 Bz2libError (interp, &c->state, res, "compressor/flush"); 453 } 454 return TCL_ERROR; 455 } 456 457 if (c->state.avail_out < OUT_SIZE) { 458 res = c->write (c->writeClientData, (unsigned char*) c->output_buffer, 459 OUT_SIZE - c->state.avail_out, interp); 460 if (res != TCL_OK) { 461 return res; 462 } 463 } 464 465 if ((c->state.avail_out == 0) && (res == BZ_OK)) 466 continue; 467 468 break; 469 } 470 471 return TCL_OK; 472} 473 474/* 475 *------------------------------------------------------* 476 * 477 * ClearEncoder -- 478 * 479 * ------------------------------------------------* 480 * Discard an incomplete character sequence. 481 * ------------------------------------------------* 482 * 483 * Sideeffects: 484 * See above. 485 * 486 * Result: 487 * None. 488 * 489 *------------------------------------------------------* 490 */ 491 492static void 493ClearEncoder (ctrlBlock, clientData) 494Trf_ControlBlock ctrlBlock; 495ClientData clientData; 496{ 497 /* EncoderControl* c = (EncoderControl*) ctrlBlock; */ 498 499 /* execute conversion specific code here (BZ2) */ 500 501 /* bz.bcompressReset (&c->state); */ 502} 503 504/* 505 *------------------------------------------------------* 506 * 507 * CreateDecoder -- 508 * 509 * ------------------------------------------------* 510 * Allocate and initialize the control block of a 511 * data decoder. 512 * ------------------------------------------------* 513 * 514 * Sideeffects: 515 * Allocates memory. 516 * 517 * Result: 518 * An opaque reference to the control block. 519 * 520 *------------------------------------------------------* 521 */ 522 523static Trf_ControlBlock 524CreateDecoder (writeClientData, fun, optInfo, interp, clientData) 525ClientData writeClientData; 526Trf_WriteProc* fun; 527Trf_Options optInfo; 528Tcl_Interp* interp; 529ClientData clientData; 530{ 531 DecoderControl* c; 532 int res; 533 534 c = (DecoderControl*) ckalloc (sizeof (DecoderControl)); 535 c->write = fun; 536 c->writeClientData = writeClientData; 537 538 /* initialize conversion specific items here (BZ2) */ 539 540 c->state.bzalloc = NULL; 541 c->state.bzfree = NULL; 542 c->state.opaque = NULL; 543 544 c->output_buffer = (char*) ckalloc (OUT_SIZE); 545 546 if (c->output_buffer == (char*) NULL) { 547 ckfree ((VOID*) c); 548 return (ClientData) NULL; 549 } 550 551 res = bz.bdecompressInit (&c->state, 0, 0); 552 553 if (res != BZ_OK) { 554 if (interp) { 555 Bz2libError (interp, &c->state, res, "decompressor/init"); 556 } 557 558 ckfree ((VOID*) c->output_buffer); 559 ckfree ((VOID*) c); 560 return (ClientData) NULL; 561 } 562 563 c->lastRes = res; 564 565 return (ClientData) c; 566} 567 568/* 569 *------------------------------------------------------* 570 * 571 * DeleteDecoder -- 572 * 573 * ------------------------------------------------* 574 * Destroy the control block of an decoder. 575 * ------------------------------------------------* 576 * 577 * Sideeffects: 578 * Releases the memory allocated by 'CreateDecoder' 579 * 580 * Result: 581 * None. 582 * 583 *------------------------------------------------------* 584 */ 585 586static void 587DeleteDecoder (ctrlBlock, clientData) 588Trf_ControlBlock ctrlBlock; 589ClientData clientData; 590{ 591 DecoderControl* c = (DecoderControl*) ctrlBlock; 592 593 /* release conversion specific items here (BZ2) */ 594 595 bz.bdecompressEnd (&c->state); 596 597 ckfree ((char*) c->output_buffer); 598 ckfree ((char*) c); 599} 600 601/* 602 *------------------------------------------------------* 603 * 604 * Decode -- 605 * 606 * ------------------------------------------------* 607 * Decode the given character and write the result. 608 * ------------------------------------------------* 609 * 610 * Sideeffects: 611 * As of the called WriteFun. 612 * 613 * Result: 614 * Generated bytes implicitly via WriteFun. 615 * A standard Tcl error code. 616 * 617 *------------------------------------------------------* 618 */ 619 620static int 621Decode (ctrlBlock, character, interp, clientData) 622Trf_ControlBlock ctrlBlock; 623unsigned int character; 624Tcl_Interp* interp; 625ClientData clientData; 626{ 627 DecoderControl* c = (DecoderControl*) ctrlBlock; 628 629 /* execute conversion specific code here (BZ2) */ 630 char in; 631 int res; 632 633 in = character; 634 635 c->state.next_in = (unsigned char*) (Bytef*) ∈ 636 c->state.avail_in = 1; 637 638 for (;;) { 639 c->state.next_out = (unsigned char*) (Bytef*) c->output_buffer; 640 c->state.avail_out = OUT_SIZE; 641 642 res = bz.bdecompress (&c->state); 643 c->lastRes = res; 644 645 if ((res < BZ_OK) && (res != BZ_STREAM_END)) { 646 if (interp) { 647 Bz2libError (interp, &c->state, res, "decompressor"); 648 } 649 return TCL_ERROR; 650 } 651 652 if (c->state.avail_out < OUT_SIZE) { 653 res = c->write (c->writeClientData, (unsigned char*) c->output_buffer, 654 OUT_SIZE - c->state.avail_out, interp); 655 if (res != TCL_OK) { 656 return res; 657 } 658 } 659 660 if (c->state.avail_in > 0) 661 continue; 662 663 if ((c->state.avail_out == 0) && (res == BZ_OK)) 664 continue; 665 666 break; 667 } 668 669 return TCL_OK; 670} 671 672/* 673 *------------------------------------------------------* 674 * 675 * DecodeBuffer -- 676 * 677 * ------------------------------------------------* 678 * Decode the given buffer and write the result. 679 * ------------------------------------------------* 680 * 681 * Sideeffects: 682 * As of the called WriteFun. 683 * 684 * Result: 685 * Generated bytes implicitly via WriteFun. 686 * A standard Tcl error code. 687 * 688 *------------------------------------------------------* 689 */ 690 691static int 692DecodeBuffer (ctrlBlock, buffer, bufLen, interp, clientData) 693Trf_ControlBlock ctrlBlock; 694unsigned char* buffer; 695int bufLen; 696Tcl_Interp* interp; 697ClientData clientData; 698{ 699 DecoderControl* c = (DecoderControl*) ctrlBlock; 700 701 /* execute conversion specific code here (BZ2) */ 702 int res; 703 704 c->state.next_in = (unsigned char*) (Bytef*) buffer; 705 c->state.avail_in = bufLen; 706 707 for (;;) { 708 c->state.next_out = (unsigned char*) (Bytef*) c->output_buffer; 709 c->state.avail_out = OUT_SIZE; 710 711 res = bz.bdecompress (&c->state); 712 c->lastRes = res; 713 714 if ((res < BZ_OK) && (res != BZ_STREAM_END)) { 715 if (interp) { 716 Bz2libError (interp, &c->state, res, "decompressor"); 717 } 718 return TCL_ERROR; 719 } 720 721 if (c->state.avail_out < OUT_SIZE) { 722 res = c->write (c->writeClientData, (unsigned char*) c->output_buffer, 723 OUT_SIZE - c->state.avail_out, interp); 724 if (res != TCL_OK) { 725 return res; 726 } 727 } 728 729 if (c->state.avail_in > 0) 730 continue; 731 732 if ((c->state.avail_out == 0) && (res == BZ_OK)) 733 continue; 734 735 break; 736 } 737 738 return TCL_OK; 739} 740 741/* 742 *------------------------------------------------------* 743 * 744 * FlushDecoder -- 745 * 746 * ------------------------------------------------* 747 * Decode an incomplete character sequence (if possible). 748 * ------------------------------------------------* 749 * 750 * Sideeffects: 751 * As of the called WriteFun. 752 * 753 * Result: 754 * Generated bytes implicitly via WriteFun. 755 * A standard Tcl error code. 756 * 757 *------------------------------------------------------* 758 */ 759 760static int 761FlushDecoder (ctrlBlock, interp, clientData) 762Trf_ControlBlock ctrlBlock; 763Tcl_Interp* interp; 764ClientData clientData; 765{ 766 DecoderControl* c = (DecoderControl*) ctrlBlock; 767 768 /* execute conversion specific code here (BZ2) */ 769 int res; 770 771 if (c->lastRes == BZ_STREAM_END) { 772 /* Essentially already flushed ! */ 773 return TCL_OK; 774 } 775 776 c->state.next_in = (unsigned char*) (Bytef*) c->output_buffer; /* fake out 777 * 'inflate' 778 */ 779 c->state.avail_in = 0; 780 781 for (;;) { 782 c->state.next_out = (unsigned char*) (Bytef*) c->output_buffer; 783 c->state.avail_out = OUT_SIZE; 784 785 res = bz.bdecompress (&c->state); 786 787 if ((res < BZ_OK) && (res != BZ_STREAM_END)) { 788 if (interp) { 789 Bz2libError (interp, &c->state, res, "decompressor/flush"); 790 } 791 return TCL_ERROR; 792 } 793 794 if (c->state.avail_out < OUT_SIZE) { 795 res = c->write (c->writeClientData, (unsigned char*) c->output_buffer, 796 OUT_SIZE - c->state.avail_out, interp); 797 if (res != TCL_OK) { 798 return res; 799 } 800 } 801 802 if ((c->state.avail_out == 0) && (res == BZ_OK)) 803 continue; 804 805 break; 806 } 807 808 return TCL_OK; 809} 810 811/* 812 *------------------------------------------------------* 813 * 814 * ClearDecoder -- 815 * 816 * ------------------------------------------------* 817 * Discard an incomplete character sequence. 818 * ------------------------------------------------* 819 * 820 * Sideeffects: 821 * See above. 822 * 823 * Result: 824 * None. 825 * 826 *------------------------------------------------------* 827 */ 828 829static void 830ClearDecoder (ctrlBlock, clientData) 831Trf_ControlBlock ctrlBlock; 832ClientData clientData; 833{ 834 /* DecoderControl* c = (DecoderControl*) ctrlBlock; */ 835 836 /* execute conversion specific code here (BZ2) */ 837 838 /* bz.bdecompressReset (&c->state); */ 839} 840 841/* 842 *------------------------------------------------------* 843 * 844 * Bz2libError -- 845 * 846 * ------------------------------------------------* 847 * Append error message from bzlib-state to interpreter 848 * ------------------------------------------------* 849 * 850 * Sideeffects: 851 * See above. 852 * 853 * Result: 854 * None. 855 * 856 *------------------------------------------------------* 857 */ 858 859static void 860Bz2libError (interp, state, errcode, prefix) 861Tcl_Interp* interp; 862bz_stream* state; 863int errcode; 864CONST char* prefix; 865{ 866 CONST char* msg; 867 868 /* 869 * A table-lookup might have been nicer, but this 870 * is more secure against changes of the codevalues 871 * used by bzlib. 872 */ 873 switch (errcode) { 874 case BZ_MEM_ERROR: 875 msg = "not enough memory available"; 876 break; 877 878 case BZ_SEQUENCE_ERROR: 879 msg = "sequence error"; 880 break; 881 882 case BZ_PARAM_ERROR: 883 msg = "param error"; 884 break; 885 886 case BZ_DATA_ERROR: 887 msg = "incoming data corrupted"; 888 break; 889 890 case BZ_DATA_ERROR_MAGIC: 891 msg = "magic number corrupted"; 892 break; 893 894 case BZ_IO_ERROR: 895 msg = "io error"; 896 break; 897 898 case BZ_UNEXPECTED_EOF: 899 msg = "unexpected eof"; 900 break; 901 902 case BZ_OUTBUFF_FULL: 903 msg = "output buffer full"; 904 break; 905 906 default: 907 msg = "?"; 908 break; 909 } 910 911 Tcl_AppendResult (interp, "bz2lib error (", (char*) NULL); 912 Tcl_AppendResult (interp, prefix, (char*) NULL); 913 Tcl_AppendResult (interp, "): ", (char*) NULL); 914 Tcl_AppendResult (interp, msg, (char*) NULL); 915} 916