1319297Sdelphij/* $Id: mstring.c,v 1.7 2016/12/02 17:57:21 tom Exp $ */
2264790Sbapt
3264790Sbapt#include <stdlib.h>
4264790Sbapt#include <stdio.h>
5264790Sbapt#include <stdarg.h>
6264790Sbapt#include <ctype.h>
7264790Sbapt#include <string.h>
8264790Sbapt#include "defs.h"
9264790Sbapt
10264790Sbapt/* parameters about string length.  HEAD is the starting size and
11264790Sbapt** HEAD+TAIL should be a power of two */
12264790Sbapt#define HEAD	24
13264790Sbapt#define TAIL	8
14264790Sbapt
15264790Sbapt#if defined(YYBTYACC)
16266639Sbapt
17266639Sbaptstatic char *buf_ptr;
18266639Sbaptstatic size_t buf_len;
19266639Sbapt
20264790Sbaptvoid
21264790Sbaptmsprintf(struct mstring *s, const char *fmt,...)
22264790Sbapt{
23264790Sbapt    va_list args;
24264790Sbapt    size_t len;
25266639Sbapt#ifdef HAVE_VSNPRINTF
26266639Sbapt    int changed;
27266639Sbapt#endif
28264790Sbapt
29264790Sbapt    if (!s || !s->base)
30264790Sbapt	return;
31266639Sbapt
32266639Sbapt    if (buf_len == 0)
33266639Sbapt    {
34266639Sbapt	buf_ptr = malloc(buf_len = 4096);
35266639Sbapt    }
36266639Sbapt    if (buf_ptr == 0)
37266639Sbapt    {
38266639Sbapt	return;
39266639Sbapt    }
40266639Sbapt
41266639Sbapt#ifdef HAVE_VSNPRINTF
42266639Sbapt    do
43266639Sbapt    {
44266639Sbapt	va_start(args, fmt);
45266639Sbapt	len = (size_t) vsnprintf(buf_ptr, buf_len, fmt, args);
46266639Sbapt	va_end(args);
47266639Sbapt	if ((changed = (len > buf_len)) != 0)
48266639Sbapt	{
49266639Sbapt	    char *new_ptr = realloc(buf_ptr, (buf_len * 3) / 2);
50266639Sbapt	    if (new_ptr == 0)
51266639Sbapt	    {
52266639Sbapt		free(buf_ptr);
53266639Sbapt		buf_ptr = 0;
54266639Sbapt		return;
55266639Sbapt	    }
56266639Sbapt	    buf_ptr = new_ptr;
57266639Sbapt	}
58266639Sbapt    }
59266639Sbapt    while (changed);
60266639Sbapt#else
61264790Sbapt    va_start(args, fmt);
62266639Sbapt    len = (size_t) vsprintf(buf_ptr, fmt, args);
63264790Sbapt    va_end(args);
64266639Sbapt    if (len >= buf_len)
65266639Sbapt	return;
66266639Sbapt#endif
67264790Sbapt
68264790Sbapt    if (len > (size_t) (s->end - s->ptr))
69264790Sbapt    {
70266639Sbapt	char *new_base;
71264790Sbapt	size_t cp = (size_t) (s->ptr - s->base);
72264790Sbapt	size_t cl = (size_t) (s->end - s->base);
73264790Sbapt	size_t nl = cl;
74264790Sbapt	while (len > (nl - cp))
75264790Sbapt	    nl = nl + nl + TAIL;
76266639Sbapt	if ((new_base = realloc(s->base, nl)))
77264790Sbapt	{
78266639Sbapt	    s->base = new_base;
79264790Sbapt	    s->ptr = s->base + cp;
80264790Sbapt	    s->end = s->base + nl;
81264790Sbapt	}
82264790Sbapt	else
83264790Sbapt	{
84266639Sbapt	    free(s->base);
85266639Sbapt	    s->base = 0;
86266639Sbapt	    s->ptr = 0;
87266639Sbapt	    s->end = 0;
88264790Sbapt	    return;
89264790Sbapt	}
90264790Sbapt    }
91266639Sbapt    memcpy(s->ptr, buf_ptr, len);
92264790Sbapt    s->ptr += len;
93264790Sbapt}
94264790Sbapt#endif
95264790Sbapt
96264790Sbaptint
97264790Sbaptmputchar(struct mstring *s, int ch)
98264790Sbapt{
99264790Sbapt    if (!s || !s->base)
100264790Sbapt	return ch;
101264790Sbapt    if (s->ptr == s->end)
102264790Sbapt    {
103264790Sbapt	size_t len = (size_t) (s->end - s->base);
104264790Sbapt	if ((s->base = realloc(s->base, len + len + TAIL)))
105264790Sbapt	{
106264790Sbapt	    s->ptr = s->base + len;
107264790Sbapt	    s->end = s->base + len + len + TAIL;
108264790Sbapt	}
109264790Sbapt	else
110264790Sbapt	{
111264790Sbapt	    s->ptr = s->end = 0;
112264790Sbapt	    return ch;
113264790Sbapt	}
114264790Sbapt    }
115264790Sbapt    *s->ptr++ = (char)ch;
116264790Sbapt    return ch;
117264790Sbapt}
118264790Sbapt
119264790Sbaptstruct mstring *
120264790Sbaptmsnew(void)
121264790Sbapt{
122266639Sbapt    struct mstring *n = TMALLOC(struct mstring, 1);
123264790Sbapt
124264790Sbapt    if (n)
125264790Sbapt    {
126266639Sbapt	if ((n->base = n->ptr = MALLOC(HEAD)) != 0)
127264790Sbapt	{
128264790Sbapt	    n->end = n->base + HEAD;
129264790Sbapt	}
130264790Sbapt	else
131264790Sbapt	{
132264790Sbapt	    free(n);
133264790Sbapt	    n = 0;
134264790Sbapt	}
135264790Sbapt    }
136264790Sbapt    return n;
137264790Sbapt}
138264790Sbapt
139264790Sbaptchar *
140264790Sbaptmsdone(struct mstring *s)
141264790Sbapt{
142264790Sbapt    char *r = 0;
143264790Sbapt    if (s)
144264790Sbapt    {
145264790Sbapt	mputc(s, 0);
146264790Sbapt	r = s->base;
147264790Sbapt	free(s);
148264790Sbapt    }
149264790Sbapt    return r;
150264790Sbapt}
151264790Sbapt
152264790Sbapt#if defined(YYBTYACC)
153264790Sbapt/* compare two strings, ignoring whitespace, except between two letters or
154264790Sbapt** digits (and treat all of these as equal) */
155264790Sbaptint
156264790Sbaptstrnscmp(const char *a, const char *b)
157264790Sbapt{
158264790Sbapt    while (1)
159264790Sbapt    {
160319297Sdelphij	while (isspace(UCH(*a)))
161264790Sbapt	    a++;
162319297Sdelphij	while (isspace(UCH(*b)))
163264790Sbapt	    b++;
164264790Sbapt	while (*a && *a == *b)
165264790Sbapt	    a++, b++;
166319297Sdelphij	if (isspace(UCH(*a)))
167264790Sbapt	{
168319297Sdelphij	    if (isalnum(UCH(a[-1])) && isalnum(UCH(*b)))
169264790Sbapt		break;
170264790Sbapt	}
171319297Sdelphij	else if (isspace(UCH(*b)))
172264790Sbapt	{
173319297Sdelphij	    if (isalnum(UCH(b[-1])) && isalnum(UCH(*a)))
174264790Sbapt		break;
175264790Sbapt	}
176264790Sbapt	else
177264790Sbapt	    break;
178264790Sbapt    }
179264790Sbapt    return *a - *b;
180264790Sbapt}
181264790Sbapt
182264790Sbaptunsigned int
183264790Sbaptstrnshash(const char *s)
184264790Sbapt{
185264790Sbapt    unsigned int h = 0;
186264790Sbapt
187264790Sbapt    while (*s)
188264790Sbapt    {
189319297Sdelphij	if (!isspace(UCH(*s)))
190264790Sbapt	    h = (h << 5) - h + (unsigned char)*s;
191264790Sbapt	s++;
192264790Sbapt    }
193264790Sbapt    return h;
194264790Sbapt}
195264790Sbapt#endif
196266639Sbapt
197266639Sbapt#ifdef NO_LEAKS
198266639Sbaptvoid
199266639Sbaptmstring_leaks(void)
200266639Sbapt{
201266639Sbapt#if defined(YYBTYACC)
202266639Sbapt    free(buf_ptr);
203266639Sbapt    buf_ptr = 0;
204266639Sbapt    buf_len = 0;
205266639Sbapt#endif
206266639Sbapt}
207266639Sbapt#endif
208