Bug Summary

File:src/text_public.c
Location:line 672, column 3
Description:Value stored to 'ret' is never read

Annotated Source Code

1/*
2 *
3 *
4 * Copyright (c) 2003 Johannes Prix
5 * Copyright (c) 2004-2010 Arthur Huillet
6 *
7 * This file is part of Freedroid
8 *
9 * Freedroid is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * Freedroid is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Freedroid; see the file COPYING. If not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 *
24 */
25
26/**
27 * This file contains some text code, that is also needed in the
28 * dialog editor.
29 */
30
31#define _text_public_c
32
33#include "system.h"
34
35#include "defs.h"
36#include "struct.h"
37#include "proto.h"
38#include "global.h"
39
40#include <zlib.h>
41
42extern int debug_level;
43
44/**
45 * This function works a malloc, except that it also checks for
46 * success and terminates in case of "out of memory", so we don't
47 * need to do this always in the code.
48 */
49void *MyMalloc(long Mamount)
50{
51 void *Mptr = NULL((void*)0);
52
53 // make Gnu-compatible even if on a broken system:
54 if (Mamount == 0)
55 Mamount = 1;
56
57 if ((Mptr = calloc(1, (size_t) Mamount)) == NULL((void*)0)) {
58 fprintf(stderrstderr, " MyMalloc(%ld) did not succeed!\n", Mamount);
59 fflush(stderrstderr);
60 Terminate(EXIT_FAILURE1);
61 }
62
63 return Mptr;
64
65}; // void* MyMalloc ( long Mamount )
66
67/**
68 * This function is used for debugging purposes. It writes the
69 * given string on the screen, or simply does
70 * nothing according to currently set debug level.
71 */
72void DebugPrintf(int db_level, const char *fmt, ...)
73{
74 va_list args;
75 va_start(args, fmt)__builtin_va_start(args, fmt);
76
77 if (db_level <= debug_level) {
78 vfprintf(stderrstderr, fmt, args);
79 }
80
81 va_end(args)__builtin_va_end(args);
82}; // void DebugPrintf ( int db_level, char *fmt, ...)
83
84/**
85 * This function should help to simplify and standardize the many error
86 * messages possible in FreedroidRPG.
87 */
88void error_message(const char *fn, const char *fmt, int error_type, ...)
89{
90 if (error_type & SILENT)
91 return;
92
93 va_list args;
94 va_start(args, error_type)__builtin_va_start(args, error_type);
95
96 fprintf(stderrstderr, "\n---------------------------------------------------------------------------------\n"
97 "FreedroidRPG %s encountered a problem in function: %s\n", freedroid_version, fn);
98 vfprintf(stderrstderr, fmt, args);
99 fprintf(stderrstderr, "\n");
100
101 va_end(args)__builtin_va_end(args);
102
103 if (error_type & PLEASE_INFORM) {
104 fprintf(stderrstderr, "\n\n"
105 "If you encounter this message, please inform the FreedroidRPG developers about it!\n"
106 "You can\n"
107 " send an e-mail to freedroid-discussion AT lists.sourceforge.net\n"""
108 " mention it on our IRC channel #freedroid on irc.freenode.net\n"
109 " or report the bug on our tracker at http://bugs.freedroid.org/\n"
110 "\n"
111 "Thank you!\n");
112 }
113
114 if (error_type & IS_FATAL) {
115 fprintf(stderrstderr, "\nFreedroidRPG will terminate now to draw attention to the problems it could\n"
116 "not resolve. We are sorry if that interrupts a major game of yours.\n"
117 "---------------------------------------------------------------------------------\n");
118 } else {
119 fprintf(stderrstderr, "\nThe problem mentioned above is not fatal, we continue the execution.\n"
120 "---------------------------------------------------------------------------------\n");
121 }
122
123 if (error_type & IS_FATAL)
124 Terminate(EXIT_FAILURE1);
125}
126
127/**
128 * This function does something similar to memmem. Indeed, it would be
129 * best perhaps if it did exactly the same as memmem, but since we do not
130 * use gnu extensions for compatibility reasons, we go this way.
131 *
132 * Be careful with using this function for searching just one byte!!
133 *
134 * Be careful with using this function for non-string NEEDLE!!
135 *
136 * Haystack can of course have ANY form!!!
137 *
138 */
139void *MyMemmem(char *haystack, size_t haystacklen, char *needle, size_t needlelen)
140{
141 char *NextFoundPointer;
142 void *MatchPointer;
143 size_t SearchPos = 0;
144
145 while (haystacklen - SearchPos > 0) {
146 // We search for the first match OF THE FIRST CHARACTER of needle
147 //
148 NextFoundPointer = memchr(haystack + SearchPos, needle[0], haystacklen - SearchPos);
149
150 // if not even that was found, we can immediately return and report our failure to find it
151 //
152 if (NextFoundPointer == NULL((void*)0))
153 return (NULL((void*)0));
154
155 // Otherwise we see, if also the rest of the strings match this time ASSUMING THEY ARE STRINGS!
156 // In case of a match, we can return immediately
157 //
158 MatchPointer = strstr(NextFoundPointer, needle);
159 if (MatchPointer != NULL((void*)0))
160 return (MatchPointer);
161
162 // At this point, we know that we had no luck with this one occasion of a first-character-match
163 // and must continue after this one occasion with our search
164 SearchPos = NextFoundPointer - haystack + 1;
165 }
166
167 return (NULL((void*)0));
168}; // void *MyMemmem ( ... );
169
170/**
171 * This function looks for a string begin indicator and takes the string
172 * from after there up to a string end indicator and mallocs memory for
173 * it, copies it there and returns it.
174 * The original source string specified should in no way be modified.
175 * Returns 0 if the prefix string is not present
176 */
177char *ReadAndMallocStringFromDataOptional(char *SearchString, const char *StartIndicationString, const char *EndIndicationString)
178{
179 char *SearchPointer;
180 char *EndOfStringPointer;
181 char *ReturnString = NULL((void*)0);
182 int StringLength;
183
184 SearchPointer = strstr(SearchString, StartIndicationString);
185
186 if (!SearchPointer)
187 return 0;
188
189 // Now we move to the beginning
190 SearchPointer += strlen(StartIndicationString);
191
192 // Now we move to the end with the end pointer
193 EndOfStringPointer = strstr(SearchPointer, EndIndicationString);
194 if (!EndOfStringPointer)
195 return 0;
196
197 // Now we allocate memory and copy the string (even empty string)...
198 StringLength = EndOfStringPointer - SearchPointer;
199 ReturnString = MyMalloc(StringLength + 1);
200 strncpy(ReturnString, SearchPointer, StringLength)__builtin_strncpy (ReturnString, SearchPointer, StringLength);
201 ReturnString[StringLength] = 0;
202
203 return ReturnString;
204}
205
206/**
207 * This function looks for a string begin indicator and takes the string
208 * from after there up to a string end indicator and mallocs memory for
209 * it, copies it there and returns it.
210 * The original source string specified should in no way be modified.
211 * The lack of searched string is fatal.
212 */
213char *ReadAndMallocStringFromData(char *SearchString, const char *StartIndicationString, const char *EndIndicationString)
214{
215 char *result = ReadAndMallocStringFromDataOptional(SearchString, StartIndicationString, EndIndicationString);
216 if (!result) {
217 fprintf(stderrstderr, "\n\nStartIndicationString: '%s'\nEndIndicationString: '%s'\n", StartIndicationString, EndIndicationString);
218 error_message(__FUNCTION__, "\
219The string that is supposed to prefix an entry in a text data file\n\
220of FreedroidRPG was not found within this text data file.\n\
221This indicates some corruption in the data file in question.", PLEASE_INFORM | IS_FATAL);
222 }
223 return result;
224}; // char* ReadAndMallocStringFromData ( ... )
225
226/**
227 * This function counts the number of occurences of a string in a given
228 * other string.
229 */
230int CountStringOccurences(char *SearchString, const char *TargetString)
231{
232 int Counter = 0;
233 char *CountPointer;
234
235 CountPointer = SearchString;
236
237 while ((CountPointer = strstr(CountPointer, TargetString)) != NULL((void*)0)) {
238 CountPointer += strlen(TargetString);
239 Counter++;
240 }
241 return (Counter);
242}; // CountStringOccurences ( char* SearchString , char* TargetString )
243
244/**
245 * This function read in a file with the specified name, allocated
246 * memory for it of course, looks for the file end string and then
247 * terminates the whole read in file with a 0 character, so that it
248 * can easily be treated like a common string.
249 */
250char *ReadAndMallocAndTerminateFile(const char *filename, const char *File_End_String)
251{
252 FILE *DataFile;
253 char *Data;
254 char *ReadPointer;
255 long MemoryAmount;
256
257 // Read the whole theme data to memory. We use binary mode, as we
258 // don't want to have to deal with any carriage return/line feed
259 // convention mess on win32 or something...
260 //
261 if ((DataFile = fopen(filename, "rb")) == NULL((void*)0)) {
262 fprintf(stderrstderr, "\n\nfilename: '%s'\n", filename);
263
264 error_message(__FUNCTION__, "\
265FreedroidRPG was unable to open a given text file,\n\
266that should be there and should be accessible.\n\
267This indicates a serious bug in this installation of FreedroidRPG.", PLEASE_INFORM | IS_FATAL);
268 } else {
269 DebugPrintf(1, "\nchar* ReadAndMallocAndTerminateFile ( char* filename ) : Opening file succeeded...");
270 }
271
272 int filelen = FS_filelength(DataFile);
273 MemoryAmount = filelen + 100;
274 Data = (char *)MyMalloc(MemoryAmount);
275
276 if (fread(Data, 1, MemoryAmount, DataFile) < filelen && ferror(DataFile)) {
277 error_message(__FUNCTION__, "\
278 FreedroidRPG was unable to read a given text file, that should be there and\n\
279 should be accessible.\n\
280 Filename: %s", PLEASE_INFORM | IS_FATAL, filename);
281 } else {
282 DebugPrintf(1, "\n%s(): Reading file succeeded...", __FUNCTION__);
283 }
284
285 if (fclose(DataFile) == EOF(-1)) {
286 fprintf(stderrstderr, "\n\nfilename: '%s'\n", filename);
287 error_message(__FUNCTION__, "\
288 FreedroidRPG was unable to close a given text file, that should be there and\n\
289 should be accessible.\n\
290 This indicates a strange bug in this installation of Freedroid, that is\n\
291 very likely a problem with the file/directory permissions of the files\n\
292 belonging to FreedroidRPG.", PLEASE_INFORM | IS_FATAL);
293 } else {
294 DebugPrintf(1, "\n%s(): file closed successfully...\n", __FUNCTION__);
295 }
296
297 // NOTE: Since we do not assume to always have pure text files here, we switched to
298 // MyMemmem, so that we can handle 0 entries in the middle of the file content as well
299 if (File_End_String) {
300 if ((ReadPointer = MyMemmem(Data, (size_t) MemoryAmount, (char *)File_End_String, (size_t) strlen(File_End_String))) == NULL((void*)0)) {
301 error_message(__FUNCTION__, "FreedroidRPG was unable to find the string, that should indicate the end of\n"
302 "the given text file within this file.\n"
303 "This indicates a corrupt or outdated data or saved game file."
304 " filename: '%s' - File_End_String: '%s'",
305 PLEASE_INFORM | IS_FATAL, filename, File_End_String);
306 } else {
307 ReadPointer[0] = 0;
308 }
309 } else
310 Data[MemoryAmount - 100] = 0;
311
312 return (Data);
313}
314
315/**
316 * This function tries to locate a string in some given data string.
317 * The data string is assumed to be null terminated. Otherwise SEGFAULTS
318 * might happen.
319 *
320 * The return value is a pointer to the first instance where the substring
321 * we are searching is found in the main text.
322 */
323char *LocateStringInData(char *SearchBeginPointer, const char *SearchTextPointer)
324{
325 char *temp;
326
327 if ((temp = strstr(SearchBeginPointer, SearchTextPointer)) == NULL((void*)0)) {
328 fprintf(stderrstderr, "\n\nSearchTextPointer: '%s'\n", SearchTextPointer);
329 error_message(__FUNCTION__, "\
330The string that was supposed to be in the text data file could not be found.\n\
331This indicates a corrupted or seriously outdated game data or saved game file.", PLEASE_INFORM | IS_FATAL);
332 }
333
334 return (temp);
335
336}; // char* LocateStringInData ( ... )
337
338/**
339 * This function should analyze a given passage of text, locate an
340 * indicator for a value, and read in the value.
341 */
342void
343ReadValueFromStringWithDefault(char *SearchBeginPointer, const char *ValuePreceedText, const char *FormatString,
344 const char *DefaultValueString, void *TargetValue, char *EndOfSearchSectionPointer)
345{
346 char OldTerminaterCharValue = 0;
347 const char *SourceLocation;
348
349 // We shortly make a termination char into the string.
350 if (EndOfSearchSectionPointer) {
351 OldTerminaterCharValue = EndOfSearchSectionPointer[0];
352 EndOfSearchSectionPointer[0] = 0;
353 }
354
355 // Now we locate the spot, where we finally will find our value
356 SourceLocation = strstr(SearchBeginPointer, ValuePreceedText);
357 if (SourceLocation)
358 SourceLocation += strlen(ValuePreceedText);
359 else
360 SourceLocation = DefaultValueString;
361
362 // Attention!!!
363 // Now we try to read in the value!!!
364 //
365 if (sscanf(SourceLocation, FormatString, TargetValue) == EOF(-1)) {
366 error_message(__FUNCTION__, "sscanf using a certain format string failed!\n"
367 "This indicates a corrupted or seriously outdated game data or saved game file.\n"
368 " FormatString: '%s' - ValuePreceedText: '%s'",
369 PLEASE_INFORM | IS_FATAL, FormatString, ValuePreceedText);
370 }
371 // Now that we are done, we restore the given SearchArea to former glory
372 if (EndOfSearchSectionPointer) {
373 EndOfSearchSectionPointer[0] = OldTerminaterCharValue;
374 }
375}
376
377/**
378 * This function should analyze a given passage of text, locate an
379 * indicator for a value, and read in the value.
380 */
381void
382ReadValueFromString(char *SearchBeginPointer, const char *ValuePreceedText, const char *FormatString, void *TargetValue,
383 char *EndOfSearchSectionPointer)
384{
385 char OldTerminaterCharValue = 0;
386 char *SourceLocation;
387
388 // We shortly make a termination char into the string if needed
389 if (EndOfSearchSectionPointer) {
390 OldTerminaterCharValue = EndOfSearchSectionPointer[0];
391 EndOfSearchSectionPointer[0] = 0;
392 }
393 // Now we locate the spot, where we finally will find our value
394 SourceLocation = LocateStringInData(SearchBeginPointer, ValuePreceedText);
395 SourceLocation += strlen(ValuePreceedText);
396
397 // Attention!!!
398 // Now we try to read in the value!!!
399 //
400 if (sscanf(SourceLocation, FormatString, TargetValue) == EOF(-1)) {
401 error_message(__FUNCTION__, "sscanf using a certain format string failed!\n"
402 "This indicates a corrupted or seriously outdated game data or saved game file.\n"
403 " FormatString: '%s' - ValuePreceedText: '%s'",
404 PLEASE_INFORM | IS_FATAL, FormatString, ValuePreceedText);
405 }
406
407 if (EndOfSearchSectionPointer) {
408 // Now that we are done, we restore the given SearchArea to former glory
409 EndOfSearchSectionPointer[0] = OldTerminaterCharValue;
410 }
411
412}; // void ReadValueFromString( ... )
413
414/**
415 * \deprecated Use get_range_from_string.
416 * \brief Read a range of integer values from a string with a default.
417 *
418 * Read the range between two indications. The function don't accept negative value.
419 *
420 * \param SearchString The global string to search the range.
421 * \param StartIndicationString The start indication.
422 * \param EndIndicationString The end indication.
423 * \param min,max The result of the conversion.
424 * \param default_val The value used as default.
425 * \return FALSE if the conversion failed and set min and max to default_val, else return TRUE.
426 */
427int ReadRangeFromString(char *SearchString, const char *StartIndicationString, const char *EndIndicationString, int *min, int *max, int default_val)
428{
429 int result;
430
431 // First, we have to get the range string.
432 char *search_ptr = ReadAndMallocStringFromDataOptional(SearchString, StartIndicationString, EndIndicationString);
433
434 result = get_range_from_string(search_ptr, min, max, default_val);
435
436 //Handle corrupted values.
437 if (*min < 0) {
438 error_message(__FUNCTION__, "\
439The value read in as a minimum (%d) is a negative number.\n\
440This most likely means corrupted data.\n\
441Setting both the maximum and minimum to the default value (%d).", NO_REPORT, *min, default_val);
442 *min = *max = default_val;
443 return FALSE(0);
444 }
445
446 free(search_ptr);
447
448 return result;
449}
450
451/**
452 * \brief Read a range of integer values from a string with a default.
453 * \param str The constant string to convert.
454 * \param min,max The result of the conversion.
455 * \param default_value The value used in case of error or NULL.
456 * \return FALSE if the conversion failed and set min and max to default_val, else return TRUE.
457 */
458int get_range_from_string(const char *str, int *min, int *max, int default_value)
459{
460 char *ptr;
461
462 if (!str) {
463 // String is NULL, set everything to default value.
464 *min = *max = default_value;
465 return TRUE(1);
466 }
467
468 *min = strtol(str, &ptr, 10);
469
470 if (str == ptr) {
471 goto read_error;
472 }
473
474 if (*ptr == '\0') {
475 // Conversion succeeded and the string contains only one value.
476 *max = *min;
477 return TRUE(1);
478 }
479
480 if (*ptr != ':') {
481 goto read_error;
482 }
483
484 // The string contains potentially another value.
485 str = ++ptr;
486 *max = strtol(str, &ptr, 10);
487
488 if (str == ptr) {
489 goto read_error;
490 }
491 // Conversion of max value succeeded
492
493 if (*max >= *min) {
494 return TRUE(1); // Values are in the good order.
495 }
496
497 error_message(__FUNCTION__, "The value read in as a maximum (%d) is less than the minimum (%d).\n"
498 "This most likely means corrupted data.\n"
499 "Setting both the maximum and minimum to the default value (%d).",
500 NO_REPORT, *max, *min, default_value);
501 *min = *max = default_value;
502 return FALSE(0);
503
504read_error:
505 // Failed to read the string.
506 error_message(__FUNCTION__, "The string (\"%s\") cannot be legaly converted to a range of integers.\n"
507 "This most likely means corrupted data.\n"
508 "Setting both the maximum and minimum to the default value (%d).",
509 NO_REPORT, str, default_value);
510 *min = *max = default_value;
511 return FALSE(0);
512}
513
514/**
515 * This function does the rotation of a given vector by a given angle.
516 * The vector is a vector.
517 * The angle given is in DEGREE MEASURE, i.e. 0-360 or so, maybe more or
518 * less than that, but you get what I mean...
519 */
520void RotateVectorByAngle(moderately_finepoint * vector, float rot_angle)
521{
522 moderately_finepoint new_vect;
523 float rad_angle;
524
525 if (rot_angle == 0)
526 return;
527
528 rad_angle = rot_angle * (M_PI3.14159265358979323846 / 180.0);
529
530 DebugPrintf(2, "\n RAD_ANGLE : %f ", rad_angle);
531 new_vect.x = sin(rad_angle) * vector->y + cos(rad_angle) * vector->x;
532 new_vect.y = cos(rad_angle) * vector->y - sin(rad_angle) * vector->x;
533 vector->x = new_vect.x;
534 vector->y = new_vect.y;
535
536}; // void RotateVectorByAngle ( ... )
537
538/*----------------------------------------------------------------------
539 * Copyright (C) 1997-2001 Id Software, Inc., under GPL
540 *
541 * FS_filelength().. (taken from quake2)
542 * contrary to stat() this fct is nice and portable,
543 *----------------------------------------------------------------------*/
544int FS_filelength(FILE * f)
545{
546 int pos;
547 int end;
548
549 pos = ftell(f);
550 fseek(f, 0, SEEK_END2);
551 end = ftell(f);
552 fseek(f, pos, SEEK_SET0);
553
554 // DebugPrintf ( -4 , "\n%s(): file length: %d." , __FUNCTION__ , end );
555
556 return end;
557}; // int FS_filelength (FILE *f)
558
559/*-------------------------------------------------------------------------
560 * Inflate a given stream using zlib
561 *
562 * Takes DataFile file and points DataBuffer to a buffer containing the
563 * uncompressed data. Sets '*size' to the size of said uncompressed data, if size
564 * is not NULL.
565 *
566 * Returns nonzero in case of error.
567 ***/
568int inflate_stream(FILE * DataFile, unsigned char **DataBuffer, int *size)
569{
570 int filelen = FS_filelength(DataFile);
571 unsigned char *src = MyMalloc(filelen + 1);
572 int cursz = 1048576; //start with 1MB
573 unsigned char *temp_dbuffer = malloc(cursz);
574 if (fread(src, filelen, 1, DataFile) != 1) {
575 error_message(__FUNCTION__, "Error reading compressed data stream.", PLEASE_INFORM);
576 free(temp_dbuffer);
577 free(src);
578 return -1;
579 }
580
581 int ret;
582 z_stream strm;
583
584 /* copy paste of public domain tool "zpipe" */
585 /* big thanks to zlib authors */
586 /* allocate inflate state */
587 strm.zalloc = Z_NULL0;
588 strm.zfree = Z_NULL0;
589 strm.opaque = Z_NULL0;
590 strm.avail_in = filelen;
591 strm.next_in = src;
592 strm.avail_out = cursz;
593 strm.next_out = (Bytef *) temp_dbuffer;
594
595 ret = inflateInit2(&strm, 47)inflateInit2_((&strm), (47), "1.2.8", (int)sizeof(z_stream
))
;
596 if (ret != Z_OK0) {
597 error_message(__FUNCTION__, "\
598 zlib was unable to start decompressing a stream.\n\
599 This indicates a serious bug in this installation of FreedroidRPG.", PLEASE_INFORM);
600 free(temp_dbuffer);
601 free(src);
602 return -1;
603 }
604
605 do {
606 if (!strm.avail_out) { //out of memory? increase
607 temp_dbuffer = realloc(temp_dbuffer, cursz + 1048576); //increase size by 1MB
608 strm.next_out = temp_dbuffer + cursz;
609 cursz += 1048576;
610 strm.avail_out += 1048576;
611 }
612 ret = inflate(&strm, Z_NO_FLUSH0);
613 switch (ret) {
614 case Z_OK0:
615 break;
616 case Z_NEED_DICT2:
617 case Z_DATA_ERROR(-3):
618 case Z_MEM_ERROR(-4):
619 (void)inflateEnd(&strm);
620
621 error_message(__FUNCTION__, "\
622 zlib was unable to decompress a stream\n\
623 This indicates a serious bug in this installation of FreedroidRPG.", PLEASE_INFORM);
624 free(temp_dbuffer);
625 free(src);
626 return -1;
627 break;
628 }
629 } while (ret != Z_STREAM_END1);
630
631 (*DataBuffer) = (unsigned char *)malloc(strm.total_out + 1);
632 memcpy(*DataBuffer, temp_dbuffer, strm.total_out);
633 (*DataBuffer)[strm.total_out] = 0;
634
635 if (size != NULL((void*)0))
636 *size = strm.total_out;
637
638 (void)inflateEnd(&strm);
639 free(src);
640 free(temp_dbuffer);
641
642 return 0;
643}
644
645int deflate_to_stream(unsigned char *source_buffer, int size, FILE *dest)
646{
647 int ret;
648 unsigned have;
649 z_stream strm;
650#define CHUNK16384 16384
651 unsigned char out[CHUNK16384];
652
653 /* allocate deflate state */
654 strm.zalloc = Z_NULL0;
655 strm.zfree = Z_NULL0;
656 strm.opaque = Z_NULL0;
657 strm.avail_in = size;
658 strm.next_in = source_buffer;
659
660 ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY)deflateInit2_((&strm),((-1)),(8),(31),(8), (0), "1.2.8", (
int)sizeof(z_stream))
;
661 if (ret != Z_OK0) {
662 error_message(__FUNCTION__, "\
663 zlib was unable to start compressing a string.", PLEASE_INFORM);
664 return -1;
665 }
666
667 /* run deflate() on input until output buffer not full, finish
668 compression if all of source has been read in */
669 do {
670 strm.avail_out = CHUNK16384;
671 strm.next_out = out;
672 ret = deflate(&strm, Z_FINISH4); /* no bad return value */
Value stored to 'ret' is never read
673 have = CHUNK16384 - strm.avail_out;
674 if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
675 (void)deflateEnd(&strm);
676 return -1;
677 }
678 } while (strm.avail_out == 0);
679
680 /* clean up and return */
681 (void)deflateEnd(&strm);
682
683 return 0;
684}
685
686#undef _text_public_c