Back to index

cell-binutils  2.17cvs20070401
concat.c
Go to the documentation of this file.
00001 /* Concatenate variable number of strings.
00002    Copyright (C) 1991, 1994, 2001 Free Software Foundation, Inc.
00003    Written by Fred Fish @ Cygnus Support
00004 
00005 This file is part of the libiberty library.
00006 Libiberty is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU Library General Public
00008 License as published by the Free Software Foundation; either
00009 version 2 of the License, or (at your option) any later version.
00010 
00011 Libiberty is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 Library General Public License for more details.
00015 
00016 You should have received a copy of the GNU Library General Public
00017 License along with libiberty; see the file COPYING.LIB.  If
00018 not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
00019 Boston, MA 02110-1301, USA.  */
00020 
00021 
00022 /*
00023 
00024 @deftypefn Extension char* concat (const char *@var{s1}, const char *@var{s2}, @dots{}, @code{NULL})
00025 
00026 Concatenate zero or more of strings and return the result in freshly
00027 @code{xmalloc}ed memory.  Returns @code{NULL} if insufficient memory is
00028 available.  The argument list is terminated by the first @code{NULL}
00029 pointer encountered.  Pointers to empty strings are ignored.
00030 
00031 @end deftypefn
00032 
00033 NOTES
00034 
00035        This function uses xmalloc() which is expected to be a front end
00036        function to malloc() that deals with low memory situations.  In
00037        typical use, if malloc() returns NULL then xmalloc() diverts to an
00038        error handler routine which never returns, and thus xmalloc will
00039        never return a NULL pointer.  If the client application wishes to
00040        deal with low memory situations itself, it should supply an xmalloc
00041        that just directly invokes malloc and blindly returns whatever
00042        malloc returns.
00043 
00044 */
00045 
00046 
00047 #ifdef HAVE_CONFIG_H
00048 #include "config.h"
00049 #endif
00050 #include "ansidecl.h"
00051 #include "libiberty.h"
00052 #include <sys/types.h>             /* size_t */
00053 
00054 #include <stdarg.h>
00055 
00056 # if HAVE_STRING_H
00057 #  include <string.h>
00058 # else
00059 #  if HAVE_STRINGS_H
00060 #   include <strings.h>
00061 #  endif
00062 # endif
00063 
00064 #if HAVE_STDLIB_H
00065 #include <stdlib.h>
00066 #endif
00067 
00068 static inline unsigned long vconcat_length (const char *, va_list);
00069 static inline unsigned long
00070 vconcat_length (const char *first, va_list args)
00071 {
00072   unsigned long length = 0;
00073   const char *arg;
00074 
00075   for (arg = first; arg ; arg = va_arg (args, const char *))
00076     length += strlen (arg);
00077 
00078   return length;
00079 }
00080 
00081 static inline char *
00082 vconcat_copy (char *dst, const char *first, va_list args)
00083 {
00084   char *end = dst;
00085   const char *arg;
00086 
00087   for (arg = first; arg ; arg = va_arg (args, const char *))
00088     {
00089       unsigned long length = strlen (arg);
00090       memcpy (end, arg, length);
00091       end += length;
00092     }
00093   *end = '\000';
00094 
00095   return dst;
00096 }
00097 
00098 /* @undocumented concat_length */
00099 
00100 unsigned long
00101 concat_length (const char *first, ...)
00102 {
00103   unsigned long length;
00104 
00105   VA_OPEN (args, first);
00106   VA_FIXEDARG (args, const char *, first);
00107   length = vconcat_length (first, args);
00108   VA_CLOSE (args);
00109 
00110   return length;
00111 }
00112 
00113 /* @undocumented concat_copy */
00114 
00115 char *
00116 concat_copy (char *dst, const char *first, ...)
00117 {
00118   char *save_dst;
00119 
00120   VA_OPEN (args, first);
00121   VA_FIXEDARG (args, char *, dst);
00122   VA_FIXEDARG (args, const char *, first);
00123   vconcat_copy (dst, first, args);
00124   save_dst = dst; /* With K&R C, dst goes out of scope here.  */
00125   VA_CLOSE (args);
00126 
00127   return save_dst;
00128 }
00129 
00130 #ifdef __cplusplus
00131 extern "C" {
00132 #endif /* __cplusplus */
00133 char *libiberty_concat_ptr;
00134 #ifdef __cplusplus
00135 }
00136 #endif /* __cplusplus */
00137 
00138 /* @undocumented concat_copy2 */
00139 
00140 char *
00141 concat_copy2 (const char *first, ...)
00142 {
00143   VA_OPEN (args, first);
00144   VA_FIXEDARG (args, const char *, first);
00145   vconcat_copy (libiberty_concat_ptr, first, args);
00146   VA_CLOSE (args);
00147 
00148   return libiberty_concat_ptr;
00149 }
00150 
00151 char *
00152 concat (const char *first, ...)
00153 {
00154   char *newstr;
00155 
00156   /* First compute the size of the result and get sufficient memory.  */
00157   VA_OPEN (args, first);
00158   VA_FIXEDARG (args, const char *, first);
00159   newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
00160   VA_CLOSE (args);
00161 
00162   /* Now copy the individual pieces to the result string. */
00163   VA_OPEN (args, first);
00164   VA_FIXEDARG (args, const char *, first);
00165   vconcat_copy (newstr, first, args);
00166   VA_CLOSE (args);
00167 
00168   return newstr;
00169 }
00170 
00171 /*
00172 
00173 @deftypefn Extension char* reconcat (char *@var{optr}, const char *@var{s1}, @dots{}, @code{NULL})
00174 
00175 Same as @code{concat}, except that if @var{optr} is not @code{NULL} it
00176 is freed after the string is created.  This is intended to be useful
00177 when you're extending an existing string or building up a string in a
00178 loop:
00179 
00180 @example
00181   str = reconcat (str, "pre-", str, NULL);
00182 @end example
00183 
00184 @end deftypefn
00185 
00186 */
00187 
00188 char *
00189 reconcat (char *optr, const char *first, ...)
00190 {
00191   char *newstr;
00192 
00193   /* First compute the size of the result and get sufficient memory.  */
00194   VA_OPEN (args, first);
00195   VA_FIXEDARG (args, char *, optr);
00196   VA_FIXEDARG (args, const char *, first);
00197   newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
00198   VA_CLOSE (args);
00199 
00200   /* Now copy the individual pieces to the result string. */
00201   VA_OPEN (args, first);
00202   VA_FIXEDARG (args, char *, optr);
00203   VA_FIXEDARG (args, const char *, first);
00204   vconcat_copy (newstr, first, args);
00205   if (optr) /* Done before VA_CLOSE so optr stays in scope for K&R C.  */
00206     free (optr);
00207   VA_CLOSE (args);
00208 
00209   return newstr;
00210 }
00211 
00212 #ifdef MAIN
00213 #define NULLP (char *)0
00214 
00215 /* Simple little test driver. */
00216 
00217 #include <stdio.h>
00218 
00219 int
00220 main (void)
00221 {
00222   printf ("\"\" = \"%s\"\n", concat (NULLP));
00223   printf ("\"a\" = \"%s\"\n", concat ("a", NULLP));
00224   printf ("\"ab\" = \"%s\"\n", concat ("a", "b", NULLP));
00225   printf ("\"abc\" = \"%s\"\n", concat ("a", "b", "c", NULLP));
00226   printf ("\"abcd\" = \"%s\"\n", concat ("ab", "cd", NULLP));
00227   printf ("\"abcde\" = \"%s\"\n", concat ("ab", "c", "de", NULLP));
00228   printf ("\"abcdef\" = \"%s\"\n", concat ("", "a", "", "bcd", "ef", NULLP));
00229   return 0;
00230 }
00231 
00232 #endif