sb.c revision 130561
133965Sjdp/* sb.c - string buffer manipulation routines
278828Sobrien   Copyright 1994, 1995, 2000 Free Software Foundation, Inc.
333965Sjdp
433965Sjdp   Written by Steve and Judy Chamberlain of Cygnus Support,
533965Sjdp      sac@cygnus.com
633965Sjdp
733965Sjdp   This file is part of GAS, the GNU Assembler.
833965Sjdp
933965Sjdp   GAS is free software; you can redistribute it and/or modify
1033965Sjdp   it under the terms of the GNU General Public License as published by
1133965Sjdp   the Free Software Foundation; either version 2, or (at your option)
1233965Sjdp   any later version.
1333965Sjdp
1433965Sjdp   GAS is distributed in the hope that it will be useful,
1533965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1633965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1733965Sjdp   GNU General Public License for more details.
1833965Sjdp
1933965Sjdp   You should have received a copy of the GNU General Public License
2033965Sjdp   along with GAS; see the file COPYING.  If not, write to the Free
2133965Sjdp   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2277298Sobrien   02111-1307, USA.  */
2333965Sjdp
2433965Sjdp#include "config.h"
2533965Sjdp#include <stdio.h>
2677298Sobrien#ifdef HAVE_STDLIB_H
2777298Sobrien#include <stdlib.h>
2877298Sobrien#endif
2933965Sjdp#ifdef HAVE_STRING_H
3033965Sjdp#include <string.h>
3133965Sjdp#else
3233965Sjdp#include <strings.h>
3333965Sjdp#endif
3433965Sjdp#include "libiberty.h"
3533965Sjdp#include "sb.h"
3633965Sjdp
3733965Sjdp/* These routines are about manipulating strings.
3833965Sjdp
3933965Sjdp   They are managed in things called `sb's which is an abbreviation
4033965Sjdp   for string buffers.  An sb has to be created, things can be glued
4133965Sjdp   on to it, and at the end of it's life it should be freed.  The
4233965Sjdp   contents should never be pointed at whilst it is still growing,
4333965Sjdp   since it could be moved at any time
4433965Sjdp
4533965Sjdp   eg:
4633965Sjdp   sb_new (&foo);
4733965Sjdp   sb_grow... (&foo,...);
4833965Sjdp   use foo->ptr[*];
4933965Sjdp   sb_kill (&foo);
5033965Sjdp
5133965Sjdp*/
5233965Sjdp
5333965Sjdp#define dsize 5
5433965Sjdp
55130561Sobrienstatic void sb_check (sb *, int);
5633965Sjdp
5733965Sjdp/* Statistics of sb structures.  */
5833965Sjdp
5933965Sjdpint string_count[sb_max_power_two];
6033965Sjdp
6133965Sjdp/* Free list of sb structures.  */
6233965Sjdp
6333965Sjdpstatic sb_list_vector free_list;
6433965Sjdp
6577298Sobrien/* initializes an sb.  */
6633965Sjdp
6733965Sjdpvoid
68130561Sobriensb_build (sb *ptr, int size)
6933965Sjdp{
7033965Sjdp  /* see if we can find one to allocate */
7133965Sjdp  sb_element *e;
7233965Sjdp
7333965Sjdp  if (size > sb_max_power_two)
7433965Sjdp    abort ();
7533965Sjdp
7633965Sjdp  e = free_list.size[size];
7733965Sjdp  if (!e)
7833965Sjdp    {
7933965Sjdp      /* nothing there, allocate one and stick into the free list */
8033965Sjdp      e = (sb_element *) xmalloc (sizeof (sb_element) + (1 << size));
8133965Sjdp      e->next = free_list.size[size];
8233965Sjdp      e->size = 1 << size;
8333965Sjdp      free_list.size[size] = e;
8433965Sjdp      string_count[size]++;
8533965Sjdp    }
8633965Sjdp
8733965Sjdp  /* remove from free list */
8833965Sjdp
8933965Sjdp  free_list.size[size] = e->next;
9033965Sjdp
9133965Sjdp  /* copy into callers world */
9233965Sjdp  ptr->ptr = e->data;
9333965Sjdp  ptr->pot = size;
9433965Sjdp  ptr->len = 0;
9533965Sjdp  ptr->item = e;
9633965Sjdp}
9733965Sjdp
9833965Sjdpvoid
99130561Sobriensb_new (sb *ptr)
10033965Sjdp{
10133965Sjdp  sb_build (ptr, dsize);
10233965Sjdp}
10333965Sjdp
10433965Sjdp/* deallocate the sb at ptr */
10533965Sjdp
10633965Sjdpvoid
107130561Sobriensb_kill (sb *ptr)
10833965Sjdp{
10933965Sjdp  /* return item to free list */
11033965Sjdp  ptr->item->next = free_list.size[ptr->pot];
11133965Sjdp  free_list.size[ptr->pot] = ptr->item;
11233965Sjdp}
11333965Sjdp
11433965Sjdp/* add the sb at s to the end of the sb at ptr */
11533965Sjdp
11633965Sjdpvoid
117130561Sobriensb_add_sb (sb *ptr, sb *s)
11833965Sjdp{
11933965Sjdp  sb_check (ptr, s->len);
12033965Sjdp  memcpy (ptr->ptr + ptr->len, s->ptr, s->len);
12133965Sjdp  ptr->len += s->len;
12233965Sjdp}
12333965Sjdp
12433965Sjdp/* make sure that the sb at ptr has room for another len characters,
12577298Sobrien   and grow it if it doesn't.  */
12633965Sjdp
12733965Sjdpstatic void
128130561Sobriensb_check (sb *ptr, int len)
12933965Sjdp{
13033965Sjdp  if (ptr->len + len >= 1 << ptr->pot)
13133965Sjdp    {
13233965Sjdp      sb tmp;
13333965Sjdp      int pot = ptr->pot;
13433965Sjdp      while (ptr->len + len >= 1 << pot)
13533965Sjdp	pot++;
13633965Sjdp      sb_build (&tmp, pot);
13733965Sjdp      sb_add_sb (&tmp, ptr);
13833965Sjdp      sb_kill (ptr);
13933965Sjdp      *ptr = tmp;
14033965Sjdp    }
14133965Sjdp}
14233965Sjdp
14333965Sjdp/* make the sb at ptr point back to the beginning.  */
14433965Sjdp
14533965Sjdpvoid
146130561Sobriensb_reset (sb *ptr)
14733965Sjdp{
14833965Sjdp  ptr->len = 0;
14933965Sjdp}
15033965Sjdp
15177298Sobrien/* add character c to the end of the sb at ptr.  */
15233965Sjdp
15333965Sjdpvoid
154130561Sobriensb_add_char (sb *ptr, int c)
15533965Sjdp{
15633965Sjdp  sb_check (ptr, 1);
15733965Sjdp  ptr->ptr[ptr->len++] = c;
15833965Sjdp}
15933965Sjdp
16077298Sobrien/* add null terminated string s to the end of sb at ptr.  */
16133965Sjdp
16233965Sjdpvoid
163130561Sobriensb_add_string (sb *ptr, const char *s)
16433965Sjdp{
16533965Sjdp  int len = strlen (s);
16633965Sjdp  sb_check (ptr, len);
16733965Sjdp  memcpy (ptr->ptr + ptr->len, s, len);
16833965Sjdp  ptr->len += len;
16933965Sjdp}
17033965Sjdp
17133965Sjdp/* add string at s of length len to sb at ptr */
17233965Sjdp
17333965Sjdpvoid
174130561Sobriensb_add_buffer (sb *ptr, const char *s, int len)
17533965Sjdp{
17633965Sjdp  sb_check (ptr, len);
17733965Sjdp  memcpy (ptr->ptr + ptr->len, s, len);
17833965Sjdp  ptr->len += len;
17933965Sjdp}
18033965Sjdp
18133965Sjdp/* print the sb at ptr to the output file */
18233965Sjdp
18333965Sjdpvoid
184130561Sobriensb_print (FILE *outfile, sb *ptr)
18533965Sjdp{
18633965Sjdp  int i;
18733965Sjdp  int nc = 0;
18833965Sjdp
18933965Sjdp  for (i = 0; i < ptr->len; i++)
19033965Sjdp    {
19133965Sjdp      if (nc)
19233965Sjdp	{
19333965Sjdp	  fprintf (outfile, ",");
19433965Sjdp	}
19533965Sjdp      fprintf (outfile, "%d", ptr->ptr[i]);
19633965Sjdp      nc = 1;
19733965Sjdp    }
19833965Sjdp}
19933965Sjdp
20077298Sobrienvoid
201130561Sobriensb_print_at (FILE *outfile, int idx, sb *ptr)
20233965Sjdp{
20333965Sjdp  int i;
20433965Sjdp  for (i = idx; i < ptr->len; i++)
20533965Sjdp    putc (ptr->ptr[i], outfile);
20633965Sjdp}
20733965Sjdp
20833965Sjdp/* put a null at the end of the sb at in and return the start of the
20977298Sobrien   string, so that it can be used as an arg to printf %s.  */
21033965Sjdp
21133965Sjdpchar *
212130561Sobriensb_name (sb *in)
21333965Sjdp{
21433965Sjdp  /* stick a null on the end of the string */
21533965Sjdp  sb_add_char (in, 0);
21633965Sjdp  return in->ptr;
21733965Sjdp}
21833965Sjdp
21933965Sjdp/* like sb_name, but don't include the null byte in the string.  */
22033965Sjdp
22133965Sjdpchar *
222130561Sobriensb_terminate (sb *in)
22333965Sjdp{
22433965Sjdp  sb_add_char (in, 0);
22533965Sjdp  --in->len;
22633965Sjdp  return in->ptr;
22733965Sjdp}
22833965Sjdp
22933965Sjdp/* start at the index idx into the string in sb at ptr and skip
23033965Sjdp   whitespace. return the index of the first non whitespace character */
23133965Sjdp
23233965Sjdpint
233130561Sobriensb_skip_white (int idx, sb *ptr)
23433965Sjdp{
23533965Sjdp  while (idx < ptr->len
23633965Sjdp	 && (ptr->ptr[idx] == ' '
23733965Sjdp	     || ptr->ptr[idx] == '\t'))
23833965Sjdp    idx++;
23933965Sjdp  return idx;
24033965Sjdp}
24133965Sjdp
24233965Sjdp/* start at the index idx into the sb at ptr. skips whitespace,
243130561Sobrien   a comma and any following whitespace. returns the index of the
24477298Sobrien   next character.  */
24533965Sjdp
24633965Sjdpint
247130561Sobriensb_skip_comma (int idx, sb *ptr)
24833965Sjdp{
24933965Sjdp  while (idx < ptr->len
25033965Sjdp	 && (ptr->ptr[idx] == ' '
25133965Sjdp	     || ptr->ptr[idx] == '\t'))
25233965Sjdp    idx++;
25333965Sjdp
25433965Sjdp  if (idx < ptr->len
25533965Sjdp      && ptr->ptr[idx] == ',')
25633965Sjdp    idx++;
25733965Sjdp
25833965Sjdp  while (idx < ptr->len
25933965Sjdp	 && (ptr->ptr[idx] == ' '
26033965Sjdp	     || ptr->ptr[idx] == '\t'))
26133965Sjdp    idx++;
26233965Sjdp
26333965Sjdp  return idx;
26433965Sjdp}
265