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