1 /* $Id: mstring.c,v 1.3 2014/04/08 20:37:26 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 void 17 msprintf(struct mstring *s, const char *fmt,...) 18 { 19 static char buf[4096]; /* a big static buffer */ 20 va_list args; 21 size_t len; 22 23 if (!s || !s->base) 24 return; 25 va_start(args, fmt); 26 vsprintf(buf, fmt, args); 27 va_end(args); 28 29 len = strlen(buf); 30 if (len > (size_t) (s->end - s->ptr)) 31 { 32 size_t cp = (size_t) (s->ptr - s->base); 33 size_t cl = (size_t) (s->end - s->base); 34 size_t nl = cl; 35 while (len > (nl - cp)) 36 nl = nl + nl + TAIL; 37 if ((s->base = realloc(s->base, nl))) 38 { 39 s->ptr = s->base + cp; 40 s->end = s->base + nl; 41 } 42 else 43 { 44 s->ptr = s->end = 0; 45 return; 46 } 47 } 48 memcpy(s->ptr, buf, len); 49 s->ptr += len; 50 } 51 #endif 52 53 int 54 mputchar(struct mstring *s, int ch) 55 { 56 if (!s || !s->base) 57 return ch; 58 if (s->ptr == s->end) 59 { 60 size_t len = (size_t) (s->end - s->base); 61 if ((s->base = realloc(s->base, len + len + TAIL))) 62 { 63 s->ptr = s->base + len; 64 s->end = s->base + len + len + TAIL; 65 } 66 else 67 { 68 s->ptr = s->end = 0; 69 return ch; 70 } 71 } 72 *s->ptr++ = (char)ch; 73 return ch; 74 } 75 76 struct mstring * 77 msnew(void) 78 { 79 struct mstring *n = malloc(sizeof(struct mstring)); 80 81 if (n) 82 { 83 if ((n->base = n->ptr = malloc(HEAD)) != 0) 84 { 85 n->end = n->base + HEAD; 86 } 87 else 88 { 89 free(n); 90 n = 0; 91 } 92 } 93 return n; 94 } 95 96 char * 97 msdone(struct mstring *s) 98 { 99 char *r = 0; 100 if (s) 101 { 102 mputc(s, 0); 103 r = s->base; 104 free(s); 105 } 106 return r; 107 } 108 109 #if defined(YYBTYACC) 110 /* compare two strings, ignoring whitespace, except between two letters or 111 ** digits (and treat all of these as equal) */ 112 int 113 strnscmp(const char *a, const char *b) 114 { 115 while (1) 116 { 117 while (isspace(*a)) 118 a++; 119 while (isspace(*b)) 120 b++; 121 while (*a && *a == *b) 122 a++, b++; 123 if (isspace(*a)) 124 { 125 if (isalnum(a[-1]) && isalnum(*b)) 126 break; 127 } 128 else if (isspace(*b)) 129 { 130 if (isalnum(b[-1]) && isalnum(*a)) 131 break; 132 } 133 else 134 break; 135 } 136 return *a - *b; 137 } 138 139 unsigned int 140 strnshash(const char *s) 141 { 142 unsigned int h = 0; 143 144 while (*s) 145 { 146 if (!isspace(*s)) 147 h = (h << 5) - h + (unsigned char)*s; 148 s++; 149 } 150 return h; 151 } 152 #endif 153