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