mstring.c revision 264803
1/* $Id: mstring.c,v 1.3 2014/04/08 20:37:26 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)
16void
17msprintf(struct mstring *s, const char *fmt,...)
18{
19    static char buf[4096];	/* a big static buffer */
20    va_list args;
21    size_t len;
22
23    if (!s || !s->base)
24	return;
25    va_start(args, fmt);
26    vsprintf(buf, fmt, args);
27    va_end(args);
28
29    len = strlen(buf);
30    if (len > (size_t) (s->end - s->ptr))
31    {
32	size_t cp = (size_t) (s->ptr - s->base);
33	size_t cl = (size_t) (s->end - s->base);
34	size_t nl = cl;
35	while (len > (nl - cp))
36	    nl = nl + nl + TAIL;
37	if ((s->base = realloc(s->base, nl)))
38	{
39	    s->ptr = s->base + cp;
40	    s->end = s->base + nl;
41	}
42	else
43	{
44	    s->ptr = s->end = 0;
45	    return;
46	}
47    }
48    memcpy(s->ptr, buf, len);
49    s->ptr += len;
50}
51#endif
52
53int
54mputchar(struct mstring *s, int ch)
55{
56    if (!s || !s->base)
57	return ch;
58    if (s->ptr == s->end)
59    {
60	size_t len = (size_t) (s->end - s->base);
61	if ((s->base = realloc(s->base, len + len + TAIL)))
62	{
63	    s->ptr = s->base + len;
64	    s->end = s->base + len + len + TAIL;
65	}
66	else
67	{
68	    s->ptr = s->end = 0;
69	    return ch;
70	}
71    }
72    *s->ptr++ = (char)ch;
73    return ch;
74}
75
76struct mstring *
77msnew(void)
78{
79    struct mstring *n = malloc(sizeof(struct mstring));
80
81    if (n)
82    {
83	if ((n->base = n->ptr = malloc(HEAD)) != 0)
84	{
85	    n->end = n->base + HEAD;
86	}
87	else
88	{
89	    free(n);
90	    n = 0;
91	}
92    }
93    return n;
94}
95
96char *
97msdone(struct mstring *s)
98{
99    char *r = 0;
100    if (s)
101    {
102	mputc(s, 0);
103	r = s->base;
104	free(s);
105    }
106    return r;
107}
108
109#if defined(YYBTYACC)
110/* compare two strings, ignoring whitespace, except between two letters or
111** digits (and treat all of these as equal) */
112int
113strnscmp(const char *a, const char *b)
114{
115    while (1)
116    {
117	while (isspace(*a))
118	    a++;
119	while (isspace(*b))
120	    b++;
121	while (*a && *a == *b)
122	    a++, b++;
123	if (isspace(*a))
124	{
125	    if (isalnum(a[-1]) && isalnum(*b))
126		break;
127	}
128	else if (isspace(*b))
129	{
130	    if (isalnum(b[-1]) && isalnum(*a))
131		break;
132	}
133	else
134	    break;
135    }
136    return *a - *b;
137}
138
139unsigned int
140strnshash(const char *s)
141{
142    unsigned int h = 0;
143
144    while (*s)
145    {
146	if (!isspace(*s))
147	    h = (h << 5) - h + (unsigned char)*s;
148	s++;
149    }
150    return h;
151}
152#endif
153