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