Merge branch 'vendor/GCC50'
[dragonfly.git] / contrib / byacc / mstring.c
1 /* $Id: mstring.c,v 1.6 2014/04/22 23:36:31 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
17 static char *buf_ptr;
18 static size_t buf_len;
19
20 void
21 msprintf(struct mstring *s, const char *fmt,...)
22 {
23     va_list args;
24     size_t len;
25 #ifdef HAVE_VSNPRINTF
26     int changed;
27 #endif
28
29     if (!s || !s->base)
30         return;
31
32     if (buf_len == 0)
33     {
34         buf_ptr = malloc(buf_len = 4096);
35     }
36     if (buf_ptr == 0)
37     {
38         return;
39     }
40
41 #ifdef HAVE_VSNPRINTF
42     do
43     {
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)
48         {
49             char *new_ptr = realloc(buf_ptr, (buf_len * 3) / 2);
50             if (new_ptr == 0)
51             {
52                 free(buf_ptr);
53                 buf_ptr = 0;
54                 return;
55             }
56             buf_ptr = new_ptr;
57         }
58     }
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
67
68     if (len > (size_t) (s->end - s->ptr))
69     {
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)))
77         {
78             s->base = new_base;
79             s->ptr = s->base + cp;
80             s->end = s->base + nl;
81         }
82         else
83         {
84             free(s->base);
85             s->base = 0;
86             s->ptr = 0;
87             s->end = 0;
88             return;
89         }
90     }
91     memcpy(s->ptr, buf_ptr, len);
92     s->ptr += len;
93 }
94 #endif
95
96 int
97 mputchar(struct mstring *s, int ch)
98 {
99     if (!s || !s->base)
100         return ch;
101     if (s->ptr == s->end)
102     {
103         size_t len = (size_t) (s->end - s->base);
104         if ((s->base = realloc(s->base, len + len + TAIL)))
105         {
106             s->ptr = s->base + len;
107             s->end = s->base + len + len + TAIL;
108         }
109         else
110         {
111             s->ptr = s->end = 0;
112             return ch;
113         }
114     }
115     *s->ptr++ = (char)ch;
116     return ch;
117 }
118
119 struct mstring *
120 msnew(void)
121 {
122     struct mstring *n = TMALLOC(struct mstring, 1);
123
124     if (n)
125     {
126         if ((n->base = n->ptr = MALLOC(HEAD)) != 0)
127         {
128             n->end = n->base + HEAD;
129         }
130         else
131         {
132             free(n);
133             n = 0;
134         }
135     }
136     return n;
137 }
138
139 char *
140 msdone(struct mstring *s)
141 {
142     char *r = 0;
143     if (s)
144     {
145         mputc(s, 0);
146         r = s->base;
147         free(s);
148     }
149     return r;
150 }
151
152 #if defined(YYBTYACC)
153 /* compare two strings, ignoring whitespace, except between two letters or
154 ** digits (and treat all of these as equal) */
155 int
156 strnscmp(const char *a, const char *b)
157 {
158     while (1)
159     {
160         while (isspace(*a))
161             a++;
162         while (isspace(*b))
163             b++;
164         while (*a && *a == *b)
165             a++, b++;
166         if (isspace(*a))
167         {
168             if (isalnum(a[-1]) && isalnum(*b))
169                 break;
170         }
171         else if (isspace(*b))
172         {
173             if (isalnum(b[-1]) && isalnum(*a))
174                 break;
175         }
176         else
177             break;
178     }
179     return *a - *b;
180 }
181
182 unsigned int
183 strnshash(const char *s)
184 {
185     unsigned int h = 0;
186
187     while (*s)
188     {
189         if (!isspace(*s))
190             h = (h << 5) - h + (unsigned char)*s;
191         s++;
192     }
193     return h;
194 }
195 #endif
196
197 #ifdef NO_LEAKS
198 void
199 mstring_leaks(void)
200 {
201 #if defined(YYBTYACC)
202     free(buf_ptr);
203     buf_ptr = 0;
204     buf_len = 0;
205 #endif
206 }
207 #endif