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