[PATCH 7/9 V3] Introduce new DTS language.

Jon Loeliger jdl at jdl.com
Sat Sep 27 06:25:46 EST 2008


Introduce function defs and statements.
Added support for expressions.
Added if, for, assign and return statements.
Added support for BUILTIN functions.
Added support for /const/ definitions.
Added support for command line defines, eg: -D x=1
Unified /memreserve/ into declaration list.
Add lexical support for column source position information.
    Notably, this involved identifying all the newline
    characters to reset the column count.  Had to rewrite
    the C comment rules, and break \n out of the {WS} set.
Prevent lone +, -, and ? chars from being property names.
Add lexical source positions to all IR nodes.
Change error reporting to use IR source positions.

Passes test suite.

Signed-off-by: Jon Loeliger <jdl at freescale.com>
---
 Makefile     |    2 +-
 Makefile.dtc |   18 ++-
 dtc-lexer.l  |  271 ++++++++++++++++++----
 dtc-parser.y |  711 ++++++++++++++++++++++++++++++++++++++++++++++------------
 dtc.c        |    7 +-
 dtc.h        |    1 +
 ir.h         |    1 -
 ir_dump.c    |    9 -
 ir_emit.c    |   67 +++---
 ir_eval.c    |    2 -
 ir_scope.c   |    3 +-
 livetree.c   |   16 ++
 nv.c         |  108 +++++++++
 nv.h         |   34 +++
 srcpos.c     |   75 +++++--
 srcpos.h     |   10 +-
 treesource.c |    3 +
 17 files changed, 1068 insertions(+), 270 deletions(-)
 create mode 100644 nv.c
 create mode 100644 nv.h

diff --git a/Makefile b/Makefile
index 5ad0189..1ae5577 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ CONFIG_LOCALVERSION =
 CPPFLAGS = -I libfdt
 CFLAGS = -Wall -g -Os -Wpointer-arith -Wcast-qual
 
-BISON = bison
+BISON = bison -v
 LEX = flex
 
 INSTALL = /usr/bin/install
diff --git a/Makefile.dtc b/Makefile.dtc
index 6ddf9ec..dd53276 100644
--- a/Makefile.dtc
+++ b/Makefile.dtc
@@ -3,7 +3,21 @@
 # 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 \
+	ir.c \
+	ir_builtin.c \
+	ir_dump.c \
+	ir_emit.c \
+	ir_eval.c \
+	ir_scope.c \
+	livetree.c \
+	nv.c \
+	srcpos.c \
+	treesource.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/dtc-lexer.l b/dtc-lexer.l
index 6b862d2..d4efdef 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -18,19 +18,20 @@
  *                                                                   USA
  */
 
-%option noyywrap nounput noinput yylineno
+%option noyywrap nounput noinput yylineno stack
 
-%x INCLUDE
 %x BYTESTRING
 %x PROPNODENAME
+%x COMMENT
 %s V1
 
+NOTPROPNAMES	[+?-]
 PROPNODECHAR	[a-zA-Z0-9,._+*#?@-]
 PATHCHAR	({PROPNODECHAR}|[/])
 LABEL		[a-zA-Z_][a-zA-Z0-9_]*
+ID		\\[a-zA-Z_][a-zA-Z0-9_]*
 STRING		\"([^\\"]|\\.)*\"
-WS		[[:space:]]
-COMMENT		"/*"([^*]|\*+[^*/])*\*+"/"
+WS		[[:blank:]]
 LINECOMMENT	"//".*\n
 
 %{
@@ -49,6 +50,22 @@ LINECOMMENT	"//".*\n
 
 static int dts_version = 1;
 
+/*
+ * Track column positions too.  Brute force.
+ */
+int yycolno = 1;
+
+#define SET_SRCPOS(yylloc)	do { \
+					yylloc.file = srcpos_file; \
+					yylloc.first_line = yylineno; \
+					yylloc.last_line = yylineno; \
+					yylloc.first_column = yycolno; \
+					yycolno += yyleng; \
+					yylloc.last_column = yycolno - 1; \
+					DPRINT("Set srcpos: %s\n", \
+						srcpos_string(&yylloc)); \
+				} while (0)
+
 #define BEGIN_DEFAULT()		DPRINT("<V1>\n"); \
 				BEGIN(V1); \
 
@@ -59,29 +76,27 @@ static int pop_input_file(void);
 %%
 <*>"/include/"{WS}*{STRING} {
 			char *name = strchr(yytext, '\"') + 1;
+			SET_SRCPOS(yylloc);
 			yytext[yyleng-1] = '\0';
 			push_input_file(name);
 		}
 
-<*><<EOF>>		{
+<*><<EOF>>	{
 			if (!pop_input_file()) {
 				yyterminate();
 			}
 		}
 
 <*>{STRING}	{
-			yylloc.file = srcpos_file;
-			yylloc.first_line = yylineno;
+			SET_SRCPOS(yylloc);
 			DPRINT("String: %s\n", yytext);
-			yylval.data = data_copy_escape_string(yytext+1,
-					yyleng-2);
-			yylloc.first_line = yylineno;
+			yytext[yyleng-1] = 0; /* remove close quote */
+			yylval.litstr = strdup(yytext + 1);
 			return DT_STRING;
 		}
 
 <*>"/dts-v1/"	{
-			yylloc.file = srcpos_file;
-			yylloc.first_line = yylineno;
+			SET_SRCPOS(yylloc);
 			DPRINT("Keyword: /dts-v1/\n");
 			dts_version = 1;
 			BEGIN_DEFAULT();
@@ -89,41 +104,31 @@ static int pop_input_file(void);
 		}
 
 <*>"/memreserve/"	{
-			yylloc.file = srcpos_file;
-			yylloc.first_line = yylineno;
+			SET_SRCPOS(yylloc);
 			DPRINT("Keyword: /memreserve/\n");
 			BEGIN_DEFAULT();
 			return DT_MEMRESERVE;
 		}
 
 <*>{LABEL}:	{
-			yylloc.file = srcpos_file;
-			yylloc.first_line = yylineno;
+			SET_SRCPOS(yylloc);
 			DPRINT("Label: %s\n", yytext);
 			yylval.labelref = strdup(yytext);
 			yylval.labelref[yyleng-1] = '\0';
 			return DT_LABEL;
 		}
 
-<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;
-		}
-
-\&{LABEL}	{	/* label reference */
-			yylloc.file = srcpos_file;
-			yylloc.first_line = yylineno;
+<*>\&{LABEL}	{
+			/* label reference */
+			SET_SRCPOS(yylloc);
 			DPRINT("Ref: %s\n", yytext+1);
 			yylval.labelref = strdup(yytext+1);
 			return DT_REF;
 		}
 
-"&{/"{PATHCHAR}+\}	{	/* new-style path reference */
-			yylloc.file = srcpos_file;
-			yylloc.first_line = yylineno;
+<*>"&{/"{PATHCHAR}+\}	{
+			/* new-style path reference */
+			SET_SRCPOS(yylloc);
 			yytext[yyleng-1] = '\0';
 			DPRINT("Ref: %s\n", yytext+2);
 			yylval.labelref = strdup(yytext+2);
@@ -131,44 +136,210 @@ static int pop_input_file(void);
 		}
 
 <BYTESTRING>[0-9a-fA-F]{2} {
-			yylloc.file = srcpos_file;
-			yylloc.first_line = yylineno;
+			SET_SRCPOS(yylloc);
 			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;
+			SET_SRCPOS(yylloc);
 			DPRINT("/BYTESTRING\n");
 			BEGIN_DEFAULT();
 			return ']';
 		}
 
