From owner-svn-src-head@freebsd.org Sun Oct 25 14:52:17 2015 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id CF3878D19; Sun, 25 Oct 2015 14:52:17 +0000 (UTC) (envelope-from theraven@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 95A8C1FD0; Sun, 25 Oct 2015 14:52:17 +0000 (UTC) (envelope-from theraven@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id t9PEqGAr081797; Sun, 25 Oct 2015 14:52:16 GMT (envelope-from theraven@FreeBSD.org) Received: (from theraven@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id t9PEqGip081790; Sun, 25 Oct 2015 14:52:16 GMT (envelope-from theraven@FreeBSD.org) Message-Id: <201510251452.t9PEqGip081790@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: theraven set sender to theraven@FreeBSD.org using -f From: David Chisnall Date: Sun, 25 Oct 2015 14:52:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r289935 - in head/usr.bin: . dtc X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 25 Oct 2015 14:52:17 -0000 Author: theraven Date: Sun Oct 25 14:52:16 2015 New Revision: 289935 URL: https://svnweb.freebsd.org/changeset/base/289935 Log: Lots of improvements to the BSD-licensed dtc - Various fixes to includes (including recursive includes) - Lots of testing that the output exactly matches GPL'd dtc - Lots of bug fixes to merging - Fix incorrect mmap usage - Ad-hoc memory management replaced with C++11 unique_ptr and similar Patrick Wildt has successfully run many (all?) of the GPL dtc test suite. Modified: head/usr.bin/Makefile head/usr.bin/dtc/checking.cc head/usr.bin/dtc/checking.hh head/usr.bin/dtc/dtb.cc head/usr.bin/dtc/dtc.cc head/usr.bin/dtc/fdt.cc head/usr.bin/dtc/fdt.hh head/usr.bin/dtc/input_buffer.cc head/usr.bin/dtc/input_buffer.hh head/usr.bin/dtc/string.hh Modified: head/usr.bin/Makefile ============================================================================== --- head/usr.bin/Makefile Sun Oct 25 14:42:56 2015 (r289934) +++ head/usr.bin/Makefile Sun Oct 25 14:52:16 2015 (r289935) @@ -210,8 +210,10 @@ SUBDIR.${MK_GAMES}+= pom SUBDIR.${MK_GAMES}+= primes SUBDIR.${MK_GAMES}+= random .if ${MK_GPL_DTC} != "yes" +.if ${COMPILER_FEATURES:Mc++11} SUBDIR+= dtc .endif +.endif SUBDIR.${MK_GROFF}+= vgrind SUBDIR.${MK_HESIOD}+= hesinfo SUBDIR.${MK_ICONV}+= iconv Modified: head/usr.bin/dtc/checking.cc ============================================================================== --- head/usr.bin/dtc/checking.cc Sun Oct 25 14:42:56 2015 (r289934) +++ head/usr.bin/dtc/checking.cc Sun Oct 25 14:52:16 2015 (r289935) @@ -51,7 +51,7 @@ namespace struct address_cells_checker : public checker { address_cells_checker(const char *name) : checker(name) {} - virtual bool check_node(device_tree *tree, node *n) + virtual bool check_node(device_tree *tree, const node_ptr &n) { // If this has no children, it trivially meets the // conditions. @@ -61,8 +61,7 @@ namespace } bool found_address = false; bool found_size = false; - for (node::property_iterator i=n->property_begin(), - e=n->property_end() ; i!=e ; ++i) + for (auto i=n->property_begin(), e=n->property_end() ; i!=e ; ++i) { if (!found_address) { @@ -91,7 +90,7 @@ namespace } // anonymous namespace bool -checker::visit_node(device_tree *tree, node *n) +checker::visit_node(device_tree *tree, const node_ptr &n) { path.push_back(std::make_pair(n->name, n->unit_address)); // Check this node @@ -100,8 +99,7 @@ checker::visit_node(device_tree *tree, n return false; } // Now check its properties - for (node::property_iterator i=n->property_begin(), e=n->property_end() - ; i!=e ; ++i) + for (auto i=n->property_begin(), e=n->property_end() ; i!=e ; ++i) { if (!check_property(tree, n, *i)) { @@ -125,22 +123,21 @@ void checker::report_error(const char *errmsg) { fprintf(stderr, "Error: %s, while checking node: ", errmsg); - for (device_tree::node_path::iterator p=path.begin()+1, pe=path.end() ; - p!=pe ; ++p) + for (auto &p : path) { putc('/', stderr); - p->first.dump(); - if (!(p->second.empty())) + p.first.dump(); + if (!(p.second.empty())) { putc('@', stderr); - p->second.dump(); + p.second.dump(); } } fprintf(stderr, " [-W%s]\n", checker_name); } bool -property_checker::check_property(device_tree *tree, node *n, property *p) +property_checker::check_property(device_tree *tree, const node_ptr &n, property_ptr p) { if (p->get_key() == key) { @@ -154,7 +151,7 @@ property_checker::check_property(device_ } bool -property_size_checker::check(device_tree *tree, node *n, property *p) +property_size_checker::check(device_tree *tree, const node_ptr &n, property_ptr p) { uint32_t psize = 0; for (property::value_iterator i=p->begin(),e=p->end() ; i!=e ; ++i) @@ -216,10 +213,9 @@ bool check_manager::run_checks(device_tree *tree, bool keep_going) { bool success = true; - for (std::map::iterator i=checkers.begin(), - e=checkers.end() ; i!=e ; ++i) + for (auto &i : checkers) { - success &= i->second->check_tree(tree); + success &= i.second->check_tree(tree); if (!(success || keep_going)) { break; @@ -231,7 +227,7 @@ check_manager::run_checks(device_tree *t bool check_manager::disable_checker(string name) { - std::map::iterator checker = checkers.find(name); + auto checker = checkers.find(name); if (checker != checkers.end()) { disabled_checkers.insert(std::make_pair(name, @@ -245,8 +241,7 @@ check_manager::disable_checker(string na bool check_manager::enable_checker(string name) { - std::map::iterator checker = - disabled_checkers.find(name); + auto checker = disabled_checkers.find(name); if (checker != disabled_checkers.end()) { checkers.insert(std::make_pair(name, checker->second)); Modified: head/usr.bin/dtc/checking.hh ============================================================================== --- head/usr.bin/dtc/checking.hh Sun Oct 25 14:42:56 2015 (r289934) +++ head/usr.bin/dtc/checking.hh Sun Oct 25 14:52:16 2015 (r289935) @@ -65,7 +65,7 @@ class checker * Visits each node, calling the checker functions on properties and * nodes. */ - bool visit_node(device_tree *tree, node *n); + bool visit_node(device_tree *tree, const node_ptr &n); protected: /** * Prints the error message, along with the path to the node that @@ -86,7 +86,7 @@ class checker * Method for checking that a node is valid. The root class version * does nothing, subclasses should override this. */ - virtual bool check_node(device_tree *tree, node *n) + virtual bool check_node(device_tree *tree, const node_ptr &n) { return true; } @@ -94,7 +94,7 @@ class checker * Method for checking that a property is valid. The root class * version does nothing, subclasses should override this. */ - virtual bool check_property(device_tree *tree, node *n, property *p) + virtual bool check_property(device_tree *tree, const node_ptr &n, property_ptr p) { return true; } @@ -124,7 +124,7 @@ class property_checker : public checker * Implementation of the generic property-checking method that checks * for a property with the name specified in the constructor */ - virtual bool check_property(device_tree *tree, node *n, property *p); + virtual bool check_property(device_tree *tree, const node_ptr &n, property_ptr p); /** * Constructor. Takes the name of the checker and the name of the * property to check. @@ -134,7 +134,7 @@ class property_checker : public checker /** * The check method, which subclasses should implement. */ - virtual bool check(device_tree *tree, node *n, property *p) = 0; + virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p) = 0; }; /** @@ -149,7 +149,7 @@ struct property_type_checker : public pr */ property_type_checker(const char* name, string property_name) : property_checker(name, property_name) {} - virtual bool check(device_tree *tree, node *n, property *p) = 0; + virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p) = 0; }; /** @@ -160,7 +160,7 @@ struct property_type_checker begin() == p->end(); } @@ -175,7 +175,7 @@ struct property_type_checker begin() + 1 == p->end()) && p->begin()->is_string(); } @@ -190,7 +190,7 @@ struct property_type_checker begin(),e=p->end() ; i!=e ; ++i) @@ -213,7 +213,7 @@ struct property_type_checker begin() + 1 == p->end()) && (tree->referenced_node(*p->begin()) != 0); @@ -239,7 +239,7 @@ struct property_size_checker : public pr /** * Check, validates that the property has the correct size. */ - virtual bool check(device_tree *tree, node *n, property *p); + virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p); }; @@ -254,12 +254,12 @@ class check_manager * disabling checkers from the command line. When this manager runs, * it will only run the checkers from this map. */ - std::map checkers; + std::unordered_map checkers; /** * The disabled checkers. Moving checkers to this list disables them, * but allows them to be easily moved back. */ - std::map disabled_checkers; + std::unordered_map disabled_checkers; /** * Helper function for adding a property value checker. */ Modified: head/usr.bin/dtc/dtb.cc ============================================================================== --- head/usr.bin/dtc/dtb.cc Sun Oct 25 14:42:56 2015 (r289934) +++ head/usr.bin/dtc/dtb.cc Sun Oct 25 14:52:16 2015 (r289935) @@ -44,9 +44,9 @@ namespace dtb void output_writer::write_data(byte_buffer b) { - for (byte_buffer::iterator i=b.begin(), e=b.end(); i!=e ; i++) + for (auto i : b) { - write_data(*i); + write_data(i); } } @@ -277,7 +277,7 @@ header::read_dtb(input_buffer &input) uint32_t string_table::add_string(string str) { - std::map::iterator old = string_offsets.find(str); + auto old = string_offsets.find(str); if (old == string_offsets.end()) { uint32_t start = size; @@ -298,10 +298,9 @@ string_table::write(dtb::output_writer & { writer.write_comment(string("Strings table.")); writer.write_label(string("dt_strings_start")); - for (std::vector::iterator i=strings.begin(), e=strings.end() ; - i!=e ; ++i) + for (auto &i : strings) { - writer.write_string(*i); + writer.write_string(i); } writer.write_label(string("dt_strings_end")); } Modified: head/usr.bin/dtc/dtc.cc ============================================================================== --- head/usr.bin/dtc/dtc.cc Sun Oct 25 14:42:56 2015 (r289934) +++ head/usr.bin/dtc/dtc.cc Sun Oct 25 14:52:16 2015 (r289935) @@ -67,7 +67,7 @@ static void usage(const char* argv0) "[-O output_format]\n" "\t\t[-o output_file] [-R entries] [-S bytes] [-p bytes]" "[-V blob_version]\n" - "\t\t-W [no-]checker_name] input_file\n", basename(argv0)); + "\t\t-W [no-]checker_name] input_file\n", basename((char*)argv0)); } /** Modified: head/usr.bin/dtc/fdt.cc ============================================================================== --- head/usr.bin/dtc/fdt.cc Sun Oct 25 14:42:56 2015 (r289934) +++ head/usr.bin/dtc/fdt.cc Sun Oct 25 14:52:16 2015 (r289935) @@ -33,8 +33,10 @@ #define __STDC_LIMIT_MACROS 1 #include "fdt.hh" +#include "dtb.hh" #include + #include #include #include @@ -44,7 +46,7 @@ #include #include #include -#include "dtb.hh" +#include namespace dtc { @@ -126,13 +128,25 @@ property_value::resolve_type() bool is_all_printable = true; int nuls = 0; int bytes = 0; - for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end()-1; i nuls)) || bytes == 0) { type = STRING; - if (nuls > 0) + if (nuls > 1) { type = STRING_LIST; } @@ -162,15 +176,25 @@ property_value::write_as_string(FILE *fi } else { - for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end()-1; i!=e ; ++i) + bool hasNull = (byte_data.back() == '\0'); + // Remove trailing null bytes from the string before printing as dts. + if (hasNull) + { + byte_data.pop_back(); + } + for (auto i : byte_data) { // FIXME Escape tabs, newlines, and so on. - if (*i == '\0') + if (i == '\0') { fputs("\", \"", file); continue; } - putc(*i, file); + putc(i, file); + } + if (hasNull) + { + byte_data.push_back('\0'); } } putc('"', file); @@ -181,7 +205,7 @@ property_value::write_as_cells(FILE *fil { putc('<', file); assert((byte_data.size() % 4) == 0); - for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e ; ++i) + for (auto i=byte_data.begin(), e=byte_data.end(); i!=e ; ++i) { uint32_t v = 0; v = (v << 8) | *i; @@ -204,7 +228,7 @@ void property_value::write_as_bytes(FILE *file) { putc('[', file); - for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e ; i++) + for (auto i=byte_data.begin(), e=byte_data.end(); i!=e ; i++) { fprintf(file, "%02hhx", *i); if (i+1 != e) @@ -238,8 +262,26 @@ property::parse_string(input_buffer &inp } void -property::parse_cells(input_buffer &input) +property::parse_cells(input_buffer &input, int cell_size) { + unsigned long long cell_max; + switch (cell_size) + { + case 8: + cell_max = UINT8_MAX; + break; + case 16: + cell_max = UINT16_MAX; + break; + case 32: + cell_max = UINT32_MAX; + break; + case 64: + cell_max = UINT64_MAX; + break; + default: + assert(0 && "Invalid cell size!"); + } assert(input[0] == '<'); ++input; property_value v; @@ -251,6 +293,12 @@ property::parse_cells(input_buffer &inpu // referenced node if (input.consume('&')) { + if (cell_size != 32) + { + input.parse_error("reference only permitted in 32-bit arrays"); + valid = false; + return; + } input.next_token(); // FIXME: We should support full paths here, but we // don't. @@ -278,20 +326,37 @@ property::parse_cells(input_buffer &inpu { //FIXME: We should support labels in the middle //of these, but we don't. - long long val; + unsigned long long val; if (!input.consume_integer(val)) { input.parse_error("Expected numbers in array of cells"); valid = false; return; } - if ((val < 0) || (val > UINT32_MAX)) + if (val > cell_max) { + fprintf(stderr, "%lld > %lld\n", val, cell_max); input.parse_error("Value out of range"); valid = false; return; } - push_big_endian(v.byte_data, (uint32_t)val); + switch (cell_size) + { + case 8: + v.byte_data.push_back(val); + break; + case 16: + push_big_endian(v.byte_data, (uint16_t)val); + break; + case 32: + push_big_endian(v.byte_data, (uint32_t)val); + break; + case 64: + push_big_endian(v.byte_data, (uint64_t)val); + break; + default: + assert(0 && "Invalid cell size!"); + } input.next_token(); } } @@ -432,11 +497,35 @@ property::property(input_buffer &input, input.parse_error("Invalid property value."); valid = false; return; + case '/': + { + unsigned long long bits = 0; + valid = input.consume("/bits/"); + input.next_token(); + valid &= input.consume_integer(bits); + if ((bits != 8) && + (bits != 16) && + (bits != 32) && + (bits != 64)) { + input.parse_error("Invalid size for elements"); + valid = false; + } + if (!valid) return; + input.next_token(); + if (input[0] != '<') + { + input.parse_error("/bits/ directive is only valid on arrays"); + valid = false; + return; + } + parse_cells(input, bits); + break; + } case '"': parse_string(input); break; case '<': - parse_cells(input); + parse_cells(input, 32); break; case '[': parse_bytes(input); @@ -458,27 +547,25 @@ property::property(input_buffer &input, } } -property* +property_ptr property::parse_dtb(input_buffer &structs, input_buffer &strings) { - property *p = new property(structs, strings); + property_ptr p(new property(structs, strings)); if (!p->valid) { - delete p; - p = 0; + p = nullptr; } return p; } -property* +property_ptr property::parse(input_buffer &input, string key, string label, bool semicolonTerminated, define_map *defines) { - property *p = new property(input, key, label, semicolonTerminated, defines); + property_ptr p(new property(input, key, label, semicolonTerminated, defines)); if (!p->valid) { - delete p; - p = 0; + p = nullptr; } return p; } @@ -498,6 +585,35 @@ property::write(dtb::output_writer &writ writer.write_data(value_buffer); } +bool +property_value::try_to_merge(property_value &other) +{ + resolve_type(); + switch (type) + { + case UNKNOWN: + __builtin_unreachable(); + assert(0); + return false; + case EMPTY: + *this = other; + case STRING: + case STRING_LIST: + case CROSS_REFERENCE: + return false; + case PHANDLE: + case BINARY: + if (other.type == PHANDLE || other.type == BINARY) + { + type = BINARY; + byte_data.insert(byte_data.end(), other.byte_data.begin(), + other.byte_data.end()); + return true; + } + } + return false; +} + void property::write_dts(FILE *file, int indent) { @@ -516,8 +632,23 @@ property::write_dts(FILE *file, int inde } if (!values.empty()) { + std::vector *vals = &values; + std::vector v; + // If we've got multiple values then try to merge them all together. + if (values.size() > 1) + { + vals = &v; + v.push_back(values.front()); + for (auto i=(++begin()), e=end() ; i!=e ; ++i) + { + if (!v.back().try_to_merge(*i)) + { + v.push_back(*i); + } + } + } fputs(" = ", file); - for (value_iterator i=begin(), e=end() ; i!=e ; ++i) + for (auto i=vals->begin(), e=vals->end() ; i!=e ; ++i) { i->write_dts(file); if (i+1 != e) @@ -590,13 +721,13 @@ node::node(input_buffer &structs, input_ // Child node, parse it. case dtb::FDT_BEGIN_NODE: { - node *child = node::parse_dtb(structs, strings); + node_ptr child = node::parse_dtb(structs, strings); if (child == 0) { valid = false; return; } - children.push_back(child); + children.push_back(std::move(child)); break; } // End of this node, no errors. @@ -605,7 +736,7 @@ node::node(input_buffer &structs, input_ // Property, parse it. case dtb::FDT_PROP: { - property *prop = property::parse_dtb(structs, strings); + property_ptr prop = property::parse_dtb(structs, strings); if (prop == 0) { valid = false; @@ -667,7 +798,7 @@ node::node(input_buffer &input, string n // If we're parsing a property, then we must actually do that. if (input.consume('=')) { - property *p= property::parse(input, child_name, + property_ptr p = property::parse(input, child_name, child_label, true, defines); if (p == 0) { @@ -680,11 +811,11 @@ node::node(input_buffer &input, string n } else if (!is_property && input[0] == ('{')) { - node *child = node::parse(input, child_name, + node_ptr child = node::parse(input, child_name, child_label, child_address, defines); if (child) { - children.push_back(child); + children.push_back(std::move(child)); } else { @@ -693,7 +824,7 @@ node::node(input_buffer &input, string n } else if (input.consume(';')) { - properties.push_back(new property(child_name, child_label)); + properties.push_back(property_ptr(new property(child_name, child_label))); } else { @@ -706,13 +837,13 @@ node::node(input_buffer &input, string n } bool -node::cmp_properties(property *p1, property *p2) +node::cmp_properties(property_ptr &p1, property_ptr &p2) { return p1->get_key() < p2->get_key(); } bool -node::cmp_children(node *c1, node *c2) +node::cmp_children(node_ptr &c1, node_ptr &c2) { if (c1->name == c2->name) { @@ -732,63 +863,47 @@ node::sort() } } -node* +node_ptr node::parse(input_buffer &input, string name, string label, string address, define_map *defines) { - node *n = new node(input, name, label, address, defines); + node_ptr n(new node(input, name, label, address, defines)); if (!n->valid) { - delete n; n = 0; } return n; } -node* +node_ptr node::parse_dtb(input_buffer &structs, input_buffer &strings) { - node *n = new node(structs, strings); + node_ptr n(new node(structs, strings)); if (!n->valid) { - delete n; n = 0; } return n; } -node::~node() -{ - while (!children.empty()) - { - delete children.back(); - children.pop_back(); - } - while (!properties.empty()) - { - delete properties.back(); - properties.pop_back(); - } -} - -property* +property_ptr node::get_property(string key) { - for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i) + for (auto &i : properties) { - if ((*i)->get_key() == key) + if (i->get_key() == key) { - return *i; + return i; } } return 0; } void -node::merge_node(node *other) +node::merge_node(node_ptr other) { if (!other->label.empty()) { @@ -799,40 +914,39 @@ node::merge_node(node *other) // large numbers of properties, but for typical usage the // entire vector will fit (easily) into cache, so iterating // over it repeatedly isn't that expensive. - while (!other->properties.empty()) + for (auto &p : other->properties) { - property *p = other->properties.front(); - for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i) + bool found = false; + for (auto i=property_begin(), e=property_end() ; i!=e ; ++i) { if ((*i)->get_key() == p->get_key()) { - delete *i; - properties.erase(i); + *i = p; + found = true; break; } } - add_property(p); - other->properties.erase(other->properties.begin()); + if (!found) + { + add_property(p); + } } - while (!other->children.empty()) + for (auto &c : other->children) { - node *c = other->children.front(); bool found = false; - for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i) + for (auto &i : children) { - if ((*i)->name == c->name && (*i)->unit_address == c->unit_address) + if (i->name == c->name && i->unit_address == c->unit_address) { - (*i)->merge_node(c); - delete c; + i->merge_node(std::move(c)); found = true; break; } } if (!found) { - children.push_back(c); + children.push_back(std::move(c)); } - other->children.erase(other->children.begin()); } } @@ -850,7 +964,7 @@ node::write(dtb::output_writer &writer, writer.write_comment(name); writer.write_data(name_buffer); writer.write_data((uint8_t)0); - for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i) + for (auto i=property_begin(), e=property_end() ; i!=e ; ++i) { (*i)->write(writer, strings); } @@ -868,11 +982,13 @@ node::write_dts(FILE *file, int indent) { putc('\t', file); } +#ifdef PRINT_LABELS if (label != string()) { label.print(file); fputs(": ", file); } +#endif if (name != string()) { name.print(file); @@ -883,7 +999,7 @@ node::write_dts(FILE *file, int indent) unit_address.print(file); } fputs(" {\n\n", file); - for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i) + for (auto i=property_begin(), e=property_end() ; i!=e ; ++i) { (*i)->write_dts(file, indent+1); } @@ -899,7 +1015,7 @@ node::write_dts(FILE *file, int indent) } void -device_tree::collect_names_recursive(node* n, node_path &path) +device_tree::collect_names_recursive(node_ptr &n, node_path &path) { string name = n->label; path.push_back(std::make_pair(n->name, n->unit_address)); @@ -907,13 +1023,13 @@ device_tree::collect_names_recursive(nod { if (node_names.find(name) == node_names.end()) { - node_names.insert(std::make_pair(name, n)); + node_names.insert(std::make_pair(name, n.get())); node_paths.insert(std::make_pair(name, path)); } else { node_names[name] = (node*)-1; - std::map::iterator i = node_paths.find(name); + auto i = node_paths.find(name); if (i != node_paths.end()) { node_paths.erase(name); @@ -930,7 +1046,7 @@ device_tree::collect_names_recursive(nod path.pop_back(); // Now we collect the phandles and properties that reference // other nodes. - for (node::property_iterator i=n->property_begin(), e=n->property_end() ; i!=e ; ++i) + for (auto i=n->property_begin(), e=n->property_end() ; i!=e ; ++i) { for (property::value_iterator p=(*i)->begin(),pe=(*i)->end() ; p!=pe ; ++p) { @@ -956,7 +1072,7 @@ device_tree::collect_names_recursive(nod else { uint32_t phandle = (*i)->begin()->get_as_uint32(); - used_phandles.insert(std::make_pair(phandle, n)); + used_phandles.insert(std::make_pair(phandle, n.get())); } } } @@ -966,18 +1082,21 @@ void device_tree::collect_names() { node_path p; + node_names.clear(); + node_paths.clear(); + cross_references.clear(); + phandles.clear(); collect_names_recursive(root, p); } void device_tree::resolve_cross_references() { - for (std::vector::iterator i=cross_references.begin(), e=cross_references.end() ; i!=e ; ++i) + for (auto *pv : cross_references) { - property_value* pv = *i; node_path path = node_paths[pv->string_data]; // Skip the first name in the path. It's always "", and implicitly / - for (node_path::iterator p=path.begin()+1, pe=path.end() ; p!=pe ; ++p) + for (auto p=path.begin()+1, pe=path.end() ; p!=pe ; ++p) { pv->byte_data.push_back('/'); p->first.push_to_buffer(pv->byte_data); @@ -987,23 +1106,22 @@ device_tree::resolve_cross_references() p->second.push_to_buffer(pv->byte_data); } } - pv->byte_data.push_back(0); } uint32_t phandle = 1; - for (std::vector::iterator i=phandles.begin(), e=phandles.end() ; i!=e ; ++i) + for (auto &i : phandles) { - string target_name = (*i)->string_data; + string target_name = i->string_data; node *target = node_names[target_name]; if (target == 0) { - fprintf(stderr, "Failed to find node with label:"); + fprintf(stderr, "Failed to find node with label: "); target_name.dump(); fprintf(stderr, "\n"); valid = 0; return; } // If there is an existing phandle, use it - property *p = target->get_property("phandle"); + property_ptr p = target->get_property("phandle"); if (p == 0) { p = target->get_property("linux,phandle"); @@ -1029,33 +1147,140 @@ device_tree::resolve_cross_references() push_big_endian(v.byte_data, phandle++); if (phandle_node_name == BOTH || phandle_node_name == LINUX) { - p = new property(string("linux,phandle")); + p.reset(new property(string("linux,phandle"))); p->add_value(v); target->add_property(p); } if (phandle_node_name == BOTH || phandle_node_name == EPAPR) { - p = new property(string("phandle")); + p.reset(new property(string("phandle"))); p->add_value(v); target->add_property(p); } } - p->begin()->push_to_buffer((*i)->byte_data); - assert((*i)->byte_data.size() == 4); + p->begin()->push_to_buffer(i->byte_data); + assert(i->byte_data.size() == 4); } } void -device_tree::parse_roots(input_buffer &input, std::vector &roots) +device_tree::parse_file(input_buffer &input, + const std::string &dir, + std::vector &roots, + FILE *depfile, + bool &read_header) { input.next_token(); - while (valid && input.consume('/')) + // Read the header + if (input.consume("/dts-v1/;")) + { + read_header = true; + } + input.next_token(); + while(input.consume("/include/")) + { + bool reallyInclude = true; + if (input.consume("if ")) + { + input.next_token(); + string name = string::parse_property_name(input); + // XXX: Error handling + if (defines.find(name) == defines.end()) + { + reallyInclude = false; + } + input.consume('/'); + } + input.next_token(); + if (!input.consume('"')) + { + input.parse_error("Expected quoted filename"); + valid = false; + return; + } + int length = 0; + while (input[length] != '"') length++; + + std::string file((const char*)input, length); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***