Fri Apr 5 18:39:28 1996 James G. Smith <jsmith@cygnus.co.uk>
[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 #include <string.h>
27 #include "libiberty.h"
28 #include "sb.h"
29
30 /* These routines are about manipulating strings.
31
32    They are managed in things called `sb's which is an abbreviation
33    for string buffers.  An sb has to be created, things can be glued
34    on to it, and at the end of it's life it should be freed.  The
35    contents should never be pointed at whilst it is still growing,
36    since it could be moved at any time
37
38    eg:
39    sb_new (&foo);
40    sb_grow... (&foo,...);
41    use foo->ptr[*];
42    sb_kill (&foo);
43
44 */
45
46 #define dsize 5
47
48 static void sb_check PARAMS ((sb *, int));
49
50 /* Statistics of sb structures.  */
51
52 int string_count[sb_max_power_two];
53
54 /* Free list of sb structures.  */
55
56 static sb_list_vector free_list;
57
58 /* initializes an sb. */
59
60 void
61 sb_build (ptr, size)
62      sb *ptr;
63      int size;
64 {
65   /* see if we can find one to allocate */
66   sb_element *e;
67
68   if (size > sb_max_power_two)
69     abort ();
70
71   e = free_list.size[size];
72   if (!e)
73     {
74       /* nothing there, allocate one and stick into the free list */
75       e = (sb_element *) xmalloc (sizeof (sb_element) + (1 << size));
76       e->next = free_list.size[size];
77       e->size = 1 << size;
78       free_list.size[size] = e;
79       string_count[size]++;
80     }
81
82   /* remove from free list */
83
84   free_list.size[size] = e->next;
85
86   /* copy into callers world */
87   ptr->ptr = e->data;
88   ptr->pot = size;
89   ptr->len = 0;
90   ptr->item = e;
91 }
92
93
94 void
95 sb_new (ptr)
96      sb *ptr;
97 {
98   sb_build (ptr, dsize);
99 }
100
101 /* deallocate the sb at ptr */
102
103 void
104 sb_kill (ptr)
105      sb *ptr;
106 {
107   /* return item to free list */
108   ptr->item->next = free_list.size[ptr->pot];
109   free_list.size[ptr->pot] = ptr->item;
110 }
111
112 /* add the sb at s to the end of the sb at ptr */
113
114 void
115 sb_add_sb (ptr, s)
116      sb *ptr;
117      sb *s;
118 {
119   sb_check (ptr, s->len);
120   memcpy (ptr->ptr + ptr->len, s->ptr, s->len);
121   ptr->len += s->len;
122 }
123
124 /* make sure that the sb at ptr has room for another len characters,
125    and grow it if it doesn't. */
126
127 static void
128 sb_check (ptr, len)
129      sb *ptr;
130      int len;
131 {
132   if (ptr->len + len >= 1 << ptr->pot)
133     {
134       sb tmp;
135       int pot = ptr->pot;
136       while (ptr->len + len >= 1 << pot)
137         pot++;
138       sb_build (&tmp, pot);
139       sb_add_sb (&tmp, ptr);
140       sb_kill (ptr);
141       *ptr = tmp;
142     }
143 }
144
145 /* make the sb at ptr point back to the beginning.  */
146
147 void
148 sb_reset (ptr)
149      sb *ptr;
150 {
151   ptr->len = 0;
152 }
153
154 /* add character c to the end of the sb at ptr. */
155
156 void
157 sb_add_char (ptr, c)
158      sb *ptr;
159      int c;
160 {
161   sb_check (ptr, 1);
162   ptr->ptr[ptr->len++] = c;
163 }
164
165 /* add null terminated string s to the end of sb at ptr. */
166
167 void
168 sb_add_string (ptr, s)
169      sb *ptr;
170      const char *s;
171 {
172   int len = strlen (s);
173   sb_check (ptr, len);
174   memcpy (ptr->ptr + ptr->len, s, len);
175   ptr->len += len;
176 }
177
178 /* add string at s of length len to sb at ptr */
179
180 void
181 sb_add_buffer (ptr, s, len)
182      sb *ptr;
183      const char *s;
184      int len;
185 {
186   sb_check (ptr, len);
187   memcpy (ptr->ptr + ptr->len, s, len);
188   ptr->len += len;
189 }
190
191 /* print the sb at ptr to the output file */
192
193 void
194 sb_print (outfile, ptr)
195      FILE *outfile;
196      sb *ptr;
197 {
198   int i;
199   int nc = 0;
200
201   for (i = 0; i < ptr->len; i++)
202     {
203       if (nc)
204         {
205           fprintf (outfile, ",");
206         }
207       fprintf (outfile, "%d", ptr->ptr[i]);
208       nc = 1;
209     }
210 }
211
212 void 
213 sb_print_at (outfile, idx, ptr)
214      FILE *outfile;
215      int idx;
216      sb *ptr;
217 {
218   int i;
219   for (i = idx; i < ptr->len; i++)
220     putc (ptr->ptr[i], outfile);
221 }
222
223 /* put a null at the end of the sb at in and return the start of the
224    string, so that it can be used as an arg to printf %s. */
225
226 char *
227 sb_name (in)
228      sb *in;
229 {
230   /* stick a null on the end of the string */
231   sb_add_char (in, 0);
232   return in->ptr;
233 }
234
235 /* like sb_name, but don't include the null byte in the string.  */
236
237 char *
238 sb_terminate (in)
239      sb *in;
240 {
241   sb_add_char (in, 0);
242   --in->len;
243   return in->ptr;
244 }
245
246 /* start at the index idx into the string in sb at ptr and skip
247    whitespace. return the index of the first non whitespace character */
248
249 int
250 sb_skip_white (idx, ptr)
251      int idx;
252      sb *ptr;
253 {
254   while (idx < ptr->len
255          && (ptr->ptr[idx] == ' '
256              || ptr->ptr[idx] == '\t'))
257     idx++;
258   return idx;
259 }
260
261 /* start at the index idx into the sb at ptr. skips whitespace,
262    a comma and any following whitespace. returnes the index of the
263    next character. */
264
265 int
266 sb_skip_comma (idx, ptr)
267      int idx;
268      sb *ptr;
269 {
270   while (idx < ptr->len
271          && (ptr->ptr[idx] == ' '
272              || ptr->ptr[idx] == '\t'))
273     idx++;
274
275   if (idx < ptr->len
276       && ptr->ptr[idx] == ',')
277     idx++;
278
279   while (idx < ptr->len
280          && (ptr->ptr[idx] == ' '
281              || ptr->ptr[idx] == '\t'))
282     idx++;
283
284   return idx;
285 }