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