1 /* $NetBSD: mstring.c,v 1.3 2015/01/04 01:34:20 christos Exp $ */
2
3 /* Id: mstring.c,v 1.6 2014/04/22 23:36:31 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.3 2015/01/04 01:34:20 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
msprintf(struct mstring * s,const char * fmt,...)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
mputchar(struct mstring * s,int ch)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 *
msnew(void)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 *
msdone(struct mstring * s)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
strnscmp(const char * a,const char * b)164 strnscmp(const char *a, const char *b)
165 {
166 while (1)
167 {
168 while (isspace((unsigned char)*a))
169 a++;
170 while (isspace((unsigned char)*b))
171 b++;
172 while (*a && *a == *b)
173 a++, b++;
174 if (isspace((unsigned char)*a))
175 {
176 if (isalnum((unsigned char)a[-1]) && isalnum((unsigned char)*b))
177 break;
178 }
179 else if (isspace((unsigned char)*b))
180 {
181 if (isalnum((unsigned char)b[-1]) && isalnum((unsigned char)*a))
182 break;
183 }
184 else
185 break;
186 }
187 return *a - *b;
188 }
189
190 unsigned int
strnshash(const char * s)191 strnshash(const char *s)
192 {
193 unsigned int h = 0;
194
195 while (*s)
196 {
197 if (!isspace((unsigned char)*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
mstring_leaks(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