-----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

Reply via email to