xref: /netbsd-src/external/gpl3/gcc.old/dist/libiberty/dyn-string.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* An abstract string datatype.
2*8feb0f0bSmrg    Copyright (C) 1998-2020 Free Software Foundation, Inc.
31debfc3dSmrg    Contributed by Mark Mitchell (mark@markmitchell.com).
41debfc3dSmrg 
51debfc3dSmrg This file is part of GNU CC.
61debfc3dSmrg 
71debfc3dSmrg GNU CC is free software; you can redistribute it and/or modify
81debfc3dSmrg it under the terms of the GNU General Public License as published by
91debfc3dSmrg the Free Software Foundation; either version 2, or (at your option)
101debfc3dSmrg any later version.
111debfc3dSmrg 
121debfc3dSmrg In addition to the permissions in the GNU General Public License, the
131debfc3dSmrg Free Software Foundation gives you unlimited permission to link the
141debfc3dSmrg compiled version of this file into combinations with other programs,
151debfc3dSmrg and to distribute those combinations without any restriction coming
161debfc3dSmrg from the use of this file.  (The General Public License restrictions
171debfc3dSmrg do apply in other respects; for example, they cover modification of
181debfc3dSmrg the file, and distribution when not linked into a combined
191debfc3dSmrg executable.)
201debfc3dSmrg 
211debfc3dSmrg GNU CC is distributed in the hope that it will be useful,
221debfc3dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
231debfc3dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
241debfc3dSmrg GNU General Public License for more details.
251debfc3dSmrg 
261debfc3dSmrg You should have received a copy of the GNU General Public License
271debfc3dSmrg along with GNU CC; see the file COPYING.  If not, write to
281debfc3dSmrg the Free Software Foundation, 51 Franklin Street - Fifth Floor,
291debfc3dSmrg Boston, MA 02110-1301, USA.  */
301debfc3dSmrg 
311debfc3dSmrg #ifdef HAVE_CONFIG_H
321debfc3dSmrg #include "config.h"
331debfc3dSmrg #endif
341debfc3dSmrg 
351debfc3dSmrg #include <stdio.h>
361debfc3dSmrg 
371debfc3dSmrg #ifdef HAVE_STRING_H
381debfc3dSmrg #include <string.h>
391debfc3dSmrg #endif
401debfc3dSmrg 
411debfc3dSmrg #ifdef HAVE_STDLIB_H
421debfc3dSmrg #include <stdlib.h>
431debfc3dSmrg #endif
441debfc3dSmrg 
451debfc3dSmrg #include "libiberty.h"
461debfc3dSmrg #include "dyn-string.h"
471debfc3dSmrg 
481debfc3dSmrg /* Performs in-place initialization of a dyn_string struct.  This
491debfc3dSmrg    function can be used with a dyn_string struct on the stack or
501debfc3dSmrg    embedded in another object.  The contents of of the string itself
511debfc3dSmrg    are still dynamically allocated.  The string initially is capable
521debfc3dSmrg    of holding at least SPACE characeters, including the terminating
531debfc3dSmrg    NUL.  If SPACE is 0, it will silently be increated to 1.
541debfc3dSmrg 
551debfc3dSmrg    If RETURN_ON_ALLOCATION_FAILURE is defined and memory allocation
561debfc3dSmrg    fails, returns 0.  Otherwise returns 1.  */
571debfc3dSmrg 
581debfc3dSmrg int
dyn_string_init(struct dyn_string * ds_struct_ptr,int space)591debfc3dSmrg dyn_string_init (struct dyn_string *ds_struct_ptr, int space)
601debfc3dSmrg {
611debfc3dSmrg   /* We need at least one byte in which to store the terminating NUL.  */
621debfc3dSmrg   if (space == 0)
631debfc3dSmrg     space = 1;
641debfc3dSmrg 
651debfc3dSmrg #ifdef RETURN_ON_ALLOCATION_FAILURE
661debfc3dSmrg   ds_struct_ptr->s = (char *) malloc (space);
671debfc3dSmrg   if (ds_struct_ptr->s == NULL)
681debfc3dSmrg     return 0;
691debfc3dSmrg #else
701debfc3dSmrg   ds_struct_ptr->s = XNEWVEC (char, space);
711debfc3dSmrg #endif
721debfc3dSmrg   ds_struct_ptr->allocated = space;
731debfc3dSmrg   ds_struct_ptr->length = 0;
741debfc3dSmrg   ds_struct_ptr->s[0] = '\0';
751debfc3dSmrg 
761debfc3dSmrg   return 1;
771debfc3dSmrg }
781debfc3dSmrg 
791debfc3dSmrg /* Create a new dynamic string capable of holding at least SPACE
801debfc3dSmrg    characters, including the terminating NUL.  If SPACE is 0, it will
811debfc3dSmrg    be silently increased to 1.  If RETURN_ON_ALLOCATION_FAILURE is
821debfc3dSmrg    defined and memory allocation fails, returns NULL.  Otherwise
831debfc3dSmrg    returns the newly allocated string.  */
841debfc3dSmrg 
851debfc3dSmrg dyn_string_t
dyn_string_new(int space)861debfc3dSmrg dyn_string_new (int space)
871debfc3dSmrg {
881debfc3dSmrg   dyn_string_t result;
891debfc3dSmrg #ifdef RETURN_ON_ALLOCATION_FAILURE
901debfc3dSmrg   result = (dyn_string_t) malloc (sizeof (struct dyn_string));
911debfc3dSmrg   if (result == NULL)
921debfc3dSmrg     return NULL;
931debfc3dSmrg   if (!dyn_string_init (result, space))
941debfc3dSmrg     {
951debfc3dSmrg       free (result);
961debfc3dSmrg       return NULL;
971debfc3dSmrg     }
981debfc3dSmrg #else
991debfc3dSmrg   result = XNEW (struct dyn_string);
1001debfc3dSmrg   dyn_string_init (result, space);
1011debfc3dSmrg #endif
1021debfc3dSmrg   return result;
1031debfc3dSmrg }
1041debfc3dSmrg 
1051debfc3dSmrg /* Free the memory used by DS.  */
1061debfc3dSmrg 
1071debfc3dSmrg void
dyn_string_delete(dyn_string_t ds)1081debfc3dSmrg dyn_string_delete (dyn_string_t ds)
1091debfc3dSmrg {
1101debfc3dSmrg   free (ds->s);
1111debfc3dSmrg   free (ds);
1121debfc3dSmrg }
1131debfc3dSmrg 
1141debfc3dSmrg /* Returns the contents of DS in a buffer allocated with malloc.  It
1151debfc3dSmrg    is the caller's responsibility to deallocate the buffer using free.
1161debfc3dSmrg    DS is then set to the empty string.  Deletes DS itself.  */
1171debfc3dSmrg 
1181debfc3dSmrg char*
dyn_string_release(dyn_string_t ds)1191debfc3dSmrg dyn_string_release (dyn_string_t ds)
1201debfc3dSmrg {
1211debfc3dSmrg   /* Store the old buffer.  */
1221debfc3dSmrg   char* result = ds->s;
1231debfc3dSmrg   /* The buffer is no longer owned by DS.  */
1241debfc3dSmrg   ds->s = NULL;
1251debfc3dSmrg   /* Delete DS.  */
1261debfc3dSmrg   free (ds);
1271debfc3dSmrg   /* Return the old buffer.  */
1281debfc3dSmrg   return result;
1291debfc3dSmrg }
1301debfc3dSmrg 
1311debfc3dSmrg /* Increase the capacity of DS so it can hold at least SPACE
1321debfc3dSmrg    characters, plus the terminating NUL.  This function will not (at
1331debfc3dSmrg    present) reduce the capacity of DS.  Returns DS on success.
1341debfc3dSmrg 
1351debfc3dSmrg    If RETURN_ON_ALLOCATION_FAILURE is defined and a memory allocation
1361debfc3dSmrg    operation fails, deletes DS and returns NULL.  */
1371debfc3dSmrg 
1381debfc3dSmrg dyn_string_t
dyn_string_resize(dyn_string_t ds,int space)1391debfc3dSmrg dyn_string_resize (dyn_string_t ds, int space)
1401debfc3dSmrg {
1411debfc3dSmrg   int new_allocated = ds->allocated;
1421debfc3dSmrg 
1431debfc3dSmrg   /* Increase SPACE to hold the NUL termination.  */
1441debfc3dSmrg   ++space;
1451debfc3dSmrg 
1461debfc3dSmrg   /* Increase allocation by factors of two.  */
1471debfc3dSmrg   while (space > new_allocated)
1481debfc3dSmrg     new_allocated *= 2;
1491debfc3dSmrg 
1501debfc3dSmrg   if (new_allocated != ds->allocated)
1511debfc3dSmrg     {
1521debfc3dSmrg       ds->allocated = new_allocated;
1531debfc3dSmrg       /* We actually need more space.  */
1541debfc3dSmrg #ifdef RETURN_ON_ALLOCATION_FAILURE
1551debfc3dSmrg       ds->s = (char *) realloc (ds->s, ds->allocated);
1561debfc3dSmrg       if (ds->s == NULL)
1571debfc3dSmrg 	{
1581debfc3dSmrg 	  free (ds);
1591debfc3dSmrg 	  return NULL;
1601debfc3dSmrg 	}
1611debfc3dSmrg #else
1621debfc3dSmrg       ds->s = XRESIZEVEC (char, ds->s, ds->allocated);
1631debfc3dSmrg #endif
1641debfc3dSmrg     }
1651debfc3dSmrg 
1661debfc3dSmrg   return ds;
1671debfc3dSmrg }
1681debfc3dSmrg 
1691debfc3dSmrg /* Sets the contents of DS to the empty string.  */
1701debfc3dSmrg 
1711debfc3dSmrg void
dyn_string_clear(dyn_string_t ds)1721debfc3dSmrg dyn_string_clear (dyn_string_t ds)
1731debfc3dSmrg {
1741debfc3dSmrg   /* A dyn_string always has room for at least the NUL terminator.  */
1751debfc3dSmrg   ds->s[0] = '\0';
1761debfc3dSmrg   ds->length = 0;
1771debfc3dSmrg }
1781debfc3dSmrg 
1791debfc3dSmrg /* Makes the contents of DEST the same as the contents of SRC.  DEST
1801debfc3dSmrg    and SRC must be distinct.  Returns 1 on success.  On failure, if
1811debfc3dSmrg    RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
1821debfc3dSmrg 
1831debfc3dSmrg int
dyn_string_copy(dyn_string_t dest,dyn_string_t src)1841debfc3dSmrg dyn_string_copy (dyn_string_t dest, dyn_string_t src)
1851debfc3dSmrg {
1861debfc3dSmrg   if (dest == src)
1871debfc3dSmrg     abort ();
1881debfc3dSmrg 
1891debfc3dSmrg   /* Make room in DEST.  */
1901debfc3dSmrg   if (dyn_string_resize (dest, src->length) == NULL)
1911debfc3dSmrg     return 0;
1921debfc3dSmrg   /* Copy DEST into SRC.  */
1931debfc3dSmrg   strcpy (dest->s, src->s);
1941debfc3dSmrg   /* Update the size of DEST.  */
1951debfc3dSmrg   dest->length = src->length;
1961debfc3dSmrg   return 1;
1971debfc3dSmrg }
1981debfc3dSmrg 
1991debfc3dSmrg /* Copies SRC, a NUL-terminated string, into DEST.  Returns 1 on
2001debfc3dSmrg    success.  On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST
2011debfc3dSmrg    and returns 0.  */
2021debfc3dSmrg 
2031debfc3dSmrg int
dyn_string_copy_cstr(dyn_string_t dest,const char * src)2041debfc3dSmrg dyn_string_copy_cstr (dyn_string_t dest, const char *src)
2051debfc3dSmrg {
2061debfc3dSmrg   int length = strlen (src);
2071debfc3dSmrg   /* Make room in DEST.  */
2081debfc3dSmrg   if (dyn_string_resize (dest, length) == NULL)
2091debfc3dSmrg     return 0;
2101debfc3dSmrg   /* Copy DEST into SRC.  */
2111debfc3dSmrg   strcpy (dest->s, src);
2121debfc3dSmrg   /* Update the size of DEST.  */
2131debfc3dSmrg   dest->length = length;
2141debfc3dSmrg   return 1;
2151debfc3dSmrg }
2161debfc3dSmrg 
2171debfc3dSmrg /* Inserts SRC at the beginning of DEST.  DEST is expanded as
2181debfc3dSmrg    necessary.  SRC and DEST must be distinct.  Returns 1 on success.
2191debfc3dSmrg    On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
2201debfc3dSmrg    returns 0.  */
2211debfc3dSmrg 
2221debfc3dSmrg int
dyn_string_prepend(dyn_string_t dest,dyn_string_t src)2231debfc3dSmrg dyn_string_prepend (dyn_string_t dest, dyn_string_t src)
2241debfc3dSmrg {
2251debfc3dSmrg   return dyn_string_insert (dest, 0, src);
2261debfc3dSmrg }
2271debfc3dSmrg 
2281debfc3dSmrg /* Inserts SRC, a NUL-terminated string, at the beginning of DEST.
2291debfc3dSmrg    DEST is expanded as necessary.  Returns 1 on success.  On failure,
2301debfc3dSmrg    if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */
2311debfc3dSmrg 
2321debfc3dSmrg int
dyn_string_prepend_cstr(dyn_string_t dest,const char * src)2331debfc3dSmrg dyn_string_prepend_cstr (dyn_string_t dest, const char *src)
2341debfc3dSmrg {
2351debfc3dSmrg   return dyn_string_insert_cstr (dest, 0, src);
2361debfc3dSmrg }
2371debfc3dSmrg 
2381debfc3dSmrg /* Inserts SRC into DEST starting at position POS.  DEST is expanded
2391debfc3dSmrg    as necessary.  SRC and DEST must be distinct.  Returns 1 on
2401debfc3dSmrg    success.  On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST
2411debfc3dSmrg    and returns 0.  */
2421debfc3dSmrg 
2431debfc3dSmrg int
dyn_string_insert(dyn_string_t dest,int pos,dyn_string_t src)2441debfc3dSmrg dyn_string_insert (dyn_string_t dest, int pos, dyn_string_t src)
2451debfc3dSmrg {
2461debfc3dSmrg   int i;
2471debfc3dSmrg 
2481debfc3dSmrg   if (src == dest)
2491debfc3dSmrg     abort ();
2501debfc3dSmrg 
2511debfc3dSmrg   if (dyn_string_resize (dest, dest->length + src->length) == NULL)
2521debfc3dSmrg     return 0;
2531debfc3dSmrg   /* Make room for the insertion.  Be sure to copy the NUL.  */
2541debfc3dSmrg   for (i = dest->length; i >= pos; --i)
2551debfc3dSmrg     dest->s[i + src->length] = dest->s[i];
2561debfc3dSmrg   /* Splice in the new stuff.  */
2571debfc3dSmrg   strncpy (dest->s + pos, src->s, src->length);
2581debfc3dSmrg   /* Compute the new length.  */
2591debfc3dSmrg   dest->length += src->length;
2601debfc3dSmrg   return 1;
2611debfc3dSmrg }
2621debfc3dSmrg 
2631debfc3dSmrg /* Inserts SRC, a NUL-terminated string, into DEST starting at
2641debfc3dSmrg    position POS.  DEST is expanded as necessary.  Returns 1 on
2651debfc3dSmrg    success.  On failure, RETURN_ON_ALLOCATION_FAILURE, deletes DEST
2661debfc3dSmrg    and returns 0.  */
2671debfc3dSmrg 
2681debfc3dSmrg int
dyn_string_insert_cstr(dyn_string_t dest,int pos,const char * src)2691debfc3dSmrg dyn_string_insert_cstr (dyn_string_t dest, int pos, const char *src)
2701debfc3dSmrg {
2711debfc3dSmrg   int i;
2721debfc3dSmrg   int length = strlen (src);
2731debfc3dSmrg 
2741debfc3dSmrg   if (dyn_string_resize (dest, dest->length + length) == NULL)
2751debfc3dSmrg     return 0;
2761debfc3dSmrg   /* Make room for the insertion.  Be sure to copy the NUL.  */
2771debfc3dSmrg   for (i = dest->length; i >= pos; --i)
2781debfc3dSmrg     dest->s[i + length] = dest->s[i];
2791debfc3dSmrg   /* Splice in the new stuff.  */
2801debfc3dSmrg   strncpy (dest->s + pos, src, length);
2811debfc3dSmrg   /* Compute the new length.  */
2821debfc3dSmrg   dest->length += length;
2831debfc3dSmrg   return 1;
2841debfc3dSmrg }
2851debfc3dSmrg 
2861debfc3dSmrg /* Inserts character C into DEST starting at position POS.  DEST is
2871debfc3dSmrg    expanded as necessary.  Returns 1 on success.  On failure,
2881debfc3dSmrg    RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
2891debfc3dSmrg 
2901debfc3dSmrg int
dyn_string_insert_char(dyn_string_t dest,int pos,int c)2911debfc3dSmrg dyn_string_insert_char (dyn_string_t dest, int pos, int c)
2921debfc3dSmrg {
2931debfc3dSmrg   int i;
2941debfc3dSmrg 
2951debfc3dSmrg   if (dyn_string_resize (dest, dest->length + 1) == NULL)
2961debfc3dSmrg     return 0;
2971debfc3dSmrg   /* Make room for the insertion.  Be sure to copy the NUL.  */
2981debfc3dSmrg   for (i = dest->length; i >= pos; --i)
2991debfc3dSmrg     dest->s[i + 1] = dest->s[i];
3001debfc3dSmrg   /* Add the new character.  */
3011debfc3dSmrg   dest->s[pos] = c;
3021debfc3dSmrg   /* Compute the new length.  */
3031debfc3dSmrg   ++dest->length;
3041debfc3dSmrg   return 1;
3051debfc3dSmrg }
3061debfc3dSmrg 
3071debfc3dSmrg /* Append S to DS, resizing DS if necessary.  Returns 1 on success.
3081debfc3dSmrg    On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
3091debfc3dSmrg    returns 0.  */
3101debfc3dSmrg 
3111debfc3dSmrg int
dyn_string_append(dyn_string_t dest,dyn_string_t s)3121debfc3dSmrg dyn_string_append (dyn_string_t dest, dyn_string_t s)
3131debfc3dSmrg {
3141debfc3dSmrg   if (dyn_string_resize (dest, dest->length + s->length) == 0)
3151debfc3dSmrg     return 0;
3161debfc3dSmrg   strcpy (dest->s + dest->length, s->s);
3171debfc3dSmrg   dest->length += s->length;
3181debfc3dSmrg   return 1;
3191debfc3dSmrg }
3201debfc3dSmrg 
3211debfc3dSmrg /* Append the NUL-terminated string S to DS, resizing DS if necessary.
3221debfc3dSmrg    Returns 1 on success.  On failure, if RETURN_ON_ALLOCATION_FAILURE,
3231debfc3dSmrg    deletes DEST and returns 0.  */
3241debfc3dSmrg 
3251debfc3dSmrg int
dyn_string_append_cstr(dyn_string_t dest,const char * s)3261debfc3dSmrg dyn_string_append_cstr (dyn_string_t dest, const char *s)
3271debfc3dSmrg {
3281debfc3dSmrg   int len = strlen (s);
3291debfc3dSmrg 
3301debfc3dSmrg   /* The new length is the old length plus the size of our string, plus
3311debfc3dSmrg      one for the null at the end.  */
3321debfc3dSmrg   if (dyn_string_resize (dest, dest->length + len) == NULL)
3331debfc3dSmrg     return 0;
3341debfc3dSmrg   strcpy (dest->s + dest->length, s);
3351debfc3dSmrg   dest->length += len;
3361debfc3dSmrg   return 1;
3371debfc3dSmrg }
3381debfc3dSmrg 
3391debfc3dSmrg /* Appends C to the end of DEST.  Returns 1 on success.  On failure,
3401debfc3dSmrg    if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
3411debfc3dSmrg 
3421debfc3dSmrg int
dyn_string_append_char(dyn_string_t dest,int c)3431debfc3dSmrg dyn_string_append_char (dyn_string_t dest, int c)
3441debfc3dSmrg {
3451debfc3dSmrg   /* Make room for the extra character.  */
3461debfc3dSmrg   if (dyn_string_resize (dest, dest->length + 1) == NULL)
3471debfc3dSmrg     return 0;
3481debfc3dSmrg   /* Append the character; it will overwrite the old NUL.  */
3491debfc3dSmrg   dest->s[dest->length] = c;
3501debfc3dSmrg   /* Add a new NUL at the end.  */
3511debfc3dSmrg   dest->s[dest->length + 1] = '\0';
3521debfc3dSmrg   /* Update the length.  */
3531debfc3dSmrg   ++(dest->length);
3541debfc3dSmrg   return 1;
3551debfc3dSmrg }
3561debfc3dSmrg 
3571debfc3dSmrg /* Sets the contents of DEST to the substring of SRC starting at START
3581debfc3dSmrg    and ending before END.  START must be less than or equal to END,
3591debfc3dSmrg    and both must be between zero and the length of SRC, inclusive.
3601debfc3dSmrg    Returns 1 on success.  On failure, if RETURN_ON_ALLOCATION_FAILURE,
3611debfc3dSmrg    deletes DEST and returns 0.  */
3621debfc3dSmrg 
3631debfc3dSmrg int
dyn_string_substring(dyn_string_t dest,dyn_string_t src,int start,int end)3641debfc3dSmrg dyn_string_substring (dyn_string_t dest, dyn_string_t src,
3651debfc3dSmrg                       int start, int end)
3661debfc3dSmrg {
3671debfc3dSmrg   int i;
3681debfc3dSmrg   int length = end - start;
3691debfc3dSmrg 
3701debfc3dSmrg   if (start > end || start > src->length || end > src->length)
3711debfc3dSmrg     abort ();
3721debfc3dSmrg 
3731debfc3dSmrg   /* Make room for the substring.  */
3741debfc3dSmrg   if (dyn_string_resize (dest, length) == NULL)
3751debfc3dSmrg     return 0;
3761debfc3dSmrg   /* Copy the characters in the substring,  */
3771debfc3dSmrg   for (i = length; --i >= 0; )
3781debfc3dSmrg     dest->s[i] = src->s[start + i];
3791debfc3dSmrg   /* NUL-terimate the result.  */
3801debfc3dSmrg   dest->s[length] = '\0';
3811debfc3dSmrg   /* Record the length of the substring.  */
3821debfc3dSmrg   dest->length = length;
3831debfc3dSmrg 
3841debfc3dSmrg   return 1;
3851debfc3dSmrg }
3861debfc3dSmrg 
3871debfc3dSmrg /* Returns non-zero if DS1 and DS2 have the same contents.  */
3881debfc3dSmrg 
3891debfc3dSmrg int
dyn_string_eq(dyn_string_t ds1,dyn_string_t ds2)3901debfc3dSmrg dyn_string_eq (dyn_string_t ds1, dyn_string_t ds2)
3911debfc3dSmrg {
3921debfc3dSmrg   /* If DS1 and DS2 have different lengths, they must not be the same.  */
3931debfc3dSmrg   if (ds1->length != ds2->length)
3941debfc3dSmrg     return 0;
3951debfc3dSmrg   else
3961debfc3dSmrg     return !strcmp (ds1->s, ds2->s);
3971debfc3dSmrg }
398