xref: /minix/external/bsd/byacc/dist/mstring.c (revision 0a6a1f1d)
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