diff options
Diffstat (limited to 'contrib/binutils/libiberty/concat.c')
-rw-r--r-- | contrib/binutils/libiberty/concat.c | 239 |
1 files changed, 154 insertions, 85 deletions
diff --git a/contrib/binutils/libiberty/concat.c b/contrib/binutils/libiberty/concat.c index 5b132c8..98b20e1 100644 --- a/contrib/binutils/libiberty/concat.c +++ b/contrib/binutils/libiberty/concat.c @@ -1,5 +1,5 @@ /* Concatenate variable number of strings. - Copyright (C) 1991, 1994 Free Software Foundation, Inc. + Copyright (C) 1991, 1994, 2001 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support This file is part of the libiberty library. @@ -21,24 +21,14 @@ Boston, MA 02111-1307, USA. */ /* -NAME +@deftypefn Extension char* concat (const char *@var{s1}, const char *@var{s2}, @dots{}, @code{NULL}) - concat -- concatenate a variable number of strings +Concatenate zero or more of strings and return the result in freshly +@code{xmalloc}ed memory. Returns @code{NULL} if insufficient memory is +available. The argument list is terminated by the first @code{NULL} +pointer encountered. Pointers to empty strings are ignored. -SYNOPSIS - - #include <varargs.h> - - char *concat (s1, s2, s3, ..., NULL) - -DESCRIPTION - - Concatenate a variable number of strings and return the result - in freshly malloc'd memory. - - Returns NULL if insufficient memory is available. The argument - list is terminated by the first NULL pointer encountered. Pointers - to empty strings are ignored. +@end deftypefn NOTES @@ -50,11 +40,16 @@ NOTES deal with low memory situations itself, it should supply an xmalloc that just directly invokes malloc and blindly returns whatever malloc returns. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include "ansidecl.h" #include "libiberty.h" +#include <sys/types.h> /* size_t */ #ifdef ANSI_PROTOTYPES #include <stdarg.h> @@ -62,90 +57,164 @@ NOTES #include <varargs.h> #endif -#ifdef __STDC__ -#include <stddef.h> -extern size_t strlen (const char *s); -#else -extern int strlen (); +# if HAVE_STRING_H +# include <string.h> +# else +# if HAVE_STRINGS_H +# include <strings.h> +# endif +# endif + +#if HAVE_STDLIB_H +#include <stdlib.h> #endif -#define NULLP (char *)0 +static inline unsigned long vconcat_length PARAMS ((const char *, va_list)); +static inline unsigned long +vconcat_length (first, args) + const char *first; + va_list args; +{ + unsigned long length = 0; + const char *arg; + + for (arg = first; arg ; arg = va_arg (args, const char *)) + length += strlen (arg); + + return length; +} + +static inline char *vconcat_copy PARAMS ((char *, const char *, va_list)); +static inline char * +vconcat_copy (dst, first, args) + char *dst; + const char *first; + va_list args; +{ + char *end = dst; + const char *arg; + + for (arg = first; arg ; arg = va_arg (args, const char *)) + { + unsigned long length = strlen (arg); + memcpy (end, arg, length); + end += length; + } + *end = '\000'; + + return dst; +} + +/* @undocumented concat_length */ + +unsigned long +concat_length VPARAMS ((const char *first, ...)) +{ + unsigned long length; + + VA_OPEN (args, first); + VA_FIXEDARG (args, const char *, first); + length = vconcat_length (first, args); + VA_CLOSE (args); + + return length; +} + +/* @undocumented concat_copy */ -/* VARARGS */ -#ifdef ANSI_PROTOTYPES char * -concat (const char *first, ...) -#else +concat_copy VPARAMS ((char *dst, const char *first, ...)) +{ + char *save_dst; + + VA_OPEN (args, first); + VA_FIXEDARG (args, char *, dst); + VA_FIXEDARG (args, const char *, first); + vconcat_copy (dst, first, args); + save_dst = dst; /* With K&R C, dst goes out of scope here. */ + VA_CLOSE (args); + + return save_dst; +} + +char *libiberty_concat_ptr; + +/* @undocumented concat_copy2 */ + char * -concat (va_alist) - va_dcl -#endif +concat_copy2 VPARAMS ((const char *first, ...)) { - register int length; - register char *newstr; - register char *end; - register const char *arg; - va_list args; -#ifndef ANSI_PROTOTYPES - const char *first; -#endif + VA_OPEN (args, first); + VA_FIXEDARG (args, const char *, first); + vconcat_copy (libiberty_concat_ptr, first, args); + VA_CLOSE (args); - /* First compute the size of the result and get sufficient memory. */ + return libiberty_concat_ptr; +} -#ifdef ANSI_PROTOTYPES - va_start (args, first); -#else - va_start (args); - first = va_arg (args, const char *); -#endif +char * +concat VPARAMS ((const char *first, ...)) +{ + char *newstr; - if (first == NULLP) - length = 0; - else - { - length = strlen (first); - while ((arg = va_arg (args, const char *)) != NULLP) - { - length += strlen (arg); - } - } - newstr = (char *) xmalloc (length + 1); - va_end (args); + /* First compute the size of the result and get sufficient memory. */ + VA_OPEN (args, first); + VA_FIXEDARG (args, const char *, first); + newstr = (char *) xmalloc (vconcat_length (first, args) + 1); + VA_CLOSE (args); /* Now copy the individual pieces to the result string. */ + VA_OPEN (args, first); + VA_FIXEDARG (args, const char *, first); + vconcat_copy (newstr, first, args); + VA_CLOSE (args); - if (newstr != NULLP) - { -#ifdef ANSI_PROTOTYPES - va_start (args, first); -#else - va_start (args); - first = va_arg (args, const char *); -#endif - end = newstr; - if (first != NULLP) - { - arg = first; - while (*arg) - { - *end++ = *arg++; - } - while ((arg = va_arg (args, const char *)) != NULLP) - { - while (*arg) - { - *end++ = *arg++; - } - } - } - *end = '\000'; - va_end (args); - } + return newstr; +} + +/* + +@deftypefn Extension char* reconcat (char *@var{optr}, const char *@var{s1}, @dots{}, @code{NULL}) + +Same as @code{concat}, except that if @var{optr} is not @code{NULL} it +is freed after the string is created. This is intended to be useful +when you're extending an existing string or building up a string in a +loop: + +@example + str = reconcat (str, "pre-", str, NULL); +@end example + +@end deftypefn - return (newstr); +*/ + +char * +reconcat VPARAMS ((char *optr, const char *first, ...)) +{ + char *newstr; + + /* First compute the size of the result and get sufficient memory. */ + VA_OPEN (args, first); + VA_FIXEDARG (args, char *, optr); + VA_FIXEDARG (args, const char *, first); + newstr = (char *) xmalloc (vconcat_length (first, args) + 1); + VA_CLOSE (args); + + /* Now copy the individual pieces to the result string. */ + VA_OPEN (args, first); + VA_FIXEDARG (args, char *, optr); + VA_FIXEDARG (args, const char *, first); + vconcat_copy (newstr, first, args); + if (optr) /* Done before VA_CLOSE so optr stays in scope for K&R C. */ + free (optr); + VA_CLOSE (args); + + return newstr; } #ifdef MAIN +#define NULLP (char *)0 /* Simple little test driver. */ |