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.
This commit is contained in:
parent
170a938721
commit
a0706eb457
@ -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
|
||||
|
@ -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, node *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_tree *tree, node *n, property *p)
|
||||
}
|
||||
|
||||
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 *tree, bool keep_going)
|
||||
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 name)
|
||||
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));
|
||||
|
@ -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 property_checker
|
||||
*/
|
||||
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_value::EMPTY> : public property_checker
|
||||
{
|
||||
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_value::STRING> : public property_checker
|
||||
{
|
||||
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_value::STRING_LIST> :
|
||||
{
|
||||
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_value::PHANDLE> : public property_checker
|
||||
{
|
||||
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 property_checker
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
@ -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)
|
||||
{
|
||||
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"));
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -32,7 +32,10 @@
|
||||
|
||||
#ifndef _FDT_HH_
|
||||
#define _FDT_HH_
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "util.hh"
|
||||
#include "string.hh"
|
||||
@ -49,7 +52,19 @@ class string_table;
|
||||
namespace fdt
|
||||
{
|
||||
class property;
|
||||
typedef std::map<string, property*> define_map;
|
||||
class node;
|
||||
/**
|
||||
* Type for (owned) pointers to properties.
|
||||
*/
|
||||
typedef std::shared_ptr<property> property_ptr;
|
||||
/**
|
||||
* Owning pointer to a node.
|
||||
*/
|
||||
typedef std::unique_ptr<node> node_ptr;
|
||||
/**
|
||||
* Map from macros to property pointers.
|
||||
*/
|
||||
typedef std::unordered_map<string, property_ptr> define_map;
|
||||
/**
|
||||
* Properties may contain a number of different value, each with a different
|
||||
* label. This class encapsulates a single value.
|
||||
@ -186,6 +201,11 @@ struct property_value
|
||||
* - Otherwise, it is printed as a byte buffer.
|
||||
*/
|
||||
void write_dts(FILE *file);
|
||||
/**
|
||||
* Tries to merge adjacent property values, returns true if it succeeds and
|
||||
* false otherwise.
|
||||
*/
|
||||
bool try_to_merge(property_value &other);
|
||||
private:
|
||||
/**
|
||||
* Returns whether the value is of the specified type. If the type of
|
||||
@ -250,7 +270,7 @@ class property
|
||||
/**
|
||||
* Parses one or more 32-bit values enclosed in angle brackets.
|
||||
*/
|
||||
void parse_cells(input_buffer &input);
|
||||
void parse_cells(input_buffer &input, int cell_size);
|
||||
/**
|
||||
* Parses an array of bytes, contained within square brackets.
|
||||
*/
|
||||
@ -299,18 +319,18 @@ class property
|
||||
* property from the input, and returns it on success. On any parse
|
||||
* error, this will return 0.
|
||||
*/
|
||||
static property* parse_dtb(input_buffer &structs,
|
||||
static property_ptr parse_dtb(input_buffer &structs,
|
||||
input_buffer &strings);
|
||||
/**
|
||||
* Factory method for constructing a new property. Attempts to parse a
|
||||
* property from the input, and returns it on success. On any parse
|
||||
* error, this will return 0.
|
||||
*/
|
||||
static property* parse(input_buffer &input,
|
||||
string key,
|
||||
string label=string(),
|
||||
bool semicolonTerminated=true,
|
||||
define_map *defines=0);
|
||||
static property_ptr parse(input_buffer &input,
|
||||
string key,
|
||||
string label=string(),
|
||||
bool semicolonTerminated=true,
|
||||
define_map *defines=0);
|
||||
/**
|
||||
* Iterator type used for accessing the values of a property.
|
||||
*/
|
||||
@ -378,15 +398,19 @@ class node
|
||||
* name followed by an at symbol.
|
||||
*/
|
||||
string unit_address;
|
||||
/**
|
||||
* The type for the property vector.
|
||||
*/
|
||||
typedef std::vector<property_ptr> property_vector;
|
||||
private:
|
||||
/**
|
||||
* The properties contained within this node.
|
||||
*/
|
||||
std::vector<property*> properties;
|
||||
property_vector properties;
|
||||
/**
|
||||
* The children of this node.
|
||||
*/
|
||||
std::vector<node*> children;
|
||||
std::vector<node_ptr> children;
|
||||
/**
|
||||
* A flag indicating whether this node is valid. This is set to false
|
||||
* if an error occurs during parsing.
|
||||
@ -415,7 +439,7 @@ class node
|
||||
* Comparison function for properties, used when sorting the properties
|
||||
* vector. Orders the properties based on their names.
|
||||
*/
|
||||
static inline bool cmp_properties(property *p1, property *p2);
|
||||
static inline bool cmp_properties(property_ptr &p1, property_ptr &p2);
|
||||
/*
|
||||
{
|
||||
return p1->get_key() < p2->get_key();
|
||||
@ -426,16 +450,7 @@ class node
|
||||
* vector. Orders the nodes based on their names or, if the names are
|
||||
* the same, by the unit addresses.
|
||||
*/
|
||||
static inline bool cmp_children(node *c1, node *c2);
|
||||
/*
|
||||
{
|
||||
if (c1->name == c2->name)
|
||||
{
|
||||
return c1->unit_address < c2->unit_address;
|
||||
}
|
||||
return c1->name < c2->name;
|
||||
}
|
||||
*/
|
||||
static inline bool cmp_children(node_ptr &c1, node_ptr &c2);
|
||||
public:
|
||||
/**
|
||||
* Sorts the node's properties and children into alphabetical order and
|
||||
@ -445,7 +460,7 @@ class node
|
||||
/**
|
||||
* Iterator type for child nodes.
|
||||
*/
|
||||
typedef std::vector<node*>::iterator child_iterator;
|
||||
typedef std::vector<node_ptr>::iterator child_iterator;
|
||||
/**
|
||||
* Returns an iterator for the first child of this node.
|
||||
*/
|
||||
@ -460,21 +475,17 @@ class node
|
||||
{
|
||||
return children.end();
|
||||
}
|
||||
/**
|
||||
* Iterator type for properties of a node.
|
||||
*/
|
||||
typedef std::vector<property*>::iterator property_iterator;
|
||||
/**
|
||||
* Returns an iterator after the last property of this node.
|
||||
*/
|
||||
inline property_iterator property_begin()
|
||||
inline property_vector::iterator property_begin()
|
||||
{
|
||||
return properties.begin();
|
||||
}
|
||||
/**
|
||||
* Returns an iterator for the first property of this node.
|
||||
*/
|
||||
inline property_iterator property_end()
|
||||
inline property_vector::iterator property_end()
|
||||
{
|
||||
return properties.end();
|
||||
}
|
||||
@ -485,11 +496,11 @@ class node
|
||||
* cursor on the open brace of the property, after the name and so on
|
||||
* have been parsed.
|
||||
*/
|
||||
static node* parse(input_buffer &input,
|
||||
string name,
|
||||
string label=string(),
|
||||
string address=string(),
|
||||
define_map *defines=0);
|
||||
static node_ptr parse(input_buffer &input,
|
||||
string name,
|
||||
string label=string(),
|
||||
string address=string(),
|
||||
define_map *defines=0);
|
||||
/**
|
||||
* Factory method for constructing a new node. Attempts to parse a
|
||||
* node in DTB format from the input, and returns it on success. On
|
||||
@ -497,21 +508,16 @@ class node
|
||||
* cursor on the open brace of the property, after the name and so on
|
||||
* have been parsed.
|
||||
*/
|
||||
static node* parse_dtb(input_buffer &structs, input_buffer &strings);
|
||||
/**
|
||||
* Destroys the node, recursively deleting all of its properties and
|
||||
* children.
|
||||
*/
|
||||
~node();
|
||||
static node_ptr parse_dtb(input_buffer &structs, input_buffer &strings);
|
||||
/**
|
||||
* Returns a property corresponding to the specified key, or 0 if this
|
||||
* node does not contain a property of that name.
|
||||
*/
|
||||
property *get_property(string key);
|
||||
property_ptr get_property(string key);
|
||||
/**
|
||||
* Adds a new property to this node.
|
||||
*/
|
||||
inline void add_property(property *p)
|
||||
inline void add_property(property_ptr &p)
|
||||
{
|
||||
properties.push_back(p);
|
||||
}
|
||||
@ -519,7 +525,7 @@ class node
|
||||
* Merges a node into this one. Any properties present in both are
|
||||
* overridden, any properties present in only one are preserved.
|
||||
*/
|
||||
void merge_node(node *other);
|
||||
void merge_node(node_ptr other);
|
||||
/**
|
||||
* Write this node to the specified output. Although nodes do not
|
||||
* refer to a string table directly, their properties do. The string
|
||||
@ -584,18 +590,18 @@ class device_tree
|
||||
/**
|
||||
* Root node. All other nodes are children of this node.
|
||||
*/
|
||||
node *root;
|
||||
node_ptr root;
|
||||
/**
|
||||
* Mapping from names to nodes. Only unambiguous names are recorded,
|
||||
* duplicate names are stored as (node*)-1.
|
||||
*/
|
||||
std::map<string, node*> node_names;
|
||||
std::unordered_map<string, node*> node_names;
|
||||
/**
|
||||
* A map from labels to node paths. When resolving cross references,
|
||||
* we look up referenced nodes in this and replace the cross reference
|
||||
* with the full path to its target.
|
||||
*/
|
||||
std::map<string, node_path> node_paths;
|
||||
std::unordered_map<string, node_path> node_paths;
|
||||
/**
|
||||
* A collection of property values that are references to other nodes.
|
||||
* These should be expanded to the full path of their targets.
|
||||
@ -607,12 +613,16 @@ class device_tree
|
||||
* destination.
|
||||
*/
|
||||
std::vector<property_value*> phandles;
|
||||
/**
|
||||
* The names of nodes that target phandles.
|
||||
*/
|
||||
std::unordered_set<string> phandle_targets;
|
||||
/**
|
||||
* A collection of input buffers that we are using. These input
|
||||
* buffers are the ones that own their memory, and so we must preserve
|
||||
* them for the lifetime of the device tree.
|
||||
*/
|
||||
std::vector<input_buffer*> buffers;
|
||||
std::vector<std::unique_ptr<input_buffer>> buffers;
|
||||
/**
|
||||
* A map of used phandle values to nodes. All phandles must be unique,
|
||||
* so we keep a set of ones that the user explicitly provides in the
|
||||
@ -622,13 +632,13 @@ class device_tree
|
||||
* find phandles that were provided by the user explicitly when we are
|
||||
* doing checking.
|
||||
*/
|
||||
std::map<uint32_t, node*> used_phandles;
|
||||
std::unordered_map<uint32_t, node*> used_phandles;
|
||||
/**
|
||||
* Paths to search for include files. This contains a set of
|
||||
* nul-terminated strings, which are not owned by this class and so
|
||||
* must be freed separately.
|
||||
*/
|
||||
std::vector<const char*> include_paths;
|
||||
std::vector<std::string> include_paths;
|
||||
/**
|
||||
* Dictionary of predefined macros provided on the command line.
|
||||
*/
|
||||
@ -655,7 +665,13 @@ class device_tree
|
||||
* used in resolving cross references. Also collects phandle
|
||||
* properties that have been explicitly added.
|
||||
*/
|
||||
void collect_names_recursive(node* n, node_path &path);
|
||||
void collect_names_recursive(node_ptr &n, node_path &path);
|
||||
/**
|
||||
* Assign phandle properties to all nodes that have been referenced and
|
||||
* require one. This method will recursively visit the tree starting at
|
||||
* the node that it is passed.
|
||||
*/
|
||||
void assign_phandles(node_ptr &n, uint32_t &next);
|
||||
/**
|
||||
* Calls the recursive version of this method on every root node.
|
||||
*/
|
||||
@ -667,9 +683,16 @@ class device_tree
|
||||
*/
|
||||
void resolve_cross_references();
|
||||
/**
|
||||
* Parses root nodes from the top level of a dts file.
|
||||
* Parses a dts file in the given buffer and adds the roots to the parsed
|
||||
* set. The `read_header` argument indicates whether the header has
|
||||
* already been read. Some dts files place the header in an include,
|
||||
* rather than in the top-level file.
|
||||
*/
|
||||
void parse_roots(input_buffer &input, std::vector<node*> &roots);
|
||||
void parse_file(input_buffer &input,
|
||||
const std::string &dir,
|
||||
std::vector<node_ptr> &roots,
|
||||
FILE *depfile,
|
||||
bool &read_header);
|
||||
/**
|
||||
* Allocates a new mmap()'d input buffer for use in parsing. This
|
||||
* object then keeps a reference to it, ensuring that it is not
|
||||
@ -706,7 +729,7 @@ class device_tree
|
||||
/**
|
||||
* Default constructor. Creates a valid, but empty FDT.
|
||||
*/
|
||||
device_tree() : phandle_node_name(EPAPR), valid(true), root(0),
|
||||
device_tree() : phandle_node_name(EPAPR), valid(true),
|
||||
boot_cpu(0), spare_reserve_map_entries(0),
|
||||
minimum_blob_size(0), blob_padding(0) {}
|
||||
/**
|
||||
@ -719,10 +742,6 @@ class device_tree
|
||||
* a file that contains device tree source.
|
||||
*/
|
||||
void parse_dts(const char *fn, FILE *depfile);
|
||||
/**
|
||||
* Destroy the tree and any input buffers that it holds.
|
||||
*/
|
||||
~device_tree();
|
||||
/**
|
||||
* Returns whether this tree is valid.
|
||||
*/
|
||||
@ -741,7 +760,7 @@ class device_tree
|
||||
* Returns a pointer to the root node of this tree. No ownership
|
||||
* transfer.
|
||||
*/
|
||||
inline node *get_root() const
|
||||
inline const node_ptr &get_root() const
|
||||
{
|
||||
return root;
|
||||
}
|
||||
@ -767,7 +786,8 @@ class device_tree
|
||||
*/
|
||||
void add_include_path(const char *path)
|
||||
{
|
||||
include_paths.push_back(path);
|
||||
std::string p(path);
|
||||
include_paths.push_back(std::move(p));
|
||||
}
|
||||
/**
|
||||
* Sets the number of empty reserve map entries to add.
|
||||
|
@ -113,7 +113,7 @@ input_buffer::consume(const char *str)
|
||||
}
|
||||
|
||||
bool
|
||||
input_buffer::consume_integer(long long &outInt)
|
||||
input_buffer::consume_integer(unsigned long long &outInt)
|
||||
{
|
||||
// The first character must be a digit. Hex and octal strings
|
||||
// are prefixed by 0 and 0x, respectively.
|
||||
@ -122,7 +122,7 @@ input_buffer::consume_integer(long long &outInt)
|
||||
return false;
|
||||
}
|
||||
char *end=0;
|
||||
outInt = strtoll(&buffer[cursor], &end, 0);
|
||||
outInt = strtoull(&buffer[cursor], &end, 0);
|
||||
if (end == &buffer[cursor])
|
||||
{
|
||||
return false;
|
||||
@ -168,9 +168,8 @@ input_buffer::next_token()
|
||||
// Eat the /
|
||||
++(*this);
|
||||
}
|
||||
// Parse // comments and # comments
|
||||
if (((*this)[0] == '/' && (*this)[1] == '/') ||
|
||||
(*this)[0] == '#')
|
||||
// Parse // comments
|
||||
if (((*this)[0] == '/' && (*this)[1] == '/'))
|
||||
{
|
||||
// eat the start of the comment
|
||||
++(*this);
|
||||
@ -238,11 +237,12 @@ mmap_input_buffer::mmap_input_buffer(int fd) : input_buffer(0, 0)
|
||||
perror("Failed to stat file");
|
||||
}
|
||||
size = sb.st_size;
|
||||
buffer = (const char*)mmap(0, size, PROT_READ,
|
||||
MAP_PREFAULT_READ, fd, 0);
|
||||
if (buffer == 0)
|
||||
buffer = (const char*)mmap(0, size, PROT_READ, MAP_PRIVATE |
|
||||
MAP_PREFAULT_READ, fd, 0);
|
||||
if (buffer == MAP_FAILED)
|
||||
{
|
||||
perror("Failed to mmap file");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,6 +80,10 @@ class input_buffer
|
||||
*/
|
||||
void skip_spaces();
|
||||
public:
|
||||
/**
|
||||
* Return whether all input has been consumed.
|
||||
*/
|
||||
bool finished() { return cursor >= size; }
|
||||
/**
|
||||
* Virtual destructor. Does nothing, but exists so that subclasses
|
||||
* that own the memory can run cleanup code for deallocating it.
|
||||
@ -181,7 +185,7 @@ class input_buffer
|
||||
*
|
||||
* The parsed value is returned via the argument.
|
||||
*/
|
||||
bool consume_integer(long long &outInt);
|
||||
bool consume_integer(unsigned long long &outInt);
|
||||
/**
|
||||
* Template function that consumes a binary value in big-endian format
|
||||
* from the input stream. Returns true and advances the cursor if
|
||||
|
@ -33,6 +33,8 @@
|
||||
#ifndef _STRING_HH_
|
||||
#define _STRING_HH_
|
||||
#include "input_buffer.hh"
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
namespace dtc
|
||||
{
|
||||
@ -48,6 +50,7 @@ namespace dtc
|
||||
*/
|
||||
class string
|
||||
{
|
||||
friend std::hash<string>;
|
||||
/** Start address. Contained within the mmap()'d input file and not
|
||||
* owned by this object. */
|
||||
const char *start;
|
||||
@ -143,5 +146,19 @@ class string
|
||||
};
|
||||
|
||||
} // namespace dtc
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<dtc::string>
|
||||
{
|
||||
std::size_t operator()(dtc::string const& s) const
|
||||
{
|
||||
std::string str(s.start, s.length);
|
||||
std::hash<std::string> h;
|
||||
return h(str);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif // !_STRING_HH_
|
||||
|
Loading…
Reference in New Issue
Block a user