diff options
Diffstat (limited to 'contrib/byacc/mstring.c')
-rw-r--r-- | contrib/byacc/mstring.c | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/contrib/byacc/mstring.c b/contrib/byacc/mstring.c new file mode 100644 index 0000000..dc384e5 --- /dev/null +++ b/contrib/byacc/mstring.c @@ -0,0 +1,207 @@ +/* $Id: mstring.c,v 1.6 2014/04/22 23:36:31 tom Exp $ */ + +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <ctype.h> +#include <string.h> +#include "defs.h" + +/* parameters about string length. HEAD is the starting size and +** HEAD+TAIL should be a power of two */ +#define HEAD 24 +#define TAIL 8 + +#if defined(YYBTYACC) + +static char *buf_ptr; +static size_t buf_len; + +void +msprintf(struct mstring *s, const char *fmt,...) +{ + va_list args; + size_t len; +#ifdef HAVE_VSNPRINTF + int changed; +#endif + + if (!s || !s->base) + return; + + if (buf_len == 0) + { + buf_ptr = malloc(buf_len = 4096); + } + if (buf_ptr == 0) + { + return; + } + +#ifdef HAVE_VSNPRINTF + do + { + va_start(args, fmt); + len = (size_t) vsnprintf(buf_ptr, buf_len, fmt, args); + va_end(args); + if ((changed = (len > buf_len)) != 0) + { + char *new_ptr = realloc(buf_ptr, (buf_len * 3) / 2); + if (new_ptr == 0) + { + free(buf_ptr); + buf_ptr = 0; + return; + } + buf_ptr = new_ptr; + } + } + while (changed); +#else + va_start(args, fmt); + len = (size_t) vsprintf(buf_ptr, fmt, args); + va_end(args); + if (len >= buf_len) + return; +#endif + + if (len > (size_t) (s->end - s->ptr)) + { + char *new_base; + size_t cp = (size_t) (s->ptr - s->base); + size_t cl = (size_t) (s->end - s->base); + size_t nl = cl; + while (len > (nl - cp)) + nl = nl + nl + TAIL; + if ((new_base = realloc(s->base, nl))) + { + s->base = new_base; + s->ptr = s->base + cp; + s->end = s->base + nl; + } + else + { + free(s->base); + s->base = 0; + s->ptr = 0; + s->end = 0; + return; + } + } + memcpy(s->ptr, buf_ptr, len); + s->ptr += len; +} +#endif + +int +mputchar(struct mstring *s, int ch) +{ + if (!s || !s->base) + return ch; + if (s->ptr == s->end) + { + size_t len = (size_t) (s->end - s->base); + if ((s->base = realloc(s->base, len + len + TAIL))) + { + s->ptr = s->base + len; + s->end = s->base + len + len + TAIL; + } + else + { + s->ptr = s->end = 0; + return ch; + } + } + *s->ptr++ = (char)ch; + return ch; +} + +struct mstring * +msnew(void) +{ + struct mstring *n = TMALLOC(struct mstring, 1); + + if (n) + { + if ((n->base = n->ptr = MALLOC(HEAD)) != 0) + { + n->end = n->base + HEAD; + } + else + { + free(n); + n = 0; + } + } + return n; +} + +char * +msdone(struct mstring *s) +{ + char *r = 0; + if (s) + { + mputc(s, 0); + r = s->base; + free(s); + } + return r; +} + +#if defined(YYBTYACC) +/* compare two strings, ignoring whitespace, except between two letters or +** digits (and treat all of these as equal) */ +int +strnscmp(const char *a, const char *b) +{ + while (1) + { + while (isspace(*a)) + a++; + while (isspace(*b)) + b++; + while (*a && *a == *b) + a++, b++; + if (isspace(*a)) + { + if (isalnum(a[-1]) && isalnum(*b)) + break; + } + else if (isspace(*b)) + { + if (isalnum(b[-1]) && isalnum(*a)) + break; + } + else + break; + } + return *a - *b; +} + +unsigned int +strnshash(const char *s) +{ + unsigned int h = 0; + + while (*s) + { + if (!isspace(*s)) + h = (h << 5) - h + (unsigned char)*s; + s++; + } + return h; +} +#endif + +#ifdef NO_LEAKS +void +mstring_leaks(void) +{ +#if defined(YYBTYACC) + free(buf_ptr); + buf_ptr = 0; + buf_len = 0; +#endif +} +#endif |