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