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