1 /* argz.c -- argz implementation for non-glibc systems
2 Copyright (C) 2004, 2006 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 program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation,
20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
22 #if defined(LTDL) && defined LT_CONFIG_H
33 #include <sys/types.h>
36 #if defined(HAVE_STRING_H)
38 #elif defined(HAVE_STRINGS_H)
41 #if defined(HAVE_MEMORY_H)
48 argz_append (char **pargz, size_t *pargz_len, const char *buf, size_t buf_len)
55 assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
57 /* If nothing needs to be appended, no more work is required. */
61 /* Ensure there is enough room to append BUF_LEN. */
62 argz_len = *pargz_len + buf_len;
63 argz = (char *) realloc (*pargz, argz_len);
67 /* Copy characters from BUF after terminating '\0' in ARGZ. */
68 memcpy (argz + *pargz_len, buf, buf_len);
70 /* Assign new values. */
72 *pargz_len = argz_len;
79 argz_create_sep (const char *str, int delim, char **pargz, size_t *pargz_len)
88 /* Make a copy of STR, but replacing each occurrence of
90 argz_len = 1+ strlen (str);
96 argz = (char *) malloc (argz_len);
100 for (p = str, q = argz; *p != EOS_CHAR; ++p)
104 /* Ignore leading delimiters, and fold consecutive
105 delimiters in STR into a single '\0' in ARGZ. */
106 if ((q > argz) && (q[-1] != EOS_CHAR))
114 /* Copy terminating EOS_CHAR. */
118 /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */
120 argz = (free (argz), (char *) 0);
122 /* Assign new values. */
124 *pargz_len = argz_len;
131 argz_insert (char **pargz, size_t *pargz_len, char *before, const char *entry)
135 assert (entry && *entry);
137 /* No BEFORE address indicates ENTRY should be inserted after the
138 current last element. */
140 return argz_append (pargz, pargz_len, entry, 1+ strlen (entry));
142 /* This probably indicates a programmer error, but to preserve
143 semantics, scan back to the start of an entry if BEFORE points
144 into the middle of it. */
145 while ((before > *pargz) && (before[-1] != EOS_CHAR))
149 size_t entry_len = 1+ strlen (entry);
150 size_t argz_len = *pargz_len + entry_len;
151 size_t offset = before - *pargz;
152 char *argz = (char *) realloc (*pargz, argz_len);
157 /* Make BEFORE point to the equivalent offset in ARGZ that it
158 used to have in *PARGZ incase realloc() moved the block. */
159 before = argz + offset;
161 /* Move the ARGZ entries starting at BEFORE up into the new
162 space at the end -- making room to copy ENTRY into the
164 memmove (before + entry_len, before, *pargz_len - offset);
165 memcpy (before, entry, entry_len);
167 /* Assign new values. */
169 *pargz_len = argz_len;
177 argz_next (char *argz, size_t argz_len, const char *entry)
179 assert ((argz && argz_len) || (!argz && !argz_len));
183 /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
184 within the ARGZ vector. */
185 assert ((!argz && !argz_len)
186 || ((argz <= entry) && (entry < (argz + argz_len))));
188 /* Move to the char immediately after the terminating
190 entry = 1+ strchr (entry, EOS_CHAR);
192 /* Return either the new ENTRY, or else NULL if ARGZ is
194 return (entry >= argz + argz_len) ? 0 : (char *) entry;
198 /* This should probably be flagged as a programmer error,
199 since starting an argz_next loop with the iterator set
200 to ARGZ is safer. To preserve semantics, handle the NULL
201 case by returning the start of ARGZ (if any). */
211 argz_stringify (char *argz, size_t argz_len, int sep)
213 assert ((argz && argz_len) || (!argz && !argz_len));
217 --argz_len; /* don't stringify the terminating EOS */
218 while (--argz_len > 0)
220 if (argz[argz_len] == EOS_CHAR)
221 argz[argz_len] = sep;