concat.c revision 89857
1/* Concatenate variable number of strings.
2   Copyright (C) 1991, 1994, 2001 Free Software Foundation, Inc.
3   Written by Fred Fish @ Cygnus Support
4
5This file is part of the libiberty library.
6Libiberty is free software; you can redistribute it and/or
7modify it under the terms of the GNU Library General Public
8License as published by the Free Software Foundation; either
9version 2 of the License, or (at your option) any later version.
10
11Libiberty is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14Library General Public License for more details.
15
16You should have received a copy of the GNU Library General Public
17License along with libiberty; see the file COPYING.LIB.  If
18not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, 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
26Concatenate zero or more of strings and return the result in freshly
27@code{xmalloc}ed memory.  Returns @code{NULL} if insufficient memory is
28available.  The argument list is terminated by the first @code{NULL}
29pointer encountered.  Pointers to empty strings are ignored.
30
31@end deftypefn
32
33NOTES
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
72static inline unsigned long vconcat_length PARAMS ((const char *, va_list));
73static inline unsigned long
74vconcat_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
87static inline char *vconcat_copy PARAMS ((char *, const char *, va_list));
88static inline char *
89vconcat_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
110unsigned long
111concat_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
125char *
126concat_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
140char *libiberty_concat_ptr;
141
142/* @undocumented concat_copy2 */
143
144char *
145concat_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
155char *
156concat 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
179Same as @code{concat}, except that if @var{optr} is not @code{NULL} it
180is freed after the string is created.  This is intended to be useful
181when you're extending an existing string or building up a string in a
182loop:
183
184@example
185  str = reconcat (str, "pre-", str, NULL);
186@end example
187
188@end deftypefn
189
190*/
191
192char *
193reconcat 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
223int
224main ()
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