Blame libiberty/vsnprintf.c

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