Re: [Toolserver-l] Alternative C function to vasprintf() on Toolserver

2011-04-11 Thread Peter Körner
Am 09.04.2011 11:28, schrieb Ilmari Karonen:
> char *vasprintf (const char *format, va_list ap) {
>   int len; char *buf;
>   len = vsnprintf(NULL, 0, format, ap);  /* get needed size */
>   if (len<  0) return NULL;
>   buf = malloc(len + 1);  /* reserve 1 byte for trailing \0 */
>   if (!len) return NULL;

shouldn't that line read
 if (!buf) return NULL;

>   if (vsnprintf(buf, len + 1, format, ap) == len) return buf;
>   free(buf);  /* something went wrong in second vsnprintf() */
>   return NULL;
> }

Peter

___
Toolserver-l mailing list (Toolserver-l@lists.wikimedia.org)
https://lists.wikimedia.org/mailman/listinfo/toolserver-l
Posting guidelines for this list: 
https://wiki.toolserver.org/view/Mailing_list_etiquette


Re: [Toolserver-l] Alternative C function to vasprintf() on Toolserver

2011-04-11 Thread Andrew Dunbar
On 11 April 2011 19:59, River Tarnell  wrote:
> -BEGIN PGP SIGNED MESSAGE-
> Hash: SHA1
>
> Andrew Dunbar:
>> Hmm currently I'm using _vscprintf / vsprintf on Windows/MSVC inside
>> #ifdef _WIN32
>> and vasprintf Ubuntu/gcc inside #else
>
>> But my C-fu is to puny to figure out what #ifdefs to use to detect
>> what combination of C compiler and libc I'm compiling under.
>
>> Apparently it's important with snprintf since some implementations
>> return "an unspecified return value less than 1" with size=0.
>
> That's true, but no current Unix implementation should do that, since
> the return value of snprintf() is standardised in the current POSIX
> standard (IEEE 1003.1-2004) and in the C99 standard (ISO/IEC 9899:1999).
>
> The following code should handle Windows and both old and new Unix,
> although it's completely untested and comes with no warranty:
>
> /* Compile with "-D_XOPEN_SOURCE=600 -std=c99" */
> int
> my_vasprintf(char **res, char const *fmt, va_list args)
> {
> int      sz, r;
> #ifdef _WIN32
>        sz = _vscprintf(fmt, args);
> #else
>        sz = snprintf(NULL, 0, fmt, args);
> #endif
>
> #if defined(_WIN32) || (defined(__STDC__) && __STDC__ >= 199901L) \
>                || (defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 600))
>        if (sz < 0)
>                return sz;
>        if (sz >= 0) {
> #else
>        if (sz >= 1) {
> #endif
>                if ((*res = malloc(sz + 1)) == NULL)
>                        return -1;
>
>                if ((sz = sprintf(*res, fmt, args)) < 0) {
>                        free(*res);
>                        *res = NULL;
>                }
>
>                return sz;
>        }
>
> #define MAXLN 65535
>        *res = NULL;
>        for (sz = 128; sz <= MAXLN; sz *= 2) {
>                if ((*res = realloc(*res, sz)) == NULL)
>                        return -1;
>                r = vsnprintf(*res, sz, fmt, args);
>                if (r > 0 && r < sz)
>                        return r;
>        }
>
>        errno = ENOMEM;
>
>        if (*res) {
>                free(*res);
>                *res = NULL;
>        }
>
>        return -1;
> }
>
> Obviously, this will be slower than the modern implementation, and you
> may want to tune the initial buffer size for the expected string length.

Thanks River, that's really helpful!

Andrew Dunbar (hippietrail)

>        - river.
> -BEGIN PGP SIGNATURE-
> Version: GnuPG v1.4.11 (SunOS)
>
> iEYEARECAAYFAk2i0QcACgkQIXd7fCuc5vI1ewCfTdlavg0rr56l7JzwAe5Oea9x
> 55sAnA4MIosJLfOnD/O3z/nkq0yqD5CE
> =AGMe
> -END PGP SIGNATURE-
>
> ___
> Toolserver-l mailing list (Toolserver-l@lists.wikimedia.org)
> https://lists.wikimedia.org/mailman/listinfo/toolserver-l
> Posting guidelines for this list: 
> https://wiki.toolserver.org/view/Mailing_list_etiquette
>

