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