Date: Fri, 7 Oct 2016 12:57:35 +0000 (UTC) From: Ed Maste <emaste@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r306806 - head/usr.bin/dtc Message-ID: <201610071257.u97CvZ3V029734@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: emaste Date: Fri Oct 7 12:57:35 2016 New Revision: 306806 URL: https://svnweb.freebsd.org/changeset/base/306806 Log: 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 Modified: head/usr.bin/dtc/checking.cc head/usr.bin/dtc/checking.hh head/usr.bin/dtc/dtb.cc head/usr.bin/dtc/dtb.hh head/usr.bin/dtc/dtc.1 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.cc head/usr.bin/dtc/util.hh Modified: head/usr.bin/dtc/checking.cc ============================================================================== --- head/usr.bin/dtc/checking.cc Fri Oct 7 11:50:59 2016 (r306805) +++ head/usr.bin/dtc/checking.cc Fri Oct 7 12:57:35 2016 (r306806) @@ -33,7 +33,7 @@ #include "checking.hh" #include <stdio.h> - +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. @@ -73,16 +97,16 @@ namespace } if (found_size && found_address) { - break; + break; } } if (!found_address) { - report_error("Missing #address-cells property"); + report_error("Missing #address-cells property"); } if (!found_size) { - report_error("Missing #size-cells property"); + report_error("Missing #size-cells property"); } return found_address && found_size; } @@ -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<property_value::value_type T> 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<T>(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: head/usr.bin/dtc/checking.hh ============================================================================== --- head/usr.bin/dtc/checking.hh Fri Oct 7 11:50:59 2016 (r306805) +++ head/usr.bin/dtc/checking.hh Fri Oct 7 12:57:35 2016 (r306806) @@ -32,7 +32,7 @@ #ifndef _CHECKING_HH_ #define _CHECKING_HH_ -#include "string.hh" +#include <string> #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 <property_value::EMPTY> : 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 <property_v template<> struct property_type_checker <property_value::STRING> : 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 <property_value::STRING_LIST> : 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 <property_v template<> struct property_type_checker <property_value::PHANDLE> : 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<string, checker*> checkers; + std::unordered_map<std::string, checker*> checkers; /** * The disabled checkers. Moving checkers to this list disables them, * but allows them to be easily moved back. */ - std::unordered_map<string, checker*> disabled_checkers; + std::unordered_map<std::string, checker*> disabled_checkers; /** * Helper function for adding a property value checker. */ template<property_value::value_type T> - 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: head/usr.bin/dtc/dtb.cc ============================================================================== --- head/usr.bin/dtc/dtb.cc Fri Oct 7 11:50:59 2016 (r306805) +++ head/usr.bin/dtc/dtb.cc Fri Oct 7 12:57:35 2016 (r306806) @@ -36,6 +36,7 @@ #include <stdio.h> #include <unistd.h> +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: head/usr.bin/dtc/dtb.hh ============================================================================== --- head/usr.bin/dtc/dtb.hh Fri Oct 7 11:50:59 2016 (r306805) +++ head/usr.bin/dtc/dtb.hh Fri Oct 7 12:57:35 2016 (r306806) @@ -33,10 +33,13 @@ #ifndef _DTB_HH_ #define _DTB_HH_ #include <map> -#include "string.hh" +#include <string> #include <assert.h> +#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,12 +189,12 @@ class binary_writer : public output_writ * The binary format does not support labels, so this method * does nothing. */ - virtual void write_label(string) {} + virtual void write_label(const std::string &) {} /** * Comments are ignored by the binary writer. */ - virtual void write_comment(string) {} - virtual void write_string(string name); + virtual void write_comment(const std::string&) {} + virtual void write_string(const std::string &name); virtual void write_data(uint8_t v); virtual void write_data(uint32_t v); virtual void write_data(uint64_t v); @@ -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); + /** * Writes the string, starting on a new line. */ void write_line(const char *c); @@ -239,9 +246,8 @@ 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_label(const std::string &name); + virtual void write_comment(const std::string &name); virtual void write_data(uint8_t v); virtual void write_data(uint32_t v); virtual void write_data(uint64_t v); @@ -328,14 +334,14 @@ class string_table { /** * Map from strings to their offset. */ - std::map<string, uint32_t> string_offsets; + std::map<std::string, uint32_t> 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<string> strings; + std::vector<std::string> 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: head/usr.bin/dtc/dtc.1 ============================================================================== --- head/usr.bin/dtc/dtc.1 Fri Oct 7 11:50:59 2016 (r306805) +++ head/usr.bin/dtc/dtc.1 Fri Oct 7 12:57:35 2016 (r306806) @@ -237,6 +237,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: head/usr.bin/dtc/dtc.cc ============================================================================== --- head/usr.bin/dtc/dtc.cc Fri Oct 7 11:50:59 2016 (r306805) +++ head/usr.bin/dtc/dtc.cc Fri Oct 7 12:57:35 2016 (r306806) @@ -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. @@ -58,7 +60,7 @@ int version_minor = 4; */ 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]" @@ -67,7 +69,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((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; @@ -115,12 +116,12 @@ main(int argc, char **argv) return EXIT_SUCCESS; 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 +134,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 +169,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 +181,7 @@ main(int argc, char **argv) { fclose(depfile); } - if (string(optarg) == string("-")) + if (string(optarg) == "-") { depfile = stdout; } @@ -197,16 +198,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 +230,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 +308,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: head/usr.bin/dtc/fdt.cc ============================================================================== --- head/usr.bin/dtc/fdt.cc Fri Oct 7 11:50:59 2016 (r306805) +++ head/usr.bin/dtc/fdt.cc Fri Oct 7 12:57:35 2016 (r306806) @@ -36,6 +36,7 @@ #include "dtb.hh" #include <algorithm> +#include <sstream> #include <ctype.h> #include <fcntl.h> @@ -48,6 +49,8 @@ #include <sys/stat.h> #include <errno.h> +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); } @@ -172,7 +175,7 @@ property_value::write_as_string(FILE *fi putc('"', file); if (byte_data.empty()) { - string_data.print(file); + fputs(string_data.c_str(), file); } else { @@ -240,31 +243,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<char> 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 +286,18 @@ 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); + bool isPath = false; + string referenced; + if (!input.consume('{')) + { + referenced = input.parse_node_name(); + } + else + { + referenced = input.parse_to('}'); + input.consume('}'); + isPath = true; + } if (referenced.empty()) { input.parse_error("Expected node name"); @@ -343,9 +356,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 +383,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 +413,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 +421,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 +442,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 +451,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 +463,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 +500,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 +547,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 +613,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()) { @@ -637,7 +656,7 @@ property::write_dts(FILE *file, int inde } 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 +665,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 +691,23 @@ node::visit(std::function<void(node&)> f node::node(input_buffer &structs, input_buffer &strings) : valid(true) { - const char *name_start = (const char*)structs; - int name_length = 0; + std::vector<char> 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(); if (structs[0] == '@') { ++structs; - name_start = (const char*)structs; - name_length = 0; while (structs[0] != '\0') { - name_length++; + bytes.push_back(structs[0]); ++structs; } - unit_address = string(name_start, name_length); + unit_address = string(bytes.begin(), bytes.end()); } ++structs; uint32_t token; @@ -747,8 +764,12 @@ node::node(input_buffer &structs, input_ return; } -node::node(input_buffer &input, string n, string l, string a, define_map *defines) : - label(l), name(n), unit_address(a), valid(true) +node::node(text_input_buffer &input, + string &&n, + std::unordered_set<string> &&l, + string &&a, + define_map *defines) + : labels(l), name(n), unit_address(a), valid(true) { if (!input.consume('{')) { @@ -760,15 +781,60 @@ node::node(input_buffer &input, string n // flag set if we find any characters that are only in // the property name character set, not the node bool is_property = false; - string child_name, child_label, child_address; + string child_name, child_address; + std::unordered_set<string> child_labels; + auto parse_delete = [&](const char *expected, bool at) + { + if (child_name == string()) + { + input.parse_error(expected); + valid = false; + return; + } + input.next_token(); + if (at && input.consume('@')) + { + child_name += '@'; + child_name += parse_name(input, is_property, "Expected unit address"); + } + if (!input.consume(';')) + { + input.parse_error("Expected semicolon"); + valid = false; + return; + } + input.next_token(); + }; + if (input.consume("/delete-node/")) + { + input.next_token(); + child_name = input.parse_node_name(); + parse_delete("Expected node name", true); + if (valid) + { + deleted_children.insert(child_name); + } + continue; + } *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201610071257.u97CvZ3V029734>