___
Toolserver-l mailing list (Toolserver-l@lists.wikimedia.org)
https://lists.wikimedia.org/mailman/listinfo/toolserver-l
Posting guidelines for this list: 
https://wiki.toolserver.org/view/Mailing_list_etiquette


Re: [Toolserver-l] Alternative C function to vasprintf() on Toolserver

2011-04-11 Thread River Tarnell
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Andrew Dunbar:
> Hmm currently I'm using _vscprintf / vsprintf on Windows/MSVC inside
> #ifdef _WIN32
> and vasprintf Ubuntu/gcc inside #else
 
> But my C-fu is to puny to figure out what #ifdefs to use to detect
> what combination of C compiler and libc I'm compiling under.

> Apparently it's important with snprintf since some implementations
> return "an unspecified return value less than 1" with size=0.
 
That's true, but no current Unix implementation should do that, since 
the return value of snprintf() is standardised in the current POSIX 
standard (IEEE 1003.1-2004) and in the C99 standard (ISO/IEC 9899:1999).

The following code should handle Windows and both old and new Unix, 
although it's completely untested and comes with no warranty:

/* Compile with "-D_XOPEN_SOURCE=600 -std=c99" */
int
my_vasprintf(char **res, char const *fmt, va_list args)
{
int  sz, r;
#ifdef _WIN32
sz = _vscprintf(fmt, args);
#else
sz = snprintf(NULL, 0, fmt, args);
#endif

#if defined(_WIN32) || (defined(__STDC__) && __STDC__ >= 199901L) \
|| (defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 600))
if (sz < 0)
return sz;
if (sz >= 0) {
#else
if (sz >= 1) {
#endif
if ((*res = malloc(sz + 1)) == NULL)
return -1;

if ((sz = sprintf(*res, fmt, args)) < 0) {
free(*res);
*res = NULL;
}

return sz;
}

#define MAXLN 65535
*res = NULL;
for (sz = 128; sz <= MAXLN; sz *= 2) {
if ((*res = realloc(*res, sz)) == NULL)
return -1;
r = vsnprintf(*res, sz, fmt, args);
if (r > 0 && r < sz)
return r;
}

errno = ENOMEM;

if (*res) {
free(*res);
*res = NULL;
}

return -1;
}

Obviously, this will be slower than the modern implementation, and you 
may want to tune the initial buffer size for the expected string length.

- river.
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.11 (SunOS)

iEYEARECAAYFAk2i0QcACgkQIXd7fCuc5vI1ewCfTdlavg0rr56l7JzwAe5Oea9x
55sAnA4MIosJLfOnD/O3z/nkq0yqD5CE
=AGMe
-END PGP SIGNATURE-

___
Toolserver-l mailing list (Toolserver-l@lists.wikimedia.org)
https://lists.wikimedia.org/mailman/listinfo/toolserver-l
Posting guidelines for this list: 
https://wiki.toolserver.org/view/Mailing_list_etiquette


Re: [Toolserver-l] Alternative C function to vasprintf() on Toolserver

2011-04-09 Thread Andrew Dunbar
On 10 April 2011 00:09, River Tarnell  wrote:
> -BEGIN PGP SIGNED MESSAGE-
> Hash: SHA1
>
> Andrew Dunbar:
>> I've got a little program to index dump files that supports Windows
>> and Linux but it doesn't compile on the Toolserver with either cc or
>> gcc due to the lack of the function vasprintf(). It's a GNU extension
>> so I'm surprised it didn't work even with gcc.
>
>> Why doesn't the Toolserver gcc have it, and does anybody know of a 
>> workaround?
>
> *printf() is not part of the compiler, but the C library (libc); GNU
> glibc (used on Linux) provides it, while Solaris doesn't.  There's been
> some discussion about it, but there are several incompatible asprintf()
> interfaces around and it's not clear which one should be implemented.
>
> Someone else already provided a version using snprintf, but you could
> also use g_vasprintf() from glib, or the version from gettext's
> libintl.h (which means you need to include  and link against
> - -lasprintf, both of which live in /opt/ts/gettext).  I personally find
> the snprintf solution the best and this is what I use in my own code.

Hmm currently I'm using _vscprintf / vsprintf on Windows/MSVC inside
#ifdef _WIN32
and vasprintf Ubuntu/gcc inside #else

But my C-fu is to puny to figure out what #ifdefs to use to detect
what combination of C compiler and libc I'm compiling under.
Apparently it's important with snprintf since some implementations
return "an unspecified return value less than 1" with size=0.

