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 ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to