Hi David,

> On Oct 21, 2015, at 05:29 , David Gibson <da...@gibson.dropbear.id.au> wrote:
> 
> On Wed, Aug 26, 2015 at 09:44:33PM +0300, Pantelis Antoniou wrote:
>> This patch enable the generation of symbols & local fixup information
>> for trees compiled with the -@ (--symbols) option.
>> 
>> Using this patch labels in the tree and their users emit information
>> in __symbols__ and __local_fixups__ nodes.
>> 
>> The __fixups__ node make possible the dynamic resolution of phandle
>> references which are present in the plugin tree but lie in the
>> tree that are applying the overlay against.
>> 
>> panto: The original alternative syntax patch required the use of an empty 
>> node
>> which is no longer required.
>> Numbering of fragments in sequence was also implemented.
>> 
>> Signed-off-by: Pantelis Antoniou <pantelis.anton...@konsulko.com>
>> Signed-off-by: Sascha Hauer <s.ha...@pengutronix.de>
>> Signed-off-by: Jan Luebbe <j...@pengutronix.de>
> 
> Sorry it's taken me so very long to look at this.  I've been a bit
> swamped by critical bugs in my day job.
> 

No worries.

> As I've said before (and say several times below), I don't much like
> the fixups/symbols format, but it's in use so I guess we're stuck with
> it.
> 
> So, the concept and behaviour of this patch seems mostly fine to me.
> I've made a number of comments below.  Some are just trivial nits, but
> a few are important implementation problems that could lead to nasty
> behaviour in edge cases.
> 
>> ---
>> Documentation/manual.txt |  16 ++++
>> checks.c                 |  18 ++++-
>> dtc-lexer.l              |   5 ++
>> dtc-parser.y             |  54 +++++++++++--
>> dtc.c                    |  21 ++++-
>> dtc.h                    |  13 ++-
>> livetree.c               | 202 
>> +++++++++++++++++++++++++++++++++++++++++++++++
>> treesource.c             |   3 +
>> 8 files changed, 321 insertions(+), 11 deletions(-)
>> 
>> diff --git a/Documentation/manual.txt b/Documentation/manual.txt
>> index 398de32..29682df 100644
>> --- a/Documentation/manual.txt
>> +++ b/Documentation/manual.txt
>> @@ -119,6 +119,20 @@ Options:
>>      Make space for <number> reserve map entries
>>      Relevant for dtb and asm output only.
>> 
>> +    -@
>> +        Generates a __symbols__ node at the root node of the resulting blob
> 
> Nit: indentation error here.
> 

OK.

