xref: /openbsd/gnu/lib/libiberty/src/concat.c (revision 20fce977)
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