1268899Sbapt/* $Id: mstring.c,v 1.6 2014/04/22 23:36:31 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)
16268899Sbapt
17268899Sbaptstatic char *buf_ptr;
18268899Sbaptstatic size_t buf_len;
19268899Sbapt
20264790Sbaptvoid
21264790Sbaptmsprintf(struct mstring *s, const char *fmt,...)
22264790Sbapt{
23264790Sbapt    va_list args;
24264790Sbapt    size_t len;
25268899Sbapt#ifdef HAVE_VSNPRINTF
26268899Sbapt    int changed;
27268899Sbapt#endif
28264790Sbapt
29264790Sbapt    if (!s || !s->base)
30264790Sbapt	return;
31268899Sbapt
32268899Sbapt    if (buf_len == 0)
33268899Sbapt    {
34268899Sbapt	buf_ptr = malloc(buf_len = 4096);
35268899Sbapt    }
36268899Sbapt    if (buf_ptr == 0)
37268899Sbapt    {
38268899Sbapt	return;
39268899Sbapt    }
40268899Sbapt
41268899Sbapt#ifdef HAVE_VSNPRINTF
42268899Sbapt    do
43268899Sbapt    {
44268899Sbapt	va_start(args, fmt);
45268899Sbapt	len = (size_t) vsnprintf(buf_ptr, buf_len, fmt, args);
46268899Sbapt	va_end(args);
47268899Sbapt	if ((changed = (len > buf_len)) != 0)
48268899Sbapt	{
49268899Sbapt	    char *new_ptr = realloc(buf_ptr, (buf_len * 3) / 2);
50268899Sbapt	    if (new_ptr == 0)
51268899Sbapt	    {
52268899Sbapt		free(buf_ptr);
53268899Sbapt		buf_ptr = 0;
54268899Sbapt		return;
55268899Sbapt	    }
56268899Sbapt	    buf_ptr = new_ptr;
57268899Sbapt	}
58268899Sbapt    }
59268899Sbapt    while (changed);
60268899Sbapt#else
61264790Sbapt    va_start(args, fmt);
62268899Sbapt    len = (size_t) vsprintf(buf_ptr, fmt, args);
63264790Sbapt    va_end(args);
64268899Sbapt    if (len >= buf_len)
65268899Sbapt	return;
66268899Sbapt#endif
67264790Sbapt
68264790Sbapt    if (len > (size_t) (s->end - s->ptr))
69264790Sbapt    {
70268899Sbapt	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;
76268899Sbapt	if ((new_base = realloc(s->base, nl)))
77264790Sbapt	{
78268899Sbapt	    s->base = new_base;
79264790Sbapt	    s->ptr = s->base + cp;
80264790Sbapt	    s->end = s->base + nl;
81264790Sbapt	}
82264790Sbapt	else
83264790Sbapt	{
84268899Sbapt	    free(s->base);
85268899Sbapt	    s->base = 0;
86268899Sbapt	    s->ptr = 0;
87268899Sbapt	    s->end = 0;
88264790Sbapt	    return;
89264790Sbapt	}
90264790Sbapt    }
91268899Sbapt    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{
122268899Sbapt    struct mstring *n = TMALLOC(struct mstring, 1);
123264790Sbapt
124264790Sbapt    if (n)
125264790Sbapt    {
126268899Sbapt	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    {
160264790Sbapt	while (isspace(*a))
161264790Sbapt	    a++;
162264790Sbapt	while (isspace(*b))
163264790Sbapt	    b++;
164264790Sbapt	while (*a && *a == *b)
165264790Sbapt	    a++, b++;
166264790Sbapt	if (isspace(*a))
167264790Sbapt	{
168264790Sbapt	    if (isalnum(a[-1]) && isalnum(*b))
169264790Sbapt		break;
170264790Sbapt	}
171264790Sbapt	else if (isspace(*b))
172264790Sbapt	{
173264790Sbapt	    if (isalnum(b[-1]) && isalnum(*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    {
189264790Sbapt	if (!isspace(*s))
190264790Sbapt	    h = (h << 5) - h + (unsigned char)*s;
191264790Sbapt	s++;
192264790Sbapt    }
193264790Sbapt    return h;
194264790Sbapt}
195264790Sbapt#endif
196268899Sbapt
197268899Sbapt#ifdef NO_LEAKS
198268899Sbaptvoid
199268899Sbaptmstring_leaks(void)
200268899Sbapt{
201268899Sbapt#if defined(YYBTYACC)
202268899Sbapt    free(buf_ptr);
203268899Sbapt    buf_ptr = 0;
204268899Sbapt    buf_len = 0;
205268899Sbapt#endif
206268899Sbapt}
207268899Sbapt#endif
208