xref: /third_party/mesa3d/src/freedreno/rnn/rnn.c (revision bf215546)
1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2010-2011 Marcin Kościelnicki <koriakin@0x04.net>
3bf215546Sopenharmony_ci * Copyright (C) 2010 Luca Barbieri <luca@luca-barbieri.com>
4bf215546Sopenharmony_ci * Copyright (C) 2010 Francisco Jerez <currojerez@riseup.net>
5bf215546Sopenharmony_ci * Copyright (C) 2010 Martin Peres <martin.peres@ensi-bourges.fr>
6bf215546Sopenharmony_ci * Copyright (C) 2010 Marcin Slusarz <marcin.slusarz@gmail.com>
7bf215546Sopenharmony_ci * All Rights Reserved.
8bf215546Sopenharmony_ci *
9bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
10bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
11bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
12bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
14bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
17bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
18bf215546Sopenharmony_ci * Software.
19bf215546Sopenharmony_ci *
20bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
27bf215546Sopenharmony_ci */
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci/* workaround libxml2 silliness: */
30bf215546Sopenharmony_ci#pragma GCC diagnostic ignored "-Wpointer-sign"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include <libxml/xmlversion.h>
33bf215546Sopenharmony_ci#include <libxml/parser.h>
34bf215546Sopenharmony_ci#include <libxml/xpath.h>
35bf215546Sopenharmony_ci#include <libxml/xmlreader.h>
36bf215546Sopenharmony_ci#include <stdint.h>
37bf215546Sopenharmony_ci#include <string.h>
38bf215546Sopenharmony_ci#include <limits.h>
39bf215546Sopenharmony_ci#include <ctype.h>
40bf215546Sopenharmony_ci#include <stdio.h>
41bf215546Sopenharmony_ci#include "rnn.h"
42bf215546Sopenharmony_ci#include "util.h"
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci#include "util/u_debug.h"
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_cistatic char *catstr (char *a, char *b) {
47bf215546Sopenharmony_ci	if (!a)
48bf215546Sopenharmony_ci		return b;
49bf215546Sopenharmony_ci	return aprintf("%s_%s", a, b);
50bf215546Sopenharmony_ci}
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_cistatic int strdiff (const char *a, const char *b) {
53bf215546Sopenharmony_ci	if (!a && !b)
54bf215546Sopenharmony_ci		return 0;
55bf215546Sopenharmony_ci	if (!a || !b)
56bf215546Sopenharmony_ci		return 1;
57bf215546Sopenharmony_ci	return strcmp (a, b);
58bf215546Sopenharmony_ci}
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_cistatic void rnn_err(struct rnndb *db, const char *format, ...) _util_printf_format(2, 3);
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_cistatic void rnn_err(struct rnndb *db, const char *format, ...)
63bf215546Sopenharmony_ci{
64bf215546Sopenharmony_ci	va_list ap;
65bf215546Sopenharmony_ci	va_start(ap, format);
66bf215546Sopenharmony_ci	vfprintf(stderr, format, ap);
67bf215546Sopenharmony_ci	va_end(ap);
68bf215546Sopenharmony_ci	db->estatus = 1;
69bf215546Sopenharmony_ci}
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_civoid rnn_init(void) {
72bf215546Sopenharmony_ci	LIBXML_TEST_VERSION
73bf215546Sopenharmony_ci	xmlInitParser();
74bf215546Sopenharmony_ci}
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_cistruct rnndb *rnn_newdb(void) {
77bf215546Sopenharmony_ci	struct rnndb *db = calloc(sizeof *db, 1);
78bf215546Sopenharmony_ci	return db;
79bf215546Sopenharmony_ci}
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_cistatic char *getcontent (xmlNode *attr) {
82bf215546Sopenharmony_ci	xmlNode *chain = attr->children;
83bf215546Sopenharmony_ci	size_t size = 0;
84bf215546Sopenharmony_ci	char *content, *p;
85bf215546Sopenharmony_ci	while (chain) {
86bf215546Sopenharmony_ci		if (chain->type == XML_TEXT_NODE)
87bf215546Sopenharmony_ci			size += strlen(chain->content);
88bf215546Sopenharmony_ci		chain = chain->next;
89bf215546Sopenharmony_ci	}
90bf215546Sopenharmony_ci	p = content = malloc(size + 1);
91bf215546Sopenharmony_ci	chain = attr->children;
92bf215546Sopenharmony_ci	while (chain) {
93bf215546Sopenharmony_ci		if (chain->type == XML_TEXT_NODE) {
94bf215546Sopenharmony_ci			char* sp = chain->content;
95bf215546Sopenharmony_ci			if(p == content) {
96bf215546Sopenharmony_ci				while(isspace(*sp))
97bf215546Sopenharmony_ci					++sp;
98bf215546Sopenharmony_ci			}
99bf215546Sopenharmony_ci			size_t len = strlen(sp);
100bf215546Sopenharmony_ci			memcpy(p, sp, len);
101bf215546Sopenharmony_ci			p += len;
102bf215546Sopenharmony_ci		}
103bf215546Sopenharmony_ci		chain = chain->next;
104bf215546Sopenharmony_ci	}
105bf215546Sopenharmony_ci	while(p != content && isspace(p[-1]))
106bf215546Sopenharmony_ci		--p;
107bf215546Sopenharmony_ci	*p = 0;
108bf215546Sopenharmony_ci	return content;
109bf215546Sopenharmony_ci}
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_cistatic char *getattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) {
112bf215546Sopenharmony_ci	xmlNode *chain = attr->children;
113bf215546Sopenharmony_ci	while (chain) {
114bf215546Sopenharmony_ci		if (chain->type != XML_TEXT_NODE) {
115bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: unknown attribute child \"%s\" in attribute \"%s\"\n", file, line, chain->name, attr->name);
116bf215546Sopenharmony_ci		} else {
117bf215546Sopenharmony_ci			return chain->content;
118bf215546Sopenharmony_ci		}
119bf215546Sopenharmony_ci		chain = chain->next;
120bf215546Sopenharmony_ci	}
121bf215546Sopenharmony_ci	return "";
122bf215546Sopenharmony_ci}
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_cistatic int getboolattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) {
125bf215546Sopenharmony_ci	char *c = getattrib(db, file, line, attr);
126bf215546Sopenharmony_ci	if (!strcmp(c, "yes") || !strcmp(c, "1") || !strcmp(c, "true"))
127bf215546Sopenharmony_ci		return 1;
128bf215546Sopenharmony_ci	if (!strcmp(c, "no") || !strcmp(c, "0") || !strcmp(c, "false"))
129bf215546Sopenharmony_ci		return 0;
130bf215546Sopenharmony_ci	rnn_err(db, "%s:%d: invalid boolean value \"%s\" in attribute \"%s\"\n", file, line, c, attr->name);
131bf215546Sopenharmony_ci	return 0;
132bf215546Sopenharmony_ci}
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_cistatic uint64_t getnum(struct rnndb *db, char *file, int line, xmlAttr *attr, char *c)
135bf215546Sopenharmony_ci{
136bf215546Sopenharmony_ci	char *cc;
137bf215546Sopenharmony_ci	uint64_t res;
138bf215546Sopenharmony_ci	if (strchr(c, 'x') || strchr(c, 'X'))
139bf215546Sopenharmony_ci		res = strtoull(c, &cc, 16);
140bf215546Sopenharmony_ci	else
141bf215546Sopenharmony_ci		res = strtoull(c, &cc, 10);
142bf215546Sopenharmony_ci	if (*cc)  {
143bf215546Sopenharmony_ci		rnn_err(db, "%s:%d: invalid numeric value \"%s\" in attribute \"%s\"\n", file, line, c, attr->name);
144bf215546Sopenharmony_ci	}
145bf215546Sopenharmony_ci	return res;
146bf215546Sopenharmony_ci}
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_cistatic uint64_t getnumattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) {
149bf215546Sopenharmony_ci	char *c = getattrib(db, file, line, attr);
150bf215546Sopenharmony_ci	return getnum(db, file, line, attr, c);
151bf215546Sopenharmony_ci}
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_cistatic int trytop (struct rnndb *db, char *file, xmlNode *node);
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_cistatic int trydoc (struct rnndb *db, char *file, xmlNode *node) {
156bf215546Sopenharmony_ci	if (!strcmp(node->name, "brief")) {
157bf215546Sopenharmony_ci		return 1;
158bf215546Sopenharmony_ci	} else if (!strcmp(node->name, "doc")) {
159bf215546Sopenharmony_ci		return 1;
160bf215546Sopenharmony_ci	}
161bf215546Sopenharmony_ci	return 0;
162bf215546Sopenharmony_ci}
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_cistatic struct rnnvalue *parsevalue(struct rnndb *db, char *file, xmlNode *node);
165bf215546Sopenharmony_cistatic struct rnnbitfield *parsebitfield(struct rnndb *db, char *file, xmlNode *node);
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_cistatic int trytypetag (struct rnndb *db, char *file, xmlNode *node, struct rnntypeinfo *ti) {
168bf215546Sopenharmony_ci	if (!strcmp(node->name, "value")) {
169bf215546Sopenharmony_ci		struct rnnvalue *val = parsevalue(db, file, node);
170bf215546Sopenharmony_ci		if (val)
171bf215546Sopenharmony_ci			ADDARRAY(ti->vals, val);
172bf215546Sopenharmony_ci		return 1;
173bf215546Sopenharmony_ci	} else if (!strcmp(node->name, "bitfield")) {
174bf215546Sopenharmony_ci		struct rnnbitfield *bf = parsebitfield(db, file, node);
175bf215546Sopenharmony_ci		if (bf)
176bf215546Sopenharmony_ci			ADDARRAY(ti->bitfields, bf);
177bf215546Sopenharmony_ci		return 1;
178bf215546Sopenharmony_ci	}
179bf215546Sopenharmony_ci	return 0;
180bf215546Sopenharmony_ci}
181bf215546Sopenharmony_cistatic int trytypeattr (struct rnndb *db, char *file, xmlNode *node, xmlAttr *attr, struct rnntypeinfo *ti) {
182bf215546Sopenharmony_ci	if (!strcmp(attr->name, "shr")) {
183bf215546Sopenharmony_ci		ti->shr = getnumattrib(db, file, node->line, attr);
184bf215546Sopenharmony_ci		return 1;
185bf215546Sopenharmony_ci	} else if (!strcmp(attr->name, "min")) {
186bf215546Sopenharmony_ci		ti->min = getnumattrib(db, file, node->line, attr);
187bf215546Sopenharmony_ci		ti->minvalid = 1;
188bf215546Sopenharmony_ci		return 1;
189bf215546Sopenharmony_ci	} else if (!strcmp(attr->name, "max")) {
190bf215546Sopenharmony_ci		ti->max = getnumattrib(db, file, node->line, attr);
191bf215546Sopenharmony_ci		ti->maxvalid = 1;
192bf215546Sopenharmony_ci		return 1;
193bf215546Sopenharmony_ci	} else if (!strcmp(attr->name, "align")) {
194bf215546Sopenharmony_ci		ti->align = getnumattrib(db, file, node->line, attr);
195bf215546Sopenharmony_ci		ti->alignvalid = 1;
196bf215546Sopenharmony_ci		return 1;
197bf215546Sopenharmony_ci	} else if (!strcmp(attr->name, "type")) {
198bf215546Sopenharmony_ci		ti->name = strdup(getattrib(db, file, node->line, attr));;
199bf215546Sopenharmony_ci		return 1;
200bf215546Sopenharmony_ci	} else if (!strcmp(attr->name, "radix")) {
201bf215546Sopenharmony_ci		ti->radix = getnumattrib(db, file, node->line, attr);
202bf215546Sopenharmony_ci		ti->radixvalid = 1;
203bf215546Sopenharmony_ci		return 1;
204bf215546Sopenharmony_ci	} else if (!strcmp(attr->name, "pos")) {
205bf215546Sopenharmony_ci		ti->high = ti->low = getnumattrib(db, file, node->line, attr);
206bf215546Sopenharmony_ci		return 1;
207bf215546Sopenharmony_ci	} else if (!strcmp(attr->name, "low")) {
208bf215546Sopenharmony_ci		ti->low = getnumattrib(db, file, node->line, attr);
209bf215546Sopenharmony_ci		return 1;
210bf215546Sopenharmony_ci	} else if (!strcmp(attr->name, "high")) {
211bf215546Sopenharmony_ci		ti->high = getnumattrib(db, file, node->line, attr);
212bf215546Sopenharmony_ci		return 1;
213bf215546Sopenharmony_ci	} else if (!strcmp(attr->name, "addvariant")) {
214bf215546Sopenharmony_ci		ti->addvariant = getboolattrib(db, file, node->line, attr);
215bf215546Sopenharmony_ci		return 1;
216bf215546Sopenharmony_ci	}
217bf215546Sopenharmony_ci	return 0;
218bf215546Sopenharmony_ci}
219bf215546Sopenharmony_ci
220bf215546Sopenharmony_cistatic struct rnnvalue *parsevalue(struct rnndb *db, char *file, xmlNode *node) {
221bf215546Sopenharmony_ci	struct rnnvalue *val = calloc(sizeof *val, 1);
222bf215546Sopenharmony_ci	val->file = file;
223bf215546Sopenharmony_ci	xmlAttr *attr = node->properties;
224bf215546Sopenharmony_ci	while (attr) {
225bf215546Sopenharmony_ci		if (!strcmp(attr->name, "name")) {
226bf215546Sopenharmony_ci			val->name = strdup(getattrib(db, file, node->line, attr));
227bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "value")) {
228bf215546Sopenharmony_ci			val->value = getnumattrib(db, file, node->line, attr);
229bf215546Sopenharmony_ci			val->valvalid = 1;
230bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "varset")) {
231bf215546Sopenharmony_ci			val->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
232bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "variants")) {
233bf215546Sopenharmony_ci			val->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
234bf215546Sopenharmony_ci		} else {
235bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong attribute \"%s\" for value\n", file, node->line, attr->name);
236bf215546Sopenharmony_ci		}
237bf215546Sopenharmony_ci		attr = attr->next;
238bf215546Sopenharmony_ci	}
239bf215546Sopenharmony_ci	xmlNode *chain = node->children;
240bf215546Sopenharmony_ci	while (chain) {
241bf215546Sopenharmony_ci		if (chain->type != XML_ELEMENT_NODE) {
242bf215546Sopenharmony_ci		} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
243bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
244bf215546Sopenharmony_ci		}
245bf215546Sopenharmony_ci		chain = chain->next;
246bf215546Sopenharmony_ci	}
247bf215546Sopenharmony_ci	if (!val->name) {
248bf215546Sopenharmony_ci		rnn_err(db, "%s:%d: nameless value\n", file, node->line);
249bf215546Sopenharmony_ci		return 0;
250bf215546Sopenharmony_ci	} else {
251bf215546Sopenharmony_ci		return val;
252bf215546Sopenharmony_ci	}
253bf215546Sopenharmony_ci}
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_cistatic void parsespectype(struct rnndb *db, char *file, xmlNode *node) {
256bf215546Sopenharmony_ci	struct rnnspectype *res = calloc (sizeof *res, 1);
257bf215546Sopenharmony_ci	res->file = file;
258bf215546Sopenharmony_ci	xmlAttr *attr = node->properties;
259bf215546Sopenharmony_ci	int i;
260bf215546Sopenharmony_ci	while (attr) {
261bf215546Sopenharmony_ci		if (!strcmp(attr->name, "name")) {
262bf215546Sopenharmony_ci			res->name = strdup(getattrib(db, file, node->line, attr));
263bf215546Sopenharmony_ci		} else if (!trytypeattr(db, file, node, attr, &res->typeinfo)) {
264bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong attribute \"%s\" for spectype\n", file, node->line, attr->name);
265bf215546Sopenharmony_ci		}
266bf215546Sopenharmony_ci		attr = attr->next;
267bf215546Sopenharmony_ci	}
268bf215546Sopenharmony_ci	if (!res->name) {
269bf215546Sopenharmony_ci		rnn_err(db, "%s:%d: nameless spectype\n", file, node->line);
270bf215546Sopenharmony_ci		return;
271bf215546Sopenharmony_ci	}
272bf215546Sopenharmony_ci	for (i = 0; i < db->spectypesnum; i++)
273bf215546Sopenharmony_ci		if (!strcmp(db->spectypes[i]->name, res->name)) {
274bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: duplicated spectype name %s\n", file, node->line, res->name);
275bf215546Sopenharmony_ci			return;
276bf215546Sopenharmony_ci		}
277bf215546Sopenharmony_ci	ADDARRAY(db->spectypes, res);
278bf215546Sopenharmony_ci	xmlNode *chain = node->children;
279bf215546Sopenharmony_ci	while (chain) {
280bf215546Sopenharmony_ci		if (chain->type != XML_ELEMENT_NODE) {
281bf215546Sopenharmony_ci		} else if (!trytypetag(db, file, chain, &res->typeinfo) && !trytop(db, file, chain) && !trydoc(db, file, chain)) {
282bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong tag in spectype: <%s>\n", file, chain->line, chain->name);
283bf215546Sopenharmony_ci		}
284bf215546Sopenharmony_ci		chain = chain->next;
285bf215546Sopenharmony_ci	}
286bf215546Sopenharmony_ci}
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_cistatic void parseenum(struct rnndb *db, char *file, xmlNode *node) {
289bf215546Sopenharmony_ci	xmlAttr *attr = node->properties;
290bf215546Sopenharmony_ci	char *name = 0;
291bf215546Sopenharmony_ci	int isinline = 0;
292bf215546Sopenharmony_ci	int bare = 0;
293bf215546Sopenharmony_ci	char *prefixstr = 0;
294bf215546Sopenharmony_ci	char *varsetstr = 0;
295bf215546Sopenharmony_ci	char *variantsstr = 0;
296bf215546Sopenharmony_ci	int i;
297bf215546Sopenharmony_ci	while (attr) {
298bf215546Sopenharmony_ci		if (!strcmp(attr->name, "name")) {
299bf215546Sopenharmony_ci			name = getattrib(db, file, node->line, attr);
300bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "bare")) {
301bf215546Sopenharmony_ci			bare = getboolattrib(db, file, node->line, attr);
302bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "inline")) {
303bf215546Sopenharmony_ci			isinline = getboolattrib(db, file, node->line, attr);
304bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "prefix")) {
305bf215546Sopenharmony_ci			prefixstr = strdup(getattrib(db, file, node->line, attr));
306bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "varset")) {
307bf215546Sopenharmony_ci			varsetstr = strdup(getattrib(db, file, node->line, attr));
308bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "variants")) {
309bf215546Sopenharmony_ci			variantsstr = strdup(getattrib(db, file, node->line, attr));
310bf215546Sopenharmony_ci		} else {
311bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong attribute \"%s\" for enum\n", file, node->line, attr->name);
312bf215546Sopenharmony_ci		}
313bf215546Sopenharmony_ci		attr = attr->next;
314bf215546Sopenharmony_ci	}
315bf215546Sopenharmony_ci	if (!name) {
316bf215546Sopenharmony_ci		rnn_err(db, "%s:%d: nameless enum\n", file, node->line);
317bf215546Sopenharmony_ci		return;
318bf215546Sopenharmony_ci	}
319bf215546Sopenharmony_ci	struct rnnenum *cur = 0;
320bf215546Sopenharmony_ci	for (i = 0; i < db->enumsnum; i++)
321bf215546Sopenharmony_ci		if (!strcmp(db->enums[i]->name, name)) {
322bf215546Sopenharmony_ci			cur = db->enums[i];
323bf215546Sopenharmony_ci			break;
324bf215546Sopenharmony_ci		}
325bf215546Sopenharmony_ci	if (cur) {
326bf215546Sopenharmony_ci		if (strdiff(cur->varinfo.prefixstr, prefixstr) ||
327bf215546Sopenharmony_ci				strdiff(cur->varinfo.varsetstr, varsetstr) ||
328bf215546Sopenharmony_ci				strdiff(cur->varinfo.variantsstr, variantsstr) ||
329bf215546Sopenharmony_ci				cur->isinline != isinline || cur->bare != bare) {
330bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: merge fail for enum %s\n", file, node->line, node->name);
331bf215546Sopenharmony_ci		}
332bf215546Sopenharmony_ci	} else {
333bf215546Sopenharmony_ci		cur = calloc(sizeof *cur, 1);
334bf215546Sopenharmony_ci		cur->name = strdup(name);
335bf215546Sopenharmony_ci		cur->isinline = isinline;
336bf215546Sopenharmony_ci		cur->bare = bare;
337bf215546Sopenharmony_ci		cur->varinfo.prefixstr = prefixstr;
338bf215546Sopenharmony_ci		cur->varinfo.varsetstr = varsetstr;
339bf215546Sopenharmony_ci		cur->varinfo.variantsstr = variantsstr;
340bf215546Sopenharmony_ci		cur->file = file;
341bf215546Sopenharmony_ci		ADDARRAY(db->enums, cur);
342bf215546Sopenharmony_ci	}
343bf215546Sopenharmony_ci	xmlNode *chain = node->children;
344bf215546Sopenharmony_ci	while (chain) {
345bf215546Sopenharmony_ci		if (chain->type != XML_ELEMENT_NODE) {
346bf215546Sopenharmony_ci		} else if (!strcmp(chain->name, "value")) {
347bf215546Sopenharmony_ci			struct rnnvalue *val = parsevalue(db, file, chain);
348bf215546Sopenharmony_ci			if (val)
349bf215546Sopenharmony_ci				ADDARRAY(cur->vals, val);
350bf215546Sopenharmony_ci		} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
351bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong tag in enum: <%s>\n", file, chain->line, chain->name);
352bf215546Sopenharmony_ci		}
353bf215546Sopenharmony_ci		chain = chain->next;
354bf215546Sopenharmony_ci	}
355bf215546Sopenharmony_ci}
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_cistatic struct rnnbitfield *parsebitfield(struct rnndb *db, char *file, xmlNode *node) {
358bf215546Sopenharmony_ci	struct rnnbitfield *bf = calloc(sizeof *bf, 1);
359bf215546Sopenharmony_ci	bf->file = file;
360bf215546Sopenharmony_ci	xmlAttr *attr = node->properties;
361bf215546Sopenharmony_ci	bf->typeinfo.low = bf->typeinfo.high = -1;
362bf215546Sopenharmony_ci	while (attr) {
363bf215546Sopenharmony_ci		if (!strcmp(attr->name, "name")) {
364bf215546Sopenharmony_ci			bf->name = strdup(getattrib(db, file, node->line, attr));
365bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "varset")) {
366bf215546Sopenharmony_ci			bf->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
367bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "variants")) {
368bf215546Sopenharmony_ci			bf->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
369bf215546Sopenharmony_ci		} else if (!trytypeattr(db, file, node, attr, &bf->typeinfo)) {
370bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong attribute \"%s\" for bitfield\n", file, node->line, attr->name);
371bf215546Sopenharmony_ci		}
372bf215546Sopenharmony_ci		attr = attr->next;
373bf215546Sopenharmony_ci	}
374bf215546Sopenharmony_ci	xmlNode *chain = node->children;
375bf215546Sopenharmony_ci	while (chain) {
376bf215546Sopenharmony_ci		if (chain->type != XML_ELEMENT_NODE) {
377bf215546Sopenharmony_ci		} else if (!trytypetag(db, file, chain, &bf->typeinfo) && !trytop(db, file, chain) && !trydoc(db, file, chain)) {
378bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
379bf215546Sopenharmony_ci		}
380bf215546Sopenharmony_ci		chain = chain->next;
381bf215546Sopenharmony_ci	}
382bf215546Sopenharmony_ci	if (!bf->name) {
383bf215546Sopenharmony_ci		rnn_err(db, "%s:%d: nameless bitfield\n", file, node->line);
384bf215546Sopenharmony_ci		return 0;
385bf215546Sopenharmony_ci	} else if (bf->typeinfo.low < 0|| bf->typeinfo.high < 0 || bf->typeinfo.high < bf->typeinfo.low) {
386bf215546Sopenharmony_ci		rnn_err(db, "%s:%d: bitfield has wrong placement\n", file, node->line);
387bf215546Sopenharmony_ci		return 0;
388bf215546Sopenharmony_ci	} else {
389bf215546Sopenharmony_ci		return bf;
390bf215546Sopenharmony_ci	}
391bf215546Sopenharmony_ci}
392bf215546Sopenharmony_ci
393bf215546Sopenharmony_cistatic void parsebitset(struct rnndb *db, char *file, xmlNode *node) {
394bf215546Sopenharmony_ci	xmlAttr *attr = node->properties;
395bf215546Sopenharmony_ci	char *name = 0;
396bf215546Sopenharmony_ci	int isinline = 0;
397bf215546Sopenharmony_ci	int bare = 0;
398bf215546Sopenharmony_ci	char *prefixstr = 0;
399bf215546Sopenharmony_ci	char *varsetstr = 0;
400bf215546Sopenharmony_ci	char *variantsstr = 0;
401bf215546Sopenharmony_ci	int i;
402bf215546Sopenharmony_ci	while (attr) {
403bf215546Sopenharmony_ci		if (!strcmp(attr->name, "name")) {
404bf215546Sopenharmony_ci			name = getattrib(db, file, node->line, attr);
405bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "bare")) {
406bf215546Sopenharmony_ci			bare = getboolattrib(db, file, node->line, attr);
407bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "inline")) {
408bf215546Sopenharmony_ci			isinline = getboolattrib(db, file, node->line, attr);
409bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "prefix")) {
410bf215546Sopenharmony_ci			prefixstr = strdup(getattrib(db, file, node->line, attr));
411bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "varset")) {
412bf215546Sopenharmony_ci			varsetstr = strdup(getattrib(db, file, node->line, attr));
413bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "variants")) {
414bf215546Sopenharmony_ci			variantsstr = strdup(getattrib(db, file, node->line, attr));
415bf215546Sopenharmony_ci		} else {
416bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong attribute \"%s\" for bitset\n", file, node->line, attr->name);
417bf215546Sopenharmony_ci		}
418bf215546Sopenharmony_ci		attr = attr->next;
419bf215546Sopenharmony_ci	}
420bf215546Sopenharmony_ci	if (!name) {
421bf215546Sopenharmony_ci		rnn_err(db, "%s:%d: nameless bitset\n", file, node->line);
422bf215546Sopenharmony_ci		return;
423bf215546Sopenharmony_ci	}
424bf215546Sopenharmony_ci	struct rnnbitset *cur = 0;
425bf215546Sopenharmony_ci	for (i = 0; i < db->bitsetsnum; i++)
426bf215546Sopenharmony_ci		if (!strcmp(db->bitsets[i]->name, name)) {
427bf215546Sopenharmony_ci			cur = db->bitsets[i];
428bf215546Sopenharmony_ci			break;
429bf215546Sopenharmony_ci		}
430bf215546Sopenharmony_ci	if (cur) {
431bf215546Sopenharmony_ci		if (strdiff(cur->varinfo.prefixstr, prefixstr) ||
432bf215546Sopenharmony_ci				strdiff(cur->varinfo.varsetstr, varsetstr) ||
433bf215546Sopenharmony_ci				strdiff(cur->varinfo.variantsstr, variantsstr) ||
434bf215546Sopenharmony_ci				cur->isinline != isinline || cur->bare != bare) {
435bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: merge fail for bitset %s\n", file, node->line, node->name);
436bf215546Sopenharmony_ci		}
437bf215546Sopenharmony_ci	} else {
438bf215546Sopenharmony_ci		cur = calloc(sizeof *cur, 1);
439bf215546Sopenharmony_ci		cur->name = strdup(name);
440bf215546Sopenharmony_ci		cur->isinline = isinline;
441bf215546Sopenharmony_ci		cur->bare = bare;
442bf215546Sopenharmony_ci		cur->varinfo.prefixstr = prefixstr;
443bf215546Sopenharmony_ci		cur->varinfo.varsetstr = varsetstr;
444bf215546Sopenharmony_ci		cur->varinfo.variantsstr = variantsstr;
445bf215546Sopenharmony_ci		cur->file = file;
446bf215546Sopenharmony_ci		ADDARRAY(db->bitsets, cur);
447bf215546Sopenharmony_ci	}
448bf215546Sopenharmony_ci	xmlNode *chain = node->children;
449bf215546Sopenharmony_ci	while (chain) {
450bf215546Sopenharmony_ci		if (chain->type != XML_ELEMENT_NODE) {
451bf215546Sopenharmony_ci		} else if (!strcmp(chain->name, "bitfield")) {
452bf215546Sopenharmony_ci			struct rnnbitfield *bf = parsebitfield(db, file, chain);
453bf215546Sopenharmony_ci			if (bf)
454bf215546Sopenharmony_ci				ADDARRAY(cur->bitfields, bf);
455bf215546Sopenharmony_ci		} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
456bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong tag in bitset: <%s>\n", file, chain->line, chain->name);
457bf215546Sopenharmony_ci		}
458bf215546Sopenharmony_ci		chain = chain->next;
459bf215546Sopenharmony_ci	}
460bf215546Sopenharmony_ci}
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_cistatic struct rnndelem *trydelem(struct rnndb *db, char *file, xmlNode *node) {
463bf215546Sopenharmony_ci	if (!strcmp(node->name, "use-group")) {
464bf215546Sopenharmony_ci		struct rnndelem *res = calloc(sizeof *res, 1);
465bf215546Sopenharmony_ci		res->file = file;
466bf215546Sopenharmony_ci		res->type = RNN_ETYPE_USE_GROUP;
467bf215546Sopenharmony_ci		xmlAttr *attr = node->properties;
468bf215546Sopenharmony_ci		while (attr) {
469bf215546Sopenharmony_ci			if (!strcmp(attr->name, "ref")) {
470bf215546Sopenharmony_ci				res->name = strdup(getattrib(db, file, node->line, attr));
471bf215546Sopenharmony_ci			} else {
472bf215546Sopenharmony_ci				rnn_err(db, "%s:%d: wrong attribute \"%s\" for %s\n", file, node->line, attr->name, node->name);
473bf215546Sopenharmony_ci			}
474bf215546Sopenharmony_ci			attr = attr->next;
475bf215546Sopenharmony_ci		}
476bf215546Sopenharmony_ci		if (!res->name) {
477bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: nameless use-group\n", file, node->line);
478bf215546Sopenharmony_ci			return 0;
479bf215546Sopenharmony_ci		}
480bf215546Sopenharmony_ci		return res;
481bf215546Sopenharmony_ci	} else if (!strcmp(node->name, "stripe") || !strcmp(node->name, "array")) {
482bf215546Sopenharmony_ci		struct rnndelem *res = calloc(sizeof *res, 1);
483bf215546Sopenharmony_ci		if (!strcmp(node->name, "array"))
484bf215546Sopenharmony_ci			res->name = "";
485bf215546Sopenharmony_ci		res->type = (strcmp(node->name, "stripe")?RNN_ETYPE_ARRAY:RNN_ETYPE_STRIPE);
486bf215546Sopenharmony_ci		res->length = 1;
487bf215546Sopenharmony_ci		res->file = file;
488bf215546Sopenharmony_ci		xmlAttr *attr = node->properties;
489bf215546Sopenharmony_ci		while (attr) {
490bf215546Sopenharmony_ci			if (!strcmp(attr->name, "name")) {
491bf215546Sopenharmony_ci				res->name = strdup(getattrib(db, file, node->line, attr));
492bf215546Sopenharmony_ci			} else if (!strcmp(attr->name, "offset")) {
493bf215546Sopenharmony_ci				res->offset = getnumattrib(db, file, node->line, attr);
494bf215546Sopenharmony_ci			} else if (!strcmp(attr->name, "offsets")) {
495bf215546Sopenharmony_ci				char *str = strdup(getattrib(db, file, node->line, attr));
496bf215546Sopenharmony_ci				char *tok, *save, *tmp = str;
497bf215546Sopenharmony_ci				while ((tok = strtok_r(str, ",", &save))) {
498bf215546Sopenharmony_ci					uint64_t offset = getnum(db, file, node->line, attr, tok);
499bf215546Sopenharmony_ci					ADDARRAY(res->offsets, offset);
500bf215546Sopenharmony_ci					str = NULL;
501bf215546Sopenharmony_ci				}
502bf215546Sopenharmony_ci				if (str)
503bf215546Sopenharmony_ci					fprintf(stderr, "%s:%d: invalid offsets: %s\n", file, node->line, str);
504bf215546Sopenharmony_ci				free(tmp);
505bf215546Sopenharmony_ci			} else if (!strcmp(attr->name, "doffset")) {
506bf215546Sopenharmony_ci				/* dynamic runtime determined offset: */
507bf215546Sopenharmony_ci				res->doffset = strdup(getattrib(db, file, node->line, attr));
508bf215546Sopenharmony_ci			} else if (!strcmp(attr->name, "doffsets")) {
509bf215546Sopenharmony_ci				/* dynamic runtime determined offsets: */
510bf215546Sopenharmony_ci				char *str = strdup(getattrib(db, file, node->line, attr));
511bf215546Sopenharmony_ci				char *tok, *save, *tmp = str;
512bf215546Sopenharmony_ci				while ((tok = strtok_r(str, ",", &save))) {
513bf215546Sopenharmony_ci					char *doffset = strdup(tok);
514bf215546Sopenharmony_ci					ADDARRAY(res->doffsets, doffset);
515bf215546Sopenharmony_ci					str = NULL;
516bf215546Sopenharmony_ci				}
517bf215546Sopenharmony_ci				if (str)
518bf215546Sopenharmony_ci					fprintf(stderr, "%s:%d: invalid offsets: %s\n", file, node->line, str);
519bf215546Sopenharmony_ci				free(tmp);
520bf215546Sopenharmony_ci			} else if (!strcmp(attr->name, "length")) {
521bf215546Sopenharmony_ci				res->length = getnumattrib(db, file, node->line, attr);
522bf215546Sopenharmony_ci			} else if (!strcmp(attr->name, "stride")) {
523bf215546Sopenharmony_ci				res->stride = getnumattrib(db, file, node->line, attr);
524bf215546Sopenharmony_ci			} else if (!strcmp(attr->name, "prefix")) {
525bf215546Sopenharmony_ci				res->varinfo.prefixstr = strdup(getattrib(db, file, node->line, attr));
526bf215546Sopenharmony_ci			} else if (!strcmp(attr->name, "varset")) {
527bf215546Sopenharmony_ci				res->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
528bf215546Sopenharmony_ci			} else if (!strcmp(attr->name, "variants")) {
529bf215546Sopenharmony_ci				res->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
530bf215546Sopenharmony_ci			} else if (!strcmp(attr->name, "index")) {
531bf215546Sopenharmony_ci				const char *enumname = getattrib(db, file, node->line, attr);
532bf215546Sopenharmony_ci				res->index = rnn_findenum(db, enumname);
533bf215546Sopenharmony_ci				if (!res->index) {
534bf215546Sopenharmony_ci					rnn_err(db, "%s:%d: invalid enum name \"%s\"\n", file, node->line, enumname);
535bf215546Sopenharmony_ci				}
536bf215546Sopenharmony_ci			} else {
537bf215546Sopenharmony_ci				rnn_err(db, "%s:%d: wrong attribute \"%s\" for %s\n", file, node->line, attr->name, node->name);
538bf215546Sopenharmony_ci			}
539bf215546Sopenharmony_ci			attr = attr->next;
540bf215546Sopenharmony_ci		}
541bf215546Sopenharmony_ci		xmlNode *chain = node->children;
542bf215546Sopenharmony_ci		while (chain) {
543bf215546Sopenharmony_ci			struct rnndelem *delem;
544bf215546Sopenharmony_ci			if (chain->type != XML_ELEMENT_NODE) {
545bf215546Sopenharmony_ci			} else if ((delem = trydelem(db, file, chain))) {
546bf215546Sopenharmony_ci				ADDARRAY(res->subelems, delem);
547bf215546Sopenharmony_ci			} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
548bf215546Sopenharmony_ci				rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
549bf215546Sopenharmony_ci			}
550bf215546Sopenharmony_ci			chain = chain->next;
551bf215546Sopenharmony_ci		}
552bf215546Sopenharmony_ci
553bf215546Sopenharmony_ci		/* Sanity checking */
554bf215546Sopenharmony_ci		if (res->type == RNN_ETYPE_ARRAY && res->stride == 0) {
555bf215546Sopenharmony_ci			fprintf(stderr, "%s: Array %s's stride is undefined. Aborting.\n", file, res->name);
556bf215546Sopenharmony_ci			exit(-1);
557bf215546Sopenharmony_ci		}
558bf215546Sopenharmony_ci		return res;
559bf215546Sopenharmony_ci
560bf215546Sopenharmony_ci	}
561bf215546Sopenharmony_ci	int width;
562bf215546Sopenharmony_ci	if (!strcmp(node->name, "reg8"))
563bf215546Sopenharmony_ci		width = 8;
564bf215546Sopenharmony_ci	else if (!strcmp(node->name, "reg16"))
565bf215546Sopenharmony_ci		width = 16;
566bf215546Sopenharmony_ci	else if (!strcmp(node->name, "reg32"))
567bf215546Sopenharmony_ci		width = 32;
568bf215546Sopenharmony_ci	else if (!strcmp(node->name, "reg64"))
569bf215546Sopenharmony_ci		width = 64;
570bf215546Sopenharmony_ci	else
571bf215546Sopenharmony_ci		return 0;
572bf215546Sopenharmony_ci	struct rnndelem *res = calloc(sizeof *res, 1);
573bf215546Sopenharmony_ci	res->file = file;
574bf215546Sopenharmony_ci	res->type = RNN_ETYPE_REG;
575bf215546Sopenharmony_ci	res->width = width;
576bf215546Sopenharmony_ci	res->length = 1;
577bf215546Sopenharmony_ci	res->access = RNN_ACCESS_RW;
578bf215546Sopenharmony_ci	xmlAttr *attr = node->properties;
579bf215546Sopenharmony_ci	res->typeinfo.low = 0;
580bf215546Sopenharmony_ci	res->typeinfo.high = width - 1;
581bf215546Sopenharmony_ci	while (attr) {
582bf215546Sopenharmony_ci		if (!strcmp(attr->name, "name")) {
583bf215546Sopenharmony_ci			res->name = strdup(getattrib(db, file, node->line, attr));
584bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "offset")) {
585bf215546Sopenharmony_ci			res->offset = getnumattrib(db, file, node->line, attr);
586bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "length")) {
587bf215546Sopenharmony_ci			res->length = getnumattrib(db, file, node->line, attr);
588bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "stride")) {
589bf215546Sopenharmony_ci			res->stride = getnumattrib(db, file, node->line, attr);
590bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "varset")) {
591bf215546Sopenharmony_ci			res->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
592bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "variants")) {
593bf215546Sopenharmony_ci			res->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
594bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "access")) {
595bf215546Sopenharmony_ci			char *str = getattrib(db, file, node->line, attr);
596bf215546Sopenharmony_ci			if (!strcmp(str, "r"))
597bf215546Sopenharmony_ci				res->access = RNN_ACCESS_R;
598bf215546Sopenharmony_ci			else if (!strcmp(str, "w"))
599bf215546Sopenharmony_ci				res->access = RNN_ACCESS_W;
600bf215546Sopenharmony_ci			else if (!strcmp(str, "rw"))
601bf215546Sopenharmony_ci				res->access = RNN_ACCESS_RW;
602bf215546Sopenharmony_ci			else
603bf215546Sopenharmony_ci				fprintf (stderr, "%s:%d: wrong access type \"%s\" for register\n", file, node->line, str);
604bf215546Sopenharmony_ci		} else if (!trytypeattr(db, file, node, attr, &res->typeinfo)) {
605bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong attribute \"%s\" for register\n", file, node->line, attr->name);
606bf215546Sopenharmony_ci		}
607bf215546Sopenharmony_ci		attr = attr->next;
608bf215546Sopenharmony_ci	}
609bf215546Sopenharmony_ci	xmlNode *chain = node->children;
610bf215546Sopenharmony_ci	while (chain) {
611bf215546Sopenharmony_ci		if (chain->type != XML_ELEMENT_NODE) {
612bf215546Sopenharmony_ci		} else if (!trytypetag(db, file, chain, &res->typeinfo) && !trytop(db, file, chain) && !trydoc(db, file, chain)) {
613bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
614bf215546Sopenharmony_ci		}
615bf215546Sopenharmony_ci		chain = chain->next;
616bf215546Sopenharmony_ci	}
617bf215546Sopenharmony_ci	if (!res->name) {
618bf215546Sopenharmony_ci		rnn_err(db, "%s:%d: nameless register\n", file, node->line);
619bf215546Sopenharmony_ci		return 0;
620bf215546Sopenharmony_ci	} else {
621bf215546Sopenharmony_ci	}
622bf215546Sopenharmony_ci	return res;
623bf215546Sopenharmony_ci}
624bf215546Sopenharmony_ci
625bf215546Sopenharmony_cistatic void parsegroup(struct rnndb *db, char *file, xmlNode *node) {
626bf215546Sopenharmony_ci	xmlAttr *attr = node->properties;
627bf215546Sopenharmony_ci	char *name = 0;
628bf215546Sopenharmony_ci	int i;
629bf215546Sopenharmony_ci	while (attr) {
630bf215546Sopenharmony_ci		if (!strcmp(attr->name, "name")) {
631bf215546Sopenharmony_ci			name = getattrib(db, file, node->line, attr);
632bf215546Sopenharmony_ci		} else {
633bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong attribute \"%s\" for group\n", file, node->line, attr->name);
634bf215546Sopenharmony_ci		}
635bf215546Sopenharmony_ci		attr = attr->next;
636bf215546Sopenharmony_ci	}
637bf215546Sopenharmony_ci	if (!name) {
638bf215546Sopenharmony_ci		rnn_err(db, "%s:%d: nameless group\n", file, node->line);
639bf215546Sopenharmony_ci		return;
640bf215546Sopenharmony_ci	}
641bf215546Sopenharmony_ci	struct rnngroup *cur = 0;
642bf215546Sopenharmony_ci	for (i = 0; i < db->groupsnum; i++)
643bf215546Sopenharmony_ci		if (!strcmp(db->groups[i]->name, name)) {
644bf215546Sopenharmony_ci			cur = db->groups[i];
645bf215546Sopenharmony_ci			break;
646bf215546Sopenharmony_ci		}
647bf215546Sopenharmony_ci	if (!cur) {
648bf215546Sopenharmony_ci		cur = calloc(sizeof *cur, 1);
649bf215546Sopenharmony_ci		cur->name = strdup(name);
650bf215546Sopenharmony_ci		ADDARRAY(db->groups, cur);
651bf215546Sopenharmony_ci	}
652bf215546Sopenharmony_ci	xmlNode *chain = node->children;
653bf215546Sopenharmony_ci	while (chain) {
654bf215546Sopenharmony_ci		struct rnndelem *delem;
655bf215546Sopenharmony_ci		if (chain->type != XML_ELEMENT_NODE) {
656bf215546Sopenharmony_ci		} else if ((delem = trydelem(db, file, chain))) {
657bf215546Sopenharmony_ci			ADDARRAY(cur->subelems, delem);
658bf215546Sopenharmony_ci		} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
659bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong tag in group: <%s>\n", file, chain->line, chain->name);
660bf215546Sopenharmony_ci		}
661bf215546Sopenharmony_ci		chain = chain->next;
662bf215546Sopenharmony_ci	}
663bf215546Sopenharmony_ci}
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_cistatic void parsedomain(struct rnndb *db, char *file, xmlNode *node) {
666bf215546Sopenharmony_ci	xmlAttr *attr = node->properties;
667bf215546Sopenharmony_ci	char *name = 0;
668bf215546Sopenharmony_ci	uint64_t size = 0; int width = 8;
669bf215546Sopenharmony_ci	int bare = 0;
670bf215546Sopenharmony_ci	char *prefixstr = 0;
671bf215546Sopenharmony_ci	char *varsetstr = 0;
672bf215546Sopenharmony_ci	char *variantsstr = 0;
673bf215546Sopenharmony_ci	int i;
674bf215546Sopenharmony_ci	while (attr) {
675bf215546Sopenharmony_ci		if (!strcmp(attr->name, "name")) {
676bf215546Sopenharmony_ci			name = getattrib(db, file, node->line, attr);
677bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "bare")) {
678bf215546Sopenharmony_ci			bare = getboolattrib(db, file, node->line, attr);
679bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "size")) {
680bf215546Sopenharmony_ci			size = getnumattrib(db, file, node->line, attr);
681bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "width")) {
682bf215546Sopenharmony_ci			width = getnumattrib(db, file, node->line, attr);
683bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "prefix")) {
684bf215546Sopenharmony_ci			prefixstr = strdup(getattrib(db, file, node->line, attr));
685bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "varset")) {
686bf215546Sopenharmony_ci			varsetstr = strdup(getattrib(db, file, node->line, attr));
687bf215546Sopenharmony_ci		} else if (!strcmp(attr->name, "variants")) {
688bf215546Sopenharmony_ci			variantsstr = strdup(getattrib(db, file, node->line, attr));
689bf215546Sopenharmony_ci		} else {
690bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong attribute \"%s\" for domain\n", file, node->line, attr->name);
691bf215546Sopenharmony_ci		}
692bf215546Sopenharmony_ci		attr = attr->next;
693bf215546Sopenharmony_ci	}
694bf215546Sopenharmony_ci	if (!name) {
695bf215546Sopenharmony_ci		rnn_err(db, "%s:%d: nameless domain\n", file, node->line);
696bf215546Sopenharmony_ci		return;
697bf215546Sopenharmony_ci	}
698bf215546Sopenharmony_ci	struct rnndomain *cur = 0;
699bf215546Sopenharmony_ci	for (i = 0; i < db->domainsnum; i++)
700bf215546Sopenharmony_ci		if (!strcmp(db->domains[i]->name, name)) {
701bf215546Sopenharmony_ci			cur = db->domains[i];
702bf215546Sopenharmony_ci			break;
703bf215546Sopenharmony_ci		}
704bf215546Sopenharmony_ci	if (cur) {
705bf215546Sopenharmony_ci		if (strdiff(cur->varinfo.prefixstr, prefixstr) ||
706bf215546Sopenharmony_ci				strdiff(cur->varinfo.varsetstr, varsetstr) ||
707bf215546Sopenharmony_ci				strdiff(cur->varinfo.variantsstr, variantsstr) ||
708bf215546Sopenharmony_ci				cur->width != width ||
709bf215546Sopenharmony_ci				cur->bare != bare ||
710bf215546Sopenharmony_ci				(size && cur->size && size != cur->size)) {
711bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: merge fail for domain %s\n", file, node->line, node->name);
712bf215546Sopenharmony_ci		} else {
713bf215546Sopenharmony_ci			if (size)
714bf215546Sopenharmony_ci				cur->size = size;
715bf215546Sopenharmony_ci		}
716bf215546Sopenharmony_ci	} else {
717bf215546Sopenharmony_ci		cur = calloc(sizeof *cur, 1);
718bf215546Sopenharmony_ci		cur->name = strdup(name);
719bf215546Sopenharmony_ci		cur->bare = bare;
720bf215546Sopenharmony_ci		cur->width = width;
721bf215546Sopenharmony_ci		cur->size = size;
722bf215546Sopenharmony_ci		cur->varinfo.prefixstr = prefixstr;
723bf215546Sopenharmony_ci		cur->varinfo.varsetstr = varsetstr;
724bf215546Sopenharmony_ci		cur->varinfo.variantsstr = variantsstr;
725bf215546Sopenharmony_ci		cur->file = file;
726bf215546Sopenharmony_ci		ADDARRAY(db->domains, cur);
727bf215546Sopenharmony_ci	}
728bf215546Sopenharmony_ci	xmlNode *chain = node->children;
729bf215546Sopenharmony_ci	while (chain) {
730bf215546Sopenharmony_ci		struct rnndelem *delem;
731bf215546Sopenharmony_ci		if (chain->type != XML_ELEMENT_NODE) {
732bf215546Sopenharmony_ci		} else if ((delem = trydelem(db, file, chain))) {
733bf215546Sopenharmony_ci			ADDARRAY(cur->subelems, delem);
734bf215546Sopenharmony_ci		} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
735bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong tag in domain: <%s>\n", file, chain->line, chain->name);
736bf215546Sopenharmony_ci		}
737bf215546Sopenharmony_ci		chain = chain->next;
738bf215546Sopenharmony_ci	}
739bf215546Sopenharmony_ci}
740bf215546Sopenharmony_ci
741bf215546Sopenharmony_cistatic void parsecopyright(struct rnndb *db, char *file, xmlNode *node) {
742bf215546Sopenharmony_ci	struct rnncopyright* copyright = &db->copyright;
743bf215546Sopenharmony_ci	xmlAttr *attr = node->properties;
744bf215546Sopenharmony_ci	while (attr) {
745bf215546Sopenharmony_ci		if (!strcmp(attr->name, "year")) {
746bf215546Sopenharmony_ci			unsigned firstyear = getnumattrib(db, file, node->line, attr);
747bf215546Sopenharmony_ci			if(!copyright->firstyear || firstyear < copyright->firstyear)
748bf215546Sopenharmony_ci				copyright->firstyear = firstyear;
749bf215546Sopenharmony_ci		} else {
750bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong attribute \"%s\" for copyright\n", file, node->line, attr->name);
751bf215546Sopenharmony_ci		}
752bf215546Sopenharmony_ci		attr = attr->next;
753bf215546Sopenharmony_ci	}
754bf215546Sopenharmony_ci	xmlNode *chain = node->children;
755bf215546Sopenharmony_ci	while (chain) {
756bf215546Sopenharmony_ci		if (chain->type != XML_ELEMENT_NODE) {
757bf215546Sopenharmony_ci		} else if (!strcmp(chain->name, "license"))
758bf215546Sopenharmony_ci			if(copyright->license) {
759bf215546Sopenharmony_ci				if(strcmp(copyright->license, node->content)) {
760bf215546Sopenharmony_ci					fprintf(stderr, "fatal error: multiple different licenses specified!\n");
761bf215546Sopenharmony_ci					abort(); /* TODO: do something better here, but headergen, xml2html, etc. should not produce anything in this case */
762bf215546Sopenharmony_ci				}
763bf215546Sopenharmony_ci			} else
764bf215546Sopenharmony_ci				copyright->license = getcontent(chain);
765bf215546Sopenharmony_ci		else if (!strcmp(chain->name, "author")) {
766bf215546Sopenharmony_ci			struct rnnauthor* author = calloc(sizeof *author, 1);
767bf215546Sopenharmony_ci			xmlAttr* authorattr = chain->properties;
768bf215546Sopenharmony_ci			xmlNode *authorchild = chain->children;
769bf215546Sopenharmony_ci			author->contributions = getcontent(chain);
770bf215546Sopenharmony_ci			while (authorattr) {
771bf215546Sopenharmony_ci				if (!strcmp(authorattr->name, "name"))
772bf215546Sopenharmony_ci					author->name = strdup(getattrib(db, file, chain->line, authorattr));
773bf215546Sopenharmony_ci				else if (!strcmp(authorattr->name, "email"))
774bf215546Sopenharmony_ci					author->email = strdup(getattrib(db, file, chain->line, authorattr));
775bf215546Sopenharmony_ci				else {
776bf215546Sopenharmony_ci					rnn_err(db, "%s:%d: wrong attribute \"%s\" for author\n", file, chain->line, authorattr->name);
777bf215546Sopenharmony_ci				}
778bf215546Sopenharmony_ci				authorattr = authorattr->next;
779bf215546Sopenharmony_ci			}
780bf215546Sopenharmony_ci			while(authorchild)  {
781bf215546Sopenharmony_ci				if (authorchild->type != XML_ELEMENT_NODE) {
782bf215546Sopenharmony_ci				} else if (!strcmp(authorchild->name, "nick")) {
783bf215546Sopenharmony_ci					xmlAttr* nickattr = authorchild->properties;
784bf215546Sopenharmony_ci					char* nickname = 0;
785bf215546Sopenharmony_ci					while(nickattr) {
786bf215546Sopenharmony_ci						if (!strcmp(nickattr->name, "name"))
787bf215546Sopenharmony_ci							nickname = strdup(getattrib(db, file, authorchild->line, nickattr));
788bf215546Sopenharmony_ci						else {
789bf215546Sopenharmony_ci							rnn_err(db, "%s:%d: wrong attribute \"%s\" for nick\n", file, authorchild->line, nickattr->name);
790bf215546Sopenharmony_ci						}
791bf215546Sopenharmony_ci						nickattr = nickattr->next;
792bf215546Sopenharmony_ci					}
793bf215546Sopenharmony_ci					if(!nickname) {
794bf215546Sopenharmony_ci						rnn_err(db, "%s:%d: missing \"name\" attribute for nick\n", file, authorchild->line);
795bf215546Sopenharmony_ci					} else
796bf215546Sopenharmony_ci						ADDARRAY(author->nicknames, nickname);
797bf215546Sopenharmony_ci				} else {
798bf215546Sopenharmony_ci					rnn_err(db, "%s:%d: wrong tag in author: <%s>\n", file, authorchild->line, authorchild->name);
799bf215546Sopenharmony_ci				}
800bf215546Sopenharmony_ci				authorchild = authorchild->next;
801bf215546Sopenharmony_ci			}
802bf215546Sopenharmony_ci			ADDARRAY(copyright->authors, author);
803bf215546Sopenharmony_ci		} else {
804bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong tag in copyright: <%s>\n", file, chain->line, chain->name);
805bf215546Sopenharmony_ci		}
806bf215546Sopenharmony_ci		chain = chain->next;
807bf215546Sopenharmony_ci	}
808bf215546Sopenharmony_ci}
809bf215546Sopenharmony_ci
810bf215546Sopenharmony_cistatic int trytop (struct rnndb *db, char *file, xmlNode *node) {
811bf215546Sopenharmony_ci	if (!strcmp(node->name, "enum")) {
812bf215546Sopenharmony_ci		parseenum(db, file, node);
813bf215546Sopenharmony_ci		return 1;
814bf215546Sopenharmony_ci	} else if (!strcmp(node->name, "bitset")) {
815bf215546Sopenharmony_ci		parsebitset(db, file, node);
816bf215546Sopenharmony_ci		return 1;
817bf215546Sopenharmony_ci	} else if (!strcmp(node->name, "group")) {
818bf215546Sopenharmony_ci		parsegroup(db, file, node);
819bf215546Sopenharmony_ci		return 1;
820bf215546Sopenharmony_ci	} else if (!strcmp(node->name, "domain")) {
821bf215546Sopenharmony_ci		parsedomain(db, file, node);
822bf215546Sopenharmony_ci		return 1;
823bf215546Sopenharmony_ci	} else if (!strcmp(node->name, "spectype")) {
824bf215546Sopenharmony_ci		parsespectype(db, file, node);
825bf215546Sopenharmony_ci		return 1;
826bf215546Sopenharmony_ci	} else if (!strcmp(node->name, "import")) {
827bf215546Sopenharmony_ci		xmlAttr *attr = node->properties;
828bf215546Sopenharmony_ci		char *subfile = 0;
829bf215546Sopenharmony_ci		while (attr) {
830bf215546Sopenharmony_ci			if (!strcmp(attr->name, "file")) {
831bf215546Sopenharmony_ci				subfile = getattrib(db, file, node->line, attr);
832bf215546Sopenharmony_ci			} else {
833bf215546Sopenharmony_ci				rnn_err(db, "%s:%d: wrong attribute \"%s\" for import\n", file, node->line, attr->name);
834bf215546Sopenharmony_ci			}
835bf215546Sopenharmony_ci			attr = attr->next;
836bf215546Sopenharmony_ci		}
837bf215546Sopenharmony_ci		if (!subfile) {
838bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: missing \"file\" attribute for import\n", file, node->line);
839bf215546Sopenharmony_ci		} else {
840bf215546Sopenharmony_ci			rnn_parsefile(db, subfile);
841bf215546Sopenharmony_ci		}
842bf215546Sopenharmony_ci		return 1;
843bf215546Sopenharmony_ci	} else if (!strcmp(node->name, "copyright")) {
844bf215546Sopenharmony_ci		parsecopyright(db, file, node);
845bf215546Sopenharmony_ci		return 1;
846bf215546Sopenharmony_ci	}
847bf215546Sopenharmony_ci	return 0;
848bf215546Sopenharmony_ci}
849bf215546Sopenharmony_ci
850bf215546Sopenharmony_cistatic char * find_file(const char *file_orig)
851bf215546Sopenharmony_ci{
852bf215546Sopenharmony_ci	const char *rnn_path = getenv("RNN_PATH");
853bf215546Sopenharmony_ci	char *fname;
854bf215546Sopenharmony_ci
855bf215546Sopenharmony_ci	if (!rnn_path)
856bf215546Sopenharmony_ci		rnn_path = RNN_DEF_PATH;
857bf215546Sopenharmony_ci
858bf215546Sopenharmony_ci	FILE *file = find_in_path(file_orig, rnn_path, &fname);
859bf215546Sopenharmony_ci	if (!file) {
860bf215546Sopenharmony_ci		fprintf (stderr, "%s: couldn't find database file. Please set the env var RNN_PATH.\n", file_orig);
861bf215546Sopenharmony_ci		return NULL;
862bf215546Sopenharmony_ci	}
863bf215546Sopenharmony_ci	fclose(file);
864bf215546Sopenharmony_ci
865bf215546Sopenharmony_ci	return fname;
866bf215546Sopenharmony_ci}
867bf215546Sopenharmony_ci
868bf215546Sopenharmony_cistatic int validate_doc(struct rnndb *db, xmlDocPtr doc, xmlNodePtr database)
869bf215546Sopenharmony_ci{
870bf215546Sopenharmony_ci	/* find the schemaLocation property: */
871bf215546Sopenharmony_ci	xmlAttrPtr attr = database->properties;
872bf215546Sopenharmony_ci	const char *schema_name = NULL;
873bf215546Sopenharmony_ci	char *schema_path;
874bf215546Sopenharmony_ci
875bf215546Sopenharmony_ci	while (attr) {
876bf215546Sopenharmony_ci		if (!strcmp(attr->name, "schemaLocation")) {
877bf215546Sopenharmony_ci			xmlNodePtr data = attr->children;
878bf215546Sopenharmony_ci			schema_name = data->content;
879bf215546Sopenharmony_ci			/* we expect this to look like <namespace url> schema.xsd.. I think
880bf215546Sopenharmony_ci			 * technically it is supposed to be just a URL, but that doesn't
881bf215546Sopenharmony_ci			 * quite match up to what we do.. Just skip over everything up to
882bf215546Sopenharmony_ci			 * and including the first whitespace character:
883bf215546Sopenharmony_ci			 */
884bf215546Sopenharmony_ci			while (schema_name && (schema_name[0] != ' '))
885bf215546Sopenharmony_ci				schema_name++;
886bf215546Sopenharmony_ci			schema_name++;
887bf215546Sopenharmony_ci			break;
888bf215546Sopenharmony_ci		}
889bf215546Sopenharmony_ci	}
890bf215546Sopenharmony_ci
891bf215546Sopenharmony_ci	if (!schema_name) {
892bf215546Sopenharmony_ci		rnn_err(db, "could not find schema.  Missing schemaLocation?");
893bf215546Sopenharmony_ci		return 0;
894bf215546Sopenharmony_ci	}
895bf215546Sopenharmony_ci
896bf215546Sopenharmony_ci	schema_path = find_file(schema_name);
897bf215546Sopenharmony_ci	if (!schema_path) {
898bf215546Sopenharmony_ci		rnn_err(db, "%s: couldn't find database file. Please set the env var RNN_PATH.\n", schema_name);
899bf215546Sopenharmony_ci		return 0;
900bf215546Sopenharmony_ci	}
901bf215546Sopenharmony_ci
902bf215546Sopenharmony_ci	xmlSchemaParserCtxtPtr parser = xmlSchemaNewParserCtxt(schema_path);
903bf215546Sopenharmony_ci	xmlSchemaPtr schema = xmlSchemaParse(parser);
904bf215546Sopenharmony_ci	xmlSchemaValidCtxtPtr validCtxt = xmlSchemaNewValidCtxt(schema);
905bf215546Sopenharmony_ci	int ret = xmlSchemaValidateDoc(validCtxt, doc);
906bf215546Sopenharmony_ci
907bf215546Sopenharmony_ci	xmlSchemaFreeValidCtxt(validCtxt);
908bf215546Sopenharmony_ci	xmlSchemaFree(schema);
909bf215546Sopenharmony_ci	xmlSchemaFreeParserCtxt(parser);
910bf215546Sopenharmony_ci
911bf215546Sopenharmony_ci	free(schema_path);
912bf215546Sopenharmony_ci
913bf215546Sopenharmony_ci	return ret;
914bf215546Sopenharmony_ci}
915bf215546Sopenharmony_ci
916bf215546Sopenharmony_civoid rnn_parsefile (struct rnndb *db, char *file_orig) {
917bf215546Sopenharmony_ci	int i;
918bf215546Sopenharmony_ci	char *fname;
919bf215546Sopenharmony_ci
920bf215546Sopenharmony_ci	fname = find_file(file_orig);
921bf215546Sopenharmony_ci	if (!fname) {
922bf215546Sopenharmony_ci		db->estatus = 1;
923bf215546Sopenharmony_ci		return;
924bf215546Sopenharmony_ci	}
925bf215546Sopenharmony_ci
926bf215546Sopenharmony_ci	for (i = 0; i < db->filesnum; i++)
927bf215546Sopenharmony_ci		if (!strcmp(db->files[i], fname))
928bf215546Sopenharmony_ci			return;
929bf215546Sopenharmony_ci
930bf215546Sopenharmony_ci	ADDARRAY(db->files, fname);
931bf215546Sopenharmony_ci	xmlDocPtr doc = xmlParseFile(fname);
932bf215546Sopenharmony_ci	if (!doc) {
933bf215546Sopenharmony_ci		rnn_err(db, "%s: couldn't open database file. Please set the env var RNN_PATH.\n", fname);
934bf215546Sopenharmony_ci		return;
935bf215546Sopenharmony_ci	}
936bf215546Sopenharmony_ci	xmlNode *root = doc->children;
937bf215546Sopenharmony_ci	while (root) {
938bf215546Sopenharmony_ci		if (root->type != XML_ELEMENT_NODE) {
939bf215546Sopenharmony_ci		} else if (strcmp(root->name, "database")) {
940bf215546Sopenharmony_ci			rnn_err(db, "%s:%d: wrong top-level tag <%s>\n", fname, root->line, root->name);
941bf215546Sopenharmony_ci		} else {
942bf215546Sopenharmony_ci			xmlNode *chain = root->children;
943bf215546Sopenharmony_ci			if (validate_doc(db, doc, root)) {
944bf215546Sopenharmony_ci				rnn_err(db, "%s: database file has errors\n", fname);
945bf215546Sopenharmony_ci				return;
946bf215546Sopenharmony_ci			}
947bf215546Sopenharmony_ci			while (chain) {
948bf215546Sopenharmony_ci				if (chain->type != XML_ELEMENT_NODE) {
949bf215546Sopenharmony_ci				} else if (!trytop(db, fname, chain) && !trydoc(db, fname, chain)) {
950bf215546Sopenharmony_ci					rnn_err(db, "%s:%d: wrong tag in database: <%s>\n", fname, chain->line, chain->name);
951bf215546Sopenharmony_ci				}
952bf215546Sopenharmony_ci				chain = chain->next;
953bf215546Sopenharmony_ci			}
954bf215546Sopenharmony_ci		}
955bf215546Sopenharmony_ci		root = root->next;
956bf215546Sopenharmony_ci	}
957bf215546Sopenharmony_ci	xmlFreeDoc(doc);
958bf215546Sopenharmony_ci}
959bf215546Sopenharmony_ci
960bf215546Sopenharmony_cistatic struct rnnvalue *copyvalue (struct rnnvalue *val, char *file) {
961bf215546Sopenharmony_ci	struct rnnvalue *res = calloc (sizeof *res, 1);
962bf215546Sopenharmony_ci	res->name = val->name;
963bf215546Sopenharmony_ci	res->valvalid = val->valvalid;
964bf215546Sopenharmony_ci	res->value = val->value;
965bf215546Sopenharmony_ci	res->varinfo = val->varinfo;
966bf215546Sopenharmony_ci	res->file = file;
967bf215546Sopenharmony_ci	return res;
968bf215546Sopenharmony_ci}
969bf215546Sopenharmony_ci
970bf215546Sopenharmony_cistatic struct rnnbitfield *copybitfield (struct rnnbitfield *bf, char *file);
971bf215546Sopenharmony_ci
972bf215546Sopenharmony_ci
973bf215546Sopenharmony_cistatic void copytypeinfo (struct rnntypeinfo *dst, struct rnntypeinfo *src, char *file) {
974bf215546Sopenharmony_ci	int i;
975bf215546Sopenharmony_ci	dst->name = src->name;
976bf215546Sopenharmony_ci	dst->shr = src->shr;
977bf215546Sopenharmony_ci	dst->low = src->low;
978bf215546Sopenharmony_ci	dst->high = src->high;
979bf215546Sopenharmony_ci	dst->min = src->min;
980bf215546Sopenharmony_ci	dst->max = src->max;
981bf215546Sopenharmony_ci	dst->align = src->align;
982bf215546Sopenharmony_ci	dst->addvariant = src->addvariant;
983bf215546Sopenharmony_ci	for (i = 0; i < src->valsnum; i++)
984bf215546Sopenharmony_ci		ADDARRAY(dst->vals, copyvalue(src->vals[i], file));
985bf215546Sopenharmony_ci	for (i = 0; i < src->bitfieldsnum; i++)
986bf215546Sopenharmony_ci		ADDARRAY(dst->bitfields, copybitfield(src->bitfields[i], file));
987bf215546Sopenharmony_ci}
988bf215546Sopenharmony_ci
989bf215546Sopenharmony_cistatic struct rnnbitfield *copybitfield (struct rnnbitfield *bf, char *file) {
990bf215546Sopenharmony_ci	struct rnnbitfield *res = calloc (sizeof *res, 1);
991bf215546Sopenharmony_ci	res->name = bf->name;
992bf215546Sopenharmony_ci	res->varinfo = bf->varinfo;
993bf215546Sopenharmony_ci	res->file = file;
994bf215546Sopenharmony_ci	copytypeinfo(&res->typeinfo, &bf->typeinfo, file);
995bf215546Sopenharmony_ci	return res;
996bf215546Sopenharmony_ci}
997bf215546Sopenharmony_ci
998bf215546Sopenharmony_cistatic struct rnndelem *copydelem (struct rnndelem *elem, char *file) {
999bf215546Sopenharmony_ci	struct rnndelem *res = calloc (sizeof *res, 1);
1000bf215546Sopenharmony_ci	res->type = elem->type;
1001bf215546Sopenharmony_ci	res->name = elem->name;
1002bf215546Sopenharmony_ci	res->width = elem->width;
1003bf215546Sopenharmony_ci	res->access = elem->access;
1004bf215546Sopenharmony_ci	res->offset = elem->offset;
1005bf215546Sopenharmony_ci	res->length = elem->length;
1006bf215546Sopenharmony_ci	res->stride = elem->stride;
1007bf215546Sopenharmony_ci	res->varinfo = elem->varinfo;
1008bf215546Sopenharmony_ci	res->file = file;
1009bf215546Sopenharmony_ci	copytypeinfo(&res->typeinfo, &elem->typeinfo, file);
1010bf215546Sopenharmony_ci	int i;
1011bf215546Sopenharmony_ci	for (i = 0; i < elem->subelemsnum; i++)
1012bf215546Sopenharmony_ci		ADDARRAY(res->subelems, copydelem(elem->subelems[i], file));
1013bf215546Sopenharmony_ci	for (i = 0; i < elem->offsetsnum; i++)
1014bf215546Sopenharmony_ci		ADDARRAY(res->offsets, elem->offsets[i]);
1015bf215546Sopenharmony_ci	return res;
1016bf215546Sopenharmony_ci}
1017bf215546Sopenharmony_ci
1018bf215546Sopenharmony_cistatic struct rnnvarset *copyvarset (struct rnnvarset *varset) {
1019bf215546Sopenharmony_ci	struct rnnvarset *res = calloc(sizeof *res, 1);
1020bf215546Sopenharmony_ci	res->venum = varset->venum;
1021bf215546Sopenharmony_ci	res->variants = calloc(sizeof *res->variants, res->venum->valsnum);
1022bf215546Sopenharmony_ci	int i;
1023bf215546Sopenharmony_ci	for (i = 0; i < res->venum->valsnum; i++)
1024bf215546Sopenharmony_ci		res->variants[i] = varset->variants[i];
1025bf215546Sopenharmony_ci	return res;
1026bf215546Sopenharmony_ci}
1027bf215546Sopenharmony_ci
1028bf215546Sopenharmony_cistatic void prepenum(struct rnndb *db, struct rnnenum *en);
1029bf215546Sopenharmony_ci
1030bf215546Sopenharmony_cistatic int findvidx (struct rnndb *db, struct rnnenum *en, char *name) {
1031bf215546Sopenharmony_ci	int i;
1032bf215546Sopenharmony_ci	for (i = 0; i < en->valsnum; i++)
1033bf215546Sopenharmony_ci		if (!strcmp(en->vals[i]->name, name))
1034bf215546Sopenharmony_ci			return i;
1035bf215546Sopenharmony_ci	rnn_err(db, "Cannot find variant %s in enum %s!\n", name, en->name);
1036bf215546Sopenharmony_ci	return -1;
1037bf215546Sopenharmony_ci}
1038bf215546Sopenharmony_ci
1039bf215546Sopenharmony_cistatic void prepvarinfo (struct rnndb *db, char *what, struct rnnvarinfo *vi, struct rnnvarinfo *parent) {
1040bf215546Sopenharmony_ci	if (parent)
1041bf215546Sopenharmony_ci		vi->prefenum = parent->prefenum;
1042bf215546Sopenharmony_ci	if (vi->prefixstr) {
1043bf215546Sopenharmony_ci		if (!strcmp(vi->prefixstr, "none"))
1044bf215546Sopenharmony_ci			vi->prefenum = 0;
1045bf215546Sopenharmony_ci		else
1046bf215546Sopenharmony_ci			vi->prefenum = rnn_findenum(db, vi->prefixstr); // XXX
1047bf215546Sopenharmony_ci	}
1048bf215546Sopenharmony_ci	int i;
1049bf215546Sopenharmony_ci	if (parent)
1050bf215546Sopenharmony_ci		for (i = 0; i < parent->varsetsnum; i++)
1051bf215546Sopenharmony_ci			ADDARRAY(vi->varsets, copyvarset(parent->varsets[i]));
1052bf215546Sopenharmony_ci	struct rnnenum *varset = vi->prefenum;
1053bf215546Sopenharmony_ci	if (!varset && !vi->varsetstr && parent)
1054bf215546Sopenharmony_ci		vi->varsetstr = parent->varsetstr;
1055bf215546Sopenharmony_ci	if (vi->varsetstr)
1056bf215546Sopenharmony_ci		varset = rnn_findenum(db, vi->varsetstr);
1057bf215546Sopenharmony_ci	if (vi->variantsstr) {
1058bf215546Sopenharmony_ci		char *vars = vi->variantsstr;
1059bf215546Sopenharmony_ci		if (!varset) {
1060bf215546Sopenharmony_ci			rnn_err(db, "%s: tried to use variants without active varset!\n", what);
1061bf215546Sopenharmony_ci			return;
1062bf215546Sopenharmony_ci		}
1063bf215546Sopenharmony_ci		struct rnnvarset *vs = 0;
1064bf215546Sopenharmony_ci		int nvars = varset->valsnum;
1065bf215546Sopenharmony_ci		for (i = 0; i < vi->varsetsnum; i++)
1066bf215546Sopenharmony_ci			if (vi->varsets[i]->venum == varset) {
1067bf215546Sopenharmony_ci				vs = vi->varsets[i];
1068bf215546Sopenharmony_ci				break;
1069bf215546Sopenharmony_ci			}
1070bf215546Sopenharmony_ci		if (!vs) {
1071bf215546Sopenharmony_ci			vs = calloc (sizeof *vs, 1);
1072bf215546Sopenharmony_ci			vs->venum = varset;
1073bf215546Sopenharmony_ci			vs->variants = calloc(sizeof *vs->variants, nvars);
1074bf215546Sopenharmony_ci			for (i = 0; i < nvars; i++)
1075bf215546Sopenharmony_ci				vs->variants[i] = 1;
1076bf215546Sopenharmony_ci			ADDARRAY(vi->varsets, vs);
1077bf215546Sopenharmony_ci		}
1078bf215546Sopenharmony_ci		while (1) {
1079bf215546Sopenharmony_ci			while (*vars == ' ') vars++;
1080bf215546Sopenharmony_ci			if (*vars == 0)
1081bf215546Sopenharmony_ci				break;
1082bf215546Sopenharmony_ci			char *split = vars;
1083bf215546Sopenharmony_ci			while (*split != ':' && *split != '-' && *split != ' '  && *split != 0)
1084bf215546Sopenharmony_ci				split++;
1085bf215546Sopenharmony_ci			char *first = 0;
1086bf215546Sopenharmony_ci			if (split != vars)
1087bf215546Sopenharmony_ci				first = strndup(vars, split-vars);
1088bf215546Sopenharmony_ci			if (*split == ' ' || *split == 0) {
1089bf215546Sopenharmony_ci				int idx = findvidx(db, varset, first);
1090bf215546Sopenharmony_ci				if (idx != -1)
1091bf215546Sopenharmony_ci					vs->variants[idx] |= 2;
1092bf215546Sopenharmony_ci				vars = split;
1093bf215546Sopenharmony_ci			} else {
1094bf215546Sopenharmony_ci				char *end = split+1;
1095bf215546Sopenharmony_ci				while (*end != ' '  && *end != 0)
1096bf215546Sopenharmony_ci					end++;
1097bf215546Sopenharmony_ci				char *second = 0;
1098bf215546Sopenharmony_ci				if (end != split+1)
1099bf215546Sopenharmony_ci					second = strndup(split+1, end-split-1);
1100bf215546Sopenharmony_ci				int idx1 = 0;
1101bf215546Sopenharmony_ci				if (first)
1102bf215546Sopenharmony_ci					idx1 = findvidx(db, varset, first);
1103bf215546Sopenharmony_ci				int idx2 = nvars;
1104bf215546Sopenharmony_ci				if (second) {
1105bf215546Sopenharmony_ci					idx2 = findvidx(db, varset, second);
1106bf215546Sopenharmony_ci					if (*split == '-')
1107bf215546Sopenharmony_ci						idx2++;
1108bf215546Sopenharmony_ci				}
1109bf215546Sopenharmony_ci				if (idx1 != -1 && idx2 != -1)
1110bf215546Sopenharmony_ci					for (i = idx1; i < idx2; i++)
1111bf215546Sopenharmony_ci						vs->variants[i] |= 2;
1112bf215546Sopenharmony_ci				vars = end;
1113bf215546Sopenharmony_ci				free(second);
1114bf215546Sopenharmony_ci			}
1115bf215546Sopenharmony_ci			free(first);
1116bf215546Sopenharmony_ci		}
1117bf215546Sopenharmony_ci		vi->dead = 1;
1118bf215546Sopenharmony_ci		for (i = 0; i < nvars; i++) {
1119bf215546Sopenharmony_ci			vs->variants[i] = (vs->variants[i] == 3);
1120bf215546Sopenharmony_ci			if (vs->variants[i])
1121bf215546Sopenharmony_ci				vi->dead = 0;
1122bf215546Sopenharmony_ci		}
1123bf215546Sopenharmony_ci	}
1124bf215546Sopenharmony_ci	if (vi->dead)
1125bf215546Sopenharmony_ci		return;
1126bf215546Sopenharmony_ci	if (vi->prefenum) {
1127bf215546Sopenharmony_ci		struct rnnvarset *vs = 0;
1128bf215546Sopenharmony_ci		for (i = 0; i < vi->varsetsnum; i++)
1129bf215546Sopenharmony_ci			if (vi->varsets[i]->venum == vi->prefenum) {
1130bf215546Sopenharmony_ci				vs = vi->varsets[i];
1131bf215546Sopenharmony_ci				break;
1132bf215546Sopenharmony_ci			}
1133bf215546Sopenharmony_ci		if (vs) {
1134bf215546Sopenharmony_ci			for (i = 0; i < vi->prefenum->valsnum; i++)
1135bf215546Sopenharmony_ci				if (vs->variants[i]) {
1136bf215546Sopenharmony_ci					vi->prefix = vi->prefenum->vals[i]->name;
1137bf215546Sopenharmony_ci					return;
1138bf215546Sopenharmony_ci				}
1139bf215546Sopenharmony_ci		} else {
1140bf215546Sopenharmony_ci			vi->prefix = vi->prefenum->vals[0]->name;
1141bf215546Sopenharmony_ci		}
1142bf215546Sopenharmony_ci	}
1143bf215546Sopenharmony_ci}
1144bf215546Sopenharmony_ci
1145bf215546Sopenharmony_cistatic void prepvalue(struct rnndb *db, struct rnnvalue *val, char *prefix, struct rnnvarinfo *parvi) {
1146bf215546Sopenharmony_ci	val->fullname = catstr(prefix, val->name);
1147bf215546Sopenharmony_ci	prepvarinfo (db, val->fullname, &val->varinfo, parvi);
1148bf215546Sopenharmony_ci	if (val->varinfo.dead)
1149bf215546Sopenharmony_ci		return;
1150bf215546Sopenharmony_ci	if (val->varinfo.prefix)
1151bf215546Sopenharmony_ci		val->fullname = catstr(val->varinfo.prefix, val->fullname);
1152bf215546Sopenharmony_ci}
1153bf215546Sopenharmony_ci
1154bf215546Sopenharmony_cistatic void prepbitfield(struct rnndb *db, struct rnnbitfield *bf, char *prefix, struct rnnvarinfo *parvi);
1155bf215546Sopenharmony_ci
1156bf215546Sopenharmony_cistatic void preptypeinfo(struct rnndb *db, struct rnntypeinfo *ti, char *prefix, struct rnnvarinfo *vi, char *file) {
1157bf215546Sopenharmony_ci	int i;
1158bf215546Sopenharmony_ci	if (ti->name) {
1159bf215546Sopenharmony_ci		struct rnnenum *en = rnn_findenum (db, ti->name);
1160bf215546Sopenharmony_ci		struct rnnbitset *bs = rnn_findbitset (db, ti->name);
1161bf215546Sopenharmony_ci		struct rnnspectype *st = rnn_findspectype (db, ti->name);
1162bf215546Sopenharmony_ci		if (en) {
1163bf215546Sopenharmony_ci			if (en->isinline) {
1164bf215546Sopenharmony_ci				ti->type = RNN_TTYPE_INLINE_ENUM;
1165bf215546Sopenharmony_ci				int j;
1166bf215546Sopenharmony_ci				for (j = 0; j < en->valsnum; j++)
1167bf215546Sopenharmony_ci					ADDARRAY(ti->vals, copyvalue(en->vals[j], file));
1168bf215546Sopenharmony_ci			} else {
1169bf215546Sopenharmony_ci				ti->type = RNN_TTYPE_ENUM;
1170bf215546Sopenharmony_ci				ti->eenum = en;
1171bf215546Sopenharmony_ci			}
1172bf215546Sopenharmony_ci		} else if (bs) {
1173bf215546Sopenharmony_ci			if (bs->isinline) {
1174bf215546Sopenharmony_ci				ti->type = RNN_TTYPE_INLINE_BITSET;
1175bf215546Sopenharmony_ci				int j;
1176bf215546Sopenharmony_ci				for (j = 0; j < bs->bitfieldsnum; j++)
1177bf215546Sopenharmony_ci					ADDARRAY(ti->bitfields, copybitfield(bs->bitfields[j], file));
1178bf215546Sopenharmony_ci			} else {
1179bf215546Sopenharmony_ci				ti->type = RNN_TTYPE_BITSET;
1180bf215546Sopenharmony_ci				ti->ebitset = bs;
1181bf215546Sopenharmony_ci			}
1182bf215546Sopenharmony_ci		} else if (st) {
1183bf215546Sopenharmony_ci			ti->type = RNN_TTYPE_SPECTYPE;
1184bf215546Sopenharmony_ci			ti->spectype = st;
1185bf215546Sopenharmony_ci		} else if (!strcmp(ti->name, "hex")) {
1186bf215546Sopenharmony_ci			ti->type = RNN_TTYPE_HEX;
1187bf215546Sopenharmony_ci		} else if (!strcmp(ti->name, "float")) {
1188bf215546Sopenharmony_ci			ti->type = RNN_TTYPE_FLOAT;
1189bf215546Sopenharmony_ci		} else if (!strcmp(ti->name, "uint")) {
1190bf215546Sopenharmony_ci			ti->type = RNN_TTYPE_UINT;
1191bf215546Sopenharmony_ci		} else if (!strcmp(ti->name, "int")) {
1192bf215546Sopenharmony_ci			ti->type = RNN_TTYPE_INT;
1193bf215546Sopenharmony_ci		} else if (!strcmp(ti->name, "boolean")) {
1194bf215546Sopenharmony_ci			ti->type = RNN_TTYPE_BOOLEAN;
1195bf215546Sopenharmony_ci		} else if (!strcmp(ti->name, "bitfield")) {
1196bf215546Sopenharmony_ci			ti->type = RNN_TTYPE_INLINE_BITSET;
1197bf215546Sopenharmony_ci		} else if (!strcmp(ti->name, "enum")) {
1198bf215546Sopenharmony_ci			ti->type = RNN_TTYPE_INLINE_ENUM;
1199bf215546Sopenharmony_ci		} else if (!strcmp(ti->name, "fixed")) {
1200bf215546Sopenharmony_ci			ti->type = RNN_TTYPE_FIXED;
1201bf215546Sopenharmony_ci		} else if (!strcmp(ti->name, "ufixed")) {
1202bf215546Sopenharmony_ci			ti->type = RNN_TTYPE_UFIXED;
1203bf215546Sopenharmony_ci		} else if (!strcmp(ti->name, "a3xx_regid")) {
1204bf215546Sopenharmony_ci			ti->type = RNN_TTYPE_A3XX_REGID;
1205bf215546Sopenharmony_ci		} else if (!strcmp(ti->name, "waddress") || !strcmp(ti->name, "address")) {
1206bf215546Sopenharmony_ci			ti->type = RNN_TTYPE_HEX;
1207bf215546Sopenharmony_ci		} else {
1208bf215546Sopenharmony_ci			ti->type = RNN_TTYPE_HEX;
1209bf215546Sopenharmony_ci			rnn_err(db, "%s: unknown type %s\n", prefix, ti->name);
1210bf215546Sopenharmony_ci		}
1211bf215546Sopenharmony_ci	} else if (ti->bitfieldsnum) {
1212bf215546Sopenharmony_ci		ti->name = "bitfield";
1213bf215546Sopenharmony_ci		ti->type = RNN_TTYPE_INLINE_BITSET;
1214bf215546Sopenharmony_ci	} else if (ti->valsnum) {
1215bf215546Sopenharmony_ci		ti->name = "enum";
1216bf215546Sopenharmony_ci		ti->type = RNN_TTYPE_INLINE_ENUM;
1217bf215546Sopenharmony_ci	} else if (ti->low == 0 && ti->high == 0) {
1218bf215546Sopenharmony_ci		ti->name = "boolean";
1219bf215546Sopenharmony_ci		ti->type = RNN_TTYPE_BOOLEAN;
1220bf215546Sopenharmony_ci	} else {
1221bf215546Sopenharmony_ci		ti->name = "hex";
1222bf215546Sopenharmony_ci		ti->type = RNN_TTYPE_HEX;
1223bf215546Sopenharmony_ci	}
1224bf215546Sopenharmony_ci	if (ti->addvariant && ti->type != RNN_TTYPE_ENUM) {
1225bf215546Sopenharmony_ci		rnn_err(db, "%s: addvariant specified on non-enum type %s\n", prefix, ti->name);
1226bf215546Sopenharmony_ci	}
1227bf215546Sopenharmony_ci	for (i = 0; i < ti->bitfieldsnum; i++)
1228bf215546Sopenharmony_ci		prepbitfield(db,  ti->bitfields[i], prefix, vi);
1229bf215546Sopenharmony_ci	for (i = 0; i < ti->valsnum; i++)
1230bf215546Sopenharmony_ci		prepvalue(db, ti->vals[i], prefix, vi);
1231bf215546Sopenharmony_ci}
1232bf215546Sopenharmony_ci
1233bf215546Sopenharmony_cistatic void prepbitfield(struct rnndb *db, struct rnnbitfield *bf, char *prefix, struct rnnvarinfo *parvi) {
1234bf215546Sopenharmony_ci	bf->fullname = catstr(prefix, bf->name);
1235bf215546Sopenharmony_ci	prepvarinfo (db, bf->fullname, &bf->varinfo, parvi);
1236bf215546Sopenharmony_ci	if (bf->varinfo.dead)
1237bf215546Sopenharmony_ci		return;
1238bf215546Sopenharmony_ci	preptypeinfo(db, &bf->typeinfo, bf->fullname, &bf->varinfo, bf->file);
1239bf215546Sopenharmony_ci	if (bf->varinfo.prefix)
1240bf215546Sopenharmony_ci		bf->fullname = catstr(bf->varinfo.prefix, bf->fullname);
1241bf215546Sopenharmony_ci}
1242bf215546Sopenharmony_ci
1243bf215546Sopenharmony_cistatic void prepdelem(struct rnndb *db, struct rnndelem *elem, char *prefix, struct rnnvarinfo *parvi, int width) {
1244bf215546Sopenharmony_ci	if (elem->type == RNN_ETYPE_USE_GROUP) {
1245bf215546Sopenharmony_ci		int i;
1246bf215546Sopenharmony_ci		struct rnngroup *gr = 0;
1247bf215546Sopenharmony_ci		for (i = 0; i < db->groupsnum; i++)
1248bf215546Sopenharmony_ci			if (!strcmp(db->groups[i]->name, elem->name)) {
1249bf215546Sopenharmony_ci				gr = db->groups[i];
1250bf215546Sopenharmony_ci				break;
1251bf215546Sopenharmony_ci			}
1252bf215546Sopenharmony_ci		if (gr) {
1253bf215546Sopenharmony_ci			for (i = 0; i < gr->subelemsnum; i++)
1254bf215546Sopenharmony_ci				ADDARRAY(elem->subelems, copydelem(gr->subelems[i], elem->file));
1255bf215546Sopenharmony_ci		} else {
1256bf215546Sopenharmony_ci			rnn_err(db, "group %s not found!\n", elem->name);
1257bf215546Sopenharmony_ci		}
1258bf215546Sopenharmony_ci		elem->type = RNN_ETYPE_STRIPE;
1259bf215546Sopenharmony_ci		elem->length = 1;
1260bf215546Sopenharmony_ci		elem->name = 0;
1261bf215546Sopenharmony_ci	}
1262bf215546Sopenharmony_ci	if (elem->name)
1263bf215546Sopenharmony_ci		elem->fullname = catstr(prefix, elem->name);
1264bf215546Sopenharmony_ci	prepvarinfo (db, elem->fullname?elem->fullname:prefix, &elem->varinfo, parvi);
1265bf215546Sopenharmony_ci	if (elem->varinfo.dead)
1266bf215546Sopenharmony_ci		return;
1267bf215546Sopenharmony_ci	if (elem->length != 1 && !elem->stride) {
1268bf215546Sopenharmony_ci		if (elem->type != RNN_ETYPE_REG) {
1269bf215546Sopenharmony_ci			rnn_err(db, "%s has non-1 length, but no stride!\n", elem->fullname);
1270bf215546Sopenharmony_ci		} else {
1271bf215546Sopenharmony_ci			elem->stride = elem->width/width;
1272bf215546Sopenharmony_ci		}
1273bf215546Sopenharmony_ci	}
1274bf215546Sopenharmony_ci	preptypeinfo(db, &elem->typeinfo, elem->name?elem->fullname:prefix, &elem->varinfo, elem->file);
1275bf215546Sopenharmony_ci
1276bf215546Sopenharmony_ci	int i;
1277bf215546Sopenharmony_ci	for (i = 0; i < elem->subelemsnum; i++)
1278bf215546Sopenharmony_ci		prepdelem(db,  elem->subelems[i], elem->name?elem->fullname:prefix, &elem->varinfo, width);
1279bf215546Sopenharmony_ci	if (elem->varinfo.prefix && elem->name)
1280bf215546Sopenharmony_ci		elem->fullname = catstr(elem->varinfo.prefix, elem->fullname);
1281bf215546Sopenharmony_ci}
1282bf215546Sopenharmony_ci
1283bf215546Sopenharmony_cistatic void prepdomain(struct rnndb *db, struct rnndomain *dom) {
1284bf215546Sopenharmony_ci	prepvarinfo (db, dom->name, &dom->varinfo, 0);
1285bf215546Sopenharmony_ci	int i;
1286bf215546Sopenharmony_ci	for (i = 0; i < dom->subelemsnum; i++)
1287bf215546Sopenharmony_ci		prepdelem(db, dom->subelems[i], dom->bare?0:dom->name, &dom->varinfo, dom->width);
1288bf215546Sopenharmony_ci	dom->fullname = catstr(dom->varinfo.prefix, dom->name);
1289bf215546Sopenharmony_ci}
1290bf215546Sopenharmony_ci
1291bf215546Sopenharmony_cistatic void prepenum(struct rnndb *db, struct rnnenum *en) {
1292bf215546Sopenharmony_ci	if (en->prepared)
1293bf215546Sopenharmony_ci		return;
1294bf215546Sopenharmony_ci	prepvarinfo (db, en->name, &en->varinfo, 0);
1295bf215546Sopenharmony_ci	int i;
1296bf215546Sopenharmony_ci	if (en->isinline)
1297bf215546Sopenharmony_ci		return;
1298bf215546Sopenharmony_ci	for (i = 0; i < en->valsnum; i++)
1299bf215546Sopenharmony_ci		prepvalue(db, en->vals[i], en->bare?0:en->name, &en->varinfo);
1300bf215546Sopenharmony_ci	en->fullname = catstr(en->varinfo.prefix, en->name);
1301bf215546Sopenharmony_ci	en->prepared = 1;
1302bf215546Sopenharmony_ci}
1303bf215546Sopenharmony_ci
1304bf215546Sopenharmony_cistatic void prepbitset(struct rnndb *db, struct rnnbitset *bs) {
1305bf215546Sopenharmony_ci	prepvarinfo (db, bs->name, &bs->varinfo, 0);
1306bf215546Sopenharmony_ci	int i;
1307bf215546Sopenharmony_ci	if (bs->isinline)
1308bf215546Sopenharmony_ci		return;
1309bf215546Sopenharmony_ci	for (i = 0; i < bs->bitfieldsnum; i++)
1310bf215546Sopenharmony_ci		prepbitfield(db, bs->bitfields[i], bs->bare?0:bs->name, &bs->varinfo);
1311bf215546Sopenharmony_ci	bs->fullname = catstr(bs->varinfo.prefix, bs->name);
1312bf215546Sopenharmony_ci}
1313bf215546Sopenharmony_ci
1314bf215546Sopenharmony_cistatic void prepspectype(struct rnndb *db, struct rnnspectype *st) {
1315bf215546Sopenharmony_ci	preptypeinfo(db, &st->typeinfo, st->name, 0, st->file); // XXX doesn't exactly make sense...
1316bf215546Sopenharmony_ci}
1317bf215546Sopenharmony_ci
1318bf215546Sopenharmony_civoid rnn_prepdb (struct rnndb *db) {
1319bf215546Sopenharmony_ci	int i;
1320bf215546Sopenharmony_ci	for (i = 0; i < db->enumsnum; i++)
1321bf215546Sopenharmony_ci		prepenum(db, db->enums[i]);
1322bf215546Sopenharmony_ci	for (i = 0; i < db->bitsetsnum; i++)
1323bf215546Sopenharmony_ci		prepbitset(db, db->bitsets[i]);
1324bf215546Sopenharmony_ci	for (i = 0; i < db->domainsnum; i++)
1325bf215546Sopenharmony_ci		prepdomain(db, db->domains[i]);
1326bf215546Sopenharmony_ci	for (i = 0; i < db->spectypesnum; i++)
1327bf215546Sopenharmony_ci		prepspectype(db, db->spectypes[i]);
1328bf215546Sopenharmony_ci}
1329bf215546Sopenharmony_ci
1330bf215546Sopenharmony_cistruct rnnenum *rnn_findenum (struct rnndb *db, const char *name) {
1331bf215546Sopenharmony_ci	int i;
1332bf215546Sopenharmony_ci	for (i = 0; i < db->enumsnum; i++)
1333bf215546Sopenharmony_ci		if (!strcmp(db->enums[i]->name, name))
1334bf215546Sopenharmony_ci			return db->enums[i];
1335bf215546Sopenharmony_ci	return 0;
1336bf215546Sopenharmony_ci}
1337bf215546Sopenharmony_ci
1338bf215546Sopenharmony_cistruct rnnbitset *rnn_findbitset (struct rnndb *db, const char *name) {
1339bf215546Sopenharmony_ci	int i;
1340bf215546Sopenharmony_ci	for (i = 0; i < db->bitsetsnum; i++)
1341bf215546Sopenharmony_ci		if (!strcmp(db->bitsets[i]->name, name))
1342bf215546Sopenharmony_ci			return db->bitsets[i];
1343bf215546Sopenharmony_ci	return 0;
1344bf215546Sopenharmony_ci}
1345bf215546Sopenharmony_ci
1346bf215546Sopenharmony_cistruct rnndomain *rnn_finddomain (struct rnndb *db, const char *name) {
1347bf215546Sopenharmony_ci	int i;
1348bf215546Sopenharmony_ci	for (i = 0; i < db->domainsnum; i++)
1349bf215546Sopenharmony_ci		if (!strcmp(db->domains[i]->name, name))
1350bf215546Sopenharmony_ci			return db->domains[i];
1351bf215546Sopenharmony_ci	return 0;
1352bf215546Sopenharmony_ci}
1353bf215546Sopenharmony_ci
1354bf215546Sopenharmony_cistruct rnnspectype *rnn_findspectype (struct rnndb *db, const char *name) {
1355bf215546Sopenharmony_ci	int i;
1356bf215546Sopenharmony_ci	for (i = 0; i < db->spectypesnum; i++)
1357bf215546Sopenharmony_ci		if (!strcmp(db->spectypes[i]->name, name))
1358bf215546Sopenharmony_ci			return db->spectypes[i];
1359bf215546Sopenharmony_ci	return 0;
1360bf215546Sopenharmony_ci}
1361