mstring.c revision 266639
1266639Sbapt/* $Id: mstring.c,v 1.6 2014/04/22 23:36:31 tom Exp $ */ 2264790Sbapt 3264790Sbapt#include <stdlib.h> 4264790Sbapt#include <stdio.h> 5264790Sbapt#include <stdarg.h> 6264790Sbapt#include <ctype.h> 7264790Sbapt#include <string.h> 8264790Sbapt#include "defs.h" 9264790Sbapt 10264790Sbapt/* parameters about string length. HEAD is the starting size and 11264790Sbapt** HEAD+TAIL should be a power of two */ 12264790Sbapt#define HEAD 24 13264790Sbapt#define TAIL 8 14264790Sbapt 15264790Sbapt#if defined(YYBTYACC) 16266639Sbapt 17266639Sbaptstatic char *buf_ptr; 18266639Sbaptstatic size_t buf_len; 19266639Sbapt 20264790Sbaptvoid 21264790Sbaptmsprintf(struct mstring *s, const char *fmt,...) 22264790Sbapt{ 23264790Sbapt va_list args; 24264790Sbapt size_t len; 25266639Sbapt#ifdef HAVE_VSNPRINTF 26266639Sbapt int changed; 27266639Sbapt#endif 28264790Sbapt 29264790Sbapt if (!s || !s->base) 30264790Sbapt return; 31266639Sbapt 32266639Sbapt if (buf_len == 0) 33266639Sbapt { 34266639Sbapt buf_ptr = malloc(buf_len = 4096); 35266639Sbapt } 36266639Sbapt if (buf_ptr == 0) 37266639Sbapt { 38266639Sbapt return; 39266639Sbapt } 40266639Sbapt 41266639Sbapt#ifdef HAVE_VSNPRINTF 42266639Sbapt do 43266639Sbapt { 44266639Sbapt va_start(args, fmt); 45266639Sbapt len = (size_t) vsnprintf(buf_ptr, buf_len, fmt, args); 46266639Sbapt va_end(args); 47266639Sbapt if ((changed = (len > buf_len)) != 0) 48266639Sbapt { 49266639Sbapt char *new_ptr = realloc(buf_ptr, (buf_len * 3) / 2); 50266639Sbapt if (new_ptr == 0) 51266639Sbapt { 52266639Sbapt free(buf_ptr); 53266639Sbapt buf_ptr = 0; 54266639Sbapt return; 55266639Sbapt } 56266639Sbapt buf_ptr = new_ptr; 57266639Sbapt } 58266639Sbapt } 59266639Sbapt while (changed); 60266639Sbapt#else 61264790Sbapt va_start(args, fmt); 62266639Sbapt len = (size_t) vsprintf(buf_ptr, fmt, args); 63264790Sbapt va_end(args); 64266639Sbapt if (len >= buf_len) 65266639Sbapt return; 66266639Sbapt#endif 67264790Sbapt 68264790Sbapt if (len > (size_t) (s->end - s->ptr)) 69264790Sbapt { 70266639Sbapt char *new_base; 71264790Sbapt size_t cp = (size_t) (s->ptr - s->base); 72264790Sbapt size_t cl = (size_t) (s->end - s->base); 73264790Sbapt size_t nl = cl; 74264790Sbapt while (len > (nl - cp)) 75264790Sbapt nl = nl + nl + TAIL; 76266639Sbapt if ((new_base = realloc(s->base, nl))) 77264790Sbapt { 78266639Sbapt s->base = new_base; 79264790Sbapt s->ptr = s->base + cp; 80264790Sbapt s->end = s->base + nl; 81264790Sbapt } 82264790Sbapt else 83264790Sbapt { 84266639Sbapt free(s->base); 85266639Sbapt s->base = 0; 86266639Sbapt s->ptr = 0; 87266639Sbapt s->end = 0; 88264790Sbapt return; 89264790Sbapt } 90264790Sbapt } 91266639Sbapt memcpy(s->ptr, buf_ptr, len); 92264790Sbapt s->ptr += len; 93264790Sbapt} 94264790Sbapt#endif 95264790Sbapt 96264790Sbaptint 97264790Sbaptmputchar(struct mstring *s, int ch) 98264790Sbapt{ 99264790Sbapt if (!s || !s->base) 100264790Sbapt return ch; 101264790Sbapt if (s->ptr == s->end) 102264790Sbapt { 103264790Sbapt size_t len = (size_t) (s->end - s->base); 104264790Sbapt if ((s->base = realloc(s->base, len + len + TAIL))) 105264790Sbapt { 106264790Sbapt s->ptr = s->base + len; 107264790Sbapt s->end = s->base + len + len + TAIL; 108264790Sbapt } 109264790Sbapt else 110264790Sbapt { 111264790Sbapt s->ptr = s->end = 0; 112264790Sbapt return ch; 113264790Sbapt } 114264790Sbapt } 115264790Sbapt *s->ptr++ = (char)ch; 116264790Sbapt return ch; 117264790Sbapt} 118264790Sbapt 119264790Sbaptstruct mstring * 120264790Sbaptmsnew(void) 121264790Sbapt{ 122266639Sbapt struct mstring *n = TMALLOC(struct mstring, 1); 123264790Sbapt 124264790Sbapt if (n) 125264790Sbapt { 126266639Sbapt if ((n->base = n->ptr = MALLOC(HEAD)) != 0) 127264790Sbapt { 128264790Sbapt n->end = n->base + HEAD; 129264790Sbapt } 130264790Sbapt else 131264790Sbapt { 132264790Sbapt free(n); 133264790Sbapt n = 0; 134264790Sbapt } 135264790Sbapt } 136264790Sbapt return n; 137264790Sbapt} 138264790Sbapt 139264790Sbaptchar * 140264790Sbaptmsdone(struct mstring *s) 141264790Sbapt{ 142264790Sbapt char *r = 0; 143264790Sbapt if (s) 144264790Sbapt { 145264790Sbapt mputc(s, 0); 146264790Sbapt r = s->base; 147264790Sbapt free(s); 148264790Sbapt } 149264790Sbapt return r; 150264790Sbapt} 151264790Sbapt 152264790Sbapt#if defined(YYBTYACC) 153264790Sbapt/* compare two strings, ignoring whitespace, except between two letters or 154264790Sbapt** digits (and treat all of these as equal) */ 155264790Sbaptint 156264790Sbaptstrnscmp(const char *a, const char *b) 157264790Sbapt{ 158264790Sbapt while (1) 159264790Sbapt { 160264790Sbapt while (isspace(*a)) 161264790Sbapt a++; 162264790Sbapt while (isspace(*b)) 163264790Sbapt b++; 164264790Sbapt while (*a && *a == *b) 165264790Sbapt a++, b++; 166264790Sbapt if (isspace(*a)) 167264790Sbapt { 168264790Sbapt if (isalnum(a[-1]) && isalnum(*b)) 169264790Sbapt break; 170264790Sbapt } 171264790Sbapt else if (isspace(*b)) 172264790Sbapt { 173264790Sbapt if (isalnum(b[-1]) && isalnum(*a)) 174264790Sbapt break; 175264790Sbapt } 176264790Sbapt else 177264790Sbapt break; 178264790Sbapt } 179264790Sbapt return *a - *b; 180264790Sbapt} 181264790Sbapt 182264790Sbaptunsigned int 183264790Sbaptstrnshash(const char *s) 184264790Sbapt{ 185264790Sbapt unsigned int h = 0; 186264790Sbapt 187264790Sbapt while (*s) 188264790Sbapt { 189264790Sbapt if (!isspace(*s)) 190264790Sbapt h = (h << 5) - h + (unsigned char)*s; 191264790Sbapt s++; 192264790Sbapt } 193264790Sbapt return h; 194264790Sbapt} 195264790Sbapt#endif 196266639Sbapt 197266639Sbapt#ifdef NO_LEAKS 198266639Sbaptvoid 199266639Sbaptmstring_leaks(void) 200266639Sbapt{ 201266639Sbapt#if defined(YYBTYACC) 202266639Sbapt free(buf_ptr); 203266639Sbapt buf_ptr = 0; 204266639Sbapt buf_len = 0; 205266639Sbapt#endif 206266639Sbapt} 207266639Sbapt#endif 208