12a6b7db3Sskrll /* An abstract string datatype.
2*f22f0ef4Schristos    Copyright (C) 1998-2022 Free Software Foundation, Inc.
32a6b7db3Sskrll    Contributed by Mark Mitchell (mark@markmitchell.com).
42a6b7db3Sskrll 
52a6b7db3Sskrll This file is part of GNU CC.
62a6b7db3Sskrll 
72a6b7db3Sskrll GNU CC is free software; you can redistribute it and/or modify
82a6b7db3Sskrll it under the terms of the GNU General Public License as published by
92a6b7db3Sskrll the Free Software Foundation; either version 2, or (at your option)
102a6b7db3Sskrll any later version.
112a6b7db3Sskrll 
122a6b7db3Sskrll In addition to the permissions in the GNU General Public License, the
132a6b7db3Sskrll Free Software Foundation gives you unlimited permission to link the
142a6b7db3Sskrll compiled version of this file into combinations with other programs,
152a6b7db3Sskrll and to distribute those combinations without any restriction coming
162a6b7db3Sskrll from the use of this file.  (The General Public License restrictions
172a6b7db3Sskrll do apply in other respects; for example, they cover modification of
182a6b7db3Sskrll the file, and distribution when not linked into a combined
192a6b7db3Sskrll executable.)
202a6b7db3Sskrll 
212a6b7db3Sskrll GNU CC is distributed in the hope that it will be useful,
222a6b7db3Sskrll but WITHOUT ANY WARRANTY; without even the implied warranty of
232a6b7db3Sskrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
242a6b7db3Sskrll GNU General Public License for more details.
252a6b7db3Sskrll 
262a6b7db3Sskrll You should have received a copy of the GNU General Public License
272a6b7db3Sskrll along with GNU CC; see the file COPYING.  If not, write to
282a6b7db3Sskrll the Free Software Foundation, 51 Franklin Street - Fifth Floor,
292a6b7db3Sskrll Boston, MA 02110-1301, USA.  */
302a6b7db3Sskrll 
312a6b7db3Sskrll #ifdef HAVE_CONFIG_H
322a6b7db3Sskrll #include "config.h"
332a6b7db3Sskrll #endif
342a6b7db3Sskrll 
352a6b7db3Sskrll #include <stdio.h>
362a6b7db3Sskrll 
372a6b7db3Sskrll #ifdef HAVE_STRING_H
382a6b7db3Sskrll #include <string.h>
392a6b7db3Sskrll #endif
402a6b7db3Sskrll 
412a6b7db3Sskrll #ifdef HAVE_STDLIB_H
422a6b7db3Sskrll #include <stdlib.h>
432a6b7db3Sskrll #endif
442a6b7db3Sskrll 
452a6b7db3Sskrll #include "libiberty.h"
462a6b7db3Sskrll #include "dyn-string.h"
472a6b7db3Sskrll 
482a6b7db3Sskrll /* Performs in-place initialization of a dyn_string struct.  This
492a6b7db3Sskrll    function can be used with a dyn_string struct on the stack or
502a6b7db3Sskrll    embedded in another object.  The contents of of the string itself
512a6b7db3Sskrll    are still dynamically allocated.  The string initially is capable
522a6b7db3Sskrll    of holding at least SPACE characeters, including the terminating
532a6b7db3Sskrll    NUL.  If SPACE is 0, it will silently be increated to 1.
542a6b7db3Sskrll 
552a6b7db3Sskrll    If RETURN_ON_ALLOCATION_FAILURE is defined and memory allocation
562a6b7db3Sskrll    fails, returns 0.  Otherwise returns 1.  */
572a6b7db3Sskrll 
582a6b7db3Sskrll int
dyn_string_init(struct dyn_string * ds_struct_ptr,int space)592a6b7db3Sskrll dyn_string_init (struct dyn_string *ds_struct_ptr, int space)
602a6b7db3Sskrll {
612a6b7db3Sskrll   /* We need at least one byte in which to store the terminating NUL.  */
622a6b7db3Sskrll   if (space == 0)
632a6b7db3Sskrll     space = 1;
642a6b7db3Sskrll 
652a6b7db3Sskrll #ifdef RETURN_ON_ALLOCATION_FAILURE
662a6b7db3Sskrll   ds_struct_ptr->s = (char *) malloc (space);
672a6b7db3Sskrll   if (ds_struct_ptr->s == NULL)
682a6b7db3Sskrll     return 0;
692a6b7db3Sskrll #else
702a6b7db3Sskrll   ds_struct_ptr->s = XNEWVEC (char, space);
712a6b7db3Sskrll #endif
722a6b7db3Sskrll   ds_struct_ptr->allocated = space;
732a6b7db3Sskrll   ds_struct_ptr->length = 0;
742a6b7db3Sskrll   ds_struct_ptr->s[0] = '\0';
752a6b7db3Sskrll 
762a6b7db3Sskrll   return 1;
772a6b7db3Sskrll }
782a6b7db3Sskrll 
792a6b7db3Sskrll /* Create a new dynamic string capable of holding at least SPACE
802a6b7db3Sskrll    characters, including the terminating NUL.  If SPACE is 0, it will
812a6b7db3Sskrll    be silently increased to 1.  If RETURN_ON_ALLOCATION_FAILURE is
822a6b7db3Sskrll    defined and memory allocation fails, returns NULL.  Otherwise
832a6b7db3Sskrll    returns the newly allocated string.  */
842a6b7db3Sskrll 
852a6b7db3Sskrll dyn_string_t
dyn_string_new(int space)862a6b7db3Sskrll dyn_string_new (int space)
872a6b7db3Sskrll {
882a6b7db3Sskrll   dyn_string_t result;
892a6b7db3Sskrll #ifdef RETURN_ON_ALLOCATION_FAILURE
902a6b7db3Sskrll   result = (dyn_string_t) malloc (sizeof (struct dyn_string));
912a6b7db3Sskrll   if (result == NULL)
922a6b7db3Sskrll     return NULL;
932a6b7db3Sskrll   if (!dyn_string_init (result, space))
942a6b7db3Sskrll     {
952a6b7db3Sskrll       free (result);
962a6b7db3Sskrll       return NULL;
972a6b7db3Sskrll     }
982a6b7db3Sskrll #else
992a6b7db3Sskrll   result = XNEW (struct dyn_string);
1002a6b7db3Sskrll   dyn_string_init (result, space);
1012a6b7db3Sskrll #endif
1022a6b7db3Sskrll   return result;
1032a6b7db3Sskrll }
1042a6b7db3Sskrll 
1052a6b7db3Sskrll /* Free the memory used by DS.  */
1062a6b7db3Sskrll 
1072a6b7db3Sskrll void
dyn_string_delete(dyn_string_t ds)1082a6b7db3Sskrll dyn_string_delete (dyn_string_t ds)
1092a6b7db3Sskrll {
1102a6b7db3Sskrll   free (ds->s);
1112a6b7db3Sskrll   free (ds);
1122a6b7db3Sskrll }
1132a6b7db3Sskrll 
1142a6b7db3Sskrll /* Returns the contents of DS in a buffer allocated with malloc.  It
1152a6b7db3Sskrll    is the caller's responsibility to deallocate the buffer using free.
1162a6b7db3Sskrll    DS is then set to the empty string.  Deletes DS itself.  */
1172a6b7db3Sskrll 
1182a6b7db3Sskrll char*
dyn_string_release(dyn_string_t ds)1192a6b7db3Sskrll dyn_string_release (dyn_string_t ds)
1202a6b7db3Sskrll {
1212a6b7db3Sskrll   /* Store the old buffer.  */
1222a6b7db3Sskrll   char* result = ds->s;
1232a6b7db3Sskrll   /* The buffer is no longer owned by DS.  */
1242a6b7db3Sskrll   ds->s = NULL;
1252a6b7db3Sskrll   /* Delete DS.  */
1262a6b7db3Sskrll   free (ds);
1272a6b7db3Sskrll   /* Return the old buffer.  */
1282a6b7db3Sskrll   return result;
1292a6b7db3Sskrll }
1302a6b7db3Sskrll 
1312a6b7db3Sskrll /* Increase the capacity of DS so it can hold at least SPACE
1322a6b7db3Sskrll    characters, plus the terminating NUL.  This function will not (at
1332a6b7db3Sskrll    present) reduce the capacity of DS.  Returns DS on success.
1342a6b7db3Sskrll 
1352a6b7db3Sskrll    If RETURN_ON_ALLOCATION_FAILURE is defined and a memory allocation
1362a6b7db3Sskrll    operation fails, deletes DS and returns NULL.  */
1372a6b7db3Sskrll 
1382a6b7db3Sskrll dyn_string_t
dyn_string_resize(dyn_string_t ds,int space)1392a6b7db3Sskrll dyn_string_resize (dyn_string_t ds, int space)
1402a6b7db3Sskrll {
1412a6b7db3Sskrll   int new_allocated = ds->allocated;
1422a6b7db3Sskrll 
1432a6b7db3Sskrll   /* Increase SPACE to hold the NUL termination.  */
1442a6b7db3Sskrll   ++space;
1452a6b7db3Sskrll 
1462a6b7db3Sskrll   /* Increase allocation by factors of two.  */
1472a6b7db3Sskrll   while (space > new_allocated)
1482a6b7db3Sskrll     new_allocated *= 2;
1492a6b7db3Sskrll 
1502a6b7db3Sskrll   if (new_allocated != ds->allocated)
1512a6b7db3Sskrll     {
1522a6b7db3Sskrll       ds->allocated = new_allocated;
1532a6b7db3Sskrll       /* We actually need more space.  */
1542a6b7db3Sskrll #ifdef RETURN_ON_ALLOCATION_FAILURE
1552a6b7db3Sskrll       ds->s = (char *) realloc (ds->s, ds->allocated);
1562a6b7db3Sskrll       if (ds->s == NULL)
1572a6b7db3Sskrll 	{
1582a6b7db3Sskrll 	  free (ds);
1592a6b7db3Sskrll 	  return NULL;
1602a6b7db3Sskrll 	}
1612a6b7db3Sskrll #else
1622a6b7db3Sskrll       ds->s = XRESIZEVEC (char, ds->s, ds->allocated);
1632a6b7db3Sskrll #endif
1642a6b7db3Sskrll     }
1652a6b7db3Sskrll 
1662a6b7db3Sskrll   return ds;
1672a6b7db3Sskrll }
1682a6b7db3Sskrll 
1692a6b7db3Sskrll /* Sets the contents of DS to the empty string.  */
1702a6b7db3Sskrll 
1712a6b7db3Sskrll void
dyn_string_clear(dyn_string_t ds)1722a6b7db3Sskrll dyn_string_clear (dyn_string_t ds)
1732a6b7db3Sskrll {
1742a6b7db3Sskrll   /* A dyn_string always has room for at least the NUL terminator.  */
1752a6b7db3Sskrll   ds->s[0] = '\0';
1762a6b7db3Sskrll   ds->length = 0;
1772a6b7db3Sskrll }
1782a6b7db3Sskrll 
1792a6b7db3Sskrll /* Makes the contents of DEST the same as the contents of SRC.  DEST
1802a6b7db3Sskrll    and SRC must be distinct.  Returns 1 on success.  On failure, if
1812a6b7db3Sskrll    RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
1822a6b7db3Sskrll 
1832a6b7db3Sskrll int
dyn_string_copy(dyn_string_t dest,dyn_string_t src)1842a6b7db3Sskrll dyn_string_copy (dyn_string_t dest, dyn_string_t src)
1852a6b7db3Sskrll {
1862a6b7db3Sskrll   if (dest == src)
1872a6b7db3Sskrll     abort ();
1882a6b7db3Sskrll 
1892a6b7db3Sskrll   /* Make room in DEST.  */
1902a6b7db3Sskrll   if (dyn_string_resize (dest, src->length) == NULL)
1912a6b7db3Sskrll     return 0;
1922a6b7db3Sskrll   /* Copy DEST into SRC.  */
1932a6b7db3Sskrll   strcpy (dest->s, src->s);
1942a6b7db3Sskrll   /* Update the size of DEST.  */
1952a6b7db3Sskrll   dest->length = src->length;
1962a6b7db3Sskrll   return 1;
1972a6b7db3Sskrll }
1982a6b7db3Sskrll 
1992a6b7db3Sskrll /* Copies SRC, a NUL-terminated string, into DEST.  Returns 1 on
2002a6b7db3Sskrll    success.  On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST
2012a6b7db3Sskrll    and returns 0.  */
2022a6b7db3Sskrll 
2032a6b7db3Sskrll int
dyn_string_copy_cstr(dyn_string_t dest,const char * src)2042a6b7db3Sskrll dyn_string_copy_cstr (dyn_string_t dest, const char *src)
2052a6b7db3Sskrll {
2062a6b7db3Sskrll   int length = strlen (src);
2072a6b7db3Sskrll   /* Make room in DEST.  */
2082a6b7db3Sskrll   if (dyn_string_resize (dest, length) == NULL)
2092a6b7db3Sskrll     return 0;
2102a6b7db3Sskrll   /* Copy DEST into SRC.  */
2112a6b7db3Sskrll   strcpy (dest->s, src);
2122a6b7db3Sskrll   /* Update the size of DEST.  */
2132a6b7db3Sskrll   dest->length = length;
2142a6b7db3Sskrll   return 1;
2152a6b7db3Sskrll }
2162a6b7db3Sskrll 
2172a6b7db3Sskrll /* Inserts SRC at the beginning of DEST.  DEST is expanded as
2182a6b7db3Sskrll    necessary.  SRC and DEST must be distinct.  Returns 1 on success.
2192a6b7db3Sskrll    On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
2202a6b7db3Sskrll    returns 0.  */
2212a6b7db3Sskrll 
2222a6b7db3Sskrll int
dyn_string_prepend(dyn_string_t dest,dyn_string_t src)2232a6b7db3Sskrll dyn_string_prepend (dyn_string_t dest, dyn_string_t src)
2242a6b7db3Sskrll {
2252a6b7db3Sskrll   return dyn_string_insert (dest, 0, src);
2262a6b7db3Sskrll }
2272a6b7db3Sskrll 
2282a6b7db3Sskrll /* Inserts SRC, a NUL-terminated string, at the beginning of DEST.
2292a6b7db3Sskrll    DEST is expanded as necessary.  Returns 1 on success.  On failure,
2302a6b7db3Sskrll    if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */
2312a6b7db3Sskrll 
2322a6b7db3Sskrll int
dyn_string_prepend_cstr(dyn_string_t dest,const char * src)2332a6b7db3Sskrll dyn_string_prepend_cstr (dyn_string_t dest, const char *src)
2342a6b7db3Sskrll {
2352a6b7db3Sskrll   return dyn_string_insert_cstr (dest, 0, src);
2362a6b7db3Sskrll }
2372a6b7db3Sskrll 
2382a6b7db3Sskrll /* Inserts SRC into DEST starting at position POS.  DEST is expanded
2392a6b7db3Sskrll    as necessary.  SRC and DEST must be distinct.  Returns 1 on
2402a6b7db3Sskrll    success.  On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST
2412a6b7db3Sskrll    and returns 0.  */
2422a6b7db3Sskrll 
2432a6b7db3Sskrll int
dyn_string_insert(dyn_string_t dest,int pos,dyn_string_t src)2442a6b7db3Sskrll dyn_string_insert (dyn_string_t dest, int pos, dyn_string_t src)
2452a6b7db3Sskrll {
2462a6b7db3Sskrll   int i;
2472a6b7db3Sskrll 
2482a6b7db3Sskrll   if (src == dest)
2492a6b7db3Sskrll     abort ();
2502a6b7db3Sskrll 
2512a6b7db3Sskrll   if (dyn_string_resize (dest, dest->length + src->length) == NULL)
2522a6b7db3Sskrll     return 0;
2532a6b7db3Sskrll   /* Make room for the insertion.  Be sure to copy the NUL.  */
2542a6b7db3Sskrll   for (i = dest->length; i >= pos; --i)
2552a6b7db3Sskrll     dest->s[i + src->length] = dest->s[i];
2562a6b7db3Sskrll   /* Splice in the new stuff.  */
2572a6b7db3Sskrll   strncpy (dest->s + pos, src->s, src->length);
2582a6b7db3Sskrll   /* Compute the new length.  */
2592a6b7db3Sskrll   dest->length += src->length;
2602a6b7db3Sskrll   return 1;
2612a6b7db3Sskrll }
2622a6b7db3Sskrll 
2632a6b7db3Sskrll /* Inserts SRC, a NUL-terminated string, into DEST starting at
2642a6b7db3Sskrll    position POS.  DEST is expanded as necessary.  Returns 1 on
2652a6b7db3Sskrll    success.  On failure, RETURN_ON_ALLOCATION_FAILURE, deletes DEST
2662a6b7db3Sskrll    and returns 0.  */
2672a6b7db3Sskrll 
2682a6b7db3Sskrll int
dyn_string_insert_cstr(dyn_string_t dest,int pos,const char * src)2692a6b7db3Sskrll dyn_string_insert_cstr (dyn_string_t dest, int pos, const char *src)
2702a6b7db3Sskrll {
2712a6b7db3Sskrll   int i;
2722a6b7db3Sskrll   int length = strlen (src);
2732a6b7db3Sskrll 
2742a6b7db3Sskrll   if (dyn_string_resize (dest, dest->length + length) == NULL)
2752a6b7db3Sskrll     return 0;
2762a6b7db3Sskrll   /* Make room for the insertion.  Be sure to copy the NUL.  */
2772a6b7db3Sskrll   for (i = dest->length; i >= pos; --i)
2782a6b7db3Sskrll     dest->s[i + length] = dest->s[i];
2792a6b7db3Sskrll   /* Splice in the new stuff.  */
280*f22f0ef4Schristos   memcpy (dest->s + pos, src, length);
2812a6b7db3Sskrll   /* Compute the new length.  */
2822a6b7db3Sskrll   dest->length += length;
2832a6b7db3Sskrll   return 1;
2842a6b7db3Sskrll }
2852a6b7db3Sskrll 
2862a6b7db3Sskrll /* Inserts character C into DEST starting at position POS.  DEST is
2872a6b7db3Sskrll    expanded as necessary.  Returns 1 on success.  On failure,
2882a6b7db3Sskrll    RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
2892a6b7db3Sskrll 
2902a6b7db3Sskrll int
dyn_string_insert_char(dyn_string_t dest,int pos,int c)2912a6b7db3Sskrll dyn_string_insert_char (dyn_string_t dest, int pos, int c)
2922a6b7db3Sskrll {
2932a6b7db3Sskrll   int i;
2942a6b7db3Sskrll 
2952a6b7db3Sskrll   if (dyn_string_resize (dest, dest->length + 1) == NULL)
2962a6b7db3Sskrll     return 0;
2972a6b7db3Sskrll   /* Make room for the insertion.  Be sure to copy the NUL.  */
2982a6b7db3Sskrll   for (i = dest->length; i >= pos; --i)
2992a6b7db3Sskrll     dest->s[i + 1] = dest->s[i];
3002a6b7db3Sskrll   /* Add the new character.  */
3012a6b7db3Sskrll   dest->s[pos] = c;
3022a6b7db3Sskrll   /* Compute the new length.  */
3032a6b7db3Sskrll   ++dest->length;
3042a6b7db3Sskrll   return 1;
3052a6b7db3Sskrll }
3062a6b7db3Sskrll 
3072a6b7db3Sskrll /* Append S to DS, resizing DS if necessary.  Returns 1 on success.
3082a6b7db3Sskrll    On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
3092a6b7db3Sskrll    returns 0.  */
3102a6b7db3Sskrll 
3112a6b7db3Sskrll int
dyn_string_append(dyn_string_t dest,dyn_string_t s)3122a6b7db3Sskrll dyn_string_append (dyn_string_t dest, dyn_string_t s)
3132a6b7db3Sskrll {
3142a6b7db3Sskrll   if (dyn_string_resize (dest, dest->length + s->length) == 0)
3152a6b7db3Sskrll     return 0;
3162a6b7db3Sskrll   strcpy (dest->s + dest->length, s->s);
3172a6b7db3Sskrll   dest->length += s->length;
3182a6b7db3Sskrll   return 1;
3192a6b7db3Sskrll }
3202a6b7db3Sskrll 
3212a6b7db3Sskrll /* Append the NUL-terminated string S to DS, resizing DS if necessary.
3222a6b7db3Sskrll    Returns 1 on success.  On failure, if RETURN_ON_ALLOCATION_FAILURE,
3232a6b7db3Sskrll    deletes DEST and returns 0.  */
3242a6b7db3Sskrll 
3252a6b7db3Sskrll int
dyn_string_append_cstr(dyn_string_t dest,const char * s)3262a6b7db3Sskrll dyn_string_append_cstr (dyn_string_t dest, const char *s)
3272a6b7db3Sskrll {
3282a6b7db3Sskrll   int len = strlen (s);
3292a6b7db3Sskrll 
3302a6b7db3Sskrll   /* The new length is the old length plus the size of our string, plus
3312a6b7db3Sskrll      one for the null at the end.  */
3322a6b7db3Sskrll   if (dyn_string_resize (dest, dest->length + len) == NULL)
3332a6b7db3Sskrll     return 0;
3342a6b7db3Sskrll   strcpy (dest->s + dest->length, s);
3352a6b7db3Sskrll   dest->length += len;
3362a6b7db3Sskrll   return 1;
3372a6b7db3Sskrll }
3382a6b7db3Sskrll 
339b3ac4aedSchristos /* Appends C to the end of DEST.  Returns 1 on success.  On failure,
3402a6b7db3Sskrll    if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
3412a6b7db3Sskrll 
3422a6b7db3Sskrll int
dyn_string_append_char(dyn_string_t dest,int c)3432a6b7db3Sskrll dyn_string_append_char (dyn_string_t dest, int c)
3442a6b7db3Sskrll {
3452a6b7db3Sskrll   /* Make room for the extra character.  */
3462a6b7db3Sskrll   if (dyn_string_resize (dest, dest->length + 1) == NULL)
3472a6b7db3Sskrll     return 0;
3482a6b7db3Sskrll   /* Append the character; it will overwrite the old NUL.  */
3492a6b7db3Sskrll   dest->s[dest->length] = c;
3502a6b7db3Sskrll   /* Add a new NUL at the end.  */
3512a6b7db3Sskrll   dest->s[dest->length + 1] = '\0';
3522a6b7db3Sskrll   /* Update the length.  */
3532a6b7db3Sskrll   ++(dest->length);
3542a6b7db3Sskrll   return 1;
3552a6b7db3Sskrll }
3562a6b7db3Sskrll 
3572a6b7db3Sskrll /* Sets the contents of DEST to the substring of SRC starting at START
3582a6b7db3Sskrll    and ending before END.  START must be less than or equal to END,
3592a6b7db3Sskrll    and both must be between zero and the length of SRC, inclusive.
3602a6b7db3Sskrll    Returns 1 on success.  On failure, if RETURN_ON_ALLOCATION_FAILURE,
3612a6b7db3Sskrll    deletes DEST and returns 0.  */
3622a6b7db3Sskrll 
3632a6b7db3Sskrll int
dyn_string_substring(dyn_string_t dest,dyn_string_t src,int start,int end)3642a6b7db3Sskrll dyn_string_substring (dyn_string_t dest, dyn_string_t src,
3652a6b7db3Sskrll                       int start, int end)
3662a6b7db3Sskrll {
3672a6b7db3Sskrll   int i;
3682a6b7db3Sskrll   int length = end - start;
3692a6b7db3Sskrll 
3702a6b7db3Sskrll   if (start > end || start > src->length || end > src->length)
3712a6b7db3Sskrll     abort ();
3722a6b7db3Sskrll 
3732a6b7db3Sskrll   /* Make room for the substring.  */
3742a6b7db3Sskrll   if (dyn_string_resize (dest, length) == NULL)
3752a6b7db3Sskrll     return 0;
3762a6b7db3Sskrll   /* Copy the characters in the substring,  */
3772a6b7db3Sskrll   for (i = length; --i >= 0; )
3782a6b7db3Sskrll     dest->s[i] = src->s[start + i];
3792a6b7db3Sskrll   /* NUL-terimate the result.  */
3802a6b7db3Sskrll   dest->s[length] = '\0';
3812a6b7db3Sskrll   /* Record the length of the substring.  */
3822a6b7db3Sskrll   dest->length = length;
3832a6b7db3Sskrll 
3842a6b7db3Sskrll   return 1;
3852a6b7db3Sskrll }
3862a6b7db3Sskrll 
3872a6b7db3Sskrll /* Returns non-zero if DS1 and DS2 have the same contents.  */
3882a6b7db3Sskrll 
3892a6b7db3Sskrll int
dyn_string_eq(dyn_string_t ds1,dyn_string_t ds2)3902a6b7db3Sskrll dyn_string_eq (dyn_string_t ds1, dyn_string_t ds2)
3912a6b7db3Sskrll {
3922a6b7db3Sskrll   /* If DS1 and DS2 have different lengths, they must not be the same.  */
3932a6b7db3Sskrll   if (ds1->length != ds2->length)
3942a6b7db3Sskrll     return 0;
3952a6b7db3Sskrll   else
3962a6b7db3Sskrll     return !strcmp (ds1->s, ds2->s);
3972a6b7db3Sskrll }
398