Windows (mingw) _vsnprintf() returns -1 not the required size on overflow.

Windows and hence mingw does not follow the standard regarding the return
value of vsnprintf(). The mingw code needs to iteratively search for a
buffer large enough to print the output.
This commit is contained in:
Cary R 2012-08-31 10:56:47 -07:00
parent 62f1aa135b
commit 01c4cd3dad
1 changed files with 20 additions and 6 deletions

View File

@ -181,7 +181,6 @@ vpi_mcd_vprintf(PLI_UINT32 mcd, const char*fmt, va_list ap)
int rc = 0;
bool need_free = false;
va_list saved_ap;
va_copy(saved_ap, ap);
if (!IS_MCD(mcd)) return 0;
@ -190,15 +189,33 @@ vpi_mcd_vprintf(PLI_UINT32 mcd, const char*fmt, va_list ap)
(unsigned int)mcd, fmt);
}
va_copy(saved_ap, ap);
#ifdef __MINGW32__
/*
* The MinGW runtime (version 3.14) fixes some things, but breaks
* %f for us, so we have to us the underlying version.
*/
rc = _vsnprintf(buffer, sizeof buffer, fmt, ap);
/*
* Windows returns -1 to indicate the result was truncated (thanks for
* following the standard!). Since we don't know how big to make the
* buffer just keep doubling it until it works.
*/
if (rc == -1) {
size_t buf_size = sizeof buffer;
buf_ptr = NULL;
need_free = true;
while (rc == -1) {
va_list tmp_ap;
va_copy(tmp_ap, saved_ap);
buf_size *= 2;
buf_ptr = (char *)realloc(buf_ptr, buf_size);
rc = vsnprintf(buf_ptr, buf_size, fmt, tmp_ap);
va_end(tmp_ap);
}
}
#else
rc = vsnprintf(buffer, sizeof buffer, fmt, ap);
#endif
assert(rc >= 0);
/*
* If rc is greater than sizeof buffer then the result was truncated
@ -207,12 +224,9 @@ vpi_mcd_vprintf(PLI_UINT32 mcd, const char*fmt, va_list ap)
if ((unsigned) rc >= sizeof buffer) {
buf_ptr = (char *)malloc(rc + 1);
need_free = true;
#ifdef __MINGW32__
rc = _vsnprintf(buf_ptr, rc+1, fmt, saved_ap);
#else
rc = vsnprintf(buf_ptr, rc+1, fmt, saved_ap);
#endif
}
#endif
va_end(saved_ap);
for(int i = 0; i < 31; i++) {