concat.c revision 1.1.1.11 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