From 4fa96a42f752bd70958eaf2635de7e0a875f13a2 Mon Sep 17 00:00:00 2001 From: John Bowler Date: Wed, 16 Nov 2011 16:39:16 -0600 Subject: [PATCH] [libpng15] Fixes for C++ compilation using g++ When libpng source is compiled using g++. The compiler imposes C++ rules on the C source; thus it is desireable to make the source work with either C or C++ rules without throwing away useful error information. This change adds png_voidcast to allow C semantic (void*) cases or the corresponding C++ static_cast operation, as appropriate. --- ANNOUNCE | 6 ++++++ png.c | 4 ++-- pngerror.c | 11 +++++++---- pngpriv.h | 26 ++++++++++++++++++++++++-- pngread.c | 26 ++++++++++++++++---------- pngwrite.c | 34 +++++++++++++++++++++------------- 6 files changed, 76 insertions(+), 31 deletions(-) diff --git a/ANNOUNCE b/ANNOUNCE index 83fb03a63..661151a88 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -78,6 +78,12 @@ Version 1.5.7beta03 [November 16, 2011] libpng transform code. This check-in also contains fixes to various bugs in the simplified APIs themselves and to some bugs in compose and rgb to gray (on palette) itself. + Fixes for C++ compilation using g++ When libpng source is compiled + using g++. The compiler imposes C++ rules on the C source; thus it + is desireable to make the source work with either C or C++ rules + without throwing away useful error information. This change adds + png_voidcast to allow C semantic (void*) cases or the corresponding + C++ static_cast operation, as appropriate. Send comments/corrections/commendations to png-mng-implement at lists.sf.net: (subscription required; visit diff --git a/png.c b/png.c index b55eae9a1..14ab048bd 100644 --- a/png.c +++ b/png.c @@ -3028,7 +3028,7 @@ png_byte png_sRGB_delta[512] = static int png_image_free_function(png_voidp argument) { - png_imagep image = argument; + png_imagep image = png_voidcast(png_imagep, argument); png_controlp cp = image->opaque; png_control c; @@ -3042,7 +3042,7 @@ png_image_free_function(png_voidp argument) # ifdef PNG_STDIO_SUPPORTED if (cp->owned_file) { - FILE *fp = cp->png_ptr->io_ptr; + FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr); cp->owned_file = 0; /* Ignore errors here. */ diff --git a/pngerror.c b/pngerror.c index 74f8cc845..d09bcba24 100644 --- a/pngerror.c +++ b/pngerror.c @@ -684,7 +684,7 @@ PNG_FUNCTION(void /* PRIVATE */, png_safe_error,(png_structp png_ptr, png_const_charp error_message), PNG_NORETURN) { - png_imagep image = png_ptr->error_ptr; + png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); /* An error is always logged here, overwriting anything (typically a warning) * that is already there: @@ -694,9 +694,12 @@ png_safe_error,(png_structp png_ptr, png_const_charp error_message), png_safecat(image->message, sizeof image->message, 0, error_message); image->warning_or_error = 1; - /* Retrieve the jmp_buf from within the png_control */ + /* Retrieve the jmp_buf from within the png_control, making this work for + * C++ compilation too is pretty tricky: C++ wants a pointer to the first + * element of a jmp_buf, but C doesn't tell us the type of that. + */ if (image->opaque != NULL && image->opaque->error_buf != NULL) - longjmp(image->opaque->error_buf, 1); + longjmp(png_control_jmp_buf(image->opaque), 1); /* Missing longjmp buffer, the following is to help debugging: */ { @@ -714,7 +717,7 @@ png_safe_error,(png_structp png_ptr, png_const_charp error_message), void /* PRIVATE */ png_safe_warning(png_structp png_ptr, png_const_charp warning_message) { - png_imagep image = png_ptr->error_ptr; + png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); /* A warning is only logged if there is no prior warning or error. */ if (image->warning_or_error == 0) diff --git a/pngpriv.h b/pngpriv.h index 04cf55234..6f6a85af8 100644 --- a/pngpriv.h +++ b/pngpriv.h @@ -234,15 +234,28 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; # define png_fixed_error(s1,s2) png_err(s1) #endif +/* C allows up-casts from (void*) to any pointer and (const void*) to any + * pointer to a const object. C++ regards this as a type error and requires an + * explicit, static, cast and provides the static_cast<> rune to ensure that + * const is not cast away. + */ +#ifdef __cplusplus +# define png_voidcast(type, value) static_cast(value) +#else +# define png_voidcast(type, value) (value) +#endif /* __cplusplus */ + #ifndef PNG_EXTERN /* The functions exported by PNG_EXTERN are internal functions, which * aren't usually used outside the library (as far as I know), so it is * debatable if they should be exported at all. In the future, when it * is possible to have run-time registry of chunk-handling functions, * some of these might be made available again. -# define PNG_EXTERN extern + * + * 1.5.7: turned the use of 'extern' back on, since it is localized to pngpriv.h + * it should be safe now (it is unclear why it was turned off.) */ -# define PNG_EXTERN +# define PNG_EXTERN extern #endif /* Some fixed point APIs are still required even if not exported because @@ -1642,6 +1655,15 @@ typedef struct png_control unsigned int owned_file :1; /* We own the file in io_ptr */ } png_control; +/* Return the pointer to the jmp_buf from a png_control: necessary because C + * does not reveal the type of the elements of jmp_buf. + */ +#ifdef __cplusplus +# define png_control_jmp_buf(pc) (((jmp_buf*)((pc)->error_buf))[0]) +#else +# define png_control_jmp_buf(pc) ((pc)->error_buf) +#endif + /* Utility to safely execute a piece of libpng code catching and logging any * errors that might occur. Returns true on success, false on failure (either * of the function or as a result of a png_error.) diff --git a/pngread.c b/pngread.c index 01dc75291..e55ec73fa 100644 --- a/pngread.c +++ b/pngread.c @@ -1332,7 +1332,8 @@ png_image_read_init(png_imagep image) if (info_ptr != NULL) { - png_controlp control = png_malloc_warn(png_ptr, sizeof *control); + png_controlp control = png_voidcast(png_controlp, + png_malloc_warn(png_ptr, sizeof *control)); if (control != NULL) { @@ -1384,7 +1385,7 @@ png_image_format(png_structp png_ptr, png_infop info_ptr) static int png_image_read_header(png_voidp argument) { - png_imagep image = argument; + png_imagep image = png_voidcast(png_imagep, argument); png_structp png_ptr = image->opaque->png_ptr; png_infop info_ptr = image->opaque->info_ptr; @@ -1508,7 +1509,7 @@ png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) { if (png_ptr != NULL) { - png_imagep image = png_ptr->io_ptr; + png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr); if (image != NULL) { png_controlp cp = image->opaque; @@ -1546,7 +1547,7 @@ int PNGAPI png_image_begin_read_from_memory(png_imagep image, * store it into io_ptr. Again do this in-place to avoid calling a * libpng function that requires error handling. */ - image->opaque->memory = memory; + image->opaque->memory = png_voidcast(png_const_bytep, memory); image->opaque->size = size; image->opaque->png_ptr->io_ptr = image; image->opaque->png_ptr->read_data_fn = png_image_memory_read; @@ -1581,7 +1582,8 @@ typedef struct static int png_image_read_composite(png_voidp argument) { - png_image_read_control *display = argument; + png_image_read_control *display = png_voidcast(png_image_read_control*, + argument); png_imagep image = display->image; png_structp png_ptr = image->opaque->png_ptr; png_byte interlace_type = png_ptr->interlaced; @@ -1707,7 +1709,8 @@ png_image_read_composite(png_voidp argument) static int png_image_read_background(png_voidp argument) { - png_image_read_control *display = argument; + png_image_read_control *display = png_voidcast(png_image_read_control*, + argument); png_imagep image = display->image; png_structp png_ptr = image->opaque->png_ptr; png_infop info_ptr = image->opaque->info_ptr; @@ -1965,7 +1968,8 @@ png_image_read_background(png_voidp argument) static int png_image_read_end(png_voidp argument) { - png_image_read_control *display = argument; + png_image_read_control *display = png_voidcast(png_image_read_control*, + argument); png_imagep image = display->image; png_structp png_ptr = image->opaque->png_ptr; png_infop info_ptr = image->opaque->info_ptr; @@ -2347,7 +2351,7 @@ png_image_read_end(png_voidp argument) * display acts as a flag. */ { - png_bytep first_row = display->buffer; + png_bytep first_row = png_voidcast(png_bytep, display->buffer); ptrdiff_t row_bytes = display->row_stride; if (linear) @@ -2366,7 +2370,8 @@ png_image_read_end(png_voidp argument) if (do_local_compose) { int result; - png_bytep row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); + png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr))); display->local_row = row; result = png_safe_execute(image, png_image_read_composite, display); @@ -2379,7 +2384,8 @@ png_image_read_end(png_voidp argument) else if (do_local_background == 2) { int result; - png_bytep row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); + png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr))); display->local_row = row; result = png_safe_execute(image, png_image_read_background, display); diff --git a/pngwrite.c b/pngwrite.c index fad6cc670..41cba812b 100644 --- a/pngwrite.c +++ b/pngwrite.c @@ -1672,7 +1672,8 @@ png_image_write_init(png_imagep image) if (info_ptr != NULL) { - png_controlp control = png_malloc_warn(png_ptr, sizeof *control); + png_controlp control = png_voidcast(png_controlp, + png_malloc_warn(png_ptr, sizeof *control)); if (control != NULL) { @@ -1717,12 +1718,14 @@ typedef struct static int png_write_image_16bit(png_voidp argument) { - png_image_write_control *display = argument; + png_image_write_control *display = png_voidcast(png_image_write_control*, + argument); png_imagep image = display->image; png_structp png_ptr = image->opaque->png_ptr; - png_const_uint_16p input_row = display->first_row; - png_uint_16p output_row = display->local_row; + png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, + display->first_row); + png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row); png_uint_16p row_end; int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; int aindex = 0; @@ -1805,7 +1808,7 @@ png_write_image_16bit(png_voidp argument) ++out_ptr; } - png_write_row(png_ptr, display->local_row); + png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row)); input_row += display->row_bytes/(sizeof (png_uint_16)); } @@ -1819,12 +1822,14 @@ png_write_image_16bit(png_voidp argument) static int png_write_image_8bit(png_voidp argument) { - png_image_write_control *display = argument; + png_image_write_control *display = png_voidcast(png_image_write_control*, + argument); png_imagep image = display->image; png_structp png_ptr = image->opaque->png_ptr; - png_const_uint_16p input_row = display->first_row; - png_bytep output_row = display->local_row; + png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, + display->first_row); + png_bytep output_row = png_voidcast(png_bytep, display->local_row); png_uint_32 y = image->height; int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; @@ -1917,7 +1922,8 @@ png_write_image_8bit(png_voidp argument) ++out_ptr; } /* while out_ptr < row_end */ - png_write_row(png_ptr, display->local_row); + png_write_row(png_ptr, png_voidcast(png_const_bytep, + display->local_row)); input_row += display->row_bytes/(sizeof (png_uint_16)); } /* while y */ } @@ -1953,7 +1959,8 @@ png_write_image_8bit(png_voidp argument) static int png_image_write_main(png_voidp argument) { - png_image_write_control *display = argument; + png_image_write_control *display = png_voidcast(png_image_write_control*, + argument); png_imagep image = display->image; png_structp png_ptr = image->opaque->png_ptr; png_infop info_ptr = image->opaque->info_ptr; @@ -2039,7 +2046,7 @@ png_image_write_main(png_voidp argument) png_error(png_ptr, "png_write_image: unsupported transformation"); { - png_const_bytep row = display->buffer; + png_const_bytep row = png_voidcast(png_const_bytep, display->buffer); ptrdiff_t row_bytes = display->row_stride; if (linear) @@ -2058,7 +2065,8 @@ png_image_write_main(png_voidp argument) */ if ((linear && alpha) || display->convert_to_8bit) { - png_bytep row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); + png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr))); int result; display->local_row = row; @@ -2080,7 +2088,7 @@ png_image_write_main(png_voidp argument) */ else { - png_const_bytep row = display->first_row; + png_const_bytep row = png_voidcast(png_const_bytep, display->first_row); ptrdiff_t row_bytes = display->row_bytes; png_uint_32 y = image->height;