concat.c revision 1.1.1.2 1 1.1 mrg /* Concatenate variable number of strings.
2 1.1.1.2 mrg Copyright (C) 1991, 1994, 2001, 2011 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 mrg @code{xmalloc}ed memory. Returns @code{NULL} if insufficient memory is
29 1.1 mrg available. The argument list is terminated by the first @code{NULL}
30 1.1 mrg pointer encountered. Pointers to empty strings are ignored.
31 1.1 mrg
32 1.1 mrg @end deftypefn
33 1.1 mrg
34 1.1 mrg NOTES
35 1.1 mrg
36 1.1 mrg This function uses xmalloc() which is expected to be a front end
37 1.1 mrg function to malloc() that deals with low memory situations. In
38 1.1 mrg typical use, if malloc() returns NULL then xmalloc() diverts to an
39 1.1 mrg error handler routine which never returns, and thus xmalloc will
40 1.1 mrg never return a NULL pointer. If the client application wishes to
41 1.1 mrg deal with low memory situations itself, it should supply an xmalloc
42 1.1 mrg that just directly invokes malloc and blindly returns whatever
43 1.1 mrg malloc returns.
44 1.1 mrg
45 1.1 mrg */
46 1.1 mrg
47 1.1 mrg
48 1.1 mrg #ifdef HAVE_CONFIG_H
49 1.1 mrg #include "config.h"
50 1.1 mrg #endif
51 1.1 mrg #include "ansidecl.h"
52 1.1 mrg #include "libiberty.h"
53 1.1 mrg #include <sys/types.h> /* size_t */
54 1.1 mrg
55 1.1 mrg #include <stdarg.h>
56 1.1 mrg
57 1.1 mrg # if HAVE_STRING_H
58 1.1 mrg # include <string.h>
59 1.1 mrg # else
60 1.1 mrg # if HAVE_STRINGS_H
61 1.1 mrg # include <strings.h>
62 1.1 mrg # endif
63 1.1 mrg # endif
64 1.1 mrg
65 1.1 mrg #if HAVE_STDLIB_H
66 1.1 mrg #include <stdlib.h>
67 1.1 mrg #endif
68 1.1 mrg
69 1.1 mrg static inline unsigned long vconcat_length (const char *, va_list);
70 1.1 mrg static inline unsigned long
71 1.1 mrg vconcat_length (const char *first, va_list args)
72 1.1 mrg {
73 1.1 mrg unsigned long length = 0;
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 length += strlen (arg);
78 1.1 mrg
79 1.1 mrg return length;
80 1.1 mrg }
81 1.1 mrg
82 1.1 mrg static inline char *
83 1.1 mrg vconcat_copy (char *dst, const char *first, va_list args)
84 1.1 mrg {
85 1.1 mrg char *end = dst;
86 1.1 mrg const char *arg;
87 1.1 mrg
88 1.1 mrg for (arg = first; arg ; arg = va_arg (args, const char *))
89 1.1 mrg {
90 1.1 mrg unsigned long length = strlen (arg);
91 1.1 mrg memcpy (end, arg, length);
92 1.1 mrg end += length;
93 1.1 mrg }
94 1.1 mrg *end = '\000';
95 1.1 mrg
96 1.1 mrg return dst;
97 1.1 mrg }
98 1.1 mrg
99 1.1 mrg /* @undocumented concat_length */
100 1.1 mrg
101 1.1 mrg unsigned long
102 1.1 mrg concat_length (const char *first, ...)
103 1.1 mrg {
104 1.1 mrg unsigned long length;
105 1.1 mrg
106 1.1 mrg VA_OPEN (args, first);
107 1.1 mrg VA_FIXEDARG (args, const char *, first);
108 1.1 mrg length = vconcat_length (first, args);
109 1.1 mrg VA_CLOSE (args);
110 1.1 mrg
111 1.1 mrg return length;
112 1.1 mrg }
113 1.1 mrg
114 1.1 mrg /* @undocumented concat_copy */
115 1.1 mrg
116 1.1 mrg char *
117 1.1 mrg concat_copy (char *dst, const char *first, ...)
118 1.1 mrg {
119 1.1 mrg char *save_dst;
120 1.1 mrg
121 1.1 mrg VA_OPEN (args, first);
122 1.1 mrg VA_FIXEDARG (args, char *, dst);
123 1.1 mrg VA_FIXEDARG (args, const char *, first);
124 1.1 mrg vconcat_copy (dst, first, args);
125 1.1 mrg save_dst = dst; /* With K&R C, dst goes out of scope here. */
126 1.1 mrg VA_CLOSE (args);
127 1.1 mrg
128 1.1 mrg return save_dst;
129 1.1 mrg }
130 1.1 mrg
131 1.1 mrg #ifdef __cplusplus
132 1.1 mrg extern "C" {
133 1.1 mrg #endif /* __cplusplus */
134 1.1 mrg char *libiberty_concat_ptr;
135 1.1 mrg #ifdef __cplusplus
136 1.1 mrg }
137 1.1 mrg #endif /* __cplusplus */
138 1.1 mrg
139 1.1 mrg /* @undocumented concat_copy2 */
140 1.1 mrg
141 1.1 mrg char *
142 1.1 mrg concat_copy2 (const char *first, ...)
143 1.1 mrg {
144 1.1 mrg VA_OPEN (args, first);
145 1.1 mrg VA_FIXEDARG (args, const char *, first);
146 1.1 mrg vconcat_copy (libiberty_concat_ptr, first, args);
147 1.1 mrg VA_CLOSE (args);
148 1.1 mrg
149 1.1 mrg return libiberty_concat_ptr;
150 1.1 mrg }
151 1.1 mrg
152 1.1 mrg char *
153 1.1 mrg concat (const char *first, ...)
154 1.1 mrg {
155 1.1 mrg char *newstr;
156 1.1 mrg
157 1.1 mrg /* First compute the size of the result and get sufficient memory. */
158 1.1 mrg VA_OPEN (args, first);
159 1.1 mrg VA_FIXEDARG (args, const char *, first);
160 1.1 mrg newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
161 1.1 mrg VA_CLOSE (args);
162 1.1 mrg
163 1.1 mrg /* Now copy the individual pieces to the result string. */
164 1.1 mrg VA_OPEN (args, first);
165 1.1 mrg VA_FIXEDARG (args, const char *, first);
166 1.1 mrg vconcat_copy (newstr, first, args);
167 1.1 mrg VA_CLOSE (args);
168 1.1 mrg
169 1.1 mrg return newstr;
170 1.1 mrg }
171 1.1 mrg
172 1.1 mrg /*
173 1.1 mrg
174 1.1.1.2 mrg @deftypefn Extension char* reconcat (char *@var{optr}, const char *@var{s1}, @
175 1.1.1.2 mrg @dots{}, @code{NULL})
176 1.1 mrg
177 1.1 mrg Same as @code{concat}, except that if @var{optr} is not @code{NULL} it
178 1.1 mrg is freed after the string is created. This is intended to be useful
179 1.1 mrg when you're extending an existing string or building up a string in a
180 1.1 mrg loop:
181 1.1 mrg
182 1.1 mrg @example
183 1.1 mrg str = reconcat (str, "pre-", str, NULL);
184 1.1 mrg @end example
185 1.1 mrg
186 1.1 mrg @end deftypefn
187 1.1 mrg
188 1.1 mrg */
189 1.1 mrg
190 1.1 mrg char *
191 1.1 mrg reconcat (char *optr, const char *first, ...)
192 1.1 mrg {
193 1.1 mrg char *newstr;
194 1.1 mrg
195 1.1 mrg /* First compute the size of the result and get sufficient memory. */
196 1.1 mrg VA_OPEN (args, first);
197 1.1 mrg VA_FIXEDARG (args, char *, optr);
198 1.1 mrg VA_FIXEDARG (args, const char *, first);
199 1.1 mrg newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
200 1.1 mrg VA_CLOSE (args);
201 1.1 mrg
202 1.1 mrg /* Now copy the individual pieces to the result string. */
203 1.1 mrg VA_OPEN (args, first);
204 1.1 mrg VA_FIXEDARG (args, char *, optr);
205 1.1 mrg VA_FIXEDARG (args, const char *, first);
206 1.1 mrg vconcat_copy (newstr, first, args);
207 1.1 mrg if (optr) /* Done before VA_CLOSE so optr stays in scope for K&R C. */
208 1.1 mrg free (optr);
209 1.1 mrg VA_CLOSE (args);
210 1.1 mrg
211 1.1 mrg return newstr;
212 1.1 mrg }
213 1.1 mrg
214 1.1 mrg #ifdef MAIN
215 1.1 mrg #define NULLP (char *)0
216 1.1 mrg
217 1.1 mrg /* Simple little test driver. */
218 1.1 mrg
219 1.1 mrg #include <stdio.h>
220 1.1 mrg
221 1.1 mrg int
222 1.1 mrg main (void)
223 1.1 mrg {
224 1.1 mrg printf ("\"\" = \"%s\"\n", concat (NULLP));
225 1.1 mrg printf ("\"a\" = \"%s\"\n", concat ("a", NULLP));
226 1.1 mrg printf ("\"ab\" = \"%s\"\n", concat ("a", "b", NULLP));
227 1.1 mrg printf ("\"abc\" = \"%s\"\n", concat ("a", "b", "c", NULLP));
228 1.1 mrg printf ("\"abcd\" = \"%s\"\n", concat ("ab", "cd", NULLP));
229 1.1 mrg printf ("\"abcde\" = \"%s\"\n", concat ("ab", "c", "de", NULLP));
230 1.1 mrg printf ("\"abcdef\" = \"%s\"\n", concat ("", "a", "", "bcd", "ef", NULLP));
231 1.1 mrg return 0;
232 1.1 mrg }
233 1.1 mrg
234 1.1 mrg #endif
235