[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;
}
}