kmalloc: Avoid code duplication.
[dragonfly.git] / contrib / byacc / mstring.c
blobdc384e5a385de1a903207f38f0ef1d3e8189c86c
1 /* $Id: mstring.c,v 1.6 2014/04/22 23:36:31 tom Exp $ */
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <stdarg.h>
6 #include <ctype.h>
7 #include <string.h>
8 #include "defs.h"
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
15 #if defined(YYBTYACC)
17 static char *buf_ptr;
18 static size_t buf_len;
20 void
21 msprintf(struct mstring *s, const char *fmt,...)
23 va_list args;
24 size_t len;
25 #ifdef HAVE_VSNPRINTF
26 int changed;
27 #endif
29 if (!s || !s->base)
30 return;
32 if (buf_len == 0)
34 buf_ptr = malloc(buf_len = 4096);
36 if (buf_ptr == 0)
38 return;
41 #ifdef HAVE_VSNPRINTF
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)
49 char *new_ptr = realloc(buf_ptr, (buf_len * 3) / 2);
50 if (new_ptr == 0)
52 free(buf_ptr);
53 buf_ptr = 0;
54 return;
56 buf_ptr = new_ptr;
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
68 if (len > (size_t) (s->end - s->ptr))
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)))
78 s->base = new_base;
79 s->ptr = s->base + cp;
80 s->end = s->base + nl;
82 else
84 free(s->base);
85 s->base = 0;
86 s->ptr = 0;
87 s->end = 0;
88 return;
91 memcpy(s->ptr, buf_ptr, len);
92 s->ptr += len;
94 #endif
96 int
97 mputchar(struct mstring *s, int ch)
99 if (!s || !s->base)
100 return ch;
101 if (s->ptr == s->end)
103 size_t len = (size_t) (s->end - s->base);
104 if ((s->base = realloc(s->base, len + len + TAIL)))
106 s->ptr = s->base + len;
107 s->end = s->base + len + len + TAIL;
109 else
111 s->ptr = s->end = 0;
112 return ch;
115 *s->ptr++ = (char)ch;
116 return ch;
119 struct mstring *
120 msnew(void)
122 struct mstring *n = TMALLOC(struct mstring, 1);
124 if (n)
126 if ((n->base = n->ptr = MALLOC(HEAD)) != 0)
128 n->end = n->base + HEAD;
130 else
132 free(n);
133 n = 0;
136 return n;
139 char *
140 msdone(struct mstring *s)
142 char *r = 0;
143 if (s)
145 mputc(s, 0);
146 r = s->base;
147 free(s);
149 return r;
152 #if defined(YYBTYACC)
153 /* compare two strings, ignoring whitespace, except between two letters or
154 ** digits (and treat all of these as equal) */
156 strnscmp(const char *a, const char *b)
158 while (1)
160 while (isspace(*a))
161 a++;
162 while (isspace(*b))
163 b++;
164 while (*a && *a == *b)
165 a++, b++;
166 if (isspace(*a))
168 if (isalnum(a[-1]) && isalnum(*b))
169 break;
171 else if (isspace(*b))
173 if (isalnum(b[-1]) && isalnum(*a))
174 break;
176 else
177 break;
179 return *a - *b;
182 unsigned int
183 strnshash(const char *s)
185 unsigned int h = 0;
187 while (*s)
189 if (!isspace(*s))
190 h = (h << 5) - h + (unsigned char)*s;
191 s++;
193 return h;
195 #endif
197 #ifdef NO_LEAKS
198 void
199 mstring_leaks(void)
201 #if defined(YYBTYACC)
202 free(buf_ptr);
203 buf_ptr = 0;
204 buf_len = 0;
205 #endif
207 #endif