I don't want to have to use autoconf or swtich to a gcc on Windows.

Andrew Dunbar (hippietrail)


>        - river.
> -BEGIN PGP SIGNATURE-
> Version: GnuPG v1.4.11 (SunOS)
>
> iEYEARECAAYFAk2gaJ4ACgkQIXd7fCuc5vKziwCfTbDgK0nX32jK8iJcLWl278BK
> HNwAnRFW8/BhMUKS7zr6RRBcPlqCeWfj
> =31oq
> -END PGP SIGNATURE-
>
> ___
> Toolserver-l mailing list (Toolserver-l@lists.wikimedia.org)
> https://lists.wikimedia.org/mailman/listinfo/toolserver-l
> Posting guidelines for this list: 
> https://wiki.toolserver.org/view/Mailing_list_etiquette
>

___
Toolserver-l mailing list (Toolserver-l@lists.wikimedia.org)
https://lists.wikimedia.org/mailman/listinfo/toolserver-l
Posting guidelines for this list: 
https://wiki.toolserver.org/view/Mailing_list_etiquette


Re: [Toolserver-l] Alternative C function to vasprintf() on Toolserver

2011-04-09 Thread River Tarnell
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Andrew Dunbar:
> I've got a little program to index dump files that supports Windows
> and Linux but it doesn't compile on the Toolserver with either cc or
> gcc due to the lack of the function vasprintf(). It's a GNU extension
> so I'm surprised it didn't work even with gcc.
 
> Why doesn't the Toolserver gcc have it, and does anybody know of a workaround?

*printf() is not part of the compiler, but the C library (libc); GNU 
glibc (used on Linux) provides it, while Solaris doesn't.  There's been 
some discussion about it, but there are several incompatible asprintf() 
interfaces around and it's not clear which one should be implemented.

Someone else already provided a version using snprintf, but you could 
also use g_vasprintf() from glib, or the version from gettext's 
libintl.h (which means you need to include  and link against 
- -lasprintf, both of which live in /opt/ts/gettext).  I personally find 
the snprintf solution the best and this is what I use in my own code.

- river.
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.11 (SunOS)

iEYEARECAAYFAk2gaJ4ACgkQIXd7fCuc5vKziwCfTbDgK0nX32jK8iJcLWl278BK
HNwAnRFW8/BhMUKS7zr6RRBcPlqCeWfj
=31oq
-END PGP SIGNATURE-

___
Toolserver-l mailing list (Toolserver-l@lists.wikimedia.org)
https://lists.wikimedia.org/mailman/listinfo/toolserver-l
Posting guidelines for this list: 
https://wiki.toolserver.org/view/Mailing_list_etiquette


Re: [Toolserver-l] Alternative C function to vasprintf() on Toolserver

2011-04-09 Thread Platonides
Andrew Dunbar wrote:
> I've got a little program to index dump files that supports Windows
> and Linux but it doesn't compile on the Toolserver with either cc or
> gcc due to the lack of the function vasprintf(). It's a GNU extension
> so I'm surprised it didn't work even with gcc.
> 
> Why doesn't the Toolserver gcc have it, and does anybody know of a workaround?

Did you do
 #define _GNU_SOURCE
at the top of the source file?


___
Toolserver-l mailing list (Toolserver-l@lists.wikimedia.org)
https://lists.wikimedia.org/mailman/listinfo/toolserver-l
Posting guidelines for this list: 
https://wiki.toolserver.org/view/Mailing_list_etiquette


Re: [Toolserver-l] Alternative C function to vasprintf() on Toolserver

