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