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