+<*>[0-9]+|0[xX][0-9a-fA-F]+      {
+			SET_SRCPOS(yylloc);
+			yylval.literal = strdup(yytext);
+			DPRINT("Literal: '%s'\n", yylval.literal);
+			return DT_LITERAL;
+		}
+
+<*>"for"	{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: for\n");
+			BEGIN_DEFAULT();
+			return DT_FOR;
+		}
+
+<*>"if"		{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: if\n");
+			BEGIN_DEFAULT();
+			return DT_IF;
+		}
+
+<*>"void"		{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: void\n");
+			return DT_VOID;
+		}
+
+<*>"in"	{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: in\n");
+			BEGIN_DEFAULT();
+			return DT_IN;
+		}
+
+<*>"else"	{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: else\n");
+			BEGIN_DEFAULT();
+			return DT_ELSE;
+		}
+
+<*>"return"	{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: return\n");
+			return DT_RETURN;
+		}
+
+<*>"/define/"	{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: define\n");
+			return DT_DEFINE;
+		}
+
+<*>"/const/"	{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: const\n");
+			return DT_CONST;
+}
+
+<*>"/incbin/"	{
+			SET_SRCPOS(yylloc);
+			DPRINT("Binary Include\n");
+			return DT_INCBIN;
+		}
+
+<*>{ID}		{
+			SET_SRCPOS(yylloc);
+			DPRINT("Id: %s\n", yytext);
+			yylval.id = strdup(yytext + 1); /* drop \ */
+			BEGIN_DEFAULT();
+			return DT_ID;
+		}
+
+<PROPNODENAME>{NOTPROPNAMES} {
+			/*
+			 * Lone +, - and ? chars shouldn't be
+			 * property names.
+			 */
+			SET_SRCPOS(yylloc);
+			BEGIN_DEFAULT();
+			return yytext[0];
+		}
+
+
 <PROPNODENAME>{PROPNODECHAR}+ {
-			yylloc.file = srcpos_file;
-			yylloc.first_line = yylineno;
+			SET_SRCPOS(yylloc);
 			DPRINT("PropNodeName: %s\n", yytext);
 			yylval.propnodename = strdup(yytext);
 			BEGIN_DEFAULT();
 			return DT_PROPNODENAME;
 		}
 
-"/incbin/"	{
-			yylloc.file = srcpos_file;
-			yylloc.first_line = yylineno;
-			DPRINT("Binary Include\n");
-			return DT_INCBIN;
+
+<*>{WS}+	{
+			/* eat whitespace, but not newline */
+			SET_SRCPOS(yylloc);
+		}
+
+<*>"/*"		{
+			SET_SRCPOS(yylloc);
+			yy_push_state(COMMENT);
+		}
+
+<COMMENT>{
+[^*\n]*		{
+			/* munch */
+			SET_SRCPOS(yylloc);
+		}
+
+[^*\n]*\n	{
+			yycolno = 1;
+		}
+
+"*"+[^*/\n]*	{
+			/* munch */
+			SET_SRCPOS(yylloc);
+		}
+
+"*"+[^*/\n]*\n {
+			yycolno = 1;
+		}
+
+"*"+"/"		{
+			SET_SRCPOS(yylloc);
+			yy_pop_state();
+		}
+}
+
+
+<*>{LINECOMMENT}+ {
+			/* eat C++-style comments including newline */
+			yycolno = 1;
 		}
 
-<*>{WS}+	/* eat whitespace */
-<*>{COMMENT}+	/* eat C-style comments */
-<*>{LINECOMMENT}+ /* eat C++-style comments */
+<*>":="		{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: <<\n");
+			return DT_ASSIGN;
+		}
+<*>"<<"		{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: <<\n");
+			return DT_LSHIFT;
+		}
+<*>">>"		{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: >>\n");
+			return DT_RSHIFT;
+		}
+<*>"<="		{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: <=\n");
+			return DT_LE;
+		}
+<*>">="		{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: >=\n");
+			return DT_GE;
+		}
+<*>"=="		{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: ==\n");
+			return DT_EQ;
+		}
+<*>"!="		{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: !=\n");
+			return DT_NE;
+		}
+<*>"&&"		{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: &&\n");
+			return DT_AND;
+		}
+<*>"||"		{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: ||\n");
+			return DT_OR;
+		}
+<*>".."		{
+			SET_SRCPOS(yylloc);
+			DPRINT("token: ..\n");
+			return DT_RANGE;
+		}
+
+<*>\n		{
+			yycolno = 1;
+		}
 
 <*>.		{
-			yylloc.file = srcpos_file;
-			yylloc.first_line = yylineno;
+			SET_SRCPOS(yylloc);
 			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
 				(unsigned)yytext[0]);
 			if (yytext[0] == '[') {
@@ -176,7 +347,9 @@ static int pop_input_file(void);
 				BEGIN(BYTESTRING);
 			}
 			if ((yytext[0] == '{')
-			    || (yytext[0] == ';')) {
+			    || (yytext[0] == ';')
+			    || (yytext[0] == ':')
+			) {
 				DPRINT("<PROPNODENAME>\n");
 				BEGIN(PROPNODENAME);
 			}
@@ -194,6 +367,7 @@ struct incl_file {
 	struct dtc_file *file;
 	YY_BUFFER_STATE yy_prev_buf;
 	int yy_prev_lineno;
+	int yy_prev_colno;
 	struct incl_file *prev;
 };
 
@@ -235,6 +409,7 @@ static void push_input_file(const char *filename)
 	 */
 	incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
 	incl_file->yy_prev_lineno = yylineno;
+	incl_file->yy_prev_lineno = yycolno;
 	incl_file->file = srcpos_file;
 	incl_file->prev = incl_file_stack;
 
@@ -245,6 +420,7 @@ static void push_input_file(const char *filename)
 	 */
 	srcpos_file = newfile;
 	yylineno = 1;
+	yycolno = 1;
 	yyin = newfile->file;
 	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
 }
