error using MacPorts zlib, not present with system zlib?

2012-02-22 Thread Adam Mercer
Hi

Not sure of the correct place to discuss this but in tracking down a
build issue with a port I've found an interesting issue with MacPorts
zlib.

This simple test code illustrates the problem:

[ram@mimir tmp]$ cat test.c
#include stdio.h
#include stdlib.h
#include zlib.h

int main(void)
{
  void *file;
  int c;

  file = gzopen(test.dat.gz, r);
  if (file == Z_NULL)
  {
fprintf(stderr, unable to open file\n);
exit(1);
  }

  c = gzgetc(file);

  fprintf(stdout, c = %c\n, c);

  gzclose(file);
}
[ram@mimir tmp]$ zcat test.dat.gz
test
file

If I compile this against the system zlib then it works as expected:

[ram@mimir tmp]$ clang -o test test.c -lz
[ram@mimir tmp]$ ./test
c = t

But not against the MacPorts zlib:

[ram@mimir tmp]$ clang -o test test.c -I/opt/local/include -L/opt/local/lib -lz
test.c:17:7: error: member reference base type 'void' is not a structure or
  union
  c = gzgetc(file);
  ^~~~
/opt/local/include/zlib.h:1655:11: note: instantiated from:
((g)-have ? ((g)-have--, (g)-pos++, *((g)-next)++) : gzgetc_(g))
 ~~~  ^
test.c:17:7: error: member reference base type 'void' is not a structure or
  union
  c = gzgetc(file);
  ^~~~
/opt/local/include/zlib.h:1655:24: note: instantiated from:
((g)-have ? ((g)-have--, (g)-pos++, *((g)-next)++) : gzgetc_(g))
  ~~~  ^
test.c:17:7: error: member reference base type 'void' is not a structure or
  union
  c = gzgetc(file);
  ^~~~
/opt/local/include/zlib.h:1655:37: note: instantiated from:
((g)-have ? ((g)-have--, (g)-pos++, *((g)-next)++) : gzgetc_(g))
   ~~~  ^
test.c:17:7: error: member reference base type 'void' is not a structure or
  union
  c = gzgetc(file);
  ^~~~
/opt/local/include/zlib.h:1655:51: note: instantiated from:
((g)-have ? ((g)-have--, (g)-pos++, *((g)-next)++) : gzgetc_(g))
 ~~~  ^
4 errors generated.
[ram@mimir tmp]$

Does anyone know why MacPorts zlib treats this as an error but the
system version doesn't?

Cheers

Adam
___
macports-users mailing list
macports-users@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macports-users


Re: error using MacPorts zlib, not present with system zlib?

2012-02-22 Thread Eric Cronin

On 22.02.2012 15:32, Adam Mercer wrote:

Hi

Not sure of the correct place to discuss this but in tracking down a
build issue with a port I've found an interesting issue with MacPorts
zlib.

This simple test code illustrates the problem:

[ram@mimir tmp]$ cat test.c
#include stdio.h
#include stdlib.h
#include zlib.h

