1 /* Functions for dealing with '\0' separated arg vectors.
2 Copyright (C) 1995-1998, 2000-2002, 2006, 2008-2024 Free Software
4 This file is part of the GNU C Library.
6 This file is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
11 This file is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with this program. If not, see <https://www.gnu.org/licenses/>. */
28 /* Add BUF, of length BUF_LEN to the argz vector in ARGZ & ARGZ_LEN. */
30 argz_append (char **argz
, size_t *argz_len
, const char *buf
, size_t buf_len
)
32 size_t new_argz_len
= *argz_len
+ buf_len
;
33 char *new_argz
= realloc (*argz
, new_argz_len
);
36 memcpy (new_argz
+ *argz_len
, buf
, buf_len
);
38 *argz_len
= new_argz_len
;
45 /* Add STR to the argz vector in ARGZ & ARGZ_LEN. This should be moved into
46 argz.c in libshouldbelibc. */
48 argz_add (char **argz
, size_t *argz_len
, const char *str
)
50 return argz_append (argz
, argz_len
, str
, strlen (str
) + 1);
56 argz_add_sep (char **argz
, size_t *argz_len
, const char *string
, int delim
)
58 size_t nlen
= strlen (string
) + 1;
65 *argz
= (char *) realloc (*argz
, *argz_len
+ nlen
);
69 wp
= *argz
+ *argz_len
;
74 if (wp
> *argz
&& wp
[-1] != '\0')
81 while (*rp
++ != '\0');
92 argz_create_sep (const char *string
, int delim
, char **argz
, size_t *len
)
94 size_t nlen
= strlen (string
) + 1;
101 *argz
= (char *) malloc (nlen
);
110 if (wp
> *argz
&& wp
[-1] != '\0')
117 while (*rp
++ != '\0');
138 /* Insert ENTRY into ARGZ & ARGZ_LEN before BEFORE, which should be an
139 existing entry in ARGZ; if BEFORE is NULL, ENTRY is appended to the end.
140 Since ARGZ's first entry is the same as ARGZ, argz_insert (ARGZ, ARGZ_LEN,
141 ARGZ, ENTRY) will insert ENTRY at the beginning of ARGZ. If BEFORE is not
142 in ARGZ, EINVAL is returned, else if memory can't be allocated for the new
143 ARGZ, ENOMEM is returned, else 0. */
145 argz_insert (char **argz
, size_t *argz_len
, char *before
, const char *entry
)
148 return argz_add (argz
, argz_len
, entry
);
150 if (before
< *argz
|| before
>= *argz
+ *argz_len
)
154 /* Make sure before is actually the beginning of an entry. */
159 size_t after_before
= *argz_len
- (before
- *argz
);
160 size_t entry_len
= strlen (entry
) + 1;
161 size_t new_argz_len
= *argz_len
+ entry_len
;
162 char *new_argz
= realloc (*argz
, new_argz_len
);
166 before
= new_argz
+ (before
- *argz
);
167 memmove (before
+ entry_len
, before
, after_before
);
168 memmove (before
, entry
, entry_len
);
170 *argz_len
= new_argz_len
;
180 argz_next (const char *argz
, size_t argz_len
, const char *entry
)
184 if (entry
< argz
+ argz_len
)
185 entry
= strchr (entry
, '\0') + 1;
187 return entry
>= argz
+ argz_len
? NULL
: (char *) entry
;
191 return (char *) argz
;
197 /* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
198 except the last into the character SEP. */
200 argz_stringify (char *argz
, size_t len
, int sep
)
205 size_t part_len
= strnlen (argz
, len
);
208 if (len
-- <= 1) /* includes final '\0' we want to stop at */
215 /* Returns the number of strings in ARGZ. */
217 argz_count (const char *argz
, size_t len
)
222 size_t part_len
= strlen (argz
);
223 argz
+= part_len
+ 1;
231 /* Puts pointers to each string in ARGZ, plus a terminating 0 element, into
232 ARGV, which must be large enough to hold them all. */
234 argz_extract (const char *argz
, size_t len
, char **argv
)
238 size_t part_len
= strlen (argz
);
239 *argv
++ = (char *) argz
;
240 argz
+= part_len
+ 1;
247 /* Make a '\0' separated arg vector from a unix argv vector, returning it in
248 ARGZ, and the total length in LEN. If a memory allocation error occurs,
249 ENOMEM is returned, otherwise 0. */
251 argz_create (char *const argv
[], char **argz
, size_t *len
)
258 for (argc
= 0; argv
[argc
] != NULL
; ++argc
)
259 tlen
+= strlen (argv
[argc
]) + 1;
265 *argz
= malloc (tlen
);
269 for (p
= *argz
, ap
= argv
; *ap
; ++ap
, ++p
)
278 /* Delete ENTRY from ARGZ & ARGZ_LEN, if any. */
280 argz_delete (char **argz
, size_t *argz_len
, char *entry
)
283 /* Get rid of the old value for NAME. */
285 size_t entry_len
= strlen (entry
) + 1;
286 *argz_len
-= entry_len
;
287 memmove (entry
, entry
+ entry_len
, *argz_len
- (entry
- *argz
));
297 /* Append BUF, of length BUF_LEN to *TO, of length *TO_LEN, reallocating and
298 updating *TO & *TO_LEN appropriately. If an allocation error occurs,
299 *TO's old value is freed, and *TO is set to 0. */
301 str_append (char **to
, size_t *to_len
, const char *buf
, const size_t buf_len
)
303 size_t new_len
= *to_len
+ buf_len
;
304 char *new_to
= realloc (*to
, new_len
+ 1);
308 *((char *) mempcpy (new_to
+ *to_len
, buf
, buf_len
)) = '\0';
319 /* Replace any occurrences of the string STR in ARGZ with WITH, reallocating
320 ARGZ as necessary. If REPLACE_COUNT is non-zero, *REPLACE_COUNT will be
321 incremented by number of replacements performed. */
323 argz_replace (char **argz
, size_t *argz_len
, const char *str
, const char *with
,
324 unsigned *replace_count
)
332 size_t src_len
= *argz_len
;
335 int delayed_copy
= 1; /* True while we've avoided copying anything. */
336 size_t str_len
= strlen (str
), with_len
= strlen (with
);
338 while (!err
&& (arg
= argz_next (src
, src_len
, arg
)))
340 char *match
= strstr (arg
, str
);
343 char *from
= match
+ str_len
;
344 size_t to_len
= match
- arg
;
345 char *to
= strndup (arg
, to_len
);
349 str_append (&to
, &to_len
, with
, with_len
);
352 match
= strstr (from
, str
);
355 str_append (&to
, &to_len
, from
, match
- from
);
356 from
= match
+ str_len
;
360 str_append (&to
, &to_len
, from
, strlen (from
));
369 /* We avoided copying SRC to DST until we found a match;
370 now that we've done so, copy everything from the start
374 err
= argz_append (&dst
, &dst_len
, src
, (arg
- src
));
378 err
= argz_add (&dst
, &dst_len
, to
);
387 else if (! delayed_copy
)
388 err
= argz_add (&dst
, &dst_len
, arg
);
394 /* We never found any instances of str. */
401 else if (dst_len
> 0)