diff options
Diffstat (limited to 'scripts/dtc')
35 files changed, 5683 insertions, 2185 deletions
diff --git a/scripts/dtc/.gitignore b/scripts/dtc/.gitignore index 095acb49a37..cdabdc95a6e 100644 --- a/scripts/dtc/.gitignore +++ b/scripts/dtc/.gitignore @@ -2,4 +2,3 @@ dtc  dtc-lexer.lex.c  dtc-parser.tab.c  dtc-parser.tab.h - diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile index 01cdb36fc58..2a48022c41e 100644 --- a/scripts/dtc/Makefile +++ b/scripts/dtc/Makefile @@ -4,7 +4,7 @@ hostprogs-y	:= dtc  always		:= $(hostprogs-y)  dtc-objs	:= dtc.o flattree.o fstree.o data.o livetree.o treesource.o \ -		   srcpos.o checks.o +		   srcpos.o checks.o util.o  dtc-objs	+= dtc-lexer.lex.o dtc-parser.tab.o  # Source files need to get at the userspace version of libfdt_env.h to compile @@ -19,36 +19,13 @@ HOSTCFLAGS_fstree.o := $(HOSTCFLAGS_DTC)  HOSTCFLAGS_livetree.o := $(HOSTCFLAGS_DTC)  HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC)  HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_util.o := $(HOSTCFLAGS_DTC)  HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC)  HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)  # dependencies on generated files need to be listed explicitly -$(obj)/dtc-parser.tab.o: $(obj)/dtc-parser.tab.c $(obj)/dtc-parser.tab.h -$(obj)/dtc-lexer.lex.o:  $(obj)/dtc-lexer.lex.c $(obj)/dtc-parser.tab.h +$(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h -targets += dtc-parser.tab.c dtc-lexer.lex.c - -clean-files += dtc-parser.tab.h - -# GENERATE_PARSER := 1		# Uncomment to rebuild flex/bison output - -ifdef GENERATE_PARSER - -BISON = bison -FLEX = flex - -quiet_cmd_bison = BISON   $@ -      cmd_bison = $(BISON) -o$@ -d $<; cp $@ $@_shipped -quiet_cmd_flex = FLEX    $@ -      cmd_flex = $(FLEX) -o$@ $<; cp $@ $@_shipped - -$(obj)/dtc-parser.tab.c: $(src)/dtc-parser.y FORCE -        $(call if_changed,bison) - -$(obj)/dtc-parser.tab.h: $(obj)/dtc-parser.tab.c - -$(obj)/dtc-lexer.lex.c: $(src)/dtc-lexer.l FORCE -        $(call if_changed,flex) - -endif +# generated files need to be cleaned explicitly +clean-files	:= dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc index 6ddf9ecac66..bece49b3553 100644 --- a/scripts/dtc/Makefile.dtc +++ b/scripts/dtc/Makefile.dtc @@ -3,7 +3,16 @@  # This is not a complete Makefile of itself.  Instead, it is designed to  # be easily embeddable into other systems of Makefiles.  # -DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \ -	checks.c +DTC_SRCS = \ +	checks.c \ +	data.c \ +	dtc.c \ +	flattree.c \ +	fstree.c \ +	livetree.c \ +	srcpos.c \ +	treesource.c \ +	util.c +  DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c  DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o) diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index 95485796f25..ee96a2519ef 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c @@ -31,12 +31,6 @@  #define TRACE(c, fmt, ...)	do { } while (0)  #endif -enum checklevel { -	IGNORE = 0, -	WARN = 1, -	ERROR = 2, -}; -  enum checkstatus {  	UNCHECKED = 0,  	PREREQ, @@ -57,14 +51,14 @@ struct check {  	node_check_fn node_fn;  	prop_check_fn prop_fn;  	void *data; -	enum checklevel level; +	bool warn, error;  	enum checkstatus status;  	int inprogress;  	int num_prereqs;  	struct check **prereq;  }; -#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \ +#define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...)	       \  	static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \  	static struct check nm = { \  		.name = #nm, \ @@ -72,20 +66,37 @@ struct check {  		.node_fn = (nfn), \  		.prop_fn = (pfn), \  		.data = (d), \ -		.level = (lvl), \ +		.warn = (w), \ +		.error = (e), \  		.status = UNCHECKED, \  		.num_prereqs = ARRAY_SIZE(nm##_prereqs), \  		.prereq = nm##_prereqs, \  	}; - -#define TREE_CHECK(nm, d, lvl, ...) \ -	CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__) -#define NODE_CHECK(nm, d, lvl, ...) \ -	CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__) -#define PROP_CHECK(nm, d, lvl, ...) \ -	CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__) -#define BATCH_CHECK(nm, lvl, ...) \ -	CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__) +#define WARNING(nm, tfn, nfn, pfn, d, ...) \ +	CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__) +#define ERROR(nm, tfn, nfn, pfn, d, ...) \ +	CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__) +#define CHECK(nm, tfn, nfn, pfn, d, ...) \ +	CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, false, __VA_ARGS__) + +#define TREE_WARNING(nm, d, ...) \ +	WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) +#define TREE_ERROR(nm, d, ...) \ +	ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) +#define TREE_CHECK(nm, d, ...) \ +	CHECK(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) +#define NODE_WARNING(nm, d, ...) \ +	WARNING(nm, NULL, check_##nm, NULL, d,  __VA_ARGS__) +#define NODE_ERROR(nm, d, ...) \ +	ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) +#define NODE_CHECK(nm, d, ...) \ +	CHECK(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) +#define PROP_WARNING(nm, d, ...) \ +	WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) +#define PROP_ERROR(nm, d, ...) \ +	ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) +#define PROP_CHECK(nm, d, ...) \ +	CHECK(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)  #ifdef __GNUC__  static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); @@ -95,13 +106,13 @@ static inline void check_msg(struct check *c, const char *fmt, ...)  	va_list ap;  	va_start(ap, fmt); -	if ((c->level < WARN) || (c->level <= quiet)) -		return; /* Suppress message */ - -	fprintf(stderr, "%s (%s): ", -		(c->level == ERROR) ? "ERROR" : "Warning", c->name); -	vfprintf(stderr, fmt, ap); -	fprintf(stderr, "\n"); +	if ((c->warn && (quiet < 1)) +	    || (c->error && (quiet < 2))) { +		fprintf(stderr, "%s (%s): ", +			(c->error) ? "ERROR" : "Warning", c->name); +		vfprintf(stderr, fmt, ap); +		fprintf(stderr, "\n"); +	}  }  #define FAIL(c, ...) \ @@ -167,7 +178,7 @@ static int run_check(struct check *c, struct node *dt)  out:  	c->inprogress = 0; -	if ((c->status != PASSED) && (c->level == ERROR)) +	if ((c->status != PASSED) && (c->error))  		error = 1;  	return error;  } @@ -176,6 +187,13 @@ out:   * Utility check functions   */ +/* A check which always fails, for testing purposes only */ +static inline void check_always_fail(struct check *c, struct node *dt) +{ +	FAIL(c, "always_fail check"); +} +TREE_CHECK(always_fail, NULL); +  static void check_is_string(struct check *c, struct node *root,  			    struct node *node)  { @@ -190,8 +208,10 @@ static void check_is_string(struct check *c, struct node *root,  		FAIL(c, "\"%s\" property in %s is not a string",  		     propname, node->fullpath);  } -#define CHECK_IS_STRING(nm, propname, lvl) \ -	CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl)) +#define WARNING_IF_NOT_STRING(nm, propname) \ +	WARNING(nm, NULL, check_is_string, NULL, (propname)) +#define ERROR_IF_NOT_STRING(nm, propname) \ +	ERROR(nm, NULL, check_is_string, NULL, (propname))  static void check_is_cell(struct check *c, struct node *root,  			  struct node *node) @@ -207,8 +227,10 @@ static void check_is_cell(struct check *c, struct node *root,  		FAIL(c, "\"%s\" property in %s is not a single cell",  		     propname, node->fullpath);  } -#define CHECK_IS_CELL(nm, propname, lvl) \ -	CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl)) +#define WARNING_IF_NOT_CELL(nm, propname) \ +	WARNING(nm, NULL, check_is_cell, NULL, (propname)) +#define ERROR_IF_NOT_CELL(nm, propname) \ +	ERROR(nm, NULL, check_is_cell, NULL, (propname))  /*   * Structural check functions @@ -227,20 +249,24 @@ static void check_duplicate_node_names(struct check *c, struct node *dt,  				FAIL(c, "Duplicate node name %s",  				     child->fullpath);  } -NODE_CHECK(duplicate_node_names, NULL, ERROR); +NODE_ERROR(duplicate_node_names, NULL);  static void check_duplicate_property_names(struct check *c, struct node *dt,  					   struct node *node)  {  	struct property *prop, *prop2; -	for_each_property(node, prop) -		for (prop2 = prop->next; prop2; prop2 = prop2->next) +	for_each_property(node, prop) { +		for (prop2 = prop->next; prop2; prop2 = prop2->next) { +			if (prop2->deleted) +				continue;  			if (streq(prop->name, prop2->name))  				FAIL(c, "Duplicate property name %s in %s",  				     prop->name, node->fullpath); +		} +	}  } -NODE_CHECK(duplicate_property_names, NULL, ERROR); +NODE_ERROR(duplicate_property_names, NULL);  #define LOWERCASE	"abcdefghijklmnopqrstuvwxyz"  #define UPPERCASE	"ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -256,7 +282,7 @@ static void check_node_name_chars(struct check *c, struct node *dt,  		FAIL(c, "Bad character '%c' in node %s",  		     node->name[n], node->fullpath);  } -NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR); +NODE_ERROR(node_name_chars, PROPNODECHARS "@");  static void check_node_name_format(struct check *c, struct node *dt,  				   struct node *node) @@ -265,7 +291,7 @@ static void check_node_name_format(struct check *c, struct node *dt,  		FAIL(c, "Node %s has multiple '@' characters in name",  		     node->fullpath);  } -NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars); +NODE_ERROR(node_name_format, NULL, &node_name_chars);  static void check_property_name_chars(struct check *c, struct node *dt,  				      struct node *node, struct property *prop) @@ -276,34 +302,114 @@ static void check_property_name_chars(struct check *c, struct node *dt,  		FAIL(c, "Bad character '%c' in property name \"%s\", node %s",  		     prop->name[n], prop->name, node->fullpath);  } -PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR); +PROP_ERROR(property_name_chars, PROPNODECHARS); + +#define DESCLABEL_FMT	"%s%s%s%s%s" +#define DESCLABEL_ARGS(node,prop,mark)		\ +	((mark) ? "value of " : ""),		\ +	((prop) ? "'" : ""), \ +	((prop) ? (prop)->name : ""), \ +	((prop) ? "' in " : ""), (node)->fullpath + +static void check_duplicate_label(struct check *c, struct node *dt, +				  const char *label, struct node *node, +				  struct property *prop, struct marker *mark) +{ +	struct node *othernode = NULL; +	struct property *otherprop = NULL; +	struct marker *othermark = NULL; + +	othernode = get_node_by_label(dt, label); + +	if (!othernode) +		otherprop = get_property_by_label(dt, label, &othernode); +	if (!othernode) +		othermark = get_marker_label(dt, label, &othernode, +					       &otherprop); + +	if (!othernode) +		return; + +	if ((othernode != node) || (otherprop != prop) || (othermark != mark)) +		FAIL(c, "Duplicate label '%s' on " DESCLABEL_FMT +		     " and " DESCLABEL_FMT, +		     label, DESCLABEL_ARGS(node, prop, mark), +		     DESCLABEL_ARGS(othernode, otherprop, othermark)); +} + +static void check_duplicate_label_node(struct check *c, struct node *dt, +				       struct node *node) +{ +	struct label *l; + +	for_each_label(node->labels, l) +		check_duplicate_label(c, dt, l->label, node, NULL, NULL); +} +static void check_duplicate_label_prop(struct check *c, struct node *dt, +				       struct node *node, struct property *prop) +{ +	struct marker *m = prop->val.markers; +	struct label *l; + +	for_each_label(prop->labels, l) +		check_duplicate_label(c, dt, l->label, node, prop, NULL); + +	for_each_marker_of_type(m, LABEL) +		check_duplicate_label(c, dt, m->ref, node, prop, m); +} +ERROR(duplicate_label, NULL, check_duplicate_label_node, +      check_duplicate_label_prop, NULL);  static void check_explicit_phandles(struct check *c, struct node *root, -					  struct node *node) +				    struct node *node, struct property *prop)  { -	struct property *prop; +	struct marker *m;  	struct node *other;  	cell_t phandle; -	prop = get_property(node, "linux,phandle"); -	if (! prop) -		return; /* No phandle, that's fine */ +	if (!streq(prop->name, "phandle") +	    && !streq(prop->name, "linux,phandle")) +		return;  	if (prop->val.len != sizeof(cell_t)) { -		FAIL(c, "%s has bad length (%d) linux,phandle property", -		     node->fullpath, prop->val.len); +		FAIL(c, "%s has bad length (%d) %s property", +		     node->fullpath, prop->val.len, prop->name); +		return; +	} + +	m = prop->val.markers; +	for_each_marker_of_type(m, REF_PHANDLE) { +		assert(m->offset == 0); +		if (node != get_node_by_ref(root, m->ref)) +			/* "Set this node's phandle equal to some +			 * other node's phandle".  That's nonsensical +			 * by construction. */ { +			FAIL(c, "%s in %s is a reference to another node", +			     prop->name, node->fullpath); +			return; +		} +		/* But setting this node's phandle equal to its own +		 * phandle is allowed - that means allocate a unique +		 * phandle for this node, even if it's not otherwise +		 * referenced.  The value will be filled in later, so +		 * no further checking for now. */  		return;  	}  	phandle = propval_cell(prop); +  	if ((phandle == 0) || (phandle == -1)) { -		FAIL(c, "%s has invalid linux,phandle value 0x%x", -		     node->fullpath, phandle); +		FAIL(c, "%s has bad value (0x%x) in %s property", +		     node->fullpath, phandle, prop->name);  		return;  	} +	if (node->phandle && (node->phandle != phandle)) +		FAIL(c, "%s has %s property which replaces existing phandle information", +		     node->fullpath, prop->name); +  	other = get_node_by_phandle(root, phandle); -	if (other) { +	if (other && (other != node)) {  		FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",  		     node->fullpath, phandle, other->fullpath);  		return; @@ -311,7 +417,7 @@ static void check_explicit_phandles(struct check *c, struct node *root,  	node->phandle = phandle;  } -NODE_CHECK(explicit_phandles, NULL, ERROR); +PROP_ERROR(explicit_phandles, NULL);  static void check_name_properties(struct check *c, struct node *root,  				  struct node *node) @@ -340,8 +446,8 @@ static void check_name_properties(struct check *c, struct node *root,  		free(prop);  	}  } -CHECK_IS_STRING(name_is_string, "name", ERROR); -NODE_CHECK(name_properties, NULL, ERROR, &name_is_string); +ERROR_IF_NOT_STRING(name_is_string, "name"); +NODE_ERROR(name_properties, NULL, &name_is_string);  /*   * Reference fixup functions @@ -368,7 +474,7 @@ static void fixup_phandle_references(struct check *c, struct node *dt,  		*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);  	}  } -CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR, +ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL,        &duplicate_node_names, &explicit_phandles);  static void fixup_path_references(struct check *c, struct node *dt, @@ -393,19 +499,19 @@ static void fixup_path_references(struct check *c, struct node *dt,  						  strlen(path) + 1);  	}  } -CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR, +ERROR(path_references, NULL, NULL, fixup_path_references, NULL,        &duplicate_node_names);  /*   * Semantic checks   */ -CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN); -CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN); -CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN); +WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells"); +WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells"); +WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells"); -CHECK_IS_STRING(device_type_is_string, "device_type", WARN); -CHECK_IS_STRING(model_is_string, "model", WARN); -CHECK_IS_STRING(status_is_string, "status", WARN); +WARNING_IF_NOT_STRING(device_type_is_string, "device_type"); +WARNING_IF_NOT_STRING(model_is_string, "model"); +WARNING_IF_NOT_STRING(status_is_string, "status");  static void fixup_addr_size_cells(struct check *c, struct node *dt,  				  struct node *node) @@ -423,8 +529,8 @@ static void fixup_addr_size_cells(struct check *c, struct node *dt,  	if (prop)  		node->size_cells = propval_cell(prop);  } -CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN, -      &address_cells_is_cell, &size_cells_is_cell); +WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, +	&address_cells_is_cell, &size_cells_is_cell);  #define node_addr_cells(n) \  	(((n)->addr_cells == -1) ? 2 : (n)->addr_cells) @@ -458,7 +564,7 @@ static void check_reg_format(struct check *c, struct node *dt,  		     "(#address-cells == %d, #size-cells == %d)",  		     node->fullpath, prop->val.len, addr_cells, size_cells);  } -NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells); +NODE_WARNING(reg_format, NULL, &addr_size_cells);  static void check_ranges_format(struct check *c, struct node *dt,  				struct node *node) @@ -499,7 +605,7 @@ static void check_ranges_format(struct check *c, struct node *dt,  		     p_addr_cells, c_addr_cells, c_size_cells);  	}  } -NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells); +NODE_WARNING(ranges_format, NULL, &addr_size_cells);  /*   * Style checks @@ -526,7 +632,7 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt,  		FAIL(c, "Relying on default #size-cells value for %s",  		     node->fullpath);  } -NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells); +NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells);  static void check_obsolete_chosen_interrupt_controller(struct check *c,  						       struct node *dt) @@ -543,12 +649,15 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,  		FAIL(c, "/chosen has obsolete \"interrupt-controller\" "  		     "property");  } -TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN); +TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);  static struct check *check_table[] = {  	&duplicate_node_names, &duplicate_property_names,  	&node_name_chars, &node_name_format, &property_name_chars,  	&name_is_string, &name_properties, + +	&duplicate_label, +  	&explicit_phandles,  	&phandle_references, &path_references, @@ -559,8 +668,71 @@ static struct check *check_table[] = {  	&avoid_default_addr_size,  	&obsolete_chosen_interrupt_controller, + +	&always_fail,  }; +static void enable_warning_error(struct check *c, bool warn, bool error) +{ +	int i; + +	/* Raising level, also raise it for prereqs */ +	if ((warn && !c->warn) || (error && !c->error)) +		for (i = 0; i < c->num_prereqs; i++) +			enable_warning_error(c->prereq[i], warn, error); + +	c->warn = c->warn || warn; +	c->error = c->error || error; +} + +static void disable_warning_error(struct check *c, bool warn, bool error) +{ +	int i; + +	/* Lowering level, also lower it for things this is the prereq +	 * for */ +	if ((warn && c->warn) || (error && c->error)) { +		for (i = 0; i < ARRAY_SIZE(check_table); i++) { +			struct check *cc = check_table[i]; +			int j; + +			for (j = 0; j < cc->num_prereqs; j++) +				if (cc->prereq[j] == c) +					disable_warning_error(cc, warn, error); +		} +	} + +	c->warn = c->warn && !warn; +	c->error = c->error && !error; +} + +void parse_checks_option(bool warn, bool error, const char *optarg) +{ +	int i; +	const char *name = optarg; +	bool enable = true; + +	if ((strncmp(optarg, "no-", 3) == 0) +	    || (strncmp(optarg, "no_", 3) == 0)) { +		name = optarg + 3; +		enable = false; +	} + +	for (i = 0; i < ARRAY_SIZE(check_table); i++) { +		struct check *c = check_table[i]; + +		if (streq(c->name, name)) { +			if (enable) +				enable_warning_error(c, warn, error); +			else +				disable_warning_error(c, warn, error); +			return; +		} +	} + +	die("Unrecognized check name \"%s\"\n", name); +} +  void process_checks(int force, struct boot_info *bi)  {  	struct node *dt = bi->dt; @@ -570,7 +742,7 @@ void process_checks(int force, struct boot_info *bi)  	for (i = 0; i < ARRAY_SIZE(check_table); i++) {  		struct check *c = check_table[i]; -		if (c->level != IGNORE) +		if (c->warn || c->error)  			error = error || run_check(c, dt);  	} diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c index fe555e819bf..4a40c5b9247 100644 --- a/scripts/dtc/data.c +++ b/scripts/dtc/data.c @@ -68,40 +68,6 @@ struct data data_copy_mem(const char *mem, int len)  	return d;  } -static char get_oct_char(const char *s, int *i) -{ -	char x[4]; -	char *endx; -	long val; - -	x[3] = '\0'; -	strncpy(x, s + *i, 3); - -	val = strtol(x, &endx, 8); - -	assert(endx > x); - -	(*i) += endx - x; -	return val; -} - -static char get_hex_char(const char *s, int *i) -{ -	char x[3]; -	char *endx; -	long val; - -	x[2] = '\0'; -	strncpy(x, s + *i, 2); - -	val = strtol(x, &endx, 16); -	if (!(endx  > x)) -		die("\\x used with no following hex digits\n"); - -	(*i) += endx - x; -	return val; -} -  struct data data_copy_escape_string(const char *s, int len)  {  	int i = 0; @@ -114,53 +80,10 @@ struct data data_copy_escape_string(const char *s, int len)  	while (i < len) {  		char c = s[i++]; -		if (c != '\\') { -			q[d.len++] = c; -			continue; -		} - -		c = s[i++]; -		assert(c); -		switch (c) { -		case 'a': -			q[d.len++] = '\a'; -			break; -		case 'b': -			q[d.len++] = '\b'; -			break; -		case 't': -			q[d.len++] = '\t'; -			break; -		case 'n': -			q[d.len++] = '\n'; -			break; -		case 'v': -			q[d.len++] = '\v'; -			break; -		case 'f': -			q[d.len++] = '\f'; -			break; -		case 'r': -			q[d.len++] = '\r'; -			break; -		case '0': -		case '1': -		case '2': -		case '3': -		case '4': -		case '5': -		case '6': -		case '7': -			i--; /* need to re-read the first digit as -			      * part of the octal value */ -			q[d.len++] = get_oct_char(s, &i); -			break; -		case 'x': -			q[d.len++] = get_hex_char(s, &i); -			break; -		default: -			q[d.len++] = c; -		} +		if (c == '\\') +			c = get_escape_char(s, &i); + +		q[d.len++] = c;  	}  	q[d.len++] = '\0'; @@ -245,11 +168,33 @@ struct data data_merge(struct data d1, struct data d2)  	return d;  } -struct data data_append_cell(struct data d, cell_t word) +struct data data_append_integer(struct data d, uint64_t value, int bits)  { -	cell_t beword = cpu_to_fdt32(word); - -	return data_append_data(d, &beword, sizeof(beword)); +	uint8_t value_8; +	uint16_t value_16; +	uint32_t value_32; +	uint64_t value_64; + +	switch (bits) { +	case 8: +		value_8 = value; +		return data_append_data(d, &value_8, 1); + +	case 16: +		value_16 = cpu_to_fdt16(value); +		return data_append_data(d, &value_16, 2); + +	case 32: +		value_32 = cpu_to_fdt32(value); +		return data_append_data(d, &value_32, 4); + +	case 64: +		value_64 = cpu_to_fdt64(value); +		return data_append_data(d, &value_64, 8); + +	default: +		die("Invalid literal size (%d)\n", bits); +	}  }  struct data data_append_re(struct data d, const struct fdt_reserve_entry *re) @@ -262,11 +207,14 @@ struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)  	return data_append_data(d, &bere, sizeof(bere));  } -struct data data_append_addr(struct data d, uint64_t addr) +struct data data_append_cell(struct data d, cell_t word)  { -	uint64_t beaddr = cpu_to_fdt64(addr); +	return data_append_integer(d, word, sizeof(word) * 8); +} -	return data_append_data(d, &beaddr, sizeof(beaddr)); +struct data data_append_addr(struct data d, uint64_t addr) +{ +	return data_append_integer(d, addr, sizeof(addr) * 8);  }  struct data data_append_byte(struct data d, uint8_t byte) diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l index a627bbee91d..3b41bfca636 100644 --- a/scripts/dtc/dtc-lexer.l +++ b/scripts/dtc/dtc-lexer.l @@ -18,7 +18,7 @@   *                                                                   USA   */ -%option noyywrap noinput nounput yylineno +%option noyywrap nounput noinput never-interactive  %x INCLUDE  %x BYTESTRING @@ -29,6 +29,7 @@ PROPNODECHAR	[a-zA-Z0-9,._+*#?@-]  PATHCHAR	({PROPNODECHAR}|[/])  LABEL		[a-zA-Z_][a-zA-Z0-9_]*  STRING		\"([^\\"]|\\.)*\" +CHAR_LITERAL	'([^']|\\')*'  WS		[[:space:]]  COMMENT		"/*"([^*]|\*+[^*/])*\*+"/"  LINECOMMENT	"//".*\n @@ -38,6 +39,13 @@ LINECOMMENT	"//".*\n  #include "srcpos.h"  #include "dtc-parser.tab.h" +YYLTYPE yylloc; + +/* CAUTION: this will stop working if we ever use yyless() or yyunput() */ +#define	YY_USER_ACTION \ +	{ \ +		srcpos_update(&yylloc, yytext, yyleng); \ +	}  /*#define LEXDEBUG	1*/ @@ -47,15 +55,10 @@ LINECOMMENT	"//".*\n  #define DPRINT(fmt, ...)	do { } while (0)  #endif -static int dts_version; /* = 0 */ +static int dts_version = 1; -#define BEGIN_DEFAULT()	if (dts_version == 0) { \ -				DPRINT("<INITIAL>\n"); \ -				BEGIN(INITIAL); \ -			} else { \ -				DPRINT("<V1>\n"); \ +#define BEGIN_DEFAULT()		DPRINT("<V1>\n"); \  				BEGIN(V1); \ -			}  static void push_input_file(const char *filename);  static int pop_input_file(void); @@ -68,6 +71,27 @@ static int pop_input_file(void);  			push_input_file(name);  		} +<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? { +			char *line, *tmp, *fn; +			/* skip text before line # */ +			line = yytext; +			while (!isdigit(*line)) +				line++; +			/* skip digits in line # */ +			tmp = line; +			while (!isspace(*tmp)) +				tmp++; +			/* "NULL"-terminate line # */ +			*tmp = '\0'; +			/* start of filename */ +			fn = strchr(tmp + 1, '"') + 1; +			/* strip trailing " from filename */ +			tmp = strchr(fn, '"'); +			*tmp = 0; +			/* -1 since #line is the number of the next line */ +			srcpos_set_line(xstrdup(fn), atoi(line) - 1); +		} +  <*><<EOF>>		{  			if (!pop_input_file()) {  				yyterminate(); @@ -75,18 +99,13 @@ static int pop_input_file(void);  		}  <*>{STRING}	{ -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			DPRINT("String: %s\n", yytext);  			yylval.data = data_copy_escape_string(yytext+1,  					yyleng-2); -			yylloc.first_line = yylineno;  			return DT_STRING;  		}  <*>"/dts-v1/"	{ -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			DPRINT("Keyword: /dts-v1/\n");  			dts_version = 1;  			BEGIN_DEFAULT(); @@ -94,106 +113,85 @@ static int pop_input_file(void);  		}  <*>"/memreserve/"	{ -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			DPRINT("Keyword: /memreserve/\n");  			BEGIN_DEFAULT();  			return DT_MEMRESERVE;  		} +<*>"/bits/"	{ +			DPRINT("Keyword: /bits/\n"); +			BEGIN_DEFAULT(); +			return DT_BITS; +		} + +<*>"/delete-property/"	{ +			DPRINT("Keyword: /delete-property/\n"); +			DPRINT("<PROPNODENAME>\n"); +			BEGIN(PROPNODENAME); +			return DT_DEL_PROP; +		} + +<*>"/delete-node/"	{ +			DPRINT("Keyword: /delete-node/\n"); +			DPRINT("<PROPNODENAME>\n"); +			BEGIN(PROPNODENAME); +			return DT_DEL_NODE; +		} +  <*>{LABEL}:	{ -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			DPRINT("Label: %s\n", yytext); -			yylval.labelref = strdup(yytext); +			yylval.labelref = xstrdup(yytext);  			yylval.labelref[yyleng-1] = '\0';  			return DT_LABEL;  		} -<INITIAL>[bodh]# { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno; -			if (*yytext == 'b') -				yylval.cbase = 2; -			else if (*yytext == 'o') -				yylval.cbase = 8; -			else if (*yytext == 'd') -				yylval.cbase = 10; -			else -				yylval.cbase = 16; -			DPRINT("Base: %d\n", yylval.cbase); -			return DT_BASE; -		} - -<INITIAL>[0-9a-fA-F]+	{ -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno; -			yylval.literal = strdup(yytext); +<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? { +			yylval.literal = xstrdup(yytext);  			DPRINT("Literal: '%s'\n", yylval.literal); -			return DT_LEGACYLITERAL; +			return DT_LITERAL;  		} -<V1>[0-9]+|0[xX][0-9a-fA-F]+      { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno; -			yylval.literal = strdup(yytext); -			DPRINT("Literal: '%s'\n", yylval.literal); -			return DT_LITERAL; +<*>{CHAR_LITERAL}	{ +			yytext[yyleng-1] = '\0'; +			yylval.literal = xstrdup(yytext+1); +			DPRINT("Character literal: %s\n", yylval.literal); +			return DT_CHAR_LITERAL;  		} -\&{LABEL}	{	/* label reference */ -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno; +<*>\&{LABEL}	{	/* label reference */  			DPRINT("Ref: %s\n", yytext+1); -			yylval.labelref = strdup(yytext+1); +			yylval.labelref = xstrdup(yytext+1);  			return DT_REF;  		} -"&{/"{PATHCHAR}+\}	{	/* new-style path reference */ -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno; +<*>"&{/"{PATHCHAR}+\}	{	/* new-style path reference */  			yytext[yyleng-1] = '\0';  			DPRINT("Ref: %s\n", yytext+2); -			yylval.labelref = strdup(yytext+2); -			return DT_REF; -		} - -<INITIAL>"&/"{PATHCHAR}+ {	/* old-style path reference */ -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno; -			DPRINT("Ref: %s\n", yytext+1); -			yylval.labelref = strdup(yytext+1); +			yylval.labelref = xstrdup(yytext+2);  			return DT_REF;  		}  <BYTESTRING>[0-9a-fA-F]{2} { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			yylval.byte = strtol(yytext, NULL, 16);  			DPRINT("Byte: %02x\n", (int)yylval.byte);  			return DT_BYTE;  		}  <BYTESTRING>"]"	{ -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			DPRINT("/BYTESTRING\n");  			BEGIN_DEFAULT();  			return ']';  		} -<PROPNODENAME>{PROPNODECHAR}+ { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno; +<PROPNODENAME>\\?{PROPNODECHAR}+ {  			DPRINT("PropNodeName: %s\n", yytext); -			yylval.propnodename = strdup(yytext); +			yylval.propnodename = xstrdup((yytext[0] == '\\') ? +							yytext + 1 : yytext);  			BEGIN_DEFAULT();  			return DT_PROPNODENAME;  		}  "/incbin/"	{ -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			DPRINT("Binary Include\n");  			return DT_INCBIN;  		} @@ -202,9 +200,16 @@ static int pop_input_file(void);  <*>{COMMENT}+	/* eat C-style comments */  <*>{LINECOMMENT}+ /* eat C++-style comments */ +<*>"<<"		{ return DT_LSHIFT; }; +<*>">>"		{ return DT_RSHIFT; }; +<*>"<="		{ return DT_LE; }; +<*>">="		{ return DT_GE; }; +<*>"=="		{ return DT_EQ; }; +<*>"!="		{ return DT_NE; }; +<*>"&&"		{ return DT_AND; }; +<*>"||"		{ return DT_OR; }; +  <*>.		{ -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			DPRINT("Char: %c (\\x%02x)\n", yytext[0],  				(unsigned)yytext[0]);  			if (yytext[0] == '[') { @@ -221,100 +226,25 @@ static int pop_input_file(void);  %% - -/* - * Stack of nested include file contexts. - */ - -struct incl_file { -	struct dtc_file *file; -	YY_BUFFER_STATE yy_prev_buf; -	int yy_prev_lineno; -	struct incl_file *prev; -}; - -static struct incl_file *incl_file_stack; - - -/* - * Detect infinite include recursion. - */ -#define MAX_INCLUDE_DEPTH	(100) - -static int incl_depth = 0; - -  static void push_input_file(const char *filename)  { -	struct incl_file *incl_file; -	struct dtc_file *newfile; -	struct search_path search, *searchptr = NULL; -  	assert(filename); -	if (incl_depth++ >= MAX_INCLUDE_DEPTH) -		die("Includes nested too deeply"); - -	if (srcpos_file) { -		search.dir = srcpos_file->dir; -		search.next = NULL; -		search.prev = NULL; -		searchptr = &search; -	} - -	newfile = dtc_open_file(filename, searchptr); - -	incl_file = xmalloc(sizeof(struct incl_file)); +	srcfile_push(filename); -	/* -	 * Save current context. -	 */ -	incl_file->yy_prev_buf = YY_CURRENT_BUFFER; -	incl_file->yy_prev_lineno = yylineno; -	incl_file->file = srcpos_file; -	incl_file->prev = incl_file_stack; +	yyin = current_srcfile->f; -	incl_file_stack = incl_file; - -	/* -	 * Establish new context. -	 */ -	srcpos_file = newfile; -	yylineno = 1; -	yyin = newfile->file; -	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); +	yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));  }  static int pop_input_file(void)  { -	struct incl_file *incl_file; - -	if (incl_file_stack == 0) +	if (srcfile_pop() == 0)  		return 0; -	dtc_close_file(srcpos_file); - -	/* -	 * Pop. -	 */ -	--incl_depth; -	incl_file = incl_file_stack; -	incl_file_stack = incl_file->prev; - -	/* -	 * Recover old context. -	 */ -	yy_delete_buffer(YY_CURRENT_BUFFER); -	yy_switch_to_buffer(incl_file->yy_prev_buf); -	yylineno = incl_file->yy_prev_lineno; -	srcpos_file = incl_file->file; -	yyin = incl_file->file ? incl_file->file->file : NULL; - -	/* -	 * Free old state. -	 */ -	free(incl_file); +	yypop_buffer_state(); +	yyin = current_srcfile->f;  	return 1;  } diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped index e27cc636e32..2d30f41778b 100644 --- a/scripts/dtc/dtc-lexer.lex.c_shipped +++ b/scripts/dtc/dtc-lexer.lex.c_shipped @@ -170,20 +170,7 @@ extern FILE *yyin, *yyout;  #define EOB_ACT_END_OF_FILE 1  #define EOB_ACT_LAST_MATCH 2 -    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires -     *       access to the local variable yy_act. Since yyless() is a macro, it would break -     *       existing scanners that call yyless() from OUTSIDE yylex.  -     *       One obvious solution it to make yy_act a global. I tried that, and saw -     *       a 5% performance hit in a non-yylineno scanner, because yy_act is -     *       normally declared as a register variable-- so it is not worth it. -     */ -    #define  YY_LESS_LINENO(n) \ -            do { \ -                int yyl;\ -                for ( yyl = n; yyl < yyleng; ++yyl )\ -                    if ( yytext[yyl] == '\n' )\ -                        --yylineno;\ -            }while(0) +    #define YY_LESS_LINENO(n)  /* Return all but the first "n" matched characters back to the input stream. */  #define yyless(n) \ @@ -385,8 +372,8 @@ static void yy_fatal_error (yyconst char msg[]  );  	*yy_cp = '\0'; \  	(yy_c_buf_p) = yy_cp; -#define YY_NUM_RULES 20 -#define YY_END_OF_BUFFER 21 +#define YY_NUM_RULES 30 +#define YY_END_OF_BUFFER 31  /* This struct is not used in this scanner,     but its presence is necessary. */  struct yy_trans_info @@ -394,38 +381,43 @@ struct yy_trans_info  	flex_int32_t yy_verify;  	flex_int32_t yy_nxt;  	}; -static yyconst flex_int16_t yy_accept[104] = +static yyconst flex_int16_t yy_accept[161] =      {   0,          0,    0,    0,    0,    0,    0,    0,    0,    0,    0, -       21,   19,   16,   16,   19,   19,   19,    7,    7,   19, -        7,   19,   19,   19,   19,   13,   14,   14,   19,    8, -        8,   16,    0,    2,    0,    0,    9,    0,    0,    0, -        0,    0,    0,    7,    7,    5,    0,    6,    0,   12, -       12,   14,   14,    8,    0,   11,    9,    0,    0,    0, -        0,   18,    0,    0,    0,    0,    8,    0,   17,    0, -        0,    0,    0,    0,   10,    0,    0,    0,    0,    0, -        0,    0,    0,    0,    0,    0,    0,    0,    3,   15, -        0,    0,    0,    0,    0,    0,    0,    0,    1,    0, - -        0,    4,    0 +       31,   29,   18,   18,   29,   29,   29,   29,   29,   29, +       29,   29,   29,   29,   29,   29,   29,   29,   15,   16, +       16,   29,   16,   10,   10,   18,   26,    0,    3,    0, +       27,   12,    0,    0,   11,    0,    0,    0,    0,    0, +        0,    0,   21,   23,   25,   24,   22,    0,    9,   28, +        0,    0,    0,   14,   14,   16,   16,   16,   10,   10, +       10,    0,   12,    0,   11,    0,    0,    0,   20,    0, +        0,    0,    0,    0,    0,    0,    0,   16,   10,   10, +       10,    0,   19,    0,    0,    0,    0,    0,    0,    0, + +        0,    0,   16,   13,    0,    0,    0,    0,    0,    0, +        0,    0,    0,   16,    6,    0,    0,    0,    0,    0, +        0,    2,    0,    0,    0,    0,    0,    0,    0,    0, +        4,   17,    0,    0,    2,    0,    0,    0,    0,    0, +        0,    0,    0,    0,    0,    0,    0,    1,    0,    0, +        0,    0,    5,    8,    0,    0,    0,    0,    7,    0      } ;  static yyconst flex_int32_t yy_ec[256] =      {   0,          1,    1,    1,    1,    1,    1,    1,    1,    2,    3, -        2,    2,    2,    1,    1,    1,    1,    1,    1,    1, +        4,    4,    4,    1,    1,    1,    1,    1,    1,    1,          1,    1,    1,    1,    1,    1,    1,    1,    1,    1, -        1,    2,    1,    4,    5,    1,    1,    6,    1,    1, -        1,    7,    8,    8,    9,    8,   10,   11,   12,   13, -       13,   13,   13,   13,   13,   13,   13,   14,    1,    1, -        1,    1,    8,    8,   15,   15,   15,   15,   15,   15, -       16,   16,   16,   16,   16,   16,   16,   16,   16,   16, -       16,   16,   16,   16,   16,   16,   16,   17,   16,   16, -        1,   18,   19,    1,   16,    1,   15,   20,   21,   22, - -       23,   15,   16,   24,   25,   16,   16,   26,   27,   28, -       24,   16,   16,   29,   30,   31,   32,   33,   16,   17, -       16,   16,   34,    1,   35,    1,    1,    1,    1,    1, +        1,    2,    5,    6,    7,    1,    1,    8,    9,    1, +        1,   10,   11,   11,   12,   11,   13,   14,   15,   16, +       16,   16,   16,   16,   16,   16,   16,   17,    1,   18, +       19,   20,   11,   11,   21,   21,   21,   21,   21,   21, +       22,   22,   22,   22,   22,   23,   22,   22,   22,   22, +       22,   22,   22,   22,   24,   22,   22,   25,   22,   22, +        1,   26,   27,    1,   22,    1,   21,   28,   29,   30, + +       31,   21,   22,   22,   32,   22,   22,   33,   34,   35, +       36,   37,   22,   38,   39,   40,   41,   42,   22,   25, +       43,   22,   44,   45,   46,    1,    1,    1,    1,    1,          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,          1,    1,    1,    1,    1,    1,    1,    1,    1,    1, @@ -442,136 +434,165 @@ static yyconst flex_int32_t yy_ec[256] =          1,    1,    1,    1,    1      } ; -static yyconst flex_int32_t yy_meta[36] = +static yyconst flex_int32_t yy_meta[47] =      {   0, -        1,    1,    1,    1,    2,    1,    2,    2,    2,    3, -        4,    4,    4,    5,    6,    7,    7,    1,    1,    6, -        6,    6,    6,    7,    7,    7,    7,    7,    7,    7, -        7,    7,    7,    8,    1 +        1,    1,    1,    1,    1,    1,    2,    3,    1,    2, +        2,    2,    4,    5,    5,    5,    6,    1,    1,    1, +        7,    8,    8,    8,    8,    1,    1,    7,    7,    7, +        7,    8,    8,    8,    8,    8,    8,    8,    8,    8, +        8,    8,    8,    3,    1,    1      } ; -static yyconst flex_int16_t yy_base[117] = +static yyconst flex_int16_t yy_base[175] =      {   0, -        0,    0,   30,    0,   44,    0,   67,    0,   97,  105, -      302,  303,   35,   44,   40,   94,  112,    0,  129,  152, -      296,  295,  159,    0,  176,  303,    0,  116,   95,  165, -       49,   46,  102,  303,  296,    0,    0,  288,  290,  293, -      264,  266,  270,    0,    0,  303,    0,  303,  264,  303, -        0,    0,  195,  101,    0,    0,    0,    0,  284,  125, -      277,  265,  225,  230,  216,  218,    0,  202,  224,  221, -      217,  107,  196,  188,  303,  206,  179,  186,  178,  185, -      183,  162,  161,  150,  169,  160,  145,  125,  303,  303, -      137,  109,  190,  103,  203,  167,  108,  197,  303,  123, - -       29,  303,  303,  215,  221,  226,  229,  234,  240,  246, -      250,  257,  265,  270,  275,  282 +        0,  385,  378,   40,   41,  383,   72,  382,   34,   44, +      388,  393,   61,  117,  368,  116,  115,  115,  115,   48, +      367,  107,  368,  339,  127,  120,    0,  147,  393,    0, +      127,    0,  133,  156,  168,  153,  393,  125,  393,  380, +      393,    0,  369,  127,  393,  160,  371,  377,  347,   21, +      343,  346,  393,  393,  393,  393,  393,  359,  393,  393, +      183,  343,  339,  393,  356,    0,  183,  340,  187,  348, +      347,    0,    0,    0,  178,  359,  195,  365,  354,  326, +      332,  325,  334,  328,  204,  326,  331,  324,  393,  335, +      150,  311,  343,  342,  315,  322,  340,  179,  313,  207, + +      319,  316,  317,  393,  337,  333,  305,  302,  311,  301, +      310,  190,  338,  337,  393,  307,  322,  301,  305,  277, +      208,  311,  307,  278,  271,  270,  248,  246,  213,  130, +      393,  393,  263,  235,  207,  221,  218,  229,  213,  213, +      206,  234,  218,  210,  208,  193,  219,  393,  223,  204, +      176,  157,  393,  393,  120,  106,   97,  119,  393,  393, +      245,  251,  259,  263,  267,  273,  280,  284,  292,  300, +      304,  310,  318,  326      } ; -static yyconst flex_int16_t yy_def[117] = +static yyconst flex_int16_t yy_def[175] =      {   0, -      103,    1,    1,    3,    3,    5,  103,    7,    3,    3, -      103,  103,  103,  103,  104,  105,  103,  106,  103,   19, -       19,   20,  103,  107,   20,  103,  108,  109,  105,  103, -      103,  103,  104,  103,  104,  110,  111,  103,  112,  113, -      103,  103,  103,  106,   19,  103,   20,  103,  103,  103, -       20,  108,  109,  103,  114,  110,  111,  115,  112,  112, -      113,  103,  103,  103,  103,  103,  114,  115,  103,  103, -      103,  103,  103,  103,  103,  103,  103,  103,  103,  103, -      103,  103,  103,  103,  103,  103,  103,  103,  103,  103, -      103,  103,  103,  103,  103,  116,  103,  116,  103,  116, - -      103,  103,    0,  103,  103,  103,  103,  103,  103,  103, -      103,  103,  103,  103,  103,  103 +      160,    1,    1,    1,    1,    5,  160,    7,    1,    1, +      160,  160,  160,  160,  160,  161,  162,  163,  160,  160, +      160,  160,  164,  160,  160,  160,  165,  164,  160,  166, +      167,  166,  166,  160,  160,  160,  160,  161,  160,  161, +      160,  168,  160,  163,  160,  163,  169,  170,  160,  160, +      160,  160,  160,  160,  160,  160,  160,  164,  160,  160, +      160,  160,  160,  160,  164,  166,  167,  166,  160,  160, +      160,  171,  168,  172,  163,  169,  169,  170,  160,  160, +      160,  160,  160,  160,  160,  160,  160,  166,  160,  160, +      171,  172,  160,  160,  160,  160,  160,  160,  160,  160, + +      160,  160,  166,  160,  160,  160,  160,  160,  160,  160, +      160,  173,  160,  166,  160,  160,  160,  160,  160,  160, +      173,  160,  173,  160,  160,  160,  160,  160,  160,  160, +      160,  160,  160,  160,  160,  160,  160,  160,  160,  160, +      160,  160,  174,  160,  160,  160,  174,  160,  174,  160, +      160,  160,  160,  160,  160,  160,  160,  160,  160,    0, +      160,  160,  160,  160,  160,  160,  160,  160,  160,  160, +      160,  160,  160,  160      } ; -static yyconst flex_int16_t yy_nxt[339] = +static yyconst flex_int16_t yy_nxt[440] =      {   0, -       12,   13,   14,   15,   12,   16,   12,   12,   12,   17, -       18,   18,   18,   12,   19,   20,   20,   12,   12,   21, -       19,   21,   19,   22,   20,   20,   20,   20,   20,   20, -       20,   20,   20,   12,   12,   12,   32,   32,  102,   23, -       12,   12,   12,   34,   20,   32,   32,   32,   32,   20, -       20,   20,   20,   20,   24,   24,   24,   35,   25,   54, -       54,   54,   26,   25,   25,   25,   25,   12,   13,   14, -       15,   27,   12,   27,   27,   27,   23,   27,   27,   27, -       12,   28,   28,   28,   12,   12,   28,   28,   28,   28, -       28,   28,   28,   28,   28,   28,   28,   28,   28,   28, - -       12,   12,   29,   36,  103,   34,   17,   30,   31,   31, -       29,   54,   54,   54,   17,   30,   31,   31,   39,   35, -       52,   40,   52,   52,   52,  103,   78,   38,   38,   46, -      101,   60,   79,   41,   69,   97,   42,   94,   43,   45, -       45,   45,   46,   45,   47,   47,   93,   92,   45,   45, -       45,   45,   47,   47,   47,   47,   47,   47,   47,   47, -       47,   47,   47,   47,   47,   39,   47,   91,   40,   90, -       99,   47,   47,   47,   47,   54,   54,   54,   89,   88, -       41,   55,   87,   49,  100,   43,   51,   51,   51,   86, -       51,   95,   95,   96,   85,   51,   51,   51,   51,   52, - -       99,   52,   52,   52,   95,   95,   96,   84,   46,   83, -       82,   81,   39,   79,  100,   33,   33,   33,   33,   33, -       33,   33,   33,   37,   80,   77,   37,   37,   37,   44, -       40,   44,   50,   76,   50,   52,   75,   52,   74,   52, -       52,   53,   73,   53,   53,   53,   53,   56,   56,   56, -       72,   56,   56,   57,   71,   57,   57,   59,   59,   59, -       59,   59,   59,   59,   59,   61,   61,   61,   61,   61, -       61,   61,   61,   67,   70,   67,   68,   68,   68,   62, -       68,   68,   98,   98,   98,   98,   98,   98,   98,   98, -       60,   66,   65,   64,   63,   62,   60,   58,  103,   48, - -       48,  103,   11,  103,  103,  103,  103,  103,  103,  103, -      103,  103,  103,  103,  103,  103,  103,  103,  103,  103, -      103,  103,  103,  103,  103,  103,  103,  103,  103,  103, -      103,  103,  103,  103,  103,  103,  103,  103 +       12,   13,   14,   13,   15,   16,   12,   17,   18,   12, +       12,   12,   19,   12,   12,   12,   12,   20,   21,   22, +       23,   23,   23,   23,   23,   12,   12,   23,   23,   23, +       23,   23,   23,   23,   23,   23,   23,   23,   23,   23, +       23,   23,   23,   12,   24,   12,   25,   34,   35,   35, +       25,   81,   26,   26,   27,   27,   27,   34,   35,   35, +       82,   28,   36,   36,   36,   53,   54,   29,   28,   28, +       28,   28,   12,   13,   14,   13,   15,   16,   30,   17, +       18,   30,   30,   30,   26,   30,   30,   30,   12,   20, +       21,   22,   31,   31,   31,   31,   31,   32,   12,   31, + +       31,   31,   31,   31,   31,   31,   31,   31,   31,   31, +       31,   31,   31,   31,   31,   12,   24,   12,   36,   36, +       36,   39,   41,   45,   47,   56,   57,   48,   61,   47, +       39,  159,   48,   66,   61,   45,   66,   66,   66,  158, +       46,   40,   49,   59,   50,  157,   51,   49,   52,   50, +       40,   63,   46,   52,   36,   36,   36,  156,   43,   62, +       65,   65,   65,   59,  136,   68,  137,   65,   75,   69, +       69,   69,   70,   71,   65,   65,   65,   65,   70,   71, +       72,   69,   69,   69,   61,   46,   45,  155,  154,   66, +       70,   71,   66,   66,   66,  122,   85,   85,   85,   59, + +       69,   69,   69,   46,   77,  100,  109,   93,  100,   70, +       71,  110,  112,  122,  129,  123,  153,   85,   85,   85, +      135,  135,  135,  148,  148,  160,  135,  135,  135,  152, +      142,  142,  142,  123,  143,  142,  142,  142,  151,  143, +      150,  146,  145,  149,  149,   38,   38,   38,   38,   38, +       38,   38,   38,   42,  144,  141,  140,   42,   42,   44, +       44,   44,   44,   44,   44,   44,   44,   58,   58,   58, +       58,   64,  139,   64,   66,  138,  134,   66,  133,   66, +       66,   67,  132,  131,   67,   67,   67,   67,   73,  130, +       73,   73,   76,   76,   76,   76,   76,   76,   76,   76, + +       78,   78,   78,   78,   78,   78,   78,   78,   91,  160, +       91,   92,  129,   92,   92,  128,   92,   92,  121,  121, +      121,  121,  121,  121,  121,  121,  147,  147,  147,  147, +      147,  147,  147,  147,  127,  126,  125,  124,   61,   61, +      120,  119,  118,  117,  116,  115,   47,  114,  110,  113, +      111,  108,  107,  106,   48,  105,  104,   89,  103,  102, +      101,   99,   98,   97,   96,   95,   94,   79,   77,   90, +       89,   88,   59,   87,   86,   59,   84,   83,   80,   79, +       77,   74,  160,   60,   59,   55,   37,  160,   33,   25, +       26,   25,   11,  160,  160,  160,  160,  160,  160,  160, + +      160,  160,  160,  160,  160,  160,  160,  160,  160,  160, +      160,  160,  160,  160,  160,  160,  160,  160,  160,  160, +      160,  160,  160,  160,  160,  160,  160,  160,  160,  160, +      160,  160,  160,  160,  160,  160,  160,  160,  160      } ; -static yyconst flex_int16_t yy_chk[339] = +static yyconst flex_int16_t yy_chk[440] =      {   0,          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,          1,    1,    1,    1,    1,    1,    1,    1,    1,    1, -        1,    1,    1,    1,    1,    3,   13,   13,  101,    3, -        3,    3,    3,   15,    3,   14,   14,   32,   32,    3, -        3,    3,    3,    3,    5,    5,    5,   15,    5,   31, -       31,   31,    5,    5,    5,    5,    5,    7,    7,    7, -        7,    7,    7,    7,    7,    7,    7,    7,    7,    7, +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1, +        1,    1,    1,    1,    1,    1,    4,    9,    9,    9, +       10,   50,    4,    5,    5,    5,    5,   10,   10,   10, +       50,    5,   13,   13,   13,   20,   20,    5,    5,    5, +        5,    5,    7,    7,    7,    7,    7,    7,    7,    7,          7,    7,    7,    7,    7,    7,    7,    7,    7,    7,          7,    7,    7,    7,    7,    7,    7,    7,    7,    7, -        7,    7,    9,   16,   29,   33,    9,    9,    9,    9, -       10,   54,   54,   54,   10,   10,   10,   10,   17,   33, -       28,   17,   28,   28,   28,  100,   72,   16,   29,   28, -       97,   60,   72,   17,   60,   94,   17,   92,   17,   19, -       19,   19,   19,   19,   19,   19,   91,   88,   19,   19, -       19,   19,   19,   19,   19,   19,   19,   19,   19,   19, -       19,   19,   20,   20,   20,   23,   20,   87,   23,   86, -       96,   20,   20,   20,   20,   30,   30,   30,   85,   84, -       23,   30,   83,   23,   96,   23,   25,   25,   25,   82, -       25,   93,   93,   93,   81,   25,   25,   25,   25,   53, - -       98,   53,   53,   53,   95,   95,   95,   80,   53,   79, -       78,   77,   76,   74,   98,  104,  104,  104,  104,  104, -      104,  104,  104,  105,   73,   71,  105,  105,  105,  106, -       70,  106,  107,   69,  107,  108,   68,  108,   66,  108, -      108,  109,   65,  109,  109,  109,  109,  110,  110,  110, -       64,  110,  110,  111,   63,  111,  111,  112,  112,  112, -      112,  112,  112,  112,  112,  113,  113,  113,  113,  113, -      113,  113,  113,  114,   62,  114,  115,  115,  115,   61, -      115,  115,  116,  116,  116,  116,  116,  116,  116,  116, -       59,   49,   43,   42,   41,   40,   39,   38,   35,   22, - -       21,   11,  103,  103,  103,  103,  103,  103,  103,  103, -      103,  103,  103,  103,  103,  103,  103,  103,  103,  103, -      103,  103,  103,  103,  103,  103,  103,  103,  103,  103, -      103,  103,  103,  103,  103,  103,  103,  103 +        7,    7,    7,    7,    7,    7,    7,    7,    7,    7, +        7,    7,    7,    7,    7,    7,    7,    7,   14,   14, +       14,   16,   17,   18,   19,   22,   22,   19,   25,   26, +       38,  158,   26,   31,   33,   44,   31,   31,   31,  157, +       18,   16,   19,   31,   19,  156,   19,   26,   19,   26, +       38,   26,   44,   26,   36,   36,   36,  155,   17,   25, +       28,   28,   28,   28,  130,   33,  130,   28,   46,   34, +       34,   34,   91,   91,   28,   28,   28,   28,   34,   34, +       34,   35,   35,   35,   61,   46,   75,  152,  151,   67, +       35,   35,   67,   67,   67,  112,   61,   61,   61,   67, + +       69,   69,   69,   75,   77,   85,   98,   77,  100,   69, +       69,   98,  100,  121,  129,  112,  150,   85,   85,   85, +      135,  135,  135,  143,  147,  149,  129,  129,  129,  146, +      138,  138,  138,  121,  138,  142,  142,  142,  145,  142, +      144,  141,  140,  143,  147,  161,  161,  161,  161,  161, +      161,  161,  161,  162,  139,  137,  136,  162,  162,  163, +      163,  163,  163,  163,  163,  163,  163,  164,  164,  164, +      164,  165,  134,  165,  166,  133,  128,  166,  127,  166, +      166,  167,  126,  125,  167,  167,  167,  167,  168,  124, +      168,  168,  169,  169,  169,  169,  169,  169,  169,  169, + +      170,  170,  170,  170,  170,  170,  170,  170,  171,  123, +      171,  172,  122,  172,  172,  120,  172,  172,  173,  173, +      173,  173,  173,  173,  173,  173,  174,  174,  174,  174, +      174,  174,  174,  174,  119,  118,  117,  116,  114,  113, +      111,  110,  109,  108,  107,  106,  105,  103,  102,  101, +       99,   97,   96,   95,   94,   93,   92,   90,   88,   87, +       86,   84,   83,   82,   81,   80,   79,   78,   76,   71, +       70,   68,   65,   63,   62,   58,   52,   51,   49,   48, +       47,   43,   40,   24,   23,   21,   15,   11,    8,    6, +        3,    2,  160,  160,  160,  160,  160,  160,  160,  160, + +      160,  160,  160,  160,  160,  160,  160,  160,  160,  160, +      160,  160,  160,  160,  160,  160,  160,  160,  160,  160, +      160,  160,  160,  160,  160,  160,  160,  160,  160,  160, +      160,  160,  160,  160,  160,  160,  160,  160,  160      } ; -/* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[21] = -    {   0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,  -    0,     }; -  static yy_state_type yy_last_accepting_state;  static char *yy_last_accepting_cpos; @@ -611,11 +632,18 @@ char *yytext; -#line 37 "dtc-lexer.l" +#line 38 "dtc-lexer.l"  #include "dtc.h"  #include "srcpos.h"  #include "dtc-parser.tab.h" +YYLTYPE yylloc; + +/* CAUTION: this will stop working if we ever use yyless() or yyunput() */ +#define	YY_USER_ACTION \ +	{ \ +		srcpos_update(&yylloc, yytext, yyleng); \ +	}  /*#define LEXDEBUG	1*/ @@ -625,19 +653,14 @@ char *yytext;  #define DPRINT(fmt, ...)	do { } while (0)  #endif -static int dts_version; /* = 0 */ +static int dts_version = 1; -#define BEGIN_DEFAULT()	if (dts_version == 0) { \ -				DPRINT("<INITIAL>\n"); \ -				BEGIN(INITIAL); \ -			} else { \ -				DPRINT("<V1>\n"); \ +#define BEGIN_DEFAULT()		DPRINT("<V1>\n"); \  				BEGIN(V1); \ -			}  static void push_input_file(const char *filename);  static int pop_input_file(void); -#line 641 "dtc-lexer.lex.c" +#line 664 "dtc-lexer.lex.c"  #define INITIAL 0  #define INCLUDE 1 @@ -816,6 +839,9 @@ extern int yylex (void);  #endif  #define YY_RULE_SETUP \ +	if ( yyleng > 0 ) \ +		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \ +				(yytext[yyleng - 1] == '\n'); \  	YY_USER_ACTION  /** The main scanner function which does all the work. @@ -826,9 +852,9 @@ YY_DECL  	register char *yy_cp, *yy_bp;  	register int yy_act; -#line 64 "dtc-lexer.l" +#line 67 "dtc-lexer.l" -#line 832 "dtc-lexer.lex.c" +#line 858 "dtc-lexer.lex.c"  	if ( !(yy_init) )  		{ @@ -869,6 +895,7 @@ YY_DECL  		yy_bp = yy_cp;  		yy_current_state = (yy_start); +		yy_current_state += YY_AT_BOL();  yy_match:  		do  			{ @@ -881,35 +908,21 @@ yy_match:  			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )  				{  				yy_current_state = (int) yy_def[yy_current_state]; -				if ( yy_current_state >= 104 ) +				if ( yy_current_state >= 161 )  					yy_c = yy_meta[(unsigned int) yy_c];  				}  			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];  			++yy_cp;  			} -		while ( yy_base[yy_current_state] != 303 ); +		while ( yy_current_state != 160 ); +		yy_cp = (yy_last_accepting_cpos); +		yy_current_state = (yy_last_accepting_state);  yy_find_action:  		yy_act = yy_accept[yy_current_state]; -		if ( yy_act == 0 ) -			{ /* have to back up */ -			yy_cp = (yy_last_accepting_cpos); -			yy_current_state = (yy_last_accepting_state); -			yy_act = yy_accept[yy_current_state]; -			}  		YY_DO_BEFORE_ACTION; -		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) -			{ -			int yyl; -			for ( yyl = 0; yyl < yyleng; ++yyl ) -				if ( yytext[yyl] == '\n' ) -					    -    yylineno++; -; -			} -  do_action:	/* This label is used only to access EOF actions. */  		switch ( yy_act ) @@ -924,216 +937,257 @@ do_action:	/* This label is used only to access EOF actions. */  case 1:  /* rule 1 can match eol */  YY_RULE_SETUP -#line 65 "dtc-lexer.l" +#line 68 "dtc-lexer.l"  {  			char *name = strchr(yytext, '\"') + 1;  			yytext[yyleng-1] = '\0';  			push_input_file(name);  		}  	YY_BREAK +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +#line 74 "dtc-lexer.l" +{ +			char *line, *tmp, *fn; +			/* skip text before line # */ +			line = yytext; +			while (!isdigit(*line)) +				line++; +			/* skip digits in line # */ +			tmp = line; +			while (!isspace(*tmp)) +				tmp++; +			/* "NULL"-terminate line # */ +			*tmp = '\0'; +			/* start of filename */ +			fn = strchr(tmp + 1, '"') + 1; +			/* strip trailing " from filename */ +			tmp = strchr(fn, '"'); +			*tmp = 0; +			/* -1 since #line is the number of the next line */ +			srcpos_set_line(xstrdup(fn), atoi(line) - 1); +		} +	YY_BREAK  case YY_STATE_EOF(INITIAL):  case YY_STATE_EOF(INCLUDE):  case YY_STATE_EOF(BYTESTRING):  case YY_STATE_EOF(PROPNODENAME):  case YY_STATE_EOF(V1): -#line 71 "dtc-lexer.l" +#line 95 "dtc-lexer.l"  {  			if (!pop_input_file()) {  				yyterminate();  			}  		}  	YY_BREAK -case 2: -/* rule 2 can match eol */ +case 3: +/* rule 3 can match eol */  YY_RULE_SETUP -#line 77 "dtc-lexer.l" +#line 101 "dtc-lexer.l"  { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			DPRINT("String: %s\n", yytext);  			yylval.data = data_copy_escape_string(yytext+1,  					yyleng-2); -			yylloc.first_line = yylineno;  			return DT_STRING;  		}  	YY_BREAK -case 3: +case 4:  YY_RULE_SETUP -#line 87 "dtc-lexer.l" +#line 108 "dtc-lexer.l"  { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			DPRINT("Keyword: /dts-v1/\n");  			dts_version = 1;  			BEGIN_DEFAULT();  			return DT_V1;  		}  	YY_BREAK -case 4: +case 5:  YY_RULE_SETUP -#line 96 "dtc-lexer.l" +#line 115 "dtc-lexer.l"  { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			DPRINT("Keyword: /memreserve/\n");  			BEGIN_DEFAULT();  			return DT_MEMRESERVE;  		}  	YY_BREAK -case 5: +case 6:  YY_RULE_SETUP -#line 104 "dtc-lexer.l" +#line 121 "dtc-lexer.l"  { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno; -			DPRINT("Label: %s\n", yytext); -			yylval.labelref = strdup(yytext); -			yylval.labelref[yyleng-1] = '\0'; -			return DT_LABEL; +			DPRINT("Keyword: /bits/\n"); +			BEGIN_DEFAULT(); +			return DT_BITS;  		}  	YY_BREAK -case 6: +case 7:  YY_RULE_SETUP -#line 113 "dtc-lexer.l" +#line 127 "dtc-lexer.l"  { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno; -			if (*yytext == 'b') -				yylval.cbase = 2; -			else if (*yytext == 'o') -				yylval.cbase = 8; -			else if (*yytext == 'd') -				yylval.cbase = 10; -			else -				yylval.cbase = 16; -			DPRINT("Base: %d\n", yylval.cbase); -			return DT_BASE; +			DPRINT("Keyword: /delete-property/\n"); +			DPRINT("<PROPNODENAME>\n"); +			BEGIN(PROPNODENAME); +			return DT_DEL_PROP;  		}  	YY_BREAK -case 7: +case 8:  YY_RULE_SETUP -#line 128 "dtc-lexer.l" +#line 134 "dtc-lexer.l"  { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno; -			yylval.literal = strdup(yytext); -			DPRINT("Literal: '%s'\n", yylval.literal); -			return DT_LEGACYLITERAL; +			DPRINT("Keyword: /delete-node/\n"); +			DPRINT("<PROPNODENAME>\n"); +			BEGIN(PROPNODENAME); +			return DT_DEL_NODE;  		}  	YY_BREAK -case 8: +case 9: +YY_RULE_SETUP +#line 141 "dtc-lexer.l" +{ +			DPRINT("Label: %s\n", yytext); +			yylval.labelref = xstrdup(yytext); +			yylval.labelref[yyleng-1] = '\0'; +			return DT_LABEL; +		} +	YY_BREAK +case 10:  YY_RULE_SETUP -#line 136 "dtc-lexer.l" +#line 148 "dtc-lexer.l"  { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno; -			yylval.literal = strdup(yytext); +			yylval.literal = xstrdup(yytext);  			DPRINT("Literal: '%s'\n", yylval.literal);  			return DT_LITERAL;  		}  	YY_BREAK -case 9: +case 11: +/* rule 11 can match eol */  YY_RULE_SETUP -#line 144 "dtc-lexer.l" +#line 154 "dtc-lexer.l" +{ +			yytext[yyleng-1] = '\0'; +			yylval.literal = xstrdup(yytext+1); +			DPRINT("Character literal: %s\n", yylval.literal); +			return DT_CHAR_LITERAL; +		} +	YY_BREAK +case 12: +YY_RULE_SETUP +#line 161 "dtc-lexer.l"  {	/* label reference */ -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			DPRINT("Ref: %s\n", yytext+1); -			yylval.labelref = strdup(yytext+1); +			yylval.labelref = xstrdup(yytext+1);  			return DT_REF;  		}  	YY_BREAK -case 10: +case 13:  YY_RULE_SETUP -#line 152 "dtc-lexer.l" +#line 167 "dtc-lexer.l"  {	/* new-style path reference */ -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			yytext[yyleng-1] = '\0';  			DPRINT("Ref: %s\n", yytext+2); -			yylval.labelref = strdup(yytext+2); -			return DT_REF; -		} -	YY_BREAK -case 11: -YY_RULE_SETUP -#line 161 "dtc-lexer.l" -{	/* old-style path reference */ -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno; -			DPRINT("Ref: %s\n", yytext+1); -			yylval.labelref = strdup(yytext+1); +			yylval.labelref = xstrdup(yytext+2);  			return DT_REF;  		}  	YY_BREAK -case 12: +case 14:  YY_RULE_SETUP -#line 169 "dtc-lexer.l" +#line 174 "dtc-lexer.l"  { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			yylval.byte = strtol(yytext, NULL, 16);  			DPRINT("Byte: %02x\n", (int)yylval.byte);  			return DT_BYTE;  		}  	YY_BREAK -case 13: +case 15:  YY_RULE_SETUP -#line 177 "dtc-lexer.l" +#line 180 "dtc-lexer.l"  { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			DPRINT("/BYTESTRING\n");  			BEGIN_DEFAULT();  			return ']';  		}  	YY_BREAK -case 14: +case 16:  YY_RULE_SETUP -#line 185 "dtc-lexer.l" +#line 186 "dtc-lexer.l"  { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			DPRINT("PropNodeName: %s\n", yytext); -			yylval.propnodename = strdup(yytext); +			yylval.propnodename = xstrdup((yytext[0] == '\\') ? +							yytext + 1 : yytext);  			BEGIN_DEFAULT();  			return DT_PROPNODENAME;  		}  	YY_BREAK -case 15: +case 17:  YY_RULE_SETUP  #line 194 "dtc-lexer.l"  { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			DPRINT("Binary Include\n");  			return DT_INCBIN;  		}  	YY_BREAK -case 16: -/* rule 16 can match eol */ +case 18: +/* rule 18 can match eol */  YY_RULE_SETUP -#line 201 "dtc-lexer.l" +#line 199 "dtc-lexer.l"  /* eat whitespace */  	YY_BREAK -case 17: -/* rule 17 can match eol */ +case 19: +/* rule 19 can match eol */  YY_RULE_SETUP -#line 202 "dtc-lexer.l" +#line 200 "dtc-lexer.l"  /* eat C-style comments */  	YY_BREAK -case 18: -/* rule 18 can match eol */ +case 20: +/* rule 20 can match eol */  YY_RULE_SETUP -#line 203 "dtc-lexer.l" +#line 201 "dtc-lexer.l"  /* eat C++-style comments */  	YY_BREAK -case 19: +case 21: +YY_RULE_SETUP +#line 203 "dtc-lexer.l" +{ return DT_LSHIFT; }; +	YY_BREAK +case 22: +YY_RULE_SETUP +#line 204 "dtc-lexer.l" +{ return DT_RSHIFT; }; +	YY_BREAK +case 23:  YY_RULE_SETUP  #line 205 "dtc-lexer.l" +{ return DT_LE; }; +	YY_BREAK +case 24: +YY_RULE_SETUP +#line 206 "dtc-lexer.l" +{ return DT_GE; }; +	YY_BREAK +case 25: +YY_RULE_SETUP +#line 207 "dtc-lexer.l" +{ return DT_EQ; }; +	YY_BREAK +case 26: +YY_RULE_SETUP +#line 208 "dtc-lexer.l" +{ return DT_NE; }; +	YY_BREAK +case 27: +YY_RULE_SETUP +#line 209 "dtc-lexer.l" +{ return DT_AND; }; +	YY_BREAK +case 28: +YY_RULE_SETUP +#line 210 "dtc-lexer.l" +{ return DT_OR; }; +	YY_BREAK +case 29: +YY_RULE_SETUP +#line 212 "dtc-lexer.l"  { -			yylloc.file = srcpos_file; -			yylloc.first_line = yylineno;  			DPRINT("Char: %c (\\x%02x)\n", yytext[0],  				(unsigned)yytext[0]);  			if (yytext[0] == '[') { @@ -1148,12 +1202,12 @@ YY_RULE_SETUP  			return yytext[0];  		}  	YY_BREAK -case 20: +case 30:  YY_RULE_SETUP -#line 222 "dtc-lexer.l" +#line 227 "dtc-lexer.l"  ECHO;  	YY_BREAK -#line 1157 "dtc-lexer.lex.c" +#line 1211 "dtc-lexer.lex.c"  	case YY_END_OF_BUFFER:  		{ @@ -1218,7 +1272,8 @@ ECHO;  			else  				{ -				yy_cp = (yy_c_buf_p); +				yy_cp = (yy_last_accepting_cpos); +				yy_current_state = (yy_last_accepting_state);  				goto yy_find_action;  				}  			} @@ -1431,6 +1486,7 @@ static int yy_get_next_buffer (void)  	register char *yy_cp;  	yy_current_state = (yy_start); +	yy_current_state += YY_AT_BOL();  	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )  		{ @@ -1443,7 +1499,7 @@ static int yy_get_next_buffer (void)  		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )  			{  			yy_current_state = (int) yy_def[yy_current_state]; -			if ( yy_current_state >= 104 ) +			if ( yy_current_state >= 161 )  				yy_c = yy_meta[(unsigned int) yy_c];  			}  		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1471,11 +1527,11 @@ static int yy_get_next_buffer (void)  	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )  		{  		yy_current_state = (int) yy_def[yy_current_state]; -		if ( yy_current_state >= 104 ) +		if ( yy_current_state >= 161 )  			yy_c = yy_meta[(unsigned int) yy_c];  		}  	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; -	yy_is_jam = (yy_current_state == 103); +	yy_is_jam = (yy_current_state == 160);  	return yy_is_jam ? 0 : yy_current_state;  } @@ -1550,10 +1606,7 @@ static int yy_get_next_buffer (void)  	*(yy_c_buf_p) = '\0';	/* preserve yytext */  	(yy_hold_char) = *++(yy_c_buf_p); -	if ( c == '\n' ) -		    -    yylineno++; -; +	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');  	return c;  } @@ -1669,10 +1722,6 @@ static void yy_load_buffer_state  (void)  	yyfree((void *) b  );  } -#ifndef __cplusplus -extern int isatty (int ); -#endif /* __cplusplus */ -      /* Initializes or reinitializes a buffer.   * This function is sometimes called more than once on the same buffer,   * such as during a yyrestart() or at EOF. @@ -1696,7 +1745,7 @@ extern int isatty (int );          b->yy_bs_column = 0;      } -        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +        b->yy_is_interactive = 0;  	errno = oerrno;  } @@ -2025,9 +2074,6 @@ static int yy_init_globals (void)       * This function is called from yylex_destroy(), so don't allocate here.       */ -    /* We do not touch yylineno unless the option is enabled. */ -    yylineno =  1; -          (yy_buffer_stack) = 0;      (yy_buffer_stack_top) = 0;      (yy_buffer_stack_max) = 0; @@ -2120,104 +2166,29 @@ void yyfree (void * ptr )  #define YYTABLES_NAME "yytables" -#line 222 "dtc-lexer.l" - - - - -/* - * Stack of nested include file contexts. - */ - -struct incl_file { -	struct dtc_file *file; -	YY_BUFFER_STATE yy_prev_buf; -	int yy_prev_lineno; -	struct incl_file *prev; -}; - -static struct incl_file *incl_file_stack; - +#line 227 "dtc-lexer.l" -/* - * Detect infinite include recursion. - */ -#define MAX_INCLUDE_DEPTH	(100) - -static int incl_depth = 0;  static void push_input_file(const char *filename)  { -	struct incl_file *incl_file; -	struct dtc_file *newfile; -	struct search_path search, *searchptr = NULL; -  	assert(filename); -	if (incl_depth++ >= MAX_INCLUDE_DEPTH) -		die("Includes nested too deeply"); +	srcfile_push(filename); -	if (srcpos_file) { -		search.dir = srcpos_file->dir; -		search.next = NULL; -		search.prev = NULL; -		searchptr = &search; -	} - -	newfile = dtc_open_file(filename, searchptr); - -	incl_file = xmalloc(sizeof(struct incl_file)); - -	/* -	 * Save current context. -	 */ -	incl_file->yy_prev_buf = YY_CURRENT_BUFFER; -	incl_file->yy_prev_lineno = yylineno; -	incl_file->file = srcpos_file; -	incl_file->prev = incl_file_stack; +	yyin = current_srcfile->f; -	incl_file_stack = incl_file; - -	/* -	 * Establish new context. -	 */ -	srcpos_file = newfile; -	yylineno = 1; -	yyin = newfile->file; -	yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE)); +	yypush_buffer_state(yy_create_buffer(yyin,YY_BUF_SIZE));  }  static int pop_input_file(void)  { -	struct incl_file *incl_file; - -	if (incl_file_stack == 0) +	if (srcfile_pop() == 0)  		return 0; -	dtc_close_file(srcpos_file); - -	/* -	 * Pop. -	 */ -	--incl_depth; -	incl_file = incl_file_stack; -	incl_file_stack = incl_file->prev; - -	/* -	 * Recover old context. -	 */ -	yy_delete_buffer(YY_CURRENT_BUFFER); -	yy_switch_to_buffer(incl_file->yy_prev_buf); -	yylineno = incl_file->yy_prev_lineno; -	srcpos_file = incl_file->file; -	yyin = incl_file->file ? incl_file->file->file : NULL; - -	/* -	 * Free old state. -	 */ -	free(incl_file); +	yypop_buffer_state(); +	yyin = current_srcfile->f;  	return 1;  } diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped index 27129377e5d..c8769d550cf 100644 --- a/scripts/dtc/dtc-parser.tab.c_shipped +++ b/scripts/dtc/dtc-parser.tab.c_shipped @@ -1,24 +1,21 @@ -/* A Bison parser, made by GNU Bison 2.3.  */ +/* A Bison parser, made by GNU Bison 2.7.12-4996.  */ -/* Skeleton implementation for Bison's Yacc-like parsers in C - -   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 -   Free Software Foundation, Inc. - -   This program is free software; you can redistribute it and/or modify +/* Bison implementation for Yacc-like parsers in C +    +      Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. +    +   This program is free software: you can redistribute it and/or modify     it under the terms of the GNU General Public License as published by -   the Free Software Foundation; either version 2, or (at your option) -   any later version. - +   the Free Software Foundation, either version 3 of the License, or +   (at your option) any later version. +        This program is distributed in the hope that it will be useful,     but WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     GNU General Public License for more details. - +        You should have received a copy of the GNU General Public License -   along with this program; if not, write to the Free Software -   Foundation, Inc., 51 Franklin Street, Fifth Floor, -   Boston, MA 02110-1301, USA.  */ +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */  /* As a special exception, you may create a larger work that contains     part or all of the Bison parser skeleton and distribute that work @@ -29,7 +26,7 @@     special exception, which will cause the skeleton and the resulting     Bison output files to be licensed under the GNU General Public     License without this special exception. - +        This special exception was added by the Free Software Foundation in     version 2.2 of Bison.  */ @@ -47,7 +44,7 @@  #define YYBISON 1  /* Bison version.  */ -#define YYBISON_VERSION "2.3" +#define YYBISON_VERSION "2.7.12-4996"  /* Skeleton name.  */  #define YYSKELETON_NAME "yacc.c" @@ -55,66 +52,46 @@  /* Pure parsers.  */  #define YYPURE 0 -/* Using locations.  */ -#define YYLSP_NEEDED 1 +/* Push parsers.  */ +#define YYPUSH 0 - - -/* Tokens.  */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE -   /* Put the tokens into the symbol table, so that GDB and other debuggers -      know about them.  */ -   enum yytokentype { -     DT_V1 = 258, -     DT_MEMRESERVE = 259, -     DT_PROPNODENAME = 260, -     DT_LITERAL = 261, -     DT_LEGACYLITERAL = 262, -     DT_BASE = 263, -     DT_BYTE = 264, -     DT_STRING = 265, -     DT_LABEL = 266, -     DT_REF = 267, -     DT_INCBIN = 268 -   }; -#endif -/* Tokens.  */ -#define DT_V1 258 -#define DT_MEMRESERVE 259 -#define DT_PROPNODENAME 260 -#define DT_LITERAL 261 -#define DT_LEGACYLITERAL 262 -#define DT_BASE 263 -#define DT_BYTE 264 -#define DT_STRING 265 -#define DT_LABEL 266 -#define DT_REF 267 -#define DT_INCBIN 268 +/* Pull parsers.  */ +#define YYPULL 1  /* Copy the first part of user declarations.  */ -#line 23 "dtc-parser.y" +/* Line 371 of yacc.c  */ +#line 21 "dtc-parser.y"  #include <stdio.h>  #include "dtc.h"  #include "srcpos.h" +YYLTYPE yylloc; +  extern int yylex(void); +extern void print_error(char const *fmt, ...); +extern void yyerror(char const *s);  extern struct boot_info *the_boot_info;  extern int treesource_error;  static unsigned long long eval_literal(const char *s, int base, int bits); +static unsigned char eval_char_literal(const char *s); +/* Line 371 of yacc.c  */ +#line 87 "dtc-parser.tab.c" -/* Enabling traces.  */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif +# ifndef YY_NULL +#  if defined __cplusplus && 201103L <= __cplusplus +#   define YY_NULL nullptr +#  else +#   define YY_NULL 0 +#  endif +# endif  /* Enabling verbose error messages.  */  #ifdef YYERROR_VERBOSE @@ -124,15 +101,56 @@ static unsigned long long eval_literal(const char *s, int base, int bits);  # define YYERROR_VERBOSE 0  #endif -/* Enabling the token table.  */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 +/* In a future release of Bison, this section will be replaced +   by #include "dtc-parser.tab.h".  */ +#ifndef YY_YY_DTC_PARSER_TAB_H_INCLUDED +# define YY_YY_DTC_PARSER_TAB_H_INCLUDED +/* Enabling traces.  */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Tokens.  */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE +   /* Put the tokens into the symbol table, so that GDB and other debuggers +      know about them.  */ +   enum yytokentype { +     DT_V1 = 258, +     DT_MEMRESERVE = 259, +     DT_LSHIFT = 260, +     DT_RSHIFT = 261, +     DT_LE = 262, +     DT_GE = 263, +     DT_EQ = 264, +     DT_NE = 265, +     DT_AND = 266, +     DT_OR = 267, +     DT_BITS = 268, +     DT_DEL_PROP = 269, +     DT_DEL_NODE = 270, +     DT_PROPNODENAME = 271, +     DT_LITERAL = 272, +     DT_CHAR_LITERAL = 273, +     DT_BASE = 274, +     DT_BYTE = 275, +     DT_STRING = 276, +     DT_LABEL = 277, +     DT_REF = 278, +     DT_INCBIN = 279 +   };  #endif +  #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED  typedef union YYSTYPE -#line 37 "dtc-parser.y"  { +/* Line 387 of yacc.c  */ +#line 40 "dtc-parser.y" +  	char *propnodename;  	char *literal;  	char *labelref; @@ -140,41 +158,49 @@ typedef union YYSTYPE  	uint8_t byte;  	struct data data; -	uint64_t addr; -	cell_t cell; +	struct { +		struct data	data; +		int		bits; +	} array; +  	struct property *prop;  	struct property *proplist;  	struct node *node;  	struct node *nodelist;  	struct reserve_info *re; -} -/* Line 187 of yacc.c.  */ -#line 153 "dtc-parser.tab.c" -	YYSTYPE; +	uint64_t integer; + + +/* Line 387 of yacc.c  */ +#line 176 "dtc-parser.tab.c" +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1  # define yystype YYSTYPE /* obsolescent; will be withdrawn */  # define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1  #endif -#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED -typedef struct YYLTYPE -{ -  int first_line; -  int first_column; -  int last_line; -  int last_column; -} YYLTYPE; -# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ -# define YYLTYPE_IS_DECLARED 1 -# define YYLTYPE_IS_TRIVIAL 1 +extern YYSTYPE yylval; + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse ();  #endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ +#endif /* !YY_YY_DTC_PARSER_TAB_H_INCLUDED  */  /* Copy the second part of user declarations.  */ - -/* Line 216 of yacc.c.  */ -#line 178 "dtc-parser.tab.c" +/* Line 390 of yacc.c  */ +#line 204 "dtc-parser.tab.c"  #ifdef short  # undef short @@ -224,39 +250,48 @@ typedef short int yytype_int16;  #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)  #ifndef YY_ -# if YYENABLE_NLS +# if defined YYENABLE_NLS && YYENABLE_NLS  #  if ENABLE_NLS  #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */ -#   define YY_(msgid) dgettext ("bison-runtime", msgid) +#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)  #  endif  # endif  # ifndef YY_ -#  define YY_(msgid) msgid +#  define YY_(Msgid) Msgid +# endif +#endif + +#ifndef __attribute__ +/* This feature is available in gcc versions 2.5 and later.  */ +# if (! defined __GNUC__ || __GNUC__ < 2 \ +      || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)) +#  define __attribute__(Spec) /* empty */  # endif  #endif  /* Suppress unused-variable warnings by "using" E.  */  #if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) +# define YYUSE(E) ((void) (E))  #else -# define YYUSE(e) /* empty */ +# define YYUSE(E) /* empty */  #endif +  /* Identity function, used to suppress warnings about constant conditions.  */  #ifndef lint -# define YYID(n) (n) +# define YYID(N) (N)  #else  #if (defined __STDC__ || defined __C99__FUNC__ \       || defined __cplusplus || defined _MSC_VER)  static int -YYID (int i) +YYID (int yyi)  #else  static int -YYID (i) -    int i; +YYID (yyi) +    int yyi;  #endif  { -  return i; +  return yyi;  }  #endif @@ -277,11 +312,12 @@ YYID (i)  #    define alloca _alloca  #   else  #    define YYSTACK_ALLOC alloca -#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \       || defined __cplusplus || defined _MSC_VER)  #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ -#     ifndef _STDLIB_H -#      define _STDLIB_H 1 +      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */ +#     ifndef EXIT_SUCCESS +#      define EXIT_SUCCESS 0  #     endif  #    endif  #   endif @@ -304,24 +340,24 @@ YYID (i)  #  ifndef YYSTACK_ALLOC_MAXIMUM  #   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM  #  endif -#  if (defined __cplusplus && ! defined _STDLIB_H \ +#  if (defined __cplusplus && ! defined EXIT_SUCCESS \         && ! ((defined YYMALLOC || defined malloc) \  	     && (defined YYFREE || defined free)))  #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ -#   ifndef _STDLIB_H -#    define _STDLIB_H 1 +#   ifndef EXIT_SUCCESS +#    define EXIT_SUCCESS 0  #   endif  #  endif  #  ifndef YYMALLOC  #   define YYMALLOC malloc -#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +#   if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \       || defined __cplusplus || defined _MSC_VER)  void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */  #   endif  #  endif  #  ifndef YYFREE  #   define YYFREE free -#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +#   if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \       || defined __cplusplus || defined _MSC_VER)  void free (void *); /* INFRINGES ON USER NAME SPACE */  #   endif @@ -332,15 +368,13 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */  #if (! defined yyoverflow \       && (! defined __cplusplus \ -	 || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ -	     && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) +	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))  /* A type that is properly aligned for any stack member.  */  union yyalloc  { -  yytype_int16 yyss; -  YYSTYPE yyvs; -    YYLTYPE yyls; +  yytype_int16 yyss_alloc; +  YYSTYPE yyvs_alloc;  };  /* The size of the maximum gap between one aligned stack and the next.  */ @@ -349,38 +383,22 @@ union yyalloc  /* The size of an array large to enough to hold all stacks, each with     N elements.  */  # define YYSTACK_BYTES(N) \ -     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ -      + 2 * YYSTACK_GAP_MAXIMUM) +     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ +      + YYSTACK_GAP_MAXIMUM) -/* Copy COUNT objects from FROM to TO.  The source and destination do -   not overlap.  */ -# ifndef YYCOPY -#  if defined __GNUC__ && 1 < __GNUC__ -#   define YYCOPY(To, From, Count) \ -      __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -#  else -#   define YYCOPY(To, From, Count)		\ -      do					\ -	{					\ -	  YYSIZE_T yyi;				\ -	  for (yyi = 0; yyi < (Count); yyi++)	\ -	    (To)[yyi] = (From)[yyi];		\ -	}					\ -      while (YYID (0)) -#  endif -# endif +# define YYCOPY_NEEDED 1  /* Relocate STACK from its old location to the new one.  The     local variables YYSIZE and YYSTACKSIZE give the old and new number of     elements in the stack, and YYPTR gives the new location of the     stack.  Advance YYPTR to a properly aligned location for the next     stack.  */ -# define YYSTACK_RELOCATE(Stack)					\ +# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\      do									\        {									\  	YYSIZE_T yynewbytes;						\ -	YYCOPY (&yyptr->Stack, Stack, yysize);				\ -	Stack = &yyptr->Stack;						\ +	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\ +	Stack = &yyptr->Stack_alloc;					\  	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \  	yyptr += yynewbytes / sizeof (*yyptr);				\        }									\ @@ -388,23 +406,43 @@ union yyalloc  #endif +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST.  The source and destination do +   not overlap.  */ +# ifndef YYCOPY +#  if defined __GNUC__ && 1 < __GNUC__ +#   define YYCOPY(Dst, Src, Count) \ +      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +#  else +#   define YYCOPY(Dst, Src, Count)              \ +      do                                        \ +        {                                       \ +          YYSIZE_T yyi;                         \ +          for (yyi = 0; yyi < (Count); yyi++)   \ +            (Dst)[yyi] = (Src)[yyi];            \ +        }                                       \ +      while (YYID (0)) +#  endif +# endif +#endif /* !YYCOPY_NEEDED */ +  /* YYFINAL -- State number of the termination state.  */ -#define YYFINAL  9 +#define YYFINAL  4  /* YYLAST -- Last index in YYTABLE.  */ -#define YYLAST   73 +#define YYLAST   133  /* YYNTOKENS -- Number of terminals.  */ -#define YYNTOKENS  27 +#define YYNTOKENS  48  /* YYNNTS -- Number of nonterminals.  */ -#define YYNNTS  20 +#define YYNNTS  28  /* YYNRULES -- Number of rules.  */ -#define YYNRULES  45 +#define YYNRULES  79  /* YYNRULES -- Number of states.  */ -#define YYNSTATES  76 +#define YYNSTATES  141  /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */  #define YYUNDEFTOK  2 -#define YYMAXUTOK   268 +#define YYMAXUTOK   279  #define YYTRANSLATE(YYX)						\    ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -415,16 +453,16 @@ static const yytype_uint8 yytranslate[] =         0,     2,     2,     2,     2,     2,     2,     2,     2,     2,         2,     2,     2,     2,     2,     2,     2,     2,     2,     2,         2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,     2,     2,    47,     2,     2,     2,    45,    41,     2, +      33,    35,    44,    42,    34,    43,     2,    26,     2,     2, +       2,     2,     2,     2,     2,     2,     2,     2,    38,    25, +      36,    29,    30,    37,     2,     2,     2,     2,     2,     2,         2,     2,     2,     2,     2,     2,     2,     2,     2,     2, -      24,    26,     2,     2,    25,    15,     2,    16,     2,     2, -       2,     2,     2,     2,     2,     2,     2,     2,     2,    14, -      20,    19,    21,     2,     2,     2,     2,     2,     2,     2,         2,     2,     2,     2,     2,     2,     2,     2,     2,     2, +       2,    31,     2,    32,    40,     2,     2,     2,     2,     2,         2,     2,     2,     2,     2,     2,     2,     2,     2,     2, -       2,    22,     2,    23,     2,     2,     2,     2,     2,     2,         2,     2,     2,     2,     2,     2,     2,     2,     2,     2, -       2,     2,     2,     2,     2,     2,     2,     2,     2,     2, -       2,     2,     2,    17,     2,    18,     2,     2,     2,     2, +       2,     2,     2,    27,    39,    28,    46,     2,     2,     2,         2,     2,     2,     2,     2,     2,     2,     2,     2,     2,         2,     2,     2,     2,     2,     2,     2,     2,     2,     2,         2,     2,     2,     2,     2,     2,     2,     2,     2,     2, @@ -438,65 +476,89 @@ static const yytype_uint8 yytranslate[] =         2,     2,     2,     2,     2,     2,     2,     2,     2,     2,         2,     2,     2,     2,     2,     2,     2,     2,     2,     2,         2,     2,     2,     2,     2,     2,     1,     2,     3,     4, -       5,     6,     7,     8,     9,    10,    11,    12,    13 +       5,     6,     7,     8,     9,    10,    11,    12,    13,    14, +      15,    16,    17,    18,    19,    20,    21,    22,    23,    24  };  #if YYDEBUG  /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in     YYRHS.  */ -static const yytype_uint8 yyprhs[] = +static const yytype_uint16 yyprhs[] =  { -       0,     0,     3,     8,    11,    12,    15,    21,    22,    25, -      27,    34,    36,    38,    41,    47,    48,    51,    57,    61, -      64,    69,    74,    77,    87,    93,    96,    97,   100,   103, -     104,   107,   110,   113,   114,   116,   118,   121,   122,   125, -     128,   129,   132,   135,   139,   140 +       0,     0,     3,     8,     9,    12,    17,    20,    23,    27, +      31,    36,    42,    43,    46,    51,    54,    58,    61,    64, +      68,    73,    76,    86,    92,    95,    96,    99,   102,   106, +     108,   111,   114,   117,   119,   121,   125,   127,   129,   135, +     137,   141,   143,   147,   149,   153,   155,   159,   161,   165, +     167,   171,   175,   177,   181,   185,   189,   193,   197,   201, +     203,   207,   211,   213,   217,   221,   225,   227,   229,   232, +     235,   238,   239,   242,   245,   246,   249,   252,   255,   259  };  /* YYRHS -- A `-1'-separated list of the rules' RHS.  */  static const yytype_int8 yyrhs[] =  { -      28,     0,    -1,     3,    14,    29,    34,    -1,    31,    34, -      -1,    -1,    30,    29,    -1,    46,     4,    33,    33,    14, -      -1,    -1,    32,    31,    -1,    30,    -1,    46,     4,    33, -      15,    33,    14,    -1,     6,    -1,     7,    -1,    16,    35, -      -1,    17,    36,    44,    18,    14,    -1,    -1,    36,    37, -      -1,    46,     5,    19,    38,    14,    -1,    46,     5,    14, -      -1,    39,    10,    -1,    39,    20,    40,    21,    -1,    39, -      22,    43,    23,    -1,    39,    12,    -1,    39,    13,    24, -      10,    25,    33,    25,    33,    26,    -1,    39,    13,    24, -      10,    26,    -1,    38,    11,    -1,    -1,    38,    25,    -1, -      39,    11,    -1,    -1,    40,    42,    -1,    40,    12,    -1, -      40,    11,    -1,    -1,     8,    -1,     6,    -1,    41,     7, -      -1,    -1,    43,     9,    -1,    43,    11,    -1,    -1,    45, -      44,    -1,    45,    37,    -1,    46,     5,    35,    -1,    -1, -      11,    -1 +      49,     0,    -1,     3,    25,    50,    52,    -1,    -1,    51, +      50,    -1,     4,    59,    59,    25,    -1,    22,    51,    -1, +      26,    53,    -1,    52,    26,    53,    -1,    52,    23,    53, +      -1,    52,    15,    23,    25,    -1,    27,    54,    74,    28, +      25,    -1,    -1,    54,    55,    -1,    16,    29,    56,    25, +      -1,    16,    25,    -1,    14,    16,    25,    -1,    22,    55, +      -1,    57,    21,    -1,    57,    58,    30,    -1,    57,    31, +      73,    32,    -1,    57,    23,    -1,    57,    24,    33,    21, +      34,    59,    34,    59,    35,    -1,    57,    24,    33,    21, +      35,    -1,    56,    22,    -1,    -1,    56,    34,    -1,    57, +      22,    -1,    13,    17,    36,    -1,    36,    -1,    58,    59, +      -1,    58,    23,    -1,    58,    22,    -1,    17,    -1,    18, +      -1,    33,    60,    35,    -1,    61,    -1,    62,    -1,    62, +      37,    60,    38,    61,    -1,    63,    -1,    62,    12,    63, +      -1,    64,    -1,    63,    11,    64,    -1,    65,    -1,    64, +      39,    65,    -1,    66,    -1,    65,    40,    66,    -1,    67, +      -1,    66,    41,    67,    -1,    68,    -1,    67,     9,    68, +      -1,    67,    10,    68,    -1,    69,    -1,    68,    36,    69, +      -1,    68,    30,    69,    -1,    68,     7,    69,    -1,    68, +       8,    69,    -1,    69,     5,    70,    -1,    69,     6,    70, +      -1,    70,    -1,    70,    42,    71,    -1,    70,    43,    71, +      -1,    71,    -1,    71,    44,    72,    -1,    71,    26,    72, +      -1,    71,    45,    72,    -1,    72,    -1,    59,    -1,    43, +      72,    -1,    46,    72,    -1,    47,    72,    -1,    -1,    73, +      20,    -1,    73,    22,    -1,    -1,    75,    74,    -1,    75, +      55,    -1,    16,    53,    -1,    15,    16,    25,    -1,    22, +      75,    -1  };  /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */  static const yytype_uint16 yyrline[] =  { -       0,    89,    89,    93,   101,   104,   111,   119,   122,   129, -     133,   140,   144,   151,   158,   166,   169,   176,   180,   187, -     191,   195,   199,   203,   220,   231,   239,   242,   246,   254, -     257,   261,   266,   274,   277,   281,   285,   293,   296,   300, -     308,   311,   315,   323,   331,   334 +       0,   109,   109,   118,   121,   128,   132,   140,   144,   148, +     158,   172,   180,   183,   190,   194,   198,   202,   210,   214, +     218,   222,   226,   243,   253,   261,   264,   268,   275,   290, +     295,   315,   329,   336,   340,   344,   351,   355,   356,   360, +     361,   365,   366,   370,   371,   375,   376,   380,   381,   385, +     386,   387,   391,   392,   393,   394,   395,   399,   400,   401, +     405,   406,   407,   411,   412,   413,   414,   418,   419,   420, +     421,   426,   429,   433,   441,   444,   448,   456,   460,   464  };  #endif -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +#if YYDEBUG || YYERROR_VERBOSE || 0  /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.     First, the terminals, then, starting at YYNTOKENS, nonterminals.  */  static const char *const yytname[] =  { -  "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE", -  "DT_PROPNODENAME", "DT_LITERAL", "DT_LEGACYLITERAL", "DT_BASE", -  "DT_BYTE", "DT_STRING", "DT_LABEL", "DT_REF", "DT_INCBIN", "';'", "'-'", -  "'/'", "'{'", "'}'", "'='", "'<'", "'>'", "'['", "']'", "'('", "','", -  "')'", "$accept", "sourcefile", "memreserves", "memreserve", -  "v0_memreserves", "v0_memreserve", "addr", "devicetree", "nodedef", -  "proplist", "propdef", "propdata", "propdataprefix", "celllist", -  "cellbase", "cellval", "bytestring", "subnodes", "subnode", "label", 0 +  "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE", "DT_LSHIFT", +  "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND", "DT_OR", +  "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME", "DT_LITERAL", +  "DT_CHAR_LITERAL", "DT_BASE", "DT_BYTE", "DT_STRING", "DT_LABEL", +  "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['", +  "']'", "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'", +  "'+'", "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile", +  "memreserves", "memreserve", "devicetree", "nodedef", "proplist", +  "propdef", "propdata", "propdataprefix", "arrayprefix", "integer_prim", +  "integer_expr", "integer_trinary", "integer_or", "integer_and", +  "integer_bitor", "integer_bitxor", "integer_bitand", "integer_eq", +  "integer_rela", "integer_shift", "integer_add", "integer_mul", +  "integer_unary", "bytestring", "subnodes", "subnode", YY_NULL  };  #endif @@ -506,116 +568,164 @@ static const char *const yytname[] =  static const yytype_uint16 yytoknum[] =  {         0,   256,   257,   258,   259,   260,   261,   262,   263,   264, -     265,   266,   267,   268,    59,    45,    47,   123,   125,    61, -      60,    62,    91,    93,    40,    44,    41 +     265,   266,   267,   268,   269,   270,   271,   272,   273,   274, +     275,   276,   277,   278,   279,    59,    47,   123,   125,    61, +      62,    91,    93,    40,    44,    41,    60,    63,    58,   124, +      94,    38,    43,    45,    42,    37,   126,    33  };  # endif  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */  static const yytype_uint8 yyr1[] =  { -       0,    27,    28,    28,    29,    29,    30,    31,    31,    32, -      32,    33,    33,    34,    35,    36,    36,    37,    37,    38, -      38,    38,    38,    38,    38,    38,    39,    39,    39,    40, -      40,    40,    40,    41,    41,    42,    42,    43,    43,    43, -      44,    44,    44,    45,    46,    46 +       0,    48,    49,    50,    50,    51,    51,    52,    52,    52, +      52,    53,    54,    54,    55,    55,    55,    55,    56,    56, +      56,    56,    56,    56,    56,    57,    57,    57,    58,    58, +      58,    58,    58,    59,    59,    59,    60,    61,    61,    62, +      62,    63,    63,    64,    64,    65,    65,    66,    66,    67, +      67,    67,    68,    68,    68,    68,    68,    69,    69,    69, +      70,    70,    70,    71,    71,    71,    71,    72,    72,    72, +      72,    73,    73,    73,    74,    74,    74,    75,    75,    75  };  /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */  static const yytype_uint8 yyr2[] =  { -       0,     2,     4,     2,     0,     2,     5,     0,     2,     1, -       6,     1,     1,     2,     5,     0,     2,     5,     3,     2, -       4,     4,     2,     9,     5,     2,     0,     2,     2,     0, -       2,     2,     2,     0,     1,     1,     2,     0,     2,     2, -       0,     2,     2,     3,     0,     1 +       0,     2,     4,     0,     2,     4,     2,     2,     3,     3, +       4,     5,     0,     2,     4,     2,     3,     2,     2,     3, +       4,     2,     9,     5,     2,     0,     2,     2,     3,     1, +       2,     2,     2,     1,     1,     3,     1,     1,     5,     1, +       3,     1,     3,     1,     3,     1,     3,     1,     3,     1, +       3,     3,     1,     3,     3,     3,     3,     3,     3,     1, +       3,     3,     1,     3,     3,     3,     1,     1,     2,     2, +       2,     0,     2,     2,     0,     2,     2,     2,     3,     2  }; -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state -   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero +/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. +   Performed when YYTABLE doesn't specify something else to do.  Zero     means the default is an error.  */  static const yytype_uint8 yydefact[] =  { -       7,     0,    45,     0,     9,     0,     7,     0,     4,     1, -       0,     3,     8,     0,     0,     4,     0,    15,    13,    11, -      12,     0,     2,     5,     0,    40,     0,     0,     0,    16, -       0,    40,     0,     0,     6,     0,    42,    41,     0,    10, -      14,    18,    26,    43,     0,     0,    25,    17,    27,    19, -      28,    22,     0,    29,    37,     0,    33,     0,     0,    35, -      34,    32,    31,    20,     0,    30,    38,    39,    21,     0, -      24,    36,     0,     0,     0,    23 +       0,     0,     0,     3,     1,     0,     0,     0,     3,    33, +      34,     0,     0,     6,     0,     2,     4,     0,     0,     0, +      67,     0,    36,    37,    39,    41,    43,    45,    47,    49, +      52,    59,    62,    66,     0,    12,     7,     0,     0,     0, +      68,    69,    70,    35,     0,     0,     0,     0,     0,     0, +       0,     0,     0,     0,     0,     0,     0,     0,     0,     0, +       0,     0,     0,     5,    74,     0,     9,     8,    40,     0, +      42,    44,    46,    48,    50,    51,    55,    56,    54,    53, +      57,    58,    60,    61,    64,    63,    65,     0,     0,     0, +       0,    13,     0,    74,    10,     0,     0,     0,    15,    25, +      77,    17,    79,     0,    76,    75,    38,    16,    78,     0, +       0,    11,    24,    14,    26,     0,    18,    27,    21,     0, +      71,    29,     0,     0,     0,     0,    32,    31,    19,    30, +      28,     0,    72,    73,    20,     0,    23,     0,     0,     0, +      22  };  /* YYDEFGOTO[NTERM-NUM].  */  static const yytype_int8 yydefgoto[] =  { -      -1,     3,    14,     4,     5,     6,    27,    11,    18,    25, -      29,    44,    45,    56,    64,    65,    57,    30,    31,     7 +      -1,     2,     7,     8,    15,    36,    64,    91,   109,   110, +     122,    20,    21,    22,    23,    24,    25,    26,    27,    28, +      29,    30,    31,    32,    33,   125,    92,    93  };  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing     STATE-NUM.  */ -#define YYPACT_NINF -14 +#define YYPACT_NINF -78  static const yytype_int8 yypact[] =  { -      30,   -11,   -14,     7,   -14,    -1,    27,    13,    27,   -14, -       8,   -14,   -14,    40,    -1,    27,    35,   -14,   -14,   -14, -     -14,    21,   -14,   -14,    40,    24,    40,    28,    40,   -14, -      32,    24,    46,    38,   -14,    39,   -14,   -14,    26,   -14, -     -14,   -14,   -14,   -14,    -9,    10,   -14,   -14,   -14,   -14, -     -14,   -14,    31,   -14,   -14,    44,    -2,     3,    23,   -14, -     -14,   -14,   -14,   -14,    50,   -14,   -14,   -14,   -14,    40, -     -14,   -14,    33,    40,    36,   -14 +      22,    11,    51,    10,   -78,    23,    10,     2,    10,   -78, +     -78,    -9,    23,   -78,    30,    38,   -78,    -9,    -9,    -9, +     -78,    35,   -78,    -6,    52,    29,    48,    49,    33,     3, +      71,    36,     0,   -78,    64,   -78,   -78,    68,    30,    30, +     -78,   -78,   -78,   -78,    -9,    -9,    -9,    -9,    -9,    -9, +      -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9, +      -9,    -9,    -9,   -78,    44,    67,   -78,   -78,    52,    55, +      29,    48,    49,    33,     3,     3,    71,    71,    71,    71, +      36,    36,     0,     0,   -78,   -78,   -78,    78,    79,    42, +      44,   -78,    69,    44,   -78,    -9,    73,    74,   -78,   -78, +     -78,   -78,   -78,    75,   -78,   -78,   -78,   -78,   -78,    -7, +      -1,   -78,   -78,   -78,   -78,    84,   -78,   -78,   -78,    63, +     -78,   -78,    32,    66,    82,    -3,   -78,   -78,   -78,   -78, +     -78,    46,   -78,   -78,   -78,    23,   -78,    70,    23,    72, +     -78  };  /* YYPGOTO[NTERM-NUM].  */  static const yytype_int8 yypgoto[] =  { -     -14,   -14,    48,    29,    53,   -14,   -13,    47,    34,   -14, -      37,   -14,   -14,   -14,   -14,   -14,   -14,    42,   -14,    -7 +     -78,   -78,    97,   100,   -78,   -37,   -78,   -77,   -78,   -78, +     -78,    -5,    65,    13,   -78,    76,    77,    62,    80,    83, +      34,    20,    26,    28,   -14,   -78,    18,    24  };  /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If     positive, shift that token.  If negative, reduce the rule which -   number is the opposite.  If zero, do what YYDEFACT says. -   If YYTABLE_NINF, syntax error.  */ -#define YYTABLE_NINF -45 -static const yytype_int8 yytable[] = +   number is the opposite.  If YYTABLE_NINF, syntax error.  */ +#define YYTABLE_NINF -1 +static const yytype_uint8 yytable[] =  { -      21,    16,    46,     8,    59,    47,    60,     9,    16,    61, -      62,    28,    66,    33,    67,    10,    48,    13,    32,    63, -      49,    50,    51,    52,    32,    17,    68,    19,    20,   -44, -      53,   -44,    54,     1,   -44,     2,    26,    15,     2,    24, -      41,     2,    34,    17,    15,    42,    19,    20,    69,    70, -      35,    38,    39,    40,    58,    55,    72,    71,    73,    12, -      74,    22,    75,    23,     0,     0,     0,     0,    36,     0, -       0,     0,    43,    37 +      12,    66,    67,    40,    41,    42,    44,    34,     9,    10, +      52,    53,   115,   101,     5,   112,   104,   132,   113,   133, +     116,   117,   118,   119,    11,     1,    60,   114,    14,   134, +     120,    45,     6,    54,    17,   121,     3,    18,    19,    55, +       9,    10,    50,    51,    61,    62,    84,    85,    86,     9, +      10,     4,   100,    37,   126,   127,    11,    35,    87,    88, +      89,    38,   128,    46,    39,    11,    90,    98,    47,    35, +      43,    99,    76,    77,    78,    79,    56,    57,    58,    59, +     135,   136,    80,    81,    74,    75,    82,    83,    48,    63, +      49,    65,    94,    95,    96,    97,   124,   103,   107,   108, +     111,   123,   130,   131,   138,    16,    13,   140,   106,    71, +      69,   105,     0,     0,   102,     0,     0,   129,     0,     0, +      68,     0,     0,    70,     0,     0,     0,     0,    72,     0, +     137,     0,    73,   139  }; -static const yytype_int8 yycheck[] = +#define yypact_value_is_default(Yystate) \ +  (!!((Yystate) == (-78))) + +#define yytable_value_is_error(Yytable_value) \ +  YYID (0) + +static const yytype_int16 yycheck[] =  { -      13,     8,    11,    14,     6,    14,     8,     0,    15,    11, -      12,    24,     9,    26,    11,    16,    25,     4,    25,    21, -      10,    11,    12,    13,    31,    17,    23,     6,     7,     5, -      20,     4,    22,     3,     4,    11,    15,     8,    11,     4, -      14,    11,    14,    17,    15,    19,     6,     7,    25,    26, -      18,     5,    14,    14,    10,    24,    69,     7,    25,     6, -      73,    14,    26,    15,    -1,    -1,    -1,    -1,    31,    -1, -      -1,    -1,    38,    31 +       5,    38,    39,    17,    18,    19,    12,    12,    17,    18, +       7,     8,    13,    90,     4,    22,    93,    20,    25,    22, +      21,    22,    23,    24,    33,     3,    26,    34,    26,    32, +      31,    37,    22,    30,    43,    36,    25,    46,    47,    36, +      17,    18,     9,    10,    44,    45,    60,    61,    62,    17, +      18,     0,    89,    15,    22,    23,    33,    27,    14,    15, +      16,    23,    30,    11,    26,    33,    22,    25,    39,    27, +      35,    29,    52,    53,    54,    55,     5,     6,    42,    43, +      34,    35,    56,    57,    50,    51,    58,    59,    40,    25, +      41,    23,    25,    38,    16,    16,    33,    28,    25,    25, +      25,    17,    36,    21,    34,     8,     6,    35,    95,    47, +      45,    93,    -1,    -1,    90,    -1,    -1,   122,    -1,    -1, +      44,    -1,    -1,    46,    -1,    -1,    -1,    -1,    48,    -1, +     135,    -1,    49,   138  };  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing     symbol of state STATE-NUM.  */  static const yytype_uint8 yystos[] =  { -       0,     3,    11,    28,    30,    31,    32,    46,    14,     0, -      16,    34,    31,     4,    29,    30,    46,    17,    35,     6, -       7,    33,    34,    29,     4,    36,    15,    33,    33,    37, -      44,    45,    46,    33,    14,    18,    37,    44,     5,    14, -      14,    14,    19,    35,    38,    39,    11,    14,    25,    10, -      11,    12,    13,    20,    22,    24,    40,    43,    10,     6, -       8,    11,    12,    21,    41,    42,     9,    11,    23,    25, -      26,     7,    33,    25,    33,    26 +       0,     3,    49,    25,     0,     4,    22,    50,    51,    17, +      18,    33,    59,    51,    26,    52,    50,    43,    46,    47, +      59,    60,    61,    62,    63,    64,    65,    66,    67,    68, +      69,    70,    71,    72,    59,    27,    53,    15,    23,    26, +      72,    72,    72,    35,    12,    37,    11,    39,    40,    41, +       9,    10,     7,     8,    30,    36,     5,     6,    42,    43, +      26,    44,    45,    25,    54,    23,    53,    53,    63,    60, +      64,    65,    66,    67,    68,    68,    69,    69,    69,    69, +      70,    70,    71,    71,    72,    72,    72,    14,    15,    16, +      22,    55,    74,    75,    25,    38,    16,    16,    25,    29, +      53,    55,    75,    28,    55,    74,    61,    25,    25,    56, +      57,    25,    22,    25,    34,    13,    21,    22,    23,    24, +      31,    36,    58,    17,    33,    73,    22,    23,    30,    59, +      36,    21,    20,    22,    32,    34,    35,    59,    34,    59, +      35  };  #define yyerrok		(yyerrstatus = 0) @@ -630,78 +740,50 @@ static const yytype_uint8 yystos[] =  /* Like YYERROR except do call yyerror.  This remains here temporarily     to ease the transition to the new meaning of YYERROR, for GCC. -   Once GCC version 2 has supplanted version 1, this can go.  */ +   Once GCC version 2 has supplanted version 1, this can go.  However, +   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated +   in Bison 2.4.2's NEWS entry, where a plan to phase it out is +   discussed.  */  #define YYFAIL		goto yyerrlab +#if defined YYFAIL +  /* This is here to suppress warnings from the GCC cpp's +     -Wunused-macros.  Normally we don't worry about that warning, but +     some users do, and we want to make it easy for users to remove +     YYFAIL uses, which will produce warnings from Bison 2.5.  */ +#endif  #define YYRECOVERING()  (!!yyerrstatus) -#define YYBACKUP(Token, Value)					\ -do								\ -  if (yychar == YYEMPTY && yylen == 1)				\ -    {								\ -      yychar = (Token);						\ -      yylval = (Value);						\ -      yytoken = YYTRANSLATE (yychar);				\ -      YYPOPSTACK (1);						\ -      goto yybackup;						\ -    }								\ -  else								\ -    {								\ +#define YYBACKUP(Token, Value)                                  \ +do                                                              \ +  if (yychar == YYEMPTY)                                        \ +    {                                                           \ +      yychar = (Token);                                         \ +      yylval = (Value);                                         \ +      YYPOPSTACK (yylen);                                       \ +      yystate = *yyssp;                                         \ +      goto yybackup;                                            \ +    }                                                           \ +  else                                                          \ +    {                                                           \        yyerror (YY_("syntax error: cannot back up")); \        YYERROR;							\      }								\  while (YYID (0)) - +/* Error token number */  #define YYTERROR	1  #define YYERRCODE	256 -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. -   If N is 0, then set CURRENT to the empty location which ends -   the previous symbol: RHS[0] (always defined).  */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N)				\ -    do									\ -      if (YYID (N))                                                    \ -	{								\ -	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\ -	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\ -	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\ -	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\ -	}								\ -      else								\ -	{								\ -	  (Current).first_line   = (Current).last_line   =		\ -	    YYRHSLOC (Rhs, 0).last_line;				\ -	  (Current).first_column = (Current).last_column =		\ -	    YYRHSLOC (Rhs, 0).last_column;				\ -	}								\ -    while (YYID (0)) -#endif - - -/* YY_LOCATION_PRINT -- Print the location on the stream. -   This macro was not mandated originally: define only if we know -   we won't break user code: when these are the locations we know.  */ - +/* This macro is provided for backward compatibility. */  #ifndef YY_LOCATION_PRINT -# if YYLTYPE_IS_TRIVIAL -#  define YY_LOCATION_PRINT(File, Loc)			\ -     fprintf (File, "%d.%d-%d.%d",			\ -	      (Loc).first_line, (Loc).first_column,	\ -	      (Loc).last_line,  (Loc).last_column) -# else -#  define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif +# define YY_LOCATION_PRINT(File, Loc) ((void) 0)  #endif  /* YYLEX -- calling `yylex' with the right arguments.  */ -  #ifdef YYLEX_PARAM  # define YYLEX yylex (YYLEX_PARAM)  #else @@ -728,7 +810,7 @@ do {									  \      {									  \        YYFPRINTF (stderr, "%s ", Title);					  \        yy_symbol_print (stderr,						  \ -		  Type, Value, Location); \ +		  Type, Value); \        YYFPRINTF (stderr, "\n");						  \      }									  \  } while (YYID (0)) @@ -742,30 +824,26 @@ do {									  \  #if (defined __STDC__ || defined __C99__FUNC__ \       || defined __cplusplus || defined _MSC_VER)  static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp) +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)  #else  static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp) +yy_symbol_value_print (yyoutput, yytype, yyvaluep)      FILE *yyoutput;      int yytype;      YYSTYPE const * const yyvaluep; -    YYLTYPE const * const yylocationp;  #endif  { +  FILE *yyo = yyoutput; +  YYUSE (yyo);    if (!yyvaluep)      return; -  YYUSE (yylocationp);  # ifdef YYPRINT    if (yytype < YYNTOKENS)      YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);  # else    YYUSE (yyoutput);  # endif -  switch (yytype) -    { -      default: -	break; -    } +  YYUSE (yytype);  } @@ -776,14 +854,13 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)  #if (defined __STDC__ || defined __C99__FUNC__ \       || defined __cplusplus || defined _MSC_VER)  static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp) +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)  #else  static void -yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp) +yy_symbol_print (yyoutput, yytype, yyvaluep)      FILE *yyoutput;      int yytype;      YYSTYPE const * const yyvaluep; -    YYLTYPE const * const yylocationp;  #endif  {    if (yytype < YYNTOKENS) @@ -791,9 +868,7 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp)    else      YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); -  YY_LOCATION_PRINT (yyoutput, *yylocationp); -  YYFPRINTF (yyoutput, ": "); -  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp); +  yy_symbol_value_print (yyoutput, yytype, yyvaluep);    YYFPRINTF (yyoutput, ")");  } @@ -805,17 +880,20 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp)  #if (defined __STDC__ || defined __C99__FUNC__ \       || defined __cplusplus || defined _MSC_VER)  static void -yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)  #else  static void -yy_stack_print (bottom, top) -    yytype_int16 *bottom; -    yytype_int16 *top; +yy_stack_print (yybottom, yytop) +    yytype_int16 *yybottom; +    yytype_int16 *yytop;  #endif  {    YYFPRINTF (stderr, "Stack now"); -  for (; bottom <= top; ++bottom) -    YYFPRINTF (stderr, " %d", *bottom); +  for (; yybottom <= yytop; yybottom++) +    { +      int yybot = *yybottom; +      YYFPRINTF (stderr, " %d", yybot); +    }    YYFPRINTF (stderr, "\n");  } @@ -833,12 +911,11 @@ do {								\  #if (defined __STDC__ || defined __C99__FUNC__ \       || defined __cplusplus || defined _MSC_VER)  static void -yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule) +yy_reduce_print (YYSTYPE *yyvsp, int yyrule)  #else  static void -yy_reduce_print (yyvsp, yylsp, yyrule) +yy_reduce_print (yyvsp, yyrule)      YYSTYPE *yyvsp; -    YYLTYPE *yylsp;      int yyrule;  #endif  { @@ -850,18 +927,18 @@ yy_reduce_print (yyvsp, yylsp, yyrule)    /* The symbols being reduced.  */    for (yyi = 0; yyi < yynrhs; yyi++)      { -      fprintf (stderr, "   $%d = ", yyi + 1); +      YYFPRINTF (stderr, "   $%d = ", yyi + 1);        yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],  		       &(yyvsp[(yyi + 1) - (yynrhs)]) -		       , &(yylsp[(yyi + 1) - (yynrhs)])		       ); -      fprintf (stderr, "\n"); +		       		       ); +      YYFPRINTF (stderr, "\n");      }  }  # define YY_REDUCE_PRINT(Rule)		\  do {					\    if (yydebug)				\ -    yy_reduce_print (yyvsp, yylsp, Rule); \ +    yy_reduce_print (yyvsp, Rule); \  } while (YYID (0))  /* Nonzero means print parse trace.  It is left uninitialized so that @@ -891,7 +968,6 @@ int yydebug;  # define YYMAXDEPTH 10000  #endif -  #if YYERROR_VERBOSE @@ -994,115 +1070,145 @@ yytnamerr (char *yyres, const char *yystr)  }  # endif -/* Copy into YYRESULT an error message about the unexpected token -   YYCHAR while in state YYSTATE.  Return the number of bytes copied, -   including the terminating null byte.  If YYRESULT is null, do not -   copy anything; just return the number of bytes that would be -   copied.  As a special case, return 0 if an ordinary "syntax error" -   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during -   size calculation.  */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) -{ -  int yyn = yypact[yystate]; +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message +   about the unexpected token YYTOKEN for the state stack whose top is +   YYSSP. -  if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) -    return 0; -  else +   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is +   not large enough to hold the message.  In that case, also set +   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the +   required number of bytes is too large to store.  */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, +                yytype_int16 *yyssp, int yytoken) +{ +  YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); +  YYSIZE_T yysize = yysize0; +  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; +  /* Internationalized format string. */ +  const char *yyformat = YY_NULL; +  /* Arguments of yyformat. */ +  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; +  /* Number of reported tokens (one for the "unexpected", one per +     "expected"). */ +  int yycount = 0; + +  /* There are many possibilities here to consider: +     - Assume YYFAIL is not used.  It's too flawed to consider.  See +       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html> +       for details.  YYERROR is fine as it does not invoke this +       function. +     - If this state is a consistent state with a default action, then +       the only way this function was invoked is if the default action +       is an error action.  In that case, don't check for expected +       tokens because there are none. +     - The only way there can be no lookahead present (in yychar) is if +       this state is a consistent state with a default action.  Thus, +       detecting the absence of a lookahead is sufficient to determine +       that there is no unexpected or expected token to report.  In that +       case, just report a simple "syntax error". +     - Don't assume there isn't a lookahead just because this state is a +       consistent state with a default action.  There might have been a +       previous inconsistent state, consistent state with a non-default +       action, or user semantic action that manipulated yychar. +     - Of course, the expected token list depends on states to have +       correct lookahead information, and it depends on the parser not +       to perform extra reductions after fetching a lookahead from the +       scanner and before detecting a syntax error.  Thus, state merging +       (from LALR or IELR) and default reductions corrupt the expected +       token list.  However, the list is correct for canonical LR with +       one exception: it will still contain any token that will not be +       accepted due to an error action in a later state. +  */ +  if (yytoken != YYEMPTY)      { -      int yytype = YYTRANSLATE (yychar); -      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); -      YYSIZE_T yysize = yysize0; -      YYSIZE_T yysize1; -      int yysize_overflow = 0; -      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; -      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; -      int yyx; - -# if 0 -      /* This is so xgettext sees the translatable formats that are -	 constructed on the fly.  */ -      YY_("syntax error, unexpected %s"); -      YY_("syntax error, unexpected %s, expecting %s"); -      YY_("syntax error, unexpected %s, expecting %s or %s"); -      YY_("syntax error, unexpected %s, expecting %s or %s or %s"); -      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif -      char *yyfmt; -      char const *yyf; -      static char const yyunexpected[] = "syntax error, unexpected %s"; -      static char const yyexpecting[] = ", expecting %s"; -      static char const yyor[] = " or %s"; -      char yyformat[sizeof yyunexpected -		    + sizeof yyexpecting - 1 -		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) -		       * (sizeof yyor - 1))]; -      char const *yyprefix = yyexpecting; - -      /* Start YYX at -YYN if negative to avoid negative indexes in -	 YYCHECK.  */ -      int yyxbegin = yyn < 0 ? -yyn : 0; - -      /* Stay within bounds of both yycheck and yytname.  */ -      int yychecklim = YYLAST - yyn + 1; -      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; -      int yycount = 1; - -      yyarg[0] = yytname[yytype]; -      yyfmt = yystpcpy (yyformat, yyunexpected); - -      for (yyx = yyxbegin; yyx < yyxend; ++yyx) -	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) -	  { -	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) -	      { -		yycount = 1; -		yysize = yysize0; -		yyformat[sizeof yyunexpected - 1] = '\0'; -		break; -	      } -	    yyarg[yycount++] = yytname[yyx]; -	    yysize1 = yysize + yytnamerr (0, yytname[yyx]); -	    yysize_overflow |= (yysize1 < yysize); -	    yysize = yysize1; -	    yyfmt = yystpcpy (yyfmt, yyprefix); -	    yyprefix = yyor; -	  } +      int yyn = yypact[*yyssp]; +      yyarg[yycount++] = yytname[yytoken]; +      if (!yypact_value_is_default (yyn)) +        { +          /* Start YYX at -YYN if negative to avoid negative indexes in +             YYCHECK.  In other words, skip the first -YYN actions for +             this state because they are default actions.  */ +          int yyxbegin = yyn < 0 ? -yyn : 0; +          /* Stay within bounds of both yycheck and yytname.  */ +          int yychecklim = YYLAST - yyn + 1; +          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; +          int yyx; + +          for (yyx = yyxbegin; yyx < yyxend; ++yyx) +            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR +                && !yytable_value_is_error (yytable[yyx + yyn])) +              { +                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) +                  { +                    yycount = 1; +                    yysize = yysize0; +                    break; +                  } +                yyarg[yycount++] = yytname[yyx]; +                { +                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); +                  if (! (yysize <= yysize1 +                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) +                    return 2; +                  yysize = yysize1; +                } +              } +        } +    } -      yyf = YY_(yyformat); -      yysize1 = yysize + yystrlen (yyf); -      yysize_overflow |= (yysize1 < yysize); -      yysize = yysize1; +  switch (yycount) +    { +# define YYCASE_(N, S)                      \ +      case N:                               \ +        yyformat = S;                       \ +      break +      YYCASE_(0, YY_("syntax error")); +      YYCASE_(1, YY_("syntax error, unexpected %s")); +      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); +      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); +      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); +      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ +    } -      if (yysize_overflow) -	return YYSIZE_MAXIMUM; +  { +    YYSIZE_T yysize1 = yysize + yystrlen (yyformat); +    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) +      return 2; +    yysize = yysize1; +  } -      if (yyresult) -	{ -	  /* Avoid sprintf, as that infringes on the user's name space. -	     Don't have undefined behavior even if the translation -	     produced a string with the wrong number of "%s"s.  */ -	  char *yyp = yyresult; -	  int yyi = 0; -	  while ((*yyp = *yyf) != '\0') -	    { -	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) -		{ -		  yyp += yytnamerr (yyp, yyarg[yyi++]); -		  yyf += 2; -		} -	      else -		{ -		  yyp++; -		  yyf++; -		} -	    } -	} -      return yysize; +  if (*yymsg_alloc < yysize) +    { +      *yymsg_alloc = 2 * yysize; +      if (! (yysize <= *yymsg_alloc +             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) +        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; +      return 1;      } + +  /* Avoid sprintf, as that infringes on the user's name space. +     Don't have undefined behavior even if the translation +     produced a string with the wrong number of "%s"s.  */ +  { +    char *yyp = *yymsg; +    int yyi = 0; +    while ((*yyp = *yyformat) != '\0') +      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) +        { +          yyp += yytnamerr (yyp, yyarg[yyi++]); +          yyformat += 2; +        } +      else +        { +          yyp++; +          yyformat++; +        } +  } +  return 0;  }  #endif /* YYERROR_VERBOSE */ -  /*-----------------------------------------------.  | Release the memory associated to this symbol.  | @@ -1112,61 +1218,44 @@ yysyntax_error (char *yyresult, int yystate, int yychar)  #if (defined __STDC__ || defined __C99__FUNC__ \       || defined __cplusplus || defined _MSC_VER)  static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp) +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)  #else  static void -yydestruct (yymsg, yytype, yyvaluep, yylocationp) +yydestruct (yymsg, yytype, yyvaluep)      const char *yymsg;      int yytype;      YYSTYPE *yyvaluep; -    YYLTYPE *yylocationp;  #endif  {    YYUSE (yyvaluep); -  YYUSE (yylocationp);    if (!yymsg)      yymsg = "Deleting";    YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); -  switch (yytype) -    { - -      default: -	break; -    } +  YYUSE (yytype);  } - - -/* Prevent warnings from -Wmissing-prototypes.  */ -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ -/* The look-ahead symbol.  */ +/* The lookahead symbol.  */  int yychar; -/* The semantic value of the look-ahead symbol.  */ -YYSTYPE yylval; + +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + +/* The semantic value of the lookahead symbol.  */ +YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);  /* Number of syntax errors so far.  */  int yynerrs; -/* Location data for the look-ahead symbol.  */ -YYLTYPE yylloc; -  /*----------. @@ -1195,14 +1284,37 @@ yyparse ()  #endif  #endif  { -   -  int yystate; +    int yystate; +    /* Number of tokens to shift before error messages enabled.  */ +    int yyerrstatus; + +    /* The stacks and their tools: +       `yyss': related to states. +       `yyvs': related to semantic values. + +       Refer to the stacks through separate pointers, to allow yyoverflow +       to reallocate them elsewhere.  */ + +    /* The state stack.  */ +    yytype_int16 yyssa[YYINITDEPTH]; +    yytype_int16 *yyss; +    yytype_int16 *yyssp; + +    /* The semantic value stack.  */ +    YYSTYPE yyvsa[YYINITDEPTH]; +    YYSTYPE *yyvs; +    YYSTYPE *yyvsp; + +    YYSIZE_T yystacksize; +    int yyn;    int yyresult; -  /* Number of tokens to shift before error messages enabled.  */ -  int yyerrstatus; -  /* Look-ahead token as an internal (translated) token number.  */ +  /* Lookahead token as an internal (translated) token number.  */    int yytoken = 0; +  /* The variables used to return semantic value and location from the +     action routines.  */ +  YYSTYPE yyval; +  #if YYERROR_VERBOSE    /* Buffer for error messages, and its allocated size.  */    char yymsgbuf[128]; @@ -1210,65 +1322,22 @@ yyparse ()    YYSIZE_T yymsg_alloc = sizeof yymsgbuf;  #endif -  /* Three stacks and their tools: -     `yyss': related to states, -     `yyvs': related to semantic values, -     `yyls': related to locations. - -     Refer to the stacks thru separate pointers, to allow yyoverflow -     to reallocate them elsewhere.  */ - -  /* The state stack.  */ -  yytype_int16 yyssa[YYINITDEPTH]; -  yytype_int16 *yyss = yyssa; -  yytype_int16 *yyssp; - -  /* The semantic value stack.  */ -  YYSTYPE yyvsa[YYINITDEPTH]; -  YYSTYPE *yyvs = yyvsa; -  YYSTYPE *yyvsp; - -  /* The location stack.  */ -  YYLTYPE yylsa[YYINITDEPTH]; -  YYLTYPE *yyls = yylsa; -  YYLTYPE *yylsp; -  /* The locations where the error started and ended.  */ -  YYLTYPE yyerror_range[2]; - -#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) - -  YYSIZE_T yystacksize = YYINITDEPTH; - -  /* The variables used to return semantic value and location from the -     action routines.  */ -  YYSTYPE yyval; -  YYLTYPE yyloc; +#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))    /* The number of symbols on the RHS of the reduced rule.       Keep to zero when no symbol should be popped.  */    int yylen = 0; +  yyssp = yyss = yyssa; +  yyvsp = yyvs = yyvsa; +  yystacksize = YYINITDEPTH; +    YYDPRINTF ((stderr, "Starting parse\n"));    yystate = 0;    yyerrstatus = 0;    yynerrs = 0; -  yychar = YYEMPTY;		/* Cause a token to be read.  */ - -  /* Initialize stack pointers. -     Waste one element of value and location stack -     so that they stay on the same level as the state stack. -     The wasted elements are never initialized.  */ - -  yyssp = yyss; -  yyvsp = yyvs; -  yylsp = yyls; -#if YYLTYPE_IS_TRIVIAL -  /* Initialize the default location before parsing starts.  */ -  yylloc.first_line   = yylloc.last_line   = 1; -  yylloc.first_column = yylloc.last_column = 0; -#endif - +  yychar = YYEMPTY; /* Cause a token to be read.  */    goto yysetstate;  /*------------------------------------------------------------. @@ -1294,7 +1363,6 @@ yyparse ()  	   memory.  */  	YYSTYPE *yyvs1 = yyvs;  	yytype_int16 *yyss1 = yyss; -	YYLTYPE *yyls1 = yyls;  	/* Each stack pointer address is followed by the size of the  	   data in use in that stack, in bytes.  This used to be a @@ -1303,9 +1371,8 @@ yyparse ()  	yyoverflow (YY_("memory exhausted"),  		    &yyss1, yysize * sizeof (*yyssp),  		    &yyvs1, yysize * sizeof (*yyvsp), -		    &yyls1, yysize * sizeof (*yylsp),  		    &yystacksize); -	yyls = yyls1; +  	yyss = yyss1;  	yyvs = yyvs1;        } @@ -1326,9 +1393,8 @@ yyparse ()  	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));  	if (! yyptr)  	  goto yyexhaustedlab; -	YYSTACK_RELOCATE (yyss); -	YYSTACK_RELOCATE (yyvs); -	YYSTACK_RELOCATE (yyls); +	YYSTACK_RELOCATE (yyss_alloc, yyss); +	YYSTACK_RELOCATE (yyvs_alloc, yyvs);  #  undef YYSTACK_RELOCATE  	if (yyss1 != yyssa)  	  YYSTACK_FREE (yyss1); @@ -1338,7 +1404,6 @@ yyparse ()        yyssp = yyss + yysize - 1;        yyvsp = yyvs + yysize - 1; -      yylsp = yyls + yysize - 1;        YYDPRINTF ((stderr, "Stack size increased to %lu\n",  		  (unsigned long int) yystacksize)); @@ -1349,6 +1414,9 @@ yyparse ()    YYDPRINTF ((stderr, "Entering state %d\n", yystate)); +  if (yystate == YYFINAL) +    YYACCEPT; +    goto yybackup;  /*-----------. @@ -1357,16 +1425,16 @@ yyparse ()  yybackup:    /* Do appropriate processing given the current state.  Read a -     look-ahead token if we need one and don't already have one.  */ +     lookahead token if we need one and don't already have one.  */ -  /* First try to decide what to do without reference to look-ahead token.  */ +  /* First try to decide what to do without reference to lookahead token.  */    yyn = yypact[yystate]; -  if (yyn == YYPACT_NINF) +  if (yypact_value_is_default (yyn))      goto yydefault; -  /* Not known => get a look-ahead token if don't already have one.  */ +  /* Not known => get a lookahead token if don't already have one.  */ -  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */ +  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */    if (yychar == YYEMPTY)      {        YYDPRINTF ((stderr, "Reading a token: ")); @@ -1392,30 +1460,28 @@ yybackup:    yyn = yytable[yyn];    if (yyn <= 0)      { -      if (yyn == 0 || yyn == YYTABLE_NINF) -	goto yyerrlab; +      if (yytable_value_is_error (yyn)) +        goto yyerrlab;        yyn = -yyn;        goto yyreduce;      } -  if (yyn == YYFINAL) -    YYACCEPT; -    /* Count tokens shifted since error; after three, turn off error       status.  */    if (yyerrstatus)      yyerrstatus--; -  /* Shift the look-ahead token.  */ +  /* Shift the lookahead token.  */    YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); -  /* Discard the shifted token unless it is eof.  */ -  if (yychar != YYEOF) -    yychar = YYEMPTY; +  /* Discard the shifted token.  */ +  yychar = YYEMPTY;    yystate = yyn; +  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN    *++yyvsp = yylval; -  *++yylsp = yylloc; +  YY_IGNORE_MAYBE_UNINITIALIZED_END +    goto yynewstate; @@ -1446,339 +1512,577 @@ yyreduce:       GCC warning that YYVAL may be used uninitialized.  */    yyval = yyvsp[1-yylen]; -  /* Default location.  */ -  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); +    YY_REDUCE_PRINT (yyn);    switch (yyn)      {          case 2: -#line 90 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 110 "dtc-parser.y"      { -			the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node), 0); -		;} +			the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node), +							guess_boot_cpuid((yyvsp[(4) - (4)].node))); +		}      break;    case 3: -#line 94 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 118 "dtc-parser.y"      { -			the_boot_info = build_boot_info((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].node), 0); -		;} +			(yyval.re) = NULL; +		}      break;    case 4: -#line 101 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 122 "dtc-parser.y"      { -			(yyval.re) = NULL; -		;} +			(yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re)); +		}      break;    case 5: -#line 105 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 129 "dtc-parser.y"      { -			(yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re)); -		;} +			(yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].integer), (yyvsp[(3) - (4)].integer)); +		}      break;    case 6: -#line 112 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 133 "dtc-parser.y"      { -			(yyval.re) = build_reserve_entry((yyvsp[(3) - (5)].addr), (yyvsp[(4) - (5)].addr), (yyvsp[(1) - (5)].labelref)); -		;} +			add_label(&(yyvsp[(2) - (2)].re)->labels, (yyvsp[(1) - (2)].labelref)); +			(yyval.re) = (yyvsp[(2) - (2)].re); +		}      break;    case 7: -#line 119 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 141 "dtc-parser.y"      { -			(yyval.re) = NULL; -		;} +			(yyval.node) = name_node((yyvsp[(2) - (2)].node), ""); +		}      break;    case 8: -#line 123 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 145 "dtc-parser.y"      { -			(yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re)); -		;} +			(yyval.node) = merge_nodes((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); +		}      break;    case 9: -#line 130 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 149 "dtc-parser.y"      { -			(yyval.re) = (yyvsp[(1) - (1)].re); -		;} +			struct node *target = get_node_by_ref((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].labelref)); + +			if (target) +				merge_nodes(target, (yyvsp[(3) - (3)].node)); +			else +				print_error("label or path, '%s', not found", (yyvsp[(2) - (3)].labelref)); +			(yyval.node) = (yyvsp[(1) - (3)].node); +		}      break;    case 10: -#line 134 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 159 "dtc-parser.y"      { -			(yyval.re) = build_reserve_entry((yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].addr) - (yyvsp[(3) - (6)].addr) + 1, (yyvsp[(1) - (6)].labelref)); -		;} +			struct node *target = get_node_by_ref((yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].labelref)); + +			if (!target) +				print_error("label or path, '%s', not found", (yyvsp[(3) - (4)].labelref)); +			else +				delete_node(target); + +			(yyval.node) = (yyvsp[(1) - (4)].node); +		}      break;    case 11: -#line 141 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 173 "dtc-parser.y"      { -			(yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64); -		;} +			(yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist)); +		}      break;    case 12: -#line 145 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 180 "dtc-parser.y"      { -			(yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 16, 64); -		;} +			(yyval.proplist) = NULL; +		}      break;    case 13: -#line 152 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 184 "dtc-parser.y"      { -			(yyval.node) = name_node((yyvsp[(2) - (2)].node), "", NULL); -		;} +			(yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist)); +		}      break;    case 14: -#line 159 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 191 "dtc-parser.y"      { -			(yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist)); -		;} +			(yyval.prop) = build_property((yyvsp[(1) - (4)].propnodename), (yyvsp[(3) - (4)].data)); +		}      break;    case 15: -#line 166 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 195 "dtc-parser.y"      { -			(yyval.proplist) = NULL; -		;} +			(yyval.prop) = build_property((yyvsp[(1) - (2)].propnodename), empty_data); +		}      break;    case 16: -#line 170 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 199 "dtc-parser.y"      { -			(yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist)); -		;} +			(yyval.prop) = build_property_delete((yyvsp[(2) - (3)].propnodename)); +		}      break;    case 17: -#line 177 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 203 "dtc-parser.y"      { -			(yyval.prop) = build_property((yyvsp[(2) - (5)].propnodename), (yyvsp[(4) - (5)].data), (yyvsp[(1) - (5)].labelref)); -		;} +			add_label(&(yyvsp[(2) - (2)].prop)->labels, (yyvsp[(1) - (2)].labelref)); +			(yyval.prop) = (yyvsp[(2) - (2)].prop); +		}      break;    case 18: -#line 181 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 211 "dtc-parser.y"      { -			(yyval.prop) = build_property((yyvsp[(2) - (3)].propnodename), empty_data, (yyvsp[(1) - (3)].labelref)); -		;} +			(yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data)); +		}      break;    case 19: -#line 188 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 215 "dtc-parser.y"      { -			(yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data)); -		;} +			(yyval.data) = data_merge((yyvsp[(1) - (3)].data), (yyvsp[(2) - (3)].array).data); +		}      break;    case 20: -#line 192 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 219 "dtc-parser.y"      {  			(yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data)); -		;} +		}      break;    case 21: -#line 196 "dtc-parser.y" -    { -			(yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data)); -		;} -    break; - -  case 22: -#line 200 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 223 "dtc-parser.y"      {  			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref)); -		;} +		}      break; -  case 23: -#line 204 "dtc-parser.y" +  case 22: +/* Line 1787 of yacc.c  */ +#line 227 "dtc-parser.y"      { -			struct search_path path = { srcpos_file->dir, NULL, NULL }; -			struct dtc_file *file = dtc_open_file((yyvsp[(4) - (9)].data).val, &path); -			struct data d = empty_data; +			FILE *f = srcfile_relative_open((yyvsp[(4) - (9)].data).val, NULL); +			struct data d; -			if ((yyvsp[(6) - (9)].addr) != 0) -				if (fseek(file->file, (yyvsp[(6) - (9)].addr), SEEK_SET) != 0) -					yyerrorf("Couldn't seek to offset %llu in \"%s\": %s", -						 (unsigned long long)(yyvsp[(6) - (9)].addr), -						 (yyvsp[(4) - (9)].data).val, strerror(errno)); +			if ((yyvsp[(6) - (9)].integer) != 0) +				if (fseek(f, (yyvsp[(6) - (9)].integer), SEEK_SET) != 0) +					print_error("Couldn't seek to offset %llu in \"%s\": %s", +						     (unsigned long long)(yyvsp[(6) - (9)].integer), +						     (yyvsp[(4) - (9)].data).val, +						     strerror(errno)); -			d = data_copy_file(file->file, (yyvsp[(8) - (9)].addr)); +			d = data_copy_file(f, (yyvsp[(8) - (9)].integer));  			(yyval.data) = data_merge((yyvsp[(1) - (9)].data), d); -			dtc_close_file(file); -		;} +			fclose(f); +		}      break; -  case 24: -#line 221 "dtc-parser.y" +  case 23: +/* Line 1787 of yacc.c  */ +#line 244 "dtc-parser.y"      { -			struct search_path path = { srcpos_file->dir, NULL, NULL }; -			struct dtc_file *file = dtc_open_file((yyvsp[(4) - (5)].data).val, &path); +			FILE *f = srcfile_relative_open((yyvsp[(4) - (5)].data).val, NULL);  			struct data d = empty_data; -			d = data_copy_file(file->file, -1); +			d = data_copy_file(f, -1);  			(yyval.data) = data_merge((yyvsp[(1) - (5)].data), d); -			dtc_close_file(file); -		;} +			fclose(f); +		}      break; -  case 25: -#line 232 "dtc-parser.y" +  case 24: +/* Line 1787 of yacc.c  */ +#line 254 "dtc-parser.y"      {  			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref)); -		;} +		}      break; -  case 26: -#line 239 "dtc-parser.y" +  case 25: +/* Line 1787 of yacc.c  */ +#line 261 "dtc-parser.y"      {  			(yyval.data) = empty_data; -		;} +		}      break; -  case 27: -#line 243 "dtc-parser.y" +  case 26: +/* Line 1787 of yacc.c  */ +#line 265 "dtc-parser.y"      {  			(yyval.data) = (yyvsp[(1) - (2)].data); -		;} +		}      break; -  case 28: -#line 247 "dtc-parser.y" +  case 27: +/* Line 1787 of yacc.c  */ +#line 269 "dtc-parser.y"      {  			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref)); -		;} +		} +    break; + +  case 28: +/* Line 1787 of yacc.c  */ +#line 276 "dtc-parser.y" +    { +			(yyval.array).data = empty_data; +			(yyval.array).bits = eval_literal((yyvsp[(2) - (3)].literal), 0, 7); + +			if (((yyval.array).bits !=  8) && +			    ((yyval.array).bits != 16) && +			    ((yyval.array).bits != 32) && +			    ((yyval.array).bits != 64)) +			{ +				print_error("Only 8, 16, 32 and 64-bit elements" +					    " are currently supported"); +				(yyval.array).bits = 32; +			} +		}      break;    case 29: -#line 254 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 291 "dtc-parser.y"      { -			(yyval.data) = empty_data; -		;} +			(yyval.array).data = empty_data; +			(yyval.array).bits = 32; +		}      break;    case 30: -#line 258 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 296 "dtc-parser.y"      { -			(yyval.data) = data_append_cell((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].cell)); -		;} +			if ((yyvsp[(1) - (2)].array).bits < 64) { +				uint64_t mask = (1ULL << (yyvsp[(1) - (2)].array).bits) - 1; +				/* +				 * Bits above mask must either be all zero +				 * (positive within range of mask) or all one +				 * (negative and sign-extended). The second +				 * condition is true if when we set all bits +				 * within the mask to one (i.e. | in the +				 * mask), all bits are one. +				 */ +				if (((yyvsp[(2) - (2)].integer) > mask) && (((yyvsp[(2) - (2)].integer) | mask) != -1ULL)) +					print_error( +						"integer value out of range " +						"%016lx (%d bits)", (yyvsp[(1) - (2)].array).bits); +			} + +			(yyval.array).data = data_append_integer((yyvsp[(1) - (2)].array).data, (yyvsp[(2) - (2)].integer), (yyvsp[(1) - (2)].array).bits); +		}      break;    case 31: -#line 262 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 316 "dtc-parser.y"      { -			(yyval.data) = data_append_cell(data_add_marker((yyvsp[(1) - (2)].data), REF_PHANDLE, -							      (yyvsp[(2) - (2)].labelref)), -1); -		;} +			uint64_t val = ~0ULL >> (64 - (yyvsp[(1) - (2)].array).bits); + +			if ((yyvsp[(1) - (2)].array).bits == 32) +				(yyvsp[(1) - (2)].array).data = data_add_marker((yyvsp[(1) - (2)].array).data, +							  REF_PHANDLE, +							  (yyvsp[(2) - (2)].labelref)); +			else +				print_error("References are only allowed in " +					    "arrays with 32-bit elements."); + +			(yyval.array).data = data_append_integer((yyvsp[(1) - (2)].array).data, val, (yyvsp[(1) - (2)].array).bits); +		}      break;    case 32: -#line 267 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 330 "dtc-parser.y"      { -			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref)); -		;} +			(yyval.array).data = data_add_marker((yyvsp[(1) - (2)].array).data, LABEL, (yyvsp[(2) - (2)].labelref)); +		}      break;    case 33: -#line 274 "dtc-parser.y" +/* Line 1787 of yacc.c  */ +#line 337 "dtc-parser.y"      { -			(yyval.cbase) = 16; -		;} +			(yyval.integer) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64); +		}      break; -  case 35: -#line 282 "dtc-parser.y" +  case 34: +/* Line 1787 of yacc.c  */ +#line 341 "dtc-parser.y"      { -			(yyval.cell) = eval_literal((yyvsp[(1) - (1)].literal), 0, 32); -		;} +			(yyval.integer) = eval_char_literal((yyvsp[(1) - (1)].literal)); +		}      break; -  case 36: -#line 286 "dtc-parser.y" +  case 35: +/* Line 1787 of yacc.c  */ +#line 345 "dtc-parser.y"      { -			(yyval.cell) = eval_literal((yyvsp[(2) - (2)].literal), (yyvsp[(1) - (2)].cbase), 32); -		;} +			(yyval.integer) = (yyvsp[(2) - (3)].integer); +		}      break; -  case 37: -#line 293 "dtc-parser.y" +  case 38: +/* Line 1787 of yacc.c  */ +#line 356 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (5)].integer) ? (yyvsp[(3) - (5)].integer) : (yyvsp[(5) - (5)].integer); } +    break; + +  case 40: +/* Line 1787 of yacc.c  */ +#line 361 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) || (yyvsp[(3) - (3)].integer); } +    break; + +  case 42: +/* Line 1787 of yacc.c  */ +#line 366 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) && (yyvsp[(3) - (3)].integer); } +    break; + +  case 44: +/* Line 1787 of yacc.c  */ +#line 371 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) | (yyvsp[(3) - (3)].integer); } +    break; + +  case 46: +/* Line 1787 of yacc.c  */ +#line 376 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) ^ (yyvsp[(3) - (3)].integer); } +    break; + +  case 48: +/* Line 1787 of yacc.c  */ +#line 381 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) & (yyvsp[(3) - (3)].integer); } +    break; + +  case 50: +/* Line 1787 of yacc.c  */ +#line 386 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) == (yyvsp[(3) - (3)].integer); } +    break; + +  case 51: +/* Line 1787 of yacc.c  */ +#line 387 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) != (yyvsp[(3) - (3)].integer); } +    break; + +  case 53: +/* Line 1787 of yacc.c  */ +#line 392 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) < (yyvsp[(3) - (3)].integer); } +    break; + +  case 54: +/* Line 1787 of yacc.c  */ +#line 393 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) > (yyvsp[(3) - (3)].integer); } +    break; + +  case 55: +/* Line 1787 of yacc.c  */ +#line 394 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) <= (yyvsp[(3) - (3)].integer); } +    break; + +  case 56: +/* Line 1787 of yacc.c  */ +#line 395 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) >= (yyvsp[(3) - (3)].integer); } +    break; + +  case 57: +/* Line 1787 of yacc.c  */ +#line 399 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) << (yyvsp[(3) - (3)].integer); } +    break; + +  case 58: +/* Line 1787 of yacc.c  */ +#line 400 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) >> (yyvsp[(3) - (3)].integer); } +    break; + +  case 60: +/* Line 1787 of yacc.c  */ +#line 405 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) + (yyvsp[(3) - (3)].integer); } +    break; + +  case 61: +/* Line 1787 of yacc.c  */ +#line 406 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) - (yyvsp[(3) - (3)].integer); } +    break; + +  case 63: +/* Line 1787 of yacc.c  */ +#line 411 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) * (yyvsp[(3) - (3)].integer); } +    break; + +  case 64: +/* Line 1787 of yacc.c  */ +#line 412 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) / (yyvsp[(3) - (3)].integer); } +    break; + +  case 65: +/* Line 1787 of yacc.c  */ +#line 413 "dtc-parser.y" +    { (yyval.integer) = (yyvsp[(1) - (3)].integer) % (yyvsp[(3) - (3)].integer); } +    break; + +  case 68: +/* Line 1787 of yacc.c  */ +#line 419 "dtc-parser.y" +    { (yyval.integer) = -(yyvsp[(2) - (2)].integer); } +    break; + +  case 69: +/* Line 1787 of yacc.c  */ +#line 420 "dtc-parser.y" +    { (yyval.integer) = ~(yyvsp[(2) - (2)].integer); } +    break; + +  case 70: +/* Line 1787 of yacc.c  */ +#line 421 "dtc-parser.y" +    { (yyval.integer) = !(yyvsp[(2) - (2)].integer); } +    break; + +  case 71: +/* Line 1787 of yacc.c  */ +#line 426 "dtc-parser.y"      {  			(yyval.data) = empty_data; -		;} +		}      break; -  case 38: -#line 297 "dtc-parser.y" +  case 72: +/* Line 1787 of yacc.c  */ +#line 430 "dtc-parser.y"      {  			(yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte)); -		;} +		}      break; -  case 39: -#line 301 "dtc-parser.y" +  case 73: +/* Line 1787 of yacc.c  */ +#line 434 "dtc-parser.y"      {  			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref)); -		;} +		}      break; -  case 40: -#line 308 "dtc-parser.y" +  case 74: +/* Line 1787 of yacc.c  */ +#line 441 "dtc-parser.y"      {  			(yyval.nodelist) = NULL; -		;} +		}      break; -  case 41: -#line 312 "dtc-parser.y" +  case 75: +/* Line 1787 of yacc.c  */ +#line 445 "dtc-parser.y"      {  			(yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist)); -		;} +		}      break; -  case 42: -#line 316 "dtc-parser.y" +  case 76: +/* Line 1787 of yacc.c  */ +#line 449 "dtc-parser.y"      { -			yyerror("syntax error: properties must precede subnodes"); +			print_error("syntax error: properties must precede subnodes");  			YYERROR; -		;} +		}      break; -  case 43: -#line 324 "dtc-parser.y" +  case 77: +/* Line 1787 of yacc.c  */ +#line 457 "dtc-parser.y"      { -			(yyval.node) = name_node((yyvsp[(3) - (3)].node), (yyvsp[(2) - (3)].propnodename), (yyvsp[(1) - (3)].labelref)); -		;} +			(yyval.node) = name_node((yyvsp[(2) - (2)].node), (yyvsp[(1) - (2)].propnodename)); +		}      break; -  case 44: -#line 331 "dtc-parser.y" +  case 78: +/* Line 1787 of yacc.c  */ +#line 461 "dtc-parser.y"      { -			(yyval.labelref) = NULL; -		;} +			(yyval.node) = name_node(build_node_delete(), (yyvsp[(2) - (3)].propnodename)); +		}      break; -  case 45: -#line 335 "dtc-parser.y" +  case 79: +/* Line 1787 of yacc.c  */ +#line 465 "dtc-parser.y"      { -			(yyval.labelref) = (yyvsp[(1) - (1)].labelref); -		;} +			add_label(&(yyvsp[(2) - (2)].node)->labels, (yyvsp[(1) - (2)].labelref)); +			(yyval.node) = (yyvsp[(2) - (2)].node); +		}      break; -/* Line 1267 of yacc.c.  */ -#line 1780 "dtc-parser.tab.c" +/* Line 1787 of yacc.c  */ +#line 2073 "dtc-parser.tab.c"        default: break;      } +  /* User semantic actions sometimes alter yychar, and that requires +     that yytoken be updated with the new translation.  We take the +     approach of translating immediately before every use of yytoken. +     One alternative is translating here after every semantic action, +     but that translation would be missed if the semantic action invokes +     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or +     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an +     incorrect destructor might then be invoked immediately.  In the +     case of YYERROR or YYBACKUP, subsequent parser actions might lead +     to an incorrect destructor call or verbose syntax error message +     before the lookahead is translated.  */    YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);    YYPOPSTACK (yylen); @@ -1786,7 +2090,6 @@ yyreduce:    YY_STACK_PRINT (yyss, yyssp);    *++yyvsp = yyval; -  *++yylsp = yyloc;    /* Now `shift' the result of the reduction.  Determine what state       that goes to, based on the state we popped back to and the rule @@ -1807,6 +2110,10 @@ yyreduce:  | yyerrlab -- here on detecting error |  `------------------------------------*/  yyerrlab: +  /* Make sure we have latest lookahead translation.  See comments at +     user semantic actions for why this is necessary.  */ +  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); +    /* If not already recovering from an error, report this error.  */    if (!yyerrstatus)      { @@ -1814,45 +2121,44 @@ yyerrlab:  #if ! YYERROR_VERBOSE        yyerror (YY_("syntax error"));  #else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ +                                        yyssp, yytoken)        { -	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); -	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) -	  { -	    YYSIZE_T yyalloc = 2 * yysize; -	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) -	      yyalloc = YYSTACK_ALLOC_MAXIMUM; -	    if (yymsg != yymsgbuf) -	      YYSTACK_FREE (yymsg); -	    yymsg = (char *) YYSTACK_ALLOC (yyalloc); -	    if (yymsg) -	      yymsg_alloc = yyalloc; -	    else -	      { -		yymsg = yymsgbuf; -		yymsg_alloc = sizeof yymsgbuf; -	      } -	  } - -	if (0 < yysize && yysize <= yymsg_alloc) -	  { -	    (void) yysyntax_error (yymsg, yystate, yychar); -	    yyerror (yymsg); -	  } -	else -	  { -	    yyerror (YY_("syntax error")); -	    if (yysize != 0) -	      goto yyexhaustedlab; -	  } +        char const *yymsgp = YY_("syntax error"); +        int yysyntax_error_status; +        yysyntax_error_status = YYSYNTAX_ERROR; +        if (yysyntax_error_status == 0) +          yymsgp = yymsg; +        else if (yysyntax_error_status == 1) +          { +            if (yymsg != yymsgbuf) +              YYSTACK_FREE (yymsg); +            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); +            if (!yymsg) +              { +                yymsg = yymsgbuf; +                yymsg_alloc = sizeof yymsgbuf; +                yysyntax_error_status = 2; +              } +            else +              { +                yysyntax_error_status = YYSYNTAX_ERROR; +                yymsgp = yymsg; +              } +          } +        yyerror (yymsgp); +        if (yysyntax_error_status == 2) +          goto yyexhaustedlab;        } +# undef YYSYNTAX_ERROR  #endif      } -  yyerror_range[0] = yylloc; +    if (yyerrstatus == 3)      { -      /* If just tried and failed to reuse look-ahead token after an +      /* If just tried and failed to reuse lookahead token after an  	 error, discard it.  */        if (yychar <= YYEOF) @@ -1864,12 +2170,12 @@ yyerrlab:        else  	{  	  yydestruct ("Error: discarding", -		      yytoken, &yylval, &yylloc); +		      yytoken, &yylval);  	  yychar = YYEMPTY;  	}      } -  /* Else will try to reuse look-ahead token after shifting the error +  /* Else will try to reuse lookahead token after shifting the error       token.  */    goto yyerrlab1; @@ -1885,7 +2191,6 @@ yyerrorlab:    if (/*CONSTCOND*/ 0)       goto yyerrorlab; -  yyerror_range[0] = yylsp[1-yylen];    /* Do not reclaim the symbols of the rule which action triggered       this YYERROR.  */    YYPOPSTACK (yylen); @@ -1904,7 +2209,7 @@ yyerrlab1:    for (;;)      {        yyn = yypact[yystate]; -      if (yyn != YYPACT_NINF) +      if (!yypact_value_is_default (yyn))  	{  	  yyn += YYTERROR;  	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) @@ -1919,24 +2224,18 @@ yyerrlab1:        if (yyssp == yyss)  	YYABORT; -      yyerror_range[0] = *yylsp; +        yydestruct ("Error: popping", -		  yystos[yystate], yyvsp, yylsp); +		  yystos[yystate], yyvsp);        YYPOPSTACK (1);        yystate = *yyssp;        YY_STACK_PRINT (yyss, yyssp);      } -  if (yyn == YYFINAL) -    YYACCEPT; - +  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN    *++yyvsp = yylval; +  YY_IGNORE_MAYBE_UNINITIALIZED_END -  yyerror_range[1] = yylloc; -  /* Using YYLLOC is tempting, but would change the location of -     the look-ahead.  YYLOC is available though.  */ -  YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2); -  *++yylsp = yyloc;    /* Shift the error token.  */    YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); @@ -1959,7 +2258,7 @@ yyabortlab:    yyresult = 1;    goto yyreturn; -#ifndef yyoverflow +#if !defined yyoverflow || YYERROR_VERBOSE  /*-------------------------------------------------.  | yyexhaustedlab -- memory exhaustion comes here.  |  `-------------------------------------------------*/ @@ -1970,9 +2269,14 @@ yyexhaustedlab:  #endif  yyreturn: -  if (yychar != YYEOF && yychar != YYEMPTY) -     yydestruct ("Cleanup: discarding lookahead", -		 yytoken, &yylval, &yylloc); +  if (yychar != YYEMPTY) +    { +      /* Make sure we have latest lookahead translation.  See comments at +         user semantic actions for why this is necessary.  */ +      yytoken = YYTRANSLATE (yychar); +      yydestruct ("Cleanup: discarding lookahead", +                  yytoken, &yylval); +    }    /* Do not reclaim the symbols of the rule which action triggered       this YYABORT or YYACCEPT.  */    YYPOPSTACK (yylen); @@ -1980,7 +2284,7 @@ yyreturn:    while (yyssp != yyss)      {        yydestruct ("Cleanup: popping", -		  yystos[*yyssp], yyvsp, yylsp); +		  yystos[*yyssp], yyvsp);        YYPOPSTACK (1);      }  #ifndef yyoverflow @@ -1996,29 +2300,23 @@ yyreturn:  } -#line 340 "dtc-parser.y" +/* Line 2050 of yacc.c  */ +#line 471 "dtc-parser.y" -void yyerrorf(char const *s, ...) +void print_error(char const *fmt, ...)  { -	const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";  	va_list va; -	va_start(va, s); -	if (strcmp(fname, "-") == 0) -		fname = "stdin"; - -	fprintf(stderr, "%s:%d ", fname, yylloc.first_line); -	vfprintf(stderr, s, va); -	fprintf(stderr, "\n"); +	va_start(va, fmt); +	srcpos_verror(&yylloc, fmt, va); +	va_end(va);  	treesource_error = 1; -	va_end(va);  } -void yyerror (char const *s) -{ -	yyerrorf("%s", s); +void yyerror(char const *s) { +	print_error("%s", s);  }  static unsigned long long eval_literal(const char *s, int base, int bits) @@ -2028,13 +2326,41 @@ static unsigned long long eval_literal(const char *s, int base, int bits)  	errno = 0;  	val = strtoull(s, &e, base); -	if (*e) -		yyerror("bad characters in literal"); -	else if ((errno == ERANGE) +	if (*e) { +		size_t uls = strspn(e, "UL"); +		if (e[uls]) +			print_error("bad characters in literal"); +	} +	if ((errno == ERANGE)  		 || ((bits < 64) && (val >= (1ULL << bits)))) -		yyerror("literal out of range"); +		print_error("literal out of range");  	else if (errno != 0) -		yyerror("bad literal"); +		print_error("bad literal");  	return val;  } +static unsigned char eval_char_literal(const char *s) +{ +	int i = 1; +	char c = s[0]; + +	if (c == '\0') +	{ +		print_error("empty character literal"); +		return 0; +	} + +	/* +	 * If the first character in the character literal is a \ then process +	 * the remaining characters as an escape encoding. If the first +	 * character is neither an escape or a terminator it should be the only +	 * character in the literal and will be returned. +	 */ +	if (c == '\\') +		c = get_escape_char(s, &i); + +	if (s[i] != '\0') +		print_error("malformed character literal"); + +	return c; +} diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped index ba99100d55c..b2e7a86cd85 100644 --- a/scripts/dtc/dtc-parser.tab.h_shipped +++ b/scripts/dtc/dtc-parser.tab.h_shipped @@ -1,24 +1,21 @@ -/* A Bison parser, made by GNU Bison 2.3.  */ +/* A Bison parser, made by GNU Bison 2.7.12-4996.  */ -/* Skeleton interface for Bison's Yacc-like parsers in C - -   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 -   Free Software Foundation, Inc. - -   This program is free software; you can redistribute it and/or modify +/* Bison interface for Yacc-like parsers in C +    +      Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. +    +   This program is free software: you can redistribute it and/or modify     it under the terms of the GNU General Public License as published by -   the Free Software Foundation; either version 2, or (at your option) -   any later version. - +   the Free Software Foundation, either version 3 of the License, or +   (at your option) any later version. +        This program is distributed in the hope that it will be useful,     but WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     GNU General Public License for more details. - +        You should have received a copy of the GNU General Public License -   along with this program; if not, write to the Free Software -   Foundation, Inc., 51 Franklin Street, Fifth Floor, -   Boston, MA 02110-1301, USA.  */ +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */  /* As a special exception, you may create a larger work that contains     part or all of the Bison parser skeleton and distribute that work @@ -29,10 +26,20 @@     special exception, which will cause the skeleton and the resulting     Bison output files to be licensed under the GNU General Public     License without this special exception. - +        This special exception was added by the Free Software Foundation in     version 2.2 of Bison.  */ +#ifndef YY_YY_DTC_PARSER_TAB_H_INCLUDED +# define YY_YY_DTC_PARSER_TAB_H_INCLUDED +/* Enabling traces.  */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; +#endif +  /* Tokens.  */  #ifndef YYTOKENTYPE  # define YYTOKENTYPE @@ -41,37 +48,36 @@     enum yytokentype {       DT_V1 = 258,       DT_MEMRESERVE = 259, -     DT_PROPNODENAME = 260, -     DT_LITERAL = 261, -     DT_LEGACYLITERAL = 262, -     DT_BASE = 263, -     DT_BYTE = 264, -     DT_STRING = 265, -     DT_LABEL = 266, -     DT_REF = 267, -     DT_INCBIN = 268 +     DT_LSHIFT = 260, +     DT_RSHIFT = 261, +     DT_LE = 262, +     DT_GE = 263, +     DT_EQ = 264, +     DT_NE = 265, +     DT_AND = 266, +     DT_OR = 267, +     DT_BITS = 268, +     DT_DEL_PROP = 269, +     DT_DEL_NODE = 270, +     DT_PROPNODENAME = 271, +     DT_LITERAL = 272, +     DT_CHAR_LITERAL = 273, +     DT_BASE = 274, +     DT_BYTE = 275, +     DT_STRING = 276, +     DT_LABEL = 277, +     DT_REF = 278, +     DT_INCBIN = 279     };  #endif -/* Tokens.  */ -#define DT_V1 258 -#define DT_MEMRESERVE 259 -#define DT_PROPNODENAME 260 -#define DT_LITERAL 261 -#define DT_LEGACYLITERAL 262 -#define DT_BASE 263 -#define DT_BYTE 264 -#define DT_STRING 265 -#define DT_LABEL 266 -#define DT_REF 267 -#define DT_INCBIN 268 - -  #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED  typedef union YYSTYPE -#line 37 "dtc-parser.y"  { +/* Line 2053 of yacc.c  */ +#line 40 "dtc-parser.y" +  	char *propnodename;  	char *literal;  	char *labelref; @@ -79,35 +85,41 @@ typedef union YYSTYPE  	uint8_t byte;  	struct data data; -	uint64_t addr; -	cell_t cell; +	struct { +		struct data	data; +		int		bits; +	} array; +  	struct property *prop;  	struct property *proplist;  	struct node *node;  	struct node *nodelist;  	struct reserve_info *re; -} -/* Line 1489 of yacc.c.  */ -#line 92 "dtc-parser.tab.h" -	YYSTYPE; +	uint64_t integer; + + +/* Line 2053 of yacc.c  */ +#line 103 "dtc-parser.tab.h" +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1  # define yystype YYSTYPE /* obsolescent; will be withdrawn */  # define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1  #endif  extern YYSTYPE yylval; -#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED -typedef struct YYLTYPE -{ -  int first_line; -  int first_column; -  int last_line; -  int last_column; -} YYLTYPE; -# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ -# define YYLTYPE_IS_DECLARED 1 -# define YYLTYPE_IS_TRIVIAL 1 +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse ();  #endif +#endif /* ! YYPARSE_PARAM */ -extern YYLTYPE yylloc; +#endif /* !YY_YY_DTC_PARSER_TAB_H_INCLUDED  */ diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index b2ab562420e..f412460f94d 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y @@ -18,20 +18,23 @@   *                                                                   USA   */ -%locations -  %{  #include <stdio.h>  #include "dtc.h"  #include "srcpos.h" +YYLTYPE yylloc; +  extern int yylex(void); +extern void print_error(char const *fmt, ...); +extern void yyerror(char const *s);  extern struct boot_info *the_boot_info;  extern int treesource_error;  static unsigned long long eval_literal(const char *s, int base, int bits); +static unsigned char eval_char_literal(const char *s);  %}  %union { @@ -42,20 +45,28 @@ static unsigned long long eval_literal(const char *s, int base, int bits);  	uint8_t byte;  	struct data data; -	uint64_t addr; -	cell_t cell; +	struct { +		struct data	data; +		int		bits; +	} array; +  	struct property *prop;  	struct property *proplist;  	struct node *node;  	struct node *nodelist;  	struct reserve_info *re; +	uint64_t integer;  }  %token DT_V1  %token DT_MEMRESERVE +%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR +%token DT_BITS +%token DT_DEL_PROP +%token DT_DEL_NODE  %token <propnodename> DT_PROPNODENAME  %token <literal> DT_LITERAL -%token <literal> DT_LEGACYLITERAL +%token <literal> DT_CHAR_LITERAL  %token <cbase> DT_BASE  %token <byte> DT_BYTE  %token <data> DT_STRING @@ -67,12 +78,7 @@ static unsigned long long eval_literal(const char *s, int base, int bits);  %type <data> propdataprefix  %type <re> memreserve  %type <re> memreserves -%type <re> v0_memreserve -%type <re> v0_memreserves -%type <addr> addr -%type <data> celllist -%type <cbase> cellbase -%type <cell> cellval +%type <array> arrayprefix  %type <data> bytestring  %type <prop> propdef  %type <proplist> proplist @@ -81,18 +87,29 @@ static unsigned long long eval_literal(const char *s, int base, int bits);  %type <node> nodedef  %type <node> subnode  %type <nodelist> subnodes -%type <labelref> label + +%type <integer> integer_prim +%type <integer> integer_unary +%type <integer> integer_mul +%type <integer> integer_add +%type <integer> integer_shift +%type <integer> integer_rela +%type <integer> integer_eq +%type <integer> integer_bitand +%type <integer> integer_bitxor +%type <integer> integer_bitor +%type <integer> integer_and +%type <integer> integer_or +%type <integer> integer_trinary +%type <integer> integer_expr  %%  sourcefile:  	  DT_V1 ';' memreserves devicetree  		{ -			the_boot_info = build_boot_info($3, $4, 0); -		} -	| v0_memreserves devicetree -		{ -			the_boot_info = build_boot_info($1, $2, 0); +			the_boot_info = build_boot_info($3, $4, +							guess_boot_cpuid($4));  		}  	; @@ -108,49 +125,46 @@ memreserves:  	;  memreserve: -	  label DT_MEMRESERVE addr addr ';' +	  DT_MEMRESERVE integer_prim integer_prim ';'  		{ -			$$ = build_reserve_entry($3, $4, $1); +			$$ = build_reserve_entry($2, $3);  		} -	; - -v0_memreserves: -	  /* empty */ +	| DT_LABEL memreserve  		{ -			$$ = NULL; +			add_label(&$2->labels, $1); +			$$ = $2;  		} -	| v0_memreserve v0_memreserves -		{ -			$$ = chain_reserve_entry($1, $2); -		};  	; -v0_memreserve: -	  memreserve +devicetree: +	  '/' nodedef  		{ -			$$ = $1; +			$$ = name_node($2, "");  		} -	| label DT_MEMRESERVE addr '-' addr ';' +	| devicetree '/' nodedef  		{ -			$$ = build_reserve_entry($3, $5 - $3 + 1, $1); +			$$ = merge_nodes($1, $3);  		} -	; - -addr: -	  DT_LITERAL +	| devicetree DT_REF nodedef  		{ -			$$ = eval_literal($1, 0, 64); +			struct node *target = get_node_by_ref($1, $2); + +			if (target) +				merge_nodes(target, $3); +			else +				print_error("label or path, '%s', not found", $2); +			$$ = $1;  		} -	| DT_LEGACYLITERAL +	| devicetree DT_DEL_NODE DT_REF ';'  		{ -			$$ = eval_literal($1, 16, 64); -		} -	  ; +			struct node *target = get_node_by_ref($1, $3); -devicetree: -	  '/' nodedef -		{ -			$$ = name_node($2, "", NULL); +			if (!target) +				print_error("label or path, '%s', not found", $3); +			else +				delete_node(target); + +			$$ = $1;  		}  	; @@ -173,13 +187,22 @@ proplist:  	;  propdef: -	  label DT_PROPNODENAME '=' propdata ';' +	  DT_PROPNODENAME '=' propdata ';'  		{ -			$$ = build_property($2, $4, $1); +			$$ = build_property($1, $3);  		} -	| label DT_PROPNODENAME ';' +	| DT_PROPNODENAME ';'  		{ -			$$ = build_property($2, empty_data, $1); +			$$ = build_property($1, empty_data); +		} +	| DT_DEL_PROP DT_PROPNODENAME ';' +		{ +			$$ = build_property_delete($2); +		} +	| DT_LABEL propdef +		{ +			add_label(&$2->labels, $1); +			$$ = $2;  		}  	; @@ -188,9 +211,9 @@ propdata:  		{  			$$ = data_merge($1, $2);  		} -	| propdataprefix '<' celllist '>' +	| propdataprefix arrayprefix '>'  		{ -			$$ = data_merge($1, $3); +			$$ = data_merge($1, $2.data);  		}  	| propdataprefix '[' bytestring ']'  		{ @@ -200,33 +223,32 @@ propdata:  		{  			$$ = data_add_marker($1, REF_PATH, $2);  		} -	| propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')' +	| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'  		{ -			struct search_path path = { srcpos_file->dir, NULL, NULL }; -			struct dtc_file *file = dtc_open_file($4.val, &path); -			struct data d = empty_data; +			FILE *f = srcfile_relative_open($4.val, NULL); +			struct data d;  			if ($6 != 0) -				if (fseek(file->file, $6, SEEK_SET) != 0) -					yyerrorf("Couldn't seek to offset %llu in \"%s\": %s", -						 (unsigned long long)$6, -						 $4.val, strerror(errno)); +				if (fseek(f, $6, SEEK_SET) != 0) +					print_error("Couldn't seek to offset %llu in \"%s\": %s", +						     (unsigned long long)$6, +						     $4.val, +						     strerror(errno)); -			d = data_copy_file(file->file, $8); +			d = data_copy_file(f, $8);  			$$ = data_merge($1, d); -			dtc_close_file(file); +			fclose(f);  		}  	| propdataprefix DT_INCBIN '(' DT_STRING ')'  		{ -			struct search_path path = { srcpos_file->dir, NULL, NULL }; -			struct dtc_file *file = dtc_open_file($4.val, &path); +			FILE *f = srcfile_relative_open($4.val, NULL);  			struct data d = empty_data; -			d = data_copy_file(file->file, -1); +			d = data_copy_file(f, -1);  			$$ = data_merge($1, d); -			dtc_close_file(file); +			fclose(f);  		}  	| propdata DT_LABEL  		{ @@ -249,45 +271,156 @@ propdataprefix:  		}  	; -celllist: -	  /* empty */ +arrayprefix: +	DT_BITS DT_LITERAL '<'  		{ -			$$ = empty_data; +			$$.data = empty_data; +			$$.bits = eval_literal($2, 0, 7); + +			if (($$.bits !=  8) && +			    ($$.bits != 16) && +			    ($$.bits != 32) && +			    ($$.bits != 64)) +			{ +				print_error("Only 8, 16, 32 and 64-bit elements" +					    " are currently supported"); +				$$.bits = 32; +			}  		} -	| celllist cellval +	| '<'  		{ -			$$ = data_append_cell($1, $2); +			$$.data = empty_data; +			$$.bits = 32;  		} -	| celllist DT_REF +	| arrayprefix integer_prim  		{ -			$$ = data_append_cell(data_add_marker($1, REF_PHANDLE, -							      $2), -1); +			if ($1.bits < 64) { +				uint64_t mask = (1ULL << $1.bits) - 1; +				/* +				 * Bits above mask must either be all zero +				 * (positive within range of mask) or all one +				 * (negative and sign-extended). The second +				 * condition is true if when we set all bits +				 * within the mask to one (i.e. | in the +				 * mask), all bits are one. +				 */ +				if (($2 > mask) && (($2 | mask) != -1ULL)) +					print_error( +						"integer value out of range " +						"%016lx (%d bits)", $1.bits); +			} + +			$$.data = data_append_integer($1.data, $2, $1.bits);  		} -	| celllist DT_LABEL +	| arrayprefix DT_REF  		{ -			$$ = data_add_marker($1, LABEL, $2); -		} -	; +			uint64_t val = ~0ULL >> (64 - $1.bits); -cellbase: -	  /* empty */ +			if ($1.bits == 32) +				$1.data = data_add_marker($1.data, +							  REF_PHANDLE, +							  $2); +			else +				print_error("References are only allowed in " +					    "arrays with 32-bit elements."); + +			$$.data = data_append_integer($1.data, val, $1.bits); +		} +	| arrayprefix DT_LABEL  		{ -			$$ = 16; +			$$.data = data_add_marker($1.data, LABEL, $2);  		} -	| DT_BASE  	; -cellval: +integer_prim:  	  DT_LITERAL  		{ -			$$ = eval_literal($1, 0, 32); +			$$ = eval_literal($1, 0, 64); +		} +	| DT_CHAR_LITERAL +		{ +			$$ = eval_char_literal($1);  		} -	| cellbase DT_LEGACYLITERAL +	| '(' integer_expr ')'  		{ -			$$ = eval_literal($2, $1, 32); +			$$ = $2;  		}  	; +integer_expr: +	integer_trinary +	; + +integer_trinary: +	  integer_or +	| integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; } +	; + +integer_or: +	  integer_and +	| integer_or DT_OR integer_and { $$ = $1 || $3; } +	; + +integer_and: +	  integer_bitor +	| integer_and DT_AND integer_bitor { $$ = $1 && $3; } +	; + +integer_bitor: +	  integer_bitxor +	| integer_bitor '|' integer_bitxor { $$ = $1 | $3; } +	; + +integer_bitxor: +	  integer_bitand +	| integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; } +	; + +integer_bitand: +	  integer_eq +	| integer_bitand '&' integer_eq { $$ = $1 & $3; } +	; + +integer_eq: +	  integer_rela +	| integer_eq DT_EQ integer_rela { $$ = $1 == $3; } +	| integer_eq DT_NE integer_rela { $$ = $1 != $3; } +	; + +integer_rela: +	  integer_shift +	| integer_rela '<' integer_shift { $$ = $1 < $3; } +	| integer_rela '>' integer_shift { $$ = $1 > $3; } +	| integer_rela DT_LE integer_shift { $$ = $1 <= $3; } +	| integer_rela DT_GE integer_shift { $$ = $1 >= $3; } +	; + +integer_shift: +	  integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; } +	| integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; } +	| integer_add +	; + +integer_add: +	  integer_add '+' integer_mul { $$ = $1 + $3; } +	| integer_add '-' integer_mul { $$ = $1 - $3; } +	| integer_mul +	; + +integer_mul: +	  integer_mul '*' integer_unary { $$ = $1 * $3; } +	| integer_mul '/' integer_unary { $$ = $1 / $3; } +	| integer_mul '%' integer_unary { $$ = $1 % $3; } +	| integer_unary +	; + +integer_unary: +	  integer_prim +	| '-' integer_unary { $$ = -$2; } +	| '~' integer_unary { $$ = ~$2; } +	| '!' integer_unary { $$ = !$2; } +	; +  bytestring:  	  /* empty */  		{ @@ -308,57 +441,48 @@ subnodes:  		{  			$$ = NULL;  		} -	|  subnode subnodes +	| subnode subnodes  		{  			$$ = chain_node($1, $2);  		}  	| subnode propdef  		{ -			yyerror("syntax error: properties must precede subnodes"); +			print_error("syntax error: properties must precede subnodes");  			YYERROR;  		}  	;  subnode: -	  label DT_PROPNODENAME nodedef +	  DT_PROPNODENAME nodedef  		{ -			$$ = name_node($3, $2, $1); +			$$ = name_node($2, $1);  		} -	; - -label: -	  /* empty */ +	| DT_DEL_NODE DT_PROPNODENAME ';'  		{ -			$$ = NULL; +			$$ = name_node(build_node_delete(), $2);  		} -	| DT_LABEL +	| DT_LABEL subnode  		{ -			$$ = $1; +			add_label(&$2->labels, $1); +			$$ = $2;  		}  	;  %% -void yyerrorf(char const *s, ...) +void print_error(char const *fmt, ...)  { -	const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";  	va_list va; -	va_start(va, s); -	if (strcmp(fname, "-") == 0) -		fname = "stdin"; - -	fprintf(stderr, "%s:%d ", fname, yylloc.first_line); -	vfprintf(stderr, s, va); -	fprintf(stderr, "\n"); +	va_start(va, fmt); +	srcpos_verror(&yylloc, fmt, va); +	va_end(va);  	treesource_error = 1; -	va_end(va);  } -void yyerror (char const *s) -{ -	yyerrorf("%s", s); +void yyerror(char const *s) { +	print_error("%s", s);  }  static unsigned long long eval_literal(const char *s, int base, int bits) @@ -368,12 +492,41 @@ static unsigned long long eval_literal(const char *s, int base, int bits)  	errno = 0;  	val = strtoull(s, &e, base); -	if (*e) -		yyerror("bad characters in literal"); -	else if ((errno == ERANGE) +	if (*e) { +		size_t uls = strspn(e, "UL"); +		if (e[uls]) +			print_error("bad characters in literal"); +	} +	if ((errno == ERANGE)  		 || ((bits < 64) && (val >= (1ULL << bits)))) -		yyerror("literal out of range"); +		print_error("literal out of range");  	else if (errno != 0) -		yyerror("bad literal"); +		print_error("bad literal");  	return val;  } + +static unsigned char eval_char_literal(const char *s) +{ +	int i = 1; +	char c = s[0]; + +	if (c == '\0') +	{ +		print_error("empty character literal"); +		return 0; +	} + +	/* +	 * If the first character in the character literal is a \ then process +	 * the remaining characters as an escape encoding. If the first +	 * character is neither an escape or a terminator it should be the only +	 * character in the literal and will be returned. +	 */ +	if (c == '\\') +		c = get_escape_char(s, &i); + +	if (s[i] != '\0') +		print_error("malformed character literal"); + +	return c; +} diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c index d8fd43b4ac1..e3c96536fd9 100644 --- a/scripts/dtc/dtc.c +++ b/scripts/dtc/dtc.c @@ -21,8 +21,6 @@  #include "dtc.h"  #include "srcpos.h" -#include "version_gen.h" -  /*   * Command line options   */ @@ -30,30 +28,7 @@ int quiet;		/* Level of quietness */  int reservenum;		/* Number of memory reservation slots */  int minsize;		/* Minimum blob size */  int padsize;		/* Additional padding to blob */ - -char *join_path(const char *path, const char *name) -{ -	int lenp = strlen(path); -	int lenn = strlen(name); -	int len; -	int needslash = 1; -	char *str; - -	len = lenp + lenn + 2; -	if ((lenp > 0) && (path[lenp-1] == '/')) { -		needslash = 0; -		len--; -	} - -	str = xmalloc(len); -	memcpy(str, path, lenp); -	if (needslash) { -		str[lenp] = '/'; -		lenp++; -	} -	memcpy(str+lenp, name, lenn+1); -	return str; -} +int phandle_format = PHANDLE_BOTH;	/* Use linux,phandle or phandle properties */  static void fill_fullpaths(struct node *tree, const char *prefix)  { @@ -72,42 +47,60 @@ static void fill_fullpaths(struct node *tree, const char *prefix)  		fill_fullpaths(child, tree->fullpath);  } -static void  __attribute__ ((noreturn)) usage(void) -{ -	fprintf(stderr, "Usage:\n"); -	fprintf(stderr, "\tdtc [options] <input file>\n"); -	fprintf(stderr, "\nOptions:\n"); -	fprintf(stderr, "\t-h\n"); -	fprintf(stderr, "\t\tThis help text\n"); -	fprintf(stderr, "\t-q\n"); -	fprintf(stderr, "\t\tQuiet: -q suppress warnings, -qq errors, -qqq all\n"); -	fprintf(stderr, "\t-I <input format>\n"); -	fprintf(stderr, "\t\tInput formats are:\n"); -	fprintf(stderr, "\t\t\tdts - device tree source text\n"); -	fprintf(stderr, "\t\t\tdtb - device tree blob\n"); -	fprintf(stderr, "\t\t\tfs - /proc/device-tree style directory\n"); -	fprintf(stderr, "\t-o <output file>\n"); -	fprintf(stderr, "\t-O <output format>\n"); -	fprintf(stderr, "\t\tOutput formats are:\n"); -	fprintf(stderr, "\t\t\tdts - device tree source text\n"); -	fprintf(stderr, "\t\t\tdtb - device tree blob\n"); -	fprintf(stderr, "\t\t\tasm - assembler source\n"); -	fprintf(stderr, "\t-V <output version>\n"); -	fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", DEFAULT_FDT_VERSION); -	fprintf(stderr, "\t-R <number>\n"); -	fprintf(stderr, "\t\tMake space for <number> reserve map entries (relevant for \n\t\tdtb and asm output only)\n"); -	fprintf(stderr, "\t-S <bytes>\n"); -	fprintf(stderr, "\t\tMake the blob at least <bytes> long (extra space)\n"); -	fprintf(stderr, "\t-p <bytes>\n"); -	fprintf(stderr, "\t\tAdd padding to the blob of <bytes> long (extra space)\n"); -	fprintf(stderr, "\t-b <number>\n"); -	fprintf(stderr, "\t\tSet the physical boot cpu\n"); -	fprintf(stderr, "\t-f\n"); -	fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n"); -	fprintf(stderr, "\t-v\n"); -	fprintf(stderr, "\t\tPrint DTC version and exit\n"); -	exit(3); -} +/* 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:fb:i:H:sW:E:hv"; +static struct option const usage_long_opts[] = { +	{"quiet",            no_argument, NULL, 'q'}, +	{"in-format",         a_argument, NULL, 'I'}, +	{"out",               a_argument, NULL, 'o'}, +	{"out-format",        a_argument, NULL, 'O'}, +	{"out-version",       a_argument, NULL, 'V'}, +	{"out-dependency",    a_argument, NULL, 'd'}, +	{"reserve",           a_argument, NULL, 'R'}, +	{"space",             a_argument, NULL, 'S'}, +	{"pad",               a_argument, NULL, 'p'}, +	{"boot-cpu",          a_argument, NULL, 'b'}, +	{"force",            no_argument, NULL, 'f'}, +	{"include",           a_argument, NULL, 'i'}, +	{"sort",             no_argument, NULL, 's'}, +	{"phandle",           a_argument, NULL, 'H'}, +	{"warning",           a_argument, NULL, 'W'}, +	{"error",             a_argument, NULL, 'E'}, +	{"help",             no_argument, NULL, 'h'}, +	{"version",          no_argument, NULL, 'v'}, +	{NULL,               no_argument, NULL, 0x0}, +}; +static const char * const usage_opts_help[] = { +	"\n\tQuiet: -q suppress warnings, -qq errors, -qqq all", +	"\n\tInput formats are:\n" +	 "\t\tdts - device tree source text\n" +	 "\t\tdtb - device tree blob\n" +	 "\t\tfs  - /proc/device-tree style directory", +	"\n\tOutput file", +	"\n\tOutput formats are:\n" +	 "\t\tdts - device tree source text\n" +	 "\t\tdtb - device tree blob\n" +	 "\t\tasm - assembler source", +	"\n\tBlob version to produce, defaults to %d (for dtb and asm output)", //, DEFAULT_FDT_VERSION); +	"\n\tOutput dependency file", +	"\n\ttMake space for <number> reserve map entries (for dtb and asm output)", +	"\n\tMake the blob at least <bytes> long (extra space)", +	"\n\tAdd padding to the blob of <bytes> long (extra space)", +	"\n\tSet the physical boot cpu", +	"\n\tTry to produce output even if the input tree has errors", +	"\n\tAdd a path to search for include files", +	"\n\tSort nodes and properties before outputting (useful for comparing trees)", +	"\n\tValid phandle formats are:\n" +	 "\t\tlegacy - \"linux,phandle\" properties only\n" +	 "\t\tepapr  - \"phandle\" properties only\n" +	 "\t\tboth   - Both \"linux,phandle\" and \"phandle\" properties", +	"\n\tEnable/disable warnings (prefix with \"no-\")", +	"\n\tEnable/disable errors (prefix with \"no-\")", +	"\n\tPrint this help and exit", +	"\n\tPrint version and exit", +	NULL, +};  int main(int argc, char *argv[])  { @@ -115,7 +108,8 @@ int main(int argc, char *argv[])  	const char *inform = "dts";  	const char *outform = "dts";  	const char *outname = "-"; -	int force = 0, check = 0; +	const char *depname = NULL; +	int force = 0, sort = 0;  	const char *arg;  	int opt;  	FILE *outf = NULL; @@ -127,7 +121,7 @@ int main(int argc, char *argv[])  	minsize    = 0;  	padsize    = 0; -	while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:v")) != EOF) { +	while ((opt = util_getopt_long()) != EOF) {  		switch (opt) {  		case 'I':  			inform = optarg; @@ -141,6 +135,9 @@ int main(int argc, char *argv[])  		case 'V':  			outversion = strtol(optarg, NULL, 0);  			break; +		case 'd': +			depname = optarg; +			break;  		case 'R':  			reservenum = strtol(optarg, NULL, 0);  			break; @@ -153,26 +150,50 @@ int main(int argc, char *argv[])  		case 'f':  			force = 1;  			break; -		case 'c': -			check = 1; -			break;  		case 'q':  			quiet++;  			break;  		case 'b':  			cmdline_boot_cpuid = strtoll(optarg, NULL, 0);  			break; +		case 'i': +			srcfile_add_search_path(optarg); +			break;  		case 'v': -			printf("Version: %s\n", DTC_VERSION); -			exit(0); +			util_version(); +		case 'H': +			if (streq(optarg, "legacy")) +				phandle_format = PHANDLE_LEGACY; +			else if (streq(optarg, "epapr")) +				phandle_format = PHANDLE_EPAPR; +			else if (streq(optarg, "both")) +				phandle_format = PHANDLE_BOTH; +			else +				die("Invalid argument \"%s\" to -H option\n", +				    optarg); +			break; + +		case 's': +			sort = 1; +			break; + +		case 'W': +			parse_checks_option(true, false, optarg); +			break; + +		case 'E': +			parse_checks_option(false, true, optarg); +			break; +  		case 'h': +			usage(NULL);  		default: -			usage(); +			usage("unknown option");  		}  	}  	if (argc > (optind+1)) -		usage(); +		usage("missing files");  	else if (argc < (optind+1))  		arg = "-";  	else @@ -182,8 +203,13 @@ int main(int argc, char *argv[])  	if (minsize && padsize)  		die("Can't set both -p and -S\n"); -	fprintf(stderr, "DTC: %s->%s  on file \"%s\"\n", -		inform, outform, arg); +	if (depname) { +		depfile = fopen(depname, "w"); +		if (!depfile) +			die("Couldn't open dependency file %s: %s\n", depname, +			    strerror(errno)); +		fprintf(depfile, "%s:", outname); +	}  	if (streq(inform, "dts"))  		bi = dt_from_source(arg); @@ -194,12 +220,19 @@ int main(int argc, char *argv[])  	else  		die("Unknown input format \"%s\"\n", inform); +	if (depfile) { +		fputc('\n', depfile); +		fclose(depfile); +	} +  	if (cmdline_boot_cpuid != -1)  		bi->boot_cpuid_phys = cmdline_boot_cpuid;  	fill_fullpaths(bi->dt, "");  	process_checks(force, bi); +	if (sort) +		sort_tree(bi);  	if (streq(outname, "-")) {  		outf = stdout; diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h index 08d54c87008..264a20cf66a 100644 --- a/scripts/dtc/dtc.h +++ b/scripts/dtc/dtc.h @@ -25,6 +25,7 @@  #include <string.h>  #include <stdlib.h>  #include <stdint.h> +#include <stdbool.h>  #include <stdarg.h>  #include <assert.h>  #include <ctype.h> @@ -34,7 +35,17 @@  #include <libfdt_env.h>  #include <fdt.h> +#include "util.h" + +#ifdef DEBUG +#define debug(fmt,args...)	printf(fmt, ##args) +#else +#define debug(fmt,args...) +#endif + +  #define DEFAULT_FDT_VERSION	17 +  /*   * Command line options   */ @@ -42,36 +53,11 @@ extern int quiet;		/* Level of quietness */  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 */ -static inline void __attribute__((noreturn)) die(char * str, ...) -{ -	va_list ap; - -	va_start(ap, str); -	fprintf(stderr, "FATAL ERROR: "); -	vfprintf(stderr, str, ap); -	exit(1); -} - -static inline void *xmalloc(size_t len) -{ -	void *new = malloc(len); - -	if (! new) -		die("malloc() failed\n"); - -	return new; -} - -static inline void *xrealloc(void *p, size_t len) -{ -	void *new = realloc(p, len); - -	if (! new) -		die("realloc() failed (len=%d)\n", len); - -	return new; -} +#define PHANDLE_LEGACY	0x1 +#define PHANDLE_EPAPR	0x2 +#define PHANDLE_BOTH	0x3  typedef uint32_t cell_t; @@ -80,7 +66,6 @@ typedef uint32_t cell_t;  #define strneq(a, b, n)	(strncmp((a), (b), (n)) == 0)  #define ALIGN(x, a)	(((x) + (a) - 1) & ~((a) - 1)) -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))  /* Data blobs */  enum markertype { @@ -124,6 +109,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m,  				  const void *p, int len);  struct data data_merge(struct data d1, struct data d2);  struct data data_append_cell(struct data d, cell_t word); +struct data data_append_integer(struct data d, uint64_t word, int bits);  struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);  struct data data_append_addr(struct data d, uint64_t addr);  struct data data_append_byte(struct data d, uint8_t byte); @@ -140,16 +126,24 @@ int data_is_one_string(struct data d);  #define MAX_NODENAME_LEN	31  /* Live trees */ +struct label { +	int deleted; +	char *label; +	struct label *next; +}; +  struct property { +	int deleted;  	char *name;  	struct data val;  	struct property *next; -	char *label; +	struct label *labels;  };  struct node { +	int deleted;  	char *name;  	struct property *proplist;  	struct node *children; @@ -163,29 +157,58 @@ struct node {  	cell_t phandle;  	int addr_cells, size_cells; -	char *label; +	struct label *labels;  }; -#define for_each_property(n, p) \ +#define for_each_label_withdel(l0, l) \ +	for ((l) = (l0); (l); (l) = (l)->next) + +#define for_each_label(l0, l) \ +	for_each_label_withdel(l0, l) \ +		if (!(l)->deleted) + +#define for_each_property_withdel(n, p) \  	for ((p) = (n)->proplist; (p); (p) = (p)->next) -#define for_each_child(n, c)	\ +#define for_each_property(n, p) \ +	for_each_property_withdel(n, p) \ +		if (!(p)->deleted) + +#define for_each_child_withdel(n, c) \  	for ((c) = (n)->children; (c); (c) = (c)->next_sibling) -struct property *build_property(char *name, struct data val, char *label); +#define for_each_child(n, c) \ +	for_each_child_withdel(n, c) \ +		if (!(c)->deleted) + +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_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 *name_node(struct node *node, char *name, char *label); +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_property(struct node *node, struct property *prop); +void delete_property_by_name(struct node *node, char *name); +void delete_property(struct property *prop);  void add_child(struct node *parent, struct node *child); +void delete_node_by_name(struct node *parent, char *name); +void delete_node(struct node *node);  const char *get_unitname(struct node *node);  struct property *get_property(struct node *node, const char *propname);  cell_t propval_cell(struct property *prop); +struct property *get_property_by_label(struct node *tree, const char *label, +				       struct node **node); +struct marker *get_marker_label(struct node *tree, const char *label, +				struct node **node, struct property **prop);  struct node *get_subnode(struct node *node, const char *nodename);  struct node *get_node_by_path(struct node *tree, const char *path);  struct node *get_node_by_label(struct node *tree, const char *label); @@ -193,6 +216,8 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle);  struct node *get_node_by_ref(struct node *tree, const char *ref);  cell_t get_node_phandle(struct node *root, struct node *node); +uint32_t guess_boot_cpuid(struct node *tree); +  /* Boot info (tree plus memreserve information */  struct reserve_info { @@ -200,10 +225,10 @@ struct reserve_info {  	struct reserve_info *next; -	char *label; +	struct label *labels;  }; -struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len, char *label); +struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len);  struct reserve_info *chain_reserve_entry(struct reserve_info *first,  					 struct reserve_info *list);  struct reserve_info *add_reserve_entry(struct reserve_info *list, @@ -218,9 +243,11 @@ 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);  /* Checks */ +void parse_checks_option(bool warn, bool error, const char *optarg);  void process_checks(int force, struct boot_info *bi);  /* Flattened trees */ @@ -239,8 +266,4 @@ struct boot_info *dt_from_source(const char *f);  struct boot_info *dt_from_fs(const char *dirname); -/* misc */ - -char *join_path(const char *path, const char *name); -  #endif /* _DTC_H */ diff --git a/scripts/dtc/fdtdump.c b/scripts/dtc/fdtdump.c new file mode 100644 index 00000000000..207a46d6486 --- /dev/null +++ b/scripts/dtc/fdtdump.c @@ -0,0 +1,162 @@ +/* + * fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com> + */ + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include <fdt.h> +#include <libfdt_env.h> + +#include "util.h" + +#define ALIGN(x, a)	(((x) + ((a) - 1)) & ~((a) - 1)) +#define PALIGN(p, a)	((void *)(ALIGN((unsigned long)(p), (a)))) +#define GET_CELL(p)	(p += 4, *((const uint32_t *)(p-4))) + +static void print_data(const char *data, int len) +{ +	int i; +	const char *p = data; + +	/* no data, don't print */ +	if (len == 0) +		return; + +	if (util_is_printable_string(data, len)) { +		printf(" = \"%s\"", (const char *)data); +	} else if ((len % 4) == 0) { +		printf(" = <"); +		for (i = 0; i < len; i += 4) +			printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)), +			       i < (len - 4) ? " " : ""); +		printf(">"); +	} else { +		printf(" = ["); +		for (i = 0; i < len; i++) +			printf("%02x%s", *p++, i < len - 1 ? " " : ""); +		printf("]"); +	} +} + +static void dump_blob(void *blob) +{ +	struct fdt_header *bph = blob; +	uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap); +	uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct); +	uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings); +	struct fdt_reserve_entry *p_rsvmap = +		(struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap); +	const char *p_struct = (const char *)blob + off_dt; +	const char *p_strings = (const char *)blob + off_str; +	uint32_t version = fdt32_to_cpu(bph->version); +	uint32_t totalsize = fdt32_to_cpu(bph->totalsize); +	uint32_t tag; +	const char *p, *s, *t; +	int depth, sz, shift; +	int i; +	uint64_t addr, size; + +	depth = 0; +	shift = 4; + +	printf("/dts-v1/;\n"); +	printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic)); +	printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize); +	printf("// off_dt_struct:\t0x%x\n", off_dt); +	printf("// off_dt_strings:\t0x%x\n", off_str); +	printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap); +	printf("// version:\t\t%d\n", version); +	printf("// last_comp_version:\t%d\n", +	       fdt32_to_cpu(bph->last_comp_version)); +	if (version >= 2) +		printf("// boot_cpuid_phys:\t0x%x\n", +		       fdt32_to_cpu(bph->boot_cpuid_phys)); + +	if (version >= 3) +		printf("// size_dt_strings:\t0x%x\n", +		       fdt32_to_cpu(bph->size_dt_strings)); +	if (version >= 17) +		printf("// size_dt_struct:\t0x%x\n", +		       fdt32_to_cpu(bph->size_dt_struct)); +	printf("\n"); + +	for (i = 0; ; i++) { +		addr = fdt64_to_cpu(p_rsvmap[i].address); +		size = fdt64_to_cpu(p_rsvmap[i].size); +		if (addr == 0 && size == 0) +			break; + +		printf("/memreserve/ %llx %llx;\n", +		       (unsigned long long)addr, (unsigned long long)size); +	} + +	p = p_struct; +	while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) { + +		/* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */ + +		if (tag == FDT_BEGIN_NODE) { +			s = p; +			p = PALIGN(p + strlen(s) + 1, 4); + +			if (*s == '\0') +				s = "/"; + +			printf("%*s%s {\n", depth * shift, "", s); + +			depth++; +			continue; +		} + +		if (tag == FDT_END_NODE) { +			depth--; + +			printf("%*s};\n", depth * shift, ""); +			continue; +		} + +		if (tag == FDT_NOP) { +			printf("%*s// [NOP]\n", depth * shift, ""); +			continue; +		} + +		if (tag != FDT_PROP) { +			fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag); +			break; +		} +		sz = fdt32_to_cpu(GET_CELL(p)); +		s = p_strings + fdt32_to_cpu(GET_CELL(p)); +		if (version < 16 && sz >= 8) +			p = PALIGN(p, 8); +		t = p; + +		p = PALIGN(p + sz, 4); + +		printf("%*s%s", depth * shift, "", s); +		print_data(t, sz); +		printf(";\n"); +	} +} + + +int main(int argc, char *argv[]) +{ +	char *buf; + +	if (argc < 2) { +		fprintf(stderr, "supply input filename\n"); +		return 5; +	} + +	buf = utilfdt_read(argv[1]); +	if (buf) +		dump_blob(buf); +	else +		return 10; + +	return 0; +} diff --git a/scripts/dtc/fdtget.c b/scripts/dtc/fdtget.c new file mode 100644 index 00000000000..c2fbab2a547 --- /dev/null +++ b/scripts/dtc/fdtget.c @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. + * + * Portions from U-Boot cmd_fdt.c (C) Copyright 2007 + * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com + * Based on code written by: + *   Pantelis Antoniou <pantelis.antoniou@gmail.com> and + *   Matthew McClintock <msm@freescale.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <assert.h> +#include <ctype.h> +#include <getopt.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <libfdt.h> + +#include "util.h" + +enum display_mode { +	MODE_SHOW_VALUE,	/* show values for node properties */ +	MODE_LIST_PROPS,	/* list the properties for a node */ +	MODE_LIST_SUBNODES,	/* list the subnodes of a node */ +}; + +/* Holds information which controls our output and options */ +struct display_info { +	int type;		/* data type (s/i/u/x or 0 for default) */ +	int size;		/* data size (1/2/4) */ +	enum display_mode mode;	/* display mode that we are using */ +	const char *default_val; /* default value if node/property not found */ +}; + +static void report_error(const char *where, int err) +{ +	fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err)); +} + +/** + * Displays data of a given length according to selected options + * + * If a specific data type is provided in disp, then this is used. Otherwise + * we try to guess the data type / size from the contents. + * + * @param disp		Display information / options + * @param data		Data to display + * @param len		Maximum length of buffer + * @return 0 if ok, -1 if data does not match format + */ +static int show_data(struct display_info *disp, const char *data, int len) +{ +	int i, size; +	const uint8_t *p = (const uint8_t *)data; +	const char *s; +	int value; +	int is_string; +	char fmt[3]; + +	/* no data, don't print */ +	if (len == 0) +		return 0; + +	is_string = (disp->type) == 's' || +		(!disp->type && util_is_printable_string(data, len)); +	if (is_string) { +		if (data[len - 1] != '\0') { +			fprintf(stderr, "Unterminated string\n"); +			return -1; +		} +		for (s = data; s - data < len; s += strlen(s) + 1) { +			if (s != data) +				printf(" "); +			printf("%s", (const char *)s); +		} +		return 0; +	} +	size = disp->size; +	if (size == -1) { +		size = (len % 4) == 0 ? 4 : 1; +	} else if (len % size) { +		fprintf(stderr, "Property length must be a multiple of " +				"selected data size\n"); +		return -1; +	} +	fmt[0] = '%'; +	fmt[1] = disp->type ? disp->type : 'd'; +	fmt[2] = '\0'; +	for (i = 0; i < len; i += size, p += size) { +		if (i) +			printf(" "); +		value = size == 4 ? fdt32_to_cpu(*(const uint32_t *)p) : +			size == 2 ? (*p << 8) | p[1] : *p; +		printf(fmt, value); +	} +	return 0; +} + +/** + * List all properties in a node, one per line. + * + * @param blob		FDT blob + * @param node		Node to display + * @return 0 if ok, or FDT_ERR... if not. + */ +static int list_properties(const void *blob, int node) +{ +	const struct fdt_property *data; +	const char *name; +	int prop; + +	prop = fdt_first_property_offset(blob, node); +	do { +		/* Stop silently when there are no more properties */ +		if (prop < 0) +			return prop == -FDT_ERR_NOTFOUND ? 0 : prop; +		data = fdt_get_property_by_offset(blob, prop, NULL); +		name = fdt_string(blob, fdt32_to_cpu(data->nameoff)); +		if (name) +			puts(name); +		prop = fdt_next_property_offset(blob, prop); +	} while (1); +} + +#define MAX_LEVEL	32		/* how deeply nested we will go */ + +/** + * List all subnodes in a node, one per line + * + * @param blob		FDT blob + * @param node		Node to display + * @return 0 if ok, or FDT_ERR... if not. + */ +static int list_subnodes(const void *blob, int node) +{ +	int nextoffset;		/* next node offset from libfdt */ +	uint32_t tag;		/* current tag */ +	int level = 0;		/* keep track of nesting level */ +	const char *pathp; +	int depth = 1;		/* the assumed depth of this node */ + +	while (level >= 0) { +		tag = fdt_next_tag(blob, node, &nextoffset); +		switch (tag) { +		case FDT_BEGIN_NODE: +			pathp = fdt_get_name(blob, node, NULL); +			if (level <= depth) { +				if (pathp == NULL) +					pathp = "/* NULL pointer error */"; +				if (*pathp == '\0') +					pathp = "/";	/* root is nameless */ +				if (level == 1) +					puts(pathp); +			} +			level++; +			if (level >= MAX_LEVEL) { +				printf("Nested too deep, aborting.\n"); +				return 1; +			} +			break; +		case FDT_END_NODE: +			level--; +			if (level == 0) +				level = -1;		/* exit the loop */ +			break; +		case FDT_END: +			return 1; +		case FDT_PROP: +			break; +		default: +			if (level <= depth) +				printf("Unknown tag 0x%08X\n", tag); +			return 1; +		} +		node = nextoffset; +	} +	return 0; +} + +/** + * Show the data for a given node (and perhaps property) according to the + * display option provided. + * + * @param blob		FDT blob + * @param disp		Display information / options + * @param node		Node to display + * @param property	Name of property to display, or NULL if none + * @return 0 if ok, -ve on error + */ +static int show_data_for_item(const void *blob, struct display_info *disp, +		int node, const char *property) +{ +	const void *value = NULL; +	int len, err = 0; + +	switch (disp->mode) { +	case MODE_LIST_PROPS: +		err = list_properties(blob, node); +		break; + +	case MODE_LIST_SUBNODES: +		err = list_subnodes(blob, node); +		break; + +	default: +		assert(property); +		value = fdt_getprop(blob, node, property, &len); +		if (value) { +			if (show_data(disp, value, len)) +				err = -1; +			else +				printf("\n"); +		} else if (disp->default_val) { +			puts(disp->default_val); +		} else { +			report_error(property, len); +			err = -1; +		} +		break; +	} + +	return err; +} + +/** + * Run the main fdtget operation, given a filename and valid arguments + * + * @param disp		Display information / options + * @param filename	Filename of blob file + * @param arg		List of arguments to process + * @param arg_count	Number of arguments + * @param return 0 if ok, -ve on error + */ +static int do_fdtget(struct display_info *disp, const char *filename, +		     char **arg, int arg_count, int args_per_step) +{ +	char *blob; +	const char *prop; +	int i, node; + +	blob = utilfdt_read(filename); +	if (!blob) +		return -1; + +	for (i = 0; i + args_per_step <= arg_count; i += args_per_step) { +		node = fdt_path_offset(blob, arg[i]); +		if (node < 0) { +			if (disp->default_val) { +				puts(disp->default_val); +				continue; +			} else { +				report_error(arg[i], node); +				return -1; +			} +		} +		prop = args_per_step == 1 ? NULL : arg[i + 1]; + +		if (show_data_for_item(blob, disp, node, prop)) +			return -1; +	} +	return 0; +} + +static const char *usage_msg = +	"fdtget - read values from device tree\n" +	"\n" +	"Each value is printed on a new line.\n\n" +	"Usage:\n" +	"	fdtget <options> <dt file> [<node> <property>]...\n" +	"	fdtget -p <options> <dt file> [<node> ]...\n" +	"Options:\n" +	"\t-t <type>\tType of data\n" +	"\t-p\t\tList properties for each node\n" +	"\t-l\t\tList subnodes for each node\n" +	"\t-d\t\tDefault value to display when the property is " +			"missing\n" +	"\t-h\t\tPrint this help\n\n" +	USAGE_TYPE_MSG; + +static void usage(const char *msg) +{ +	if (msg) +		fprintf(stderr, "Error: %s\n\n", msg); + +	fprintf(stderr, "%s", usage_msg); +	exit(2); +} + +int main(int argc, char *argv[]) +{ +	char *filename = NULL; +	struct display_info disp; +	int args_per_step = 2; + +	/* set defaults */ +	memset(&disp, '\0', sizeof(disp)); +	disp.size = -1; +	disp.mode = MODE_SHOW_VALUE; +	for (;;) { +		int c = getopt(argc, argv, "d:hlpt:"); +		if (c == -1) +			break; + +		switch (c) { +		case 'h': +		case '?': +			usage(NULL); + +		case 't': +			if (utilfdt_decode_type(optarg, &disp.type, +					&disp.size)) +				usage("Invalid type string"); +			break; + +		case 'p': +			disp.mode = MODE_LIST_PROPS; +			args_per_step = 1; +			break; + +		case 'l': +			disp.mode = MODE_LIST_SUBNODES; +			args_per_step = 1; +			break; + +		case 'd': +			disp.default_val = optarg; +			break; +		} +	} + +	if (optind < argc) +		filename = argv[optind++]; +	if (!filename) +		usage("Missing filename"); + +	argv += optind; +	argc -= optind; + +	/* Allow no arguments, and silently succeed */ +	if (!argc) +		return 0; + +	/* Check for node, property arguments */ +	if (args_per_step == 2 && (argc % 2)) +		usage("Must have an even number of arguments"); + +	if (do_fdtget(&disp, filename, argv, argc, args_per_step)) +		return 1; +	return 0; +} diff --git a/scripts/dtc/fdtput.c b/scripts/dtc/fdtput.c new file mode 100644 index 00000000000..f2197f51930 --- /dev/null +++ b/scripts/dtc/fdtput.c @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <assert.h> +#include <ctype.h> +#include <getopt.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <libfdt.h> + +#include "util.h" + +/* These are the operations we support */ +enum oper_type { +	OPER_WRITE_PROP,		/* Write a property in a node */ +	OPER_CREATE_NODE,		/* Create a new node */ +}; + +struct display_info { +	enum oper_type oper;	/* operation to perform */ +	int type;		/* data type (s/i/u/x or 0 for default) */ +	int size;		/* data size (1/2/4) */ +	int verbose;		/* verbose output */ +	int auto_path;		/* automatically create all path components */ +}; + + +/** + * Report an error with a particular node. + * + * @param name		Node name to report error on + * @param namelen	Length of node name, or -1 to use entire string + * @param err		Error number to report (-FDT_ERR_...) + */ +static void report_error(const char *name, int namelen, int err) +{ +	if (namelen == -1) +		namelen = strlen(name); +	fprintf(stderr, "Error at '%1.*s': %s\n", namelen, name, +		fdt_strerror(err)); +} + +/** + * Encode a series of arguments in a property value. + * + * @param disp		Display information / options + * @param arg		List of arguments from command line + * @param arg_count	Number of arguments (may be 0) + * @param valuep	Returns buffer containing value + * @param *value_len	Returns length of value encoded + */ +static int encode_value(struct display_info *disp, char **arg, int arg_count, +			char **valuep, int *value_len) +{ +	char *value = NULL;	/* holding area for value */ +	int value_size = 0;	/* size of holding area */ +	char *ptr;		/* pointer to current value position */ +	int len;		/* length of this cell/string/byte */ +	int ival; +	int upto;	/* the number of bytes we have written to buf */ +	char fmt[3]; + +	upto = 0; + +	if (disp->verbose) +		fprintf(stderr, "Decoding value:\n"); + +	fmt[0] = '%'; +	fmt[1] = disp->type ? disp->type : 'd'; +	fmt[2] = '\0'; +	for (; arg_count > 0; arg++, arg_count--, upto += len) { +		/* assume integer unless told otherwise */ +		if (disp->type == 's') +			len = strlen(*arg) + 1; +		else +			len = disp->size == -1 ? 4 : disp->size; + +		/* enlarge our value buffer by a suitable margin if needed */ +		if (upto + len > value_size) { +			value_size = (upto + len) + 500; +			value = realloc(value, value_size); +			if (!value) { +				fprintf(stderr, "Out of mmory: cannot alloc " +					"%d bytes\n", value_size); +				return -1; +			} +		} + +		ptr = value + upto; +		if (disp->type == 's') { +			memcpy(ptr, *arg, len); +			if (disp->verbose) +				fprintf(stderr, "\tstring: '%s'\n", ptr); +		} else { +			int *iptr = (int *)ptr; +			sscanf(*arg, fmt, &ival); +			if (len == 4) +				*iptr = cpu_to_fdt32(ival); +			else +				*ptr = (uint8_t)ival; +			if (disp->verbose) { +				fprintf(stderr, "\t%s: %d\n", +					disp->size == 1 ? "byte" : +					disp->size == 2 ? "short" : "int", +					ival); +			} +		} +	} +	*value_len = upto; +	*valuep = value; +	if (disp->verbose) +		fprintf(stderr, "Value size %d\n", upto); +	return 0; +} + +static int store_key_value(void *blob, const char *node_name, +		const char *property, const char *buf, int len) +{ +	int node; +	int err; + +	node = fdt_path_offset(blob, node_name); +	if (node < 0) { +		report_error(node_name, -1, node); +		return -1; +	} + +	err = fdt_setprop(blob, node, property, buf, len); +	if (err) { +		report_error(property, -1, err); +		return -1; +	} +	return 0; +} + +/** + * Create paths as needed for all components of a path + * + * Any components of the path that do not exist are created. Errors are + * reported. + * + * @param blob		FDT blob to write into + * @param in_path	Path to process + * @return 0 if ok, -1 on error + */ +static int create_paths(void *blob, const char *in_path) +{ +	const char *path = in_path; +	const char *sep; +	int node, offset = 0; + +	/* skip leading '/' */ +	while (*path == '/') +		path++; + +	for (sep = path; *sep; path = sep + 1, offset = node) { +		/* equivalent to strchrnul(), but it requires _GNU_SOURCE */ +		sep = strchr(path, '/'); +		if (!sep) +			sep = path + strlen(path); + +		node = fdt_subnode_offset_namelen(blob, offset, path, +				sep - path); +		if (node == -FDT_ERR_NOTFOUND) { +			node = fdt_add_subnode_namelen(blob, offset, path, +						       sep - path); +		} +		if (node < 0) { +			report_error(path, sep - path, node); +			return -1; +		} +	} + +	return 0; +} + +/** + * Create a new node in the fdt. + * + * This will overwrite the node_name string. Any error is reported. + * + * TODO: Perhaps create fdt_path_offset_namelen() so we don't need to do this. + * + * @param blob		FDT blob to write into + * @param node_name	Name of node to create + * @return new node offset if found, or -1 on failure + */ +static int create_node(void *blob, const char *node_name) +{ +	int node = 0; +	char *p; + +	p = strrchr(node_name, '/'); +	if (!p) { +		report_error(node_name, -1, -FDT_ERR_BADPATH); +		return -1; +	} +	*p = '\0'; + +	if (p > node_name) { +		node = fdt_path_offset(blob, node_name); +		if (node < 0) { +			report_error(node_name, -1, node); +			return -1; +		} +	} + +	node = fdt_add_subnode(blob, node, p + 1); +	if (node < 0) { +		report_error(p + 1, -1, node); +		return -1; +	} + +	return 0; +} + +static int do_fdtput(struct display_info *disp, const char *filename, +		    char **arg, int arg_count) +{ +	char *value; +	char *blob; +	int len, ret = 0; + +	blob = utilfdt_read(filename); +	if (!blob) +		return -1; + +	switch (disp->oper) { +	case OPER_WRITE_PROP: +		/* +		 * Convert the arguments into a single binary value, then +		 * store them into the property. +		 */ +		assert(arg_count >= 2); +		if (disp->auto_path && create_paths(blob, *arg)) +			return -1; +		if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) || +			store_key_value(blob, *arg, arg[1], value, len)) +			ret = -1; +		break; +	case OPER_CREATE_NODE: +		for (; ret >= 0 && arg_count--; arg++) { +			if (disp->auto_path) +				ret = create_paths(blob, *arg); +			else +				ret = create_node(blob, *arg); +		} +		break; +	} +	if (ret >= 0) +		ret = utilfdt_write(filename, blob); + +	free(blob); +	return ret; +} + +static const char *usage_msg = +	"fdtput - write a property value to a device tree\n" +	"\n" +	"The command line arguments are joined together into a single value.\n" +	"\n" +	"Usage:\n" +	"	fdtput <options> <dt file> <node> <property> [<value>...]\n" +	"	fdtput -c <options> <dt file> [<node>...]\n" +	"Options:\n" +	"\t-c\t\tCreate nodes if they don't already exist\n" +	"\t-p\t\tAutomatically create nodes as needed for the node path\n" +	"\t-t <type>\tType of data\n" +	"\t-v\t\tVerbose: display each value decoded from command line\n" +	"\t-h\t\tPrint this help\n\n" +	USAGE_TYPE_MSG; + +static void usage(const char *msg) +{ +	if (msg) +		fprintf(stderr, "Error: %s\n\n", msg); + +	fprintf(stderr, "%s", usage_msg); +	exit(2); +} + +int main(int argc, char *argv[]) +{ +	struct display_info disp; +	char *filename = NULL; + +	memset(&disp, '\0', sizeof(disp)); +	disp.size = -1; +	disp.oper = OPER_WRITE_PROP; +	for (;;) { +		int c = getopt(argc, argv, "chpt:v"); +		if (c == -1) +			break; + +		/* +		 * TODO: add options to: +		 * - delete property +		 * - delete node (optionally recursively) +		 * - rename node +		 * - pack fdt before writing +		 * - set amount of free space when writing +		 * - expand fdt if value doesn't fit +		 */ +		switch (c) { +		case 'c': +			disp.oper = OPER_CREATE_NODE; +			break; +		case 'h': +		case '?': +			usage(NULL); +		case 'p': +			disp.auto_path = 1; +			break; +		case 't': +			if (utilfdt_decode_type(optarg, &disp.type, +					&disp.size)) +				usage("Invalid type string"); +			break; + +		case 'v': +			disp.verbose = 1; +			break; +		} +	} + +	if (optind < argc) +		filename = argv[optind++]; +	if (!filename) +		usage("Missing filename"); + +	argv += optind; +	argc -= optind; + +	if (disp.oper == OPER_WRITE_PROP) { +		if (argc < 1) +			usage("Missing node"); +		if (argc < 2) +			usage("Missing property"); +	} + +	if (do_fdtput(&disp, filename, argv, argc)) +		return 1; +	return 0; +} diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c index 76acd28c068..665dad7bb46 100644 --- a/scripts/dtc/flattree.c +++ b/scripts/dtc/flattree.c @@ -52,9 +52,9 @@ struct emitter {  	void (*string)(void *, char *, int);  	void (*align)(void *, int);  	void (*data)(void *, struct data); -	void (*beginnode)(void *, const char *); -	void (*endnode)(void *, const char *); -	void (*property)(void *, const char *); +	void (*beginnode)(void *, struct label *labels); +	void (*endnode)(void *, struct label *labels); +	void (*property)(void *, struct label *labels);  };  static void bin_emit_cell(void *e, cell_t val) @@ -89,17 +89,17 @@ static void bin_emit_data(void *e, struct data d)  	*dtbuf = data_append_data(*dtbuf, d.val, d.len);  } -static void bin_emit_beginnode(void *e, const char *label) +static void bin_emit_beginnode(void *e, struct label *labels)  {  	bin_emit_cell(e, FDT_BEGIN_NODE);  } -static void bin_emit_endnode(void *e, const char *label) +static void bin_emit_endnode(void *e, struct label *labels)  {  	bin_emit_cell(e, FDT_END_NODE);  } -static void bin_emit_property(void *e, const char *label) +static void bin_emit_property(void *e, struct label *labels)  {  	bin_emit_cell(e, FDT_PROP);  } @@ -127,11 +127,21 @@ static void emit_offset_label(FILE *f, const char *label, int offset)  	fprintf(f, "%s\t= . + %d\n", label, offset);  } +#define ASM_EMIT_BELONG(f, fmt, ...) \ +	{ \ +		fprintf((f), "\t.byte\t((" fmt ") >> 24) & 0xff\n", __VA_ARGS__); \ +		fprintf((f), "\t.byte\t((" fmt ") >> 16) & 0xff\n", __VA_ARGS__); \ +		fprintf((f), "\t.byte\t((" fmt ") >> 8) & 0xff\n", __VA_ARGS__); \ +		fprintf((f), "\t.byte\t(" fmt ") & 0xff\n", __VA_ARGS__); \ +	} +  static void asm_emit_cell(void *e, cell_t val)  {  	FILE *f = e; -	fprintf(f, "\t.long\t0x%x\n", val); +	fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n", +		(val >> 24) & 0xff, (val >> 16) & 0xff, +		(val >> 8) & 0xff, val & 0xff);  }  static void asm_emit_string(void *e, char *str, int len) @@ -156,7 +166,7 @@ static void asm_emit_align(void *e, int a)  {  	FILE *f = e; -	fprintf(f, "\t.balign\t%d\n", a); +	fprintf(f, "\t.balign\t%d, 0\n", a);  }  static void asm_emit_data(void *e, struct data d) @@ -169,8 +179,7 @@ static void asm_emit_data(void *e, struct data d)  		emit_offset_label(f, m->ref, m->offset);  	while ((d.len - off) >= sizeof(uint32_t)) { -		fprintf(f, "\t.long\t0x%x\n", -			fdt32_to_cpu(*((uint32_t *)(d.val+off)))); +		asm_emit_cell(e, fdt32_to_cpu(*((uint32_t *)(d.val+off))));  		off += sizeof(uint32_t);  	} @@ -182,37 +191,43 @@ static void asm_emit_data(void *e, struct data d)  	assert(off == d.len);  } -static void asm_emit_beginnode(void *e, const char *label) +static void asm_emit_beginnode(void *e, struct label *labels)  {  	FILE *f = e; +	struct label *l; -	if (label) { -		fprintf(f, "\t.globl\t%s\n", label); -		fprintf(f, "%s:\n", label); +	for_each_label(labels, l) { +		fprintf(f, "\t.globl\t%s\n", l->label); +		fprintf(f, "%s:\n", l->label);  	} -	fprintf(f, "\t.long\tFDT_BEGIN_NODE\n"); +	fprintf(f, "\t/* FDT_BEGIN_NODE */\n"); +	asm_emit_cell(e, FDT_BEGIN_NODE);  } -static void asm_emit_endnode(void *e, const char *label) +static void asm_emit_endnode(void *e, struct label *labels)  {  	FILE *f = e; +	struct label *l; -	fprintf(f, "\t.long\tFDT_END_NODE\n"); -	if (label) { -		fprintf(f, "\t.globl\t%s_end\n", label); -		fprintf(f, "%s_end:\n", label); +	fprintf(f, "\t/* FDT_END_NODE */\n"); +	asm_emit_cell(e, FDT_END_NODE); +	for_each_label(labels, l) { +		fprintf(f, "\t.globl\t%s_end\n", l->label); +		fprintf(f, "%s_end:\n", l->label);  	}  } -static void asm_emit_property(void *e, const char *label) +static void asm_emit_property(void *e, struct label *labels)  {  	FILE *f = e; +	struct label *l; -	if (label) { -		fprintf(f, "\t.globl\t%s\n", label); -		fprintf(f, "%s:\n", label); +	for_each_label(labels, l) { +		fprintf(f, "\t.globl\t%s\n", l->label); +		fprintf(f, "%s:\n", l->label);  	} -	fprintf(f, "\t.long\tFDT_PROP\n"); +	fprintf(f, "\t/* FDT_PROP */\n"); +	asm_emit_cell(e, FDT_PROP);  }  static struct emitter asm_emitter = { @@ -248,7 +263,10 @@ static void flatten_tree(struct node *tree, struct emitter *emit,  	struct node *child;  	int seen_name_prop = 0; -	emit->beginnode(etarget, tree->label); +	if (tree->deleted) +		return; + +	emit->beginnode(etarget, tree->labels);  	if (vi->flags & FTF_FULLPATH)  		emit->string(etarget, tree->fullpath, 0); @@ -265,7 +283,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit,  		nameoff = stringtable_insert(strbuf, prop->name); -		emit->property(etarget, prop->label); +		emit->property(etarget, prop->labels);  		emit->cell(etarget, prop->val.len);  		emit->cell(etarget, nameoff); @@ -292,7 +310,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit,  		flatten_tree(child, emit, etarget, strbuf, vi);  	} -	emit->endnode(etarget, tree->label); +	emit->endnode(etarget, tree->labels);  }  static struct data flatten_reserve_list(struct reserve_info *reservelist, @@ -413,10 +431,13 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version)  	if (padlen > 0)  		blob = data_append_zeroes(blob, padlen); -	fwrite(blob.val, blob.len, 1, f); - -	if (ferror(f)) -		die("Error writing device tree blob: %s\n", strerror(errno)); +	if (fwrite(blob.val, blob.len, 1, f) != 1) { +		if (ferror(f)) +			die("Error writing device tree blob: %s\n", +			    strerror(errno)); +		else +			die("Short write on device tree blob\n"); +	}  	/*  	 * data_merge() frees the right-hand element so only the blob @@ -455,39 +476,44 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)  		die("Unknown device tree blob version %d\n", version);  	fprintf(f, "/* autogenerated by dtc, do not edit */\n\n"); -	fprintf(f, "#define FDT_MAGIC 0x%x\n", FDT_MAGIC); -	fprintf(f, "#define FDT_BEGIN_NODE 0x%x\n", FDT_BEGIN_NODE); -	fprintf(f, "#define FDT_END_NODE 0x%x\n", FDT_END_NODE); -	fprintf(f, "#define FDT_PROP 0x%x\n", FDT_PROP); -	fprintf(f, "#define FDT_END 0x%x\n", FDT_END); -	fprintf(f, "\n");  	emit_label(f, symprefix, "blob_start");  	emit_label(f, symprefix, "header"); -	fprintf(f, "\t.long\tFDT_MAGIC\t\t\t\t/* magic */\n"); -	fprintf(f, "\t.long\t_%s_blob_abs_end - _%s_blob_start\t/* totalsize */\n", -		symprefix, symprefix); -	fprintf(f, "\t.long\t_%s_struct_start - _%s_blob_start\t/* off_dt_struct */\n", +	fprintf(f, "\t/* magic */\n"); +	asm_emit_cell(f, FDT_MAGIC); +	fprintf(f, "\t/* totalsize */\n"); +	ASM_EMIT_BELONG(f, "_%s_blob_abs_end - _%s_blob_start", +			symprefix, symprefix); +	fprintf(f, "\t/* off_dt_struct */\n"); +	ASM_EMIT_BELONG(f, "_%s_struct_start - _%s_blob_start",  		symprefix, symprefix); -	fprintf(f, "\t.long\t_%s_strings_start - _%s_blob_start\t/* off_dt_strings */\n", +	fprintf(f, "\t/* off_dt_strings */\n"); +	ASM_EMIT_BELONG(f, "_%s_strings_start - _%s_blob_start",  		symprefix, symprefix); -	fprintf(f, "\t.long\t_%s_reserve_map - _%s_blob_start\t/* off_dt_strings */\n", +	fprintf(f, "\t/* off_mem_rsvmap */\n"); +	ASM_EMIT_BELONG(f, "_%s_reserve_map - _%s_blob_start",  		symprefix, symprefix); -	fprintf(f, "\t.long\t%d\t\t\t\t\t/* version */\n", vi->version); -	fprintf(f, "\t.long\t%d\t\t\t\t\t/* last_comp_version */\n", -		vi->last_comp_version); - -	if (vi->flags & FTF_BOOTCPUID) -		fprintf(f, "\t.long\t%i\t\t\t\t\t/* boot_cpuid_phys */\n", -			bi->boot_cpuid_phys); +	fprintf(f, "\t/* version */\n"); +	asm_emit_cell(f, vi->version); +	fprintf(f, "\t/* last_comp_version */\n"); +	asm_emit_cell(f, vi->last_comp_version); + +	if (vi->flags & FTF_BOOTCPUID) { +		fprintf(f, "\t/* boot_cpuid_phys */\n"); +		asm_emit_cell(f, bi->boot_cpuid_phys); +	} -	if (vi->flags & FTF_STRTABSIZE) -		fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n", -			symprefix, symprefix); +	if (vi->flags & FTF_STRTABSIZE) { +		fprintf(f, "\t/* size_dt_strings */\n"); +		ASM_EMIT_BELONG(f, "_%s_strings_end - _%s_strings_start", +				symprefix, symprefix); +	} -	if (vi->flags & FTF_STRUCTSIZE) -		fprintf(f, "\t.long\t_%s_struct_end - _%s_struct_start\t/* size_dt_struct */\n", +	if (vi->flags & FTF_STRUCTSIZE) { +		fprintf(f, "\t/* size_dt_struct */\n"); +		ASM_EMIT_BELONG(f, "_%s_struct_end - _%s_struct_start",  			symprefix, symprefix); +	}  	/*  	 * Reserve map entries. @@ -505,16 +531,17 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)  	 * as it appears .quad isn't available in some assemblers.  	 */  	for (re = bi->reservelist; re; re = re->next) { -		if (re->label) { -			fprintf(f, "\t.globl\t%s\n", re->label); -			fprintf(f, "%s:\n", re->label); +		struct label *l; + +		for_each_label(re->labels, l) { +			fprintf(f, "\t.globl\t%s\n", l->label); +			fprintf(f, "%s:\n", l->label);  		} -		fprintf(f, "\t.long\t0x%08x, 0x%08x\n", -			(unsigned int)(re->re.address >> 32), -			(unsigned int)(re->re.address & 0xffffffff)); -		fprintf(f, "\t.long\t0x%08x, 0x%08x\n", -			(unsigned int)(re->re.size >> 32), -			(unsigned int)(re->re.size & 0xffffffff)); +		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32)); +		ASM_EMIT_BELONG(f, "0x%08x", +				(unsigned int)(re->re.address & 0xffffffff)); +		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32)); +		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff));  	}  	for (i = 0; i < reservenum; i++) {  		fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); @@ -524,7 +551,9 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)  	emit_label(f, symprefix, "struct_start");  	flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi); -	fprintf(f, "\t.long\tFDT_END\n"); + +	fprintf(f, "\t/* FDT_END */\n"); +	asm_emit_cell(f, FDT_END);  	emit_label(f, symprefix, "struct_end");  	emit_label(f, symprefix, "strings_start"); @@ -601,7 +630,7 @@ static char *flat_read_string(struct inbuf *inb)  		len++;  	} while ((*p++) != '\0'); -	str = strdup(inb->ptr); +	str = xstrdup(inb->ptr);  	inb->ptr += len; @@ -643,7 +672,7 @@ static char *flat_read_stringtable(struct inbuf *inb, int offset)  		p++;  	} -	return strdup(inb->base + offset); +	return xstrdup(inb->base + offset);  }  static struct property *flat_read_property(struct inbuf *dtbuf, @@ -663,7 +692,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf,  	val = flat_read_data(dtbuf, proplen); -	return build_property(name, val, NULL); +	return build_property(name, val);  } @@ -671,7 +700,6 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)  {  	struct reserve_info *reservelist = NULL;  	struct reserve_info *new; -	const char *p;  	struct fdt_reserve_entry re;  	/* @@ -680,7 +708,6 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)  	 *  	 * First pass, count entries.  	 */ -	p = inb->ptr;  	while (1) {  		flat_read_chunk(inb, &re, sizeof(re));  		re.address  = fdt64_to_cpu(re.address); @@ -688,7 +715,7 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)  		if (re.size == 0)  			break; -		new = build_reserve_entry(re.address, re.size, NULL); +		new = build_reserve_entry(re.address, re.size);  		reservelist = add_reserve_entry(reservelist, new);  	} @@ -710,7 +737,7 @@ static char *nodename_from_path(const char *ppath, const char *cpath)  	if (!streq(ppath, "/"))  		plen++; -	return strdup(cpath + plen); +	return xstrdup(cpath + plen);  }  static struct node *unflatten_tree(struct inbuf *dtbuf, @@ -776,7 +803,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,  struct boot_info *dt_from_blob(const char *fname)  { -	struct dtc_file *dtcf; +	FILE *f;  	uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;  	uint32_t off_dt, off_str, off_mem_rsvmap;  	int rc; @@ -791,14 +818,14 @@ struct boot_info *dt_from_blob(const char *fname)  	uint32_t val;  	int flags = 0; -	dtcf = dtc_open_file(fname, NULL); +	f = srcfile_relative_open(fname, NULL); -	rc = fread(&magic, sizeof(magic), 1, dtcf->file); -	if (ferror(dtcf->file)) +	rc = fread(&magic, sizeof(magic), 1, f); +	if (ferror(f))  		die("Error reading DT blob magic number: %s\n",  		    strerror(errno));  	if (rc < 1) { -		if (feof(dtcf->file)) +		if (feof(f))  			die("EOF reading DT blob magic number\n");  		else  			die("Mysterious short read reading magic number\n"); @@ -808,11 +835,11 @@ struct boot_info *dt_from_blob(const char *fname)  	if (magic != FDT_MAGIC)  		die("Blob has incorrect magic number\n"); -	rc = fread(&totalsize, sizeof(totalsize), 1, dtcf->file); -	if (ferror(dtcf->file)) +	rc = fread(&totalsize, sizeof(totalsize), 1, f); +	if (ferror(f))  		die("Error reading DT blob size: %s\n", strerror(errno));  	if (rc < 1) { -		if (feof(dtcf->file)) +		if (feof(f))  			die("EOF reading DT blob size\n");  		else  			die("Mysterious short read reading blob size\n"); @@ -832,12 +859,12 @@ struct boot_info *dt_from_blob(const char *fname)  	p = blob + sizeof(magic)  + sizeof(totalsize);  	while (sizeleft) { -		if (feof(dtcf->file)) +		if (feof(f))  			die("EOF before reading %d bytes of DT blob\n",  			    totalsize); -		rc = fread(p, 1, sizeleft, dtcf->file); -		if (ferror(dtcf->file)) +		rc = fread(p, 1, sizeleft, f); +		if (ferror(f))  			die("Error reading DT blob: %s\n",  			    strerror(errno)); @@ -900,7 +927,7 @@ struct boot_info *dt_from_blob(const char *fname)  	free(blob); -	dtc_close_file(dtcf); +	fclose(f);  	return build_boot_info(reservelist, tree, boot_cpuid_phys);  } diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c index 8fe1bdf239f..e464727c880 100644 --- a/scripts/dtc/fstree.c +++ b/scripts/dtc/fstree.c @@ -58,10 +58,9 @@ static struct node *read_fstree(const char *dirname)  					"WARNING: Cannot open %s: %s\n",  					tmpnam, strerror(errno));  			} else { -				prop = build_property(strdup(de->d_name), +				prop = build_property(xstrdup(de->d_name),  						      data_copy_file(pfile, -								     st.st_size), -						      NULL); +								     st.st_size));  				add_property(tree, prop);  				fclose(pfile);  			} @@ -69,8 +68,7 @@ static struct node *read_fstree(const char *dirname)  			struct node *newchild;  			newchild = read_fstree(tmpnam); -			newchild = name_node(newchild, strdup(de->d_name), -					     NULL); +			newchild = name_node(newchild, xstrdup(de->d_name));  			add_child(tree, newchild);  		} @@ -86,8 +84,7 @@ struct boot_info *dt_from_fs(const char *dirname)  	struct node *tree;  	tree = read_fstree(dirname); -	tree = name_node(tree, "", NULL); +	tree = name_node(tree, ""); -	return build_boot_info(NULL, tree, 0); +	return build_boot_info(NULL, tree, guess_boot_cpuid(tree));  } - diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt index 6c42acfa21e..91126c000a1 100644 --- a/scripts/dtc/libfdt/Makefile.libfdt +++ b/scripts/dtc/libfdt/Makefile.libfdt @@ -3,6 +3,8 @@  # This is not a complete Makefile of itself.  Instead, it is designed to  # be easily embeddable into other systems of Makefiles.  # -LIBFDT_INCLUDES = fdt.h libfdt.h -LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c +LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1 +LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h +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  LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c index 2acaec5923a..e56833ae9b6 100644 --- a/scripts/dtc/libfdt/fdt.c +++ b/scripts/dtc/libfdt/fdt.c @@ -74,7 +74,7 @@ int fdt_check_header(const void *fdt)  	return 0;  } -const void *fdt_offset_ptr(const void *fdt, int offset, int len) +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)  {  	const char *p; @@ -90,42 +90,53 @@ const void *fdt_offset_ptr(const void *fdt, int offset, int len)  	return p;  } -uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset) +uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)  {  	const uint32_t *tagp, *lenp;  	uint32_t tag; +	int offset = startoffset;  	const char *p; -	if (offset % FDT_TAGSIZE) -		return -1; - +	*nextoffset = -FDT_ERR_TRUNCATED;  	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); -	if (! tagp) +	if (!tagp)  		return FDT_END; /* premature end */  	tag = fdt32_to_cpu(*tagp);  	offset += FDT_TAGSIZE; +	*nextoffset = -FDT_ERR_BADSTRUCTURE;  	switch (tag) {  	case FDT_BEGIN_NODE:  		/* skip name */  		do {  			p = fdt_offset_ptr(fdt, offset++, 1);  		} while (p && (*p != '\0')); -		if (! p) -			return FDT_END; +		if (!p) +			return FDT_END; /* premature end */  		break; +  	case FDT_PROP:  		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); -		if (! lenp) -			return FDT_END; -		/* skip name offset, length and value */ -		offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp); +		if (!lenp) +			return FDT_END; /* premature end */ +		/* skip-name offset, length and value */ +		offset += sizeof(struct fdt_property) - FDT_TAGSIZE +			+ fdt32_to_cpu(*lenp); +		break; + +	case FDT_END: +	case FDT_END_NODE: +	case FDT_NOP:  		break; + +	default: +		return FDT_END;  	} -	if (nextoffset) -		*nextoffset = FDT_TAGALIGN(offset); +	if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) +		return FDT_END; /* premature end */ +	*nextoffset = FDT_TAGALIGN(offset);  	return tag;  } @@ -138,6 +149,15 @@ int _fdt_check_node_offset(const void *fdt, int offset)  	return offset;  } +int _fdt_check_prop_offset(const void *fdt, int offset) +{ +	if ((offset < 0) || (offset % FDT_TAGSIZE) +	    || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) +		return -FDT_ERR_BADOFFSET; + +	return offset; +} +  int fdt_next_node(const void *fdt, int offset, int *depth)  {  	int nextoffset = 0; @@ -162,15 +182,16 @@ int fdt_next_node(const void *fdt, int offset, int *depth)  			break;  		case FDT_END_NODE: -			if (depth) -				(*depth)--; +			if (depth && ((--(*depth)) < 0)) +				return nextoffset;  			break;  		case FDT_END: -			return -FDT_ERR_NOTFOUND; - -		default: -			return -FDT_ERR_BADSTRUCTURE; +			if ((nextoffset >= 0) +			    || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) +				return -FDT_ERR_NOTFOUND; +			else +				return nextoffset;  		}  	} while (tag != FDT_BEGIN_NODE); diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c new file mode 100644 index 00000000000..f2ae9b77c28 --- /dev/null +++ b/scripts/dtc/libfdt/fdt_empty_tree.c @@ -0,0 +1,83 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2012 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + *  a) This library is free software; you can redistribute it and/or + *     modify it under the terms of the GNU General Public License as + *     published by the Free Software Foundation; either version 2 of the + *     License, or (at your option) any later version. + * + *     This library is distributed in the hope that it will be useful, + *     but WITHOUT ANY WARRANTY; without even the implied warranty of + *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *     GNU General Public License for more details. + * + *     You should have received a copy of the GNU General Public + *     License along with this library; if not, write to the Free + *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + *     MA 02110-1301 USA + * + * Alternatively, + * + *  b) Redistribution and use in source and binary forms, with or + *     without modification, are permitted provided that the following + *     conditions are met: + * + *     1. Redistributions of source code must retain the above + *        copyright notice, this list of conditions and the following + *        disclaimer. + *     2. Redistributions in binary form must reproduce the above + *        copyright notice, this list of conditions and the following + *        disclaimer in the documentation and/or other materials + *        provided with the distribution. + * + *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +int fdt_create_empty_tree(void *buf, int bufsize) +{ +	int err; + +	err = fdt_create(buf, bufsize); +	if (err) +		return err; + +	err = fdt_finish_reservemap(buf); +	if (err) +		return err; + +	err = fdt_begin_node(buf, ""); +	if (err) +		return err; + +	err =  fdt_end_node(buf); +	if (err) +		return err; + +	err = fdt_finish(buf); +	if (err) +		return err; + +	return fdt_open_into(buf, buf, bufsize); +} diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index 22e692919ff..02b6d687537 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -80,6 +80,14 @@ const char *fdt_string(const void *fdt, int stroffset)  	return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;  } +static int _fdt_string_eq(const void *fdt, int stroffset, +			  const char *s, int len) +{ +	const char *p = fdt_string(fdt, stroffset); + +	return (strlen(p) == len) && (memcmp(p, s, len) == 0); +} +  int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)  {  	FDT_CHECK_HEADER(fdt); @@ -97,6 +105,30 @@ int fdt_num_mem_rsv(const void *fdt)  	return i;  } +static int _nextprop(const void *fdt, int offset) +{ +	uint32_t tag; +	int nextoffset; + +	do { +		tag = fdt_next_tag(fdt, offset, &nextoffset); + +		switch (tag) { +		case FDT_END: +			if (nextoffset >= 0) +				return -FDT_ERR_BADSTRUCTURE; +			else +				return nextoffset; + +		case FDT_PROP: +			return offset; +		} +		offset = nextoffset; +	} while (tag == FDT_NOP); + +	return -FDT_ERR_NOTFOUND; +} +  int fdt_subnode_offset_namelen(const void *fdt, int offset,  			       const char *name, int namelen)  { @@ -104,20 +136,16 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,  	FDT_CHECK_HEADER(fdt); -	for (depth = 0, offset = fdt_next_node(fdt, offset, &depth); -	     (offset >= 0) && (depth > 0); -	     offset = fdt_next_node(fdt, offset, &depth)) { -		if (depth < 0) -			return -FDT_ERR_NOTFOUND; -		else if ((depth == 1) -			 && _fdt_nodename_eq(fdt, offset, name, namelen)) +	for (depth = 0; +	     (offset >= 0) && (depth >= 0); +	     offset = fdt_next_node(fdt, offset, &depth)) +		if ((depth == 1) +		    && _fdt_nodename_eq(fdt, offset, name, namelen))  			return offset; -	} -	if (offset < 0) -		return offset; /* error */ -	else +	if (depth < 0)  		return -FDT_ERR_NOTFOUND; +	return offset; /* error */  }  int fdt_subnode_offset(const void *fdt, int parentoffset, @@ -134,8 +162,20 @@ int fdt_path_offset(const void *fdt, const char *path)  	FDT_CHECK_HEADER(fdt); -	if (*path != '/') -		return -FDT_ERR_BADPATH; +	/* see if we have an alias */ +	if (*path != '/') { +		const char *q = strchr(path, '/'); + +		if (!q) +			q = end; + +		p = fdt_get_alias_namelen(fdt, p, q - p); +		if (!p) +			return -FDT_ERR_BADPATH; +		offset = fdt_path_offset(fdt, p); + +		p = q; +	}  	while (*p) {  		const char *q; @@ -178,93 +218,142 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)  	return NULL;  } -const struct fdt_property *fdt_get_property(const void *fdt, -					    int nodeoffset, -					    const char *name, int *lenp) +int fdt_first_property_offset(const void *fdt, int nodeoffset) +{ +	int offset; + +	if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) +		return offset; + +	return _nextprop(fdt, offset); +} + +int fdt_next_property_offset(const void *fdt, int offset) +{ +	if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0) +		return offset; + +	return _nextprop(fdt, offset); +} + +const struct fdt_property *fdt_get_property_by_offset(const void *fdt, +						      int offset, +						      int *lenp)  { -	uint32_t tag; -	const struct fdt_property *prop; -	int namestroff; -	int offset, nextoffset;  	int err; +	const struct fdt_property *prop; -	if (((err = fdt_check_header(fdt)) != 0) -	    || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) -			goto fail; +	if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { +		if (lenp) +			*lenp = err; +		return NULL; +	} -	nextoffset = err; -	do { -		offset = nextoffset; +	prop = _fdt_offset_ptr(fdt, offset); -		tag = fdt_next_tag(fdt, offset, &nextoffset); -		switch (tag) { -		case FDT_END: -			err = -FDT_ERR_TRUNCATED; -			goto fail; +	if (lenp) +		*lenp = fdt32_to_cpu(prop->len); -		case FDT_BEGIN_NODE: -		case FDT_END_NODE: -		case FDT_NOP: -			break; +	return prop; +} -		case FDT_PROP: -			err = -FDT_ERR_BADSTRUCTURE; -			prop = fdt_offset_ptr(fdt, offset, sizeof(*prop)); -			if (! prop) -				goto fail; -			namestroff = fdt32_to_cpu(prop->nameoff); -			if (strcmp(fdt_string(fdt, namestroff), name) == 0) { -				/* Found it! */ -				int len = fdt32_to_cpu(prop->len); -				prop = fdt_offset_ptr(fdt, offset, -						      sizeof(*prop)+len); -				if (! prop) -					goto fail; - -				if (lenp) -					*lenp = len; - -				return prop; -			} -			break; +const struct fdt_property *fdt_get_property_namelen(const void *fdt, +						    int offset, +						    const char *name, +						    int namelen, int *lenp) +{ +	for (offset = fdt_first_property_offset(fdt, offset); +	     (offset >= 0); +	     (offset = fdt_next_property_offset(fdt, offset))) { +		const struct fdt_property *prop; -		default: -			err = -FDT_ERR_BADSTRUCTURE; -			goto fail; +		if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) { +			offset = -FDT_ERR_INTERNAL; +			break;  		} -	} while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE)); +		if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), +				   name, namelen)) +			return prop; +	} -	err = -FDT_ERR_NOTFOUND; - fail:  	if (lenp) -		*lenp = err; +		*lenp = offset;  	return NULL;  } -const void *fdt_getprop(const void *fdt, int nodeoffset, -		  const char *name, int *lenp) +const struct fdt_property *fdt_get_property(const void *fdt, +					    int nodeoffset, +					    const char *name, int *lenp) +{ +	return fdt_get_property_namelen(fdt, nodeoffset, name, +					strlen(name), lenp); +} + +const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, +				const char *name, int namelen, int *lenp)  {  	const struct fdt_property *prop; -	prop = fdt_get_property(fdt, nodeoffset, name, lenp); +	prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);  	if (! prop)  		return NULL;  	return prop->data;  } +const void *fdt_getprop_by_offset(const void *fdt, int offset, +				  const char **namep, int *lenp) +{ +	const struct fdt_property *prop; + +	prop = fdt_get_property_by_offset(fdt, offset, lenp); +	if (!prop) +		return NULL; +	if (namep) +		*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); +	return prop->data; +} + +const void *fdt_getprop(const void *fdt, int nodeoffset, +			const char *name, int *lenp) +{ +	return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); +} +  uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)  {  	const uint32_t *php;  	int len; -	php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); -	if (!php || (len != sizeof(*php))) -		return 0; +	/* FIXME: This is a bit sub-optimal, since we potentially scan +	 * over all the properties twice. */ +	php = fdt_getprop(fdt, nodeoffset, "phandle", &len); +	if (!php || (len != sizeof(*php))) { +		php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); +		if (!php || (len != sizeof(*php))) +			return 0; +	}  	return fdt32_to_cpu(*php);  } +const char *fdt_get_alias_namelen(const void *fdt, +				  const char *name, int namelen) +{ +	int aliasoffset; + +	aliasoffset = fdt_path_offset(fdt, "/aliases"); +	if (aliasoffset < 0) +		return NULL; + +	return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); +} + +const char *fdt_get_alias(const void *fdt, const char *name) +{ +	return fdt_get_alias_namelen(fdt, name, strlen(name)); +} +  int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)  {  	int pdepth = 0, p = 0; @@ -279,9 +368,6 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)  	for (offset = 0, depth = 0;  	     (offset >= 0) && (offset <= nodeoffset);  	     offset = fdt_next_node(fdt, offset, &depth)) { -		if (pdepth < depth) -			continue; /* overflowed buffer */ -  		while (pdepth > depth) {  			do {  				p--; @@ -289,14 +375,16 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)  			pdepth--;  		} -		name = fdt_get_name(fdt, offset, &namelen); -		if (!name) -			return namelen; -		if ((p + namelen + 1) <= buflen) { -			memcpy(buf + p, name, namelen); -			p += namelen; -			buf[p++] = '/'; -			pdepth++; +		if (pdepth >= depth) { +			name = fdt_get_name(fdt, offset, &namelen); +			if (!name) +				return namelen; +			if ((p + namelen + 1) <= buflen) { +				memcpy(buf + p, name, namelen); +				p += namelen; +				buf[p++] = '/'; +				pdepth++; +			}  		}  		if (offset == nodeoffset) { @@ -306,7 +394,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)  			if (p > 1) /* special case so that root path is "/", not "" */  				p--;  			buf[p] = '\0'; -			return p; +			return 0;  		}  	} @@ -404,14 +492,31 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,  int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)  { +	int offset; +  	if ((phandle == 0) || (phandle == -1))  		return -FDT_ERR_BADPHANDLE; -	phandle = cpu_to_fdt32(phandle); -	return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle", -					     &phandle, sizeof(phandle)); + +	FDT_CHECK_HEADER(fdt); + +	/* FIXME: The algorithm here is pretty horrible: we +	 * potentially scan each property of a node in +	 * fdt_get_phandle(), then if that didn't find what +	 * we want, we scan over them again making our way to the next +	 * node.  Still it's the easiest to implement approach; +	 * performance can come later. */ +	for (offset = fdt_next_node(fdt, -1, NULL); +	     offset >= 0; +	     offset = fdt_next_node(fdt, offset, NULL)) { +		if (fdt_get_phandle(fdt, offset) == phandle) +			return offset; +	} + +	return offset; /* error from fdt_next_node() */  } -static int _stringlist_contains(const char *strlist, int listlen, const char *str) +static int _fdt_stringlist_contains(const char *strlist, int listlen, +				    const char *str)  {  	int len = strlen(str);  	const char *p; @@ -437,7 +542,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,  	prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);  	if (!prop)  		return len; -	if (_stringlist_contains(prop, len, compatible)) +	if (_fdt_stringlist_contains(prop, len, compatible))  		return 0;  	else  		return 1; diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c index 8e7ec4cb7bc..24437dfc32b 100644 --- a/scripts/dtc/libfdt/fdt_rw.c +++ b/scripts/dtc/libfdt/fdt_rw.c @@ -289,6 +289,33 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,  	return 0;  } +int fdt_appendprop(void *fdt, int nodeoffset, const char *name, +		   const void *val, int len) +{ +	struct fdt_property *prop; +	int err, oldlen, newlen; + +	FDT_RW_CHECK_HEADER(fdt); + +	prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); +	if (prop) { +		newlen = len + oldlen; +		err = _fdt_splice_struct(fdt, prop->data, +					 FDT_TAGALIGN(oldlen), +					 FDT_TAGALIGN(newlen)); +		if (err) +			return err; +		prop->len = cpu_to_fdt32(newlen); +		memcpy(prop->data + oldlen, val, len); +	} else { +		err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); +		if (err) +			return err; +		memcpy(prop->data, val, len); +	} +	return 0; +} +  int fdt_delprop(void *fdt, int nodeoffset, const char *name)  {  	struct fdt_property *prop; @@ -406,6 +433,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)  		struct_size = 0;  		while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)  			; +		if (struct_size < 0) +			return struct_size;  	}  	if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c index 698329e0cca..55ebebf1eb2 100644 --- a/scripts/dtc/libfdt/fdt_sw.c +++ b/scripts/dtc/libfdt/fdt_sw.c @@ -70,7 +70,7 @@ static int _fdt_sw_check_header(void *fdt)  			return err; \  	} -static void *_fdt_grab_space(void *fdt, int len) +static void *_fdt_grab_space(void *fdt, size_t len)  {  	int offset = fdt_size_dt_struct(fdt);  	int spaceleft; @@ -82,7 +82,7 @@ static void *_fdt_grab_space(void *fdt, int len)  		return NULL;  	fdt_set_size_dt_struct(fdt, offset + len); -	return fdt_offset_ptr_w(fdt, offset, len); +	return _fdt_offset_ptr_w(fdt, offset);  }  int fdt_create(void *buf, int bufsize) @@ -237,18 +237,17 @@ int fdt_finish(void *fdt)  	while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {  		if (tag == FDT_PROP) {  			struct fdt_property *prop = -				fdt_offset_ptr_w(fdt, offset, sizeof(*prop)); +				_fdt_offset_ptr_w(fdt, offset);  			int nameoff; -			if (! prop) -				return -FDT_ERR_BADSTRUCTURE; -  			nameoff = fdt32_to_cpu(prop->nameoff);  			nameoff += fdt_size_dt_strings(fdt);  			prop->nameoff = cpu_to_fdt32(nameoff);  		}  		offset = nextoffset;  	} +	if (nextoffset < 0) +		return nextoffset;  	/* Finally, adjust the header */  	fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c index a4652c6e787..6025fa1fe8f 100644 --- a/scripts/dtc/libfdt/fdt_wip.c +++ b/scripts/dtc/libfdt/fdt_wip.c @@ -94,41 +94,14 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)  	return 0;  } -int _fdt_node_end_offset(void *fdt, int nodeoffset) +int _fdt_node_end_offset(void *fdt, int offset)  { -	int level = 0; -	uint32_t tag; -	int offset, nextoffset; - -	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset); -	if (tag != FDT_BEGIN_NODE) -		return -FDT_ERR_BADOFFSET; -	do { -		offset = nextoffset; -		tag = fdt_next_tag(fdt, offset, &nextoffset); - -		switch (tag) { -		case FDT_END: -			return offset; - -		case FDT_BEGIN_NODE: -			level++; -			break; - -		case FDT_END_NODE: -			level--; -			break; - -		case FDT_PROP: -		case FDT_NOP: -			break; - -		default: -			return -FDT_ERR_BADSTRUCTURE; -		} -	} while (level >= 0); - -	return nextoffset; +	int depth = 0; + +	while ((offset >= 0) && (depth >= 0)) +		offset = fdt_next_node(fdt, offset, &depth); + +	return offset;  }  int fdt_nop_node(void *fdt, int nodeoffset) diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h index ce80e4fb41b..73f49759a5e 100644 --- a/scripts/dtc/libfdt/libfdt.h +++ b/scripts/dtc/libfdt/libfdt.h @@ -122,7 +122,7 @@  /* Low-level functions (you probably don't need these)                */  /**********************************************************************/ -const void *fdt_offset_ptr(const void *fdt, int offset, int checklen); +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);  static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)  {  	return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); @@ -156,7 +156,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth);  #define __fdt_set_hdr(name) \  	static inline void fdt_set_##name(void *fdt, uint32_t val) \  	{ \ -		struct fdt_header *fdth = fdt; \ +		struct fdt_header *fdth = (struct fdt_header*)fdt; \  		fdth->name = cpu_to_fdt32(val); \  	}  __fdt_set_hdr(magic); @@ -343,6 +343,91 @@ int fdt_path_offset(const void *fdt, const char *path);  const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);  /** + * fdt_first_property_offset - find the offset of a node's first property + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of a node + * + * fdt_first_property_offset() finds the first property of the node at + * the given structure block offset. + * + * returns: + *	structure block offset of the property (>=0), on success + *	-FDT_ERR_NOTFOUND, if the requested node has no properties + *	-FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag + *      -FDT_ERR_BADMAGIC, + *	-FDT_ERR_BADVERSION, + *	-FDT_ERR_BADSTATE, + *	-FDT_ERR_BADSTRUCTURE, + *	-FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_first_property_offset(const void *fdt, int nodeoffset); + +/** + * fdt_next_property_offset - step through a node's properties + * @fdt: pointer to the device tree blob + * @offset: structure block offset of a property + * + * fdt_next_property_offset() finds the property immediately after the + * one at the given structure block offset.  This will be a property + * of the same node as the given property. + * + * returns: + *	structure block offset of the next property (>=0), on success + *	-FDT_ERR_NOTFOUND, if the given property is the last in its node + *	-FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag + *      -FDT_ERR_BADMAGIC, + *	-FDT_ERR_BADVERSION, + *	-FDT_ERR_BADSTATE, + *	-FDT_ERR_BADSTRUCTURE, + *	-FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_next_property_offset(const void *fdt, int offset); + +/** + * fdt_get_property_by_offset - retrieve the property at a given offset + * @fdt: pointer to the device tree blob + * @offset: offset of the property to retrieve + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_property_by_offset() retrieves a pointer to the + * fdt_property structure within the device tree blob at the given + * offset.  If lenp is non-NULL, the length of the property value is + * also returned, in the integer pointed to by lenp. + * + * returns: + *	pointer to the structure representing the property + *		if lenp is non-NULL, *lenp contains the length of the property + *		value (>=0) + *	NULL, on error + *		if lenp is non-NULL, *lenp contains an error code (<0): + *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag + *		-FDT_ERR_BADMAGIC, + *		-FDT_ERR_BADVERSION, + *		-FDT_ERR_BADSTATE, + *		-FDT_ERR_BADSTRUCTURE, + *		-FDT_ERR_TRUNCATED, standard meanings + */ +const struct fdt_property *fdt_get_property_by_offset(const void *fdt, +						      int offset, +						      int *lenp); + +/** + * fdt_get_property_namelen - find a property based on substring + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @namelen: number of characters of name to consider + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * Identical to fdt_get_property_namelen(), but only examine the first + * namelen characters of name for matching the property name. + */ +const struct fdt_property *fdt_get_property_namelen(const void *fdt, +						    int nodeoffset, +						    const char *name, +						    int namelen, int *lenp); + +/**   * fdt_get_property - find a given property in a given node   * @fdt: pointer to the device tree blob   * @nodeoffset: offset of the node whose property to find @@ -380,6 +465,54 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,  }  /** + * fdt_getprop_by_offset - retrieve the value of a property at a given offset + * @fdt: pointer to the device tree blob + * @ffset: offset of the property to read + * @namep: pointer to a string variable (will be overwritten) or NULL + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_getprop_by_offset() retrieves a pointer to the value of the + * property at structure block offset 'offset' (this will be a pointer + * to within the device blob itself, not a copy of the value).  If + * lenp is non-NULL, the length of the property value is also + * returned, in the integer pointed to by lenp.  If namep is non-NULL, + * the property's namne will also be returned in the char * pointed to + * by namep (this will be a pointer to within the device tree's string + * block, not a new copy of the name). + * + * returns: + *	pointer to the property's value + *		if lenp is non-NULL, *lenp contains the length of the property + *		value (>=0) + *		if namep is non-NULL *namep contiains a pointer to the property + *		name. + *	NULL, on error + *		if lenp is non-NULL, *lenp contains an error code (<0): + *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag + *		-FDT_ERR_BADMAGIC, + *		-FDT_ERR_BADVERSION, + *		-FDT_ERR_BADSTATE, + *		-FDT_ERR_BADSTRUCTURE, + *		-FDT_ERR_TRUNCATED, standard meanings + */ +const void *fdt_getprop_by_offset(const void *fdt, int offset, +				  const char **namep, int *lenp); + +/** + * fdt_getprop_namelen - get property value based on substring + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @namelen: number of characters of name to consider + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * Identical to fdt_getprop(), but only examine the first namelen + * characters of name for matching the property name. + */ +const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, +				const char *name, int namelen, int *lenp); + +/**   * fdt_getprop - retrieve the value of a given property   * @fdt: pointer to the device tree blob   * @nodeoffset: offset of the node whose property to find @@ -429,6 +562,32 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset,  uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);  /** + * fdt_get_alias_namelen - get alias based on substring + * @fdt: pointer to the device tree blob + * @name: name of the alias th look up + * @namelen: number of characters of name to consider + * + * Identical to fdt_get_alias(), but only examine the first namelen + * characters of name for matching the alias name. + */ +const char *fdt_get_alias_namelen(const void *fdt, +				  const char *name, int namelen); + +/** + * fdt_get_alias - retreive the path referenced by a given alias + * @fdt: pointer to the device tree blob + * @name: name of the alias th look up + * + * fdt_get_alias() retrieves the value of a given alias.  That is, the + * value of the property named 'name' in the node /aliases. + * + * returns: + *	a pointer to the expansion of the alias named 'name', of it exists + *	NULL, if the given alias or the /aliases node does not exist + */ +const char *fdt_get_alias(const void *fdt, const char *name); + +/**   * fdt_get_path - determine the full path of a node   * @fdt: pointer to the device tree blob   * @nodeoffset: offset of the node whose path to find @@ -693,17 +852,17 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,  			const void *val, int len);  /** - * fdt_setprop_inplace_cell - change the value of a single-cell property + * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property   * @fdt: pointer to the device tree blob   * @nodeoffset: offset of the node whose property to change   * @name: name of the property to change - * @val: cell (32-bit integer) value to replace the property with + * @val: 32-bit integer value to replace the property with   * - * fdt_setprop_inplace_cell() replaces the value of a given property - * with the 32-bit integer cell value in val, converting val to - * big-endian if necessary.  This function cannot change the size of a - * property, and so will only work if the property already exists and - * has length 4. + * fdt_setprop_inplace_u32() replaces the value of a given property + * with the 32-bit integer value in val, converting val to big-endian + * if necessary.  This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 4.   *   * This function will alter only the bytes in the blob which contain   * the given property value, and will not alter or move any other part @@ -712,7 +871,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,   * returns:   *	0, on success   *	-FDT_ERR_NOSPACE, if the property's length is not equal to 4 -  *	-FDT_ERR_NOTFOUND, node does not have the named property + *	-FDT_ERR_NOTFOUND, node does not have the named property   *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag   *	-FDT_ERR_BADMAGIC,   *	-FDT_ERR_BADVERSION, @@ -720,14 +879,60 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,   *	-FDT_ERR_BADSTRUCTURE,   *	-FDT_ERR_TRUNCATED, standard meanings   */ -static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, -					   const char *name, uint32_t val) +static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, +					  const char *name, uint32_t val)  {  	val = cpu_to_fdt32(val);  	return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));  }  /** + * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value to replace the property with + * + * fdt_setprop_inplace_u64() replaces the value of a given property + * with the 64-bit integer value in val, converting val to big-endian + * if necessary.  This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 8. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + *	0, on success + *	-FDT_ERR_NOSPACE, if the property's length is not equal to 8 + *	-FDT_ERR_NOTFOUND, node does not have the named property + *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + *	-FDT_ERR_BADMAGIC, + *	-FDT_ERR_BADVERSION, + *	-FDT_ERR_BADSTATE, + *	-FDT_ERR_BADSTRUCTURE, + *	-FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, +					  const char *name, uint64_t val) +{ +	val = cpu_to_fdt64(val); +	return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); +} + +/** + * fdt_setprop_inplace_cell - change the value of a single-cell property + * + * This is an alternative name for fdt_setprop_inplace_u32() + */ +static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, +					   const char *name, uint32_t val) +{ +	return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val); +} + +/**   * fdt_nop_property - replace a property with nop tags   * @fdt: pointer to the device tree blob   * @nodeoffset: offset of the node whose property to nop @@ -786,11 +991,20 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);  int fdt_finish_reservemap(void *fdt);  int fdt_begin_node(void *fdt, const char *name);  int fdt_property(void *fdt, const char *name, const void *val, int len); -static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) +static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)  {  	val = cpu_to_fdt32(val);  	return fdt_property(fdt, name, &val, sizeof(val));  } +static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) +{ +	val = cpu_to_fdt64(val); +	return fdt_property(fdt, name, &val, sizeof(val)); +} +static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) +{ +	return fdt_property_u32(fdt, name, val); +}  #define fdt_property_string(fdt, name, str) \  	fdt_property(fdt, name, str, strlen(str)+1)  int fdt_end_node(void *fdt); @@ -800,6 +1014,7 @@ int fdt_finish(void *fdt);  /* Read-write functions                                               */  /**********************************************************************/ +int fdt_create_empty_tree(void *buf, int bufsize);  int fdt_open_into(const void *fdt, void *buf, int bufsize);  int fdt_pack(void *fdt); @@ -909,14 +1124,14 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,  		const void *val, int len);  /** - * fdt_setprop_cell - set a property to a single cell value + * fdt_setprop_u32 - set a property to a 32-bit integer   * @fdt: pointer to the device tree blob   * @nodeoffset: offset of the node whose property to change   * @name: name of the property to change   * @val: 32-bit integer value for the property (native endian)   * - * fdt_setprop_cell() sets the value of the named property in the - * given node to the given cell value (converting to big-endian if + * fdt_setprop_u32() sets the value of the named property in the given + * node to the given 32-bit integer value (converting to big-endian if   * necessary), or creates a new property with that value if it does   * not already exist.   * @@ -936,14 +1151,60 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,   *	-FDT_ERR_BADLAYOUT,   *	-FDT_ERR_TRUNCATED, standard meanings   */ -static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, -				   uint32_t val) +static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, +				  uint32_t val)  {  	val = cpu_to_fdt32(val);  	return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));  }  /** + * fdt_setprop_u64 - set a property to a 64-bit integer + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value for the property (native endian) + * + * fdt_setprop_u64() sets the value of the named property in the given + * node to the given 64-bit integer value (converting to big-endian if + * necessary), or creates a new property with that value if it does + * not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + *	0, on success + *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to + *		contain the new property value + *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + *	-FDT_ERR_BADLAYOUT, + *	-FDT_ERR_BADMAGIC, + *	-FDT_ERR_BADVERSION, + *	-FDT_ERR_BADSTATE, + *	-FDT_ERR_BADSTRUCTURE, + *	-FDT_ERR_BADLAYOUT, + *	-FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, +				  uint64_t val) +{ +	val = cpu_to_fdt64(val); +	return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); +} + +/** + * fdt_setprop_cell - set a property to a single cell value + * + * This is an alternative name for fdt_setprop_u32() + */ +static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, +				   uint32_t val) +{ +	return fdt_setprop_u32(fdt, nodeoffset, name, val); +} + +/**   * fdt_setprop_string - set a property to a string value   * @fdt: pointer to the device tree blob   * @nodeoffset: offset of the node whose property to change @@ -975,6 +1236,147 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,  	fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)  /** + * fdt_appendprop - append to or create a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to append to + * @val: pointer to data to append to the property value + * @len: length of the data to append to the property value + * + * fdt_appendprop() appends the value to the named property in the + * given node, creating the property if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + *	0, on success + *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to + *		contain the new property value + *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + *	-FDT_ERR_BADLAYOUT, + *	-FDT_ERR_BADMAGIC, + *	-FDT_ERR_BADVERSION, + *	-FDT_ERR_BADSTATE, + *	-FDT_ERR_BADSTRUCTURE, + *	-FDT_ERR_BADLAYOUT, + *	-FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_appendprop(void *fdt, int nodeoffset, const char *name, +		   const void *val, int len); + +/** + * fdt_appendprop_u32 - append a 32-bit integer value to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value to append to the property (native endian) + * + * fdt_appendprop_u32() appends the given 32-bit integer value + * (converting to big-endian if necessary) to the value of the named + * property in the given node, or creates a new property with that + * value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + *	0, on success + *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to + *		contain the new property value + *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + *	-FDT_ERR_BADLAYOUT, + *	-FDT_ERR_BADMAGIC, + *	-FDT_ERR_BADVERSION, + *	-FDT_ERR_BADSTATE, + *	-FDT_ERR_BADSTRUCTURE, + *	-FDT_ERR_BADLAYOUT, + *	-FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, +				     const char *name, uint32_t val) +{ +	val = cpu_to_fdt32(val); +	return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val)); +} + +/** + * fdt_appendprop_u64 - append a 64-bit integer value to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value to append to the property (native endian) + * + * fdt_appendprop_u64() appends the given 64-bit integer value + * (converting to big-endian if necessary) to the value of the named + * property in the given node, or creates a new property with that + * value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + *	0, on success + *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to + *		contain the new property value + *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + *	-FDT_ERR_BADLAYOUT, + *	-FDT_ERR_BADMAGIC, + *	-FDT_ERR_BADVERSION, + *	-FDT_ERR_BADSTATE, + *	-FDT_ERR_BADSTRUCTURE, + *	-FDT_ERR_BADLAYOUT, + *	-FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, +				     const char *name, uint64_t val) +{ +	val = cpu_to_fdt64(val); +	return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val)); +} + +/** + * fdt_appendprop_cell - append a single cell value to a property + * + * This is an alternative name for fdt_appendprop_u32() + */ +static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, +				      const char *name, uint32_t val) +{ +	return fdt_appendprop_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_appendprop_string - append a string to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @str: string value to append to the property + * + * fdt_appendprop_string() appends the given string to the value of + * the named property in the given node, or creates a new property + * with that value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + *	0, on success + *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to + *		contain the new property value + *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + *	-FDT_ERR_BADLAYOUT, + *	-FDT_ERR_BADMAGIC, + *	-FDT_ERR_BADVERSION, + *	-FDT_ERR_BADSTATE, + *	-FDT_ERR_BADSTRUCTURE, + *	-FDT_ERR_BADLAYOUT, + *	-FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_appendprop_string(fdt, nodeoffset, name, str) \ +	fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) + +/**   * fdt_delprop - delete a property   * @fdt: pointer to the device tree blob   * @nodeoffset: offset of the node whose property to nop diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h index 449bf602daf..213d7fb81c4 100644 --- a/scripts/dtc/libfdt/libfdt_env.h +++ b/scripts/dtc/libfdt/libfdt_env.h @@ -5,19 +5,25 @@  #include <stdint.h>  #include <string.h> -#define _B(n)	((unsigned long long)((uint8_t *)&x)[n]) +#define EXTRACT_BYTE(n)	((unsigned long long)((uint8_t *)&x)[n]) +static inline uint16_t fdt16_to_cpu(uint16_t x) +{ +	return (EXTRACT_BYTE(0) << 8) | EXTRACT_BYTE(1); +} +#define cpu_to_fdt16(x) fdt16_to_cpu(x) +  static inline uint32_t fdt32_to_cpu(uint32_t x)  { -	return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3); +	return (EXTRACT_BYTE(0) << 24) | (EXTRACT_BYTE(1) << 16) | (EXTRACT_BYTE(2) << 8) | EXTRACT_BYTE(3);  }  #define cpu_to_fdt32(x) fdt32_to_cpu(x)  static inline uint64_t fdt64_to_cpu(uint64_t x)  { -	return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32) -		| (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7); +	return (EXTRACT_BYTE(0) << 56) | (EXTRACT_BYTE(1) << 48) | (EXTRACT_BYTE(2) << 40) | (EXTRACT_BYTE(3) << 32) +		| (EXTRACT_BYTE(4) << 24) | (EXTRACT_BYTE(5) << 16) | (EXTRACT_BYTE(6) << 8) | EXTRACT_BYTE(7);  }  #define cpu_to_fdt64(x) fdt64_to_cpu(x) -#undef _B +#undef EXTRACT_BYTE  #endif /* _LIBFDT_ENV_H */ diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h index 46eb93e4af5..381133ba81d 100644 --- a/scripts/dtc/libfdt/libfdt_internal.h +++ b/scripts/dtc/libfdt/libfdt_internal.h @@ -62,8 +62,8 @@  			return err; \  	} -uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);  int _fdt_check_node_offset(const void *fdt, int offset); +int _fdt_check_prop_offset(const void *fdt, int offset);  const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);  int _fdt_node_end_offset(void *fdt, int nodeoffset); diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c index 0ca3de550b3..b61465fb2f3 100644 --- a/scripts/dtc/livetree.c +++ b/scripts/dtc/livetree.c @@ -24,16 +24,52 @@   * Tree building functions   */ -struct property *build_property(char *name, struct data val, char *label) +void add_label(struct label **labels, char *label) +{ +	struct label *new; + +	/* Make sure the label isn't already there */ +	for_each_label_withdel(*labels, new) +		if (streq(new->label, label)) { +			new->deleted = 0; +			return; +		} + +	new = xmalloc(sizeof(*new)); +	memset(new, 0, sizeof(*new)); +	new->label = label; +	new->next = *labels; +	*labels = new; +} + +void delete_labels(struct label **labels) +{ +	struct label *label; + +	for_each_label(*labels, label) +		label->deleted = 1; +} + +struct property *build_property(char *name, struct data val)  {  	struct property *new = xmalloc(sizeof(*new)); +	memset(new, 0, sizeof(*new)); +  	new->name = name;  	new->val = val; -	new->next = NULL; +	return new; +} -	new->label = label; +struct property *build_property_delete(char *name) +{ +	struct property *new = xmalloc(sizeof(*new)); + +	memset(new, 0, sizeof(*new)); + +	new->name = name; +	new->deleted = 1;  	return new;  } @@ -78,17 +114,108 @@ struct node *build_node(struct property *proplist, struct node *children)  	return new;  } -struct node *name_node(struct node *node, char *name, char * label) +struct node *build_node_delete(void) +{ +	struct node *new = xmalloc(sizeof(*new)); + +	memset(new, 0, sizeof(*new)); + +	new->deleted = 1; + +	return new; +} + +struct node *name_node(struct node *node, char *name)  {  	assert(node->name == NULL);  	node->name = name; -	node->label = label; -  	return node;  } +struct node *merge_nodes(struct node *old_node, struct node *new_node) +{ +	struct property *new_prop, *old_prop; +	struct node *new_child, *old_child; +	struct label *l; + +	old_node->deleted = 0; + +	/* Add new node labels to old node */ +	for_each_label_withdel(new_node->labels, l) +		add_label(&old_node->labels, l->label); + +	/* Move properties from the new node to the old node.  If there +	 * is a collision, replace the old value with the new */ +	while (new_node->proplist) { +		/* Pop the property off the list */ +		new_prop = new_node->proplist; +		new_node->proplist = new_prop->next; +		new_prop->next = NULL; + +		if (new_prop->deleted) { +			delete_property_by_name(old_node, new_prop->name); +			free(new_prop); +			continue; +		} + +		/* Look for a collision, set new value if there is */ +		for_each_property_withdel(old_node, old_prop) { +			if (streq(old_prop->name, new_prop->name)) { +				/* Add new labels to old property */ +				for_each_label_withdel(new_prop->labels, l) +					add_label(&old_prop->labels, l->label); + +				old_prop->val = new_prop->val; +				old_prop->deleted = 0; +				free(new_prop); +				new_prop = NULL; +				break; +			} +		} + +		/* if no collision occurred, add property to the old node. */ +		if (new_prop) +			add_property(old_node, new_prop); +	} + +	/* Move the override child nodes into the primary node.  If +	 * there is a collision, then merge the nodes. */ +	while (new_node->children) { +		/* Pop the child node off the list */ +		new_child = new_node->children; +		new_node->children = new_child->next_sibling; +		new_child->parent = NULL; +		new_child->next_sibling = NULL; + +		if (new_child->deleted) { +			delete_node_by_name(old_node, new_child->name); +			free(new_child); +			continue; +		} + +		/* Search for a collision.  Merge if there is */ +		for_each_child_withdel(old_node, old_child) { +			if (streq(old_child->name, new_child->name)) { +				merge_nodes(old_child, new_child); +				new_child = NULL; +				break; +			} +		} + +		/* if no collision occured, add child to the old node. */ +		if (new_child) +			add_child(old_node, new_child); +	} + +	/* The new node contents are now merged into the old node.  Free +	 * the new node. */ +	free(new_node); + +	return old_node; +} +  struct node *chain_node(struct node *first, struct node *list)  {  	assert(first->next_sibling == NULL); @@ -110,6 +237,25 @@ void add_property(struct node *node, struct property *prop)  	*p = prop;  } +void delete_property_by_name(struct node *node, char *name) +{ +	struct property *prop = node->proplist; + +	while (prop) { +		if (!strcmp(prop->name, name)) { +			delete_property(prop); +			return; +		} +		prop = prop->next; +	} +} + +void delete_property(struct property *prop) +{ +	prop->deleted = 1; +	delete_labels(&prop->labels); +} +  void add_child(struct node *parent, struct node *child)  {  	struct node **p; @@ -124,18 +270,41 @@ void add_child(struct node *parent, struct node *child)  	*p = child;  } -struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size, -					 char *label) +void delete_node_by_name(struct node *parent, char *name) +{ +	struct node *node = parent->children; + +	while (node) { +		if (!strcmp(node->name, name)) { +			delete_node(node); +			return; +		} +		node = node->next_sibling; +	} +} + +void delete_node(struct node *node) +{ +	struct property *prop; +	struct node *child; + +	node->deleted = 1; +	for_each_child(node, child) +		delete_node(child); +	for_each_property(node, prop) +		delete_property(prop); +	delete_labels(&node->labels); +} + +struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)  {  	struct reserve_info *new = xmalloc(sizeof(*new)); +	memset(new, 0, sizeof(*new)); +  	new->re.address = address;  	new->re.size = size; -	new->next = NULL; - -	new->label = label; -  	return new;  } @@ -208,6 +377,60 @@ cell_t propval_cell(struct property *prop)  	return fdt32_to_cpu(*((cell_t *)prop->val.val));  } +struct property *get_property_by_label(struct node *tree, const char *label, +				       struct node **node) +{ +	struct property *prop; +	struct node *c; + +	*node = tree; + +	for_each_property(tree, prop) { +		struct label *l; + +		for_each_label(prop->labels, l) +			if (streq(l->label, label)) +				return prop; +	} + +	for_each_child(tree, c) { +		prop = get_property_by_label(c, label, node); +		if (prop) +			return prop; +	} + +	*node = NULL; +	return NULL; +} + +struct marker *get_marker_label(struct node *tree, const char *label, +				struct node **node, struct property **prop) +{ +	struct marker *m; +	struct property *p; +	struct node *c; + +	*node = tree; + +	for_each_property(tree, p) { +		*prop = p; +		m = p->val.markers; +		for_each_marker_of_type(m, LABEL) +			if (streq(m->ref, label)) +				return m; +	} + +	for_each_child(tree, c) { +		m = get_marker_label(c, label, node, prop); +		if (m) +			return m; +	} + +	*prop = NULL; +	*node = NULL; +	return NULL; +} +  struct node *get_subnode(struct node *node, const char *nodename)  {  	struct node *child; @@ -224,8 +447,11 @@ struct node *get_node_by_path(struct node *tree, const char *path)  	const char *p;  	struct node *child; -	if (!path || ! (*path)) +	if (!path || ! (*path)) { +		if (tree->deleted) +			return NULL;  		return tree; +	}  	while (path[0] == '/')  		path++; @@ -245,11 +471,13 @@ struct node *get_node_by_path(struct node *tree, const char *path)  struct node *get_node_by_label(struct node *tree, const char *label)  {  	struct node *child, *node; +	struct label *l;  	assert(label && (strlen(label) > 0)); -	if (tree->label && streq(tree->label, label)) -		return tree; +	for_each_label(tree->labels, l) +		if (streq(l->label, label)) +			return tree;  	for_each_child(tree, child) {  		node = get_node_by_label(child, label); @@ -266,8 +494,11 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)  	assert((phandle != 0) && (phandle != -1)); -	if (tree->phandle == phandle) +	if (tree->phandle == phandle) { +		if (tree->deleted) +			return NULL;  		return tree; +	}  	for_each_child(tree, child) {  		node = get_node_by_phandle(child, phandle); @@ -293,16 +524,186 @@ cell_t get_node_phandle(struct node *root, struct node *node)  	if ((node->phandle != 0) && (node->phandle != -1))  		return node->phandle; -	assert(! get_property(node, "linux,phandle")); -  	while (get_node_by_phandle(root, phandle))  		phandle++;  	node->phandle = phandle; -	add_property(node, -		     build_property("linux,phandle", -				    data_append_cell(empty_data, phandle), -				    NULL)); + +	if (!get_property(node, "linux,phandle") +	    && (phandle_format & PHANDLE_LEGACY)) +		add_property(node, +			     build_property("linux,phandle", +					    data_append_cell(empty_data, phandle))); + +	if (!get_property(node, "phandle") +	    && (phandle_format & PHANDLE_EPAPR)) +		add_property(node, +			     build_property("phandle", +					    data_append_cell(empty_data, phandle))); + +	/* If the node *does* have a phandle property, we must +	 * be dealing with a self-referencing phandle, which will be +	 * fixed up momentarily in the caller */  	return node->phandle;  } + +uint32_t guess_boot_cpuid(struct node *tree) +{ +	struct node *cpus, *bootcpu; +	struct property *reg; + +	cpus = get_node_by_path(tree, "/cpus"); +	if (!cpus) +		return 0; + + +	bootcpu = cpus->children; +	if (!bootcpu) +		return 0; + +	reg = get_property(bootcpu, "reg"); +	if (!reg || (reg->val.len != sizeof(uint32_t))) +		return 0; + +	/* FIXME: Sanity check node? */ + +	return propval_cell(reg); +} + +static int cmp_reserve_info(const void *ax, const void *bx) +{ +	const struct reserve_info *a, *b; + +	a = *((const struct reserve_info * const *)ax); +	b = *((const struct reserve_info * const *)bx); + +	if (a->re.address < b->re.address) +		return -1; +	else if (a->re.address > b->re.address) +		return 1; +	else if (a->re.size < b->re.size) +		return -1; +	else if (a->re.size > b->re.size) +		return 1; +	else +		return 0; +} + +static void sort_reserve_entries(struct boot_info *bi) +{ +	struct reserve_info *ri, **tbl; +	int n = 0, i = 0; + +	for (ri = bi->reservelist; +	     ri; +	     ri = ri->next) +		n++; + +	if (n == 0) +		return; + +	tbl = xmalloc(n * sizeof(*tbl)); + +	for (ri = bi->reservelist; +	     ri; +	     ri = ri->next) +		tbl[i++] = ri; + +	qsort(tbl, n, sizeof(*tbl), cmp_reserve_info); + +	bi->reservelist = tbl[0]; +	for (i = 0; i < (n-1); i++) +		tbl[i]->next = tbl[i+1]; +	tbl[n-1]->next = NULL; + +	free(tbl); +} + +static int cmp_prop(const void *ax, const void *bx) +{ +	const struct property *a, *b; + +	a = *((const struct property * const *)ax); +	b = *((const struct property * const *)bx); + +	return strcmp(a->name, b->name); +} + +static void sort_properties(struct node *node) +{ +	int n = 0, i = 0; +	struct property *prop, **tbl; + +	for_each_property_withdel(node, prop) +		n++; + +	if (n == 0) +		return; + +	tbl = xmalloc(n * sizeof(*tbl)); + +	for_each_property_withdel(node, prop) +		tbl[i++] = prop; + +	qsort(tbl, n, sizeof(*tbl), cmp_prop); + +	node->proplist = tbl[0]; +	for (i = 0; i < (n-1); i++) +		tbl[i]->next = tbl[i+1]; +	tbl[n-1]->next = NULL; + +	free(tbl); +} + +static int cmp_subnode(const void *ax, const void *bx) +{ +	const struct node *a, *b; + +	a = *((const struct node * const *)ax); +	b = *((const struct node * const *)bx); + +	return strcmp(a->name, b->name); +} + +static void sort_subnodes(struct node *node) +{ +	int n = 0, i = 0; +	struct node *subnode, **tbl; + +	for_each_child_withdel(node, subnode) +		n++; + +	if (n == 0) +		return; + +	tbl = xmalloc(n * sizeof(*tbl)); + +	for_each_child_withdel(node, subnode) +		tbl[i++] = subnode; + +	qsort(tbl, n, sizeof(*tbl), cmp_subnode); + +	node->children = tbl[0]; +	for (i = 0; i < (n-1); i++) +		tbl[i]->next_sibling = tbl[i+1]; +	tbl[n-1]->next_sibling = NULL; + +	free(tbl); +} + +static void sort_node(struct node *node) +{ +	struct node *c; + +	sort_properties(node); +	sort_subnodes(node); +	for_each_child_withdel(node, c) +		sort_node(c); +} + +void sort_tree(struct boot_info *bi) +{ +	sort_reserve_entries(bi); +	sort_node(bi->dt); +} diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c index 9641b7628b4..c20bc5315bc 100644 --- a/scripts/dtc/srcpos.c +++ b/scripts/dtc/srcpos.c @@ -17,100 +17,320 @@   *                                                                   USA   */ +#define _GNU_SOURCE + +#include <stdio.h> +  #include "dtc.h"  #include "srcpos.h" -/* - * Like yylineno, this is the current open file pos. +/* A node in our list of directories to search for source/include files */ +struct search_path { +	struct search_path *next;	/* next node in list, NULL for end */ +	const char *dirname;		/* name of directory to search */ +}; + +/* This is the list of directories that we search for source files */ +static struct search_path *search_path_head, **search_path_tail; + + +static char *dirname(const char *path) +{ +	const char *slash = strrchr(path, '/'); + +	if (slash) { +		int len = slash - path; +		char *dir = xmalloc(len + 1); + +		memcpy(dir, path, len); +		dir[len] = '\0'; +		return dir; +	} +	return NULL; +} + +FILE *depfile; /* = NULL */ +struct srcfile_state *current_srcfile; /* = NULL */ + +/* Detect infinite include recursion. */ +#define MAX_SRCFILE_DEPTH     (100) +static int srcfile_depth; /* = 0 */ + + +/** + * Try to open a file in a given directory. + * + * If the filename is an absolute path, then dirname is ignored. If it is a + * relative path, then we look in that directory for the file. + * + * @param dirname	Directory to look in, or NULL for none + * @param fname		Filename to look for + * @param fp		Set to NULL if file did not open + * @return allocated filename on success (caller must free), NULL on failure   */ +static char *try_open(const char *dirname, const char *fname, FILE **fp) +{ +	char *fullname; + +	if (!dirname || fname[0] == '/') +		fullname = xstrdup(fname); +	else +		fullname = join_path(dirname, fname); + +	*fp = fopen(fullname, "r"); +	if (!*fp) { +		free(fullname); +		fullname = NULL; +	} -struct dtc_file *srcpos_file; +	return fullname; +} -static int dtc_open_one(struct dtc_file *file, -                        const char *search, -                        const char *fname) +/** + * Open a file for read access + * + * If it is a relative filename, we search the full search path for it. + * + * @param fname	Filename to open + * @param fp	Returns pointer to opened FILE, or NULL on failure + * @return pointer to allocated filename, which caller must free + */ +static char *fopen_any_on_path(const char *fname, FILE **fp)  { +	const char *cur_dir = NULL; +	struct search_path *node;  	char *fullname; -	if (search) { -		fullname = xmalloc(strlen(search) + strlen(fname) + 2); +	/* Try current directory first */ +	assert(fp); +	if (current_srcfile) +		cur_dir = current_srcfile->dir; +	fullname = try_open(cur_dir, fname, fp); + +	/* Failing that, try each search path in turn */ +	for (node = search_path_head; !*fp && node; node = node->next) +		fullname = try_open(node->dirname, fname, fp); + +	return fullname; +} + +FILE *srcfile_relative_open(const char *fname, char **fullnamep) +{ +	FILE *f; +	char *fullname; -		strcpy(fullname, search); -		strcat(fullname, "/"); -		strcat(fullname, fname); +	if (streq(fname, "-")) { +		f = stdin; +		fullname = xstrdup("<stdin>");  	} else { -		fullname = strdup(fname); +		fullname = fopen_any_on_path(fname, &f); +		if (!f) +			die("Couldn't open \"%s\": %s\n", fname, +			    strerror(errno));  	} -	file->file = fopen(fullname, "r"); -	if (!file->file) { +	if (depfile) +		fprintf(depfile, " %s", fullname); + +	if (fullnamep) +		*fullnamep = fullname; +	else  		free(fullname); -		return 0; -	} -	file->name = fullname; -	return 1; +	return f;  } +void srcfile_push(const char *fname) +{ +	struct srcfile_state *srcfile; + +	if (srcfile_depth++ >= MAX_SRCFILE_DEPTH) +		die("Includes nested too deeply"); + +	srcfile = xmalloc(sizeof(*srcfile)); + +	srcfile->f = srcfile_relative_open(fname, &srcfile->name); +	srcfile->dir = dirname(srcfile->name); +	srcfile->prev = current_srcfile; + +	srcfile->lineno = 1; +	srcfile->colno = 1; -struct dtc_file *dtc_open_file(const char *fname, -                               const struct search_path *search) +	current_srcfile = srcfile; +} + +int srcfile_pop(void)  { -	static const struct search_path default_search = { NULL, NULL, NULL }; +	struct srcfile_state *srcfile = current_srcfile; -	struct dtc_file *file; -	const char *slash; +	assert(srcfile); -	file = xmalloc(sizeof(struct dtc_file)); +	current_srcfile = srcfile->prev; -	slash = strrchr(fname, '/'); -	if (slash) { -		char *dir = xmalloc(slash - fname + 1); +	if (fclose(srcfile->f)) +		die("Error closing \"%s\": %s\n", srcfile->name, +		    strerror(errno)); -		memcpy(dir, fname, slash - fname); -		dir[slash - fname] = 0; -		file->dir = dir; -	} else { -		file->dir = NULL; -	} +	/* FIXME: We allow the srcfile_state structure to leak, +	 * because it could still be referenced from a location +	 * variable being carried through the parser somewhere.  To +	 * fix this we could either allocate all the files from a +	 * table, or use a pool allocator. */ -	if (streq(fname, "-")) { -		file->name = "stdin"; -		file->file = stdin; -		return file; -	} +	return current_srcfile ? 1 : 0; +} + +void srcfile_add_search_path(const char *dirname) +{ +	struct search_path *node; -	if (fname[0] == '/') { -		file->file = fopen(fname, "r"); -		if (!file->file) -			goto fail; +	/* Create the node */ +	node = xmalloc(sizeof(*node)); +	node->next = NULL; +	node->dirname = xstrdup(dirname); -		file->name = strdup(fname); -		return file; -	} +	/* Add to the end of our list */ +	if (search_path_tail) +		*search_path_tail = node; +	else +		search_path_head = node; +	search_path_tail = &node->next; +} -	if (!search) -		search = &default_search; +/* + * The empty source position. + */ -	while (search) { -		if (dtc_open_one(file, search->dir, fname)) -			return file; +struct srcpos srcpos_empty = { +	.first_line = 0, +	.first_column = 0, +	.last_line = 0, +	.last_column = 0, +	.file = NULL, +}; -		if (errno != ENOENT) -			goto fail; +#define TAB_SIZE      8 -		search = search->next; -	} +void srcpos_update(struct srcpos *pos, const char *text, int len) +{ +	int i; + +	pos->file = current_srcfile; + +	pos->first_line = current_srcfile->lineno; +	pos->first_column = current_srcfile->colno; -fail: -	die("Couldn't open \"%s\": %s\n", fname, strerror(errno)); +	for (i = 0; i < len; i++) +		if (text[i] == '\n') { +			current_srcfile->lineno++; +			current_srcfile->colno = 1; +		} else if (text[i] == '\t') { +			current_srcfile->colno = +				ALIGN(current_srcfile->colno, TAB_SIZE); +		} else { +			current_srcfile->colno++; +		} + +	pos->last_line = current_srcfile->lineno; +	pos->last_column = current_srcfile->colno; +} + +struct srcpos * +srcpos_copy(struct srcpos *pos) +{ +	struct srcpos *pos_new; + +	pos_new = xmalloc(sizeof(struct srcpos)); +	memcpy(pos_new, pos, sizeof(struct srcpos)); + +	return pos_new;  } -void dtc_close_file(struct dtc_file *file) + + +void +srcpos_dump(struct srcpos *pos) +{ +	printf("file        : \"%s\"\n", +	       pos->file ? (char *) pos->file : "<no file>"); +	printf("first_line  : %d\n", pos->first_line); +	printf("first_column: %d\n", pos->first_column); +	printf("last_line   : %d\n", pos->last_line); +	printf("last_column : %d\n", pos->last_column); +	printf("file        : %s\n", pos->file->name); +} + + +char * +srcpos_string(struct srcpos *pos)  { -	if (fclose(file->file)) -		die("Error closing \"%s\": %s\n", file->name, strerror(errno)); +	const char *fname = "<no-file>"; +	char *pos_str; +	int rc; -	free(file->dir); -	free(file); +	if (pos) +		fname = pos->file->name; + + +	if (pos->first_line != pos->last_line) +		rc = asprintf(&pos_str, "%s:%d.%d-%d.%d", fname, +			      pos->first_line, pos->first_column, +			      pos->last_line, pos->last_column); +	else if (pos->first_column != pos->last_column) +		rc = asprintf(&pos_str, "%s:%d.%d-%d", fname, +			      pos->first_line, pos->first_column, +			      pos->last_column); +	else +		rc = asprintf(&pos_str, "%s:%d.%d", fname, +			      pos->first_line, pos->first_column); + +	if (rc == -1) +		die("Couldn't allocate in srcpos string"); + +	return pos_str; +} + +void +srcpos_verror(struct srcpos *pos, char const *fmt, va_list va) +{ +       const char *srcstr; + +       srcstr = srcpos_string(pos); + +       fprintf(stderr, "Error: %s ", srcstr); +       vfprintf(stderr, fmt, va); +       fprintf(stderr, "\n"); +} + +void +srcpos_error(struct srcpos *pos, char const *fmt, ...) +{ +	va_list va; + +	va_start(va, fmt); +	srcpos_verror(pos, fmt, va); +	va_end(va); +} + + +void +srcpos_warn(struct srcpos *pos, char const *fmt, ...) +{ +	const char *srcstr; +	va_list va; +	va_start(va, fmt); + +	srcstr = srcpos_string(pos); + +	fprintf(stderr, "Warning: %s ", srcstr); +	vfprintf(stderr, fmt, va); +	fprintf(stderr, "\n"); + +	va_end(va); +} + +void srcpos_set_line(char *f, int l) +{ +	current_srcfile->name = f; +	current_srcfile->lineno = l;  } diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h index e17c7c04db8..93a27123c2e 100644 --- a/scripts/dtc/srcpos.h +++ b/scripts/dtc/srcpos.h @@ -17,69 +17,102 @@   *                                                                   USA   */ -/* - * Augment the standard YYLTYPE with a filenum index into an - * array of all opened filenames. - */ +#ifndef _SRCPOS_H_ +#define _SRCPOS_H_  #include <stdio.h> -struct dtc_file { +struct srcfile_state { +	FILE *f; +	char *name;  	char *dir; -	const char *name; -	FILE *file; +	int lineno, colno; +	struct srcfile_state *prev;  }; -#if ! defined(YYLTYPE) && ! defined(YYLTYPE_IS_DECLARED) -typedef struct YYLTYPE { +extern FILE *depfile; /* = NULL */ +extern struct srcfile_state *current_srcfile; /* = NULL */ + +/** + * Open a source file. + * + * If the source file is a relative pathname, then it is searched for in the + * current directory (the directory of the last source file read) and after + * that in the search path. + * + * We work through the search path in order from the first path specified to + * the last. + * + * If the file is not found, then this function does not return, but calls + * die(). + * + * @param fname		Filename to search + * @param fullnamep	If non-NULL, it is set to the allocated filename of the + *			file that was opened. The caller is then responsible + *			for freeing the pointer. + * @return pointer to opened FILE + */ +FILE *srcfile_relative_open(const char *fname, char **fullnamep); + +void srcfile_push(const char *fname); +int srcfile_pop(void); + +/** + * Add a new directory to the search path for input files + * + * The new path is added at the end of the list. + * + * @param dirname	Directory to add + */ +void srcfile_add_search_path(const char *dirname); + +struct srcpos {      int first_line;      int first_column;      int last_line;      int last_column; -    struct dtc_file *file; -} YYLTYPE; - -#define YYLTYPE_IS_DECLARED	1 -#define YYLTYPE_IS_TRIVIAL	1 -#endif - -/* Cater to old parser templates. */ -#ifndef YYID -#define YYID(n)	(n) -#endif - -#define YYLLOC_DEFAULT(Current, Rhs, N)					\ -    do									\ -      if (YYID (N))							\ -	{								\ -	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\ -	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\ -	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\ -	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\ -	  (Current).file         = YYRHSLOC (Rhs, N).file;		\ -	}								\ -      else								\ -	{								\ -	  (Current).first_line   = (Current).last_line   =		\ -	    YYRHSLOC (Rhs, 0).last_line;				\ -	  (Current).first_column = (Current).last_column =		\ -	    YYRHSLOC (Rhs, 0).last_column;				\ -	  (Current).file         = YYRHSLOC (Rhs, 0).file;		\ -	}								\ -    while (YYID (0)) - - - -extern void yyerror(char const *); -extern void yyerrorf(char const *, ...) __attribute__((format(printf, 1, 2))); - -extern struct dtc_file *srcpos_file; - -struct search_path { -	const char *dir; /* NULL for current directory */ -	struct search_path *prev, *next; +    struct srcfile_state *file;  }; -extern struct dtc_file *dtc_open_file(const char *fname, -                                      const struct search_path *search); -extern void dtc_close_file(struct dtc_file *file); +#define YYLTYPE struct srcpos + +#define YYLLOC_DEFAULT(Current, Rhs, N)						\ +	do {									\ +		if (N) {							\ +			(Current).first_line = YYRHSLOC(Rhs, 1).first_line;	\ +			(Current).first_column = YYRHSLOC(Rhs, 1).first_column;	\ +			(Current).last_line = YYRHSLOC(Rhs, N).last_line;	\ +			(Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\ +			(Current).file = YYRHSLOC(Rhs, N).file;			\ +		} else {							\ +			(Current).first_line = (Current).last_line =		\ +				YYRHSLOC(Rhs, 0).last_line;			\ +			(Current).first_column = (Current).last_column =	\ +				YYRHSLOC(Rhs, 0).last_column;			\ +			(Current).file = YYRHSLOC (Rhs, 0).file;		\ +		}								\ +	} 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 char *srcpos_string(struct srcpos *pos); +extern void srcpos_dump(struct srcpos *pos); + +extern void srcpos_verror(struct srcpos *pos, char const *, va_list va) +     __attribute__((format(printf, 2, 0))); +extern void srcpos_error(struct srcpos *pos, char const *, ...) +     __attribute__((format(printf, 2, 3))); +extern void srcpos_warn(struct srcpos *pos, char const *, ...) +     __attribute__((format(printf, 2, 3))); + +extern void srcpos_set_line(char *f, int l); + +#endif /* _SRCPOS_H_ */ diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c index 1521ff11bb9..5740e6992d3 100644 --- a/scripts/dtc/treesource.c +++ b/scripts/dtc/treesource.c @@ -23,6 +23,7 @@  extern FILE *yyin;  extern int yyparse(void); +extern YYLTYPE yylloc;  struct boot_info *the_boot_info;  int treesource_error; @@ -32,8 +33,9 @@ struct boot_info *dt_from_source(const char *fname)  	the_boot_info = NULL;  	treesource_error = 0; -	srcpos_file = dtc_open_file(fname, NULL); -	yyin = srcpos_file->file; +	srcfile_push(fname); +	yyin = current_srcfile->f; +	yylloc.file = current_srcfile;  	if (yyparse() != 0)  		die("Unable to parse input tree\n"); @@ -63,26 +65,20 @@ static void write_propval_string(FILE *f, struct data val)  {  	const char *str = val.val;  	int i; -	int newchunk = 1;  	struct marker *m = val.markers;  	assert(str[val.len-1] == '\0'); +	while (m && (m->offset == 0)) { +		if (m->type == LABEL) +			fprintf(f, "%s: ", m->ref); +		m = m->next; +	} +	fprintf(f, "\""); +  	for (i = 0; i < (val.len-1); i++) {  		char c = str[i]; -		if (newchunk) { -			while (m && (m->offset <= i)) { -				if (m->type == LABEL) { -					assert(m->offset == i); -					fprintf(f, "%s: ", m->ref); -				} -				m = m->next; -			} -			fprintf(f, "\""); -			newchunk = 0; -		} -  		switch (c) {  		case '\a':  			fprintf(f, "\\a"); @@ -113,7 +109,14 @@ static void write_propval_string(FILE *f, struct data val)  			break;  		case '\0':  			fprintf(f, "\", "); -			newchunk = 1; +			while (m && (m->offset < i)) { +				if (m->type == LABEL) { +					assert(m->offset == (i+1)); +					fprintf(f, "%s: ", m->ref); +				} +				m = m->next; +			} +			fprintf(f, "\"");  			break;  		default:  			if (isprint(c)) @@ -234,10 +237,11 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level)  {  	struct property *prop;  	struct node *child; +	struct label *l;  	write_prefix(f, level); -	if (tree->label) -		fprintf(f, "%s: ", tree->label); +	for_each_label(tree->labels, l) +		fprintf(f, "%s: ", l->label);  	if (tree->name && (*tree->name))  		fprintf(f, "%s {\n", tree->name);  	else @@ -245,8 +249,8 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level)  	for_each_property(tree, prop) {  		write_prefix(f, level+1); -		if (prop->label) -			fprintf(f, "%s: ", prop->label); +		for_each_label(prop->labels, l) +			fprintf(f, "%s: ", l->label);  		fprintf(f, "%s", prop->name);  		write_propval(f, prop);  	} @@ -266,8 +270,10 @@ void dt_to_source(FILE *f, struct boot_info *bi)  	fprintf(f, "/dts-v1/;\n\n");  	for (re = bi->reservelist; re; re = re->next) { -		if (re->label) -			fprintf(f, "%s: ", re->label); +		struct label *l; + +		for_each_label(re->labels, l) +			fprintf(f, "%s: ", l->label);  		fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",  			(unsigned long long)re->re.address,  			(unsigned long long)re->re.size); @@ -275,4 +281,3 @@ void dt_to_source(FILE *f, struct boot_info *bi)  	write_tree_source_node(f, bi->dt, 0);  } - diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh new file mode 100755 index 00000000000..feb01ef26be --- /dev/null +++ b/scripts/dtc/update-dtc-source.sh @@ -0,0 +1,54 @@ +#!/bin/sh +# Simple script to update the version of DTC carried by the Linux kernel +# +# This script assumes that the dtc and the linux git trees are in the +# same directory. After building dtc in the dtc directory, it copies the +# source files and generated source files into the scripts/dtc directory +# in the kernel and creates a git commit updating them to the new +# version. +# +# Usage: from the top level Linux source tree, run: +# $ ./scripts/dtc/update-dtc-source.sh +# +# The script will change into the dtc tree, build and test dtc, copy the +# relevant files into the kernel tree and create a git commit. The commit +# message will need to be modified to reflect the version of DTC being +# imported +# +# TODO: +# This script is pretty basic, but it is seldom used so a few manual tasks +# aren't a big deal. If anyone is interested in making it more robust, the +# the following would be nice: +# * Actually fail to complete if any testcase fails. +#   - The dtc "make check" target needs to return a failure +# * Extract the version number from the dtc repo for the commit message +# * Build dtc in the kernel tree +# * run 'make check" on dtc built from the kernel tree + +set -ev + +DTC_UPSTREAM_PATH=`pwd`/../dtc +DTC_LINUX_PATH=`pwd`/scripts/dtc + +DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c \ +		srcpos.h treesource.c util.c util.h version_gen.h Makefile.dtc \ +		dtc-lexer.l dtc-parser.y" +DTC_GENERATED="dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h" + +# Build DTC +cd $DTC_UPSTREAM_PATH +make clean +make check + +# Copy the files into the Linux tree +cd $DTC_LINUX_PATH +for f in $DTC_SOURCE; do +	cp ${DTC_UPSTREAM_PATH}/${f} ${f} +	git add ${f} +done +for f in $DTC_GENERATED; do +	cp ${DTC_UPSTREAM_PATH}/$f ${f}_shipped +	git add ${f}_shipped +done + +git commit -e -v -m "scripts/dtc: Update to upstream version [CHANGEME]" diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c new file mode 100644 index 00000000000..3055c16e980 --- /dev/null +++ b/scripts/dtc/util.c @@ -0,0 +1,448 @@ +/* + * Copyright 2011 The Chromium Authors, All Rights Reserved. + * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. + * + * util_is_printable_string contributed by + *	Pantelis Antoniou <pantelis.antoniou AT gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + *  General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 + *                                                                   USA + */ + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <assert.h> + +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + +#include "libfdt.h" +#include "util.h" +#include "version_gen.h" + +char *xstrdup(const char *s) +{ +	int len = strlen(s) + 1; +	char *dup = xmalloc(len); + +	memcpy(dup, s, len); + +	return dup; +} + +char *join_path(const char *path, const char *name) +{ +	int lenp = strlen(path); +	int lenn = strlen(name); +	int len; +	int needslash = 1; +	char *str; + +	len = lenp + lenn + 2; +	if ((lenp > 0) && (path[lenp-1] == '/')) { +		needslash = 0; +		len--; +	} + +	str = xmalloc(len); +	memcpy(str, path, lenp); +	if (needslash) { +		str[lenp] = '/'; +		lenp++; +	} +	memcpy(str+lenp, name, lenn+1); +	return str; +} + +int util_is_printable_string(const void *data, int len) +{ +	const char *s = data; +	const char *ss, *se; + +	/* zero length is not */ +	if (len == 0) +		return 0; + +	/* must terminate with zero */ +	if (s[len - 1] != '\0') +		return 0; + +	se = s + len; + +	while (s < se) { +		ss = s; +		while (s < se && *s && isprint(*s)) +			s++; + +		/* not zero, or not done yet */ +		if (*s != '\0' || s == ss) +			return 0; + +		s++; +	} + +	return 1; +} + +/* + * Parse a octal encoded character starting at index i in string s.  The + * resulting character will be returned and the index i will be updated to + * point at the character directly after the end of the encoding, this may be + * the '\0' terminator of the string. + */ +static char get_oct_char(const char *s, int *i) +{ +	char x[4]; +	char *endx; +	long val; + +	x[3] = '\0'; +	strncpy(x, s + *i, 3); + +	val = strtol(x, &endx, 8); + +	assert(endx > x); + +	(*i) += endx - x; +	return val; +} + +/* + * Parse a hexadecimal encoded character starting at index i in string s.  The + * resulting character will be returned and the index i will be updated to + * point at the character directly after the end of the encoding, this may be + * the '\0' terminator of the string. + */ +static char get_hex_char(const char *s, int *i) +{ +	char x[3]; +	char *endx; +	long val; + +	x[2] = '\0'; +	strncpy(x, s + *i, 2); + +	val = strtol(x, &endx, 16); +	if (!(endx  > x)) +		die("\\x used with no following hex digits\n"); + +	(*i) += endx - x; +	return val; +} + +char get_escape_char(const char *s, int *i) +{ +	char	c = s[*i]; +	int	j = *i + 1; +	char	val; + +	assert(c); +	switch (c) { +	case 'a': +		val = '\a'; +		break; +	case 'b': +		val = '\b'; +		break; +	case 't': +		val = '\t'; +		break; +	case 'n': +		val = '\n'; +		break; +	case 'v': +		val = '\v'; +		break; +	case 'f': +		val = '\f'; +		break; +	case 'r': +		val = '\r'; +		break; +	case '0': +	case '1': +	case '2': +	case '3': +	case '4': +	case '5': +	case '6': +	case '7': +		j--; /* need to re-read the first digit as +		      * part of the octal value */ +		val = get_oct_char(s, &j); +		break; +	case 'x': +		val = get_hex_char(s, &j); +		break; +	default: +		val = c; +	} + +	(*i) = j; +	return val; +} + +int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len) +{ +	int fd = 0;	/* assume stdin */ +	char *buf = NULL; +	off_t bufsize = 1024, offset = 0; +	int ret = 0; + +	*buffp = NULL; +	if (strcmp(filename, "-") != 0) { +		fd = open(filename, O_RDONLY); +		if (fd < 0) +			return errno; +	} + +	/* Loop until we have read everything */ +	buf = xmalloc(bufsize); +	do { +		/* Expand the buffer to hold the next chunk */ +		if (offset == bufsize) { +			bufsize *= 2; +			buf = xrealloc(buf, bufsize); +			if (!buf) { +				ret = ENOMEM; +				break; +			} +		} + +		ret = read(fd, &buf[offset], bufsize - offset); +		if (ret < 0) { +			ret = errno; +			break; +		} +		offset += ret; +	} while (ret != 0); + +	/* Clean up, including closing stdin; return errno on error */ +	close(fd); +	if (ret) +		free(buf); +	else +		*buffp = buf; +	*len = bufsize; +	return ret; +} + +int utilfdt_read_err(const char *filename, char **buffp) +{ +	off_t len; +	return utilfdt_read_err_len(filename, buffp, &len); +} + +char *utilfdt_read_len(const char *filename, off_t *len) +{ +	char *buff; +	int ret = utilfdt_read_err_len(filename, &buff, len); + +	if (ret) { +		fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, +			strerror(ret)); +		return NULL; +	} +	/* Successful read */ +	return buff; +} + +char *utilfdt_read(const char *filename) +{ +	off_t len; +	return utilfdt_read_len(filename, &len); +} + +int utilfdt_write_err(const char *filename, const void *blob) +{ +	int fd = 1;	/* assume stdout */ +	int totalsize; +	int offset; +	int ret = 0; +	const char *ptr = blob; + +	if (strcmp(filename, "-") != 0) { +		fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); +		if (fd < 0) +			return errno; +	} + +	totalsize = fdt_totalsize(blob); +	offset = 0; + +	while (offset < totalsize) { +		ret = write(fd, ptr + offset, totalsize - offset); +		if (ret < 0) { +			ret = -errno; +			break; +		} +		offset += ret; +	} +	/* Close the file/stdin; return errno on error */ +	if (fd != 1) +		close(fd); +	return ret < 0 ? -ret : 0; +} + + +int utilfdt_write(const char *filename, const void *blob) +{ +	int ret = utilfdt_write_err(filename, blob); + +	if (ret) { +		fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename, +			strerror(ret)); +	} +	return ret ? -1 : 0; +} + +int utilfdt_decode_type(const char *fmt, int *type, int *size) +{ +	int qualifier = 0; + +	if (!*fmt) +		return -1; + +	/* get the conversion qualifier */ +	*size = -1; +	if (strchr("hlLb", *fmt)) { +		qualifier = *fmt++; +		if (qualifier == *fmt) { +			switch (*fmt++) { +/* TODO:		case 'l': qualifier = 'L'; break;*/ +			case 'h': +				qualifier = 'b'; +				break; +			} +		} +	} + +	/* we should now have a type */ +	if ((*fmt == '\0') || !strchr("iuxs", *fmt)) +		return -1; + +	/* convert qualifier (bhL) to byte size */ +	if (*fmt != 's') +		*size = qualifier == 'b' ? 1 : +				qualifier == 'h' ? 2 : +				qualifier == 'l' ? 4 : -1; +	*type = *fmt++; + +	/* that should be it! */ +	if (*fmt) +		return -1; +	return 0; +} + +void utilfdt_print_data(const char *data, int len) +{ +	int i; +	const char *p = data; +	const char *s; + +	/* no data, don't print */ +	if (len == 0) +		return; + +	if (util_is_printable_string(data, len)) { +		printf(" = "); + +		s = data; +		do { +			printf("\"%s\"", s); +			s += strlen(s) + 1; +			if (s < data + len) +				printf(", "); +		} while (s < data + len); + +	} else if ((len % 4) == 0) { +		const uint32_t *cell = (const uint32_t *)data; + +		printf(" = <"); +		for (i = 0; i < len; i += 4) +			printf("0x%08x%s", fdt32_to_cpu(cell[i]), +			       i < (len - 4) ? " " : ""); +		printf(">"); +	} else { +		printf(" = ["); +		for (i = 0; i < len; i++) +			printf("%02x%s", *p++, i < len - 1 ? " " : ""); +		printf("]"); +	} +} + +void util_version(void) +{ +	printf("Version: %s\n", DTC_VERSION); +	exit(0); +} + +void util_usage(const char *errmsg, const char *synopsis, +		const char *short_opts, struct option const long_opts[], +		const char * const opts_help[]) +{ +	FILE *fp = errmsg ? stderr : stdout; +	const char a_arg[] = "<arg>"; +	size_t a_arg_len = strlen(a_arg) + 1; +	size_t i; +	int optlen; + +	fprintf(fp, +		"Usage: %s\n" +		"\n" +		"Options: -[%s]\n", synopsis, short_opts); + +	/* prescan the --long opt length to auto-align */ +	optlen = 0; +	for (i = 0; long_opts[i].name; ++i) { +		/* +1 is for space between --opt and help text */ +		int l = strlen(long_opts[i].name) + 1; +		if (long_opts[i].has_arg == a_argument) +			l += a_arg_len; +		if (optlen < l) +			optlen = l; +	} + +	for (i = 0; long_opts[i].name; ++i) { +		/* helps when adding new applets or options */ +		assert(opts_help[i] != NULL); + +		/* first output the short flag if it has one */ +		if (long_opts[i].val > '~') +			fprintf(fp, "      "); +		else +			fprintf(fp, "  -%c, ", long_opts[i].val); + +		/* then the long flag */ +		if (long_opts[i].has_arg == no_argument) +			fprintf(fp, "--%-*s", optlen, long_opts[i].name); +		else +			fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg, +				(int)(optlen - strlen(long_opts[i].name) - a_arg_len), ""); + +		/* finally the help text */ +		fprintf(fp, "%s\n", opts_help[i]); +	} + +	if (errmsg) { +		fprintf(fp, "\nError: %s\n", errmsg); +		exit(EXIT_FAILURE); +	} else +		exit(EXIT_SUCCESS); +} diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h new file mode 100644 index 00000000000..8f40b449935 --- /dev/null +++ b/scripts/dtc/util.h @@ -0,0 +1,250 @@ +#ifndef _UTIL_H +#define _UTIL_H + +#include <stdarg.h> +#include <getopt.h> + +/* + * Copyright 2011 The Chromium Authors, All Rights Reserved. + * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + *  General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 + *                                                                   USA + */ + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +static inline void __attribute__((noreturn)) die(const char *str, ...) +{ +	va_list ap; + +	va_start(ap, str); +	fprintf(stderr, "FATAL ERROR: "); +	vfprintf(stderr, str, ap); +	exit(1); +} + +static inline void *xmalloc(size_t len) +{ +	void *new = malloc(len); + +	if (!new) +		die("malloc() failed\n"); + +	return new; +} + +static inline void *xrealloc(void *p, size_t len) +{ +	void *new = realloc(p, len); + +	if (!new) +		die("realloc() failed (len=%d)\n", len); + +	return new; +} + +extern char *xstrdup(const char *s); +extern char *join_path(const char *path, const char *name); + +/** + * Check a property of a given length to see if it is all printable and + * has a valid terminator. The property can contain either a single string, + * or multiple strings each of non-zero length. + * + * @param data	The string to check + * @param len	The string length including terminator + * @return 1 if a valid printable string, 0 if not + */ +int util_is_printable_string(const void *data, int len); + +/* + * Parse an escaped character starting at index i in string s.  The resulting + * character will be returned and the index i will be updated to point at the + * character directly after the end of the encoding, this may be the '\0' + * terminator of the string. + */ +char get_escape_char(const char *s, int *i); + +/** + * Read a device tree file into a buffer. This will report any errors on + * stderr. + * + * @param filename	The filename to read, or - for stdin + * @return Pointer to allocated buffer containing fdt, or NULL on error + */ +char *utilfdt_read(const char *filename); + +/** + * Like utilfdt_read(), but also passes back the size of the file read. + * + * @param len		If non-NULL, the amount of data we managed to read + */ +char *utilfdt_read_len(const char *filename, off_t *len); + +/** + * Read a device tree file into a buffer. Does not report errors, but only + * returns them. The value returned can be passed to strerror() to obtain + * an error message for the user. + * + * @param filename	The filename to read, or - for stdin + * @param buffp		Returns pointer to buffer containing fdt + * @return 0 if ok, else an errno value representing the error + */ +int utilfdt_read_err(const char *filename, char **buffp); + +/** + * Like utilfdt_read_err(), but also passes back the size of the file read. + * + * @param len		If non-NULL, the amount of data we managed to read + */ +int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len); + +/** + * Write a device tree buffer to a file. This will report any errors on + * stderr. + * + * @param filename	The filename to write, or - for stdout + * @param blob		Poiner to buffer containing fdt + * @return 0 if ok, -1 on error + */ +int utilfdt_write(const char *filename, const void *blob); + +/** + * Write a device tree buffer to a file. Does not report errors, but only + * returns them. The value returned can be passed to strerror() to obtain + * an error message for the user. + * + * @param filename	The filename to write, or - for stdout + * @param blob		Poiner to buffer containing fdt + * @return 0 if ok, else an errno value representing the error + */ +int utilfdt_write_err(const char *filename, const void *blob); + +/** + * Decode a data type string. The purpose of this string + * + * The string consists of an optional character followed by the type: + *	Modifier characters: + *		hh or b	1 byte + *		h	2 byte + *		l	4 byte, default + * + *	Type character: + *		s	string + *		i	signed integer + *		u	unsigned integer + *		x	hex + * + * TODO: Implement ll modifier (8 bytes) + * TODO: Implement o type (octal) + * + * @param fmt		Format string to process + * @param type		Returns type found(s/d/u/x), or 0 if none + * @param size		Returns size found(1,2,4,8) or 4 if none + * @return 0 if ok, -1 on error (no type given, or other invalid format) + */ +int utilfdt_decode_type(const char *fmt, int *type, int *size); + +/* + * This is a usage message fragment for the -t option. It is the format + * supported by utilfdt_decode_type. + */ + +#define USAGE_TYPE_MSG \ +	"<type>\ts=string, i=int, u=unsigned, x=hex\n" \ +	"\tOptional modifier prefix:\n" \ +	"\t\thh or b=byte, h=2 byte, l=4 byte (default)"; + +/** + * Print property data in a readable format to stdout + * + * Properties that look like strings will be printed as strings. Otherwise + * the data will be displayed either as cells (if len is a multiple of 4 + * bytes) or bytes. + * + * If len is 0 then this function does nothing. + * + * @param data	Pointers to property data + * @param len	Length of property data + */ +void utilfdt_print_data(const char *data, int len); + +/** + * Show source version and exit + */ +void util_version(void) __attribute__((noreturn)); + +/** + * Show usage and exit + * + * This helps standardize the output of various utils.  You most likely want + * to use the usage() helper below rather than call this. + * + * @param errmsg	If non-NULL, an error message to display + * @param synopsis	The initial example usage text (and possible examples) + * @param short_opts	The string of short options + * @param long_opts	The structure of long options + * @param opts_help	An array of help strings (should align with long_opts) + */ +void util_usage(const char *errmsg, const char *synopsis, +		const char *short_opts, struct option const long_opts[], +		const char * const opts_help[]) __attribute__((noreturn)); + +/** + * Show usage and exit + * + * If you name all your usage variables with usage_xxx, then you can call this + * help macro rather than expanding all arguments yourself. + * + * @param errmsg	If non-NULL, an error message to display + */ +#define usage(errmsg) \ +	util_usage(errmsg, usage_synopsis, usage_short_opts, \ +		   usage_long_opts, usage_opts_help) + +/** + * Call getopt_long() with standard options + * + * Since all util code runs getopt in the same way, provide a helper. + */ +#define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \ +				       usage_long_opts, NULL) + +/* Helper for aligning long_opts array */ +#define a_argument required_argument + +/* Helper for usage_short_opts string constant */ +#define USAGE_COMMON_SHORT_OPTS "hV" + +/* Helper for usage_long_opts option array */ +#define USAGE_COMMON_LONG_OPTS \ +	{"help",      no_argument, NULL, 'h'}, \ +	{"version",   no_argument, NULL, 'V'}, \ +	{NULL,        no_argument, NULL, 0x0} + +/* Helper for usage_opts_help array */ +#define USAGE_COMMON_OPTS_HELP \ +	"Print this help and exit", \ +	"Print version and exit", \ +	NULL + +/* Helper for getopt case statements */ +#define case_USAGE_COMMON_FLAGS \ +	case 'h': usage(NULL); \ +	case 'V': util_version(); \ +	case '?': usage("unknown option"); + +#endif /* _UTIL_H */ diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index 658ff42429d..54d4e904433 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.2.0" +#define DTC_VERSION "DTC 1.4.0-dirty"  | 