@@ -272,6 +448,7 @@ static int pop_input_file(void)
 	yy_delete_buffer(YY_CURRENT_BUFFER);
 	yy_switch_to_buffer(incl_file->yy_prev_buf);
 	yylineno = incl_file->yy_prev_lineno;
+	yycolno = incl_file->yy_prev_colno;
 	srcpos_file = incl_file->file;
 	yyin = incl_file->file ? incl_file->file->file : NULL;
 
diff --git a/dtc-parser.y b/dtc-parser.y
index 3762181..f976623 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -25,309 +25,722 @@
 
 #include "dtc.h"
 #include "srcpos.h"
+#include "ir.h"
 
 extern int yylex(void);
+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);
+#define YYERROR_VERBOSE
+
 %}
 
 %union {
+	struct ir *ir;
 	char *propnodename;
+	char *id;
+	char *litstr;
 	char *literal;
 	char *labelref;
-	unsigned int cbase;
 	uint8_t byte;
-	struct data data;
-
-	uint64_t addr;
-	cell_t cell;
-	struct property *prop;
-	struct property *proplist;
-	struct node *node;
-	struct node *nodelist;
-	struct reserve_info *re;
 }
 
 %token DT_V1
 %token DT_MEMRESERVE
+%token DT_INCBIN
+%token DT_DEFINE
+%token DT_CONST
+%token DT_FOR
+%token DT_IN
+%token DT_RANGE
+%token DT_VOID
+%token DT_IF
+%token DT_ELSE
+%token DT_RETURN
+
 %token <propnodename> DT_PROPNODENAME
+%token <id> DT_ID
 %token <literal> DT_LITERAL
-%token <cbase> DT_BASE
 %token <byte> DT_BYTE
-%token <data> DT_STRING
+%token <litstr> DT_STRING
 %token <labelref> DT_LABEL
 %token <labelref> DT_REF
-%token DT_INCBIN
 
-%type <data> propdata
-%type <data> propdataprefix
-%type <re> memreserve
-%type <re> memreserves
-%type <addr> addr
-%type <data> celllist
-%type <cell> cellval
-%type <data> bytestring
-%type <prop> propdef
-%type <proplist> proplist
-
-%type <node> devicetree
-%type <node> nodedef
-%type <node> subnode
-%type <nodelist> subnodes
-%type <labelref> label
+%token DT_OR
+%token DT_AND
+%token DT_EQ DT_NE
+%token DT_LE DT_GE
+%token DT_LSHIFT DT_RSHIFT
+%token DT_ASSIGN
+
+%type <ir> sourcefile
+%type <ir> memreserve
+%type <ir> devicetree
+%type <ir> declaration_list
+%type <ir> declaration
+%type <ir> funcdef
+%type <ir> constdef
+%type <ir> errordef
+%type <ir> subnode
+%type <ir> paramdecl_list
+%type <ir> paramdecls
+%type <ir> paramdecl
+
+%type <ir> statement_block
+%type <ir> statement_list
+%type <ir> statement
+%type <ir> for_statement
+%type <ir> if_statement
+%type <ir> return_statement
+%type <ir> assign_statement
+%type <ir> trivial_statement
+%type <ir> error_statement
+
+%type <ir> propdef
+%type <ir> celllist
+%type <ir> cellval
+%type <ir> literal
+%type <ir> string
+%type <ir> addr
+%type <ir> byte
+%type <ir> propnodename
+%type <ir> label
+%type <ir> opt_label
+%type <ir> node_label
+%type <ir> propdata
+%type <ir> propdataitem
+%type <ir> propdataprefix
+%type <ir> bytestring
+
+%type <ir> param_list
+
+%type <ir> expr
+%type <ir> expr_primary
+%type <ir> expr_postfix
+%type <ir> expr_unary
+%type <ir> expr_mul
+%type <ir> expr_add
+%type <ir> expr_shift
+%type <ir> expr_rela
+%type <ir> expr_eq
+%type <ir> expr_bitand
+%type <ir> expr_bitxor
+%type <ir> expr_bitor
+%type <ir> expr_and
+%type <ir> expr_or
+%type <ir> expr_conditional
+
+%type <ir> range
+%type <ir> identifier
 
 %%
 
 sourcefile:
-	  DT_V1 ';' memreserves devicetree
+	  DT_V1 ';' declaration_list devicetree
 		{
-			the_boot_info = build_boot_info($3, $4, 0);
+			the_ir_tree = ir_alloc(IR_ROOT, &@4);
+			the_ir_tree->ir_declarations = $3;
+			the_ir_tree->ir_statements = $4;
 		}
 	;
 
-memreserves:
+declaration_list:
 	  /* empty */
 		{
 			$$ = NULL;
 		}
-	| memreserve memreserves
+	| declaration_list declaration
 		{
-			$$ = chain_reserve_entry($1, $2);
+			$$ = ir_list_append($1, $2);
 		}
 	;
 
+declaration:
+	  memreserve
+	| constdef
+	| funcdef
+	| errordef
+	;
+
 memreserve:
-	  label DT_MEMRESERVE addr addr ';'
+	  opt_label DT_MEMRESERVE addr addr ';'
 		{
-			$$ = build_reserve_entry($3, $4, $1);
+			$$ = ir_alloc_binop(IR_MEM_RESERVE, $3, $4, &@2);
+			$$->ir_label = $1;
 		}
 	;
 
-addr:
-	  DT_LITERAL
+
+constdef:
+	  DT_CONST identifier '=' expr ';'
 		{
-			$$ = eval_literal($1, 0, 64);
+			$$ = ir_alloc_binop(IR_CONST_DEF, $2, $4, &@1);
 		}
-	  ;
+	;
 
