1169695Skan/* Concatenate variable number of strings. 2169695Skan Copyright (C) 1991, 1994, 2001 Free Software Foundation, Inc. 3169695Skan Written by Fred Fish @ Cygnus Support 4169695Skan 5169695SkanThis file is part of the libiberty library. 6169695SkanLibiberty is free software; you can redistribute it and/or 7169695Skanmodify it under the terms of the GNU Library General Public 8169695SkanLicense as published by the Free Software Foundation; either 9169695Skanversion 2 of the License, or (at your option) any later version. 10169695Skan 11169695SkanLibiberty is distributed in the hope that it will be useful, 12169695Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of 13169695SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14169695SkanLibrary General Public License for more details. 15169695Skan 16169695SkanYou should have received a copy of the GNU Library General Public 17169695SkanLicense along with libiberty; see the file COPYING.LIB. If 18169695Skannot, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 19169695SkanBoston, MA 02110-1301, USA. */ 20169695Skan 21169695Skan 22169695Skan/* 23169695Skan 24169695Skan@deftypefn Extension char* concat (const char *@var{s1}, const char *@var{s2}, @dots{}, @code{NULL}) 25169695Skan 26169695SkanConcatenate zero or more of strings and return the result in freshly 27169695Skan@code{xmalloc}ed memory. Returns @code{NULL} if insufficient memory is 28169695Skanavailable. The argument list is terminated by the first @code{NULL} 29169695Skanpointer encountered. Pointers to empty strings are ignored. 30169695Skan 31169695Skan@end deftypefn 32169695Skan 33169695SkanNOTES 34169695Skan 35169695Skan This function uses xmalloc() which is expected to be a front end 36169695Skan function to malloc() that deals with low memory situations. In 37169695Skan typical use, if malloc() returns NULL then xmalloc() diverts to an 38169695Skan error handler routine which never returns, and thus xmalloc will 39169695Skan never return a NULL pointer. If the client application wishes to 40169695Skan deal with low memory situations itself, it should supply an xmalloc 41169695Skan that just directly invokes malloc and blindly returns whatever 42169695Skan malloc returns. 43169695Skan 44169695Skan*/ 45169695Skan 46169695Skan 47169695Skan#ifdef HAVE_CONFIG_H 48169695Skan#include "config.h" 49169695Skan#endif 50169695Skan#include "ansidecl.h" 51169695Skan#include "libiberty.h" 52169695Skan#include <sys/types.h> /* size_t */ 53169695Skan 54169695Skan#include <stdarg.h> 55169695Skan 56169695Skan# if HAVE_STRING_H 57169695Skan# include <string.h> 58169695Skan# else 59169695Skan# if HAVE_STRINGS_H 60169695Skan# include <strings.h> 61169695Skan# endif 62169695Skan# endif 63169695Skan 64169695Skan#if HAVE_STDLIB_H 65169695Skan#include <stdlib.h> 66169695Skan#endif 67169695Skan 68169695Skanstatic inline unsigned long vconcat_length (const char *, va_list); 69169695Skanstatic inline unsigned long 70169695Skanvconcat_length (const char *first, va_list args) 71169695Skan{ 72169695Skan unsigned long length = 0; 73169695Skan const char *arg; 74169695Skan 75169695Skan for (arg = first; arg ; arg = va_arg (args, const char *)) 76169695Skan length += strlen (arg); 77169695Skan 78169695Skan return length; 79169695Skan} 80169695Skan 81169695Skanstatic inline char * 82169695Skanvconcat_copy (char *dst, const char *first, va_list args) 83169695Skan{ 84169695Skan char *end = dst; 85169695Skan const char *arg; 86169695Skan 87169695Skan for (arg = first; arg ; arg = va_arg (args, const char *)) 88169695Skan { 89169695Skan unsigned long length = strlen (arg); 90169695Skan memcpy (end, arg, length); 91169695Skan end += length; 92169695Skan } 93169695Skan *end = '\000'; 94169695Skan 95169695Skan return dst; 96169695Skan} 97169695Skan 98169695Skan/* @undocumented concat_length */ 99169695Skan 100169695Skanunsigned long 101169695Skanconcat_length (const char *first, ...) 102169695Skan{ 103169695Skan unsigned long length; 104169695Skan 105169695Skan VA_OPEN (args, first); 106169695Skan VA_FIXEDARG (args, const char *, first); 107169695Skan length = vconcat_length (first, args); 108169695Skan VA_CLOSE (args); 109169695Skan 110169695Skan return length; 111169695Skan} 112169695Skan 113169695Skan/* @undocumented concat_copy */ 114169695Skan 115169695Skanchar * 116169695Skanconcat_copy (char *dst, const char *first, ...) 117169695Skan{ 118169695Skan char *save_dst; 119169695Skan 120169695Skan VA_OPEN (args, first); 121169695Skan VA_FIXEDARG (args, char *, dst); 122169695Skan VA_FIXEDARG (args, const char *, first); 123169695Skan vconcat_copy (dst, first, args); 124169695Skan save_dst = dst; /* With K&R C, dst goes out of scope here. */ 125169695Skan VA_CLOSE (args); 126169695Skan 127169695Skan return save_dst; 128169695Skan} 129169695Skan 130169695Skan#ifdef __cplusplus 131169695Skanextern "C" { 132169695Skan#endif /* __cplusplus */ 133169695Skanchar *libiberty_concat_ptr; 134169695Skan#ifdef __cplusplus 135169695Skan} 136169695Skan#endif /* __cplusplus */ 137169695Skan 138169695Skan/* @undocumented concat_copy2 */ 139169695Skan 140169695Skanchar * 141169695Skanconcat_copy2 (const char *first, ...) 142169695Skan{ 143169695Skan VA_OPEN (args, first); 144169695Skan VA_FIXEDARG (args, const char *, first); 145169695Skan vconcat_copy (libiberty_concat_ptr, first, args); 146169695Skan VA_CLOSE (args); 147169695Skan 148169695Skan return libiberty_concat_ptr; 149169695Skan} 150169695Skan 151169695Skanchar * 152169695Skanconcat (const char *first, ...) 153169695Skan{ 154169695Skan char *newstr; 155169695Skan 156169695Skan /* First compute the size of the result and get sufficient memory. */ 157169695Skan VA_OPEN (args, first); 158169695Skan VA_FIXEDARG (args, const char *, first); 159169695Skan newstr = XNEWVEC (char, vconcat_length (first, args) + 1); 160169695Skan VA_CLOSE (args); 161169695Skan 162169695Skan /* Now copy the individual pieces to the result string. */ 163169695Skan VA_OPEN (args, first); 164169695Skan VA_FIXEDARG (args, const char *, first); 165169695Skan vconcat_copy (newstr, first, args); 166169695Skan VA_CLOSE (args); 167169695Skan 168169695Skan return newstr; 169169695Skan} 170169695Skan 171169695Skan/* 172169695Skan 173169695Skan@deftypefn Extension char* reconcat (char *@var{optr}, const char *@var{s1}, @dots{}, @code{NULL}) 174169695Skan 175169695SkanSame as @code{concat}, except that if @var{optr} is not @code{NULL} it 176169695Skanis freed after the string is created. This is intended to be useful 177169695Skanwhen you're extending an existing string or building up a string in a 178169695Skanloop: 179169695Skan 180169695Skan@example 181169695Skan str = reconcat (str, "pre-", str, NULL); 182169695Skan@end example 183169695Skan 184169695Skan@end deftypefn 185169695Skan 186169695Skan*/ 187169695Skan 188169695Skanchar * 189169695Skanreconcat (char *optr, const char *first, ...) 190169695Skan{ 191169695Skan char *newstr; 192169695Skan 193169695Skan /* First compute the size of the result and get sufficient memory. */ 194169695Skan VA_OPEN (args, first); 195169695Skan VA_FIXEDARG (args, char *, optr); 196169695Skan VA_FIXEDARG (args, const char *, first); 197169695Skan newstr = XNEWVEC (char, vconcat_length (first, args) + 1); 198169695Skan VA_CLOSE (args); 199169695Skan 200169695Skan /* Now copy the individual pieces to the result string. */ 201169695Skan VA_OPEN (args, first); 202169695Skan VA_FIXEDARG (args, char *, optr); 203169695Skan VA_FIXEDARG (args, const char *, first); 204169695Skan vconcat_copy (newstr, first, args); 205169695Skan if (optr) /* Done before VA_CLOSE so optr stays in scope for K&R C. */ 206169695Skan free (optr); 207169695Skan VA_CLOSE (args); 208169695Skan 209169695Skan return newstr; 210169695Skan} 211169695Skan 212169695Skan#ifdef MAIN 213169695Skan#define NULLP (char *)0 214169695Skan 215169695Skan/* Simple little test driver. */ 216169695Skan 217169695Skan#include <stdio.h> 218169695Skan 219169695Skanint 220169695Skanmain (void) 221169695Skan{ 222169695Skan printf ("\"\" = \"%s\"\n", concat (NULLP)); 223169695Skan printf ("\"a\" = \"%s\"\n", concat ("a", NULLP)); 224169695Skan printf ("\"ab\" = \"%s\"\n", concat ("a", "b", NULLP)); 225169695Skan printf ("\"abc\" = \"%s\"\n", concat ("a", "b", "c", NULLP)); 226169695Skan printf ("\"abcd\" = \"%s\"\n", concat ("ab", "cd", NULLP)); 227169695Skan printf ("\"abcde\" = \"%s\"\n", concat ("ab", "c", "de", NULLP)); 228169695Skan printf ("\"abcdef\" = \"%s\"\n", concat ("", "a", "", "bcd", "ef", NULLP)); 229169695Skan return 0; 230169695Skan} 231169695Skan 232169695Skan#endif 233