bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 2/2, updated] Add missing argz_* functions from glibc


From: David Lutterkort
Subject: Re: [PATCH 2/2, updated] Add missing argz_* functions from glibc
Date: Thu, 29 May 2008 14:48:08 -0700

>From 7bce6f3f1ac91a482f6c72aa4b84239e5cadfec4 Mon Sep 17 00:00:00 2001
From: David Lutterkort <address@hidden>
Date: Wed, 28 May 2008 15:28:57 -0700
Subject: [PATCH 2/3] Add missing argz_* functions from glibc

* argz.c (argz_add_sep, argz_create, argz_create_sep, argz_replace,
  argz_delete): import almost verbatim from glibc-2.7; only changes are
  renaming of __ functions to public interface
* argz.m4: check for newly added functions
* modules/argz: new dependencies on mempcpy, stpcpy, and strndup

Signed-off-by: David Lutterkort <address@hidden>
---
 lib/argz.c    |  207 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/argz.in.h |    7 ++
 m4/argz.m4    |    3 +-
 modules/argz  |    3 +
 4 files changed, 219 insertions(+), 1 deletions(-)

diff --git a/lib/argz.c b/lib/argz.c
index f31ce17..91d284c 100644
--- a/lib/argz.c
+++ b/lib/argz.c
@@ -85,6 +85,70 @@ argz_add (char **pargz, size_t *pargz_len, const char *str)
 
 
 error_t
+argz_add_sep (char **argz, size_t *argz_len, const char *string, int delim)
+{
+  size_t nlen = strlen(string) + 1;
+
+  if (nlen > 1)
+    {
+      const char *rp;
+      char *wp;
+
+      *argz = (char *) realloc (*argz, *argz_len + nlen);
+      if (*argz == NULL)
+       return ENOMEM;
+
+      wp = *argz + *argz_len;
+      rp = string;
+      do
+       if (*rp == delim)
+         {
+           if (wp > *argz && wp[-1] != '\0')
+             *wp++ = '\0';
+           else
+             --nlen;
+         }
+       else
+         *wp++ = *rp;
+      while (*rp++ != '\0');
+
+      *argz_len += nlen;
+    }
+
+  return 0;
+}
+
+/* Make a '\0' separated arg vector from a unix argv vector, returning it in
+   ARGZ, and the total length in LEN.  If a memory allocation error occurs,
+   ENOMEM is returned, otherwise 0.  */
+error_t
+argz_create (char *const argv[], char **argz, size_t *len)
+{
+  int argc;
+  size_t tlen = 0;
+  char *const *ap;
+  char *p;
+
+  for (argc = 0; argv[argc] != NULL; ++argc)
+    tlen += strlen (argv[argc]) + 1;
+
+  if (tlen == 0)
+    *argz = NULL;
+  else
+    {
+      *argz = malloc (tlen);
+      if (*argz == NULL)
+       return ENOMEM;
+
+      for (p = *argz, ap = argv; *ap; ++ap, ++p)
+       p = stpcpy (p, *ap);
+    }
+  *len = tlen;
+
+  return 0;
+}
+
+error_t
 argz_create_sep (const char *str, int delim, char **pargz, size_t *pargz_len)
 {
   size_t argz_len;
@@ -181,6 +245,134 @@ argz_insert (char **pargz, size_t *pargz_len, char 
*before, const char *entry)
   return 0;
 }
 
