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