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: