123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- /* Implement the vsnprintf function.
- Copyright (C) 2003, 2004, 2005, 2011, 2013 Free Software Foundation, Inc.
- Written by Kaveh R. Ghazi <ghazi@caip.rutgers.edu>.
- This file is part of the libiberty library. This library is free
- software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option)
- any later version.
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to
- the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
- As a special exception, if you link this library with files
- compiled with a GNU compiler to produce an executable, this does not cause
- the resulting executable to be covered by the GNU General Public License.
- This exception does not however invalidate any other reasons why
- the executable file might be covered by the GNU General Public License. */
- /*
- @deftypefn Supplemental int vsnprintf (char *@var{buf}, size_t @var{n}, @
- const char *@var{format}, va_list @var{ap})
- This function is similar to @code{vsprintf}, but it will write to
- @var{buf} at most @code{@var{n}-1} bytes of text, followed by a
- terminating null byte, for a total of @var{n} bytes. On error the
- return value is -1, otherwise it returns the number of characters that
- would have been printed had @var{n} been sufficiently large,
- regardless of the actual value of @var{n}. Note some pre-C99 system
- libraries do not implement this correctly so users cannot generally
- rely on the return value if the system version of this function is
- used.
- @end deftypefn
- */
- #include "config.h"
- #include "ansidecl.h"
- #include <stdarg.h>
- #ifdef HAVE_STRING_H
- #include <string.h>
- #endif
- #ifdef HAVE_STDLIB_H
- #include <stdlib.h>
- #endif
- #include "libiberty.h"
- /* This implementation relies on a working vasprintf. */
- int
- vsnprintf (char *s, size_t n, const char *format, va_list ap)
- {
- char *buf = 0;
- int result = vasprintf (&buf, format, ap);
- if (!buf)
- return -1;
- if (result < 0)
- {
- free (buf);
- return -1;
- }
- result = strlen (buf);
- if (n > 0)
- {
- if ((long) n > result)
- memcpy (s, buf, result+1);
- else
- {
- memcpy (s, buf, n-1);
- s[n - 1] = 0;
- }
- }
- free (buf);
- return result;
- }
- #ifdef TEST
- /* Set the buffer to a known state. */
- #define CLEAR(BUF) do { memset ((BUF), 'X', sizeof (BUF)); (BUF)[14] = '\0'; } while (0)
- /* For assertions. */
- #define VERIFY(P) do { if (!(P)) abort(); } while (0)
- static int ATTRIBUTE_PRINTF_3
- checkit (char *s, size_t n, const char *format, ...)
- {
- int result;
- va_list ap;
- va_start (ap, format);
- result = vsnprintf (s, n, format, ap);
- va_end (ap);
- return result;
- }
- extern int main (void);
- int
- main (void)
- {
- char buf[128];
- int status;
-
- CLEAR (buf);
- status = checkit (buf, 10, "%s:%d", "foobar", 9);
- VERIFY (status==8 && memcmp (buf, "foobar:9\0XXXXX\0", 15) == 0);
- CLEAR (buf);
- status = checkit (buf, 9, "%s:%d", "foobar", 9);
- VERIFY (status==8 && memcmp (buf, "foobar:9\0XXXXX\0", 15) == 0);
- CLEAR (buf);
- status = checkit (buf, 8, "%s:%d", "foobar", 9);
- VERIFY (status==8 && memcmp (buf, "foobar:\0XXXXXX\0", 15) == 0);
- CLEAR (buf);
- status = checkit (buf, 7, "%s:%d", "foobar", 9);
- VERIFY (status==8 && memcmp (buf, "foobar\0XXXXXXX\0", 15) == 0);
- CLEAR (buf);
- status = checkit (buf, 6, "%s:%d", "foobar", 9);
- VERIFY (status==8 && memcmp (buf, "fooba\0XXXXXXXX\0", 15) == 0);
- CLEAR (buf);
- status = checkit (buf, 2, "%s:%d", "foobar", 9);
- VERIFY (status==8 && memcmp (buf, "f\0XXXXXXXXXXXX\0", 15) == 0);
- CLEAR (buf);
- status = checkit (buf, 1, "%s:%d", "foobar", 9);
- VERIFY (status==8 && memcmp (buf, "\0XXXXXXXXXXXXX\0", 15) == 0);
- CLEAR (buf);
- status = checkit (buf, 0, "%s:%d", "foobar", 9);
- VERIFY (status==8 && memcmp (buf, "XXXXXXXXXXXXXX\0", 15) == 0);
- return 0;
- }
- #endif /* TEST */
|