diff options
| -rw-r--r-- | 3rdparty/ezxml/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | 3rdparty/ezxml/ezxml.c | 1015 | ||||
| -rw-r--r-- | 3rdparty/ezxml/ezxml.h | 167 | ||||
| -rw-r--r-- | 3rdparty/stb_ds.h | 1895 | ||||
| -rw-r--r-- | CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/geometry/geometry.c | 36 | ||||
| -rw-r--r-- | src/geometry/geometry.h | 3 | ||||
| -rw-r--r-- | src/geometry/geometry.test.c | 30 | ||||
| -rw-r--r-- | src/xml/CMakeLists.txt | 7 | ||||
| -rw-r--r-- | src/xml/kalmia.lex.c | 2343 | ||||
| -rw-r--r-- | src/xml/kalmia.lex.h | 735 | ||||
| -rw-r--r-- | src/xml/kalmia.tab.c | 2001 | ||||
| -rw-r--r-- | src/xml/kalmia.tab.h | 141 | ||||
| -rw-r--r-- | src/xml/xml.c | 20 | ||||
| -rw-r--r-- | src/xml/xml.h | 11 | ||||
| -rw-r--r-- | yy/demo.c (renamed from yy/main.c) | 0 | ||||
| -rw-r--r-- | yy/makefile | 8 | 
18 files changed, 5264 insertions, 3157 deletions
| diff --git a/3rdparty/ezxml/CMakeLists.txt b/3rdparty/ezxml/CMakeLists.txt deleted file mode 100644 index db024d9..0000000 --- a/3rdparty/ezxml/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -cmake_minimum_required(VERSION 3.2) -project(ezxml) - -add_library(ezxml STATIC ezxml.c) diff --git a/3rdparty/ezxml/ezxml.c b/3rdparty/ezxml/ezxml.c deleted file mode 100644 index 82b11fb..0000000 --- a/3rdparty/ezxml/ezxml.c +++ /dev/null @@ -1,1015 +0,0 @@ -/* ezxml.c - * - * Copyright 2004-2006 Aaron Voisine <aaron@voisine.org> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <ctype.h> -#include <unistd.h> -#include <sys/types.h> -#ifndef EZXML_NOMMAP -#include <sys/mman.h> -#endif // EZXML_NOMMAP -#include <sys/stat.h> -#include "ezxml.h" - -#define EZXML_WS   "\t\r\n "  // whitespace -#define EZXML_ERRL 128        // maximum error string length - -typedef struct ezxml_root *ezxml_root_t; -struct ezxml_root {       // additional data for the root tag -    struct ezxml xml;     // is a super-struct built on top of ezxml struct -    ezxml_t cur;          // current xml tree insertion point -    char *m;              // original xml string -    size_t len;           // length of allocated memory for mmap, -1 for malloc -    char *u;              // UTF-8 conversion of string if original was UTF-16 -    char *s;              // start of work area -    char *e;              // end of work area -    char **ent;           // general entities (ampersand sequences) -    char ***attr;         // default attributes -    char ***pi;           // processing instructions -    short standalone;     // non-zero if <?xml standalone="yes"?> -    char err[EZXML_ERRL]; // error string -}; - -char *EZXML_NIL[] = { NULL }; // empty, null terminated array of strings - -// returns the first child tag with the given name or NULL if not found -ezxml_t ezxml_child(ezxml_t xml, const char *name) -{ -    xml = (xml) ? xml->child : NULL; -    while (xml && strcmp(name, xml->name)) xml = xml->sibling; -    return xml; -} - -// returns the Nth tag with the same name in the same subsection or NULL if not -// found -ezxml_t ezxml_idx(ezxml_t xml, int idx) -{ -    for (; xml && idx; idx--) xml = xml->next; -    return xml; -} - -// returns the value of the requested tag attribute or NULL if not found -const char *ezxml_attr(ezxml_t xml, const char *attr) -{ -    int i = 0, j = 1; -    ezxml_root_t root = (ezxml_root_t)xml; - -    if (! xml || ! xml->attr) return NULL; -    while (xml->attr[i] && strcmp(attr, xml->attr[i])) i += 2; -    if (xml->attr[i]) return xml->attr[i + 1]; // found attribute - -    while (root->xml.parent) root = (ezxml_root_t)root->xml.parent; // root tag -    for (i = 0; root->attr[i] && strcmp(xml->name, root->attr[i][0]); i++); -    if (! root->attr[i]) return NULL; // no matching default attributes -    while (root->attr[i][j] && strcmp(attr, root->attr[i][j])) j += 3; -    return (root->attr[i][j]) ? root->attr[i][j + 1] : NULL; // found default -} - -// same as ezxml_get but takes an already initialized va_list -ezxml_t ezxml_vget(ezxml_t xml, va_list ap) -{ -    char *name = va_arg(ap, char *); -    int idx = -1; - -    if (name && *name) { -        idx = va_arg(ap, int);     -        xml = ezxml_child(xml, name); -    } -    return (idx < 0) ? xml : ezxml_vget(ezxml_idx(xml, idx), ap); -} - -// Traverses the xml tree to retrieve a specific subtag. Takes a variable -// length list of tag names and indexes. The argument list must be terminated -// by either an index of -1 or an empty string tag name. Example:  -// title = ezxml_get(library, "shelf", 0, "book", 2, "title", -1); -// This retrieves the title of the 3rd book on the 1st shelf of library. -// Returns NULL if not found. -ezxml_t ezxml_get(ezxml_t xml, ...) -{ -    va_list ap; -    ezxml_t r; - -    va_start(ap, xml); -    r = ezxml_vget(xml, ap); -    va_end(ap); -    return r; -} - -// returns a null terminated array of processing instructions for the given -// target -const char **ezxml_pi(ezxml_t xml, const char *target) -{ -    ezxml_root_t root = (ezxml_root_t)xml; -    int i = 0; - -    if (! root) return (const char **)EZXML_NIL; -    while (root->xml.parent) root = (ezxml_root_t)root->xml.parent; // root tag -    while (root->pi[i] && strcmp(target, root->pi[i][0])) i++; // find target -    return (const char **)((root->pi[i]) ? root->pi[i] + 1 : EZXML_NIL); -} - -// set an error string and return root -ezxml_t ezxml_err(ezxml_root_t root, char *s, const char *err, ...) -{ -    va_list ap; -    int line = 1; -    char *t, fmt[EZXML_ERRL]; -     -    for (t = root->s; t < s; t++) if (*t == '\n') line++; -    snprintf(fmt, EZXML_ERRL, "[error near line %d]: %s", line, err); - -    va_start(ap, err); -    vsnprintf(root->err, EZXML_ERRL, fmt, ap); -    va_end(ap); - -    return &root->xml; -} - -// Recursively decodes entity and character references and normalizes new lines -// ent is a null terminated array of alternating entity names and values. set t -// to '&' for general entity decoding, '%' for parameter entity decoding, 'c' -// for cdata sections, ' ' for attribute normalization, or '*' for non-cdata -// attribute normalization. Returns s, or if the decoded string is longer than -// s, returns a malloced string that must be freed. -char *ezxml_decode(char *s, char **ent, char t) -{ -    char *e, *r = s, *m = s; -    long b, c, d, l; - -    for (; *s; s++) { // normalize line endings -        while (*s == '\r') { -            *(s++) = '\n'; -            if (*s == '\n') memmove(s, (s + 1), strlen(s)); -        } -    } -     -    for (s = r; ; ) { -        while (*s && *s != '&' && (*s != '%' || t != '%') && !isspace(*s)) s++; - -        if (! *s) break; -        else if (t != 'c' && ! strncmp(s, "&#", 2)) { // character reference -            if (s[2] == 'x') c = strtol(s + 3, &e, 16); // base 16 -            else c = strtol(s + 2, &e, 10); // base 10 -            if (! c || *e != ';') { s++; continue; } // not a character ref - -            if (c < 0x80) *(s++) = c; // US-ASCII subset -            else { // multi-byte UTF-8 sequence -                for (b = 0, d = c; d; d /= 2) b++; // number of bits in c -                b = (b - 2) / 5; // number of bytes in payload -                *(s++) = (0xFF << (7 - b)) | (c >> (6 * b)); // head -                while (b) *(s++) = 0x80 | ((c >> (6 * --b)) & 0x3F); // payload -            } - -            memmove(s, strchr(s, ';') + 1, strlen(strchr(s, ';'))); -        } -        else if ((*s == '&' && (t == '&' || t == ' ' || t == '*')) || -                 (*s == '%' && t == '%')) { // entity reference -            for (b = 0; ent[b] && strncmp(s + 1, ent[b], strlen(ent[b])); -                 b += 2); // find entity in entity list - -            if (ent[b++]) { // found a match -                if ((c = strlen(ent[b])) - 1 > (e = strchr(s, ';')) - s) { -                    l = (d = (s - r)) + c + strlen(e); // new length -                    r = (r == m) ? strcpy(malloc(l), r) : realloc(r, l); -                    e = strchr((s = r + d), ';'); // fix up pointers -                } - -                memmove(s + c, e + 1, strlen(e)); // shift rest of string -                strncpy(s, ent[b], c); // copy in replacement text -            } -            else s++; // not a known entity -        } -        else if ((t == ' ' || t == '*') && isspace(*s)) *(s++) = ' '; -        else s++; // no decoding needed -    } - -    if (t == '*') { // normalize spaces for non-cdata attributes -        for (s = r; *s; s++) { -            if ((l = strspn(s, " "))) memmove(s, s + l, strlen(s + l) + 1); -            while (*s && *s != ' ') s++; -        } -        if (--s >= r && *s == ' ') *s = '\0'; // trim any trailing space -    } -    return r; -} - -// called when parser finds start of new tag -void ezxml_open_tag(ezxml_root_t root, char *name, char **attr) -{ -    ezxml_t xml = root->cur; -     -    if (xml->name) xml = ezxml_add_child(xml, name, strlen(xml->txt)); -    else xml->name = name; // first open tag - -    xml->attr = attr; -    root->cur = xml; // update tag insertion point -} - -// called when parser finds character content between open and closing tag -void ezxml_char_content(ezxml_root_t root, char *s, size_t len, char t) -{ -    ezxml_t xml = root->cur; -    char *m = s; -    size_t l; - -    if (! xml || ! xml->name || ! len) return; // sanity check - -    s[len] = '\0'; // null terminate text (calling functions anticipate this) -    len = strlen(s = ezxml_decode(s, root->ent, t)) + 1; - -    if (! *(xml->txt)) xml->txt = s; // initial character content -    else { // allocate our own memory and make a copy -        xml->txt = (xml->flags & EZXML_TXTM) // allocate some space -                   ? realloc(xml->txt, (l = strlen(xml->txt)) + len) -                   : strcpy(malloc((l = strlen(xml->txt)) + len), xml->txt); -        strcpy(xml->txt + l, s); // add new char content -        if (s != m) free(s); // free s if it was malloced by ezxml_decode() -    } - -    if (xml->txt != m) ezxml_set_flag(xml, EZXML_TXTM); -} - -// called when parser finds closing tag -ezxml_t ezxml_close_tag(ezxml_root_t root, char *name, char *s) -{ -    if (! root->cur || ! root->cur->name || strcmp(name, root->cur->name)) -        return ezxml_err(root, s, "unexpected closing tag </%s>", name); - -    root->cur = root->cur->parent; -    return NULL; -} - -// checks for circular entity references, returns non-zero if no circular -// references are found, zero otherwise -int ezxml_ent_ok(char *name, char *s, char **ent) -{ -    int i; - -    for (; ; s++) { -        while (*s && *s != '&') s++; // find next entity reference -        if (! *s) return 1; -        if (! strncmp(s + 1, name, strlen(name))) return 0; // circular ref. -        for (i = 0; ent[i] && strncmp(ent[i], s + 1, strlen(ent[i])); i += 2); -        if (ent[i] && ! ezxml_ent_ok(name, ent[i + 1], ent)) return 0; -    } -} - -// called when the parser finds a processing instruction -void ezxml_proc_inst(ezxml_root_t root, char *s, size_t len) -{ -    int i = 0, j = 1; -    char *target = s; - -    s[len] = '\0'; // null terminate instruction -    if (*(s += strcspn(s, EZXML_WS))) { -        *s = '\0'; // null terminate target -        s += strspn(s + 1, EZXML_WS) + 1; // skip whitespace after target -    } - -    if (! strcmp(target, "xml")) { // <?xml ... ?> -        if ((s = strstr(s, "standalone")) && ! strncmp(s + strspn(s + 10, -            EZXML_WS "='\"") + 10, "yes", 3)) root->standalone = 1; -        return; -    } - -    if (! root->pi[0]) *(root->pi = malloc(sizeof(char **))) = NULL; //first pi - -    while (root->pi[i] && strcmp(target, root->pi[i][0])) i++; // find target -    if (! root->pi[i]) { // new target -        root->pi = realloc(root->pi, sizeof(char **) * (i + 2)); -        root->pi[i] = malloc(sizeof(char *) * 3); -        root->pi[i][0] = target; -        root->pi[i][1] = (char *)(root->pi[i + 1] = NULL); // terminate pi list -        root->pi[i][2] = strdup(""); // empty document position list -    } - -    while (root->pi[i][j]) j++; // find end of instruction list for this target -    root->pi[i] = realloc(root->pi[i], sizeof(char *) * (j + 3)); -    root->pi[i][j + 2] = realloc(root->pi[i][j + 1], j + 1); -    strcpy(root->pi[i][j + 2] + j - 1, (root->xml.name) ? ">" : "<"); -    root->pi[i][j + 1] = NULL; // null terminate pi list for this target -    root->pi[i][j] = s; // set instruction -} - -// called when the parser finds an internal doctype subset -short ezxml_internal_dtd(ezxml_root_t root, char *s, size_t len) -{ -    char q, *c, *t, *n = NULL, *v, **ent, **pe; -    int i, j; -     -    pe = memcpy(malloc(sizeof(EZXML_NIL)), EZXML_NIL, sizeof(EZXML_NIL)); - -    for (s[len] = '\0'; s; ) { -        while (*s && *s != '<' && *s != '%') s++; // find next declaration - -        if (! *s) break; -        else if (! strncmp(s, "<!ENTITY", 8)) { // parse entity definitions -            c = s += strspn(s + 8, EZXML_WS) + 8; // skip white space separator -            n = s + strspn(s, EZXML_WS "%"); // find name -            *(s = n + strcspn(n, EZXML_WS)) = ';'; // append ; to name - -            v = s + strspn(s + 1, EZXML_WS) + 1; // find value -            if ((q = *(v++)) != '"' && q != '\'') { // skip externals -                s = strchr(s, '>'); -                continue; -            } - -            for (i = 0, ent = (*c == '%') ? pe : root->ent; ent[i]; i++); -            ent = realloc(ent, (i + 3) * sizeof(char *)); // space for next ent -            if (*c == '%') pe = ent; -            else root->ent = ent; - -            *(++s) = '\0'; // null terminate name -            if ((s = strchr(v, q))) *(s++) = '\0'; // null terminate value -            ent[i + 1] = ezxml_decode(v, pe, '%'); // set value -            ent[i + 2] = NULL; // null terminate entity list -            if (! ezxml_ent_ok(n, ent[i + 1], ent)) { // circular reference -                if (ent[i + 1] != v) free(ent[i + 1]); -                ezxml_err(root, v, "circular entity declaration &%s", n); -                break; -            } -            else ent[i] = n; // set entity name -        } -        else if (! strncmp(s, "<!ATTLIST", 9)) { // parse default attributes -            t = s + strspn(s + 9, EZXML_WS) + 9; // skip whitespace separator -            if (! *t) { ezxml_err(root, t, "unclosed <!ATTLIST"); break; } -            if (*(s = t + strcspn(t, EZXML_WS ">")) == '>') continue; -            else *s = '\0'; // null terminate tag name -            for (i = 0; root->attr[i] && strcmp(n, root->attr[i][0]); i++); - -            while (*(n = ++s + strspn(s, EZXML_WS)) && *n != '>') { -                if (*(s = n + strcspn(n, EZXML_WS))) *s = '\0'; // attr name -                else { ezxml_err(root, t, "malformed <!ATTLIST"); break; } - -                s += strspn(s + 1, EZXML_WS) + 1; // find next token -                c = (strncmp(s, "CDATA", 5)) ? "*" : " "; // is it cdata? -                if (! strncmp(s, "NOTATION", 8)) -                    s += strspn(s + 8, EZXML_WS) + 8; -                s = (*s == '(') ? strchr(s, ')') : s + strcspn(s, EZXML_WS); -                if (! s) { ezxml_err(root, t, "malformed <!ATTLIST"); break; } - -                s += strspn(s, EZXML_WS ")"); // skip white space separator -                if (! strncmp(s, "#FIXED", 6)) -                    s += strspn(s + 6, EZXML_WS) + 6; -                if (*s == '#') { // no default value -                    s += strcspn(s, EZXML_WS ">") - 1; -                    if (*c == ' ') continue; // cdata is default, nothing to do -                    v = NULL; -                } -                else if ((*s == '"' || *s == '\'')  &&  // default value -                         (s = strchr(v = s + 1, *s))) *s = '\0'; -                else { ezxml_err(root, t, "malformed <!ATTLIST"); break; } - -                if (! root->attr[i]) { // new tag name -                    root->attr = (! i) ? malloc(2 * sizeof(char **)) -                                       : realloc(root->attr, -                                                 (i + 2) * sizeof(char **)); -                    root->attr[i] = malloc(2 * sizeof(char *)); -                    root->attr[i][0] = t; // set tag name -                    root->attr[i][1] = (char *)(root->attr[i + 1] = NULL); -                } - -                for (j = 1; root->attr[i][j]; j += 3); // find end of list -                root->attr[i] = realloc(root->attr[i], -                                        (j + 4) * sizeof(char *)); - -                root->attr[i][j + 3] = NULL; // null terminate list -                root->attr[i][j + 2] = c; // is it cdata? -                root->attr[i][j + 1] = (v) ? ezxml_decode(v, root->ent, *c) -                                           : NULL; -                root->attr[i][j] = n; // attribute name  -            } -        } -        else if (! strncmp(s, "<!--", 4)) s = strstr(s + 4, "-->"); // comments -        else if (! strncmp(s, "<?", 2)) { // processing instructions -            if ((s = strstr(c = s + 2, "?>"))) -                ezxml_proc_inst(root, c, s++ - c); -        } -        else if (*s == '<') s = strchr(s, '>'); // skip other declarations -        else if (*(s++) == '%' && ! root->standalone) break; -    } - -    free(pe); -    return ! *root->err; -} - -// Converts a UTF-16 string to UTF-8. Returns a new string that must be freed -// or NULL if no conversion was needed. -char *ezxml_str2utf8(char **s, size_t *len) -{ -    char *u; -    size_t l = 0, sl, max = *len; -    long c, d; -    int b, be = (**s == '\xFE') ? 1 : (**s == '\xFF') ? 0 : -1; - -    if (be == -1) return NULL; // not UTF-16 - -    u = malloc(max); -    for (sl = 2; sl < *len - 1; sl += 2) { -        c = (be) ? (((*s)[sl] & 0xFF) << 8) | ((*s)[sl + 1] & 0xFF)  //UTF-16BE -                 : (((*s)[sl + 1] & 0xFF) << 8) | ((*s)[sl] & 0xFF); //UTF-16LE -        if (c >= 0xD800 && c <= 0xDFFF && (sl += 2) < *len - 1) { // high-half -            d = (be) ? (((*s)[sl] & 0xFF) << 8) | ((*s)[sl + 1] & 0xFF) -                     : (((*s)[sl + 1] & 0xFF) << 8) | ((*s)[sl] & 0xFF); -            c = (((c & 0x3FF) << 10) | (d & 0x3FF)) + 0x10000; -        } - -        while (l + 6 > max) u = realloc(u, max += EZXML_BUFSIZE); -        if (c < 0x80) u[l++] = c; // US-ASCII subset -        else { // multi-byte UTF-8 sequence -            for (b = 0, d = c; d; d /= 2) b++; // bits in c -            b = (b - 2) / 5; // bytes in payload -            u[l++] = (0xFF << (7 - b)) | (c >> (6 * b)); // head -            while (b) u[l++] = 0x80 | ((c >> (6 * --b)) & 0x3F); // payload -        } -    } -    return *s = realloc(u, *len = l); -} - -// frees a tag attribute list -void ezxml_free_attr(char **attr) { -    int i = 0; -    char *m; -     -    if (! attr || attr == EZXML_NIL) return; // nothing to free -    while (attr[i]) i += 2; // find end of attribute list -    m = attr[i + 1]; // list of which names and values are malloced -    for (i = 0; m[i]; i++) { -        if (m[i] & EZXML_NAMEM) free(attr[i * 2]); -        if (m[i] & EZXML_TXTM) free(attr[(i * 2) + 1]); -    } -    free(m); -    free(attr); -} - -// parse the given xml string and return an ezxml structure -ezxml_t ezxml_parse_str(char *s, size_t len) -{ -    ezxml_root_t root = (ezxml_root_t)ezxml_new(NULL); -    char q, e, *d, **attr, **a = NULL; // initialize a to avoid compile warning -    int l, i, j; - -    root->m = s; -    if (! len) return ezxml_err(root, NULL, "root tag missing"); -    root->u = ezxml_str2utf8(&s, &len); // convert utf-16 to utf-8 -    root->e = (root->s = s) + len; // record start and end of work area -     -    e = s[len - 1]; // save end char -    s[len - 1] = '\0'; // turn end char into null terminator - -    while (*s && *s != '<') s++; // find first tag -    if (! *s) return ezxml_err(root, s, "root tag missing"); - -    for (; ; ) { -        attr = (char **)EZXML_NIL; -        d = ++s; -         -        if (isalpha(*s) || *s == '_' || *s == ':' || *s < '\0') { // new tag -            if (! root->cur) -                return ezxml_err(root, d, "markup outside of root element"); - -            s += strcspn(s, EZXML_WS "/>"); -            while (isspace(*s)) *(s++) = '\0'; // null terminate tag name -   -            if (*s && *s != '/' && *s != '>') // find tag in default attr list -                for (i = 0; (a = root->attr[i]) && strcmp(a[0], d); i++); - -            for (l = 0; *s && *s != '/' && *s != '>'; l += 2) { // new attrib -                attr = (l) ? realloc(attr, (l + 4) * sizeof(char *)) -                           : malloc(4 * sizeof(char *)); // allocate space -                attr[l + 3] = (l) ? realloc(attr[l + 1], (l / 2) + 2) -                                  : malloc(2); // mem for list of maloced vals -                strcpy(attr[l + 3] + (l / 2), " "); // value is not malloced -                attr[l + 2] = NULL; // null terminate list -                attr[l + 1] = ""; // temporary attribute value -                attr[l] = s; // set attribute name - -                s += strcspn(s, EZXML_WS "=/>"); -                if (*s == '=' || isspace(*s)) {  -                    *(s++) = '\0'; // null terminate tag attribute name -                    q = *(s += strspn(s, EZXML_WS "=")); -                    if (q == '"' || q == '\'') { // attribute value -                        attr[l + 1] = ++s; -                        while (*s && *s != q) s++; -                        if (*s) *(s++) = '\0'; // null terminate attribute val -                        else { -                            ezxml_free_attr(attr); -                            return ezxml_err(root, d, "missing %c", q); -                        } - -                        for (j = 1; a && a[j] && strcmp(a[j], attr[l]); j +=3); -                        attr[l + 1] = ezxml_decode(attr[l + 1], root->ent, (a -                                                   && a[j]) ? *a[j + 2] : ' '); -                        if (attr[l + 1] < d || attr[l + 1] > s) -                            attr[l + 3][l / 2] = EZXML_TXTM; // value malloced -                    } -                } -                while (isspace(*s)) s++; -            } - -            if (*s == '/') { // self closing tag -                *(s++) = '\0'; -                if ((*s && *s != '>') || (! *s && e != '>')) { -                    if (l) ezxml_free_attr(attr); -                    return ezxml_err(root, d, "missing >"); -                } -                ezxml_open_tag(root, d, attr); -                ezxml_close_tag(root, d, s); -            } -            else if ((q = *s) == '>' || (! *s && e == '>')) { // open tag -                *s = '\0'; // temporarily null terminate tag name -                ezxml_open_tag(root, d, attr); -                *s = q; -            } -            else { -                if (l) ezxml_free_attr(attr); -                return ezxml_err(root, d, "missing >");  -            } -        } -        else if (*s == '/') { // close tag -            s += strcspn(d = s + 1, EZXML_WS ">") + 1; -            if (! (q = *s) && e != '>') return ezxml_err(root, d, "missing >"); -            *s = '\0'; // temporarily null terminate tag name -            if (ezxml_close_tag(root, d, s)) return &root->xml; -            if (isspace(*s = q)) s += strspn(s, EZXML_WS); -        } -        else if (! strncmp(s, "!--", 3)) { // xml comment -            if (! (s = strstr(s + 3, "--")) || (*(s += 2) != '>' && *s) || -                (! *s && e != '>')) return ezxml_err(root, d, "unclosed <!--"); -        } -        else if (! strncmp(s, "![CDATA[", 8)) { // cdata -            if ((s = strstr(s, "]]>"))) -                ezxml_char_content(root, d + 8, (s += 2) - d - 10, 'c'); -            else return ezxml_err(root, d, "unclosed <![CDATA["); -        } -        else if (! strncmp(s, "!DOCTYPE", 8)) { // dtd -            for (l = 0; *s && ((! l && *s != '>') || (l && (*s != ']' ||  -                 *(s + strspn(s + 1, EZXML_WS) + 1) != '>'))); -                 l = (*s == '[') ? 1 : l) s += strcspn(s + 1, "[]>") + 1; -            if (! *s && e != '>') -                return ezxml_err(root, d, "unclosed <!DOCTYPE"); -            d = (l) ? strchr(d, '[') + 1 : d; -            if (l && ! ezxml_internal_dtd(root, d, s++ - d)) return &root->xml; -        } -        else if (*s == '?') { // <?...?> processing instructions -            do { s = strchr(s, '?'); } while (s && *(++s) && *s != '>'); -            if (! s || (! *s && e != '>'))  -                return ezxml_err(root, d, "unclosed <?"); -            else ezxml_proc_inst(root, d + 1, s - d - 2); -        } -        else return ezxml_err(root, d, "unexpected <"); -         -        if (! s || ! *s) break; -        *s = '\0'; -        d = ++s; -        if (*s && *s != '<') { // tag character content -            while (*s && *s != '<') s++; -            if (*s) ezxml_char_content(root, d, s - d, '&'); -            else break; -        } -        else if (! *s) break; -    } - -    if (! root->cur) return &root->xml; -    else if (! root->cur->name) return ezxml_err(root, d, "root tag missing"); -    else return ezxml_err(root, d, "unclosed tag <%s>", root->cur->name); -} - -// Wrapper for ezxml_parse_str() that accepts a file stream. Reads the entire -// stream into memory and then parses it. For xml files, use ezxml_parse_file() -// or ezxml_parse_fd() -ezxml_t ezxml_parse_fp(FILE *fp) -{ -    ezxml_root_t root; -    size_t l, len = 0; -    char *s; - -    if (! (s = malloc(EZXML_BUFSIZE))) return NULL; -    do { -        len += (l = fread((s + len), 1, EZXML_BUFSIZE, fp)); -        if (l == EZXML_BUFSIZE) s = realloc(s, len + EZXML_BUFSIZE); -    } while (s && l == EZXML_BUFSIZE); - -    if (! s) return NULL; -    root = (ezxml_root_t)ezxml_parse_str(s, len); -    root->len = -1; // so we know to free s in ezxml_free() -    return &root->xml; -} - -// A wrapper for ezxml_parse_str() that accepts a file descriptor. First -// attempts to mem map the file. Failing that, reads the file into memory. -// Returns NULL on failure. -ezxml_t ezxml_parse_fd(int fd) -{ -    ezxml_root_t root; -    struct stat st; -    size_t l; -    void *m; - -    if (fd < 0) return NULL; -    fstat(fd, &st); - -#ifndef EZXML_NOMMAP -    l = (st.st_size + sysconf(_SC_PAGESIZE) - 1) & ~(sysconf(_SC_PAGESIZE) -1); -    if ((m = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) != -        MAP_FAILED) { -        madvise(m, l, MADV_SEQUENTIAL); // optimize for sequential access -        root = (ezxml_root_t)ezxml_parse_str(m, st.st_size); -        madvise(m, root->len = l, MADV_NORMAL); // put it back to normal -    } -    else { // mmap failed, read file into memory -#endif // EZXML_NOMMAP -        l = read(fd, m = malloc(st.st_size), st.st_size); -        root = (ezxml_root_t)ezxml_parse_str(m, l); -        root->len = -1; // so we know to free s in ezxml_free() -#ifndef EZXML_NOMMAP -    } -#endif // EZXML_NOMMAP -    return &root->xml; -} - -// a wrapper for ezxml_parse_fd that accepts a file name -ezxml_t ezxml_parse_file(const char *file) -{ -    int fd = open(file, O_RDONLY, 0); -    ezxml_t xml = ezxml_parse_fd(fd); -     -    if (fd >= 0) close(fd); -    return xml; -} - -// Encodes ampersand sequences appending the results to *dst, reallocating *dst -// if length excedes max. a is non-zero for attribute encoding. Returns *dst -char *ezxml_ampencode(const char *s, size_t len, char **dst, size_t *dlen, -                      size_t *max, short a) -{ -    const char *e; -     -    for (e = s + len; s != e; s++) { -        while (*dlen + 10 > *max) *dst = realloc(*dst, *max += EZXML_BUFSIZE); - -        switch (*s) { -        case '\0': return *dst; -        case '&': *dlen += sprintf(*dst + *dlen, "&"); break; -        case '<': *dlen += sprintf(*dst + *dlen, "<"); break; -        case '>': *dlen += sprintf(*dst + *dlen, ">"); break; -        case '"': *dlen += sprintf(*dst + *dlen, (a) ? """ : "\""); break; -        case '\n': *dlen += sprintf(*dst + *dlen, (a) ? "
" : "\n"); break; -        case '\t': *dlen += sprintf(*dst + *dlen, (a) ? "	" : "\t"); break; -        case '\r': *dlen += sprintf(*dst + *dlen, "
"); break; -        default: (*dst)[(*dlen)++] = *s; -        } -    } -    return *dst; -} - -// Recursively converts each tag to xml appending it to *s. Reallocates *s if -// its length excedes max. start is the location of the previous tag in the -// parent tag's character content. Returns *s. -char *ezxml_toxml_r(ezxml_t xml, char **s, size_t *len, size_t *max, -                    size_t start, char ***attr) -{ -    int i, j; -    char *txt = (xml->parent) ? xml->parent->txt : ""; -    size_t off = 0; - -    // parent character content up to this tag -    *s = ezxml_ampencode(txt + start, xml->off - start, s, len, max, 0); - -    while (*len + strlen(xml->name) + 4 > *max) // reallocate s -        *s = realloc(*s, *max += EZXML_BUFSIZE); - -    *len += sprintf(*s + *len, "<%s", xml->name); // open tag -    for (i = 0; xml->attr[i]; i += 2) { // tag attributes -        if (ezxml_attr(xml, xml->attr[i]) != xml->attr[i + 1]) continue; -        while (*len + strlen(xml->attr[i]) + 7 > *max) // reallocate s -            *s = realloc(*s, *max += EZXML_BUFSIZE); - -        *len += sprintf(*s + *len, " %s=\"", xml->attr[i]); -        ezxml_ampencode(xml->attr[i + 1], -1, s, len, max, 1); -        *len += sprintf(*s + *len, "\""); -    } - -    for (i = 0; attr[i] && strcmp(attr[i][0], xml->name); i++); -    for (j = 1; attr[i] && attr[i][j]; j += 3) { // default attributes -        if (! attr[i][j + 1] || ezxml_attr(xml, attr[i][j]) != attr[i][j + 1]) -            continue; // skip duplicates and non-values -        while (*len + strlen(attr[i][j]) + 7 > *max) // reallocate s -            *s = realloc(*s, *max += EZXML_BUFSIZE); - -        *len += sprintf(*s + *len, " %s=\"", attr[i][j]); -        ezxml_ampencode(attr[i][j + 1], -1, s, len, max, 1); -        *len += sprintf(*s + *len, "\""); -    } -    *len += sprintf(*s + *len, ">"); - -    *s = (xml->child) ? ezxml_toxml_r(xml->child, s, len, max, 0, attr) //child -                      : ezxml_ampencode(xml->txt, -1, s, len, max, 0);  //data -     -    while (*len + strlen(xml->name) + 4 > *max) // reallocate s -        *s = realloc(*s, *max += EZXML_BUFSIZE); - -    *len += sprintf(*s + *len, "</%s>", xml->name); // close tag - -    while (txt[off] && off < xml->off) off++; // make sure off is within bounds -    return (xml->ordered) ? ezxml_toxml_r(xml->ordered, s, len, max, off, attr) -                          : ezxml_ampencode(txt + off, -1, s, len, max, 0); -} - -// Converts an ezxml structure back to xml. Returns a string of xml data that -// must be freed. -char *ezxml_toxml(ezxml_t xml) -{ -    ezxml_t p = (xml) ? xml->parent : NULL, o = (xml) ? xml->ordered : NULL; -    ezxml_root_t root = (ezxml_root_t)xml; -    size_t len = 0, max = EZXML_BUFSIZE; -    char *s = strcpy(malloc(max), ""), *t, *n; -    int i, j, k; - -    if (! xml || ! xml->name) return realloc(s, len + 1); -    while (root->xml.parent) root = (ezxml_root_t)root->xml.parent; // root tag - -    for (i = 0; ! p && root->pi[i]; i++) { // pre-root processing instructions -        for (k = 2; root->pi[i][k - 1]; k++); -        for (j = 1; (n = root->pi[i][j]); j++) { -            if (root->pi[i][k][j - 1] == '>') continue; // not pre-root -            while (len + strlen(t = root->pi[i][0]) + strlen(n) + 7 > max) -                s = realloc(s, max += EZXML_BUFSIZE); -            len += sprintf(s + len, "<?%s%s%s?>\n", t, *n ? " " : "", n); -        } -    } - -    xml->parent = xml->ordered = NULL; -    s = ezxml_toxml_r(xml, &s, &len, &max, 0, root->attr); -    xml->parent = p; -    xml->ordered = o; - -    for (i = 0; ! p && root->pi[i]; i++) { // post-root processing instructions -        for (k = 2; root->pi[i][k - 1]; k++); -        for (j = 1; (n = root->pi[i][j]); j++) { -            if (root->pi[i][k][j - 1] == '<') continue; // not post-root -            while (len + strlen(t = root->pi[i][0]) + strlen(n) + 7 > max) -                s = realloc(s, max += EZXML_BUFSIZE); -            len += sprintf(s + len, "\n<?%s%s%s?>", t, *n ? " " : "", n); -        } -    } -    return realloc(s, len + 1); -} - -// free the memory allocated for the ezxml structure -void ezxml_free(ezxml_t xml) -{ -    ezxml_root_t root = (ezxml_root_t)xml; -    int i, j; -    char **a, *s; - -    if (! xml) return; -    ezxml_free(xml->child); -    ezxml_free(xml->ordered); - -    if (! xml->parent) { // free root tag allocations -        for (i = 10; root->ent[i]; i += 2) // 0 - 9 are default entites (<>&"') -            if ((s = root->ent[i + 1]) < root->s || s > root->e) free(s); -        free(root->ent); // free list of general entities - -        for (i = 0; (a = root->attr[i]); i++) { -            for (j = 1; a[j++]; j += 2) // free malloced attribute values -                if (a[j] && (a[j] < root->s || a[j] > root->e)) free(a[j]); -            free(a); -        } -        if (root->attr[0]) free(root->attr); // free default attribute list - -        for (i = 0; root->pi[i]; i++) { -            for (j = 1; root->pi[i][j]; j++); -            free(root->pi[i][j + 1]); -            free(root->pi[i]); -        }             -        if (root->pi[0]) free(root->pi); // free processing instructions - -        if (root->len == -1) free(root->m); // malloced xml data -#ifndef EZXML_NOMMAP -        else if (root->len) munmap(root->m, root->len); // mem mapped xml data -#endif // EZXML_NOMMAP -        if (root->u) free(root->u); // utf8 conversion -    } - -    ezxml_free_attr(xml->attr); // tag attributes -    if ((xml->flags & EZXML_TXTM)) free(xml->txt); // character content -    if ((xml->flags & EZXML_NAMEM)) free(xml->name); // tag name -    free(xml); -} - -// return parser error message or empty string if none -const char *ezxml_error(ezxml_t xml) -{ -    while (xml && xml->parent) xml = xml->parent; // find root tag -    return (xml) ? ((ezxml_root_t)xml)->err : ""; -} - -// returns a new empty ezxml structure with the given root tag name -ezxml_t ezxml_new(const char *name) -{ -    static char *ent[] = { "lt;", "<", "gt;", ">", "quot;", """, -                           "apos;", "'", "amp;", "&", NULL }; -    ezxml_root_t root = (ezxml_root_t)memset(malloc(sizeof(struct ezxml_root)),  -                                             '\0', sizeof(struct ezxml_root)); -    root->xml.name = (char *)name; -    root->cur = &root->xml; -    strcpy(root->err, root->xml.txt = ""); -    root->ent = memcpy(malloc(sizeof(ent)), ent, sizeof(ent)); -    root->attr = root->pi = (char ***)(root->xml.attr = EZXML_NIL); -    return &root->xml; -} - -// inserts an existing tag into an ezxml structure -ezxml_t ezxml_insert(ezxml_t xml, ezxml_t dest, size_t off) -{ -    ezxml_t cur, prev, head; - -    xml->next = xml->sibling = xml->ordered = NULL; -    xml->off = off; -    xml->parent = dest; - -    if ((head = dest->child)) { // already have sub tags -        if (head->off <= off) { // not first subtag -            for (cur = head; cur->ordered && cur->ordered->off <= off; -                 cur = cur->ordered); -            xml->ordered = cur->ordered; -            cur->ordered = xml; -        } -        else { // first subtag -            xml->ordered = head; -            dest->child = xml; -        } - -        for (cur = head, prev = NULL; cur && strcmp(cur->name, xml->name); -             prev = cur, cur = cur->sibling); // find tag type -        if (cur && cur->off <= off) { // not first of type -            while (cur->next && cur->next->off <= off) cur = cur->next; -            xml->next = cur->next; -            cur->next = xml; -        } -        else { // first tag of this type -            if (prev && cur) prev->sibling = cur->sibling; // remove old first -            xml->next = cur; // old first tag is now next -            for (cur = head, prev = NULL; cur && cur->off <= off; -                 prev = cur, cur = cur->sibling); // new sibling insert point -            xml->sibling = cur; -            if (prev) prev->sibling = xml; -        } -    } -    else dest->child = xml; // only sub tag - -    return xml; -} - -// Adds a child tag. off is the offset of the child tag relative to the start -// of the parent tag's character content. Returns the child tag. -ezxml_t ezxml_add_child(ezxml_t xml, const char *name, size_t off) -{ -    ezxml_t child; - -    if (! xml) return NULL; -    child = (ezxml_t)memset(malloc(sizeof(struct ezxml)), '\0', -                            sizeof(struct ezxml)); -    child->name = (char *)name; -    child->attr = EZXML_NIL; -    child->txt = ""; - -    return ezxml_insert(child, xml, off); -} - -// sets the character content for the given tag and returns the tag -ezxml_t ezxml_set_txt(ezxml_t xml, const char *txt) -{ -    if (! xml) return NULL; -    if (xml->flags & EZXML_TXTM) free(xml->txt); // existing txt was malloced -    xml->flags &= ~EZXML_TXTM; -    xml->txt = (char *)txt; -    return xml; -} - -// Sets the given tag attribute or adds a new attribute if not found. A value -// of NULL will remove the specified attribute. Returns the tag given. -ezxml_t ezxml_set_attr(ezxml_t xml, const char *name, const char *value) -{ -    int l = 0, c; - -    if (! xml) return NULL; -    while (xml->attr[l] && strcmp(xml->attr[l], name)) l += 2; -    if (! xml->attr[l]) { // not found, add as new attribute -        if (! value) return xml; // nothing to do -        if (xml->attr == EZXML_NIL) { // first attribute -            xml->attr = malloc(4 * sizeof(char *)); -            xml->attr[1] = strdup(""); // empty list of malloced names/vals -        } -        else xml->attr = realloc(xml->attr, (l + 4) * sizeof(char *)); - -        xml->attr[l] = (char *)name; // set attribute name -        xml->attr[l + 2] = NULL; // null terminate attribute list -        xml->attr[l + 3] = realloc(xml->attr[l + 1], -                                   (c = strlen(xml->attr[l + 1])) + 2); -        strcpy(xml->attr[l + 3] + c, " "); // set name/value as not malloced -        if (xml->flags & EZXML_DUP) xml->attr[l + 3][c] = EZXML_NAMEM; -    } -    else if (xml->flags & EZXML_DUP) free((char *)name); // name was strduped - -    for (c = l; xml->attr[c]; c += 2); // find end of attribute list -    if (xml->attr[c + 1][l / 2] & EZXML_TXTM) free(xml->attr[l + 1]); //old val -    if (xml->flags & EZXML_DUP) xml->attr[c + 1][l / 2] |= EZXML_TXTM; -    else xml->attr[c + 1][l / 2] &= ~EZXML_TXTM; - -    if (value) xml->attr[l + 1] = (char *)value; // set attribute value -    else { // remove attribute -        if (xml->attr[c + 1][l / 2] & EZXML_NAMEM) free(xml->attr[l]); -        memmove(xml->attr + l, xml->attr + l + 2, (c - l + 2) * sizeof(char*)); -        xml->attr = realloc(xml->attr, (c + 2) * sizeof(char *)); -        memmove(xml->attr[c + 1] + (l / 2), xml->attr[c + 1] + (l / 2) + 1, -                (c / 2) - (l / 2)); // fix list of which name/vals are malloced -    } -    xml->flags &= ~EZXML_DUP; // clear strdup() flag -    return xml; -} - -// sets a flag for the given tag and returns the tag -ezxml_t ezxml_set_flag(ezxml_t xml, short flag) -{ -    if (xml) xml->flags |= flag; -    return xml; -} - -// removes a tag along with its subtags without freeing its memory -ezxml_t ezxml_cut(ezxml_t xml) -{ -    ezxml_t cur; - -    if (! xml) return NULL; // nothing to do -    if (xml->next) xml->next->sibling = xml->sibling; // patch sibling list - -    if (xml->parent) { // not root tag -        cur = xml->parent->child; // find head of subtag list -        if (cur == xml) xml->parent->child = xml->ordered; // first subtag -        else { // not first subtag -            while (cur->ordered != xml) cur = cur->ordered; -            cur->ordered = cur->ordered->ordered; // patch ordered list - -            cur = xml->parent->child; // go back to head of subtag list -            if (strcmp(cur->name, xml->name)) { // not in first sibling list -                while (strcmp(cur->sibling->name, xml->name)) -                    cur = cur->sibling; -                if (cur->sibling == xml) { // first of a sibling list -                    cur->sibling = (xml->next) ? xml->next -                                               : cur->sibling->sibling; -                } -                else cur = cur->sibling; // not first of a sibling list -            } - -            while (cur->next && cur->next != xml) cur = cur->next; -            if (cur->next) cur->next = cur->next->next; // patch next list -        }         -    } -    xml->ordered = xml->sibling = xml->next = NULL; -    return xml; -} - -#ifdef EZXML_TEST // test harness -int main(int argc, char **argv) -{ -    ezxml_t xml; -    char *s; -    int i; - -    if (argc != 2) return fprintf(stderr, "usage: %s xmlfile\n", argv[0]); - -    xml = ezxml_parse_file(argv[1]); -    printf("%s\n", (s = ezxml_toxml(xml))); -    free(s); -    i = fprintf(stderr, "%s", ezxml_error(xml)); -    ezxml_free(xml); -    return (i) ? 1 : 0; -} -#endif // EZXML_TEST diff --git a/3rdparty/ezxml/ezxml.h b/3rdparty/ezxml/ezxml.h deleted file mode 100644 index 3e02078..0000000 --- a/3rdparty/ezxml/ezxml.h +++ /dev/null @@ -1,167 +0,0 @@ -/* ezxml.h - * - * Copyright 2004-2006 Aaron Voisine <aaron@voisine.org> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EZXML_H -#define _EZXML_H - -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <fcntl.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#define EZXML_BUFSIZE 1024 // size of internal memory buffers -#define EZXML_NAMEM   0x80 // name is malloced -#define EZXML_TXTM    0x40 // txt is malloced -#define EZXML_DUP     0x20 // attribute name and value are strduped - -typedef struct ezxml *ezxml_t; -struct ezxml { -    char *name;      // tag name -    char **attr;     // tag attributes { name, value, name, value, ... NULL } -    char *txt;       // tag character content, empty string if none -    size_t off;      // tag offset from start of parent tag character content -    ezxml_t next;    // next tag with same name in this section at this depth -    ezxml_t sibling; // next tag with different name in same section and depth -    ezxml_t ordered; // next tag, same section and depth, in original order -    ezxml_t child;   // head of sub tag list, NULL if none -    ezxml_t parent;  // parent tag, NULL if current tag is root tag -    short flags;     // additional information -}; - -// Given a string of xml data and its length, parses it and creates an ezxml -// structure. For efficiency, modifies the data by adding null terminators -// and decoding ampersand sequences. If you don't want this, copy the data and -// pass in the copy. Returns NULL on failure. -ezxml_t ezxml_parse_str(char *s, size_t len); - -// A wrapper for ezxml_parse_str() that accepts a file descriptor. First -// attempts to mem map the file. Failing that, reads the file into memory. -// Returns NULL on failure. -ezxml_t ezxml_parse_fd(int fd); - -// a wrapper for ezxml_parse_fd() that accepts a file name -ezxml_t ezxml_parse_file(const char *file); -     -// Wrapper for ezxml_parse_str() that accepts a file stream. Reads the entire -// stream into memory and then parses it. For xml files, use ezxml_parse_file() -// or ezxml_parse_fd() -ezxml_t ezxml_parse_fp(FILE *fp); - -// returns the first child tag (one level deeper) with the given name or NULL -// if not found -ezxml_t ezxml_child(ezxml_t xml, const char *name); - -// returns the next tag of the same name in the same section and depth or NULL -// if not found -#define ezxml_next(xml) ((xml) ? xml->next : NULL) - -// Returns the Nth tag with the same name in the same section at the same depth -// or NULL if not found. An index of 0 returns the tag given. -ezxml_t ezxml_idx(ezxml_t xml, int idx); - -// returns the name of the given tag -#define ezxml_name(xml) ((xml) ? xml->name : NULL) - -// returns the given tag's character content or empty string if none -#define ezxml_txt(xml) ((xml) ? xml->txt : "") - -// returns the value of the requested tag attribute, or NULL if not found -const char *ezxml_attr(ezxml_t xml, const char *attr); - -// Traverses the ezxml sturcture to retrieve a specific subtag. Takes a -// variable length list of tag names and indexes. The argument list must be -// terminated by either an index of -1 or an empty string tag name. Example:  -// title = ezxml_get(library, "shelf", 0, "book", 2, "title", -1); -// This retrieves the title of the 3rd book on the 1st shelf of library. -// Returns NULL if not found. -ezxml_t ezxml_get(ezxml_t xml, ...); - -// Converts an ezxml structure back to xml. Returns a string of xml data that -// must be freed. -char *ezxml_toxml(ezxml_t xml); - -// returns a NULL terminated array of processing instructions for the given -// target -const char **ezxml_pi(ezxml_t xml, const char *target); - -// frees the memory allocated for an ezxml structure -void ezxml_free(ezxml_t xml); -     -// returns parser error message or empty string if none -const char *ezxml_error(ezxml_t xml); - -// returns a new empty ezxml structure with the given root tag name -ezxml_t ezxml_new(const char *name); - -// wrapper for ezxml_new() that strdup()s name -#define ezxml_new_d(name) ezxml_set_flag(ezxml_new(strdup(name)), EZXML_NAMEM) - -// Adds a child tag. off is the offset of the child tag relative to the start -// of the parent tag's character content. Returns the child tag. -ezxml_t ezxml_add_child(ezxml_t xml, const char *name, size_t off); - -// wrapper for ezxml_add_child() that strdup()s name -#define ezxml_add_child_d(xml, name, off) \ -    ezxml_set_flag(ezxml_add_child(xml, strdup(name), off), EZXML_NAMEM) - -// sets the character content for the given tag and returns the tag -ezxml_t ezxml_set_txt(ezxml_t xml, const char *txt); - -// wrapper for ezxml_set_txt() that strdup()s txt -#define ezxml_set_txt_d(xml, txt) \ -    ezxml_set_flag(ezxml_set_txt(xml, strdup(txt)), EZXML_TXTM) - -// Sets the given tag attribute or adds a new attribute if not found. A value -// of NULL will remove the specified attribute. Returns the tag given. -ezxml_t ezxml_set_attr(ezxml_t xml, const char *name, const char *value); - -// Wrapper for ezxml_set_attr() that strdup()s name/value. Value cannot be NULL -#define ezxml_set_attr_d(xml, name, value) \ -    ezxml_set_attr(ezxml_set_flag(xml, EZXML_DUP), strdup(name), strdup(value)) - -// sets a flag for the given tag and returns the tag -ezxml_t ezxml_set_flag(ezxml_t xml, short flag); - -// removes a tag along with its subtags without freeing its memory -ezxml_t ezxml_cut(ezxml_t xml); - -// inserts an existing tag into an ezxml structure -ezxml_t ezxml_insert(ezxml_t xml, ezxml_t dest, size_t off); - -// Moves an existing tag to become a subtag of dest at the given offset from -// the start of dest's character content. Returns the moved tag. -#define ezxml_move(xml, dest, off) ezxml_insert(ezxml_cut(xml), dest, off) - -// removes a tag along with all its subtags -#define ezxml_remove(xml) ezxml_free(ezxml_cut(xml)) - -#ifdef __cplusplus -} -#endif - -#endif // _EZXML_H diff --git a/3rdparty/stb_ds.h b/3rdparty/stb_ds.h deleted file mode 100644 index e84c82d..0000000 --- a/3rdparty/stb_ds.h +++ /dev/null @@ -1,1895 +0,0 @@ -/* stb_ds.h - v0.67 - public domain data structures - Sean Barrett 2019 - -   This is a single-header-file library that provides easy-to-use -   dynamic arrays and hash tables for C (also works in C++). - -   For a gentle introduction: -      http://nothings.org/stb_ds - -   To use this library, do this in *one* C or C++ file: -      #define STB_DS_IMPLEMENTATION -      #include "stb_ds.h" - -TABLE OF CONTENTS - -  Table of Contents -  Compile-time options -  License -  Documentation -  Notes -  Notes - Dynamic arrays -  Notes - Hash maps -  Credits - -COMPILE-TIME OPTIONS - -  #define STBDS_NO_SHORT_NAMES - -     This flag needs to be set globally. - -     By default stb_ds exposes shorter function names that are not qualified -     with the "stbds_" prefix. If these names conflict with the names in your -     code, define this flag. - -  #define STBDS_SIPHASH_2_4 - -     This flag only needs to be set in the file containing #define STB_DS_IMPLEMENTATION. - -     By default stb_ds.h hashes using a weaker variant of SipHash and a custom hash for -     4- and 8-byte keys. On 64-bit platforms, you can define the above flag to force -     stb_ds.h to use specification-compliant SipHash-2-4 for all keys. Doing so makes -     hash table insertion about 20% slower on 4- and 8-byte keys, 5% slower on -     64-byte keys, and 10% slower on 256-byte keys on my test computer. - -  #define STBDS_REALLOC(context,ptr,size) better_realloc -  #define STBDS_FREE(context,ptr)         better_free - -     These defines only need to be set in the file containing #define STB_DS_IMPLEMENTATION. - -     By default stb_ds uses stdlib realloc() and free() for memory management. You can -     substitute your own functions instead by defining these symbols. You must either -     define both, or neither. Note that at the moment, 'context' will always be NULL. -     @TODO add an array/hash initialization function that takes a memory context pointer. - -  #define STBDS_UNIT_TESTS - -     Defines a function stbds_unit_tests() that checks the functioning of the data structures. - -  Note that on older versions of gcc (e.g. 5.x.x) you may need to build with '-std=c++0x' -     (or equivalentally '-std=c++11') when using anonymous structures as seen on the web -     page or in STBDS_UNIT_TESTS. - -LICENSE - -  Placed in the public domain and also MIT licensed. -  See end of file for detailed license information. - -DOCUMENTATION - -  Dynamic Arrays - -    Non-function interface: - -      Declare an empty dynamic array of type T -        T* foo = NULL; - -      Access the i'th item of a dynamic array 'foo' of type T, T* foo: -        foo[i] - -    Functions (actually macros) - -      arrfree: -        void arrfree(T*); -          Frees the array. - -      arrlen: -        ptrdiff_t arrlen(T*); -          Returns the number of elements in the array. - -      arrlenu: -        size_t arrlenu(T*); -          Returns the number of elements in the array as an unsigned type. - -      arrpop: -        T arrpop(T* a) -          Removes the final element of the array and returns it. - -      arrput: -        T arrput(T* a, T b); -          Appends the item b to the end of array a. Returns b. - -      arrins: -        T arrins(T* a, int p, T b); -          Inserts the item b into the middle of array a, into a[p], -          moving the rest of the array over. Returns b. - -      arrinsn: -        void arrinsn(T* a, int p, int n); -          Inserts n uninitialized items into array a starting at a[p], -          moving the rest of the array over. - -      arraddnptr: -        T* arraddnptr(T* a, int n) -          Appends n uninitialized items onto array at the end. -          Returns a pointer to the first uninitialized item added. - -      arraddnindex: -        size_t arraddnindex(T* a, int n) -          Appends n uninitialized items onto array at the end. -          Returns the index of the first uninitialized item added. - -      arrdel: -        void arrdel(T* a, int p); -          Deletes the element at a[p], moving the rest of the array over. - -      arrdeln: -        void arrdeln(T* a, int p, int n); -          Deletes n elements starting at a[p], moving the rest of the array over. - -      arrdelswap: -        void arrdelswap(T* a, int p); -          Deletes the element at a[p], replacing it with the element from -          the end of the array. O(1) performance. - -      arrsetlen: -        void arrsetlen(T* a, int n); -          Changes the length of the array to n. Allocates uninitialized -          slots at the end if necessary. - -      arrsetcap: -        size_t arrsetcap(T* a, int n); -          Sets the length of allocated storage to at least n. It will not -          change the length of the array. - -      arrcap: -        size_t arrcap(T* a); -          Returns the number of total elements the array can contain without -          needing to be reallocated. - -  Hash maps & String hash maps - -    Given T is a structure type: struct { TK key; TV value; }. Note that some -    functions do not require TV value and can have other fields. For string -    hash maps, TK must be 'char *'. - -    Special interface: - -      stbds_rand_seed: -        void stbds_rand_seed(size_t seed); -          For security against adversarially chosen data, you should seed the -          library with a strong random number. Or at least seed it with time(). - -      stbds_hash_string: -        size_t stbds_hash_string(char *str, size_t seed); -          Returns a hash value for a string. - -      stbds_hash_bytes: -        size_t stbds_hash_bytes(void *p, size_t len, size_t seed); -          These functions hash an arbitrary number of bytes. The function -          uses a custom hash for 4- and 8-byte data, and a weakened version -          of SipHash for everything else. On 64-bit platforms you can get -          specification-compliant SipHash-2-4 on all data by defining -          STBDS_SIPHASH_2_4, at a significant cost in speed. - -    Non-function interface: - -      Declare an empty hash map of type T -        T* foo = NULL; - -      Access the i'th entry in a hash table T* foo: -        foo[i] - -    Function interface (actually macros): - -      hmfree -      shfree -        void hmfree(T*); -        void shfree(T*); -          Frees the hashmap and sets the pointer to NULL. - -      hmlen -      shlen -        ptrdiff_t hmlen(T*) -        ptrdiff_t shlen(T*) -          Returns the number of elements in the hashmap. - -      hmlenu -      shlenu -        size_t hmlenu(T*) -        size_t shlenu(T*) -          Returns the number of elements in the hashmap. - -      hmgeti -      shgeti -      hmgeti_ts -        ptrdiff_t hmgeti(T*, TK key) -        ptrdiff_t shgeti(T*, char* key) -        ptrdiff_t hmgeti_ts(T*, TK key, ptrdiff_t tempvar) -          Returns the index in the hashmap which has the key 'key', or -1 -          if the key is not present. - -      hmget -      hmget_ts -      shget -        TV hmget(T*, TK key) -        TV shget(T*, char* key) -        TV hmget_ts(T*, TK key, ptrdiff_t tempvar) -          Returns the value corresponding to 'key' in the hashmap. -          The structure must have a 'value' field - -      hmgets -      shgets -        T hmgets(T*, TK key) -        T shgets(T*, char* key) -          Returns the structure corresponding to 'key' in the hashmap. - -      hmgetp -      shgetp -      hmgetp_ts -      hmgetp_null -      shgetp_null -        T* hmgetp(T*, TK key) -        T* shgetp(T*, char* key) -        T* hmgetp_ts(T*, TK key, ptrdiff_t tempvar) -        T* hmgetp_null(T*, TK key) -        T* shgetp_null(T*, char *key) -          Returns a pointer to the structure corresponding to 'key' in -          the hashmap. Functions ending in "_null" return NULL if the key -          is not present in the hashmap; the others return a pointer to a -          structure holding the default value (but not the searched-for key). - -      hmdefault -      shdefault -        TV hmdefault(T*, TV value) -        TV shdefault(T*, TV value) -          Sets the default value for the hashmap, the value which will be -          returned by hmget/shget if the key is not present. - -      hmdefaults -      shdefaults -        TV hmdefaults(T*, T item) -        TV shdefaults(T*, T item) -          Sets the default struct for the hashmap, the contents which will be -          returned by hmgets/shgets if the key is not present. - -      hmput -      shput -        TV hmput(T*, TK key, TV value) -        TV shput(T*, char* key, TV value) -          Inserts a <key,value> pair into the hashmap. If the key is already -          present in the hashmap, updates its value. - -      hmputs -      shputs -        T hmputs(T*, T item) -        T shputs(T*, T item) -          Inserts a struct with T.key into the hashmap. If the struct is already -          present in the hashmap, updates it. - -      hmdel -      shdel -        int hmdel(T*, TK key) -        int shdel(T*, char* key) -          If 'key' is in the hashmap, deletes its entry and returns 1. -          Otherwise returns 0. - -    Function interface (actually macros) for strings only: - -      sh_new_strdup -        void sh_new_strdup(T*); -          Overwrites the existing pointer with a newly allocated -          string hashmap which will automatically allocate and free -          each string key using realloc/free - -      sh_new_arena -        void sh_new_arena(T*); -          Overwrites the existing pointer with a newly allocated -          string hashmap which will automatically allocate each string -          key to a string arena. Every string key ever used by this -          hash table remains in the arena until the arena is freed. -          Additionally, any key which is deleted and reinserted will -          be allocated multiple times in the string arena. - -NOTES - -  * These data structures are realloc'd when they grow, and the macro -    "functions" write to the provided pointer. This means: (a) the pointer -    must be an lvalue, and (b) the pointer to the data structure is not -    stable, and you must maintain it the same as you would a realloc'd -    pointer. For example, if you pass a pointer to a dynamic array to a -    function which updates it, the function must return back the new -    pointer to the caller. This is the price of trying to do this in C. - -  * The following are the only functions that are thread-safe on a single data -    structure, i.e. can be run in multiple threads simultaneously on the same -    data structure -        hmlen        shlen -        hmlenu       shlenu -        hmget_ts     shget_ts -        hmgeti_ts    shgeti_ts -        hmgets_ts    shgets_ts - -  * You iterate over the contents of a dynamic array and a hashmap in exactly -    the same way, using arrlen/hmlen/shlen: - -      for (i=0; i < arrlen(foo); ++i) -         ... foo[i] ... - -  * All operations except arrins/arrdel are O(1) amortized, but individual -    operations can be slow, so these data structures may not be suitable -    for real time use. Dynamic arrays double in capacity as needed, so -    elements are copied an average of once. Hash tables double/halve -    their size as needed, with appropriate hysteresis to maintain O(1) -    performance. - -NOTES - DYNAMIC ARRAY - -  * If you know how long a dynamic array is going to be in advance, you can avoid -    extra memory allocations by using arrsetlen to allocate it to that length in -    advance and use foo[n] while filling it out, or arrsetcap to allocate the memory -    for that length and use arrput/arrpush as normal. - -  * Unlike some other versions of the dynamic array, this version should -    be safe to use with strict-aliasing optimizations. - -NOTES - HASH MAP - -  * For compilers other than GCC and clang (e.g. Visual Studio), for hmput/hmget/hmdel -    and variants, the key must be an lvalue (so the macro can take the address of it). -    Extensions are used that eliminate this requirement if you're using C99 and later -    in GCC or clang, or if you're using C++ in GCC. But note that this can make your -    code less portable. - -  * To test for presence of a key in a hashmap, just do 'hmgeti(foo,key) >= 0'. - -  * The iteration order of your data in the hashmap is determined solely by the -    order of insertions and deletions. In particular, if you never delete, new -    keys are always added at the end of the array. This will be consistent -    across all platforms and versions of the library. However, you should not -    attempt to serialize the internal hash table, as the hash is not consistent -    between different platforms, and may change with future versions of the library. - -  * Use sh_new_arena() for string hashmaps that you never delete from. Initialize -    with NULL if you're managing the memory for your strings, or your strings are -    never freed (at least until the hashmap is freed). Otherwise, use sh_new_strdup(). -    @TODO: make an arena variant that garbage collects the strings with a trivial -    copy collector into a new arena whenever the table shrinks / rebuilds. Since -    current arena recommendation is to only use arena if it never deletes, then -    this can just replace current arena implementation. - -  * If adversarial input is a serious concern and you're on a 64-bit platform, -    enable STBDS_SIPHASH_2_4 (see the 'Compile-time options' section), and pass -    a strong random number to stbds_rand_seed. - -  * The default value for the hash table is stored in foo[-1], so if you -    use code like 'hmget(T,k)->value = 5' you can accidentally overwrite -    the value stored by hmdefault if 'k' is not present. - -CREDITS - -  Sean Barrett -- library, idea for dynamic array API/implementation -  Per Vognsen  -- idea for hash table API/implementation -  Rafael Sachetto -- arrpop() -  github:HeroicKatora -- arraddn() reworking - -  Bugfixes: -    Andy Durdin -    Shane Liesegang -    Vinh Truong -    Andreas Molzer -    github:hashitaku -    github:srdjanstipic -    Macoy Madson -    Andreas Vennstrom -    Tobias Mansfield-Williams -*/ - -#ifdef STBDS_UNIT_TESTS -#define _CRT_SECURE_NO_WARNINGS -#endif - -#ifndef INCLUDE_STB_DS_H -#define INCLUDE_STB_DS_H - -#include <stddef.h> -#include <string.h> - -#ifndef STBDS_NO_SHORT_NAMES -#define arrlen      stbds_arrlen -#define arrlenu     stbds_arrlenu -#define arrput      stbds_arrput -#define arrpush     stbds_arrput -#define arrpop      stbds_arrpop -#define arrfree     stbds_arrfree -#define arraddn     stbds_arraddn // deprecated, use one of the following instead: -#define arraddnptr  stbds_arraddnptr -#define arraddnindex stbds_arraddnindex -#define arrsetlen   stbds_arrsetlen -#define arrlast     stbds_arrlast -#define arrins      stbds_arrins -#define arrinsn     stbds_arrinsn -#define arrdel      stbds_arrdel -#define arrdeln     stbds_arrdeln -#define arrdelswap  stbds_arrdelswap -#define arrcap      stbds_arrcap -#define arrsetcap   stbds_arrsetcap - -#define hmput       stbds_hmput -#define hmputs      stbds_hmputs -#define hmget       stbds_hmget -#define hmget_ts    stbds_hmget_ts -#define hmgets      stbds_hmgets -#define hmgetp      stbds_hmgetp -#define hmgetp_ts   stbds_hmgetp_ts -#define hmgetp_null stbds_hmgetp_null -#define hmgeti      stbds_hmgeti -#define hmgeti_ts   stbds_hmgeti_ts -#define hmdel       stbds_hmdel -#define hmlen       stbds_hmlen -#define hmlenu      stbds_hmlenu -#define hmfree      stbds_hmfree -#define hmdefault   stbds_hmdefault -#define hmdefaults  stbds_hmdefaults - -#define shput       stbds_shput -#define shputi      stbds_shputi -#define shputs      stbds_shputs -#define shget       stbds_shget -#define shgeti      stbds_shgeti -#define shgets      stbds_shgets -#define shgetp      stbds_shgetp -#define shgetp_null stbds_shgetp_null -#define shdel       stbds_shdel -#define shlen       stbds_shlen -#define shlenu      stbds_shlenu -#define shfree      stbds_shfree -#define shdefault   stbds_shdefault -#define shdefaults  stbds_shdefaults -#define sh_new_arena  stbds_sh_new_arena -#define sh_new_strdup stbds_sh_new_strdup - -#define stralloc    stbds_stralloc -#define strreset    stbds_strreset -#endif - -#if defined(STBDS_REALLOC) && !defined(STBDS_FREE) || !defined(STBDS_REALLOC) && defined(STBDS_FREE) -#error "You must define both STBDS_REALLOC and STBDS_FREE, or neither." -#endif -#if !defined(STBDS_REALLOC) && !defined(STBDS_FREE) -#include <stdlib.h> -#define STBDS_REALLOC(c,p,s) realloc(p,s) -#define STBDS_FREE(c,p)      free(p) -#endif - -#ifdef _MSC_VER -#define STBDS_NOTUSED(v)  (void)(v) -#else -#define STBDS_NOTUSED(v)  (void)sizeof(v) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// for security against attackers, seed the library with a random number, at least time() but stronger is better -extern void stbds_rand_seed(size_t seed); - -// these are the hash functions used internally if you want to test them or use them for other purposes -extern size_t stbds_hash_bytes(void *p, size_t len, size_t seed); -extern size_t stbds_hash_string(char *str, size_t seed); - -// this is a simple string arena allocator, initialize with e.g. 'stbds_string_arena my_arena={0}'. -typedef struct stbds_string_arena stbds_string_arena; -extern char * stbds_stralloc(stbds_string_arena *a, char *str); -extern void   stbds_strreset(stbds_string_arena *a); - -// have to #define STBDS_UNIT_TESTS to call this -extern void stbds_unit_tests(void); - -/////////////// -// -// Everything below here is implementation details -// - -extern void * stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap); -extern void   stbds_arrfreef(void *a); -extern void   stbds_hmfree_func(void *p, size_t elemsize); -extern void * stbds_hmget_key(void *a, size_t elemsize, void *key, size_t keysize, int mode); -extern void * stbds_hmget_key_ts(void *a, size_t elemsize, void *key, size_t keysize, ptrdiff_t *temp, int mode); -extern void * stbds_hmput_default(void *a, size_t elemsize); -extern void * stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int mode); -extern void * stbds_hmdel_key(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode); -extern void * stbds_shmode_func(size_t elemsize, int mode); - -#ifdef __cplusplus -} -#endif - -#if defined(__GNUC__) || defined(__clang__) -#define STBDS_HAS_TYPEOF -#ifdef __cplusplus -//#define STBDS_HAS_LITERAL_ARRAY  // this is currently broken for clang -#endif -#endif - -#if !defined(__cplusplus) -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -#define STBDS_HAS_LITERAL_ARRAY -#endif -#endif - -// this macro takes the address of the argument, but on gcc/clang can accept rvalues -#if defined(STBDS_HAS_LITERAL_ARRAY) && defined(STBDS_HAS_TYPEOF) -  #if __clang__ -  #define STBDS_ADDRESSOF(typevar, value)     ((__typeof__(typevar)[1]){value}) // literal array decays to pointer to value -  #else -  #define STBDS_ADDRESSOF(typevar, value)     ((typeof(typevar)[1]){value}) // literal array decays to pointer to value -  #endif -#else -#define STBDS_ADDRESSOF(typevar, value)     &(value) -#endif - -#define STBDS_OFFSETOF(var,field)           ((char *) &(var)->field - (char *) (var)) - -#define stbds_header(t)  ((stbds_array_header *) (t) - 1) -#define stbds_temp(t)    stbds_header(t)->temp -#define stbds_temp_key(t) (*(char **) stbds_header(t)->hash_table) - -#define stbds_arrsetcap(a,n)   (stbds_arrgrow(a,0,n)) -#define stbds_arrsetlen(a,n)   ((stbds_arrcap(a) < (size_t) (n) ? stbds_arrsetcap((a),(size_t)(n)),0 : 0), (a) ? stbds_header(a)->length = (size_t) (n) : 0) -#define stbds_arrcap(a)        ((a) ? stbds_header(a)->capacity : 0) -#define stbds_arrlen(a)        ((a) ? (ptrdiff_t) stbds_header(a)->length : 0) -#define stbds_arrlenu(a)       ((a) ?             stbds_header(a)->length : 0) -#define stbds_arrput(a,v)      (stbds_arrmaybegrow(a,1), (a)[stbds_header(a)->length++] = (v)) -#define stbds_arrpush          stbds_arrput  // synonym -#define stbds_arrpop(a)        (stbds_header(a)->length--, (a)[stbds_header(a)->length]) -#define stbds_arraddn(a,n)     ((void)(stbds_arraddnindex(a, n)))    // deprecated, use one of the following instead: -#define stbds_arraddnptr(a,n)  (stbds_arrmaybegrow(a,n), (n) ? (stbds_header(a)->length += (n), &(a)[stbds_header(a)->length-(n)]) : (a)) -#define stbds_arraddnindex(a,n)(stbds_arrmaybegrow(a,n), (n) ? (stbds_header(a)->length += (n), stbds_header(a)->length-(n)) : stbds_arrlen(a)) -#define stbds_arraddnoff       stbds_arraddnindex -#define stbds_arrlast(a)       ((a)[stbds_header(a)->length-1]) -#define stbds_arrfree(a)       ((void) ((a) ? STBDS_FREE(NULL,stbds_header(a)) : (void)0), (a)=NULL) -#define stbds_arrdel(a,i)      stbds_arrdeln(a,i,1) -#define stbds_arrdeln(a,i,n)   (memmove(&(a)[i], &(a)[(i)+(n)], sizeof *(a) * (stbds_header(a)->length-(n)-(i))), stbds_header(a)->length -= (n)) -#define stbds_arrdelswap(a,i)  ((a)[i] = stbds_arrlast(a), stbds_header(a)->length -= 1) -#define stbds_arrinsn(a,i,n)   (stbds_arraddn((a),(n)), memmove(&(a)[(i)+(n)], &(a)[i], sizeof *(a) * (stbds_header(a)->length-(n)-(i)))) -#define stbds_arrins(a,i,v)    (stbds_arrinsn((a),(i),1), (a)[i]=(v)) - -#define stbds_arrmaybegrow(a,n)  ((!(a) || stbds_header(a)->length + (n) > stbds_header(a)->capacity) \ -                                  ? (stbds_arrgrow(a,n,0),0) : 0) - -#define stbds_arrgrow(a,b,c)   ((a) = stbds_arrgrowf_wrapper((a), sizeof *(a), (b), (c))) - -#define stbds_hmput(t, k, v) \ -    ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, 0),   \ -     (t)[stbds_temp((t)-1)].key = (k),    \ -     (t)[stbds_temp((t)-1)].value = (v)) - -#define stbds_hmputs(t, s) \ -    ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), &(s).key, sizeof (s).key, STBDS_HM_BINARY), \ -     (t)[stbds_temp((t)-1)] = (s)) - -#define stbds_hmgeti(t,k) \ -    ((t) = stbds_hmget_key_wrapper((t), sizeof *(t), (void*) STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, STBDS_HM_BINARY), \ -      stbds_temp((t)-1)) - -#define stbds_hmgeti_ts(t,k,temp) \ -    ((t) = stbds_hmget_key_ts_wrapper((t), sizeof *(t), (void*) STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, &(temp), STBDS_HM_BINARY), \ -      (temp)) - -#define stbds_hmgetp(t, k) \ -    ((void) stbds_hmgeti(t,k), &(t)[stbds_temp((t)-1)]) - -#define stbds_hmgetp_ts(t, k, temp) \ -    ((void) stbds_hmgeti_ts(t,k,temp), &(t)[temp]) - -#define stbds_hmdel(t,k) \ -    (((t) = stbds_hmdel_key_wrapper((t),sizeof *(t), (void*) STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, STBDS_OFFSETOF((t),key), STBDS_HM_BINARY)),(t)?stbds_temp((t)-1):0) - -#define stbds_hmdefault(t, v) \ -    ((t) = stbds_hmput_default_wrapper((t), sizeof *(t)), (t)[-1].value = (v)) - -#define stbds_hmdefaults(t, s) \ -    ((t) = stbds_hmput_default_wrapper((t), sizeof *(t)), (t)[-1] = (s)) - -#define stbds_hmfree(p)        \ -    ((void) ((p) != NULL ? stbds_hmfree_func((p)-1,sizeof*(p)),0 : 0),(p)=NULL) - -#define stbds_hmgets(t, k)    (*stbds_hmgetp(t,k)) -#define stbds_hmget(t, k)     (stbds_hmgetp(t,k)->value) -#define stbds_hmget_ts(t, k, temp)  (stbds_hmgetp_ts(t,k,temp)->value) -#define stbds_hmlen(t)        ((t) ? (ptrdiff_t) stbds_header((t)-1)->length-1 : 0) -#define stbds_hmlenu(t)       ((t) ?             stbds_header((t)-1)->length-1 : 0) -#define stbds_hmgetp_null(t,k)  (stbds_hmgeti(t,k) == -1 ? NULL : &(t)[stbds_temp((t)-1)]) - -#define stbds_shput(t, k, v) \ -    ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) (k), sizeof (t)->key, STBDS_HM_STRING),   \ -     (t)[stbds_temp((t)-1)].value = (v)) - -#define stbds_shputi(t, k, v) \ -    ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) (k), sizeof (t)->key, STBDS_HM_STRING),   \ -     (t)[stbds_temp((t)-1)].value = (v), stbds_temp((t)-1)) - -#define stbds_shputs(t, s) \ -    ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) (s).key, sizeof (s).key, STBDS_HM_STRING), \ -     (t)[stbds_temp((t)-1)] = (s), \ -     (t)[stbds_temp((t)-1)].key = stbds_temp_key((t)-1)) // above line overwrites whole structure, so must rewrite key here if it was allocated internally - -#define stbds_pshput(t, p) \ -    ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) (p)->key, sizeof (p)->key, STBDS_HM_PTR_TO_STRING), \ -     (t)[stbds_temp((t)-1)] = (p)) - -#define stbds_shgeti(t,k) \ -     ((t) = stbds_hmget_key_wrapper((t), sizeof *(t), (void*) (k), sizeof (t)->key, STBDS_HM_STRING), \ -      stbds_temp((t)-1)) - -#define stbds_pshgeti(t,k) \ -     ((t) = stbds_hmget_key_wrapper((t), sizeof *(t), (void*) (k), sizeof (*(t))->key, STBDS_HM_PTR_TO_STRING), \ -      stbds_temp((t)-1)) - -#define stbds_shgetp(t, k) \ -    ((void) stbds_shgeti(t,k), &(t)[stbds_temp((t)-1)]) - -#define stbds_pshget(t, k) \ -    ((void) stbds_pshgeti(t,k), (t)[stbds_temp((t)-1)]) - -#define stbds_shdel(t,k) \ -    (((t) = stbds_hmdel_key_wrapper((t),sizeof *(t), (void*) (k), sizeof (t)->key, STBDS_OFFSETOF((t),key), STBDS_HM_STRING)),(t)?stbds_temp((t)-1):0) -#define stbds_pshdel(t,k) \ -    (((t) = stbds_hmdel_key_wrapper((t),sizeof *(t), (void*) (k), sizeof (*(t))->key, STBDS_OFFSETOF(*(t),key), STBDS_HM_PTR_TO_STRING)),(t)?stbds_temp((t)-1):0) - -#define stbds_sh_new_arena(t)  \ -    ((t) = stbds_shmode_func_wrapper(t, sizeof *(t), STBDS_SH_ARENA)) -#define stbds_sh_new_strdup(t) \ -    ((t) = stbds_shmode_func_wrapper(t, sizeof *(t), STBDS_SH_STRDUP)) - -#define stbds_shdefault(t, v)  stbds_hmdefault(t,v) -#define stbds_shdefaults(t, s) stbds_hmdefaults(t,s) - -#define stbds_shfree       stbds_hmfree -#define stbds_shlenu       stbds_hmlenu - -#define stbds_shgets(t, k) (*stbds_shgetp(t,k)) -#define stbds_shget(t, k)  (stbds_shgetp(t,k)->value) -#define stbds_shgetp_null(t,k)  (stbds_shgeti(t,k) == -1 ? NULL : &(t)[stbds_temp((t)-1)]) -#define stbds_shlen        stbds_hmlen - -typedef struct -{ -  size_t      length; -  size_t      capacity; -  void      * hash_table; -  ptrdiff_t   temp; -} stbds_array_header; - -typedef struct stbds_string_block -{ -  struct stbds_string_block *next; -  char storage[8]; -} stbds_string_block; - -struct stbds_string_arena -{ -  stbds_string_block *storage; -  size_t remaining; -  unsigned char block; -  unsigned char mode;  // this isn't used by the string arena itself -}; - -#define STBDS_HM_BINARY         0 -#define STBDS_HM_STRING         1 - -enum -{ -   STBDS_SH_NONE, -   STBDS_SH_DEFAULT, -   STBDS_SH_STRDUP, -   STBDS_SH_ARENA -}; - -#ifdef __cplusplus -// in C we use implicit assignment from these void*-returning functions to T*. -// in C++ these templates make the same code work -template<class T> static T * stbds_arrgrowf_wrapper(T *a, size_t elemsize, size_t addlen, size_t min_cap) { -  return (T*)stbds_arrgrowf((void *)a, elemsize, addlen, min_cap); -} -template<class T> static T * stbds_hmget_key_wrapper(T *a, size_t elemsize, void *key, size_t keysize, int mode) { -  return (T*)stbds_hmget_key((void*)a, elemsize, key, keysize, mode); -} -template<class T> static T * stbds_hmget_key_ts_wrapper(T *a, size_t elemsize, void *key, size_t keysize, ptrdiff_t *temp, int mode) { -  return (T*)stbds_hmget_key_ts((void*)a, elemsize, key, keysize, temp, mode); -} -template<class T> static T * stbds_hmput_default_wrapper(T *a, size_t elemsize) { -  return (T*)stbds_hmput_default((void *)a, elemsize); -} -template<class T> static T * stbds_hmput_key_wrapper(T *a, size_t elemsize, void *key, size_t keysize, int mode) { -  return (T*)stbds_hmput_key((void*)a, elemsize, key, keysize, mode); -} -template<class T> static T * stbds_hmdel_key_wrapper(T *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode){ -  return (T*)stbds_hmdel_key((void*)a, elemsize, key, keysize, keyoffset, mode); -} -template<class T> static T * stbds_shmode_func_wrapper(T *, size_t elemsize, int mode) { -  return (T*)stbds_shmode_func(elemsize, mode); -} -#else -#define stbds_arrgrowf_wrapper            stbds_arrgrowf -#define stbds_hmget_key_wrapper           stbds_hmget_key -#define stbds_hmget_key_ts_wrapper        stbds_hmget_key_ts -#define stbds_hmput_default_wrapper       stbds_hmput_default -#define stbds_hmput_key_wrapper           stbds_hmput_key -#define stbds_hmdel_key_wrapper           stbds_hmdel_key -#define stbds_shmode_func_wrapper(t,e,m)  stbds_shmode_func(e,m) -#endif - -#endif // INCLUDE_STB_DS_H - - -////////////////////////////////////////////////////////////////////////////// -// -//   IMPLEMENTATION -// - -#ifdef STB_DS_IMPLEMENTATION -#include <assert.h> -#include <string.h> - -#ifndef STBDS_ASSERT -#define STBDS_ASSERT_WAS_UNDEFINED -#define STBDS_ASSERT(x)   ((void) 0) -#endif - -#ifdef STBDS_STATISTICS -#define STBDS_STATS(x)   x -size_t stbds_array_grow; -size_t stbds_hash_grow; -size_t stbds_hash_shrink; -size_t stbds_hash_rebuild; -size_t stbds_hash_probes; -size_t stbds_hash_alloc; -size_t stbds_rehash_probes; -size_t stbds_rehash_items; -#else -#define STBDS_STATS(x) -#endif - -// -// stbds_arr implementation -// - -//int *prev_allocs[65536]; -//int num_prev; - -void *stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap) -{ -  stbds_array_header temp={0}; // force debugging -  void *b; -  size_t min_len = stbds_arrlen(a) + addlen; -  (void) sizeof(temp); - -  // compute the minimum capacity needed -  if (min_len > min_cap) -    min_cap = min_len; - -  if (min_cap <= stbds_arrcap(a)) -    return a; - -  // increase needed capacity to guarantee O(1) amortized -  if (min_cap < 2 * stbds_arrcap(a)) -    min_cap = 2 * stbds_arrcap(a); -  else if (min_cap < 4) -    min_cap = 4; - -  //if (num_prev < 65536) if (a) prev_allocs[num_prev++] = (int *) ((char *) a+1); -  //if (num_prev == 2201) -  //  num_prev = num_prev; -  b = STBDS_REALLOC(NULL, (a) ? stbds_header(a) : 0, elemsize * min_cap + sizeof(stbds_array_header)); -  //if (num_prev < 65536) prev_allocs[num_prev++] = (int *) (char *) b; -  b = (char *) b + sizeof(stbds_array_header); -  if (a == NULL) { -    stbds_header(b)->length = 0; -    stbds_header(b)->hash_table = 0; -    stbds_header(b)->temp = 0; -  } else { -    STBDS_STATS(++stbds_array_grow); -  } -  stbds_header(b)->capacity = min_cap; - -  return b; -} - -void stbds_arrfreef(void *a) -{ -  STBDS_FREE(NULL, stbds_header(a)); -} - -// -// stbds_hm hash table implementation -// - -#ifdef STBDS_INTERNAL_SMALL_BUCKET -#define STBDS_BUCKET_LENGTH      4 -#else -#define STBDS_BUCKET_LENGTH      8 -#endif - -#define STBDS_BUCKET_SHIFT      (STBDS_BUCKET_LENGTH == 8 ? 3 : 2) -#define STBDS_BUCKET_MASK       (STBDS_BUCKET_LENGTH-1) -#define STBDS_CACHE_LINE_SIZE   64 - -#define STBDS_ALIGN_FWD(n,a)   (((n) + (a) - 1) & ~((a)-1)) - -typedef struct -{ -   size_t    hash [STBDS_BUCKET_LENGTH]; -   ptrdiff_t index[STBDS_BUCKET_LENGTH]; -} stbds_hash_bucket; // in 32-bit, this is one 64-byte cache line; in 64-bit, each array is one 64-byte cache line - -typedef struct -{ -  char * temp_key; // this MUST be the first field of the hash table -  size_t slot_count; -  size_t used_count; -  size_t used_count_threshold; -  size_t used_count_shrink_threshold; -  size_t tombstone_count; -  size_t tombstone_count_threshold; -  size_t seed; -  size_t slot_count_log2; -  stbds_string_arena string; -  stbds_hash_bucket *storage; // not a separate allocation, just 64-byte aligned storage after this struct -} stbds_hash_index; - -#define STBDS_INDEX_EMPTY    -1 -#define STBDS_INDEX_DELETED  -2 -#define STBDS_INDEX_IN_USE(x)  ((x) >= 0) - -#define STBDS_HASH_EMPTY      0 -#define STBDS_HASH_DELETED    1 - -static size_t stbds_hash_seed=0x31415926; - -void stbds_rand_seed(size_t seed) -{ -  stbds_hash_seed = seed; -} - -#define stbds_load_32_or_64(var, temp, v32, v64_hi, v64_lo)                                          \ -  temp = v64_lo ^ v32, temp <<= 16, temp <<= 16, temp >>= 16, temp >>= 16, /* discard if 32-bit */   \ -  var = v64_hi, var <<= 16, var <<= 16,                                    /* discard if 32-bit */   \ -  var ^= temp ^ v32 - -#define STBDS_SIZE_T_BITS           ((sizeof (size_t)) * 8) - -static size_t stbds_probe_position(size_t hash, size_t slot_count, size_t slot_log2) -{ -  size_t pos; -  STBDS_NOTUSED(slot_log2); -  pos = hash & (slot_count-1); -  #ifdef STBDS_INTERNAL_BUCKET_START -  pos &= ~STBDS_BUCKET_MASK; -  #endif -  return pos; -} - -static size_t stbds_log2(size_t slot_count) -{ -  size_t n=0; -  while (slot_count > 1) { -    slot_count >>= 1; -    ++n; -  } -  return n; -} - -static stbds_hash_index *stbds_make_hash_index(size_t slot_count, stbds_hash_index *ot) -{ -  stbds_hash_index *t; -  t = (stbds_hash_index *) STBDS_REALLOC(NULL,0,(slot_count >> STBDS_BUCKET_SHIFT) * sizeof(stbds_hash_bucket) + sizeof(stbds_hash_index) + STBDS_CACHE_LINE_SIZE-1); -  t->storage = (stbds_hash_bucket *) STBDS_ALIGN_FWD((size_t) (t+1), STBDS_CACHE_LINE_SIZE); -  t->slot_count = slot_count; -  t->slot_count_log2 = stbds_log2(slot_count); -  t->tombstone_count = 0; -  t->used_count = 0; - -  #if 0 // A1 -  t->used_count_threshold        = slot_count*12/16; // if 12/16th of table is occupied, grow -  t->tombstone_count_threshold   = slot_count* 2/16; // if tombstones are 2/16th of table, rebuild -  t->used_count_shrink_threshold = slot_count* 4/16; // if table is only 4/16th full, shrink -  #elif 1 // A2 -  //t->used_count_threshold        = slot_count*12/16; // if 12/16th of table is occupied, grow -  //t->tombstone_count_threshold   = slot_count* 3/16; // if tombstones are 3/16th of table, rebuild -  //t->used_count_shrink_threshold = slot_count* 4/16; // if table is only 4/16th full, shrink - -  // compute without overflowing -  t->used_count_threshold        = slot_count - (slot_count>>2); -  t->tombstone_count_threshold   = (slot_count>>3) + (slot_count>>4); -  t->used_count_shrink_threshold = slot_count >> 2; - -  #elif 0 // B1 -  t->used_count_threshold        = slot_count*13/16; // if 13/16th of table is occupied, grow -  t->tombstone_count_threshold   = slot_count* 2/16; // if tombstones are 2/16th of table, rebuild -  t->used_count_shrink_threshold = slot_count* 5/16; // if table is only 5/16th full, shrink -  #else // C1 -  t->used_count_threshold        = slot_count*14/16; // if 14/16th of table is occupied, grow -  t->tombstone_count_threshold   = slot_count* 2/16; // if tombstones are 2/16th of table, rebuild -  t->used_count_shrink_threshold = slot_count* 6/16; // if table is only 6/16th full, shrink -  #endif -  // Following statistics were measured on a Core i7-6700 @ 4.00Ghz, compiled with clang 7.0.1 -O2 -    // Note that the larger tables have high variance as they were run fewer times -  //     A1            A2          B1           C1 -  //    0.10ms :     0.10ms :     0.10ms :     0.11ms :      2,000 inserts creating 2K table -  //    0.96ms :     0.95ms :     0.97ms :     1.04ms :     20,000 inserts creating 20K table -  //   14.48ms :    14.46ms :    10.63ms :    11.00ms :    200,000 inserts creating 200K table -  //  195.74ms :   196.35ms :   203.69ms :   214.92ms :  2,000,000 inserts creating 2M table -  // 2193.88ms :  2209.22ms :  2285.54ms :  2437.17ms : 20,000,000 inserts creating 20M table -  //   65.27ms :    53.77ms :    65.33ms :    65.47ms : 500,000 inserts & deletes in 2K table -  //   72.78ms :    62.45ms :    71.95ms :    72.85ms : 500,000 inserts & deletes in 20K table -  //   89.47ms :    77.72ms :    96.49ms :    96.75ms : 500,000 inserts & deletes in 200K table -  //   97.58ms :    98.14ms :    97.18ms :    97.53ms : 500,000 inserts & deletes in 2M table -  //  118.61ms :   119.62ms :   120.16ms :   118.86ms : 500,000 inserts & deletes in 20M table -  //  192.11ms :   194.39ms :   196.38ms :   195.73ms : 500,000 inserts & deletes in 200M table - -  if (slot_count <= STBDS_BUCKET_LENGTH) -    t->used_count_shrink_threshold = 0; -  // to avoid infinite loop, we need to guarantee that at least one slot is empty and will terminate probes -  STBDS_ASSERT(t->used_count_threshold + t->tombstone_count_threshold < t->slot_count); -  STBDS_STATS(++stbds_hash_alloc); -  if (ot) { -    t->string = ot->string; -    // reuse old seed so we can reuse old hashes so below "copy out old data" doesn't do any hashing -    t->seed = ot->seed; -  } else { -    size_t a,b,temp; -    memset(&t->string, 0, sizeof(t->string)); -    t->seed = stbds_hash_seed; -    // LCG -    // in 32-bit, a =          2147001325   b =  715136305 -    // in 64-bit, a = 2862933555777941757   b = 3037000493 -    stbds_load_32_or_64(a,temp, 2147001325, 0x27bb2ee6, 0x87b0b0fd); -    stbds_load_32_or_64(b,temp,  715136305,          0, 0xb504f32d); -    stbds_hash_seed = stbds_hash_seed  * a + b; -  } - -  { -    size_t i,j; -    for (i=0; i < slot_count >> STBDS_BUCKET_SHIFT; ++i) { -      stbds_hash_bucket *b = &t->storage[i]; -      for (j=0; j < STBDS_BUCKET_LENGTH; ++j) -        b->hash[j] = STBDS_HASH_EMPTY; -      for (j=0; j < STBDS_BUCKET_LENGTH; ++j) -        b->index[j] = STBDS_INDEX_EMPTY; -    } -  } - -  // copy out the old data, if any -  if (ot) { -    size_t i,j; -    t->used_count = ot->used_count; -    for (i=0; i < ot->slot_count >> STBDS_BUCKET_SHIFT; ++i) { -      stbds_hash_bucket *ob = &ot->storage[i]; -      for (j=0; j < STBDS_BUCKET_LENGTH; ++j) { -        if (STBDS_INDEX_IN_USE(ob->index[j])) { -          size_t hash = ob->hash[j]; -          size_t pos = stbds_probe_position(hash, t->slot_count, t->slot_count_log2); -          size_t step = STBDS_BUCKET_LENGTH; -          STBDS_STATS(++stbds_rehash_items); -          for (;;) { -            size_t limit,z; -            stbds_hash_bucket *bucket; -            bucket = &t->storage[pos >> STBDS_BUCKET_SHIFT]; -            STBDS_STATS(++stbds_rehash_probes); - -            for (z=pos & STBDS_BUCKET_MASK; z < STBDS_BUCKET_LENGTH; ++z) { -              if (bucket->hash[z] == 0) { -                bucket->hash[z] = hash; -                bucket->index[z] = ob->index[j]; -                goto done; -              } -            } - -            limit = pos & STBDS_BUCKET_MASK; -            for (z = 0; z < limit; ++z) { -              if (bucket->hash[z] == 0) { -                bucket->hash[z] = hash; -                bucket->index[z] = ob->index[j]; -                goto done; -              } -            } - -            pos += step;                  // quadratic probing -            step += STBDS_BUCKET_LENGTH; -            pos &= (t->slot_count-1); -          } -        } -       done: -        ; -      } -    } -  } - -  return t; -} - -#define STBDS_ROTATE_LEFT(val, n)   (((val) << (n)) | ((val) >> (STBDS_SIZE_T_BITS - (n)))) -#define STBDS_ROTATE_RIGHT(val, n)  (((val) >> (n)) | ((val) << (STBDS_SIZE_T_BITS - (n)))) - -size_t stbds_hash_string(char *str, size_t seed) -{ -  size_t hash = seed; -  while (*str) -     hash = STBDS_ROTATE_LEFT(hash, 9) + (unsigned char) *str++; - -  // Thomas Wang 64-to-32 bit mix function, hopefully also works in 32 bits -  hash ^= seed; -  hash = (~hash) + (hash << 18); -  hash ^= hash ^ STBDS_ROTATE_RIGHT(hash,31); -  hash = hash * 21; -  hash ^= hash ^ STBDS_ROTATE_RIGHT(hash,11); -  hash += (hash << 6); -  hash ^= STBDS_ROTATE_RIGHT(hash,22); -  return hash+seed; -} - -#ifdef STBDS_SIPHASH_2_4 -#define STBDS_SIPHASH_C_ROUNDS 2 -#define STBDS_SIPHASH_D_ROUNDS 4 -typedef int STBDS_SIPHASH_2_4_can_only_be_used_in_64_bit_builds[sizeof(size_t) == 8 ? 1 : -1]; -#endif - -#ifndef STBDS_SIPHASH_C_ROUNDS -#define STBDS_SIPHASH_C_ROUNDS 1 -#endif -#ifndef STBDS_SIPHASH_D_ROUNDS -#define STBDS_SIPHASH_D_ROUNDS 1 -#endif - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4127) // conditional expression is constant, for do..while(0) and sizeof()== -#endif - -static size_t stbds_siphash_bytes(void *p, size_t len, size_t seed) -{ -  unsigned char *d = (unsigned char *) p; -  size_t i,j; -  size_t v0,v1,v2,v3, data; - -  // hash that works on 32- or 64-bit registers without knowing which we have -  // (computes different results on 32-bit and 64-bit platform) -  // derived from siphash, but on 32-bit platforms very different as it uses 4 32-bit state not 4 64-bit -  v0 = ((((size_t) 0x736f6d65 << 16) << 16) + 0x70736575) ^  seed; -  v1 = ((((size_t) 0x646f7261 << 16) << 16) + 0x6e646f6d) ^ ~seed; -  v2 = ((((size_t) 0x6c796765 << 16) << 16) + 0x6e657261) ^  seed; -  v3 = ((((size_t) 0x74656462 << 16) << 16) + 0x79746573) ^ ~seed; - -  #ifdef STBDS_TEST_SIPHASH_2_4 -  // hardcoded with key material in the siphash test vectors -  v0 ^= 0x0706050403020100ull ^  seed; -  v1 ^= 0x0f0e0d0c0b0a0908ull ^ ~seed; -  v2 ^= 0x0706050403020100ull ^  seed; -  v3 ^= 0x0f0e0d0c0b0a0908ull ^ ~seed; -  #endif - -  #define STBDS_SIPROUND() \ -    do {                   \ -      v0 += v1; v1 = STBDS_ROTATE_LEFT(v1, 13);  v1 ^= v0; v0 = STBDS_ROTATE_LEFT(v0,STBDS_SIZE_T_BITS/2); \ -      v2 += v3; v3 = STBDS_ROTATE_LEFT(v3, 16);  v3 ^= v2;                                                 \ -      v2 += v1; v1 = STBDS_ROTATE_LEFT(v1, 17);  v1 ^= v2; v2 = STBDS_ROTATE_LEFT(v2,STBDS_SIZE_T_BITS/2); \ -      v0 += v3; v3 = STBDS_ROTATE_LEFT(v3, 21);  v3 ^= v0;                                                 \ -    } while (0) - -  for (i=0; i+sizeof(size_t) <= len; i += sizeof(size_t), d += sizeof(size_t)) { -    data = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24); -    data |= (size_t) (d[4] | (d[5] << 8) | (d[6] << 16) | (d[7] << 24)) << 16 << 16; // discarded if size_t == 4 - -    v3 ^= data; -    for (j=0; j < STBDS_SIPHASH_C_ROUNDS; ++j) -      STBDS_SIPROUND(); -    v0 ^= data; -  } -  data = len << (STBDS_SIZE_T_BITS-8); -  switch (len - i) { -    case 7: data |= ((size_t) d[6] << 24) << 24; // fall through -    case 6: data |= ((size_t) d[5] << 20) << 20; // fall through -    case 5: data |= ((size_t) d[4] << 16) << 16; // fall through -    case 4: data |= (d[3] << 24); // fall through -    case 3: data |= (d[2] << 16); // fall through -    case 2: data |= (d[1] << 8); // fall through -    case 1: data |= d[0]; // fall through -    case 0: break; -  } -  v3 ^= data; -  for (j=0; j < STBDS_SIPHASH_C_ROUNDS; ++j) -    STBDS_SIPROUND(); -  v0 ^= data; -  v2 ^= 0xff; -  for (j=0; j < STBDS_SIPHASH_D_ROUNDS; ++j) -    STBDS_SIPROUND(); - -#ifdef STBDS_SIPHASH_2_4 -  return v0^v1^v2^v3; -#else -  return v1^v2^v3; // slightly stronger since v0^v3 in above cancels out final round operation? I tweeted at the authors of SipHash about this but they didn't reply -#endif -} - -size_t stbds_hash_bytes(void *p, size_t len, size_t seed) -{ -#ifdef STBDS_SIPHASH_2_4 -  return stbds_siphash_bytes(p,len,seed); -#else -  unsigned char *d = (unsigned char *) p; - -  if (len == 4) { -    unsigned int hash = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24); -    #if 0 -    // HASH32-A  Bob Jenkin's hash function w/o large constants -    hash ^= seed; -    hash -= (hash<<6); -    hash ^= (hash>>17); -    hash -= (hash<<9); -    hash ^= seed; -    hash ^= (hash<<4); -    hash -= (hash<<3); -    hash ^= (hash<<10); -    hash ^= (hash>>15); -    #elif 1 -    // HASH32-BB  Bob Jenkin's presumably-accidental version of Thomas Wang hash with rotates turned into shifts. -    // Note that converting these back to rotates makes it run a lot slower, presumably due to collisions, so I'm -    // not really sure what's going on. -    hash ^= seed; -    hash = (hash ^ 61) ^ (hash >> 16); -    hash = hash + (hash << 3); -    hash = hash ^ (hash >> 4); -    hash = hash * 0x27d4eb2d; -    hash ^= seed; -    hash = hash ^ (hash >> 15); -    #else  // HASH32-C   -  Murmur3 -    hash ^= seed; -    hash *= 0xcc9e2d51; -    hash = (hash << 17) | (hash >> 15); -    hash *= 0x1b873593; -    hash ^= seed; -    hash = (hash << 19) | (hash >> 13); -    hash = hash*5 + 0xe6546b64; -    hash ^= hash >> 16; -    hash *= 0x85ebca6b; -    hash ^= seed; -    hash ^= hash >> 13; -    hash *= 0xc2b2ae35; -    hash ^= hash >> 16; -    #endif -    // Following statistics were measured on a Core i7-6700 @ 4.00Ghz, compiled with clang 7.0.1 -O2 -    // Note that the larger tables have high variance as they were run fewer times -    //  HASH32-A   //  HASH32-BB  //  HASH32-C -    //    0.10ms   //    0.10ms   //    0.10ms :      2,000 inserts creating 2K table -    //    0.96ms   //    0.95ms   //    0.99ms :     20,000 inserts creating 20K table -    //   14.69ms   //   14.43ms   //   14.97ms :    200,000 inserts creating 200K table -    //  199.99ms   //  195.36ms   //  202.05ms :  2,000,000 inserts creating 2M table -    // 2234.84ms   // 2187.74ms   // 2240.38ms : 20,000,000 inserts creating 20M table -    //   55.68ms   //   53.72ms   //   57.31ms : 500,000 inserts & deletes in 2K table -    //   63.43ms   //   61.99ms   //   65.73ms : 500,000 inserts & deletes in 20K table -    //   80.04ms   //   77.96ms   //   81.83ms : 500,000 inserts & deletes in 200K table -    //  100.42ms   //   97.40ms   //  102.39ms : 500,000 inserts & deletes in 2M table -    //  119.71ms   //  120.59ms   //  121.63ms : 500,000 inserts & deletes in 20M table -    //  185.28ms   //  195.15ms   //  187.74ms : 500,000 inserts & deletes in 200M table -    //   15.58ms   //   14.79ms   //   15.52ms : 200,000 inserts creating 200K table with varying key spacing - -    return (((size_t) hash << 16 << 16) | hash) ^ seed; -  } else if (len == 8 && sizeof(size_t) == 8) { -    size_t hash = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24); -    hash |= (size_t) (d[4] | (d[5] << 8) | (d[6] << 16) | (d[7] << 24)) << 16 << 16; // avoid warning if size_t == 4 -    hash ^= seed; -    hash = (~hash) + (hash << 21); -    hash ^= STBDS_ROTATE_RIGHT(hash,24); -    hash *= 265; -    hash ^= STBDS_ROTATE_RIGHT(hash,14); -    hash ^= seed; -    hash *= 21; -    hash ^= STBDS_ROTATE_RIGHT(hash,28); -    hash += (hash << 31); -    hash = (~hash) + (hash << 18); -    return hash; -  } else { -    return stbds_siphash_bytes(p,len,seed); -  } -#endif -} -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - -static int stbds_is_key_equal(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode, size_t i) -{ -  if (mode >= STBDS_HM_STRING) -    return 0==strcmp((char *) key, * (char **) ((char *) a + elemsize*i + keyoffset)); -  else -    return 0==memcmp(key, (char *) a + elemsize*i + keyoffset, keysize); -} - -#define STBDS_HASH_TO_ARR(x,elemsize) ((char*) (x) - (elemsize)) -#define STBDS_ARR_TO_HASH(x,elemsize) ((char*) (x) + (elemsize)) - -#define stbds_hash_table(a)  ((stbds_hash_index *) stbds_header(a)->hash_table) - -void stbds_hmfree_func(void *a, size_t elemsize) -{ -  if (a == NULL) return; -  if (stbds_hash_table(a) != NULL) { -    if (stbds_hash_table(a)->string.mode == STBDS_SH_STRDUP) { -      size_t i; -      // skip 0th element, which is default -      for (i=1; i < stbds_header(a)->length; ++i) -        STBDS_FREE(NULL, *(char**) ((char *) a + elemsize*i)); -    } -    stbds_strreset(&stbds_hash_table(a)->string); -  } -  STBDS_FREE(NULL, stbds_header(a)->hash_table); -  STBDS_FREE(NULL, stbds_header(a)); -} - -static ptrdiff_t stbds_hm_find_slot(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode) -{ -  void *raw_a = STBDS_HASH_TO_ARR(a,elemsize); -  stbds_hash_index *table = stbds_hash_table(raw_a); -  size_t hash = mode >= STBDS_HM_STRING ? stbds_hash_string((char*)key,table->seed) : stbds_hash_bytes(key, keysize,table->seed); -  size_t step = STBDS_BUCKET_LENGTH; -  size_t limit,i; -  size_t pos; -  stbds_hash_bucket *bucket; - -  if (hash < 2) hash += 2; // stored hash values are forbidden from being 0, so we can detect empty slots - -  pos = stbds_probe_position(hash, table->slot_count, table->slot_count_log2); - -  for (;;) { -    STBDS_STATS(++stbds_hash_probes); -    bucket = &table->storage[pos >> STBDS_BUCKET_SHIFT]; - -    // start searching from pos to end of bucket, this should help performance on small hash tables that fit in cache -    for (i=pos & STBDS_BUCKET_MASK; i < STBDS_BUCKET_LENGTH; ++i) { -      if (bucket->hash[i] == hash) { -        if (stbds_is_key_equal(a, elemsize, key, keysize, keyoffset, mode, bucket->index[i])) { -          return (pos & ~STBDS_BUCKET_MASK)+i; -        } -      } else if (bucket->hash[i] == STBDS_HASH_EMPTY) { -        return -1; -      } -    } - -    // search from beginning of bucket to pos -    limit = pos & STBDS_BUCKET_MASK; -    for (i = 0; i < limit; ++i) { -      if (bucket->hash[i] == hash) { -        if (stbds_is_key_equal(a, elemsize, key, keysize, keyoffset, mode, bucket->index[i])) { -          return (pos & ~STBDS_BUCKET_MASK)+i; -        } -      } else if (bucket->hash[i] == STBDS_HASH_EMPTY) { -        return -1; -      } -    } - -    // quadratic probing -    pos += step; -    step += STBDS_BUCKET_LENGTH; -    pos &= (table->slot_count-1); -  } -  /* NOTREACHED */ -} - -void * stbds_hmget_key_ts(void *a, size_t elemsize, void *key, size_t keysize, ptrdiff_t *temp, int mode) -{ -  size_t keyoffset = 0; -  if (a == NULL) { -    // make it non-empty so we can return a temp -    a = stbds_arrgrowf(0, elemsize, 0, 1); -    stbds_header(a)->length += 1; -    memset(a, 0, elemsize); -    *temp = STBDS_INDEX_EMPTY; -    // adjust a to point after the default element -    return STBDS_ARR_TO_HASH(a,elemsize); -  } else { -    stbds_hash_index *table; -    void *raw_a = STBDS_HASH_TO_ARR(a,elemsize); -    // adjust a to point to the default element -    table = (stbds_hash_index *) stbds_header(raw_a)->hash_table; -    if (table == 0) { -      *temp = -1; -    } else { -      ptrdiff_t slot = stbds_hm_find_slot(a, elemsize, key, keysize, keyoffset, mode); -      if (slot < 0) { -        *temp = STBDS_INDEX_EMPTY; -      } else { -        stbds_hash_bucket *b = &table->storage[slot >> STBDS_BUCKET_SHIFT]; -        *temp = b->index[slot & STBDS_BUCKET_MASK]; -      } -    } -    return a; -  } -} - -void * stbds_hmget_key(void *a, size_t elemsize, void *key, size_t keysize, int mode) -{ -  ptrdiff_t temp; -  void *p = stbds_hmget_key_ts(a, elemsize, key, keysize, &temp, mode); -  stbds_temp(STBDS_HASH_TO_ARR(p,elemsize)) = temp; -  return p; -} - -void * stbds_hmput_default(void *a, size_t elemsize) -{ -  // three cases: -  //   a is NULL <- allocate -  //   a has a hash table but no entries, because of shmode <- grow -  //   a has entries <- do nothing -  if (a == NULL || stbds_header(STBDS_HASH_TO_ARR(a,elemsize))->length == 0) { -    a = stbds_arrgrowf(a ? STBDS_HASH_TO_ARR(a,elemsize) : NULL, elemsize, 0, 1); -    stbds_header(a)->length += 1; -    memset(a, 0, elemsize); -    a=STBDS_ARR_TO_HASH(a,elemsize); -  } -  return a; -} - -static char *stbds_strdup(char *str); - -void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int mode) -{ -  size_t keyoffset=0; -  void *raw_a; -  stbds_hash_index *table; - -  if (a == NULL) { -    a = stbds_arrgrowf(0, elemsize, 0, 1); -    memset(a, 0, elemsize); -    stbds_header(a)->length += 1; -    // adjust a to point AFTER the default element -    a = STBDS_ARR_TO_HASH(a,elemsize); -  } - -  // adjust a to point to the default element -  raw_a = a; -  a = STBDS_HASH_TO_ARR(a,elemsize); - -  table = (stbds_hash_index *) stbds_header(a)->hash_table; - -  if (table == NULL || table->used_count >= table->used_count_threshold) { -    stbds_hash_index *nt; -    size_t slot_count; - -    slot_count = (table == NULL) ? STBDS_BUCKET_LENGTH : table->slot_count*2; -    nt = stbds_make_hash_index(slot_count, table); -    if (table) -      STBDS_FREE(NULL, table); -    else -      nt->string.mode = mode >= STBDS_HM_STRING ? STBDS_SH_DEFAULT : 0; -    stbds_header(a)->hash_table = table = nt; -    STBDS_STATS(++stbds_hash_grow); -  } - -  // we iterate hash table explicitly because we want to track if we saw a tombstone -  { -    size_t hash = mode >= STBDS_HM_STRING ? stbds_hash_string((char*)key,table->seed) : stbds_hash_bytes(key, keysize,table->seed); -    size_t step = STBDS_BUCKET_LENGTH; -    size_t pos; -    ptrdiff_t tombstone = -1; -    stbds_hash_bucket *bucket; - -    // stored hash values are forbidden from being 0, so we can detect empty slots to early out quickly -    if (hash < 2) hash += 2; - -    pos = stbds_probe_position(hash, table->slot_count, table->slot_count_log2); - -    for (;;) { -      size_t limit, i; -      STBDS_STATS(++stbds_hash_probes); -      bucket = &table->storage[pos >> STBDS_BUCKET_SHIFT]; - -      // start searching from pos to end of bucket -      for (i=pos & STBDS_BUCKET_MASK; i < STBDS_BUCKET_LENGTH; ++i) { -        if (bucket->hash[i] == hash) { -          if (stbds_is_key_equal(raw_a, elemsize, key, keysize, keyoffset, mode, bucket->index[i])) { -            stbds_temp(a) = bucket->index[i]; -            if (mode >= STBDS_HM_STRING) -              stbds_temp_key(a) = * (char **) ((char *) raw_a + elemsize*bucket->index[i] + keyoffset); -            return STBDS_ARR_TO_HASH(a,elemsize); -          } -        } else if (bucket->hash[i] == 0) { -          pos = (pos & ~STBDS_BUCKET_MASK) + i; -          goto found_empty_slot; -        } else if (tombstone < 0) { -          if (bucket->index[i] == STBDS_INDEX_DELETED) -            tombstone = (ptrdiff_t) ((pos & ~STBDS_BUCKET_MASK) + i); -        } -      } - -      // search from beginning of bucket to pos -      limit = pos & STBDS_BUCKET_MASK; -      for (i = 0; i < limit; ++i) { -        if (bucket->hash[i] == hash) { -          if (stbds_is_key_equal(raw_a, elemsize, key, keysize, keyoffset, mode, bucket->index[i])) { -            stbds_temp(a) = bucket->index[i]; -            return STBDS_ARR_TO_HASH(a,elemsize); -          } -        } else if (bucket->hash[i] == 0) { -          pos = (pos & ~STBDS_BUCKET_MASK) + i; -          goto found_empty_slot; -        } else if (tombstone < 0) { -          if (bucket->index[i] == STBDS_INDEX_DELETED) -            tombstone = (ptrdiff_t) ((pos & ~STBDS_BUCKET_MASK) + i); -        } -      } - -      // quadratic probing -      pos += step; -      step += STBDS_BUCKET_LENGTH; -      pos &= (table->slot_count-1); -    } -   found_empty_slot: -    if (tombstone >= 0) { -      pos = tombstone; -      --table->tombstone_count; -    } -    ++table->used_count; - -    { -      ptrdiff_t i = (ptrdiff_t) stbds_arrlen(a); -      // we want to do stbds_arraddn(1), but we can't use the macros since we don't have something of the right type -      if ((size_t) i+1 > stbds_arrcap(a)) -        *(void **) &a = stbds_arrgrowf(a, elemsize, 1, 0); -      raw_a = STBDS_ARR_TO_HASH(a,elemsize); - -      STBDS_ASSERT((size_t) i+1 <= stbds_arrcap(a)); -      stbds_header(a)->length = i+1; -      bucket = &table->storage[pos >> STBDS_BUCKET_SHIFT]; -      bucket->hash[pos & STBDS_BUCKET_MASK] = hash; -      bucket->index[pos & STBDS_BUCKET_MASK] = i-1; -      stbds_temp(a) = i-1; - -      switch (table->string.mode) { -         case STBDS_SH_STRDUP:  stbds_temp_key(a) = *(char **) ((char *) a + elemsize*i) = stbds_strdup((char*) key); break; -         case STBDS_SH_ARENA:   stbds_temp_key(a) = *(char **) ((char *) a + elemsize*i) = stbds_stralloc(&table->string, (char*)key); break; -         case STBDS_SH_DEFAULT: stbds_temp_key(a) = *(char **) ((char *) a + elemsize*i) = (char *) key; break; -         default:                memcpy((char *) a + elemsize*i, key, keysize); break; -      } -    } -    return STBDS_ARR_TO_HASH(a,elemsize); -  } -} - -void * stbds_shmode_func(size_t elemsize, int mode) -{ -  void *a = stbds_arrgrowf(0, elemsize, 0, 1); -  stbds_hash_index *h; -  memset(a, 0, elemsize); -  stbds_header(a)->length = 1; -  stbds_header(a)->hash_table = h = (stbds_hash_index *) stbds_make_hash_index(STBDS_BUCKET_LENGTH, NULL); -  h->string.mode = (unsigned char) mode; -  return STBDS_ARR_TO_HASH(a,elemsize); -} - -void * stbds_hmdel_key(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode) -{ -  if (a == NULL) { -    return 0; -  } else { -    stbds_hash_index *table; -    void *raw_a = STBDS_HASH_TO_ARR(a,elemsize); -    table = (stbds_hash_index *) stbds_header(raw_a)->hash_table; -    stbds_temp(raw_a) = 0; -    if (table == 0) { -      return a; -    } else { -      ptrdiff_t slot; -      slot = stbds_hm_find_slot(a, elemsize, key, keysize, keyoffset, mode); -      if (slot < 0) -        return a; -      else { -        stbds_hash_bucket *b = &table->storage[slot >> STBDS_BUCKET_SHIFT]; -        int i = slot & STBDS_BUCKET_MASK; -        ptrdiff_t old_index = b->index[i]; -        ptrdiff_t final_index = (ptrdiff_t) stbds_arrlen(raw_a)-1-1; // minus one for the raw_a vs a, and minus one for 'last' -        STBDS_ASSERT(slot < (ptrdiff_t) table->slot_count); -        --table->used_count; -        ++table->tombstone_count; -        stbds_temp(raw_a) = 1; -        STBDS_ASSERT(table->used_count >= 0); -        //STBDS_ASSERT(table->tombstone_count < table->slot_count/4); -        b->hash[i] = STBDS_HASH_DELETED; -        b->index[i] = STBDS_INDEX_DELETED; - -        if (mode == STBDS_HM_STRING && table->string.mode == STBDS_SH_STRDUP) -          STBDS_FREE(NULL, *(char**) ((char *) a+elemsize*old_index)); - -        // if indices are the same, memcpy is a no-op, but back-pointer-fixup will fail, so skip -        if (old_index != final_index) { -          // swap delete -          memmove((char*) a + elemsize*old_index, (char*) a + elemsize*final_index, elemsize); - -          // now find the slot for the last element -          if (mode == STBDS_HM_STRING) -            slot = stbds_hm_find_slot(a, elemsize, *(char**) ((char *) a+elemsize*old_index + keyoffset), keysize, keyoffset, mode); -          else -            slot = stbds_hm_find_slot(a, elemsize,  (char* ) a+elemsize*old_index + keyoffset, keysize, keyoffset, mode); -          STBDS_ASSERT(slot >= 0); -          b = &table->storage[slot >> STBDS_BUCKET_SHIFT]; -          i = slot & STBDS_BUCKET_MASK; -          STBDS_ASSERT(b->index[i] == final_index); -          b->index[i] = old_index; -        } -        stbds_header(raw_a)->length -= 1; - -        if (table->used_count < table->used_count_shrink_threshold && table->slot_count > STBDS_BUCKET_LENGTH) { -          stbds_header(raw_a)->hash_table = stbds_make_hash_index(table->slot_count>>1, table); -          STBDS_FREE(NULL, table); -          STBDS_STATS(++stbds_hash_shrink); -        } else if (table->tombstone_count > table->tombstone_count_threshold) { -          stbds_header(raw_a)->hash_table = stbds_make_hash_index(table->slot_count   , table); -          STBDS_FREE(NULL, table); -          STBDS_STATS(++stbds_hash_rebuild); -        } - -        return a; -      } -    } -  } -  /* NOTREACHED */ -} - -static char *stbds_strdup(char *str) -{ -  // to keep replaceable allocator simple, we don't want to use strdup. -  // rolling our own also avoids problem of strdup vs _strdup -  size_t len = strlen(str)+1; -  char *p = (char*) STBDS_REALLOC(NULL, 0, len); -  memmove(p, str, len); -  return p; -} - -#ifndef STBDS_STRING_ARENA_BLOCKSIZE_MIN -#define STBDS_STRING_ARENA_BLOCKSIZE_MIN  512u -#endif -#ifndef STBDS_STRING_ARENA_BLOCKSIZE_MAX -#define STBDS_STRING_ARENA_BLOCKSIZE_MAX  (1u<<20) -#endif - -char *stbds_stralloc(stbds_string_arena *a, char *str) -{ -  char *p; -  size_t len = strlen(str)+1; -  if (len > a->remaining) { -    // compute the next blocksize -    size_t blocksize = a->block; - -    // size is 512, 512, 1024, 1024, 2048, 2048, 4096, 4096, etc., so that -    // there are log(SIZE) allocations to free when we destroy the table -    blocksize = (size_t) (STBDS_STRING_ARENA_BLOCKSIZE_MIN) << (blocksize>>1); - -    // if size is under 1M, advance to next blocktype -    if (blocksize < (size_t)(STBDS_STRING_ARENA_BLOCKSIZE_MAX)) -      ++a->block; - -    if (len > blocksize) { -      // if string is larger than blocksize, then just allocate the full size. -      // note that we still advance string_block so block size will continue -      // increasing, so e.g. if somebody only calls this with 1000-long strings, -      // eventually the arena will start doubling and handling those as well -      stbds_string_block *sb = (stbds_string_block *) STBDS_REALLOC(NULL, 0, sizeof(*sb)-8 + len); -      memmove(sb->storage, str, len); -      if (a->storage) { -        // insert it after the first element, so that we don't waste the space there -        sb->next = a->storage->next; -        a->storage->next = sb; -      } else { -        sb->next = 0; -        a->storage = sb; -        a->remaining = 0; // this is redundant, but good for clarity -      } -      return sb->storage; -    } else { -      stbds_string_block *sb = (stbds_string_block *) STBDS_REALLOC(NULL, 0, sizeof(*sb)-8 + blocksize); -      sb->next = a->storage; -      a->storage = sb; -      a->remaining = blocksize; -    } -  } - -  STBDS_ASSERT(len <= a->remaining); -  p = a->storage->storage + a->remaining - len; -  a->remaining -= len; -  memmove(p, str, len); -  return p; -} - -void stbds_strreset(stbds_string_arena *a) -{ -  stbds_string_block *x,*y; -  x = a->storage; -  while (x) { -    y = x->next; -    STBDS_FREE(NULL, x); -    x = y; -  } -  memset(a, 0, sizeof(*a)); -} - -#endif - -////////////////////////////////////////////////////////////////////////////// -// -//   UNIT TESTS -// - -#ifdef STBDS_UNIT_TESTS -#include <stdio.h> -#ifdef STBDS_ASSERT_WAS_UNDEFINED -#undef STBDS_ASSERT -#endif -#ifndef STBDS_ASSERT -#define STBDS_ASSERT assert -#include <assert.h> -#endif - -typedef struct { int key,b,c,d; } stbds_struct; -typedef struct { int key[2],b,c,d; } stbds_struct2; - -static char buffer[256]; -char *strkey(int n) -{ -#if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__) -   sprintf_s(buffer, sizeof(buffer), "test_%d", n); -#else -   sprintf(buffer, "test_%d", n); -#endif -   return buffer; -} - -void stbds_unit_tests(void) -{ -#if defined(_MSC_VER) && _MSC_VER <= 1200 && defined(__cplusplus) -  // VC6 C++ doesn't like the template<> trick on unnamed structures, so do nothing! -  STBDS_ASSERT(0); -#else -  const int testsize = 100000; -  const int testsize2 = testsize/20; -  int *arr=NULL; -  struct { int   key;        int value; }  *intmap  = NULL; -  struct { char *key;        int value; }  *strmap  = NULL, s; -  struct { stbds_struct key; int value; }  *map     = NULL; -  stbds_struct                             *map2    = NULL; -  stbds_struct2                            *map3    = NULL; -  stbds_string_arena                        sa      = { 0 }; -  int key3[2] = { 1,2 }; -  ptrdiff_t temp; - -  int i,j; - -  STBDS_ASSERT(arrlen(arr)==0); -  for (i=0; i < 20000; i += 50) { -    for (j=0; j < i; ++j) -      arrpush(arr,j); -    arrfree(arr); -  } - -  for (i=0; i < 4; ++i) { -    arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4); -    arrdel(arr,i); -    arrfree(arr); -    arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4); -    arrdelswap(arr,i); -    arrfree(arr); -  } - -  for (i=0; i < 5; ++i) { -    arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4); -    stbds_arrins(arr,i,5); -    STBDS_ASSERT(arr[i] == 5); -    if (i < 4) -      STBDS_ASSERT(arr[4] == 4); -    arrfree(arr); -  } - -  i = 1; -  STBDS_ASSERT(hmgeti(intmap,i) == -1); -  hmdefault(intmap, -2); -  STBDS_ASSERT(hmgeti(intmap, i) == -1); -  STBDS_ASSERT(hmget (intmap, i) == -2); -  for (i=0; i < testsize; i+=2) -    hmput(intmap, i, i*5); -  for (i=0; i < testsize; i+=1) { -    if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -2 ); -    else       STBDS_ASSERT(hmget(intmap, i) == i*5); -    if (i & 1) STBDS_ASSERT(hmget_ts(intmap, i, temp) == -2 ); -    else       STBDS_ASSERT(hmget_ts(intmap, i, temp) == i*5); -  } -  for (i=0; i < testsize; i+=2) -    hmput(intmap, i, i*3); -  for (i=0; i < testsize; i+=1) -    if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -2 ); -    else       STBDS_ASSERT(hmget(intmap, i) == i*3); -  for (i=2; i < testsize; i+=4) -    hmdel(intmap, i); // delete half the entries -  for (i=0; i < testsize; i+=1) -    if (i & 3) STBDS_ASSERT(hmget(intmap, i) == -2 ); -    else       STBDS_ASSERT(hmget(intmap, i) == i*3); -  for (i=0; i < testsize; i+=1) -    hmdel(intmap, i); // delete the rest of the entries -  for (i=0; i < testsize; i+=1) -    STBDS_ASSERT(hmget(intmap, i) == -2 ); -  hmfree(intmap); -  for (i=0; i < testsize; i+=2) -    hmput(intmap, i, i*3); -  hmfree(intmap); - -  #if defined(__clang__) || defined(__GNUC__) -  #ifndef __cplusplus -  intmap = NULL; -  hmput(intmap, 15, 7); -  hmput(intmap, 11, 3); -  hmput(intmap,  9, 5); -  STBDS_ASSERT(hmget(intmap, 9) == 5); -  STBDS_ASSERT(hmget(intmap, 11) == 3); -  STBDS_ASSERT(hmget(intmap, 15) == 7); -  #endif -  #endif - -  for (i=0; i < testsize; ++i) -    stralloc(&sa, strkey(i)); -  strreset(&sa); - -  { -    s.key = "a", s.value = 1; -    shputs(strmap, s); -    STBDS_ASSERT(*strmap[0].key == 'a'); -    STBDS_ASSERT(strmap[0].key == s.key); -    STBDS_ASSERT(strmap[0].value == s.value); -    shfree(strmap); -  } - -  { -    s.key = "a", s.value = 1; -    sh_new_strdup(strmap); -    shputs(strmap, s); -    STBDS_ASSERT(*strmap[0].key == 'a'); -    STBDS_ASSERT(strmap[0].key != s.key); -    STBDS_ASSERT(strmap[0].value == s.value); -    shfree(strmap); -  } - -  { -    s.key = "a", s.value = 1; -    sh_new_arena(strmap); -    shputs(strmap, s); -    STBDS_ASSERT(*strmap[0].key == 'a'); -    STBDS_ASSERT(strmap[0].key != s.key); -    STBDS_ASSERT(strmap[0].value == s.value); -    shfree(strmap); -  } - -  for (j=0; j < 2; ++j) { -    STBDS_ASSERT(shgeti(strmap,"foo") == -1); -    if (j == 0) -      sh_new_strdup(strmap); -    else -      sh_new_arena(strmap); -    STBDS_ASSERT(shgeti(strmap,"foo") == -1); -    shdefault(strmap, -2); -    STBDS_ASSERT(shgeti(strmap,"foo") == -1); -    for (i=0; i < testsize; i+=2) -      shput(strmap, strkey(i), i*3); -    for (i=0; i < testsize; i+=1) -      if (i & 1) STBDS_ASSERT(shget(strmap, strkey(i)) == -2 ); -      else       STBDS_ASSERT(shget(strmap, strkey(i)) == i*3); -    for (i=2; i < testsize; i+=4) -      shdel(strmap, strkey(i)); // delete half the entries -    for (i=0; i < testsize; i+=1) -      if (i & 3) STBDS_ASSERT(shget(strmap, strkey(i)) == -2 ); -      else       STBDS_ASSERT(shget(strmap, strkey(i)) == i*3); -    for (i=0; i < testsize; i+=1) -      shdel(strmap, strkey(i)); // delete the rest of the entries -    for (i=0; i < testsize; i+=1) -      STBDS_ASSERT(shget(strmap, strkey(i)) == -2 ); -    shfree(strmap); -  } - -  { -    struct { char *key; char value; } *hash = NULL; -    char name[4] = "jen"; -    shput(hash, "bob"   , 'h'); -    shput(hash, "sally" , 'e'); -    shput(hash, "fred"  , 'l'); -    shput(hash, "jen"   , 'x'); -    shput(hash, "doug"  , 'o'); - -    shput(hash, name    , 'l'); -    shfree(hash); -  } - -  for (i=0; i < testsize; i += 2) { -    stbds_struct s = { i,i*2,i*3,i*4 }; -    hmput(map, s, i*5); -  } - -  for (i=0; i < testsize; i += 1) { -    stbds_struct s = { i,i*2,i*3  ,i*4 }; -    stbds_struct t = { i,i*2,i*3+1,i*4 }; -    if (i & 1) STBDS_ASSERT(hmget(map, s) == 0); -    else       STBDS_ASSERT(hmget(map, s) == i*5); -    if (i & 1) STBDS_ASSERT(hmget_ts(map, s, temp) == 0); -    else       STBDS_ASSERT(hmget_ts(map, s, temp) == i*5); -    //STBDS_ASSERT(hmget(map, t.key) == 0); -  } - -  for (i=0; i < testsize; i += 2) { -    stbds_struct s = { i,i*2,i*3,i*4 }; -    hmputs(map2, s); -  } -  hmfree(map); - -  for (i=0; i < testsize; i += 1) { -    stbds_struct s = { i,i*2,i*3,i*4 }; -    stbds_struct t = { i,i*2,i*3+1,i*4 }; -    if (i & 1) STBDS_ASSERT(hmgets(map2, s.key).d == 0); -    else       STBDS_ASSERT(hmgets(map2, s.key).d == i*4); -    //STBDS_ASSERT(hmgetp(map2, t.key) == 0); -  } -  hmfree(map2); - -  for (i=0; i < testsize; i += 2) { -    stbds_struct2 s = { { i,i*2 }, i*3,i*4, i*5 }; -    hmputs(map3, s); -  } -  for (i=0; i < testsize; i += 1) { -    stbds_struct2 s = { { i,i*2}, i*3, i*4, i*5 }; -    stbds_struct2 t = { { i,i*2}, i*3+1, i*4, i*5 }; -    if (i & 1) STBDS_ASSERT(hmgets(map3, s.key).d == 0); -    else       STBDS_ASSERT(hmgets(map3, s.key).d == i*5); -    //STBDS_ASSERT(hmgetp(map3, t.key) == 0); -  } -#endif -} -#endif - - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright (c) 2019 Sean Barrett -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain (www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/ diff --git a/CMakeLists.txt b/CMakeLists.txt index b22b369..87e68c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ option(KALMIA_BUILD_TESTS "Build the tests" ON)  option(KALMIA_BUILD_EXAMPLE "Build the example" ON)  add_library(kalmia STATIC) -target_include_directories(kalmia PUBLIC include 3rdparty 3rdparty/ezxml) +target_include_directories(kalmia PUBLIC include)  if (UNIX)  	set_target_properties(  		kalmia PROPERTIES @@ -34,4 +34,3 @@ if (KALMIA_BUILD_EXAMPLE)  endif()  add_subdirectory(src) -add_subdirectory(3rdparty/ezxml) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d0589ed..6ad8ede 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,6 @@  project(kalmia)  target_include_directories(kalmia PUBLIC ${CMAKE_CURRENT_LIST_DIR}) -target_link_libraries(kalmia ezxml)  if (KALMIA_BUILD_TESTS)  	target_sources( @@ -12,3 +11,4 @@ endif()  add_subdirectory(util)  add_subdirectory(geometry) +add_subdirectory(xml) diff --git a/src/geometry/geometry.c b/src/geometry/geometry.c index 7046f1e..ba1ca58 100644 --- a/src/geometry/geometry.c +++ b/src/geometry/geometry.c @@ -1,41 +1,5 @@  #include <string.h>  #include <kalmia.h> -#include <ezxml.h>  #include "util/util.h"  #include "geometry.h" - - -int kai_parse_float_array(struct ka_float_array_t *dest, ezxml_t src) -{ -	/* get count */ -	const char *count = ezxml_attr(src, "count"); -	if (count == NULL) { -		fprintf(stderr, "[kalmia] ERROR: required \"count\" parameter not present for float_array\n"); -		return -1; -	} -	char *end; -	dest->count = strtol(count, &end, 10); - -	/* get id, if present */ -	const char *id = ezxml_attr(src, "id"); -	if (id != NULL) { -		size_t id_len = strlen(id) + 1; -		dest->id = kai_alloc(sizeof(char) * id_len, "float_array id"); -		if (dest->id == NULL) { -			return -1; -		} -		strncpy(dest->id, id, id_len); -	} -	else { -		dest->id = NULL; -	} - -	/* parse floats */ -	dest->data = kai_alloc(sizeof(ka_real_t) * dest->count, "float_array data"); -	if (dest->data == NULL) { -		free(dest->id); -		return -1; -	} -	kai_text_to_reals(dest->data, ezxml_txt(src), dest->count); -} diff --git a/src/geometry/geometry.h b/src/geometry/geometry.h index 6268e3b..da089c1 100644 --- a/src/geometry/geometry.h +++ b/src/geometry/geometry.h @@ -2,8 +2,5 @@  #define KALMIA_GEOMETRY_H  #include <kalmia.h> -#include <ezxml.h> - -int kai_parse_float_array(struct ka_float_array_t *dest, ezxml_t src);  #endif diff --git a/src/geometry/geometry.test.c b/src/geometry/geometry.test.c index bb06aeb..fe4421e 100644 --- a/src/geometry/geometry.test.c +++ b/src/geometry/geometry.test.c @@ -1,7 +1,6 @@  #include <string.h>  #include <kalmia.h> -#include <ezxml.h>  #include "geometry.h"  #include "test/test.h" @@ -9,34 +8,5 @@  LILY_FILE_BEGIN(geometry_suite) -LILY_TEST("parse float array") -{ -	char str[1024]; -	strncpy( -		str, -		"<float_array id=\"sequence\" count=\"5\">\n" -		"	-0.5 -0.25 0 0.25 0.5\n" -		"</float_array>", -		1024 -	); - -	ezxml_t tag = ezxml_parse_str(str, strlen(str)+1); - -	struct ka_float_array_t float_array; -	kai_parse_float_array(&float_array, tag); - -	CHECK_EQS(float_array.id, "sequence"); -	REQUIRE_EQ(float_array.count, 5, "%ul"); -	REQUIRE_NEQ(float_array.data, NULL, "%p"); - -	CHECK_EQ(float_array.data[0], -0.50, "%f"); -	CHECK_EQ(float_array.data[1], -0.25, "%f"); -	CHECK_EQ(float_array.data[2],  0.00, "%f"); -	CHECK_EQ(float_array.data[3],  0.25, "%f"); -	CHECK_EQ(float_array.data[4],  0.50, "%f"); -} -#include LILY_PUSH_TEST() - -  #define LILY_FILE_END  #include LILY_REGISTER_TESTS() diff --git a/src/xml/CMakeLists.txt b/src/xml/CMakeLists.txt new file mode 100644 index 0000000..9790692 --- /dev/null +++ b/src/xml/CMakeLists.txt @@ -0,0 +1,7 @@ +project(kalmia) + +target_sources(kalmia PUBLIC  +	kalmia.tab.c +	kalmia.lex.c +	xml.c +) diff --git a/src/xml/kalmia.lex.c b/src/xml/kalmia.lex.c new file mode 100644 index 0000000..1862064 --- /dev/null +++ b/src/xml/kalmia.lex.c @@ -0,0 +1,2343 @@ +#line 1 "kalmia.lex.c" + +#line 3 "kalmia.lex.c" + +#define  YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +#ifdef yy_create_buffer +#define kalmia_create_buffer_ALREADY_DEFINED +#else +#define yy_create_buffer kalmia_create_buffer +#endif + +#ifdef yy_delete_buffer +#define kalmia_delete_buffer_ALREADY_DEFINED +#else +#define yy_delete_buffer kalmia_delete_buffer +#endif + +#ifdef yy_scan_buffer +#define kalmia_scan_buffer_ALREADY_DEFINED +#else +#define yy_scan_buffer kalmia_scan_buffer +#endif + +#ifdef yy_scan_string +#define kalmia_scan_string_ALREADY_DEFINED +#else +#define yy_scan_string kalmia_scan_string +#endif + +#ifdef yy_scan_bytes +#define kalmia_scan_bytes_ALREADY_DEFINED +#else +#define yy_scan_bytes kalmia_scan_bytes +#endif + +#ifdef yy_init_buffer +#define kalmia_init_buffer_ALREADY_DEFINED +#else +#define yy_init_buffer kalmia_init_buffer +#endif + +#ifdef yy_flush_buffer +#define kalmia_flush_buffer_ALREADY_DEFINED +#else +#define yy_flush_buffer kalmia_flush_buffer +#endif + +#ifdef yy_load_buffer_state +#define kalmia_load_buffer_state_ALREADY_DEFINED +#else +#define yy_load_buffer_state kalmia_load_buffer_state +#endif + +#ifdef yy_switch_to_buffer +#define kalmia_switch_to_buffer_ALREADY_DEFINED +#else +#define yy_switch_to_buffer kalmia_switch_to_buffer +#endif + +#ifdef yypush_buffer_state +#define kalmiapush_buffer_state_ALREADY_DEFINED +#else +#define yypush_buffer_state kalmiapush_buffer_state +#endif + +#ifdef yypop_buffer_state +#define kalmiapop_buffer_state_ALREADY_DEFINED +#else +#define yypop_buffer_state kalmiapop_buffer_state +#endif + +#ifdef yyensure_buffer_stack +#define kalmiaensure_buffer_stack_ALREADY_DEFINED +#else +#define yyensure_buffer_stack kalmiaensure_buffer_stack +#endif + +#ifdef yylex +#define kalmialex_ALREADY_DEFINED +#else +#define yylex kalmialex +#endif + +#ifdef yyrestart +#define kalmiarestart_ALREADY_DEFINED +#else +#define yyrestart kalmiarestart +#endif + +#ifdef yylex_init +#define kalmialex_init_ALREADY_DEFINED +#else +#define yylex_init kalmialex_init +#endif + +#ifdef yylex_init_extra +#define kalmialex_init_extra_ALREADY_DEFINED +#else +#define yylex_init_extra kalmialex_init_extra +#endif + +#ifdef yylex_destroy +#define kalmialex_destroy_ALREADY_DEFINED +#else +#define yylex_destroy kalmialex_destroy +#endif + +#ifdef yyget_debug +#define kalmiaget_debug_ALREADY_DEFINED +#else +#define yyget_debug kalmiaget_debug +#endif + +#ifdef yyset_debug +#define kalmiaset_debug_ALREADY_DEFINED +#else +#define yyset_debug kalmiaset_debug +#endif + +#ifdef yyget_extra +#define kalmiaget_extra_ALREADY_DEFINED +#else +#define yyget_extra kalmiaget_extra +#endif + +#ifdef yyset_extra +#define kalmiaset_extra_ALREADY_DEFINED +#else +#define yyset_extra kalmiaset_extra +#endif + +#ifdef yyget_in +#define kalmiaget_in_ALREADY_DEFINED +#else +#define yyget_in kalmiaget_in +#endif + +#ifdef yyset_in +#define kalmiaset_in_ALREADY_DEFINED +#else +#define yyset_in kalmiaset_in +#endif + +#ifdef yyget_out +#define kalmiaget_out_ALREADY_DEFINED +#else +#define yyget_out kalmiaget_out +#endif + +#ifdef yyset_out +#define kalmiaset_out_ALREADY_DEFINED +#else +#define yyset_out kalmiaset_out +#endif + +#ifdef yyget_leng +#define kalmiaget_leng_ALREADY_DEFINED +#else +#define yyget_leng kalmiaget_leng +#endif + +#ifdef yyget_text +#define kalmiaget_text_ALREADY_DEFINED +#else +#define yyget_text kalmiaget_text +#endif + +#ifdef yyget_lineno +#define kalmiaget_lineno_ALREADY_DEFINED +#else +#define yyget_lineno kalmiaget_lineno +#endif + +#ifdef yyset_lineno +#define kalmiaset_lineno_ALREADY_DEFINED +#else +#define yyset_lineno kalmiaset_lineno +#endif + +#ifdef yyget_column +#define kalmiaget_column_ALREADY_DEFINED +#else +#define yyget_column kalmiaget_column +#endif + +#ifdef yyset_column +#define kalmiaset_column_ALREADY_DEFINED +#else +#define yyset_column kalmiaset_column +#endif + +#ifdef yywrap +#define kalmiawrap_ALREADY_DEFINED +#else +#define yywrap kalmiawrap +#endif + +#ifdef yyget_lval +#define kalmiaget_lval_ALREADY_DEFINED +#else +#define yyget_lval kalmiaget_lval +#endif + +#ifdef yyset_lval +#define kalmiaset_lval_ALREADY_DEFINED +#else +#define yyset_lval kalmiaset_lval +#endif + +#ifdef yyget_lloc +#define kalmiaget_lloc_ALREADY_DEFINED +#else +#define yyget_lloc kalmiaget_lloc +#endif + +#ifdef yyset_lloc +#define kalmiaset_lloc_ALREADY_DEFINED +#else +#define yyset_lloc kalmiaset_lloc +#endif + +#ifdef yyalloc +#define kalmiaalloc_ALREADY_DEFINED +#else +#define yyalloc kalmiaalloc +#endif + +#ifdef yyrealloc +#define kalmiarealloc_ALREADY_DEFINED +#else +#define yyrealloc kalmiarealloc +#endif + +#ifdef yyfree +#define kalmiafree_ALREADY_DEFINED +#else +#define yyfree kalmiafree +#endif + +/* First, we deal with  platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types.  + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t;  +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN               (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN              (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN              (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX               (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX              (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX              (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX              (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX             (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX             (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX               (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* begin standard C++ headers. */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an + *   integer in range [0..255] for use as an array index. + */ +#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) +   are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Enter a start condition.  This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yyg->yy_start = 1 + 2 * +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state.  The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yyg->yy_start - 1) / 2) +#define YYSTATE YY_START +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin , yyscanner ) +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 +     +    #define YY_LESS_LINENO(n) +    #define YY_LINENO_REWIND_TO(ptr) +     +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ +	do \ +		{ \ +		/* Undo effects of setting up yytext. */ \ +        int yyless_macro_arg = (n); \ +        YY_LESS_LINENO(yyless_macro_arg);\ +		*yy_cp = yyg->yy_hold_char; \ +		YY_RESTORE_YY_MORE_OFFSET \ +		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ +		YY_DO_BEFORE_ACTION; /* set up yytext again */ \ +		} \ +	while ( 0 ) +#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state +	{ +	FILE *yy_input_file; + +	char *yy_ch_buf;		/* input buffer */ +	char *yy_buf_pos;		/* current position in input buffer */ + +	/* Size of input buffer in bytes, not including room for EOB +	 * characters. +	 */ +	int yy_buf_size; + +	/* Number of characters read into yy_ch_buf, not including EOB +	 * characters. +	 */ +	int yy_n_chars; + +	/* Whether we "own" the buffer - i.e., we know we created it, +	 * and can realloc() it to grow it, and should free() it to +	 * delete it. +	 */ +	int yy_is_our_buffer; + +	/* Whether this is an "interactive" input source; if so, and +	 * if we're using stdio for input, then we want to use getc() +	 * instead of fread(), to make sure we stop fetching input after +	 * each newline. +	 */ +	int yy_is_interactive; + +	/* Whether we're considered to be at the beginning of a line. +	 * If so, '^' rules will be active on the next match, otherwise +	 * not. +	 */ +	int yy_at_bol; + +    int yy_bs_lineno; /**< The line count. */ +    int yy_bs_column; /**< The column count. */ + +	/* Whether to try to fill the input buffer when we reach the +	 * end of it. +	 */ +	int yy_fill_buffer; + +	int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 +	/* When an EOF's been seen but there's still some text to process +	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we +	 * shouldn't try reading from the input source any more.  We might +	 * still have a bunch of tokens to match, though, because of +	 * possible backing-up. +	 * +	 * When we actually see the EOF, we change the status to "new" +	 * (via yyrestart()), so that the user can continue scanning by +	 * just pointing yyin at a new input file. +	 */ +#define YY_BUFFER_EOF_PENDING 2 + +	}; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ +                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ +                          : NULL) +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] + +void yyrestart ( FILE *input_file , yyscan_t yyscanner ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); +void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +void yypop_buffer_state ( yyscan_t yyscanner ); + +static void yyensure_buffer_stack ( yyscan_t yyscanner ); +static void yy_load_buffer_state ( yyscan_t yyscanner ); +static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner ); +#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner) + +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner ); + +void *yyalloc ( yy_size_t , yyscan_t yyscanner ); +void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); +void yyfree ( void * , yyscan_t yyscanner ); + +#define yy_new_buffer yy_create_buffer +#define yy_set_interactive(is_interactive) \ +	{ \ +	if ( ! YY_CURRENT_BUFFER ){ \ +        yyensure_buffer_stack (yyscanner); \ +		YY_CURRENT_BUFFER_LVALUE =    \ +            yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ +	} \ +	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ +	} +#define yy_set_bol(at_bol) \ +	{ \ +	if ( ! YY_CURRENT_BUFFER ){\ +        yyensure_buffer_stack (yyscanner); \ +		YY_CURRENT_BUFFER_LVALUE =    \ +            yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ +	} \ +	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ +	} +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +#define kalmiawrap(yyscanner) (/*CONSTCOND*/1) +#define YY_SKIP_YYWRAP +typedef flex_uint8_t YY_CHAR; + +typedef int yy_state_type; + +#define yytext_ptr yytext_r + +static yy_state_type yy_get_previous_state ( yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans ( yy_state_type current_state  , yyscan_t yyscanner); +static int yy_get_next_buffer ( yyscan_t yyscanner ); +static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ +	yyg->yytext_ptr = yy_bp; \ +	yyleng = (int) (yy_cp - yy_bp); \ +	yyg->yy_hold_char = *yy_cp; \ +	*yy_cp = '\0'; \ +	yyg->yy_c_buf_p = yy_cp; +#define YY_NUM_RULES 15 +#define YY_END_OF_BUFFER 16 +/* This struct is not used in this scanner, +   but its presence is necessary. */ +struct yy_trans_info +	{ +	flex_int32_t yy_verify; +	flex_int32_t yy_nxt; +	}; +static const flex_int16_t yy_acclist[32] = +    {   0, +       16,   15,    2,   15,    4,   15,   13,   15,   12,   15, +       15,    3,   15,   11,   15,   15,    8,   15,16393,   10, +       15,    6,   15,   14,    5,   13,    7,    8,16393, 8201, +        1 +    } ; + +static const flex_int16_t yy_accept[37] = +    {   0, +        1,    1,    1,    1,    1,    1,    1,    2,    3,    5, +        7,    9,   11,   12,   14,   16,   17,   20,   22,   24, +       25,   25,   26,   26,   27,   28,   28,   30,   31,   31, +       31,   31,   31,   31,   32,   32 +    } ; + +static const YY_CHAR yy_ec[256] = +    {   0, +        1,    1,    1,    1,    1,    1,    1,    1,    2,    3, +        1,    1,    2,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    2,    1,    4,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    5,    5,    6,    5,    5,    5, +        5,    5,    5,    5,    5,    5,    5,    7,    1,    8, +        9,   10,   11,    1,    7,    7,    7,    7,    7,    7, +        7,    7,    7,    7,    7,    7,    7,    7,    7,    7, +        7,    7,    7,    7,    7,    7,    7,    7,    7,    7, +        1,    1,    1,    1,    7,    1,    7,    7,    7,    7, + +        7,    7,    7,    7,    7,    7,    7,   12,   13,    7, +        7,    7,    7,    7,    7,    7,    7,    7,    7,   14, +        7,    7,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, + +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1 +    } ; + +static const YY_CHAR yy_meta[15] = +    {   0, +        1,    2,    3,    4,    5,    1,    5,    6,    2,    1, +        1,    5,    5,    5 +    } ; + +static const flex_int16_t yy_base[43] = +    {   0, +        0,    7,   77,   73,   15,    0,   71,    2,   82,    0, +        0,   82,   82,   82,   82,   56,   28,   82,   82,   10, +       30,   82,   30,    0,   82,   34,   36,   82,   29,   29, +       29,   25,   24,    3,   82,   45,   51,   57,   62,   67, +       71,   74 +    } ; + +static const flex_int16_t yy_def[43] = +    {   0, +       36,   36,   37,   37,   35,    5,   35,   38,   35,   35, +       39,   35,   35,   35,   35,   35,   40,   35,   35,   38, +       38,   35,   35,   39,   35,   41,   40,   35,   35,   35, +       42,   42,   42,   42,    0,   35,   35,   35,   35,   35, +       35,   35 +    } ; + +static const flex_int16_t yy_nxt[97] = +    {   0, +       35,    9,    9,   21,   21,   22,   35,   10,    9,    9, +       23,   21,   21,   33,   10,   13,   14,   14,   15,   13, +       16,   17,   13,   18,   19,   13,   17,   17,   17,   26, +       26,   21,   21,   34,   33,   33,   28,   26,   26,   33, +       31,   30,   28,   29,   28,    8,    8,    8,    8,    8, +        8,   11,   11,   11,   11,   11,   11,   20,   20,   20, +       20,   20,   24,   24,   24,   25,   24,   24,   27,   27, +       35,   27,   26,   26,   32,   32,   12,   32,   32,   32, +       12,    7,   35,   35,   35,   35,   35,   35,   35,   35, +       35,   35,   35,   35,   35,   35 + +    } ; + +static const flex_int16_t yy_chk[97] = +    {   0, +        0,    1,    1,    8,    8,   10,    0,    1,    2,    2, +       10,   20,   20,   34,    2,    5,    5,    5,    5,    5, +        5,    5,    5,    5,    5,    5,    5,    5,    5,   17, +       17,   21,   21,   33,   33,   32,   17,   27,   27,   31, +       30,   29,   26,   23,   27,   36,   36,   36,   36,   36, +       36,   37,   37,   37,   37,   37,   37,   38,   38,   38, +       38,   38,   39,   39,   39,   16,   39,   39,   40,   40, +        7,   40,   41,   41,   42,   42,    4,   42,   42,   42, +        3,   35,   35,   35,   35,   35,   35,   35,   35,   35, +       35,   35,   35,   35,   35,   35 + +    } ; + +#define YY_TRAILING_MASK 0x2000 +#define YY_TRAILING_HEAD_MASK 0x4000 +#define REJECT \ +{ \ +*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */ \ +yy_cp = yyg->yy_full_match; /* restore poss. backed-over text */ \ +yyg->yy_lp = yyg->yy_full_lp; /* restore orig. accepting pos. */ \ +yyg->yy_state_ptr = yyg->yy_full_state; /* restore orig. state */ \ +yy_current_state = *yyg->yy_state_ptr; /* restore curr. state */ \ +++yyg->yy_lp; \ +goto find_rule; \ +} + +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +#line 1 "kalmia.l" +#define YY_NO_INPUT 1 + +#line 7 "kalmia.l" +#include <string.h> +#define YYLTYPE KALMIALTYPE +#define YYSTYPE KALMIASTYPE +#include "kalmia.tab.h" +#define YY_USER_ACTION \ +	yylloc->first_line = yylloc->last_line; \ +	yylloc->first_column = yylloc->last_column; \ +	if (*yytext == '\n') { \ +		yylloc->last_line += 1; \ +		yylloc->last_column = 0; \ +	} \ +	else { \ +		yylloc->last_column += yyleng; \ +	} +#line 719 "kalmia.lex.c" +#line 720 "kalmia.lex.c" + +#define INITIAL 0 +#define STRING 1 +#define TAG 2 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include <unistd.h> +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* Holds the entire state of the reentrant scanner. */ +struct yyguts_t +    { + +    /* User-defined. Not touched by flex. */ +    YY_EXTRA_TYPE yyextra_r; + +    /* The rest are the same as the globals declared in the non-reentrant scanner. */ +    FILE *yyin_r, *yyout_r; +    size_t yy_buffer_stack_top; /**< index of top of stack. */ +    size_t yy_buffer_stack_max; /**< capacity of stack. */ +    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ +    char yy_hold_char; +    int yy_n_chars; +    int yyleng_r; +    char *yy_c_buf_p; +    int yy_init; +    int yy_start; +    int yy_did_buffer_switch_on_eof; +    int yy_start_stack_ptr; +    int yy_start_stack_depth; +    int *yy_start_stack; +    yy_state_type yy_last_accepting_state; +    char* yy_last_accepting_cpos; + +    int yylineno_r; +    int yy_flex_debug_r; + +    yy_state_type *yy_state_buf; +    yy_state_type *yy_state_ptr; +    char *yy_full_match; +    int yy_lp; + +    /* These are only needed for trailing context rules, +     * but there's no conditional variable for that yet. */ +    int yy_looking_for_trail_begin; +    int yy_full_lp; +    int *yy_full_state; + +    char *yytext_r; +    int yy_more_flag; +    int yy_more_len; + +    YYSTYPE * yylval_r; + +    YYLTYPE * yylloc_r; + +    }; /* end struct yyguts_t */ + +static int yy_init_globals ( yyscan_t yyscanner ); + +    /* This must go here because YYSTYPE and YYLTYPE are included +     * from bison output in section 1.*/ +    #    define yylval yyg->yylval_r +     +    #    define yylloc yyg->yylloc_r +     +int yylex_init (yyscan_t* scanner); + +int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); + +/* Accessor methods to globals. +   These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy ( yyscan_t yyscanner ); + +int yyget_debug ( yyscan_t yyscanner ); + +void yyset_debug ( int debug_flag , yyscan_t yyscanner ); + +YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); + +void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); + +FILE *yyget_in ( yyscan_t yyscanner ); + +void yyset_in  ( FILE * _in_str , yyscan_t yyscanner ); + +FILE *yyget_out ( yyscan_t yyscanner ); + +void yyset_out  ( FILE * _out_str , yyscan_t yyscanner ); + +			int yyget_leng ( yyscan_t yyscanner ); + +char *yyget_text ( yyscan_t yyscanner ); + +int yyget_lineno ( yyscan_t yyscanner ); + +void yyset_lineno ( int _line_number , yyscan_t yyscanner ); + +int yyget_column  ( yyscan_t yyscanner ); + +void yyset_column ( int _column_no , yyscan_t yyscanner ); + +YYSTYPE * yyget_lval ( yyscan_t yyscanner ); + +void yyset_lval ( YYSTYPE * yylval_param , yyscan_t yyscanner ); + +       YYLTYPE *yyget_lloc ( yyscan_t yyscanner ); +     +        void yyset_lloc ( YYLTYPE * yylloc_param , yyscan_t yyscanner ); +     +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap ( yyscan_t yyscanner ); +#else +extern int yywrap ( yyscan_t yyscanner ); +#endif +#endif + +#ifndef YY_NO_UNPUT +     +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen ( const char * , yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput ( yyscan_t yyscanner ); +#else +static int input ( yyscan_t yyscanner ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ +	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ +		{ \ +		int c = '*'; \ +		int n; \ +		for ( n = 0; n < max_size && \ +			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ +			buf[n] = (char) c; \ +		if ( c == '\n' ) \ +			buf[n++] = (char) c; \ +		if ( c == EOF && ferror( yyin ) ) \ +			YY_FATAL_ERROR( "input in flex scanner failed" ); \ +		result = n; \ +		} \ +	else \ +		{ \ +		errno=0; \ +		while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ +			{ \ +			if( errno != EINTR) \ +				{ \ +				YY_FATAL_ERROR( "input in flex scanner failed" ); \ +				break; \ +				} \ +			errno=0; \ +			clearerr(yyin); \ +			} \ +		}\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex \ +               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner); + +#define YY_DECL int yylex \ +               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK /*LINTED*/break; +#endif + +#define YY_RULE_SETUP \ +	YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ +	yy_state_type yy_current_state; +	char *yy_cp, *yy_bp; +	int yy_act; +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +    yylval = yylval_param; + +    yylloc = yylloc_param; + +	if ( !yyg->yy_init ) +		{ +		yyg->yy_init = 1; + +#ifdef YY_USER_INIT +		YY_USER_INIT; +#endif + +        /* Create the reject buffer large enough to save one state per allowed character. */ +        if ( ! yyg->yy_state_buf ) +            yyg->yy_state_buf = (yy_state_type *)yyalloc(YY_STATE_BUF_SIZE  , yyscanner); +            if ( ! yyg->yy_state_buf ) +                YY_FATAL_ERROR( "out of dynamic memory in yylex()" ); + +		if ( ! yyg->yy_start ) +			yyg->yy_start = 1;	/* first start state */ + +		if ( ! yyin ) +			yyin = stdin; + +		if ( ! yyout ) +			yyout = stdout; + +		if ( ! YY_CURRENT_BUFFER ) { +			yyensure_buffer_stack (yyscanner); +			YY_CURRENT_BUFFER_LVALUE = +				yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); +		} + +		yy_load_buffer_state( yyscanner ); +		} + +	{ +#line 29 "kalmia.l" + + + +#line 1025 "kalmia.lex.c" + +	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */ +		{ +		yy_cp = yyg->yy_c_buf_p; + +		/* Support of yytext. */ +		*yy_cp = yyg->yy_hold_char; + +		/* yy_bp points to the position in yy_ch_buf of the start of +		 * the current run. +		 */ +		yy_bp = yy_cp; + +		yy_current_state = yyg->yy_start; + +		yyg->yy_state_ptr = yyg->yy_state_buf; +		*yyg->yy_state_ptr++ = yy_current_state; + +yy_match: +		do +			{ +			YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; +			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) +				{ +				yy_current_state = (int) yy_def[yy_current_state]; +				if ( yy_current_state >= 36 ) +					yy_c = yy_meta[yy_c]; +				} +			yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; +			*yyg->yy_state_ptr++ = yy_current_state; +			++yy_cp; +			} +		while ( yy_base[yy_current_state] != 82 ); + +yy_find_action: +		yy_current_state = *--yyg->yy_state_ptr; +		yyg->yy_lp = yy_accept[yy_current_state]; +find_rule: /* we branch to this label when backing up */ +		for ( ; ; ) /* until we find what rule we matched */ +			{ +			if ( yyg->yy_lp && yyg->yy_lp < yy_accept[yy_current_state + 1] ) +				{ +				yy_act = yy_acclist[yyg->yy_lp]; +				if ( yy_act & YY_TRAILING_HEAD_MASK || +				     yyg->yy_looking_for_trail_begin ) +					{ +					if ( yy_act == yyg->yy_looking_for_trail_begin ) +						{ +						yyg->yy_looking_for_trail_begin = 0; +						yy_act &= ~YY_TRAILING_HEAD_MASK; +						break; +						} +					} +				else if ( yy_act & YY_TRAILING_MASK ) +					{ +					yyg->yy_looking_for_trail_begin = yy_act & ~YY_TRAILING_MASK; +					yyg->yy_looking_for_trail_begin |= YY_TRAILING_HEAD_MASK; +					} +				else +					{ +					yyg->yy_full_match = yy_cp; +					yyg->yy_full_state = yyg->yy_state_ptr; +					yyg->yy_full_lp = yyg->yy_lp; +					break; +					} +				++yyg->yy_lp; +				goto find_rule; +				} +			--yy_cp; +			yy_current_state = *--yyg->yy_state_ptr; +			yyg->yy_lp = yy_accept[yy_current_state]; +			} + +		YY_DO_BEFORE_ACTION; + +do_action:	/* This label is used only to access EOF actions. */ + +		switch ( yy_act ) +	{ /* beginning of action switch */ +case 1: +YY_RULE_SETUP +#line 32 "kalmia.l" +{ +	/* xml prologue */ +	return PROLOG; +} +	YY_BREAK +case 2: +/* rule 2 can match eol */ +#line 37 "kalmia.l" +case 3: +/* rule 3 can match eol */ +YY_RULE_SETUP +#line 37 "kalmia.l" +{ +	/* ignore whitespace */ +} +	YY_BREAK +case 4: +YY_RULE_SETUP +#line 42 "kalmia.l" +{ BEGIN(TAG);     return S_TAG_OPEN; } +	YY_BREAK +case 5: +YY_RULE_SETUP +#line 43 "kalmia.l" +{ BEGIN(TAG);     return E_TAG_OPEN; } +	YY_BREAK +case 6: +YY_RULE_SETUP +#line 44 "kalmia.l" +{ BEGIN(INITIAL); return TAG_CLOSE; } +	YY_BREAK +case 7: +YY_RULE_SETUP +#line 45 "kalmia.l" +{ BEGIN(INITIAL); return EMPTY_TAG_CLOSE; } +	YY_BREAK +case 8: +YY_RULE_SETUP +#line 48 "kalmia.l" +{  +	/* generic tag name */ +	yylval->string = strdup(yytext);  +	return NAME;  +} +	YY_BREAK +case 9: +/* rule 9 can match eol */ +YY_RULE_SETUP +#line 53 "kalmia.l" +{ +	/* generic attribute key */ +	yylval->string = strdup(yytext); +	return ATTR; +} +	YY_BREAK +case 10: +YY_RULE_SETUP +#line 58 "kalmia.l" +{ +	/* attribute "=" */ +	return *yytext; +} +	YY_BREAK +case 11: +YY_RULE_SETUP +#line 64 "kalmia.l" +{  +	/* begin a string */ +	BEGIN(STRING); +	return *yytext; +} +	YY_BREAK +case 12: +YY_RULE_SETUP +#line 69 "kalmia.l" +{ +	/* end a string */ +	BEGIN(TAG); +	return *yytext; +} +	YY_BREAK +case 13: +/* rule 13 can match eol */ +YY_RULE_SETUP +#line 74 "kalmia.l" +{ +	/* within a string */ +	yylval->string = strdup(yytext); +	return TEXT; +} +	YY_BREAK +case 14: +/* rule 14 can match eol */ +YY_RULE_SETUP +#line 81 "kalmia.l" +{  +	yylval->string = strdup(yytext); +	return CONTENT; +} +	YY_BREAK +case 15: +YY_RULE_SETUP +#line 85 "kalmia.l" +YY_FATAL_ERROR( "flex scanner jammed" ); +	YY_BREAK +#line 1213 "kalmia.lex.c" +			case YY_STATE_EOF(INITIAL): +			case YY_STATE_EOF(STRING): +			case YY_STATE_EOF(TAG): +				yyterminate(); + +	case YY_END_OF_BUFFER: +		{ +		/* Amount of text matched not including the EOB char. */ +		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; + +		/* Undo the effects of YY_DO_BEFORE_ACTION. */ +		*yy_cp = yyg->yy_hold_char; +		YY_RESTORE_YY_MORE_OFFSET + +		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) +			{ +			/* We're scanning a new file or input source.  It's +			 * possible that this happened because the user +			 * just pointed yyin at a new source and called +			 * yylex().  If so, then we have to assure +			 * consistency between YY_CURRENT_BUFFER and our +			 * globals.  Here is the right place to do so, because +			 * this is the first action (other than possibly a +			 * back-up) that will match for the new input source. +			 */ +			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; +			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; +			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; +			} + +		/* Note that here we test for yy_c_buf_p "<=" to the position +		 * of the first EOB in the buffer, since yy_c_buf_p will +		 * already have been incremented past the NUL character +		 * (since all states make transitions on EOB to the +		 * end-of-buffer state).  Contrast this with the test +		 * in input(). +		 */ +		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) +			{ /* This was really a NUL. */ +			yy_state_type yy_next_state; + +			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + +			yy_current_state = yy_get_previous_state( yyscanner ); + +			/* Okay, we're now positioned to make the NUL +			 * transition.  We couldn't have +			 * yy_get_previous_state() go ahead and do it +			 * for us because it doesn't know how to deal +			 * with the possibility of jamming (and we don't +			 * want to build jamming into it because then it +			 * will run more slowly). +			 */ + +			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); + +			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + +			if ( yy_next_state ) +				{ +				/* Consume the NUL. */ +				yy_cp = ++yyg->yy_c_buf_p; +				yy_current_state = yy_next_state; +				goto yy_match; +				} + +			else +				{ +				yy_cp = yyg->yy_c_buf_p; +				goto yy_find_action; +				} +			} + +		else switch ( yy_get_next_buffer( yyscanner ) ) +			{ +			case EOB_ACT_END_OF_FILE: +				{ +				yyg->yy_did_buffer_switch_on_eof = 0; + +				if ( yywrap( yyscanner ) ) +					{ +					/* Note: because we've taken care in +					 * yy_get_next_buffer() to have set up +					 * yytext, we can now set up +					 * yy_c_buf_p so that if some total +					 * hoser (like flex itself) wants to +					 * call the scanner after we return the +					 * YY_NULL, it'll still work - another +					 * YY_NULL will get returned. +					 */ +					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + +					yy_act = YY_STATE_EOF(YY_START); +					goto do_action; +					} + +				else +					{ +					if ( ! yyg->yy_did_buffer_switch_on_eof ) +						YY_NEW_FILE; +					} +				break; +				} + +			case EOB_ACT_CONTINUE_SCAN: +				yyg->yy_c_buf_p = +					yyg->yytext_ptr + yy_amount_of_matched_text; + +				yy_current_state = yy_get_previous_state( yyscanner ); + +				yy_cp = yyg->yy_c_buf_p; +				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; +				goto yy_match; + +			case EOB_ACT_LAST_MATCH: +				yyg->yy_c_buf_p = +				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + +				yy_current_state = yy_get_previous_state( yyscanner ); + +				yy_cp = yyg->yy_c_buf_p; +				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; +				goto yy_find_action; +			} +		break; +		} + +	default: +		YY_FATAL_ERROR( +			"fatal flex scanner internal error--no action found" ); +	} /* end of action switch */ +		} /* end of scanning one token */ +	} /* end of user's declarations */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + *	EOB_ACT_LAST_MATCH - + *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position + *	EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +	char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; +	char *source = yyg->yytext_ptr; +	int number_to_move, i; +	int ret_val; + +	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) +		YY_FATAL_ERROR( +		"fatal flex scanner internal error--end of buffer missed" ); + +	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) +		{ /* Don't try to fill the buffer, so this is an EOF. */ +		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) +			{ +			/* We matched a single character, the EOB, so +			 * treat this as a final EOF. +			 */ +			return EOB_ACT_END_OF_FILE; +			} + +		else +			{ +			/* We matched some text prior to the EOB, first +			 * process it. +			 */ +			return EOB_ACT_LAST_MATCH; +			} +		} + +	/* Try to read more data. */ + +	/* First move last chars to start of buffer. */ +	number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1); + +	for ( i = 0; i < number_to_move; ++i ) +		*(dest++) = *(source++); + +	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) +		/* don't do the read, it's not guaranteed to return an EOF, +		 * just force an EOF +		 */ +		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + +	else +		{ +			int num_to_read = +			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + +		while ( num_to_read <= 0 ) +			{ /* Not enough room in the buffer - grow it. */ + +			YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); + +			} + +		if ( num_to_read > YY_READ_BUF_SIZE ) +			num_to_read = YY_READ_BUF_SIZE; + +		/* Read in more data. */ +		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), +			yyg->yy_n_chars, num_to_read ); + +		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; +		} + +	if ( yyg->yy_n_chars == 0 ) +		{ +		if ( number_to_move == YY_MORE_ADJ ) +			{ +			ret_val = EOB_ACT_END_OF_FILE; +			yyrestart( yyin  , yyscanner); +			} + +		else +			{ +			ret_val = EOB_ACT_LAST_MATCH; +			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = +				YY_BUFFER_EOF_PENDING; +			} +		} + +	else +		ret_val = EOB_ACT_CONTINUE_SCAN; + +	if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { +		/* Extend the array by 50%, plus the number we really need. */ +		int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); +		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( +			(void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner ); +		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) +			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); +		/* "- 2" to take care of EOB's */ +		YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); +	} + +	yyg->yy_n_chars += number_to_move; +	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; +	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + +	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + +	return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +    static yy_state_type yy_get_previous_state (yyscan_t yyscanner) +{ +	yy_state_type yy_current_state; +	char *yy_cp; +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +	yy_current_state = yyg->yy_start; + +	yyg->yy_state_ptr = yyg->yy_state_buf; +	*yyg->yy_state_ptr++ = yy_current_state; + +	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) +		{ +		YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); +		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) +			{ +			yy_current_state = (int) yy_def[yy_current_state]; +			if ( yy_current_state >= 36 ) +				yy_c = yy_meta[yy_c]; +			} +		yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; +		*yyg->yy_state_ptr++ = yy_current_state; +		} + +	return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + *	next_state = yy_try_NUL_trans( current_state ); + */ +    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner) +{ +	int yy_is_jam; +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ + +	YY_CHAR yy_c = 1; +	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) +		{ +		yy_current_state = (int) yy_def[yy_current_state]; +		if ( yy_current_state >= 36 ) +			yy_c = yy_meta[yy_c]; +		} +	yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; +	yy_is_jam = (yy_current_state == 35); +	if ( ! yy_is_jam ) +		*yyg->yy_state_ptr++ = yy_current_state; + +	(void)yyg; +	return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +    static int yyinput (yyscan_t yyscanner) +#else +    static int input  (yyscan_t yyscanner) +#endif + +{ +	int c; +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +	*yyg->yy_c_buf_p = yyg->yy_hold_char; + +	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) +		{ +		/* yy_c_buf_p now points to the character we want to return. +		 * If this occurs *before* the EOB characters, then it's a +		 * valid NUL; if not, then we've hit the end of the buffer. +		 */ +		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) +			/* This was really a NUL. */ +			*yyg->yy_c_buf_p = '\0'; + +		else +			{ /* need more input */ +			int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr); +			++yyg->yy_c_buf_p; + +			switch ( yy_get_next_buffer( yyscanner ) ) +				{ +				case EOB_ACT_LAST_MATCH: +					/* This happens because yy_g_n_b() +					 * sees that we've accumulated a +					 * token and flags that we need to +					 * try matching the token before +					 * proceeding.  But for input(), +					 * there's no matching to consider. +					 * So convert the EOB_ACT_LAST_MATCH +					 * to EOB_ACT_END_OF_FILE. +					 */ + +					/* Reset buffer status. */ +					yyrestart( yyin , yyscanner); + +					/*FALLTHROUGH*/ + +				case EOB_ACT_END_OF_FILE: +					{ +					if ( yywrap( yyscanner ) ) +						return 0; + +					if ( ! yyg->yy_did_buffer_switch_on_eof ) +						YY_NEW_FILE; +#ifdef __cplusplus +					return yyinput(yyscanner); +#else +					return input(yyscanner); +#endif +					} + +				case EOB_ACT_CONTINUE_SCAN: +					yyg->yy_c_buf_p = yyg->yytext_ptr + offset; +					break; +				} +			} +		} + +	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */ +	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */ +	yyg->yy_hold_char = *++yyg->yy_c_buf_p; + +	return c; +} +#endif	/* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * @param yyscanner The scanner object. + * @note This function does not reset the start condition to @c INITIAL . + */ +    void yyrestart  (FILE * input_file , yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +	if ( ! YY_CURRENT_BUFFER ){ +        yyensure_buffer_stack (yyscanner); +		YY_CURRENT_BUFFER_LVALUE = +            yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); +	} + +	yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner); +	yy_load_buffer_state( yyscanner ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * @param yyscanner The scanner object. + */ +    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +	/* TODO. We should be able to replace this entire function body +	 * with +	 *		yypop_buffer_state(); +	 *		yypush_buffer_state(new_buffer); +     */ +	yyensure_buffer_stack (yyscanner); +	if ( YY_CURRENT_BUFFER == new_buffer ) +		return; + +	if ( YY_CURRENT_BUFFER ) +		{ +		/* Flush out information for old buffer. */ +		*yyg->yy_c_buf_p = yyg->yy_hold_char; +		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; +		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; +		} + +	YY_CURRENT_BUFFER_LVALUE = new_buffer; +	yy_load_buffer_state( yyscanner ); + +	/* We don't actually know whether we did this switch during +	 * EOF (yywrap()) processing, but the only time this flag +	 * is looked at is after yywrap() is called, so it's safe +	 * to go ahead and always set it. +	 */ +	yyg->yy_did_buffer_switch_on_eof = 1; +} + +static void yy_load_buffer_state  (yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; +	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; +	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; +	yyg->yy_hold_char = *yyg->yy_c_buf_p; +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * @param yyscanner The scanner object. + * @return the allocated buffer state. + */ +    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size , yyscan_t yyscanner) +{ +	YY_BUFFER_STATE b; +     +	b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); +	if ( ! b ) +		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + +	b->yy_buf_size = size; + +	/* yy_ch_buf has to be 2 characters longer than the size given because +	 * we need to put in 2 end-of-buffer characters. +	 */ +	b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); +	if ( ! b->yy_ch_buf ) +		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + +	b->yy_is_our_buffer = 1; + +	yy_init_buffer( b, file , yyscanner); + +	return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * @param yyscanner The scanner object. + */ +    void yy_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +	if ( ! b ) +		return; + +	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ +		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + +	if ( b->yy_is_our_buffer ) +		yyfree( (void *) b->yy_ch_buf , yyscanner ); + +	yyfree( (void *) b , yyscanner ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ +    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner) + +{ +	int oerrno = errno; +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +	yy_flush_buffer( b , yyscanner); + +	b->yy_input_file = file; +	b->yy_fill_buffer = 1; + +    /* If b is the current buffer, then yy_init_buffer was _probably_ +     * called from yyrestart() or through yy_get_next_buffer. +     * In that case, we don't want to reset the lineno or column. +     */ +    if (b != YY_CURRENT_BUFFER){ +        b->yy_bs_lineno = 1; +        b->yy_bs_column = 0; +    } + +        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +     +	errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * @param yyscanner The scanner object. + */ +    void yy_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +	if ( ! b ) +		return; + +	b->yy_n_chars = 0; + +	/* We always need two end-of-buffer characters.  The first causes +	 * a transition to the end-of-buffer state.  The second causes +	 * a jam in that state. +	 */ +	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; +	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + +	b->yy_buf_pos = &b->yy_ch_buf[0]; + +	b->yy_at_bol = 1; +	b->yy_buffer_status = YY_BUFFER_NEW; + +	if ( b == YY_CURRENT_BUFFER ) +		yy_load_buffer_state( yyscanner ); +} + +/** Pushes the new state onto the stack. The new state becomes + *  the current state. This function will allocate the stack + *  if necessary. + *  @param new_buffer The new state. + *  @param yyscanner The scanner object. + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +	if (new_buffer == NULL) +		return; + +	yyensure_buffer_stack(yyscanner); + +	/* This block is copied from yy_switch_to_buffer. */ +	if ( YY_CURRENT_BUFFER ) +		{ +		/* Flush out information for old buffer. */ +		*yyg->yy_c_buf_p = yyg->yy_hold_char; +		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; +		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; +		} + +	/* Only push if top exists. Otherwise, replace top. */ +	if (YY_CURRENT_BUFFER) +		yyg->yy_buffer_stack_top++; +	YY_CURRENT_BUFFER_LVALUE = new_buffer; + +	/* copied from yy_switch_to_buffer. */ +	yy_load_buffer_state( yyscanner ); +	yyg->yy_did_buffer_switch_on_eof = 1; +} + +/** Removes and deletes the top of the stack, if present. + *  The next element becomes the new top. + *  @param yyscanner The scanner object. + */ +void yypop_buffer_state (yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +	if (!YY_CURRENT_BUFFER) +		return; + +	yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner); +	YY_CURRENT_BUFFER_LVALUE = NULL; +	if (yyg->yy_buffer_stack_top > 0) +		--yyg->yy_buffer_stack_top; + +	if (YY_CURRENT_BUFFER) { +		yy_load_buffer_state( yyscanner ); +		yyg->yy_did_buffer_switch_on_eof = 1; +	} +} + +/* Allocates the stack if it does not exist. + *  Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (yyscan_t yyscanner) +{ +	yy_size_t num_to_alloc; +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +	if (!yyg->yy_buffer_stack) { + +		/* First allocation is just for 2 elements, since we don't know if this +		 * scanner will even need a stack. We use 2 instead of 1 to avoid an +		 * immediate realloc on the next call. +         */ +      num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ +		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc +								(num_to_alloc * sizeof(struct yy_buffer_state*) +								, yyscanner); +		if ( ! yyg->yy_buffer_stack ) +			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + +		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + +		yyg->yy_buffer_stack_max = num_to_alloc; +		yyg->yy_buffer_stack_top = 0; +		return; +	} + +	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ + +		/* Increase the buffer to prepare for a possible push. */ +		yy_size_t grow_size = 8 /* arbitrary grow size */; + +		num_to_alloc = yyg->yy_buffer_stack_max + grow_size; +		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc +								(yyg->yy_buffer_stack, +								num_to_alloc * sizeof(struct yy_buffer_state*) +								, yyscanner); +		if ( ! yyg->yy_buffer_stack ) +			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + +		/* zero only the new slots.*/ +		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); +		yyg->yy_buffer_stack_max = num_to_alloc; +	} +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner) +{ +	YY_BUFFER_STATE b; +     +	if ( size < 2 || +	     base[size-2] != YY_END_OF_BUFFER_CHAR || +	     base[size-1] != YY_END_OF_BUFFER_CHAR ) +		/* They forgot to leave room for the EOB's. */ +		return NULL; + +	b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); +	if ( ! b ) +		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + +	b->yy_buf_size = (int) (size - 2);	/* "- 2" to take care of EOB's */ +	b->yy_buf_pos = b->yy_ch_buf = base; +	b->yy_is_our_buffer = 0; +	b->yy_input_file = NULL; +	b->yy_n_chars = b->yy_buf_size; +	b->yy_is_interactive = 0; +	b->yy_at_bol = 1; +	b->yy_fill_buffer = 0; +	b->yy_buffer_status = YY_BUFFER_NEW; + +	yy_switch_to_buffer( b , yyscanner ); + +	return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + *       yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner) +{ +     +	return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes  (const char * yybytes, int  _yybytes_len , yyscan_t yyscanner) +{ +	YY_BUFFER_STATE b; +	char *buf; +	yy_size_t n; +	int i; +     +	/* Get memory for full buffer, including space for trailing EOB's. */ +	n = (yy_size_t) (_yybytes_len + 2); +	buf = (char *) yyalloc( n , yyscanner ); +	if ( ! buf ) +		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + +	for ( i = 0; i < _yybytes_len; ++i ) +		buf[i] = yybytes[i]; + +	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + +	b = yy_scan_buffer( buf, n , yyscanner); +	if ( ! b ) +		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + +	/* It's okay to grow etc. this buffer, and we should throw it +	 * away when we're done. +	 */ +	b->yy_is_our_buffer = 1; + +	return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner) +{ +	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +	(void)yyg; +	fprintf( stderr, "%s\n", msg ); +	exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ +	do \ +		{ \ +		/* Undo effects of setting up yytext. */ \ +        int yyless_macro_arg = (n); \ +        YY_LESS_LINENO(yyless_macro_arg);\ +		yytext[yyleng] = yyg->yy_hold_char; \ +		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ +		yyg->yy_hold_char = *yyg->yy_c_buf_p; \ +		*yyg->yy_c_buf_p = '\0'; \ +		yyleng = yyless_macro_arg; \ +		} \ +	while ( 0 ) + +/* Accessor  methods (get/set functions) to struct members. */ + +/** Get the user-defined data for this scanner. + * @param yyscanner The scanner object. + */ +YY_EXTRA_TYPE yyget_extra  (yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +    return yyextra; +} + +/** Get the current line number. + * @param yyscanner The scanner object. + */ +int yyget_lineno  (yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +        if (! YY_CURRENT_BUFFER) +            return 0; +     +    return yylineno; +} + +/** Get the current column number. + * @param yyscanner The scanner object. + */ +int yyget_column  (yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +        if (! YY_CURRENT_BUFFER) +            return 0; +     +    return yycolumn; +} + +/** Get the input stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_in  (yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +    return yyin; +} + +/** Get the output stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_out  (yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +    return yyout; +} + +/** Get the length of the current token. + * @param yyscanner The scanner object. + */ +int yyget_leng  (yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +    return yyleng; +} + +/** Get the current token. + * @param yyscanner The scanner object. + */ + +char *yyget_text  (yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +    return yytext; +} + +/** Set the user-defined data. This data is never touched by the scanner. + * @param user_defined The data to be associated with this scanner. + * @param yyscanner The scanner object. + */ +void yyset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +    yyextra = user_defined ; +} + +/** Set the current line number. + * @param _line_number line number + * @param yyscanner The scanner object. + */ +void yyset_lineno (int  _line_number , yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +        /* lineno is only valid if an input buffer exists. */ +        if (! YY_CURRENT_BUFFER ) +           YY_FATAL_ERROR( "yyset_lineno called with no buffer" ); +     +    yylineno = _line_number; +} + +/** Set the current column. + * @param _column_no column number + * @param yyscanner The scanner object. + */ +void yyset_column (int  _column_no , yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +        /* column is only valid if an input buffer exists. */ +        if (! YY_CURRENT_BUFFER ) +           YY_FATAL_ERROR( "yyset_column called with no buffer" ); +     +    yycolumn = _column_no; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * @param yyscanner The scanner object. + * @see yy_switch_to_buffer + */ +void yyset_in (FILE *  _in_str , yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +    yyin = _in_str ; +} + +void yyset_out (FILE *  _out_str , yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +    yyout = _out_str ; +} + +int yyget_debug  (yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +    return yy_flex_debug; +} + +void yyset_debug (int  _bdebug , yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +    yy_flex_debug = _bdebug ; +} + +/* Accessor methods for yylval and yylloc */ + +YYSTYPE * yyget_lval  (yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +    return yylval; +} + +void yyset_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +    yylval = yylval_param; +} + +YYLTYPE *yyget_lloc  (yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +    return yylloc; +} +     +void yyset_lloc (YYLTYPE *  yylloc_param , yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +    yylloc = yylloc_param; +} +     +/* User-visible API */ + +/* yylex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ +int yylex_init(yyscan_t* ptr_yy_globals) +{ +    if (ptr_yy_globals == NULL){ +        errno = EINVAL; +        return 1; +    } + +    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL ); + +    if (*ptr_yy_globals == NULL){ +        errno = ENOMEM; +        return 1; +    } + +    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ +    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + +    return yy_init_globals ( *ptr_yy_globals ); +} + +/* yylex_init_extra has the same functionality as yylex_init, but follows the + * convention of taking the scanner as the last argument. Note however, that + * this is a *pointer* to a scanner, as it will be allocated by this call (and + * is the reason, too, why this function also must handle its own declaration). + * The user defined value in the first argument will be available to yyalloc in + * the yyextra field. + */ +int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals ) +{ +    struct yyguts_t dummy_yyguts; + +    yyset_extra (yy_user_defined, &dummy_yyguts); + +    if (ptr_yy_globals == NULL){ +        errno = EINVAL; +        return 1; +    } + +    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + +    if (*ptr_yy_globals == NULL){ +        errno = ENOMEM; +        return 1; +    } + +    /* By setting to 0xAA, we expose bugs in +    yy_init_globals. Leave at 0x00 for releases. */ +    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + +    yyset_extra (yy_user_defined, *ptr_yy_globals); + +    return yy_init_globals ( *ptr_yy_globals ); +} + +static int yy_init_globals (yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +    /* Initialization is the same as for the non-reentrant scanner. +     * This function is called from yylex_destroy(), so don't allocate here. +     */ + +    yyg->yy_buffer_stack = NULL; +    yyg->yy_buffer_stack_top = 0; +    yyg->yy_buffer_stack_max = 0; +    yyg->yy_c_buf_p = NULL; +    yyg->yy_init = 0; +    yyg->yy_start = 0; + +    yyg->yy_start_stack_ptr = 0; +    yyg->yy_start_stack_depth = 0; +    yyg->yy_start_stack =  NULL; + +    yyg->yy_state_buf = 0; +    yyg->yy_state_ptr = 0; +    yyg->yy_full_match = 0; +    yyg->yy_lp = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT +    yyin = stdin; +    yyout = stdout; +#else +    yyin = NULL; +    yyout = NULL; +#endif + +    /* For future reference: Set errno on error, since we are called by +     * yylex_init() +     */ +    return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy  (yyscan_t yyscanner) +{ +    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +    /* Pop the buffer stack, destroying each element. */ +	while(YY_CURRENT_BUFFER){ +		yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner ); +		YY_CURRENT_BUFFER_LVALUE = NULL; +		yypop_buffer_state(yyscanner); +	} + +	/* Destroy the stack itself. */ +	yyfree(yyg->yy_buffer_stack , yyscanner); +	yyg->yy_buffer_stack = NULL; + +    /* Destroy the start condition stack. */ +        yyfree( yyg->yy_start_stack , yyscanner ); +        yyg->yy_start_stack = NULL; + +    yyfree ( yyg->yy_state_buf , yyscanner); +    yyg->yy_state_buf  = NULL; + +    /* Reset the globals. This is important in a non-reentrant scanner so the next time +     * yylex() is called, initialization will occur. */ +    yy_init_globals( yyscanner); + +    /* Destroy the main struct (reentrant only). */ +    yyfree ( yyscanner , yyscanner ); +    yyscanner = NULL; +    return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner) +{ +	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +	(void)yyg; + +	int i; +	for ( i = 0; i < n; ++i ) +		s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (const char * s , yyscan_t yyscanner) +{ +	int n; +	for ( n = 0; s[n]; ++n ) +		; + +	return n; +} +#endif + +void *yyalloc (yy_size_t  size , yyscan_t yyscanner) +{ +	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +	(void)yyg; +	return malloc(size); +} + +void *yyrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner) +{ +	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +	(void)yyg; + +	/* The cast to (char *) in the following accommodates both +	 * implementations that use char* generic pointers, and those +	 * that use void* generic pointers.  It works with the latter +	 * because both ANSI C and C++ allow castless assignment from +	 * any pointer type to void*, and deal with argument conversions +	 * as though doing an assignment. +	 */ +	return realloc(ptr, size); +} + +void yyfree (void * ptr , yyscan_t yyscanner) +{ +	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; +	(void)yyg; +	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 85 "kalmia.l" diff --git a/src/xml/kalmia.lex.h b/src/xml/kalmia.lex.h new file mode 100644 index 0000000..ad35689 --- /dev/null +++ b/src/xml/kalmia.lex.h @@ -0,0 +1,735 @@ +#ifndef kalmiaHEADER_H +#define kalmiaHEADER_H 1 +#define kalmiaIN_HEADER 1 + +#line 5 "kalmia.lex.h" + +#line 7 "kalmia.lex.h" + +#define  YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +#ifdef yy_create_buffer +#define kalmia_create_buffer_ALREADY_DEFINED +#else +#define yy_create_buffer kalmia_create_buffer +#endif + +#ifdef yy_delete_buffer +#define kalmia_delete_buffer_ALREADY_DEFINED +#else +#define yy_delete_buffer kalmia_delete_buffer +#endif + +#ifdef yy_scan_buffer +#define kalmia_scan_buffer_ALREADY_DEFINED +#else +#define yy_scan_buffer kalmia_scan_buffer +#endif + +#ifdef yy_scan_string +#define kalmia_scan_string_ALREADY_DEFINED +#else +#define yy_scan_string kalmia_scan_string +#endif + +#ifdef yy_scan_bytes +#define kalmia_scan_bytes_ALREADY_DEFINED +#else +#define yy_scan_bytes kalmia_scan_bytes +#endif + +#ifdef yy_init_buffer +#define kalmia_init_buffer_ALREADY_DEFINED +#else +#define yy_init_buffer kalmia_init_buffer +#endif + +#ifdef yy_flush_buffer +#define kalmia_flush_buffer_ALREADY_DEFINED +#else +#define yy_flush_buffer kalmia_flush_buffer +#endif + +#ifdef yy_load_buffer_state +#define kalmia_load_buffer_state_ALREADY_DEFINED +#else +#define yy_load_buffer_state kalmia_load_buffer_state +#endif + +#ifdef yy_switch_to_buffer +#define kalmia_switch_to_buffer_ALREADY_DEFINED +#else +#define yy_switch_to_buffer kalmia_switch_to_buffer +#endif + +#ifdef yypush_buffer_state +#define kalmiapush_buffer_state_ALREADY_DEFINED +#else +#define yypush_buffer_state kalmiapush_buffer_state +#endif + +#ifdef yypop_buffer_state +#define kalmiapop_buffer_state_ALREADY_DEFINED +#else +#define yypop_buffer_state kalmiapop_buffer_state +#endif + +#ifdef yyensure_buffer_stack +#define kalmiaensure_buffer_stack_ALREADY_DEFINED +#else +#define yyensure_buffer_stack kalmiaensure_buffer_stack +#endif + +#ifdef yylex +#define kalmialex_ALREADY_DEFINED +#else +#define yylex kalmialex +#endif + +#ifdef yyrestart +#define kalmiarestart_ALREADY_DEFINED +#else +#define yyrestart kalmiarestart +#endif + +#ifdef yylex_init +#define kalmialex_init_ALREADY_DEFINED +#else +#define yylex_init kalmialex_init +#endif + +#ifdef yylex_init_extra +#define kalmialex_init_extra_ALREADY_DEFINED +#else +#define yylex_init_extra kalmialex_init_extra +#endif + +#ifdef yylex_destroy +#define kalmialex_destroy_ALREADY_DEFINED +#else +#define yylex_destroy kalmialex_destroy +#endif + +#ifdef yyget_debug +#define kalmiaget_debug_ALREADY_DEFINED +#else +#define yyget_debug kalmiaget_debug +#endif + +#ifdef yyset_debug +#define kalmiaset_debug_ALREADY_DEFINED +#else +#define yyset_debug kalmiaset_debug +#endif + +#ifdef yyget_extra +#define kalmiaget_extra_ALREADY_DEFINED +#else +#define yyget_extra kalmiaget_extra +#endif + +#ifdef yyset_extra +#define kalmiaset_extra_ALREADY_DEFINED +#else +#define yyset_extra kalmiaset_extra +#endif + +#ifdef yyget_in +#define kalmiaget_in_ALREADY_DEFINED +#else +#define yyget_in kalmiaget_in +#endif + +#ifdef yyset_in +#define kalmiaset_in_ALREADY_DEFINED +#else +#define yyset_in kalmiaset_in +#endif + +#ifdef yyget_out +#define kalmiaget_out_ALREADY_DEFINED +#else +#define yyget_out kalmiaget_out +#endif + +#ifdef yyset_out +#define kalmiaset_out_ALREADY_DEFINED +#else +#define yyset_out kalmiaset_out +#endif + +#ifdef yyget_leng +#define kalmiaget_leng_ALREADY_DEFINED +#else +#define yyget_leng kalmiaget_leng +#endif + +#ifdef yyget_text +#define kalmiaget_text_ALREADY_DEFINED +#else +#define yyget_text kalmiaget_text +#endif + +#ifdef yyget_lineno +#define kalmiaget_lineno_ALREADY_DEFINED +#else +#define yyget_lineno kalmiaget_lineno +#endif + +#ifdef yyset_lineno +#define kalmiaset_lineno_ALREADY_DEFINED +#else +#define yyset_lineno kalmiaset_lineno +#endif + +#ifdef yyget_column +#define kalmiaget_column_ALREADY_DEFINED +#else +#define yyget_column kalmiaget_column +#endif + +#ifdef yyset_column +#define kalmiaset_column_ALREADY_DEFINED +#else +#define yyset_column kalmiaset_column +#endif + +#ifdef yywrap +#define kalmiawrap_ALREADY_DEFINED +#else +#define yywrap kalmiawrap +#endif + +#ifdef yyget_lval +#define kalmiaget_lval_ALREADY_DEFINED +#else +#define yyget_lval kalmiaget_lval +#endif + +#ifdef yyset_lval +#define kalmiaset_lval_ALREADY_DEFINED +#else +#define yyset_lval kalmiaset_lval +#endif + +#ifdef yyget_lloc +#define kalmiaget_lloc_ALREADY_DEFINED +#else +#define yyget_lloc kalmiaget_lloc +#endif + +#ifdef yyset_lloc +#define kalmiaset_lloc_ALREADY_DEFINED +#else +#define yyset_lloc kalmiaset_lloc +#endif + +#ifdef yyalloc +#define kalmiaalloc_ALREADY_DEFINED +#else +#define yyalloc kalmiaalloc +#endif + +#ifdef yyrealloc +#define kalmiarealloc_ALREADY_DEFINED +#else +#define yyrealloc kalmiarealloc +#endif + +#ifdef yyfree +#define kalmiafree_ALREADY_DEFINED +#else +#define yyfree kalmiafree +#endif + +/* First, we deal with  platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types.  + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t;  +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN               (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN              (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN              (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX               (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX              (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX              (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX              (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX             (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX             (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX               (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* begin standard C++ headers. */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) +   are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state +	{ +	FILE *yy_input_file; + +	char *yy_ch_buf;		/* input buffer */ +	char *yy_buf_pos;		/* current position in input buffer */ + +	/* Size of input buffer in bytes, not including room for EOB +	 * characters. +	 */ +	int yy_buf_size; + +	/* Number of characters read into yy_ch_buf, not including EOB +	 * characters. +	 */ +	int yy_n_chars; + +	/* Whether we "own" the buffer - i.e., we know we created it, +	 * and can realloc() it to grow it, and should free() it to +	 * delete it. +	 */ +	int yy_is_our_buffer; + +	/* Whether this is an "interactive" input source; if so, and +	 * if we're using stdio for input, then we want to use getc() +	 * instead of fread(), to make sure we stop fetching input after +	 * each newline. +	 */ +	int yy_is_interactive; + +	/* Whether we're considered to be at the beginning of a line. +	 * If so, '^' rules will be active on the next match, otherwise +	 * not. +	 */ +	int yy_at_bol; + +    int yy_bs_lineno; /**< The line count. */ +    int yy_bs_column; /**< The column count. */ + +	/* Whether to try to fill the input buffer when we reach the +	 * end of it. +	 */ +	int yy_fill_buffer; + +	int yy_buffer_status; + +	}; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +void yyrestart ( FILE *input_file , yyscan_t yyscanner ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); +void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +void yypop_buffer_state ( yyscan_t yyscanner ); + +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner ); + +void *yyalloc ( yy_size_t , yyscan_t yyscanner ); +void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); +void yyfree ( void * , yyscan_t yyscanner ); + +#define kalmiawrap(yyscanner) (/*CONSTCOND*/1) +#define YY_SKIP_YYWRAP + +#define yytext_ptr yytext_r + +#ifdef YY_HEADER_EXPORT_START_CONDITIONS +#define INITIAL 0 +#define STRING 1 +#define TAG 2 + +#endif + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include <unistd.h> +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +int yylex_init (yyscan_t* scanner); + +int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); + +/* Accessor methods to globals. +   These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy ( yyscan_t yyscanner ); + +int yyget_debug ( yyscan_t yyscanner ); + +void yyset_debug ( int debug_flag , yyscan_t yyscanner ); + +YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); + +void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); + +FILE *yyget_in ( yyscan_t yyscanner ); + +void yyset_in  ( FILE * _in_str , yyscan_t yyscanner ); + +FILE *yyget_out ( yyscan_t yyscanner ); + +void yyset_out  ( FILE * _out_str , yyscan_t yyscanner ); + +			int yyget_leng ( yyscan_t yyscanner ); + +char *yyget_text ( yyscan_t yyscanner ); + +int yyget_lineno ( yyscan_t yyscanner ); + +void yyset_lineno ( int _line_number , yyscan_t yyscanner ); + +int yyget_column  ( yyscan_t yyscanner ); + +void yyset_column ( int _column_no , yyscan_t yyscanner ); + +YYSTYPE * yyget_lval ( yyscan_t yyscanner ); + +void yyset_lval ( YYSTYPE * yylval_param , yyscan_t yyscanner ); + +       YYLTYPE *yyget_lloc ( yyscan_t yyscanner ); +     +        void yyset_lloc ( YYLTYPE * yylloc_param , yyscan_t yyscanner ); +     +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap ( yyscan_t yyscanner ); +#else +extern int yywrap ( yyscan_t yyscanner ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen ( const char * , yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex \ +               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner); + +#define YY_DECL int yylex \ +               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif + +#ifndef kalmia_create_buffer_ALREADY_DEFINED +#undef yy_create_buffer +#endif +#ifndef kalmia_delete_buffer_ALREADY_DEFINED +#undef yy_delete_buffer +#endif +#ifndef kalmia_scan_buffer_ALREADY_DEFINED +#undef yy_scan_buffer +#endif +#ifndef kalmia_scan_string_ALREADY_DEFINED +#undef yy_scan_string +#endif +#ifndef kalmia_scan_bytes_ALREADY_DEFINED +#undef yy_scan_bytes +#endif +#ifndef kalmia_init_buffer_ALREADY_DEFINED +#undef yy_init_buffer +#endif +#ifndef kalmia_flush_buffer_ALREADY_DEFINED +#undef yy_flush_buffer +#endif +#ifndef kalmia_load_buffer_state_ALREADY_DEFINED +#undef yy_load_buffer_state +#endif +#ifndef kalmia_switch_to_buffer_ALREADY_DEFINED +#undef yy_switch_to_buffer +#endif +#ifndef kalmiapush_buffer_state_ALREADY_DEFINED +#undef yypush_buffer_state +#endif +#ifndef kalmiapop_buffer_state_ALREADY_DEFINED +#undef yypop_buffer_state +#endif +#ifndef kalmiaensure_buffer_stack_ALREADY_DEFINED +#undef yyensure_buffer_stack +#endif +#ifndef kalmialex_ALREADY_DEFINED +#undef yylex +#endif +#ifndef kalmiarestart_ALREADY_DEFINED +#undef yyrestart +#endif +#ifndef kalmialex_init_ALREADY_DEFINED +#undef yylex_init +#endif +#ifndef kalmialex_init_extra_ALREADY_DEFINED +#undef yylex_init_extra +#endif +#ifndef kalmialex_destroy_ALREADY_DEFINED +#undef yylex_destroy +#endif +#ifndef kalmiaget_debug_ALREADY_DEFINED +#undef yyget_debug +#endif +#ifndef kalmiaset_debug_ALREADY_DEFINED +#undef yyset_debug +#endif +#ifndef kalmiaget_extra_ALREADY_DEFINED +#undef yyget_extra +#endif +#ifndef kalmiaset_extra_ALREADY_DEFINED +#undef yyset_extra +#endif +#ifndef kalmiaget_in_ALREADY_DEFINED +#undef yyget_in +#endif +#ifndef kalmiaset_in_ALREADY_DEFINED +#undef yyset_in +#endif +#ifndef kalmiaget_out_ALREADY_DEFINED +#undef yyget_out +#endif +#ifndef kalmiaset_out_ALREADY_DEFINED +#undef yyset_out +#endif +#ifndef kalmiaget_leng_ALREADY_DEFINED +#undef yyget_leng +#endif +#ifndef kalmiaget_text_ALREADY_DEFINED +#undef yyget_text +#endif +#ifndef kalmiaget_lineno_ALREADY_DEFINED +#undef yyget_lineno +#endif +#ifndef kalmiaset_lineno_ALREADY_DEFINED +#undef yyset_lineno +#endif +#ifndef kalmiaget_column_ALREADY_DEFINED +#undef yyget_column +#endif +#ifndef kalmiaset_column_ALREADY_DEFINED +#undef yyset_column +#endif +#ifndef kalmiawrap_ALREADY_DEFINED +#undef yywrap +#endif +#ifndef kalmiaget_lval_ALREADY_DEFINED +#undef yyget_lval +#endif +#ifndef kalmiaset_lval_ALREADY_DEFINED +#undef yyset_lval +#endif +#ifndef kalmiaget_lloc_ALREADY_DEFINED +#undef yyget_lloc +#endif +#ifndef kalmiaset_lloc_ALREADY_DEFINED +#undef yyset_lloc +#endif +#ifndef kalmiaalloc_ALREADY_DEFINED +#undef yyalloc +#endif +#ifndef kalmiarealloc_ALREADY_DEFINED +#undef yyrealloc +#endif +#ifndef kalmiafree_ALREADY_DEFINED +#undef yyfree +#endif +#ifndef kalmiatext_ALREADY_DEFINED +#undef yytext +#endif +#ifndef kalmialeng_ALREADY_DEFINED +#undef yyleng +#endif +#ifndef kalmiain_ALREADY_DEFINED +#undef yyin +#endif +#ifndef kalmiaout_ALREADY_DEFINED +#undef yyout +#endif +#ifndef kalmia_flex_debug_ALREADY_DEFINED +#undef yy_flex_debug +#endif +#ifndef kalmialineno_ALREADY_DEFINED +#undef yylineno +#endif +#ifndef kalmiatables_fload_ALREADY_DEFINED +#undef yytables_fload +#endif +#ifndef kalmiatables_destroy_ALREADY_DEFINED +#undef yytables_destroy +#endif +#ifndef kalmiaTABLES_NAME_ALREADY_DEFINED +#undef yyTABLES_NAME +#endif + +#line 85 "kalmia.l" + +#line 733 "kalmia.lex.h" +#undef kalmiaIN_HEADER +#endif /* kalmiaHEADER_H */ diff --git a/src/xml/kalmia.tab.c b/src/xml/kalmia.tab.c new file mode 100644 index 0000000..6f6f547 --- /dev/null +++ b/src/xml/kalmia.tab.c @@ -0,0 +1,2001 @@ +/* A Bison parser, made by GNU Bison 3.8.2.  */ + +/* Bison implementation for Yacc-like parsers in C + +   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, +   Inc. + +   This program is free software: you can redistribute it and/or modify +   it under the terms of the GNU General Public License as published by +   the Free Software Foundation, either version 3 of the License, or +   (at your option) any later version. + +   This program is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */ + +/* As a special exception, you may create a larger work that contains +   part or all of the Bison parser skeleton and distribute that work +   under terms of your choice, so long as that work isn't itself a +   parser generator using the skeleton or a modified version thereof +   as a parser skeleton.  Alternatively, if you modify or redistribute +   the parser skeleton itself, you may (at your option) remove this +   special exception, which will cause the skeleton and the resulting +   Bison output files to be licensed under the GNU General Public +   License without this special exception. + +   This special exception was added by the Free Software Foundation in +   version 2.2 of Bison.  */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by +   simplifying the original so-called "semantic" parser.  */ + +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, +   especially those whose name start with YY_ or yy_.  They are +   private implementation details that can be changed or removed.  */ + +/* All symbols defined below should begin with yy or YY, to avoid +   infringing on user name space.  This should be done even for local +   variables, as they might otherwise be expanded by user macros. +   There are some unavoidable exceptions within include files to +   define necessary library symbols; they are noted "INFRINGES ON +   USER NAME SPACE" below.  */ + +/* Identify Bison output, and Bison version.  */ +#define YYBISON 30802 + +/* Bison version string.  */ +#define YYBISON_VERSION "3.8.2" + +/* Skeleton name.  */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers.  */ +#define YYPURE 2 + +/* Push parsers.  */ +#define YYPUSH 0 + +/* Pull parsers.  */ +#define YYPULL 1 + +/* "%code top" blocks.  */ +#line 7 "kalmia.y" + +	#include <stdio.h> +	#include <stdlib.h> +	#include <stdarg.h> +	#include <string.h> + +#line 75 "kalmia.tab.c" +/* Substitute the type names.  */ +#define YYSTYPE         KALMIASTYPE +#define YYLTYPE         KALMIALTYPE +/* Substitute the variable and function names.  */ +#define yyparse         kalmiaparse +#define yylex           kalmialex +#define yyerror         kalmiaerror +#define yydebug         kalmiadebug +#define yynerrs         kalmianerrs + + +# ifndef YY_CAST +#  ifdef __cplusplus +#   define YY_CAST(Type, Val) static_cast<Type> (Val) +#   define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast<Type> (Val) +#  else +#   define YY_CAST(Type, Val) ((Type) (Val)) +#   define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) +#  endif +# endif +# ifndef YY_NULLPTR +#  if defined __cplusplus +#   if 201103L <= __cplusplus +#    define YY_NULLPTR nullptr +#   else +#    define YY_NULLPTR 0 +#   endif +#  else +#   define YY_NULLPTR ((void*)0) +#  endif +# endif + +#include "kalmia.tab.h" +/* Symbol kind.  */ +enum yysymbol_kind_t +{ +  YYSYMBOL_YYEMPTY = -2, +  YYSYMBOL_YYEOF = 0,                      /* "end of file"  */ +  YYSYMBOL_YYerror = 1,                    /* error  */ +  YYSYMBOL_YYUNDEF = 2,                    /* "invalid token"  */ +  YYSYMBOL_PROLOG = 3,                     /* PROLOG  */ +  YYSYMBOL_S_TAG_OPEN = 4,                 /* S_TAG_OPEN  */ +  YYSYMBOL_E_TAG_OPEN = 5,                 /* E_TAG_OPEN  */ +  YYSYMBOL_TAG_CLOSE = 6,                  /* TAG_CLOSE  */ +  YYSYMBOL_EMPTY_TAG_CLOSE = 7,            /* EMPTY_TAG_CLOSE  */ +  YYSYMBOL_NAME = 8,                       /* NAME  */ +  YYSYMBOL_ATTR = 9,                       /* ATTR  */ +  YYSYMBOL_TEXT = 10,                      /* TEXT  */ +  YYSYMBOL_CONTENT = 11,                   /* CONTENT  */ +  YYSYMBOL_12_ = 12,                       /* '='  */ +  YYSYMBOL_13_ = 13,                       /* '"'  */ +  YYSYMBOL_YYACCEPT = 14,                  /* $accept  */ +  YYSYMBOL_document = 15,                  /* document  */ +  YYSYMBOL_tags = 16,                      /* tags  */ +  YYSYMBOL_tag = 17,                       /* tag  */ +  YYSYMBOL_start_tag = 18,                 /* start_tag  */ +  YYSYMBOL_empty_tag = 19,                 /* empty_tag  */ +  YYSYMBOL_end_tag = 20,                   /* end_tag  */ +  YYSYMBOL_attributes = 21,                /* attributes  */ +  YYSYMBOL_attribute = 22                  /* attribute  */ +}; +typedef enum yysymbol_kind_t yysymbol_kind_t; + + + +/* Unqualified %code blocks.  */ +#line 36 "kalmia.y" + +	/* flex definitions */ +	int yylex(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t scanner); +	int kalmialex_init(yyscan_t *); +	void kalmiaset_in(FILE *, yyscan_t); +	int kalmialex_destroy(yyscan_t); + +	int yyerror(YYLTYPE *yyllocp, yyscan_t unused,  +		struct kai_tag_t **unused2, const char *msg); + +	#define TAG_MISMATCH(a, b) \ +	do { \ +		char buf[1024]; \ +		snprintf(buf, 1024, "Tag name mismatch: \"%s\" != \"%s\"", a, b); \ +		yyerror(&yylloc, NULL, NULL, (const char*) buf); \ +		YYABORT; \ +	} while (0) + +	/* create/destroy kai_attr_t */ +	struct kai_attr_t * kai_attr_new(char *key, char *value); +	struct kai_attr_t * kai_attr_last(struct kai_attr_t *head); +	void kai_attr_destroy(struct kai_attr_t *attr); + +	/* create/destroy kai_tag_t */ +	struct kai_tag_t * kai_tag_new(char *type, struct kai_attr_t *attrs); +	struct kai_tag_t * kai_tag_last(struct kai_tag_t *head); +	void kai_tag_destroy(struct kai_tag_t *tag); + +#line 171 "kalmia.tab.c" + +#ifdef short +# undef short +#endif + +/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure +   <limits.h> and (if available) <stdint.h> are included +   so that the code can choose integer types of a good width.  */ + +#ifndef __PTRDIFF_MAX__ +# include <limits.h> /* INFRINGES ON USER NAME SPACE */ +# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +#  include <stdint.h> /* INFRINGES ON USER NAME SPACE */ +#  define YY_STDINT_H +# endif +#endif + +/* Narrow types that promote to a signed type and that can represent a +   signed or unsigned integer of at least N bits.  In tables they can +   save space and decrease cache pressure.  Promoting to a signed type +   helps avoid bugs in integer arithmetic.  */ + +#ifdef __INT_LEAST8_MAX__ +typedef __INT_LEAST8_TYPE__ yytype_int8; +#elif defined YY_STDINT_H +typedef int_least8_t yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef __INT_LEAST16_MAX__ +typedef __INT_LEAST16_TYPE__ yytype_int16; +#elif defined YY_STDINT_H +typedef int_least16_t yytype_int16; +#else +typedef short yytype_int16; +#endif + +/* Work around bug in HP-UX 11.23, which defines these macros +   incorrectly for preprocessor constants.  This workaround can likely +   be removed in 2023, as HPE has promised support for HP-UX 11.23 +   (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of +   <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>.  */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + +#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST8_TYPE__ yytype_uint8; +#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ +       && UINT_LEAST8_MAX <= INT_MAX) +typedef uint_least8_t yytype_uint8; +#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX +typedef unsigned char yytype_uint8; +#else +typedef short yytype_uint8; +#endif + +#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST16_TYPE__ yytype_uint16; +#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ +       && UINT_LEAST16_MAX <= INT_MAX) +typedef uint_least16_t yytype_uint16; +#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX +typedef unsigned short yytype_uint16; +#else +typedef int yytype_uint16; +#endif + +#ifndef YYPTRDIFF_T +# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ +#  define YYPTRDIFF_T __PTRDIFF_TYPE__ +#  define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ +# elif defined PTRDIFF_MAX +#  ifndef ptrdiff_t +#   include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +#  endif +#  define YYPTRDIFF_T ptrdiff_t +#  define YYPTRDIFF_MAXIMUM PTRDIFF_MAX +# else +#  define YYPTRDIFF_T long +#  define YYPTRDIFF_MAXIMUM LONG_MAX +# endif +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +#  define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +#  define YYSIZE_T size_t +# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +#  define YYSIZE_T size_t +# else +#  define YYSIZE_T unsigned +# endif +#endif + +#define YYSIZE_MAXIMUM                                  \ +  YY_CAST (YYPTRDIFF_T,                                 \ +           (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1)  \ +            ? YYPTRDIFF_MAXIMUM                         \ +            : YY_CAST (YYSIZE_T, -1))) + +#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) + + +/* Stored state numbers (used for stacks). */ +typedef yytype_int8 yy_state_t; + +/* State numbers in computations.  */ +typedef int yy_state_fast_t; + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +#  if ENABLE_NLS +#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */ +#   define YY_(Msgid) dgettext ("bison-runtime", Msgid) +#  endif +# endif +# ifndef YY_ +#  define YY_(Msgid) Msgid +# endif +#endif + + +#ifndef YY_ATTRIBUTE_PURE +# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +#  define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +#  define YY_ATTRIBUTE_PURE +# endif +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +#  define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +# else +#  define YY_ATTRIBUTE_UNUSED +# endif +#endif + +/* Suppress unused-variable warnings by "using" E.  */ +#if ! defined lint || defined __GNUC__ +# define YY_USE(E) ((void) (E)) +#else +# define YY_USE(E) /* empty */ +#endif + +/* Suppress an incorrect diagnostic about yylval being uninitialized.  */ +#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +#  define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN                           \ +    _Pragma ("GCC diagnostic push")                                     \ +    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") +# else +#  define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN                           \ +    _Pragma ("GCC diagnostic push")                                     \ +    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")              \ +    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# endif +# define YY_IGNORE_MAYBE_UNINITIALIZED_END      \ +    _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + +#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ +# define YY_IGNORE_USELESS_CAST_BEGIN                          \ +    _Pragma ("GCC diagnostic push")                            \ +    _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") +# define YY_IGNORE_USELESS_CAST_END            \ +    _Pragma ("GCC diagnostic pop") +#endif +#ifndef YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_END +#endif + + +#define YY_ASSERT(E) ((void) (0 && (E))) + +#if 1 + +/* The parser invokes alloca or malloc; define the necessary symbols.  */ + +# ifdef YYSTACK_USE_ALLOCA +#  if YYSTACK_USE_ALLOCA +#   ifdef __GNUC__ +#    define YYSTACK_ALLOC __builtin_alloca +#   elif defined __BUILTIN_VA_ARG_INCR +#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */ +#   elif defined _AIX +#    define YYSTACK_ALLOC __alloca +#   elif defined _MSC_VER +#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */ +#    define alloca _alloca +#   else +#    define YYSTACK_ALLOC alloca +#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */ +#     ifndef EXIT_SUCCESS +#      define EXIT_SUCCESS 0 +#     endif +#    endif +#   endif +#  endif +# endif + +# ifdef YYSTACK_ALLOC +   /* Pacify GCC's 'empty if-body' warning.  */ +#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +#  ifndef YYSTACK_ALLOC_MAXIMUM +    /* The OS might guarantee only one guard page at the bottom of the stack, +       and a page size can be as small as 4096 bytes.  So we cannot safely +       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number +       to allow for a few compiler-allocated temporary stack slots.  */ +#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +#  endif +# else +#  define YYSTACK_ALLOC YYMALLOC +#  define YYSTACK_FREE YYFREE +#  ifndef YYSTACK_ALLOC_MAXIMUM +#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +#  endif +#  if (defined __cplusplus && ! defined EXIT_SUCCESS \ +       && ! ((defined YYMALLOC || defined malloc) \ +             && (defined YYFREE || defined free))) +#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +#   ifndef EXIT_SUCCESS +#    define EXIT_SUCCESS 0 +#   endif +#  endif +#  ifndef YYMALLOC +#   define YYMALLOC malloc +#   if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +#   endif +#  endif +#  ifndef YYFREE +#   define YYFREE free +#   if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +#   endif +#  endif +# endif +#endif /* 1 */ + +#if (! defined yyoverflow \ +     && (! defined __cplusplus \ +         || (defined KALMIALTYPE_IS_TRIVIAL && KALMIALTYPE_IS_TRIVIAL \ +             && defined KALMIASTYPE_IS_TRIVIAL && KALMIASTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member.  */ +union yyalloc +{ +  yy_state_t yyss_alloc; +  YYSTYPE yyvs_alloc; +  YYLTYPE yyls_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next.  */ +# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with +   N elements.  */ +# define YYSTACK_BYTES(N) \ +     ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE) \ +             + YYSIZEOF (YYLTYPE)) \ +      + 2 * YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one.  The +   local variables YYSIZE and YYSTACKSIZE give the old and new number of +   elements in the stack, and YYPTR gives the new location of the +   stack.  Advance YYPTR to a properly aligned location for the next +   stack.  */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \ +    do                                                                  \ +      {                                                                 \ +        YYPTRDIFF_T yynewbytes;                                         \ +        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \ +        Stack = &yyptr->Stack_alloc;                                    \ +        yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ +        yyptr += yynewbytes / YYSIZEOF (*yyptr);                        \ +      }                                                                 \ +    while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST.  The source and destination do +   not overlap.  */ +# ifndef YYCOPY +#  if defined __GNUC__ && 1 < __GNUC__ +#   define YYCOPY(Dst, Src, Count) \ +      __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) +#  else +#   define YYCOPY(Dst, Src, Count)              \ +      do                                        \ +        {                                       \ +          YYPTRDIFF_T yyi;                      \ +          for (yyi = 0; yyi < (Count); yyi++)   \ +            (Dst)[yyi] = (Src)[yyi];            \ +        }                                       \ +      while (0) +#  endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state.  */ +#define YYFINAL  7 +/* YYLAST -- Last index in YYTABLE.  */ +#define YYLAST   31 + +/* YYNTOKENS -- Number of terminals.  */ +#define YYNTOKENS  14 +/* YYNNTS -- Number of nonterminals.  */ +#define YYNNTS  9 +/* YYNRULES -- Number of rules.  */ +#define YYNRULES  16 +/* YYNSTATES -- Number of states.  */ +#define YYNSTATES  31 + +/* YYMAXUTOK -- Last valid token kind.  */ +#define YYMAXUTOK   266 + + +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM +   as returned by yylex, with out-of-bounds checking.  */ +#define YYTRANSLATE(YYX)                                \ +  (0 <= (YYX) && (YYX) <= YYMAXUTOK                     \ +   ? YY_CAST (yysymbol_kind_t, yytranslate[YYX])        \ +   : YYSYMBOL_YYUNDEF) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM +   as returned by yylex.  */ +static const yytype_int8 yytranslate[] = +{ +       0,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,    13,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,    12,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,     2,     2,     2,     1,     2,     3,     4, +       5,     6,     7,     8,     9,    10,    11 +}; + +#if KALMIADEBUG +/* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */ +static const yytype_uint8 yyrline[] = +{ +       0,    94,    94,    98,    99,   104,   110,   117,   124,   128, +     133,   142,   147,   156,   161,   162,   166 +}; +#endif + +/** Accessing symbol of state STATE.  */ +#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) + +#if 1 +/* The user-facing name of the symbol whose (internal) number is +   YYSYMBOL.  No bounds checking.  */ +static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; + +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. +   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */ +static const char *const yytname[] = +{ +  "\"end of file\"", "error", "\"invalid token\"", "PROLOG", "S_TAG_OPEN", +  "E_TAG_OPEN", "TAG_CLOSE", "EMPTY_TAG_CLOSE", "NAME", "ATTR", "TEXT", +  "CONTENT", "'='", "'\"'", "$accept", "document", "tags", "tag", +  "start_tag", "empty_tag", "end_tag", "attributes", "attribute", YY_NULLPTR +}; + +static const char * +yysymbol_name (yysymbol_kind_t yysymbol) +{ +  return yytname[yysymbol]; +} +#endif + +#define YYPACT_NINF (-6) + +#define yypact_value_is_default(Yyn) \ +  ((Yyn) == YYPACT_NINF) + +#define YYTABLE_NINF (-1) + +#define yytable_value_is_error(Yyn) \ +  0 + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing +   STATE-NUM.  */ +static const yytype_int8 yypact[] = +{ +       8,    11,    17,    10,    -6,    -4,    -6,    -6,     3,    12, +      14,    -1,    -6,    -6,    -6,    -6,     9,     7,    -6,    16, +      -6,    -6,    -6,    13,    -6,    -6,    -6,    -6,    15,    18, +      -6 +}; + +/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. +   Performed when YYTABLE does not specify something else to do.  Zero +   means the default is an error.  */ +static const yytype_int8 yydefact[] = +{ +       0,     0,     0,     0,     2,     0,     8,     1,     0,     0, +       0,     0,     3,     5,     9,    11,     0,     0,    14,     0, +       6,     4,     7,     0,    10,    12,    15,    13,     0,     0, +      16 +}; + +/* YYPGOTO[NTERM-NUM].  */ +static const yytype_int8 yypgoto[] = +{ +      -6,    -6,    -6,    -3,    -6,    -6,    -5,    -6,     6 +}; + +/* YYDEFGOTO[NTERM-NUM].  */ +static const yytype_int8 yydefgoto[] = +{ +       0,     2,    11,     4,     5,     6,    13,    17,    18 +}; + +/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If +   positive, shift that token.  If negative, reduce the rule whose +   number is the opposite.  If YYTABLE_NINF, syntax error.  */ +static const yytype_int8 yytable[] = +{ +       3,     9,    12,     3,     9,    20,    22,    10,    21,    14, +      15,     1,    16,    24,    25,     3,    16,     7,     8,     9, +      19,    23,    27,    26,     0,    29,    28,     0,     0,     0, +       0,    30 +}; + +static const yytype_int8 yycheck[] = +{ +       4,     5,     5,     4,     5,    10,    11,    11,    11,     6, +       7,     3,     9,     6,     7,     4,     9,     0,     8,     5, +       8,    12,     6,    17,    -1,    10,    13,    -1,    -1,    -1, +      -1,    13 +}; + +/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of +   state STATE-NUM.  */ +static const yytype_int8 yystos[] = +{ +       0,     3,    15,     4,    17,    18,    19,     0,     8,     5, +      11,    16,    17,    20,     6,     7,     9,    21,    22,     8, +      20,    17,    20,    12,     6,     7,    22,     6,    13,    10, +      13 +}; + +/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM.  */ +static const yytype_int8 yyr1[] = +{ +       0,    14,    15,    16,    16,    17,    17,    17,    17,    18, +      18,    19,    19,    20,    21,    21,    22 +}; + +/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM.  */ +static const yytype_int8 yyr2[] = +{ +       0,     2,     2,     1,     2,     2,     3,     3,     1,     3, +       4,     3,     4,     3,     1,     2,     5 +}; + + +enum { YYENOMEM = -2 }; + +#define yyerrok         (yyerrstatus = 0) +#define yyclearin       (yychar = KALMIAEMPTY) + +#define YYACCEPT        goto yyacceptlab +#define YYABORT         goto yyabortlab +#define YYERROR         goto yyerrorlab +#define YYNOMEM         goto yyexhaustedlab + + +#define YYRECOVERING()  (!!yyerrstatus) + +#define YYBACKUP(Token, Value)                                    \ +  do                                                              \ +    if (yychar == KALMIAEMPTY)                                        \ +      {                                                           \ +        yychar = (Token);                                         \ +        yylval = (Value);                                         \ +        YYPOPSTACK (yylen);                                       \ +        yystate = *yyssp;                                         \ +        goto yybackup;                                            \ +      }                                                           \ +    else                                                          \ +      {                                                           \ +        yyerror (&yylloc, scanner, document, YY_("syntax error: cannot back up")); \ +        YYERROR;                                                  \ +      }                                                           \ +  while (0) + +/* Backward compatibility with an undocumented macro. +   Use KALMIAerror or KALMIAUNDEF. */ +#define YYERRCODE KALMIAUNDEF + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. +   If N is 0, then set CURRENT to the empty location which ends +   the previous symbol: RHS[0] (always defined).  */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N)                                \ +    do                                                                  \ +      if (N)                                                            \ +        {                                                               \ +          (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \ +          (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \ +          (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \ +          (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \ +        }                                                               \ +      else                                                              \ +        {                                                               \ +          (Current).first_line   = (Current).last_line   =              \ +            YYRHSLOC (Rhs, 0).last_line;                                \ +          (Current).first_column = (Current).last_column =              \ +            YYRHSLOC (Rhs, 0).last_column;                              \ +        }                                                               \ +    while (0) +#endif + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) + + +/* Enable debugging if requested.  */ +#if KALMIADEBUG + +# ifndef YYFPRINTF +#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +#  define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args)                        \ +do {                                            \ +  if (yydebug)                                  \ +    YYFPRINTF Args;                             \ +} while (0) + + +/* YYLOCATION_PRINT -- Print the location on the stream. +   This macro was not mandated originally: define only if we know +   we won't break user code: when these are the locations we know.  */ + +# ifndef YYLOCATION_PRINT + +#  if defined YY_LOCATION_PRINT + +   /* Temporary convenience wrapper in case some people defined the +      undocumented and private YY_LOCATION_PRINT macros.  */ +#   define YYLOCATION_PRINT(File, Loc)  YY_LOCATION_PRINT(File, *(Loc)) + +#  elif defined KALMIALTYPE_IS_TRIVIAL && KALMIALTYPE_IS_TRIVIAL + +/* Print *YYLOCP on YYO.  Private, do not rely on its existence. */ + +YY_ATTRIBUTE_UNUSED +static int +yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) +{ +  int res = 0; +  int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; +  if (0 <= yylocp->first_line) +    { +      res += YYFPRINTF (yyo, "%d", yylocp->first_line); +      if (0 <= yylocp->first_column) +        res += YYFPRINTF (yyo, ".%d", yylocp->first_column); +    } +  if (0 <= yylocp->last_line) +    { +      if (yylocp->first_line < yylocp->last_line) +        { +          res += YYFPRINTF (yyo, "-%d", yylocp->last_line); +          if (0 <= end_col) +            res += YYFPRINTF (yyo, ".%d", end_col); +        } +      else if (0 <= end_col && yylocp->first_column < end_col) +        res += YYFPRINTF (yyo, "-%d", end_col); +    } +  return res; +} + +#   define YYLOCATION_PRINT  yy_location_print_ + +    /* Temporary convenience wrapper in case some people defined the +       undocumented and private YY_LOCATION_PRINT macros.  */ +#   define YY_LOCATION_PRINT(File, Loc)  YYLOCATION_PRINT(File, &(Loc)) + +#  else + +#   define YYLOCATION_PRINT(File, Loc) ((void) 0) +    /* Temporary convenience wrapper in case some people defined the +       undocumented and private YY_LOCATION_PRINT macros.  */ +#   define YY_LOCATION_PRINT  YYLOCATION_PRINT + +#  endif +# endif /* !defined YYLOCATION_PRINT */ + + +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location)                    \ +do {                                                                      \ +  if (yydebug)                                                            \ +    {                                                                     \ +      YYFPRINTF (stderr, "%s ", Title);                                   \ +      yy_symbol_print (stderr,                                            \ +                  Kind, Value, Location, scanner, document); \ +      YYFPRINTF (stderr, "\n");                                           \ +    }                                                                     \ +} while (0) + + +/*-----------------------------------. +| Print this symbol's value on YYO.  | +`-----------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyo, +                       yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, yyscan_t scanner, struct kai_tag_t **document) +{ +  FILE *yyoutput = yyo; +  YY_USE (yyoutput); +  YY_USE (yylocationp); +  YY_USE (scanner); +  YY_USE (document); +  if (!yyvaluep) +    return; +  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +  YY_USE (yykind); +  YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + +/*---------------------------. +| Print this symbol on YYO.  | +`---------------------------*/ + +static void +yy_symbol_print (FILE *yyo, +                 yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, yyscan_t scanner, struct kai_tag_t **document) +{ +  YYFPRINTF (yyo, "%s %s (", +             yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); + +  YYLOCATION_PRINT (yyo, yylocationp); +  YYFPRINTF (yyo, ": "); +  yy_symbol_value_print (yyo, yykind, yyvaluep, yylocationp, scanner, document); +  YYFPRINTF (yyo, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included).                                                   | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) +{ +  YYFPRINTF (stderr, "Stack now"); +  for (; yybottom <= yytop; yybottom++) +    { +      int yybot = *yybottom; +      YYFPRINTF (stderr, " %d", yybot); +    } +  YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top)                            \ +do {                                                            \ +  if (yydebug)                                                  \ +    yy_stack_print ((Bottom), (Top));                           \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced.  | +`------------------------------------------------*/ + +static void +yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, +                 int yyrule, yyscan_t scanner, struct kai_tag_t **document) +{ +  int yylno = yyrline[yyrule]; +  int yynrhs = yyr2[yyrule]; +  int yyi; +  YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", +             yyrule - 1, yylno); +  /* The symbols being reduced.  */ +  for (yyi = 0; yyi < yynrhs; yyi++) +    { +      YYFPRINTF (stderr, "   $%d = ", yyi + 1); +      yy_symbol_print (stderr, +                       YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), +                       &yyvsp[(yyi + 1) - (yynrhs)], +                       &(yylsp[(yyi + 1) - (yynrhs)]), scanner, document); +      YYFPRINTF (stderr, "\n"); +    } +} + +# define YY_REDUCE_PRINT(Rule)          \ +do {                                    \ +  if (yydebug)                          \ +    yy_reduce_print (yyssp, yyvsp, yylsp, Rule, scanner, document); \ +} while (0) + +/* Nonzero means print parse trace.  It is left uninitialized so that +   multiple parsers can coexist.  */ +int yydebug; +#else /* !KALMIADEBUG */ +# define YYDPRINTF(Args) ((void) 0) +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !KALMIADEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks.  */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only +   if the built-in stack extension method is used). + +   Do not make this value too large; the results are undefined if +   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) +   evaluated with infinite-precision integer arithmetic.  */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + +/* Context of a parse error.  */ +typedef struct +{ +  yy_state_t *yyssp; +  yysymbol_kind_t yytoken; +  YYLTYPE *yylloc; +} yypcontext_t; + +/* Put in YYARG at most YYARGN of the expected tokens given the +   current YYCTX, and return the number of tokens stored in YYARG.  If +   YYARG is null, return the number of expected tokens (guaranteed to +   be less than YYNTOKENS).  Return YYENOMEM on memory exhaustion. +   Return 0 if there are more than YYARGN expected tokens, yet fill +   YYARG up to YYARGN. */ +static int +yypcontext_expected_tokens (const yypcontext_t *yyctx, +                            yysymbol_kind_t yyarg[], int yyargn) +{ +  /* Actual size of YYARG. */ +  int yycount = 0; +  int yyn = yypact[+*yyctx->yyssp]; +  if (!yypact_value_is_default (yyn)) +    { +      /* Start YYX at -YYN if negative to avoid negative indexes in +         YYCHECK.  In other words, skip the first -YYN actions for +         this state because they are default actions.  */ +      int yyxbegin = yyn < 0 ? -yyn : 0; +      /* Stay within bounds of both yycheck and yytname.  */ +      int yychecklim = YYLAST - yyn + 1; +      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; +      int yyx; +      for (yyx = yyxbegin; yyx < yyxend; ++yyx) +        if (yycheck[yyx + yyn] == yyx && yyx != YYSYMBOL_YYerror +            && !yytable_value_is_error (yytable[yyx + yyn])) +          { +            if (!yyarg) +              ++yycount; +            else if (yycount == yyargn) +              return 0; +            else +              yyarg[yycount++] = YY_CAST (yysymbol_kind_t, yyx); +          } +    } +  if (yyarg && yycount == 0 && 0 < yyargn) +    yyarg[0] = YYSYMBOL_YYEMPTY; +  return yycount; +} + + + + +#ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +#  define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S))) +# else +/* Return the length of YYSTR.  */ +static YYPTRDIFF_T +yystrlen (const char *yystr) +{ +  YYPTRDIFF_T yylen; +  for (yylen = 0; yystr[yylen]; yylen++) +    continue; +  return yylen; +} +# endif +#endif + +#ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +#  define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in +   YYDEST.  */ +static char * +yystpcpy (char *yydest, const char *yysrc) +{ +  char *yyd = yydest; +  const char *yys = yysrc; + +  while ((*yyd++ = *yys++) != '\0') +    continue; + +  return yyd - 1; +} +# endif +#endif + +#ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary +   quotes and backslashes, so that it's suitable for yyerror.  The +   heuristic is that double-quoting is unnecessary unless the string +   contains an apostrophe, a comma, or backslash (other than +   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is +   null, do not copy; instead, return the length of what the result +   would have been.  */ +static YYPTRDIFF_T +yytnamerr (char *yyres, const char *yystr) +{ +  if (*yystr == '"') +    { +      YYPTRDIFF_T yyn = 0; +      char const *yyp = yystr; +      for (;;) +        switch (*++yyp) +          { +          case '\'': +          case ',': +            goto do_not_strip_quotes; + +          case '\\': +            if (*++yyp != '\\') +              goto do_not_strip_quotes; +            else +              goto append; + +          append: +          default: +            if (yyres) +              yyres[yyn] = *yyp; +            yyn++; +            break; + +          case '"': +            if (yyres) +              yyres[yyn] = '\0'; +            return yyn; +          } +    do_not_strip_quotes: ; +    } + +  if (yyres) +    return yystpcpy (yyres, yystr) - yyres; +  else +    return yystrlen (yystr); +} +#endif + + +static int +yy_syntax_error_arguments (const yypcontext_t *yyctx, +                           yysymbol_kind_t yyarg[], int yyargn) +{ +  /* Actual size of YYARG. */ +  int yycount = 0; +  /* There are many possibilities here to consider: +     - If this state is a consistent state with a default action, then +       the only way this function was invoked is if the default action +       is an error action.  In that case, don't check for expected +       tokens because there are none. +     - The only way there can be no lookahead present (in yychar) is if +       this state is a consistent state with a default action.  Thus, +       detecting the absence of a lookahead is sufficient to determine +       that there is no unexpected or expected token to report.  In that +       case, just report a simple "syntax error". +     - Don't assume there isn't a lookahead just because this state is a +       consistent state with a default action.  There might have been a +       previous inconsistent state, consistent state with a non-default +       action, or user semantic action that manipulated yychar. +     - Of course, the expected token list depends on states to have +       correct lookahead information, and it depends on the parser not +       to perform extra reductions after fetching a lookahead from the +       scanner and before detecting a syntax error.  Thus, state merging +       (from LALR or IELR) and default reductions corrupt the expected +       token list.  However, the list is correct for canonical LR with +       one exception: it will still contain any token that will not be +       accepted due to an error action in a later state. +  */ +  if (yyctx->yytoken != YYSYMBOL_YYEMPTY) +    { +      int yyn; +      if (yyarg) +        yyarg[yycount] = yyctx->yytoken; +      ++yycount; +      yyn = yypcontext_expected_tokens (yyctx, +                                        yyarg ? yyarg + 1 : yyarg, yyargn - 1); +      if (yyn == YYENOMEM) +        return YYENOMEM; +      else +        yycount += yyn; +    } +  return yycount; +} + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message +   about the unexpected token YYTOKEN for the state stack whose top is +   YYSSP. + +   Return 0 if *YYMSG was successfully written.  Return -1 if *YYMSG is +   not large enough to hold the message.  In that case, also set +   *YYMSG_ALLOC to the required number of bytes.  Return YYENOMEM if the +   required number of bytes is too large to store.  */ +static int +yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg, +                const yypcontext_t *yyctx) +{ +  enum { YYARGS_MAX = 5 }; +  /* Internationalized format string. */ +  const char *yyformat = YY_NULLPTR; +  /* Arguments of yyformat: reported tokens (one for the "unexpected", +     one per "expected"). */ +  yysymbol_kind_t yyarg[YYARGS_MAX]; +  /* Cumulated lengths of YYARG.  */ +  YYPTRDIFF_T yysize = 0; + +  /* Actual size of YYARG. */ +  int yycount = yy_syntax_error_arguments (yyctx, yyarg, YYARGS_MAX); +  if (yycount == YYENOMEM) +    return YYENOMEM; + +  switch (yycount) +    { +#define YYCASE_(N, S)                       \ +      case N:                               \ +        yyformat = S;                       \ +        break +    default: /* Avoid compiler warnings. */ +      YYCASE_(0, YY_("syntax error")); +      YYCASE_(1, YY_("syntax error, unexpected %s")); +      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); +      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); +      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); +      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +#undef YYCASE_ +    } + +  /* Compute error message size.  Don't count the "%s"s, but reserve +     room for the terminator.  */ +  yysize = yystrlen (yyformat) - 2 * yycount + 1; +  { +    int yyi; +    for (yyi = 0; yyi < yycount; ++yyi) +      { +        YYPTRDIFF_T yysize1 +          = yysize + yytnamerr (YY_NULLPTR, yytname[yyarg[yyi]]); +        if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) +          yysize = yysize1; +        else +          return YYENOMEM; +      } +  } + +  if (*yymsg_alloc < yysize) +    { +      *yymsg_alloc = 2 * yysize; +      if (! (yysize <= *yymsg_alloc +             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) +        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; +      return -1; +    } + +  /* Avoid sprintf, as that infringes on the user's name space. +     Don't have undefined behavior even if the translation +     produced a string with the wrong number of "%s"s.  */ +  { +    char *yyp = *yymsg; +    int yyi = 0; +    while ((*yyp = *yyformat) != '\0') +      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) +        { +          yyp += yytnamerr (yyp, yytname[yyarg[yyi++]]); +          yyformat += 2; +        } +      else +        { +          ++yyp; +          ++yyformat; +        } +  } +  return 0; +} + + +/*-----------------------------------------------. +| Release the memory associated to this symbol.  | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, +            yysymbol_kind_t yykind, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, yyscan_t scanner, struct kai_tag_t **document) +{ +  YY_USE (yyvaluep); +  YY_USE (yylocationp); +  YY_USE (scanner); +  YY_USE (document); +  if (!yymsg) +    yymsg = "Deleting"; +  YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); + +  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +  YY_USE (yykind); +  YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + + + + + +/*----------. +| yyparse.  | +`----------*/ + +int +yyparse (yyscan_t scanner, struct kai_tag_t **document) +{ +/* Lookahead token kind.  */ +int yychar; + + +/* The semantic value of the lookahead symbol.  */ +/* Default value used for initialization, for pacifying older GCCs +   or non-GCC compilers.  */ +YY_INITIAL_VALUE (static YYSTYPE yyval_default;) +YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); + +/* Location data for the lookahead symbol.  */ +static YYLTYPE yyloc_default +# if defined KALMIALTYPE_IS_TRIVIAL && KALMIALTYPE_IS_TRIVIAL +  = { 1, 1, 1, 1 } +# endif +; +YYLTYPE yylloc = yyloc_default; + +    /* Number of syntax errors so far.  */ +    int yynerrs = 0; + +    yy_state_fast_t yystate = 0; +    /* Number of tokens to shift before error messages enabled.  */ +    int yyerrstatus = 0; + +    /* Refer to the stacks through separate pointers, to allow yyoverflow +       to reallocate them elsewhere.  */ + +    /* Their size.  */ +    YYPTRDIFF_T yystacksize = YYINITDEPTH; + +    /* The state stack: array, bottom, top.  */ +    yy_state_t yyssa[YYINITDEPTH]; +    yy_state_t *yyss = yyssa; +    yy_state_t *yyssp = yyss; + +    /* The semantic value stack: array, bottom, top.  */ +    YYSTYPE yyvsa[YYINITDEPTH]; +    YYSTYPE *yyvs = yyvsa; +    YYSTYPE *yyvsp = yyvs; + +    /* The location stack: array, bottom, top.  */ +    YYLTYPE yylsa[YYINITDEPTH]; +    YYLTYPE *yyls = yylsa; +    YYLTYPE *yylsp = yyls; + +  int yyn; +  /* The return value of yyparse.  */ +  int yyresult; +  /* Lookahead symbol kind.  */ +  yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; +  /* The variables used to return semantic value and location from the +     action routines.  */ +  YYSTYPE yyval; +  YYLTYPE yyloc; + +  /* The locations where the error started and ended.  */ +  YYLTYPE yyerror_range[3]; + +  /* Buffer for error messages, and its allocated size.  */ +  char yymsgbuf[128]; +  char *yymsg = yymsgbuf; +  YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf; + +#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) + +  /* The number of symbols on the RHS of the reduced rule. +     Keep to zero when no symbol should be popped.  */ +  int yylen = 0; + +  YYDPRINTF ((stderr, "Starting parse\n")); + +  yychar = KALMIAEMPTY; /* Cause a token to be read.  */ + +  yylsp[0] = yylloc; +  goto yysetstate; + + +/*------------------------------------------------------------. +| yynewstate -- push a new state, which is found in yystate.  | +`------------------------------------------------------------*/ +yynewstate: +  /* In all cases, when you get here, the value and location stacks +     have just been pushed.  So pushing a state here evens the stacks.  */ +  yyssp++; + + +/*--------------------------------------------------------------------. +| yysetstate -- set current state (the top of the stack) to yystate.  | +`--------------------------------------------------------------------*/ +yysetstate: +  YYDPRINTF ((stderr, "Entering state %d\n", yystate)); +  YY_ASSERT (0 <= yystate && yystate < YYNSTATES); +  YY_IGNORE_USELESS_CAST_BEGIN +  *yyssp = YY_CAST (yy_state_t, yystate); +  YY_IGNORE_USELESS_CAST_END +  YY_STACK_PRINT (yyss, yyssp); + +  if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE +    YYNOMEM; +#else +    { +      /* Get the current used size of the three stacks, in elements.  */ +      YYPTRDIFF_T yysize = yyssp - yyss + 1; + +# if defined yyoverflow +      { +        /* Give user a chance to reallocate the stack.  Use copies of +           these so that the &'s don't force the real ones into +           memory.  */ +        yy_state_t *yyss1 = yyss; +        YYSTYPE *yyvs1 = yyvs; +        YYLTYPE *yyls1 = yyls; + +        /* Each stack pointer address is followed by the size of the +           data in use in that stack, in bytes.  This used to be a +           conditional around just the two extra args, but that might +           be undefined if yyoverflow is a macro.  */ +        yyoverflow (YY_("memory exhausted"), +                    &yyss1, yysize * YYSIZEOF (*yyssp), +                    &yyvs1, yysize * YYSIZEOF (*yyvsp), +                    &yyls1, yysize * YYSIZEOF (*yylsp), +                    &yystacksize); +        yyss = yyss1; +        yyvs = yyvs1; +        yyls = yyls1; +      } +# else /* defined YYSTACK_RELOCATE */ +      /* Extend the stack our own way.  */ +      if (YYMAXDEPTH <= yystacksize) +        YYNOMEM; +      yystacksize *= 2; +      if (YYMAXDEPTH < yystacksize) +        yystacksize = YYMAXDEPTH; + +      { +        yy_state_t *yyss1 = yyss; +        union yyalloc *yyptr = +          YY_CAST (union yyalloc *, +                   YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); +        if (! yyptr) +          YYNOMEM; +        YYSTACK_RELOCATE (yyss_alloc, yyss); +        YYSTACK_RELOCATE (yyvs_alloc, yyvs); +        YYSTACK_RELOCATE (yyls_alloc, yyls); +#  undef YYSTACK_RELOCATE +        if (yyss1 != yyssa) +          YYSTACK_FREE (yyss1); +      } +# endif + +      yyssp = yyss + yysize - 1; +      yyvsp = yyvs + yysize - 1; +      yylsp = yyls + yysize - 1; + +      YY_IGNORE_USELESS_CAST_BEGIN +      YYDPRINTF ((stderr, "Stack size increased to %ld\n", +                  YY_CAST (long, yystacksize))); +      YY_IGNORE_USELESS_CAST_END + +      if (yyss + yystacksize - 1 <= yyssp) +        YYABORT; +    } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ + + +  if (yystate == YYFINAL) +    YYACCEPT; + +  goto yybackup; + + +/*-----------. +| yybackup.  | +`-----------*/ +yybackup: +  /* Do appropriate processing given the current state.  Read a +     lookahead token if we need one and don't already have one.  */ + +  /* First try to decide what to do without reference to lookahead token.  */ +  yyn = yypact[yystate]; +  if (yypact_value_is_default (yyn)) +    goto yydefault; + +  /* Not known => get a lookahead token if don't already have one.  */ + +  /* YYCHAR is either empty, or end-of-input, or a valid lookahead.  */ +  if (yychar == KALMIAEMPTY) +    { +      YYDPRINTF ((stderr, "Reading a token\n")); +      yychar = yylex (&yylval, &yylloc, scanner); +    } + +  if (yychar <= KALMIAEOF) +    { +      yychar = KALMIAEOF; +      yytoken = YYSYMBOL_YYEOF; +      YYDPRINTF ((stderr, "Now at end of input.\n")); +    } +  else if (yychar == KALMIAerror) +    { +      /* The scanner already issued an error message, process directly +         to error recovery.  But do not keep the error token as +         lookahead, it is too special and may lead us to an endless +         loop in error recovery. */ +      yychar = KALMIAUNDEF; +      yytoken = YYSYMBOL_YYerror; +      yyerror_range[1] = yylloc; +      goto yyerrlab1; +    } +  else +    { +      yytoken = YYTRANSLATE (yychar); +      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); +    } + +  /* If the proper action on seeing token YYTOKEN is to reduce or to +     detect an error, take that action.  */ +  yyn += yytoken; +  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) +    goto yydefault; +  yyn = yytable[yyn]; +  if (yyn <= 0) +    { +      if (yytable_value_is_error (yyn)) +        goto yyerrlab; +      yyn = -yyn; +      goto yyreduce; +    } + +  /* Count tokens shifted since error; after three, turn off error +     status.  */ +  if (yyerrstatus) +    yyerrstatus--; + +  /* Shift the lookahead token.  */ +  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); +  yystate = yyn; +  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +  *++yyvsp = yylval; +  YY_IGNORE_MAYBE_UNINITIALIZED_END +  *++yylsp = yylloc; + +  /* Discard the shifted token.  */ +  yychar = KALMIAEMPTY; +  goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state.  | +`-----------------------------------------------------------*/ +yydefault: +  yyn = yydefact[yystate]; +  if (yyn == 0) +    goto yyerrlab; +  goto yyreduce; + + +/*-----------------------------. +| yyreduce -- do a reduction.  | +`-----------------------------*/ +yyreduce: +  /* yyn is the number of a rule to reduce with.  */ +  yylen = yyr2[yyn]; + +  /* If YYLEN is nonzero, implement the default value of the action: +     '$$ = $1'. + +     Otherwise, the following line sets YYVAL to garbage. +     This behavior is undocumented and Bison +     users should not rely upon it.  Assigning to YYVAL +     unconditionally makes the parser a bit smaller, and it avoids a +     GCC warning that YYVAL may be used uninitialized.  */ +  yyval = yyvsp[1-yylen]; + +  /* Default location. */ +  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); +  yyerror_range[1] = yyloc; +  YY_REDUCE_PRINT (yyn); +  switch (yyn) +    { +  case 2: /* document: PROLOG tag  */ +#line 94 "kalmia.y" +                     { *document = (yyvsp[0].tag); } +#line 1531 "kalmia.tab.c" +    break; + +  case 3: /* tags: tag  */ +#line 98 "kalmia.y" +            { (yyval.tag) = (yyvsp[0].tag); } +#line 1537 "kalmia.tab.c" +    break; + +  case 4: /* tags: tags tag  */ +#line 99 "kalmia.y" +                   { (yyval.tag) = (yyvsp[-1].tag); kai_tag_last((yyval.tag))->next = (yyvsp[0].tag); } +#line 1543 "kalmia.tab.c" +    break; + +  case 5: /* tag: start_tag end_tag  */ +#line 105 "kalmia.y" +        {  +		(yyval.tag) = (yyvsp[-1].tag);  +		if (strcmp((yyval.tag)->type, (yyvsp[0].string)) != 0) TAG_MISMATCH((yyval.tag)->type, (yyvsp[0].string));  +		free((yyvsp[0].string));  +	} +#line 1553 "kalmia.tab.c" +    break; + +  case 6: /* tag: start_tag CONTENT end_tag  */ +#line 111 "kalmia.y" +        {  +		(yyval.tag) = (yyvsp[-2].tag);  +		(yyval.tag)->content = (yyvsp[-1].string); +		if (strcmp((yyval.tag)->type, (yyvsp[0].string)) != 0) TAG_MISMATCH((yyval.tag)->type, (yyvsp[0].string)); +		free((yyvsp[0].string));  +	} +#line 1564 "kalmia.tab.c" +    break; + +  case 7: /* tag: start_tag tags end_tag  */ +#line 118 "kalmia.y" +        {  +		(yyval.tag) = (yyvsp[-2].tag);  +		(yyval.tag)->children = (yyvsp[-1].tag); +		if (strcmp((yyval.tag)->type, (yyvsp[0].string)) != 0) TAG_MISMATCH((yyval.tag)->type, (yyvsp[0].string)); +		free((yyvsp[0].string));  +	} +#line 1575 "kalmia.tab.c" +    break; + +  case 8: /* tag: empty_tag  */ +#line 124 "kalmia.y" +                    { (yyval.tag) = (yyvsp[0].tag); } +#line 1581 "kalmia.tab.c" +    break; + +  case 9: /* start_tag: S_TAG_OPEN NAME TAG_CLOSE  */ +#line 129 "kalmia.y" +        { +		(yyval.tag) = kai_tag_new((yyvsp[-1].string), NULL); +		if ((yyval.tag) == NULL) YYNOMEM; +	} +#line 1590 "kalmia.tab.c" +    break; + +  case 10: /* start_tag: S_TAG_OPEN NAME attributes TAG_CLOSE  */ +#line 134 "kalmia.y" +        { +		(yyval.tag) = kai_tag_new((yyvsp[-2].string), (yyvsp[-1].attr)); +		if ((yyval.tag) == NULL) YYNOMEM; +	} +#line 1599 "kalmia.tab.c" +    break; + +  case 11: /* empty_tag: S_TAG_OPEN NAME EMPTY_TAG_CLOSE  */ +#line 143 "kalmia.y" +        { +		(yyval.tag) = kai_tag_new((yyvsp[-1].string), NULL); +		if ((yyval.tag) == NULL) YYNOMEM; +	} +#line 1608 "kalmia.tab.c" +    break; + +  case 12: /* empty_tag: S_TAG_OPEN NAME attributes EMPTY_TAG_CLOSE  */ +#line 148 "kalmia.y" +        { +		(yyval.tag) = kai_tag_new((yyvsp[-2].string), (yyvsp[-1].attr)); +		if ((yyval.tag) == NULL) YYNOMEM; +	} +#line 1617 "kalmia.tab.c" +    break; + +  case 13: /* end_tag: E_TAG_OPEN NAME TAG_CLOSE  */ +#line 156 "kalmia.y" +                                  { (yyval.string) = (yyvsp[-1].string); } +#line 1623 "kalmia.tab.c" +    break; + +  case 14: /* attributes: attribute  */ +#line 161 "kalmia.y" +                  { (yyval.attr) = (yyvsp[0].attr); } +#line 1629 "kalmia.tab.c" +    break; + +  case 15: /* attributes: attributes attribute  */ +#line 162 "kalmia.y" +                               { (yyval.attr) = (yyvsp[-1].attr); kai_attr_last((yyval.attr))->next = (yyvsp[0].attr); } +#line 1635 "kalmia.tab.c" +    break; + +  case 16: /* attribute: ATTR '=' '"' TEXT '"'  */ +#line 167 "kalmia.y" +        {  +		(yyval.attr) = kai_attr_new((yyvsp[-4].string), (yyvsp[-1].string)); +		if ((yyval.attr) == NULL) YYNOMEM; +	} +#line 1644 "kalmia.tab.c" +    break; + + +#line 1648 "kalmia.tab.c" + +      default: break; +    } +  /* User semantic actions sometimes alter yychar, and that requires +     that yytoken be updated with the new translation.  We take the +     approach of translating immediately before every use of yytoken. +     One alternative is translating here after every semantic action, +     but that translation would be missed if the semantic action invokes +     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or +     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an +     incorrect destructor might then be invoked immediately.  In the +     case of YYERROR or YYBACKUP, subsequent parser actions might lead +     to an incorrect destructor call or verbose syntax error message +     before the lookahead is translated.  */ +  YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); + +  YYPOPSTACK (yylen); +  yylen = 0; + +  *++yyvsp = yyval; +  *++yylsp = yyloc; + +  /* Now 'shift' the result of the reduction.  Determine what state +     that goes to, based on the state we popped back to and the rule +     number reduced by.  */ +  { +    const int yylhs = yyr1[yyn] - YYNTOKENS; +    const int yyi = yypgoto[yylhs] + *yyssp; +    yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp +               ? yytable[yyi] +               : yydefgoto[yylhs]); +  } + +  goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error.  | +`--------------------------------------*/ +yyerrlab: +  /* Make sure we have latest lookahead translation.  See comments at +     user semantic actions for why this is necessary.  */ +  yytoken = yychar == KALMIAEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); +  /* If not already recovering from an error, report this error.  */ +  if (!yyerrstatus) +    { +      ++yynerrs; +      { +        yypcontext_t yyctx +          = {yyssp, yytoken, &yylloc}; +        char const *yymsgp = YY_("syntax error"); +        int yysyntax_error_status; +        yysyntax_error_status = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx); +        if (yysyntax_error_status == 0) +          yymsgp = yymsg; +        else if (yysyntax_error_status == -1) +          { +            if (yymsg != yymsgbuf) +              YYSTACK_FREE (yymsg); +            yymsg = YY_CAST (char *, +                             YYSTACK_ALLOC (YY_CAST (YYSIZE_T, yymsg_alloc))); +            if (yymsg) +              { +                yysyntax_error_status +                  = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx); +                yymsgp = yymsg; +              } +            else +              { +                yymsg = yymsgbuf; +                yymsg_alloc = sizeof yymsgbuf; +                yysyntax_error_status = YYENOMEM; +              } +          } +        yyerror (&yylloc, scanner, document, yymsgp); +        if (yysyntax_error_status == YYENOMEM) +          YYNOMEM; +      } +    } + +  yyerror_range[1] = yylloc; +  if (yyerrstatus == 3) +    { +      /* If just tried and failed to reuse lookahead token after an +         error, discard it.  */ + +      if (yychar <= KALMIAEOF) +        { +          /* Return failure if at end of input.  */ +          if (yychar == KALMIAEOF) +            YYABORT; +        } +      else +        { +          yydestruct ("Error: discarding", +                      yytoken, &yylval, &yylloc, scanner, document); +          yychar = KALMIAEMPTY; +        } +    } + +  /* Else will try to reuse lookahead token after shifting the error +     token.  */ +  goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR.  | +`---------------------------------------------------*/ +yyerrorlab: +  /* Pacify compilers when the user code never invokes YYERROR and the +     label yyerrorlab therefore never appears in user code.  */ +  if (0) +    YYERROR; +  ++yynerrs; + +  /* Do not reclaim the symbols of the rule whose action triggered +     this YYERROR.  */ +  YYPOPSTACK (yylen); +  yylen = 0; +  YY_STACK_PRINT (yyss, yyssp); +  yystate = *yyssp; +  goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR.  | +`-------------------------------------------------------------*/ +yyerrlab1: +  yyerrstatus = 3;      /* Each real token shifted decrements this.  */ + +  /* Pop stack until we find a state that shifts the error token.  */ +  for (;;) +    { +      yyn = yypact[yystate]; +      if (!yypact_value_is_default (yyn)) +        { +          yyn += YYSYMBOL_YYerror; +          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) +            { +              yyn = yytable[yyn]; +              if (0 < yyn) +                break; +            } +        } + +      /* Pop the current state because it cannot handle the error token.  */ +      if (yyssp == yyss) +        YYABORT; + +      yyerror_range[1] = *yylsp; +      yydestruct ("Error: popping", +                  YY_ACCESSING_SYMBOL (yystate), yyvsp, yylsp, scanner, document); +      YYPOPSTACK (1); +      yystate = *yyssp; +      YY_STACK_PRINT (yyss, yyssp); +    } + +  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +  *++yyvsp = yylval; +  YY_IGNORE_MAYBE_UNINITIALIZED_END + +  yyerror_range[2] = yylloc; +  ++yylsp; +  YYLLOC_DEFAULT (*yylsp, yyerror_range, 2); + +  /* Shift the error token.  */ +  YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); + +  yystate = yyn; +  goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here.  | +`-------------------------------------*/ +yyacceptlab: +  yyresult = 0; +  goto yyreturnlab; + + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here.  | +`-----------------------------------*/ +yyabortlab: +  yyresult = 1; +  goto yyreturnlab; + + +/*-----------------------------------------------------------. +| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here.  | +`-----------------------------------------------------------*/ +yyexhaustedlab: +  yyerror (&yylloc, scanner, document, YY_("memory exhausted")); +  yyresult = 2; +  goto yyreturnlab; + + +/*----------------------------------------------------------. +| yyreturnlab -- parsing is finished, clean up and return.  | +`----------------------------------------------------------*/ +yyreturnlab: +  if (yychar != KALMIAEMPTY) +    { +      /* Make sure we have latest lookahead translation.  See comments at +         user semantic actions for why this is necessary.  */ +      yytoken = YYTRANSLATE (yychar); +      yydestruct ("Cleanup: discarding lookahead", +                  yytoken, &yylval, &yylloc, scanner, document); +    } +  /* Do not reclaim the symbols of the rule whose action triggered +     this YYABORT or YYACCEPT.  */ +  YYPOPSTACK (yylen); +  YY_STACK_PRINT (yyss, yyssp); +  while (yyssp != yyss) +    { +      yydestruct ("Cleanup: popping", +                  YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, yylsp, scanner, document); +      YYPOPSTACK (1); +    } +#ifndef yyoverflow +  if (yyss != yyssa) +    YYSTACK_FREE (yyss); +#endif +  if (yymsg != yymsgbuf) +    YYSTACK_FREE (yymsg); +  return yyresult; +} + +#line 174 "kalmia.y" + + + +/* print an error message */ +int yyerror( +	YYLTYPE *yyllocp,  +	yyscan_t unused,  +	struct kai_tag_t **unused2,  +	const char *msg) +{ +	fprintf( +		stderr, "[%d:%d]: %s\n", +		yyllocp->first_line, yyllocp->first_column, msg +	); +	return 1; +} + + + +/* create a new kai_attr_t object */ +struct kai_attr_t * kai_attr_new(char *key, char *value) +{ +	struct kai_attr_t *attr = malloc(sizeof(struct kai_attr_t)); +	if (attr == NULL) { +		return NULL; +	} +	attr->key = key; +	attr->value = value; +	attr->next = NULL; +	return attr; +} + +/* get the end of a kai_attr_t list */ +struct kai_attr_t * kai_attr_last(struct kai_attr_t *head) +{ +	struct kai_attr_t *ptr = head; +	while (ptr->next != NULL) { +		ptr = ptr->next; +	} +	return ptr; +} + +/* destroy a kai_attr_t list */ +void kai_attr_destroy(struct kai_attr_t *attr) +{ +	if (attr == NULL) { +		return; +	} + +	kai_attr_destroy(attr->next); +	free(attr->key); +	free(attr->value); +	free(attr); +} + + + +/* create a kai_tag_t object */ +struct kai_tag_t * kai_tag_new(char *type, struct kai_attr_t *attrs) +{ +	struct kai_tag_t *tag = malloc(sizeof(struct kai_tag_t)); +	if (tag == NULL) { +		return NULL; +	} + +	tag->type = type; +	tag->attrs = attrs; +	tag->children = NULL; +	tag->content = NULL; +	tag->next = NULL; +	return tag; +} + +/* get the end of a kai_tag_t list */ +struct kai_tag_t * kai_tag_last(struct kai_tag_t *head) +{ +	struct kai_tag_t *ptr = head; +	while (ptr->next != NULL) { +		ptr = ptr->next; +	} +	return ptr; +} + +/* destroy a kai_tag_t list */ +void kai_tag_destroy(struct kai_tag_t *tag) +{ +	if (tag == NULL) { +		return; +	} + +	free(tag->type); +	kai_attr_destroy(tag->attrs); +	kai_tag_destroy(tag->children); +	free(tag->content); +	kai_tag_destroy(tag->next); +	free(tag); +} + + + +/* parse a file into a document */ +struct kai_tag_t * kai_parse_file(const char *filename) +{ +	FILE *file = fopen(filename, "r"); +	if (file == NULL) { +		fprintf(stderr, "Could not open file \"%s\"\n", filename); +		return NULL; +	} + +	yyscan_t scanner; +	struct kai_tag_t *document; + +	kalmialex_init(&scanner); +	kalmiaset_in(file, scanner); +	int result = kalmiaparse(scanner, &document); +	kalmialex_destroy(scanner); +	fclose(file); + +	if (result != 0) { +		/* parse function will print error message */ +		return NULL; +	} + +	return document; +} diff --git a/src/xml/kalmia.tab.h b/src/xml/kalmia.tab.h new file mode 100644 index 0000000..987ac6c --- /dev/null +++ b/src/xml/kalmia.tab.h @@ -0,0 +1,141 @@ +/* A Bison parser, made by GNU Bison 3.8.2.  */ + +/* Bison interface for Yacc-like parsers in C + +   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, +   Inc. + +   This program is free software: you can redistribute it and/or modify +   it under the terms of the GNU General Public License as published by +   the Free Software Foundation, either version 3 of the License, or +   (at your option) any later version. + +   This program is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */ + +/* As a special exception, you may create a larger work that contains +   part or all of the Bison parser skeleton and distribute that work +   under terms of your choice, so long as that work isn't itself a +   parser generator using the skeleton or a modified version thereof +   as a parser skeleton.  Alternatively, if you modify or redistribute +   the parser skeleton itself, you may (at your option) remove this +   special exception, which will cause the skeleton and the resulting +   Bison output files to be licensed under the GNU General Public +   License without this special exception. + +   This special exception was added by the Free Software Foundation in +   version 2.2 of Bison.  */ + +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, +   especially those whose name start with YY_ or yy_.  They are +   private implementation details that can be changed or removed.  */ + +#ifndef YY_KALMIA_KALMIA_TAB_H_INCLUDED +# define YY_KALMIA_KALMIA_TAB_H_INCLUDED +/* Debug traces.  */ +#ifndef KALMIADEBUG +# if defined YYDEBUG +#if YYDEBUG +#   define KALMIADEBUG 1 +#  else +#   define KALMIADEBUG 0 +#  endif +# else /* ! defined YYDEBUG */ +#  define KALMIADEBUG 0 +# endif /* ! defined YYDEBUG */ +#endif  /* ! defined KALMIADEBUG */ +#if KALMIADEBUG +extern int kalmiadebug; +#endif +/* "%code requires" blocks.  */ +#line 13 "kalmia.y" + +	typedef void* yyscan_t; + +	struct kai_attr_t { +		char *key; +		char *value; +		struct kai_attr_t *next; +	}; + +	struct kai_tag_t { +		char *type; +		struct kai_attr_t *attrs; + +		struct kai_tag_t *children; +		char *content; + +		struct kai_tag_t *next; +	}; + +	struct kai_tag_t * kai_parse_file(const char *filename); +	void kai_tag_destroy(struct kai_tag_t *tag); + +#line 80 "kalmia.tab.h" + +/* Token kinds.  */ +#ifndef KALMIATOKENTYPE +# define KALMIATOKENTYPE +  enum kalmiatokentype +  { +    KALMIAEMPTY = -2, +    KALMIAEOF = 0,                 /* "end of file"  */ +    KALMIAerror = 256,             /* error  */ +    KALMIAUNDEF = 257,             /* "invalid token"  */ +    PROLOG = 258,                  /* PROLOG  */ +    S_TAG_OPEN = 259,              /* S_TAG_OPEN  */ +    E_TAG_OPEN = 260,              /* E_TAG_OPEN  */ +    TAG_CLOSE = 261,               /* TAG_CLOSE  */ +    EMPTY_TAG_CLOSE = 262,         /* EMPTY_TAG_CLOSE  */ +    NAME = 263,                    /* NAME  */ +    ATTR = 264,                    /* ATTR  */ +    TEXT = 265,                    /* TEXT  */ +    CONTENT = 266                  /* CONTENT  */ +  }; +  typedef enum kalmiatokentype kalmiatoken_kind_t; +#endif + +/* Value type.  */ +#if ! defined KALMIASTYPE && ! defined KALMIASTYPE_IS_DECLARED +union KALMIASTYPE +{ +#line 65 "kalmia.y" + +	char *string; +	struct kai_attr_t *attr; +	struct kai_tag_t *tag; + +#line 114 "kalmia.tab.h" + +}; +typedef union KALMIASTYPE KALMIASTYPE; +# define KALMIASTYPE_IS_TRIVIAL 1 +# define KALMIASTYPE_IS_DECLARED 1 +#endif + +/* Location type.  */ +#if ! defined KALMIALTYPE && ! defined KALMIALTYPE_IS_DECLARED +typedef struct KALMIALTYPE KALMIALTYPE; +struct KALMIALTYPE +{ +  int first_line; +  int first_column; +  int last_line; +  int last_column; +}; +# define KALMIALTYPE_IS_DECLARED 1 +# define KALMIALTYPE_IS_TRIVIAL 1 +#endif + + + + +int kalmiaparse (yyscan_t scanner, struct kai_tag_t **document); + + +#endif /* !YY_KALMIA_KALMIA_TAB_H_INCLUDED  */ diff --git a/src/xml/xml.c b/src/xml/xml.c new file mode 100644 index 0000000..e2aa008 --- /dev/null +++ b/src/xml/xml.c @@ -0,0 +1,20 @@ +#include "xml.h" + +/* parse a string into a document */ +struct kai_tag_t * kai_parse_string(const char *str) +{ +	yyscan_t scanner; +	struct kai_tag_t *document; + +	kalmialex_init(&scanner); +	YY_BUFFER_STATE buf = kalmia_scan_string(str, scanner); +	int result = kalmiaparse(scanner, &document); +	kalmia_delete_buffer(buf, scanner); +	kalmialex_destroy(scanner); + +	if (result != 0) { +		return NULL; +	} + +	return document; +} diff --git a/src/xml/xml.h b/src/xml/xml.h new file mode 100644 index 0000000..238177e --- /dev/null +++ b/src/xml/xml.h @@ -0,0 +1,11 @@ +#ifndef KALMIA_XML_H +#define KALMIA_XML_H + +#define YYLTYPE KALMIALTYPE +#define YYSTYPE KALMIASTYPE +#include "xml/kalmia.tab.h" +#include "xml/kalmia.lex.h" + +struct kai_tag_t * kai_parse_string(const char *str); + +#endif diff --git a/yy/makefile b/yy/makefile index a2022a2..6567b56 100644 --- a/yy/makefile +++ b/yy/makefile @@ -1,6 +1,6 @@  WARNINGS = -Wall -Wextra -Wpedantic -all: kalmia +all: kalmia.tab.c kalmia.lex.c  kalmia.tab.c: kalmia.y  	bison -o "$@" --header=kalmia.tab.h kalmia.y @@ -8,8 +8,8 @@ kalmia.tab.c: kalmia.y  kalmia.lex.c: kalmia.l  	flex -o "$@" --header-file="kalmia.lex.h" kalmia.l -kalmia: kalmia.tab.c kalmia.lex.c main.c -	gcc -g -o kalmia ${WARNINGS} main.c kalmia.tab.c kalmia.lex.c  +demo: kalmia.tab.c kalmia.lex.c demo.c +	gcc -g -o demo ${WARNINGS} demo.c kalmia.tab.c kalmia.lex.c   clean: -	rm kalmia.lex.c kalmia.lex.h kalmia.tab.c kalmia.tab.h kalmia +	rm kalmia.lex.c kalmia.lex.h kalmia.tab.c kalmia.tab.h demo  | 
