Here's my counter-attempt at node iterators for libfdt. It's based on an internal function very similar to Scott's fdt_next_node(), but the exported interfaces are altered to be (IMO) safer and simpler.
So far, it only handles iterating across immediate children of a node, not traversing an entire subtree. I'm still working on extending the internals to cover that case. No property iteration as yet, either. Index: dtc/libfdt/fdt_ro.c =================================================================== --- dtc.orig/libfdt/fdt_ro.c 2008-01-16 15:06:49.000000000 +1100 +++ dtc/libfdt/fdt_ro.c 2008-01-16 16:27:55.000000000 +1100 @@ -65,7 +65,7 @@ static int nodename_eq(const void *fdt, int offset, const char *s, int len) { - const char *p = fdt_offset_ptr(fdt, offset, len+1); + const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); if (! p) /* short match */ @@ -104,50 +104,16 @@ int fdt_num_mem_rsv(const void *fdt) return i; } -int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, +int fdt_subnode_offset_namelen(const void *fdt, int offset, const char *name, int namelen) { - int level = 0; - uint32_t tag; - int offset, nextoffset; - CHECK_HEADER(fdt); - tag = fdt_next_tag(fdt, parentoffset, &nextoffset); - if (tag != FDT_BEGIN_NODE) - return -FDT_ERR_BADOFFSET; - - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - - switch (tag) { - case FDT_END: - return -FDT_ERR_TRUNCATED; - - case FDT_BEGIN_NODE: - level++; - if (level != 1) - continue; - if (nodename_eq(fdt, offset+FDT_TAGSIZE, name, namelen)) - /* Found it! */ - return offset; - break; - - case FDT_END_NODE: - level--; - break; - - case FDT_PROP: - case FDT_NOP: - break; - - default: - return -FDT_ERR_BADSTRUCTURE; - } - } while (level >= 0); + for_each_subnode(fdt, offset) + if (nodename_eq(fdt, offset, name, namelen)) + return offset; - return -FDT_ERR_NOTFOUND; + return offset; } int fdt_subnode_offset(const void *fdt, int parentoffset, Index: dtc/libfdt/fdt.c =================================================================== --- dtc.orig/libfdt/fdt.c 2008-01-16 16:26:48.000000000 +1100 +++ dtc/libfdt/fdt.c 2008-01-16 17:03:09.000000000 +1100 @@ -129,6 +129,58 @@ uint32_t fdt_next_tag(const void *fdt, i return tag; } +static int _fdt_next_node(const void *fdt, int offset, int *depth) +{ + uint32_t tag; + int nextoffset; + + tag = fdt_next_tag(fdt, offset, &nextoffset); + if (tag != FDT_BEGIN_NODE) + return -FDT_ERR_BADOFFSET; + + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_PROP: + case FDT_NOP: + break; + + case FDT_BEGIN_NODE: + (*depth)++; + if (*depth == 1) + return offset; + break; + + case FDT_END_NODE: + (*depth)--; + break; + + case FDT_END: + return -FDT_ERR_TRUNCATED; + + default: + return -FDT_ERR_BADSTRUCTURE; + } + } while (*depth >= 0); + + return -FDT_ERR_NOTFOUND; +} + +int _fdt_first_subnode(const void *fdt, int offset) +{ + int depth = 0; + + return _fdt_next_node(fdt, offset, &depth); +} + +int _fdt_next_subnode(const void *fdt, int offset) +{ + int depth = 1; + return _fdt_next_node(fdt, offset, &depth); +} + const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) { int len = strlen(s) + 1; Index: dtc/libfdt/libfdt.h =================================================================== --- dtc.orig/libfdt/libfdt.h 2008-01-16 16:27:09.000000000 +1100 +++ dtc/libfdt/libfdt.h 2008-01-16 17:06:31.000000000 +1100 @@ -131,6 +131,18 @@ static inline void *fdt_offset_ptr_w(voi uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); /**********************************************************************/ +/* Traversal functions */ +/**********************************************************************/ + +int _fdt_first_subnode(const void *fdt, int offset); +int _fdt_next_subnode(const void *fdt, int offset); + +#define for_each_subnode(fdt, offset) \ + for ((offset) = _fdt_first_subnode((fdt), (offset)); \ + (offset) >= 0; \ + (offset) = _fdt_next_subnode((fdt), (offset))) + +/**********************************************************************/ /* General functions */ /**********************************************************************/ -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev