xref: /freebsd/contrib/byacc/mstring.c (revision 4313cc83440a39bdf976f955b1d4d3f3c4d1552f)
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)
16 void
17 msprintf(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 
53 int
54 mputchar(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 
76 struct mstring *
77 msnew(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 
96 char *
97 msdone(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) */
112 int
113 strnscmp(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 
139 unsigned int
140 strnshash(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