1 1.1 mrg /* Concatenate variable number of strings. 2 1.1.1.11 mrg Copyright (C) 1991-2024 Free Software Foundation, Inc. 3 1.1 mrg Written by Fred Fish @ Cygnus Support 4 1.1 mrg 5 1.1 mrg This file is part of the libiberty library. 6 1.1 mrg Libiberty is free software; you can redistribute it and/or 7 1.1 mrg modify it under the terms of the GNU Library General Public 8 1.1 mrg License as published by the Free Software Foundation; either 9 1.1 mrg version 2 of the License, or (at your option) any later version. 10 1.1 mrg 11 1.1 mrg Libiberty is distributed in the hope that it will be useful, 12 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 1.1 mrg Library General Public License for more details. 15 1.1 mrg 16 1.1 mrg You should have received a copy of the GNU Library General Public 17 1.1 mrg License along with libiberty; see the file COPYING.LIB. If 18 1.1 mrg not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 19 1.1 mrg Boston, MA 02110-1301, USA. */ 20 1.1 mrg 21 1.1 mrg 22 1.1 mrg /* 23 1.1 mrg 24 1.1.1.2 mrg @deftypefn Extension char* concat (const char *@var{s1}, const char *@var{s2}, @ 25 1.1.1.2 mrg @dots{}, @code{NULL}) 26 1.1 mrg 27 1.1 mrg Concatenate zero or more of strings and return the result in freshly 28 1.1.1.3 mrg @code{xmalloc}ed memory. The argument list is terminated by the first 29 1.1.1.3 mrg @code{NULL} pointer encountered. Pointers to empty strings are ignored. 30 1.1 mrg 31 1.1 mrg @end deftypefn 32 1.1 mrg 33 1.1 mrg */ 34 1.1 mrg 35 1.1 mrg 36 1.1 mrg #ifdef HAVE_CONFIG_H 37 1.1 mrg #include "config.h" 38 1.1 mrg #endif 39 1.1 mrg #include "ansidecl.h" 40 1.1 mrg #include "libiberty.h" 41 1.1 mrg #include <sys/types.h> /* size_t */ 42 1.1 mrg 43 1.1 mrg #include <stdarg.h> 44 1.1 mrg 45 1.1 mrg # if HAVE_STRING_H 46 1.1 mrg # include <string.h> 47 1.1 mrg # else 48 1.1 mrg # if HAVE_STRINGS_H 49 1.1 mrg # include <strings.h> 50 1.1 mrg # endif 51 1.1 mrg # endif 52 1.1 mrg 53 1.1 mrg #if HAVE_STDLIB_H 54 1.1 mrg #include <stdlib.h> 55 1.1 mrg #endif 56 1.1 mrg 57 1.1 mrg static inline unsigned long vconcat_length (const char *, va_list); 58 1.1 mrg static inline unsigned long 59 1.1 mrg vconcat_length (const char *first, va_list args) 60 1.1 mrg { 61 1.1 mrg unsigned long length = 0; 62 1.1 mrg const char *arg; 63 1.1 mrg 64 1.1 mrg for (arg = first; arg ; arg = va_arg (args, const char *)) 65 1.1 mrg length += strlen (arg); 66 1.1 mrg 67 1.1 mrg return length; 68 1.1 mrg } 69 1.1 mrg 70 1.1 mrg static inline char * 71 1.1 mrg vconcat_copy (char *dst, const char *first, va_list args) 72 1.1 mrg { 73 1.1 mrg char *end = dst; 74 1.1 mrg const char *arg; 75 1.1 mrg 76 1.1 mrg for (arg = first; arg ; arg = va_arg (args, const char *)) 77 1.1 mrg { 78 1.1 mrg unsigned long length = strlen (arg); 79 1.1 mrg memcpy (end, arg, length); 80 1.1 mrg end += length; 81 1.1 mrg } 82 1.1 mrg *end = '\000'; 83 1.1 mrg 84 1.1 mrg return dst; 85 1.1 mrg } 86 1.1 mrg 87 1.1 mrg /* @undocumented concat_length */ 88 1.1 mrg 89 1.1 mrg unsigned long 90 1.1 mrg concat_length (const char *first, ...) 91 1.1 mrg { 92 1.1 mrg unsigned long length; 93 1.1.1.3 mrg va_list args; 94 1.1 mrg 95 1.1.1.3 mrg va_start (args, first); 96 1.1 mrg length = vconcat_length (first, args); 97 1.1.1.3 mrg va_end (args); 98 1.1 mrg 99 1.1 mrg return length; 100 1.1 mrg } 101 1.1 mrg 102 1.1 mrg /* @undocumented concat_copy */ 103 1.1 mrg 104 1.1 mrg char * 105 1.1 mrg concat_copy (char *dst, const char *first, ...) 106 1.1 mrg { 107 1.1 mrg char *save_dst; 108 1.1.1.3 mrg va_list args; 109 1.1 mrg 110 1.1.1.3 mrg va_start (args, first); 111 1.1 mrg vconcat_copy (dst, first, args); 112 1.1 mrg save_dst = dst; /* With K&R C, dst goes out of scope here. */ 113 1.1.1.3 mrg va_end (args); 114 1.1 mrg 115 1.1 mrg return save_dst; 116 1.1 mrg } 117 1.1 mrg 118 1.1 mrg #ifdef __cplusplus 119 1.1 mrg extern "C" { 120 1.1 mrg #endif /* __cplusplus */ 121 1.1 mrg char *libiberty_concat_ptr; 122 1.1 mrg #ifdef __cplusplus 123 1.1 mrg } 124 1.1 mrg #endif /* __cplusplus */ 125 1.1 mrg 126 1.1 mrg /* @undocumented concat_copy2 */ 127 1.1 mrg 128 1.1 mrg char * 129 1.1 mrg concat_copy2 (const char *first, ...) 130 1.1 mrg { 131 1.1.1.3 mrg va_list args; 132 1.1.1.3 mrg va_start (args, first); 133 1.1 mrg vconcat_copy (libiberty_concat_ptr, first, args); 134 1.1.1.3 mrg va_end (args); 135 1.1 mrg 136 1.1 mrg return libiberty_concat_ptr; 137 1.1 mrg } 138 1.1 mrg 139 1.1 mrg char * 140 1.1 mrg concat (const char *first, ...) 141 1.1 mrg { 142 1.1 mrg char *newstr; 143 1.1.1.3 mrg va_list args; 144 1.1 mrg 145 1.1 mrg /* First compute the size of the result and get sufficient memory. */ 146 1.1.1.3 mrg va_start (args, first); 147 1.1 mrg newstr = XNEWVEC (char, vconcat_length (first, args) + 1); 148 1.1.1.3 mrg va_end (args); 149 1.1 mrg 150 1.1 mrg /* Now copy the individual pieces to the result string. */ 151 1.1.1.3 mrg va_start (args, first); 152 1.1 mrg vconcat_copy (newstr, first, args); 153 1.1.1.3 mrg va_end (args); 154 1.1 mrg 155 1.1 mrg return newstr; 156 1.1 mrg } 157 1.1 mrg 158 1.1 mrg /* 159 1.1 mrg 160 1.1.1.2 mrg @deftypefn Extension char* reconcat (char *@var{optr}, const char *@var{s1}, @ 161 1.1.1.2 mrg @dots{}, @code{NULL}) 162 1.1 mrg 163 1.1 mrg Same as @code{concat}, except that if @var{optr} is not @code{NULL} it 164 1.1 mrg is freed after the string is created. This is intended to be useful 165 1.1 mrg when you're extending an existing string or building up a string in a 166 1.1 mrg loop: 167 1.1 mrg 168 1.1 mrg @example 169 1.1 mrg str = reconcat (str, "pre-", str, NULL); 170 1.1 mrg @end example 171 1.1 mrg 172 1.1 mrg @end deftypefn 173 1.1 mrg 174 1.1 mrg */ 175 1.1 mrg 176 1.1 mrg char * 177 1.1 mrg reconcat (char *optr, const char *first, ...) 178 1.1 mrg { 179 1.1 mrg char *newstr; 180 1.1.1.3 mrg va_list args; 181 1.1 mrg 182 1.1 mrg /* First compute the size of the result and get sufficient memory. */ 183 1.1.1.3 mrg va_start (args, first); 184 1.1 mrg newstr = XNEWVEC (char, vconcat_length (first, args) + 1); 185 1.1.1.3 mrg va_end (args); 186 1.1 mrg 187 1.1 mrg /* Now copy the individual pieces to the result string. */ 188 1.1.1.3 mrg va_start (args, first); 189 1.1 mrg vconcat_copy (newstr, first, args); 190 1.1 mrg if (optr) /* Done before VA_CLOSE so optr stays in scope for K&R C. */ 191 1.1 mrg free (optr); 192 1.1.1.3 mrg va_end (args); 193 1.1 mrg 194 1.1 mrg return newstr; 195 1.1 mrg } 196 1.1 mrg 197 1.1 mrg #ifdef MAIN 198 1.1 mrg #define NULLP (char *)0 199 1.1 mrg 200 1.1 mrg /* Simple little test driver. */ 201 1.1 mrg 202 1.1 mrg #include <stdio.h> 203 1.1 mrg 204 1.1 mrg int 205 1.1 mrg main (void) 206 1.1 mrg { 207 1.1 mrg printf ("\"\" = \"%s\"\n", concat (NULLP)); 208 1.1 mrg printf ("\"a\" = \"%s\"\n", concat ("a", NULLP)); 209 1.1 mrg printf ("\"ab\" = \"%s\"\n", concat ("a", "b", NULLP)); 210 1.1 mrg printf ("\"abc\" = \"%s\"\n", concat ("a", "b", "c", NULLP)); 211 1.1 mrg printf ("\"abcd\" = \"%s\"\n", concat ("ab", "cd", NULLP)); 212 1.1 mrg printf ("\"abcde\" = \"%s\"\n", concat ("ab", "c", "de", NULLP)); 213 1.1 mrg printf ("\"abcdef\" = \"%s\"\n", concat ("", "a", "", "bcd", "ef", NULLP)); 214 1.1 mrg return 0; 215 1.1 mrg } 216 1.1 mrg 217 1.1 mrg #endif 218