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