133965Sjdp/* Concatenate variable number of strings. 289857Sobrien Copyright (C) 1991, 1994, 2001 Free Software Foundation, Inc. 333965Sjdp Written by Fred Fish @ Cygnus Support 433965Sjdp 533965SjdpThis file is part of the libiberty library. 633965SjdpLibiberty is free software; you can redistribute it and/or 733965Sjdpmodify it under the terms of the GNU Library General Public 833965SjdpLicense as published by the Free Software Foundation; either 933965Sjdpversion 2 of the License, or (at your option) any later version. 1033965Sjdp 1133965SjdpLibiberty is distributed in the hope that it will be useful, 1233965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1333965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1433965SjdpLibrary General Public License for more details. 1533965Sjdp 1633965SjdpYou should have received a copy of the GNU Library General Public 1733965SjdpLicense along with libiberty; see the file COPYING.LIB. If 18218822Sdimnot, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 19218822SdimBoston, MA 02110-1301, USA. */ 2033965Sjdp 2133965Sjdp 2233965Sjdp/* 2333965Sjdp 2489857Sobrien@deftypefn Extension char* concat (const char *@var{s1}, const char *@var{s2}, @dots{}, @code{NULL}) 2533965Sjdp 2689857SobrienConcatenate zero or more of strings and return the result in freshly 2789857Sobrien@code{xmalloc}ed memory. Returns @code{NULL} if insufficient memory is 2889857Sobrienavailable. The argument list is terminated by the first @code{NULL} 2989857Sobrienpointer encountered. Pointers to empty strings are ignored. 3033965Sjdp 3189857Sobrien@end deftypefn 3233965Sjdp 3333965SjdpNOTES 3433965Sjdp 3533965Sjdp This function uses xmalloc() which is expected to be a front end 3633965Sjdp function to malloc() that deals with low memory situations. In 3733965Sjdp typical use, if malloc() returns NULL then xmalloc() diverts to an 3833965Sjdp error handler routine which never returns, and thus xmalloc will 3933965Sjdp never return a NULL pointer. If the client application wishes to 4033965Sjdp deal with low memory situations itself, it should supply an xmalloc 4133965Sjdp that just directly invokes malloc and blindly returns whatever 4233965Sjdp malloc returns. 4389857Sobrien 4433965Sjdp*/ 4533965Sjdp 4633965Sjdp 4789857Sobrien#ifdef HAVE_CONFIG_H 4889857Sobrien#include "config.h" 4989857Sobrien#endif 5033965Sjdp#include "ansidecl.h" 5133965Sjdp#include "libiberty.h" 5289857Sobrien#include <sys/types.h> /* size_t */ 5333965Sjdp 5433965Sjdp#include <stdarg.h> 5533965Sjdp 5689857Sobrien# if HAVE_STRING_H 5789857Sobrien# include <string.h> 5889857Sobrien# else 5989857Sobrien# if HAVE_STRINGS_H 6089857Sobrien# include <strings.h> 6189857Sobrien# endif 6289857Sobrien# endif 6389857Sobrien 6489857Sobrien#if HAVE_STDLIB_H 6589857Sobrien#include <stdlib.h> 6633965Sjdp#endif 6733965Sjdp 68218822Sdimstatic inline unsigned long vconcat_length (const char *, va_list); 6989857Sobrienstatic inline unsigned long 70218822Sdimvconcat_length (const char *first, va_list args) 7189857Sobrien{ 7289857Sobrien unsigned long length = 0; 7389857Sobrien const char *arg; 7433965Sjdp 7589857Sobrien for (arg = first; arg ; arg = va_arg (args, const char *)) 7689857Sobrien length += strlen (arg); 7789857Sobrien 7889857Sobrien return length; 7989857Sobrien} 8089857Sobrien 8189857Sobrienstatic inline char * 82218822Sdimvconcat_copy (char *dst, const char *first, va_list args) 8389857Sobrien{ 8489857Sobrien char *end = dst; 8589857Sobrien const char *arg; 8689857Sobrien 8789857Sobrien for (arg = first; arg ; arg = va_arg (args, const char *)) 8889857Sobrien { 8989857Sobrien unsigned long length = strlen (arg); 9089857Sobrien memcpy (end, arg, length); 9189857Sobrien end += length; 9289857Sobrien } 9389857Sobrien *end = '\000'; 9489857Sobrien 9589857Sobrien return dst; 9689857Sobrien} 9789857Sobrien 9889857Sobrien/* @undocumented concat_length */ 9989857Sobrien 10089857Sobrienunsigned long 101218822Sdimconcat_length (const char *first, ...) 10289857Sobrien{ 10389857Sobrien unsigned long length; 10489857Sobrien 10589857Sobrien VA_OPEN (args, first); 10689857Sobrien VA_FIXEDARG (args, const char *, first); 10789857Sobrien length = vconcat_length (first, args); 10889857Sobrien VA_CLOSE (args); 10989857Sobrien 11089857Sobrien return length; 11189857Sobrien} 11289857Sobrien 11389857Sobrien/* @undocumented concat_copy */ 11489857Sobrien 11533965Sjdpchar * 116218822Sdimconcat_copy (char *dst, const char *first, ...) 11789857Sobrien{ 11889857Sobrien char *save_dst; 11989857Sobrien 12089857Sobrien VA_OPEN (args, first); 12189857Sobrien VA_FIXEDARG (args, char *, dst); 12289857Sobrien VA_FIXEDARG (args, const char *, first); 12389857Sobrien vconcat_copy (dst, first, args); 12489857Sobrien save_dst = dst; /* With K&R C, dst goes out of scope here. */ 12589857Sobrien VA_CLOSE (args); 12689857Sobrien 12789857Sobrien return save_dst; 12889857Sobrien} 12989857Sobrien 130218822Sdim#ifdef __cplusplus 131218822Sdimextern "C" { 132218822Sdim#endif /* __cplusplus */ 13389857Sobrienchar *libiberty_concat_ptr; 134218822Sdim#ifdef __cplusplus 135218822Sdim} 136218822Sdim#endif /* __cplusplus */ 13789857Sobrien 13889857Sobrien/* @undocumented concat_copy2 */ 13989857Sobrien 14033965Sjdpchar * 141218822Sdimconcat_copy2 (const char *first, ...) 14233965Sjdp{ 14389857Sobrien VA_OPEN (args, first); 14489857Sobrien VA_FIXEDARG (args, const char *, first); 14589857Sobrien vconcat_copy (libiberty_concat_ptr, first, args); 14689857Sobrien VA_CLOSE (args); 14733965Sjdp 14889857Sobrien return libiberty_concat_ptr; 14989857Sobrien} 15033965Sjdp 15189857Sobrienchar * 152218822Sdimconcat (const char *first, ...) 15389857Sobrien{ 15489857Sobrien char *newstr; 15533965Sjdp 15689857Sobrien /* First compute the size of the result and get sufficient memory. */ 15789857Sobrien VA_OPEN (args, first); 15889857Sobrien VA_FIXEDARG (args, const char *, first); 159218822Sdim newstr = XNEWVEC (char, vconcat_length (first, args) + 1); 16089857Sobrien VA_CLOSE (args); 16133965Sjdp 16233965Sjdp /* Now copy the individual pieces to the result string. */ 16389857Sobrien VA_OPEN (args, first); 16489857Sobrien VA_FIXEDARG (args, const char *, first); 16589857Sobrien vconcat_copy (newstr, first, args); 16689857Sobrien VA_CLOSE (args); 16733965Sjdp 16889857Sobrien return newstr; 16989857Sobrien} 17033965Sjdp 17189857Sobrien/* 17289857Sobrien 17389857Sobrien@deftypefn Extension char* reconcat (char *@var{optr}, const char *@var{s1}, @dots{}, @code{NULL}) 17489857Sobrien 17589857SobrienSame as @code{concat}, except that if @var{optr} is not @code{NULL} it 17689857Sobrienis freed after the string is created. This is intended to be useful 17789857Sobrienwhen you're extending an existing string or building up a string in a 17889857Sobrienloop: 17989857Sobrien 18089857Sobrien@example 18189857Sobrien str = reconcat (str, "pre-", str, NULL); 18289857Sobrien@end example 18389857Sobrien 18489857Sobrien@end deftypefn 18589857Sobrien 18689857Sobrien*/ 18789857Sobrien 18889857Sobrienchar * 189218822Sdimreconcat (char *optr, const char *first, ...) 19089857Sobrien{ 19189857Sobrien char *newstr; 19289857Sobrien 19389857Sobrien /* First compute the size of the result and get sufficient memory. */ 19489857Sobrien VA_OPEN (args, first); 19589857Sobrien VA_FIXEDARG (args, char *, optr); 19689857Sobrien VA_FIXEDARG (args, const char *, first); 197218822Sdim newstr = XNEWVEC (char, vconcat_length (first, args) + 1); 19889857Sobrien VA_CLOSE (args); 19989857Sobrien 20089857Sobrien /* Now copy the individual pieces to the result string. */ 20189857Sobrien VA_OPEN (args, first); 20289857Sobrien VA_FIXEDARG (args, char *, optr); 20389857Sobrien VA_FIXEDARG (args, const char *, first); 20489857Sobrien vconcat_copy (newstr, first, args); 20589857Sobrien if (optr) /* Done before VA_CLOSE so optr stays in scope for K&R C. */ 20689857Sobrien free (optr); 20789857Sobrien VA_CLOSE (args); 20889857Sobrien 20989857Sobrien return newstr; 21033965Sjdp} 21133965Sjdp 21233965Sjdp#ifdef MAIN 21389857Sobrien#define NULLP (char *)0 21433965Sjdp 21533965Sjdp/* Simple little test driver. */ 21633965Sjdp 21733965Sjdp#include <stdio.h> 21833965Sjdp 21933965Sjdpint 220218822Sdimmain (void) 22133965Sjdp{ 22233965Sjdp printf ("\"\" = \"%s\"\n", concat (NULLP)); 22333965Sjdp printf ("\"a\" = \"%s\"\n", concat ("a", NULLP)); 22433965Sjdp printf ("\"ab\" = \"%s\"\n", concat ("a", "b", NULLP)); 22533965Sjdp printf ("\"abc\" = \"%s\"\n", concat ("a", "b", "c", NULLP)); 22633965Sjdp printf ("\"abcd\" = \"%s\"\n", concat ("ab", "cd", NULLP)); 22733965Sjdp printf ("\"abcde\" = \"%s\"\n", concat ("ab", "c", "de", NULLP)); 22833965Sjdp printf ("\"abcdef\" = \"%s\"\n", concat ("", "a", "", "bcd", "ef", NULLP)); 22933965Sjdp return 0; 23033965Sjdp} 23133965Sjdp 23233965Sjdp#endif 233