-devicetree:
-	  '/' nodedef
+funcdef:
+	  DT_DEFINE propnodename paramdecls statement_block
+		{
+			$$ = ir_alloc(IR_FUNC_DEF, &@1);
+			$$->ir_name = $2;
+			$$->ir_declarations = $3;
+			$$->ir_statements = $4;
+		}
+	;
+
+errordef:
+	  error
 		{
-			$$ = name_node($2, "", NULL);
+			$$ = NULL
 		}
 	;
 
-nodedef:
-	  '{' proplist subnodes '}' ';'
+paramdecls:
+	  '(' paramdecl_list ')'
 		{
-			$$ = build_node($2, $3);
+			$$ = $2;
 		}
 	;
 
-proplist:
+paramdecl_list:
 	  /* empty */
 		{
 			$$ = NULL;
 		}
-	| proplist propdef
+	| paramdecl
+		{
+			$$ = ir_list_append(NULL, $1);
+		}
+	| paramdecl_list ',' paramdecl
 		{
-			$$ = chain_property($2, $1);
+			$$ = ir_list_append($1, $3);
 		}
 	;
 
-propdef:
-	  label DT_PROPNODENAME '=' propdata ';'
+paramdecl:
+	  identifier
+	;
+
+
+devicetree:
+	  '/' statement_block ';'
 		{
-			$$ = build_property($2, $4, $1);
+			$$ = ir_alloc(IR_NODE, &@2);
+			$$->ir_statements = $2;
+			$$->ir_name = ir_alloc(IR_PROPNODENAME, &@1);
+			$$->ir_name->ir_lit_str = "";
+			$$->ir_label = NULL;
 		}
-	| label DT_PROPNODENAME ';'
+	;
+
+
+statement_block:
+	  '{' statement_list '}'
 		{
-			$$ = build_property($2, empty_data, $1);
+			$$ = $2;
 		}
 	;
 
-propdata:
-	  propdataprefix DT_STRING
+statement_list:
+	  /* empty */
 		{
-			$$ = data_merge($1, $2);
+			$$ = NULL;
 		}
-	| propdataprefix '<' celllist '>'
+	| statement_list statement
 		{
-			$$ = data_merge($1, $3);
+			$$ = ir_list_append($1, $2);
 		}
-	| propdataprefix '[' bytestring ']'
+	;
+
+statement:
+	  for_statement
+	| if_statement
+	| return_statement
+	| assign_statement
+	| propdef
+	| subnode
+	| statement_block
+	| trivial_statement
+	| error_statement
+	;
+
+
+subnode:
+	  node_label expr statement_block ';'
 		{
-			$$ = data_merge($1, $3);
+			$$ = ir_alloc(IR_NODE, &@3);
+			$$->ir_statements = $3;
+			$$->ir_label = $1;
+			$$->ir_name = $2;
 		}
-	| propdataprefix DT_REF
+	| label expr statement_block ';'
 		{
-			$$ = data_add_marker($1, REF_PATH, $2);
+			$$ = ir_alloc(IR_NODE, &@3);
+			$$->ir_statements = $3;
+			$$->ir_label = $1;
+			$$->ir_name = $2;
 		}
-	| propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
+	| expr statement_block ';'
 		{
-			struct search_path path = { srcpos_file->dir, NULL, NULL };
-			struct dtc_file *file = dtc_open_file($4.val, &path);
-			struct data d = empty_data;
+			$$ = ir_alloc(IR_NODE, &@2);
+			$$->ir_statements = $2;
+			$$->ir_label = NULL;
+			$$->ir_name = $1;
+		}
+	;
 
-			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));
+for_statement:
+	  DT_FOR identifier DT_IN range statement_block
+		{
+			$$ = ir_alloc_binop(IR_FOR, $2, $4, &@1);
+			$$->ir_statements = $5;
+		}
+	;
 
-			d = data_copy_file(file->file, $8);
+range:
+	  expr DT_RANGE expr
+		{
+			$$ = ir_alloc_binop(IR_RANGE, $1, $3, &@2);
+		}
+	;
 
-			$$ = data_merge($1, d);
-			dtc_close_file(file);
+if_statement:
+	  DT_IF '(' expr ')' statement_block
+		{
+			$$ = ir_alloc_unop(IR_IF, $3, &@1);
+			$$->ir_statements = $5;
 		}
-	| propdataprefix DT_INCBIN '(' DT_STRING ')'
+	| DT_IF '(' expr ')' statement_block DT_ELSE statement_block
 		{
-			struct search_path path = { srcpos_file->dir, NULL, NULL };
-			struct dtc_file *file = dtc_open_file($4.val, &path);
-			struct data d = empty_data;
+			$$ = ir_alloc_unop(IR_IF, $3, &@1);
+			$$->ir_statements = $5;
+			$$->ir_statements2 = $7;
+		}
+	;
 
-			d = data_copy_file(file->file, -1);
+return_statement:
+	  DT_RETURN expr ';'
+		{
+			$$ = ir_alloc_unop(IR_RETURN, $2, &@1);
+		}
+	;
 
-			$$ = data_merge($1, d);
-			dtc_close_file(file);
+assign_statement:
+	  identifier DT_ASSIGN expr ';'
+		{
+			$$ = ir_alloc_binop(IR_ASSIGN, $1, $3, &@2);
 		}
-	| propdata DT_LABEL
+	;
+
+trivial_statement:
+	  ';'
 		{
-			$$ = data_add_marker($1, LABEL, $2);
+			$$ = NULL;
+		}
+	;
+
+error_statement:
+	  error
+		{
+			$$ = NULL;
+		}
+	;
+
+propdef:
+	  expr ';'
+		{
+			$$ = ir_alloc_unop(IR_PROP_DEF,
+					   ir_alloc_unop(IR_CVT_PROPNODENAME,
+							 $1,
+							 &@1),
+					   &@1);
+			$$->ir_label = NULL;
+		}
+	| expr '=' propdata ';'
+		{
+			$$ = ir_alloc_binop(IR_PROP_DEF,
+					    ir_alloc_unop(IR_CVT_PROPNODENAME,
+							  $1,
+							  &@1),
+					    $3,
+					    &@2);
+			$$->ir_label = NULL;
+		}
+	| label expr ';'
+		{
+			$$ = ir_alloc_unop(IR_PROP_DEF,
+					   ir_alloc_unop(IR_CVT_PROPNODENAME,
+							 $2,
+							 &@2),
+					   &@2);
+			$$->ir_label = $1;
+		}
+	| label expr '=' propdata ';'
+		{
+			$$ = ir_alloc_binop(IR_PROP_DEF,
+					    ir_alloc_unop(IR_CVT_PROPNODENAME,
+							  $2,
+							  &@2),
+					    $4,
+					    &@3);
+			$$->ir_label = $1;
+		}
+	;
+
+propdata:
+	  propdataprefix propdataitem
+		{
+			$$ = ir_list_append($1, $2);
+		}
+	| propdata label
+		{
+			$$ = ir_list_append($1, $2);
+		}
+	;
+
+propdataitem:
+	  string
+		{
+			$$ = $1;
+		}
+	| '<' celllist '>'
+		{
+			$$ = $2;
+		}
+	| '[' bytestring ']'
+		{
+			$$ = $2;
+		}
+	| DT_REF
+		{
+			$$ = ir_alloc(IR_REF_PATH, &@1);
+			$$->ir_label_name = $1;
+		}
+	| DT_INCBIN '(' expr ')'
+		{
+			$$ = ir_alloc_unop(IR_INCBIN, $3, &@1);
+		}
+	| DT_INCBIN '(' expr ',' expr ',' expr ')'
+		{
+			$$ = ir_alloc_triop(IR_INCBIN, $3, $5, $7, &@1);
 		}
 	;
 
 propdataprefix:
 	  /* empty */
 		{
-			$$ = empty_data;
+			$$ = NULL;
 		}
 	| propdata ','
 		{
 			$$ = $1;
 		}
