Correctly check gcc version.
[platform/upstream/binutils.git] / gas / sb.c
1 /* sb.c - string buffer manipulation routines
2    Copyright (C) 1994, 1995 Free Software Foundation, Inc.
3
4    Written by Steve and Judy Chamberlain of Cygnus Support,
5       sac@cygnus.com
6
7    This file is part of GAS, the GNU Assembler.
8
9    GAS is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2, or (at your option)
12    any later version.
13
14    GAS is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with GAS; see the file COPYING.  If not, write to the Free
21    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22    02111-1307, USA. */
23
24 #include "config.h"
25 #include <stdio.h>
26 #ifdef HAVE_STRING_H
27 #include <string.h>
28 #else
29 #include <strings.h>
30 #endif
31 #include "libiberty.h"
32 #include "sb.h"
33
34 /* These routines are about manipulating strings.
35
36    They are managed in things called `sb's which is an abbreviation
37    for string buffers.  An sb has to be created, things can be glued
38    on to it, and at the end of it's life it should be freed.  The
39    contents should never be pointed at whilst it is still growing,
40    since it could be moved at any time
41
42    eg:
43    sb_new (&foo);
44    sb_grow... (&foo,...);
45    use foo->ptr[*];
46    sb_kill (&foo);
47
48 */
49
50 #define dsize 5
51
52 static void sb_check PARAMS ((sb *, int));
53
54 /* Statistics of sb structures.  */
55
56 int string_count[sb_max_power_two];
57
58 /* Free list of sb structures.  */
59
60 static sb_list_vector free_list;
61
62 /* initializes an sb. */
63
64 void
65 sb_build (ptr, size)
66      sb *ptr;
67      int size;
68 {
69   /* see if we can find one to allocate */
70   sb_element *e;
71
72   if (size > sb_max_power_two)
73     abort ();
74
75   e = free_list.size[size];
76   if (!e)
77     {
78       /* nothing there, allocate one and stick into the free list */
79       e = (sb_element *) xmalloc (sizeof (sb_element) + (1 << size));
80       e->next = free_list.size[size];
81       e->size = 1 << size;
82       free_list.size[size] = e;
83       string_count[size]++;
84     }
85
86   /* remove from free list */
87
88   free_list.size[size] = e->next;
89
90   /* copy into callers world */
91   ptr->ptr = e->data;
92   ptr->pot = size;
93   ptr->len = 0;
94   ptr->item = e;
95 }
96
97
98 void
99 sb_new (ptr)
100      sb *ptr;
101 {
102   sb_build (ptr, dsize);
103 }
104
105 /* deallocate the sb at ptr */
106
107 void
108 sb_kill (ptr)
109      sb *ptr;
110 {
111   /* return item to free list */
112   ptr->item->next = free_list.size[ptr->pot];
113   free_list.size[ptr->pot] = ptr->item;
114 }
115
116 /* add the sb at s to the end of the sb at ptr */
117
118 void
119 sb_add_sb (ptr, s)
120      sb *ptr;
121      sb *s;
122 {
123   sb_check (ptr, s->len);
124   memcpy (ptr->ptr + ptr->len, s->ptr, s->len);
125   ptr->len += s->len;
126 }
127
128 /* make sure that the sb at ptr has room for another len characters,
129    and grow it if it doesn't. */
130
131 static void
132 sb_check (ptr, len)
133      sb *ptr;
134      int len;
135 {
136   if (ptr->len + len >= 1 << ptr->pot)
137     {
138       sb tmp;
139       int pot = ptr->pot;
140       while (ptr->len + len >= 1 << pot)
141         pot++;
142       sb_build (&tmp, pot);
143       sb_add_sb (&tmp, ptr);
144       sb_kill (ptr);
145       *ptr = tmp;
146     }
147 }
148
149 /* make the sb at ptr point back to the beginning.  */
150
151 void
152 sb_reset (ptr)
153      sb *ptr;
154 {
155   ptr->len = 0;
156 }
157
158 /* add character c to the end of the sb at ptr. */
159
160 void
161 sb_add_char (ptr, c)
162      sb *ptr;
163      int c;
164 {
165   sb_check (ptr, 1);
166   ptr->ptr[ptr->len++] = c;
167 }
168
169 /* add null terminated string s to the end of sb at ptr. */
170
171 void
172 sb_add_string (ptr, s)
173      sb *ptr;
174      const char *s;
175 {
176   int len = strlen (s);
177   sb_check (ptr, len);
178   memcpy (ptr->ptr + ptr->len, s, len);
179   ptr->len += len;
180 }
181
182 /* add string at s of length len to sb at ptr */
183
184 void
185 sb_add_buffer (ptr, s, len)
186      sb *ptr;
187      const char *s;
188      int len;
189 {
190   sb_check (ptr, len);
191   memcpy (ptr->ptr + ptr->len, s, len);
192   ptr->len += len;
193 }
194
195 /* print the sb at ptr to the output file */
196
197 void
198 sb_print (outfile, ptr)
199      FILE *outfile;
200      sb *ptr;
201 {
202   int i;
203   int nc = 0;
204
205   for (i = 0; i < ptr->len; i++)
206     {
207       if (nc)
208         {
209           fprintf (outfile, ",");
210         }
211       fprintf (outfile, "%d", ptr->ptr[i]);
212       nc = 1;
213     }
214 }
215
216 void 
217 sb_print_at (outfile, idx, ptr)
218      FILE *outfile;
219      int idx;
220      sb *ptr;
221 {
222   int i;
223   for (i = idx; i < ptr->len; i++)
224     putc (ptr->ptr[i], outfile);
225 }
226
227 /* put a null at the end of the sb at in and return the start of the
228    string, so that it can be used as an arg to printf %s. */
229
230 char *
231 sb_name (in)
232      sb *in;
233 {
234   /* stick a null on the end of the string */
235   sb_add_char (in, 0);
236   return in->ptr;
237 }
238
239 /* like sb_name, but don't include the null byte in the string.  */
240
241 char *
242 sb_terminate (in)
243      sb *in;
244 {
245   sb_add_char (in, 0);
246   --in->len;
247   return in->ptr;
248 }
249
250 /* start at the index idx into the string in sb at ptr and skip
251    whitespace. return the index of the first non whitespace character */
252
253 int
254 sb_skip_white (idx, ptr)
255      int idx;
256      sb *ptr;
257 {
258   while (idx < ptr->len
259          && (ptr->ptr[idx] == ' '
260              || ptr->ptr[idx] == '\t'))
261     idx++;
262   return idx;
263 }
264
265 /* start at the index idx into the sb at ptr. skips whitespace,
266    a comma and any following whitespace. returnes the index of the
267    next character. */
268
269 int
270 sb_skip_comma (idx, ptr)
271      int idx;
272      sb *ptr;
273 {
274   while (idx < ptr->len
275          && (ptr->ptr[idx] == ' '
276              || ptr->ptr[idx] == '\t'))
277     idx++;
278
279   if (idx < ptr->len
280       && ptr->ptr[idx] == ',')
281     idx++;
282
283   while (idx < ptr->len
284          && (ptr->ptr[idx] == ' '
285              || ptr->ptr[idx] == '\t'))
286     idx++;
287
288   return idx;
289 }