[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/2] Add missing argz_* functions from glibc
From: |
David Lutterkort |
Subject: |
[PATCH 2/2] Add missing argz_* functions from glibc |
Date: |
Wed, 28 May 2008 16:06:50 -0700 |
* argz.c (argz_add_sep, argz_create, argz_create_sep, argz_replace,
argz_delete): import almost verbatim from glibc-2.7; only changes are
additional asserts and 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 | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/argz.in.h | 7 ++
m4/argz.m4 | 3 +-
modules/argz | 3 +
4 files changed, 233 insertions(+), 1 deletions(-)
diff --git a/lib/argz.c b/lib/argz.c
index f31ce17..a847bd4 100644
--- a/lib/argz.c
+++ b/lib/argz.c
@@ -85,6 +85,75 @@ 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;
+
+ assert(argz);
+ assert(argz_len);
+ assert(string);
+
+ 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 +250,140 @@ 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;
+
+ assert(argz);
+ assert(*argz);
+ assert(argz_len);
+ assert(with);
+ assert(replace_count);
+
+ 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 +455,21 @@ 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)
+{
+ assert(argz);
+ assert(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
- [PATCH 0/2] Add missing functions to argz, David Lutterkort, 2008/05/28
- Re: [PATCH 0/2] Add missing functions to argz, Eric Blake, 2008/05/28
- [PATCH 2/2] Add missing argz_* functions from glibc,
David Lutterkort <=
- Re: [PATCH 2/2] Add missing argz_* functions from glibc, Ralf Wildenhues, 2008/05/29
- Re: [PATCH 2/2] Add missing argz_* functions from glibc, David Lutterkort, 2008/05/29
- Re: [PATCH 2/2, updated] Add missing argz_* functions from glibc, David Lutterkort, 2008/05/29
- Re: [PATCH 2/2] Add missing argz_* functions from glibc, Bob Friesenhahn, 2008/05/29
[PATCH 1/2] Make stpcpy LGPLv2+, David Lutterkort, 2008/05/28