blob: aaa7e363194fc2d5211e9bdcc50958f8cfb0caaa [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001/* An abstract string datatype.
2 Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
3 Contributed by Mark Mitchell (mark@markmitchell.com).
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25
26#ifdef HAVE_STRING_H
27#include <string.h>
28#endif
29
30#ifdef HAVE_STDLIB_H
31#include <stdlib.h>
32#endif
33
34#include "vg_include.h"
35#include "ansidecl.h"
36#include "dyn-string.h"
37
38#ifndef STANDALONE
39#define malloc(s) VG_(malloc)(VG_AR_DEMANGLE, s)
40#define free(p) VG_(free)(VG_AR_DEMANGLE, p)
41#define realloc(p,s) VG_(realloc)(VG_AR_DEMANGLE, p, s)
42#endif
43
44/* If this file is being compiled for inclusion in the C++ runtime
45 library, as part of the demangler implementation, we don't want to
46 abort if an allocation fails. Instead, percolate an error code up
47 through the call chain. */
48
49#ifdef IN_LIBGCC2
50#define RETURN_ON_ALLOCATION_FAILURE
51#endif
52
53/* Performs in-place initialization of a dyn_string struct. This
54 function can be used with a dyn_string struct on the stack or
55 embedded in another object. The contents of of the string itself
56 are still dynamically allocated. The string initially is capable
57 of holding at least SPACE characeters, including the terminating
58 NUL. If SPACE is 0, it will silently be increated to 1.
59
60 If RETURN_ON_ALLOCATION_FAILURE is defined and memory allocation
61 fails, returns 0. Otherwise returns 1. */
62
63int
64dyn_string_init (ds_struct_ptr, space)
65 struct dyn_string *ds_struct_ptr;
66 int space;
67{
68 /* We need at least one byte in which to store the terminating NUL. */
69 if (space == 0)
70 space = 1;
71
72#ifdef RETURN_ON_ALLOCATION_FAILURE
73 ds_struct_ptr->s = (char *) malloc (space);
74 if (ds_struct_ptr->s == NULL)
75 return 0;
76#else
77 ds_struct_ptr->s = (char *) malloc (space);
78#endif
79 ds_struct_ptr->allocated = space;
80 ds_struct_ptr->length = 0;
81 ds_struct_ptr->s[0] = '\0';
82
83 return 1;
84}
85
86/* Create a new dynamic string capable of holding at least SPACE
87 characters, including the terminating NUL. If SPACE is 0, it will
88 be silently increased to 1. If RETURN_ON_ALLOCATION_FAILURE is
89 defined and memory allocation fails, returns NULL. Otherwise
90 returns the newly allocated string. */
91
92dyn_string_t
93dyn_string_new (space)
94 int space;
95{
96 dyn_string_t result;
97#ifdef RETURN_ON_ALLOCATION_FAILURE
98 result = (dyn_string_t) malloc (sizeof (struct dyn_string));
99 if (result == NULL)
100 return NULL;
101 if (!dyn_string_init (result, space))
102 {
103 free (result);
104 return NULL;
105 }
106#else
107 result = (dyn_string_t) malloc (sizeof (struct dyn_string));
108 dyn_string_init (result, space);
109#endif
110 return result;
111}
112
113/* Free the memory used by DS. */
114
115void
116dyn_string_delete (ds)
117 dyn_string_t ds;
118{
119 free (ds->s);
120 free (ds);
121}
122
123/* Returns the contents of DS in a buffer allocated with malloc. It
124 is the caller's responsibility to deallocate the buffer using free.
125 DS is then set to the empty string. Deletes DS itself. */
126
127char*
128dyn_string_release (ds)
129 dyn_string_t ds;
130{
131 /* Store the old buffer. */
132 char* result = ds->s;
133 /* The buffer is no longer owned by DS. */
134 ds->s = NULL;
135 /* Delete DS. */
136 free (ds);
137 /* Return the old buffer. */
138 return result;
139}
140
141/* Increase the capacity of DS so it can hold at least SPACE
142 characters, plus the terminating NUL. This function will not (at
143 present) reduce the capacity of DS. Returns DS on success.
144
145 If RETURN_ON_ALLOCATION_FAILURE is defined and a memory allocation
146 operation fails, deletes DS and returns NULL. */
147
148dyn_string_t
149dyn_string_resize (ds, space)
150 dyn_string_t ds;
151 int space;
152{
153 int new_allocated = ds->allocated;
154
155 /* Increase SPACE to hold the NUL termination. */
156 ++space;
157
158 /* Increase allocation by factors of two. */
159 while (space > new_allocated)
160 new_allocated *= 2;
161
162 if (new_allocated != ds->allocated)
163 {
164 ds->allocated = new_allocated;
165 /* We actually need more space. */
166#ifdef RETURN_ON_ALLOCATION_FAILURE
167 ds->s = (char *) realloc (ds->s, ds->allocated);
168 if (ds->s == NULL)
169 {
170 free (ds);
171 return NULL;
172 }
173#else
174 ds->s = (char *) realloc (ds->s, ds->allocated);
175#endif
176 }
177
178 return ds;
179}
180
181/* Sets the contents of DS to the empty string. */
182
183void
184dyn_string_clear (ds)
185 dyn_string_t ds;
186{
187 /* A dyn_string always has room for at least the NUL terminator. */
188 ds->s[0] = '\0';
189 ds->length = 0;
190}
191
192/* Makes the contents of DEST the same as the contents of SRC. DEST
193 and SRC must be distinct. Returns 1 on success. On failure, if
194 RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */
195
196int
197dyn_string_copy (dest, src)
198 dyn_string_t dest;
199 dyn_string_t src;
200{
201 if (dest == src)
202 VG_(panic) ("dyn_string_copy: src==dest");
203
204 /* Make room in DEST. */
205 if (dyn_string_resize (dest, src->length) == NULL)
206 return 0;
207 /* Copy DEST into SRC. */
208 VG_(strcpy) (dest->s, src->s);
209 /* Update the size of DEST. */
210 dest->length = src->length;
211 return 1;
212}
213
214/* Copies SRC, a NUL-terminated string, into DEST. Returns 1 on
215 success. On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST
216 and returns 0. */
217
218int
219dyn_string_copy_cstr (dest, src)
220 dyn_string_t dest;
221 const char *src;
222{
223 int length = VG_(strlen) (src);
224 /* Make room in DEST. */
225 if (dyn_string_resize (dest, length) == NULL)
226 return 0;
227 /* Copy DEST into SRC. */
228 VG_(strcpy) (dest->s, src);
229 /* Update the size of DEST. */
230 dest->length = length;
231 return 1;
232}
233
234/* Inserts SRC at the beginning of DEST. DEST is expanded as
235 necessary. SRC and DEST must be distinct. Returns 1 on success.
236 On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
237 returns 0. */
238
239int
240dyn_string_prepend (dest, src)
241 dyn_string_t dest;
242 dyn_string_t src;
243{
244 return dyn_string_insert (dest, 0, src);
245}
246
247/* Inserts SRC, a NUL-terminated string, at the beginning of DEST.
248 DEST is expanded as necessary. Returns 1 on success. On failure,
249 if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */
250
251int
252dyn_string_prepend_cstr (dest, src)
253 dyn_string_t dest;
254 const char *src;
255{
256 return dyn_string_insert_cstr (dest, 0, src);
257}
258
259/* Inserts SRC into DEST starting at position POS. DEST is expanded
260 as necessary. SRC and DEST must be distinct. Returns 1 on
261 success. On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST
262 and returns 0. */
263
264int
265dyn_string_insert (dest, pos, src)
266 dyn_string_t dest;
267 int pos;
268 dyn_string_t src;
269{
270 int i;
271
272 if (src == dest)
273 VG_(panic)( "dyn_string_insert: src==dest" );
274
275 if (dyn_string_resize (dest, dest->length + src->length) == NULL)
276 return 0;
277 /* Make room for the insertion. Be sure to copy the NUL. */
278 for (i = dest->length; i >= pos; --i)
279 dest->s[i + src->length] = dest->s[i];
280 /* Splice in the new stuff. */
281 VG_(strncpy) (dest->s + pos, src->s, src->length);
282 /* Compute the new length. */
283 dest->length += src->length;
284 return 1;
285}
286
287/* Inserts SRC, a NUL-terminated string, into DEST starting at
288 position POS. DEST is expanded as necessary. Returns 1 on
289 success. On failure, RETURN_ON_ALLOCATION_FAILURE, deletes DEST
290 and returns 0. */
291
292int
293dyn_string_insert_cstr (dest, pos, src)
294 dyn_string_t dest;
295 int pos;
296 const char *src;
297{
298 int i;
299 int length = VG_(strlen) (src);
300
301 if (dyn_string_resize (dest, dest->length + length) == NULL)
302 return 0;
303 /* Make room for the insertion. Be sure to copy the NUL. */
304 for (i = dest->length; i >= pos; --i)
305 dest->s[i + length] = dest->s[i];
306 /* Splice in the new stuff. */
307 VG_(strncpy) (dest->s + pos, src, length);
308 /* Compute the new length. */
309 dest->length += length;
310 return 1;
311}
312
313/* Inserts character C into DEST starting at position POS. DEST is
314 expanded as necessary. Returns 1 on success. On failure,
315 RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */
316
317int
318dyn_string_insert_char (dest, pos, c)
319 dyn_string_t dest;
320 int pos;
321 int c;
322{
323 int i;
324
325 if (dyn_string_resize (dest, dest->length + 1) == NULL)
326 return 0;
327 /* Make room for the insertion. Be sure to copy the NUL. */
328 for (i = dest->length; i >= pos; --i)
329 dest->s[i + 1] = dest->s[i];
330 /* Add the new character. */
331 dest->s[pos] = c;
332 /* Compute the new length. */
333 ++dest->length;
334 return 1;
335}
336
337/* Append S to DS, resizing DS if necessary. Returns 1 on success.
338 On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
339 returns 0. */
340
341int
342dyn_string_append (dest, s)
343 dyn_string_t dest;
344 dyn_string_t s;
345{
346 if (dyn_string_resize (dest, dest->length + s->length) == 0)
347 return 0;
348 VG_(strcpy) (dest->s + dest->length, s->s);
349 dest->length += s->length;
350 return 1;
351}
352
353/* Append the NUL-terminated string S to DS, resizing DS if necessary.
354 Returns 1 on success. On failure, if RETURN_ON_ALLOCATION_FAILURE,
355 deletes DEST and returns 0. */
356
357int
358dyn_string_append_cstr (dest, s)
359 dyn_string_t dest;
360 const char *s;
361{
362 int len = VG_(strlen) (s);
363
364 /* The new length is the old length plus the size of our string, plus
365 one for the null at the end. */
366 if (dyn_string_resize (dest, dest->length + len) == NULL)
367 return 0;
368 VG_(strcpy) (dest->s + dest->length, s);
369 dest->length += len;
370 return 1;
371}
372
373/* Appends C to the end of DEST. Returns 1 on success. On failiure,
374 if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */
375
376int
377dyn_string_append_char (dest, c)
378 dyn_string_t dest;
379 int c;
380{
381 /* Make room for the extra character. */
382 if (dyn_string_resize (dest, dest->length + 1) == NULL)
383 return 0;
384 /* Append the character; it will overwrite the old NUL. */
385 dest->s[dest->length] = c;
386 /* Add a new NUL at the end. */
387 dest->s[dest->length + 1] = '\0';
388 /* Update the length. */
389 ++(dest->length);
390 return 1;
391}
392
393/* Sets the contents of DEST to the substring of SRC starting at START
394 and ending before END. START must be less than or equal to END,
395 and both must be between zero and the length of SRC, inclusive.
396 Returns 1 on success. On failure, if RETURN_ON_ALLOCATION_FAILURE,
397 deletes DEST and returns 0. */
398
399int
400dyn_string_substring (dest, src, start, end)
401 dyn_string_t dest;
402 dyn_string_t src;
403 int start;
404 int end;
405{
406 int i;
407 int length = end - start;
408
409 /*
410 vg_assert (start > end || start > src->length || end > src->length);
411 */
412
413 /* Make room for the substring. */
414 if (dyn_string_resize (dest, length) == NULL)
415 return 0;
416 /* Copy the characters in the substring, */
417 for (i = length; --i >= 0; )
418 dest->s[i] = src->s[start + i];
419 /* NUL-terimate the result. */
420 dest->s[length] = '\0';
421 /* Record the length of the substring. */
422 dest->length = length;
423
424 return 1;
425}
426
427/* Returns non-zero if DS1 and DS2 have the same contents. */
428
429int
430dyn_string_eq (ds1, ds2)
431 dyn_string_t ds1;
432 dyn_string_t ds2;
433{
434 /* If DS1 and DS2 have different lengths, they must not be the same. */
435 if (ds1->length != ds2->length)
436 return 0;
437 else
438 return !VG_(strcmp) (ds1->s, ds2->s);
439}