OSDN Git Service

2003-09-22 Andrew Cagney <cagney@redhat.com>
[pf3gnuchains/gcc-fork.git] / libiberty / concat.c
index 01270ea..98b20e1 100644 (file)
@@ -21,24 +21,14 @@ Boston, MA 02111-1307, 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.  Returns @code{NULL} if insufficient memory is
+available.  The argument list is terminated by the first @code{NULL}
+pointer encountered.  Pointers to empty strings are ignored.
 
-SYNOPSIS
-
-       #include <varargs.h>
-
-       char *concat (s1, s2, s3, ..., NULL)
-
-DESCRIPTION
-
-       Concatenate a variable number of strings and return the result
-       in freshly malloc'd memory.
-
-       Returns NULL if insufficient memory is available.  The argument
-       list is terminated by the first NULL pointer encountered.  Pointers
-       to empty strings are ignored.
+@end deftypefn
 
 NOTES
 
@@ -50,6 +40,7 @@ NOTES
        deal with low memory situations itself, it should supply an xmalloc
        that just directly invokes malloc and blindly returns whatever
        malloc returns.
+
 */
 
 
@@ -74,58 +65,150 @@ NOTES
 #  endif
 # endif
 
-/* VARARGS */
-#ifdef ANSI_PROTOTYPES
-char *
-concat (const char *first, ...)
-#else
-char *
-concat (va_alist)
-     va_dcl
-#endif
-{
-  register size_t length;
-  register char *newstr;
-  register char *end;
-  register const char *arg;
-  va_list args;
-#ifndef ANSI_PROTOTYPES
-  const char *first;
+#if HAVE_STDLIB_H
+#include <stdlib.h>
 #endif
 
-  /* First compute the size of the result and get sufficient memory.  */
-#ifdef ANSI_PROTOTYPES
-  va_start (args, first);
-#else
-  va_start (args);
-  first = va_arg (args, const char *);
-#endif
+static inline unsigned long vconcat_length PARAMS ((const char *, va_list));
+static inline unsigned long
+vconcat_length (first, args)
+     const char *first;
+     va_list args;
+{
+  unsigned long length = 0;
+  const char *arg;
 
-  length = 0;
   for (arg = first; arg ; arg = va_arg (args, const char *))
     length += strlen (arg);
 
-  va_end (args);
-
-  newstr = (char *) xmalloc (length + 1);
+  return length;
+}
 
-  /* Now copy the individual pieces to the result string. */
-#ifdef ANSI_PROTOTYPES
-  va_start (args, first);
-#else
-  va_start (args);
-  first = va_arg (args, const char *);
-#endif
+static inline char *vconcat_copy PARAMS ((char *, const char *, va_list));
+static inline char *
+vconcat_copy (dst, first, args)
+     char *dst;
+     const char *first;
+     va_list args;
+{
+  char *end = dst;
+  const char *arg;
 
-  end = newstr;
   for (arg = first; arg ; arg = va_arg (args, const char *))
     {
-      length = strlen (arg);
+      unsigned long length = strlen (arg);
       memcpy (end, arg, length);
       end += length;
     }
   *end = '\000';
-  va_end (args);
+
+  return dst;
+}
+
+/* @undocumented concat_length */
+
+unsigned long
+concat_length VPARAMS ((const char *first, ...))
+{
+  unsigned long length;
+
+  VA_OPEN (args, first);
+  VA_FIXEDARG (args, const char *, first);
+  length = vconcat_length (first, args);
+  VA_CLOSE (args);
+
+  return length;
+}
+
+/* @undocumented concat_copy */
+
+char *
+concat_copy VPARAMS ((char *dst, const char *first, ...))
+{
+  char *save_dst;
+
+  VA_OPEN (args, first);
+  VA_FIXEDARG (args, char *, dst);
+  VA_FIXEDARG (args, const char *, first);
+  vconcat_copy (dst, first, args);
+  save_dst = dst; /* With K&R C, dst goes out of scope here.  */
+  VA_CLOSE (args);
+
+  return save_dst;
+}
+
+char *libiberty_concat_ptr;
+
+/* @undocumented concat_copy2 */
+
+char *
+concat_copy2 VPARAMS ((const char *first, ...))
+{
+  VA_OPEN (args, first);
+  VA_FIXEDARG (args, const char *, first);
+  vconcat_copy (libiberty_concat_ptr, first, args);
+  VA_CLOSE (args);
+
+  return libiberty_concat_ptr;
+}
+
+char *
+concat VPARAMS ((const char *first, ...))
+{
+  char *newstr;
+
+  /* First compute the size of the result and get sufficient memory.  */
+  VA_OPEN (args, first);
+  VA_FIXEDARG (args, const char *, first);
+  newstr = (char *) xmalloc (vconcat_length (first, args) + 1);
+  VA_CLOSE (args);
+
+  /* Now copy the individual pieces to the result string. */
+  VA_OPEN (args, first);
+  VA_FIXEDARG (args, const char *, first);
+  vconcat_copy (newstr, first, args);
+  VA_CLOSE (args);
+
+  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 VPARAMS ((char *optr, const char *first, ...))
+{
+  char *newstr;
+
+  /* First compute the size of the result and get sufficient memory.  */
+  VA_OPEN (args, first);
+  VA_FIXEDARG (args, char *, optr);
+  VA_FIXEDARG (args, const char *, first);
+  newstr = (char *) xmalloc (vconcat_length (first, args) + 1);
+  VA_CLOSE (args);
+
+  /* Now copy the individual pieces to the result string. */
+  VA_OPEN (args, first);
+  VA_FIXEDARG (args, char *, optr);
+  VA_FIXEDARG (args, const char *, first);
+  vconcat_copy (newstr, first, args);
+  if (optr) /* Done before VA_CLOSE so optr stays in scope for K&R C.  */
+    free (optr);
+  VA_CLOSE (args);
 
   return newstr;
 }