concat.c revision 89857
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 1833965Sjdpnot, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 1933965SjdpBoston, MA 02111-1307, 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#ifdef ANSI_PROTOTYPES 5533965Sjdp#include <stdarg.h> 5633965Sjdp#else 5733965Sjdp#include <varargs.h> 5833965Sjdp#endif 5933965Sjdp 6089857Sobrien# if HAVE_STRING_H 6189857Sobrien# include <string.h> 6289857Sobrien# else 6389857Sobrien# if HAVE_STRINGS_H 6489857Sobrien# include <strings.h> 6589857Sobrien# endif 6689857Sobrien# endif 6789857Sobrien 6889857Sobrien#if HAVE_STDLIB_H 6989857Sobrien#include <stdlib.h> 7033965Sjdp#endif 7133965Sjdp 7289857Sobrienstatic inline unsigned long vconcat_length PARAMS ((const char *, va_list)); 7389857Sobrienstatic inline unsigned long 7489857Sobrienvconcat_length (first, args) 7589857Sobrien const char *first; 7689857Sobrien va_list args; 7789857Sobrien{ 7889857Sobrien unsigned long length = 0; 7989857Sobrien const char *arg; 8033965Sjdp 8189857Sobrien for (arg = first; arg ; arg = va_arg (args, const char *)) 8289857Sobrien length += strlen (arg); 8389857Sobrien 8489857Sobrien return length; 8589857Sobrien} 8689857Sobrien 8789857Sobrienstatic inline char *vconcat_copy PARAMS ((char *, const char *, va_list)); 8889857Sobrienstatic inline char * 8989857Sobrienvconcat_copy (dst, first, args) 9089857Sobrien char *dst; 9189857Sobrien const char *first; 9289857Sobrien va_list args; 9389857Sobrien{ 9489857Sobrien char *end = dst; 9589857Sobrien const char *arg; 9689857Sobrien 9789857Sobrien for (arg = first; arg ; arg = va_arg (args, const char *)) 9889857Sobrien { 9989857Sobrien unsigned long length = strlen (arg); 10089857Sobrien memcpy (end, arg, length); 10189857Sobrien end += length; 10289857Sobrien } 10389857Sobrien *end = '\000'; 10489857Sobrien 10589857Sobrien return dst; 10689857Sobrien} 10789857Sobrien 10889857Sobrien/* @undocumented concat_length */ 10989857Sobrien 11089857Sobrienunsigned long 11189857Sobrienconcat_length VPARAMS ((const char *first, ...)) 11289857Sobrien{ 11389857Sobrien unsigned long length; 11489857Sobrien 11589857Sobrien VA_OPEN (args, first); 11689857Sobrien VA_FIXEDARG (args, const char *, first); 11789857Sobrien length = vconcat_length (first, args); 11889857Sobrien VA_CLOSE (args); 11989857Sobrien 12089857Sobrien return length; 12189857Sobrien} 12289857Sobrien 12389857Sobrien/* @undocumented concat_copy */ 12489857Sobrien 12533965Sjdpchar * 12689857Sobrienconcat_copy VPARAMS ((char *dst, const char *first, ...)) 12789857Sobrien{ 12889857Sobrien char *save_dst; 12989857Sobrien 13089857Sobrien VA_OPEN (args, first); 13189857Sobrien VA_FIXEDARG (args, char *, dst); 13289857Sobrien VA_FIXEDARG (args, const char *, first); 13389857Sobrien vconcat_copy (dst, first, args); 13489857Sobrien save_dst = dst; /* With K&R C, dst goes out of scope here. */ 13589857Sobrien VA_CLOSE (args); 13689857Sobrien 13789857Sobrien return save_dst; 13889857Sobrien} 13989857Sobrien 14089857Sobrienchar *libiberty_concat_ptr; 14189857Sobrien 14289857Sobrien/* @undocumented concat_copy2 */ 14389857Sobrien 14433965Sjdpchar * 14589857Sobrienconcat_copy2 VPARAMS ((const char *first, ...)) 14633965Sjdp{ 14789857Sobrien VA_OPEN (args, first); 14889857Sobrien VA_FIXEDARG (args, const char *, first); 14989857Sobrien vconcat_copy (libiberty_concat_ptr, first, args); 15089857Sobrien VA_CLOSE (args); 15133965Sjdp 15289857Sobrien return libiberty_concat_ptr; 15389857Sobrien} 15433965Sjdp 15589857Sobrienchar * 15689857Sobrienconcat VPARAMS ((const char *first, ...)) 15789857Sobrien{ 15889857Sobrien char *newstr; 15933965Sjdp 16089857Sobrien /* First compute the size of the result and get sufficient memory. */ 16189857Sobrien VA_OPEN (args, first); 16289857Sobrien VA_FIXEDARG (args, const char *, first); 16389857Sobrien newstr = (char *) xmalloc (vconcat_length (first, args) + 1); 16489857Sobrien VA_CLOSE (args); 16533965Sjdp 16633965Sjdp /* Now copy the individual pieces to the result string. */ 16789857Sobrien VA_OPEN (args, first); 16889857Sobrien VA_FIXEDARG (args, const char *, first); 16989857Sobrien vconcat_copy (newstr, first, args); 17089857Sobrien VA_CLOSE (args); 17133965Sjdp 17289857Sobrien return newstr; 17389857Sobrien} 17433965Sjdp 17589857Sobrien/* 17689857Sobrien 17789857Sobrien@deftypefn Extension char* reconcat (char *@var{optr}, const char *@var{s1}, @dots{}, @code{NULL}) 17889857Sobrien 17989857SobrienSame as @code{concat}, except that if @var{optr} is not @code{NULL} it 18089857Sobrienis freed after the string is created. This is intended to be useful 18189857Sobrienwhen you're extending an existing string or building up a string in a 18289857Sobrienloop: 18389857Sobrien 18489857Sobrien@example 18589857Sobrien str = reconcat (str, "pre-", str, NULL); 18689857Sobrien@end example 18789857Sobrien 18889857Sobrien@end deftypefn 18989857Sobrien 19089857Sobrien*/ 19189857Sobrien 19289857Sobrienchar * 19389857Sobrienreconcat VPARAMS ((char *optr, const char *first, ...)) 19489857Sobrien{ 19589857Sobrien char *newstr; 19689857Sobrien 19789857Sobrien /* First compute the size of the result and get sufficient memory. */ 19889857Sobrien VA_OPEN (args, first); 19989857Sobrien VA_FIXEDARG (args, char *, optr); 20089857Sobrien VA_FIXEDARG (args, const char *, first); 20189857Sobrien newstr = (char *) xmalloc (vconcat_length (first, args) + 1); 20289857Sobrien VA_CLOSE (args); 20389857Sobrien 20489857Sobrien /* Now copy the individual pieces to the result string. */ 20589857Sobrien VA_OPEN (args, first); 20689857Sobrien VA_FIXEDARG (args, char *, optr); 20789857Sobrien VA_FIXEDARG (args, const char *, first); 20889857Sobrien vconcat_copy (newstr, first, args); 20989857Sobrien if (optr) /* Done before VA_CLOSE so optr stays in scope for K&R C. */ 21089857Sobrien free (optr); 21189857Sobrien VA_CLOSE (args); 21289857Sobrien 21389857Sobrien return newstr; 21433965Sjdp} 21533965Sjdp 21633965Sjdp#ifdef MAIN 21789857Sobrien#define NULLP (char *)0 21833965Sjdp 21933965Sjdp/* Simple little test driver. */ 22033965Sjdp 22133965Sjdp#include <stdio.h> 22233965Sjdp 22333965Sjdpint 22433965Sjdpmain () 22533965Sjdp{ 22633965Sjdp printf ("\"\" = \"%s\"\n", concat (NULLP)); 22733965Sjdp printf ("\"a\" = \"%s\"\n", concat ("a", NULLP)); 22833965Sjdp printf ("\"ab\" = \"%s\"\n", concat ("a", "b", NULLP)); 22933965Sjdp printf ("\"abc\" = \"%s\"\n", concat ("a", "b", "c", NULLP)); 23033965Sjdp printf ("\"abcd\" = \"%s\"\n", concat ("ab", "cd", NULLP)); 23133965Sjdp printf ("\"abcde\" = \"%s\"\n", concat ("ab", "c", "de", NULLP)); 23233965Sjdp printf ("\"abcdef\" = \"%s\"\n", concat ("", "a", "", "bcd", "ef", NULLP)); 23333965Sjdp return 0; 23433965Sjdp} 23533965Sjdp 23633965Sjdp#endif 237