19313Ssos/* Concatenate variable number of strings.
29313Ssos   Copyright (C) 1991, 1994, 2001 Free Software Foundation, Inc.
39313Ssos   Written by Fred Fish @ Cygnus Support
49313Ssos
59313SsosThis file is part of the libiberty library.
69313SsosLibiberty is free software; you can redistribute it and/or
79313Ssosmodify it under the terms of the GNU Library General Public
89313SsosLicense as published by the Free Software Foundation; either
99313Ssosversion 2 of the License, or (at your option) any later version.
109313Ssos
119313SsosLibiberty is distributed in the hope that it will be useful,
129313Ssosbut WITHOUT ANY WARRANTY; without even the implied warranty of
139313SsosMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
149313SsosLibrary General Public License for more details.
159313Ssos
169313SsosYou should have received a copy of the GNU Library General Public
179313SsosLicense along with libiberty; see the file COPYING.LIB.  If
189313Ssosnot, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
199313SsosBoston, MA 02110-1301, USA.  */
209313Ssos
219313Ssos
229313Ssos/*
239313Ssos
249313Ssos@deftypefn Extension char* concat (const char *@var{s1}, const char *@var{s2}, @dots{}, @code{NULL})
259313Ssos
269313SsosConcatenate zero or more of strings and return the result in freshly
279313Ssos@code{xmalloc}ed memory.  Returns @code{NULL} if insufficient memory is
2850477Speteravailable.  The argument list is terminated by the first @code{NULL}
299313Ssospointer encountered.  Pointers to empty strings are ignored.
309313Ssos
3131784Seivind@end deftypefn
3231784Seivind
339313SsosNOTES
349313Ssos
3512458Sbde	This function uses xmalloc() which is expected to be a front end
369313Ssos	function to malloc() that deals with low memory situations.  In
379313Ssos	typical use, if malloc() returns NULL then xmalloc() diverts to an
389313Ssos	error handler routine which never returns, and thus xmalloc will
3931561Sbde	never return a NULL pointer.  If the client application wishes to
409313Ssos	deal with low memory situations itself, it should supply an xmalloc
419313Ssos	that just directly invokes malloc and blindly returns whatever
429313Ssos	malloc returns.
439313Ssos
4414331Speter*/
4514331Speter
4612458Sbde
4712458Sbde#ifdef HAVE_CONFIG_H
4814331Speter#include "config.h"
4914331Speter#endif
509313Ssos#include "ansidecl.h"
519313Ssos#include "libiberty.h"
5230994Sphk#include <sys/types.h>		/* size_t */
539313Ssos
5412858Speter#include <stdarg.h>
559313Ssos
569313Ssos# if HAVE_STRING_H
579313Ssos#  include <string.h>
5812858Speter# else
5914331Speter#  if HAVE_STRINGS_H
609313Ssos#   include <strings.h>
6114331Speter#  endif
6214331Speter# endif
6314331Speter
649313Ssos#if HAVE_STDLIB_H
659313Ssos#include <stdlib.h>
669313Ssos#endif
679313Ssos
689313Ssosstatic inline unsigned long vconcat_length (const char *, va_list);
699313Ssosstatic inline unsigned long
709313Ssosvconcat_length (const char *first, va_list args)
7130994Sphk{
729313Ssos  unsigned long length = 0;
739313Ssos  const char *arg;
749313Ssos
7530994Sphk  for (arg = first; arg ; arg = va_arg (args, const char *))
769313Ssos    length += strlen (arg);
7712858Speter
789313Ssos  return length;
799313Ssos}
809313Ssos
8112858Speterstatic inline char *
829313Ssosvconcat_copy (char *dst, const char *first, va_list args)
8314331Speter{
8414331Speter  char *end = dst;
8514331Speter  const char *arg;
869313Ssos
8714331Speter  for (arg = first; arg ; arg = va_arg (args, const char *))
8814331Speter    {
8914331Speter      unsigned long length = strlen (arg);
9014331Speter      memcpy (end, arg, length);
9114331Speter      end += length;
929313Ssos    }
939313Ssos  *end = '\000';
949313Ssos
959313Ssos  return dst;
969313Ssos}
979313Ssos
989313Ssos/* @undocumented concat_length */
999313Ssos
1009313Ssosunsigned long
1019313Ssosconcat_length (const char *first, ...)
1029313Ssos{
1039313Ssos  unsigned long length;
1049313Ssos
1059313Ssos  VA_OPEN (args, first);
1069313Ssos  VA_FIXEDARG (args, const char *, first);
1079313Ssos  length = vconcat_length (first, args);
1089313Ssos  VA_CLOSE (args);
1099313Ssos
1109313Ssos  return length;
1119313Ssos}
1129313Ssos
1139313Ssos/* @undocumented concat_copy */
1149313Ssos
1159313Ssoschar *
1169313Ssosconcat_copy (char *dst, const char *first, ...)
1179313Ssos{
1189313Ssos  char *save_dst;
1199313Ssos
1209313Ssos  VA_OPEN (args, first);
1219313Ssos  VA_FIXEDARG (args, char *, dst);
1229313Ssos  VA_FIXEDARG (args, const char *, first);
1239313Ssos  vconcat_copy (dst, first, args);
12430994Sphk  save_dst = dst; /* With K&R C, dst goes out of scope here.  */
1259313Ssos  VA_CLOSE (args);
1269313Ssos
1279313Ssos  return save_dst;
12830994Sphk}
1299313Ssos
1309313Ssos#ifdef __cplusplus
13151418Sgreenextern "C" {
1329313Ssos#endif /* __cplusplus */
13314331Speterchar *libiberty_concat_ptr;
13414331Speter#ifdef __cplusplus
13514331Speter}
13614331Speter#endif /* __cplusplus */
1379313Ssos
1389313Ssos/* @undocumented concat_copy2 */
1399313Ssos
1409313Ssoschar *
1419313Ssosconcat_copy2 (const char *first, ...)
1429313Ssos{
1439313Ssos  VA_OPEN (args, first);
1449313Ssos  VA_FIXEDARG (args, const char *, first);
1459313Ssos  vconcat_copy (libiberty_concat_ptr, first, args);
1469313Ssos  VA_CLOSE (args);
1479313Ssos
1489313Ssos  return libiberty_concat_ptr;
1499313Ssos}
1509313Ssos
1519313Ssoschar *
1529313Ssosconcat (const char *first, ...)
1539313Ssos{
1549313Ssos  char *newstr;
1559313Ssos
1569313Ssos  /* First compute the size of the result and get sufficient memory.  */
1579313Ssos  VA_OPEN (args, first);
1589313Ssos  VA_FIXEDARG (args, const char *, first);
1599313Ssos  newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
1609313Ssos  VA_CLOSE (args);
16149676Smarcel
16249676Smarcel  /* Now copy the individual pieces to the result string. */
16349676Smarcel  VA_OPEN (args, first);
1649313Ssos  VA_FIXEDARG (args, const char *, first);
1659313Ssos  vconcat_copy (newstr, first, args);
1669313Ssos  VA_CLOSE (args);
1679313Ssos
1689313Ssos  return newstr;
1699313Ssos}
1709313Ssos
1719313Ssos/*
1729313Ssos
1739313Ssos@deftypefn Extension char* reconcat (char *@var{optr}, const char *@var{s1}, @dots{}, @code{NULL})
1749313Ssos
1759313SsosSame as @code{concat}, except that if @var{optr} is not @code{NULL} it
1769313Ssosis freed after the string is created.  This is intended to be useful
1779313Ssoswhen you're extending an existing string or building up a string in a
1789313Ssosloop:
1799313Ssos
1809313Ssos@example
1819313Ssos  str = reconcat (str, "pre-", str, NULL);
1829313Ssos@end example
1839313Ssos
1849313Ssos@end deftypefn
1859313Ssos
1869313Ssos*/
1879313Ssos
1889313Ssoschar *
1899313Ssosreconcat (char *optr, const char *first, ...)
1909313Ssos{
1919313Ssos  char *newstr;
19230994Sphk
1939313Ssos  /* First compute the size of the result and get sufficient memory.  */
1949313Ssos  VA_OPEN (args, first);
19512858Speter  VA_FIXEDARG (args, char *, optr);
1969313Ssos  VA_FIXEDARG (args, const char *, first);
1979313Ssos  newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
1989313Ssos  VA_CLOSE (args);
19912858Speter
2009313Ssos  /* Now copy the individual pieces to the result string. */
20114331Speter  VA_OPEN (args, first);
20214331Speter  VA_FIXEDARG (args, char *, optr);
20314331Speter  VA_FIXEDARG (args, const char *, first);
20414331Speter  vconcat_copy (newstr, first, args);
20514331Speter  if (optr) /* Done before VA_CLOSE so optr stays in scope for K&R C.  */
20614331Speter    free (optr);
20751654Sphk  VA_CLOSE (args);
20814331Speter
20947028Sphk  return newstr;
2109313Ssos}
21114331Speter
21214331Speter#ifdef MAIN
21314331Speter#define NULLP (char *)0
2149313Ssos
2159313Ssos/* Simple little test driver. */
2169313Ssos
2179313Ssos#include <stdio.h>
2189313Ssos
2199313Ssosint
2209313Ssosmain (void)
2219313Ssos{
2229313Ssos  printf ("\"\" = \"%s\"\n", concat (NULLP));
22349845Smarcel  printf ("\"a\" = \"%s\"\n", concat ("a", NULLP));
22430994Sphk  printf ("\"ab\" = \"%s\"\n", concat ("a", "b", NULLP));
2259313Ssos  printf ("\"abc\" = \"%s\"\n", concat ("a", "b", "c", NULLP));
2269313Ssos  printf ("\"abcd\" = \"%s\"\n", concat ("ab", "cd", NULLP));
2279313Ssos  printf ("\"abcde\" = \"%s\"\n", concat ("ab", "c", "de", NULLP));
22830994Sphk  printf ("\"abcdef\" = \"%s\"\n", concat ("", "a", "", "bcd", "ef", NULLP));
2299313Ssos  return 0;
2309313Ssos}
2319313Ssos
23249845Smarcel#endif
23330994Sphk