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