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