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