> Author: kevans
> Date: Thu Apr  4 17:26:35 2019
> New Revision: 345880
> URL: https://svnweb.freebsd.org/changeset/base/345880
> 
> Log:
>   dtc(1): Update to 1a79f5f26631

Is there someway to update the quality of this pointer?
When googled it tends to loop back to FreeBSD.org stuff.

Thanks,
Rod

>   Highlights:
>   - Bugfix for order in which /delete-node/ and /delete-property/ are
>     processed [0]
>   - /omit-if-no-ref/ support has been added (used only by U-Boot at this
>     point, in theory)
>   - GPL dtc compat version bumped to 1.4.7
>   - Various small fixes and compatibility improvements
> 
> Modified:
>   stable/12/usr.bin/dtc/dtb.cc
>   stable/12/usr.bin/dtc/dtb.hh
>   stable/12/usr.bin/dtc/dtc.1
>   stable/12/usr.bin/dtc/dtc.cc
>   stable/12/usr.bin/dtc/fdt.cc
>   stable/12/usr.bin/dtc/fdt.hh
>   stable/12/usr.bin/dtc/input_buffer.cc
>   stable/12/usr.bin/dtc/util.hh
> Directory Properties:
>   stable/12/   (props changed)
> 
> Modified: stable/12/usr.bin/dtc/dtb.cc
> ==============================================================================
> --- stable/12/usr.bin/dtc/dtb.cc      Thu Apr  4 17:24:57 2019        
> (r345879)
> +++ stable/12/usr.bin/dtc/dtb.cc      Thu Apr  4 17:26:35 2019        
> (r345880)
> @@ -37,9 +37,33 @@
>  #include <inttypes.h>
>  #include <stdio.h>
>  #include <unistd.h>
> +#include <errno.h>
>  
>  using std::string;
>  
> +namespace {
> +
> +void write(dtc::byte_buffer &buffer, int fd)
> +{
> +     size_t size = buffer.size();
> +     uint8_t *data = buffer.data();
> +     while (size > 0)
> +     {
> +             ssize_t r = ::write(fd, data, size);
> +             if (r >= 0)
> +             {
> +                     data += r;
> +                     size -= r;
> +             }
> +             else if (errno != EAGAIN)
> +             {
> +                     fprintf(stderr, "Writing to file failed\n");
> +                     exit(-1);
> +             }
> +     }
> +}
> +}
> +
>  namespace dtc
>  {
>  namespace dtb
> @@ -90,8 +114,7 @@ binary_writer::write_data(uint64_t v)
>  void
>  binary_writer::write_to_file(int fd)
>  {
> -     // FIXME: Check return
> -     write(fd, buffer.data(), buffer.size());
> +     write(buffer, fd);
>  }
>  
>  uint32_t
> @@ -222,8 +245,7 @@ asm_writer::write_data(uint64_t v)
>  void
>  asm_writer::write_to_file(int fd)
>  {
> -     // FIXME: Check return
> -     write(fd, buffer.data(), buffer.size());
> +     write(buffer, fd);
>  }
>  
>  uint32_t
> 
> Modified: stable/12/usr.bin/dtc/dtb.hh
> ==============================================================================
> --- stable/12/usr.bin/dtc/dtb.hh      Thu Apr  4 17:24:57 2019        
> (r345879)
> +++ stable/12/usr.bin/dtc/dtb.hh      Thu Apr  4 17:26:35 2019        
> (r345880)
> @@ -109,6 +109,8 @@ inline const char *token_type_name(token_type t)
>                       return "FDT_END";
>       }
>       assert(0);
> +     // Not reached.
> +     return nullptr;
>  }
>  
>  /**
> 
> Modified: stable/12/usr.bin/dtc/dtc.1
> ==============================================================================
> --- stable/12/usr.bin/dtc/dtc.1       Thu Apr  4 17:24:57 2019        
> (r345879)
> +++ stable/12/usr.bin/dtc/dtc.1       Thu Apr  4 17:26:35 2019        
> (r345880)
> @@ -30,7 +30,7 @@
>  .\"
>  .\" $FreeBSD$
>  .\"/
> -.Dd April 7, 2018
> +.Dd March 27, 2019
>  .Dt DTC 1
>  .Os
>  .Sh NAME
> @@ -304,7 +304,18 @@ Overlay blobs can be applied at boot time by setting
>  in
>  .Xr loader.conf 5 .
>  Multiple overlays may be specified, and they will be applied in the order 
> given.
> -.El
> +.Sh NODE OMISSION
> +This utility supports the
> +.Va /omit-if-no-ref/
> +statement to mark nodes for omission if they are ultimately not referenced
> +elsewhere in the device tree.
> +This may be used in more space-constrained environments to remove nodes that 
> may
> +not be applicable to the specific device the tree is being compiled for.
> +.Pp
> +When the
> +.Fl @
> +flag is used to write symbols, nodes with labels will be considered 
> referenced
> +and will not be removed from the tree.
>  .Sh EXAMPLES
>  The command:
>  .Pp
> @@ -403,7 +414,11 @@ A dtc tool first appeared in
>  This version of the tool first appeared in
>  .Fx 10.0 .
>  .Sh AUTHORS
> -.An David T. Chisnall
> +.Nm
> +was written by
> +.An David T. Chisnall .
> +Some features were added later by
> +.An Kyle Evans .
>  .Pp
>  Note: The fact that the tool and the author share the same initials is 
> entirely
>  coincidental.
> 
> Modified: stable/12/usr.bin/dtc/dtc.cc
> ==============================================================================
> --- stable/12/usr.bin/dtc/dtc.cc      Thu Apr  4 17:24:57 2019        
> (r345879)
> +++ stable/12/usr.bin/dtc/dtc.cc      Thu Apr  4 17:26:35 2019        
> (r345880)
> @@ -38,6 +38,7 @@
>  #include <limits.h>
>  #include <stdio.h>
>  #include <stdlib.h>
> +#include <string.h>
>  #include <time.h>
>  #include <unistd.h>
>  
> @@ -65,7 +66,7 @@ int version_minor_compatible = 4;
>   * The current patch level of the tool.
>   */
>  int version_patch = 0;
> -int version_patch_compatible = 0;
> +int version_patch_compatible = 7;
>  
>  void usage(const string &argv0)
>  {
> @@ -105,7 +106,7 @@ main(int argc, char **argv)
>       bool debug_mode = false;
>       auto write_fn = &device_tree::write_binary;
>       auto read_fn = &device_tree::parse_dts;
> -     uint32_t boot_cpu;
> +     uint32_t boot_cpu = 0;
>       bool boot_cpu_specified = false;
>       bool keep_going = false;
>       bool sort = false;
> 
> Modified: stable/12/usr.bin/dtc/fdt.cc
> ==============================================================================
> --- stable/12/usr.bin/dtc/fdt.cc      Thu Apr  4 17:24:57 2019        
> (r345879)
> +++ stable/12/usr.bin/dtc/fdt.cc      Thu Apr  4 17:26:35 2019        
> (r345880)
> @@ -46,6 +46,7 @@
>  #include <libgen.h>
>  #include <stdio.h>
>  #include <stdlib.h>
> +#include <string.h>
>  #include <unistd.h>
>  #include <sys/types.h>
>  #include <sys/stat.h>
> @@ -491,6 +492,7 @@ property::property(text_input_buffer &input,
>                                       break;
>                               }
>                       }
> +                     [[fallthrough]];
>                       default:
>                               input.parse_error("Invalid property value.");
>                               valid = false;
> @@ -622,6 +624,7 @@ property_value::try_to_merge(property_value &other)
>                       return false;
>               case EMPTY:
>                       *this = other;
> +                     [[fallthrough]];
>               case STRING:
>               case STRING_LIST:
>               case CROSS_REFERENCE:
> @@ -846,6 +849,7 @@ node_ptr node::create_special_node(const string &name,
>  }
>  
>  node::node(text_input_buffer &input,
> +           device_tree &tree,
>             string &&n,
>             std::unordered_set<string> &&l,
>             string &&a,
> @@ -862,6 +866,9 @@ node::node(text_input_buffer &input,
>               // flag set if we find any characters that are only in
>               // the property name character set, not the node 
>               bool is_property = false;
> +             // flag set if our node is marked as /omit-if-no-ref/ to be
> +             // garbage collected later if nothing references it
> +             bool marked_omit_if_no_ref = false;
>               string child_name, child_address;
>               std::unordered_set<string> child_labels;
>               auto parse_delete = [&](const char *expected, bool at)
> @@ -908,6 +915,12 @@ node::node(text_input_buffer &input,
>                       }
>                       continue;
>               }
> +             if (input.consume("/omit-if-no-ref/"))
> +             {
> +                     input.next_token();
> +                     marked_omit_if_no_ref = true;
> +                     tree.set_needs_garbage_collection();
> +             }
>               child_name = parse_name(input, is_property,
>                               "Expected property or node name");
>               while (input.consume(':'))
> @@ -943,10 +956,11 @@ node::node(text_input_buffer &input,
>               }
>               else if (!is_property && *input == ('{'))
>               {
> -                     node_ptr child = node::parse(input, 
> std::move(child_name),
> +                     node_ptr child = node::parse(input, tree, 
> std::move(child_name),
>                                       std::move(child_labels), 
> std::move(child_address), defines);
>                       if (child)
>                       {
> +                             child->omit_if_no_ref = marked_omit_if_no_ref;
>                               children.push_back(std::move(child));
>                       }
>                       else
> @@ -998,12 +1012,14 @@ node::sort()
>  
>  node_ptr
>  node::parse(text_input_buffer &input,
> +            device_tree &tree,
>              string &&name,
>              string_set &&label,
>              string &&address,
>              define_map *defines)
>  {
>       node_ptr n(new node(input,
> +                         tree,
>                           std::move(name),
>                           std::move(label),
>                           std::move(address),
> @@ -1046,6 +1062,30 @@ node::merge_node(node_ptr &other)
>       {
>               labels.insert(l);
>       }
> +     children.erase(std::remove_if(children.begin(), children.end(),
> +                     [&](const node_ptr &p) {
> +                             string full_name = p->name;
> +                             if (p->unit_address != string())
> +                             {
> +                                     full_name += '@';
> +                                     full_name += p->unit_address;
> +                             }
> +                             if (other->deleted_children.count(full_name) > 
> 0)
> +                             {
> +                                     
> other->deleted_children.erase(full_name);
> +                                     return true;
> +                             }
> +                             return false;
> +                     }), children.end());
> +     props.erase(std::remove_if(props.begin(), props.end(),
> +                     [&](const property_ptr &p) {
> +                             if (other->deleted_props.count(p->get_key()) > 
> 0)
> +                             {
> +                                     
> other->deleted_props.erase(p->get_key());
> +                                     return true;
> +                             }
> +                             return false;
> +                     }), props.end());
>       // Note: this is an O(n*m) operation.  It might be sensible to
>       // optimise this if we find that there are nodes with very
>       // large numbers of properties, but for typical usage the
> @@ -1085,30 +1125,6 @@ node::merge_node(node_ptr &other)
>                       children.push_back(std::move(c));
>               }
>       }
> -     children.erase(std::remove_if(children.begin(), children.end(),
> -                     [&](const node_ptr &p) {
> -                             string full_name = p->name;
> -                             if (p->unit_address != string())
> -                             {
> -                                     full_name += '@';
> -                                     full_name += p->unit_address;
> -                             }
> -                             if (other->deleted_children.count(full_name) > 
> 0)
> -                             {
> -                                     
> other->deleted_children.erase(full_name);
> -                                     return true;
> -                             }
> -                             return false;
> -                     }), children.end());
> -     props.erase(std::remove_if(props.begin(), props.end(),
> -                     [&](const property_ptr &p) {
> -                             if (other->deleted_props.count(p->get_key()) > 
> 0)
> -                             {
> -                                     
> other->deleted_props.erase(p->get_key());
> -                                     return true;
> -                             }
> -                             return false;
> -                     }), props.end());
>  }
>  
>  void
> @@ -1187,6 +1203,7 @@ device_tree::collect_names_recursive(node_ptr &n, node
>                       {
>                               node_names.insert(std::make_pair(name, 
> n.get()));
>                               node_paths.insert(std::make_pair(name, path));
> +                             ordered_node_paths.push_back({name, path});
>                       }
>                       else
>                       {
> @@ -1243,6 +1260,7 @@ device_tree::collect_names()
>       node_path p;
>       node_names.clear();
>       node_paths.clear();
> +     ordered_node_paths.clear();
>       cross_references.clear();
>       fixups.clear();
>       collect_names_recursive(root, p);
> @@ -1353,7 +1371,6 @@ device_tree::resolve_cross_references(uint32_t &phandl
>               return node::VISIT_RECURSE;
>       }, nullptr);
>       assert(sorted_phandles.size() == fixups.size());
> -
>       for (auto &i : sorted_phandles)
>       {
>               string target_name = i.get().val.string_data;
> @@ -1441,7 +1458,104 @@ device_tree::resolve_cross_references(uint32_t &phandl
>       }
>  }
>  
> +bool
> +device_tree::garbage_collect_marked_nodes()
> +{
> +     std::unordered_set<node*> previously_referenced_nodes;
> +     std::unordered_set<node*> newly_referenced_nodes;
>  
> +     auto mark_referenced_nodes_used = [&](node &n)
> +     {
> +             for (auto &p : n.properties())
> +             {
> +                     for (auto &v : *p)
> +                     {
> +                             if (v.is_phandle())
> +                             {
> +                                     node *nx = node_names[v.string_data];
> +                                     if (nx == nullptr)
> +                                     {
> +                                             // Try it again, but as a path
> +                                             for (auto &s : node_paths)
> +                                             {
> +                                                     if (v.string_data == 
> s.second.to_string())
> +                                                     {
> +                                                             nx = 
> node_names[s.first];
> +                                                             break;
> +                                                     }
> +                                             }
> +                                     }
> +                                     if (nx == nullptr)
> +                                     {
> +                                             // Couldn't resolve this one?
> +                                             continue;
> +                                     }
> +                                     // Only mark those currently unmarked
> +                                     if (!nx->used)
> +                                     {
> +                                                     nx->used = 1;
> +                                                     
> newly_referenced_nodes.insert(nx);
> +                                     }
> +                             }
> +                     }
> +             }
> +     };
> +
> +     // Seed our referenced nodes with those that have been seen by a node 
> that
> +     // either will not be omitted if it's unreferenced or has a symbol.
> +     // Nodes with symbols are explicitly not garbage collected because they 
> may
> +     // be expected for referencing by an overlay, and we do not want 
> surprises
> +     // there.
> +     root->visit([&](node &n, node *) {
> +             if (!n.omit_if_no_ref || (write_symbols && !n.labels.empty()))
> +             {
> +                     mark_referenced_nodes_used(n);
> +             }
> +             // Recurse as normal
> +             return node::VISIT_RECURSE;
> +     }, nullptr);
> +
> +     while (!newly_referenced_nodes.empty())
> +     {
> +                     previously_referenced_nodes = 
> std::move(newly_referenced_nodes);
> +                     for (auto *n : previously_referenced_nodes)
> +                     {
> +                             mark_referenced_nodes_used(*n);
> +                     }
> +     }
> +
> +     previously_referenced_nodes.clear();
> +     bool children_deleted = false;
> +
> +     // Delete
> +     root->visit([&](node &n, node *) {
> +             bool gc_children = false;
> +
> +             for (auto &cn : n.child_nodes())
> +             {
> +                             if (cn->omit_if_no_ref && !cn->used)
> +                             {
> +                                     gc_children = true;
> +                                     break;
> +                             }
> +             }
> +
> +             if (gc_children)
> +             {
> +                     children_deleted = true;
> +                     n.delete_children_if([](node_ptr &nx) {
> +                             return (nx->omit_if_no_ref && !nx->used);
> +                     });
> +
> +                     return node::VISIT_CONTINUE;
> +             }
> +
> +             return node::VISIT_RECURSE;
> +     }, nullptr);
> +
> +     return children_deleted;
> +}
> +
>  void
>  device_tree::parse_file(text_input_buffer &input,
>                          std::vector<node_ptr> &roots,
> @@ -1486,7 +1600,7 @@ device_tree::parse_file(text_input_buffer &input,
>               if (input.consume('/'))
>               {
>                       input.next_token();
> -                     n = node::parse(input, string(), string_set(), 
> string(), &defines);
> +                     n = node::parse(input, *this, string(), string_set(), 
> string(), &defines);
>               }
>               else if (input.consume('&'))
>               {
> @@ -1507,7 +1621,7 @@ device_tree::parse_file(text_input_buffer &input,
>                               name = input.parse_node_name();
>                       }
>                       input.next_token();
> -                     n = node::parse(input, std::move(name), string_set(), 
> string(), &defines);
> +                     n = node::parse(input, *this, std::move(name), 
> string_set(), string(), &defines);
>                       n->name_is_path_reference = name_is_path_reference;
>               }
>               else
> @@ -1890,6 +2004,12 @@ device_tree::parse_dts(const string &fn, FILE *depfile
>               }
>       }
>       collect_names();
> +     // Return value indicates whether we've dirtied the tree or not and 
> need to
> +     // recollect names
> +     if (garbage_collect && garbage_collect_marked_nodes())
> +     {
> +             collect_names();
> +     }
>       uint32_t phandle = 1;
>       // If we're writing symbols, go ahead and assign phandles to the entire
>       // tree. We'll do this before we resolve cross references, just to keep
> @@ -1906,8 +2026,14 @@ device_tree::parse_dts(const string &fn, FILE *depfile
>               // referenced by other plugins, so we create a __symbols__ node 
> inside
>               // the root that contains mappings (properties) from label 
> names to
>               // paths.
> -             for (auto &s : node_paths)
> +             for (auto i=ordered_node_paths.rbegin(), 
> e=ordered_node_paths.rend() ; i!=e ; ++i)
>               {
> +                     auto &s = *i;
> +                     if (node_paths.find(s.first) == node_paths.end())
> +                     {
> +                             // Erased node, skip it.
> +                             continue;
> +                     }
>                       property_value v;
>                       v.string_data = s.second.to_string();
>                       v.type = property_value::STRING;
> @@ -1986,19 +2112,23 @@ device_tree::parse_dts(const string &fn, FILE *depfile
>                               {
>                                       if (c->name == p.first)
>                                       {
> -                                             string path = p.first;
> -                                             if (!(p.second.empty()))
> +                                             if (c->unit_address == p.second)
>                                               {
> -                                                     path += '@';
> -                                                     path += p.second;
> +                                                     n = c.get();
> +                                                     found = true;
> +                                                     break;
>                                               }
> -                                             
> n->add_child(node::create_special_node(path, symbols));
> -                                             n = (--n->child_end())->get();
>                                       }
>                               }
>                               if (!found)
>                               {
> -                                     
> n->add_child(node::create_special_node(p.first, symbols));
> +                                     string path = p.first;
> +                                     if (!(p.second.empty()))
> +                                     {
> +                                             path += '@';
> +                                             path += p.second;
> +                                     }
> +                                     
> n->add_child(node::create_special_node(path, symbols));
>                                       n = (--n->child_end())->get();
>                               }
>                       }
> 
> Modified: stable/12/usr.bin/dtc/fdt.hh
> ==============================================================================
> --- stable/12/usr.bin/dtc/fdt.hh      Thu Apr  4 17:24:57 2019        
> (r345879)
> +++ stable/12/usr.bin/dtc/fdt.hh      Thu Apr  4 17:26:35 2019        
> (r345880)
> @@ -56,6 +56,7 @@ namespace fdt
>  {
>  class property;
>  class node;
> +class device_tree;
>  /**
>   * Type for (owned) pointers to properties.
>   */
> @@ -418,6 +419,17 @@ class node
>        */
>       std::string unit_address;
>       /**
> +      * A flag indicating that this node has been marked /omit-if-no-ref/ and
> +      * will be omitted if it is not referenced, either directly or 
> indirectly,
> +      * by a node that is not similarly denoted.
> +      */
> +     bool omit_if_no_ref = false;
> +     /**
> +      * A flag indicating that this node has been referenced, either directly
> +      * or indirectly, by a node that is not marked /omit-if-no-ref/.
> +      */
> +     bool used = false;
> +     /**
>        * The type for the property vector.
>        */
>       typedef std::vector<property_ptr> property_vector;
> @@ -507,6 +519,7 @@ class node
>        * already been parsed.
>        */
>       node(text_input_buffer &input,
> +          device_tree &tree,
>            std::string &&n,
>            std::unordered_set<std::string> &&l,
>            std::string &&a,
> @@ -603,6 +616,7 @@ class node
>        * have been parsed.
>        */
>       static node_ptr parse(text_input_buffer &input,
> +                           device_tree &tree,
>                             std::string &&name,
>                             std::unordered_set<std::string> 
> &&label=std::unordered_set<std::string>(),
>                             std::string &&address=std::string(),
> @@ -640,6 +654,13 @@ class node
>               children.push_back(std::move(n));
>       }
>       /**
> +      * Deletes any children from this node.
> +      */
> +     inline void delete_children_if(bool (*predicate)(node_ptr &))
> +     {
> +             children.erase(std::remove_if(children.begin(), children.end(), 
> predicate), children.end());
> +     }
> +     /**
>        * Merges a node into this one.  Any properties present in both are
>        * overridden, any properties present in only one are preserved.
>        */
> @@ -710,6 +731,11 @@ class device_tree
>        */
>       bool valid = true;
>       /**
> +      * Flag indicating that this tree requires garbage collection.  This 
> will be
> +      * set to true if a node marked /omit-if-no-ref/ is encountered.
> +      */
> +     bool garbage_collect = false;
> +     /**
>        * Type used for memory reservations.  A reservation is two 64-bit
>        * values indicating a base address and length in memory that the
>        * kernel should not use.  The high 32 bits are ignored on 32-bit
> @@ -736,6 +762,12 @@ class device_tree
>        */
>       std::unordered_map<std::string, node_path> node_paths;
>       /**
> +      * All of the elements in `node_paths` in the order that they were
> +      * created.  This is used for emitting the `__symbols__` section, where
> +      * we want to guarantee stable ordering.
> +      */
> +     std::vector<std::pair<std::string, node_path>> ordered_node_paths;
> +     /**
>        * A collection of property values that are references to other nodes.
>        * These should be expanded to the full path of their targets.
>        */
> @@ -847,10 +879,20 @@ class device_tree
>        * node must have their values replaced by either the node path or
>        * phandle value.  The phandle parameter holds the next phandle to be
>        * assigned, should the need arise.  It will be incremented upon each
> -      * assignment of a phandle.
> +      * assignment of a phandle.  Garbage collection of unreferenced nodes
> +      * marked for "delete if unreferenced" will also occur here.
>        */
>       void resolve_cross_references(uint32_t &phandle);
>       /**
> +      * Garbage collects nodes that have been marked /omit-if-no-ref/ and do 
> not
> +      * have any references to them from nodes that are similarly marked.  
> This
> +      * is a fairly expensive operation.  The return value indicates whether 
> the
> +      * tree has been dirtied as a result of this operation, so that the 
> caller
> +      * may take appropriate measures to bring the device tree into a 
> consistent
> +      * state as needed.
> +      */
> +     bool garbage_collect_marked_nodes();
> +     /**
>        * 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,
> @@ -931,6 +973,14 @@ class device_tree
>       inline bool is_valid()
>       {
>               return valid;
> +     }
> +     /**
> +      * Mark this tree as needing garbage collection, because an 
> /omit-if-no-ref/
> +      * node has been encountered.
> +      */
> +     void set_needs_garbage_collection()
> +     {
> +             garbage_collect = true;
>       }
>       /**
>        * Sets the format for writing phandle properties.
> 
> Modified: stable/12/usr.bin/dtc/input_buffer.cc
> ==============================================================================
> --- stable/12/usr.bin/dtc/input_buffer.cc     Thu Apr  4 17:24:57 2019        
> (r345879)
> +++ stable/12/usr.bin/dtc/input_buffer.cc     Thu Apr  4 17:26:35 2019        
> (r345880)
> @@ -126,7 +126,7 @@ mmap_input_buffer::~mmap_input_buffer()
>  {
>       if (buffer != 0)
>       {
> -             munmap((void*)buffer, size);
> +             munmap(const_cast<char*>(buffer), size);
>       }
>  }
>  
> 
> Modified: stable/12/usr.bin/dtc/util.hh
> ==============================================================================
> --- stable/12/usr.bin/dtc/util.hh     Thu Apr  4 17:24:57 2019        
> (r345879)
> +++ stable/12/usr.bin/dtc/util.hh     Thu Apr  4 17:26:35 2019        
> (r345880)
> @@ -47,6 +47,38 @@
>  #endif
>  #endif
>  
> +#ifdef MISSING_DIGITTOINT
> +namespace
> +{
> +     /**
> +      * Glibc doesn't have a definition of digittoint, so provide our own.
> +      */
> +     inline int digittoint(int c)
> +     {
> +             switch (c)
> +             {
> +                     default:
> +                     case '0': return 0;
> +                     case '1': return 1;
> +                     case '2': return 2;
> +                     case '3': return 3;
> +                     case '4': return 4;
> +                     case '5': return 5;
> +                     case '6': return 6;
> +                     case '7': return 7;
> +                     case '8': return 8;
> +                     case '9': return 9;
> +                     case 'a': return 10;
> +                     case 'b': return 11;
> +                     case 'c': return 12;
> +                     case 'd': return 13;
> +                     case 'e': return 14;
> +                     case 'f': return 15;
> +             }
> +     }
> +}
> +#endif
> +
>  namespace dtc {
>  
>  /**
> 
> 

-- 
Rod Grimes                                                 [email protected]


_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to