*/
#include "dtc.h"
+#include "srcpos.h"
#ifdef TRACE_CHECKS
#define TRACE(c, ...) \
const char *fmt, ...)
{
va_list ap;
- va_start(ap, fmt);
+ char *str = NULL;
+ struct srcpos *pos = NULL;
+ char *file_str;
+
+ if (!(c->warn && (quiet < 1)) && !(c->error && (quiet < 2)))
+ return;
+
+ if (prop && prop->srcpos)
+ pos = prop->srcpos;
+ else if (node && node->srcpos)
+ pos = node->srcpos;
+
+ if (pos) {
+ file_str = srcpos_string(pos);
+ xasprintf(&str, "%s", file_str);
+ free(file_str);
+ } else if (streq(dti->outname, "-")) {
+ xasprintf(&str, "<stdout>");
+ } else {
+ xasprintf(&str, "%s", dti->outname);
+ }
- if ((c->warn && (quiet < 1))
- || (c->error && (quiet < 2))) {
- fprintf(stderr, "%s: %s (%s): ",
- strcmp(dti->outname, "-") ? dti->outname : "<stdout>",
+ xasprintf_append(&str, ": %s (%s): ",
(c->error) ? "ERROR" : "Warning", c->name);
- if (node) {
- fprintf(stderr, "%s", node->fullpath);
- if (prop)
- fprintf(stderr, ":%s", prop->name);
- fputs(": ", stderr);
- }
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
+
+ if (node) {
+ if (prop)
+ xasprintf_append(&str, "%s:%s: ", node->fullpath, prop->name);
+ else
+ xasprintf_append(&str, "%s: ", node->fullpath);
}
+
+ va_start(ap, fmt);
+ xavsprintf_append(&str, fmt, ap);
va_end(ap);
+
+ xasprintf_append(&str, "\n");
+
+ if (!prop && pos) {
+ pos = node->srcpos;
+ while (pos->next) {
+ pos = pos->next;
+
+ file_str = srcpos_string(pos);
+ xasprintf_append(&str, " also defined at %s\n", file_str);
+ free(file_str);
+ }
+ }
+
+ fputs(str, stderr);
}
#define FAIL(c, dti, node, ...) \
for (str = prop->val.val, end = str + prop->val.len; str < end;
str += strnlen(str, end - str) + 1) {
- if (strprefixeq(str, end - str, compat))
+ if (streq(str, compat))
return true;
}
return false;
if (node_is_compatible(node, "simple-bus"))
node->bus = &simple_bus;
}
-WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells);
+WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL,
+ &addr_size_cells, &compatible_is_string_list);
static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
{
static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
{
+ int spi_addr_cells = 1;
if (strprefixeq(node->name, node->basenamelen, "spi")) {
node->bus = &spi_bus;
if (node->bus != &spi_bus || !node->children)
return;
- if (node_addr_cells(node) != 1)
+ if (get_property(node, "spi-slave"))
+ spi_addr_cells = 0;
+ if (node_addr_cells(node) != spi_addr_cells)
FAIL(c, dti, node, "incorrect #address-cells for SPI bus");
if (node_size_cells(node) != 0)
FAIL(c, dti, node, "incorrect #size-cells for SPI bus");
if (!node->parent || (node->parent->bus != &spi_bus))
return;
+ if (get_property(node->parent, "spi-slave"))
+ return;
+
prop = get_property(node, "reg");
if (prop)
cells = (cell_t *)prop->val.val;
<*>\&{LABEL} { /* label reference */
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1);
- return DT_REF;
+ return DT_LABEL_REF;
}
<*>"&{/"{PATHCHAR}*\} { /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
yylval.labelref = xstrdup(yytext+2);
- return DT_REF;
+ return DT_PATH_REF;
}
<BYTESTRING>[0-9a-fA-F]{2} {
%token <byte> DT_BYTE
%token <data> DT_STRING
%token <labelref> DT_LABEL
-%token <labelref> DT_REF
+%token <labelref> DT_LABEL_REF
+%token <labelref> DT_PATH_REF
%token DT_INCBIN
%type <data> propdata
%type <data> bytestring
%type <prop> propdef
%type <proplist> proplist
+%type <labelref> dt_ref
%type <node> devicetree
%type <node> nodedef
}
;
+dt_ref: DT_LABEL_REF | DT_PATH_REF;
+
devicetree:
'/' nodedef
{
{
$$ = merge_nodes($1, $3);
}
- | DT_REF nodedef
+ | dt_ref nodedef
{
/*
* We rely on the rule being always:
*/
if (!($<flags>-1 & DTSF_PLUGIN))
ERROR(&@2, "Label or path %s not found", $1);
- $$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1);
+ $$ = add_orphan_node(
+ name_node(build_node(NULL, NULL, NULL),
+ ""),
+ $2, $1);
}
- | devicetree DT_LABEL DT_REF nodedef
+ | devicetree DT_LABEL dt_ref nodedef
{
struct node *target = get_node_by_ref($1, $3);
ERROR(&@3, "Label or path %s not found", $3);
$$ = $1;
}
- | devicetree DT_REF nodedef
+ | devicetree DT_PATH_REF nodedef
{
/*
* We rely on the rule being always:
}
$$ = $1;
}
- | devicetree DT_DEL_NODE DT_REF ';'
+ | devicetree DT_LABEL_REF nodedef
+ {
+ struct node *target = get_node_by_ref($1, $2);
+
+ if (target) {
+ merge_nodes(target, $3);
+ } else {
+ /*
+ * We rely on the rule being always:
+ * versioninfo plugindecl memreserves devicetree
+ * so $-1 is what we want (plugindecl)
+ */
+ if ($<flags>-1 & DTSF_PLUGIN)
+ add_orphan_node($1, $3, $2);
+ else
+ ERROR(&@2, "Label or path %s not found", $2);
+ }
+ $$ = $1;
+ }
+ | devicetree DT_DEL_NODE dt_ref ';'
{
struct node *target = get_node_by_ref($1, $3);
$$ = $1;
}
- | devicetree DT_OMIT_NO_REF DT_REF ';'
+ | devicetree DT_OMIT_NO_REF dt_ref ';'
{
struct node *target = get_node_by_ref($1, $3);
nodedef:
'{' proplist subnodes '}' ';'
{
- $$ = build_node($2, $3);
+ $$ = build_node($2, $3, &@$);
}
;
propdef:
DT_PROPNODENAME '=' propdata ';'
{
- $$ = build_property($1, $3);
+ $$ = build_property($1, $3, &@$);
}
| DT_PROPNODENAME ';'
{
- $$ = build_property($1, empty_data);
+ $$ = build_property($1, empty_data, &@$);
}
| DT_DEL_PROP DT_PROPNODENAME ';'
{
{
$$ = data_merge($1, $3);
}
- | propdataprefix DT_REF
+ | propdataprefix dt_ref
{
$1 = data_add_marker($1, TYPE_STRING, $2);
$$ = data_add_marker($1, REF_PATH, $2);
$$.data = data_append_integer($1.data, $2, $1.bits);
}
- | arrayprefix DT_REF
+ | arrayprefix dt_ref
{
uint64_t val = ~0ULL >> (64 - $1.bits);
}
| DT_DEL_NODE DT_PROPNODENAME ';'
{
- $$ = name_node(build_node_delete(), $2);
+ $$ = name_node(build_node_delete(&@$), $2);
}
| DT_OMIT_NO_REF subnode
{
int generate_symbols; /* enable symbols & fixup support */
int generate_fixups; /* suppress generation of fixups on symbol support */
int auto_label_aliases; /* auto generate labels -> aliases */
+int annotate; /* Level of annotation: 1 for input source location
+ >1 for full input source location. */
static int is_power_of_2(int x)
{
/* Usage related data. */
static const char usage_synopsis[] = "dtc [options] <input file>";
-static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv";
+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv";
static struct option const usage_long_opts[] = {
{"quiet", no_argument, NULL, 'q'},
{"in-format", a_argument, NULL, 'I'},
{"error", a_argument, NULL, 'E'},
{"symbols", no_argument, NULL, '@'},
{"auto-alias", no_argument, NULL, 'A'},
+ {"annotate", no_argument, NULL, 'T'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'},
{NULL, no_argument, NULL, 0x0},
"\n\tEnable/disable errors (prefix with \"no-\")",
"\n\tEnable generation of symbols",
"\n\tEnable auto-alias of labels",
+ "\n\tAnnotate output .dts with input source file and line (-T -T for more details)",
"\n\tPrint this help and exit",
"\n\tPrint version and exit",
NULL,
case 'A':
auto_label_aliases = 1;
break;
+ case 'T':
+ annotate++;
+ break;
case 'h':
usage(NULL);
outform = "dts";
}
}
+ if (annotate && (!streq(inform, "dts") || !streq(outform, "dts")))
+ die("--annotate requires -I dts -O dts\n");
if (streq(inform, "dts"))
dti = dt_from_source(arg);
else if (streq(inform, "fs"))
extern int generate_symbols; /* generate symbols for nodes with labels */
extern int generate_fixups; /* generate fixups */
extern int auto_label_aliases; /* auto generate labels -> aliases */
+extern int annotate; /* annotate .dts with input source location */
#define PHANDLE_LEGACY 0x1
#define PHANDLE_EPAPR 0x2
struct property *next;
struct label *labels;
+ struct srcpos *srcpos;
};
struct node {
struct label *labels;
const struct bus_type *bus;
+ struct srcpos *srcpos;
bool omit_if_unused, is_referenced;
};
void add_label(struct label **labels, char *label);
void delete_labels(struct label **labels);
-struct property *build_property(char *name, struct data val);
+struct property *build_property(char *name, struct data val,
+ struct srcpos *srcpos);
struct property *build_property_delete(char *name);
struct property *chain_property(struct property *first, struct property *list);
struct property *reverse_properties(struct property *first);
-struct node *build_node(struct property *proplist, struct node *children);
-struct node *build_node_delete(void);
+struct node *build_node(struct property *proplist, struct node *children,
+ struct srcpos *srcpos);
+struct node *build_node_delete(struct srcpos *srcpos);
struct node *name_node(struct node *node, char *name);
struct node *omit_node_if_unused(struct node *node);
struct node *reference_node(struct node *node);
val = flat_read_data(dtbuf, proplen);
- return build_property(name, val);
+ return build_property(name, val, NULL);
}
char *flatname;
uint32_t val;
- node = build_node(NULL, NULL);
+ node = build_node(NULL, NULL, NULL);
flatname = flat_read_string(dtbuf);
if (!d)
die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno));
- tree = build_node(NULL, NULL);
+ tree = build_node(NULL, NULL, NULL);
while ((de = readdir(d)) != NULL) {
char *tmpname;
} else {
prop = build_property(xstrdup(de->d_name),
data_copy_file(pfile,
- st.st_size));
+ st.st_size),
+ NULL);
add_property(tree, prop);
fclose(pfile);
}
LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \
fdt_addresses.c fdt_overlay.c
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
+
+libfdt_clean:
+ @$(VECHO) CLEAN "(libfdt)"
+ rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%)
c = fdt_getprop(fdt, nodeoffset, name, &len);
if (!c)
- return 2;
+ return len;
if (len != sizeof(*c))
return -FDT_ERR_BADNCELLS;
int fdt_address_cells(const void *fdt, int nodeoffset)
{
- return fdt_cells(fdt, nodeoffset, "#address-cells");
+ int val;
+
+ val = fdt_cells(fdt, nodeoffset, "#address-cells");
+ if (val == -FDT_ERR_NOTFOUND)
+ return 2;
+ return val;
}
int fdt_size_cells(const void *fdt, int nodeoffset)
{
- return fdt_cells(fdt, nodeoffset, "#size-cells");
+ int val;
+
+ val = fdt_cells(fdt, nodeoffset, "#size-cells");
+ if (val == -FDT_ERR_NOTFOUND)
+ return 1;
+ return val;
}
static inline uint32_t fdt32_ld(const fdt32_t *p)
{
- fdt32_t v;
+ const uint8_t *bp = (const uint8_t *)p;
- memcpy(&v, p, sizeof(v));
- return fdt32_to_cpu(v);
+ return ((uint32_t)bp[0] << 24)
+ | ((uint32_t)bp[1] << 16)
+ | ((uint32_t)bp[2] << 8)
+ | bp[3];
}
static inline uint64_t fdt64_ld(const fdt64_t *p)
{
- fdt64_t v;
-
- memcpy(&v, p, sizeof(v));
- return fdt64_to_cpu(v);
+ const uint8_t *bp = (const uint8_t *)p;
+
+ return ((uint64_t)bp[0] << 56)
+ | ((uint64_t)bp[1] << 48)
+ | ((uint64_t)bp[2] << 40)
+ | ((uint64_t)bp[3] << 32)
+ | ((uint64_t)bp[4] << 24)
+ | ((uint64_t)bp[5] << 16)
+ | ((uint64_t)bp[6] << 8)
+ | bp[7];
}
/**********************************************************************/
*
* returns:
* 0 <= n < FDT_MAX_NCELLS, on success
- * 2, if the node has no #size-cells property
+ * 1, if the node has no #size-cells property
* -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
* #size-cells property
* -FDT_ERR_BADMAGIC,
*/
#include "dtc.h"
+#include "srcpos.h"
/*
* Tree building functions
label->deleted = 1;
}
-struct property *build_property(char *name, struct data val)
+struct property *build_property(char *name, struct data val,
+ struct srcpos *srcpos)
{
struct property *new = xmalloc(sizeof(*new));
new->name = name;
new->val = val;
+ new->srcpos = srcpos_copy(srcpos);
return new;
}
return head;
}
-struct node *build_node(struct property *proplist, struct node *children)
+struct node *build_node(struct property *proplist, struct node *children,
+ struct srcpos *srcpos)
{
struct node *new = xmalloc(sizeof(*new));
struct node *child;
new->proplist = reverse_properties(proplist);
new->children = children;
+ new->srcpos = srcpos_copy(srcpos);
for_each_child(new, child) {
child->parent = new;
return new;
}
-struct node *build_node_delete(void)
+struct node *build_node_delete(struct srcpos *srcpos)
{
struct node *new = xmalloc(sizeof(*new));
memset(new, 0, sizeof(*new));
new->deleted = 1;
+ new->srcpos = srcpos_copy(srcpos);
return new;
}
old_prop->val = new_prop->val;
old_prop->deleted = 0;
+ free(old_prop->srcpos);
+ old_prop->srcpos = new_prop->srcpos;
free(new_prop);
new_prop = NULL;
break;
add_child(old_node, new_child);
}
+ old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos);
+
/* The new node contents are now merged into the old node. Free
* the new node. */
free(new_node);
if (ref[0] == '/') {
d = data_append_data(d, ref, strlen(ref) + 1);
- p = build_property("target-path", d);
+ p = build_property("target-path", d, NULL);
} else {
d = data_add_marker(d, REF_PHANDLE, ref);
d = data_append_integer(d, 0xffffffff, 32);
- p = build_property("target", d);
+ p = build_property("target", d, NULL);
}
xasprintf(&name, "fragment@%u",
next_orphan_fragment++);
name_node(new_node, "__overlay__");
- node = build_node(p, new_node);
+ node = build_node(p, new_node, NULL);
name_node(node, name);
add_child(dt, node);
p->val = d;
} else {
d = data_append_data(empty_data, data, len);
- p = build_property(name, d);
+ p = build_property(name, d, NULL);
add_property(node, p);
}
}
if (!get_property(node, "linux,phandle")
&& (phandle_format & PHANDLE_LEGACY))
- add_property(node, build_property("linux,phandle", d));
+ add_property(node, build_property("linux,phandle", d, NULL));
if (!get_property(node, "phandle")
&& (phandle_format & PHANDLE_EPAPR))
- add_property(node, build_property("phandle", d));
+ add_property(node, build_property("phandle", d, NULL));
/* If the node *does* have a phandle property, we must
* be dealing with a self-referencing phandle, which will be
{
struct node *node;
- node = build_node(NULL, NULL);
+ node = build_node(NULL, NULL, NULL);
name_node(node, xstrdup(name));
add_child(parent, node);
/* insert it */
p = build_property(l->label,
data_copy_mem(node->fullpath,
- strlen(node->fullpath) + 1));
+ strlen(node->fullpath) + 1),
+ NULL);
add_property(an, p);
}
/* This is the list of directories that we search for source files */
static struct search_path *search_path_head, **search_path_tail;
+/* Detect infinite include recursion. */
+#define MAX_SRCFILE_DEPTH (100)
+static int srcfile_depth; /* = 0 */
static char *get_dirname(const char *path)
{
FILE *depfile; /* = NULL */
struct srcfile_state *current_srcfile; /* = NULL */
+static char *initial_path; /* = NULL */
+static int initial_pathlen; /* = 0 */
+static bool initial_cpp = true;
-/* Detect infinite include recursion. */
-#define MAX_SRCFILE_DEPTH (100)
-static int srcfile_depth; /* = 0 */
+static void set_initial_path(char *fname)
+{
+ int i, len = strlen(fname);
+ xasprintf(&initial_path, "%s", fname);
+ initial_pathlen = 0;
+ for (i = 0; i != len; i++)
+ if (initial_path[i] == '/')
+ initial_pathlen++;
+}
+
+static char *shorten_to_initial_path(char *fname)
+{
+ char *p1, *p2, *prevslash1 = NULL;
+ int slashes = 0;
+
+ for (p1 = fname, p2 = initial_path; *p1 && *p2; p1++, p2++) {
+ if (*p1 != *p2)
+ break;
+ if (*p1 == '/') {
+ prevslash1 = p1;
+ slashes++;
+ }
+ }
+ p1 = prevslash1 + 1;
+ if (prevslash1) {
+ int diff = initial_pathlen - slashes, i, j;
+ int restlen = strlen(fname) - (p1 - fname);
+ char *res;
+
+ res = xmalloc((3 * diff) + restlen + 1);
+ for (i = 0, j = 0; i != diff; i++) {
+ res[j++] = '.';
+ res[j++] = '.';
+ res[j++] = '/';
+ }
+ strcpy(res + j, p1);
+ return res;
+ }
+ return NULL;
+}
/**
* Try to open a file in a given directory.
srcfile->colno = 1;
current_srcfile = srcfile;
+
+ if (srcfile_depth == 1)
+ set_initial_path(srcfile->name);
}
bool srcfile_pop(void)
search_path_tail = &node->next;
}
-/*
- * The empty source position.
- */
-
-struct srcpos srcpos_empty = {
- .first_line = 0,
- .first_column = 0,
- .last_line = 0,
- .last_column = 0,
- .file = NULL,
-};
-
void srcpos_update(struct srcpos *pos, const char *text, int len)
{
int i;
srcpos_copy(struct srcpos *pos)
{
struct srcpos *pos_new;
+ struct srcfile_state *srcfile_state;
+
+ if (!pos)
+ return NULL;
pos_new = xmalloc(sizeof(struct srcpos));
+ assert(pos->next == NULL);
memcpy(pos_new, pos, sizeof(struct srcpos));
+ /* allocate without free */
+ srcfile_state = xmalloc(sizeof(struct srcfile_state));
+ memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state));
+ pos_new->file = srcfile_state;
+
return pos_new;
}
+struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail)
+{
+ struct srcpos *p;
+
+ if (!pos)
+ return newtail;
+
+ for (p = pos; p->next != NULL; p = p->next);
+ p->next = newtail;
+ return pos;
+}
+
char *
srcpos_string(struct srcpos *pos)
{
return pos_str;
}
+static char *
+srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
+{
+ char *pos_str, *fname, *first, *rest;
+ bool fresh_fname = false;
+
+ if (!pos) {
+ if (level > 1) {
+ xasprintf(&pos_str, "<no-file>:<no-line>");
+ return pos_str;
+ } else {
+ return NULL;
+ }
+ }
+
+ if (!pos->file)
+ fname = "<no-file>";
+ else if (!pos->file->name)
+ fname = "<no-filename>";
+ else if (level > 1)
+ fname = pos->file->name;
+ else {
+ fname = shorten_to_initial_path(pos->file->name);
+ if (fname)
+ fresh_fname = true;
+ else
+ fname = pos->file->name;
+ }
+
+ if (level > 1)
+ xasprintf(&first, "%s:%d:%d-%d:%d", fname,
+ pos->first_line, pos->first_column,
+ pos->last_line, pos->last_column);
+ else
+ xasprintf(&first, "%s:%d", fname,
+ first_line ? pos->first_line : pos->last_line);
+
+ if (fresh_fname)
+ free(fname);
+
+ if (pos->next != NULL) {
+ rest = srcpos_string_comment(pos->next, first_line, level);
+ xasprintf(&pos_str, "%s, %s", first, rest);
+ free(first);
+ free(rest);
+ } else {
+ pos_str = first;
+ }
+
+ return pos_str;
+}
+
+char *srcpos_string_first(struct srcpos *pos, int level)
+{
+ return srcpos_string_comment(pos, true, level);
+}
+
+char *srcpos_string_last(struct srcpos *pos, int level)
+{
+ return srcpos_string_comment(pos, false, level);
+}
+
void srcpos_verror(struct srcpos *pos, const char *prefix,
const char *fmt, va_list va)
{
{
current_srcfile->name = f;
current_srcfile->lineno = l;
+
+ if (initial_cpp) {
+ initial_cpp = false;
+ set_initial_path(f);
+ }
}
int last_line;
int last_column;
struct srcfile_state *file;
+ struct srcpos *next;
};
#define YYLTYPE struct srcpos
YYRHSLOC(Rhs, 0).last_column; \
(Current).file = YYRHSLOC (Rhs, 0).file; \
} \
+ (Current).next = NULL; \
} while (0)
-/*
- * Fictional source position used for IR nodes that are
- * created without otherwise knowing a true source position.
- * For example,constant definitions from the command line.
- */
-extern struct srcpos srcpos_empty;
-
extern void srcpos_update(struct srcpos *pos, const char *text, int len);
extern struct srcpos *srcpos_copy(struct srcpos *pos);
+extern struct srcpos *srcpos_extend(struct srcpos *new_srcpos,
+ struct srcpos *old_srcpos);
extern char *srcpos_string(struct srcpos *pos);
+extern char *srcpos_string_first(struct srcpos *pos, int level);
+extern char *srcpos_string_last(struct srcpos *pos, int level);
+
extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix,
const char *fmt, va_list va);
static void write_propval_string(FILE *f, const char *s, size_t len)
{
const char *end = s + len - 1;
+
+ if (!len)
+ return;
+
assert(*end == '\0');
fprintf(f, "\"");
for (; p < end; p += width) {
switch (width) {
case 1:
- fprintf(f, " %02"PRIx8, *(const uint8_t*)p);
+ fprintf(f, "%02"PRIx8, *(const uint8_t*)p);
break;
case 2:
- fprintf(f, " 0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p));
+ fprintf(f, "0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p));
break;
case 4:
- fprintf(f, " 0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p));
+ fprintf(f, "0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p));
break;
case 8:
- fprintf(f, " 0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p));
+ fprintf(f, "0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p));
break;
}
+ if (p + width < end)
+ fputc(' ', f);
}
}
[TYPE_STRING] = "",
};
static const char *delim_end[] = {
- [TYPE_UINT8] = " ]",
- [TYPE_UINT16] = " >",
- [TYPE_UINT32] = " >",
- [TYPE_UINT64] = " >",
+ [TYPE_UINT8] = "]",
+ [TYPE_UINT16] = ">",
+ [TYPE_UINT32] = ">",
+ [TYPE_UINT64] = ">",
[TYPE_STRING] = "",
};
struct marker *m = prop->val.markers;
struct marker dummy_marker;
enum markertype emit_type = TYPE_NONE;
+ char *srcstr;
if (len == 0) {
- fprintf(f, ";\n");
+ fprintf(f, ";");
+ if (annotate) {
+ srcstr = srcpos_string_first(prop->srcpos, annotate);
+ if (srcstr) {
+ fprintf(f, " /* %s */", srcstr);
+ free(srcstr);
+ }
+ }
+ fprintf(f, "\n");
return;
}
- fprintf(f, " = ");
+ fprintf(f, " =");
if (!next_type_marker(m)) {
/* data type information missing, need to guess */
m = &dummy_marker;
}
- struct marker *m_label = prop->val.markers;
for_each_marker(m) {
- size_t chunk_len;
+ size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
+ size_t data_len = type_marker_length(m) ? : len - m->offset;
const char *p = &prop->val.val[m->offset];
- if (!has_data_type_information(m))
- continue;
-
- chunk_len = type_marker_length(m);
- if (!chunk_len)
- chunk_len = len - m->offset;
-
- if (emit_type != TYPE_NONE)
- fprintf(f, "%s, ", delim_end[emit_type]);
- emit_type = m->type;
-
- for_each_marker_of_type(m_label, LABEL) {
- if (m_label->offset > m->offset)
- break;
- fprintf(f, "%s: ", m_label->ref);
- }
-
- fprintf(f, "%s", delim_start[emit_type]);
+ if (has_data_type_information(m)) {
+ emit_type = m->type;
+ fprintf(f, " %s", delim_start[emit_type]);
+ } else if (m->type == LABEL)
+ fprintf(f, " %s:", m->ref);
+ else if (m->offset)
+ fputc(' ', f);
- if (chunk_len <= 0)
+ if (emit_type == TYPE_NONE) {
+ assert(chunk_len == 0);
continue;
+ }
switch(emit_type) {
case TYPE_UINT16:
default:
write_propval_int(f, p, chunk_len, 1);
}
- }
- /* Wrap up any labels at the end of the value */
- for_each_marker_of_type(m_label, LABEL) {
- assert (m_label->offset == len);
- fprintf(f, " %s:", m_label->ref);
+ if (chunk_len == data_len) {
+ size_t pos = m->offset + chunk_len;
+ fprintf(f, pos == len ? "%s" : "%s,",
+ delim_end[emit_type] ? : "");
+ emit_type = TYPE_NONE;
+ }
}
-
- fprintf(f, "%s;\n", delim_end[emit_type] ? : "");
+ fprintf(f, ";");
+ if (annotate) {
+ srcstr = srcpos_string_first(prop->srcpos, annotate);
+ if (srcstr) {
+ fprintf(f, " /* %s */", srcstr);
+ free(srcstr);
+ }
+ }
+ fprintf(f, "\n");
}
static void write_tree_source_node(FILE *f, struct node *tree, int level)
struct property *prop;
struct node *child;
struct label *l;
+ char *srcstr;
write_prefix(f, level);
for_each_label(tree->labels, l)
fprintf(f, "%s: ", l->label);
if (tree->name && (*tree->name))
- fprintf(f, "%s {\n", tree->name);
+ fprintf(f, "%s {", tree->name);
else
- fprintf(f, "/ {\n");
+ fprintf(f, "/ {");
+
+ if (annotate) {
+ srcstr = srcpos_string_first(tree->srcpos, annotate);
+ if (srcstr) {
+ fprintf(f, " /* %s */", srcstr);
+ free(srcstr);
+ }
+ }
+ fprintf(f, "\n");
for_each_property(tree, prop) {
write_prefix(f, level+1);
write_tree_source_node(f, child, level+1);
}
write_prefix(f, level);
- fprintf(f, "};\n");
+ fprintf(f, "};");
+ if (annotate) {
+ srcstr = srcpos_string_last(tree->srcpos, annotate);
+ if (srcstr) {
+ fprintf(f, " /* %s */", srcstr);
+ free(srcstr);
+ }
+ }
+ fprintf(f, "\n");
}
-
void dt_to_source(FILE *f, struct dt_info *dti)
{
struct reserve_info *re;
return d;
}
-/* based in part from (3) vsnprintf */
-int xasprintf(char **strp, const char *fmt, ...)
+int xavsprintf_append(char **strp, const char *fmt, va_list ap)
{
- int n, size = 128; /* start with 128 bytes */
+ int n, size = 0; /* start with 128 bytes */
char *p;
- va_list ap;
+ va_list ap_copy;
- /* initial pointer is NULL making the fist realloc to be malloc */
- p = NULL;
- while (1) {
- p = xrealloc(p, size);
+ p = *strp;
+ if (p)
+ size = strlen(p);
- /* Try to print in the allocated space. */
- va_start(ap, fmt);
- n = vsnprintf(p, size, fmt, ap);
- va_end(ap);
+ va_copy(ap_copy, ap);
+ n = vsnprintf(NULL, 0, fmt, ap_copy) + 1;
+ va_end(ap_copy);
+
+ p = xrealloc(p, size + n);
+
+ n = vsnprintf(p + size, n, fmt, ap);
- /* If that worked, return the string. */
- if (n > -1 && n < size)
- break;
- /* Else try again with more space. */
- if (n > -1) /* glibc 2.1 */
- size = n + 1; /* precisely what is needed */
- else /* glibc 2.0 */
- size *= 2; /* twice the old size */
- }
*strp = p;
return strlen(p);
}
+int xasprintf_append(char **strp, const char *fmt, ...)
+{
+ int n;
+ va_list ap;
+
+ va_start(ap, fmt);
+ n = xavsprintf_append(strp, fmt, ap);
+ va_end(ap);
+
+ return n;
+}
+
+int xasprintf(char **strp, const char *fmt, ...)
+{
+ int n;
+ va_list ap;
+
+ *strp = NULL;
+
+ va_start(ap, fmt);
+ n = xavsprintf_append(strp, fmt, ap);
+ va_end(ap);
+
+ return n;
+}
+
char *join_path(const char *path, const char *name)
{
int lenp = strlen(path);
extern char *xstrdup(const char *s);
extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
+extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...);
+extern int xavsprintf_append(char **strp, const char *fmt, va_list ap);
extern char *join_path(const char *path, const char *name);
/**
-#define DTC_VERSION "DTC 1.4.7-gc86da84d"
+#define DTC_VERSION "DTC 1.4.7-gf267e674"