-	| propdataprefix DT_LABEL
+	| propdataprefix label
 		{
-			$$ = data_add_marker($1, LABEL, $2);
+			$$ = ir_list_append($1, $2);
 		}
 	;
 
 celllist:
 	  /* empty */
 		{
-			$$ = empty_data;
+			$$ = NULL;
 		}
 	| celllist cellval
 		{
-			$$ = data_append_cell($1, $2);
+			$$ = ir_list_append($1, $2);
+		}
+	| celllist '&' '(' expr ')'
+		{
+			$$ = ir_alloc(IR_REF_PHANDLE, &@2);
+			$$->ir_label = $4;
+			$$ = ir_list_append($1, $$);
+
 		}
 	| celllist DT_REF
 		{
-			$$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
-							      $2), -1);
+			$$ = ir_alloc(IR_REF_PHANDLE, &@2);
+			$$->ir_label_name = $2;
+			$$ = ir_list_append($1, $$);
 		}
-	| celllist DT_LABEL
+	| celllist label
 		{
-			$$ = data_add_marker($1, LABEL, $2);
+			$$ = ir_list_append($1, $2);
 		}
 	;
 
 cellval:
-	  DT_LITERAL
+	  expr_primary
 		{
-			$$ = eval_literal($1, 0, 32);
+			$$ = ir_alloc_unop(IR_CELL, $1, &@1);
 		}
 	;
 
-bytestring:
-	  /* empty */
+
+expr:
+	  expr_conditional
+	;
+
+expr_conditional:
+	  expr_or
+	| expr_or '?' expr_or ':' expr_conditional
 		{
-			$$ = empty_data;
+			$$ = ir_alloc_triop(IR_SELECT, $1, $3, $5, &@2);
 		}
-	| bytestring DT_BYTE
+	;
+
+expr_or:
+	  expr_and
+	| expr_or DT_OR expr_and
+		{
+			$$ = ir_alloc_binop(IR_OR, $1, $3, &@2);
+		};
+
+expr_and:
+	  expr_bitor
+	| expr_and DT_AND expr_bitor
+		{
+			$$ = ir_alloc_binop(IR_AND, $1, $3, &@2);
+		};
+	;
+
+expr_bitor:
+	  expr_bitxor
+	| expr_bitor '|' expr_bitxor
 		{
-			$$ = data_append_byte($1, $2);
+			$$ = ir_alloc_binop(IR_BIT_OR, $1, $3, &@2);
+		};
+	;
+
+expr_bitxor:
+	  expr_bitand
+	| expr_bitxor '^' expr_bitand
+		{
+			$$ = ir_alloc_binop(IR_BIT_XOR, $1, $3, &@2);
+		};
+	;
+
+expr_bitand:
+	  expr_eq
+	| expr_bitand '&' expr_eq
+		{
+			$$ = ir_alloc_binop(IR_BIT_AND, $1, $3, &@2);
+		};
+	;
+
+expr_eq:
+	  expr_rela
+	| expr_eq DT_EQ expr_rela
+		{
+			$$ = ir_alloc_binop(IR_EQ, $1, $3, &@2);
+		}
+	| expr_eq DT_NE expr_rela
+		{
+			$$ = ir_alloc_binop(IR_NE, $1, $3, &@2);
+		}
+	;
+
+expr_rela:
+	  expr_shift
+	| expr_rela '<' expr_shift
+		{
+			$$ = ir_alloc_binop(IR_LT, $1, $3, &@2);
+		}
+	| expr_rela '>' expr_shift
+		{
+			$$ = ir_alloc_binop(IR_GT, $1, $3, &@2);
+		}
+	| expr_rela DT_LE expr_shift
+		{
+			$$ = ir_alloc_binop(IR_LE, $1, $3, &@2);
+		}
+	| expr_rela DT_GE expr_shift
+		{
+			$$ = ir_alloc_binop(IR_GE, $1, $3, &@2);
+		}
+	;
+
+expr_shift:
+	  expr_add
+	| expr_shift DT_LSHIFT expr_add
+		{
+			$$ = ir_alloc_binop(IR_LSHIFT, $1, $3, &@2);
+		}
+	| expr_shift DT_RSHIFT expr_add
+		{
+			$$ = ir_alloc_binop(IR_RSHIFT, $1, $3, &@2);
+		}
+	;
+
+expr_add:
+	  expr_mul
+	| expr_add '+' expr_mul
+		{
+			$$ = ir_alloc_binop(IR_ADD, $1, $3, &@2);
+		}
+	| expr_add '-' expr_mul
+		{
+			$$ = ir_alloc_binop(IR_MINUS, $1, $3, &@2);
+		}
+	;
+
+expr_mul:
+	  expr_unary
+	| expr_mul '*' expr_unary
+		{
+			$$ = ir_alloc_binop(IR_MULT, $1, $3, &@2);
+		}
+	| expr_mul '/' expr_unary
+		{
+			$$ = ir_alloc_binop(IR_DIV, $1, $3, &@2);
+		}
+	| expr_mul '%' expr_unary
+		{
+			$$ = ir_alloc_binop(IR_MOD, $1, $3, &@2);
+		}
+	;
+
+expr_unary:
+	  expr_postfix
+	| '-' expr_unary
+		{
+			$$ = ir_alloc_unop(IR_UMINUS, $2, &@1);
+		}
+	| '~' expr_unary
+		{
+			$$ = ir_alloc_unop(IR_BIT_COMPL, $2, &@1);
+		}
+	| '!' expr_unary
+		{
+			$$ = ir_alloc_unop(IR_NOT, $2, &@1);
+		}
+	;
+
+expr_postfix:
+	  expr_primary
+	| expr_postfix '(' ')'
+		{
+			$$ = ir_alloc_binop(IR_FUNC_CALL, $1, NULL, &@2);
 		}
