A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 990 lines 28 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2012 by Amaury Pouly 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21#include "soc_desc_v1.hpp" 22#include <libxml/parser.h> 23#include <libxml/tree.h> 24#include <libxml/xmlsave.h> 25#include <libxml/xmlwriter.h> 26#include <stdio.h> 27#include <string.h> 28#include <algorithm> 29#include <cctype> 30 31namespace soc_desc_v1 32{ 33 34#define XML_CHAR_TO_CHAR(s) ((const char *)(s)) 35 36#define BEGIN_ATTR_MATCH(attr) \ 37 for(xmlAttr *a = attr; a; a = a->next) { 38 39#define MATCH_X_ATTR(attr_name, hook, ...) \ 40 if(strcmp(XML_CHAR_TO_CHAR(a->name), attr_name) == 0) { \ 41 std::string s; \ 42 if(!parse_text_attr(a, s) || !hook(s, __VA_ARGS__)) \ 43 return false; \ 44 } 45 46#define SOFT_MATCH_X_ATTR(attr_name, hook, ...) \ 47 if(strcmp(XML_CHAR_TO_CHAR(a->name), attr_name) == 0) { \ 48 std::string s; \ 49 if(parse_text_attr(a, s)) \ 50 hook(s, __VA_ARGS__); \ 51 } 52 53#define SOFT_MATCH_SCT_ATTR(attr_name, var) \ 54 SOFT_MATCH_X_ATTR(attr_name, validate_sct_hook, var) 55 56#define MATCH_TEXT_ATTR(attr_name, var) \ 57 MATCH_X_ATTR(attr_name, validate_string_hook, var) 58 59#define MATCH_UINT32_ATTR(attr_name, var) \ 60 MATCH_X_ATTR(attr_name, validate_uint32_hook, var) 61 62#define MATCH_BITRANGE_ATTR(attr_name, first, last) \ 63 MATCH_X_ATTR(attr_name, validate_bitrange_hook, first, last) 64 65#define END_ATTR_MATCH() \ 66 } 67 68#define BEGIN_NODE_MATCH(node) \ 69 for(xmlNode *sub = node; sub; sub = sub->next) { 70 71#define MATCH_ELEM_NODE(node_name, array, parse_fn) \ 72 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \ 73 array.resize(array.size() + 1); \ 74 if(!parse_fn(sub, array.back())) \ 75 return false; \ 76 } 77 78#define SOFT_MATCH_ELEM_NODE(node_name, array, parse_fn) \ 79 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \ 80 array.resize(array.size() + 1); \ 81 if(!parse_fn(sub, array.back())) \ 82 array.pop_back(); \ 83 } 84 85#define END_NODE_MATCH() \ 86 } 87 88namespace 89{ 90 91bool validate_string_hook(const std::string& str, std::string& s) 92{ 93 s = str; 94 return true; 95} 96 97bool validate_sct_hook(const std::string& str, soc_reg_flags_t& flags) 98{ 99 if(str == "yes") flags |= REG_HAS_SCT; 100 else if(str != "no") return false; 101 return true; 102} 103 104bool validate_unsigned_long_hook(const std::string& str, unsigned long& s) 105{ 106 char *end; 107 s = strtoul(str.c_str(), &end, 0); 108 return *end == 0; 109} 110 111bool validate_uint32_hook(const std::string& str, uint32_t& s) 112{ 113 unsigned long u; 114 if(!validate_unsigned_long_hook(str, u)) return false; 115#if ULONG_MAX > 0xffffffff 116 if(u > 0xffffffff) return false; 117#endif 118 s = u; 119 return true; 120} 121 122bool validate_bitrange_hook(const std::string& str, unsigned& first, unsigned& last) 123{ 124 unsigned long a, b; 125 size_t sep = str.find(':'); 126 if(sep == std::string::npos) return false; 127 if(!validate_unsigned_long_hook(str.substr(0, sep), a)) return false; 128 if(!validate_unsigned_long_hook(str.substr(sep + 1), b)) return false; 129 if(a > 31 || b > 31 || a < b) return false; 130 first = b; 131 last = a; 132 return true; 133} 134 135bool parse_text_attr(xmlAttr *attr, std::string& s) 136{ 137 if(attr->children != attr->last) 138 return false; 139 if(attr->children->type != XML_TEXT_NODE) 140 return false; 141 s = XML_CHAR_TO_CHAR(attr->children->content); 142 return true; 143} 144 145bool parse_value_elem(xmlNode *node, soc_reg_field_value_t& value) 146{ 147 BEGIN_ATTR_MATCH(node->properties) 148 MATCH_TEXT_ATTR("name", value.name) 149 MATCH_UINT32_ATTR("value", value.value) 150 MATCH_TEXT_ATTR("desc", value.desc) 151 END_ATTR_MATCH() 152 153 return true; 154} 155 156bool parse_field_elem(xmlNode *node, soc_reg_field_t& field) 157{ 158 BEGIN_ATTR_MATCH(node->properties) 159 MATCH_TEXT_ATTR("name", field.name) 160 MATCH_BITRANGE_ATTR("bitrange", field.first_bit, field.last_bit) 161 MATCH_TEXT_ATTR("desc", field.desc) 162 END_ATTR_MATCH() 163 164 BEGIN_NODE_MATCH(node->children) 165 SOFT_MATCH_ELEM_NODE("value", field.value, parse_value_elem) 166 END_NODE_MATCH() 167 168 return true; 169} 170 171bool parse_reg_addr_elem(xmlNode *node, soc_reg_addr_t& addr) 172{ 173 BEGIN_ATTR_MATCH(node->properties) 174 MATCH_TEXT_ATTR("name", addr.name) 175 MATCH_UINT32_ATTR("addr", addr.addr) 176 END_ATTR_MATCH() 177 178 return true; 179} 180 181bool parse_reg_formula_elem(xmlNode *node, soc_reg_formula_t& formula) 182{ 183 BEGIN_ATTR_MATCH(node->properties) 184 MATCH_TEXT_ATTR("string", formula.string) 185 END_ATTR_MATCH() 186 187 formula.type = REG_FORMULA_STRING; 188 189 return true; 190} 191 192bool parse_add_trivial_addr(const std::string& str, soc_reg_t& reg) 193{ 194 soc_reg_addr_t a; 195 a.name = reg.name; 196 if(!validate_uint32_hook(str, a.addr)) 197 return false; 198 reg.addr.push_back(a); 199 return true; 200} 201 202bool parse_reg_elem(xmlNode *node, soc_reg_t& reg) 203{ 204 std::list< soc_reg_formula_t > formulas; 205 BEGIN_ATTR_MATCH(node->properties) 206 MATCH_TEXT_ATTR("name", reg.name) 207 SOFT_MATCH_SCT_ATTR("sct", reg.flags) 208 SOFT_MATCH_X_ATTR("addr", parse_add_trivial_addr, reg) 209 MATCH_TEXT_ATTR("desc", reg.desc) 210 END_ATTR_MATCH() 211 212 BEGIN_NODE_MATCH(node->children) 213 MATCH_ELEM_NODE("addr", reg.addr, parse_reg_addr_elem) 214 MATCH_ELEM_NODE("formula", formulas, parse_reg_formula_elem) 215 MATCH_ELEM_NODE("field", reg.field, parse_field_elem) 216 END_NODE_MATCH() 217 218 if(formulas.size() > 1) 219 { 220 fprintf(stderr, "Only one formula is allowed per register\n"); 221 return false; 222 } 223 if(formulas.size() == 1) 224 reg.formula = formulas.front(); 225 226 return true; 227} 228 229bool parse_dev_addr_elem(xmlNode *node, soc_dev_addr_t& addr) 230{ 231 BEGIN_ATTR_MATCH(node->properties) 232 MATCH_TEXT_ATTR("name", addr.name) 233 MATCH_UINT32_ATTR("addr", addr.addr) 234 END_ATTR_MATCH() 235 236 return true; 237} 238 239bool parse_dev_elem(xmlNode *node, soc_dev_t& dev) 240{ 241 BEGIN_ATTR_MATCH(node->properties) 242 MATCH_TEXT_ATTR("name", dev.name) 243 MATCH_TEXT_ATTR("long_name", dev.long_name) 244 MATCH_TEXT_ATTR("desc", dev.desc) 245 MATCH_TEXT_ATTR("version", dev.version) 246 END_ATTR_MATCH() 247 248 BEGIN_NODE_MATCH(node->children) 249 MATCH_ELEM_NODE("addr", dev.addr, parse_dev_addr_elem) 250 MATCH_ELEM_NODE("reg", dev.reg, parse_reg_elem) 251 END_NODE_MATCH() 252 253 return true; 254} 255 256bool parse_soc_elem(xmlNode *node, soc_t& soc) 257{ 258 BEGIN_ATTR_MATCH(node->properties) 259 MATCH_TEXT_ATTR("name", soc.name) 260 MATCH_TEXT_ATTR("desc", soc.desc) 261 END_ATTR_MATCH() 262 263 BEGIN_NODE_MATCH(node->children) 264 MATCH_ELEM_NODE("dev", soc.dev, parse_dev_elem) 265 END_NODE_MATCH() 266 267 return true; 268} 269 270bool parse_root_elem(xmlNode *node, soc_t& soc) 271{ 272 std::vector< soc_t > socs; 273 BEGIN_NODE_MATCH(node) 274 MATCH_ELEM_NODE("soc", socs, parse_soc_elem) 275 END_NODE_MATCH() 276 if(socs.size() != 1) 277 { 278 fprintf(stderr, "A description file must contain exactly one soc element\n"); 279 return false; 280 } 281 soc = socs[0]; 282 return true; 283} 284 285} 286 287bool parse_xml(const std::string& filename, soc_t& socs) 288{ 289 LIBXML_TEST_VERSION 290 291 xmlDocPtr doc = xmlReadFile(filename.c_str(), NULL, 0); 292 if(doc == NULL) 293 return false; 294 295 xmlNodePtr root_element = xmlDocGetRootElement(doc); 296 bool ret = parse_root_elem(root_element, socs); 297 298 xmlFreeDoc(doc); 299 300 return ret; 301} 302 303namespace 304{ 305 306int produce_field(xmlTextWriterPtr writer, const soc_reg_field_t& field) 307{ 308#define SAFE(x) if((x) < 0) return -1; 309 /* <field> */ 310 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "field")); 311 /* name */ 312 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST field.name.c_str())); 313 /* desc */ 314 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST field.desc.c_str())); 315 /* bitrange */ 316 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "bitrange", "%d:%d", 317 field.last_bit, field.first_bit)); 318 /* values */ 319 for(size_t i = 0; i < field.value.size(); i++) 320 { 321 /* <value> */ 322 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "value")); 323 /* name */ 324 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST field.value[i].name.c_str())); 325 /* value */ 326 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "value", "0x%x", field.value[i].value)); 327 /* name */ 328 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST field.value[i].desc.c_str())); 329 /* </value> */ 330 SAFE(xmlTextWriterEndElement(writer)); 331 } 332 /* </field> */ 333 SAFE(xmlTextWriterEndElement(writer)); 334#undef SAFE 335 return 0; 336} 337 338int produce_reg(xmlTextWriterPtr writer, const soc_reg_t& reg) 339{ 340#define SAFE(x) if((x) < 0) return -1; 341 /* <reg> */ 342 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "reg")); 343 /* name */ 344 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST reg.name.c_str())); 345 /* name */ 346 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST reg.desc.c_str())); 347 /* flags */ 348 if(reg.flags & REG_HAS_SCT) 349 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "sct", BAD_CAST "yes")); 350 /* formula */ 351 if(reg.formula.type != REG_FORMULA_NONE) 352 { 353 /* <formula> */ 354 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "formula")); 355 switch(reg.formula.type) 356 { 357 case REG_FORMULA_STRING: 358 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "string", 359 BAD_CAST reg.formula.string.c_str())); 360 break; 361 default: 362 break; 363 } 364 /* </formula> */ 365 SAFE(xmlTextWriterEndElement(writer)); 366 } 367 /* addresses */ 368 for(size_t i = 0; i < reg.addr.size(); i++) 369 { 370 /* <addr> */ 371 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "addr")); 372 /* name */ 373 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST reg.addr[i].name.c_str())); 374 /* addr */ 375 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "addr", "0x%x", reg.addr[i].addr)); 376 /* </addr> */ 377 SAFE(xmlTextWriterEndElement(writer)); 378 } 379 /* fields */ 380 for(size_t i = 0; i < reg.field.size(); i++) 381 produce_field(writer, reg.field[i]); 382 /* </reg> */ 383 SAFE(xmlTextWriterEndElement(writer)); 384#undef SAFE 385 return 0; 386} 387 388int produce_dev(xmlTextWriterPtr writer, const soc_dev_t& dev) 389{ 390#define SAFE(x) if((x) < 0) return -1; 391 /* <dev> */ 392 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "dev")); 393 /* name */ 394 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST dev.name.c_str())); 395 /* long_name */ 396 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "long_name", BAD_CAST dev.long_name.c_str())); 397 /* desc */ 398 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST dev.desc.c_str())); 399 /* version */ 400 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "version", BAD_CAST dev.version.c_str())); 401 /* addresses */ 402 for(size_t i = 0; i < dev.addr.size(); i++) 403 { 404 /* <addr> */ 405 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "addr")); 406 /* name */ 407 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST dev.addr[i].name.c_str())); 408 /* addr */ 409 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "addr", "0x%x", dev.addr[i].addr)); 410 /* </addr> */ 411 SAFE(xmlTextWriterEndElement(writer)); 412 } 413 /* registers */ 414 for(size_t i = 0; i < dev.reg.size(); i++) 415 produce_reg(writer, dev.reg[i]); 416 /* </dev> */ 417 SAFE(xmlTextWriterEndElement(writer)); 418#undef SAFE 419 return 0; 420} 421 422} 423 424bool produce_xml(const std::string& filename, const soc_t& soc) 425{ 426 LIBXML_TEST_VERSION 427 428 xmlTextWriterPtr writer = xmlNewTextWriterFilename(filename.c_str(), 0); 429 if(writer == NULL) 430 return false; 431#define SAFE(x) if((x) < 0) goto Lerr 432 SAFE(xmlTextWriterSetIndent(writer, 1)); 433 SAFE(xmlTextWriterSetIndentString(writer, BAD_CAST " ")); 434 /* <xml> */ 435 SAFE(xmlTextWriterStartDocument(writer, NULL, NULL, NULL)); 436 /* <soc> */ 437 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "soc")); 438 /* name */ 439 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST soc.name.c_str())); 440 /* desc */ 441 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST soc.desc.c_str())); 442 /* devices */ 443 for(size_t i = 0; i < soc.dev.size(); i++) 444 SAFE(produce_dev(writer, soc.dev[i])); 445 /* end <soc> */ 446 SAFE(xmlTextWriterEndElement(writer)); 447 /* </xml> */ 448 SAFE(xmlTextWriterEndDocument(writer)); 449 xmlFreeTextWriter(writer); 450 return true; 451#undef SAFE 452Lerr: 453 xmlFreeTextWriter(writer); 454 return false; 455} 456 457namespace 458{ 459 460struct soc_sorter 461{ 462 bool operator()(const soc_dev_t& a, const soc_dev_t& b) const 463 { 464 return a.name < b.name; 465 } 466 467 bool operator()(const soc_dev_addr_t& a, const soc_dev_addr_t& b) const 468 { 469 return a.name < b.name; 470 } 471 472 bool operator()(const soc_reg_t& a, const soc_reg_t& b) const 473 { 474 soc_addr_t aa = a.addr.size() > 0 ? a.addr[0].addr : 0; 475 soc_addr_t ab = b.addr.size() > 0 ? b.addr[0].addr : 0; 476 return aa < ab; 477 } 478 479 bool operator()(const soc_reg_addr_t& a, const soc_reg_addr_t& b) const 480 { 481 return a.addr < b.addr; 482 } 483 484 bool operator()(const soc_reg_field_t& a, const soc_reg_field_t& b) const 485 { 486 return a.last_bit > b.last_bit; 487 } 488 489 bool operator()(const soc_reg_field_value_t a, const soc_reg_field_value_t& b) const 490 { 491 return a.value < b.value; 492 } 493}; 494 495void normalize(soc_reg_field_t& field) 496{ 497 std::sort(field.value.begin(), field.value.end(), soc_sorter()); 498} 499 500void normalize(soc_reg_t& reg) 501{ 502 std::sort(reg.addr.begin(), reg.addr.end(), soc_sorter()); 503 std::sort(reg.field.begin(), reg.field.end(), soc_sorter()); 504 for(size_t i = 0; i < reg.field.size(); i++) 505 normalize(reg.field[i]); 506} 507 508void normalize(soc_dev_t& dev) 509{ 510 std::sort(dev.addr.begin(), dev.addr.end(), soc_sorter()); 511 std::sort(dev.reg.begin(), dev.reg.end(), soc_sorter()); 512 for(size_t i = 0; i < dev.reg.size(); i++) 513 normalize(dev.reg[i]); 514} 515 516} 517 518void normalize(soc_t& soc) 519{ 520 std::sort(soc.dev.begin(), soc.dev.end(), soc_sorter()); 521 for(size_t i = 0; i < soc.dev.size(); i++) 522 normalize(soc.dev[i]); 523} 524 525namespace 526{ 527 soc_error_t make_error(soc_error_level_t lvl, std::string at, std::string what) 528 { 529 soc_error_t err; 530 err.level = lvl; 531 err.location = at; 532 err.message = what; 533 return err; 534 } 535 536 soc_error_t make_warning(std::string at, std::string what) 537 { 538 return make_error(SOC_ERROR_WARNING, at, what); 539 } 540 541 soc_error_t make_fatal(std::string at, std::string what) 542 { 543 return make_error(SOC_ERROR_FATAL, at, what); 544 } 545 546 soc_error_t prefix(soc_error_t err, const std::string& prefix_at) 547 { 548 err.location = prefix_at + "." + err.location; 549 return err; 550 } 551 552 void add_errors(std::vector< soc_error_t >& errors, 553 const std::vector< soc_error_t >& new_errors, const std::string& prefix_at) 554 { 555 for(size_t i = 0; i < new_errors.size(); i++) 556 errors.push_back(prefix(new_errors[i], prefix_at)); 557 } 558 559 std::vector< soc_error_t > no_error() 560 { 561 std::vector< soc_error_t > s; 562 return s; 563 } 564 565 std::vector< soc_error_t > one_error(const soc_error_t& err) 566 { 567 std::vector< soc_error_t > s; 568 s.push_back(err); 569 return s; 570 } 571 572 bool name_valid(char c) 573 { 574 return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || 575 (c >= 'A' && c <= 'Z') || c == '_'; 576 } 577 578 bool name_valid(const std::string& s) 579 { 580 for(size_t i = 0; i < s.size(); i++) 581 if(!name_valid(s[i])) 582 return false; 583 return true; 584 } 585} 586 587std::vector< soc_error_t > soc_reg_field_value_t::errors(bool recursive) 588{ 589 (void) recursive; 590 if(name.size() == 0) 591 return one_error(make_fatal(name, "empty name")); 592 else if(!name_valid(name)) 593 return one_error(make_fatal(name, "invalid name")); 594 else 595 return no_error(); 596} 597 598std::vector< soc_error_t > soc_reg_field_t::errors(bool recursive) 599{ 600 std::vector< soc_error_t > err; 601 std::string at(name); 602 if(name.size() == 0) 603 err.push_back(make_fatal(at, "empty name")); 604 else if(!name_valid(name)) 605 err.push_back(make_fatal(at, "invalid name")); 606 if(last_bit > 31) 607 err.push_back(make_fatal(at, "last bit is greater than 31")); 608 if(first_bit > last_bit) 609 err.push_back(make_fatal(at, "last bit is greater than first bit")); 610 for(size_t i = 0; i < value.size(); i++) 611 { 612 for(size_t j = 0; j < value.size(); j++) 613 { 614 if(i == j) 615 continue; 616 if(value[i].name == value[j].name) 617 err.push_back(prefix(make_fatal(value[i].name, 618 "there are several values with the same name"), at)); 619 if(value[i].value == value[j].value) 620 err.push_back(prefix(make_warning(value[i].name, 621 "there are several values with the same value"), at)); 622 } 623 if(value[i].value > (bitmask() >> first_bit)) 624 err.push_back(prefix(make_warning(at, "value doesn't fit into the field"), value[i].name)); 625 if(recursive) 626 add_errors(err, value[i].errors(true), at); 627 } 628 return err; 629} 630 631std::vector< soc_error_t > soc_reg_addr_t::errors(bool recursive) 632{ 633 (void) recursive; 634 if(name.size() == 0) 635 return one_error(make_fatal("", "empty name")); 636 else if(!name_valid(name)) 637 return one_error(make_fatal(name, "invalid name")); 638 else 639 return no_error(); 640} 641 642std::vector< soc_error_t > soc_reg_formula_t::errors(bool recursive) 643{ 644 (void) recursive; 645 if(type == REG_FORMULA_STRING && string.size() == 0) 646 return one_error(make_fatal("", "empty string formula")); 647 else 648 return no_error(); 649} 650 651namespace 652{ 653 654bool field_overlap(const soc_reg_field_t& a, const soc_reg_field_t& b) 655{ 656 return !(a.first_bit > b.last_bit || b.first_bit > a.last_bit); 657} 658 659} 660 661std::vector< soc_error_t > soc_reg_t::errors(bool recursive) 662{ 663 std::vector< soc_error_t > err; 664 std::string at(name); 665 if(name.size() == 0) 666 err.push_back(make_fatal(at, "empty name")); 667 else if(!name_valid(name)) 668 err.push_back(make_fatal(at, "invalid name")); 669 for(size_t i = 0; i < addr.size(); i++) 670 { 671 for(size_t j = 0; j < addr.size(); j++) 672 { 673 if(i == j) 674 continue; 675 if(addr[i].name == addr[j].name) 676 err.push_back(prefix(make_fatal(addr[i].name, 677 "there are several instances with the same name"), at)); 678 if(addr[i].addr == addr[j].addr) 679 err.push_back(prefix(make_fatal(addr[i].name, 680 "there are several instances with the same address"), at)); 681 } 682 if(recursive) 683 add_errors(err, addr[i].errors(true), at); 684 } 685 if(recursive) 686 add_errors(err, formula.errors(true), at); 687 for(size_t i = 0; i < field.size(); i++) 688 { 689 for(size_t j = 0; j < field.size(); j++) 690 { 691 if(i == j) 692 continue; 693 if(field[i].name == field[j].name) 694 err.push_back(prefix(make_fatal(field[i].name, 695 "there are several fields with the same name"), at)); 696 if(field_overlap(field[i], field[j])) 697 err.push_back(prefix(make_fatal(field[i].name, 698 "there are overlapping fields"), at)); 699 } 700 if(recursive) 701 add_errors(err, field[i].errors(true), at); 702 } 703 return err; 704} 705 706std::vector< soc_error_t > soc_dev_addr_t::errors(bool recursive) 707{ 708 (void) recursive; 709 if(name.size() == 0) 710 return one_error(make_fatal("", "empty name")); 711 else if(!name_valid(name)) 712 return one_error(make_fatal(name, "invalid name")); 713 else 714 return no_error(); 715} 716 717std::vector< soc_error_t > soc_dev_t::errors(bool recursive) 718{ 719 std::vector< soc_error_t > err; 720 std::string at(name); 721 if(name.size() == 0) 722 err.push_back(make_fatal(at, "empty name")); 723 else if(!name_valid(name)) 724 err.push_back(make_fatal(at, "invalid name")); 725 for(size_t i = 0; i < addr.size(); i++) 726 { 727 for(size_t j = 0; j < addr.size(); j++) 728 { 729 if(i == j) 730 continue; 731 if(addr[i].name == addr[j].name) 732 err.push_back(prefix(make_fatal(addr[i].name, 733 "there are several instances with the same name"), at)); 734 if(addr[i].addr == addr[j].addr) 735 err.push_back(prefix(make_fatal(addr[i].name, 736 "there are several instances with the same address"), at)); 737 } 738 if(recursive) 739 add_errors(err, addr[i].errors(true), at); 740 } 741 for(size_t i = 0; i < reg.size(); i++) 742 { 743 for(size_t j = 0; j < reg.size(); j++) 744 { 745 if(i == j) 746 continue; 747 if(reg[i].name == reg[j].name) 748 err.push_back(prefix(make_fatal(reg[i].name, 749 "there are several registers with the same name"), at)); 750 } 751 if(recursive) 752 add_errors(err, reg[i].errors(true), at); 753 } 754 return err; 755} 756 757std::vector< soc_error_t > soc_t::errors(bool recursive) 758{ 759 std::vector< soc_error_t > err; 760 std::string at(name); 761 for(size_t i = 0; i < dev.size(); i++) 762 { 763 for(size_t j = 0; j < dev.size(); j++) 764 { 765 if(i == j) 766 continue; 767 if(dev[i].name == dev[j].name) 768 err.push_back(prefix(make_fatal(dev[i].name, 769 "there are several devices with the same name"), at)); 770 } 771 if(recursive) 772 add_errors(err, dev[i].errors(true), at); 773 } 774 return err; 775} 776 777namespace 778{ 779 780struct formula_evaluator 781{ 782 std::string formula; 783 size_t pos; 784 std::string error; 785 786 bool err(const char *fmt, ...) 787 { 788 char buffer[256]; 789 va_list args; 790 va_start(args, fmt); 791 vsnprintf(buffer,sizeof(buffer), fmt, args); 792 va_end(args); 793 error = buffer; 794 return false; 795 } 796 797 formula_evaluator(const std::string& s):pos(0) 798 { 799 for(size_t i = 0; i < s.size(); i++) 800 if(!isspace(s[i])) 801 formula.push_back(s[i]); 802 } 803 804 void adv() 805 { 806 pos++; 807 } 808 809 char cur() 810 { 811 return end() ? 0 : formula[pos]; 812 } 813 814 bool end() 815 { 816 return pos >= formula.size(); 817 } 818 819 bool parse_digit(char c, int basis, soc_word_t& res) 820 { 821 c = tolower(c); 822 if(isdigit(c)) 823 { 824 res = c - '0'; 825 return true; 826 } 827 if(basis == 16 && isxdigit(c)) 828 { 829 res = c + 10 - 'a'; 830 return true; 831 } 832 return err("invalid digit '%c'", c); 833 } 834 835 bool parse_signed(soc_word_t& res) 836 { 837 char op = cur(); 838 if(op == '+' || op == '-') 839 { 840 adv(); 841 if(!parse_signed(res)) 842 return false; 843 if(op == '-') 844 res *= -1; 845 return true; 846 } 847 else if(op == '(') 848 { 849 adv(); 850 if(!parse_expression(res)) 851 return false; 852 if(cur() != ')') 853 return err("expected ')', got '%c'", cur()); 854 adv(); 855 return true; 856 } 857 else if(isdigit(op)) 858 { 859 res = op - '0'; 860 adv(); 861 int basis = 10; 862 if(op == '0' && cur() == 'x') 863 { 864 basis = 16; 865 adv(); 866 } 867 soc_word_t digit = 0; 868 while(parse_digit(cur(), basis, digit)) 869 { 870 res = res * basis + digit; 871 adv(); 872 } 873 return true; 874 } 875 else if(isalpha(op) || op == '_') 876 { 877 std::string name; 878 while(isalnum(cur()) || cur() == '_') 879 { 880 name.push_back(cur()); 881 adv(); 882 } 883 return get_variable(name, res); 884 } 885 else 886 return err("express signed expression, got '%c'", op); 887 } 888 889 bool parse_term(soc_word_t& res) 890 { 891 if(!parse_signed(res)) 892 return false; 893 while(cur() == '*' || cur() == '/' || cur() == '%') 894 { 895 char op = cur(); 896 adv(); 897 soc_word_t tmp; 898 if(!parse_signed(tmp)) 899 return false; 900 if(op == '*') 901 res *= tmp; 902 else if(tmp != 0) 903 res = op == '/' ? res / tmp : res % tmp; 904 else 905 return err("division by 0"); 906 } 907 return true; 908 } 909 910 bool parse_expression(soc_word_t& res) 911 { 912 if(!parse_term(res)) 913 return false; 914 while(!end() && (cur() == '+' || cur() == '-')) 915 { 916 char op = cur(); 917 adv(); 918 soc_word_t tmp; 919 if(!parse_term(tmp)) 920 return false; 921 if(op == '+') 922 res += tmp; 923 else 924 res -= tmp; 925 } 926 return true; 927 } 928 929 bool parse(soc_word_t& res, std::string& _error) 930 { 931 bool ok = parse_expression(res); 932 if(ok && !end()) 933 err("unexpected character '%c'", cur()); 934 _error = error; 935 return ok && end(); 936 } 937 938 virtual bool get_variable(std::string name, soc_word_t& res) 939 { 940 return err("unknown variable '%s'", name.c_str()); 941 } 942}; 943 944struct my_evaluator : public formula_evaluator 945{ 946 const std::map< std::string, soc_word_t>& var; 947 948 my_evaluator(const std::string& formula, const std::map< std::string, soc_word_t>& _var) 949 :formula_evaluator(formula), var(_var) {} 950 951 virtual bool get_variable(std::string name, soc_word_t& res) 952 { 953 std::map< std::string, soc_word_t>::const_iterator it = var.find(name); 954 if(it == var.end()) 955 return formula_evaluator::get_variable(name, res); 956 else 957 { 958 res = it->second; 959 return true; 960 } 961 } 962}; 963 964} 965 966bool evaluate_formula(const std::string& formula, 967 const std::map< std::string, soc_word_t>& var, soc_word_t& result, std::string& error) 968{ 969 my_evaluator e(formula, var); 970 return e.parse(result, error); 971} 972 973/** WARNING we need to call xmlInitParser() to init libxml2 but it needs to 974 * called from the main thread, which is a super strong requirement, so do it 975 * using a static constructor */ 976namespace 977{ 978class xml_parser_init 979{ 980public: 981 xml_parser_init() 982 { 983 xmlInitParser(); 984 } 985}; 986 987xml_parser_init __xml_parser_init; 988} 989 990} // soc_desc_v1