17ec681f3Smrg/* 27ec681f3Smrg * Copyright (C) 2010-2011 Marcin Kościelnicki <koriakin@0x04.net> 37ec681f3Smrg * Copyright (C) 2010 Luca Barbieri <luca@luca-barbieri.com> 47ec681f3Smrg * Copyright (C) 2010 Francisco Jerez <currojerez@riseup.net> 57ec681f3Smrg * Copyright (C) 2010 Martin Peres <martin.peres@ensi-bourges.fr> 67ec681f3Smrg * Copyright (C) 2010 Marcin Slusarz <marcin.slusarz@gmail.com> 77ec681f3Smrg * All Rights Reserved. 87ec681f3Smrg * 97ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 107ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 117ec681f3Smrg * to deal in the Software without restriction, including without limitation 127ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 137ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 147ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 157ec681f3Smrg * 167ec681f3Smrg * The above copyright notice and this permission notice (including the next 177ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 187ec681f3Smrg * Software. 197ec681f3Smrg * 207ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 217ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 227ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 237ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 247ec681f3Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 257ec681f3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 267ec681f3Smrg * OTHER DEALINGS IN THE SOFTWARE. 277ec681f3Smrg */ 287ec681f3Smrg 297ec681f3Smrg/* workaround libxml2 silliness: */ 307ec681f3Smrg#pragma GCC diagnostic ignored "-Wpointer-sign" 317ec681f3Smrg 327ec681f3Smrg#include <libxml/xmlversion.h> 337ec681f3Smrg#include <libxml/parser.h> 347ec681f3Smrg#include <libxml/xpath.h> 357ec681f3Smrg#include <libxml/xmlreader.h> 367ec681f3Smrg#include <stdint.h> 377ec681f3Smrg#include <string.h> 387ec681f3Smrg#include <limits.h> 397ec681f3Smrg#include <ctype.h> 407ec681f3Smrg#include <stdio.h> 417ec681f3Smrg#include "rnn.h" 427ec681f3Smrg#include "util.h" 437ec681f3Smrg 447ec681f3Smrg#include "util/u_debug.h" 457ec681f3Smrg 467ec681f3Smrgstatic char *catstr (char *a, char *b) { 477ec681f3Smrg if (!a) 487ec681f3Smrg return b; 497ec681f3Smrg return aprintf("%s_%s", a, b); 507ec681f3Smrg} 517ec681f3Smrg 527ec681f3Smrgstatic int strdiff (const char *a, const char *b) { 537ec681f3Smrg if (!a && !b) 547ec681f3Smrg return 0; 557ec681f3Smrg if (!a || !b) 567ec681f3Smrg return 1; 577ec681f3Smrg return strcmp (a, b); 587ec681f3Smrg} 597ec681f3Smrg 607ec681f3Smrgstatic void rnn_err(struct rnndb *db, const char *format, ...) _util_printf_format(2, 3); 617ec681f3Smrg 627ec681f3Smrgstatic void rnn_err(struct rnndb *db, const char *format, ...) 637ec681f3Smrg{ 647ec681f3Smrg va_list ap; 657ec681f3Smrg va_start(ap, format); 667ec681f3Smrg vfprintf(stderr, format, ap); 677ec681f3Smrg va_end(ap); 687ec681f3Smrg db->estatus = 1; 697ec681f3Smrg} 707ec681f3Smrg 717ec681f3Smrgvoid rnn_init(void) { 727ec681f3Smrg LIBXML_TEST_VERSION 737ec681f3Smrg xmlInitParser(); 747ec681f3Smrg} 757ec681f3Smrg 767ec681f3Smrgstruct rnndb *rnn_newdb(void) { 777ec681f3Smrg struct rnndb *db = calloc(sizeof *db, 1); 787ec681f3Smrg return db; 797ec681f3Smrg} 807ec681f3Smrg 817ec681f3Smrgstatic char *getcontent (xmlNode *attr) { 827ec681f3Smrg xmlNode *chain = attr->children; 837ec681f3Smrg size_t size = 0; 847ec681f3Smrg char *content, *p; 857ec681f3Smrg while (chain) { 867ec681f3Smrg if (chain->type == XML_TEXT_NODE) 877ec681f3Smrg size += strlen(chain->content); 887ec681f3Smrg chain = chain->next; 897ec681f3Smrg } 907ec681f3Smrg p = content = malloc(size + 1); 917ec681f3Smrg chain = attr->children; 927ec681f3Smrg while (chain) { 937ec681f3Smrg if (chain->type == XML_TEXT_NODE) { 947ec681f3Smrg char* sp = chain->content; 957ec681f3Smrg if(p == content) { 967ec681f3Smrg while(isspace(*sp)) 977ec681f3Smrg ++sp; 987ec681f3Smrg } 997ec681f3Smrg size_t len = strlen(sp); 1007ec681f3Smrg memcpy(p, sp, len); 1017ec681f3Smrg p += len; 1027ec681f3Smrg } 1037ec681f3Smrg chain = chain->next; 1047ec681f3Smrg } 1057ec681f3Smrg while(p != content && isspace(p[-1])) 1067ec681f3Smrg --p; 1077ec681f3Smrg *p = 0; 1087ec681f3Smrg return content; 1097ec681f3Smrg} 1107ec681f3Smrg 1117ec681f3Smrgstatic char *getattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) { 1127ec681f3Smrg xmlNode *chain = attr->children; 1137ec681f3Smrg while (chain) { 1147ec681f3Smrg if (chain->type != XML_TEXT_NODE) { 1157ec681f3Smrg rnn_err(db, "%s:%d: unknown attribute child \"%s\" in attribute \"%s\"\n", file, line, chain->name, attr->name); 1167ec681f3Smrg } else { 1177ec681f3Smrg return chain->content; 1187ec681f3Smrg } 1197ec681f3Smrg chain = chain->next; 1207ec681f3Smrg } 1217ec681f3Smrg return ""; 1227ec681f3Smrg} 1237ec681f3Smrg 1247ec681f3Smrgstatic int getboolattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) { 1257ec681f3Smrg char *c = getattrib(db, file, line, attr); 1267ec681f3Smrg if (!strcmp(c, "yes") || !strcmp(c, "1") || !strcmp(c, "true")) 1277ec681f3Smrg return 1; 1287ec681f3Smrg if (!strcmp(c, "no") || !strcmp(c, "0") || !strcmp(c, "false")) 1297ec681f3Smrg return 0; 1307ec681f3Smrg rnn_err(db, "%s:%d: invalid boolean value \"%s\" in attribute \"%s\"\n", file, line, c, attr->name); 1317ec681f3Smrg return 0; 1327ec681f3Smrg} 1337ec681f3Smrg 1347ec681f3Smrgstatic uint64_t getnum(struct rnndb *db, char *file, int line, xmlAttr *attr, char *c) 1357ec681f3Smrg{ 1367ec681f3Smrg char *cc; 1377ec681f3Smrg uint64_t res; 1387ec681f3Smrg if (strchr(c, 'x') || strchr(c, 'X')) 1397ec681f3Smrg res = strtoull(c, &cc, 16); 1407ec681f3Smrg else 1417ec681f3Smrg res = strtoull(c, &cc, 10); 1427ec681f3Smrg if (*cc) { 1437ec681f3Smrg rnn_err(db, "%s:%d: invalid numeric value \"%s\" in attribute \"%s\"\n", file, line, c, attr->name); 1447ec681f3Smrg } 1457ec681f3Smrg return res; 1467ec681f3Smrg} 1477ec681f3Smrg 1487ec681f3Smrgstatic uint64_t getnumattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) { 1497ec681f3Smrg char *c = getattrib(db, file, line, attr); 1507ec681f3Smrg return getnum(db, file, line, attr, c); 1517ec681f3Smrg} 1527ec681f3Smrg 1537ec681f3Smrgstatic int trytop (struct rnndb *db, char *file, xmlNode *node); 1547ec681f3Smrg 1557ec681f3Smrgstatic int trydoc (struct rnndb *db, char *file, xmlNode *node) { 1567ec681f3Smrg if (!strcmp(node->name, "brief")) { 1577ec681f3Smrg return 1; 1587ec681f3Smrg } else if (!strcmp(node->name, "doc")) { 1597ec681f3Smrg return 1; 1607ec681f3Smrg } 1617ec681f3Smrg return 0; 1627ec681f3Smrg} 1637ec681f3Smrg 1647ec681f3Smrgstatic struct rnnvalue *parsevalue(struct rnndb *db, char *file, xmlNode *node); 1657ec681f3Smrgstatic struct rnnbitfield *parsebitfield(struct rnndb *db, char *file, xmlNode *node); 1667ec681f3Smrg 1677ec681f3Smrgstatic int trytypetag (struct rnndb *db, char *file, xmlNode *node, struct rnntypeinfo *ti) { 1687ec681f3Smrg if (!strcmp(node->name, "value")) { 1697ec681f3Smrg struct rnnvalue *val = parsevalue(db, file, node); 1707ec681f3Smrg if (val) 1717ec681f3Smrg ADDARRAY(ti->vals, val); 1727ec681f3Smrg return 1; 1737ec681f3Smrg } else if (!strcmp(node->name, "bitfield")) { 1747ec681f3Smrg struct rnnbitfield *bf = parsebitfield(db, file, node); 1757ec681f3Smrg if (bf) 1767ec681f3Smrg ADDARRAY(ti->bitfields, bf); 1777ec681f3Smrg return 1; 1787ec681f3Smrg } 1797ec681f3Smrg return 0; 1807ec681f3Smrg} 1817ec681f3Smrgstatic int trytypeattr (struct rnndb *db, char *file, xmlNode *node, xmlAttr *attr, struct rnntypeinfo *ti) { 1827ec681f3Smrg if (!strcmp(attr->name, "shr")) { 1837ec681f3Smrg ti->shr = getnumattrib(db, file, node->line, attr); 1847ec681f3Smrg return 1; 1857ec681f3Smrg } else if (!strcmp(attr->name, "min")) { 1867ec681f3Smrg ti->min = getnumattrib(db, file, node->line, attr); 1877ec681f3Smrg ti->minvalid = 1; 1887ec681f3Smrg return 1; 1897ec681f3Smrg } else if (!strcmp(attr->name, "max")) { 1907ec681f3Smrg ti->max = getnumattrib(db, file, node->line, attr); 1917ec681f3Smrg ti->maxvalid = 1; 1927ec681f3Smrg return 1; 1937ec681f3Smrg } else if (!strcmp(attr->name, "align")) { 1947ec681f3Smrg ti->align = getnumattrib(db, file, node->line, attr); 1957ec681f3Smrg ti->alignvalid = 1; 1967ec681f3Smrg return 1; 1977ec681f3Smrg } else if (!strcmp(attr->name, "type")) { 1987ec681f3Smrg ti->name = strdup(getattrib(db, file, node->line, attr));; 1997ec681f3Smrg return 1; 2007ec681f3Smrg } else if (!strcmp(attr->name, "radix")) { 2017ec681f3Smrg ti->radix = getnumattrib(db, file, node->line, attr); 2027ec681f3Smrg ti->radixvalid = 1; 2037ec681f3Smrg return 1; 2047ec681f3Smrg } else if (!strcmp(attr->name, "pos")) { 2057ec681f3Smrg ti->high = ti->low = getnumattrib(db, file, node->line, attr); 2067ec681f3Smrg return 1; 2077ec681f3Smrg } else if (!strcmp(attr->name, "low")) { 2087ec681f3Smrg ti->low = getnumattrib(db, file, node->line, attr); 2097ec681f3Smrg return 1; 2107ec681f3Smrg } else if (!strcmp(attr->name, "high")) { 2117ec681f3Smrg ti->high = getnumattrib(db, file, node->line, attr); 2127ec681f3Smrg return 1; 2137ec681f3Smrg } else if (!strcmp(attr->name, "addvariant")) { 2147ec681f3Smrg ti->addvariant = getboolattrib(db, file, node->line, attr); 2157ec681f3Smrg return 1; 2167ec681f3Smrg } 2177ec681f3Smrg return 0; 2187ec681f3Smrg} 2197ec681f3Smrg 2207ec681f3Smrgstatic struct rnnvalue *parsevalue(struct rnndb *db, char *file, xmlNode *node) { 2217ec681f3Smrg struct rnnvalue *val = calloc(sizeof *val, 1); 2227ec681f3Smrg val->file = file; 2237ec681f3Smrg xmlAttr *attr = node->properties; 2247ec681f3Smrg while (attr) { 2257ec681f3Smrg if (!strcmp(attr->name, "name")) { 2267ec681f3Smrg val->name = strdup(getattrib(db, file, node->line, attr)); 2277ec681f3Smrg } else if (!strcmp(attr->name, "value")) { 2287ec681f3Smrg val->value = getnumattrib(db, file, node->line, attr); 2297ec681f3Smrg val->valvalid = 1; 2307ec681f3Smrg } else if (!strcmp(attr->name, "varset")) { 2317ec681f3Smrg val->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr)); 2327ec681f3Smrg } else if (!strcmp(attr->name, "variants")) { 2337ec681f3Smrg val->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr)); 2347ec681f3Smrg } else { 2357ec681f3Smrg rnn_err(db, "%s:%d: wrong attribute \"%s\" for value\n", file, node->line, attr->name); 2367ec681f3Smrg } 2377ec681f3Smrg attr = attr->next; 2387ec681f3Smrg } 2397ec681f3Smrg xmlNode *chain = node->children; 2407ec681f3Smrg while (chain) { 2417ec681f3Smrg if (chain->type != XML_ELEMENT_NODE) { 2427ec681f3Smrg } else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) { 2437ec681f3Smrg rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name); 2447ec681f3Smrg } 2457ec681f3Smrg chain = chain->next; 2467ec681f3Smrg } 2477ec681f3Smrg if (!val->name) { 2487ec681f3Smrg rnn_err(db, "%s:%d: nameless value\n", file, node->line); 2497ec681f3Smrg return 0; 2507ec681f3Smrg } else { 2517ec681f3Smrg return val; 2527ec681f3Smrg } 2537ec681f3Smrg} 2547ec681f3Smrg 2557ec681f3Smrgstatic void parsespectype(struct rnndb *db, char *file, xmlNode *node) { 2567ec681f3Smrg struct rnnspectype *res = calloc (sizeof *res, 1); 2577ec681f3Smrg res->file = file; 2587ec681f3Smrg xmlAttr *attr = node->properties; 2597ec681f3Smrg int i; 2607ec681f3Smrg while (attr) { 2617ec681f3Smrg if (!strcmp(attr->name, "name")) { 2627ec681f3Smrg res->name = strdup(getattrib(db, file, node->line, attr)); 2637ec681f3Smrg } else if (!trytypeattr(db, file, node, attr, &res->typeinfo)) { 2647ec681f3Smrg rnn_err(db, "%s:%d: wrong attribute \"%s\" for spectype\n", file, node->line, attr->name); 2657ec681f3Smrg } 2667ec681f3Smrg attr = attr->next; 2677ec681f3Smrg } 2687ec681f3Smrg if (!res->name) { 2697ec681f3Smrg rnn_err(db, "%s:%d: nameless spectype\n", file, node->line); 2707ec681f3Smrg return; 2717ec681f3Smrg } 2727ec681f3Smrg for (i = 0; i < db->spectypesnum; i++) 2737ec681f3Smrg if (!strcmp(db->spectypes[i]->name, res->name)) { 2747ec681f3Smrg rnn_err(db, "%s:%d: duplicated spectype name %s\n", file, node->line, res->name); 2757ec681f3Smrg return; 2767ec681f3Smrg } 2777ec681f3Smrg ADDARRAY(db->spectypes, res); 2787ec681f3Smrg xmlNode *chain = node->children; 2797ec681f3Smrg while (chain) { 2807ec681f3Smrg if (chain->type != XML_ELEMENT_NODE) { 2817ec681f3Smrg } else if (!trytypetag(db, file, chain, &res->typeinfo) && !trytop(db, file, chain) && !trydoc(db, file, chain)) { 2827ec681f3Smrg rnn_err(db, "%s:%d: wrong tag in spectype: <%s>\n", file, chain->line, chain->name); 2837ec681f3Smrg } 2847ec681f3Smrg chain = chain->next; 2857ec681f3Smrg } 2867ec681f3Smrg} 2877ec681f3Smrg 2887ec681f3Smrgstatic void parseenum(struct rnndb *db, char *file, xmlNode *node) { 2897ec681f3Smrg xmlAttr *attr = node->properties; 2907ec681f3Smrg char *name = 0; 2917ec681f3Smrg int isinline = 0; 2927ec681f3Smrg int bare = 0; 2937ec681f3Smrg char *prefixstr = 0; 2947ec681f3Smrg char *varsetstr = 0; 2957ec681f3Smrg char *variantsstr = 0; 2967ec681f3Smrg int i; 2977ec681f3Smrg while (attr) { 2987ec681f3Smrg if (!strcmp(attr->name, "name")) { 2997ec681f3Smrg name = getattrib(db, file, node->line, attr); 3007ec681f3Smrg } else if (!strcmp(attr->name, "bare")) { 3017ec681f3Smrg bare = getboolattrib(db, file, node->line, attr); 3027ec681f3Smrg } else if (!strcmp(attr->name, "inline")) { 3037ec681f3Smrg isinline = getboolattrib(db, file, node->line, attr); 3047ec681f3Smrg } else if (!strcmp(attr->name, "prefix")) { 3057ec681f3Smrg prefixstr = strdup(getattrib(db, file, node->line, attr)); 3067ec681f3Smrg } else if (!strcmp(attr->name, "varset")) { 3077ec681f3Smrg varsetstr = strdup(getattrib(db, file, node->line, attr)); 3087ec681f3Smrg } else if (!strcmp(attr->name, "variants")) { 3097ec681f3Smrg variantsstr = strdup(getattrib(db, file, node->line, attr)); 3107ec681f3Smrg } else { 3117ec681f3Smrg rnn_err(db, "%s:%d: wrong attribute \"%s\" for enum\n", file, node->line, attr->name); 3127ec681f3Smrg } 3137ec681f3Smrg attr = attr->next; 3147ec681f3Smrg } 3157ec681f3Smrg if (!name) { 3167ec681f3Smrg rnn_err(db, "%s:%d: nameless enum\n", file, node->line); 3177ec681f3Smrg return; 3187ec681f3Smrg } 3197ec681f3Smrg struct rnnenum *cur = 0; 3207ec681f3Smrg for (i = 0; i < db->enumsnum; i++) 3217ec681f3Smrg if (!strcmp(db->enums[i]->name, name)) { 3227ec681f3Smrg cur = db->enums[i]; 3237ec681f3Smrg break; 3247ec681f3Smrg } 3257ec681f3Smrg if (cur) { 3267ec681f3Smrg if (strdiff(cur->varinfo.prefixstr, prefixstr) || 3277ec681f3Smrg strdiff(cur->varinfo.varsetstr, varsetstr) || 3287ec681f3Smrg strdiff(cur->varinfo.variantsstr, variantsstr) || 3297ec681f3Smrg cur->isinline != isinline || cur->bare != bare) { 3307ec681f3Smrg rnn_err(db, "%s:%d: merge fail for enum %s\n", file, node->line, node->name); 3317ec681f3Smrg } 3327ec681f3Smrg } else { 3337ec681f3Smrg cur = calloc(sizeof *cur, 1); 3347ec681f3Smrg cur->name = strdup(name); 3357ec681f3Smrg cur->isinline = isinline; 3367ec681f3Smrg cur->bare = bare; 3377ec681f3Smrg cur->varinfo.prefixstr = prefixstr; 3387ec681f3Smrg cur->varinfo.varsetstr = varsetstr; 3397ec681f3Smrg cur->varinfo.variantsstr = variantsstr; 3407ec681f3Smrg cur->file = file; 3417ec681f3Smrg ADDARRAY(db->enums, cur); 3427ec681f3Smrg } 3437ec681f3Smrg xmlNode *chain = node->children; 3447ec681f3Smrg while (chain) { 3457ec681f3Smrg if (chain->type != XML_ELEMENT_NODE) { 3467ec681f3Smrg } else if (!strcmp(chain->name, "value")) { 3477ec681f3Smrg struct rnnvalue *val = parsevalue(db, file, chain); 3487ec681f3Smrg if (val) 3497ec681f3Smrg ADDARRAY(cur->vals, val); 3507ec681f3Smrg } else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) { 3517ec681f3Smrg rnn_err(db, "%s:%d: wrong tag in enum: <%s>\n", file, chain->line, chain->name); 3527ec681f3Smrg } 3537ec681f3Smrg chain = chain->next; 3547ec681f3Smrg } 3557ec681f3Smrg} 3567ec681f3Smrg 3577ec681f3Smrgstatic struct rnnbitfield *parsebitfield(struct rnndb *db, char *file, xmlNode *node) { 3587ec681f3Smrg struct rnnbitfield *bf = calloc(sizeof *bf, 1); 3597ec681f3Smrg bf->file = file; 3607ec681f3Smrg xmlAttr *attr = node->properties; 3617ec681f3Smrg bf->typeinfo.low = bf->typeinfo.high = -1; 3627ec681f3Smrg while (attr) { 3637ec681f3Smrg if (!strcmp(attr->name, "name")) { 3647ec681f3Smrg bf->name = strdup(getattrib(db, file, node->line, attr)); 3657ec681f3Smrg } else if (!strcmp(attr->name, "varset")) { 3667ec681f3Smrg bf->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr)); 3677ec681f3Smrg } else if (!strcmp(attr->name, "variants")) { 3687ec681f3Smrg bf->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr)); 3697ec681f3Smrg } else if (!trytypeattr(db, file, node, attr, &bf->typeinfo)) { 3707ec681f3Smrg rnn_err(db, "%s:%d: wrong attribute \"%s\" for bitfield\n", file, node->line, attr->name); 3717ec681f3Smrg } 3727ec681f3Smrg attr = attr->next; 3737ec681f3Smrg } 3747ec681f3Smrg xmlNode *chain = node->children; 3757ec681f3Smrg while (chain) { 3767ec681f3Smrg if (chain->type != XML_ELEMENT_NODE) { 3777ec681f3Smrg } else if (!trytypetag(db, file, chain, &bf->typeinfo) && !trytop(db, file, chain) && !trydoc(db, file, chain)) { 3787ec681f3Smrg rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name); 3797ec681f3Smrg } 3807ec681f3Smrg chain = chain->next; 3817ec681f3Smrg } 3827ec681f3Smrg if (!bf->name) { 3837ec681f3Smrg rnn_err(db, "%s:%d: nameless bitfield\n", file, node->line); 3847ec681f3Smrg return 0; 3857ec681f3Smrg } else if (bf->typeinfo.low < 0|| bf->typeinfo.high < 0 || bf->typeinfo.high < bf->typeinfo.low) { 3867ec681f3Smrg rnn_err(db, "%s:%d: bitfield has wrong placement\n", file, node->line); 3877ec681f3Smrg return 0; 3887ec681f3Smrg } else { 3897ec681f3Smrg return bf; 3907ec681f3Smrg } 3917ec681f3Smrg} 3927ec681f3Smrg 3937ec681f3Smrgstatic void parsebitset(struct rnndb *db, char *file, xmlNode *node) { 3947ec681f3Smrg xmlAttr *attr = node->properties; 3957ec681f3Smrg char *name = 0; 3967ec681f3Smrg int isinline = 0; 3977ec681f3Smrg int bare = 0; 3987ec681f3Smrg char *prefixstr = 0; 3997ec681f3Smrg char *varsetstr = 0; 4007ec681f3Smrg char *variantsstr = 0; 4017ec681f3Smrg int i; 4027ec681f3Smrg while (attr) { 4037ec681f3Smrg if (!strcmp(attr->name, "name")) { 4047ec681f3Smrg name = getattrib(db, file, node->line, attr); 4057ec681f3Smrg } else if (!strcmp(attr->name, "bare")) { 4067ec681f3Smrg bare = getboolattrib(db, file, node->line, attr); 4077ec681f3Smrg } else if (!strcmp(attr->name, "inline")) { 4087ec681f3Smrg isinline = getboolattrib(db, file, node->line, attr); 4097ec681f3Smrg } else if (!strcmp(attr->name, "prefix")) { 4107ec681f3Smrg prefixstr = strdup(getattrib(db, file, node->line, attr)); 4117ec681f3Smrg } else if (!strcmp(attr->name, "varset")) { 4127ec681f3Smrg varsetstr = strdup(getattrib(db, file, node->line, attr)); 4137ec681f3Smrg } else if (!strcmp(attr->name, "variants")) { 4147ec681f3Smrg variantsstr = strdup(getattrib(db, file, node->line, attr)); 4157ec681f3Smrg } else { 4167ec681f3Smrg rnn_err(db, "%s:%d: wrong attribute \"%s\" for bitset\n", file, node->line, attr->name); 4177ec681f3Smrg } 4187ec681f3Smrg attr = attr->next; 4197ec681f3Smrg } 4207ec681f3Smrg if (!name) { 4217ec681f3Smrg rnn_err(db, "%s:%d: nameless bitset\n", file, node->line); 4227ec681f3Smrg return; 4237ec681f3Smrg } 4247ec681f3Smrg struct rnnbitset *cur = 0; 4257ec681f3Smrg for (i = 0; i < db->bitsetsnum; i++) 4267ec681f3Smrg if (!strcmp(db->bitsets[i]->name, name)) { 4277ec681f3Smrg cur = db->bitsets[i]; 4287ec681f3Smrg break; 4297ec681f3Smrg } 4307ec681f3Smrg if (cur) { 4317ec681f3Smrg if (strdiff(cur->varinfo.prefixstr, prefixstr) || 4327ec681f3Smrg strdiff(cur->varinfo.varsetstr, varsetstr) || 4337ec681f3Smrg strdiff(cur->varinfo.variantsstr, variantsstr) || 4347ec681f3Smrg cur->isinline != isinline || cur->bare != bare) { 4357ec681f3Smrg rnn_err(db, "%s:%d: merge fail for bitset %s\n", file, node->line, node->name); 4367ec681f3Smrg } 4377ec681f3Smrg } else { 4387ec681f3Smrg cur = calloc(sizeof *cur, 1); 4397ec681f3Smrg cur->name = strdup(name); 4407ec681f3Smrg cur->isinline = isinline; 4417ec681f3Smrg cur->bare = bare; 4427ec681f3Smrg cur->varinfo.prefixstr = prefixstr; 4437ec681f3Smrg cur->varinfo.varsetstr = varsetstr; 4447ec681f3Smrg cur->varinfo.variantsstr = variantsstr; 4457ec681f3Smrg cur->file = file; 4467ec681f3Smrg ADDARRAY(db->bitsets, cur); 4477ec681f3Smrg } 4487ec681f3Smrg xmlNode *chain = node->children; 4497ec681f3Smrg while (chain) { 4507ec681f3Smrg if (chain->type != XML_ELEMENT_NODE) { 4517ec681f3Smrg } else if (!strcmp(chain->name, "bitfield")) { 4527ec681f3Smrg struct rnnbitfield *bf = parsebitfield(db, file, chain); 4537ec681f3Smrg if (bf) 4547ec681f3Smrg ADDARRAY(cur->bitfields, bf); 4557ec681f3Smrg } else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) { 4567ec681f3Smrg rnn_err(db, "%s:%d: wrong tag in bitset: <%s>\n", file, chain->line, chain->name); 4577ec681f3Smrg } 4587ec681f3Smrg chain = chain->next; 4597ec681f3Smrg } 4607ec681f3Smrg} 4617ec681f3Smrg 4627ec681f3Smrgstatic struct rnndelem *trydelem(struct rnndb *db, char *file, xmlNode *node) { 4637ec681f3Smrg if (!strcmp(node->name, "use-group")) { 4647ec681f3Smrg struct rnndelem *res = calloc(sizeof *res, 1); 4657ec681f3Smrg res->file = file; 4667ec681f3Smrg res->type = RNN_ETYPE_USE_GROUP; 4677ec681f3Smrg xmlAttr *attr = node->properties; 4687ec681f3Smrg while (attr) { 4697ec681f3Smrg if (!strcmp(attr->name, "ref")) { 4707ec681f3Smrg res->name = strdup(getattrib(db, file, node->line, attr)); 4717ec681f3Smrg } else { 4727ec681f3Smrg rnn_err(db, "%s:%d: wrong attribute \"%s\" for %s\n", file, node->line, attr->name, node->name); 4737ec681f3Smrg } 4747ec681f3Smrg attr = attr->next; 4757ec681f3Smrg } 4767ec681f3Smrg if (!res->name) { 4777ec681f3Smrg rnn_err(db, "%s:%d: nameless use-group\n", file, node->line); 4787ec681f3Smrg return 0; 4797ec681f3Smrg } 4807ec681f3Smrg return res; 4817ec681f3Smrg } else if (!strcmp(node->name, "stripe") || !strcmp(node->name, "array")) { 4827ec681f3Smrg struct rnndelem *res = calloc(sizeof *res, 1); 4837ec681f3Smrg if (!strcmp(node->name, "array")) 4847ec681f3Smrg res->name = ""; 4857ec681f3Smrg res->type = (strcmp(node->name, "stripe")?RNN_ETYPE_ARRAY:RNN_ETYPE_STRIPE); 4867ec681f3Smrg res->length = 1; 4877ec681f3Smrg res->file = file; 4887ec681f3Smrg xmlAttr *attr = node->properties; 4897ec681f3Smrg while (attr) { 4907ec681f3Smrg if (!strcmp(attr->name, "name")) { 4917ec681f3Smrg res->name = strdup(getattrib(db, file, node->line, attr)); 4927ec681f3Smrg } else if (!strcmp(attr->name, "offset")) { 4937ec681f3Smrg res->offset = getnumattrib(db, file, node->line, attr); 4947ec681f3Smrg } else if (!strcmp(attr->name, "offsets")) { 4957ec681f3Smrg char *str = strdup(getattrib(db, file, node->line, attr)); 4967ec681f3Smrg char *tok, *save, *tmp = str; 4977ec681f3Smrg while ((tok = strtok_r(str, ",", &save))) { 4987ec681f3Smrg uint64_t offset = getnum(db, file, node->line, attr, tok); 4997ec681f3Smrg ADDARRAY(res->offsets, offset); 5007ec681f3Smrg str = NULL; 5017ec681f3Smrg } 5027ec681f3Smrg if (str) 5037ec681f3Smrg fprintf(stderr, "%s:%d: invalid offsets: %s\n", file, node->line, str); 5047ec681f3Smrg free(tmp); 5057ec681f3Smrg } else if (!strcmp(attr->name, "doffset")) { 5067ec681f3Smrg /* dynamic runtime determined offset: */ 5077ec681f3Smrg res->doffset = strdup(getattrib(db, file, node->line, attr)); 5087ec681f3Smrg } else if (!strcmp(attr->name, "doffsets")) { 5097ec681f3Smrg /* dynamic runtime determined offsets: */ 5107ec681f3Smrg char *str = strdup(getattrib(db, file, node->line, attr)); 5117ec681f3Smrg char *tok, *save, *tmp = str; 5127ec681f3Smrg while ((tok = strtok_r(str, ",", &save))) { 5137ec681f3Smrg char *doffset = strdup(tok); 5147ec681f3Smrg ADDARRAY(res->doffsets, doffset); 5157ec681f3Smrg str = NULL; 5167ec681f3Smrg } 5177ec681f3Smrg if (str) 5187ec681f3Smrg fprintf(stderr, "%s:%d: invalid offsets: %s\n", file, node->line, str); 5197ec681f3Smrg free(tmp); 5207ec681f3Smrg } else if (!strcmp(attr->name, "length")) { 5217ec681f3Smrg res->length = getnumattrib(db, file, node->line, attr); 5227ec681f3Smrg } else if (!strcmp(attr->name, "stride")) { 5237ec681f3Smrg res->stride = getnumattrib(db, file, node->line, attr); 5247ec681f3Smrg } else if (!strcmp(attr->name, "prefix")) { 5257ec681f3Smrg res->varinfo.prefixstr = strdup(getattrib(db, file, node->line, attr)); 5267ec681f3Smrg } else if (!strcmp(attr->name, "varset")) { 5277ec681f3Smrg res->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr)); 5287ec681f3Smrg } else if (!strcmp(attr->name, "variants")) { 5297ec681f3Smrg res->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr)); 5307ec681f3Smrg } else if (!strcmp(attr->name, "index")) { 5317ec681f3Smrg const char *enumname = getattrib(db, file, node->line, attr); 5327ec681f3Smrg res->index = rnn_findenum(db, enumname); 5337ec681f3Smrg if (!res->index) { 5347ec681f3Smrg rnn_err(db, "%s:%d: invalid enum name \"%s\"\n", file, node->line, enumname); 5357ec681f3Smrg } 5367ec681f3Smrg } else { 5377ec681f3Smrg rnn_err(db, "%s:%d: wrong attribute \"%s\" for %s\n", file, node->line, attr->name, node->name); 5387ec681f3Smrg } 5397ec681f3Smrg attr = attr->next; 5407ec681f3Smrg } 5417ec681f3Smrg xmlNode *chain = node->children; 5427ec681f3Smrg while (chain) { 5437ec681f3Smrg struct rnndelem *delem; 5447ec681f3Smrg if (chain->type != XML_ELEMENT_NODE) { 5457ec681f3Smrg } else if ((delem = trydelem(db, file, chain))) { 5467ec681f3Smrg ADDARRAY(res->subelems, delem); 5477ec681f3Smrg } else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) { 5487ec681f3Smrg rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name); 5497ec681f3Smrg } 5507ec681f3Smrg chain = chain->next; 5517ec681f3Smrg } 5527ec681f3Smrg 5537ec681f3Smrg /* Sanity checking */ 5547ec681f3Smrg if (res->type == RNN_ETYPE_ARRAY && res->stride == 0) { 5557ec681f3Smrg fprintf(stderr, "%s: Array %s's stride is undefined. Aborting.\n", file, res->name); 5567ec681f3Smrg exit(-1); 5577ec681f3Smrg } 5587ec681f3Smrg return res; 5597ec681f3Smrg 5607ec681f3Smrg } 5617ec681f3Smrg int width; 5627ec681f3Smrg if (!strcmp(node->name, "reg8")) 5637ec681f3Smrg width = 8; 5647ec681f3Smrg else if (!strcmp(node->name, "reg16")) 5657ec681f3Smrg width = 16; 5667ec681f3Smrg else if (!strcmp(node->name, "reg32")) 5677ec681f3Smrg width = 32; 5687ec681f3Smrg else if (!strcmp(node->name, "reg64")) 5697ec681f3Smrg width = 64; 5707ec681f3Smrg else 5717ec681f3Smrg return 0; 5727ec681f3Smrg struct rnndelem *res = calloc(sizeof *res, 1); 5737ec681f3Smrg res->file = file; 5747ec681f3Smrg res->type = RNN_ETYPE_REG; 5757ec681f3Smrg res->width = width; 5767ec681f3Smrg res->length = 1; 5777ec681f3Smrg res->access = RNN_ACCESS_RW; 5787ec681f3Smrg xmlAttr *attr = node->properties; 5797ec681f3Smrg res->typeinfo.low = 0; 5807ec681f3Smrg res->typeinfo.high = width - 1; 5817ec681f3Smrg while (attr) { 5827ec681f3Smrg if (!strcmp(attr->name, "name")) { 5837ec681f3Smrg res->name = strdup(getattrib(db, file, node->line, attr)); 5847ec681f3Smrg } else if (!strcmp(attr->name, "offset")) { 5857ec681f3Smrg res->offset = getnumattrib(db, file, node->line, attr); 5867ec681f3Smrg } else if (!strcmp(attr->name, "length")) { 5877ec681f3Smrg res->length = getnumattrib(db, file, node->line, attr); 5887ec681f3Smrg } else if (!strcmp(attr->name, "stride")) { 5897ec681f3Smrg res->stride = getnumattrib(db, file, node->line, attr); 5907ec681f3Smrg } else if (!strcmp(attr->name, "varset")) { 5917ec681f3Smrg res->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr)); 5927ec681f3Smrg } else if (!strcmp(attr->name, "variants")) { 5937ec681f3Smrg res->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr)); 5947ec681f3Smrg } else if (!strcmp(attr->name, "access")) { 5957ec681f3Smrg char *str = getattrib(db, file, node->line, attr); 5967ec681f3Smrg if (!strcmp(str, "r")) 5977ec681f3Smrg res->access = RNN_ACCESS_R; 5987ec681f3Smrg else if (!strcmp(str, "w")) 5997ec681f3Smrg res->access = RNN_ACCESS_W; 6007ec681f3Smrg else if (!strcmp(str, "rw")) 6017ec681f3Smrg res->access = RNN_ACCESS_RW; 6027ec681f3Smrg else 6037ec681f3Smrg fprintf (stderr, "%s:%d: wrong access type \"%s\" for register\n", file, node->line, str); 6047ec681f3Smrg } else if (!trytypeattr(db, file, node, attr, &res->typeinfo)) { 6057ec681f3Smrg rnn_err(db, "%s:%d: wrong attribute \"%s\" for register\n", file, node->line, attr->name); 6067ec681f3Smrg } 6077ec681f3Smrg attr = attr->next; 6087ec681f3Smrg } 6097ec681f3Smrg xmlNode *chain = node->children; 6107ec681f3Smrg while (chain) { 6117ec681f3Smrg if (chain->type != XML_ELEMENT_NODE) { 6127ec681f3Smrg } else if (!trytypetag(db, file, chain, &res->typeinfo) && !trytop(db, file, chain) && !trydoc(db, file, chain)) { 6137ec681f3Smrg rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name); 6147ec681f3Smrg } 6157ec681f3Smrg chain = chain->next; 6167ec681f3Smrg } 6177ec681f3Smrg if (!res->name) { 6187ec681f3Smrg rnn_err(db, "%s:%d: nameless register\n", file, node->line); 6197ec681f3Smrg return 0; 6207ec681f3Smrg } else { 6217ec681f3Smrg } 6227ec681f3Smrg return res; 6237ec681f3Smrg} 6247ec681f3Smrg 6257ec681f3Smrgstatic void parsegroup(struct rnndb *db, char *file, xmlNode *node) { 6267ec681f3Smrg xmlAttr *attr = node->properties; 6277ec681f3Smrg char *name = 0; 6287ec681f3Smrg int i; 6297ec681f3Smrg while (attr) { 6307ec681f3Smrg if (!strcmp(attr->name, "name")) { 6317ec681f3Smrg name = getattrib(db, file, node->line, attr); 6327ec681f3Smrg } else { 6337ec681f3Smrg rnn_err(db, "%s:%d: wrong attribute \"%s\" for group\n", file, node->line, attr->name); 6347ec681f3Smrg } 6357ec681f3Smrg attr = attr->next; 6367ec681f3Smrg } 6377ec681f3Smrg if (!name) { 6387ec681f3Smrg rnn_err(db, "%s:%d: nameless group\n", file, node->line); 6397ec681f3Smrg return; 6407ec681f3Smrg } 6417ec681f3Smrg struct rnngroup *cur = 0; 6427ec681f3Smrg for (i = 0; i < db->groupsnum; i++) 6437ec681f3Smrg if (!strcmp(db->groups[i]->name, name)) { 6447ec681f3Smrg cur = db->groups[i]; 6457ec681f3Smrg break; 6467ec681f3Smrg } 6477ec681f3Smrg if (!cur) { 6487ec681f3Smrg cur = calloc(sizeof *cur, 1); 6497ec681f3Smrg cur->name = strdup(name); 6507ec681f3Smrg ADDARRAY(db->groups, cur); 6517ec681f3Smrg } 6527ec681f3Smrg xmlNode *chain = node->children; 6537ec681f3Smrg while (chain) { 6547ec681f3Smrg struct rnndelem *delem; 6557ec681f3Smrg if (chain->type != XML_ELEMENT_NODE) { 6567ec681f3Smrg } else if ((delem = trydelem(db, file, chain))) { 6577ec681f3Smrg ADDARRAY(cur->subelems, delem); 6587ec681f3Smrg } else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) { 6597ec681f3Smrg rnn_err(db, "%s:%d: wrong tag in group: <%s>\n", file, chain->line, chain->name); 6607ec681f3Smrg } 6617ec681f3Smrg chain = chain->next; 6627ec681f3Smrg } 6637ec681f3Smrg} 6647ec681f3Smrg 6657ec681f3Smrgstatic void parsedomain(struct rnndb *db, char *file, xmlNode *node) { 6667ec681f3Smrg xmlAttr *attr = node->properties; 6677ec681f3Smrg char *name = 0; 6687ec681f3Smrg uint64_t size = 0; int width = 8; 6697ec681f3Smrg int bare = 0; 6707ec681f3Smrg char *prefixstr = 0; 6717ec681f3Smrg char *varsetstr = 0; 6727ec681f3Smrg char *variantsstr = 0; 6737ec681f3Smrg int i; 6747ec681f3Smrg while (attr) { 6757ec681f3Smrg if (!strcmp(attr->name, "name")) { 6767ec681f3Smrg name = getattrib(db, file, node->line, attr); 6777ec681f3Smrg } else if (!strcmp(attr->name, "bare")) { 6787ec681f3Smrg bare = getboolattrib(db, file, node->line, attr); 6797ec681f3Smrg } else if (!strcmp(attr->name, "size")) { 6807ec681f3Smrg size = getnumattrib(db, file, node->line, attr); 6817ec681f3Smrg } else if (!strcmp(attr->name, "width")) { 6827ec681f3Smrg width = getnumattrib(db, file, node->line, attr); 6837ec681f3Smrg } else if (!strcmp(attr->name, "prefix")) { 6847ec681f3Smrg prefixstr = strdup(getattrib(db, file, node->line, attr)); 6857ec681f3Smrg } else if (!strcmp(attr->name, "varset")) { 6867ec681f3Smrg varsetstr = strdup(getattrib(db, file, node->line, attr)); 6877ec681f3Smrg } else if (!strcmp(attr->name, "variants")) { 6887ec681f3Smrg variantsstr = strdup(getattrib(db, file, node->line, attr)); 6897ec681f3Smrg } else { 6907ec681f3Smrg rnn_err(db, "%s:%d: wrong attribute \"%s\" for domain\n", file, node->line, attr->name); 6917ec681f3Smrg } 6927ec681f3Smrg attr = attr->next; 6937ec681f3Smrg } 6947ec681f3Smrg if (!name) { 6957ec681f3Smrg rnn_err(db, "%s:%d: nameless domain\n", file, node->line); 6967ec681f3Smrg return; 6977ec681f3Smrg } 6987ec681f3Smrg struct rnndomain *cur = 0; 6997ec681f3Smrg for (i = 0; i < db->domainsnum; i++) 7007ec681f3Smrg if (!strcmp(db->domains[i]->name, name)) { 7017ec681f3Smrg cur = db->domains[i]; 7027ec681f3Smrg break; 7037ec681f3Smrg } 7047ec681f3Smrg if (cur) { 7057ec681f3Smrg if (strdiff(cur->varinfo.prefixstr, prefixstr) || 7067ec681f3Smrg strdiff(cur->varinfo.varsetstr, varsetstr) || 7077ec681f3Smrg strdiff(cur->varinfo.variantsstr, variantsstr) || 7087ec681f3Smrg cur->width != width || 7097ec681f3Smrg cur->bare != bare || 7107ec681f3Smrg (size && cur->size && size != cur->size)) { 7117ec681f3Smrg rnn_err(db, "%s:%d: merge fail for domain %s\n", file, node->line, node->name); 7127ec681f3Smrg } else { 7137ec681f3Smrg if (size) 7147ec681f3Smrg cur->size = size; 7157ec681f3Smrg } 7167ec681f3Smrg } else { 7177ec681f3Smrg cur = calloc(sizeof *cur, 1); 7187ec681f3Smrg cur->name = strdup(name); 7197ec681f3Smrg cur->bare = bare; 7207ec681f3Smrg cur->width = width; 7217ec681f3Smrg cur->size = size; 7227ec681f3Smrg cur->varinfo.prefixstr = prefixstr; 7237ec681f3Smrg cur->varinfo.varsetstr = varsetstr; 7247ec681f3Smrg cur->varinfo.variantsstr = variantsstr; 7257ec681f3Smrg cur->file = file; 7267ec681f3Smrg ADDARRAY(db->domains, cur); 7277ec681f3Smrg } 7287ec681f3Smrg xmlNode *chain = node->children; 7297ec681f3Smrg while (chain) { 7307ec681f3Smrg struct rnndelem *delem; 7317ec681f3Smrg if (chain->type != XML_ELEMENT_NODE) { 7327ec681f3Smrg } else if ((delem = trydelem(db, file, chain))) { 7337ec681f3Smrg ADDARRAY(cur->subelems, delem); 7347ec681f3Smrg } else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) { 7357ec681f3Smrg rnn_err(db, "%s:%d: wrong tag in domain: <%s>\n", file, chain->line, chain->name); 7367ec681f3Smrg } 7377ec681f3Smrg chain = chain->next; 7387ec681f3Smrg } 7397ec681f3Smrg} 7407ec681f3Smrg 7417ec681f3Smrgstatic void parsecopyright(struct rnndb *db, char *file, xmlNode *node) { 7427ec681f3Smrg struct rnncopyright* copyright = &db->copyright; 7437ec681f3Smrg xmlAttr *attr = node->properties; 7447ec681f3Smrg while (attr) { 7457ec681f3Smrg if (!strcmp(attr->name, "year")) { 7467ec681f3Smrg unsigned firstyear = getnumattrib(db, file, node->line, attr); 7477ec681f3Smrg if(!copyright->firstyear || firstyear < copyright->firstyear) 7487ec681f3Smrg copyright->firstyear = firstyear; 7497ec681f3Smrg } else { 7507ec681f3Smrg rnn_err(db, "%s:%d: wrong attribute \"%s\" for copyright\n", file, node->line, attr->name); 7517ec681f3Smrg } 7527ec681f3Smrg attr = attr->next; 7537ec681f3Smrg } 7547ec681f3Smrg xmlNode *chain = node->children; 7557ec681f3Smrg while (chain) { 7567ec681f3Smrg if (chain->type != XML_ELEMENT_NODE) { 7577ec681f3Smrg } else if (!strcmp(chain->name, "license")) 7587ec681f3Smrg if(copyright->license) { 7597ec681f3Smrg if(strcmp(copyright->license, node->content)) { 7607ec681f3Smrg fprintf(stderr, "fatal error: multiple different licenses specified!\n"); 7617ec681f3Smrg abort(); /* TODO: do something better here, but headergen, xml2html, etc. should not produce anything in this case */ 7627ec681f3Smrg } 7637ec681f3Smrg } else 7647ec681f3Smrg copyright->license = getcontent(chain); 7657ec681f3Smrg else if (!strcmp(chain->name, "author")) { 7667ec681f3Smrg struct rnnauthor* author = calloc(sizeof *author, 1); 7677ec681f3Smrg xmlAttr* authorattr = chain->properties; 7687ec681f3Smrg xmlNode *authorchild = chain->children; 7697ec681f3Smrg author->contributions = getcontent(chain); 7707ec681f3Smrg while (authorattr) { 7717ec681f3Smrg if (!strcmp(authorattr->name, "name")) 7727ec681f3Smrg author->name = strdup(getattrib(db, file, chain->line, authorattr)); 7737ec681f3Smrg else if (!strcmp(authorattr->name, "email")) 7747ec681f3Smrg author->email = strdup(getattrib(db, file, chain->line, authorattr)); 7757ec681f3Smrg else { 7767ec681f3Smrg rnn_err(db, "%s:%d: wrong attribute \"%s\" for author\n", file, chain->line, authorattr->name); 7777ec681f3Smrg } 7787ec681f3Smrg authorattr = authorattr->next; 7797ec681f3Smrg } 7807ec681f3Smrg while(authorchild) { 7817ec681f3Smrg if (authorchild->type != XML_ELEMENT_NODE) { 7827ec681f3Smrg } else if (!strcmp(authorchild->name, "nick")) { 7837ec681f3Smrg xmlAttr* nickattr = authorchild->properties; 7847ec681f3Smrg char* nickname = 0; 7857ec681f3Smrg while(nickattr) { 7867ec681f3Smrg if (!strcmp(nickattr->name, "name")) 7877ec681f3Smrg nickname = strdup(getattrib(db, file, authorchild->line, nickattr)); 7887ec681f3Smrg else { 7897ec681f3Smrg rnn_err(db, "%s:%d: wrong attribute \"%s\" for nick\n", file, authorchild->line, nickattr->name); 7907ec681f3Smrg } 7917ec681f3Smrg nickattr = nickattr->next; 7927ec681f3Smrg } 7937ec681f3Smrg if(!nickname) { 7947ec681f3Smrg rnn_err(db, "%s:%d: missing \"name\" attribute for nick\n", file, authorchild->line); 7957ec681f3Smrg } else 7967ec681f3Smrg ADDARRAY(author->nicknames, nickname); 7977ec681f3Smrg } else { 7987ec681f3Smrg rnn_err(db, "%s:%d: wrong tag in author: <%s>\n", file, authorchild->line, authorchild->name); 7997ec681f3Smrg } 8007ec681f3Smrg authorchild = authorchild->next; 8017ec681f3Smrg } 8027ec681f3Smrg ADDARRAY(copyright->authors, author); 8037ec681f3Smrg } else { 8047ec681f3Smrg rnn_err(db, "%s:%d: wrong tag in copyright: <%s>\n", file, chain->line, chain->name); 8057ec681f3Smrg } 8067ec681f3Smrg chain = chain->next; 8077ec681f3Smrg } 8087ec681f3Smrg} 8097ec681f3Smrg 8107ec681f3Smrgstatic int trytop (struct rnndb *db, char *file, xmlNode *node) { 8117ec681f3Smrg if (!strcmp(node->name, "enum")) { 8127ec681f3Smrg parseenum(db, file, node); 8137ec681f3Smrg return 1; 8147ec681f3Smrg } else if (!strcmp(node->name, "bitset")) { 8157ec681f3Smrg parsebitset(db, file, node); 8167ec681f3Smrg return 1; 8177ec681f3Smrg } else if (!strcmp(node->name, "group")) { 8187ec681f3Smrg parsegroup(db, file, node); 8197ec681f3Smrg return 1; 8207ec681f3Smrg } else if (!strcmp(node->name, "domain")) { 8217ec681f3Smrg parsedomain(db, file, node); 8227ec681f3Smrg return 1; 8237ec681f3Smrg } else if (!strcmp(node->name, "spectype")) { 8247ec681f3Smrg parsespectype(db, file, node); 8257ec681f3Smrg return 1; 8267ec681f3Smrg } else if (!strcmp(node->name, "import")) { 8277ec681f3Smrg xmlAttr *attr = node->properties; 8287ec681f3Smrg char *subfile = 0; 8297ec681f3Smrg while (attr) { 8307ec681f3Smrg if (!strcmp(attr->name, "file")) { 8317ec681f3Smrg subfile = getattrib(db, file, node->line, attr); 8327ec681f3Smrg } else { 8337ec681f3Smrg rnn_err(db, "%s:%d: wrong attribute \"%s\" for import\n", file, node->line, attr->name); 8347ec681f3Smrg } 8357ec681f3Smrg attr = attr->next; 8367ec681f3Smrg } 8377ec681f3Smrg if (!subfile) { 8387ec681f3Smrg rnn_err(db, "%s:%d: missing \"file\" attribute for import\n", file, node->line); 8397ec681f3Smrg } else { 8407ec681f3Smrg rnn_parsefile(db, subfile); 8417ec681f3Smrg } 8427ec681f3Smrg return 1; 8437ec681f3Smrg } else if (!strcmp(node->name, "copyright")) { 8447ec681f3Smrg parsecopyright(db, file, node); 8457ec681f3Smrg return 1; 8467ec681f3Smrg } 8477ec681f3Smrg return 0; 8487ec681f3Smrg} 8497ec681f3Smrg 8507ec681f3Smrgstatic char * find_file(const char *file_orig) 8517ec681f3Smrg{ 8527ec681f3Smrg const char *rnn_path = getenv("RNN_PATH"); 8537ec681f3Smrg char *fname; 8547ec681f3Smrg 8557ec681f3Smrg if (!rnn_path) 8567ec681f3Smrg rnn_path = RNN_DEF_PATH; 8577ec681f3Smrg 8587ec681f3Smrg FILE *file = find_in_path(file_orig, rnn_path, &fname); 8597ec681f3Smrg if (!file) { 8607ec681f3Smrg fprintf (stderr, "%s: couldn't find database file. Please set the env var RNN_PATH.\n", file_orig); 8617ec681f3Smrg return NULL; 8627ec681f3Smrg } 8637ec681f3Smrg fclose(file); 8647ec681f3Smrg 8657ec681f3Smrg return fname; 8667ec681f3Smrg} 8677ec681f3Smrg 8687ec681f3Smrgstatic int validate_doc(struct rnndb *db, xmlDocPtr doc, xmlNodePtr database) 8697ec681f3Smrg{ 8707ec681f3Smrg /* find the schemaLocation property: */ 8717ec681f3Smrg xmlAttrPtr attr = database->properties; 8727ec681f3Smrg const char *schema_name = NULL; 8737ec681f3Smrg char *schema_path; 8747ec681f3Smrg 8757ec681f3Smrg while (attr) { 8767ec681f3Smrg if (!strcmp(attr->name, "schemaLocation")) { 8777ec681f3Smrg xmlNodePtr data = attr->children; 8787ec681f3Smrg schema_name = data->content; 8797ec681f3Smrg /* we expect this to look like <namespace url> schema.xsd.. I think 8807ec681f3Smrg * technically it is supposed to be just a URL, but that doesn't 8817ec681f3Smrg * quite match up to what we do.. Just skip over everything up to 8827ec681f3Smrg * and including the first whitespace character: 8837ec681f3Smrg */ 8847ec681f3Smrg while (schema_name && (schema_name[0] != ' ')) 8857ec681f3Smrg schema_name++; 8867ec681f3Smrg schema_name++; 8877ec681f3Smrg break; 8887ec681f3Smrg } 8897ec681f3Smrg } 8907ec681f3Smrg 8917ec681f3Smrg if (!schema_name) { 8927ec681f3Smrg rnn_err(db, "could not find schema. Missing schemaLocation?"); 8937ec681f3Smrg return 0; 8947ec681f3Smrg } 8957ec681f3Smrg 8967ec681f3Smrg schema_path = find_file(schema_name); 8977ec681f3Smrg if (!schema_path) { 8987ec681f3Smrg rnn_err(db, "%s: couldn't find database file. Please set the env var RNN_PATH.\n", schema_name); 8997ec681f3Smrg return 0; 9007ec681f3Smrg } 9017ec681f3Smrg 9027ec681f3Smrg xmlSchemaParserCtxtPtr parser = xmlSchemaNewParserCtxt(schema_path); 9037ec681f3Smrg xmlSchemaPtr schema = xmlSchemaParse(parser); 9047ec681f3Smrg xmlSchemaValidCtxtPtr validCtxt = xmlSchemaNewValidCtxt(schema); 9057ec681f3Smrg int ret = xmlSchemaValidateDoc(validCtxt, doc); 9067ec681f3Smrg 9077ec681f3Smrg xmlSchemaFreeValidCtxt(validCtxt); 9087ec681f3Smrg xmlSchemaFree(schema); 9097ec681f3Smrg xmlSchemaFreeParserCtxt(parser); 9107ec681f3Smrg 9117ec681f3Smrg free(schema_path); 9127ec681f3Smrg 9137ec681f3Smrg return ret; 9147ec681f3Smrg} 9157ec681f3Smrg 9167ec681f3Smrgvoid rnn_parsefile (struct rnndb *db, char *file_orig) { 9177ec681f3Smrg int i; 9187ec681f3Smrg char *fname; 9197ec681f3Smrg 9207ec681f3Smrg fname = find_file(file_orig); 9217ec681f3Smrg if (!fname) { 9227ec681f3Smrg db->estatus = 1; 9237ec681f3Smrg return; 9247ec681f3Smrg } 9257ec681f3Smrg 9267ec681f3Smrg for (i = 0; i < db->filesnum; i++) 9277ec681f3Smrg if (!strcmp(db->files[i], fname)) 9287ec681f3Smrg return; 9297ec681f3Smrg 9307ec681f3Smrg ADDARRAY(db->files, fname); 9317ec681f3Smrg xmlDocPtr doc = xmlParseFile(fname); 9327ec681f3Smrg if (!doc) { 9337ec681f3Smrg rnn_err(db, "%s: couldn't open database file. Please set the env var RNN_PATH.\n", fname); 9347ec681f3Smrg return; 9357ec681f3Smrg } 9367ec681f3Smrg xmlNode *root = doc->children; 9377ec681f3Smrg while (root) { 9387ec681f3Smrg if (root->type != XML_ELEMENT_NODE) { 9397ec681f3Smrg } else if (strcmp(root->name, "database")) { 9407ec681f3Smrg rnn_err(db, "%s:%d: wrong top-level tag <%s>\n", fname, root->line, root->name); 9417ec681f3Smrg } else { 9427ec681f3Smrg xmlNode *chain = root->children; 9437ec681f3Smrg if (validate_doc(db, doc, root)) { 9447ec681f3Smrg rnn_err(db, "%s: database file has errors\n", fname); 9457ec681f3Smrg return; 9467ec681f3Smrg } 9477ec681f3Smrg while (chain) { 9487ec681f3Smrg if (chain->type != XML_ELEMENT_NODE) { 9497ec681f3Smrg } else if (!trytop(db, fname, chain) && !trydoc(db, fname, chain)) { 9507ec681f3Smrg rnn_err(db, "%s:%d: wrong tag in database: <%s>\n", fname, chain->line, chain->name); 9517ec681f3Smrg } 9527ec681f3Smrg chain = chain->next; 9537ec681f3Smrg } 9547ec681f3Smrg } 9557ec681f3Smrg root = root->next; 9567ec681f3Smrg } 9577ec681f3Smrg xmlFreeDoc(doc); 9587ec681f3Smrg} 9597ec681f3Smrg 9607ec681f3Smrgstatic struct rnnvalue *copyvalue (struct rnnvalue *val, char *file) { 9617ec681f3Smrg struct rnnvalue *res = calloc (sizeof *res, 1); 9627ec681f3Smrg res->name = val->name; 9637ec681f3Smrg res->valvalid = val->valvalid; 9647ec681f3Smrg res->value = val->value; 9657ec681f3Smrg res->varinfo = val->varinfo; 9667ec681f3Smrg res->file = file; 9677ec681f3Smrg return res; 9687ec681f3Smrg} 9697ec681f3Smrg 9707ec681f3Smrgstatic struct rnnbitfield *copybitfield (struct rnnbitfield *bf, char *file); 9717ec681f3Smrg 9727ec681f3Smrg 9737ec681f3Smrgstatic void copytypeinfo (struct rnntypeinfo *dst, struct rnntypeinfo *src, char *file) { 9747ec681f3Smrg int i; 9757ec681f3Smrg dst->name = src->name; 9767ec681f3Smrg dst->shr = src->shr; 9777ec681f3Smrg dst->low = src->low; 9787ec681f3Smrg dst->high = src->high; 9797ec681f3Smrg dst->min = src->min; 9807ec681f3Smrg dst->max = src->max; 9817ec681f3Smrg dst->align = src->align; 9827ec681f3Smrg dst->addvariant = src->addvariant; 9837ec681f3Smrg for (i = 0; i < src->valsnum; i++) 9847ec681f3Smrg ADDARRAY(dst->vals, copyvalue(src->vals[i], file)); 9857ec681f3Smrg for (i = 0; i < src->bitfieldsnum; i++) 9867ec681f3Smrg ADDARRAY(dst->bitfields, copybitfield(src->bitfields[i], file)); 9877ec681f3Smrg} 9887ec681f3Smrg 9897ec681f3Smrgstatic struct rnnbitfield *copybitfield (struct rnnbitfield *bf, char *file) { 9907ec681f3Smrg struct rnnbitfield *res = calloc (sizeof *res, 1); 9917ec681f3Smrg res->name = bf->name; 9927ec681f3Smrg res->varinfo = bf->varinfo; 9937ec681f3Smrg res->file = file; 9947ec681f3Smrg copytypeinfo(&res->typeinfo, &bf->typeinfo, file); 9957ec681f3Smrg return res; 9967ec681f3Smrg} 9977ec681f3Smrg 9987ec681f3Smrgstatic struct rnndelem *copydelem (struct rnndelem *elem, char *file) { 9997ec681f3Smrg struct rnndelem *res = calloc (sizeof *res, 1); 10007ec681f3Smrg res->type = elem->type; 10017ec681f3Smrg res->name = elem->name; 10027ec681f3Smrg res->width = elem->width; 10037ec681f3Smrg res->access = elem->access; 10047ec681f3Smrg res->offset = elem->offset; 10057ec681f3Smrg res->length = elem->length; 10067ec681f3Smrg res->stride = elem->stride; 10077ec681f3Smrg res->varinfo = elem->varinfo; 10087ec681f3Smrg res->file = file; 10097ec681f3Smrg copytypeinfo(&res->typeinfo, &elem->typeinfo, file); 10107ec681f3Smrg int i; 10117ec681f3Smrg for (i = 0; i < elem->subelemsnum; i++) 10127ec681f3Smrg ADDARRAY(res->subelems, copydelem(elem->subelems[i], file)); 10137ec681f3Smrg for (i = 0; i < elem->offsetsnum; i++) 10147ec681f3Smrg ADDARRAY(res->offsets, elem->offsets[i]); 10157ec681f3Smrg return res; 10167ec681f3Smrg} 10177ec681f3Smrg 10187ec681f3Smrgstatic struct rnnvarset *copyvarset (struct rnnvarset *varset) { 10197ec681f3Smrg struct rnnvarset *res = calloc(sizeof *res, 1); 10207ec681f3Smrg res->venum = varset->venum; 10217ec681f3Smrg res->variants = calloc(sizeof *res->variants, res->venum->valsnum); 10227ec681f3Smrg int i; 10237ec681f3Smrg for (i = 0; i < res->venum->valsnum; i++) 10247ec681f3Smrg res->variants[i] = varset->variants[i]; 10257ec681f3Smrg return res; 10267ec681f3Smrg} 10277ec681f3Smrg 10287ec681f3Smrgstatic void prepenum(struct rnndb *db, struct rnnenum *en); 10297ec681f3Smrg 10307ec681f3Smrgstatic int findvidx (struct rnndb *db, struct rnnenum *en, char *name) { 10317ec681f3Smrg int i; 10327ec681f3Smrg for (i = 0; i < en->valsnum; i++) 10337ec681f3Smrg if (!strcmp(en->vals[i]->name, name)) 10347ec681f3Smrg return i; 10357ec681f3Smrg rnn_err(db, "Cannot find variant %s in enum %s!\n", name, en->name); 10367ec681f3Smrg return -1; 10377ec681f3Smrg} 10387ec681f3Smrg 10397ec681f3Smrgstatic void prepvarinfo (struct rnndb *db, char *what, struct rnnvarinfo *vi, struct rnnvarinfo *parent) { 10407ec681f3Smrg if (parent) 10417ec681f3Smrg vi->prefenum = parent->prefenum; 10427ec681f3Smrg if (vi->prefixstr) { 10437ec681f3Smrg if (!strcmp(vi->prefixstr, "none")) 10447ec681f3Smrg vi->prefenum = 0; 10457ec681f3Smrg else 10467ec681f3Smrg vi->prefenum = rnn_findenum(db, vi->prefixstr); // XXX 10477ec681f3Smrg } 10487ec681f3Smrg int i; 10497ec681f3Smrg if (parent) 10507ec681f3Smrg for (i = 0; i < parent->varsetsnum; i++) 10517ec681f3Smrg ADDARRAY(vi->varsets, copyvarset(parent->varsets[i])); 10527ec681f3Smrg struct rnnenum *varset = vi->prefenum; 10537ec681f3Smrg if (!varset && !vi->varsetstr && parent) 10547ec681f3Smrg vi->varsetstr = parent->varsetstr; 10557ec681f3Smrg if (vi->varsetstr) 10567ec681f3Smrg varset = rnn_findenum(db, vi->varsetstr); 10577ec681f3Smrg if (vi->variantsstr) { 10587ec681f3Smrg char *vars = vi->variantsstr; 10597ec681f3Smrg if (!varset) { 10607ec681f3Smrg rnn_err(db, "%s: tried to use variants without active varset!\n", what); 10617ec681f3Smrg return; 10627ec681f3Smrg } 10637ec681f3Smrg struct rnnvarset *vs = 0; 10647ec681f3Smrg int nvars = varset->valsnum; 10657ec681f3Smrg for (i = 0; i < vi->varsetsnum; i++) 10667ec681f3Smrg if (vi->varsets[i]->venum == varset) { 10677ec681f3Smrg vs = vi->varsets[i]; 10687ec681f3Smrg break; 10697ec681f3Smrg } 10707ec681f3Smrg if (!vs) { 10717ec681f3Smrg vs = calloc (sizeof *vs, 1); 10727ec681f3Smrg vs->venum = varset; 10737ec681f3Smrg vs->variants = calloc(sizeof *vs->variants, nvars); 10747ec681f3Smrg for (i = 0; i < nvars; i++) 10757ec681f3Smrg vs->variants[i] = 1; 10767ec681f3Smrg ADDARRAY(vi->varsets, vs); 10777ec681f3Smrg } 10787ec681f3Smrg while (1) { 10797ec681f3Smrg while (*vars == ' ') vars++; 10807ec681f3Smrg if (*vars == 0) 10817ec681f3Smrg break; 10827ec681f3Smrg char *split = vars; 10837ec681f3Smrg while (*split != ':' && *split != '-' && *split != ' ' && *split != 0) 10847ec681f3Smrg split++; 10857ec681f3Smrg char *first = 0; 10867ec681f3Smrg if (split != vars) 10877ec681f3Smrg first = strndup(vars, split-vars); 10887ec681f3Smrg if (*split == ' ' || *split == 0) { 10897ec681f3Smrg int idx = findvidx(db, varset, first); 10907ec681f3Smrg if (idx != -1) 10917ec681f3Smrg vs->variants[idx] |= 2; 10927ec681f3Smrg vars = split; 10937ec681f3Smrg } else { 10947ec681f3Smrg char *end = split+1; 10957ec681f3Smrg while (*end != ' ' && *end != 0) 10967ec681f3Smrg end++; 10977ec681f3Smrg char *second = 0; 10987ec681f3Smrg if (end != split+1) 10997ec681f3Smrg second = strndup(split+1, end-split-1); 11007ec681f3Smrg int idx1 = 0; 11017ec681f3Smrg if (first) 11027ec681f3Smrg idx1 = findvidx(db, varset, first); 11037ec681f3Smrg int idx2 = nvars; 11047ec681f3Smrg if (second) { 11057ec681f3Smrg idx2 = findvidx(db, varset, second); 11067ec681f3Smrg if (*split == '-') 11077ec681f3Smrg idx2++; 11087ec681f3Smrg } 11097ec681f3Smrg if (idx1 != -1 && idx2 != -1) 11107ec681f3Smrg for (i = idx1; i < idx2; i++) 11117ec681f3Smrg vs->variants[i] |= 2; 11127ec681f3Smrg vars = end; 11137ec681f3Smrg free(second); 11147ec681f3Smrg } 11157ec681f3Smrg free(first); 11167ec681f3Smrg } 11177ec681f3Smrg vi->dead = 1; 11187ec681f3Smrg for (i = 0; i < nvars; i++) { 11197ec681f3Smrg vs->variants[i] = (vs->variants[i] == 3); 11207ec681f3Smrg if (vs->variants[i]) 11217ec681f3Smrg vi->dead = 0; 11227ec681f3Smrg } 11237ec681f3Smrg } 11247ec681f3Smrg if (vi->dead) 11257ec681f3Smrg return; 11267ec681f3Smrg if (vi->prefenum) { 11277ec681f3Smrg struct rnnvarset *vs = 0; 11287ec681f3Smrg for (i = 0; i < vi->varsetsnum; i++) 11297ec681f3Smrg if (vi->varsets[i]->venum == vi->prefenum) { 11307ec681f3Smrg vs = vi->varsets[i]; 11317ec681f3Smrg break; 11327ec681f3Smrg } 11337ec681f3Smrg if (vs) { 11347ec681f3Smrg for (i = 0; i < vi->prefenum->valsnum; i++) 11357ec681f3Smrg if (vs->variants[i]) { 11367ec681f3Smrg vi->prefix = vi->prefenum->vals[i]->name; 11377ec681f3Smrg return; 11387ec681f3Smrg } 11397ec681f3Smrg } else { 11407ec681f3Smrg vi->prefix = vi->prefenum->vals[0]->name; 11417ec681f3Smrg } 11427ec681f3Smrg } 11437ec681f3Smrg} 11447ec681f3Smrg 11457ec681f3Smrgstatic void prepvalue(struct rnndb *db, struct rnnvalue *val, char *prefix, struct rnnvarinfo *parvi) { 11467ec681f3Smrg val->fullname = catstr(prefix, val->name); 11477ec681f3Smrg prepvarinfo (db, val->fullname, &val->varinfo, parvi); 11487ec681f3Smrg if (val->varinfo.dead) 11497ec681f3Smrg return; 11507ec681f3Smrg if (val->varinfo.prefix) 11517ec681f3Smrg val->fullname = catstr(val->varinfo.prefix, val->fullname); 11527ec681f3Smrg} 11537ec681f3Smrg 11547ec681f3Smrgstatic void prepbitfield(struct rnndb *db, struct rnnbitfield *bf, char *prefix, struct rnnvarinfo *parvi); 11557ec681f3Smrg 11567ec681f3Smrgstatic void preptypeinfo(struct rnndb *db, struct rnntypeinfo *ti, char *prefix, struct rnnvarinfo *vi, char *file) { 11577ec681f3Smrg int i; 11587ec681f3Smrg if (ti->name) { 11597ec681f3Smrg struct rnnenum *en = rnn_findenum (db, ti->name); 11607ec681f3Smrg struct rnnbitset *bs = rnn_findbitset (db, ti->name); 11617ec681f3Smrg struct rnnspectype *st = rnn_findspectype (db, ti->name); 11627ec681f3Smrg if (en) { 11637ec681f3Smrg if (en->isinline) { 11647ec681f3Smrg ti->type = RNN_TTYPE_INLINE_ENUM; 11657ec681f3Smrg int j; 11667ec681f3Smrg for (j = 0; j < en->valsnum; j++) 11677ec681f3Smrg ADDARRAY(ti->vals, copyvalue(en->vals[j], file)); 11687ec681f3Smrg } else { 11697ec681f3Smrg ti->type = RNN_TTYPE_ENUM; 11707ec681f3Smrg ti->eenum = en; 11717ec681f3Smrg } 11727ec681f3Smrg } else if (bs) { 11737ec681f3Smrg if (bs->isinline) { 11747ec681f3Smrg ti->type = RNN_TTYPE_INLINE_BITSET; 11757ec681f3Smrg int j; 11767ec681f3Smrg for (j = 0; j < bs->bitfieldsnum; j++) 11777ec681f3Smrg ADDARRAY(ti->bitfields, copybitfield(bs->bitfields[j], file)); 11787ec681f3Smrg } else { 11797ec681f3Smrg ti->type = RNN_TTYPE_BITSET; 11807ec681f3Smrg ti->ebitset = bs; 11817ec681f3Smrg } 11827ec681f3Smrg } else if (st) { 11837ec681f3Smrg ti->type = RNN_TTYPE_SPECTYPE; 11847ec681f3Smrg ti->spectype = st; 11857ec681f3Smrg } else if (!strcmp(ti->name, "hex")) { 11867ec681f3Smrg ti->type = RNN_TTYPE_HEX; 11877ec681f3Smrg } else if (!strcmp(ti->name, "float")) { 11887ec681f3Smrg ti->type = RNN_TTYPE_FLOAT; 11897ec681f3Smrg } else if (!strcmp(ti->name, "uint")) { 11907ec681f3Smrg ti->type = RNN_TTYPE_UINT; 11917ec681f3Smrg } else if (!strcmp(ti->name, "int")) { 11927ec681f3Smrg ti->type = RNN_TTYPE_INT; 11937ec681f3Smrg } else if (!strcmp(ti->name, "boolean")) { 11947ec681f3Smrg ti->type = RNN_TTYPE_BOOLEAN; 11957ec681f3Smrg } else if (!strcmp(ti->name, "bitfield")) { 11967ec681f3Smrg ti->type = RNN_TTYPE_INLINE_BITSET; 11977ec681f3Smrg } else if (!strcmp(ti->name, "enum")) { 11987ec681f3Smrg ti->type = RNN_TTYPE_INLINE_ENUM; 11997ec681f3Smrg } else if (!strcmp(ti->name, "fixed")) { 12007ec681f3Smrg ti->type = RNN_TTYPE_FIXED; 12017ec681f3Smrg } else if (!strcmp(ti->name, "ufixed")) { 12027ec681f3Smrg ti->type = RNN_TTYPE_UFIXED; 12037ec681f3Smrg } else if (!strcmp(ti->name, "a3xx_regid")) { 12047ec681f3Smrg ti->type = RNN_TTYPE_A3XX_REGID; 12057ec681f3Smrg } else if (!strcmp(ti->name, "waddress") || !strcmp(ti->name, "address")) { 12067ec681f3Smrg ti->type = RNN_TTYPE_HEX; 12077ec681f3Smrg } else { 12087ec681f3Smrg ti->type = RNN_TTYPE_HEX; 12097ec681f3Smrg rnn_err(db, "%s: unknown type %s\n", prefix, ti->name); 12107ec681f3Smrg } 12117ec681f3Smrg } else if (ti->bitfieldsnum) { 12127ec681f3Smrg ti->name = "bitfield"; 12137ec681f3Smrg ti->type = RNN_TTYPE_INLINE_BITSET; 12147ec681f3Smrg } else if (ti->valsnum) { 12157ec681f3Smrg ti->name = "enum"; 12167ec681f3Smrg ti->type = RNN_TTYPE_INLINE_ENUM; 12177ec681f3Smrg } else if (ti->low == 0 && ti->high == 0) { 12187ec681f3Smrg ti->name = "boolean"; 12197ec681f3Smrg ti->type = RNN_TTYPE_BOOLEAN; 12207ec681f3Smrg } else { 12217ec681f3Smrg ti->name = "hex"; 12227ec681f3Smrg ti->type = RNN_TTYPE_HEX; 12237ec681f3Smrg } 12247ec681f3Smrg if (ti->addvariant && ti->type != RNN_TTYPE_ENUM) { 12257ec681f3Smrg rnn_err(db, "%s: addvariant specified on non-enum type %s\n", prefix, ti->name); 12267ec681f3Smrg } 12277ec681f3Smrg for (i = 0; i < ti->bitfieldsnum; i++) 12287ec681f3Smrg prepbitfield(db, ti->bitfields[i], prefix, vi); 12297ec681f3Smrg for (i = 0; i < ti->valsnum; i++) 12307ec681f3Smrg prepvalue(db, ti->vals[i], prefix, vi); 12317ec681f3Smrg} 12327ec681f3Smrg 12337ec681f3Smrgstatic void prepbitfield(struct rnndb *db, struct rnnbitfield *bf, char *prefix, struct rnnvarinfo *parvi) { 12347ec681f3Smrg bf->fullname = catstr(prefix, bf->name); 12357ec681f3Smrg prepvarinfo (db, bf->fullname, &bf->varinfo, parvi); 12367ec681f3Smrg if (bf->varinfo.dead) 12377ec681f3Smrg return; 12387ec681f3Smrg preptypeinfo(db, &bf->typeinfo, bf->fullname, &bf->varinfo, bf->file); 12397ec681f3Smrg if (bf->varinfo.prefix) 12407ec681f3Smrg bf->fullname = catstr(bf->varinfo.prefix, bf->fullname); 12417ec681f3Smrg} 12427ec681f3Smrg 12437ec681f3Smrgstatic void prepdelem(struct rnndb *db, struct rnndelem *elem, char *prefix, struct rnnvarinfo *parvi, int width) { 12447ec681f3Smrg if (elem->type == RNN_ETYPE_USE_GROUP) { 12457ec681f3Smrg int i; 12467ec681f3Smrg struct rnngroup *gr = 0; 12477ec681f3Smrg for (i = 0; i < db->groupsnum; i++) 12487ec681f3Smrg if (!strcmp(db->groups[i]->name, elem->name)) { 12497ec681f3Smrg gr = db->groups[i]; 12507ec681f3Smrg break; 12517ec681f3Smrg } 12527ec681f3Smrg if (gr) { 12537ec681f3Smrg for (i = 0; i < gr->subelemsnum; i++) 12547ec681f3Smrg ADDARRAY(elem->subelems, copydelem(gr->subelems[i], elem->file)); 12557ec681f3Smrg } else { 12567ec681f3Smrg rnn_err(db, "group %s not found!\n", elem->name); 12577ec681f3Smrg } 12587ec681f3Smrg elem->type = RNN_ETYPE_STRIPE; 12597ec681f3Smrg elem->length = 1; 12607ec681f3Smrg elem->name = 0; 12617ec681f3Smrg } 12627ec681f3Smrg if (elem->name) 12637ec681f3Smrg elem->fullname = catstr(prefix, elem->name); 12647ec681f3Smrg prepvarinfo (db, elem->fullname?elem->fullname:prefix, &elem->varinfo, parvi); 12657ec681f3Smrg if (elem->varinfo.dead) 12667ec681f3Smrg return; 12677ec681f3Smrg if (elem->length != 1 && !elem->stride) { 12687ec681f3Smrg if (elem->type != RNN_ETYPE_REG) { 12697ec681f3Smrg rnn_err(db, "%s has non-1 length, but no stride!\n", elem->fullname); 12707ec681f3Smrg } else { 12717ec681f3Smrg elem->stride = elem->width/width; 12727ec681f3Smrg } 12737ec681f3Smrg } 12747ec681f3Smrg preptypeinfo(db, &elem->typeinfo, elem->name?elem->fullname:prefix, &elem->varinfo, elem->file); 12757ec681f3Smrg 12767ec681f3Smrg int i; 12777ec681f3Smrg for (i = 0; i < elem->subelemsnum; i++) 12787ec681f3Smrg prepdelem(db, elem->subelems[i], elem->name?elem->fullname:prefix, &elem->varinfo, width); 12797ec681f3Smrg if (elem->varinfo.prefix && elem->name) 12807ec681f3Smrg elem->fullname = catstr(elem->varinfo.prefix, elem->fullname); 12817ec681f3Smrg} 12827ec681f3Smrg 12837ec681f3Smrgstatic void prepdomain(struct rnndb *db, struct rnndomain *dom) { 12847ec681f3Smrg prepvarinfo (db, dom->name, &dom->varinfo, 0); 12857ec681f3Smrg int i; 12867ec681f3Smrg for (i = 0; i < dom->subelemsnum; i++) 12877ec681f3Smrg prepdelem(db, dom->subelems[i], dom->bare?0:dom->name, &dom->varinfo, dom->width); 12887ec681f3Smrg dom->fullname = catstr(dom->varinfo.prefix, dom->name); 12897ec681f3Smrg} 12907ec681f3Smrg 12917ec681f3Smrgstatic void prepenum(struct rnndb *db, struct rnnenum *en) { 12927ec681f3Smrg if (en->prepared) 12937ec681f3Smrg return; 12947ec681f3Smrg prepvarinfo (db, en->name, &en->varinfo, 0); 12957ec681f3Smrg int i; 12967ec681f3Smrg if (en->isinline) 12977ec681f3Smrg return; 12987ec681f3Smrg for (i = 0; i < en->valsnum; i++) 12997ec681f3Smrg prepvalue(db, en->vals[i], en->bare?0:en->name, &en->varinfo); 13007ec681f3Smrg en->fullname = catstr(en->varinfo.prefix, en->name); 13017ec681f3Smrg en->prepared = 1; 13027ec681f3Smrg} 13037ec681f3Smrg 13047ec681f3Smrgstatic void prepbitset(struct rnndb *db, struct rnnbitset *bs) { 13057ec681f3Smrg prepvarinfo (db, bs->name, &bs->varinfo, 0); 13067ec681f3Smrg int i; 13077ec681f3Smrg if (bs->isinline) 13087ec681f3Smrg return; 13097ec681f3Smrg for (i = 0; i < bs->bitfieldsnum; i++) 13107ec681f3Smrg prepbitfield(db, bs->bitfields[i], bs->bare?0:bs->name, &bs->varinfo); 13117ec681f3Smrg bs->fullname = catstr(bs->varinfo.prefix, bs->name); 13127ec681f3Smrg} 13137ec681f3Smrg 13147ec681f3Smrgstatic void prepspectype(struct rnndb *db, struct rnnspectype *st) { 13157ec681f3Smrg preptypeinfo(db, &st->typeinfo, st->name, 0, st->file); // XXX doesn't exactly make sense... 13167ec681f3Smrg} 13177ec681f3Smrg 13187ec681f3Smrgvoid rnn_prepdb (struct rnndb *db) { 13197ec681f3Smrg int i; 13207ec681f3Smrg for (i = 0; i < db->enumsnum; i++) 13217ec681f3Smrg prepenum(db, db->enums[i]); 13227ec681f3Smrg for (i = 0; i < db->bitsetsnum; i++) 13237ec681f3Smrg prepbitset(db, db->bitsets[i]); 13247ec681f3Smrg for (i = 0; i < db->domainsnum; i++) 13257ec681f3Smrg prepdomain(db, db->domains[i]); 13267ec681f3Smrg for (i = 0; i < db->spectypesnum; i++) 13277ec681f3Smrg prepspectype(db, db->spectypes[i]); 13287ec681f3Smrg} 13297ec681f3Smrg 13307ec681f3Smrgstruct rnnenum *rnn_findenum (struct rnndb *db, const char *name) { 13317ec681f3Smrg int i; 13327ec681f3Smrg for (i = 0; i < db->enumsnum; i++) 13337ec681f3Smrg if (!strcmp(db->enums[i]->name, name)) 13347ec681f3Smrg return db->enums[i]; 13357ec681f3Smrg return 0; 13367ec681f3Smrg} 13377ec681f3Smrg 13387ec681f3Smrgstruct rnnbitset *rnn_findbitset (struct rnndb *db, const char *name) { 13397ec681f3Smrg int i; 13407ec681f3Smrg for (i = 0; i < db->bitsetsnum; i++) 13417ec681f3Smrg if (!strcmp(db->bitsets[i]->name, name)) 13427ec681f3Smrg return db->bitsets[i]; 13437ec681f3Smrg return 0; 13447ec681f3Smrg} 13457ec681f3Smrg 13467ec681f3Smrgstruct rnndomain *rnn_finddomain (struct rnndb *db, const char *name) { 13477ec681f3Smrg int i; 13487ec681f3Smrg for (i = 0; i < db->domainsnum; i++) 13497ec681f3Smrg if (!strcmp(db->domains[i]->name, name)) 13507ec681f3Smrg return db->domains[i]; 13517ec681f3Smrg return 0; 13527ec681f3Smrg} 13537ec681f3Smrg 13547ec681f3Smrgstruct rnnspectype *rnn_findspectype (struct rnndb *db, const char *name) { 13557ec681f3Smrg int i; 13567ec681f3Smrg for (i = 0; i < db->spectypesnum; i++) 13577ec681f3Smrg if (!strcmp(db->spectypes[i]->name, name)) 13587ec681f3Smrg return db->spectypes[i]; 13597ec681f3Smrg return 0; 13607ec681f3Smrg} 1361