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