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