Author: theraven
Date: Sun Oct 25 14:52:16 2015
New Revision: 289935
URL: https://svnweb.freebsd.org/changeset/base/289935

Log:
  Lots of improvements to the BSD-licensed dtc
  
  - Various fixes to includes (including recursive includes)
  - Lots of testing that the output exactly matches GPL'd dtc
  - Lots of bug fixes to merging
  - Fix incorrect mmap usage
  - Ad-hoc memory management replaced with C++11 unique_ptr and similar
  
  Patrick Wildt has successfully run many (all?) of the GPL dtc test suite.

Modified:
  head/usr.bin/Makefile
  head/usr.bin/dtc/checking.cc
  head/usr.bin/dtc/checking.hh
  head/usr.bin/dtc/dtb.cc
  head/usr.bin/dtc/dtc.cc
  head/usr.bin/dtc/fdt.cc
  head/usr.bin/dtc/fdt.hh
  head/usr.bin/dtc/input_buffer.cc
  head/usr.bin/dtc/input_buffer.hh
  head/usr.bin/dtc/string.hh

Modified: head/usr.bin/Makefile
==============================================================================
--- head/usr.bin/Makefile       Sun Oct 25 14:42:56 2015        (r289934)
+++ head/usr.bin/Makefile       Sun Oct 25 14:52:16 2015        (r289935)
@@ -210,8 +210,10 @@ SUBDIR.${MK_GAMES}+=       pom
 SUBDIR.${MK_GAMES}+=   primes
 SUBDIR.${MK_GAMES}+=   random
 .if ${MK_GPL_DTC} != "yes"
+.if ${COMPILER_FEATURES:Mc++11}
 SUBDIR+=       dtc
 .endif
+.endif
 SUBDIR.${MK_GROFF}+=   vgrind
 SUBDIR.${MK_HESIOD}+=  hesinfo
 SUBDIR.${MK_ICONV}+=   iconv

