Annotation of parser3/src/lib/ltdl/lt__argz.c, revision 1.1
1.1 ! moko 1: /* lt__argz.c -- argz implementation for non-glibc systems
! 2:
! 3: Copyright (C) 2004, 2006-2008, 2011-2019, 2021-2024 Free Software
! 4: Foundation, Inc.
! 5: Written by Gary V. Vaughan, 2004
! 6:
! 7: NOTE: The canonical source of this file is maintained with the
! 8: GNU Libtool package. Report bugs to bug-libtool@gnu.org.
! 9:
! 10: GNU Libltdl is free software; you can redistribute it and/or
! 11: modify it under the terms of the GNU Lesser General Public
! 12: License as published by the Free Software Foundation; either
! 13: version 2 of the License, or (at your option) any later version.
! 14:
! 15: As a special exception to the GNU Lesser General Public License,
! 16: if you distribute this file as part of a program or library that
! 17: is built using GNU Libtool, you may include this file under the
! 18: same distribution terms that you use for the rest of that program.
! 19:
! 20: GNU Libltdl is distributed in the hope that it will be useful,
! 21: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 22: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 23: GNU Lesser General Public License for more details.
! 24:
! 25: You should have received a copy of the GNU Lesser General Public
! 26: License along with GNU Libltdl. If not, see <https://www.gnu.org/licenses/>.
! 27: */
! 28:
! 29: #if defined LTDL && defined LT_CONFIG_H
! 30: # include LT_CONFIG_H
! 31: #else
! 32: # include <config.h>
! 33: #endif
! 34:
! 35: #include <lt__argz.h>
! 36:
! 37: #include <assert.h>
! 38: #include <stdlib.h>
! 39: #include <sys/types.h>
! 40: #include <errno.h>
! 41: #include <string.h>
! 42:
! 43: #define EOS_CHAR '\0'
! 44:
! 45: error_t
! 46: argz_append (char **pargz, size_t *pargz_len, const char *buf, size_t buf_len)
! 47: {
! 48: size_t argz_len;
! 49: char *argz;
! 50:
! 51: assert (pargz);
! 52: assert (pargz_len);
! 53: assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
! 54:
! 55: /* If nothing needs to be appended, no more work is required. */
! 56: if (buf_len == 0)
! 57: return 0;
! 58:
! 59: /* Ensure there is enough room to append BUF_LEN. */
! 60: argz_len = *pargz_len + buf_len;
! 61: argz = (char *) realloc (*pargz, argz_len);
! 62: if (!argz)
! 63: return ENOMEM;
! 64:
! 65: /* Copy characters from BUF after terminating '\0' in ARGZ. */
! 66: memcpy (argz + *pargz_len, buf, buf_len);
! 67:
! 68: /* Assign new values. */
! 69: *pargz = argz;
! 70: *pargz_len = argz_len;
! 71:
! 72: return 0;
! 73: }
! 74:
! 75:
! 76: error_t
! 77: argz_create_sep (const char *str, int delim, char **pargz, size_t *pargz_len)
! 78: {
! 79: size_t argz_len;
! 80: char *argz = 0;
! 81:
! 82: assert (str);
! 83: assert (pargz);
! 84: assert (pargz_len);
! 85:
! 86: /* Make a copy of STR, but replacing each occurrence of
! 87: DELIM with '\0'. */
! 88: argz_len = 1+ strlen (str);
! 89: if (argz_len)
! 90: {
! 91: const char *p;
! 92: char *q;
! 93:
! 94: argz = (char *) malloc (argz_len);
! 95: if (!argz)
! 96: return ENOMEM;
! 97:
! 98: for (p = str, q = argz; *p != EOS_CHAR; ++p)
! 99: {
! 100: if (*p == delim)
! 101: {
! 102: /* Ignore leading delimiters, and fold consecutive
! 103: delimiters in STR into a single '\0' in ARGZ. */
! 104: if ((q > argz) && (q[-1] != EOS_CHAR))
! 105: *q++ = EOS_CHAR;
! 106: else
! 107: --argz_len;
! 108: }
! 109: else
! 110: *q++ = *p;
! 111: }
! 112: /* Copy terminating EOS_CHAR. */
! 113: *q = *p;
! 114: }
! 115:
! 116: /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */
! 117: if (!argz_len)
! 118: argz = (free (argz), (char *) 0);
! 119:
! 120: /* Assign new values. */
! 121: *pargz = argz;
! 122: *pargz_len = argz_len;
! 123:
! 124: return 0;
! 125: }
! 126:
! 127:
! 128: error_t
! 129: argz_insert (char **pargz, size_t *pargz_len, char *before, const char *entry)
! 130: {
! 131: assert (pargz);
! 132: assert (pargz_len);
! 133: assert (entry && *entry);
! 134:
! 135: /* No BEFORE address indicates ENTRY should be inserted after the
! 136: current last element. */
! 137: if (!before)
! 138: return argz_append (pargz, pargz_len, entry, 1+ strlen (entry));
! 139:
! 140: /* This probably indicates a programmer error, but to preserve
! 141: semantics, scan back to the start of an entry if BEFORE points
! 142: into the middle of it. */
! 143: while ((before > *pargz) && (before[-1] != EOS_CHAR))
! 144: --before;
! 145:
! 146: {
! 147: size_t entry_len = 1+ strlen (entry);
! 148: size_t argz_len = *pargz_len + entry_len;
! 149: size_t offset = before - *pargz;
! 150: char *argz = (char *) realloc (*pargz, argz_len);
! 151:
! 152: if (!argz)
! 153: return ENOMEM;
! 154:
! 155: /* Make BEFORE point to the equivalent offset in ARGZ that it
! 156: used to have in *PARGZ in case realloc() moved the block. */
! 157: before = argz + offset;
! 158:
! 159: /* Move the ARGZ entries starting at BEFORE up into the new
! 160: space at the end -- making room to copy ENTRY into the
! 161: resulting gap. */
! 162: memmove (before + entry_len, before, *pargz_len - offset);
! 163: memcpy (before, entry, entry_len);
! 164:
! 165: /* Assign new values. */
! 166: *pargz = argz;
! 167: *pargz_len = argz_len;
! 168: }
! 169:
! 170: return 0;
! 171: }
! 172:
! 173:
! 174: char *
! 175: argz_next (char *argz, size_t argz_len, const char *entry)
! 176: {
! 177: assert ((argz && argz_len) || (!argz && !argz_len));
! 178:
! 179: if (entry)
! 180: {
! 181: /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
! 182: within the ARGZ vector. */
! 183: assert ((!argz && !argz_len)
! 184: || ((argz <= entry) && (entry < (argz + argz_len))));
! 185:
! 186: /* Move to the char immediately after the terminating
! 187: '\0' of ENTRY. */
! 188: entry = 1+ strchr (entry, EOS_CHAR);
! 189:
! 190: /* Return either the new ENTRY, or else NULL if ARGZ is
! 191: exhausted. */
! 192: return (entry >= argz + argz_len) ? 0 : (char *) entry;
! 193: }
! 194: else
! 195: {
! 196: /* This should probably be flagged as a programmer error,
! 197: since starting an argz_next loop with the iterator set
! 198: to ARGZ is safer. To preserve semantics, handle the NULL
! 199: case by returning the start of ARGZ (if any). */
! 200: if (argz_len > 0)
! 201: return argz;
! 202: else
! 203: return 0;
! 204: }
! 205: }
! 206:
! 207:
! 208: void
! 209: argz_stringify (char *argz, size_t argz_len, int sep)
! 210: {
! 211: assert ((argz && argz_len) || (!argz && !argz_len));
! 212:
! 213: if (sep)
! 214: {
! 215: --argz_len; /* don't stringify the terminating EOS */
! 216: while (--argz_len > 0)
! 217: {
! 218: if (argz[argz_len] == EOS_CHAR)
! 219: argz[argz_len] = sep;
! 220: }
! 221: }
! 222: }
E-mail: