From owner-svn-src-stable-11@freebsd.org Tue May 9 18:46:51 2017 Return-Path: Delivered-To: svn-src-stable-11@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 4F489D65EE9; Tue, 9 May 2017 18:46:51 +0000 (UTC) (envelope-from gonzo@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 E67E6BC4; Tue, 9 May 2017 18:46:50 +0000 (UTC) (envelope-from gonzo@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v49IkoL8092826; Tue, 9 May 2017 18:46:50 GMT (envelope-from gonzo@FreeBSD.org) Received: (from gonzo@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v49IknNp092818; Tue, 9 May 2017 18:46:49 GMT (envelope-from gonzo@FreeBSD.org) Message-Id: <201705091846.v49IknNp092818@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: gonzo set sender to gonzo@FreeBSD.org using -f From: Oleksandr Tymoshenko Date: Tue, 9 May 2017 18:46:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r318093 - stable/11/usr.bin/dtc X-SVN-Group: stable-11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-11@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for only the 11-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 09 May 2017 18:46:51 -0000 Author: gonzo Date: Tue May 9 18:46:49 2017 New Revision: 318093 URL: https://svnweb.freebsd.org/changeset/base/318093 Log: MFC r306806, r313709, r317058, r317060 r306806 by emaste: Improvements to BSD-licensed DTC. - Numerous crash and bug fixes - Improved warning and error messages - Permit multiple labels on nodes and properties - Fix node@address references - Add support for /delete-node/ - Consume whitespace after a node - Read the next token before the second /memreserve/ - Fix parsing of whitespace - Clean up /delete-node/ and add support for /delete-property/ - Handle /delete-node/ specifying a unit address Obtained from: https://github.com/davidchisnall/dtc @df5ede4 r313709 by dim: Fix build of BSD dtc when NDEBUG is defined (MK_ASSERT_DEBUG=no): * Initialize correct parent in binary_operator's constructor. * Include explicitly, otherwise errno is undefined (without NDEBUG, this is accidentally 'fixed' by including ). Reported by: matteo r317058 by emaste: dtc: remove unused (since r306806) string.hh r317060 by emaste: dtc: update to upstream 227d6a3 - Report missing includes at the correct location. - Add initial support for the -@ option emitting a symbol table. - Add support for running tests with and without -@ - Add support for generating __fixups__ and __local_fixups__ - Attach the to-string transform to the node path. Deleted: stable/11/usr.bin/dtc/string.hh Modified: stable/11/usr.bin/dtc/checking.cc stable/11/usr.bin/dtc/checking.hh stable/11/usr.bin/dtc/dtb.cc stable/11/usr.bin/dtc/dtb.hh stable/11/usr.bin/dtc/dtc.1 stable/11/usr.bin/dtc/dtc.cc stable/11/usr.bin/dtc/fdt.cc stable/11/usr.bin/dtc/fdt.hh stable/11/usr.bin/dtc/input_buffer.cc stable/11/usr.bin/dtc/input_buffer.hh stable/11/usr.bin/dtc/string.cc stable/11/usr.bin/dtc/util.hh Directory Properties: stable/11/ (props changed) Modified: stable/11/usr.bin/dtc/checking.cc ============================================================================== --- stable/11/usr.bin/dtc/checking.cc Tue May 9 18:45:34 2017 (r318092) +++ stable/11/usr.bin/dtc/checking.cc Tue May 9 18:46:49 2017 (r318093) @@ -33,7 +33,7 @@ #include "checking.hh" #include - +using std::string; namespace dtc { @@ -44,6 +44,30 @@ namespace checking namespace { + struct deleted_node_checker : public checker + { + deleted_node_checker(const char *name) : checker(name) {} + virtual bool check_node(device_tree *, const node_ptr &n) + { + auto &deleted = n->deleted_child_nodes(); + if (deleted.empty()) + { + return true; + } + bool plural = deleted.size() > 1; + string errmsg("Attempts to delete "); + errmsg += plural ? "nodes" : "node"; + errmsg += " that "; + errmsg += plural ? "were" : "was"; + errmsg += " not added in merge: "; + for (auto &d : deleted) + { + errmsg += d; + } + report_error(errmsg.c_str()); + return false; + } + }; /** * Checker that verifies that every node that has children has * #address-cells and #size-cells properties. @@ -126,11 +150,11 @@ checker::report_error(const char *errmsg for (auto &p : path) { putc('/', stderr); - p.first.dump(); + puts(p.first.c_str()); if (!(p.second.empty())) { putc('@', stderr); - p.second.dump(); + puts(p.second.c_str()); } } fprintf(stderr, " [-W%s]\n", checker_name); @@ -167,7 +191,7 @@ property_size_checker::check(device_tree template void -check_manager::add_property_type_checker(const char *name, string prop) +check_manager::add_property_type_checker(const char *name, const string &prop) { checkers.insert(std::make_pair(string(name), new property_type_checker(name, prop))); @@ -175,7 +199,7 @@ check_manager::add_property_type_checker void check_manager::add_property_size_checker(const char *name, - string prop, + const string &prop, uint32_t size) { checkers.insert(std::make_pair(string(name), @@ -207,6 +231,8 @@ check_manager::check_manager() add_property_size_checker("type-phandle", string("phandle"), 4); disabled_checkers.insert(std::make_pair(string("cells-attributes"), new address_cells_checker("cells-attributes"))); + checkers.insert(std::make_pair(string("deleted-nodes"), + new deleted_node_checker("deleted-nodes"))); } bool @@ -225,7 +251,7 @@ check_manager::run_checks(device_tree *t } bool -check_manager::disable_checker(string name) +check_manager::disable_checker(const string &name) { auto checker = checkers.find(name); if (checker != checkers.end()) @@ -239,7 +265,7 @@ check_manager::disable_checker(string na } bool -check_manager::enable_checker(string name) +check_manager::enable_checker(const string &name) { auto checker = disabled_checkers.find(name); if (checker != disabled_checkers.end()) Modified: stable/11/usr.bin/dtc/checking.hh ============================================================================== --- stable/11/usr.bin/dtc/checking.hh Tue May 9 18:45:34 2017 (r318092) +++ stable/11/usr.bin/dtc/checking.hh Tue May 9 18:46:49 2017 (r318093) @@ -32,7 +32,7 @@ #ifndef _CHECKING_HH_ #define _CHECKING_HH_ -#include "string.hh" +#include #include "fdt.hh" namespace dtc @@ -58,7 +58,7 @@ class checker /** * The name of the checker. This is used for printing error messages * and for enabling / disabling specific checkers from the command - * line. + * line. */ const char *checker_name; /** @@ -118,18 +118,18 @@ class property_checker : public checker /** * The name of the property that this checker is looking for. */ - string key; + std::string key; public: /** * Implementation of the generic property-checking method that checks - * for a property with the name specified in the constructor + * for a property with the name specified in the constructor. */ 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. */ - property_checker(const char* name, string property_name) + property_checker(const char* name, const std::string &property_name) : checker(name), key(property_name) {} /** * The check method, which subclasses should implement. @@ -147,7 +147,7 @@ struct property_type_checker : public pr * Constructor, takes the name of the checker and the name of the * property to check as arguments. */ - property_type_checker(const char* name, string property_name) : + property_type_checker(const char* name, const std::string &property_name) : property_checker(name, property_name) {} virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p) = 0; }; @@ -158,7 +158,7 @@ struct property_type_checker : public pr template<> struct property_type_checker : public property_checker { - property_type_checker(const char* name, string property_name) : + property_type_checker(const char* name, const std::string &property_name) : property_checker(name, property_name) {} virtual bool check(device_tree *, const node_ptr &, property_ptr p) { @@ -173,7 +173,7 @@ struct property_type_checker struct property_type_checker : public property_checker { - property_type_checker(const char* name, string property_name) : + property_type_checker(const char* name, const std::string &property_name) : property_checker(name, property_name) {} virtual bool check(device_tree *, const node_ptr &, property_ptr p) { @@ -188,7 +188,7 @@ template<> struct property_type_checker : public property_checker { - property_type_checker(const char* name, string property_name) : + property_type_checker(const char* name, const std::string &property_name) : property_checker(name, property_name) {} virtual bool check(device_tree *, const node_ptr &, property_ptr p) { @@ -211,11 +211,11 @@ struct property_type_checker struct property_type_checker : public property_checker { - property_type_checker(const char* name, string property_name) : + property_type_checker(const char* name, const std::string &property_name) : property_checker(name, property_name) {} virtual bool check(device_tree *tree, const node_ptr &, property_ptr p) { - return (p->begin() + 1 == p->end()) && + return (p->begin() + 1 == p->end()) && (tree->referenced_node(*p->begin()) != 0); } }; @@ -234,7 +234,9 @@ struct property_size_checker : public pr * Constructor, takes the name of the checker, the name of the property * to check, and its expected size as arguments. */ - property_size_checker(const char* name, string property_name, uint32_t bytes) + property_size_checker(const char* name, + const std::string &property_name, + uint32_t bytes) : property_checker(name, property_name), size(bytes) {} /** * Check, validates that the property has the correct size. @@ -254,26 +256,26 @@ class check_manager * disabling checkers from the command line. When this manager runs, * it will only run the checkers from this map. */ - std::unordered_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::unordered_map disabled_checkers; + std::unordered_map disabled_checkers; /** * Helper function for adding a property value checker. */ template - void add_property_type_checker(const char *name, string prop); + void add_property_type_checker(const char *name, const std::string &prop); /** * Helper function for adding a simple type checker. */ - void add_property_type_checker(const char *name, string prop); + void add_property_type_checker(const char *name, const std::string &prop); /** * Helper function for adding a property value checker. */ void add_property_size_checker(const char *name, - string prop, + const std::string &prop, uint32_t size); public: /** @@ -292,11 +294,11 @@ class check_manager /** * Disables the named checker. */ - bool disable_checker(string name); + bool disable_checker(const std::string &name); /** - * Enables the named checker. + * Enables the named checker. */ - bool enable_checker(string name); + bool enable_checker(const std::string &name); }; } // namespace checking Modified: stable/11/usr.bin/dtc/dtb.cc ============================================================================== --- stable/11/usr.bin/dtc/dtb.cc Tue May 9 18:45:34 2017 (r318092) +++ stable/11/usr.bin/dtc/dtb.cc Tue May 9 18:46:49 2017 (r318093) @@ -36,6 +36,7 @@ #include #include +using std::string; namespace dtc { @@ -51,9 +52,9 @@ void output_writer::write_data(byte_buff } void -binary_writer::write_string(string name) +binary_writer::write_string(const string &name) { - name.push_to_buffer(buffer); + push_string(buffer, name); // Trailing nul buffer.push_back(0); } @@ -98,15 +99,6 @@ binary_writer::size() } void -asm_writer::write_string(const char *c) -{ - while (*c) - { - buffer.push_back((uint8_t)*(c++)); - } -} - -void asm_writer::write_line(const char *c) { if (byte_count != 0) @@ -142,34 +134,44 @@ asm_writer::write_byte(uint8_t b) } void -asm_writer::write_label(string name) +asm_writer::write_label(const string &name) { write_line("\t.globl "); - name.push_to_buffer(buffer); + push_string(buffer, name); buffer.push_back('\n'); - name.push_to_buffer(buffer); + push_string(buffer, name); buffer.push_back(':'); buffer.push_back('\n'); buffer.push_back('_'); - name.push_to_buffer(buffer); + push_string(buffer, name); buffer.push_back(':'); buffer.push_back('\n'); } void -asm_writer::write_comment(string name) +asm_writer::write_comment(const string &name) { write_line("\t/* "); - name.push_to_buffer(buffer); + push_string(buffer, name); write_string(" */\n"); } void -asm_writer::write_string(string name) +asm_writer::write_string(const char *c) +{ + while (*c) + { + buffer.push_back((uint8_t)*(c++)); + } +} + + +void +asm_writer::write_string(const string &name) { write_line("\t.string \""); - name.push_to_buffer(buffer); + push_string(buffer, name); write_line("\"\n"); bytes_written += name.size() + 1; } @@ -231,8 +233,8 @@ asm_writer::size() void header::write(output_writer &out) { - out.write_label(string("dt_blob_start")); - out.write_label(string("dt_header")); + out.write_label("dt_blob_start"); + out.write_label("dt_header"); out.write_comment("magic"); out.write_data(magic); out.write_comment("totalsize"); @@ -275,7 +277,7 @@ header::read_dtb(input_buffer &input) input.consume_binary(size_dt_struct); } uint32_t -string_table::add_string(string str) +string_table::add_string(const string &str) { auto old = string_offsets.find(str); if (old == string_offsets.end()) @@ -296,13 +298,13 @@ string_table::add_string(string str) void string_table::write(dtb::output_writer &writer) { - writer.write_comment(string("Strings table.")); - writer.write_label(string("dt_strings_start")); + writer.write_comment("Strings table."); + writer.write_label("dt_strings_start"); for (auto &i : strings) { writer.write_string(i); } - writer.write_label(string("dt_strings_end")); + writer.write_label("dt_strings_end"); } } // namespace dtb Modified: stable/11/usr.bin/dtc/dtb.hh ============================================================================== --- stable/11/usr.bin/dtc/dtb.hh Tue May 9 18:45:34 2017 (r318092) +++ stable/11/usr.bin/dtc/dtb.hh Tue May 9 18:46:49 2017 (r318093) @@ -33,10 +33,13 @@ #ifndef _DTB_HH_ #define _DTB_HH_ #include -#include "string.hh" +#include #include +#include "input_buffer.hh" +#include "util.hh" + namespace dtc { /** @@ -121,16 +124,16 @@ struct output_writer * assembly output, where the labels become symbols that can be * resolved at link time. */ - virtual void write_label(string name) = 0; + virtual void write_label(const std::string &name) = 0; /** * Writes a comment into the output stream. Useful only when debugging * the output. */ - virtual void write_comment(string name) = 0; + virtual void write_comment(const std::string &name) = 0; /** * Writes a string. A nul terminator is implicitly added. */ - virtual void write_string(string name) = 0; + virtual void write_string(const std::string &name) = 0; /** * Writes a single 8-bit value. */ @@ -186,17 +189,17 @@ class binary_writer : public output_writ * The binary format does not support labels, so this method * does nothing. */ - virtual void write_label(string) {} + void write_label(const std::string &) override {} /** * Comments are ignored by the binary writer. */ - virtual void write_comment(string) {} - virtual void write_string(string name); - virtual void write_data(uint8_t v); - virtual void write_data(uint32_t v); - virtual void write_data(uint64_t v); - virtual void write_to_file(int fd); - virtual uint32_t size(); + void write_comment(const std::string&) override {} + void write_string(const std::string &name) override; + void write_data(uint8_t v) override; + void write_data(uint32_t v) override; + void write_data(uint64_t v) override; + void write_to_file(int fd) override; + uint32_t size() override; }; /** * Assembly writer. This class is responsible for writing the output in an @@ -224,11 +227,15 @@ class asm_writer : public output_writer uint32_t bytes_written; /** - * Writes a C string directly to the output as-is. This is mainly used - * for writing directives. + * Writes a string directly to the output as-is. This is the function that + * performs the real output. */ void write_string(const char *c); /** + * Write a string to the output. + */ + void write_string(const std::string &c) override; + /** * Writes the string, starting on a new line. */ void write_line(const char *c); @@ -239,14 +246,13 @@ class asm_writer : public output_writer void write_byte(uint8_t b); public: asm_writer() : byte_count(0), bytes_written(0) {} - virtual void write_label(string name); - virtual void write_comment(string name); - virtual void write_string(string name); - virtual void write_data(uint8_t v); - virtual void write_data(uint32_t v); - virtual void write_data(uint64_t v); - virtual void write_to_file(int fd); - virtual uint32_t size(); + void write_label(const std::string &name) override; + void write_comment(const std::string &name) override; + void write_data(uint8_t v) override; + void write_data(uint32_t v) override; + void write_data(uint64_t v) override; + void write_to_file(int fd) override; + uint32_t size() override; }; /** @@ -328,14 +334,14 @@ class string_table { /** * Map from strings to their offset. */ - std::map string_offsets; + std::map string_offsets; /** * The strings, in the order in which they should be written to the * output. The order must be stable - adding another string must not * change the offset of any that we have already referenced - and so we * simply write the strings in the order that they are passed. */ - std::vector strings; + std::vector strings; /** * The current size of the strings section. */ @@ -351,7 +357,7 @@ class string_table { * will return its existing offset, otherwise it will return a new * offset. */ - uint32_t add_string(string str); + uint32_t add_string(const std::string &str); /** * Writes the strings table to the specified output. */ Modified: stable/11/usr.bin/dtc/dtc.1 ============================================================================== --- stable/11/usr.bin/dtc/dtc.1 Tue May 9 18:45:34 2017 (r318092) +++ stable/11/usr.bin/dtc/dtc.1 Tue May 9 18:46:49 2017 (r318093) @@ -38,7 +38,7 @@ .Nd device tree compiler .Sh SYNOPSIS .Nm -.Op Fl fhsv +.Op Fl @fhsv .Op Fl b Ar boot_cpu_id .Op Fl d Ar dependency_file .Op Fl E Ar [no-]checker_name @@ -84,6 +84,8 @@ Enable or disable a specified checker. The argument is the name of the checker. The full list of checkers is given in .Sx CHECKERS . +.It Fl @ +Emit a __symbols__ node to allow plugins to be loaded. .It Fl f Force the tool to attempt to generate the output, even if the input had errors. .It Fl h @@ -237,6 +239,10 @@ Checks that all nodes with children have and .Va #size-cells properties. +.It deleted-nodes +Checks that all +.Va /delete-node/ +statements refer to nodes that are merged. .El .Sh EXAMPLES The command: Modified: stable/11/usr.bin/dtc/dtc.cc ============================================================================== --- stable/11/usr.bin/dtc/dtc.cc Tue May 9 18:45:34 2017 (r318092) +++ stable/11/usr.bin/dtc/dtc.cc Tue May 9 18:46:49 2017 (r318093) @@ -42,8 +42,10 @@ #include "fdt.hh" #include "checking.hh" +#include "util.hh" using namespace dtc; +using std::string; /** * The current major version of the tool. @@ -52,22 +54,22 @@ int version_major = 0; /** * The current minor version of the tool. */ -int version_minor = 4; +int version_minor = 5; /** * The current patch level of the tool. */ int version_patch = 0; -static void usage(const char* argv0) +static void usage(const string &argv0) { fprintf(stderr, "Usage:\n" - "\t%s\t[-fhsv] [-b boot_cpu_id] [-d dependency_file]" + "\t%s\t[-fhsv@] [-b boot_cpu_id] [-d dependency_file]" "[-E [no-]checker_name]\n" "\t\t[-H phandle_format] [-I input_format]" "[-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((char*)argv0)); + "\t\t-W [no-]checker_name] input_file\n", basename(argv0).c_str()); } /** @@ -90,9 +92,8 @@ main(int argc, char **argv) const char *in_file = "-"; FILE *depfile = 0; bool debug_mode = false; - void (device_tree::*write_fn)(int) = &device_tree::write_binary; - void (device_tree::*read_fn)(const char*, FILE*) = - &device_tree::parse_dts; + auto write_fn = &device_tree::write_binary; + auto read_fn = &device_tree::parse_dts; uint32_t boot_cpu; bool boot_cpu_specified = false; bool keep_going = false; @@ -100,7 +101,7 @@ main(int argc, char **argv) clock_t c0 = clock(); class device_tree tree; fdt::checking::check_manager checks; - const char *options = "hqI:O:o:V:d:R:S:p:b:fi:svH:W:E:DP:"; + const char *options = "@hqI:O:o:V:d:R:S:p:b:fi:svH:W:E:DP:"; // Don't forget to update the man page if any more options are added. while ((ch = getopt(argc, argv, options)) != -1) @@ -113,14 +114,17 @@ main(int argc, char **argv) case 'v': version(argv[0]); return EXIT_SUCCESS; + case '@': + tree.write_symbols = true; + break; case 'I': { - string arg = string(optarg); - if (arg == string("dtb")) + string arg(optarg); + if (arg == "dtb") { read_fn = &device_tree::parse_dtb; } - else if (arg == string("dts")) + else if (arg == "dts") { read_fn = &device_tree::parse_dts; } @@ -133,16 +137,16 @@ main(int argc, char **argv) } case 'O': { - string arg = string(optarg); - if (arg == string("dtb")) + string arg(optarg); + if (arg == "dtb") { write_fn = &device_tree::write_binary; } - else if (arg == string("asm")) + else if (arg == "asm") { write_fn = &device_tree::write_asm; } - else if (arg == string("dts")) + else if (arg == "dts") { write_fn = &device_tree::write_dts; } @@ -168,7 +172,7 @@ main(int argc, char **argv) debug_mode = true; break; case 'V': - if (string(optarg) != string("17")) + if (string(optarg) != "17") { fprintf(stderr, "Unknown output format version: %s\n", optarg); return EXIT_FAILURE; @@ -180,7 +184,7 @@ main(int argc, char **argv) { fclose(depfile); } - if (string(optarg) == string("-")) + if (string(optarg) == "-") { depfile = stdout; } @@ -197,16 +201,16 @@ main(int argc, char **argv) } case 'H': { - string arg = string(optarg); - if (arg == string("both")) + string arg(optarg); + if (arg == "both") { tree.set_phandle_format(device_tree::BOTH); } - else if (arg == string("epapr")) + else if (arg == "epapr") { tree.set_phandle_format(device_tree::EPAPR); } - else if (arg == string("linux")) + else if (arg == "linux") { tree.set_phandle_format(device_tree::LINUX); } @@ -229,7 +233,7 @@ main(int argc, char **argv) case 'W': case 'E': { - string arg = string(optarg); + string arg(optarg); if ((arg.size() > 3) && (strncmp(optarg, "no-", 3) == 0)) { arg = string(optarg+3); @@ -307,7 +311,7 @@ main(int argc, char **argv) } if (!(tree.is_valid() || keep_going)) { - fprintf(stderr, "Failed to parse tree. Unhappy face!\n"); + fprintf(stderr, "Failed to parse tree.\n"); return EXIT_FAILURE; } clock_t c2 = clock(); Modified: stable/11/usr.bin/dtc/fdt.cc ============================================================================== --- stable/11/usr.bin/dtc/fdt.cc Tue May 9 18:45:34 2017 (r318092) +++ stable/11/usr.bin/dtc/fdt.cc Tue May 9 18:46:49 2017 (r318093) @@ -36,6 +36,7 @@ #include "dtb.hh" #include +#include #include #include @@ -48,6 +49,8 @@ #include #include +using std::string; + namespace dtc { @@ -78,7 +81,7 @@ property_value::push_to_buffer(byte_buff } else { - string_data.push_to_buffer(buffer, true); + push_string(buffer, string_data, true); // Trailing nul buffer.push_back(0); } @@ -166,13 +169,23 @@ property_value::resolve_type() type = BINARY; } +size_t +property_value::size() +{ + if (!byte_data.empty()) + { + return byte_data.size(); + } + return string_data.size() + 1; +} + void property_value::write_as_string(FILE *file) { putc('"', file); if (byte_data.empty()) { - string_data.print(file); + fputs(string_data.c_str(), file); } else { @@ -240,31 +253,32 @@ property_value::write_as_bytes(FILE *fil } void -property::parse_string(input_buffer &input) +property::parse_string(text_input_buffer &input) { property_value v; - assert(input[0] == '"'); + assert(*input == '"'); ++input; - const char *start = (const char*)input; - int length = 0; - while (char c = input[0]) + std::vector bytes; + bool isEscaped = false; + while (char c = *input) { - if (c == '"' && input[-1] != '\\') + if (c == '"' && !isEscaped) { input.consume('"'); break; } + isEscaped = (c == '\\'); + bytes.push_back(c); ++input; - ++length; } - v.string_data = string(start, length); + v.string_data = string(bytes.begin(), bytes.end()); values.push_back(v); } void -property::parse_cells(input_buffer &input, int cell_size) +property::parse_cells(text_input_buffer &input, int cell_size) { - assert(input[0] == '<'); + assert(*input == '<'); ++input; property_value v; input.next_token(); @@ -282,9 +296,16 @@ property::parse_cells(input_buffer &inpu return; } input.next_token(); - // FIXME: We should support full paths here, but we - // don't. - string referenced = string::parse_node_name(input); + string referenced; + if (!input.consume('{')) + { + referenced = input.parse_node_name(); + } + else + { + referenced = input.parse_to('}'); + input.consume('}'); + } if (referenced.empty()) { input.parse_error("Expected node name"); @@ -343,9 +364,9 @@ property::parse_cells(input_buffer &inpu } void -property::parse_bytes(input_buffer &input) +property::parse_bytes(text_input_buffer &input) { - assert(input[0] == '['); + assert(*input == '['); ++input; property_value v; input.next_token(); @@ -370,13 +391,13 @@ property::parse_bytes(input_buffer &inpu } void -property::parse_reference(input_buffer &input) +property::parse_reference(text_input_buffer &input) { - assert(input[0] == '&'); + assert(*input == '&'); ++input; input.next_token(); property_value v; - v.string_data = string::parse_node_name(input); + v.string_data = input.parse_node_name(); if (v.string_data.empty()) { input.parse_error("Expected node name"); @@ -400,7 +421,7 @@ property::property(input_buffer &structs } // Find the name input_buffer name_buffer = strings.buffer_from_offset(name_offset); - if (name_buffer.empty()) + if (name_buffer.finished()) { fprintf(stderr, "Property name offset %" PRIu32 " is past the end of the strings table\n", @@ -408,7 +429,7 @@ property::property(input_buffer &structs valid = false; return; } - key = string(name_buffer); + key = name_buffer.parse_to(0); // If we're empty, do not push anything as value. if (!length) @@ -429,7 +450,7 @@ property::property(input_buffer &structs values.push_back(v); } -void property::parse_define(input_buffer &input, define_map *defines) +void property::parse_define(text_input_buffer &input, define_map *defines) { input.consume('$'); if (!defines) @@ -438,7 +459,7 @@ void property::parse_define(input_buffer valid = false; return; } - string name = string::parse_property_name(input); + string name = input.parse_property_name(); define_map::iterator found; if ((name == string()) || ((found = defines->find(name)) == defines->end())) @@ -450,15 +471,15 @@ void property::parse_define(input_buffer values.push_back((*found).second->values[0]); } -property::property(input_buffer &input, - string k, - string l, +property::property(text_input_buffer &input, + string &&k, + string_set &&l, bool semicolonTerminated, - define_map *defines) : key(k), label(l), valid(true) + define_map *defines) : key(k), labels(l), valid(true) { do { input.next_token(); - switch (input[0]) + switch (*input) { case '$': { @@ -487,7 +508,7 @@ property::property(input_buffer &input, } if (!valid) return; input.next_token(); - if (input[0] != '<') + if (*input != '<') { input.parse_error("/bits/ directive is only valid on arrays"); valid = false; @@ -534,10 +555,14 @@ property::parse_dtb(input_buffer &struct } property_ptr -property::parse(input_buffer &input, string key, string label, +property::parse(text_input_buffer &input, string &&key, string_set &&label, bool semicolonTerminated, define_map *defines) { - property_ptr p(new property(input, key, label, semicolonTerminated, defines)); + property_ptr p(new property(input, + std::move(key), + std::move(label), + semicolonTerminated, + defines)); if (!p->valid) { p = nullptr; @@ -596,14 +621,16 @@ property::write_dts(FILE *file, int inde { putc('\t', file); } - if (label != string()) +#ifdef PRINT_LABELS + for (auto &l : labels) { - label.print(file); + fputs(l.c_str(), file); fputs(": ", file); } +#endif if (key != string()) { - key.print(file); + fputs(key.c_str(), file); } if (!values.empty()) { @@ -636,8 +663,23 @@ property::write_dts(FILE *file, int inde fputs(";\n", file); } +size_t +property::offset_of_value(property_value &val) +{ + size_t off = 0; + for (auto &v : values) + { + if (&v == &val) + { + return off; + } + off += v.size(); + } + return -1; +} + string -node::parse_name(input_buffer &input, bool &is_property, const char *error) +node::parse_name(text_input_buffer &input, bool &is_property, const char *error) { if (!valid) { @@ -646,9 +688,9 @@ node::parse_name(input_buffer &input, bo input.next_token(); if (is_property) { - return string::parse_property_name(input); + return input.parse_property_name(); } - string n = string::parse_node_or_property_name(input, is_property); + string n = input.parse_node_or_property_name(is_property); if (n.empty()) { if (n.empty()) @@ -672,25 +714,23 @@ node::visit(std::function f node::node(input_buffer &structs, input_buffer &strings) : valid(true) { - const char *name_start = (const char*)structs; - int name_length = 0; + std::vector bytes; while (structs[0] != '\0' && structs[0] != '@') { - name_length++; + bytes.push_back(structs[0]); ++structs; } - name = string(name_start, name_length); + name = string(bytes.begin(), bytes.end()); + bytes.clear(); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***