mirror of
https://github.com/torvalds/linux.git
synced 2024-12-26 12:52:30 +00:00
scripts/dtc: Update to upstream version v1.4.7-57-gf267e674d145
This adds the following commits from upstream: f267e674d145 checks: Fix crash with multiple source annotations 3616b9a811b6 checks: Use source position information for check failures 2bdbd07a1223 checks: Make each message output atomic a1eff70c02cf util: Add xa{v}sprintf_append functions 82a52ce4573b libfdt: Add a test for fdt_getprop_by_offset() 607b8586b383 PEP8 / Flake8 cleanups for setup.py f9c0a425b648 Remove broken objdir / srcdir support 5182b5e6f28c pylibfdt: Use common PREFIX variable d45bf1f5f2a6 Refine make tests_clean target 99284c4db9cb Refine pylibfdt_clean target a4629cfaedfb Refine libfdt_clean target 08380fc43aa2 tests: Use modern octal literals for Python 8113c00b99d3 pylibfdt: Allow switch to Python 3 via environment variable PYTHON 11738cf01f15 libfdt: Don't use memcpy to handle unaligned reads on ARM 86a288a73670 checks: Restructure check_msg to decrease indentation 5667e7ef9a9a annotations: add the annotation functionality 8e20ccf52f90 annotations: add positions ca930e20bb54 tests: Don't lose errors from make checkm 43366bb4eeee tests: Property count valgrind errors in wrapped tests 5062516fb8cb srcpos: Remove srcpos_empty a3143fafbf83 Revert "annotations: add positions" 403cc79f06a1 checks: Update SPI bus check for 'spi-slave' baa1d2cf7894 annotations: add positions ff2ad38f6a5a Merge remote-tracking branch 'origin/pr/18' aa7254d9cb17 libfdt: return correct value if #size-cells property is not present 49903aed7783 use ptrdiff_t modifier for printing pointer differences da2b691ccf68 treesource: Fix dts output for phandles in middle of a sequence of ints 8f8b77a0d62d tests: Wrap check_align() calls with base_run_test() 522d81d572f2 Fix dts output with a REF_PATH marker e45198c98359 Added test cases for target references 0fcffda15e9f Merge nodes with local target label references 1e4a0928f3b3 pylibfdt: Don't have setup.py depend on where it's invoked from ca399b14956f pylibfdt: Eliminate run_setup make function 98972f1b3e33 pylibfdt: Improved version extraction 7ba2be6cda5f pylibfdt: Don't silence setup.py when V=1 7691f9d39301 pylibfdt: Make SETUP make variable 855b9963def9 pylibfdt: Simpler CFLAGS handling 47cafbeeb977 pylibfdt: Link extension module with libfdt rather than rebuilding dd695d6afb19 pylibfdt: Correctly set build output directory 59327523d0d8 pylibfdt: We don't need include files from the base directory e84742aa7b93 checks: fix simple-bus compatible matching 8c59a97ce096 Fix missing labels when emitting dts format d448f9a5fd94 Revert dts output formatting changes of spaces around brackets Signed-off-by: Rob Herring <robh@kernel.org>
This commit is contained in:
parent
e8b1dee214
commit
c2e7075ca8
@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "dtc.h"
|
||||
#include "srcpos.h"
|
||||
|
||||
#ifdef TRACE_CHECKS
|
||||
#define TRACE(c, ...) \
|
||||
@ -78,23 +79,56 @@ static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti,
|
||||
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))) {
|
||||
fprintf(stderr, "%s: %s (%s): ",
|
||||
strcmp(dti->outname, "-") ? dti->outname : "<stdout>",
|
||||
(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 (!(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);
|
||||
}
|
||||
|
||||
xasprintf_append(&str, ": %s (%s): ",
|
||||
(c->error) ? "ERROR" : "Warning", c->name);
|
||||
|
||||
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, ...) \
|
||||
@ -910,7 +944,7 @@ static bool node_is_compatible(struct node *node, const char *compat)
|
||||
|
||||
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;
|
||||
@ -921,7 +955,8 @@ static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct
|
||||
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)
|
||||
{
|
||||
@ -1035,6 +1070,7 @@ static const struct bus_type spi_bus = {
|
||||
|
||||
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;
|
||||
@ -1063,7 +1099,9 @@ static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct no
|
||||
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");
|
||||
@ -1082,6 +1120,9 @@ static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node
|
||||
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;
|
||||
|
@ -213,14 +213,14 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
|
||||
<*>\&{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} {
|
||||
|
@ -70,7 +70,8 @@ extern bool treesource_error;
|
||||
%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
|
||||
@ -83,6 +84,7 @@ extern bool treesource_error;
|
||||
%type <data> bytestring
|
||||
%type <prop> propdef
|
||||
%type <proplist> proplist
|
||||
%type <labelref> dt_ref
|
||||
|
||||
%type <node> devicetree
|
||||
%type <node> nodedef
|
||||
@ -158,6 +160,8 @@ memreserve:
|
||||
}
|
||||
;
|
||||
|
||||
dt_ref: DT_LABEL_REF | DT_PATH_REF;
|
||||
|
||||
devicetree:
|
||||
'/' nodedef
|
||||
{
|
||||
@ -167,7 +171,7 @@ devicetree:
|
||||
{
|
||||
$$ = merge_nodes($1, $3);
|
||||
}
|
||||
| DT_REF nodedef
|
||||
| dt_ref nodedef
|
||||
{
|
||||
/*
|
||||
* We rely on the rule being always:
|
||||
@ -176,9 +180,12 @@ devicetree:
|
||||
*/
|
||||
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);
|
||||
|
||||
@ -189,7 +196,7 @@ devicetree:
|
||||
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:
|
||||
@ -208,7 +215,26 @@ devicetree:
|
||||
}
|
||||
$$ = $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);
|
||||
|
||||
@ -220,7 +246,7 @@ devicetree:
|
||||
|
||||
$$ = $1;
|
||||
}
|
||||
| devicetree DT_OMIT_NO_REF DT_REF ';'
|
||||
| devicetree DT_OMIT_NO_REF dt_ref ';'
|
||||
{
|
||||
struct node *target = get_node_by_ref($1, $3);
|
||||
|
||||
@ -237,7 +263,7 @@ devicetree:
|
||||
nodedef:
|
||||
'{' proplist subnodes '}' ';'
|
||||
{
|
||||
$$ = build_node($2, $3);
|
||||
$$ = build_node($2, $3, &@$);
|
||||
}
|
||||
;
|
||||
|
||||
@ -255,11 +281,11 @@ proplist:
|
||||
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 ';'
|
||||
{
|
||||
@ -285,7 +311,7 @@ propdata:
|
||||
{
|
||||
$$ = 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);
|
||||
@ -383,7 +409,7 @@ arrayprefix:
|
||||
|
||||
$$.data = data_append_integer($1.data, $2, $1.bits);
|
||||
}
|
||||
| arrayprefix DT_REF
|
||||
| arrayprefix dt_ref
|
||||
{
|
||||
uint64_t val = ~0ULL >> (64 - $1.bits);
|
||||
|
||||
@ -540,7 +566,7 @@ subnode:
|
||||
}
|
||||
| DT_DEL_NODE DT_PROPNODENAME ';'
|
||||
{
|
||||
$$ = name_node(build_node_delete(), $2);
|
||||
$$ = name_node(build_node_delete(&@$), $2);
|
||||
}
|
||||
| DT_OMIT_NO_REF subnode
|
||||
{
|
||||
|
@ -35,6 +35,8 @@ int phandle_format = PHANDLE_EPAPR; /* Use linux,phandle or phandle properties *
|
||||
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)
|
||||
{
|
||||
@ -60,7 +62,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
|
||||
|
||||
/* 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'},
|
||||
@ -81,6 +83,7 @@ static struct option const usage_long_opts[] = {
|
||||
{"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},
|
||||
@ -117,6 +120,7 @@ static const char * const usage_opts_help[] = {
|
||||
"\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,
|
||||
@ -264,6 +268,9 @@ int main(int argc, char *argv[])
|
||||
case 'A':
|
||||
auto_label_aliases = 1;
|
||||
break;
|
||||
case 'T':
|
||||
annotate++;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
usage(NULL);
|
||||
@ -302,6 +309,8 @@ int main(int argc, char *argv[])
|
||||
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"))
|
||||
|
@ -58,6 +58,7 @@ extern int phandle_format; /* Use linux,phandle or phandle properties */
|
||||
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
|
||||
@ -158,6 +159,7 @@ struct property {
|
||||
struct property *next;
|
||||
|
||||
struct label *labels;
|
||||
struct srcpos *srcpos;
|
||||
};
|
||||
|
||||
struct node {
|
||||
@ -177,6 +179,7 @@ struct node {
|
||||
|
||||
struct label *labels;
|
||||
const struct bus_type *bus;
|
||||
struct srcpos *srcpos;
|
||||
|
||||
bool omit_if_unused, is_referenced;
|
||||
};
|
||||
@ -205,13 +208,15 @@ struct node {
|
||||
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);
|
||||
|
@ -692,7 +692,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf,
|
||||
|
||||
val = flat_read_data(dtbuf, proplen);
|
||||
|
||||
return build_property(name, val);
|
||||
return build_property(name, val, NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -750,7 +750,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
|
||||
char *flatname;
|
||||
uint32_t val;
|
||||
|
||||
node = build_node(NULL, NULL);
|
||||
node = build_node(NULL, NULL, NULL);
|
||||
|
||||
flatname = flat_read_string(dtbuf);
|
||||
|
||||
|
@ -34,7 +34,7 @@ static struct node *read_fstree(const char *dirname)
|
||||
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;
|
||||
@ -60,7 +60,8 @@ static struct node *read_fstree(const char *dirname)
|
||||
} 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);
|
||||
}
|
||||
|
@ -9,3 +9,7 @@ LIBFDT_VERSION = version.lds
|
||||
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)/%)
|
||||
|
@ -64,7 +64,7 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
|
||||
|
||||
c = fdt_getprop(fdt, nodeoffset, name, &len);
|
||||
if (!c)
|
||||
return 2;
|
||||
return len;
|
||||
|
||||
if (len != sizeof(*c))
|
||||
return -FDT_ERR_BADNCELLS;
|
||||
@ -78,10 +78,20 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -163,18 +163,26 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
|
||||
|
||||
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;
|
||||
const uint8_t *bp = (const uint8_t *)p;
|
||||
|
||||
memcpy(&v, p, sizeof(v));
|
||||
return fdt64_to_cpu(v);
|
||||
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];
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
@ -1145,7 +1153,7 @@ int fdt_address_cells(const void *fdt, int nodeoffset);
|
||||
*
|
||||
* 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,
|
||||
|
@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "dtc.h"
|
||||
#include "srcpos.h"
|
||||
|
||||
/*
|
||||
* Tree building functions
|
||||
@ -50,7 +51,8 @@ void delete_labels(struct label **labels)
|
||||
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));
|
||||
|
||||
@ -58,6 +60,7 @@ struct property *build_property(char *name, struct data val)
|
||||
|
||||
new->name = name;
|
||||
new->val = val;
|
||||
new->srcpos = srcpos_copy(srcpos);
|
||||
|
||||
return new;
|
||||
}
|
||||
@ -97,7 +100,8 @@ struct property *reverse_properties(struct property *first)
|
||||
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;
|
||||
@ -106,6 +110,7 @@ struct node *build_node(struct property *proplist, struct node *children)
|
||||
|
||||
new->proplist = reverse_properties(proplist);
|
||||
new->children = children;
|
||||
new->srcpos = srcpos_copy(srcpos);
|
||||
|
||||
for_each_child(new, child) {
|
||||
child->parent = new;
|
||||
@ -114,13 +119,14 @@ struct node *build_node(struct property *proplist, struct node *children)
|
||||
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;
|
||||
}
|
||||
@ -183,6 +189,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
|
||||
|
||||
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;
|
||||
@ -223,6 +231,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
|
||||
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);
|
||||
@ -241,18 +251,18 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
|
||||
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);
|
||||
@ -351,7 +361,7 @@ void append_to_property(struct node *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);
|
||||
}
|
||||
}
|
||||
@ -609,11 +619,11 @@ cell_t get_node_phandle(struct node *root, struct node *node)
|
||||
|
||||
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
|
||||
@ -787,7 +797,7 @@ static struct node *build_and_name_child_node(struct node *parent, char *name)
|
||||
{
|
||||
struct node *node;
|
||||
|
||||
node = build_node(NULL, NULL);
|
||||
node = build_node(NULL, NULL, NULL);
|
||||
name_node(node, xstrdup(name));
|
||||
add_child(parent, node);
|
||||
|
||||
@ -849,7 +859,8 @@ static void generate_label_tree_internal(struct dt_info *dti,
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,9 @@ struct search_path {
|
||||
/* 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)
|
||||
{
|
||||
@ -51,11 +54,51 @@ 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.
|
||||
@ -157,6 +200,9 @@ void srcfile_push(const char *fname)
|
||||
srcfile->colno = 1;
|
||||
|
||||
current_srcfile = srcfile;
|
||||
|
||||
if (srcfile_depth == 1)
|
||||
set_initial_path(srcfile->name);
|
||||
}
|
||||
|
||||
bool srcfile_pop(void)
|
||||
@ -197,18 +243,6 @@ void srcfile_add_search_path(const char *dirname)
|
||||
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;
|
||||
@ -234,13 +268,35 @@ struct srcpos *
|
||||
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)
|
||||
{
|
||||
@ -266,6 +322,68 @@ 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)
|
||||
{
|
||||
@ -294,4 +412,9 @@ void srcpos_set_line(char *f, int l)
|
||||
{
|
||||
current_srcfile->name = f;
|
||||
current_srcfile->lineno = l;
|
||||
|
||||
if (initial_cpp) {
|
||||
initial_cpp = false;
|
||||
set_initial_path(f);
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +74,7 @@ struct srcpos {
|
||||
int last_line;
|
||||
int last_column;
|
||||
struct srcfile_state *file;
|
||||
struct srcpos *next;
|
||||
};
|
||||
|
||||
#define YYLTYPE struct srcpos
|
||||
@ -93,19 +94,18 @@ 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);
|
||||
|
@ -64,6 +64,10 @@ static bool isstring(char c)
|
||||
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, "\"");
|
||||
@ -118,18 +122,20 @@ static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,10 +168,10 @@ static const char *delim_start[] = {
|
||||
[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] = "",
|
||||
};
|
||||
|
||||
@ -208,13 +214,22 @@ static void write_propval(FILE *f, struct property *prop)
|
||||
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 */
|
||||
@ -225,33 +240,24 @@ static void write_propval(FILE *f, struct property *prop)
|
||||
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))
|
||||
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 (emit_type == TYPE_NONE) {
|
||||
assert(chunk_len == 0);
|
||||
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 (chunk_len <= 0)
|
||||
continue;
|
||||
|
||||
switch(emit_type) {
|
||||
case TYPE_UINT16:
|
||||
write_propval_int(f, p, chunk_len, 2);
|
||||
@ -268,15 +274,23 @@ static void write_propval(FILE *f, struct property *prop)
|
||||
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)
|
||||
@ -284,14 +298,24 @@ 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);
|
||||
@ -305,10 +329,17 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level)
|
||||
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;
|
||||
|
@ -46,36 +46,54 @@ char *xstrdup(const char *s)
|
||||
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);
|
||||
|
@ -72,6 +72,8 @@ static inline void *xrealloc(void *p, size_t len)
|
||||
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);
|
||||
|
||||
/**
|
||||
|
@ -1 +1 @@
|
||||
#define DTC_VERSION "DTC 1.4.7-gc86da84d"
|
||||
#define DTC_VERSION "DTC 1.4.7-gf267e674"
|
||||
|
Loading…
Reference in New Issue
Block a user