Back to index

cell-binutils  2.17cvs20070401
vsnprintf.c
Go to the documentation of this file.
00001 /* Implement the vsnprintf function.
00002    Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
00003    Written by Kaveh R. Ghazi <ghazi@caip.rutgers.edu>.
00004 
00005 This file is part of the libiberty library.  This library is free
00006 software; you can redistribute it and/or modify it under the
00007 terms of the GNU General Public License as published by the
00008 Free Software Foundation; either version 2, or (at your option)
00009 any later version.
00010 
00011 This library is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License
00017 along with GNU CC; see the file COPYING.  If not, write to
00018 the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
00019 
00020 As a special exception, if you link this library with files
00021 compiled with a GNU compiler to produce an executable, this does not cause
00022 the resulting executable to be covered by the GNU General Public License.
00023 This exception does not however invalidate any other reasons why
00024 the executable file might be covered by the GNU General Public License. */
00025 
00026 /*
00027 
00028 @deftypefn Supplemental int vsnprintf (char *@var{buf}, size_t @var{n}, const char *@var{format}, va_list @var{ap})
00029 
00030 This function is similar to vsprintf, but it will print at most
00031 @var{n} characters.  On error the return value is -1, otherwise it
00032 returns the number of characters that would have been printed had
00033 @var{n} been sufficiently large, regardless of the actual value of
00034 @var{n}.  Note some pre-C99 system libraries do not implement this
00035 correctly so users cannot generally rely on the return value if the
00036 system version of this function is used.
00037 
00038 @end deftypefn
00039 
00040 */
00041 
00042 #include "config.h"
00043 #include "ansidecl.h"
00044 
00045 #include <stdarg.h>
00046 #ifdef HAVE_STRING_H
00047 #include <string.h>
00048 #endif
00049 #ifdef HAVE_STDLIB_H
00050 #include <stdlib.h>
00051 #endif
00052 
00053 #include "libiberty.h"
00054 
00055 /* This implementation relies on a working vasprintf.  */
00056 int
00057 vsnprintf (char *s, size_t n, const char *format, va_list ap)
00058 {
00059   char *buf = 0;
00060   int result = vasprintf (&buf, format, ap);
00061 
00062   if (!buf)
00063     return -1;
00064   if (result < 0)
00065     {
00066       free (buf);
00067       return -1;
00068     }
00069 
00070   result = strlen (buf);
00071   if (n > 0)
00072     {
00073       if ((long) n > result)
00074        memcpy (s, buf, result+1);
00075       else
00076         {
00077          memcpy (s, buf, n-1);
00078          s[n - 1] = 0;
00079        }
00080     }
00081   free (buf);
00082   return result;
00083 }
00084 
00085 #ifdef TEST
00086 /* Set the buffer to a known state.  */
00087 #define CLEAR(BUF) do { memset ((BUF), 'X', sizeof (BUF)); (BUF)[14] = '\0'; } while (0)
00088 /* For assertions.  */
00089 #define VERIFY(P) do { if (!(P)) abort(); } while (0)
00090 
00091 static int ATTRIBUTE_PRINTF_3
00092 checkit (char *s, size_t n, const char *format, ...)
00093 {
00094   int result;
00095   VA_OPEN (ap, format);
00096   VA_FIXEDARG (ap, char *, s);
00097   VA_FIXEDARG (ap, size_t, n);
00098   VA_FIXEDARG (ap, const char *, format);
00099   result = vsnprintf (s, n, format, ap);
00100   VA_CLOSE (ap);
00101   return result;
00102 }
00103 
00104 extern int main (void);
00105 int
00106 main (void)
00107 {
00108   char buf[128];
00109   int status;
00110   
00111   CLEAR (buf);
00112   status = checkit (buf, 10, "%s:%d", "foobar", 9);
00113   VERIFY (status==8 && memcmp (buf, "foobar:9\0XXXXX\0", 15) == 0);
00114 
00115   CLEAR (buf);
00116   status = checkit (buf, 9, "%s:%d", "foobar", 9);
00117   VERIFY (status==8 && memcmp (buf, "foobar:9\0XXXXX\0", 15) == 0);
00118 
00119   CLEAR (buf);
00120   status = checkit (buf, 8, "%s:%d", "foobar", 9);
00121   VERIFY (status==8 && memcmp (buf, "foobar:\0XXXXXX\0", 15) == 0);
00122 
00123   CLEAR (buf);
00124   status = checkit (buf, 7, "%s:%d", "foobar", 9);
00125   VERIFY (status==8 && memcmp (buf, "foobar\0XXXXXXX\0", 15) == 0);
00126 
00127   CLEAR (buf);
00128   status = checkit (buf, 6, "%s:%d", "foobar", 9);
00129   VERIFY (status==8 && memcmp (buf, "fooba\0XXXXXXXX\0", 15) == 0);
00130 
00131   CLEAR (buf);
00132   status = checkit (buf, 2, "%s:%d", "foobar", 9);
00133   VERIFY (status==8 && memcmp (buf, "f\0XXXXXXXXXXXX\0", 15) == 0);
00134 
00135   CLEAR (buf);
00136   status = checkit (buf, 1, "%s:%d", "foobar", 9);
00137   VERIFY (status==8 && memcmp (buf, "\0XXXXXXXXXXXXX\0", 15) == 0);
00138 
00139   CLEAR (buf);
00140   status = checkit (buf, 0, "%s:%d", "foobar", 9);
00141   VERIFY (status==8 && memcmp (buf, "XXXXXXXXXXXXXX\0", 15) == 0);
00142 
00143   return 0;
00144 }
00145 #endif /* TEST */