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