>> +    for any node labels used, and for any local references using phandles
>> +    it also generates a __local_fixups__ node that tracks them.
>> +
>> +    When using the /plugin/ tag all unresolved label references to
>> +    be tracked in the __fixups__ node, making dynamic resolution possible.
>> +
>> +    -A
>> +    Generate automatically aliases for all node labels. This is similar to
>> +    the -@ option (the __symbols__ node contain identical information) but
>> +    the semantics are slightly different since no phandles are automatically
>> +    generated for labeled nodes.
>> +
>>     -S <bytes>
>>      Ensure the blob at least <bytes> long, adding additional
>>      space if needed.
>> @@ -153,6 +167,8 @@ Here is a very rough overview of the layout of a DTS 
>> source file:
>> 
>>     devicetree:   '/' nodedef
>> 
>> +    plugindecl:   '/' 'plugin' '/' ';'
>> +
>>     nodedef:      '{' list_of_property list_of_subnode '}' ';'
>> 
>>     property:     label PROPNAME '=' propdata ';'
>> diff --git a/checks.c b/checks.c
>> index 0c03ac9..65bf6fd 100644
>> --- a/checks.c
>> +++ b/checks.c
>> @@ -466,8 +466,12 @@ static void fixup_phandle_references(struct check *c, 
>> struct node *dt,
>> 
>>              refnode = get_node_by_ref(dt, m->ref);
>>              if (! refnode) {
>> -                    FAIL(c, "Reference to non-existent node or label 
>> \"%s\"\n",
>> -                         m->ref);
>> +                    if (!source_is_plugin)
>> +                            FAIL(c, "Reference to non-existent node or "
>> +                                            "label \"%s\"\n", m->ref);
>> +                    else /* mark the entry as unresolved */
>> +                            *((cell_t *)(prop->val.val + m->offset)) =
>> +                                    cpu_to_fdt32(0xffffffff);
>>                      continue;
>>              }
>> 
>> @@ -652,6 +656,15 @@ static void 
>> check_obsolete_chosen_interrupt_controller(struct check *c,
>> }
>> TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
>> 
>> +static void check_deprecated_plugin_syntax(struct check *c,
>> +                                       struct node *dt)
>> +{
>> +    if (deprecated_plugin_syntax_warning)
>> +            FAIL(c, "Use '/dts-v1/ /plugin/'; syntax. /dts-v1/; /plugin/; "
>> +                            "is going to be removed in next versions");
> 
> Better to put this warning directly where the bad syntax is detected
> in the parser (using ERROR), transferring it to here with the global
> is pretty ugly.
> 
> The checks infrastructure isn't meant to handle all possible error
> conditions - just those that are related to the tree's semantic
> content, rather than pars
> 
> Plus.. the old syntax was never committed upstream, so I'm inclined to
> just drop it now, making this irrelevant.
> 

OK, I will drop the deprecated syntax, but I will maintain an out of tree
patch for people that still keep old style DTSes around.

>> +}
>> +TREE_WARNING(deprecated_plugin_syntax, NULL);
>> +
>> static struct check *check_table[] = {
>>      &duplicate_node_names, &duplicate_property_names,
>>      &node_name_chars, &node_name_format, &property_name_chars,
>> @@ -669,6 +682,7 @@ static struct check *check_table[] = {
>> 
>>      &avoid_default_addr_size,
>>      &obsolete_chosen_interrupt_controller,
>> +    &deprecated_plugin_syntax,
>> 
>>      &always_fail,
>> };
>> diff --git a/dtc-lexer.l b/dtc-lexer.l
>> index 0ee1caf..dd44ba2 100644
>> --- a/dtc-lexer.l
>> +++ b/dtc-lexer.l
>> @@ -113,6 +113,11 @@ static void lexical_error(const char *fmt, ...);
>>                      return DT_V1;
>>              }
>> 
>> +<*>"/plugin/"       {
>> +                    DPRINT("Keyword: /plugin/\n");
>> +                    return DT_PLUGIN;
>> +            }
>> +
>> <*>"/memreserve/"    {
>>                      DPRINT("Keyword: /memreserve/\n");
>>                      BEGIN_DEFAULT();
>> diff --git a/dtc-parser.y b/dtc-parser.y
>> index 5a897e3..accccba 100644
>> --- a/dtc-parser.y
>> +++ b/dtc-parser.y
>> @@ -19,6 +19,7 @@
>>  */
>> %{
>> #include <stdio.h>
>> +#include <inttypes.h>
>> 
>> #include "dtc.h"
>> #include "srcpos.h"
>> @@ -52,9 +53,11 @@ extern bool treesource_error;
>>      struct node *nodelist;
>>      struct reserve_info *re;
>>      uint64_t integer;
>> +    bool is_plugin;
>> }
>> 
>> %token DT_V1
>> +%token DT_PLUGIN
>> %token DT_MEMRESERVE
>> %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
>> %token DT_BITS
>> @@ -71,6 +74,7 @@ extern bool treesource_error;
>> 
>> %type <data> propdata
>> %type <data> propdataprefix
>> +%type <is_plugin> plugindecl
>> %type <re> memreserve
>> %type <re> memreserves
>> %type <array> arrayprefix
>> @@ -101,10 +105,39 @@ extern bool treesource_error;
>> %%
>> 
>> sourcefile:
>> -      DT_V1 ';' memreserves devicetree
>> +        basesource
>> +      | pluginsource
>> +      ;
>> +
>> +basesource:
>> +      DT_V1 ';' plugindecl memreserves devicetree
>> +            {
>> +                    source_is_plugin = $3;
>> +                    if (source_is_plugin)
>> +                            deprecated_plugin_syntax_warning = true;
>> +                    the_boot_info = build_boot_info($4, $5,
>> +                                                    guess_boot_cpuid($5));
>> +            }
>> +    ;
>> +
>> +plugindecl:
>> +    /* empty */
>> +            {
>> +                    $$ = false;
>> +            }
>> +    | DT_PLUGIN ';'
>> +            {
>> +                    $$ = true;
>> +            }
>> +    ;
>> +
>> +pluginsource:
>> +    DT_V1 DT_PLUGIN ';' memreserves devicetree
>>              {
>> -                    the_boot_info = build_boot_info($3, $4,
>> -                                                    guess_boot_cpuid($4));
>> +                    source_is_plugin = true;
>> +                    deprecated_plugin_syntax_warning = false;
>> +                    the_boot_info = build_boot_info($4, $5,
>> +                                                    guess_boot_cpuid($5));
>>              }
> 
> I think the above will be clearer if you make a new non-terminal, say
> 'versioninfo', that incorporates the DT_V1 and (optionally) the
> /plugin/ tag.  We can extend that with other global flags if we ever
> need them.
> 

OK.

>>      ;
>> 
>> @@ -156,10 +189,14 @@ devicetree:
>>              {
>>                      struct node *target = get_node_by_ref($1, $2);
>> 
>> -                    if (target)
>> +                    if (target) {
>>                              merge_nodes(target, $3);
>> -                    else
>> -                            ERROR(&@2, "Label or path %s not found", $2);
>> +                    } else {
>> +                            if (symbol_fixup_support)
>> +                                    add_orphan_node($1, $3, $2);
>> +                            else
>> +                                    ERROR(&@2, "Label or path %s not 
>> found", $2);
>> +                    }
>>                      $$ = $1;
>>              }
>>      | devicetree DT_DEL_NODE DT_REF ';'
>> @@ -174,6 +211,11 @@ devicetree:
>> 
>>                      $$ = $1;
>>              }
>> +    | /* empty */
>> +            {
>> +                    /* build empty node */
>> +                    $$ = name_node(build_node(NULL, NULL), "");
>> +            }
>>      ;
> 
> What's the importance of this new rule?  It's connection to plugins
> isn't obvious to me.
> 

It is required when you use the syntactic sugar version of an overlay 
definition. 

&target {
        foo;
};

>> 
>> nodedef:
>> diff --git a/dtc.c b/dtc.c
>> index 5fa23c4..ee37be9 100644
>> --- a/dtc.c
>> +++ b/dtc.c
>> @@ -31,6 +31,8 @@ int reservenum;            /* Number of memory reservation 
>> slots */
>> int minsize;         /* Minimum blob size */
>> int padsize;         /* Additional padding to blob */
>> int phandle_format = PHANDLE_BOTH;   /* Use linux,phandle or phandle 
>> properties */
>> +int symbol_fixup_support;
>> +int auto_label_aliases;
>> 
>> static void fill_fullpaths(struct node *tree, const char *prefix)
>> {
>> @@ -53,7 +55,7 @@ static void fill_fullpaths(struct node *tree, const char 
>> *prefix)
>> #define FDT_VERSION(version) _FDT_VERSION(version)
>> #define _FDT_VERSION(version)        #version
>> static const char usage_synopsis[] = "dtc [options] <input file>";
>> -static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv";
>> +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:@Ahv";
>> static struct option const usage_long_opts[] = {
>>      {"quiet",            no_argument, NULL, 'q'},
>>      {"in-format",         a_argument, NULL, 'I'},
>> @@ -71,6 +73,8 @@ static struct option const usage_long_opts[] = {
>>      {"phandle",           a_argument, NULL, 'H'},
>>      {"warning",           a_argument, NULL, 'W'},
>>      {"error",             a_argument, NULL, 'E'},
>> +    {"symbols",          no_argument, NULL, '@'},
>> +    {"auto-alias",       no_argument, NULL, 'A'},
>>      {"help",             no_argument, NULL, 'h'},
>>      {"version",          no_argument, NULL, 'v'},
>>      {NULL,               no_argument, NULL, 0x0},
>> @@ -101,6 +105,8 @@ static const char * const usage_opts_help[] = {
>>       "\t\tboth   - Both \"linux,phandle\" and \"phandle\" properties",
>>      "\n\tEnable/disable warnings (prefix with \"no-\")",
>>      "\n\tEnable/disable errors (prefix with \"no-\")",
>> +    "\n\tEnable symbols/fixup support",
>> +    "\n\tEnable auto-alias of labels",
>>      "\n\tPrint this help and exit",
>>      "\n\tPrint version and exit",
>>      NULL,
>> @@ -233,7 +239,12 @@ int main(int argc, char *argv[])
>>              case 'E':
>>                      parse_checks_option(false, true, optarg);
>>                      break;
>> -
>> +            case '@':
>> +                    symbol_fixup_support = 1;
>> +                    break;
>> +            case 'A':
>> +                    auto_label_aliases = 1;
>> +                    break;
>>              case 'h':
>>                      usage(NULL);
>>              default:
>> @@ -294,6 +305,12 @@ int main(int argc, char *argv[])
>>      if (sort)
>>              sort_tree(bi);
>> 
>> +    if (symbol_fixup_support || auto_label_aliases)
>> +            generate_label_node(bi->dt, bi->dt);
>> +
>> +    if (symbol_fixup_support)
>> +            generate_fixups_node(bi->dt, bi->dt);
>> +
>>      if (streq(outname, "-")) {
>>              outf = stdout;
>>      } else {
>> diff --git a/dtc.h b/dtc.h
>> index 56212c8..d025111 100644
>> --- a/dtc.h
>> +++ b/dtc.h
>> @@ -20,7 +20,7 @@
>>  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>>  *                                                                   USA
>>  */
>> -
>> +#define _GNU_SOURCE
> 
> Ugh.. I'm at least trying to keep dtc compilable on FreeBSD, so I'd
> prefer to avoid using GNU extensions.  What's the feature you needed
> this for?
> 

Hmm, it’s for using asprintf.

Funnily asprintf is already used in the srcpos.c file, which is used for the
converter. I can easily switch to sprintf with some hit to readability.

>> #include <stdio.h>
>> #include <string.h>
>> #include <stdlib.h>
>> @@ -54,6 +54,14 @@ extern int reservenum;            /* Number of memory 
>> reservation slots */
>> extern int minsize;          /* Minimum blob size */
>> extern int padsize;          /* Additional padding to blob */
>> extern int phandle_format;   /* Use linux,phandle or phandle properties */
>> +extern int symbol_fixup_support;/* enable symbols & fixup support */
>> +extern int auto_label_aliases;      /* auto generate labels -> aliases */
>> +
>> +/*
>> + * Tree source globals
>> + */
>> +extern bool source_is_plugin;
> 
> I think it makes sense to put this flag into the_boot_info, rather
> than adding a new global.

OK

> 
>> +extern bool deprecated_plugin_syntax_warning;
> 
> And as noted above, I don't think you need this one at all.
> 

OK.

>> #define PHANDLE_LEGACY       0x1
>> #define PHANDLE_EPAPR        0x2
>> @@ -194,6 +202,7 @@ struct node *build_node_delete(void);
>> struct node *name_node(struct node *node, char *name);
>> struct node *chain_node(struct node *first, struct node *list);
>> struct node *merge_nodes(struct node *old_node, struct node *new_node);
>> +void add_orphan_node(struct node *old_node, struct node *new_node, char 
>> *ref);
>> 
>> void add_property(struct node *node, struct property *prop);
>> void delete_property_by_name(struct node *node, char *name);
>> @@ -244,6 +253,8 @@ struct boot_info {
>> struct boot_info *build_boot_info(struct reserve_info *reservelist,
>>                                struct node *tree, uint32_t boot_cpuid_phys);
>> void sort_tree(struct boot_info *bi);
>> +void generate_label_node(struct node *node, struct node *dt);
>> +void generate_fixups_node(struct node *node, struct node *dt);
>> 
>> /* Checks */
>> 
>> diff --git a/livetree.c b/livetree.c
>> index e229b84..1ef9fc4 100644
>> --- a/livetree.c
>> +++ b/livetree.c
>> @@ -216,6 +216,34 @@ struct node *merge_nodes(struct node *old_node, struct 
>> node *new_node)
>>      return old_node;
>> }
>> 
>> +void add_orphan_node(struct node *dt, struct node *new_node, char *ref)
>> +{
>> +    static unsigned int next_orphan_fragment = 0;
>> +    struct node *ovl = xmalloc(sizeof(*ovl));
>> +    struct property *p;
>> +    struct data d = empty_data;
>> +    char *name;
>> +    int ret;
>> +
>> +    memset(ovl, 0, sizeof(*ovl));
>> +
>> +    d = data_add_marker(d, REF_PHANDLE, ref);
>> +    d = data_append_integer(d, 0xffffffff, 32);
>> +    p = build_property("target", d);
>> +    add_property(ovl, p);
> 
> Hmm, using a phandle (which has to be later mangled) rather than a
> string ref directly in the target property seems an unnecessarily
> difficult way of doing things, but I guess the format's in use so we
> can't fix that now.

It makes sense in practice though and it makes this to work:

&target {
        foo;
};

> 
>> +    ret = asprintf(&name, "fragment@%u",
>> +                    next_orphan_fragment++);
>> +    if (ret == -1)
>> +            die("asprintf() failed\n");
>> +    name_node(ovl, name);
>> +    name_node(new_node, "__overlay__");
> 
> It's a bit confusing to me that it's the original node, not 'ovl'
> which gets the name "__overlay__".  Maybe a different variable name.
> 
> This could produce some confusing results if a plugin source contains
> a "base" tree construction.
> 

This is part of the syntactic sugar part. I will change the names of
the variables to make things clearer.

>> +    add_child(dt, ovl);
>> +    add_child(ovl, new_node);
>> +}
>> +
>> struct node *chain_node(struct node *first, struct node *list)
>> {
>>      assert(first->next_sibling == NULL);
>> @@ -709,3 +737,177 @@ void sort_tree(struct boot_info *bi)
>>      sort_reserve_entries(bi);
>>      sort_node(bi->dt);
>> }
>> +
>> +void generate_label_node(struct node *node, struct node *dt)
> 
> I prefer to put "context" parameters before more specific parameters,
> so I'd like to see dt then node.  Also, maybe call it 'tree', since
> that seems to be the more common name in livetree.c.
> 

OK.

>> +{
>> +    struct node *c, *an;
>> +    struct property *p;
>> +    struct label *l;
>> +    int has_label;
>> +    char *gen_node_name;
>> +
>> +    if (auto_label_aliases)
>> +            gen_node_name = "aliases";
>> +    else
>> +            gen_node_name = "__symbols__";
> 
> Doing just one or the other here also seems dubious to me, as does
> referencing the global here.  I'd prefer to see this as a parameter,
> which the main function can pass in.  That way you can also better
> handle the case of using both -A and -@ at the same time.
> 

I’ll see what I can do… there were some complications when I tried it.

> I also think it would be nice to construct the alias/symbols node just
> once for the tree then pass the reference to the recursive call.
> 

Hmm… maybe. I’ll give it a whirl.

> 
>> +
>> +    /* Make sure the label isn't already there */
> 
> Comment doesn't match the code, this just tests if the node has a
> label at all.  For which 'if (node-labels)' would suffice.
> 

Comment will be deleted. Probably a leftover.

>> +    has_label = 0;
>> +    for_each_label(node->labels, l) {
>> +            has_label = 1;
>> +            break;
>> +    }
>> +
>> +    if (has_label) {
>> +
> 
> Nit: extraneous blank line.
> 

OK. (geeze)

>> +            /* an is the aliases/__symbols__ node */
>> +            an = get_subnode(dt, gen_node_name);
>> +            /* if no node exists, create it */
>> +            if (!an) {
>> +                    an = build_node(NULL, NULL);
>> +                    name_node(an, gen_node_name);
>> +                    add_child(dt, an);
>> +            }
>> +
>> +            /* now add the label in the node */
>> +            for_each_label(node->labels, l) {
>> +                    /* check whether the label already exists */
>> +                    p = get_property(an, l->label);
>> +                    if (p) {
>> +                            fprintf(stderr, "WARNING: label %s already"
>> +                                    " exists in /%s", l->label,
>> +                                    gen_node_name);
>> +                            continue;
>> +                    }
>> +
>> +                    /* insert it */
>> +                    p = build_property(l->label,
>> +                            data_copy_escape_string(node->fullpath,
>> +                                            strlen(node->fullpath)));
> 
> fullpath should not contain escape characters, and if it does you
> shouldn't be unescaping them, so data_copy_escape_string() is the
> wrong tool for this job.
> 

OK.

>> +                    add_property(an, p);
>> +            }
>> +
>> +            /* force allocation of a phandle for this node */
>> +            if (symbol_fixup_support)
>> +                    (void)get_node_phandle(dt, node);
> 
> Again, I'd prefer to see a parameter rather than referencing the global.
> 

OK

>> +    }
>> +
>> +    for_each_child(node, c)
>> +            generate_label_node(c, dt);
>> +}
>> +
>> +static void add_fixup_entry(struct node *dt, struct node *node,
>> +            struct property *prop, struct marker *m)
>> +{
>> +    struct node *fn;        /* local fixup node */
>> +    struct property *p;
>> +    char *fixups_name = "__fixups__";
>> +    struct data d;
>> +    char *entry;
>> +    int ret;
>> +
>> +    /* fn is the node we're putting entries in */
>> +    fn = get_subnode(dt, fixups_name);
>> +    /* if no node exists, create it */
>> +    if (!fn) {
>> +            fn = build_node(NULL, NULL);
>> +            name_node(fn, fixups_name);
>> +            add_child(dt, fn);
>> +    }
> 
> Again, I'd prefer to see construction and location of the fixups node
> factored out.
> 

OK.

>> +
>> +    ret = asprintf(&entry, "%s:%s:%u",
>> +                    node->fullpath, prop->name, m->offset);
> 
> I hate this encoding of things into a string that will have to be
> parsed, rather than using the existing mechanisms we have for
> structure in the tree.  But, again, the format is in use so I guess
> we're stuck with it.
> 
> I would at least like to see this throw an error if the path or the
> property name include ':' characters that will mess this up.
> 

Will do.

> 
>> +    if (ret == -1)
>> +            die("asprintf() failed\n");
> 
> Hrm.  We should put an xasprintf function in util.  That also lets us
> supply our own implementation when necessary and avoid relying on the
> gnu extension.
> 

I think that would be best.

>> +
>> +    p = get_property(fn, m->ref);
> 
> This doesn't handle the case where m->ref is a path rather than a
> label.  It will lead to creating a property with '/' in the name
> below, which you really don't want.
> 

I haven’t thought of the m->ref being a path. Will guard against it.

>> +    d = data_append_data(p ? p->val : empty_data, entry, strlen(entry) + 1);
>> +    if (!p)
>> +            add_property(fn, build_property(m->ref, d));
>> +    else
>> +            p->val = d;
> 
> I think this would be clearer with just a single if, rather than an if
> and the parallel conditional expression.
> 

OK.

>> +}
>> +
>> +static void add_local_fixup_entry(struct node *dt, struct node *node,
>> +            struct property *prop, struct marker *m,
>> +            struct node *refnode)
>> +{
>> +    struct node *lfn, *wn, *nwn;    /* local fixup node, walk node, new */
>> +    struct property *p;
>> +    struct data d;
>> +    char *local_fixups_name = "__local_fixups__";
>> +    char *s, *e, *comp;
>> +    int len;
>> +
>> +    /* fn is the node we're putting entries in */
>> +    lfn = get_subnode(dt, local_fixups_name);
>> +    /* if no node exists, create it */
>> +    if (!lfn) {
>> +            lfn = build_node(NULL, NULL);
>> +            name_node(lfn, local_fixups_name);
>> +            add_child(dt, lfn);
>> +    }
> 
> Again, please factor the node creation.
> 

OK

>> +
>> +    /* walk the path components creating nodes if they don't exist */
> 
> Might be worth making a helper function for this operation.  As it is,
> it somewhat obscures the fixup logic that this function is actually
> about.
> 

OK

> It also seems absurd to me that the local fixups take such a
> completely different format from the non-local fixups.  But, yet
> again, stuck with it.
> 

I explained before, there’s a reason for it :)

>> +    comp = NULL;
>> +    /* start skipping the first / */
>> +    s = node->fullpath + 1;
>> +    wn = lfn;
>> +    while (*s) {
>> +            /* retrieve path component */
>> +            e = strchr(s, '/');
>> +            if (e == NULL)
>> +                    e = s + strlen(s);
>> +            len = e - s;
>> +            comp = xrealloc(comp, len + 1);
> 
> You can just allocate comp with strlen(fullpath) bytes in the first
> place, rather than realloc()ing on every iteration.
> 

OK

>> +            memcpy(comp, s, len);
>> +            comp[len] = '\0';
>> +
>> +            /* if no node exists, create it */
>> +            nwn = get_subnode(wn, comp);
>> +            if (!nwn) {
>> +                    nwn = build_node(NULL, NULL);
>> +                    name_node(nwn, strdup(comp));
>> +                    add_child(wn, nwn);
> 
> This build/name/add tuple appears in a bunch of places in your code,
> might be worth a helper function for that too.
> 

OK

>> +            }
>> +            wn = nwn;
>> +
>> +            /* last path component */
>> +            if (!*e)
>> +                    break;
>> +
>> +            /* next path component */
>> +            s = e + 1;
>> +    }
>> +    free(comp);
>> +
>> +    p = get_property(wn, prop->name);
>> +    d = data_append_cell(p ? p->val : empty_data, (cell_t)m->offset);
>> +    if (!p)
>> +            add_property(wn, build_property(prop->name, d));
>> +    else
>> +            p->val = d;
>> +}
>> +
>> +void generate_fixups_node(struct node *node, struct node *dt)
>> +{
>> +    struct node *c;
>> +    struct property *prop;
>> +    struct marker *m;
>> +    struct node *refnode;
>> +
>> +    for_each_property(node, prop) {
>> +            m = prop->val.markers;
>> +            for_each_marker_of_type(m, REF_PHANDLE) {
>> +                    refnode = get_node_by_ref(dt, m->ref);
>> +                    if (!refnode)
>> +                            add_fixup_entry(dt, node, prop, m);
>> +                    else
>> +                            add_local_fixup_entry(dt, node, prop, m,
>> +                                            refnode);
> 
> Do you need to consider REF_PATH fixups?
> 

I don’t think so, but I will take a look.

>> +            }
>> +    }
>> +
>> +    for_each_child(node, c)
>> +            generate_fixups_node(c, dt);
>> +}
>> diff --git a/treesource.c b/treesource.c
>> index a55d1d1..e1d6657 100644
>> --- a/treesource.c
>> +++ b/treesource.c
>> @@ -28,6 +28,9 @@ extern YYLTYPE yylloc;
>> struct boot_info *the_boot_info;
>> bool treesource_error;
>> 
>> +bool source_is_plugin;
>> +bool deprecated_plugin_syntax_warning;
>> +
>> struct boot_info *dt_from_source(const char *fname)
>> {
>>      the_boot_info = NULL;
> 

It’s going to take a couple of days for the updated patch to be sent.

Thanks for the review.

> -- 
> 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

Regards

— Pantelis

--
To unsubscribe from this list: send the line "unsubscribe devicetree-compiler" 
in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to