xref: /netbsd-src/external/gpl3/gdb/dist/libiberty/concat.c (revision 7e120ff03ede3fe64e2c8620c01465d528502ddb)
198b9484cSchristos /* Concatenate variable number of strings.
2*7e120ff0Schristos    Copyright (C) 1991-2024 Free Software Foundation, Inc.
398b9484cSchristos    Written by Fred Fish @ Cygnus Support
498b9484cSchristos 
598b9484cSchristos This file is part of the libiberty library.
698b9484cSchristos Libiberty is free software; you can redistribute it and/or
798b9484cSchristos modify it under the terms of the GNU Library General Public
898b9484cSchristos License as published by the Free Software Foundation; either
998b9484cSchristos version 2 of the License, or (at your option) any later version.
1098b9484cSchristos 
1198b9484cSchristos Libiberty is distributed in the hope that it will be useful,
1298b9484cSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of
1398b9484cSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1498b9484cSchristos Library General Public License for more details.
1598b9484cSchristos 
1698b9484cSchristos You should have received a copy of the GNU Library General Public
1798b9484cSchristos License along with libiberty; see the file COPYING.LIB.  If
1898b9484cSchristos not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
1998b9484cSchristos Boston, MA 02110-1301, USA.  */
2098b9484cSchristos 
2198b9484cSchristos 
2298b9484cSchristos /*
2398b9484cSchristos 
2498b9484cSchristos @deftypefn Extension char* concat (const char *@var{s1}, const char *@var{s2}, @
2598b9484cSchristos   @dots{}, @code{NULL})
2698b9484cSchristos 
2798b9484cSchristos Concatenate zero or more of strings and return the result in freshly
2803467a24Schristos @code{xmalloc}ed memory.  The argument list is terminated by the first
2903467a24Schristos @code{NULL} pointer encountered.  Pointers to empty strings are ignored.
3098b9484cSchristos 
3198b9484cSchristos @end deftypefn
3298b9484cSchristos 
3398b9484cSchristos */
3498b9484cSchristos 
3598b9484cSchristos 
3698b9484cSchristos #ifdef HAVE_CONFIG_H
3798b9484cSchristos #include "config.h"
3898b9484cSchristos #endif
3998b9484cSchristos #include "ansidecl.h"
4098b9484cSchristos #include "libiberty.h"
4198b9484cSchristos #include <sys/types.h>		/* size_t */
4298b9484cSchristos 
4398b9484cSchristos #include <stdarg.h>
4498b9484cSchristos 
4598b9484cSchristos # if HAVE_STRING_H
4698b9484cSchristos #  include <string.h>
4798b9484cSchristos # else
4898b9484cSchristos #  if HAVE_STRINGS_H
4998b9484cSchristos #   include <strings.h>
5098b9484cSchristos #  endif
5198b9484cSchristos # endif
5298b9484cSchristos 
5398b9484cSchristos #if HAVE_STDLIB_H
5498b9484cSchristos #include <stdlib.h>
5598b9484cSchristos #endif
5698b9484cSchristos 
5798b9484cSchristos static inline unsigned long vconcat_length (const char *, va_list);
5898b9484cSchristos static inline unsigned long
5998b9484cSchristos vconcat_length (const char *first, va_list args)
6098b9484cSchristos {
6198b9484cSchristos   unsigned long length = 0;
6298b9484cSchristos   const char *arg;
6398b9484cSchristos 
6498b9484cSchristos   for (arg = first; arg ; arg = va_arg (args, const char *))
6598b9484cSchristos     length += strlen (arg);
6698b9484cSchristos 
6798b9484cSchristos   return length;
6898b9484cSchristos }
6998b9484cSchristos 
7098b9484cSchristos static inline char *
7198b9484cSchristos vconcat_copy (char *dst, const char *first, va_list args)
7298b9484cSchristos {
7398b9484cSchristos   char *end = dst;
7498b9484cSchristos   const char *arg;
7598b9484cSchristos 
7698b9484cSchristos   for (arg = first; arg ; arg = va_arg (args, const char *))
7798b9484cSchristos     {
7898b9484cSchristos       unsigned long length = strlen (arg);
7998b9484cSchristos       memcpy (end, arg, length);
8098b9484cSchristos       end += length;
8198b9484cSchristos     }
8298b9484cSchristos   *end = '\000';
8398b9484cSchristos 
8498b9484cSchristos   return dst;
8598b9484cSchristos }
8698b9484cSchristos 
8798b9484cSchristos /* @undocumented concat_length */
8898b9484cSchristos 
8998b9484cSchristos unsigned long
9098b9484cSchristos concat_length (const char *first, ...)
9198b9484cSchristos {
9298b9484cSchristos   unsigned long length;
93837edd6bSchristos   va_list args;
9498b9484cSchristos 
95837edd6bSchristos   va_start (args, first);
9698b9484cSchristos   length = vconcat_length (first, args);
97837edd6bSchristos   va_end (args);
9898b9484cSchristos 
9998b9484cSchristos   return length;
10098b9484cSchristos }
10198b9484cSchristos 
10298b9484cSchristos /* @undocumented concat_copy */
10398b9484cSchristos 
10498b9484cSchristos char *
10598b9484cSchristos concat_copy (char *dst, const char *first, ...)
10698b9484cSchristos {
10798b9484cSchristos   char *save_dst;
108837edd6bSchristos   va_list args;
10998b9484cSchristos 
110837edd6bSchristos   va_start (args, first);
11198b9484cSchristos   vconcat_copy (dst, first, args);
11298b9484cSchristos   save_dst = dst; /* With K&R C, dst goes out of scope here.  */
113837edd6bSchristos   va_end (args);
11498b9484cSchristos 
11598b9484cSchristos   return save_dst;
11698b9484cSchristos }
11798b9484cSchristos 
11898b9484cSchristos #ifdef __cplusplus
11998b9484cSchristos extern "C" {
12098b9484cSchristos #endif /* __cplusplus */
12198b9484cSchristos char *libiberty_concat_ptr;
12298b9484cSchristos #ifdef __cplusplus
12398b9484cSchristos }
12498b9484cSchristos #endif /* __cplusplus */
12598b9484cSchristos 
12698b9484cSchristos /* @undocumented concat_copy2 */
12798b9484cSchristos 
12898b9484cSchristos char *
12998b9484cSchristos concat_copy2 (const char *first, ...)
13098b9484cSchristos {
131837edd6bSchristos   va_list args;
132837edd6bSchristos   va_start (args, first);
13398b9484cSchristos   vconcat_copy (libiberty_concat_ptr, first, args);
134837edd6bSchristos   va_end (args);
13598b9484cSchristos 
13698b9484cSchristos   return libiberty_concat_ptr;
13798b9484cSchristos }
13898b9484cSchristos 
13998b9484cSchristos char *
14098b9484cSchristos concat (const char *first, ...)
14198b9484cSchristos {
14298b9484cSchristos   char *newstr;
143837edd6bSchristos   va_list args;
14498b9484cSchristos 
14598b9484cSchristos   /* First compute the size of the result and get sufficient memory.  */
146837edd6bSchristos   va_start (args, first);
14798b9484cSchristos   newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
148837edd6bSchristos   va_end (args);
14998b9484cSchristos 
15098b9484cSchristos   /* Now copy the individual pieces to the result string. */
151837edd6bSchristos   va_start (args, first);
15298b9484cSchristos   vconcat_copy (newstr, first, args);
153837edd6bSchristos   va_end (args);
15498b9484cSchristos 
15598b9484cSchristos   return newstr;
15698b9484cSchristos }
15798b9484cSchristos 
15898b9484cSchristos /*
15998b9484cSchristos 
16098b9484cSchristos @deftypefn Extension char* reconcat (char *@var{optr}, const char *@var{s1}, @
16198b9484cSchristos   @dots{}, @code{NULL})
16298b9484cSchristos 
16398b9484cSchristos Same as @code{concat}, except that if @var{optr} is not @code{NULL} it
16498b9484cSchristos is freed after the string is created.  This is intended to be useful
16598b9484cSchristos when you're extending an existing string or building up a string in a
16698b9484cSchristos loop:
16798b9484cSchristos 
16898b9484cSchristos @example
16998b9484cSchristos   str = reconcat (str, "pre-", str, NULL);
17098b9484cSchristos @end example
17198b9484cSchristos 
17298b9484cSchristos @end deftypefn
17398b9484cSchristos 
17498b9484cSchristos */
17598b9484cSchristos 
17698b9484cSchristos char *
17798b9484cSchristos reconcat (char *optr, const char *first, ...)
17898b9484cSchristos {
17998b9484cSchristos   char *newstr;
180837edd6bSchristos   va_list args;
18198b9484cSchristos 
18298b9484cSchristos   /* First compute the size of the result and get sufficient memory.  */
183837edd6bSchristos   va_start (args, first);
18498b9484cSchristos   newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
185837edd6bSchristos   va_end (args);
18698b9484cSchristos 
18798b9484cSchristos   /* Now copy the individual pieces to the result string. */
188837edd6bSchristos   va_start (args, first);
18998b9484cSchristos   vconcat_copy (newstr, first, args);
19098b9484cSchristos   if (optr) /* Done before VA_CLOSE so optr stays in scope for K&R C.  */
19198b9484cSchristos     free (optr);
192837edd6bSchristos   va_end (args);
19398b9484cSchristos 
19498b9484cSchristos   return newstr;
19598b9484cSchristos }
19698b9484cSchristos 
19798b9484cSchristos #ifdef MAIN
19898b9484cSchristos #define NULLP (char *)0
19998b9484cSchristos 
20098b9484cSchristos /* Simple little test driver. */
20198b9484cSchristos 
20298b9484cSchristos #include <stdio.h>
20398b9484cSchristos 
20498b9484cSchristos int
20598b9484cSchristos main (void)
20698b9484cSchristos {
20798b9484cSchristos   printf ("\"\" = \"%s\"\n", concat (NULLP));
20898b9484cSchristos   printf ("\"a\" = \"%s\"\n", concat ("a", NULLP));
20998b9484cSchristos   printf ("\"ab\" = \"%s\"\n", concat ("a", "b", NULLP));
21098b9484cSchristos   printf ("\"abc\" = \"%s\"\n", concat ("a", "b", "c", NULLP));
21198b9484cSchristos   printf ("\"abcd\" = \"%s\"\n", concat ("ab", "cd", NULLP));
21298b9484cSchristos   printf ("\"abcde\" = \"%s\"\n", concat ("ab", "c", "de", NULLP));
21398b9484cSchristos   printf ("\"abcdef\" = \"%s\"\n", concat ("", "a", "", "bcd", "ef", NULLP));
21498b9484cSchristos   return 0;
21598b9484cSchristos }
21698b9484cSchristos 
21798b9484cSchristos #endif
218