-	| bytestring DT_LABEL
+	| expr_postfix '(' param_list ')'
 		{
-			$$ = data_add_marker($1, LABEL, $2);
+			$$ = ir_alloc_binop(IR_FUNC_CALL, $1, $3, &@2);
 		}
 	;
 
-subnodes:
+param_list:
+	  expr
+		{
+			$$ = ir_list_append(NULL, $1);
+		}
+	| param_list ',' expr
+		{
+			$$ = ir_list_append($1, $3);
+		}
+	;
+
+
+
+expr_primary:
+	  literal
+	| string
+	| propnodename
+	| identifier
+	| '(' expr ')'
+		{
+			$$ = $2;
+		}
+	;
+
+addr:
+	  expr_primary
+	;
+
+
+bytestring:
 	  /* empty */
 		{
 			$$ = NULL;
 		}
-	|  subnode subnodes
+	| bytestring byte
 		{
-			$$ = chain_node($1, $2);
+			$$ = ir_list_append($1, $2);
 		}
-	| subnode propdef
+	| bytestring label
 		{
-			yyerror("syntax error: properties must precede subnodes");
-			YYERROR;
+			$$ = ir_list_append($1, $2);
 		}
 	;
 
-subnode:
-	  label DT_PROPNODENAME nodedef
+propnodename:
+	  DT_PROPNODENAME
 		{
-			$$ = name_node($3, $2, $1);
+			$$ = ir_alloc(IR_PROPNODENAME, &@1);
+			$$->ir_lit_str = $1;
 		}
 	;
 
-label:
+identifier:
+	  DT_ID
+		{
+			$$ = ir_alloc(IR_ID, &@1);
+			$$->ir_lit_str = $1;
+		}
+	;
+
+literal:
+	  DT_LITERAL
+		{
+			$$ = ir_alloc(IR_LITERAL, &@1);
+			$$->ir_lit_str = $1;
+		}
+	;
+
+byte:
+	  DT_BYTE
+		{
+			$$ = ir_alloc(IR_LIT_BYTE, &@1);
+			$$->ir_literal = $1;
+		}
+	;
+
+string:
+	  DT_STRING
+		{
+			$$ = ir_alloc(IR_LIT_STR, &@1);
+			$$->ir_lit_str = $1;
+		}
+	;
+
+opt_label:
 	  /* empty */
 		{
 			$$ = NULL;
 		}
-	| DT_LABEL
+	| label
 		{
 			$$ = $1;
 		}
 	;
 
-%%
-
-void yyerrorf(char const *s, ...)
-{
-	const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";
-	va_list va;
-	va_start(va, s);
-
-	if (strcmp(fname, "-") == 0)
-		fname = "stdin";
+label:
+	  DT_LABEL
+		{
+			$$ = ir_alloc(IR_LABEL, &@1);
+			$$->ir_label_name = $1;
+		}
+	;
 
-	fprintf(stderr, "%s:%d ", fname, yylloc.first_line);
-	vfprintf(stderr, s, va);
-	fprintf(stderr, "\n");
+node_label:
+	  expr ':'
+	;
 
-	treesource_error = 1;
-	va_end(va);
-}
 
-void yyerror (char const *s)
-{
-	yyerrorf("%s", s);
-}
+%%
 
-static unsigned long long eval_literal(const char *s, int base, int bits)
+void yyerror(char const *s)
 {
-	unsigned long long val;
-	char *e;
-
-	errno = 0;
-	val = strtoull(s, &e, base);
-	if (*e)
-		yyerror("bad characters in literal");
-	else if ((errno == ERANGE)
-		 || ((bits < 64) && (val >= (1ULL << bits))))
-		yyerror("literal out of range");
-	else if (errno != 0)
-		yyerror("bad literal");
-	return val;
+	srcpos_error(&yylloc, "%s", s);
+	treesource_error = 1;
 }
diff --git a/dtc.c b/dtc.c
index 84bee2d..ccaf89c 100644
--- a/dtc.c
+++ b/dtc.c
@@ -20,6 +20,7 @@
 
 #include "dtc.h"
 #include "srcpos.h"
+#include "nv.h"
 
 #include "version_gen.h"
 
