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