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