1 /* Functions for dealing with '\0' separated arg vectors.
2 Copyright (C) 1995-1998, 2000-2002, 2006, 2008 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
25 /* Add BUF, of length BUF_LEN to the argz vector in ARGZ & ARGZ_LEN. */
27 argz_append (char **argz, size_t *argz_len, const char *buf, size_t buf_len)
29 size_t new_argz_len = *argz_len + buf_len;
30 char *new_argz = realloc (*argz, new_argz_len);
33 memcpy (new_argz + *argz_len, buf, buf_len);
35 *argz_len = new_argz_len;
42 /* Add STR to the argz vector in ARGZ & ARGZ_LEN. This should be moved into
43 argz.c in libshouldbelibc. */
45 argz_add (char **argz, size_t *argz_len, const char *str)
47 return argz_append (argz, argz_len, str, strlen (str) + 1);
53 argz_add_sep (char **argz, size_t *argz_len, const char *string, int delim)
55 size_t nlen = strlen (string) + 1;
62 *argz = (char *) realloc (*argz, *argz_len + nlen);
66 wp = *argz + *argz_len;
71 if (wp > *argz && wp[-1] != '\0')
78 while (*rp++ != '\0');
89 argz_create_sep (const char *string, int delim, char **argz, size_t *len)
91 size_t nlen = strlen (string) + 1;
98 *argz = (char *) malloc (nlen);
107 if (wp > *argz && wp[-1] != '\0')
114 while (*rp++ != '\0');
135 /* Insert ENTRY into ARGZ & ARGZ_LEN before BEFORE, which should be an
136 existing entry in ARGZ; if BEFORE is NULL, ENTRY is appended to the end.
137 Since ARGZ's first entry is the same as ARGZ, argz_insert (ARGZ, ARGZ_LEN,
138 ARGZ, ENTRY) will insert ENTRY at the beginning of ARGZ. If BEFORE is not
139 in ARGZ, EINVAL is returned, else if memory can't be allocated for the new
140 ARGZ, ENOMEM is returned, else 0. */
142 argz_insert (char **argz, size_t *argz_len, char *before, const char *entry)
145 return argz_add (argz, argz_len, entry);
147 if (before < *argz || before >= *argz + *argz_len)
151 /* Make sure before is actually the beginning of an entry. */
156 size_t after_before = *argz_len - (before - *argz);
157 size_t entry_len = strlen (entry) + 1;
158 size_t new_argz_len = *argz_len + entry_len;
159 char *new_argz = realloc (*argz, new_argz_len);
163 before = new_argz + (before - *argz);
164 memmove (before + entry_len, before, after_before);
165 memmove (before, entry, entry_len);
167 *argz_len = new_argz_len;
177 argz_next (const char *argz, size_t argz_len, const char *entry)
181 if (entry < argz + argz_len)
182 entry = strchr (entry, '\0') + 1;
184 return entry >= argz + argz_len ? NULL : (char *) entry;
188 return (char *) argz;
194 /* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
195 except the last into the character SEP. */
197 argz_stringify (char *argz, size_t len, int sep)
202 size_t part_len = strnlen (argz, len);
205 if (len-- <= 1) /* includes final '\0' we want to stop at */
212 /* Returns the number of strings in ARGZ. */
214 argz_count (const char *argz, size_t len)
219 size_t part_len = strlen(argz);
220 argz += part_len + 1;
228 /* Puts pointers to each string in ARGZ, plus a terminating 0 element, into
229 ARGV, which must be large enough to hold them all. */
231 argz_extract (const char *argz, size_t len, char **argv)
235 size_t part_len = strlen (argz);
236 *argv++ = (char *) argz;
237 argz += part_len + 1;
244 /* Make a '\0' separated arg vector from a unix argv vector, returning it in
245 ARGZ, and the total length in LEN. If a memory allocation error occurs,
246 ENOMEM is returned, otherwise 0. */
248 argz_create (char *const argv[], char **argz, size_t *len)
255 for (argc = 0; argv[argc] != NULL; ++argc)
256 tlen += strlen (argv[argc]) + 1;
262 *argz = malloc (tlen);
266 for (p = *argz, ap = argv; *ap; ++ap, ++p)
275 /* Delete ENTRY from ARGZ & ARGZ_LEN, if any. */
277 argz_delete (char **argz, size_t *argz_len, char *entry)
280 /* Get rid of the old value for NAME. */
282 size_t entry_len = strlen (entry) + 1;
283 *argz_len -= entry_len;
284 memmove (entry, entry + entry_len, *argz_len - (entry - *argz));
294 /* Append BUF, of length BUF_LEN to *TO, of length *TO_LEN, reallocating and
295 updating *TO & *TO_LEN appropriately. If an allocation error occurs,
296 *TO's old value is freed, and *TO is set to 0. */
298 str_append (char **to, size_t *to_len, const char *buf, const size_t buf_len)
300 size_t new_len = *to_len + buf_len;
301 char *new_to = realloc (*to, new_len + 1);
305 *((char *) mempcpy (new_to + *to_len, buf, buf_len)) = '\0';
316 /* Replace any occurrences of the string STR in ARGZ with WITH, reallocating
317 ARGZ as necessary. If REPLACE_COUNT is non-zero, *REPLACE_COUNT will be
318 incremented by number of replacements performed. */
320 argz_replace (char **argz, size_t *argz_len, const char *str, const char *with,
321 unsigned *replace_count)
329 size_t src_len = *argz_len;
332 int delayed_copy = 1; /* True while we've avoided copying anything. */
333 size_t str_len = strlen (str), with_len = strlen (with);
335 while (!err && (arg = argz_next (src, src_len, arg)))
337 char *match = strstr (arg, str);
340 char *from = match + str_len;
341 size_t to_len = match - arg;
342 char *to = strndup (arg, to_len);
346 str_append (&to, &to_len, with, with_len);
349 match = strstr (from, str);
352 str_append (&to, &to_len, from, match - from);
353 from = match + str_len;
357 str_append (&to, &to_len, from, strlen (from));
366 /* We avoided copying SRC to DST until we found a match;
367 now that we've done so, copy everything from the start
371 err = argz_append (&dst, &dst_len, src, (arg - src));
375 err = argz_add (&dst, &dst_len, to);
384 else if (! delayed_copy)
385 err = argz_add (&dst, &dst_len, arg);
391 /* We never found any instances of str. */
398 else if (dst_len > 0)