[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [MiNT] Gcc 3.3.6 v 4.0.1



Vincent Rivière wrote:
The test calls gmp_obstack_vprintf(), then it turns to call the MiNTLib in obstack_vprintf() then vprintf().

vfprintf() returns -1, it means failure.
Look at the MiNTLib sources at mintlib/stdio/vfprintf.c
http://sparemint.org/cgi-bin/cvsweb/mintlib/stdio/vfprintf.c?rev=1.5

That source is quite horrible and not debugger friendly :-(
It seems that it fails very soon due to the macro ARGCHECK() (maybe because a bad FILE status ??)

I reproduced the bug with a small standalone testcase (not using gmp).
It passes on Linux, but fails on MiNT.
So the bug is in the MiNTLib.

The testcase is attached to this message.
Compile with :
gcc ob.c -o ob -g -Wall -D_GNU_SOURCE

$ ./ob
FAIL, errno = 37: Bad file descriptor

Again, the macro ARGCHECK() is hit.
Unfortunately macros cannot be debugged :-(

So I guess these versions are used :
In mintlib/stdio/vfprintf.c:
# define ARGCHECK(S, Format)				\
  do							\
    {							\
      /* Check file argument for consistence.  */	\
      if (!__validfp (S) || !S->__mode.__write)		\
	{						\
/*here?*/ __set_errno (EBADF);				\
	  return -1;					\
	}						\
      if (Format == NULL)				\
	{						\
	  __set_errno (EINVAL);				\
	  return -1;					\
	}						\
      if (!S->__seen)					\
	{						\
	  if (__flshfp (S, EOF) == EOF)			\
	    return -1;					\
	}						\
    }							\
   while (0)

In mintlib/include/stdio.h:
/* Nonzero if STREAM is a valid stream.
   STREAM must be a modifiable lvalue (wow, I got to use that term).
   See stdio/glue.c for what the confusing bit is about.  */
#define	__validfp(stream)					      \
  (stream != NULL &&						      \
   ({ if (stream->__magic == _GLUEMAGIC)			      \
	stream = *((struct { int __magic; FILE **__p; } *) stream)->__p; \
      stream->__magic == _IOMAGIC; }))

It seems that some black magic is involved here :-(
No time to dig further...
The help of an stdio expert would be welcome.

--
Vincent Rivière
#include <stdio.h>
#include <obstack.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

#define obstack_chunk_alloc malloc
#define obstack_chunk_free  free

int main(int argc, char* argv[])
{
	struct obstack ob;
	int len;
	
	obstack_init(&ob);
	len = obstack_printf(&ob, "%ld", 0L);
	
	if (len < 0)
	{
		printf("FAIL, errno = %d: %s\n", errno, strerror(errno));
		return 1;
	}
	else
	{
		puts("PASS");
		return 0;
	}
}