1 /* argz.c -- argz implementation for non-glibc systems
2 Copyright (C) 2004 Free Software Foundation, Inc.
3 Originally by Gary V. Vaughan <gary@gnu.org>
5 NOTE: The canonical source of this file is maintained with the
6 GNU Libtool package. Report bugs to bug-libtool@gnu.org.
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
13 As a special exception to the GNU Lesser General Public License,
14 if you distribute this file as part of a program or library that
15 is built using GNU libtool, you may include it under the same
16 distribution terms that you use for the rest of that program.
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 /* Provide our wierdo HAVE_CONFIG_H rvalue for other clients. */
31 #if !defined(LTDL) && defined(HAVE_CONFIG_H)
33 # define HAVE_CONFIG_H <config.h>
36 #if defined(HAVE_CONFIG_H)
37 # include HAVE_CONFIG_H
45 #include <sys/types.h>
48 #if defined(HAVE_STRING_H)
50 #elif defined(HAVE_STRINGS_H)
53 #if defined(HAVE_MEMORY_H)
60 argz_append (char **pargz, size_t *pargz_len, const char *buf, size_t buf_len)
67 assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
69 /* If nothing needs to be appended, no more work is required. */
73 /* Ensure there is enough room to append BUF_LEN. */
74 argz_len = *pargz_len + buf_len;
75 argz = (char *) realloc (*pargz, argz_len);
79 /* Copy characters from BUF after terminating '\0' in ARGZ. */
80 memcpy (argz + *pargz_len, buf, buf_len);
82 /* Assign new values. */
84 *pargz_len = argz_len;
91 argz_create_sep (const char *str, int delim, char **pargz, size_t *pargz_len)
100 /* Make a copy of STR, but replacing each occurrence of
102 argz_len = 1+ strlen (str);
108 argz = (char *) malloc (argz_len);
112 for (p = str, q = argz; *p != EOS_CHAR; ++p)
116 /* Ignore leading delimiters, and fold consecutive
117 delimiters in STR into a single '\0' in ARGZ. */
118 if ((q > argz) && (q[-1] != EOS_CHAR))
126 /* Copy terminating EOS_CHAR. */
130 /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */
132 argz = (free (argz), (char *) 0);
134 /* Assign new values. */
136 *pargz_len = argz_len;
143 argz_insert (char **pargz, size_t *pargz_len, char *before, const char *entry)
147 assert (entry && *entry);
149 /* No BEFORE address indicates ENTRY should be inserted after the
150 current last element. */
152 return argz_append (pargz, pargz_len, entry, 1+ strlen (entry));
154 /* This probably indicates a programmer error, but to preserve
155 semantics, scan back to the start of an entry if BEFORE points
156 into the middle of it. */
157 while ((before > *pargz) && (before[-1] != EOS_CHAR))
161 size_t entry_len = 1+ strlen (entry);
162 size_t argz_len = *pargz_len + entry_len;
163 size_t offset = before - *pargz;
164 char *argz = (char *) realloc (*pargz, argz_len);
169 /* Make BEFORE point to the equivalent offset in ARGZ that it
170 used to have in *PARGZ incase realloc() moved the block. */
171 before = argz + offset;
173 /* Move the ARGZ entries starting at BEFORE up into the new
174 space at the end -- making room to copy ENTRY into the
176 memmove (before + entry_len, before, *pargz_len - offset);
177 memcpy (before, entry, entry_len);
179 /* Assign new values. */
181 *pargz_len = argz_len;
189 argz_next (char *argz, size_t argz_len, const char *entry)
191 assert ((argz && argz_len) || (!argz && !argz_len));
195 /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
196 within the ARGZ vector. */
197 assert ((!argz && !argz_len)
198 || ((argz <= entry) && (entry < (argz + argz_len))));
200 /* Move to the char immediately after the terminating
202 entry = 1+ strchr (entry, EOS_CHAR);
204 /* Return either the new ENTRY, or else NULL if ARGZ is
206 return (entry >= argz + argz_len) ? 0 : (char *) entry;
210 /* This should probably be flagged as a programmer error,
211 since starting an argz_next loop with the iterator set
212 to ARGZ is safer. To preserve semantics, handle the NULL
213 case by returning the start of ARGZ (if any). */
223 argz_stringify (char *argz, size_t argz_len, int sep)
225 assert ((argz && argz_len) || (!argz && !argz_len));
229 --argz_len; /* don't stringify the terminating EOS */
230 while (--argz_len > 0)
232 if (argz[argz_len] == EOS_CHAR)
233 argz[argz_len] = sep;