Modified: head/usr.bin/dtc/checking.cc
==============================================================================
--- head/usr.bin/dtc/checking.cc        Sun Oct 25 14:42:56 2015        
(r289934)
+++ head/usr.bin/dtc/checking.cc        Sun Oct 25 14:52:16 2015        
(r289935)
@@ -51,7 +51,7 @@ namespace
        struct address_cells_checker : public checker
        {
                address_cells_checker(const char *name) : checker(name) {}
-               virtual bool check_node(device_tree *tree, node *n)
+               virtual bool check_node(device_tree *tree, const node_ptr &n)
                {
                        // If this has no children, it trivially meets the
                        // conditions.
@@ -61,8 +61,7 @@ namespace
                        }
                        bool found_address = false;
                        bool found_size = false;
-                       for (node::property_iterator i=n->property_begin(),
-                            e=n->property_end() ; i!=e ; ++i)
+                       for (auto i=n->property_begin(), e=n->property_end() ; 
i!=e ; ++i)
                        {
                                if (!found_address)
                                {
@@ -91,7 +90,7 @@ namespace
 } // anonymous namespace
 
 bool
-checker::visit_node(device_tree *tree, node *n)
+checker::visit_node(device_tree *tree, const node_ptr &n)
 {
        path.push_back(std::make_pair(n->name, n->unit_address));
        // Check this node
@@ -100,8 +99,7 @@ checker::visit_node(device_tree *tree, n
                return false;
        }
        // Now check its properties
-       for (node::property_iterator i=n->property_begin(), e=n->property_end()
-            ; i!=e ; ++i)
+       for (auto i=n->property_begin(), e=n->property_end() ; i!=e ; ++i)
        {
                if (!check_property(tree, n, *i))
                {
@@ -125,22 +123,21 @@ void
 checker::report_error(const char *errmsg)
 {
        fprintf(stderr, "Error: %s, while checking node: ", errmsg);
-       for (device_tree::node_path::iterator p=path.begin()+1, pe=path.end() ;
-            p!=pe ; ++p)
+       for (auto &p : path)
        {
                putc('/', stderr);
-               p->first.dump();
-               if (!(p->second.empty()))
+               p.first.dump();
+               if (!(p.second.empty()))
                {
                        putc('@', stderr);
-                       p->second.dump();
+                       p.second.dump();
                }
        }
        fprintf(stderr, " [-W%s]\n", checker_name);
 }
 
 bool
-property_checker::check_property(device_tree *tree, node *n, property *p)
+property_checker::check_property(device_tree *tree, const node_ptr &n, 
property_ptr p)
 {
        if (p->get_key() == key)
        {
@@ -154,7 +151,7 @@ property_checker::check_property(device_
 }
 
 bool
-property_size_checker::check(device_tree *tree, node *n, property *p)
+property_size_checker::check(device_tree *tree, const node_ptr &n, 
property_ptr p)
 {
        uint32_t psize = 0;
        for (property::value_iterator i=p->begin(),e=p->end() ; i!=e ; ++i)
@@ -216,10 +213,9 @@ bool
 check_manager::run_checks(device_tree *tree, bool keep_going)
 {
        bool success = true;
-       for (std::map<string, checker*>::iterator i=checkers.begin(),
-            e=checkers.end() ; i!=e ; ++i)
+       for (auto &i : checkers)
        {
-               success &= i->second->check_tree(tree);
+               success &= i.second->check_tree(tree);
                if (!(success || keep_going))
                {
                        break;
@@ -231,7 +227,7 @@ check_manager::run_checks(device_tree *t
 bool
 check_manager::disable_checker(string name)
 {
-       std::map<string, checker*>::iterator checker = checkers.find(name);
+       auto checker = checkers.find(name);
        if (checker != checkers.end())
        {
                disabled_checkers.insert(std::make_pair(name,
@@ -245,8 +241,7 @@ check_manager::disable_checker(string na
 bool
 check_manager::enable_checker(string name)
 {
-       std::map<string, checker*>::iterator checker =
-               disabled_checkers.find(name);
+       auto checker = disabled_checkers.find(name);
        if (checker != disabled_checkers.end())
        {
                checkers.insert(std::make_pair(name, checker->second));

Modified: head/usr.bin/dtc/checking.hh
==============================================================================
--- head/usr.bin/dtc/checking.hh        Sun Oct 25 14:42:56 2015        
(r289934)
+++ head/usr.bin/dtc/checking.hh        Sun Oct 25 14:52:16 2015        
(r289935)
@@ -65,7 +65,7 @@ class checker
         * Visits each node, calling the checker functions on properties and
         * nodes.
         */
-       bool visit_node(device_tree *tree, node *n);
+       bool visit_node(device_tree *tree, const node_ptr &n);
        protected:
        /**
         * Prints the error message, along with the path to the node that
@@ -86,7 +86,7 @@ class checker
         * Method for checking that a node is valid.  The root class version
         * does nothing, subclasses should override this.
         */
-       virtual bool check_node(device_tree *tree, node *n)
+       virtual bool check_node(device_tree *tree, const node_ptr &n)
        {
                return true;
        }
@@ -94,7 +94,7 @@ class checker
         * Method for checking that a property is valid.  The root class
         * version does nothing, subclasses should override this.
         */
-       virtual bool check_property(device_tree *tree, node *n, property *p)
+       virtual bool check_property(device_tree *tree, const node_ptr &n, 
property_ptr p)
        {
                return true;
        }
@@ -124,7 +124,7 @@ class property_checker : public checker
         * Implementation of the generic property-checking method that checks
         * for a property with the name specified in the constructor 
         */
-       virtual bool check_property(device_tree *tree, node *n, property *p);
+       virtual bool check_property(device_tree *tree, const node_ptr &n, 
property_ptr p);
        /**
         * Constructor.  Takes the name of the checker and the name of the
         * property to check.
@@ -134,7 +134,7 @@ class property_checker : public checker
        /**
         * The check method, which subclasses should implement.
         */
-       virtual bool check(device_tree *tree, node *n, property *p) = 0;
+       virtual bool check(device_tree *tree, const node_ptr &n, property_ptr 
p) = 0;
 };
 
 /**
@@ -149,7 +149,7 @@ struct property_type_checker : public pr
         */
        property_type_checker(const char* name, string property_name) : 
                property_checker(name, property_name) {}
-       virtual bool check(device_tree *tree, node *n, property *p) = 0;
+       virtual bool check(device_tree *tree, const node_ptr &n, property_ptr 
p) = 0;
 };
 
 /**
@@ -160,7 +160,7 @@ struct property_type_checker <property_v
 {
        property_type_checker(const char* name, string property_name) : 
                property_checker(name, property_name) {}
-       virtual bool check(device_tree *tree, node *n, property *p)
+       virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p)
        {
                return p->begin() == p->end();
        }
@@ -175,7 +175,7 @@ struct property_type_checker <property_v
 {
        property_type_checker(const char* name, string property_name) : 
                property_checker(name, property_name) {}
-       virtual bool check(device_tree *tree, node *n, property *p)
+       virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p)
        {
                return (p->begin() + 1 == p->end()) && p->begin()->is_string();
        }
@@ -190,7 +190,7 @@ struct property_type_checker <property_v
 {
        property_type_checker(const char* name, string property_name) : 
                property_checker(name, property_name) {}
-       virtual bool check(device_tree *tree, node *n, property *p)
+       virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p)
        {
                for (property::value_iterator i=p->begin(),e=p->end() ; i!=e ;
                     ++i)
@@ -213,7 +213,7 @@ struct property_type_checker <property_v
 {
        property_type_checker(const char* name, string property_name) : 
                property_checker(name, property_name) {}
-       virtual bool check(device_tree *tree, node *n, property *p)
+       virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p)
        {
                return (p->begin() + 1 == p->end()) && 
                        (tree->referenced_node(*p->begin()) != 0);
@@ -239,7 +239,7 @@ struct property_size_checker : public pr
        /**
         * Check, validates that the property has the correct size.
         */
-       virtual bool check(device_tree *tree, node *n, property *p);
+       virtual bool check(device_tree *tree, const node_ptr &n, property_ptr 
p);
 };
 
 
@@ -254,12 +254,12 @@ class check_manager
         * disabling checkers from the command line.  When this manager runs,
         * it will only run the checkers from this map.
         */
-       std::map<string, checker*> checkers;
+       std::unordered_map<string, checker*> checkers;
        /**
         * The disabled checkers.  Moving checkers to this list disables them,
         * but allows them to be easily moved back.
         */
-       std::map<string, checker*> disabled_checkers;
+       std::unordered_map<string, checker*> disabled_checkers;
        /**
         * Helper function for adding a property value checker.
         */

Modified: head/usr.bin/dtc/dtb.cc
==============================================================================
--- head/usr.bin/dtc/dtb.cc     Sun Oct 25 14:42:56 2015        (r289934)
+++ head/usr.bin/dtc/dtb.cc     Sun Oct 25 14:52:16 2015        (r289935)
@@ -44,9 +44,9 @@ namespace dtb
 
 void output_writer::write_data(byte_buffer b)
 {
-       for (byte_buffer::iterator i=b.begin(), e=b.end(); i!=e ; i++)
+       for (auto i : b)
        {
-               write_data(*i);
+               write_data(i);
        }
 }
 
@@ -277,7 +277,7 @@ header::read_dtb(input_buffer &input)
 uint32_t
 string_table::add_string(string str)
 {
-       std::map<string, uint32_t>::iterator old = string_offsets.find(str);
+       auto old = string_offsets.find(str);
        if (old == string_offsets.end())
        {
                uint32_t start = size;
@@ -298,10 +298,9 @@ string_table::write(dtb::output_writer &
 {
        writer.write_comment(string("Strings table."));
        writer.write_label(string("dt_strings_start"));
-       for (std::vector<string>::iterator i=strings.begin(), e=strings.end() ;
-            i!=e ; ++i)
+       for (auto &i : strings)
        {
-               writer.write_string(*i);
+               writer.write_string(i);
        }
        writer.write_label(string("dt_strings_end"));
 }

Modified: head/usr.bin/dtc/dtc.cc
==============================================================================
--- head/usr.bin/dtc/dtc.cc     Sun Oct 25 14:42:56 2015        (r289934)
+++ head/usr.bin/dtc/dtc.cc     Sun Oct 25 14:52:16 2015        (r289935)
@@ -67,7 +67,7 @@ static void usage(const char* argv0)
                        "[-O output_format]\n"
                "\t\t[-o output_file] [-R entries] [-S bytes] [-p bytes]"
                        "[-V blob_version]\n"
-               "\t\t-W [no-]checker_name] input_file\n", basename(argv0));
+               "\t\t-W [no-]checker_name] input_file\n", 
basename((char*)argv0));
 }
 
 /**

Modified: head/usr.bin/dtc/fdt.cc
==============================================================================
--- head/usr.bin/dtc/fdt.cc     Sun Oct 25 14:42:56 2015        (r289934)
+++ head/usr.bin/dtc/fdt.cc     Sun Oct 25 14:52:16 2015        (r289935)
@@ -33,8 +33,10 @@
 #define __STDC_LIMIT_MACROS 1
 
 #include "fdt.hh"
+#include "dtb.hh"
 
 #include <algorithm>
+
 #include <ctype.h>
 #include <fcntl.h>
 #include <inttypes.h>
@@ -44,7 +46,7 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include "dtb.hh"
+#include <errno.h>
 
 namespace dtc
 {
@@ -126,13 +128,25 @@ property_value::resolve_type()
                bool is_all_printable = true;
                int nuls = 0;
                int bytes = 0;
-               for (byte_buffer::iterator i=byte_data.begin(), 
e=byte_data.end()-1; i<e ; i++)
+               bool lastWasNull = false;
+               for (auto i : byte_data)
                {
                        bytes++;
-                       is_all_printable &= (*i == '\0') || isprint(*i);
-                       if (*i == '\0')
+                       is_all_printable &= (i == '\0') || isprint(i);
+                       if (i == '\0')
                        {
+                               // If there are two nulls in a row, then we're 
probably binary.
+                               if (lastWasNull)
+                               {
+                                       type = BINARY;
+                                       return;
+                               }
                                nuls++;
+                               lastWasNull = true;
+                       }
+                       else
+                       {
+                               lastWasNull = false;
                        }
                        if (!is_all_printable)
                        {
@@ -142,7 +156,7 @@ property_value::resolve_type()
                if ((is_all_printable && (bytes > nuls)) || bytes == 0)
                {
                        type = STRING;
-                       if (nuls > 0)
+                       if (nuls > 1)
                        {
                                type = STRING_LIST;
                        }
@@ -162,15 +176,25 @@ property_value::write_as_string(FILE *fi
        }
        else
        {
-               for (byte_buffer::iterator i=byte_data.begin(), 
e=byte_data.end()-1; i!=e ; ++i)
+               bool hasNull = (byte_data.back() == '\0');
+               // Remove trailing null bytes from the string before printing 
as dts.
+               if (hasNull)
+               {
+                       byte_data.pop_back();
+               }
+               for (auto i : byte_data)
                {
                        // FIXME Escape tabs, newlines, and so on.
-                       if (*i == '\0')
+                       if (i == '\0')
                        {
                                fputs("\", \"", file);
                                continue;
                        }
-                       putc(*i, file);
+                       putc(i, file);
+               }
+               if (hasNull)
+               {
+                       byte_data.push_back('\0');
                }
        }
        putc('"', file);
@@ -181,7 +205,7 @@ property_value::write_as_cells(FILE *fil
 {
        putc('<', file);
        assert((byte_data.size() % 4) == 0);
-       for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e 
; ++i)
+       for (auto i=byte_data.begin(), e=byte_data.end(); i!=e ; ++i)
        {
                uint32_t v = 0;
                v = (v << 8) | *i;
@@ -204,7 +228,7 @@ void
 property_value::write_as_bytes(FILE *file)
 {
        putc('[', file);
-       for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e 
; i++)
+       for (auto i=byte_data.begin(), e=byte_data.end(); i!=e ; i++)
        {
                fprintf(file, "%02hhx", *i);
                if (i+1 != e)
@@ -238,8 +262,26 @@ property::parse_string(input_buffer &inp
 }
 
 void
-property::parse_cells(input_buffer &input)
+property::parse_cells(input_buffer &input, int cell_size)
 {
+       unsigned long long cell_max;
+       switch (cell_size)
+       {
+               case 8:
+                       cell_max = UINT8_MAX;
+                       break;
+               case 16:
+                       cell_max = UINT16_MAX;
+                       break;
+               case 32:
+                       cell_max = UINT32_MAX;
+                       break;
+               case 64:
+                       cell_max = UINT64_MAX;
+                       break;
+               default:
+                       assert(0 && "Invalid cell size!");
+       }
        assert(input[0] == '<');
        ++input;
        property_value v;
@@ -251,6 +293,12 @@ property::parse_cells(input_buffer &inpu
                // referenced node
                if (input.consume('&'))
                {
+                       if (cell_size != 32)
+                       {
+                               input.parse_error("reference only permitted in 
32-bit arrays");
+                               valid = false;
+                               return;
+                       }
                        input.next_token();
                        // FIXME: We should support full paths here, but we
                        // don't.
@@ -278,20 +326,37 @@ property::parse_cells(input_buffer &inpu
                {
                        //FIXME: We should support labels in the middle
                        //of these, but we don't.
-                       long long val;
+                       unsigned long long val;
                        if (!input.consume_integer(val))
                        {
                                input.parse_error("Expected numbers in array of 
cells");
                                valid = false;
                                return;
                        }
-                       if ((val < 0) || (val > UINT32_MAX))
+                       if (val > cell_max)
                        {
+                               fprintf(stderr, "%lld > %lld\n", val, cell_max);
                                input.parse_error("Value out of range");
                                valid = false;
                                return;
                        }
-                       push_big_endian(v.byte_data, (uint32_t)val);
+                       switch (cell_size)
+                       {
+                               case 8:
+                                       v.byte_data.push_back(val);
+                                       break;
+                               case 16:
+                                       push_big_endian(v.byte_data, 
(uint16_t)val);
+                                       break;
+                               case 32:
+                                       push_big_endian(v.byte_data, 
(uint32_t)val);
+                                       break;
+                               case 64:
+                                       push_big_endian(v.byte_data, 
(uint64_t)val);
+                                       break;
+                               default:
+                                       assert(0 && "Invalid cell size!");
+                       }
                        input.next_token();
                }
        }
@@ -432,11 +497,35 @@ property::property(input_buffer &input,
                                input.parse_error("Invalid property value.");
                                valid = false;
                                return;
+                       case '/':
+                       {
+                               unsigned long long bits = 0;
+                               valid = input.consume("/bits/");
+                               input.next_token();
+                               valid &= input.consume_integer(bits);
+                               if ((bits != 8) &&
+                                   (bits != 16) &&
+                                   (bits != 32) &&
+                                   (bits != 64)) {
+                                       input.parse_error("Invalid size for 
elements");
+                                       valid = false;
+                               }
+                               if (!valid) return;
+                               input.next_token();
+                               if (input[0] != '<')
+                               {
+                                       input.parse_error("/bits/ directive is 
only valid on arrays");
+                                       valid = false;
+                                       return;
+                               }
+                               parse_cells(input, bits);
+                               break;
+                       }
                        case '"':
                                parse_string(input);
                                break;
                        case '<':
-                               parse_cells(input);
+                               parse_cells(input, 32);
                                break;
                        case '[':
                                parse_bytes(input);
@@ -458,27 +547,25 @@ property::property(input_buffer &input,
        }
 }
 
-property*
+property_ptr
 property::parse_dtb(input_buffer &structs, input_buffer &strings)
 {
-       property *p = new property(structs, strings);
+       property_ptr p(new property(structs, strings));
        if (!p->valid)
        {
-               delete p;
-               p = 0;
+               p = nullptr;
        }
        return p;
 }
 
-property*
+property_ptr
 property::parse(input_buffer &input, string key, string label,
                 bool semicolonTerminated, define_map *defines)
 {
-       property *p = new property(input, key, label, semicolonTerminated, 
defines);
+       property_ptr p(new property(input, key, label, semicolonTerminated, 
defines));
        if (!p->valid)
        {
-               delete p;
-               p = 0;
+               p = nullptr;
        }
        return p;
 }
@@ -498,6 +585,35 @@ property::write(dtb::output_writer &writ
        writer.write_data(value_buffer);
 }
 
+bool
+property_value::try_to_merge(property_value &other)
+{
+       resolve_type();
+       switch (type)
+       {
+               case UNKNOWN:
+                       __builtin_unreachable();
+                       assert(0);
+                       return false;
+               case EMPTY:
+                       *this = other;
+               case STRING:
+               case STRING_LIST:
+               case CROSS_REFERENCE:
+                       return false;
+               case PHANDLE:
+               case BINARY:
+                       if (other.type == PHANDLE || other.type == BINARY)
+                       {
+                               type = BINARY;
+                               byte_data.insert(byte_data.end(), 
other.byte_data.begin(),
+                                                other.byte_data.end());
+                               return true;
+                       }
+       }
+       return false;
+}
+
 void
 property::write_dts(FILE *file, int indent)
 {
@@ -516,8 +632,23 @@ property::write_dts(FILE *file, int inde
        }
        if (!values.empty())
        {
+               std::vector<property_value> *vals = &values;
+               std::vector<property_value> v;
+               // If we've got multiple values then try to merge them all 
together.
+               if (values.size() > 1)
+               {
+                       vals = &v;
+                       v.push_back(values.front());
+                       for (auto i=(++begin()), e=end() ; i!=e ; ++i)
+                       {
+                               if (!v.back().try_to_merge(*i))
+                               {
+                                       v.push_back(*i);
+                               }
+                       }
+               }
                fputs(" = ", file);
-               for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
+               for (auto i=vals->begin(), e=vals->end() ; i!=e ; ++i)
                {
                        i->write_dts(file);
                        if (i+1 != e)
@@ -590,13 +721,13 @@ node::node(input_buffer &structs, input_
                        // Child node, parse it.
                        case dtb::FDT_BEGIN_NODE:
                        {
-                               node *child = node::parse_dtb(structs, strings);
+                               node_ptr child = node::parse_dtb(structs, 
strings);
                                if (child == 0)
                                {
                                        valid = false;
                                        return;
                                }
-                               children.push_back(child);
+                               children.push_back(std::move(child));
                                break;
                        }
                        // End of this node, no errors.
@@ -605,7 +736,7 @@ node::node(input_buffer &structs, input_
                        // Property, parse it.
                        case dtb::FDT_PROP:
                        {
-                               property *prop = property::parse_dtb(structs, 
strings);
+                               property_ptr prop = 
property::parse_dtb(structs, strings);
                                if (prop == 0)
                                {
                                        valid = false;
@@ -667,7 +798,7 @@ node::node(input_buffer &input, string n
                // If we're parsing a property, then we must actually do that.
                if (input.consume('='))
                {
-                       property *p= property::parse(input, child_name,
+                       property_ptr p = property::parse(input, child_name,
                                        child_label, true, defines);
                        if (p == 0)
                        {
@@ -680,11 +811,11 @@ node::node(input_buffer &input, string n
                }
                else if (!is_property && input[0] == ('{'))
                {
-                       node *child = node::parse(input, child_name,
+                       node_ptr child = node::parse(input, child_name,
                                        child_label, child_address, defines);
                        if (child)
                        {
-                               children.push_back(child);
+                               children.push_back(std::move(child));
                        }
                        else
                        {
@@ -693,7 +824,7 @@ node::node(input_buffer &input, string n
                }
                else if (input.consume(';'))
                {
-                       properties.push_back(new property(child_name, 
child_label));
+                       properties.push_back(property_ptr(new 
property(child_name, child_label)));
                }
                else
                {
@@ -706,13 +837,13 @@ node::node(input_buffer &input, string n
 }
 
 bool
-node::cmp_properties(property *p1, property *p2)
+node::cmp_properties(property_ptr &p1, property_ptr &p2)
 {
        return p1->get_key() < p2->get_key();
 }
 
 bool
-node::cmp_children(node *c1, node *c2)
+node::cmp_children(node_ptr &c1, node_ptr &c2)
 {
        if (c1->name == c2->name)
        {
@@ -732,63 +863,47 @@ node::sort()
        }
 }
 
-node*
+node_ptr
 node::parse(input_buffer &input,
             string name,
             string label,
             string address,
             define_map *defines)
 {
-       node *n = new node(input, name, label, address, defines);
+       node_ptr n(new node(input, name, label, address, defines));
        if (!n->valid)
        {
-               delete n;
                n = 0;
        }
        return n;
 }
 
-node*
+node_ptr
 node::parse_dtb(input_buffer &structs, input_buffer &strings)
 {
-       node *n = new node(structs, strings);
+       node_ptr n(new node(structs, strings));
        if (!n->valid)
        {
-               delete n;
                n = 0;
        }
        return n;
 }
 
-node::~node()
-{
-       while (!children.empty())
-       {
-               delete children.back();
-               children.pop_back();
-       }
-       while (!properties.empty())
-       {
-               delete properties.back();
-               properties.pop_back();
-       }
-}
-
-property*
+property_ptr
 node::get_property(string key)
 {
-       for (property_iterator i=property_begin(), e=property_end() ; i!=e ; 
++i)
+       for (auto &i : properties)
        {
-               if ((*i)->get_key() == key)
+               if (i->get_key() == key)
                {
-                       return *i;
+                       return i;
                }
        }
        return 0;
 }
 
 void
-node::merge_node(node *other)
+node::merge_node(node_ptr other)
 {
        if (!other->label.empty())
        {
@@ -799,40 +914,39 @@ node::merge_node(node *other)
        // large numbers of properties, but for typical usage the
        // entire vector will fit (easily) into cache, so iterating
        // over it repeatedly isn't that expensive.
-       while (!other->properties.empty())
+       for (auto &p : other->properties)
        {
-               property *p = other->properties.front();
-               for (property_iterator i=property_begin(), e=property_end() ; 
i!=e ; ++i)
+               bool found = false;
+               for (auto i=property_begin(), e=property_end() ; i!=e ; ++i)
                {
                        if ((*i)->get_key() == p->get_key())
                        {
-                               delete *i;
-                               properties.erase(i);
+                               *i = p;
+                               found = true;
                                break;
                        }
                }
-               add_property(p);
-               other->properties.erase(other->properties.begin());
+               if (!found)
+               {
+                       add_property(p);
+               }
        }
-       while (!other->children.empty())
+       for (auto &c : other->children)
        {
-               node *c = other->children.front();
                bool found = false;
-               for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
+               for (auto &i : children)
                {
-                       if ((*i)->name == c->name && (*i)->unit_address == 
c->unit_address)
+                       if (i->name == c->name && i->unit_address == 
c->unit_address)
                        {
-                               (*i)->merge_node(c);
-                               delete c;
+                               i->merge_node(std::move(c));
                                found = true;
                                break;
                        }
                }
                if (!found)
                {
-                       children.push_back(c);
+                       children.push_back(std::move(c));
                }
-               other->children.erase(other->children.begin());
        }
 }
 
@@ -850,7 +964,7 @@ node::write(dtb::output_writer &writer, 
        writer.write_comment(name);
        writer.write_data(name_buffer);
        writer.write_data((uint8_t)0);
-       for (property_iterator i=property_begin(), e=property_end() ; i!=e ; 
++i)
+       for (auto i=property_begin(), e=property_end() ; i!=e ; ++i)
        {
                (*i)->write(writer, strings);
        }
@@ -868,11 +982,13 @@ node::write_dts(FILE *file, int indent)
        {
                putc('\t', file);
        }
+#ifdef PRINT_LABELS
        if (label != string())
        {
                label.print(file);
                fputs(": ", file);
        }
+#endif
        if (name != string())
        {
                name.print(file);
@@ -883,7 +999,7 @@ node::write_dts(FILE *file, int indent)
                unit_address.print(file);
        }
        fputs(" {\n\n", file);
-       for (property_iterator i=property_begin(), e=property_end() ; i!=e ; 
++i)
+       for (auto i=property_begin(), e=property_end() ; i!=e ; ++i)
        {
                (*i)->write_dts(file, indent+1);
        }
@@ -899,7 +1015,7 @@ node::write_dts(FILE *file, int indent)
 }
 
 void
-device_tree::collect_names_recursive(node* n, node_path &path)
+device_tree::collect_names_recursive(node_ptr &n, node_path &path)
 {
        string name = n->label;
        path.push_back(std::make_pair(n->name, n->unit_address));
@@ -907,13 +1023,13 @@ device_tree::collect_names_recursive(nod
        {
                if (node_names.find(name) == node_names.end())
                {
-                       node_names.insert(std::make_pair(name, n));
+                       node_names.insert(std::make_pair(name, n.get()));
                        node_paths.insert(std::make_pair(name, path));
                }
                else
                {
                        node_names[name] = (node*)-1;
-                       std::map<string, node_path>::iterator i = 
node_paths.find(name);
+                       auto i = node_paths.find(name);
                        if (i != node_paths.end())
                        {
                                node_paths.erase(name);
@@ -930,7 +1046,7 @@ device_tree::collect_names_recursive(nod
        path.pop_back();
        // Now we collect the phandles and properties that reference
        // other nodes.
-       for (node::property_iterator i=n->property_begin(), e=n->property_end() 
; i!=e ; ++i)
+       for (auto i=n->property_begin(), e=n->property_end() ; i!=e ; ++i)
        {
                for (property::value_iterator p=(*i)->begin(),pe=(*i)->end() ; 
p!=pe ; ++p)
                {
@@ -956,7 +1072,7 @@ device_tree::collect_names_recursive(nod
                        else
                        {
                                uint32_t phandle = 
(*i)->begin()->get_as_uint32();
-                               used_phandles.insert(std::make_pair(phandle, 
n));
+                               used_phandles.insert(std::make_pair(phandle, 
n.get()));
                        }
                }
        }
@@ -966,18 +1082,21 @@ void
 device_tree::collect_names()
 {
        node_path p;
+       node_names.clear();
+       node_paths.clear();
+       cross_references.clear();
+       phandles.clear();
        collect_names_recursive(root, p);
 }
 
 void
 device_tree::resolve_cross_references()
 {
-       for (std::vector<property_value*>::iterator i=cross_references.begin(), 
e=cross_references.end() ; i!=e ; ++i)
+       for (auto *pv : cross_references)
        {
-               property_value* pv = *i;
                node_path path = node_paths[pv->string_data];
                // Skip the first name in the path.  It's always "", and 
implicitly /
-               for (node_path::iterator p=path.begin()+1, pe=path.end() ; 
p!=pe ; ++p)
+               for (auto p=path.begin()+1, pe=path.end() ; p!=pe ; ++p)
                {
                        pv->byte_data.push_back('/');
                        p->first.push_to_buffer(pv->byte_data);
@@ -987,23 +1106,22 @@ device_tree::resolve_cross_references()
                                p->second.push_to_buffer(pv->byte_data);
                        }
                }
-               pv->byte_data.push_back(0);
        }
        uint32_t phandle = 1;
-       for (std::vector<property_value*>::iterator i=phandles.begin(), 
e=phandles.end() ; i!=e ; ++i)
+       for (auto &i : phandles)
        {
-               string target_name = (*i)->string_data;
+               string target_name = i->string_data;
                node *target = node_names[target_name];
                if (target == 0)
                {
-                       fprintf(stderr, "Failed to find node with label:");
+                       fprintf(stderr, "Failed to find node with label: ");
                        target_name.dump();
                        fprintf(stderr, "\n");
                        valid = 0;
                        return;
                }
                // If there is an existing phandle, use it
-               property *p = target->get_property("phandle");
+               property_ptr p = target->get_property("phandle");
                if (p == 0)
                {
                        p = target->get_property("linux,phandle");
@@ -1029,33 +1147,140 @@ device_tree::resolve_cross_references()
                        push_big_endian(v.byte_data, phandle++);
                        if (phandle_node_name == BOTH || phandle_node_name == 
LINUX)
                        {
-                               p = new property(string("linux,phandle"));
+                               p.reset(new property(string("linux,phandle")));
                                p->add_value(v);
                                target->add_property(p);
                        }
                        if (phandle_node_name == BOTH || phandle_node_name == 
EPAPR)
                        {
-                               p = new property(string("phandle"));
+                               p.reset(new property(string("phandle")));
                                p->add_value(v);
                                target->add_property(p);
                        }
                }
-               p->begin()->push_to_buffer((*i)->byte_data);
-               assert((*i)->byte_data.size() == 4);
+               p->begin()->push_to_buffer(i->byte_data);
+               assert(i->byte_data.size() == 4);
        }
 }
 
 void
-device_tree::parse_roots(input_buffer &input, std::vector<node*> &roots)
+device_tree::parse_file(input_buffer &input,
+                        const std::string &dir,
+                        std::vector<node_ptr> &roots,
+                        FILE *depfile,
+                        bool &read_header)
 {
        input.next_token();
-       while (valid && input.consume('/'))
+       // Read the header
+       if (input.consume("/dts-v1/;"))
+       {
+               read_header = true;
+       }
+       input.next_token();
+       while(input.consume("/include/"))
+       {
+               bool reallyInclude = true;
+               if (input.consume("if "))
+               {
+                       input.next_token();
+                       string name = string::parse_property_name(input);
+                       // XXX: Error handling
+                       if (defines.find(name) == defines.end())
+                       {
+                               reallyInclude = false;
+                       }
+                       input.consume('/');
+               }
+               input.next_token();
+               if (!input.consume('"'))
+               {
+                       input.parse_error("Expected quoted filename");
+                       valid = false;
+                       return;
+               }
+               int length = 0;
+               while (input[length] != '"') length++;
+
+               std::string file((const char*)input, length);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
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