OSDN Git Service

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