| 1 | /* vsnprintf.c |
| 2 | * |
| 3 | * $Id: vsnprintf.c,v 1.3 2008/07/28 23:24:20 keithmarshall Exp $ |
| 4 | * |
| 5 | * Provides an implementation of the "vsnprintf" function, conforming |
| 6 | * generally to C99 and SUSv3/POSIX specifications, with extensions |
| 7 | * to support Microsoft's non-standard format specifications. This |
| 8 | * is included in libmingwex.a, replacing the redirection through |
| 9 | * libmoldnames.a, to the MSVCRT standard "_vsnprintf" function; (the |
| 10 | * standard MSVCRT function remains available, and may be invoked |
| 11 | * directly, using this fully qualified form of its name). |
| 12 | * |
| 13 | * Written by Keith Marshall <keithmarshall@users.sourceforge.net> |
| 14 | * |
| 15 | * This is free software. You may redistribute and/or modify it as you |
| 16 | * see fit, without restriction of copyright. |
| 17 | * |
| 18 | * This software is provided "as is", in the hope that it may be useful, |
| 19 | * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of |
| 20 | * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no |
| 21 | * time will the author accept any form of liability for any damages, |
| 22 | * however caused, resulting from the use of this software. |
| 23 | * |
| 24 | */ |
| 25 | |
| 26 | #include <stdio.h> |
| 27 | #include <stdarg.h> |
| 28 | |
| 29 | #include "mingw_pformat.h" |
| 30 | |
| 31 | int __cdecl __vsnprintf (APICHAR *, size_t, const APICHAR *fmt, va_list) __MINGW_NOTHROW; |
| 32 | int __cdecl __vsnprintf(APICHAR *buf, size_t length, const APICHAR *fmt, va_list argv ) |
| 33 | { |
| 34 | register int retval; |
| 35 | |
| 36 | if( length == (size_t)(0) ) |
| 37 | { |
| 38 | #if defined(__BUILD_WIDEAPI) && defined(__BUILD_WIDEAPI_ISO) |
| 39 | /* No buffer; for wide api ISO C95+ vswprintf() function |
| 40 | * simply returns negative value as required by ISO C95+. |
| 41 | */ |
| 42 | return -1; |
| 43 | #else |
| 44 | /* |
| 45 | * No buffer; simply compute and return the size required, |
| 46 | * without actually emitting any data. |
| 47 | */ |
| 48 | return __pformat( 0, buf, 0, fmt, argv); |
| 49 | #endif |
| 50 | } |
| 51 | |
| 52 | /* If we get to here, then we have a buffer... |
| 53 | * Emit data up to the limit of buffer length less one, |
| 54 | * then add the requisite NUL terminator. |
| 55 | */ |
| 56 | retval = __pformat( 0, buf, --length, fmt, argv ); |
| 57 | buf[retval < (int) length ? retval : (int)length] = '\0'; |
| 58 | |
| 59 | #if defined(__BUILD_WIDEAPI) && defined(__BUILD_WIDEAPI_ISO) |
| 60 | /* ISO C95+ fails when n or more data wide chars are needed. length was |
| 61 | * already decremented once for the terminator, so use > not >= here. |
| 62 | */ |
| 63 | if( retval > (int) length ) |
| 64 | retval = -1; |
| 65 | #endif |
| 66 | |
| 67 | return retval; |
| 68 | } |
| 69 | |