+/* Append BUF, of length BUF_LEN to *TO, of length *TO_LEN, reallocating and
+   updating *TO & *TO_LEN appropriately.  If an allocation error occurs,
+   *TO's old value is freed, and *TO is set to 0.  */
+static void
+str_append (char **to, size_t *to_len, const char *buf, const size_t buf_len)
+{
+  size_t new_len = *to_len + buf_len;
+  char *new_to = realloc (*to, new_len + 1);
+
+  if (new_to)
+    {
+      *((char *) mempcpy (new_to + *to_len, buf, buf_len)) = '\0';
+      *to = new_to;
+      *to_len = new_len;
+    }
+  else
+    {
+      free (*to);
+      *to = 0;
+    }
+}
+
+/* Replace any occurrences of the string STR in ARGZ with WITH, reallocating
+   ARGZ as necessary.  If REPLACE_COUNT is non-zero, *REPLACE_COUNT will be
+   incremented by number of replacements performed.  */
+error_t
+argz_replace (char **argz, size_t *argz_len, const char *str, const char *with,
+               unsigned int *replace_count)
+{
+  error_t err = 0;
+
+  if (str && *str)
+    {
+      char *arg = 0;
+      char *src = *argz;
+      size_t src_len = *argz_len;
+      char *dst = 0;
+      size_t dst_len = 0;
+      int delayed_copy = 1;    /* True while we've avoided copying anything.  
*/
+      size_t str_len = strlen (str), with_len = strlen (with);
+
+      while (!err && (arg = argz_next (src, src_len, arg)))
+       {
+         char *match = strstr (arg, str);
+         if (match)
+           {
+             char *from = match + str_len;
+             size_t to_len = match - arg;
+             char *to = strndup (arg, to_len);
+
+             while (to && from)
+               {
+                 str_append (&to, &to_len, with, with_len);
+                 if (to)
+                   {
+                     match = strstr (from, str);
+                     if (match)
+                       {
+                         str_append (&to, &to_len, from, match - from);
+                         from = match + str_len;
+                       }
+                     else
+                       {
+                         str_append (&to, &to_len, from, strlen (from));
+                         from = 0;
+                       }
+                   }
+               }
+
+             if (to)
+               {
+                 if (delayed_copy)
+                   /* We avoided copying SRC to DST until we found a match;
+                       now that we've done so, copy everything from the start
+                       of SRC.  */
+                   {
+                     if (arg > src)
+                       err = argz_append (&dst, &dst_len, src, (arg - src));
+                     delayed_copy = 0;
+                   }
+                 if (! err)
+                   err = argz_add (&dst, &dst_len, to);
+                 free (to);
+               }
+             else
+               err = ENOMEM;
+
+             if (replace_count)
+               (*replace_count)++;
+           }
+         else if (! delayed_copy)
+           err = argz_add (&dst, &dst_len, arg);
+       }
+
+      if (! err)
+       {
+         if (! delayed_copy)
+           /* We never found any instances of str.  */
+           {
+             free (src);
+             *argz = dst;
+             *argz_len = dst_len;
+           }
+       }
+      else if (dst_len > 0)
+       free (dst);
+    }
+
+  return err;
+}
+
+/* Delete ENTRY from ARGZ & ARGZ_LEN, if any.  */
+void
+argz_delete (char **argz, size_t *argz_len, char *entry)
+{
+  if (entry)
+    /* Get rid of the old value for NAME.  */
+    {
+      size_t entry_len = strlen (entry) + 1;
+      *argz_len -= entry_len;
+      memmove (entry, entry + entry_len, *argz_len - (entry - *argz));
+      if (*argz_len == 0)
+       {
+         free (*argz);
+         *argz = 0;
+       }
+    }
+}
 
 char *
 argz_next (char *argz, size_t argz_len, const char *entry)
@@ -252,3 +444,18 @@ argz_count (const char *argz, size_t argz_len)
 
   return count;
 }
+
+/* Puts pointers to each string in ARGZ, plus a terminating 0 element, into
+   ARGV, which must be large enough to hold them all.  */
+void
+argz_extract (const char *argz, size_t len, char **argv)
+{
+  while (len > 0)
+    {
+      size_t part_len = strlen (argz);
+      *argv++ = (char *) argz;
+      argz += part_len + 1;
+      len -= part_len + 1;
+    }
+  *argv = 0;
+}
diff --git a/lib/argz.in.h b/lib/argz.in.h
index 40d5176..4191e12 100644
--- a/lib/argz.in.h
+++ b/lib/argz.in.h
@@ -51,10 +51,17 @@ LT_SCOPE error_t argz_append        (char **pargz, size_t 
*pargz_len,
                                 const char *buf, size_t buf_len);
 LT_SCOPE error_t argz_add       (char **pargz, size_t *pargz_len,
                                  const char *str);
+LT_SCOPE error_t argz_add_sep   (char **argz, size_t *argz_len,
+                                 const char *string, int delim);
+LT_SCOPE error_t argz_create    (char *const argv[], char **argz, size_t *len);
 LT_SCOPE error_t argz_create_sep(const char *str, int delim,
                                 char **pargz, size_t *pargz_len);
 LT_SCOPE error_t argz_insert   (char **pargz, size_t *pargz_len,
                                 char *before, const char *entry);
+LT_SCOPE error_t argz_replace   (char **argz, size_t *argz_len,
+                                 const char *str, const char *with,
+                                 unsigned int *replace_count);
+LT_SCOPE void    argz_delete    (char **argz, size_t *argz_len, char *entry);
 LT_SCOPE char *         argz_next      (char *argz, size_t argz_len,
                                 const char *entry);
 LT_SCOPE void   argz_stringify (char *argz, size_t argz_len, int sep);
diff --git a/m4/argz.m4 b/m4/argz.m4
index 37c1b11..cb7d490 100644
--- a/m4/argz.m4
+++ b/m4/argz.m4
@@ -25,7 +25,8 @@ AC_CHECK_TYPES([error_t],
 #endif])
 
 ARGZ_H=
-AC_CHECK_FUNCS([argz_add argz_append argz_count argz_create_sep argz_insert \
+AC_CHECK_FUNCS([argz_add argz_add_sep argz_append argz_count \
+        argz_create_sep argz_insert argz_replace argz_delete \
        argz_next argz_stringify], [], [ARGZ_H=argz.h; AC_LIBOBJ([argz])])
 
 dnl if have system argz functions, allow forced use of
diff --git a/modules/argz b/modules/argz
index 601abb7..9898435 100644
--- a/modules/argz
+++ b/modules/argz
@@ -7,6 +7,9 @@ lib/argz.c
 m4/argz.m4
 
 Depends-on:
+mempcpy
+stpcpy
+strndup
 
 configure.ac:
 gl_FUNC_ARGZ
-- 
1.5.4.1







reply via email to

[Prev in Thread] Current Thread [Next in Thread]