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 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 /* Provide our wierdo HAVE_CONFIG_H rvalue for other clients. */
23 #if !defined(LTDL) && defined(HAVE_CONFIG_H)
24 # define HAVE_CONFIG_H <config.h>
27 #if defined(HAVE_CONFIG_H)
28 # include HAVE_CONFIG_H
36 #include <sys/types.h>
39 #if defined(HAVE_STRING_H)
41 #elif defined(HAVE_STRINGS_H)
44 #if defined(HAVE_MEMORY_H)
51 argz_append (char **pargz, size_t *pargz_len, const char *buf, size_t buf_len)
58 assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
60 /* If nothing needs to be appended, no more work is required. */
64 /* Ensure there is enough room to append BUF_LEN. */
65 argz_len = *pargz_len + buf_len;
66 argz = (char *) realloc (*pargz, argz_len);
70 /* Copy characters from BUF after terminating '\0' in ARGZ. */
71 memcpy (argz + *pargz_len, buf, buf_len);
73 /* Assign new values. */
75 *pargz_len = argz_len;
82 argz_create_sep (const char *str, int delim, char **pargz, size_t *pargz_len)
91 /* Make a copy of STR, but replacing each occurence of
93 argz_len = 1+ strlen (str);
99 argz = (char *) malloc (argz_len);
103 for (p = str, q = argz; *p != EOS_CHAR; ++p)
107 /* Ignore leading delimiters, and fold consecutive
108 delimiters in STR into a single '\0' in ARGZ. */
109 if ((q > argz) && (q[-1] != EOS_CHAR))
117 /* Copy terminating EOS_CHAR. */
121 /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */
123 argz = (free (argz), (char *) 0);
125 /* Assign new values. */
127 *pargz_len = argz_len;
134 argz_insert (char **pargz, size_t *pargz_len, char *before, const char *entry)
138 assert (entry && *entry);
140 /* No BEFORE address indicates ENTRY should be inserted after the
141 current last element. */
143 return argz_append (pargz, pargz_len, entry, 1+ strlen (entry));
145 /* This probably indicates a programmer error, but to preserve
146 semantics, scan back to the start of an entry if BEFORE points
147 into the middle of it. */
148 while ((before > *pargz) && (before[-1] != EOS_CHAR))
152 size_t entry_len = 1+ strlen (entry);
153 size_t argz_len = *pargz_len + entry_len;
154 size_t offset = before - *pargz;
155 char *argz = (char *) realloc (*pargz, argz_len);
160 /* Make BEFORE point to the equivalent offset in ARGZ that it
161 used to have in *PARGZ incase realloc() moved the block. */
162 before = argz + offset;
164 /* Move the ARGZ entries starting at BEFORE up into the new
165 space at the end -- making room to copy ENTRY into the
167 memmove (before + entry_len, before, *pargz_len - offset);
168 memcpy (before, entry, entry_len);
170 /* Assign new values. */
172 *pargz_len = argz_len;
180 argz_next (char *argz, size_t argz_len, const char *entry)
182 assert ((argz && argz_len) || (!argz && !argz_len));
186 /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
187 within the ARGZ vector. */
188 assert ((!argz && !argz_len)
189 || ((argz <= entry) && (entry < (argz + argz_len))));
191 /* Move to the char immediately after the terminating
193 entry = 1+ strchr (entry, EOS_CHAR);
195 /* Return either the new ENTRY, or else NULL if ARGZ is
197 return (entry >= argz + argz_len) ? 0 : (char *) entry;
201 /* This should probably be flagged as a programmer error,
202 since starting an argz_next loop with the iterator set
203 to ARGZ is safer. To preserve semantics, handle the NULL
204 case by returning the start of ARGZ (if any). */
214 argz_stringify (char *argz, size_t argz_len, int sep)
216 assert ((argz && argz_len) || (!argz && !argz_len));
220 --argz_len; /* don't stringify the terminating EOS */
221 while (--argz_len > 0)
223 if (argz[argz_len] == EOS_CHAR)
224 argz[argz_len] = sep;