1268899Sbapt/* $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) 16268899Sbapt 17268899Sbaptstatic char *buf_ptr; 18268899Sbaptstatic size_t buf_len; 19268899Sbapt 20264790Sbaptvoid 21264790Sbaptmsprintf(struct mstring *s, const char *fmt,...) 22264790Sbapt{ 23264790Sbapt va_list args; 24264790Sbapt size_t len; 25268899Sbapt#ifdef HAVE_VSNPRINTF 26268899Sbapt int changed; 27268899Sbapt#endif 28264790Sbapt 29264790Sbapt if (!s || !s->base) 30264790Sbapt return; 31268899Sbapt 32268899Sbapt if (buf_len == 0) 33268899Sbapt { 34268899Sbapt buf_ptr = malloc(buf_len = 4096); 35268899Sbapt } 36268899Sbapt if (buf_ptr == 0) 37268899Sbapt { 38268899Sbapt return; 39268899Sbapt } 40268899Sbapt 41268899Sbapt#ifdef HAVE_VSNPRINTF 42268899Sbapt do 43268899Sbapt { 44268899Sbapt va_start(args, fmt); 45268899Sbapt len = (size_t) vsnprintf(buf_ptr, buf_len, fmt, args); 46268899Sbapt va_end(args); 47268899Sbapt if ((changed = (len > buf_len)) != 0) 48268899Sbapt { 49268899Sbapt char *new_ptr = realloc(buf_ptr, (buf_len * 3) / 2); 50268899Sbapt if (new_ptr == 0) 51268899Sbapt { 52268899Sbapt free(buf_ptr); 53268899Sbapt buf_ptr = 0; 54268899Sbapt return; 55268899Sbapt } 56268899Sbapt buf_ptr = new_ptr; 57268899Sbapt } 58268899Sbapt } 59268899Sbapt while (changed); 60268899Sbapt#else 61264790Sbapt va_start(args, fmt); 62268899Sbapt len = (size_t) vsprintf(buf_ptr, fmt, args); 63264790Sbapt va_end(args); 64268899Sbapt if (len >= buf_len) 65268899Sbapt return; 66268899Sbapt#endif 67264790Sbapt 68264790Sbapt if (len > (size_t) (s->end - s->ptr)) 69264790Sbapt { 70268899Sbapt 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; 76268899Sbapt if ((new_base = realloc(s->base, nl))) 77264790Sbapt { 78268899Sbapt s->base = new_base; 79264790Sbapt s->ptr = s->base + cp; 80264790Sbapt s->end = s->base + nl; 81264790Sbapt } 82264790Sbapt else 83264790Sbapt { 84268899Sbapt free(s->base); 85268899Sbapt s->base = 0; 86268899Sbapt s->ptr = 0; 87268899Sbapt s->end = 0; 88264790Sbapt return; 89264790Sbapt } 90264790Sbapt } 91268899Sbapt 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{ 122268899Sbapt struct mstring *n = TMALLOC(struct mstring, 1); 123264790Sbapt 124264790Sbapt if (n) 125264790Sbapt { 126268899Sbapt 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 196268899Sbapt 197268899Sbapt#ifdef NO_LEAKS 198268899Sbaptvoid 199268899Sbaptmstring_leaks(void) 200268899Sbapt{ 201268899Sbapt#if defined(YYBTYACC) 202268899Sbapt free(buf_ptr); 203268899Sbapt buf_ptr = 0; 204268899Sbapt buf_len = 0; 205268899Sbapt#endif 206268899Sbapt} 207268899Sbapt#endif 208