sb.c revision 77298
133965Sjdp/* sb.c - string buffer manipulation routines
277298Sobrien   Copyright (C) 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
5533965Sjdpstatic void sb_check PARAMS ((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
6833965Sjdpsb_build (ptr, size)
6933965Sjdp     sb *ptr;
7033965Sjdp     int size;
7133965Sjdp{
7233965Sjdp  /* see if we can find one to allocate */
7333965Sjdp  sb_element *e;
7433965Sjdp
7533965Sjdp  if (size > sb_max_power_two)
7633965Sjdp    abort ();
7733965Sjdp
7833965Sjdp  e = free_list.size[size];
7933965Sjdp  if (!e)
8033965Sjdp    {
8133965Sjdp      /* nothing there, allocate one and stick into the free list */
8233965Sjdp      e = (sb_element *) xmalloc (sizeof (sb_element) + (1 << size));
8333965Sjdp      e->next = free_list.size[size];
8433965Sjdp      e->size = 1 << size;
8533965Sjdp      free_list.size[size] = e;
8633965Sjdp      string_count[size]++;
8733965Sjdp    }
8833965Sjdp
8933965Sjdp  /* remove from free list */
9033965Sjdp
9133965Sjdp  free_list.size[size] = e->next;
9233965Sjdp
9333965Sjdp  /* copy into callers world */
9433965Sjdp  ptr->ptr = e->data;
9533965Sjdp  ptr->pot = size;
9633965Sjdp  ptr->len = 0;
9733965Sjdp  ptr->item = e;
9833965Sjdp}
9933965Sjdp
10033965Sjdpvoid
10133965Sjdpsb_new (ptr)
10233965Sjdp     sb *ptr;
10333965Sjdp{
10433965Sjdp  sb_build (ptr, dsize);
10533965Sjdp}
10633965Sjdp
10733965Sjdp/* deallocate the sb at ptr */
10833965Sjdp
10933965Sjdpvoid
11033965Sjdpsb_kill (ptr)
11133965Sjdp     sb *ptr;
11233965Sjdp{
11333965Sjdp  /* return item to free list */
11433965Sjdp  ptr->item->next = free_list.size[ptr->pot];
11533965Sjdp  free_list.size[ptr->pot] = ptr->item;
11633965Sjdp}
11733965Sjdp
11833965Sjdp/* add the sb at s to the end of the sb at ptr */
11933965Sjdp
12033965Sjdpvoid
12133965Sjdpsb_add_sb (ptr, s)
12233965Sjdp     sb *ptr;
12333965Sjdp     sb *s;
12433965Sjdp{
12533965Sjdp  sb_check (ptr, s->len);
12633965Sjdp  memcpy (ptr->ptr + ptr->len, s->ptr, s->len);
12733965Sjdp  ptr->len += s->len;
12833965Sjdp}
12933965Sjdp
13033965Sjdp/* make sure that the sb at ptr has room for another len characters,
13177298Sobrien   and grow it if it doesn't.  */
13233965Sjdp
13333965Sjdpstatic void
13433965Sjdpsb_check (ptr, len)
13533965Sjdp     sb *ptr;
13633965Sjdp     int len;
13733965Sjdp{
13833965Sjdp  if (ptr->len + len >= 1 << ptr->pot)
13933965Sjdp    {
14033965Sjdp      sb tmp;
14133965Sjdp      int pot = ptr->pot;
14233965Sjdp      while (ptr->len + len >= 1 << pot)
14333965Sjdp	pot++;
14433965Sjdp      sb_build (&tmp, pot);
14533965Sjdp      sb_add_sb (&tmp, ptr);
14633965Sjdp      sb_kill (ptr);
14733965Sjdp      *ptr = tmp;
14833965Sjdp    }
14933965Sjdp}
15033965Sjdp
15133965Sjdp/* make the sb at ptr point back to the beginning.  */
15233965Sjdp
15333965Sjdpvoid
15433965Sjdpsb_reset (ptr)
15533965Sjdp     sb *ptr;
15633965Sjdp{
15733965Sjdp  ptr->len = 0;
15833965Sjdp}
15933965Sjdp
16077298Sobrien/* add character c to the end of the sb at ptr.  */
16133965Sjdp
16233965Sjdpvoid
16333965Sjdpsb_add_char (ptr, c)
16433965Sjdp     sb *ptr;
16533965Sjdp     int c;
16633965Sjdp{
16733965Sjdp  sb_check (ptr, 1);
16833965Sjdp  ptr->ptr[ptr->len++] = c;
16933965Sjdp}
17033965Sjdp
17177298Sobrien/* add null terminated string s to the end of sb at ptr.  */
17233965Sjdp
17333965Sjdpvoid
17433965Sjdpsb_add_string (ptr, s)
17533965Sjdp     sb *ptr;
17633965Sjdp     const char *s;
17733965Sjdp{
17833965Sjdp  int len = strlen (s);
17933965Sjdp  sb_check (ptr, len);
18033965Sjdp  memcpy (ptr->ptr + ptr->len, s, len);
18133965Sjdp  ptr->len += len;
18233965Sjdp}
18333965Sjdp
18433965Sjdp/* add string at s of length len to sb at ptr */
18533965Sjdp
18633965Sjdpvoid
18733965Sjdpsb_add_buffer (ptr, s, len)
18833965Sjdp     sb *ptr;
18933965Sjdp     const char *s;
19033965Sjdp     int len;
19133965Sjdp{
19233965Sjdp  sb_check (ptr, len);
19333965Sjdp  memcpy (ptr->ptr + ptr->len, s, len);
19433965Sjdp  ptr->len += len;
19533965Sjdp}
19633965Sjdp
19733965Sjdp/* print the sb at ptr to the output file */
19833965Sjdp
19933965Sjdpvoid
20033965Sjdpsb_print (outfile, ptr)
20133965Sjdp     FILE *outfile;
20233965Sjdp     sb *ptr;
20333965Sjdp{
20433965Sjdp  int i;
20533965Sjdp  int nc = 0;
20633965Sjdp
20733965Sjdp  for (i = 0; i < ptr->len; i++)
20833965Sjdp    {
20933965Sjdp      if (nc)
21033965Sjdp	{
21133965Sjdp	  fprintf (outfile, ",");
21233965Sjdp	}
21333965Sjdp      fprintf (outfile, "%d", ptr->ptr[i]);
21433965Sjdp      nc = 1;
21533965Sjdp    }
21633965Sjdp}
21733965Sjdp
21877298Sobrienvoid
21933965Sjdpsb_print_at (outfile, idx, ptr)
22033965Sjdp     FILE *outfile;
22133965Sjdp     int idx;
22233965Sjdp     sb *ptr;
22333965Sjdp{
22433965Sjdp  int i;
22533965Sjdp  for (i = idx; i < ptr->len; i++)
22633965Sjdp    putc (ptr->ptr[i], outfile);
22733965Sjdp}
22833965Sjdp
22933965Sjdp/* put a null at the end of the sb at in and return the start of the
23077298Sobrien   string, so that it can be used as an arg to printf %s.  */
23133965Sjdp
23233965Sjdpchar *
23333965Sjdpsb_name (in)
23433965Sjdp     sb *in;
23533965Sjdp{
23633965Sjdp  /* stick a null on the end of the string */
23733965Sjdp  sb_add_char (in, 0);
23833965Sjdp  return in->ptr;
23933965Sjdp}
24033965Sjdp
24133965Sjdp/* like sb_name, but don't include the null byte in the string.  */
24233965Sjdp
24333965Sjdpchar *
24433965Sjdpsb_terminate (in)
24533965Sjdp     sb *in;
24633965Sjdp{
24733965Sjdp  sb_add_char (in, 0);
24833965Sjdp  --in->len;
24933965Sjdp  return in->ptr;
25033965Sjdp}
25133965Sjdp
25233965Sjdp/* start at the index idx into the string in sb at ptr and skip
25333965Sjdp   whitespace. return the index of the first non whitespace character */
25433965Sjdp
25533965Sjdpint
25633965Sjdpsb_skip_white (idx, ptr)
25733965Sjdp     int idx;
25833965Sjdp     sb *ptr;
25933965Sjdp{
26033965Sjdp  while (idx < ptr->len
26133965Sjdp	 && (ptr->ptr[idx] == ' '
26233965Sjdp	     || ptr->ptr[idx] == '\t'))
26333965Sjdp    idx++;
26433965Sjdp  return idx;
26533965Sjdp}
26633965Sjdp
26733965Sjdp/* start at the index idx into the sb at ptr. skips whitespace,
26833965Sjdp   a comma and any following whitespace. returnes the index of the
26977298Sobrien   next character.  */
27033965Sjdp
27133965Sjdpint
27233965Sjdpsb_skip_comma (idx, ptr)
27333965Sjdp     int idx;
27433965Sjdp     sb *ptr;
27533965Sjdp{
27633965Sjdp  while (idx < ptr->len
27733965Sjdp	 && (ptr->ptr[idx] == ' '
27833965Sjdp	     || ptr->ptr[idx] == '\t'))
27933965Sjdp    idx++;
28033965Sjdp
28133965Sjdp  if (idx < ptr->len
28233965Sjdp      && ptr->ptr[idx] == ',')
28333965Sjdp    idx++;
28433965Sjdp
28533965Sjdp  while (idx < ptr->len
28633965Sjdp	 && (ptr->ptr[idx] == ' '
28733965Sjdp	     || ptr->ptr[idx] == '\t'))
28833965Sjdp    idx++;
28933965Sjdp
29033965Sjdp  return idx;
29133965Sjdp}
292