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