133965Sjdp/* sb.c - string buffer manipulation routines 2218822Sdim Copyright 1994, 1995, 2000, 2003, 2006 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 21218822Sdim Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 22218822Sdim 02110-1301, USA. */ 2333965Sjdp 24218822Sdim#include "as.h" 2533965Sjdp#include "sb.h" 2633965Sjdp 2733965Sjdp/* These routines are about manipulating strings. 2833965Sjdp 2933965Sjdp They are managed in things called `sb's which is an abbreviation 3033965Sjdp for string buffers. An sb has to be created, things can be glued 3133965Sjdp on to it, and at the end of it's life it should be freed. The 3233965Sjdp contents should never be pointed at whilst it is still growing, 3333965Sjdp since it could be moved at any time 3433965Sjdp 3533965Sjdp eg: 3633965Sjdp sb_new (&foo); 3733965Sjdp sb_grow... (&foo,...); 3833965Sjdp use foo->ptr[*]; 39218822Sdim sb_kill (&foo); */ 4033965Sjdp 41218822Sdimstatic int dsize = 5; 42130561Sobrienstatic void sb_check (sb *, int); 4333965Sjdp 4433965Sjdp/* Statistics of sb structures. */ 45218822Sdimstatic int string_count[sb_max_power_two]; 4633965Sjdp 4733965Sjdp/* Free list of sb structures. */ 48218822Sdimstatic struct 49218822Sdim{ 50218822Sdim sb_element *size[sb_max_power_two]; 51218822Sdim} free_list; 5233965Sjdp 53218822Sdim/* Initializes an sb. */ 5433965Sjdp 55218822Sdimstatic void 56130561Sobriensb_build (sb *ptr, int size) 5733965Sjdp{ 58218822Sdim /* See if we can find one to allocate. */ 5933965Sjdp sb_element *e; 6033965Sjdp 61218822Sdim assert (size < sb_max_power_two); 6233965Sjdp 6333965Sjdp e = free_list.size[size]; 6433965Sjdp if (!e) 6533965Sjdp { 66218822Sdim /* Nothing there, allocate one and stick into the free list. */ 6733965Sjdp e = (sb_element *) xmalloc (sizeof (sb_element) + (1 << size)); 6833965Sjdp e->next = free_list.size[size]; 6933965Sjdp e->size = 1 << size; 7033965Sjdp free_list.size[size] = e; 7133965Sjdp string_count[size]++; 7233965Sjdp } 7333965Sjdp 74218822Sdim /* Remove from free list. */ 7533965Sjdp free_list.size[size] = e->next; 7633965Sjdp 77218822Sdim /* Copy into callers world. */ 7833965Sjdp ptr->ptr = e->data; 7933965Sjdp ptr->pot = size; 8033965Sjdp ptr->len = 0; 8133965Sjdp ptr->item = e; 8233965Sjdp} 8333965Sjdp 8433965Sjdpvoid 85130561Sobriensb_new (sb *ptr) 8633965Sjdp{ 8733965Sjdp sb_build (ptr, dsize); 8833965Sjdp} 8933965Sjdp 90218822Sdim/* Deallocate the sb at ptr. */ 9133965Sjdp 9233965Sjdpvoid 93130561Sobriensb_kill (sb *ptr) 9433965Sjdp{ 95218822Sdim /* Return item to free list. */ 9633965Sjdp ptr->item->next = free_list.size[ptr->pot]; 9733965Sjdp free_list.size[ptr->pot] = ptr->item; 9833965Sjdp} 9933965Sjdp 100218822Sdim/* Add the sb at s to the end of the sb at ptr. */ 10133965Sjdp 10233965Sjdpvoid 103130561Sobriensb_add_sb (sb *ptr, sb *s) 10433965Sjdp{ 10533965Sjdp sb_check (ptr, s->len); 10633965Sjdp memcpy (ptr->ptr + ptr->len, s->ptr, s->len); 10733965Sjdp ptr->len += s->len; 10833965Sjdp} 10933965Sjdp 110218822Sdim/* Helper for sb_scrub_and_add_sb. */ 111218822Sdim 112218822Sdimstatic sb *sb_to_scrub; 113218822Sdimstatic char *scrub_position; 114218822Sdimstatic int 115218822Sdimscrub_from_sb (char *buf, int buflen) 116218822Sdim{ 117218822Sdim int copy; 118218822Sdim copy = sb_to_scrub->len - (scrub_position - sb_to_scrub->ptr); 119218822Sdim if (copy > buflen) 120218822Sdim copy = buflen; 121218822Sdim memcpy (buf, scrub_position, copy); 122218822Sdim scrub_position += copy; 123218822Sdim return copy; 124218822Sdim} 125218822Sdim 126218822Sdim/* Run the sb at s through do_scrub_chars and add the result to the sb 127218822Sdim at ptr. */ 128218822Sdim 129218822Sdimvoid 130218822Sdimsb_scrub_and_add_sb (sb *ptr, sb *s) 131218822Sdim{ 132218822Sdim sb_to_scrub = s; 133218822Sdim scrub_position = s->ptr; 134218822Sdim 135218822Sdim sb_check (ptr, s->len); 136218822Sdim ptr->len += do_scrub_chars (scrub_from_sb, ptr->ptr + ptr->len, s->len); 137218822Sdim 138218822Sdim sb_to_scrub = 0; 139218822Sdim scrub_position = 0; 140218822Sdim} 141218822Sdim 142218822Sdim/* Make sure that the sb at ptr has room for another len characters, 14377298Sobrien and grow it if it doesn't. */ 14433965Sjdp 14533965Sjdpstatic void 146130561Sobriensb_check (sb *ptr, int len) 14733965Sjdp{ 14833965Sjdp if (ptr->len + len >= 1 << ptr->pot) 14933965Sjdp { 15033965Sjdp sb tmp; 15133965Sjdp int pot = ptr->pot; 152218822Sdim 15333965Sjdp while (ptr->len + len >= 1 << pot) 15433965Sjdp pot++; 15533965Sjdp sb_build (&tmp, pot); 15633965Sjdp sb_add_sb (&tmp, ptr); 15733965Sjdp sb_kill (ptr); 15833965Sjdp *ptr = tmp; 15933965Sjdp } 16033965Sjdp} 16133965Sjdp 162218822Sdim/* Make the sb at ptr point back to the beginning. */ 16333965Sjdp 16433965Sjdpvoid 165130561Sobriensb_reset (sb *ptr) 16633965Sjdp{ 16733965Sjdp ptr->len = 0; 16833965Sjdp} 16933965Sjdp 170218822Sdim/* Add character c to the end of the sb at ptr. */ 17133965Sjdp 17233965Sjdpvoid 173130561Sobriensb_add_char (sb *ptr, int c) 17433965Sjdp{ 17533965Sjdp sb_check (ptr, 1); 17633965Sjdp ptr->ptr[ptr->len++] = c; 17733965Sjdp} 17833965Sjdp 179218822Sdim/* Add null terminated string s to the end of sb at ptr. */ 18033965Sjdp 18133965Sjdpvoid 182130561Sobriensb_add_string (sb *ptr, const char *s) 18333965Sjdp{ 18433965Sjdp int len = strlen (s); 18533965Sjdp sb_check (ptr, len); 18633965Sjdp memcpy (ptr->ptr + ptr->len, s, len); 18733965Sjdp ptr->len += len; 18833965Sjdp} 18933965Sjdp 190218822Sdim/* Add string at s of length len to sb at ptr */ 19133965Sjdp 19233965Sjdpvoid 193130561Sobriensb_add_buffer (sb *ptr, const char *s, int len) 19433965Sjdp{ 19533965Sjdp sb_check (ptr, len); 19633965Sjdp memcpy (ptr->ptr + ptr->len, s, len); 19733965Sjdp ptr->len += len; 19833965Sjdp} 19933965Sjdp 200218822Sdim/* Like sb_name, but don't include the null byte in the string. */ 20133965Sjdp 20233965Sjdpchar * 203130561Sobriensb_terminate (sb *in) 20433965Sjdp{ 20533965Sjdp sb_add_char (in, 0); 20633965Sjdp --in->len; 20733965Sjdp return in->ptr; 20833965Sjdp} 20933965Sjdp 210218822Sdim/* Start at the index idx into the string in sb at ptr and skip 211218822Sdim whitespace. return the index of the first non whitespace character. */ 21233965Sjdp 21333965Sjdpint 214130561Sobriensb_skip_white (int idx, sb *ptr) 21533965Sjdp{ 21633965Sjdp while (idx < ptr->len 21733965Sjdp && (ptr->ptr[idx] == ' ' 21833965Sjdp || ptr->ptr[idx] == '\t')) 21933965Sjdp idx++; 22033965Sjdp return idx; 22133965Sjdp} 22233965Sjdp 223218822Sdim/* Start at the index idx into the sb at ptr. skips whitespace, 224130561Sobrien a comma and any following whitespace. returns the index of the 22577298Sobrien next character. */ 22633965Sjdp 22733965Sjdpint 228130561Sobriensb_skip_comma (int idx, sb *ptr) 22933965Sjdp{ 23033965Sjdp while (idx < ptr->len 23133965Sjdp && (ptr->ptr[idx] == ' ' 23233965Sjdp || ptr->ptr[idx] == '\t')) 23333965Sjdp idx++; 23433965Sjdp 23533965Sjdp if (idx < ptr->len 23633965Sjdp && ptr->ptr[idx] == ',') 23733965Sjdp idx++; 23833965Sjdp 23933965Sjdp while (idx < ptr->len 24033965Sjdp && (ptr->ptr[idx] == ' ' 24133965Sjdp || ptr->ptr[idx] == '\t')) 24233965Sjdp idx++; 24333965Sjdp 24433965Sjdp return idx; 24533965Sjdp} 246