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