1169695Skan/* Implement the vsnprintf function.
2169695Skan   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
3169695Skan   Written by Kaveh R. Ghazi <ghazi@caip.rutgers.edu>.
4169695Skan
5169695SkanThis file is part of the libiberty library.  This library is free
6169695Skansoftware; you can redistribute it and/or modify it under the
7169695Skanterms of the GNU General Public License as published by the
8169695SkanFree Software Foundation; either version 2, or (at your option)
9169695Skanany later version.
10169695Skan
11169695SkanThis library is distributed in the hope that it will be useful,
12169695Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of
13169695SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14169695SkanGNU General Public License for more details.
15169695Skan
16169695SkanYou should have received a copy of the GNU General Public License
17169695Skanalong with GNU CC; see the file COPYING.  If not, write to
18169695Skanthe Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
19169695Skan
20169695SkanAs a special exception, if you link this library with files
21169695Skancompiled with a GNU compiler to produce an executable, this does not cause
22169695Skanthe resulting executable to be covered by the GNU General Public License.
23169695SkanThis exception does not however invalidate any other reasons why
24169695Skanthe executable file might be covered by the GNU General Public License. */
25169695Skan
26169695Skan/*
27169695Skan
28169695Skan@deftypefn Supplemental int vsnprintf (char *@var{buf}, size_t @var{n}, const char *@var{format}, va_list @var{ap})
29169695Skan
30169695SkanThis function is similar to vsprintf, but it will print at most
31169695Skan@var{n} characters.  On error the return value is -1, otherwise it
32169695Skanreturns the number of characters that would have been printed had
33169695Skan@var{n} been sufficiently large, regardless of the actual value of
34169695Skan@var{n}.  Note some pre-C99 system libraries do not implement this
35169695Skancorrectly so users cannot generally rely on the return value if the
36169695Skansystem version of this function is used.
37169695Skan
38169695Skan@end deftypefn
39169695Skan
40169695Skan*/
41169695Skan
42169695Skan#include "config.h"
43169695Skan#include "ansidecl.h"
44169695Skan
45169695Skan#include <stdarg.h>
46169695Skan#ifdef HAVE_STRING_H
47169695Skan#include <string.h>
48169695Skan#endif
49169695Skan#ifdef HAVE_STDLIB_H
50169695Skan#include <stdlib.h>
51169695Skan#endif
52169695Skan
53169695Skan#include "libiberty.h"
54169695Skan
55169695Skan/* This implementation relies on a working vasprintf.  */
56169695Skanint
57169695Skanvsnprintf (char *s, size_t n, const char *format, va_list ap)
58169695Skan{
59169695Skan  char *buf = 0;
60169695Skan  int result = vasprintf (&buf, format, ap);
61169695Skan
62169695Skan  if (!buf)
63169695Skan    return -1;
64169695Skan  if (result < 0)
65169695Skan    {
66169695Skan      free (buf);
67169695Skan      return -1;
68169695Skan    }
69169695Skan
70169695Skan  result = strlen (buf);
71169695Skan  if (n > 0)
72169695Skan    {
73169695Skan      if ((long) n > result)
74169695Skan	memcpy (s, buf, result+1);
75169695Skan      else
76169695Skan        {
77169695Skan	  memcpy (s, buf, n-1);
78169695Skan	  s[n - 1] = 0;
79169695Skan	}
80169695Skan    }
81169695Skan  free (buf);
82169695Skan  return result;
83169695Skan}
84169695Skan
85169695Skan#ifdef TEST
86169695Skan/* Set the buffer to a known state.  */
87169695Skan#define CLEAR(BUF) do { memset ((BUF), 'X', sizeof (BUF)); (BUF)[14] = '\0'; } while (0)
88169695Skan/* For assertions.  */
89169695Skan#define VERIFY(P) do { if (!(P)) abort(); } while (0)
90169695Skan
91169695Skanstatic int ATTRIBUTE_PRINTF_3
92169695Skancheckit (char *s, size_t n, const char *format, ...)
93169695Skan{
94169695Skan  int result;
95169695Skan  VA_OPEN (ap, format);
96169695Skan  VA_FIXEDARG (ap, char *, s);
97169695Skan  VA_FIXEDARG (ap, size_t, n);
98169695Skan  VA_FIXEDARG (ap, const char *, format);
99169695Skan  result = vsnprintf (s, n, format, ap);
100169695Skan  VA_CLOSE (ap);
101169695Skan  return result;
102169695Skan}
103169695Skan
104169695Skanextern int main (void);
105169695Skanint
106169695Skanmain (void)
107169695Skan{
108169695Skan  char buf[128];
109169695Skan  int status;
110169695Skan
111169695Skan  CLEAR (buf);
112169695Skan  status = checkit (buf, 10, "%s:%d", "foobar", 9);
113169695Skan  VERIFY (status==8 && memcmp (buf, "foobar:9\0XXXXX\0", 15) == 0);
114169695Skan
115169695Skan  CLEAR (buf);
116169695Skan  status = checkit (buf, 9, "%s:%d", "foobar", 9);
117169695Skan  VERIFY (status==8 && memcmp (buf, "foobar:9\0XXXXX\0", 15) == 0);
118169695Skan
119169695Skan  CLEAR (buf);
120169695Skan  status = checkit (buf, 8, "%s:%d", "foobar", 9);
121169695Skan  VERIFY (status==8 && memcmp (buf, "foobar:\0XXXXXX\0", 15) == 0);
122169695Skan
123169695Skan  CLEAR (buf);
124169695Skan  status = checkit (buf, 7, "%s:%d", "foobar", 9);
125169695Skan  VERIFY (status==8 && memcmp (buf, "foobar\0XXXXXXX\0", 15) == 0);
126169695Skan
127169695Skan  CLEAR (buf);
128169695Skan  status = checkit (buf, 6, "%s:%d", "foobar", 9);
129169695Skan  VERIFY (status==8 && memcmp (buf, "fooba\0XXXXXXXX\0", 15) == 0);
130169695Skan
131169695Skan  CLEAR (buf);
132169695Skan  status = checkit (buf, 2, "%s:%d", "foobar", 9);
133169695Skan  VERIFY (status==8 && memcmp (buf, "f\0XXXXXXXXXXXX\0", 15) == 0);
134169695Skan
135169695Skan  CLEAR (buf);
136169695Skan  status = checkit (buf, 1, "%s:%d", "foobar", 9);
137169695Skan  VERIFY (status==8 && memcmp (buf, "\0XXXXXXXXXXXXX\0", 15) == 0);
138169695Skan
139169695Skan  CLEAR (buf);
140169695Skan  status = checkit (buf, 0, "%s:%d", "foobar", 9);
141169695Skan  VERIFY (status==8 && memcmp (buf, "XXXXXXXXXXXXXX\0", 15) == 0);
142169695Skan
143169695Skan  return 0;
144169695Skan}
145169695Skan#endif /* TEST */
146