mstring.c revision 303975
1/* $Id: mstring.c,v 1.6 2014/04/22 23:36:31 tom Exp $ */ 2 3#include <stdlib.h> 4#include <stdio.h> 5#include <stdarg.h> 6#include <ctype.h> 7#include <string.h> 8#include "defs.h" 9 10/* parameters about string length. HEAD is the starting size and 11** HEAD+TAIL should be a power of two */ 12#define HEAD 24 13#define TAIL 8 14 15#if defined(YYBTYACC) 16 17static char *buf_ptr; 18static size_t buf_len; 19 20void 21msprintf(struct mstring *s, const char *fmt,...) 22{ 23 va_list args; 24 size_t len; 25#ifdef HAVE_VSNPRINTF 26 int changed; 27#endif 28 29 if (!s || !s->base) 30 return; 31 32 if (buf_len == 0) 33 { 34 buf_ptr = malloc(buf_len = 4096); 35 } 36 if (buf_ptr == 0) 37 { 38 return; 39 } 40 41#ifdef HAVE_VSNPRINTF 42 do 43 { 44 va_start(args, fmt); 45 len = (size_t) vsnprintf(buf_ptr, buf_len, fmt, args); 46 va_end(args); 47 if ((changed = (len > buf_len)) != 0) 48 { 49 char *new_ptr = realloc(buf_ptr, (buf_len * 3) / 2); 50 if (new_ptr == 0) 51 { 52 free(buf_ptr); 53 buf_ptr = 0; 54 return; 55 } 56 buf_ptr = new_ptr; 57 } 58 } 59 while (changed); 60#else 61 va_start(args, fmt); 62 len = (size_t) vsprintf(buf_ptr, fmt, args); 63 va_end(args); 64 if (len >= buf_len) 65 return; 66#endif 67 68 if (len > (size_t) (s->end - s->ptr)) 69 { 70 char *new_base; 71 size_t cp = (size_t) (s->ptr - s->base); 72 size_t cl = (size_t) (s->end - s->base); 73 size_t nl = cl; 74 while (len > (nl - cp)) 75 nl = nl + nl + TAIL; 76 if ((new_base = realloc(s->base, nl))) 77 { 78 s->base = new_base; 79 s->ptr = s->base + cp; 80 s->end = s->base + nl; 81 } 82 else 83 { 84 free(s->base); 85 s->base = 0; 86 s->ptr = 0; 87 s->end = 0; 88 return; 89 } 90 } 91 memcpy(s->ptr, buf_ptr, len); 92 s->ptr += len; 93} 94#endif 95 96int 97mputchar(struct mstring *s, int ch) 98{ 99 if (!s || !s->base) 100 return ch; 101 if (s->ptr == s->end) 102 { 103 size_t len = (size_t) (s->end - s->base); 104 if ((s->base = realloc(s->base, len + len + TAIL))) 105 { 106 s->ptr = s->base + len; 107 s->end = s->base + len + len + TAIL; 108 } 109 else 110 { 111 s->ptr = s->end = 0; 112 return ch; 113 } 114 } 115 *s->ptr++ = (char)ch; 116 return ch; 117} 118 119struct mstring * 120msnew(void) 121{ 122 struct mstring *n = TMALLOC(struct mstring, 1); 123 124 if (n) 125 { 126 if ((n->base = n->ptr = MALLOC(HEAD)) != 0) 127 { 128 n->end = n->base + HEAD; 129 } 130 else 131 { 132 free(n); 133 n = 0; 134 } 135 } 136 return n; 137} 138 139char * 140msdone(struct mstring *s) 141{ 142 char *r = 0; 143 if (s) 144 { 145 mputc(s, 0); 146 r = s->base; 147 free(s); 148 } 149 return r; 150} 151 152#if defined(YYBTYACC) 153/* compare two strings, ignoring whitespace, except between two letters or 154** digits (and treat all of these as equal) */ 155int 156strnscmp(const char *a, const char *b) 157{ 158 while (1) 159 { 160 while (isspace(*a)) 161 a++; 162 while (isspace(*b)) 163 b++; 164 while (*a && *a == *b) 165 a++, b++; 166 if (isspace(*a)) 167 { 168 if (isalnum(a[-1]) && isalnum(*b)) 169 break; 170 } 171 else if (isspace(*b)) 172 { 173 if (isalnum(b[-1]) && isalnum(*a)) 174 break; 175 } 176 else 177 break; 178 } 179 return *a - *b; 180} 181 182unsigned int 183strnshash(const char *s) 184{ 185 unsigned int h = 0; 186 187 while (*s) 188 { 189 if (!isspace(*s)) 190 h = (h << 5) - h + (unsigned char)*s; 191 s++; 192 } 193 return h; 194} 195#endif 196 197#ifdef NO_LEAKS 198void 199mstring_leaks(void) 200{ 201#if defined(YYBTYACC) 202 free(buf_ptr); 203 buf_ptr = 0; 204 buf_len = 0; 205#endif 206} 207#endif 208