@@ -127,7 +128,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 = getopt(argc, argv, "hD:I:O:o:V:R:S:p:fcqb:v")) != EOF) {
 		switch (opt) {
 		case 'I':
 			inform = optarg;
@@ -162,6 +163,9 @@ int main(int argc, char *argv[])
 		case 'b':
 			cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
 			break;
+		case 'D':
+			nv_note_define(optarg);
+			break;
 		case 'v':
 			printf("Version: %s\n", DTC_VERSION);
 			exit(0);
@@ -203,7 +207,6 @@ int main(int argc, char *argv[])
 	fill_fullpaths(bi->dt, "");
 	process_checks(force, bi);
 
-
 	if (streq(outname, "-")) {
 		outf = stdout;
 	} else {
diff --git a/dtc.h b/dtc.h
index ec636f8..327fc15 100644
--- a/dtc.h
+++ b/dtc.h
@@ -187,6 +187,7 @@ 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 *chain_node(struct node *first, struct node *list);
+struct node *reverse_nodes(struct node *first);
 
 void add_property(struct node *node, struct property *prop);
 void add_child(struct node *parent, struct node *child);
diff --git a/ir.h b/ir.h
index 630ec52..b17b87d 100644
--- a/ir.h
+++ b/ir.h
@@ -100,7 +100,6 @@ struct ir {
 	struct ir *ir_expr2;
 	struct ir *ir_expr3;
 
-	struct ir *ir_mem_reserves;
 	struct ir *ir_statements;
 	struct ir *ir_statements2;
 	struct ir *ir_declarations;
diff --git a/ir_dump.c b/ir_dump.c
index f949423..edf11a7 100644
--- a/ir_dump.c
+++ b/ir_dump.c
@@ -152,15 +152,6 @@ ir_dump_node(struct ir *ir, unsigned int level)
 		       indent, "", ir->ir_prev);
 
 	/*
-	 * Dump mem-reserves.
-	 */
-	if (ir->ir_mem_reserves) {
-		printf("%*sir_mem_reserves: %p\n",
-		       indent, "", ir->ir_mem_reserves);
-		ir_dump_node(ir->ir_mem_reserves, level + 1);
-	}
-
-	/*
 	 * Dump sub-expressions
 	 */
 	if (ir->ir_expr1) {
diff --git a/ir_emit.c b/ir_emit.c
index 31005ca..54b5a00 100644
--- a/ir_emit.c
+++ b/ir_emit.c
@@ -323,6 +323,34 @@ ir_emit_const_def(struct ir *ir_const_def)
 
 
 void
+ir_emit_mem_reserve(struct ir *ir_mem)
+{
+	struct reserve_info *ri;
+	uint64_t addr;
+	uint64_t size;
+	char *lab;
+
+	if (ir_mem == NULL)
+		return;
+
+	addr = ir_eval_for_addr(ir_mem->ir_expr1);
+	size = ir_eval_for_addr(ir_mem->ir_expr2);
+	lab = ir_eval_for_label(ir_mem->ir_label);
+
+	debug("ir_emit_mem_reserve(0x%llx, 0x%llx, ",
+	      (unsigned long long)addr, (unsigned long long)size);
+	if (lab) {
+		debug("%s)\n", lab);
+	} else {
+		debug("<no-label>)\n");
+	}
+
+	ri = build_reserve_entry(addr, size, lab);
+	irs_append_reserve(ri);
+}
+
+
+void
 ir_emit_declaration_list(struct ir *ir_list)
 {
 	struct ir *ir;
@@ -343,9 +371,13 @@ ir_emit_declaration_list(struct ir *ir_list)
 			ir_emit_func_def(ir);
 			break;
 
+		case IR_MEM_RESERVE:
+			ir_emit_mem_reserve(ir);
+			break;
+
 		default:
 			ir_error(ir,
-				 "Unknown devlaration type %s\n",
+				 "Unknown declaration type %s\n",
 				 ir_type_string(ir->ir_type));
 			break;
 		}
@@ -391,37 +423,6 @@ ir_emit_node(struct ir *ir)
 
 
 void
-ir_emit_mem_reserves(struct ir *ir_mem)
-{
-	struct ir *ir;
-	struct reserve_info *ri;
-	uint64_t addr;
-	uint64_t size;
-	char *lab;
-
-	if (ir_mem == NULL)
-		return;
-
-	for (ir = ir_mem->ir_first; ir != NULL; ir = ir->ir_next) {
-		addr = ir_eval_for_addr(ir->ir_expr1);
-		size = ir_eval_for_addr(ir->ir_expr2);
-		lab = ir_eval_for_label(ir->ir_label);
-
-		debug("emit: build_reserve_entry(0x%llx, 0x%llx, ",
-		      (unsigned long long)addr, (unsigned long long)size);
-		if (lab) {
-			debug("%s)\n", lab);
-		} else {
-			debug("<no-label>)\n");
-		}
-
-		ri = build_reserve_entry(addr, size, lab);
-		irs_append_reserve(ri);
-	}
-}
-
-
-void
 ir_add_cmd_line_constant_defs(void)
 {
 	struct nv_pair *nv;
@@ -460,8 +461,6 @@ ir_emit_root(struct ir *ir)
 	 */
 	ir_add_cmd_line_constant_defs();
 
-	ir_emit_mem_reserves(ir->ir_mem_reserves);
-
 	/*
 	 * Fast-and-loose... These are definitions, not declarations!
 	 */
diff --git a/ir_eval.c b/ir_eval.c
index bd667cb..ba6da6a 100644
--- a/ir_eval.c
+++ b/ir_eval.c
@@ -1461,8 +1461,6 @@ ir_simplify(struct ir *ir, unsigned int ctxt)
 
 	case IR_ROOT:
 		ir_new = ir_copy(ir);
-		ir_new->ir_mem_reserves =
-			ir_simplify(ir->ir_mem_reserves, ctxt);
 		ir_new->ir_declarations =
 			ir_simplify(ir->ir_declarations, ctxt);
 		ir_new->ir_statements =
diff --git a/ir_scope.c b/ir_scope.c
index c9a52e8..20d784d 100644
--- a/ir_scope.c
+++ b/ir_scope.c
@@ -97,8 +97,7 @@ irs_append_reserve(struct reserve_info *ri)
 	struct ir_scope *irs;
 
 	irs = irs_find_scope(IRS_ROOT);
-	irs->irs_reserve_list = chain_reserve_entry(ri,
-						    irs->irs_reserve_list);
+	irs->irs_reserve_list = add_reserve_entry(irs->irs_reserve_list, ri);
 }
 
 
diff --git a/livetree.c b/livetree.c
index 0ca3de5..fec33b4 100644
--- a/livetree.c
+++ b/livetree.c
@@ -97,6 +97,22 @@ struct node *chain_node(struct node *first, struct node *list)
 	return first;
 }
 
+struct node *reverse_nodes(struct node *first)
+{
+	struct node *p = first;
+	struct node *head = NULL;
+	struct node *next;
+
+	while (p) {
+		next = p->next_sibling;
+		p->next_sibling = head;
+		head = p;
+		p = next;
+	}
+	return head;
+}
+
+
 void add_property(struct node *node, struct property *prop)
 {
 	struct property **p;
diff --git a/nv.c b/nv.c
new file mode 100644
index 0000000..f02b8bc
--- /dev/null
+++ b/nv.c
@@ -0,0 +1,108 @@
+/*
+ * 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
+ */
+
+#include "dtc.h"
+#include "nv.h"
+
+struct nv_pair *nv_list;
+
+
+struct nv_pair *
+nv_alloc(void)
+{
+	struct nv_pair *nv;
+
+	nv = xmalloc(sizeof(struct nv_pair));
+	memset(nv, 0, sizeof(struct nv_pair));
+
+	return nv;
+}
+
+
+int
+nv_is_present(char *name)
+{
+	struct nv_pair *nv;
+
+	for (nv = nv_list; nv != NULL; nv = nv->nv_next) {
+		if (strcmp(nv->nv_name, name) == 0) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+
+void
+nv_dump(void)
+{
+	struct nv_pair *nv;
+
+	for (nv = nv_list; nv != NULL; nv = nv->nv_next) {
+		printf("NV: %s = \"%s\"\n", nv->nv_name, nv->nv_value);
+	}
+}
+
+
+/*
+ * Accept a string like "foo=123", or "cpu=mpc8548".
+ * Split it on the = for name and value parts.
+ * Record it in a name-value pairing list for later
+ * use when setting up the IR evaluation environment.
+ */
+
+void
+nv_note_define(char *defstr)
+{
+	struct nv_pair *nv;
+	char *name;
+	char *value;
+
+	if (!defstr || ! *defstr)
+		return;
+
+	name = strdup(defstr);
+
+	/*
+	 * Separate name and value at equal sign.
+	 */
+	value = strchr(name, '=');
+	if (value) {
+		*value = 0;
+		value++;
+		if (! *value) {
+			value = NULL;
+		}
+	}
+
+	if (nv_is_present(name)) {
+		printf("Warning: Ignored duplicate value %s for %s\n",
+		       value, name);
+		return;
+	}
+
+	debug("nv_note_define(): %s = \"%s\"\n", name, value);
+
+	nv = nv_alloc();
+	nv->nv_name = name;
+	nv->nv_value = value;
+
+	nv->nv_next = nv_list;
+	nv_list = nv;
+}
diff --git a/nv.h b/nv.h
new file mode 100644
index 0000000..70ed718
--- /dev/null
+++ b/nv.h
@@ -0,0 +1,34 @@
+/*
+ * 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
+ */
+
+#ifndef _NV_H_
+#define _NV_H_
+
+
+struct nv_pair {
+	char *nv_name;
+	char *nv_value;
+	struct nv_pair *nv_next;
+};
+
+extern struct nv_pair *nv_list;
+
+extern void nv_note_define(char *defstr);
+
+#endif /* _NV_H_ */
diff --git a/srcpos.c b/srcpos.c
index 59d1835..ac1fdab 100644
--- a/srcpos.c
+++ b/srcpos.c
@@ -17,9 +17,14 @@
  *                                                                   USA
  */
 
+#define _GNU_SOURCE
+
+#include <stdio.h>
+
 #include "dtc.h"
 #include "srcpos.h"
 
+
 /*
  * Like yylineno, this is the current open file pos.
  */
@@ -129,9 +134,6 @@ dtc_close_file(struct dtc_file *file)
 {
 	if (fclose(file->file))
 		die("Error closing \"%s\": %s\n", file->name, strerror(errno));
-
-	free(file->dir);
-	free(file);
 }
 
 
@@ -164,34 +166,75 @@ srcpos_dump(srcpos *pos)
 char *
 srcpos_string(srcpos *pos)
 {
-#	define POS_BUF_SIZE	(100)
-
 	const char *fname;
-	char buf[POS_BUF_SIZE];
+	char col_buf[100];
+	char *pos_str;
 
-	if (pos->file && pos->file->name)
+	if (!pos) {
+		fname = "<no-file>";
+	} else if (pos->file->name) {
 		fname = pos->file->name;
-	else
+		if (strcmp(fname, "-") == 0)
+			fname = "stdin";
+	} else {
 		fname = "<no-file>";
+	}
 
 	if (pos->first_line == pos->last_line) {
 		if (pos->first_column == pos->last_column) {
-			snprintf(buf, POS_BUF_SIZE, "%s %d:%d",
-				 fname, pos->first_line, pos->first_column);
+			snprintf(col_buf, sizeof(col_buf),
+				 "%d:%d",
+				 pos->first_line, pos->first_column);
 		} else {
-			snprintf(buf, POS_BUF_SIZE, "%s %d:%d-%d",
-				 fname, pos->first_line,
+			snprintf(col_buf, sizeof(col_buf),
+				 "%d:%d-%d",
+				 pos->first_line,
 				 pos->first_column, pos->last_column);
 		}
 
 	} else {
-		snprintf(buf, POS_BUF_SIZE, "%s %d:%d - %d:%d",
-			 fname,
+		snprintf(col_buf, sizeof(col_buf),
+			 "%d:%d - %d:%d",
 			 pos->first_line, pos->first_column,
 			 pos->last_line, pos->last_column);
 	}
 
-	return strdup(buf);
+	if (asprintf(&pos_str, "%s %s", fname, col_buf) == -1)
+		return "<unknown source position?";
+
+	return pos_str;
+}
+
+
+void
+srcpos_error(srcpos *pos, char const *fmt, ...)
+{
+	const char *srcstr;
+	va_list va;
+	va_start(va, fmt);
+
+	srcstr = srcpos_string(pos);
+
+	fprintf(stderr, "Error: %s ", srcstr);
+	vfprintf(stderr, fmt, va);
+	fprintf(stderr, "\n");
+
+	va_end(va);
+}
+
+
+void
+srcpos_warn(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");
 
-#	undef POS_BUF_SIZE
+	va_end(va);
 }
diff --git a/srcpos.h b/srcpos.h
index 3c39dd0..a6d0077 100644
--- a/srcpos.h
+++ b/srcpos.h
@@ -81,11 +81,6 @@ typedef YYLTYPE srcpos;
  */
 extern srcpos srcpos_empty;
 
-
-
-extern void yyerror(char const *);
-extern void yyerrorf(char const *, ...) __attribute__((format(printf, 1, 2)));
-
 extern struct dtc_file *srcpos_file;
 
 struct search_path {
@@ -101,4 +96,9 @@ extern srcpos *srcpos_copy(srcpos *pos);
 extern char *srcpos_string(srcpos *pos);
 extern void srcpos_dump(srcpos *pos);
 
+extern void srcpos_error(srcpos *pos, char const *, ...)
+     __attribute__((format(printf, 2, 3)));
+extern void srcpos_warn(srcpos *pos, char const *, ...)
+     __attribute__((format(printf, 2, 3)));
+
 #endif /* _SRCPOS_H_ */
diff --git a/treesource.c b/treesource.c
index 1521ff1..5d69878 100644
--- a/treesource.c
+++ b/treesource.c
@@ -20,6 +20,7 @@
 
 #include "dtc.h"
 #include "srcpos.h"
+#include "ir.h"
 
 extern FILE *yyin;
 extern int yyparse(void);
@@ -41,6 +42,8 @@ struct boot_info *dt_from_source(const char *fname)
 	if (treesource_error)
 		die("Syntax error parsing input tree\n");
 
+	ir_process();
+
 	return the_boot_info;
 }
 
-- 
1.6.0.90.g436ed




More information about the devicetree-discuss mailing list