mstring.c revision 268899
167754Smsmith/* $Id: mstring.c,v 1.6 2014/04/22 23:36:31 tom Exp $ */
267754Smsmith
3249112Sjkim#include <stdlib.h>
467754Smsmith#include <stdio.h>
567754Smsmith#include <stdarg.h>
667754Smsmith#include <ctype.h>
7316303Sjkim#include <string.h>
8316303Sjkim#include "defs.h"
9316303Sjkim
10316303Sjkim/* parameters about string length.  HEAD is the starting size and
11316303Sjkim** HEAD+TAIL should be a power of two */
1270243Smsmith#define HEAD	24
1367754Smsmith#define TAIL	8
14316303Sjkim
15316303Sjkim#if defined(YYBTYACC)
16316303Sjkim
17316303Sjkimstatic char *buf_ptr;
18316303Sjkimstatic size_t buf_len;
19316303Sjkim
20316303Sjkimvoid
21316303Sjkimmsprintf(struct mstring *s, const char *fmt,...)
22316303Sjkim{
23316303Sjkim    va_list args;
24316303Sjkim    size_t len;
25316303Sjkim#ifdef HAVE_VSNPRINTF
26316303Sjkim    int changed;
27316303Sjkim#endif
28316303Sjkim
29316303Sjkim    if (!s || !s->base)
30316303Sjkim	return;
31316303Sjkim
32316303Sjkim    if (buf_len == 0)
33316303Sjkim    {
34316303Sjkim	buf_ptr = malloc(buf_len = 4096);
35316303Sjkim    }
36316303Sjkim    if (buf_ptr == 0)
37316303Sjkim    {
38316303Sjkim	return;
39316303Sjkim    }
40316303Sjkim
41316303Sjkim#ifdef HAVE_VSNPRINTF
42316303Sjkim    do
43316303Sjkim    {
44316303Sjkim	va_start(args, fmt);
45316303Sjkim	len = (size_t) vsnprintf(buf_ptr, buf_len, fmt, args);
46316303Sjkim	va_end(args);
47316303Sjkim	if ((changed = (len > buf_len)) != 0)
48316303Sjkim	{
49316303Sjkim	    char *new_ptr = realloc(buf_ptr, (buf_len * 3) / 2);
50316303Sjkim	    if (new_ptr == 0)
51316303Sjkim	    {
52316303Sjkim		free(buf_ptr);
53316303Sjkim		buf_ptr = 0;
54316303Sjkim		return;
55316303Sjkim	    }
56316303Sjkim	    buf_ptr = new_ptr;
57316303Sjkim	}
58316303Sjkim    }
59316303Sjkim    while (changed);
60316303Sjkim#else
61316303Sjkim    va_start(args, fmt);
62316303Sjkim    len = (size_t) vsprintf(buf_ptr, fmt, args);
63316303Sjkim    va_end(args);
64316303Sjkim    if (len >= buf_len)
65316303Sjkim	return;
66316303Sjkim#endif
67316303Sjkim
68316303Sjkim    if (len > (size_t) (s->end - s->ptr))
69316303Sjkim    {
70316303Sjkim	char *new_base;
71316303Sjkim	size_t cp = (size_t) (s->ptr - s->base);
72316303Sjkim	size_t cl = (size_t) (s->end - s->base);
73316303Sjkim	size_t nl = cl;
74316303Sjkim	while (len > (nl - cp))
75316303Sjkim	    nl = nl + nl + TAIL;
76316303Sjkim	if ((new_base = realloc(s->base, nl)))
77316303Sjkim	{
78316303Sjkim	    s->base = new_base;
79316303Sjkim	    s->ptr = s->base + cp;
80316303Sjkim	    s->end = s->base + nl;
81316303Sjkim	}
82316303Sjkim	else
83316303Sjkim	{
84316303Sjkim	    free(s->base);
85316303Sjkim	    s->base = 0;
86316303Sjkim	    s->ptr = 0;
87316303Sjkim	    s->end = 0;
88316303Sjkim	    return;
89316303Sjkim	}
90316303Sjkim    }
91316303Sjkim    memcpy(s->ptr, buf_ptr, len);
92316303Sjkim    s->ptr += len;
93316303Sjkim}
94316303Sjkim#endif
95316303Sjkim
96316303Sjkimint
97316303Sjkimmputchar(struct mstring *s, int ch)
98316303Sjkim{
99316303Sjkim    if (!s || !s->base)
100316303Sjkim	return ch;
101316303Sjkim    if (s->ptr == s->end)
102316303Sjkim    {
103316303Sjkim	size_t len = (size_t) (s->end - s->base);
104316303Sjkim	if ((s->base = realloc(s->base, len + len + TAIL)))
105316303Sjkim	{
106316303Sjkim	    s->ptr = s->base + len;
107316303Sjkim	    s->end = s->base + len + len + TAIL;
108316303Sjkim	}
109316303Sjkim	else
110316303Sjkim	{
111316303Sjkim	    s->ptr = s->end = 0;
112316303Sjkim	    return ch;
113316303Sjkim	}
114316303Sjkim    }
115316303Sjkim    *s->ptr++ = (char)ch;
116316303Sjkim    return ch;
117316303Sjkim}
118316303Sjkim
119217365Sjkimstruct mstring *
120217365Sjkimmsnew(void)
121217365Sjkim{
122217365Sjkim    struct mstring *n = TMALLOC(struct mstring, 1);
123217365Sjkim
124217365Sjkim    if (n)
125217365Sjkim    {
126217365Sjkim	if ((n->base = n->ptr = MALLOC(HEAD)) != 0)
127217365Sjkim	{
128217365Sjkim	    n->end = n->base + HEAD;
129217365Sjkim	}
130217365Sjkim	else
131217365Sjkim	{
132217365Sjkim	    free(n);
13367754Smsmith	    n = 0;
134316303Sjkim	}
135316303Sjkim    }
136316303Sjkim    return n;
137316303Sjkim}
138316303Sjkim
139316303Sjkimchar *
140316303Sjkimmsdone(struct mstring *s)
141316303Sjkim{
142316303Sjkim    char *r = 0;
143316303Sjkim    if (s)
144316303Sjkim    {
145316303Sjkim	mputc(s, 0);
146316303Sjkim	r = s->base;
147217365Sjkim	free(s);
148217365Sjkim    }
14967754Smsmith    return r;
150316303Sjkim}
15167754Smsmith
152193341Sjkim#if defined(YYBTYACC)
153193341Sjkim/* compare two strings, ignoring whitespace, except between two letters or
154193341Sjkim** digits (and treat all of these as equal) */
155193341Sjkimint
156193341Sjkimstrnscmp(const char *a, const char *b)
157193341Sjkim{
158193341Sjkim    while (1)
159193341Sjkim    {
160193341Sjkim	while (isspace(*a))
16167754Smsmith	    a++;
16277424Smsmith	while (isspace(*b))
16391116Smsmith	    b++;
16467754Smsmith	while (*a && *a == *b)
165151937Sjkim	    a++, b++;
16667754Smsmith	if (isspace(*a))
167151937Sjkim	{
168151937Sjkim	    if (isalnum(a[-1]) && isalnum(*b))
169151937Sjkim		break;
170151937Sjkim	}
171151937Sjkim	else if (isspace(*b))
172151937Sjkim	{
173151937Sjkim	    if (isalnum(b[-1]) && isalnum(*a))
174151937Sjkim		break;
175151937Sjkim	}
176151937Sjkim	else
177151937Sjkim	    break;
17867754Smsmith    }
17967754Smsmith    return *a - *b;
18067754Smsmith}
181151937Sjkim
18267754Smsmithunsigned int
18367754Smsmithstrnshash(const char *s)
18467754Smsmith{
18599679Siwasaki    unsigned int h = 0;
18667754Smsmith
187151937Sjkim    while (*s)
18867754Smsmith    {
18967754Smsmith	if (!isspace(*s))
19067754Smsmith	    h = (h << 5) - h + (unsigned char)*s;
19167754Smsmith	s++;
19267754Smsmith    }
19367754Smsmith    return h;
19467754Smsmith}
19567754Smsmith#endif
19667754Smsmith
19767754Smsmith#ifdef NO_LEAKS
19867754Smsmithvoid
19967754Smsmithmstring_leaks(void)
20067754Smsmith{
201316303Sjkim#if defined(YYBTYACC)
20267754Smsmith    free(buf_ptr);
20367754Smsmith    buf_ptr = 0;
20467754Smsmith    buf_len = 0;
20567754Smsmith#endif
206151937Sjkim}
20767754Smsmith#endif
20899679Siwasaki