100bf4279Sespie /* Concatenate variable number of strings.
29588ddcfSespie Copyright (C) 1991, 1994, 2001 Free Software Foundation, Inc.
300bf4279Sespie Written by Fred Fish @ Cygnus Support
400bf4279Sespie
500bf4279Sespie This file is part of the libiberty library.
600bf4279Sespie Libiberty is free software; you can redistribute it and/or
700bf4279Sespie modify it under the terms of the GNU Library General Public
800bf4279Sespie License as published by the Free Software Foundation; either
900bf4279Sespie version 2 of the License, or (at your option) any later version.
1000bf4279Sespie
1100bf4279Sespie Libiberty is distributed in the hope that it will be useful,
1200bf4279Sespie but WITHOUT ANY WARRANTY; without even the implied warranty of
1300bf4279Sespie MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1400bf4279Sespie Library General Public License for more details.
1500bf4279Sespie
1600bf4279Sespie You should have received a copy of the GNU Library General Public
1700bf4279Sespie License along with libiberty; see the file COPYING.LIB. If
18*20fce977Smiod not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19*20fce977Smiod Boston, MA 02110-1301, USA. */
2000bf4279Sespie
2100bf4279Sespie
2200bf4279Sespie /*
2300bf4279Sespie
249588ddcfSespie @deftypefn Extension char* concat (const char *@var{s1}, const char *@var{s2}, @dots{}, @code{NULL})
2500bf4279Sespie
269588ddcfSespie Concatenate zero or more of strings and return the result in freshly
279588ddcfSespie @code{xmalloc}ed memory. Returns @code{NULL} if insufficient memory is
289588ddcfSespie available. The argument list is terminated by the first @code{NULL}
299588ddcfSespie pointer encountered. Pointers to empty strings are ignored.
3000bf4279Sespie
319588ddcfSespie @end deftypefn
3200bf4279Sespie
3300bf4279Sespie NOTES
3400bf4279Sespie
3500bf4279Sespie This function uses xmalloc() which is expected to be a front end
3600bf4279Sespie function to malloc() that deals with low memory situations. In
3700bf4279Sespie typical use, if malloc() returns NULL then xmalloc() diverts to an
3800bf4279Sespie error handler routine which never returns, and thus xmalloc will
3900bf4279Sespie never return a NULL pointer. If the client application wishes to
4000bf4279Sespie deal with low memory situations itself, it should supply an xmalloc
4100bf4279Sespie that just directly invokes malloc and blindly returns whatever
4200bf4279Sespie malloc returns.
439588ddcfSespie
4400bf4279Sespie */
4500bf4279Sespie
4600bf4279Sespie
479588ddcfSespie #ifdef HAVE_CONFIG_H
489588ddcfSespie #include "config.h"
499588ddcfSespie #endif
5000bf4279Sespie #include "ansidecl.h"
5100bf4279Sespie #include "libiberty.h"
529588ddcfSespie #include <sys/types.h> /* size_t */
5300bf4279Sespie
5400bf4279Sespie #include <stdarg.h>
5500bf4279Sespie
569588ddcfSespie # if HAVE_STRING_H
579588ddcfSespie # include <string.h>
5800bf4279Sespie # else
599588ddcfSespie # if HAVE_STRINGS_H
609588ddcfSespie # include <strings.h>
619588ddcfSespie # endif
6200bf4279Sespie # endif
6300bf4279Sespie
649588ddcfSespie #if HAVE_STDLIB_H
659588ddcfSespie #include <stdlib.h>
6600bf4279Sespie #endif
679588ddcfSespie
68*20fce977Smiod static inline unsigned long vconcat_length (const char *, va_list);
699588ddcfSespie static inline unsigned long
vconcat_length(const char * first,va_list args)70*20fce977Smiod vconcat_length (const char *first, va_list args)
7100bf4279Sespie {
729588ddcfSespie unsigned long length = 0;
739588ddcfSespie const char *arg;
749588ddcfSespie
759588ddcfSespie for (arg = first; arg ; arg = va_arg (args, const char *))
7600bf4279Sespie length += strlen (arg);
7700bf4279Sespie
789588ddcfSespie return length;
799588ddcfSespie }
8000bf4279Sespie
819588ddcfSespie static inline char *
vconcat_copy(char * dst,const char * first,va_list args)82*20fce977Smiod vconcat_copy (char *dst, const char *first, va_list args)
8300bf4279Sespie {
849588ddcfSespie char *end = dst;
859588ddcfSespie const char *arg;
869588ddcfSespie
879588ddcfSespie for (arg = first; arg ; arg = va_arg (args, const char *))
8800bf4279Sespie {
899588ddcfSespie unsigned long length = strlen (arg);
909588ddcfSespie memcpy (end, arg, length);
919588ddcfSespie end += length;
9200bf4279Sespie }
9300bf4279Sespie *end = '\000';
949588ddcfSespie
959588ddcfSespie return dst;
9600bf4279Sespie }
9700bf4279Sespie
989588ddcfSespie /* @undocumented concat_length */
999588ddcfSespie
1009588ddcfSespie unsigned long
concat_length(const char * first,...)101*20fce977Smiod concat_length (const char *first, ...)
1029588ddcfSespie {
1039588ddcfSespie unsigned long length;
1049588ddcfSespie
1059588ddcfSespie VA_OPEN (args, first);
1069588ddcfSespie VA_FIXEDARG (args, const char *, first);
1079588ddcfSespie length = vconcat_length (first, args);
1089588ddcfSespie VA_CLOSE (args);
1099588ddcfSespie
1109588ddcfSespie return length;
1119588ddcfSespie }
1129588ddcfSespie
1139588ddcfSespie /* @undocumented concat_copy */
1149588ddcfSespie
1159588ddcfSespie char *
concat_copy(char * dst,const char * first,...)116*20fce977Smiod concat_copy (char *dst, const char *first, ...)
1179588ddcfSespie {
1189588ddcfSespie char *save_dst;
1199588ddcfSespie
1209588ddcfSespie VA_OPEN (args, first);
1219588ddcfSespie VA_FIXEDARG (args, char *, dst);
1229588ddcfSespie VA_FIXEDARG (args, const char *, first);
1239588ddcfSespie vconcat_copy (dst, first, args);
1249588ddcfSespie save_dst = dst; /* With K&R C, dst goes out of scope here. */
1259588ddcfSespie VA_CLOSE (args);
1269588ddcfSespie
1279588ddcfSespie return save_dst;
1289588ddcfSespie }
1299588ddcfSespie
130*20fce977Smiod #ifdef __cplusplus
131*20fce977Smiod extern "C" {
132*20fce977Smiod #endif /* __cplusplus */
1339588ddcfSespie char *libiberty_concat_ptr;
134*20fce977Smiod #ifdef __cplusplus
135*20fce977Smiod }
136*20fce977Smiod #endif /* __cplusplus */
1379588ddcfSespie
1389588ddcfSespie /* @undocumented concat_copy2 */
1399588ddcfSespie
1409588ddcfSespie char *
concat_copy2(const char * first,...)141*20fce977Smiod concat_copy2 (const char *first, ...)
1429588ddcfSespie {
1439588ddcfSespie VA_OPEN (args, first);
1449588ddcfSespie VA_FIXEDARG (args, const char *, first);
1459588ddcfSespie vconcat_copy (libiberty_concat_ptr, first, args);
1469588ddcfSespie VA_CLOSE (args);
1479588ddcfSespie
1489588ddcfSespie return libiberty_concat_ptr;
1499588ddcfSespie }
1509588ddcfSespie
1519588ddcfSespie char *
concat(const char * first,...)152*20fce977Smiod concat (const char *first, ...)
1539588ddcfSespie {
1549588ddcfSespie char *newstr;
1559588ddcfSespie
1569588ddcfSespie /* First compute the size of the result and get sufficient memory. */
1579588ddcfSespie VA_OPEN (args, first);
1589588ddcfSespie VA_FIXEDARG (args, const char *, first);
159*20fce977Smiod newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
1609588ddcfSespie VA_CLOSE (args);
1619588ddcfSespie
1629588ddcfSespie /* Now copy the individual pieces to the result string. */
1639588ddcfSespie VA_OPEN (args, first);
1649588ddcfSespie VA_FIXEDARG (args, const char *, first);
1659588ddcfSespie vconcat_copy (newstr, first, args);
1669588ddcfSespie VA_CLOSE (args);
1679588ddcfSespie
1689588ddcfSespie return newstr;
1699588ddcfSespie }
1709588ddcfSespie
1719588ddcfSespie /*
1729588ddcfSespie
1739588ddcfSespie @deftypefn Extension char* reconcat (char *@var{optr}, const char *@var{s1}, @dots{}, @code{NULL})
1749588ddcfSespie
1759588ddcfSespie Same as @code{concat}, except that if @var{optr} is not @code{NULL} it
1769588ddcfSespie is freed after the string is created. This is intended to be useful
1779588ddcfSespie when you're extending an existing string or building up a string in a
1789588ddcfSespie loop:
1799588ddcfSespie
1809588ddcfSespie @example
1819588ddcfSespie str = reconcat (str, "pre-", str, NULL);
1829588ddcfSespie @end example
1839588ddcfSespie
1849588ddcfSespie @end deftypefn
1859588ddcfSespie
1869588ddcfSespie */
1879588ddcfSespie
1889588ddcfSespie char *
reconcat(char * optr,const char * first,...)189*20fce977Smiod reconcat (char *optr, const char *first, ...)
1909588ddcfSespie {
1919588ddcfSespie char *newstr;
1929588ddcfSespie
1939588ddcfSespie /* First compute the size of the result and get sufficient memory. */
1949588ddcfSespie VA_OPEN (args, first);
1959588ddcfSespie VA_FIXEDARG (args, char *, optr);
1969588ddcfSespie VA_FIXEDARG (args, const char *, first);
197*20fce977Smiod newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
1989588ddcfSespie VA_CLOSE (args);
1999588ddcfSespie
2009588ddcfSespie /* Now copy the individual pieces to the result string. */
2019588ddcfSespie VA_OPEN (args, first);
2029588ddcfSespie VA_FIXEDARG (args, char *, optr);
2039588ddcfSespie VA_FIXEDARG (args, const char *, first);
2049588ddcfSespie vconcat_copy (newstr, first, args);
2059588ddcfSespie if (optr) /* Done before VA_CLOSE so optr stays in scope for K&R C. */
2069588ddcfSespie free (optr);
2079588ddcfSespie VA_CLOSE (args);
2089588ddcfSespie
2099588ddcfSespie return newstr;
21000bf4279Sespie }
21100bf4279Sespie
21200bf4279Sespie #ifdef MAIN
2139588ddcfSespie #define NULLP (char *)0
21400bf4279Sespie
21500bf4279Sespie /* Simple little test driver. */
21600bf4279Sespie
21700bf4279Sespie #include <stdio.h>
21800bf4279Sespie
21900bf4279Sespie int
main(void)220*20fce977Smiod main (void)
22100bf4279Sespie {
22200bf4279Sespie printf ("\"\" = \"%s\"\n", concat (NULLP));
22300bf4279Sespie printf ("\"a\" = \"%s\"\n", concat ("a", NULLP));
22400bf4279Sespie printf ("\"ab\" = \"%s\"\n", concat ("a", "b", NULLP));
22500bf4279Sespie printf ("\"abc\" = \"%s\"\n", concat ("a", "b", "c", NULLP));
22600bf4279Sespie printf ("\"abcd\" = \"%s\"\n", concat ("ab", "cd", NULLP));
22700bf4279Sespie printf ("\"abcde\" = \"%s\"\n", concat ("ab", "c", "de", NULLP));
22800bf4279Sespie printf ("\"abcdef\" = \"%s\"\n", concat ("", "a", "", "bcd", "ef", NULLP));
22900bf4279Sespie return 0;
23000bf4279Sespie }
23100bf4279Sespie
23200bf4279Sespie #endif
233