int main(void)
{
  void *file;


snip


  c = gzgetc(file);


This code is wrong.  The zlib documentation says gzgetc takes a gzFile* 
not a void*.




Does anyone know why MacPorts zlib treats this as an error but the
system version doesn't?


I'm not near a Mac right now, but I believe the system version of zlib 
is pretty ancient.  In version 1.2.4 there was a Wholesale replacement 
of gz* functions with faster versions according to zlib.net, one of 
which I suspect was the replacement of the gzgetc() function with a 
macro.


C treats void* very unsafely, silently converting it to and from other 
pointer types whenever it knows how.  So converting the gzFile* gzopen() 
returned to the void* 'file' is legal.  Then, if gzgetc() is an actual 
function declared as 'char gzgetc(gzFile*)' the compiler will allow the 
void* be passed to the function, and within the function it is treated 
as a gzFile*.  But if gzgetc is just a macro the compiler doesn't know 
to convert 'file' to a gzFile*, so you get errors about trying to treat 
void as struct/union.  If the API said gzgetc took a void* they would 
fix this by casting g to a gzFile* inside the macro that replaced the 
function, but the API doesn't say this, and so the zlib authors don't... 
The current version is actually both faster and safer since it catches 
this type of void* abuse.


So tldr answer: patch the port using libz to use a gzFile* or to cast 
the void* gack to a gzFile* before calling functions expecting a 
gzFile*.


Thanks,
Eric
___
macports-users mailing list
macports-users@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macports-users


Re: error using MacPorts zlib, not present with system zlib?

2012-02-22 Thread Adam Mercer
On Wed, Feb 22, 2012 at 15:50, Eric Cronin ecro...@macports.org wrote:

 I'm not near a Mac right now, but I believe the system version of zlib is
 pretty ancient.  In version 1.2.4 there was a Wholesale replacement of gz*
 functions with faster versions according to zlib.net, one of which I
 suspect was the replacement of the gzgetc() function with a macro.

Looks like it, Lion seems to have zlib 1.2.5 which has a standard
fucntion prototype for the gzgetc() function whereas 1.2.6 in MacPorts
gzgetc() is indeed a macro.

 C treats void* very unsafely, silently converting it to and from other
 pointer types whenever it knows how.  So converting the gzFile* gzopen()
 returned to the void* 'file' is legal.  Then, if gzgetc() is an actual
 function declared as 'char gzgetc(gzFile*)' the compiler will allow the
 void* be passed to the function, and within the function it is treated as a
 gzFile*.  But if gzgetc is just a macro the compiler doesn't know to convert
 'file' to a gzFile*, so you get errors about trying to treat void as
 struct/union.  If the API said gzgetc took a void* they would fix this by
 casting g to a gzFile* inside the macro that replaced the function, but
 the API doesn't say this, and so the zlib authors don't... The current
 version is actually both faster and safer since it catches this type of
 void* abuse.

 So tldr answer: patch the port using libz to use a gzFile* or to cast the
 void* gack to a gzFile* before calling functions expecting a gzFile*.

I ended up applying a patch to the port that casts the void* pointer
to gzFile and that allows it to build, but the upstream developer
didn't like that approach. But this analysis is interesting and
imagine this build error will be seen on other platforms that have
zlib-1.2.6.

Thanks for the help.

Cheers

Adam
___
macports-users mailing list
macports-users@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macports-users


Re: error using MacPorts zlib, not present with system zlib?

2012-02-22 Thread Mike Alexander
--On February 22, 2012 4:50:52 PM -0500 Eric Cronin 
ecro...@macports.org wrote:



This code is wrong.  The zlib documentation says gzgetc takes a
gzFile* not a void*.


Your analysis of this is correct except for one minor point.  gzopen 
returns and gzgetc (and others) take a gzFile not a gzFile*.  The 
definition of gzFile is



 typedef struct gzFile_s *gzFile;

so it's defined as a pointer.  Some compilers at some warning levels 
get annoyed if you use a gzFile* instead of gzFile for these parameters.


   Mike

___
macports-users mailing list
macports-users@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macports-users


Re: error using MacPorts zlib, not present with system zlib?

2012-02-22 Thread Brandon Allbery
On Wed, Feb 22, 2012 at 21:36, Mike Alexander m...@umich.edu wrote:

 --On February 22, 2012 4:50:52 PM -0500 Eric Cronin ecro...@macports.org
 wrote:

 This code is wrong.  The zlib documentation says gzgetc takes a
 gzFile* not a void*.


  typedef struct gzFile_s *gzFile;

 so it's defined as a pointer.  Some compilers at some warning levels get
 annoyed if you use a gzFile* instead of gzFile for these parameters.


As they well should.

-- 
brandon s allbery  allber...@gmail.com
wandering unix systems administrator (available) (412) 475-9364 vm/sms
___
macports-users mailing list
macports-users@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macports-users