Re: [PATCH v2 2/2] Preserve datatype markers when emitting dts format

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



On Fri, Mar 23, 2018 at 08:30:38AM -0600, Simon Glass wrote:
> Hi Grant,
> 
> On 20 March 2018 at 21:45, Grant Likely <grant.likely@xxxxxxxxxxxx> wrote:
> > From: Grant Likely <grant@xxxxxxxxxxxxxxxxxxxxxxxxx>
> >
> > If datatype markers are present in the property value, use them to
> > output the data in the correct format instead of trying to guess the
> > datatype. This also will preserve data grouping, such as in an
> > interrupts list.
> >
> > This is a step forward for preserving and using datatype information
> > when processing DTS/DTB files. Schema validation tools can use the
> > datatype information to make sure a DT is correctly formed and
> > intepreted.
> >
> > Signed-off-by: Grant Likely <grant.likely@xxxxxxxxxxxx>
> > ---
> >  dtc.h        |   1 +
> >  treesource.c | 227 ++++++++++++++++++++++++++++++++---------------------------
> >  2 files changed, 125 insertions(+), 103 deletions(-)
> >
> 
> I think this should have a test.

I agree.

> 
> [...]
> 
> > +const char * delim_start[] = {
> 
> A few places in this patch the * appears in a different place from the
> rest of the code.

Right dtc code style (which is basically == Linux kernel style) is to
use "type *variable".

> 
> > +       [MARKER_UINT8] = "[",
> > +       [MARKER_UINT16] = "/bits/ 16 <",
> > +       [MARKER_UINT32] = "<",
> > +       [MARKER_UINT64] = "/bits/ 64 <",
> > +       [MARKER_STRING] = "",
> > +};
> > +const char * delim_end[] = {
> > +       [MARKER_UINT8] = " ]",
> > +       [MARKER_UINT16] = " >",
> > +       [MARKER_UINT32] = " >",
> > +       [MARKER_UINT64] = " >",
> > +       [MARKER_STRING] = "",
> > +};
> >  static void write_propval(FILE *f, struct property *prop)
> >  {
> > -       int len = prop->val.len;
> > -       const char *p = prop->val.val;
> > -       struct marker *m = prop->val.markers;
> > +       size_t len = prop->val.len;
> > +       size_t chunk_len;
> > +       struct marker *next_type, *m = prop->val.markers;
> > +       struct marker dummy_marker;
> >         int nnotstring = 0, nnul = 0;
> >         int nnotstringlbl = 0, nnotcelllbl = 0;
> >         int i;
> > +       enum markertype emit_type = MARKER_NONE;
> >
> >         if (len == 0) {
> >                 fprintf(f, ";\n");
> >                 return;
> >         }
> >
> > -       for (i = 0; i < len; i++) {
> > -               if (! isstring(p[i]))
> > -                       nnotstring++;
> > -               if (p[i] == '\0')
> > -                       nnul++;
> > -       }
> > +       fprintf(f, " = ");
> > +
> > +       next_type = next_type_marker(m);
> > +       chunk_len = (next_type ? next_type->offset : len);
> > +       if (chunk_len) {
> > +               /* data type information missing, need to guess */
> > +               const char *p = prop->val.val;
> > +               for (i = 0; i < chunk_len; i++) {
> > +                       if (! isstring(p[i]))
> > +                               nnotstring++;
> > +                       if (p[i] == '\0')
> > +                               nnul++;
> > +               }
> > +
> > +               for_each_marker_of_type(m, LABEL) {
> > +                       if (m->offset >= chunk_len)
> > +                               break;
> > +                       if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
> > +                               nnotstringlbl++;
> > +                       if ((m->offset % sizeof(cell_t)) != 0)
> > +                               nnotcelllbl++;
> > +               }
> >
> > -       for_each_marker_of_type(m, LABEL) {
> > -               if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
> > -                       nnotstringlbl++;
> > -               if ((m->offset % sizeof(cell_t)) != 0)
> > -                       nnotcelllbl++;
> > +               if ((p[chunk_len-1] == '\0') && (nnotstring == 0) && (nnul < (chunk_len-nnul))
> > +                   && (nnotstringlbl == 0)) {
> > +                       dummy_marker.type = MARKER_STRING;
> > +               } else if (((chunk_len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
> > +                       dummy_marker.type = MARKER_UINT32;
> > +               } else {
> > +                       dummy_marker.type = MARKER_UINT8;
> > +               }
> > +
> > +               dummy_marker.next = prop->val.markers;
> > +               dummy_marker.offset = 0;
> > +               dummy_marker.ref = NULL;
> 
> So is the dummy marker used to hold the guess? Could the output code
> go for a particularly type and value go in a separate function
> instead?
> 
> > +               m = &dummy_marker;
> >         }
> >
> > -       fprintf(f, " = ");
> > -       if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
> > -           && (nnotstringlbl == 0)) {
> > -               write_propval_string(f, prop->val);
> > -       } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
> > -               write_propval_cells(f, prop->val);
> > -       } else {
> > -               write_propval_bytes(f, prop->val);
> > +       for_each_marker(m) {
> > +               chunk_len = (m->next ? m->next->offset : len) - m->offset;
> > +               const char *p = &prop->val.val[m->offset];
> > +
> > +               switch(m->type) {
> > +               case MARKER_UINT8:
> > +               case MARKER_UINT16:
> > +               case MARKER_UINT32:
> > +               case MARKER_UINT64:
> > +               case MARKER_STRING:
> > +                       if (emit_type != MARKER_NONE)
> > +                               fprintf(f, "%s, ", delim_end[emit_type]);
> > +                       emit_type = m->type;
> > +                       fprintf(f, "%s", delim_start[emit_type]);
> > +                       break;
> > +               case LABEL:
> > +                       fprintf(f, " %s:", m->ref);
> > +                       break;
> > +               default:
> > +                       break;
> > +               }
> > +
> > +               if (chunk_len <= 0)
> > +                       continue;
> > +
> > +               switch(emit_type) {
> > +               case MARKER_UINT16:
> > +                       write_propval_int(f, p, chunk_len, 2);
> > +                       break;
> > +               case MARKER_UINT32:
> > +                       write_propval_int(f, p, chunk_len, 4);
> > +                       break;
> > +               case MARKER_UINT64:
> > +                       write_propval_int(f, p, chunk_len, 8);
> > +                       break;
> > +               case MARKER_STRING:
> > +                       write_propval_string(f, p, chunk_len);
> > +                       break;
> > +               default:
> > +                       write_propval_int(f, p, chunk_len, 1);
> > +               }
> >         }
> >
> > -       fprintf(f, ";\n");
> > +       fprintf(f, "%s;\n", delim_end[emit_type] ? : "");
> >  }
> >
> >  static void write_tree_source_node(FILE *f, struct node *tree, int level)
> 
> Regards,
> Simon

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

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Device Tree]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux