~ubuntu-branches/ubuntu/hoary/binutils/hoary

« back to all changes in this revision

Viewing changes to libiberty/dyn-string.c

  • Committer: Bazaar Package Importer
  • Author(s): James Troup
  • Date: 2004-05-19 10:35:44 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040519103544-17h3o6e8pwndydrg
Tags: 2.14.90.0.7-8
debian/rules: don't use gcc-2.95 on m68k.  Thanks to Adam Conrad for
pointing this out.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#if defined(IN_LIBGCC2) || defined(IN_GLIBCPP_V3)
 
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
}