gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / libiberty / concat.c
index 5b132c85764f896b6d51b681641a9e69db964eea..533e4a99b0d8ced71abf8d86c8e2b6f8141c1962 100644 (file)
@@ -1,5 +1,5 @@
 /* Concatenate variable number of strings.
-   Copyright (C) 1991, 1994 Free Software Foundation, Inc.
+   Copyright (C) 1991-2020 Free Software Foundation, Inc.
    Written by Fred Fish @ Cygnus Support
 
 This file is part of the libiberty library.
@@ -15,144 +15,194 @@ Library General Public License for more details.
 
 You should have received a copy of the GNU Library General Public
 License along with libiberty; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 
 /*
 
-NAME
+@deftypefn Extension char* concat (const char *@var{s1}, const char *@var{s2}, @
+  @dots{}, @code{NULL})
 
-       concat -- concatenate a variable number of strings
+Concatenate zero or more of strings and return the result in freshly
+@code{xmalloc}ed memory.  The argument list is terminated by the first
+@code{NULL} pointer encountered.  Pointers to empty strings are ignored.
 
-SYNOPSIS
+@end deftypefn
 
-       #include <varargs.h>
+*/
 
-       char *concat (s1, s2, s3, ..., NULL)
 
-DESCRIPTION
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "ansidecl.h"
+#include "libiberty.h"
+#include <sys/types.h>         /* size_t */
 
-       Concatenate a variable number of strings and return the result
-       in freshly malloc'd memory.
+#include <stdarg.h>
 
-       Returns NULL if insufficient memory is available.  The argument
-       list is terminated by the first NULL pointer encountered.  Pointers
-       to empty strings are ignored.
+# if HAVE_STRING_H
+#  include <string.h>
+# else
+#  if HAVE_STRINGS_H
+#   include <strings.h>
+#  endif
+# endif
 
-NOTES
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
 
-       This function uses xmalloc() which is expected to be a front end
-       function to malloc() that deals with low memory situations.  In
-       typical use, if malloc() returns NULL then xmalloc() diverts to an
-       error handler routine which never returns, and thus xmalloc will
-       never return a NULL pointer.  If the client application wishes to
-       deal with low memory situations itself, it should supply an xmalloc
-       that just directly invokes malloc and blindly returns whatever
-       malloc returns.
-*/
+static inline unsigned long vconcat_length (const char *, va_list);
+static inline unsigned long
+vconcat_length (const char *first, va_list args)
+{
+  unsigned long length = 0;
+  const char *arg;
 
+  for (arg = first; arg ; arg = va_arg (args, const char *))
+    length += strlen (arg);
 
-#include "ansidecl.h"
-#include "libiberty.h"
+  return length;
+}
 
-#ifdef ANSI_PROTOTYPES
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
+static inline char *
+vconcat_copy (char *dst, const char *first, va_list args)
+{
+  char *end = dst;
+  const char *arg;
 
-#ifdef __STDC__
-#include <stddef.h>
-extern size_t strlen (const char *s);
-#else
-extern int strlen ();
-#endif
+  for (arg = first; arg ; arg = va_arg (args, const char *))
+    {
+      unsigned long length = strlen (arg);
+      memcpy (end, arg, length);
+      end += length;
+    }
+  *end = '\000';
 
-#define NULLP (char *)0
+  return dst;
+}
+
+/* @undocumented concat_length */
+
+unsigned long
+concat_length (const char *first, ...)
+{
+  unsigned long length;
+  va_list args;
+
+  va_start (args, first);
+  length = vconcat_length (first, args);
+  va_end (args);
+
+  return length;
+}
+
+/* @undocumented concat_copy */
 
-/* VARARGS */
-#ifdef ANSI_PROTOTYPES
-char *
-concat (const char *first, ...)
-#else
 char *
-concat (va_alist)
-     va_dcl
-#endif
+concat_copy (char *dst, const char *first, ...)
 {
-  register int length;
-  register char *newstr;
-  register char *end;
-  register const char *arg;
+  char *save_dst;
   va_list args;
-#ifndef ANSI_PROTOTYPES
-  const char *first;
-#endif
 
-  /* First compute the size of the result and get sufficient memory. */
+  va_start (args, first);
+  vconcat_copy (dst, first, args);
+  save_dst = dst; /* With K&R C, dst goes out of scope here.  */
+  va_end (args);
+
+  return save_dst;
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+char *libiberty_concat_ptr;
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
 
-#ifdef ANSI_PROTOTYPES
+/* @undocumented concat_copy2 */
+
+char *
+concat_copy2 (const char *first, ...)
+{
+  va_list args;
   va_start (args, first);
-#else
-  va_start (args);
-  first = va_arg (args, const char *);
-#endif
+  vconcat_copy (libiberty_concat_ptr, first, args);
+  va_end (args);
 
-  if (first == NULLP)
-    length = 0;
-  else
-    {
-      length = strlen (first);
-      while ((arg = va_arg (args, const char *)) != NULLP)
-       {
-         length += strlen (arg);
-       }
-    }
-  newstr = (char *) xmalloc (length + 1);
+  return libiberty_concat_ptr;
+}
+
+char *
+concat (const char *first, ...)
+{
+  char *newstr;
+  va_list args;
+
+  /* First compute the size of the result and get sufficient memory.  */
+  va_start (args, first);
+  newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
   va_end (args);
 
   /* Now copy the individual pieces to the result string. */
+  va_start (args, first);
+  vconcat_copy (newstr, first, args);
+  va_end (args);
 
-  if (newstr != NULLP)
-    {
-#ifdef ANSI_PROTOTYPES
-      va_start (args, first);
-#else
-      va_start (args);
-      first = va_arg (args, const char *);
-#endif
-      end = newstr;
-      if (first != NULLP)
-       {
-         arg = first;
-         while (*arg)
-           {
-             *end++ = *arg++;
-           }
-         while ((arg = va_arg (args, const char *)) != NULLP)
-           {
-             while (*arg)
-               {
-                 *end++ = *arg++;
-               }
-           }
-       }
-      *end = '\000';
-      va_end (args);
-    }
+  return newstr;
+}
 
-  return (newstr);
+/*
+
+@deftypefn Extension char* reconcat (char *@var{optr}, const char *@var{s1}, @
+  @dots{}, @code{NULL})
+
+Same as @code{concat}, except that if @var{optr} is not @code{NULL} it
+is freed after the string is created.  This is intended to be useful
+when you're extending an existing string or building up a string in a
+loop:
+
+@example
+  str = reconcat (str, "pre-", str, NULL);
+@end example
+
+@end deftypefn
+
+*/
+
+char *
+reconcat (char *optr, const char *first, ...)
+{
+  char *newstr;
+  va_list args;
+
+  /* First compute the size of the result and get sufficient memory.  */
+  va_start (args, first);
+  newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
+  va_end (args);
+
+  /* Now copy the individual pieces to the result string. */
+  va_start (args, first);
+  vconcat_copy (newstr, first, args);
+  if (optr) /* Done before VA_CLOSE so optr stays in scope for K&R C.  */
+    free (optr);
+  va_end (args);
+
+  return newstr;
 }
 
 #ifdef MAIN
+#define NULLP (char *)0
 
 /* Simple little test driver. */
 
 #include <stdio.h>
 
 int
-main ()
+main (void)
 {
   printf ("\"\" = \"%s\"\n", concat (NULLP));
   printf ("\"a\" = \"%s\"\n", concat ("a", NULLP));
This page took 0.029909 seconds and 4 git commands to generate.