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