Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/byacc/mstring.c
39475 views
1
/* $Id: mstring.c,v 1.10 2023/02/26 10:15:01 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
static char *buf_ptr;
16
static size_t buf_len;
17
18
void
19
msprintf(struct mstring *s, const char *fmt, ...)
20
{
21
va_list args;
22
size_t len;
23
#ifdef HAVE_VSNPRINTF
24
int changed;
25
#endif
26
27
if (!s || !s->base)
28
return;
29
30
if (buf_len == 0)
31
{
32
buf_ptr = malloc(buf_len = 4096);
33
}
34
if (buf_ptr == 0)
35
{
36
return;
37
}
38
39
#ifdef HAVE_VSNPRINTF
40
do
41
{
42
va_start(args, fmt);
43
len = (size_t)vsnprintf(buf_ptr, buf_len, fmt, args);
44
va_end(args);
45
if ((changed = (len > buf_len)) != 0)
46
{
47
char *new_ptr = realloc(buf_ptr, (buf_len * 3) / 2);
48
if (new_ptr == 0)
49
{
50
free(buf_ptr);
51
buf_ptr = 0;
52
return;
53
}
54
buf_ptr = new_ptr;
55
}
56
}
57
while (changed);
58
#else
59
va_start(args, fmt);
60
len = (size_t)vsprintf(buf_ptr, fmt, args);
61
va_end(args);
62
if (len >= buf_len)
63
return;
64
#endif
65
66
if (len > (size_t)(s->end - s->ptr))
67
{
68
char *new_base;
69
size_t cp = (size_t)(s->ptr - s->base);
70
size_t cl = (size_t)(s->end - s->base);
71
size_t nl = cl;
72
while (len > (nl - cp))
73
nl = nl + nl + TAIL;
74
if ((new_base = realloc(s->base, nl)))
75
{
76
s->base = new_base;
77
s->ptr = s->base + cp;
78
s->end = s->base + nl;
79
}
80
else
81
{
82
free(s->base);
83
s->base = 0;
84
s->ptr = 0;
85
s->end = 0;
86
return;
87
}
88
}
89
memcpy(s->ptr, buf_ptr, len);
90
s->ptr += len;
91
}
92
93
int
94
mputchar(struct mstring *s, int ch)
95
{
96
if (!s || !s->base)
97
return ch;
98
if (s->ptr == s->end)
99
{
100
size_t len = (size_t)(s->end - s->base);
101
if ((s->base = realloc(s->base, len + len + TAIL)))
102
{
103
s->ptr = s->base + len;
104
s->end = s->base + len + len + TAIL;
105
}
106
else
107
{
108
s->ptr = s->end = 0;
109
return ch;
110
}
111
}
112
*s->ptr++ = (char)ch;
113
return ch;
114
}
115
116
struct mstring *
117
msnew(void)
118
{
119
struct mstring *n = TMALLOC(struct mstring, 1);
120
121
if (n)
122
{
123
if ((n->base = n->ptr = MALLOC(HEAD)) != 0)
124
{
125
n->end = n->base + HEAD;
126
}
127
else
128
{
129
free(n);
130
n = 0;
131
}
132
}
133
return n;
134
}
135
136
struct mstring *
137
msrenew(char *value)
138
{
139
struct mstring *r = 0;
140
if (value != 0)
141
{
142
r = msnew();
143
r->base = value;
144
r->end = value + strlen(value);
145
r->ptr = r->end;
146
}
147
return r;
148
}
149
150
char *
151
msdone(struct mstring *s)
152
{
153
char *r = 0;
154
if (s)
155
{
156
mputc(s, 0);
157
r = s->base;
158
free(s);
159
}
160
return r;
161
}
162
163
#if defined(YYBTYACC)
164
/* compare two strings, ignoring whitespace, except between two letters or
165
** digits (and treat all of these as equal) */
166
int
167
strnscmp(const char *a, const char *b)
168
{
169
while (1)
170
{
171
while (isspace(UCH(*a)))
172
a++;
173
while (isspace(UCH(*b)))
174
b++;
175
while (*a && *a == *b)
176
a++, b++;
177
if (isspace(UCH(*a)))
178
{
179
if (isalnum(UCH(a[-1])) && isalnum(UCH(*b)))
180
break;
181
}
182
else if (isspace(UCH(*b)))
183
{
184
if (isalnum(UCH(b[-1])) && isalnum(UCH(*a)))
185
break;
186
}
187
else
188
break;
189
}
190
return *a - *b;
191
}
192
193
unsigned int
194
strnshash(const char *s)
195
{
196
unsigned int h = 0;
197
198
while (*s)
199
{
200
if (!isspace(UCH(*s)))
201
h = (h << 5) - h + (unsigned char)*s;
202
s++;
203
}
204
return h;
205
}
206
#endif
207
208
#ifdef NO_LEAKS
209
void
210
mstring_leaks(void)
211
{
212
free(buf_ptr);
213
buf_ptr = 0;
214
buf_len = 0;
215
}
216
#endif
217
218