Patch to add snprintf/vsnprintf to libiberty [take 3]

Kaveh R. Ghazi ghazi@caip.rutgers.edu
Wed Apr 16 16:16:00 GMT 2003


 > From: "Joseph S. Myers" <jsm28@cam.ac.uk>
 > 
 > On Wed, 16 Apr 2003, Kaveh R. Ghazi wrote:
 > 
 > > 2.  I added embedded documentation.
 > 
 > The embedded documentation fails to document the return value.  It
 > should document the return value, while noting that the existence of
 > system libraries which implement snprintf but with a pre-C99 return
 > value means that users of snprintf can't generally rely on the return
 > value.

Thanks for the feedback.  I've included updated snprintf.c and
vsnprintf.c files which have new documentation text per your
suggestions.

I also arranged for them to include less headers, especially stdio.h
which may provide a conflicting prototype (I found it used ssize_t
instead of size_t on irix6.)  That's only relevant when doing "make
testlib.a" not "make libiberty.a" since irix6 has it's own [v]snprintf
and wouldn't normally compile these files, but I figured I should be
safe.

Ok for mainline?


diff -rup orig/egcc-CVS20030416/libiberty/snprintf.c egcc-CVS20030416/libiberty/snprintf.c
--- orig/egcc-CVS20030416/libiberty/snprintf.c	2003-04-16 11:49:00.687088000 -0400
+++ egcc-CVS20030416/libiberty/snprintf.c	2003-04-16 12:04:39.013547000 -0400
@@ -0,0 +1,65 @@
+/* Implement the snprintf function.
+   Copyright (C) 2003 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 snprintf (char *@var{buf}, size_t @var{n}, const char *@var{format}, ...)
+
+This function is similar to sprintf, but it will print at most @var{n}
+characters.  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 "ansidecl.h"
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#include <stddef.h>
+#else
+#include <varargs.h>
+#define size_t unsigned long
+#endif
+
+int vsnprintf PARAMS ((char *, size_t, const char *, va_list));
+
+int
+snprintf VPARAMS ((char *s, size_t n, const char *format, ...))
+{
+  int result;
+  VA_OPEN (ap, format);
+  VA_FIXEDARG (ap, char *, s);
+  VA_FIXEDARG (ap, size_t, n);
+  VA_FIXEDARG (ap, const char *, format);
+  result = vsnprintf (s, n, format, ap);
+  VA_CLOSE (ap);
+  return result;
+}
diff -rup orig/egcc-CVS20030416/libiberty/vsnprintf.c egcc-CVS20030416/libiberty/vsnprintf.c
--- orig/egcc-CVS20030416/libiberty/vsnprintf.c	2003-04-16 11:49:03.876877000 -0400
+++ egcc-CVS20030416/libiberty/vsnprintf.c	2003-04-16 12:04:36.723742000 -0400
@@ -0,0 +1,149 @@
+/* Implement the vsnprintf function.
+   Copyright (C) 2003 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 vsprintf, but it will print at most
+@var{n} characters.  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"
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#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 (s, n, format, ap)
+     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)
+    {
+      strncpy (s, buf, n);
+      if (n - 1 < (size_t) result)
+	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 VPARAMS ((char *s, size_t n, const char *format, ...))
+{
+  int result;
+  VA_OPEN (ap, format);
+  VA_FIXEDARG (ap, char *, s);
+  VA_FIXEDARG (ap, size_t, n);
+  VA_FIXEDARG (ap, const char *, format);
+  result = vsnprintf (s, n, format, ap);
+  VA_CLOSE (ap);
+  return result;
+}
+
+extern int main PARAMS ((void));
+int
+main ()
+{
+  char buf[128];
+  int status;
+  
+  CLEAR (buf);
+  status = checkit (buf, 10, "%s:%d", "foobar", 9);
+  VERIFY (status==8 && strcmp (buf, "foobar:9") == 0);
+
+  CLEAR (buf);
+  status = checkit (buf, 9, "%s:%d", "foobar", 9);
+  VERIFY (status==8 && strcmp (buf, "foobar:9") == 0);
+
+  CLEAR (buf);
+  status = checkit (buf, 8, "%s:%d", "foobar", 9);
+  VERIFY (status==8 && strcmp (buf, "foobar:") == 0);
+
+  CLEAR (buf);
+  status = checkit (buf, 7, "%s:%d", "foobar", 9);
+  VERIFY (status==8 && strcmp (buf, "foobar") == 0);
+
+  CLEAR (buf);
+  status = checkit (buf, 6, "%s:%d", "foobar", 9);
+  VERIFY (status==8 && strcmp (buf, "fooba") == 0);
+
+  CLEAR (buf);
+  status = checkit (buf, 2, "%s:%d", "foobar", 9);
+  VERIFY (status==8 && strcmp (buf, "f") == 0);
+
+  CLEAR (buf);
+  status = checkit (buf, 1, "%s:%d", "foobar", 9);
+  VERIFY (status==8 && strcmp (buf, "") == 0);
+
+  CLEAR (buf);
+  status = checkit (buf, 0, "%s:%d", "foobar", 9);
+  VERIFY (status==8 && strcmp (buf, "XXXXXXXXXXXXXX") == 0);
+
+  return 0;
+}
+#endif /* TEST */



More information about the Gcc-patches mailing list