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