2011-04-09 Thread Andrew Dunbar
On 9 April 2011 19:28, Ilmari Karonen  wrote:
> On 04/09/2011 10:29 AM, Andrew Dunbar wrote:
>> I've got a little program to index dump files that supports Windows
>> and Linux but it doesn't compile on the Toolserver with either cc or
>> gcc due to the lack of the function vasprintf(). It's a GNU extension
>> so I'm surprised it didn't work even with gcc.
>>
>> Why doesn't the Toolserver gcc have it, and does anybody know of a 
>> workaround?
>>
>> vasprintf() is a version of vsprintf() which writes to a memory buffer
>> of just the right size that it allocates and which the caller must
>> call free() on when done.
>
> You could try writing your own.  Off the top of my head (untested):
>
> char *vasprintf (const char *format, va_list ap) {
>        int len; char *buf;
>        len = vsnprintf(NULL, 0, format, ap);  /* get needed size */
>        if (len < 0) return NULL;
>        buf = malloc(len + 1);  /* reserve 1 byte for trailing \0 */
>        if (!len) return NULL;
>        if (vsnprintf(buf, len + 1, format, ap) == len) return buf;
>        free(buf);  /* something went wrong in second vsnprintf() */
>        return NULL;
> }
>
> I think the vsnprintf(NULL, 0, ...) trick should work, although I
> haven't tried it.  If it complains about the NULL, just use some valid
> dummy pointer instead.  You could probably trade some memory for speed
> in some cases by guessing and allocating some reasonable initial size
> for the buffer before the first vsnprintf() call and extending it only
> if the first guess wasn't long enough.

Aha thanks! I already use vsnprintf in the Windows version of the code
but since the gcc on my Ubuntu 10 doesn't have it I didn't expect it
to be on the Toolserver gcc.

Any ideas how I can set up the #ifdefs to detect that it's compiling
on the toolserver environment or that it has this function available?

Andrew Dunbar (hippietrail)

> --
> Ilmari Karonen
>
> ___
> Toolserver-l mailing list (Toolserver-l@lists.wikimedia.org)
> https://lists.wikimedia.org/mailman/listinfo/toolserver-l
> Posting guidelines for this list: 
> https://wiki.toolserver.org/view/Mailing_list_etiquette
>

___
Toolserver-l mailing list (Toolserver-l@lists.wikimedia.org)
https://lists.wikimedia.org/mailman/listinfo/toolserver-l
Posting guidelines for this list: 
https://wiki.toolserver.org/view/Mailing_list_etiquette


Re: [Toolserver-l] Alternative C function to vasprintf() on Toolserver

2011-04-09 Thread Ilmari Karonen
On 04/09/2011 10:29 AM, Andrew Dunbar wrote:
> I've got a little program to index dump files that supports Windows
> and Linux but it doesn't compile on the Toolserver with either cc or
> gcc due to the lack of the function vasprintf(). It's a GNU extension
> so I'm surprised it didn't work even with gcc.
>
> Why doesn't the Toolserver gcc have it, and does anybody know of a workaround?
>
> vasprintf() is a version of vsprintf() which writes to a memory buffer
> of just the right size that it allocates and which the caller must
> call free() on when done.

You could try writing your own.  Off the top of my head (untested):

char *vasprintf (const char *format, va_list ap) {
int len; char *buf;
len = vsnprintf(NULL, 0, format, ap);  /* get needed size */
if (len < 0) return NULL;
buf = malloc(len + 1);  /* reserve 1 byte for trailing \0 */
if (!len) return NULL;
if (vsnprintf(buf, len + 1, format, ap) == len) return buf;
free(buf);  /* something went wrong in second vsnprintf() */
return NULL;
}

I think the vsnprintf(NULL, 0, ...) trick should work, although I 
haven't tried it.  If it complains about the NULL, just use some valid 
dummy pointer instead.  You could probably trade some memory for speed 
in some cases by guessing and allocating some reasonable initial size 
for the buffer before the first vsnprintf() call and extending it only 
if the first guess wasn't long enough.

-- 
Ilmari Karonen

___
Toolserver-l mailing list (Toolserver-l@lists.wikimedia.org)
https://lists.wikimedia.org/mailman/listinfo/toolserver-l
Posting guidelines for this list: 
https://wiki.toolserver.org/view/Mailing_list_etiquette


[Toolserver-l] Alternative C function to vasprintf() on Toolserver

2011-04-09 Thread Andrew Dunbar
I've got a little program to index dump files that supports Windows
and Linux but it doesn't compile on the Toolserver with either cc or
gcc due to the lack of the function vasprintf(). It's a GNU extension
so I'm surprised it didn't work even with gcc.

Why doesn't the Toolserver gcc have it, and does anybody know of a workaround?

vasprintf() is a version of vsprintf() which writes to a memory buffer
of just the right size that it allocates and which the caller must
call free() on when done.

Andrew Dunbar (hippietrail)

___
Toolserver-l mailing list (Toolserver-l@lists.wikimedia.org)
https://lists.wikimedia.org/mailman/listinfo/toolserver-l
Posting guidelines for this list: 
https://wiki.toolserver.org/view/Mailing_list_etiquette