Annotation of sql/sqlite/libltdl/argz.c, revision 1.2

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

E-mail: