mstring.c revision 268899
167754Smsmith/* $Id: mstring.c,v 1.6 2014/04/22 23:36:31 tom Exp $ */ 267754Smsmith 3249112Sjkim#include <stdlib.h> 467754Smsmith#include <stdio.h> 567754Smsmith#include <stdarg.h> 667754Smsmith#include <ctype.h> 7316303Sjkim#include <string.h> 8316303Sjkim#include "defs.h" 9316303Sjkim 10316303Sjkim/* parameters about string length. HEAD is the starting size and 11316303Sjkim** HEAD+TAIL should be a power of two */ 1270243Smsmith#define HEAD 24 1367754Smsmith#define TAIL 8 14316303Sjkim 15316303Sjkim#if defined(YYBTYACC) 16316303Sjkim 17316303Sjkimstatic char *buf_ptr; 18316303Sjkimstatic size_t buf_len; 19316303Sjkim 20316303Sjkimvoid 21316303Sjkimmsprintf(struct mstring *s, const char *fmt,...) 22316303Sjkim{ 23316303Sjkim va_list args; 24316303Sjkim size_t len; 25316303Sjkim#ifdef HAVE_VSNPRINTF 26316303Sjkim int changed; 27316303Sjkim#endif 28316303Sjkim 29316303Sjkim if (!s || !s->base) 30316303Sjkim return; 31316303Sjkim 32316303Sjkim if (buf_len == 0) 33316303Sjkim { 34316303Sjkim buf_ptr = malloc(buf_len = 4096); 35316303Sjkim } 36316303Sjkim if (buf_ptr == 0) 37316303Sjkim { 38316303Sjkim return; 39316303Sjkim } 40316303Sjkim 41316303Sjkim#ifdef HAVE_VSNPRINTF 42316303Sjkim do 43316303Sjkim { 44316303Sjkim va_start(args, fmt); 45316303Sjkim len = (size_t) vsnprintf(buf_ptr, buf_len, fmt, args); 46316303Sjkim va_end(args); 47316303Sjkim if ((changed = (len > buf_len)) != 0) 48316303Sjkim { 49316303Sjkim char *new_ptr = realloc(buf_ptr, (buf_len * 3) / 2); 50316303Sjkim if (new_ptr == 0) 51316303Sjkim { 52316303Sjkim free(buf_ptr); 53316303Sjkim buf_ptr = 0; 54316303Sjkim return; 55316303Sjkim } 56316303Sjkim buf_ptr = new_ptr; 57316303Sjkim } 58316303Sjkim } 59316303Sjkim while (changed); 60316303Sjkim#else 61316303Sjkim va_start(args, fmt); 62316303Sjkim len = (size_t) vsprintf(buf_ptr, fmt, args); 63316303Sjkim va_end(args); 64316303Sjkim if (len >= buf_len) 65316303Sjkim return; 66316303Sjkim#endif 67316303Sjkim 68316303Sjkim if (len > (size_t) (s->end - s->ptr)) 69316303Sjkim { 70316303Sjkim char *new_base; 71316303Sjkim size_t cp = (size_t) (s->ptr - s->base); 72316303Sjkim size_t cl = (size_t) (s->end - s->base); 73316303Sjkim size_t nl = cl; 74316303Sjkim while (len > (nl - cp)) 75316303Sjkim nl = nl + nl + TAIL; 76316303Sjkim if ((new_base = realloc(s->base, nl))) 77316303Sjkim { 78316303Sjkim s->base = new_base; 79316303Sjkim s->ptr = s->base + cp; 80316303Sjkim s->end = s->base + nl; 81316303Sjkim } 82316303Sjkim else 83316303Sjkim { 84316303Sjkim free(s->base); 85316303Sjkim s->base = 0; 86316303Sjkim s->ptr = 0; 87316303Sjkim s->end = 0; 88316303Sjkim return; 89316303Sjkim } 90316303Sjkim } 91316303Sjkim memcpy(s->ptr, buf_ptr, len); 92316303Sjkim s->ptr += len; 93316303Sjkim} 94316303Sjkim#endif 95316303Sjkim 96316303Sjkimint 97316303Sjkimmputchar(struct mstring *s, int ch) 98316303Sjkim{ 99316303Sjkim if (!s || !s->base) 100316303Sjkim return ch; 101316303Sjkim if (s->ptr == s->end) 102316303Sjkim { 103316303Sjkim size_t len = (size_t) (s->end - s->base); 104316303Sjkim if ((s->base = realloc(s->base, len + len + TAIL))) 105316303Sjkim { 106316303Sjkim s->ptr = s->base + len; 107316303Sjkim s->end = s->base + len + len + TAIL; 108316303Sjkim } 109316303Sjkim else 110316303Sjkim { 111316303Sjkim s->ptr = s->end = 0; 112316303Sjkim return ch; 113316303Sjkim } 114316303Sjkim } 115316303Sjkim *s->ptr++ = (char)ch; 116316303Sjkim return ch; 117316303Sjkim} 118316303Sjkim 119217365Sjkimstruct mstring * 120217365Sjkimmsnew(void) 121217365Sjkim{ 122217365Sjkim struct mstring *n = TMALLOC(struct mstring, 1); 123217365Sjkim 124217365Sjkim if (n) 125217365Sjkim { 126217365Sjkim if ((n->base = n->ptr = MALLOC(HEAD)) != 0) 127217365Sjkim { 128217365Sjkim n->end = n->base + HEAD; 129217365Sjkim } 130217365Sjkim else 131217365Sjkim { 132217365Sjkim free(n); 13367754Smsmith n = 0; 134316303Sjkim } 135316303Sjkim } 136316303Sjkim return n; 137316303Sjkim} 138316303Sjkim 139316303Sjkimchar * 140316303Sjkimmsdone(struct mstring *s) 141316303Sjkim{ 142316303Sjkim char *r = 0; 143316303Sjkim if (s) 144316303Sjkim { 145316303Sjkim mputc(s, 0); 146316303Sjkim r = s->base; 147217365Sjkim free(s); 148217365Sjkim } 14967754Smsmith return r; 150316303Sjkim} 15167754Smsmith 152193341Sjkim#if defined(YYBTYACC) 153193341Sjkim/* compare two strings, ignoring whitespace, except between two letters or 154193341Sjkim** digits (and treat all of these as equal) */ 155193341Sjkimint 156193341Sjkimstrnscmp(const char *a, const char *b) 157193341Sjkim{ 158193341Sjkim while (1) 159193341Sjkim { 160193341Sjkim while (isspace(*a)) 16167754Smsmith a++; 16277424Smsmith while (isspace(*b)) 16391116Smsmith b++; 16467754Smsmith while (*a && *a == *b) 165151937Sjkim a++, b++; 16667754Smsmith if (isspace(*a)) 167151937Sjkim { 168151937Sjkim if (isalnum(a[-1]) && isalnum(*b)) 169151937Sjkim break; 170151937Sjkim } 171151937Sjkim else if (isspace(*b)) 172151937Sjkim { 173151937Sjkim if (isalnum(b[-1]) && isalnum(*a)) 174151937Sjkim break; 175151937Sjkim } 176151937Sjkim else 177151937Sjkim break; 17867754Smsmith } 17967754Smsmith return *a - *b; 18067754Smsmith} 181151937Sjkim 18267754Smsmithunsigned int 18367754Smsmithstrnshash(const char *s) 18467754Smsmith{ 18599679Siwasaki unsigned int h = 0; 18667754Smsmith 187151937Sjkim while (*s) 18867754Smsmith { 18967754Smsmith if (!isspace(*s)) 19067754Smsmith h = (h << 5) - h + (unsigned char)*s; 19167754Smsmith s++; 19267754Smsmith } 19367754Smsmith return h; 19467754Smsmith} 19567754Smsmith#endif 19667754Smsmith 19767754Smsmith#ifdef NO_LEAKS 19867754Smsmithvoid 19967754Smsmithmstring_leaks(void) 20067754Smsmith{ 201316303Sjkim#if defined(YYBTYACC) 20267754Smsmith free(buf_ptr); 20367754Smsmith buf_ptr = 0; 20467754Smsmith buf_len = 0; 20567754Smsmith#endif 206151937Sjkim} 20767754Smsmith#endif 20899679Siwasaki