diff options
author | Bruno Haible <bruno@clisp.org> | 2006-05-09 17:26:15 +0000 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2006-05-09 17:26:15 +0000 |
commit | f46a1e87e0533bfb1801edf0465c45f7fe574f5c (patch) | |
tree | df21f43cac35fd601ef8ee0ef1adaf45de42ca61 | |
parent | 53de50e139f6c6ac0e5fb448b84d216aeece602e (diff) | |
download | gnulib-f46a1e87e0533bfb1801edf0465c45f7fe574f5c.tar.gz |
Recognize the special case of a string concatenation in xvasprintf.
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | lib/ChangeLog | 7 | ||||
-rw-r--r-- | lib/xvasprintf.c | 77 | ||||
-rw-r--r-- | m4/ChangeLog | 4 | ||||
-rw-r--r-- | m4/xvasprintf.m4 | 11 | ||||
-rw-r--r-- | modules/xvasprintf | 4 |
6 files changed, 108 insertions, 1 deletions
@@ -1,3 +1,9 @@ +2006-05-09 Bruno Haible <bruno@clisp.org> + + * modules/xvasprintf (Files): Add m4/xvasprintf.m4. + (Depends-on): Depend also on xsize, stdarg. + (configure.ac): Add gl_XVASPRINTF. + 2006-05-08 Eric Blake <ebb9@byu.net> * gnulib-tool (func_version): Base copyright year on CVS date. diff --git a/lib/ChangeLog b/lib/ChangeLog index 8ce48d3f3d..bc3eb6fe34 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,10 @@ +2006-05-09 Bruno Haible <bruno@clisp.org> + + * xvasprintf.c: Include limits.h, string.h, xsize.h. + (EOVERFLOW): Define fallback value. + (xstrcat): New function. + (xvasprintf): Recognize the special case of a string concatenation. + 2006-05-01 Bruno Haible <bruno@clisp.org> * stdint_.h: Shorter URL. diff --git a/lib/xvasprintf.c b/lib/xvasprintf.c index 9e8476642c..d68a50d83c 100644 --- a/lib/xvasprintf.c +++ b/lib/xvasprintf.c @@ -1,5 +1,5 @@ /* vasprintf and asprintf with out-of-memory checking. - Copyright (C) 1999, 2002-2004 Free Software Foundation, Inc. + Copyright (C) 1999, 2002-2004, 2006 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,15 +23,90 @@ #include "xvasprintf.h" #include <errno.h> +#include <limits.h> +#include <string.h> #include "vasprintf.h" #include "xalloc.h" +/* Checked size_t computations. */ +#include "xsize.h" + +/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ +#ifndef EOVERFLOW +# define EOVERFLOW E2BIG +#endif + +static inline char * +xstrcat (size_t argcount, va_list args) +{ + char *result; + va_list ap; + size_t totalsize; + size_t i; + char *p; + + /* Determine the total size. */ + totalsize = 0; + va_copy (ap, args); + for (i = argcount; i > 0; i--) + { + const char *next = va_arg (ap, const char *); + totalsize = xsum (totalsize, strlen (next)); + } + va_end (ap); + + /* Test for overflow in the summing pass above or in (totalsize + 1) below. + Also, don't return a string longer than INT_MAX, for consistency with + vasprintf(). */ + if (totalsize == SIZE_MAX || totalsize > INT_MAX) + { + errno = EOVERFLOW; + return NULL; + } + + /* Allocate and fill the result string. */ + result = (char *) xmalloc (totalsize + 1); + p = result; + for (i = argcount; i > 0; i--) + { + const char *next = va_arg (args, const char *); + size_t len = strlen (next); + memcpy (p, next, len); + p += len; + } + *p = '\0'; + + return result; +} + char * xvasprintf (const char *format, va_list args) { char *result; + /* Recognize the special case format = "%s...%s". It is a frequently used + idiom for string concatenation and needs to be fast. We don't want to + have a separate function xstrcat() for this purpose. */ + { + size_t argcount = 0; + const char *f; + + for (f = format;;) + { + if (*f == '\0') + /* Recognized the special case of string concatenation. */ + return xstrcat (argcount, args); + if (*f != '%') + break; + f++; + if (*f != 's') + break; + f++; + argcount++; + } + } + if (vasprintf (&result, format, args) < 0) { if (errno == ENOMEM) diff --git a/m4/ChangeLog b/m4/ChangeLog index 97b0dca136..8b54a51912 100644 --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,3 +1,7 @@ +2006-05-09 Bruno Haible <bruno@clisp.org> + + * xvasprintf.m4: New file. + 2006-05-08 Bruno Haible <bruno@clisp.org> * stdarg.m4: New file, from GNU gettext. diff --git a/m4/xvasprintf.m4 b/m4/xvasprintf.m4 new file mode 100644 index 0000000000..215631c454 --- /dev/null +++ b/m4/xvasprintf.m4 @@ -0,0 +1,11 @@ +# xvasprintf.m4 serial 1 +dnl Copyright (C) 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_XASPRINTF], +[ + dnl Prerequisites of lib/xvasprintf.c. + AC_REQUIRE([AC_C_INLINE]) +]) diff --git a/modules/xvasprintf b/modules/xvasprintf index e8f0d21939..984509cb42 100644 --- a/modules/xvasprintf +++ b/modules/xvasprintf @@ -6,12 +6,16 @@ lib/xvasprintf.h lib/xvasprintf.c lib/xasprintf.c lib/xalloc.h +m4/xvasprintf.m4 Depends-on: vasprintf xalloc-die +xsize +stdarg configure.ac: +gl_XVASPRINTF Makefile.am: lib_SOURCES += xvasprintf.h xvasprintf.c xasprintf.c |