All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9 V3] Implement a new DTS Source Language
@ 2008-09-26 20:25 Jon Loeliger
       [not found] ` <1222460748-20127-1-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Jon Loeliger @ 2008-09-26 20:25 UTC (permalink / raw)
  To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

This series of patches enhances the DTS source language to
support a fullly interpreted language for generating nodes
and properties.  It is backward compatible with V1 sources.

The main features implemented by this patch set support
function definitions, 'if', 'for', 'return' and assignment
statements.  Local variables, global constants and
almost complete C-like expressions are also supported.

Enhancements to the source position and error/warning
reporting now support source column positions too.

Version 1 was the original posting.
Version 2 only fixed one patch in the series

This is Version 3 and it includes fixes and suggestions
due to community review and feedback, and includes a
new patch that provides some testing.  Git bisectability
has been ensured as well.


Jon Loeliger (9):
  Remove support for the legacy DTS source file format.
  Add conditionalized debug() print macro.
  Enhance source position implementation.
  Add header files for new Internal Representation form.
  Add most of the new IR implementation files.
  Add the main IR evaluation implementation
  Introduce new DTS language.
  Add documentation for the new DTS language.
  Test constant expressions in cell contexts.

 Documentation/manual.txt  |  500 ++++++++++++++--
 Makefile                  |    2 +-
 Makefile.dtc              |   18 +-
 dtc-lexer.l               |  311 +++++++---
 dtc-parser.y              |  721 ++++++++++++++++------
 dtc.c                     |    7 +-
 dtc.h                     |    9 +
 ir.c                      |  190 ++++++
 ir.h                      |  175 ++++++
 ir_builtin.c              |  180 ++++++
 ir_builtin.h              |   31 +
 ir_dump.c                 |  211 +++++++
 ir_emit.c                 |  490 +++++++++++++++
 ir_eval.c                 | 1502 +++++++++++++++++++++++++++++++++++++++++++++
 ir_scope.c                |  318 ++++++++++
 ir_scope.h                |  114 ++++
 livetree.c                |   16 +
 nv.c                      |  108 ++++
 nv.h                      |   34 +
 srcpos.c                  |  142 ++++-
 srcpos.h                  |   23 +-
 tests/Makefile.tests      |    1 +
 tests/base01.dts          |   24 +-
 tests/cell-expressions.c  |  116 ++++
 tests/empty.dts           |    2 +
 tests/escapes.dts         |    2 +
 tests/label01.dts         |   38 +-
 tests/references_dts0.dts |   12 +-
 tests/run_tests.sh        |   32 +-
 tests/test01.dts          |   38 +-
 tests/test_tree1_dts0.dts |   18 +-
 treesource.c              |    3 +
 32 files changed, 4987 insertions(+), 401 deletions(-)
 create mode 100644 ir.c
 create mode 100644 ir.h
 create mode 100644 ir_builtin.c
 create mode 100644 ir_builtin.h
 create mode 100644 ir_dump.c
 create mode 100644 ir_emit.c
 create mode 100644 ir_eval.c
 create mode 100644 ir_scope.c
 create mode 100644 ir_scope.h
 create mode 100644 nv.c
 create mode 100644 nv.h
 create mode 100644 tests/cell-expressions.c

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [PATCH 1/9 V3] Remove support for the legacy DTS source file format.
       [not found] ` <1222460748-20127-1-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-26 20:25   ` Jon Loeliger
       [not found]     ` <1222460748-20127-2-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Jon Loeliger @ 2008-09-26 20:25 UTC (permalink / raw)
  To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

Now that all in-kernel-tree DTS files are properly /dts-v1/,
remove direct support for the older, un-numbered DTS
source file format.

Convert existing tests to /dts-v1/ and remove support
for the conversion tests themselves.

For now, though, the conversion tool still exists.

Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 dtc-lexer.l               |   40 +-------------------------------------
 dtc-parser.y              |   46 ---------------------------------------------
 tests/base01.dts          |   24 ++++++++++++----------
 tests/empty.dts           |    2 +
 tests/escapes.dts         |    2 +
 tests/label01.dts         |   38 +++++++++++++++++++-----------------
 tests/references_dts0.dts |   12 ++++++----
 tests/run_tests.sh        |   27 +-------------------------
 tests/test01.dts          |   38 +++++++++++++++++++-----------------
 tests/test_tree1_dts0.dts |   18 +++++++++-------
 10 files changed, 77 insertions(+), 170 deletions(-)

diff --git a/dtc-lexer.l b/dtc-lexer.l
index 6f8b7dd..6b862d2 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -47,15 +47,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);
@@ -110,29 +105,6 @@ static int pop_input_file(void);
 			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);
-			DPRINT("Literal: '%s'\n", yylval.literal);
-			return DT_LEGACYLITERAL;
-		}
-
 <V1>[0-9]+|0[xX][0-9a-fA-F]+      {
 			yylloc.file = srcpos_file;
 			yylloc.first_line = yylineno;
@@ -158,14 +130,6 @@ static int pop_input_file(void);
 			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);
-			return DT_REF;
-		}
-
 <BYTESTRING>[0-9a-fA-F]{2} {
 			yylloc.file = srcpos_file;
 			yylloc.first_line = yylineno;
diff --git a/dtc-parser.y b/dtc-parser.y
index b2ab562..3762181 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -55,7 +55,6 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
 %token DT_MEMRESERVE
 %token <propnodename> DT_PROPNODENAME
 %token <literal> DT_LITERAL
-%token <literal> DT_LEGACYLITERAL
 %token <cbase> DT_BASE
 %token <byte> DT_BYTE
 %token <data> DT_STRING
@@ -67,11 +66,8 @@ 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 <data> bytestring
 %type <prop> propdef
@@ -90,10 +86,6 @@ sourcefile:
 		{
 			the_boot_info = build_boot_info($3, $4, 0);
 		}
-	| v0_memreserves devicetree
-		{
-			the_boot_info = build_boot_info($1, $2, 0);
-		}
 	;
 
 memreserves:
@@ -114,37 +106,11 @@ memreserve:
 		}
 	;
 
-v0_memreserves:
-	  /* empty */
-		{
-			$$ = NULL;
-		}
-	| v0_memreserve v0_memreserves
-		{
-			$$ = chain_reserve_entry($1, $2);
-		};
-	;
-
-v0_memreserve:
-	  memreserve
-		{
-			$$ = $1;
-		}
-	| label DT_MEMRESERVE addr '-' addr ';'
-		{
-			$$ = build_reserve_entry($3, $5 - $3 + 1, $1);
-		}
-	;
-
 addr:
 	  DT_LITERAL
 		{
 			$$ = eval_literal($1, 0, 64);
 		}
-	| DT_LEGACYLITERAL
-		{
-			$$ = eval_literal($1, 16, 64);
-		}
 	  ;
 
 devicetree:
@@ -269,23 +235,11 @@ celllist:
 		}
 	;
 
-cellbase:
-	  /* empty */
-		{
-			$$ = 16;
-		}
-	| DT_BASE
-	;
-
 cellval:
 	  DT_LITERAL
 		{
 			$$ = eval_literal($1, 0, 32);
 		}
-	| cellbase DT_LEGACYLITERAL
-		{
-			$$ = eval_literal($2, $1, 32);
-		}
 	;
 
 bytestring:
diff --git a/tests/base01.dts b/tests/base01.dts
index f84bc49..97a5dd5 100644
--- a/tests/base01.dts
+++ b/tests/base01.dts
@@ -1,3 +1,5 @@
+/dts-v1/;
+
 / {
 	model = "SomeModel";
 	compatible = "Nothing";
@@ -6,26 +8,26 @@
 
         memory@0 {
                 device_type = "memory";
-		reg = <00000000 00000000 00000000 20000000>;
+		reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
         };
 
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
-		d10 = <d# 10>;		// hex: 0xa
-		d23 = <d# 23>;		// hex: 0x17
-		b101 = <b# 101>;	// hex: 0x5
-		o17 = <o# 17>;		// hex: 0xf
-		hd00d = <h# d00d>;	// hex: 0xd00d
+		d10 = < 10>;		// hex: 0xa
+		d23 = < 23>;		// hex: 0x17
+		b101 = < 0x5>;	// hex: 0x5
+		o17 = < 017>;		// hex: 0xf
+		hd00d = < 0xd00d>;	// hex: 0xd00d
 
 		//   hex:  0x4d2    0x163e      0x2334    0xd80
-		stuff = <d# 1234    d# 5678    d# 9012    d# 3456>;
+		stuff = < 1234     5678     9012     3456>;
 
 
-		bad-d-1 = <d# abc123>;		// Hrm. 0
-		bad-d-2 = <d# 123456789012345>;
-		bad-o-1 = <o# 891>;
-		bad-o-2 = <o# 123456123456>;
+		bad-d-1 = < 0>;		// Hrm. 0
+		bad-d-2 = < 123456789012345>;
+		bad-o-1 = < 00>;
+		bad-o-2 = < 0123456123456>;
 	};
 
 };
diff --git a/tests/empty.dts b/tests/empty.dts
index 336d7a2..e160dad 100644
--- a/tests/empty.dts
+++ b/tests/empty.dts
@@ -1,2 +1,4 @@
+/dts-v1/;
+
 / {
 };
diff --git a/tests/escapes.dts b/tests/escapes.dts
index f1b8dbc..e05ab46 100644
--- a/tests/escapes.dts
+++ b/tests/escapes.dts
@@ -1,3 +1,5 @@
+/dts-v1/;
+
 / {
 	compatible = "test_string_escapes";
 	escape-str = "nastystring: \a\b\t\n\v\f\r\\\"";
diff --git a/tests/label01.dts b/tests/label01.dts
index 372b17a..a895803 100644
--- a/tests/label01.dts
+++ b/tests/label01.dts
@@ -1,6 +1,8 @@
-/memreserve/ 1000000000000000 0000000002000000;
-memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff;
-/memreserve/ 0-13;
+/dts-v1/;
+
+/memreserve/ 0x1000000000000000 0x0000000002000000;
+memrsv2: /memreserve/ 0x2000000000000000 0x0100000000000000;
+/memreserve/ 0x0000000000000000 0x0000000000000014;
 
 / {
 	model = "MyBoardName";
@@ -9,28 +11,28 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff;
 	#size-cells = <2>;
 
 	cpus {
-		linux,phandle = <1>;
+		linux,phandle = <0x1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		PowerPC,970@0 {
 			name = "PowerPC,970";
 			device_type = "cpu";
-			reg = <0>;
-			clock-frequency = <5f5e1000>;
-			timebase-frequency = <1FCA055>;
+			reg = <0x00000000>;
+			clock-frequency = <1600000000>;
+			timebase-frequency = <33333333>;
 			linux,boot-cpu;
-			i-cache-size = <10000>;
-			d-cache-size = <8000>;
+			i-cache-size = <65536>;
+			d-cache-size = <32768>;
 		};
 
 		PowerPC,970@1 {
 			name = "PowerPC,970";
 			device_type = "cpu";
-			reg = <1>;
-			clock-frequency = <5f5e1000>;
-			timebase-frequency = <1FCA055>;
-			i-cache-size = <10000>;
-			d-cache-size = <8000>;
+			reg = <0x00000001>;
+			clock-frequency = <1600000000>;
+			timebase-frequency = <33333333>;
+			i-cache-size = <65536>;
+			d-cache-size = <32768>;
 		};
 
 	};
@@ -38,8 +40,8 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff;
 	node: randomnode {
 		prop: string = str: "foo", str_mid: "stuffstuff\t\t\t\n\n\n" str_end: ;
 		blob = [byte: 0a 0b 0c 0d byte_mid: de ea ad be ef byte_end: ];
-		ref = < cell: &/memory@0 0 cell_mid: ffffffff cell_end: >;
-		mixed = "abc", pre: [1234] post: , gap: < aligned: a b c>;
+		ref = < cell: &{/memory@0} 0x0 cell_mid: 0xffffffff cell_end: >;
+		mixed = "abc", pre: [1234] post: , gap: < aligned: 0xa 0xb 0xc>;
 		tricky1 = [61 lt1: 62 63 00];
 		subnode: child {
 		};
@@ -49,12 +51,12 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff;
 
 	memory@0 {
 		device_type = "memory";
-		memreg: reg = <00000000 00000000 00000000 20000000>;
+		memreg: reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
 	};
 
 	chosen {
 		bootargs = "root=/dev/sda2";
-		linux,platform = <00000600>;
+		linux,platform = <0x600>;
 	};
 
 };
diff --git a/tests/references_dts0.dts b/tests/references_dts0.dts
index df82c23..36b6f51 100644
--- a/tests/references_dts0.dts
+++ b/tests/references_dts0.dts
@@ -1,19 +1,21 @@
+/dts-v1/;
+
 / {
 	/* Explicit phandles */
 	n1: node1 {
-		linux,phandle = <2000>;
-		ref = <&/node2>; /* reference precedes target */
+		linux,phandle = <0x2000>;
+		ref = <&{/node2}>; /* reference precedes target */
 		lref = <&n2>;
 	};
 	n2: node2 {
-		linux,phandle = <1>;
-		ref = <&/node1>; /* reference after target */
+		linux,phandle = <0x1>;
+		ref = <&{/node1}>; /* reference after target */
 		lref = <&n1>;
 	};
 
 	/* Implicit phandles */
 	n3: node3 {
-		ref = <&/node4>;
+		ref = <&{/node4}>;
 		lref = <&n4>;
 	};
 	n4: node4 {
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index eb29462..30cd9a1 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -71,13 +71,6 @@ run_dtc_test () {
     base_run_test wrap_test $VALGRIND $DTC "$@"
 }
 
-CONVERT=../convert-dtsv0
-
-run_convert_test () {
-    echo -n "convert-dtsv0 $@:	"
-    base_run_test wrap_test $VALGRIND $CONVERT "$@"
-}
-
 tree1_tests () {
     TREE=$1
 
@@ -287,21 +280,6 @@ dtc_tests () {
     run_sh_test dtc-fatal.sh -I fs -O dtb nosuchfile
 }
 
-convert_tests () {
-    V0_DTS="test_tree1_dts0.dts references_dts0.dts empty.dts escapes.dts \
-	test01.dts label01.dts"
-    for dts in $V0_DTS; do
-	run_dtc_test -I dts -O dtb -o cvtraw_$dts.test.dtb $dts
-	run_dtc_test -I dts -O dts -o cvtdtc_$dts.test.dts $dts
-	run_dtc_test -I dts -O dtb -o cvtdtc_$dts.test.dtb cvtdtc_$dts.test.dts
-	run_convert_test $dts
-	run_dtc_test -I dts -O dtb -o cvtcvt_$dts.test.dtb ${dts}v1
-
-	run_wrap_test cmp cvtraw_$dts.test.dtb cvtdtc_$dts.test.dtb
-	run_wrap_test cmp cvtraw_$dts.test.dtb cvtcvt_$dts.test.dtb
-    done
-}
-
 while getopts "vt:m" ARG ; do
     case $ARG in
 	"v")
@@ -317,7 +295,7 @@ while getopts "vt:m" ARG ; do
 done
 
 if [ -z "$TESTSETS" ]; then
-    TESTSETS="libfdt dtc convert"
+    TESTSETS="libfdt dtc"
 fi
 
 # Make sure we don't have stale blobs lying around
@@ -331,9 +309,6 @@ for set in $TESTSETS; do
 	"dtc")
 	    dtc_tests
 	    ;;
-	"convert")
-	    convert_tests
-	    ;;
     esac
 done
 
diff --git a/tests/test01.dts b/tests/test01.dts
index ed2b178..f9fd165 100644
--- a/tests/test01.dts
+++ b/tests/test01.dts
@@ -1,6 +1,8 @@
-/memreserve/ 1000000000000000 0000000002000000;
-/memreserve/ 2000000000000000-20ffffffffffffff;
-/memreserve/ 0-13;
+/dts-v1/;
+
+/memreserve/ 0x1000000000000000 0x0000000002000000;
+/memreserve/ 0x2000000000000000 0x0100000000000000;
+/memreserve/ 0x0000000000000000 0x0000000000000014;
 
 / {
 	model = "MyBoardName";
@@ -9,28 +11,28 @@
 	#size-cells = <2>;
 
 	cpus {
-		linux,phandle = <1>;
+		linux,phandle = <0x1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		PowerPC,970@0 {
 			name = "PowerPC,970";
 			device_type = "cpu";
-			reg = <0>;
-			clock-frequency = <5f5e1000>;
-			timebase-frequency = <1FCA055>;
+			reg = <0x00000000>;
+			clock-frequency = <1600000000>;
+			timebase-frequency = <33333333>;
 			linux,boot-cpu;
-			i-cache-size = <10000>;
-			d-cache-size = <8000>;
+			i-cache-size = <65536>;
+			d-cache-size = <32768>;
 		};
 
 		PowerPC,970@1 {
 			name = "PowerPC,970";
 			device_type = "cpu";
-			reg = <1>;
-			clock-frequency = <5f5e1000>;
-			timebase-frequency = <1FCA055>;
-			i-cache-size = <10000>;
-			d-cache-size = <8000>;
+			reg = <0x00000001>;
+			clock-frequency = <1600000000>;
+			timebase-frequency = <33333333>;
+			i-cache-size = <65536>;
+			d-cache-size = <32768>;
 		};
 
 	};
@@ -38,18 +40,18 @@
 	randomnode {
 		string = "\xff\0stuffstuff\t\t\t\n\n\n";
 		blob = [0a 0b 0c 0d de ea ad be ef];
-		ref = < &/memory@0 >;
-		mixed = "abc", [1234], <a b c>;
+		ref = < &{/memory@0} >;
+		mixed = "abc", [1234], <0xa 0xb 0xc>;
 	};
 
 	memory@0 {
 		device_type = "memory";
-		memreg: reg = <00000000 00000000 00000000 20000000>;
+		memreg: reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
 	};
 
 	chosen {
 		bootargs = "root=/dev/sda2";
-		linux,platform = <00000600>;
+		linux,platform = <0x600>;
 	};
 
 };
diff --git a/tests/test_tree1_dts0.dts b/tests/test_tree1_dts0.dts
index bc65819..6b40cf5 100644
--- a/tests/test_tree1_dts0.dts
+++ b/tests/test_tree1_dts0.dts
@@ -1,9 +1,11 @@
-/memreserve/ deadbeef00000000-deadbeef000fffff;
-/memreserve/ 75bcd15 1000;
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x0000000000100000;
+/memreserve/ 0x00000000075bcd15 0x0000000000001000;
 
 / {
 	compatible = "test_tree1";
-	prop-int = <deadbeef>;
+	prop-int = <0xdeadbeef>;
 	prop-str = "hello world";
 
 	subnode@1 {
@@ -12,18 +14,18 @@
 
 		subsubnode {
 			compatible = "subsubnode1", "subsubnode";
-			prop-int = <h# deadbeef>;
+			prop-int = < 0xdeadbeef>;
 		};
 	};
 
 	subnode@2 {
-		linux,phandle = <2000>;
-		prop-int = <d# 123456789>;
+		linux,phandle = <0x2000>;
+		prop-int = < 123456789>;
 
 		subsubnode@0 {
-			linux,phandle = <2001>;
+			linux,phandle = <0x2001>;
 			compatible = "subsubnode2", "subsubnode";
-			prop-int = <o# 0726746425>;
+			prop-int = < 0726746425>;
 		};
 	};
 };
-- 
1.6.0.90.g436ed

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 2/9 V3] Add conditionalized debug() print macro.
       [not found]     ` <1222460748-20127-2-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-26 20:25       ` Jon Loeliger
       [not found]         ` <1222460748-20127-3-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
  2008-09-30  5:57       ` [PATCH 1/9 V3] Remove support for the legacy DTS source file format David Gibson
  1 sibling, 1 reply; 79+ messages in thread
From: Jon Loeliger @ 2008-09-26 20:25 UTC (permalink / raw)
  To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

From: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>

Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 dtc.h |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/dtc.h b/dtc.h
index 08d54c8..ec636f8 100644
--- a/dtc.h
+++ b/dtc.h
@@ -34,7 +34,15 @@
 #include <libfdt_env.h>
 #include <fdt.h>
 
+#ifdef DEBUG
+#define debug(fmt,args...)	printf(fmt, ##args)
+#else
+#define debug(fmt,args...)
+#endif
+
+
 #define DEFAULT_FDT_VERSION	17
+
 /*
  * Command line options
  */
-- 
1.6.0.90.g436ed

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 3/9 V3] Enhance source position implementation.
       [not found]         ` <1222460748-20127-3-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-26 20:25           ` Jon Loeliger
       [not found]             ` <1222460748-20127-4-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Jon Loeliger @ 2008-09-26 20:25 UTC (permalink / raw)
  To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

Implemented some print and copy routines.
Made empty srcpos objects that will be used later.
Protected .h file from multiple #include's.

Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 srcpos.c |   95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 srcpos.h |   19 ++++++++++++
 2 files changed, 107 insertions(+), 7 deletions(-)

diff --git a/srcpos.c b/srcpos.c
index 9641b76..59d1835 100644
--- a/srcpos.c
+++ b/srcpos.c
@@ -23,12 +23,29 @@
 /*
  * Like yylineno, this is the current open file pos.
  */
-
 struct dtc_file *srcpos_file;
 
-static int dtc_open_one(struct dtc_file *file,
-                        const char *search,
-                        const char *fname)
+/*
+ * The empty source position.
+ */
+
+struct dtc_file dtc_empty_file = {
+	.dir = NULL,
+	.name = "<no file>",
+	.file = NULL
+};
+
+srcpos srcpos_empty = {
+	.first_line = 0,
+	.first_column = 0,
+	.last_line = 0,
+	.last_column = 0,
+	.file = &dtc_empty_file
+};
+
+
+static int
+dtc_open_one(struct dtc_file *file, const char *search, const char *fname)
 {
 	char *fullname;
 
@@ -53,8 +70,8 @@ static int dtc_open_one(struct dtc_file *file,
 }
 
 
-struct dtc_file *dtc_open_file(const char *fname,
-                               const struct search_path *search)
+struct dtc_file *
+dtc_open_file(const char *fname, const struct search_path *search)
 {
 	static const struct search_path default_search = { NULL, NULL, NULL };
 
@@ -106,7 +123,9 @@ fail:
 	die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
 }
 
-void dtc_close_file(struct dtc_file *file)
+
+void
+dtc_close_file(struct dtc_file *file)
 {
 	if (fclose(file->file))
 		die("Error closing \"%s\": %s\n", file->name, strerror(errno));
@@ -114,3 +133,65 @@ void dtc_close_file(struct dtc_file *file)
 	free(file->dir);
 	free(file);
 }
+
+
+srcpos *
+srcpos_copy(srcpos *pos)
+{
+	srcpos *pos_new;
+
+	pos_new = xmalloc(sizeof(srcpos));
+	memcpy(pos_new, pos, sizeof(srcpos));
+
+	return pos_new;
+}
+
+
+
+void
+srcpos_dump(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(srcpos *pos)
+{
+#	define POS_BUF_SIZE	(100)
+
+	const char *fname;
+	char buf[POS_BUF_SIZE];
+
+	if (pos->file && pos->file->name)
+		fname = pos->file->name;
+	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);
+		} else {
+			snprintf(buf, POS_BUF_SIZE, "%s %d:%d-%d",
+				 fname, pos->first_line,
+				 pos->first_column, pos->last_column);
+		}
+
+	} else {
+		snprintf(buf, POS_BUF_SIZE, "%s %d:%d - %d:%d",
+			 fname,
+			 pos->first_line, pos->first_column,
+			 pos->last_line, pos->last_column);
+	}
+
+	return strdup(buf);
+
+#	undef POS_BUF_SIZE
+}
diff --git a/srcpos.h b/srcpos.h
index e17c7c0..3c39dd0 100644
--- a/srcpos.h
+++ b/srcpos.h
@@ -17,6 +17,9 @@
  *                                                                   USA
  */
 
+#ifndef _SRCPOS_H_
+#define _SRCPOS_H_
+
 /*
  * Augment the standard YYLTYPE with a filenum index into an
  * array of all opened filenames.
@@ -69,6 +72,16 @@ typedef struct YYLTYPE {
     while (YYID (0))
 
 
+typedef YYLTYPE srcpos;
+
+/*
+ * 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 srcpos srcpos_empty;
+
+
 
 extern void yyerror(char const *);
 extern void yyerrorf(char const *, ...) __attribute__((format(printf, 1, 2)));
@@ -83,3 +96,9 @@ struct search_path {
 extern struct dtc_file *dtc_open_file(const char *fname,
                                       const struct search_path *search);
 extern void dtc_close_file(struct dtc_file *file);
+
+extern srcpos *srcpos_copy(srcpos *pos);
+extern char *srcpos_string(srcpos *pos);
+extern void srcpos_dump(srcpos *pos);
+
+#endif /* _SRCPOS_H_ */
-- 
1.6.0.90.g436ed

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 4/9 V3] Add header files for new Internal Representation form.
       [not found]             ` <1222460748-20127-4-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-26 20:25               ` Jon Loeliger
       [not found]                 ` <1222460748-20127-5-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
  2008-09-30  6:00               ` [PATCH 3/9 V3] Enhance source position implementation David Gibson
  1 sibling, 1 reply; 79+ messages in thread
From: Jon Loeliger @ 2008-09-26 20:25 UTC (permalink / raw)
  To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 ir.h         |  176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ir_builtin.h |   31 ++++++++++
 ir_scope.h   |  114 +++++++++++++++++++++++++++++++++++++
 3 files changed, 321 insertions(+), 0 deletions(-)
 create mode 100644 ir.h
 create mode 100644 ir_builtin.h
 create mode 100644 ir_scope.h

diff --git a/ir.h b/ir.h
new file mode 100644
index 0000000..630ec52
--- /dev/null
+++ b/ir.h
@@ -0,0 +1,176 @@
+/*
+ * 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 _IR_H_
+#define _IR_H_
+
+#include "srcpos.h"
+#include "ir_builtin.h"
+
+
+#define IR_UNDEF	0
+#define IR_ROOT		1
+#define IR_MEM_RESERVE	2
+#define IR_ASSIGN	3
+#define IR_PROP_DEF	4
+#define IR_REF_PHANDLE	5
+#define IR_REF_PATH	6
+#define IR_CELL		7
+#define IR_LITERAL	8
+#define IR_LIT_STR	9
+#define IR_LIT_BYTE	10
+#define IR_LABEL	11
+#define IR_LIST		12
+#define IR_INCBIN	13
+#define IR_BUILTIN	14
+#define IR_SELECT	15
+#define IR_OR		16
+#define IR_AND		17
+#define IR_BIT_OR	18
+#define IR_BIT_XOR	19
+#define IR_BIT_AND	20
+#define IR_EQ		21
+#define IR_LT		22
+#define IR_LE		23
+#define IR_GT		24
+#define IR_GE		25
+#define IR_NE		26
+#define IR_LSHIFT	27
+#define IR_RSHIFT	28
+#define IR_ADD		29
+#define IR_MINUS	30
+#define IR_MULT		31
+#define IR_DIV		32
+#define IR_MOD		33
+#define IR_UMINUS	34
+#define IR_BIT_COMPL	35
+#define IR_NOT		36
+#define IR_FUNC_DEF	37
+#define IR_FOR		38
+#define IR_RETURN	39
+#define IR_RANGE	40
+#define IR_ID		41
+#define IR_IF		42
+#define IR_PARAMDECL	43
+#define IR_FUNC_CALL	44
+#define IR_NODE		45
+#define IR_PROPNODENAME	46
+#define IR_LIT_CELL	47
+#define IR_LIT_ADDR	48
+#define IR_CVT_PROPNODENAME	49
+#define IR_CVT_STRING	50
+#define IR_CONST_DEF	51
+
+#define IR_NUM_TYPES	52
+
+
+typedef unsigned int ir_type;
+
+extern char const *ir_type_string(ir_type ir_type);
+
+
+struct ir {
+	ir_type ir_type;
+	srcpos *ir_srcpos;
+
+	long long ir_literal;
+	char *ir_lit_str;
+	char *ir_label_name;
+	irb_id ir_builtin_id;
+
+	struct ir *ir_name;
+	struct ir *ir_label;
+	struct ir *ir_expr1;
+	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;
+
+	struct ir *ir_first;
+	struct ir *ir_last;
+	struct ir *ir_prev;
+	struct ir *ir_next;
+};
+
+
+extern struct ir *the_ir_tree;
+
+extern struct ir *ir_alloc(ir_type ir_type, srcpos *);
+extern struct ir *ir_copy(struct ir *ir);	/* shallow copy */
+extern void ir_free(struct ir *ir);
+extern void ir_free_all(struct ir *ir);
+
+extern struct ir *ir_alloc_unop(ir_type ir_type,
+				struct ir *ir1,
+				srcpos *pos);
+extern struct ir *ir_alloc_binop(ir_type ir_type,
+				 struct ir *ir1,
+				 struct ir *ir2,
+				 srcpos *pos);
+extern struct ir *ir_alloc_triop(ir_type ir_type,
+				 struct ir *ir1,
+				 struct ir *ir2,
+				 struct ir *ir3,
+				 srcpos *pos);
+extern struct ir *ir_list_append(struct ir *ir_list, struct ir *ir_node);
+extern void ir_dump(struct ir *ir);
+extern struct ir *ir_eval(struct ir *ir);
+extern struct ir_scope *ir_eval_func_body(struct ir *ir_func);
+
+extern void ir_process(void);
+extern struct ir *ir_simplify(struct ir *ir, unsigned int ctxt);
+extern void ir_emit(struct ir *ir);
+extern void ir_emit_statement_list(struct ir *ir_list);
+
+
+#define IR_EVAL_CTXT_ANY	0
+#define IR_EVAL_CTXT_CELL	1
+
+extern int ir_is_constant(struct ir *ir);
+extern int ir_is_string(struct ir *ir);
+extern char *ir_eval_for_label(struct ir *ir);
+extern char *ir_eval_for_name(struct ir *ir);
+extern uint64_t ir_eval_for_addr(struct ir *ir);
+extern void ir_eval_for_data(struct ir *ir, struct data *d);
+extern char *ir_eval_for_c_string(struct ir *ir);
+
+
+/*
+ * IR Messaging.
+ */
+
+#define IR_SEV_INFO	0
+#define IR_SEV_WARN	1
+#define IR_SEV_ERROR	2
+
+typedef	unsigned int ir_severity_t;
+
+#define ir_info(ir, fmt...)	ir_msg(IR_SEV_INFO, ir, ##fmt)
+#define ir_warn(ir, fmt...)	ir_msg(IR_SEV_WARN, ir, ##fmt)
+#define ir_error(ir, fmt...)	ir_msg(IR_SEV_ERROR, ir, ##fmt)
+
+extern void ir_msg(ir_severity_t severity,
+		   struct ir *ir,
+		   char const *fmt, ...)
+     __attribute__((format(printf, 3, 4)));
+
+#endif /* _IR_H_ */
diff --git a/ir_builtin.h b/ir_builtin.h
new file mode 100644
index 0000000..8dfed67
--- /dev/null
+++ b/ir_builtin.h
@@ -0,0 +1,31 @@
+/*
+ * 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 _IR_BUILTIN_H_
+#define _IR_BUILTIN_H_
+
+
+typedef int irb_id;
+
+#define IRB_UNDEF	(-1)
+
+extern irb_id ir_lookup_builtin_by_name(char *str_name);
+extern struct ir *ir_eval_builtin(struct ir *ir);
+
+#endif /* _IR_BUILTIN_H_ */
diff --git a/ir_scope.h b/ir_scope.h
new file mode 100644
index 0000000..4529d50
--- /dev/null
+++ b/ir_scope.h
@@ -0,0 +1,114 @@
+/*
+ * 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 _IR_SCOPE_H_
+#define _IR_SCOPE_H_
+
+/*
+ * IR Symbols and Symbol Tables
+ *
+ * Each ir_scope structure can have its own Symbol Table, represented
+ * as a simple linked list of symbols.
+ *
+ * As the number of symbols and scopes is expected to be relatively
+ * small (dozens total), and not large (hundreds or more), the
+ * current implementation is a dead-simple brute force linear search
+ * of a Symbol Table.
+ *
+ * Symbol Table operations (add, lookup) are implicitly performed
+ * relative to the IR Scope Stack.
+ *
+ * During evaluation of the IR form, each symbol can have at most
+ * one value, represented as an IR expression.  In the case of
+ * variables (or constants), the IR expression should be a
+ * literal of some type.  For function definitions, the expression
+ * is the complete IR representation of the function definition.
+ */
+
+#define IRSYM_NONE	0
+#define IRSYM_VAR	1
+#define IRSYM_FUNCDEF	2
+#define IRSYM_PARAM	3
+#define IRSYM_CONST	4
+
+#define IRSYM_NUM_TYPES	5
+
+typedef unsigned int irsym_type;
+
+struct ir_symbol {
+	irsym_type irsym_type;
+	char *irsym_name;
+	struct ir *irsym_value;
+	struct ir_symbol *irsym_next;
+};
+
+
+
+/*
+ * IR Evaluation Scope
+ */
+
+#define IRS_NONE	0x00
+#define IRS_ROOT	0x01
+#define IRS_NODE	0x02
+#define IRS_FOR_LOOP	0x04
+#define IRS_FUNC_CALL	0x08
+
+#define IRS_MAX_BIT	IRS_FUNC_CALL
+#define IRS_ANY		0xFF
+
+typedef unsigned int irs_type;
+
+struct ir_scope {
+	irs_type irs_type;
+	struct ir_symbol *irs_symtab;
+	struct ir *irs_expr;
+	struct reserve_info *irs_reserve_list;
+	struct property *irs_prop_list;
+	struct node *irs_node_list;
+
+	struct ir_scope *irs_next;
+};
+
+/*
+ * Each entry on this stack provides an evaluation environment.
+ */
+extern struct ir_scope *irs_scope_stack;
+
+extern void irs_push_scope(irs_type irs_type);
+extern struct ir_scope *irs_pop_scope(void);
+
+extern void irs_append_reserve(struct reserve_info *ri);
+extern void irs_append_property(struct property *p);
+extern void irs_append_node(struct node *n);
+extern void irs_scope_append_node_list(struct node *nl);
+extern void irs_scope_append_property_list(struct property *pl);
+extern void irs_set_return_value(struct ir *ir_ret);
+
+extern struct ir_symbol *irs_alloc_symbol(char *name, irsym_type irsym_type);
+extern struct ir_symbol *irs_lookup_in_scope(struct ir_scope *irs, char *name);
+extern struct ir_symbol *irs_lookup(char *name, irs_type irs_type);
+extern struct ir_symbol *irs_lookup_local(char *name);
+extern struct ir_symbol *irs_create_local(char *name, irsym_type irsym_type);
+extern struct ir_symbol *irs_create_symbol(irs_type irs_type,
+					   char *name,
+					   irsym_type irsym_type);
+extern void irs_dump_symbols(void);
+
+#endif /* _IR_SCOPE_H_ */
-- 
1.6.0.90.g436ed

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 5/9 V3] Add most of the new IR implementation files.
       [not found]                 ` <1222460748-20127-5-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-26 20:25                   ` Jon Loeliger
       [not found]                     ` <1222460748-20127-6-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
  2008-09-30  6:03                   ` [PATCH 4/9 V3] Add header files for new Internal Representation form David Gibson
  1 sibling, 1 reply; 79+ messages in thread
From: Jon Loeliger @ 2008-09-26 20:25 UTC (permalink / raw)
  To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 ir.c         |  190 ++++++++++++++++++++++
 ir_builtin.c |  180 +++++++++++++++++++++
 ir_dump.c    |  220 ++++++++++++++++++++++++++
 ir_emit.c    |  491 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ir_scope.c   |  319 +++++++++++++++++++++++++++++++++++++
 5 files changed, 1400 insertions(+), 0 deletions(-)
 create mode 100644 ir.c
 create mode 100644 ir_builtin.c
 create mode 100644 ir_dump.c
 create mode 100644 ir_emit.c
 create mode 100644 ir_scope.c

diff --git a/ir.c b/ir.c
new file mode 100644
index 0000000..7ebe806
--- /dev/null
+++ b/ir.c
@@ -0,0 +1,190 @@
+/*
+ * 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 "ir.h"
+
+extern int treesource_error;
+
+
+struct ir *the_ir_tree;
+
+
+extern struct ir *
+ir_alloc(ir_type ir_type, srcpos *pos)
+{
+	struct ir *ir;
+
+	ir = xmalloc(sizeof(struct ir));
+	memset(ir, 0, sizeof(struct ir));
+
+	ir->ir_type = ir_type;
+	ir->ir_srcpos = srcpos_copy(pos);
+
+	return ir;
+}
+
+
+/*
+ * Shallow copy, mostly.
+ *
+ * Note that things like the immediate strings and source position
+ * are copied, but the sub-IR-expressions are not.
+ */
+extern struct ir *
+ir_copy(struct ir *ir)
+{
+	struct ir *ir_new;
+
+	if (!ir)
+		return NULL;
+
+	ir_new = ir_alloc(ir->ir_type, ir->ir_srcpos);
+	ir_new->ir_literal = ir->ir_literal;
+	if (ir->ir_lit_str)
+		ir_new->ir_lit_str = strdup(ir->ir_lit_str);
+	if (ir->ir_label_name)
+		ir_new->ir_label_name = strdup(ir->ir_label_name);
+
+	return ir_new;
+}
+
+
+void
+ir_free(struct ir *ir)
+{
+}
+
+
+void
+ir_free_all(struct ir *ir)
+{
+}
+
+
+extern struct ir *
+ir_alloc_unop(ir_type ir_type, struct ir *ir1, srcpos *pos)
+{
+    struct ir *ir;
+
+    ir = ir_alloc(ir_type, pos);
+    ir->ir_expr1 = ir1;
+
+    return ir;
+}
+
+
+extern struct ir *
+ir_alloc_binop(ir_type ir_type,
+	       struct ir *ir1, struct ir *ir2,
+	       srcpos *pos)
+{
+    struct ir *ir;
+
+    ir = ir_alloc(ir_type, pos);
+    ir->ir_expr1 = ir1;
+    ir->ir_expr2 = ir2;
+
+    return ir;
+}
+
+
+extern struct ir *
+ir_alloc_triop(ir_type ir_type,
+	       struct ir *ir1, struct ir *ir2, struct ir *ir3,
+	       srcpos *pos)
+{
+    struct ir *ir;
+
+    ir = ir_alloc(ir_type, pos);
+    ir->ir_expr1 = ir1;
+    ir->ir_expr2 = ir2;
+    ir->ir_expr3 = ir3;
+
+    return ir;
+}
+
+
+extern struct ir *
+ir_list_append(struct ir *ir_list, struct ir *ir_node)
+{
+	if (ir_node == NULL) {
+		return ir_list;
+	}
+
+	if (ir_list == NULL) {
+		ir_list = ir_alloc(IR_LIST, ir_node->ir_srcpos);
+	}
+
+	ir_node->ir_prev = ir_list->ir_last;
+
+	if (ir_list->ir_last) {
+		ir_list->ir_last->ir_next = ir_node;
+	} else {
+		ir_list->ir_first = ir_node;
+	}
+
+	ir_list->ir_last = ir_node;
+
+	return ir_list;
+}
+
+
+void
+ir_process(void)
+{
+	/*
+	 * FIXME: Fix leaking the whole orginal IR tree here.
+	 */
+	the_ir_tree = ir_simplify(the_ir_tree, IR_EVAL_CTXT_ANY);
+
+	ir_emit(the_ir_tree);
+}
+
+
+static const char *ir_severity_str[] = {
+        "Info",
+	"Warning",
+	"Error",
+};
+
+#define IR_NUM_SEV	ARRAY_SIZE(ir_severity_str)
+
+
+void
+ir_msg(ir_severity_t severity, struct ir *ir, char const *fmt, ...)
+{
+	srcpos *pos;
+	const char *srcstr;
+	va_list va;
+	va_start(va, fmt);
+
+	pos = ir ? ir->ir_srcpos : &srcpos_empty;
+	srcstr = srcpos_string(pos);
+
+	if (severity >= IR_NUM_SEV)
+		severity = IR_SEV_INFO;
+
+	fprintf(stderr, "%s: %s ", ir_severity_str[severity], srcstr);
+
+	vfprintf(stderr, fmt, va);
+	fprintf(stderr, "\n");
+
+	va_end(va);
+}
diff --git a/ir_builtin.c b/ir_builtin.c
new file mode 100644
index 0000000..c448502
--- /dev/null
+++ b/ir_builtin.c
@@ -0,0 +1,180 @@
+/*
+ * 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 <stdio.h>
+
+#include "dtc.h"
+#include "ir.h"
+
+
+typedef struct ir * (*irb_impl_func)(struct ir *ir_params);
+
+struct builtin_func {
+	char *name;
+	irb_impl_func implementation;
+};
+
+struct ir *ir_builtin_join(struct ir *ir_params);
+struct ir *ir_builtin_hexstr(struct ir *ir_params);
+
+static const struct builtin_func builtin_table[] = {
+	{ "join", ir_builtin_join },
+	{ "hexstr", ir_builtin_hexstr },
+};
+
+#define IRB_NUM_BUILTINS	ARRAY_SIZE(builtin_table)
+
+
+irb_id
+ir_lookup_builtin_by_name(char *str_name)
+{
+	irb_id irb;
+
+	for (irb = 0; irb < IRB_NUM_BUILTINS; irb++) {
+		if (strcmp(builtin_table[irb].name, str_name) == 0) {
+			return irb;
+		}
+	}
+
+	return IRB_UNDEF;
+}
+
+
+struct ir *
+ir_eval_builtin(struct ir *ir)
+{
+	irb_id irb;
+	const struct builtin_func *bf;
+
+	if (ir == NULL)
+		return NULL;
+
+	if (ir->ir_type != IR_BUILTIN)
+		return NULL;
+
+	irb = ir->ir_builtin_id;
+
+	if (irb <= IRB_UNDEF || irb >= IRB_NUM_BUILTINS)
+		return NULL;
+
+	bf = &builtin_table[irb];
+
+	return (*bf->implementation)(ir);
+}
+
+
+struct ir *
+ir_builtin_join(struct ir *ir_builtin)
+{
+	struct ir *ir_new;
+	struct ir *irp;
+	struct ir *ir;
+	char *s;
+	char *str;
+	int len;
+	char buf[30];
+
+	debug("ir_builtin_impl_join():\n");
+
+	irp = ir_builtin->ir_expr1;
+	if (irp->ir_type == IR_LIST)
+		irp = irp->ir_first;
+
+	len = 1;
+	str = xmalloc(1);
+	*str  = 0;
+
+	while (irp != NULL) {
+		ir = ir_eval(irp);
+
+		if (ir_is_string(ir)) {
+			s = ir_eval_for_c_string(ir);
+		} else if (ir_is_constant(ir)) {
+			unsigned long long a;
+			a = ir_eval_for_addr(ir);
+			snprintf(buf, sizeof(buf), "%llu", a);
+			s = buf;
+		} else {
+			ir_error(ir,
+				 "Can't handle %s in join()\n",
+				 ir_type_string(ir->ir_type));
+			s = 0;
+		}
+
+		len += strlen(s);
+
+		str = xrealloc(str, len);
+		strcat(str, s);
+
+		irp = irp->ir_next;
+	}
+
+	ir_new = ir_alloc(IR_LIT_STR, ir_builtin->ir_srcpos);
+	ir_new->ir_lit_str = str;
+
+	return ir_new;
+}
+
+
+
+struct ir *
+ir_builtin_hexstr(struct ir *ir_builtin)
+{
+	struct ir *ir_new;
+	struct ir *irp;
+	struct ir *ir;
+	char *s;
+	char *str;
+	int len;
+	char buf[30];
+
+	irp = ir_builtin->ir_expr1;
+	if (irp->ir_type == IR_LIST)
+		irp = irp->ir_first;
+
+	len = 1;
+	str = xmalloc(1);
+	*str  = 0;
+
+	while (irp != NULL) {
+		ir = ir_eval(irp);
+		if (ir_is_constant(ir)) {
+			unsigned long long a;
+			a = ir_eval_for_addr(ir);
+			snprintf(buf, 30, "%llx", a);
+			s = buf;
+		} else {
+			ir_error(ir,
+				 "Can't handle %s in hexstr()\n",
+				 ir_type_string(ir->ir_type));
+			s = 0;
+		}
+		len += strlen(s);
+
+		str = xrealloc(str, len);
+		strcat(str, s);
+
+		irp = irp->ir_next;
+	}
+
+	ir_new = ir_alloc(IR_LIT_STR, ir_builtin->ir_srcpos);
+	ir_new->ir_lit_str = str;
+
+	return ir_new;
+}
diff --git a/ir_dump.c b/ir_dump.c
new file mode 100644
index 0000000..f949423
--- /dev/null
+++ b/ir_dump.c
@@ -0,0 +1,220 @@
+/*
+ * 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 <stdio.h>
+
+#include "dtc.h"
+#include "ir.h"
+
+
+static const char *ir_type_str[IR_NUM_TYPES] = {
+	"IR_UNDEF",
+	"IR_ROOT",
+	"IR_MEM_RESERVE",
+	"IR_ASSIGN",
+	"IR_PROP_DEF",
+	"IR_REF_PHANDLE",
+	"IR_REF_PATH",
+	"IR_CELL",
+	"IR_LITERAL",
+	"IR_LIT_STR",
+	"IR_LIT_BYTE",
+	"IR_LABEL",
+	"IR_LIST",
+	"IR_INCBIN",
+	"IR_BUILTIN",
+	"IR_SELECT",
+	"IR_OR",
+	"IR_AND",
+	"IR_BIT_OR",
+	"IR_BIT_XOR",
+	"IR_BIT_AND",
+	"IR_EQ",
+	"IR_LT",
+	"IR_LE",
+	"IR_GT",
+	"IR_GE",
+	"IR_NE",
+	"IR_LSHIFT",
+	"IR_RSHIFT",
+	"IR_ADD",
+	"IR_MINUS",
+	"IR_MULT",
+	"IR_DIV",
+	"IR_MOD",
+	"IR_UMINUS",
+	"IR_BIT_COMPL",
+	"IR_NOT",
+	"IR_FUNC_DEF",
+	"IR_FOR",
+	"IR_RETURN",
+	"IR_RANGE",
+	"IR_ID",
+	"IR_IF",
+	"IR_PARAMDECL",
+	"IR_FUNC_CALL",
+	"IR_NODE",
+	"IR_PROPNODENAME",
+	"IR_LIT_CELL",
+	"IR_LIT_ADDR",
+	"IR_CVT_PROPNODENAME",
+	"IR_CVT_STRING",
+	"IR_CONST_DEF",
+};
+
+
+const char *
+ir_type_string(ir_type ir_type)
+{
+	if (0 <= ir_type && ir_type < IR_NUM_TYPES)
+		return ir_type_str[ir_type];
+	else
+		return "<unknown>";
+}
+
+
+static void
+ir_dump_node(struct ir *ir, unsigned int level)
+{
+	int indent = 4 * level;
+	struct ir *iri;
+
+	if (ir == NULL)
+		return;
+
+	/*
+	 * Print node values
+	 */
+	printf("%*sNODE       : %p\n",
+	       indent, "", ir);
+
+	printf("%*sir_type    : %s\n",
+	       indent, "", ir_type_string(ir->ir_type));
+
+	printf("%*sir_srcpos : %s\n",
+	       indent, "", srcpos_string(ir->ir_srcpos));
+
+
+	printf("%*sir_literal : %lld\n", indent, "", ir->ir_literal);
+
+	if (ir->ir_builtin_id != IRB_UNDEF) {
+		printf("%*sir_builtin_id : %d\n",
+		       indent, "", ir->ir_builtin_id);
+	}
+	if (ir->ir_lit_str) {
+		printf("%*sir_lit_str : %s\n",
+		       indent, "", ir->ir_lit_str);
+	}
+	if (ir->ir_label_name) {
+		printf("%*sir_label_name : %s\n",
+		       indent, "", ir->ir_label_name);
+	}
+
+	if (ir->ir_name) {
+		printf("%*sir_name   : %p\n",
+		       indent, "", ir->ir_name);
+		ir_dump_node(ir->ir_name, level + 1);
+	}
+
+	if (ir->ir_label) {
+		printf("%*sir_label   : %p\n",
+		       indent, "", ir->ir_label);
+		ir_dump_node(ir->ir_label, level + 1);
+	}
+
+	if (ir->ir_first)
+		printf("%*sir_first   : %p\n",
+		       indent, "", ir->ir_first);
+	if (ir->ir_last)
+		printf("%*sir_last    : %p\n",
+		       indent, "", ir->ir_last);
+	if (ir->ir_next)
+		printf("%*sir_next    : %p\n",
+		       indent, "", ir->ir_next);
+	if (ir->ir_prev)
+		printf("%*sir_prev    : %p\n",
+		       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) {
+		printf("%*sir_expr1   : %p\n",
+		       indent, "", ir->ir_expr1);
+		ir_dump_node(ir->ir_expr1, level + 1);
+	}
+
+	if (ir->ir_expr2) {
+		printf("%*sir_expr2   : %p\n",
+		       indent, "", ir->ir_expr2);
+		ir_dump_node(ir->ir_expr2, level + 1);
+	}
+
+	if (ir->ir_expr3) {
+		printf("%*sir_expr3   : %p\n",
+		       indent, "", ir->ir_expr3);
+		ir_dump_node(ir->ir_expr3, level + 1);
+	}
+
+	/*
+	 * Recursively dump declarations.
+	 */
+	if (ir->ir_declarations) {
+		printf("%*sir_declarations: %p\n",
+		       indent, "", ir->ir_declarations);
+		ir_dump_node(ir->ir_declarations, level + 1);
+	}
+
+	/*
+	 * Recursively dump statements.
+	 */
+	if (ir->ir_statements) {
+		printf("%*sir_statements: %p\n",
+		       indent, "", ir->ir_statements);
+		ir_dump_node(ir->ir_statements, level + 1);
+	}
+	if (ir->ir_statements2) {
+		printf("%*sir_statements2: %p\n",
+		       indent, "", ir->ir_statements2);
+		ir_dump_node(ir->ir_statements2, level + 1);
+	}
+
+	/*
+	 * Recursively dump LIST chain.
+	 */
+	for (iri = ir->ir_first; iri != NULL; iri = iri->ir_next) {
+		ir_dump_node(iri, level + 1);
+	}
+}
+
+
+extern void
+ir_dump(struct ir *ir)
+{
+	ir_dump_node(ir, 0);
+}
diff --git a/ir_emit.c b/ir_emit.c
new file mode 100644
index 0000000..31005ca
--- /dev/null
+++ b/ir_emit.c
@@ -0,0 +1,491 @@
+/*
+ * 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 <stdio.h>
+
+#include "dtc.h"
+#include "ir.h"
+#include "ir_scope.h"
+#include "nv.h"
+
+extern struct boot_info *the_boot_info;
+
+
+void ir_emit_node(struct ir *ir);
+
+
+void
+ir_emit_prop_def(struct ir *irp)
+{
+	struct ir *ir_lhs;
+	struct property *p;
+	char *prop_name;
+	char *lab;
+	struct data d;
+
+	debug("ir_emit_prop_def(");
+
+	lab = ir_eval_for_label(irp->ir_label);
+	if (lab) {
+		debug("%s : ", lab);
+	}
+
+	ir_lhs = ir_eval(irp->ir_expr1);
+	prop_name = ir_eval_for_name(ir_lhs);
+	debug("%s = <expr>)\n", prop_name);
+
+	if (prop_name) {
+		d = empty_data;
+		ir_eval_for_data(irp->ir_expr2, &d);
+		p =  build_property(prop_name, d, lab);
+		irs_append_property(p);
+	}
+
+	debug("ir_emit_prop_def(): Done\n");
+}
+
+
+void
+ir_emit_assign(struct ir *ir_assign)
+{
+	char *var_name;
+	struct ir_symbol *irsym;
+	struct ir *ir_val;
+	struct ir *ir_pos;
+
+	ir_pos = ir_assign->ir_expr1 ? ir_assign->ir_expr1 : ir_assign;
+
+	var_name = ir_eval_for_name(ir_assign->ir_expr1);
+
+	debug("ir_emit_assign(%s)\n", var_name);
+
+	if (!var_name) {
+		ir_error(ir_pos, "Can't determine LHS name\n");
+		return;
+	}
+
+	irsym = irs_lookup_local(var_name);
+	if (irsym != NULL) {
+		if (irsym->irsym_type == IRSYM_CONST) {
+			ir_error(ir_pos,
+				 "Can't assign to constant \"%s\"\n",
+				 var_name);
+		}
+	} else {
+		/*
+		 * FIXME: Debate on-the-fly creation or pre-declaration.
+		 */
+		irsym = irs_create_local(var_name, IRSYM_VAR);
+	}
+
+	ir_val = ir_eval(ir_assign->ir_expr2);
+	irsym->irsym_value = ir_val;
+}
+
+
+void
+ir_emit_for(struct ir *ir_for)
+{
+	char *var_name;
+	struct ir_symbol *irsym;
+	struct ir *ir_id;
+	struct ir *ir_val;
+	struct ir *ir_range;
+	unsigned long long var;
+	unsigned long long start;
+	unsigned long long stop;
+
+	irs_push_scope(IRS_FOR_LOOP);
+
+	/*
+	 * Introduce for-loop variable into FOR_LOOP scope.
+	 */
+	ir_id = ir_for->ir_expr1;
+	var_name = ir_eval_for_name(ir_id);
+	irsym = irs_create_local(var_name, IRSYM_VAR);
+
+	ir_val = ir_alloc(IR_LIT_ADDR, ir_id->ir_srcpos);
+	irsym->irsym_value = ir_val;
+
+	ir_range = ir_for->ir_expr2;
+	start = ir_eval_for_addr(ir_range->ir_expr1);
+	stop = ir_eval_for_addr(ir_range->ir_expr2);
+
+	debug("Range appears to be %llu to %llu\n", start, stop);
+
+	var = start;
+	while (var <= stop ) {
+	    ir_val->ir_literal = var;
+	    ir_emit_statement_list(ir_for->ir_statements);
+	    var++;
+	}
+
+	irs_pop_scope();
+}
+
+
+void
+ir_emit_if(struct ir *ir_if)
+{
+	uint64_t lit;
+
+	debug("ir_if()\n");
+	lit = ir_eval_for_addr(ir_if->ir_expr1);
+	if (lit) {
+		ir_emit_statement_list(ir_if->ir_statements);
+	} else {
+		ir_emit_statement_list(ir_if->ir_statements2);
+	}
+}
+
+
+void
+ir_emit_return(struct ir *ir_return)
+{
+	struct ir *ir_ret_expr;
+
+	ir_ret_expr = ir_eval(ir_return->ir_expr1);
+	irs_set_return_value(ir_ret_expr);
+}
+
+
+void
+ir_emit_func_call(struct ir *ir_func)
+{
+	struct ir_scope *irs_scope;
+
+	/*
+	 * Perform function body.
+	 *
+	 * Returned scope has node and property "side effects".
+	 * Function return value is thrown to /dev/null.
+	 */
+	irs_scope = ir_eval_func_body(ir_func);
+
+	/*
+	 * Propagate any nodes or properties into parent scope.
+	 */
+	irs_scope_append_property_list(irs_scope->irs_prop_list);
+	irs_scope_append_node_list(irs_scope->irs_node_list);
+}
+
+
+void
+ir_emit_statement(struct ir *ir)
+{
+	if (ir == NULL)
+		return;
+
+	switch (ir->ir_type) {
+	case IR_NODE:
+		ir_emit_node(ir);
+		break;
+
+	case IR_PROP_DEF:
+		ir_emit_prop_def(ir);
+		break;
+
+	case IR_FOR:
+		ir_emit_for(ir);
+		break;
+
+	case IR_IF:
+		ir_emit_if(ir);
+		break;
+
+	case IR_RETURN:
+		ir_emit_return(ir);
+		break;
+
+	case IR_ASSIGN:
+		ir_emit_assign(ir);
+		break;
+
+	case IR_FUNC_CALL:
+		ir_emit_func_call(ir);
+		break;
+
+	case IR_LIST:
+		/*
+		 * FIXME: LIST within a LIST.  Optimize out earlier?
+		 */
+		ir_emit_statement_list(ir);
+		break;
+
+	default:
+		ir_error(ir, "Unknown statement with ir_type %s\n",
+			 ir_type_string(ir->ir_type));
+	}
+}
+
+
+void
+ir_emit_statement_list(struct ir *ir_list)
+{
+	struct ir *ir;
+
+	if (ir_list == NULL)
+		return;
+
+	if (ir_list->ir_type != IR_LIST)
+		return;
+
+	for (ir = ir_list->ir_first; ir != NULL; ir = ir->ir_next) {
+		ir_emit_statement(ir);
+	}
+}
+
+
+/*
+ * Enter a /define/ function definitin into IRS_ROOT symtab.
+ */
+void
+ir_emit_func_def(struct ir *ir_func_def)
+{
+	char *func_name;
+	struct ir_symbol *irsym;
+	struct ir *ir_pos;
+
+	ir_pos = ir_func_def->ir_expr1
+		? ir_func_def->ir_expr1 : ir_func_def;
+
+	func_name = ir_eval_for_name(ir_func_def->ir_name);
+
+
+	irsym = irs_lookup(func_name, IRS_ROOT);
+	if (irsym != NULL) {
+		ir_error(ir_pos,
+			 "Redefinintion of \"%s\" ignored\n",
+			 func_name);
+		return;
+	}
+
+	irsym = irs_create_symbol(IRS_ROOT, func_name, IRSYM_FUNCDEF);
+
+	irsym->irsym_value = ir_func_def;
+
+	debug("ir_emit_func_def(): Defined %s\n", func_name);
+}
+
+
+/*
+ * Enter a /define/ function definitin into IRS_ROOT symtab.
+ */
+void
+ir_emit_const_def(struct ir *ir_const_def)
+{
+	char *const_name;
+	struct ir_symbol *irsym;
+	struct ir *ir_val;
+	struct ir *ir_pos;
+
+	ir_pos = ir_const_def->ir_expr1
+		? ir_const_def->ir_expr1 : ir_const_def;
+
+	const_name = ir_eval_for_name(ir_const_def->ir_expr1);
+
+	debug("ir_const_def(%s)\n", const_name);
+
+	if (!const_name) {
+		ir_error(ir_pos, "Can't determine LHS constant name\n");
+		return;
+	}
+
+	irsym = irs_lookup(const_name, IRS_ANY);
+	if (irsym != NULL) {
+		ir_warn(ir_pos,
+			"Redefinintion of \"%s\" ignored\n",
+		        const_name);
+		return;
+	}
+
+	irsym = irs_create_symbol(IRS_ROOT, const_name, IRSYM_CONST);
+
+	ir_val = ir_eval(ir_const_def->ir_expr2);
+	irsym->irsym_value = ir_val;
+}
+
+
+void
+ir_emit_declaration_list(struct ir *ir_list)
+{
+	struct ir *ir;
+
+	if (ir_list == NULL)
+		return;
+
+	if (ir_list->ir_type != IR_LIST)
+		return;
+
+	for (ir = ir_list->ir_first; ir != NULL; ir = ir->ir_next) {
+		switch (ir->ir_type) {
+		case IR_CONST_DEF:
+			ir_emit_const_def(ir);
+			break;
+
+		case IR_FUNC_DEF:
+			ir_emit_func_def(ir);
+			break;
+
+		default:
+			ir_error(ir,
+				 "Unknown devlaration type %s\n",
+				 ir_type_string(ir->ir_type));
+			break;
+		}
+	}
+}
+
+
+void
+ir_emit_node(struct ir *ir)
+{
+	struct ir *ir_name;
+	struct ir *ir_label;
+	char *name;
+	char *label;
+	struct node *node;
+	struct node *node_list;
+	struct ir_scope *irs_scope;
+
+	if (ir == NULL)
+		return;
+
+	if (ir->ir_type != IR_NODE)
+		return;
+
+	ir_name = ir_eval(ir->ir_name);
+	name = ir_eval_for_name(ir_name);
+
+	ir_label = ir_eval(ir->ir_label);
+	label = ir_eval_for_label(ir_label);
+
+	debug("ir_emit_node(): Making node %s : %s\n", label, name);
+
+	irs_push_scope(IRS_NODE);
+	ir_emit_statement_list(ir->ir_statements);
+	irs_scope = irs_pop_scope();
+
+	node_list = reverse_nodes(irs_scope->irs_node_list);
+	node = build_node(irs_scope->irs_prop_list, node_list);
+	name_node(node, name, label);
+
+	irs_append_node(node);
+}
+
+
+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;
+	struct ir_symbol *irsym;
+	struct ir *ir_const;
+
+	for (nv = nv_list; nv != NULL; nv = nv->nv_next) {
+		irsym = irs_create_symbol(IRS_ROOT, nv->nv_name, IRSYM_CONST);
+		if (nv->nv_value) {
+			ir_const = ir_alloc(IR_LITERAL, &srcpos_empty);
+			ir_const->ir_lit_str = strdup(nv->nv_value);
+			irsym->irsym_value = ir_const;
+		}
+	}
+}
+
+
+void
+ir_emit_root(struct ir *ir)
+{
+	struct reserve_info *ri_list;
+	struct node *node_list;
+
+	if (ir == NULL)
+		return;
+
+	if (ir->ir_type != IR_ROOT) {
+		ir_error(ir, "Bad root node\n");
+		return;
+	}
+
+	irs_push_scope(IRS_ROOT);
+
+	/*
+	 * Establish constant definitions from command line.
+	 */
+	ir_add_cmd_line_constant_defs();
+
+	ir_emit_mem_reserves(ir->ir_mem_reserves);
+
+	/*
+	 * Fast-and-loose... These are definitions, not declarations!
+	 */
+	ir_emit_declaration_list(ir->ir_declarations);
+
+	/*
+	 * Emit the root IR_NODE.
+	 */
+	ir_emit_node(ir->ir_statements);
+
+	/*
+	 * Build the_boot_info.
+	 */
+	ri_list = irs_scope_stack->irs_reserve_list;
+	node_list = irs_scope_stack->irs_node_list;
+	the_boot_info = build_boot_info(ri_list, node_list, 0);
+
+	irs_pop_scope();
+}
+
+
+extern void
+ir_emit(struct ir *ir)
+{
+	ir_emit_root(ir);
+	fflush(stdout);
+}
diff --git a/ir_scope.c b/ir_scope.c
new file mode 100644
index 0000000..c9a52e8
--- /dev/null
+++ b/ir_scope.c
@@ -0,0 +1,319 @@
+/*
+ * 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 <stdio.h>
+
+#include "dtc.h"
+#include "srcpos.h"
+#include "ir.h"
+#include "ir_scope.h"
+
+
+struct ir_scope *irs_scope_stack;
+
+static const char *irs_scope_bits_str[] = {
+	"ROOT",
+	"NODE",
+	"FOR_LOOP",
+	"FUNC_CALL",
+};
+
+
+static const char *irsym_type_str[IRSYM_NUM_TYPES] = {
+	"NONE",
+	"VAR",
+	"FUNCDEF",
+	"PARAM",
+	"CONST",
+};
+
+
+void
+irs_push_scope(irs_type irs_type)
+{
+	struct ir_scope *irs_new;
+
+	irs_new = xmalloc(sizeof(struct ir_scope));
+	memset(irs_new, 0, sizeof(struct ir_scope));
+
+	irs_new->irs_type = irs_type;
+	irs_new->irs_next = irs_scope_stack;
+
+	irs_scope_stack = irs_new;
+}
+
+
+struct ir_scope *
+irs_pop_scope()
+{
+	struct ir_scope *irs_top = irs_scope_stack;
+
+	irs_scope_stack = irs_top->irs_next;
+	irs_top->irs_next = NULL;
+
+	return irs_top;
+}
+
+
+void
+irs_free_scope(struct ir_scope *irs)
+{
+	free(irs);
+}
+
+
+struct ir_scope *
+irs_find_scope(irs_type irs_match)
+{
+	struct ir_scope *irs;
+
+	for (irs = irs_scope_stack; irs != NULL; irs = irs->irs_next) {
+		if (irs->irs_type & irs_match)
+			return irs;
+	}
+	return NULL;
+}
+
+
+void
+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);
+}
+
+
+void
+irs_scope_append_property_list(struct property *pl)
+{
+	struct ir_scope *irs;
+	struct property *p;
+
+	irs = irs_find_scope(IRS_NODE);
+	for (p = pl; p != NULL; p = p->next) {
+		irs->irs_prop_list = chain_property(p, irs->irs_prop_list);
+	}
+}
+
+void
+irs_scope_append_node_list(struct node *nl)
+{
+	struct ir_scope *irs;
+	struct node *n;
+
+	irs = irs_find_scope(IRS_NODE);
+	for (n = nl; n != NULL; n = n->parent) {
+		irs->irs_node_list = chain_node(n, irs->irs_node_list);
+	}
+}
+
+
+void
+irs_append_property(struct property *p)
+{
+	struct ir_scope *irs;
+
+	irs = irs_find_scope(IRS_NODE);
+	irs->irs_prop_list = chain_property(p, irs->irs_prop_list);
+}
+
+
+void
+irs_append_node(struct node *n)
+{
+	struct ir_scope *irs;
+
+	irs = irs_find_scope(IRS_NODE | IRS_ROOT);
+	irs->irs_node_list = chain_node(n, irs->irs_node_list);
+}
+
+
+void
+irs_set_return_value(struct ir *ir_ret)
+{
+	struct ir_scope *irs;
+
+	/*
+	 * FIXME: If a  previous irs_expr existed, it just leaked.
+	 */
+	irs = irs_find_scope(IRS_FUNC_CALL);
+	irs->irs_expr = ir_ret;
+}
+
+
+
+struct ir_symbol *
+irs_alloc_symbol(char *name, irsym_type irsym_type)
+{
+	struct ir_symbol *irsym;
+
+	irsym = xmalloc(sizeof(struct ir_symbol));
+	memset(irsym, 0, sizeof(struct ir_symbol));
+
+	irsym->irsym_type = irsym_type;
+	irsym->irsym_name = strdup(name);
+
+	return irsym;
+}
+
+
+void
+irs_add_symbol(struct ir_scope *irs, struct ir_symbol *irsym)
+{
+	irsym->irsym_next = irs->irs_symtab;
+	irs->irs_symtab = irsym;
+}
+
+
+struct ir_symbol *
+irs_lookup_in_scope(struct ir_scope *irs, char *name)
+{
+	struct ir_symbol *irsym;
+
+	for (irsym = irs->irs_symtab; irsym; irsym = irsym->irsym_next)
+		if (strcmp(irsym->irsym_name, name) == 0)
+			return irsym;
+
+	return NULL;
+}
+
+
+struct ir_symbol *
+irs_lookup(char *name, irs_type irs_type)
+{
+	struct ir_scope *irs;
+	struct ir_symbol *irsym;
+
+	/*
+	 * Look through scope stack finding matching scopes.
+	 */
+	for (irs = irs_scope_stack; irs != NULL; irs = irs->irs_next)
+		if (irs->irs_type & irs_type) {
+			irsym = irs_lookup_in_scope(irs, name);
+			if (irsym != NULL)
+				return irsym;
+		}
+
+	return NULL;
+}
+
+
+/*
+ * Try to find a symbol that is local to the innermost function.
+ *
+ * Look through scope stack finding matching scopes.
+ * Peer into FUNC_CALL, FOR_LOOP and IR_ROOT symbol tables,
+ * but bail at first FUNC_CALL to make them be "local".
+ */
+struct ir_symbol *
+irs_lookup_local(char *name)
+{
+	struct ir_scope *irs;
+	struct ir_symbol *irsym;
+
+	for (irs = irs_scope_stack; irs != NULL; irs = irs->irs_next) {
+		if (irs->irs_type & (IRS_FUNC_CALL|IRS_FOR_LOOP|IRS_ROOT)) {
+			irsym = irs_lookup_in_scope(irs, name);
+			if (irsym != NULL)
+				return irsym;
+			if (irs->irs_type & IRS_FUNC_CALL)
+				return NULL;
+		}
+	}
+
+	return NULL;
+}
+
+
+struct ir_symbol *
+irs_create_local(char *name, irsym_type irsym_type)
+{
+	struct ir_scope *irs;
+	struct ir_symbol *irsym;
+
+	for (irs = irs_scope_stack; irs != NULL; irs = irs->irs_next) {
+		if (irs->irs_type & (IRS_FUNC_CALL|IRS_ROOT)) {
+			break;
+		}
+	}
+
+	irsym = irs_alloc_symbol(name, irsym_type);
+	irs_add_symbol(irs_scope_stack, irsym);
+
+	return irsym;
+}
+
+
+struct ir_symbol *
+irs_create_symbol(irs_type irs_type, char *name, irsym_type irsym_type)
+{
+	struct ir_scope *irs;
+	struct ir_symbol *irsym;
+
+	/*
+	 * Check for prior existence of symbol first.
+	 */
+	irsym = irs_lookup(name, irs_type);
+	if (irsym != NULL)
+		return irsym;
+
+	/*
+	 * Create the symbol.
+	 */
+	irsym = irs_alloc_symbol(name, irsym_type);
+
+	/*
+	 * Locate the right scope and add symbol.
+	 */
+	irs = irs_find_scope(irs_type);
+	irs_add_symbol(irs, irsym);
+
+	return irsym;
+}
+
+
+void
+irs_dump_symbols(void)
+{
+	struct ir_scope *irs;
+	struct ir_symbol *irsym;
+	int i;
+
+	/*
+	 * Look through scope stack.
+	 */
+	for (irs = irs_scope_stack; irs != NULL; irs = irs->irs_next) {
+		printf("Type: 0x%02x : ", irs->irs_type);
+		for (i = 0; i < IRS_MAX_BIT; i++) {
+			if (irs->irs_type & (1 << i))
+				printf("%s ", irs_scope_bits_str[i]);
+		}
+		printf("\n");
+		for (irsym = irs->irs_symtab;
+		     irsym != NULL;
+		     irsym = irsym->irsym_next) {
+			printf("    %s : %s\n",
+			       irsym_type_str[irsym->irsym_type],
+			       irsym->irsym_name);
+		}
+	}
+}
-- 
1.6.0.90.g436ed

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 6/9 V3] Add the main IR evaluation implementation
       [not found]                     ` <1222460748-20127-6-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-26 20:25                       ` Jon Loeliger
       [not found]                         ` <1222460748-20127-7-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Jon Loeliger @ 2008-09-26 20:25 UTC (permalink / raw)
  To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 ir_eval.c | 1504 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1504 insertions(+), 0 deletions(-)
 create mode 100644 ir_eval.c

diff --git a/ir_eval.c b/ir_eval.c
new file mode 100644
index 0000000..bd667cb
--- /dev/null
+++ b/ir_eval.c
@@ -0,0 +1,1504 @@
+/*
+ * 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 <stdio.h>
+
+#include "dtc.h"
+#include "srcpos.h"
+#include "ir.h"
+#include "ir_scope.h"
+
+
+/*
+ * Returns:
+ *    0 on success, with *val filled in
+ *    -1 == bad characters in literal number
+ *    -2 == literal out of range
+ *    -3 == bad literal
+ */
+
+int
+ir_eval_literal_guessing(const char *s, int base, int bits,
+			 unsigned long long *val)
+{
+	char *e;
+
+	errno = 0;
+	*val = strtoull(s, &e, base);
+
+	if (*e)
+		return -1;
+	else if ((errno == ERANGE)
+		 || ((bits < 64) && (*val >= (1ULL << bits))))
+		return -2;
+	else if (errno != 0)
+		return -3;
+
+	return 0;
+}
+
+unsigned long long
+ir_eval_literal_str(const char *s, int base, int bits)
+{
+	unsigned long long val;
+	char *e;
+
+	errno = 0;
+	val = strtoull(s, &e, base);
+
+	if (*e)
+		die("bad characters in literal");
+	else if ((errno == ERANGE)
+		 || ((bits < 64) && (val >= (1ULL << bits))))
+		die("literal out of range");
+	else if (errno != 0)
+		die("bad literal");
+
+	return val;
+}
+
+
+struct ir *
+ir_eval_cvt_to_string(struct ir *ir)
+{
+	char buf[30];
+	unsigned long long lit1;
+	struct ir *ir_new;
+
+	ir_new = ir_alloc(IR_LIT_STR, ir->ir_srcpos);
+	if (ir_is_constant(ir)) {
+		lit1 = ir_eval_for_addr(ir);
+		snprintf(buf, 30, "%llu", lit1);
+		ir_new->ir_lit_str = strdup(buf);
+	} else {
+		ir_error(ir,
+			 "Can't convert %s to a string\n",
+			 ir_type_string(ir->ir_type));
+	}
+
+	return ir_new;
+}
+
+
+/*
+ * FIXME: This should be named ir_is_constant_number()
+ */
+int
+ir_is_constant(struct ir *ir)
+{
+	return ir &&
+		(ir->ir_type == IR_LITERAL
+		 || ir->ir_type == IR_LIT_BYTE
+		 || ir->ir_type == IR_LIT_CELL
+		 || ir->ir_type == IR_LIT_ADDR);
+}
+
+
+int
+ir_is_string(struct ir *ir)
+{
+	return ir && ir->ir_type == IR_LIT_STR;
+}
+
+
+char *
+ir_eval_for_label(struct ir *ir)
+{
+	char *str;
+
+	if (ir == NULL)
+		return NULL;
+
+	if (ir->ir_type == IR_LABEL
+	    || ir->ir_type == IR_REF_PATH
+	    || ir->ir_type == IR_REF_PHANDLE) {
+		str = strdup(ir->ir_label_name);
+	} else if (ir->ir_type == IR_LIT_STR) {
+		str = strdup(ir->ir_lit_str);
+	} else {
+		str = NULL;
+	}
+
+	return str;
+}
+
+
+char *
+ir_eval_for_name(struct ir *ir)
+{
+	struct ir *ir_val;
+	char *str;
+
+	if (ir == NULL)
+		return NULL;
+
+	ir_val = ir;
+
+	if (ir_val == NULL) {
+		ir_error(ir, "Expected a name\n");
+		return NULL;
+	}
+
+	if (ir_val->ir_type != IR_PROPNODENAME
+	    && ir_val->ir_type != IR_ID
+	    && ir_val->ir_type != IR_LIT_STR)
+		return NULL;
+
+	str = strdup(ir->ir_lit_str);
+
+	return str;
+}
+
+
+/*
+ * FIXME: This is misnamed.  Should be more like ir_eval_for_const()
+ */
+uint64_t
+ir_eval_for_addr(struct ir *ir)
+{
+	unsigned long long a = 0;
+
+	struct ir *ir_val;
+
+	ir_val = ir_eval(ir);
+	if (ir_val == NULL) {
+		ir_error(ir, "Expected a const expression\n");
+		return 0;
+	}
+
+	/*
+	 * FIXME: UH, ir_is_constant() check or something?
+	 */
+
+	a  = ir_val->ir_literal;
+	ir_free(ir_val);
+	debug("eval_for_addr() is 0x%08llx\n", a);
+
+	return a;
+}
+
+
+char *
+ir_eval_for_c_string(struct ir *ir)
+{
+	struct data dtmp;
+	char *p;
+
+	if (ir == NULL)
+		return NULL;
+
+
+	if (!ir_is_string(ir))
+		return NULL;
+
+	p = ir->ir_lit_str;
+	dtmp = data_copy_escape_string(p, strlen(p));
+
+	return strdup(dtmp.val);
+}
+
+
+void
+ir_eval_for_data(struct ir *ir, struct data *d)
+{
+	struct ir *ir_val;
+	struct ir *iri;
+	struct data dtmp;
+	char *lab;
+	cell_t c;
+	unsigned long long ulit64;
+
+	if (ir == NULL)
+		return;
+
+	ir_val = ir_eval(ir);
+
+	switch (ir_val->ir_type) {
+	case IR_LIST:
+		for (iri = ir_val->ir_first; iri != NULL; iri = iri->ir_next) {
+			ir_eval_for_data(iri, d);
+		}
+		break;
+
+	case IR_LIT_STR:
+		dtmp = data_copy_escape_string(ir_val->ir_lit_str,
+					       strlen(ir_val->ir_lit_str));
+		*d = data_merge(*d, dtmp);
+		break;
+
+	case IR_LIT_BYTE:
+		*d = data_append_byte(*d, ir_val->ir_literal);
+		break;
+
+	case IR_LIT_ADDR:
+		ulit64 = ir_val->ir_literal;
+		*d = data_append_addr(*d, ulit64);
+		break;
+
+	case IR_LIT_CELL:
+		c = (cell_t) ir_val->ir_literal;
+		*d = data_append_cell(*d, c);
+		break;
+
+	case IR_CELL:
+		ir_eval_for_data(ir_val->ir_expr1, d);
+		break;
+
+	case IR_LABEL:
+		lab = ir_eval_for_label(ir);
+		*d = data_add_marker(*d, LABEL, lab);
+		break;
+
+	case IR_REF_PATH:
+		lab = ir_eval_for_label(ir);
+		*d = data_add_marker(*d, REF_PATH, lab);
+		break;
+
+	case IR_REF_PHANDLE:
+		lab = ir_eval_for_label(ir);
+		*d = data_add_marker(*d, REF_PHANDLE, lab);
+		*d = data_append_cell(*d, -1);
+		break;
+
+	case IR_INCBIN:	{
+		struct search_path path = { srcpos_file->dir, NULL, NULL };
+		struct data dinc = empty_data;
+		char *file_name;
+		struct dtc_file *file;
+		unsigned long long start;
+		unsigned long long len;
+		struct ir *ir_pos;
+
+		/*
+		 * expr1 is file_name
+		 * expr2 is start, NULL implies start of file
+		 * expr3 is length, NULL implies whole file
+		 */
+		file_name = ir_eval_for_c_string(ir_val->ir_expr1);
+		file = dtc_open_file(file_name, &path);
+
+		ir_pos = ir_val->ir_expr2;
+		start = ir_eval_for_addr(ir_val->ir_expr2);
+		if (ir_val->ir_expr3)
+			len = ir_eval_for_addr(ir_val->ir_expr3);
+		else
+			len = -1;
+
+		if (start != 0) {
+			if (fseek(file->file, start, SEEK_SET) != 0) {
+				ir_error(ir_pos,
+					 "Couldn't seek to offset %llu in \"%s\": %s",
+					 (unsigned long long)start,
+					 file_name,
+					 strerror(errno));
+			}
+		}
+
+		dinc = data_copy_file(file->file, len);
+		*d = data_merge(*d, dinc);
+		dtc_close_file(file);
+		break;
+	}
+
+	default:
+		ir_error(ir,
+			 "Can't convert IR type %s to data\n",
+			 ir_type_string(ir_val->ir_type));
+		break;
+	}
+}
+
+
+struct ir_scope *
+ir_eval_func_body(struct ir *ir_func)
+{
+	char *func_name;
+	struct ir *ir_func_def;
+	struct ir *ir_parameters;
+	struct ir *ir_statements;
+	struct ir_symbol *irsym;
+	struct ir *ir_p;
+	struct ir *ir_f;
+	char *param_name;
+	struct ir_scope *irs_scope;
+	struct ir *ir_next;
+	struct ir *ir_pos;
+
+	if (ir_func == NULL)
+		return NULL;
+
+	if (ir_func->ir_type != IR_FUNC_CALL)
+		return NULL;
+
+	/*
+	 * Lookup the function definition.
+	 */
+	ir_pos = ir_func->ir_expr1;
+	func_name = ir_eval_for_name(ir_func->ir_expr1);
+	debug("ir_eval_func_body(): Looking up %s\n", func_name);
+
+	irsym = irs_lookup(func_name, IRS_ANY);
+	if (irsym == NULL || irsym->irsym_type != IRSYM_FUNCDEF) {
+		ir_error(ir_pos,
+			 "%s isn't a function definition\n",
+			 func_name);
+		return NULL;
+	}
+
+	ir_func_def = irsym->irsym_value;
+	ir_statements = ir_func_def->ir_statements;
+	ir_parameters = ir_func_def->ir_declarations;
+
+	debug("ir_eval_func_body(): Found definition for %s\n",
+	      irsym->irsym_name);
+
+	/*
+	 * Set up parameter binding via eval-and-copy-in.
+	 *
+	 * First pass evaluates each parameter expression and
+	 * builds a temporary list of each eval() parameter.
+	 * These evaluations need to be done before the function
+	 * scope is opened.
+	 *
+	 * Remember to dodge a possible parent IR_LIST node.
+	 */
+	debug("ir_eval_func_body(): Evaluating parameters\n");
+	ir_p = ir_eval(ir_func->ir_expr2);
+	if (ir_p != NULL && ir_p->ir_type == IR_LIST) {
+		ir_p = ir_p->ir_first;
+	}
+
+	/*
+	 * Open an evaluation scope and symbol table for
+	 * the function.
+	 */
+	irs_push_scope(IRS_FUNC_CALL);
+
+	/*
+	 * Second pass loops over each formal parameter
+	 * and each actual expression simultaneously.
+	 *
+	 * Again remember to dodge a possible parent IR_LIST node.
+	 */
+	ir_f = ir_parameters;
+	if (ir_f != NULL && ir_f->ir_type == IR_LIST) {
+		ir_f = ir_f->ir_first;
+	}
+
+	debug("ir_eval_func_body(): Binding parameter to formals\n");
+
+	ir_pos = ir_p;
+	while (ir_f != NULL && ir_p != NULL) {
+		param_name = ir_f->ir_lit_str;
+
+		debug("ir_eval_func_body(): Binding parameter %s\n",
+		      param_name);
+
+		irsym = irs_create_local(param_name, IRSYM_VAR);
+
+		irsym->irsym_value = ir_p;
+		ir_next = ir_p->ir_next;
+		ir_p->ir_next = ir_p->ir_prev = NULL;
+
+		ir_f = ir_f->ir_next;
+		ir_p = ir_next;
+		ir_pos = ir_p;
+	}
+
+	if (ir_f != NULL && ir_p == NULL) {
+		ir_error(ir_pos,
+			 "Not enough parameters to %s (%s)\n",
+			 func_name,
+			 srcpos_string(ir_func_def->ir_srcpos));
+	}
+
+	if (ir_f == NULL && ir_p != NULL) {
+		ir_error(ir_pos,
+			 "Too many parameters to %s (%s)\n",
+			 func_name,
+			 srcpos_string(ir_func_def->ir_srcpos));
+	}
+
+	/*
+	 * And "invoke" it.
+	 */
+	ir_emit_statement_list(ir_statements);
+
+	/*
+	 * FIXME:  Do parameter copy-out here?
+	 */
+	irs_scope = irs_pop_scope();
+
+	/*
+	 * FIXME: This is a bit dodgy perhaps.
+	 */
+	return irs_scope;
+}
+
+
+struct ir *
+ir_eval_func_call(struct ir *ir_func)
+{
+	struct ir_scope *irs_scope;
+
+	/*
+	 * Perform function body.
+	 * Returned scope has "side effects".
+	 *
+	 * This context really just wants the return value,
+	 * but we could debate using nodes and properties too?
+	 */
+	irs_scope = ir_eval_func_body(ir_func);
+
+	if (!irs_scope)
+		return NULL;
+
+	return irs_scope->irs_expr;
+}
+
+
+struct ir *
+ir_eval(struct ir *ir)
+{
+	struct ir *ir_new;
+	struct ir *iri;
+	struct ir *ir1;
+	struct ir *ir2;
+	struct ir_symbol *irsym;
+	unsigned long long lit1;
+	unsigned long long lit2;
+	char *str;
+	int len;
+
+	if (ir == NULL)
+		return NULL;
+
+	ir_new = NULL;
+
+	/*
+	 * Perform IR node-specific evaluations.
+	 */
+	switch (ir->ir_type) {
+	case IR_LIT_STR:
+	case IR_LIT_BYTE:
+	case IR_LIT_CELL:
+	case IR_LIT_ADDR:
+	case IR_PROPNODENAME:
+	case IR_REF_PATH:
+		/*
+		 * Values already present in the IR node.
+		 */
+		ir_new = ir_copy(ir);
+		break;
+
+	case IR_REF_PHANDLE:
+		/*
+		 * Promote a REF_PHANDLE of a LIT_STR to a
+		 * direct REF_PHANDLE.
+		 */
+		ir_new = ir_copy(ir);
+		if (ir->ir_label) {
+			iri = ir_eval(ir->ir_label);
+			if (ir_is_string(iri)) {
+				ir_new->ir_label_name = iri->ir_lit_str;
+			}
+		}
+		break;
+
+	case IR_LABEL:
+		ir_new = ir_copy(ir);
+		break;
+
+	case IR_CVT_PROPNODENAME:
+		iri = ir_eval(ir->ir_expr1);
+		str = ir_eval_for_name(iri);
+		if (str) {
+			ir_new = ir_alloc(IR_PROPNODENAME, ir->ir_srcpos);
+			ir_new->ir_lit_str = str;
+		}
+		break;
+
+	case IR_CVT_STRING:
+		iri = ir_eval(ir->ir_expr1);
+		ir_new = ir_eval_cvt_to_string(iri);
+		break;
+
+	case IR_ID:
+		irsym = irs_lookup(ir->ir_lit_str, IRS_ANY);
+		if (irsym != NULL) {
+			ir_new = ir_eval(irsym->irsym_value);
+		} else {
+			ir_error(ir,
+				 "Unknown value for \"%s\"\n",
+				 ir->ir_lit_str);
+		}
+		break;
+
+	case IR_LIST:
+		ir_new = ir_alloc(IR_LIST, ir->ir_srcpos);
+		for (iri = ir->ir_first; iri != NULL; iri = iri->ir_next) {
+			ir_list_append(ir_new, ir_eval(iri));
+		}
+		break;
+
+	case IR_SELECT:
+		/*
+		 * Pick the ? or the : side.
+		 */
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		if (lit1) {
+			ir_new = ir_eval(ir->ir_expr2);
+		} else {
+			ir_new = ir_eval(ir->ir_expr3);
+		}
+		break;
+
+	case IR_OR:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		if (!lit1) {
+			lit1 = ir_eval_for_addr(ir->ir_expr2);
+		}
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = (lit1 != 0);
+		break;
+
+	case IR_AND:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		if (lit1) {
+			lit1 = ir_eval_for_addr(ir->ir_expr2);
+		}
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = (lit1 != 0);
+
+		break;
+
+	case IR_BIT_OR:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		lit2 = ir_eval_for_addr(ir->ir_expr2);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = lit1 | lit2;
+		break;
+
+	case IR_BIT_XOR:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		lit2 = ir_eval_for_addr(ir->ir_expr2);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = lit1 ^ lit2;
+		break;
+
+	case IR_BIT_AND:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		lit2 = ir_eval_for_addr(ir->ir_expr2);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = lit1 & lit2;
+		break;
+
+	case IR_EQ:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		lit2 = ir_eval_for_addr(ir->ir_expr2);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = lit1 == lit2;
+		break;
+
+	case IR_LT:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		lit2 = ir_eval_for_addr(ir->ir_expr2);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = lit1 < lit2;
+		break;
+
+	case IR_LE:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		lit2 = ir_eval_for_addr(ir->ir_expr2);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = lit1 <= lit2;
+		break;
+
+	case IR_GT:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		lit2 = ir_eval_for_addr(ir->ir_expr2);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = lit1 > lit2;
+		break;
+
+	case IR_GE:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		lit2 = ir_eval_for_addr(ir->ir_expr2);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = lit1 >= lit2;
+		break;
+
+	case IR_NE:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		lit2 = ir_eval_for_addr(ir->ir_expr2);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = lit1 != lit2;
+		break;
+
+	case IR_LSHIFT:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		lit2 = ir_eval_for_addr(ir->ir_expr2);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = lit1 << lit2;
+		break;
+
+	case IR_RSHIFT:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		lit2 = ir_eval_for_addr(ir->ir_expr2);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = lit1 >> lit2;
+		break;
+
+	case IR_ADD:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		lit2 = ir_eval_for_addr(ir->ir_expr2);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = lit1 + lit2;
+		break;
+
+	case IR_MINUS:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		lit2 = ir_eval_for_addr(ir->ir_expr2);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = lit1 - lit2;
+		break;
+
+	case IR_MULT:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		lit2 = ir_eval_for_addr(ir->ir_expr2);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = lit1 * lit2;
+		break;
+
+	case IR_DIV:
+		/* FIXME: check for division by const 0 */
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		lit2 = ir_eval_for_addr(ir->ir_expr2);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = lit1 / lit2;
+		break;
+
+	case IR_MOD:
+		/*
+		 * This is really a bit upside down due to not having
+		 * a real typing system.  Cope for now.
+		 */
+		ir1 = ir_eval(ir->ir_expr1);
+		ir2 = ir_eval(ir->ir_expr2);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			/*
+			 * FIXME: check for division by const 0.
+			 */
+			lit1 = ir_eval_for_addr(ir->ir_expr1);
+			lit2 = ir_eval_for_addr(ir->ir_expr2);
+			ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 % lit2;
+
+		} else if (ir_is_string(ir1) || ir_is_string(ir2)) {
+			if (!ir_is_string(ir1))
+				ir1 = ir_eval_cvt_to_string(ir1);
+			if (!ir_is_string(ir2))
+				ir2 = ir_eval_cvt_to_string(ir2);
+			len = strlen(ir1->ir_lit_str)
+				+ strlen(ir2->ir_lit_str) + 1;
+			str = xmalloc(len);
+			strcpy(str, ir1->ir_lit_str);
+			strcat(str, ir2->ir_lit_str);
+			str[len - 1] = 0;
+			ir_new = ir_alloc(IR_LIT_STR, ir->ir_srcpos);
+			ir_new->ir_lit_str = str;
+		}
+		break;
+
+	case IR_BIT_COMPL:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = ~lit1;
+		break;
+
+	case IR_NOT:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = !lit1;
+		break;
+
+	case IR_UMINUS:
+		lit1 = ir_eval_for_addr(ir->ir_expr1);
+		ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		ir_new->ir_literal = -lit1;
+		break;
+
+	case IR_FUNC_CALL:
+		ir_new = ir_eval_func_call(ir);
+		break;
+
+	case IR_BUILTIN:
+		ir_new = ir_eval_builtin(ir);
+		break;
+
+	case IR_RANGE:
+		ir_new = ir_copy(ir);
+		ir_new->ir_expr1 = ir_eval(ir->ir_expr1);
+		ir_new->ir_expr2 = ir_eval(ir->ir_expr2);
+		break;
+
+	case IR_CELL:
+		ir_new = ir_eval(ir->ir_expr1);
+		if (ir_is_constant(ir_new)) {
+			/* FIXME: Check for 32-bit range here? */
+			ir_new->ir_type = IR_LIT_CELL;
+		} else if (ir_is_string(ir_new)) {
+			/* empty */
+		} else {
+			ir_error(ir, "Can't determine CELL value\n");
+		}
+		break;
+
+	case IR_LITERAL:
+		lit1 = 0;
+		if (ir_eval_literal_guessing(ir->ir_lit_str,
+					     0, 64, &lit1) == 0) {
+			/*
+			 * Smells like an number.
+			 */
+			ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+			ir_new->ir_literal = lit1;
+		} else {
+			/*
+			 * Dunno what it is.  Must be a string.
+			 * FIXME: ir_eval_for_c_string() here?
+			 */
+			ir_new = ir_alloc(IR_LIT_STR, ir->ir_srcpos);
+			ir_new->ir_lit_str = strdup(ir->ir_lit_str);
+		}
+		break;
+
+	case IR_INCBIN:
+		ir_new = ir_copy(ir);
+		ir_new->ir_expr1 = ir_eval(ir->ir_expr1);
+		ir_new->ir_expr2 = ir_eval(ir->ir_expr2);
+		ir_new->ir_expr3 = ir_eval(ir->ir_expr3);
+		break;
+
+	case IR_PROP_DEF:
+		ir_error(ir, "Can't evaluate IR_PROP_DEF here.\n");
+		break;
+
+	case IR_ROOT:
+	case IR_RETURN:
+	case IR_IF:
+	case IR_FOR:
+	case IR_ASSIGN:
+	case IR_MEM_RESERVE:
+	case IR_FUNC_DEF:
+	case IR_PARAMDECL:
+	case IR_NODE:
+		ir_error(ir,
+			 "Can't evaluate %s statements in expressions\n",
+			 ir_type_string(ir->ir_type));
+		break;
+
+	default:
+		ir_error(ir,
+			 "Unknown expression ir_type %s\n",
+			 ir_type_string(ir->ir_type));
+	}
+
+	return ir_new;
+}
+
+
+struct ir *
+ir_simplify(struct ir *ir, unsigned int ctxt)
+{
+	struct ir *ir1;
+	struct ir *ir2;
+	ir_type ir_type;
+	struct ir *ir_new;
+	unsigned long long lit1;
+	unsigned long long lit2;
+	unsigned long long ulit64;
+
+	if (ir == NULL)
+		return NULL;
+
+	/*
+	 * First determine what the evaluation context will be
+	 * for any sub-expression based on the current IR node.
+	 */
+	switch (ir->ir_type) {
+	case IR_CELL:
+		/*
+		 * Pass new context down.
+		 */
+		ctxt = IR_EVAL_CTXT_CELL;
+		break;
+
+	case IR_INCBIN:
+	case IR_IF:
+	case IR_FOR:
+	case IR_MEM_RESERVE:
+		/*
+		 * These are always done in an ANY context.
+		 */
+		ctxt = IR_EVAL_CTXT_ANY;
+		break;
+
+	default:
+		/*
+		 * Use the supplied (parameter) context.
+		 */
+		break;
+	}
+
+
+	/*
+	 * Perform IR node-specific optimizations.
+	 */
+	switch (ir->ir_type) {
+	case IR_ID:
+	case IR_LIT_STR:
+	case IR_LIT_BYTE:
+	case IR_LIT_CELL:
+	case IR_LIT_ADDR:
+	case IR_PROPNODENAME:
+	case IR_LABEL:
+	case IR_REF_PATH:
+		/*
+		 * Already as simple as they can be.
+		 */
+		ir_new = ir_copy(ir);
+		break;
+
+	case IR_REF_PHANDLE:
+		ir_new = ir_copy(ir);
+		ir_new->ir_label = ir_simplify(ir->ir_label, ctxt);
+		break;
+
+	case IR_RETURN:
+		ir_new = ir_copy(ir);
+		ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+		break;
+
+	case IR_MEM_RESERVE:
+	case IR_RANGE:
+		ir_new = ir_copy(ir);
+		ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+		break;
+
+	case IR_CELL:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		if (ir1 && ir1->ir_type == IR_LIT_CELL) {
+			ir_new = ir1;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+		}
+		break;
+
+	case IR_PROP_DEF:
+		ir_new = ir_copy(ir);
+		ir_new->ir_label = ir_simplify(ir->ir_label, ctxt);
+		ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+		break;
+
+	case IR_LITERAL:
+		/*
+		 * Based on context, evaluate literal into 32 or 64 bits.
+		 * LIT_ADDR could be a lie; it just means 64-bit.  Feh.
+		 */
+		if (ctxt == IR_EVAL_CTXT_CELL) {
+			ulit64 = ir_eval_literal_str(ir->ir_lit_str, 0, 32);
+			ir_new = ir_alloc(IR_LIT_CELL, ir->ir_srcpos);
+		} else {
+			ulit64 = ir_eval_literal_str(ir->ir_lit_str, 0, 64);
+			ir_new = ir_alloc(IR_LIT_ADDR, ir->ir_srcpos);
+		}
+		ir_new->ir_literal = ulit64;
+		break;
+
+	case IR_FUNC_CALL:
+		{
+			char *name;
+			irb_id irb;
+
+			ir_new = ir_copy(ir);
+			ir1 = ir_simplify(ir->ir_expr1, ctxt);
+			ir2 = ir_simplify(ir->ir_expr2, ctxt);
+			name = ir_eval_for_name(ir1);
+			if (name) {
+				irb = ir_lookup_builtin_by_name(name);
+				if (irb != IRB_UNDEF) {
+					debug("ir_simplify(): Use builtin %s\n",
+					      name);
+					ir_new->ir_type = IR_BUILTIN;
+					ir_new->ir_builtin_id = irb;
+					ir_new->ir_expr1 = ir2;
+				} else {
+					ir_new->ir_expr1 = ir1;
+					ir_new->ir_expr2 = ir2;
+				}
+			} else {
+				ir_error(ir1, "Unknown function %s\n", name);
+			}
+		}
+		break;
+
+	case IR_BUILTIN:
+		ir_new = ir_copy(ir);
+		ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+		break;
+
+	case IR_LIST:
+		ir_new = ir_alloc(IR_LIST, ir->ir_srcpos);
+		for (ir1 = ir->ir_first; ir1 != NULL; ir1 = ir1->ir_next) {
+			ir_list_append(ir_new,
+				       ir_simplify(ir1, ctxt));
+		}
+		break;
+
+	case IR_INCBIN:
+		/*
+		 * Ponder loading and caching files?
+		 */
+		ir_new = ir_copy(ir);
+		ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+		ir_new->ir_expr3 = ir_simplify(ir->ir_expr3, ctxt);
+		break;
+
+	case IR_ASSIGN:
+		ir_new = ir_copy(ir);
+		ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+		break;
+
+	case IR_IF:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		if (ir_is_constant(ir1)) {
+			/*
+			 * Eliminate the IR_IF.
+			 * Pick the THEN or ELSE statements only.
+			 * FIXME: Fix leaking ir1 here.
+			 */
+			ulit64 = ir_eval_for_addr(ir1);
+			if (ulit64) {
+				/*
+				 * Keep the THEN statements.
+				 */
+				ir_new = ir_simplify(ir->ir_statements, ctxt);
+			} else {
+				/*
+				 * Keep the ELSE statements.
+				 */
+				ir_new = ir_simplify(ir->ir_statements2, ctxt);
+			}
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir1 = ir_simplify(ir->ir_statements, ctxt);
+			ir_new->ir_statements = ir1;
+			ir1 = ir_simplify(ir->ir_statements2, ctxt);
+			ir_new->ir_statements2 = ir1;
+		}
+		break;
+
+	case IR_FOR:
+		/*
+		 * Lots of optimizations possible here based on
+		 * empty statements and trivial ranges.  Later.
+		 * FIXME: Do "for" simplification optimizations.
+		 */
+		ir_new = ir_copy(ir);
+		ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+		ir_new->ir_expr3 = ir_simplify(ir->ir_expr3, ctxt);
+		ir_new->ir_statements = ir_simplify(ir->ir_statements, ctxt);
+		break;
+
+	case IR_SELECT:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		if (ir_is_constant(ir1)) {
+			/*
+			 * Pick the ? or the : side.
+			 * FIXME: Fix leaking ir1.
+			 */
+			ulit64 = ir_eval_for_addr(ir1);
+			if (ulit64) {
+				ir_new = ir_simplify(ir->ir_expr2, ctxt);
+			} else {
+				ir_new = ir_simplify(ir->ir_expr3, ctxt);
+			}
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+			ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+			ir_new->ir_expr3 = ir_simplify(ir->ir_expr3, ctxt);
+		}
+		break;
+
+	case IR_CVT_PROPNODENAME:
+		/*
+		 * IR_CVT_PROPNODENAME(IR_PROPNODENAME) == IR_PROPNODENAME,
+		 * so drop the CVT.
+		 */
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		if (ir1 && ir1->ir_type == IR_PROPNODENAME) {
+			ir_new = ir1;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+		}
+		break;
+
+	case IR_CVT_STRING:
+		/*
+		 * IR_CVT_STRING(IR_LIT_STR) == IR_LIT_STR,
+		 * so drop the CVT.
+		 */
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		if (ir1 && ir1->ir_type == IR_LIT_STR) {
+			ir_new = ir1;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+		}
+		break;
+
+	case IR_OR:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		if (ir_is_constant(ir1)) {
+			ulit64 = ir_eval_for_addr(ir1);
+			if (ulit64) {
+				ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+					? IR_LIT_CELL : IR_LIT_ADDR;
+				ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+				ir_new->ir_literal = 1;
+				break;
+			}
+		}
+
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new->ir_literal = lit1 || lit2;
+
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir_simplify(ir1, ctxt);
+			ir_new->ir_expr2 = ir_simplify(ir2, ctxt);
+		}
+		break;
+
+	case IR_AND:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		if (ir_is_constant(ir1)) {
+			ulit64 = ir_eval_for_addr(ir1);
+			if (ulit64 == 0) {
+				ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+					? IR_LIT_CELL : IR_LIT_ADDR;
+				ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+				ir_new->ir_literal = 0;
+				break;
+			}
+		}
+
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new->ir_literal = lit1 && lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_BIT_OR:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 | lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_BIT_XOR:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 ^ lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_BIT_AND:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 & lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_EQ:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 == lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_LT:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 < lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_LE:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 <= lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_GT:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 > lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_GE:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 >= lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_NE:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 != lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_LSHIFT:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 << lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_RSHIFT:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 >> lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_ADD:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 + lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_MINUS:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 - lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_MULT:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 * lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_DIV:
+		/* FIXME: check for division by const 0 */
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 / lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_MOD:
+		/* FIXME: check for division by const 0 */
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir2 = ir_simplify(ir->ir_expr2, ctxt);
+		if (ir_is_constant(ir1) && ir_is_constant(ir2)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			lit2 = ir_eval_for_addr(ir2);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = lit1 % lit2;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+			ir_new->ir_expr2 = ir2;
+		}
+		break;
+
+	case IR_BIT_COMPL:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		if (ir_is_constant(ir1)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = ~lit1;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+		}
+		break;
+
+	case IR_NOT:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		if (ir_is_constant(ir1)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = !lit1;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+		}
+		break;
+
+	case IR_UMINUS:
+		ir1 = ir_simplify(ir->ir_expr1, ctxt);
+		if (ir_is_constant(ir1)) {
+			ir_type = (ctxt == IR_EVAL_CTXT_CELL)
+				? IR_LIT_CELL : IR_LIT_ADDR;
+			lit1 = ir_eval_for_addr(ir1);
+			ir_new = ir_alloc(ir_type, ir->ir_srcpos);
+			ir_new->ir_literal = -lit1;
+		} else {
+			ir_new = ir_copy(ir);
+			ir_new->ir_expr1 = ir1;
+		}
+		break;
+
+	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 =
+			ir_simplify(ir->ir_statements, ctxt);
+		break;
+
+	case IR_NODE:
+		ir_new = ir_copy(ir);
+		ir_new->ir_label = ir_simplify(ir->ir_label, ctxt);
+		ir_new->ir_name = ir_simplify(ir->ir_name, ctxt);
+		ir_new->ir_statements =
+			ir_simplify(ir->ir_statements, ctxt);
+		break;
+
+	case IR_CONST_DEF:
+		ir_new = ir_copy(ir);
+		ir_new->ir_expr1 = ir_simplify(ir->ir_expr1, ctxt);
+		ir_new->ir_expr2 = ir_simplify(ir->ir_expr2, ctxt);
+		break;
+
+	case IR_FUNC_DEF:
+		ir_new = ir_copy(ir);
+		ir_new->ir_name = ir_simplify(ir->ir_name, ctxt);
+		ir_new->ir_declarations =
+			ir_simplify(ir->ir_declarations, ctxt);
+		ir_new->ir_statements =
+			ir_simplify(ir->ir_statements, ctxt);
+		break;
+
+	case IR_PARAMDECL:
+	default:
+		ir_new = NULL;
+		ir_error(ir,
+			 "Can't simplify unknown ir_type %s\n",
+			 ir_type_string(ir->ir_type));
+	}
+
+	return ir_new;
+}
-- 
1.6.0.90.g436ed

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 7/9 V3] Introduce new DTS language.
       [not found]                         ` <1222460748-20127-7-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-26 20:25                           ` Jon Loeliger
       [not found]                             ` <1222460748-20127-8-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Jon Loeliger @ 2008-09-26 20:25 UTC (permalink / raw)
  To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

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-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                             ` <1222460748-20127-8-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-26 20:25                               ` Jon Loeliger
       [not found]                                 ` <1222460748-20127-9-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
  2008-10-02  8:25                               ` [PATCH 7/9 V3] Introduce " David Gibson
  1 sibling, 1 reply; 79+ messages in thread
From: Jon Loeliger @ 2008-09-26 20:25 UTC (permalink / raw)
  To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

From: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>

Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 Documentation/manual.txt |  500 ++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 463 insertions(+), 37 deletions(-)

diff --git a/Documentation/manual.txt b/Documentation/manual.txt
index b957662..ac56309 100644
--- a/Documentation/manual.txt
+++ b/Documentation/manual.txt
@@ -105,13 +105,21 @@ Options:
     -q
 	Quiet: -q suppress warnings, -qq errors, -qqq all
 
+    -D <id>
+    -D <id>=<value>
+	Introduce a constant definition for symbol <id> with
+	possible initial value given by <value>.  The RHS
+	should be a literal number or string value.
+
+    -p <padsize>
+	Add at least <padsize> additional space to the DTB image.
+
     -R <number>
 	Make space for <number> reserve map entries
 	Relevant for dtb and asm output only.
 
     -S <bytes>
-	Ensure the blob at least <bytes> long, adding additional
-	space if needed.
+	Deprecated option.
 
     -v
 	Print DTC version and exit.
@@ -131,47 +139,338 @@ Additionally, dtc performs various sanity checks on the tree.
 
 4) Device Tree Source file
 
-4.1) Overview
 
-Here is a very rough overview of the layout of a DTS source file:
+4.1) DTS Lexical Components
+
+Property and node names		[a-zA-Z0-9,._+*#?@-]+
+Identifiers			\\[a-zA-Z_][a-zA-Z0-9_]*
+Labels				[a-zA-Z_][a-zA-Z0-9_]*
+Strings				<C-style-double-quoted-strings>
+Comments			Both /* ... */ and // style are supported
+Numeric literals		<C-style-integer-numbers>
+Bytes				[0-9a-fA-F][0-9a-fA-F]
+
+Keywords:
+	else
+	for
+	if
+	in
+	return
+	void
+	/const/
+	/define/
+	/incbin/
+
+C-style expression operators:
+	<<
+	>>
+	<=
+	>=
+	==
+	!=
+	&&
+	||
+	+
+	-
+	*
+	/
+	%
+
+Additional tokens:
+	..
+	:=
+	{
+	}
+	,
+	&
+
+
+These constructs are handled and eliminated purely at the
+lexical level and do not appear in the grammar proper:
+
+    - Source files included using the syntax:
+
+        /include/ "filename"
+
+    - Both classic C style and C++ style comments are supported.
+      Comments don't nest.
+      For example, given:
+
+	1    /*
+	2     *  asdasdasd  // asdasdad
+	3     //   */
+	4    asasd
+	5     */
+      The // comment on line 3 is not effective and is ignored.
+      The original /* comment ends on line 3.  Line 5 is in error.
+
+      And given:
+
+	1    // /*
+	2     *  asdasdasd  // asdasdad
+	3     */
+
+      The // comment on line 1 hides the opening /*.
+      Line 2 is in error.
+
+
+4.2) DTS Grammar
+
+Here is a very rough overview of the grammar of a DTS source file:
+
+
+    sourcefile:
+		'/dts-v1/' ';' possibly_empty_list_of_declarations devicetree
+
+    declaration:
+		  memreserve
+		| constdef
+		| funcdef
+
+    memreserve:	label '/memreserve/' addr addr ';'
+
+    constdef:	'/const/' identifier '=' expr ';'
+
+    funcdef:	'/define/' propnodename paramdecls statement_block
+
+    paramdecls:	'(' possibly_empty_paramdecl_list ')'
+
+    paramdecl: identifier
+
+    devicetree:   '/' statement_block
+
+    statement_block: '{' possibly_empty_list_of_statements '}'
+
+    statement:
+		  subnode
+		| for_statement
+		| if_statement
+		| return_statement
+		| assign_statement
+		| property_definition
+		| statement_block
+		| ';'
+
+    subnode:
+		  node_label expr statement_block ';'
+		|      label expr statement_block ';'
+		|            expr statement_block ';'
+
+    for_statement:
+		'for' identifier 'in' expr '..' expr statement_block
+
+    if_statement:
+		  'if' '(' expr ')' statement_block
+		| 'if' '(' expr ')' statement_block 'else' statement_block
+
+    return_statement: 'return' expr ';'
+
+    assign_statement: identifier ':=' expr ';'
+
+    property_definition:
+		  optional_label expr ';'
+		| optional_label expr '=' list_of_property_data_and_labels ';'
 
+    list_of_property_data_and_labels:
+		  STRING
+		| '<' possibly_empty_list_of_cell_values_and_labels '>'
+		| '[' possibly_empty_list_of_byte_values_and_labels ']'
+		| label
+		| '/incbin/' '(' expr ')'
+		| '/incbin/' '(' expr ',' expr ',' expr ')'
 
-    sourcefile:   list_of_memreserve devicetree
+    cell_value:
+		  expr_primary
+		| '&' '(' expr ')'
+		| '&' phandle_reference
+		| label
 
-    memreserve:   label 'memreserve' ADDR ADDR ';'
-		| label 'memreserve' ADDR '-' ADDR ';'
 
-    devicetree:   '/' nodedef
+    expr:
+          expr_primary
+	| expr '?' expr ':' expr
+	| expr expr_oper expr
 
-    nodedef:      '{' list_of_property list_of_subnode '}' ';'
+    expr_oper:
+	||
+        &&
+	|
+	^
+	&
+	==
+	< | > | <= | >=
+	<< | >>
+	+ | -
+	* | / | %
+	- | ~ | !
+        '(' ')' | '(' non_empty_list_of_param_exprs ')'
 
-    property:     label PROPNAME '=' propdata ';'
+    expr_primary:
+	  literal
+	| string
+	| propnodename
+	| identifier
+	| '(' expr ')'
 
-    propdata:     STRING
-		| '<' list_of_cells '>'
-		| '[' list_of_bytes ']'
+    addr:	expr
 
-    subnode:      label nodename nodedef
+    node_label:	expr ':'
 
-That structure forms a hierarchical layout of nodes and properties
-rooted at an initial node as:
+    propnodename: <1275-property-name>
+
+    identifier:	'\'-<C style name>
+
+    literal:	<C style number>
+    byte:	<exactly two hex digits>
+    string:	<C style string>
+    label:	'&'-<label name>-':'
+
+
+4.2) Overview
+
+The DTS source file begins with the '/dts-v1/' token to state
+that it is using "Version 1" style source files.
+
+Any declarations are executed in order, and can use the
+effects of earlier declarations.
+
+All declarations must precede the required root node definition,
+which is introduced with the '/'-named node:
 
     / {
+	...
     }
 
-Both classic C style and C++ style comments are supported.
+The statement-block structure forms a hierarchical layout of nodes
+and properties along with some control-statements that allow for
+repeated and alternate statement blocks.
+
+
+4.3) Declarations
+
+An arbitrary list of declarations can be made between '/dts-v1/'
+and the beginning of the root node.  These declarations are
+introduced in order.
+
+
+4.3.1) Memory Reservations
+
+A memory reservation is a declaration that a block of memory
+from the first address expression, with a size given by the
+second address expression, is to be "reserved" and not used
+by the kernel.  These address ranges are passed through to
+the DTB to the kernel.
+
+
+4.3.2) Function Definitions
+
+A function definition can be introduced using /define/.
+These definitions are just "stored" and then later invoked as
+either a subroutine in a statement context, or as a function
+with a return value in an expression context.
 
-Source files may be directly included using the syntax:
+Functions declare the number of formal parameters which will
+be passed in at the call site, and must match one-to-one.
 
-    /include/ "filename"
+Any property definitions generated by the function are emitted
+into the caller's context at the point of the call.
 
+Any node definitions generated by the function are emitted
+into the caller's context at the point of the call.
 
-4.2) Properties
 
-Properties are named, possibly labeled, values.  Each value
-is one of:
+4.3.3) Constant Definitions
 
-    - A null-teminated C-like string,
+Constant definitions introduce a named identifier into the outer-most
+symbol scope.  The constants can not be changed by later assignment
+statements, though they can be hidden.  (Be careful.)
+
+Constants may be expressions yielding constant numeric or strings
+values.  It is an error for them not to be evaluatable at their
+point of definition.
+
+Constant definitions may also be introduced from the command line
+using the '-D var=value" options.  They will be placed into the
+same outer-most scope.  Constant definitions from the command line
+override the definitions within the source file, but with a warning.
+
+
+4.4) Statements
+
+A statement block is simply a list of sequentially executed
+statements introduced with a required opening brace and terminated
+with a required closing brace.
+
+4.4.1) Subnodes
+
+Node may contain sub-nodes to obtain a hierarchical structure.
+
+For example:
+
+    - A child node named "childnode" whose unit name is
+      "childnode at address".  It it turn has a string property
+      called "childprop".
+
+	childnode@address {
+	    childprop = "hello\n";
+	};
+
+
+4.4.2) 'for' Statement
+
+The 'for' statement provides iterative execution of a
+block of statements.
+
+The lower bound of the range is evaluated once, and the
+upper bound is evaluated once.
+
+A new scope that contains the loop variable is created
+and pushed onto the symbol table scope stack.  The loop
+variable is initialized with the lower bound value.
+
+The statement block is executed once for each inclusive value
+in the given range in increasing order.
+
+After the loop terminates, the loop variable scope is popped.
+
+
+4.4.3) 'if' Statement
+
+The 'if' statement provides alternate execution flow paths.
+The expression is evaluated once, and if non-zero, the fist
+statement block is executed, otherwise the 'else' block of
+statements is executed if present.
+
+
+4.4.4) 'return' Statement
+
+Inside a function definition, the 'return' statement allows
+a value to be passed back to the caller.  The return expression
+is evaluated once, in the context of the function's scope,
+and its resultant value is made available as the function's
+return result.
+
+
+4.4.5) Assign Statement
+
+The ':=' operator allows assignment to non-constant identifiers.
+
+The identifiers can be either formal parameters or variable as
+found by the searching using the dynamic symbol table scoping rules.
+
+An assignment to an otherwise unknown identifier causes that
+identifier to be introduced into the current scope.
+
+You can't assign to /constant/ identifiers (except in the initial
+definition of them).
+
+
+4.4.6) Property Definition
+
+Properties are named, possibly labeled, values.
+Each value within a property is one of:
+
+    - A null-terminated C-like string,
     - A numeric value fitting in 32 bits,
     - A list of 32-bit values
     - A byte sequence
@@ -195,27 +494,126 @@ Here are some example property definitions:
 	property4 = [0a 0b 0c 0d de ea ad be ef];
 
 
-Node may contain sub-nodes to obtain a hierarchical structure.
-For example:
+4.4.7) Subroutine calls
 
-    - A child node named "childnode" whose unit name is
-      "childnode at address".  It it turn has a string property
-      called "childprop".
+An expression at the statement level should be a function call,
+though it might be considered as just a "subroutine call" as
+any return value is thrown away.
 
-	childnode@addresss {
-	    childprop = "hello\n";
-	};
+Invocation of the function introduces a symbol table scope
+in which the formal paramters are introduced and bound.
+Initial values for the formals are obtained by evaluating
+the actual parameters, in order, and using a copy-in binding.
+
+Any incidental (dynamically occurring) assignment to an
+otherwise unknown identifier will cause the introduction of
+a new variable in the function's execution scope.
+
+Any property definitions generated by the function are emitted
+into the caller's context at the point of the subroutine call.
+
+Any node definitions generated by the function are emitted
+into the caller's context at the point of the subroutine call.
+
+Any return value from a return statement is thrown away.
 
+Execution control is returned to the point of the call.
 
-By default, all numeric values are hexadecimal.  Alternate bases
-may be specified using a prefix "d#" for decimal, "b#" for binary,
-and "o#" for octal.
 
-Strings support common escape sequences from C: "\n", "\t", "\r",
-"\(octal value)", "\x(hex value)".
+4.5) Expressions
 
+Basically, expressions follow C conventions.  However, there
+are no assignment operations such as +=, or pre-/post-
+increment/decrement.
 
-4.3) Labels and References
+The '%' operation is a modulus operation for integers, and
+a string concatenation operation if at least one of the operands
+is determined to be a string value.
+
+
+4.5.1) Expressions
+
+Pretend it is C and see how close we get.
+
+
+4.5.2) Function Invocations
+
+A previously defined function may be invoked from within an
+expression.  A "return" statement should be used to return
+a resulting expression value to the caller's context.
+
+Invocation of the function introduces a symbol table scope
+in which the formal parameters are introduced and bound.
+Initial values for the formals are obtained by evaluating
+the actual parameters, in order, and using a copy-in binding.
+
+Any incidental (dynamically occurring) assignment to an
+otherwise unknown identifier will cause the introduciton of
+a new variable in the function's execution scope.
+
+Any property definitions generated by the function are emitted
+into the caller's context at the point of the subroutine call.
+
+Any node definitions generated by the function are emitted
+into the caller's context at the point of the subroutine call.
+
+Any return value from a return statement is used as the result
+of the function call within the context of the original expression.
+
+Execution control is returned to the point of the call.
+
+
+4.5.3) Builtin Functions
+
+There are a few builtin function names;
+
+    join()	Concatenate and return a list of expression
+		as a string.  Non-string arguments are coerced
+		into being a string.
+
+    hexstr()	Format and return a hex string representation
+		of the one parameter without a leading '0x'.
+
+While not here yet, /incbin/ should be converted into a builtin.
+
+
+4.5.4) Literal Numbers
+
+Literal numbers follow C conventions.  Specifically, they are
+base-ten by default, but can be hexadecimal, binary or octal
+with a leading 0x or 0X, 0b or OB, or a simple leading zero,
+respectively.
+
+There is no support for floating point representations at all.
+
+Most math and expression handling is assumed to be 64-bit, but
+a cell-context may force a 32-bit container instead.
+
+
+4.5.5) Literal Strings
+
+Strings support common escape sequences from C:
+    "\n", "\t", "\r"
+    "\(octal value)"
+    "\x(hex value)"
+
+
+4.5.6) Identifiers
+
+Identifiers references are resolved using dynamic symbol table
+scoping rules.  An identifier referenced on the right-hand-side
+of an expression must be resolvable or else it is an error.
+
+An identifier occurring on the left-hand-side of a ':=' assignment
+is first sought and used if found.  If it is not found, it is
+introduced dynamically in the innermost, current scope.
+
+Sometimes identifiers can be used without the leading slash,
+other times they are required, especially if to disambiguate
+from property names.  It's not ideal yet at all.
+
+
+4.6) Labels and References
 
 Labels may be applied to nodes or properties.  Labels appear
 before a node name, and are referenced using an ampersand: &label.
@@ -239,6 +637,34 @@ And used in properties, lables may appear before or after any value:
 	...
     };
 
+The names of some labels can be constructed in an expression
+context using the representation "&( <string_expr> )".
+
+
+4.7) Symbol Table
+
+During the execution of the program, the evaluation context for
+both statements and expressions is performed in the context of
+a dynamic scoping environment.  That is, as each function,
+subroutine or for-loop is encountered, a new symbol table scope
+is pushed onto a dynamic run-time stack.  When an identifier's
+name needs to be resolved and a value for it determined, a
+search is performed from the inner-most, current top of the
+scope-stack back through the dynamic scope stack towards the
+outer-most and earliest scope.
+
+At each scope, an attempt is made to locate the symbol.  If it
+is found, that is the symbol that is used.  If the symbol can not
+be found at any level, it may be an error, or it may be cause to
+introduce the symbol, as determined by the context in which the
+identifier occurs.
+
+Constants from the command line using the "-D id=value" construct
+are introduced into the outermost scope prior to beginning to
+execute the source file proper.  This is the same outer-most scope
+into which the /const/ and /define/ function symbols are also
+introduced.
+
 
 
 II - The DT block format
-- 
1.6.0.90.g436ed

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 9/9 V3] Test constant expressions in cell contexts.
       [not found]                                 ` <1222460748-20127-9-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-26 20:25                                   ` Jon Loeliger
       [not found]                                     ` <1222460748-20127-10-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
  2008-09-30 14:55                                   ` [PATCH 8/9 V3] Add documentation for the new DTS language Grant Likely
  1 sibling, 1 reply; 79+ messages in thread
From: Jon Loeliger @ 2008-09-26 20:25 UTC (permalink / raw)
  To: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

From: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>

This code is derived from code posted by David Gibson.

Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 tests/Makefile.tests     |    1 +
 tests/cell-expressions.c |  116 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/run_tests.sh       |    5 ++
 3 files changed, 122 insertions(+), 0 deletions(-)
 create mode 100644 tests/cell-expressions.c

diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index 44021b0..55aa1de 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -10,6 +10,7 @@ LIB_TESTS_L = get_mem_rsv \
 	move_and_save mangle-layout nopulate \
 	open_pack rw_tree1 set_name setprop del_property del_node \
 	string_escapes references path-references boot-cpuid incbin \
+	cell-expressions \
 	dtbs_equal_ordered \
 	add_subnode_with_nops path_offset_aliases
 LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
diff --git a/tests/cell-expressions.c b/tests/cell-expressions.c
new file mode 100644
index 0000000..453cd81
--- /dev/null
+++ b/tests/cell-expressions.c
@@ -0,0 +1,116 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ *	Testcase for dtc expression support
+ * Copyright (C) 2008 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+struct test_expr {
+	const char *expr;
+	uint32_t result;
+} expr_table[] = {
+#define TE(expr)	{ #expr, (expr) }
+	TE(0xdeadb00f),
+	TE(-0x21524111),
+	TE(1+1),
+	TE(2*3),
+	TE(4/2),
+	TE(10/3),
+	TE(19%4),
+	TE(1 << 13),
+	TE(3*2+1), TE(3*(2+1)),
+	TE(1+2*3), TE((1+2)*3),
+	TE(1 < 2), TE(2 < 1), TE(1 < 1),
+	TE(1 <= 2), TE(2 <= 1), TE(1 <= 1),
+	TE(1 > 2), TE(2 > 1), TE(1 > 1),
+	TE(1 >= 2), TE(2 >= 1), TE(1 >= 1),
+	TE(1 == 1), TE(1 == 2),
+	TE(1 != 1), TE(1 != 2),
+	TE(0xabcdabcd & 0xffff0000),
+	TE(0xdead4110 ^ 0xf0f0f0f0),
+	TE(0xabcd0000 | 0x0000abcd),
+	TE(~0x21524110), TE(~~0xdeadbeef),
+	TE(0 && 0), TE(17 && 0), TE(0 && 17), TE(17 && 17),
+	TE(0 || 0), TE(17 || 0), TE(0 || 17), TE(17 || 17),
+	TE(!0), TE(!1), TE(!17), TE(!!0), TE(!!17),
+	TE(0 ? 17 : 39), TE(1 ? 17 : 39), TE(17 ? 0xdeadbeef : 0xabcd1234),
+	//	TE(11 * 257 * 1321517),
+	TE(123456790 - 4/2 + 17%4),
+};
+
+#define ARRAY_SIZE(x)	(sizeof(x) / sizeof((x)[0]))
+
+int main(int argc, char *argv[])
+{
+	void *fdt;
+	const uint32_t *res;
+	int reslen;
+	int i;
+
+	test_init(argc, argv);
+
+	if ((argc == 3) && (strcmp(argv[1], "-g") == 0)) {
+		FILE *f = fopen(argv[2], "w");
+
+		if (!f)
+			FAIL("Couldn't open \"%s\" for output: %s\n",
+			     argv[2], strerror(errno));
+
+		fprintf(f, "/dts-v1/;\n");
+		fprintf(f, "/ {\n");
+		fprintf(f, "\texpressions = <\n");
+		for (i = 0; i < ARRAY_SIZE(expr_table); i++)
+			fprintf(f, "\t\t(%s)\n", expr_table[i].expr);
+		fprintf(f, "\t>;\n");
+		fprintf(f, "};\n");
+		fclose(f);
+	} else {
+		fdt = load_blob_arg(argc, argv);
+
+		res = fdt_getprop(fdt, 0, "expressions", &reslen);
+
+		if (!res)
+			FAIL("Error retreiving expression results: %s\n",
+		     fdt_strerror(reslen));
+
+		if (reslen != (ARRAY_SIZE(expr_table) * sizeof(uint32_t)))
+			FAIL("Unexpected length of results %d instead of %d\n",
+			     reslen,
+			     (int)(ARRAY_SIZE(expr_table) * sizeof(uint32_t)));
+
+		for (i = 0; i < ARRAY_SIZE(expr_table); i++)
+			if (fdt32_to_cpu(res[i]) != expr_table[i].result)
+				FAIL("Incorrect result for expression \"%s\","
+				     " 0x%x instead of 0x%x\n",
+				     expr_table[i].expr, res[i],
+				     expr_table[i].result);
+	}
+
+	PASS();
+}
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 30cd9a1..fc7162a 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -274,6 +274,11 @@ dtc_tests () {
     run_dtc_test -I dtb -O dts -o stdin_odts_test_tree1.dtb.test.dts - < test_tree1.dtb
     run_wrap_test cmp stdin_odts_test_tree1.dtb.test.dts odts_test_tree1.dtb.test.dts
 
+    # Check integer expresisons
+    run_test cell-expressions -g cell-expressions.test.dts
+    run_dtc_test -I dts -O dtb -o cell-expressions.test.dtb cell-expressions.test.dts
+    run_test cell-expressions cell-expressions.test.dtb
+
     # Check for graceful failure in some error conditions
     run_sh_test dtc-fatal.sh -I dts -O dtb nosuchfile.dts
     run_sh_test dtc-fatal.sh -I dtb -O dtb nosuchfile.dtb
-- 
1.6.0.90.g436ed

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* Re: [PATCH 1/9 V3] Remove support for the legacy DTS source file format.
       [not found]     ` <1222460748-20127-2-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
  2008-09-26 20:25       ` [PATCH 2/9 V3] Add conditionalized debug() print macro Jon Loeliger
@ 2008-09-30  5:57       ` David Gibson
       [not found]         ` <20080930055716.GA18695-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
  1 sibling, 1 reply; 79+ messages in thread
From: David Gibson @ 2008-09-30  5:57 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Fri, Sep 26, 2008 at 03:25:40PM -0500, Jon Loeliger wrote:
> Now that all in-kernel-tree DTS files are properly /dts-v1/,
> remove direct support for the older, un-numbered DTS
> source file format.
> 
> Convert existing tests to /dts-v1/ and remove support
> for the conversion tests themselves.
> 
> For now, though, the conversion tool still exists.

Hrm.  Again, I don't think we should need to do this.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 3/9 V3] Enhance source position implementation.
       [not found]             ` <1222460748-20127-4-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
  2008-09-26 20:25               ` [PATCH 4/9 V3] Add header files for new Internal Representation form Jon Loeliger
@ 2008-09-30  6:00               ` David Gibson
  1 sibling, 0 replies; 79+ messages in thread
From: David Gibson @ 2008-09-30  6:00 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Fri, Sep 26, 2008 at 03:25:42PM -0500, Jon Loeliger wrote:
> Implemented some print and copy routines.
> Made empty srcpos objects that will be used later.
> Protected .h file from multiple #include's.

Can we separate this out as a different series.  I've been thinking
the srcpos stuff needs some cleanup for a while, and this is not
directly relevant to the IR stuff, which I think needs considerably
more discussion and thought.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 4/9 V3] Add header files for new Internal Representation form.
       [not found]                 ` <1222460748-20127-5-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
  2008-09-26 20:25                   ` [PATCH 5/9 V3] Add most of the new IR implementation files Jon Loeliger
@ 2008-09-30  6:03                   ` David Gibson
  1 sibling, 0 replies; 79+ messages in thread
From: David Gibson @ 2008-09-30  6:03 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Fri, Sep 26, 2008 at 03:25:43PM -0500, Jon Loeliger wrote:
> Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>

I think patches 4, 5, 6 and 7 should be merged together.  Splitting
patches into logical sections is ok, but these are all basically
interdependent.  Sure, the ordering you have doesn't actually break
bisect, but the earlier patches don't *do* anything until the later
ones activate them, so there's really no point separating them out.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 9/9 V3] Test constant expressions in cell contexts.
       [not found]                                     ` <1222460748-20127-10-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
@ 2008-09-30  6:04                                       ` David Gibson
       [not found]                                         ` <20080930060418.GD18695-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: David Gibson @ 2008-09-30  6:04 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Fri, Sep 26, 2008 at 03:25:48PM -0500, Jon Loeliger wrote:
> From: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> 
> This code is derived from code posted by David Gibson.

[snip]
> +		for (i = 0; i < ARRAY_SIZE(expr_table); i++)
> +			if (fdt32_to_cpu(res[i]) != expr_table[i].result)

Hrm.. when you fixed the endian bug here (I found it myself the other
day), you might have thought to fix it...


> +				FAIL("Incorrect result for expression \"%s\","
> +				     " 0x%x instead of 0x%x\n",
> +				     expr_table[i].expr, res[i],
                                                         ^^^^^^

...here, too.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                 ` <1222460748-20127-9-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
  2008-09-26 20:25                                   ` [PATCH 9/9 V3] Test constant expressions in cell contexts Jon Loeliger
@ 2008-09-30 14:55                                   ` Grant Likely
       [not found]                                     ` <20080930145537.GJ18313-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
  1 sibling, 1 reply; 79+ messages in thread
From: Grant Likely @ 2008-09-30 14:55 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Fri, Sep 26, 2008 at 03:25:47PM -0500, Jon Loeliger wrote:
> From: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> 
> Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> ---
>  Documentation/manual.txt |  500 ++++++++++++++++++++++++++++++++++++++++++----
>  1 files changed, 463 insertions(+), 37 deletions(-)

Hey Jon,

I don't yet have fully formed thoughts about this stuff so I've held off
on making comments.  But FWIW, here are my initial thoughts.

I'm not convinced about the approach of interleaving the executable and
data syntaxes.  The whole design of the existing syntax is to represent
the data structure.  Adding additional syntax to define executable
elements doesn't feel right to me.  I think many people will find the
resulting file structure to be confusing.

I'm also not convinced that it is a good idea to implement a new
interpreted language.  Any new language is a new thing that needs to be
maintained and a new thing for users to learn.  I'd prefer to make use
of an existing language with a library of support routines for
maintaining an internal representation of the data and building up a
device tree programmatically with the ability to import and manipulate
'stock' nodes for existing parts.  However, I haven't spent enough brain
cell cycles on this to make any recommendations on a specific language
or to figure out if that will just result in even more complexity for
users.

As I said, these are just initial thoughts.  My opinion could be swayed.

g.

> 
> diff --git a/Documentation/manual.txt b/Documentation/manual.txt
> index b957662..ac56309 100644
> --- a/Documentation/manual.txt
> +++ b/Documentation/manual.txt
> @@ -105,13 +105,21 @@ Options:
>      -q
>  	Quiet: -q suppress warnings, -qq errors, -qqq all
>  
> +    -D <id>
> +    -D <id>=<value>
> +	Introduce a constant definition for symbol <id> with
> +	possible initial value given by <value>.  The RHS
> +	should be a literal number or string value.
> +
> +    -p <padsize>
> +	Add at least <padsize> additional space to the DTB image.
> +
>      -R <number>
>  	Make space for <number> reserve map entries
>  	Relevant for dtb and asm output only.
>  
>      -S <bytes>
> -	Ensure the blob at least <bytes> long, adding additional
> -	space if needed.
> +	Deprecated option.
>  
>      -v
>  	Print DTC version and exit.
> @@ -131,47 +139,338 @@ Additionally, dtc performs various sanity checks on the tree.
>  
>  4) Device Tree Source file
>  
> -4.1) Overview
>  
> -Here is a very rough overview of the layout of a DTS source file:
> +4.1) DTS Lexical Components
> +
> +Property and node names		[a-zA-Z0-9,._+*#?@-]+
> +Identifiers			\\[a-zA-Z_][a-zA-Z0-9_]*
> +Labels				[a-zA-Z_][a-zA-Z0-9_]*
> +Strings				<C-style-double-quoted-strings>
> +Comments			Both /* ... */ and // style are supported
> +Numeric literals		<C-style-integer-numbers>
> +Bytes				[0-9a-fA-F][0-9a-fA-F]
> +
> +Keywords:
> +	else
> +	for
> +	if
> +	in
> +	return
> +	void
> +	/const/
> +	/define/
> +	/incbin/
> +
> +C-style expression operators:
> +	<<
> +	>>
> +	<=
> +	>=
> +	==
> +	!=
> +	&&
> +	||
> +	+
> +	-
> +	*
> +	/
> +	%
> +
> +Additional tokens:
> +	..
> +	:=
> +	{
> +	}
> +	,
> +	&
> +
> +
> +These constructs are handled and eliminated purely at the
> +lexical level and do not appear in the grammar proper:
> +
> +    - Source files included using the syntax:
> +
> +        /include/ "filename"
> +
> +    - Both classic C style and C++ style comments are supported.
> +      Comments don't nest.
> +      For example, given:
> +
> +	1    /*
> +	2     *  asdasdasd  // asdasdad
> +	3     //   */
> +	4    asasd
> +	5     */
> +      The // comment on line 3 is not effective and is ignored.
> +      The original /* comment ends on line 3.  Line 5 is in error.
> +
> +      And given:
> +
> +	1    // /*
> +	2     *  asdasdasd  // asdasdad
> +	3     */
> +
> +      The // comment on line 1 hides the opening /*.
> +      Line 2 is in error.
> +
> +
> +4.2) DTS Grammar
> +
> +Here is a very rough overview of the grammar of a DTS source file:
> +
> +
> +    sourcefile:
> +		'/dts-v1/' ';' possibly_empty_list_of_declarations devicetree
> +
> +    declaration:
> +		  memreserve
> +		| constdef
> +		| funcdef
> +
> +    memreserve:	label '/memreserve/' addr addr ';'
> +
> +    constdef:	'/const/' identifier '=' expr ';'
> +
> +    funcdef:	'/define/' propnodename paramdecls statement_block
> +
> +    paramdecls:	'(' possibly_empty_paramdecl_list ')'
> +
> +    paramdecl: identifier
> +
> +    devicetree:   '/' statement_block
> +
> +    statement_block: '{' possibly_empty_list_of_statements '}'
> +
> +    statement:
> +		  subnode
> +		| for_statement
> +		| if_statement
> +		| return_statement
> +		| assign_statement
> +		| property_definition
> +		| statement_block
> +		| ';'
> +
> +    subnode:
> +		  node_label expr statement_block ';'
> +		|      label expr statement_block ';'
> +		|            expr statement_block ';'
> +
> +    for_statement:
> +		'for' identifier 'in' expr '..' expr statement_block
> +
> +    if_statement:
> +		  'if' '(' expr ')' statement_block
> +		| 'if' '(' expr ')' statement_block 'else' statement_block
> +
> +    return_statement: 'return' expr ';'
> +
> +    assign_statement: identifier ':=' expr ';'
> +
> +    property_definition:
> +		  optional_label expr ';'
> +		| optional_label expr '=' list_of_property_data_and_labels ';'
>  
> +    list_of_property_data_and_labels:
> +		  STRING
> +		| '<' possibly_empty_list_of_cell_values_and_labels '>'
> +		| '[' possibly_empty_list_of_byte_values_and_labels ']'
> +		| label
> +		| '/incbin/' '(' expr ')'
> +		| '/incbin/' '(' expr ',' expr ',' expr ')'
>  
> -    sourcefile:   list_of_memreserve devicetree
> +    cell_value:
> +		  expr_primary
> +		| '&' '(' expr ')'
> +		| '&' phandle_reference
> +		| label
>  
> -    memreserve:   label 'memreserve' ADDR ADDR ';'
> -		| label 'memreserve' ADDR '-' ADDR ';'
>  
> -    devicetree:   '/' nodedef
> +    expr:
> +          expr_primary
> +	| expr '?' expr ':' expr
> +	| expr expr_oper expr
>  
> -    nodedef:      '{' list_of_property list_of_subnode '}' ';'
> +    expr_oper:
> +	||
> +        &&
> +	|
> +	^
> +	&
> +	==
> +	< | > | <= | >=
> +	<< | >>
> +	+ | -
> +	* | / | %
> +	- | ~ | !
> +        '(' ')' | '(' non_empty_list_of_param_exprs ')'
>  
> -    property:     label PROPNAME '=' propdata ';'
> +    expr_primary:
> +	  literal
> +	| string
> +	| propnodename
> +	| identifier
> +	| '(' expr ')'
>  
> -    propdata:     STRING
> -		| '<' list_of_cells '>'
> -		| '[' list_of_bytes ']'
> +    addr:	expr
>  
> -    subnode:      label nodename nodedef
> +    node_label:	expr ':'
>  
> -That structure forms a hierarchical layout of nodes and properties
> -rooted at an initial node as:
> +    propnodename: <1275-property-name>
> +
> +    identifier:	'\'-<C style name>
> +
> +    literal:	<C style number>
> +    byte:	<exactly two hex digits>
> +    string:	<C style string>
> +    label:	'&'-<label name>-':'
> +
> +
> +4.2) Overview
> +
> +The DTS source file begins with the '/dts-v1/' token to state
> +that it is using "Version 1" style source files.
> +
> +Any declarations are executed in order, and can use the
> +effects of earlier declarations.
> +
> +All declarations must precede the required root node definition,
> +which is introduced with the '/'-named node:
>  
>      / {
> +	...
>      }
>  
> -Both classic C style and C++ style comments are supported.
> +The statement-block structure forms a hierarchical layout of nodes
> +and properties along with some control-statements that allow for
> +repeated and alternate statement blocks.
> +
> +
> +4.3) Declarations
> +
> +An arbitrary list of declarations can be made between '/dts-v1/'
> +and the beginning of the root node.  These declarations are
> +introduced in order.
> +
> +
> +4.3.1) Memory Reservations
> +
> +A memory reservation is a declaration that a block of memory
> +from the first address expression, with a size given by the
> +second address expression, is to be "reserved" and not used
> +by the kernel.  These address ranges are passed through to
> +the DTB to the kernel.
> +
> +
> +4.3.2) Function Definitions
> +
> +A function definition can be introduced using /define/.
> +These definitions are just "stored" and then later invoked as
> +either a subroutine in a statement context, or as a function
> +with a return value in an expression context.
>  
> -Source files may be directly included using the syntax:
> +Functions declare the number of formal parameters which will
> +be passed in at the call site, and must match one-to-one.
>  
> -    /include/ "filename"
> +Any property definitions generated by the function are emitted
> +into the caller's context at the point of the call.
>  
> +Any node definitions generated by the function are emitted
> +into the caller's context at the point of the call.
>  
> -4.2) Properties
>  
> -Properties are named, possibly labeled, values.  Each value
> -is one of:
> +4.3.3) Constant Definitions
>  
> -    - A null-teminated C-like string,
> +Constant definitions introduce a named identifier into the outer-most
> +symbol scope.  The constants can not be changed by later assignment
> +statements, though they can be hidden.  (Be careful.)
> +
> +Constants may be expressions yielding constant numeric or strings
> +values.  It is an error for them not to be evaluatable at their
> +point of definition.
> +
> +Constant definitions may also be introduced from the command line
> +using the '-D var=value" options.  They will be placed into the
> +same outer-most scope.  Constant definitions from the command line
> +override the definitions within the source file, but with a warning.
> +
> +
> +4.4) Statements
> +
> +A statement block is simply a list of sequentially executed
> +statements introduced with a required opening brace and terminated
> +with a required closing brace.
> +
> +4.4.1) Subnodes
> +
> +Node may contain sub-nodes to obtain a hierarchical structure.
> +
> +For example:
> +
> +    - A child node named "childnode" whose unit name is
> +      "childnode at address".  It it turn has a string property
> +      called "childprop".
> +
> +	childnode@address {
> +	    childprop = "hello\n";
> +	};
> +
> +
> +4.4.2) 'for' Statement
> +
> +The 'for' statement provides iterative execution of a
> +block of statements.
> +
> +The lower bound of the range is evaluated once, and the
> +upper bound is evaluated once.
> +
> +A new scope that contains the loop variable is created
> +and pushed onto the symbol table scope stack.  The loop
> +variable is initialized with the lower bound value.
> +
> +The statement block is executed once for each inclusive value
> +in the given range in increasing order.
> +
> +After the loop terminates, the loop variable scope is popped.
> +
> +
> +4.4.3) 'if' Statement
> +
> +The 'if' statement provides alternate execution flow paths.
> +The expression is evaluated once, and if non-zero, the fist
> +statement block is executed, otherwise the 'else' block of
> +statements is executed if present.
> +
> +
> +4.4.4) 'return' Statement
> +
> +Inside a function definition, the 'return' statement allows
> +a value to be passed back to the caller.  The return expression
> +is evaluated once, in the context of the function's scope,
> +and its resultant value is made available as the function's
> +return result.
> +
> +
> +4.4.5) Assign Statement
> +
> +The ':=' operator allows assignment to non-constant identifiers.
> +
> +The identifiers can be either formal parameters or variable as
> +found by the searching using the dynamic symbol table scoping rules.
> +
> +An assignment to an otherwise unknown identifier causes that
> +identifier to be introduced into the current scope.
> +
> +You can't assign to /constant/ identifiers (except in the initial
> +definition of them).
> +
> +
> +4.4.6) Property Definition
> +
> +Properties are named, possibly labeled, values.
> +Each value within a property is one of:
> +
> +    - A null-terminated C-like string,
>      - A numeric value fitting in 32 bits,
>      - A list of 32-bit values
>      - A byte sequence
> @@ -195,27 +494,126 @@ Here are some example property definitions:
>  	property4 = [0a 0b 0c 0d de ea ad be ef];
>  
>  
> -Node may contain sub-nodes to obtain a hierarchical structure.
> -For example:
> +4.4.7) Subroutine calls
>  
> -    - A child node named "childnode" whose unit name is
> -      "childnode at address".  It it turn has a string property
> -      called "childprop".
> +An expression at the statement level should be a function call,
> +though it might be considered as just a "subroutine call" as
> +any return value is thrown away.
>  
> -	childnode@addresss {
> -	    childprop = "hello\n";
> -	};
> +Invocation of the function introduces a symbol table scope
> +in which the formal paramters are introduced and bound.
> +Initial values for the formals are obtained by evaluating
> +the actual parameters, in order, and using a copy-in binding.
> +
> +Any incidental (dynamically occurring) assignment to an
> +otherwise unknown identifier will cause the introduction of
> +a new variable in the function's execution scope.
> +
> +Any property definitions generated by the function are emitted
> +into the caller's context at the point of the subroutine call.
> +
> +Any node definitions generated by the function are emitted
> +into the caller's context at the point of the subroutine call.
> +
> +Any return value from a return statement is thrown away.
>  
> +Execution control is returned to the point of the call.
>  
> -By default, all numeric values are hexadecimal.  Alternate bases
> -may be specified using a prefix "d#" for decimal, "b#" for binary,
> -and "o#" for octal.
>  
> -Strings support common escape sequences from C: "\n", "\t", "\r",
> -"\(octal value)", "\x(hex value)".
> +4.5) Expressions
>  
> +Basically, expressions follow C conventions.  However, there
> +are no assignment operations such as +=, or pre-/post-
> +increment/decrement.
>  
> -4.3) Labels and References
> +The '%' operation is a modulus operation for integers, and
> +a string concatenation operation if at least one of the operands
> +is determined to be a string value.
> +
> +
> +4.5.1) Expressions
> +
> +Pretend it is C and see how close we get.
> +
> +
> +4.5.2) Function Invocations
> +
> +A previously defined function may be invoked from within an
> +expression.  A "return" statement should be used to return
> +a resulting expression value to the caller's context.
> +
> +Invocation of the function introduces a symbol table scope
> +in which the formal parameters are introduced and bound.
> +Initial values for the formals are obtained by evaluating
> +the actual parameters, in order, and using a copy-in binding.
> +
> +Any incidental (dynamically occurring) assignment to an
> +otherwise unknown identifier will cause the introduciton of
> +a new variable in the function's execution scope.
> +
> +Any property definitions generated by the function are emitted
> +into the caller's context at the point of the subroutine call.
> +
> +Any node definitions generated by the function are emitted
> +into the caller's context at the point of the subroutine call.
> +
> +Any return value from a return statement is used as the result
> +of the function call within the context of the original expression.
> +
> +Execution control is returned to the point of the call.
> +
> +
> +4.5.3) Builtin Functions
> +
> +There are a few builtin function names;
> +
> +    join()	Concatenate and return a list of expression
> +		as a string.  Non-string arguments are coerced
> +		into being a string.
> +
> +    hexstr()	Format and return a hex string representation
> +		of the one parameter without a leading '0x'.
> +
> +While not here yet, /incbin/ should be converted into a builtin.
> +
> +
> +4.5.4) Literal Numbers
> +
> +Literal numbers follow C conventions.  Specifically, they are
> +base-ten by default, but can be hexadecimal, binary or octal
> +with a leading 0x or 0X, 0b or OB, or a simple leading zero,
> +respectively.
> +
> +There is no support for floating point representations at all.
> +
> +Most math and expression handling is assumed to be 64-bit, but
> +a cell-context may force a 32-bit container instead.
> +
> +
> +4.5.5) Literal Strings
> +
> +Strings support common escape sequences from C:
> +    "\n", "\t", "\r"
> +    "\(octal value)"
> +    "\x(hex value)"
> +
> +
> +4.5.6) Identifiers
> +
> +Identifiers references are resolved using dynamic symbol table
> +scoping rules.  An identifier referenced on the right-hand-side
> +of an expression must be resolvable or else it is an error.
> +
> +An identifier occurring on the left-hand-side of a ':=' assignment
> +is first sought and used if found.  If it is not found, it is
> +introduced dynamically in the innermost, current scope.
> +
> +Sometimes identifiers can be used without the leading slash,
> +other times they are required, especially if to disambiguate
> +from property names.  It's not ideal yet at all.
> +
> +
> +4.6) Labels and References
>  
>  Labels may be applied to nodes or properties.  Labels appear
>  before a node name, and are referenced using an ampersand: &label.
> @@ -239,6 +637,34 @@ And used in properties, lables may appear before or after any value:
>  	...
>      };
>  
> +The names of some labels can be constructed in an expression
> +context using the representation "&( <string_expr> )".
> +
> +
> +4.7) Symbol Table
> +
> +During the execution of the program, the evaluation context for
> +both statements and expressions is performed in the context of
> +a dynamic scoping environment.  That is, as each function,
> +subroutine or for-loop is encountered, a new symbol table scope
> +is pushed onto a dynamic run-time stack.  When an identifier's
> +name needs to be resolved and a value for it determined, a
> +search is performed from the inner-most, current top of the
> +scope-stack back through the dynamic scope stack towards the
> +outer-most and earliest scope.
> +
> +At each scope, an attempt is made to locate the symbol.  If it
> +is found, that is the symbol that is used.  If the symbol can not
> +be found at any level, it may be an error, or it may be cause to
> +introduce the symbol, as determined by the context in which the
> +identifier occurs.
> +
> +Constants from the command line using the "-D id=value" construct
> +are introduced into the outermost scope prior to beginning to
> +execute the source file proper.  This is the same outer-most scope
> +into which the /const/ and /define/ function symbols are also
> +introduced.
> +
>  
>  
>  II - The DT block format
> -- 
> 1.6.0.90.g436ed
> 
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss-mnsaURCQ41sdnm+yROfE0A@public.gmane.org
> https://ozlabs.org/mailman/listinfo/devicetree-discuss

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 9/9 V3] Test constant expressions in cell contexts.
       [not found]                                         ` <20080930060418.GD18695-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
@ 2008-09-30 15:46                                           ` Jon Loeliger
  0 siblings, 0 replies; 79+ messages in thread
From: Jon Loeliger @ 2008-09-30 15:46 UTC (permalink / raw)
  To: David Gibson; +Cc: devicetree-discuss

On Tue, 2008-09-30 at 16:04 +1000, David Gibson wrote:
> On Fri, Sep 26, 2008 at 03:25:48PM -0500, Jon Loeliger wrote:
> > From: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> > 
> > This code is derived from code posted by David Gibson.
> 
> [snip]
> > +		for (i = 0; i < ARRAY_SIZE(expr_table); i++)
> > +			if (fdt32_to_cpu(res[i]) != expr_table[i].result)
> 
> Hrm.. when you fixed the endian bug here (I found it myself the other
> day), you might have thought to fix it...
> 
> 
> > +				FAIL("Incorrect result for expression \"%s\","
> > +				     " 0x%x instead of 0x%x\n",
> > +				     expr_table[i].expr, res[i],
>                                                          ^^^^^^
> 
> ...here, too.


Gah.  Sorry.  I'll definitely pick that up.

jdl

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 1/9 V3] Remove support for the legacy DTS source file format.
       [not found]         ` <20080930055716.GA18695-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
@ 2008-09-30 16:30           ` Scott Wood
       [not found]             ` <48E2541B.1000801-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Scott Wood @ 2008-09-30 16:30 UTC (permalink / raw)
  To: David Gibson; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

David Gibson wrote:
> On Fri, Sep 26, 2008 at 03:25:40PM -0500, Jon Loeliger wrote:
>> Now that all in-kernel-tree DTS files are properly /dts-v1/,
>> remove direct support for the older, un-numbered DTS
>> source file format.
>>
>> Convert existing tests to /dts-v1/ and remove support
>> for the conversion tests themselves.
>>
>> For now, though, the conversion tool still exists.
> 
> Hrm.  Again, I don't think we should need to do this.

Older dtc versions are still around for those that need them...  IIUC, 
keeping the old syntax around will complicate the code when adding the 
new features.

-Scott

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 1/9 V3] Remove support for the legacy DTS source file format.
       [not found]             ` <48E2541B.1000801-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
@ 2008-10-01  1:26               ` David Gibson
  0 siblings, 0 replies; 79+ messages in thread
From: David Gibson @ 2008-10-01  1:26 UTC (permalink / raw)
  To: Scott Wood; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Tue, Sep 30, 2008 at 11:30:19AM -0500, Scott Wood wrote:
> David Gibson wrote:
>> On Fri, Sep 26, 2008 at 03:25:40PM -0500, Jon Loeliger wrote:
>>> Now that all in-kernel-tree DTS files are properly /dts-v1/,
>>> remove direct support for the older, un-numbered DTS
>>> source file format.
>>>
>>> Convert existing tests to /dts-v1/ and remove support
>>> for the conversion tests themselves.
>>>
>>> For now, though, the conversion tool still exists.
>>
>> Hrm.  Again, I don't think we should need to do this.
>
> Older dtc versions are still around for those that need them...
> IIUC, keeping the old syntax around will complicate the code when
> adding the new features.

I realise that, I'm just not all that convinced it's a good tradeoff
at this time.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                     ` <20080930145537.GJ18313-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
@ 2008-10-01  3:46                                       ` David Gibson
       [not found]                                         ` <20081001034656.GF30810-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: David Gibson @ 2008-10-01  3:46 UTC (permalink / raw)
  To: Grant Likely; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Tue, Sep 30, 2008 at 08:55:37AM -0600, Grant Likely wrote:
> On Fri, Sep 26, 2008 at 03:25:47PM -0500, Jon Loeliger wrote:
> > From: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> > 
> > Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> > ---
> >  Documentation/manual.txt |  500 ++++++++++++++++++++++++++++++++++++++++++----
> >  1 files changed, 463 insertions(+), 37 deletions(-)
> 
> Hey Jon,
> 
> I don't yet have fully formed thoughts about this stuff so I've held off
> on making comments.  But FWIW, here are my initial thoughts.
> 
> I'm not convinced about the approach of interleaving the executable and
> data syntaxes.  The whole design of the existing syntax is to represent
> the data structure.  Adding additional syntax to define executable
> elements doesn't feel right to me.  I think many people will find the
> resulting file structure to be confusing.
> 
> I'm also not convinced that it is a good idea to implement a new
> interpreted language.  Any new language is a new thing that needs to be
> maintained and a new thing for users to learn.  I'd prefer to make use
> of an existing language with a library of support routines for
> maintaining an internal representation of the data and building up a
> device tree programmatically with the ability to import and manipulate
> 'stock' nodes for existing parts.  However, I haven't spent enough brain
> cell cycles on this to make any recommendations on a specific language
> or to figure out if that will just result in even more complexity for
> users.
> 
> As I said, these are just initial thoughts.  My opinion could be
> swayed.

Ah, thank you Grant, you've helped clarify by own objections to the
current proposal.

The current device tree description is purely declarative, but this
proposal would make it a rather odd hybrid of declarative and
imperative components.  I do think this could be confusing,
particularly to device tree newcomers who may not realise which
components are compile time evaluated and which go into the output
tree.  I had in mind a rather more functional-programming style for
macros/computed properties to ameliorate this.

The several new components of not-C-feel syntax worry me greatly.  If
you recall the one time I stepped away from C-inspired syntax in the
original language (bare hex constants), turned out to be a big mistake
requiring an incompatible source format change to fix.  I really want
to avoid doing that again, if we possibly can.

I'm also concerned about adding language-level functions to the
language.  This requires us to have runtime notions of type and
symbols and carry them around for evaluation.  I still favour a
macro-expansion style preprocessing stage instead of semantic-level
functions for several reasons:
	- it provides high flexibility for low conceptual complexity
	- we don't have to carry around run-time evaluation structures
	- it's a form familiar to C programmers from the preprocessor

This could either be done by actually invoking cpp, using some
pre-and-post mangling to deal with the #-in-property-names problem.
Or we could build our own preprocessor that uses something other than
# as a magic character, but otherwise works like cpp.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                         ` <20081001034656.GF30810-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
@ 2008-10-01  4:01                                           ` Warner Losh
       [not found]                                             ` <20080930.220151.41675821.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org>
  2008-10-01 15:26                                           ` Scott Wood
  2010-02-20 16:13                                           ` Grant Likely
  2 siblings, 1 reply; 79+ messages in thread
From: Warner Losh @ 2008-10-01  4:01 UTC (permalink / raw)
  To: david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+
  Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

From: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Date: Wed, 1 Oct 2008 13:46:56 +1000

> This could either be done by actually invoking cpp, using some
> pre-and-post mangling to deal with the #-in-property-names problem.
> Or we could build our own preprocessor that uses something other than
> # as a magic character, but otherwise works like cpp.

There's always m4, but that has its own set of issues.

Not sure if I should add a :-) or a :-(.

You could also s/#/$/g on the source and pass that through cpp and
then undo it on the other side.  Assuming that cpp has been compiled
with $ in symbol name support.

The root of the problem here is that the original openfirmware spec
wasn't 'C' and many of the new language features are aimed at a 'C'
audience...

Warner

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                             ` <20080930.220151.41675821.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org>
@ 2008-10-01  4:22                                               ` David Gibson
  0 siblings, 0 replies; 79+ messages in thread
From: David Gibson @ 2008-10-01  4:22 UTC (permalink / raw)
  To: Warner Losh; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Tue, Sep 30, 2008 at 10:01:51PM -0600, Warner Losh wrote:
> From: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
> Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
> Date: Wed, 1 Oct 2008 13:46:56 +1000
> 
> > This could either be done by actually invoking cpp, using some
> > pre-and-post mangling to deal with the #-in-property-names problem.
> > Or we could build our own preprocessor that uses something other than
> > # as a magic character, but otherwise works like cpp.
> 
> There's always m4, but that has its own set of issues.

Yes.  I've thought about m4, but I'm pretty sure I don't want to go
there.

> Not sure if I should add a :-) or a :-(.
> 
> You could also s/#/$/g on the source and pass that through cpp and
> then undo it on the other side.  Assuming that cpp has been compiled
> with $ in symbol name support.

Something vaguely like that was what I had in mind - probably using
some magic based on '/' instead.  I planned to leave the processor
directives as #, but with the # only recognized in column 0.  Strictly
speaking that's a syntax change, but it won't bite any properly
indented existing source.

> The root of the problem here is that the original openfirmware spec
> wasn't 'C' and many of the new language features are aimed at a 'C'
> audience...

Well, the dtc source format has been aimed at C programmers from day
1, not just the new features.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                         ` <20081001034656.GF30810-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
  2008-10-01  4:01                                           ` Warner Losh
@ 2008-10-01 15:26                                           ` Scott Wood
       [not found]                                             ` <48E396A3.809-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
  2010-02-20 16:13                                           ` Grant Likely
  2 siblings, 1 reply; 79+ messages in thread
From: Scott Wood @ 2008-10-01 15:26 UTC (permalink / raw)
  To: David Gibson; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

David Gibson wrote:
> The current device tree description is purely declarative, but this
> proposal would make it a rather odd hybrid of declarative and
> imperative components.  I do think this could be confusing,
> particularly to device tree newcomers who may not realise which
> components are compile time evaluated and which go into the output
> tree.  I had in mind a rather more functional-programming style for
> macros/computed properties to ameliorate this.
> 
> The several new components of not-C-feel syntax worry me greatly.

Wouldn't a "more functional-programming style" be further away from C?

> If
> you recall the one time I stepped away from C-inspired syntax in the
> original language (bare hex constants), turned out to be a big mistake
> requiring an incompatible source format change to fix.  I really want
> to avoid doing that again, if we possibly can.

If you really want to be as much like C as possible, nothing's stopping 
you from just defining the data structures in real C. :-P

Bare hex constants being a bad idea was not purely due to it being 
different from C.

We also have a substantial difference in the syntax of node/property 
definitions, which forces syntax differences in other parts of the 
lanugage to avoid ambiguity.

> I'm also concerned about adding language-level functions to the
> language.  This requires us to have runtime notions of type and
> symbols and carry them around for evaluation.  I still favour a
> macro-expansion style preprocessing stage instead of semantic-level
> functions for several reasons:
> 	- it provides high flexibility for low conceptual complexity
> 	- we don't have to carry around run-time evaluation structures
> 	- it's a form familiar to C programmers from the preprocessor

I vote against anything similar to the C preprocessor.

-Scott

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                             ` <48E396A3.809-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
@ 2008-10-01 15:43                                               ` Warner Losh
       [not found]                                                 ` <20081001.094306.71131107.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org>
  2008-10-02  1:18                                               ` David Gibson
  1 sibling, 1 reply; 79+ messages in thread
From: Warner Losh @ 2008-10-01 15:43 UTC (permalink / raw)
  To: scottwood-KZfg59tc24xl57MIdRCFDg
  Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

> I vote against anything similar to the C preprocessor.

The advantage of the current language that's been floated here is that
its 'execution' elements offer a far more expressive macro generation
capability than the cpp.  cpp doesn't have for loops.  There's no way
to convert a number to hex in cpp.  Complicated if statements aren't
possible.  And so on.  m4 allows these things, but imposes
restrictions that make it awkward to use in this context, so it is out
(despite my comments yesterday, and the fact I use it to genreate the
html for my resume).  There's really no other widely available
preprocessor that would be useful here.

Then again, I'm not sure that I completely buy into the mixing data
definitions and execution elements being confusing.  We do that right
now in every C program you write with global variables...  The problem
here is that we're inventing a scripting language to generate data
structures, much like web pages are generated in some scripting
languages by haing the output be html.  There's little confusion
there (and no, I'm not suggesting we use one of them :-).

Warner

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                             ` <48E396A3.809-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
  2008-10-01 15:43                                               ` Warner Losh
@ 2008-10-02  1:18                                               ` David Gibson
       [not found]                                                 ` <20081002011800.GI25598-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
  1 sibling, 1 reply; 79+ messages in thread
From: David Gibson @ 2008-10-02  1:18 UTC (permalink / raw)
  To: Scott Wood; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Wed, Oct 01, 2008 at 10:26:27AM -0500, Scott Wood wrote:
> David Gibson wrote:
>> The current device tree description is purely declarative, but this
>> proposal would make it a rather odd hybrid of declarative and
>> imperative components.  I do think this could be confusing,
>> particularly to device tree newcomers who may not realise which
>> components are compile time evaluated and which go into the output
>> tree.  I had in mind a rather more functional-programming style for
>> macros/computed properties to ameliorate this.
>>
>> The several new components of not-C-feel syntax worry me greatly.
>
> Wouldn't a "more functional-programming style" be further away from
> C?

Yes and no - the preprocessor aspects of C are roughly
functional-programming style, at least in the sense I'm intending
here.  Besides, it's not the language as a whole that's supposed to be
like C - clearly it's not - it's the syntactic feel.  The idea is to
make syntactic analogies with C wherever possible, so that C
programmers writing dts files won't find themselves continually making
little syntactic mistakes.

>> If
>> you recall the one time I stepped away from C-inspired syntax in the
>> original language (bare hex constants), turned out to be a big mistake
>> requiring an incompatible source format change to fix.  I really want
>> to avoid doing that again, if we possibly can.
>
> If you really want to be as much like C as possible, nothing's stopping  
> you from just defining the data structures in real C. :-P
>
> Bare hex constants being a bad idea was not purely due to it being  
> different from C.
>
> We also have a substantial difference in the syntax of node/property  
> definitions, which forces syntax differences in other parts of the  
> lanugage to avoid ambiguity.

Yes.  But I think insufficient thought has gone into the current
proposal as to how to avoid ambiguity where we have to, while keeping
the C-syntactic-feel as much as possible.

>> I'm also concerned about adding language-level functions to the
>> language.  This requires us to have runtime notions of type and
>> symbols and carry them around for evaluation.  I still favour a
>> macro-expansion style preprocessing stage instead of semantic-level
>> functions for several reasons:
>> 	- it provides high flexibility for low conceptual complexity
>> 	- we don't have to carry around run-time evaluation structures
>> 	- it's a form familiar to C programmers from the preprocessor
>
> I vote against anything similar to the C preprocessor.

Why?

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                 ` <20081001.094306.71131107.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org>
@ 2008-10-02  1:20                                                   ` David Gibson
  0 siblings, 0 replies; 79+ messages in thread
From: David Gibson @ 2008-10-02  1:20 UTC (permalink / raw)
  To: Warner Losh
  Cc: scottwood-KZfg59tc24xl57MIdRCFDg,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Wed, Oct 01, 2008 at 09:43:06AM -0600, Warner Losh wrote:
> > I vote against anything similar to the C preprocessor.
> 
> The advantage of the current language that's been floated here is that
> its 'execution' elements offer a far more expressive macro generation
> capability than the cpp.  cpp doesn't have for loops.  There's no way
> to convert a number to hex in cpp.

But those can be done in expressions which the macros can generate.
It's just a matter of implementing the right operators and builtin
functions.

>  Complicated if statements aren't
> possible.  And so on.  m4 allows these things, but imposes
> restrictions that make it awkward to use in this context, so it is out
> (despite my comments yesterday, and the fact I use it to genreate the
> html for my resume).  There's really no other widely available
> preprocessor that would be useful here.
> 
> Then again, I'm not sure that I completely buy into the mixing data
> definitions and execution elements being confusing.  We do that right
> now in every C program you write with global variables...  The problem
> here is that we're inventing a scripting language to generate data
> structures, much like web pages are generated in some scripting
> languages by haing the output be html.  There's little confusion
> there (and no, I'm not suggesting we use one of them :-).

Hrm, yes.  And I really dislike the idea of creating yet-another
scripting language just for our purposes.  It may be simple now, but I
greatly fear if we start down this path it will grow to become a
Turing-complete monstrosity.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 7/9 V3] Introduce new DTS language.
       [not found]                             ` <1222460748-20127-8-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
  2008-09-26 20:25                               ` [PATCH 8/9 V3] Add documentation for the " Jon Loeliger
@ 2008-10-02  8:25                               ` David Gibson
  1 sibling, 0 replies; 79+ messages in thread
From: David Gibson @ 2008-10-02  8:25 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Fri, Sep 26, 2008 at 03:25:46PM -0500, Jon Loeliger wrote:
> Introduce function defs and statements.

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

This really doesn't belong in this patch.  It ought to be folded in
with the rest of the srcpos changes.

Except, I'm a fair way through implementing srcpos cleanups of my own
which will subsume these.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                 ` <20081002011800.GI25598-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
@ 2008-10-02 15:22                                                   ` Scott Wood
       [not found]                                                     ` <20081002152242.GB22258-VKaLA/mbEU932VTgPCOETVjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Scott Wood @ 2008-10-02 15:22 UTC (permalink / raw)
  To: David Gibson; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
> > I vote against anything similar to the C preprocessor.
> 
> Why?

It's not nearly as powerful as the semantic approach, and it is
syntactically clumsy (I do *not* want to have to put a backslash at the
end of every line within a macro, for example).

-Scott

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                     ` <20081002152242.GB22258-VKaLA/mbEU932VTgPCOETVjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
@ 2008-10-02 16:11                                                       ` David Gibson
       [not found]                                                         ` <20081002161150.GA14351-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
  2008-10-02 19:50                                                       ` M. Warner Losh
  1 sibling, 1 reply; 79+ messages in thread
From: David Gibson @ 2008-10-02 16:11 UTC (permalink / raw)
  To: Scott Wood; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Thu, Oct 02, 2008 at 10:22:42AM -0500, Scott Wood wrote:
> On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
> > > I vote against anything similar to the C preprocessor.
> > 
> > Why?
> 
> It's not nearly as powerful as the semantic approach, and it is

How so?  If anything I think it's more powerful, because the macro
boundaries can be anywhere, not only at the edges of particular
semantic constructs.

> syntactically clumsy (I do *not* want to have to put a backslash at the
> end of every line within a macro, for example).

Avoiding the backslashes everywhere is a reasonable argument though.
That's avoidable without dropping the basic idea of macro expansion,
though.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                         ` <20081002161150.GA14351-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
@ 2008-10-02 17:22                                                           ` Scott Wood
       [not found]                                                             ` <48E5036D.9040509-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Scott Wood @ 2008-10-02 17:22 UTC (permalink / raw)
  To: David Gibson; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

David Gibson wrote:
> On Thu, Oct 02, 2008 at 10:22:42AM -0500, Scott Wood wrote:
>> On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
>>>> I vote against anything similar to the C preprocessor.
>>> Why?
>> It's not nearly as powerful as the semantic approach, and it is
> 
> How so? 

Compare this:

/for/ i in 0..7
	do_something(\i);

to this:

#define DO2SOMETIHNGS DOSOMETHING DOSOMETHING
#define DO4SOMETHINGS DO2SOMETHINGS DO2SOMETHINGS
#define DO8SOMETHINGS DO4SOMETHINGS DO4SOMETHINGS

And if you want the number of somethings to be easily tweakable, you may 
need to do #include/#ifdef recursion.

> If anything I think it's more powerful, because the macro
> boundaries can be anywhere, not only at the edges of particular
> semantic constructs.

Is that useful outside the International Obfuscated DTC Contest?

-Scott

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                     ` <20081002152242.GB22258-VKaLA/mbEU932VTgPCOETVjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
  2008-10-02 16:11                                                       ` David Gibson
@ 2008-10-02 19:50                                                       ` M. Warner Losh
       [not found]                                                         ` <20081002.135004.1723231860.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org>
  1 sibling, 1 reply; 79+ messages in thread
From: M. Warner Losh @ 2008-10-02 19:50 UTC (permalink / raw)
  To: scottwood-KZfg59tc24xl57MIdRCFDg
  Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

In message: <20081002152242.GB22258-VKaLA/mbEU932VTgPCOETVjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
            Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org> writes:
: On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
: > > I vote against anything similar to the C preprocessor.
: > 
: > Why?
: 
: It's not nearly as powerful as the semantic approach, and it is
: syntactically clumsy (I do *not* want to have to put a backslash at the
: end of every line within a macro, for example).

And there are no looping constructs at all in CPP.  You flat out can't
do a generalized for loop with the macro language, for example.  Its
symbols also do not map 1-1/onto symbols used by the dts files.  It
can only grok macros you define for it, so it has no way of knowing
many useful things that dts just knows.

Basically, it is using a hammer to pound screws in.  Sure, it seems to
work, but the results are shoddy.

Warner

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                         ` <20081002.135004.1723231860.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org>
@ 2008-10-02 20:46                                                           ` Jon Loeliger
  2008-10-03  0:23                                                             ` David Gibson
  2008-10-03  0:23                                                           ` David Gibson
  1 sibling, 1 reply; 79+ messages in thread
From: Jon Loeliger @ 2008-10-02 20:46 UTC (permalink / raw)
  To: M. Warner Losh; +Cc: Scott Wood, devicetree-discuss

On Thu, 2008-10-02 at 13:50 -0600, M. Warner Losh wrote:
> In message: <20081002152242.GB22258-VKaLA/mbEU932VTgPCOETVjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
>             Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org> writes:
> : On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
> : > > I vote against anything similar to the C preprocessor.
> : > 
> : > Why?
> : 
> : It's not nearly as powerful as the semantic approach, and it is
> : syntactically clumsy (I do *not* want to have to put a backslash at the
> : end of every line within a macro, for example).
> 
> And there are no looping constructs at all in CPP.  You flat out can't
> do a generalized for loop with the macro language, for example.  Its
> symbols also do not map 1-1/onto symbols used by the dts files.  It
> can only grok macros you define for it, so it has no way of knowing
> many useful things that dts just knows.
> 
> Basically, it is using a hammer to pound screws in.  Sure, it seems to
> work, but the results are shoddy.
> 
> Warner

Also, it  might be worth noting that if one uses "-I dts -O dts"
with my patch set, it is pretty-darn similar behavior to a simple
pre-processing pass that simply expands the original constructs
into a flat DTS file like we have today.

jdl

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                         ` <20081002.135004.1723231860.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org>
  2008-10-02 20:46                                                           ` Jon Loeliger
@ 2008-10-03  0:23                                                           ` David Gibson
       [not found]                                                             ` <20081003002337.GB3002-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
  1 sibling, 1 reply; 79+ messages in thread
From: David Gibson @ 2008-10-03  0:23 UTC (permalink / raw)
  To: M. Warner Losh
  Cc: scottwood-KZfg59tc24xl57MIdRCFDg,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Thu, Oct 02, 2008 at 01:50:04PM -0600, M. Warner Losh wrote:
> In message: <20081002152242.GB22258-VKaLA/mbEU932VTgPCOETVjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
>             Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org> writes:
> : On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
> : > > I vote against anything similar to the C preprocessor.
> : > 
> : > Why?
> : 
> : It's not nearly as powerful as the semantic approach, and it is
> : syntactically clumsy (I do *not* want to have to put a backslash at the
> : end of every line within a macro, for example).
> 
> And there are no looping constructs at all in CPP.  You flat out can't
> do a generalized for loop with the macro language, for example.  Its

But we can put looping constructs into the expression support which
macros can then use.

> symbols also do not map 1-1/onto symbols used by the dts files.  It
> can only grok macros you define for it, so it has no way of knowing
> many useful things that dts just knows.

Uh.. I'm not sure what you mean by this.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
  2008-10-02 20:46                                                           ` Jon Loeliger
@ 2008-10-03  0:23                                                             ` David Gibson
  0 siblings, 0 replies; 79+ messages in thread
From: David Gibson @ 2008-10-03  0:23 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: Scott Wood, devicetree-discuss

On Thu, Oct 02, 2008 at 03:46:02PM -0500, Jon Loeliger wrote:
> On Thu, 2008-10-02 at 13:50 -0600, M. Warner Losh wrote:
> > In message: <20081002152242.GB22258-VKaLA/mbEU932VTgPCOETVjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
> >             Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org> writes:
> > : On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
> > : > > I vote against anything similar to the C preprocessor.
> > : > 
> > : > Why?
> > : 
> > : It's not nearly as powerful as the semantic approach, and it is
> > : syntactically clumsy (I do *not* want to have to put a backslash at the
> > : end of every line within a macro, for example).
> > 
> > And there are no looping constructs at all in CPP.  You flat out can't
> > do a generalized for loop with the macro language, for example.  Its
> > symbols also do not map 1-1/onto symbols used by the dts files.  It
> > can only grok macros you define for it, so it has no way of knowing
> > many useful things that dts just knows.
> > 
> > Basically, it is using a hammer to pound screws in.  Sure, it seems to
> > work, but the results are shoddy.
> > 
> > Warner
> 
> Also, it  might be worth noting that if one uses "-I dts -O dts"
> with my patch set, it is pretty-darn similar behavior to a simple
> pre-processing pass that simply expands the original constructs
> into a flat DTS file like we have today.

Sorry, I don't see the relevance of this.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                             ` <20081003002337.GB3002-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
@ 2008-10-03  1:17                                                               ` M. Warner Losh
       [not found]                                                                 ` <20081002.191705.-108805802.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: M. Warner Losh @ 2008-10-03  1:17 UTC (permalink / raw)
  To: david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+
  Cc: scottwood-KZfg59tc24xl57MIdRCFDg,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

In message: <20081003002337.GB3002-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
            David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> writes:
: On Thu, Oct 02, 2008 at 01:50:04PM -0600, M. Warner Losh wrote:
: > In message: <20081002152242.GB22258-VKaLA/mbEU932VTgPCOETVjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
: >             Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org> writes:
: > : On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
: > : > > I vote against anything similar to the C preprocessor.
: > : > 
: > : > Why?
: > : 
: > : It's not nearly as powerful as the semantic approach, and it is
: > : syntactically clumsy (I do *not* want to have to put a backslash at the
: > : end of every line within a macro, for example).
: > 
: > And there are no looping constructs at all in CPP.  You flat out can't
: > do a generalized for loop with the macro language, for example.  Its
: 
: But we can put looping constructs into the expression support which
: macros can then use.
: 
: > symbols also do not map 1-1/onto symbols used by the dts files.  It
: > can only grok macros you define for it, so it has no way of knowing
: > many useful things that dts just knows.
: 
: Uh.. I'm not sure what you mean by this.

I mean that identifiers have # in them in the dts language.  cpp deals
with identifiers that are similar to, but not the same thing as dts.

Warner

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                             ` <48E5036D.9040509-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
@ 2008-10-03  2:24                                                               ` David Gibson
       [not found]                                                                 ` <20081003022424.GG3002-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: David Gibson @ 2008-10-03  2:24 UTC (permalink / raw)
  To: Scott Wood; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Thu, Oct 02, 2008 at 12:22:53PM -0500, Scott Wood wrote:
> David Gibson wrote:
>> On Thu, Oct 02, 2008 at 10:22:42AM -0500, Scott Wood wrote:
>>> On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
>>>>> I vote against anything similar to the C preprocessor.
>>>> Why?
>>> It's not nearly as powerful as the semantic approach, and it is
>>
>> How so? 
>
> Compare this:
>
> /for/ i in 0..7
> 	do_something(\i);
>
> to this:
>
> #define DO2SOMETIHNGS DOSOMETHING DOSOMETHING
> #define DO4SOMETHINGS DO2SOMETHINGS DO2SOMETHINGS
> #define DO8SOMETHINGS DO4SOMETHINGS DO4SOMETHINGS
>
> And if you want the number of somethings to be easily tweakable, you may  
> need to do #include/#ifdef recursion.

Yes, we'd certainly need some sort of iteration operator in the
expressions for this sort of thing.

>
>> If anything I think it's more powerful, because the macro
>> boundaries can be anywhere, not only at the edges of particular
>> semantic constructs.
>
> Is that useful outside the International Obfuscated DTC Contest?

Maybe.  I can see uses for both this style:
	mynodename@12345 NODE_CONTENTS_MACRO(x,y,z);
and this style:
	NODE_MACRO(p,q,r);
where the macro generates the name as well.

Both are trivially possible with macros, but would need different
types of definition with a runtime system, which increases complexity.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                 ` <20081002.191705.-108805802.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org>
@ 2008-10-03  4:38                                                                   ` David Gibson
  0 siblings, 0 replies; 79+ messages in thread
From: David Gibson @ 2008-10-03  4:38 UTC (permalink / raw)
  To: M. Warner Losh
  Cc: scottwood-KZfg59tc24xl57MIdRCFDg,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Thu, Oct 02, 2008 at 07:17:05PM -0600, M. Warner Losh wrote:
> In message: <20081003002337.GB3002-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
>             David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> writes:
> : On Thu, Oct 02, 2008 at 01:50:04PM -0600, M. Warner Losh wrote:
> : > In message: <20081002152242.GB22258-VKaLA/mbEU932VTgPCOETVjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
> : >             Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org> writes:
> : > : On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
> : > : > > I vote against anything similar to the C preprocessor.
> : > : > 
> : > : > Why?
> : > : 
> : > : It's not nearly as powerful as the semantic approach, and it is
> : > : syntactically clumsy (I do *not* want to have to put a backslash at the
> : > : end of every line within a macro, for example).
> : > 
> : > And there are no looping constructs at all in CPP.  You flat out can't
> : > do a generalized for loop with the macro language, for example.  Its
> : 
> : But we can put looping constructs into the expression support which
> : macros can then use.
> : 
> : > symbols also do not map 1-1/onto symbols used by the dts files.  It
> : > can only grok macros you define for it, so it has no way of knowing
> : > many useful things that dts just knows.
> : 
> : Uh.. I'm not sure what you mean by this.
> 
> I mean that identifiers have # in them in the dts language.  cpp deals
> with identifiers that are similar to, but not the same thing as dts.

No.  Property and node names can have # in them in the dts.  I don't
think of those as identifiers - bare propnodenames are only recognized
in limited contexts.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                 ` <20081003022424.GG3002-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
@ 2008-10-03 15:27                                                                   ` Scott Wood
       [not found]                                                                     ` <20081003152700.GA9115-VKaLA/mbEU932VTgPCOETVjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Scott Wood @ 2008-10-03 15:27 UTC (permalink / raw)
  To: David Gibson; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Fri, Oct 03, 2008 at 12:24:24PM +1000, David Gibson wrote:
> > And if you want the number of somethings to be easily tweakable, you may  
> > need to do #include/#ifdef recursion.
> 
> Yes, we'd certainly need some sort of iteration operator in the
> expressions for this sort of thing.

OK, but now we're talking about something more complex than running it
through CPP with some character conversion.

A more powerful macro language is certainly an option, though I have a
personal preference for the semantic approach.

> >> If anything I think it's more powerful, because the macro
> >> boundaries can be anywhere, not only at the edges of particular
> >> semantic constructs.
> >
> > Is that useful outside the International Obfuscated DTC Contest?
> 
> Maybe.  I can see uses for both this style:
> 	mynodename@12345 NODE_CONTENTS_MACRO(x,y,z);
> and this style:
> 	NODE_MACRO(p,q,r);
> where the macro generates the name as well.
> 
> Both are trivially possible with macros, but would need different
> types of definition with a runtime system, which increases complexity.

You can do this in the proposed language by either defining a function
that takes the node name/unit address as a parameter, or by defining a
function that returns a set of properties.

-Scott

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                     ` <20081003152700.GA9115-VKaLA/mbEU932VTgPCOETVjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
@ 2008-10-04  4:52                                                                       ` David Gibson
  0 siblings, 0 replies; 79+ messages in thread
From: David Gibson @ 2008-10-04  4:52 UTC (permalink / raw)
  To: Scott Wood; +Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A

On Fri, Oct 03, 2008 at 10:27:01AM -0500, Scott Wood wrote:
> On Fri, Oct 03, 2008 at 12:24:24PM +1000, David Gibson wrote:
> > > And if you want the number of somethings to be easily tweakable, you may  
> > > need to do #include/#ifdef recursion.
> > 
> > Yes, we'd certainly need some sort of iteration operator in the
> > expressions for this sort of thing.
> 
> OK, but now we're talking about something more complex than running it
> through CPP with some character conversion.
> 
> A more powerful macro language is certainly an option, though I have a
> personal preference for the semantic approach.

Ugh.. actually.  What I had in mind was not macro features to do
iteration, but iteration constructs in expressions that macros could
expand to.  But I just realised that might not suffice.  It's a fairly
limited number of use cases that that will work for, although I think
they will be common ones.

But you do have a point here.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                         ` <20081001034656.GF30810-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
  2008-10-01  4:01                                           ` Warner Losh
  2008-10-01 15:26                                           ` Scott Wood
@ 2010-02-20 16:13                                           ` Grant Likely
       [not found]                                             ` <fa686aa41002200813o3fea9a34s198be367ad81b367-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2 siblings, 1 reply; 79+ messages in thread
From: Grant Likely @ 2010-02-20 16:13 UTC (permalink / raw)
  To: David Gibson, Jon Loeliger, Jeremy Kerr
  Cc: Scott Wood, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, John Williams

Okay, I'm going to reach way into the past here and reopen an old argument...

Here's a link to the original conversation:

http://www.mail-archive.com/devicetree-discuss-mnsaURCQ41sdnm+yROfE0A@public.gmane.org/msg00161.html

On Tue, Sep 30, 2008 at 8:46 PM, David Gibson
<david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote:
> On Tue, Sep 30, 2008 at 08:55:37AM -0600, Grant Likely wrote:
>> On Fri, Sep 26, 2008 at 03:25:47PM -0500, Jon Loeliger wrote:
>> > From: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
>> >
>> > Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
>> > ---
>> >  Documentation/manual.txt |  500 ++++++++++++++++++++++++++++++++++++++++++----
>> >  1 files changed, 463 insertions(+), 37 deletions(-)

[snip Jon's new language proposal]

>> I'm not convinced about the approach of interleaving the executable and
>> data syntaxes.  The whole design of the existing syntax is to represent
>> the data structure.  Adding additional syntax to define executable
>> elements doesn't feel right to me.  I think many people will find the
>> resulting file structure to be confusing.

[Snip the rest of my comments]

> The current device tree description is purely declarative, but this
> proposal would make it a rather odd hybrid of declarative and
> imperative components.  I do think this could be confusing,
> particularly to device tree newcomers who may not realise which
> components are compile time evaluated and which go into the output
> tree.  I had in mind a rather more functional-programming style for
> macros/computed properties to ameliorate this.

[snip the rest of David's comments]

Now that I've had about a year and a half to simmer about it, I think
I have a counter proposal on a dts syntax extension.

First, I should state the problems I'm trying to solve.  I have two
use cases that interest me:

1) Multiple boards that use the same SoC.
Right now each dts file carries around the full dts definition, even
though 95% of it is 'stock' description of the soc.  For example,
arch/powerpc/boot/dts/*5200* and arch/powerpc/boot/dts/*8349*.  I want
a way to put all the common description into an SoC dts file, and then
be able to tailor it (add nodes, change properties, etc) for the
specific board.

2) FPGA designs
The Xilinx FPGA toolchain will generate a dts file to describe a
PowerPC or Microblaze FPGA design.  However, the generated file is
usually not complete.  Properties need to be modified (ie. console
device or kernel command line) and additional devices need to be added
(devices hanging off the i2c, mdio and spi busses, gpio connections).
The tool doesn't have a way to tailor the device tree generation, and
the FPGA toolchain doesn't know about board level details.  I want a
way for the developer to write a board-level .dts file that "wraps" or
includes the generated file so that it doesn't need to be modified by
hand.

I also have some design goals for the proposed solution.  First, I
want to avoid design a new programming language.  If we need full
programmatic generation of device trees, there are plenty of general
purpose languages that can do the job.  I already know of two existing
device tree generators; I wrote a prototype generator written in
Python, and the Michal wrote the Xilinx dts generator using TCL.  I
don't want users to have to learn a new language, and I don't want it
to be more complex than is needed to solve the specific use cases.  As
such, I've got no loops, no macros, and no conditionals.

The model that I'm using to approach the problem is to add syntax for
including .dts files (exactly how Jon proposed) and syntax for going
back after the tree is parsed and changing things.  I'm not an expert
on syntax, so I'm open to changes in the details, but this is what I'm
thinking.  Add the following directives to the syntax:

/include/ Include a file
/cd/ Change the 'working node', accepts a full or relative path to a
node.  Also accepts labels.
/delete-node/ Delete a child node.  Similar to /cd/, accepts a full
path, a relative path, or a label.
/delete-property/ Delete a property from the working node.

So, for example, I might have the following for the pcm030.dts:

/dts-v1/;
/include/ mpc5200.dtsi;  /* dts include file */
/* at this point the basic structure of an mpc5200 board is layed down */

/* Change some properties in the chosen and memory nodes. */
/cd/ /chosen;
linux,stdout-path = &psc1;
/cd/ /memory
reg = <0 0x10000000>;

/* Add some devices to the i2c bus */
/cd/ &i2c1;   /* "i2c1" is a label from mpc5200.dtsi */
rtc@51 {
        compatible = "nxp,pcf8563";
        reg = <0x51>;
};
eeprom@52 {
        compatible = "catalyst,24c32";
        reg = <0x52>;
};

/* Remove the first i2c bus because it isn't used */
/delete-node/ &i2c0

/* The watchdog doesn't work, so remove the fsl,has-wdt property */
/cd/ &timer0;
/delete-prop/ fsl,has-wdt;

And that's it.  I think this covers the functionality that I need.
What does everyone think?  Are there other important use cases that I
should also be addressing?

Cheers,
g.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                             ` <fa686aa41002200813o3fea9a34s198be367ad81b367-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-02-21  6:30                                               ` John Williams
  2010-02-22  1:30                                               ` David Gibson
  1 sibling, 0 replies; 79+ messages in thread
From: John Williams @ 2010-02-21  6:30 UTC (permalink / raw)
  To: Grant Likely
  Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Scott Wood, Jeremy Kerr

On Sun, Feb 21, 2010 at 2:13 AM, Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org> wrote:
> Okay, I'm going to reach way into the past here and reopen an old argument...
>
> Here's a link to the original conversation:
>
> http://www.mail-archive.com/devicetree-discuss-mnsaURCQ41sdnm+yROfE0A@public.gmane.org/msg00161.html
>
> On Tue, Sep 30, 2008 at 8:46 PM, David Gibson
> <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote:
>> On Tue, Sep 30, 2008 at 08:55:37AM -0600, Grant Likely wrote:
>>> On Fri, Sep 26, 2008 at 03:25:47PM -0500, Jon Loeliger wrote:
>>> > From: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
>>> >
>>> > Signed-off-by: Jon Loeliger <jdl-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
>>> > ---
>>> >  Documentation/manual.txt |  500 ++++++++++++++++++++++++++++++++++++++++++----
>>> >  1 files changed, 463 insertions(+), 37 deletions(-)
>
> [snip Jon's new language proposal]
>
>>> I'm not convinced about the approach of interleaving the executable and
>>> data syntaxes.  The whole design of the existing syntax is to represent
>>> the data structure.  Adding additional syntax to define executable
>>> elements doesn't feel right to me.  I think many people will find the
>>> resulting file structure to be confusing.
>
> [Snip the rest of my comments]
>
>> The current device tree description is purely declarative, but this
>> proposal would make it a rather odd hybrid of declarative and
>> imperative components.  I do think this could be confusing,
>> particularly to device tree newcomers who may not realise which
>> components are compile time evaluated and which go into the output
>> tree.  I had in mind a rather more functional-programming style for
>> macros/computed properties to ameliorate this.
>
> [snip the rest of David's comments]
>
> Now that I've had about a year and a half to simmer about it, I think
> I have a counter proposal on a dts syntax extension.
>
> First, I should state the problems I'm trying to solve.  I have two
> use cases that interest me:
>
> 1) Multiple boards that use the same SoC.
> Right now each dts file carries around the full dts definition, even
> though 95% of it is 'stock' description of the soc.  For example,
> arch/powerpc/boot/dts/*5200* and arch/powerpc/boot/dts/*8349*.  I want
> a way to put all the common description into an SoC dts file, and then
> be able to tailor it (add nodes, change properties, etc) for the
> specific board.
>
> 2) FPGA designs
> The Xilinx FPGA toolchain will generate a dts file to describe a
> PowerPC or Microblaze FPGA design.  However, the generated file is
> usually not complete.  Properties need to be modified (ie. console
> device or kernel command line) and additional devices need to be added
> (devices hanging off the i2c, mdio and spi busses, gpio connections).
> The tool doesn't have a way to tailor the device tree generation, and
> the FPGA toolchain doesn't know about board level details.  I want a
> way for the developer to write a board-level .dts file that "wraps" or
> includes the generated file so that it doesn't need to be modified by
> hand.
>
> I also have some design goals for the proposed solution.  First, I
> want to avoid design a new programming language.  If we need full
> programmatic generation of device trees, there are plenty of general
> purpose languages that can do the job.  I already know of two existing
> device tree generators; I wrote a prototype generator written in
> Python, and the Michal wrote the Xilinx dts generator using TCL.  I
> don't want users to have to learn a new language, and I don't want it
> to be more complex than is needed to solve the specific use cases.  As
> such, I've got no loops, no macros, and no conditionals.
>
> The model that I'm using to approach the problem is to add syntax for
> including .dts files (exactly how Jon proposed) and syntax for going
> back after the tree is parsed and changing things.  I'm not an expert
> on syntax, so I'm open to changes in the details, but this is what I'm
> thinking.  Add the following directives to the syntax:
>
> /include/ Include a file
> /cd/ Change the 'working node', accepts a full or relative path to a
> node.  Also accepts labels.
> /delete-node/ Delete a child node.  Similar to /cd/, accepts a full
> path, a relative path, or a label.
> /delete-property/ Delete a property from the working node.
>
> So, for example, I might have the following for the pcm030.dts:
>
> /dts-v1/;
> /include/ mpc5200.dtsi;  /* dts include file */
> /* at this point the basic structure of an mpc5200 board is layed down */
>
> /* Change some properties in the chosen and memory nodes. */
> /cd/ /chosen;
> linux,stdout-path = &psc1;
> /cd/ /memory
> reg = <0 0x10000000>;
>
> /* Add some devices to the i2c bus */
> /cd/ &i2c1;   /* "i2c1" is a label from mpc5200.dtsi */
> rtc@51 {
>        compatible = "nxp,pcf8563";
>        reg = <0x51>;
> };
> eeprom@52 {
>        compatible = "catalyst,24c32";
>        reg = <0x52>;
> };
>
> /* Remove the first i2c bus because it isn't used */
> /delete-node/ &i2c0
>
> /* The watchdog doesn't work, so remove the fsl,has-wdt property */
> /cd/ &timer0;
> /delete-prop/ fsl,has-wdt;
>
> And that's it.  I think this covers the functionality that I need.
> What does everyone think?  Are there other important use cases that I
> should also be addressing?

So the "commands" are interpreted at DTS compile time right?  They
have no representation in the DTB?

How about support for adding nodes, such as MTD partitions as child
nodes of a flash device and so on?

Does inclusion happen only at the root?  If so is it meaningful to
have multiple includes in a single dts?

Again with the flash partition example, it might be usefiul to include
a partitional table .dtsi insidethe flash device node.

Seems overall like a useful functionality, we tend to create tools to
tweak the DTS based upon preferences that cannot be expressed to or
known by the device tree generator, their needs would be mostly served
by what you are proposing I think.

John

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                             ` <fa686aa41002200813o3fea9a34s198be367ad81b367-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2010-02-21  6:30                                               ` John Williams
@ 2010-02-22  1:30                                               ` David Gibson
  2010-02-22  6:26                                                 ` Grant Likely
  1 sibling, 1 reply; 79+ messages in thread
From: David Gibson @ 2010-02-22  1:30 UTC (permalink / raw)
  To: Grant Likely
  Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, John Williams,
	Scott Wood, Jeremy Kerr

On Sat, Feb 20, 2010 at 09:13:13AM -0700, Grant Likely wrote:
> Okay, I'm going to reach way into the past here and reopen an old
> argument...

And it's probably about time, too.

[snip]
> Now that I've had about a year and a half to simmer about it, I think
> I have a counter proposal on a dts syntax extension.
> 
> First, I should state the problems I'm trying to solve.  I have two
> use cases that interest me:
> 
> 1) Multiple boards that use the same SoC.
> Right now each dts file carries around the full dts definition, even
> though 95% of it is 'stock' description of the soc.  For example,
> arch/powerpc/boot/dts/*5200* and arch/powerpc/boot/dts/*8349*.  I want
> a way to put all the common description into an SoC dts file, and then
> be able to tailor it (add nodes, change properties, etc) for the
> specific board.
> 
> 2) FPGA designs
> The Xilinx FPGA toolchain will generate a dts file to describe a
> PowerPC or Microblaze FPGA design.  However, the generated file is
> usually not complete.  Properties need to be modified (ie. console
> device or kernel command line) and additional devices need to be added
> (devices hanging off the i2c, mdio and spi busses, gpio connections).
> The tool doesn't have a way to tailor the device tree generation, and
> the FPGA toolchain doesn't know about board level details.  I want a
> way for the developer to write a board-level .dts file that "wraps" or
> includes the generated file so that it doesn't need to be modified by
> hand.
> 
> I also have some design goals for the proposed solution.  First, I
> want to avoid design a new programming language.  If we need full
> programmatic generation of device trees, there are plenty of general
> purpose languages that can do the job.  I already know of two existing
> device tree generators; I wrote a prototype generator written in
> Python, and the Michal wrote the Xilinx dts generator using TCL.  I
> don't want users to have to learn a new language, and I don't want it
> to be more complex than is needed to solve the specific use cases.  As
> such, I've got no loops, no macros, and no conditionals.

A good goal.  Certainly I think it's preferable to use a device tree
generator in an existing good language that to make ourselves a new
bad language.

> The model that I'm using to approach the problem is to add syntax for
> including .dts files (exactly how Jon proposed) and syntax for going
> back after the tree is parsed and changing things.  I'm not an expert
> on syntax, so I'm open to changes in the details, but this is what I'm
> thinking.  Add the following directives to the syntax:
> 
> /include/ Include a file

Uh.. we already have /include/, which works pretty much exactly as you
want it to.

> /cd/ Change the 'working node', accepts a full or relative path to a
> node.  Also accepts labels.
> /delete-node/ Delete a child node.  Similar to /cd/, accepts a full
> path, a relative path, or a label.
> /delete-property/ Delete a property from the working node.
> 
> So, for example, I might have the following for the pcm030.dts:
> 
> /dts-v1/;
> /include/ mpc5200.dtsi;  /* dts include file */
> /* at this point the basic structure of an mpc5200 board is layed down */
> 
> /* Change some properties in the chosen and memory nodes. */
> /cd/ /chosen;
> linux,stdout-path = &psc1;
> /cd/ /memory
> reg = <0 0x10000000>;
> 
> /* Add some devices to the i2c bus */
> /cd/ &i2c1;   /* "i2c1" is a label from mpc5200.dtsi */
> rtc@51 {
>         compatible = "nxp,pcf8563";
>         reg = <0x51>;
> };
> eeprom@52 {
>         compatible = "catalyst,24c32";
>         reg = <0x52>;
> };
> 
> /* Remove the first i2c bus because it isn't used */
> /delete-node/ &i2c0
> 
> /* The watchdog doesn't work, so remove the fsl,has-wdt property */
> /cd/ &timer0;
> /delete-prop/ fsl,has-wdt;

Ok, I quite like the functionality, but I'm not that fond of the
syntax.  I think I have a similar but neater proposal, at least for
the adding-stuff parts.  There's two parts to my counter-proposal

1) This is essentially part of your proposal, but I'm separating it
out from the /cd/ syntax.

We allow redefinition of properties, nodes, or even the whole device
tree.  For properties the later definition overrides the earlier.  For
nodes, or the whole tree, the definitions are merged in the obvious
way (again with later property definitions overriding earlier).  In
this way an include could define a base tree, and you could then
define an "overlay" tree which adds things or changes properties where
necessary.

Optional extension: because allowing redefinitions potentially allows
genuine mistakes to silently generate unexpected output, it might be
wise to allow only "weak" definitions, marked somehow, to be
overriden.  I'm not sure what syntax we'd use for that.

I think (1) fits very naturally into the existing syntax.

2) The trouble with the above is that having included a template
device tree, redefining some property deep within it is unpleasantly
verbose.  You address that with /cd/, which I don't like very much.
So my counter proposal is that we allow a path instead of just a name
at the beginning of a node definition.  This would essentially define
an empty node for all the initial path elements, then let the node
body define the final path element in the appropriate location.  So:

/include/ template.dtsi;

/somebus@XX/someotherbus@XX/i2c@XX/board-control-widget@XXX {
	board-specific-property = "whatever";
};

Optional extension 1: Give an error if the earlier path components
haven't been defined yet (i.e. _don't+ allow implicit mkdir -p like
behaviour).  I suspect this would rarely to never be an inconvenience,
because you don't generally want to define a node with no properties
at all, and it would catch some genuine mistakes (like a typo which
adds a / to a node name).

Optional extension 2: Allow a node label to be invoked at the
beginning of a node redefinition in.  That would let include files put
labels on the nodes most likely to be extended or overriden,
particularly if they're buried deep in the tree and then the necessary
redefinitions become less verbose again.

(2) is a bit more problematic syntax-wise.  The fact that paths are
now possible before the node definition raises some lexical issues.
In particular it means the /-surrounded "reserved words" might no
longer be clearly lexically distinct from a node definition (I chose
to make the reserved words surround by / specifically so that that
would be the case).  I suspect this is not a fatal problem, but I'll
need to think about it some more.


That still leaves node and property deletion to cover.  In keeping
with the above approach, I'd like to do that in the form of "negative
redefinitions" of properties or nodes.  A neat syntax for that doesn't
immediately occur to be for that yet, though.

> And that's it.  I think this covers the functionality that I need.
> What does everyone think?  Are there other important use cases that I
> should also be addressing?

Probably, but I'm not really sure what they are.

So I think my proposal (1) above accomplishes some of what you want,
while being unlikely to badly conflict with any of the various paths
we might want to take in the future.  So, shall we proceed in that
direction while we think about the rest?

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
  2010-02-22  1:30                                               ` David Gibson
@ 2010-02-22  6:26                                                 ` Grant Likely
       [not found]                                                   ` <fa686aa41002212226i4c83376cn8d88a045dd13fe00-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Grant Likely @ 2010-02-22  6:26 UTC (permalink / raw)
  To: Grant Likely, Jon Loeliger, Jeremy Kerr,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Scott Wood

On Sun, Feb 21, 2010 at 6:30 PM, David Gibson
<david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote:

>> The model that I'm using to approach the problem is to add syntax for
>> including .dts files (exactly how Jon proposed) and syntax for going
>> back after the tree is parsed and changing things.  I'm not an expert
>> on syntax, so I'm open to changes in the details, but this is what I'm
>> thinking.  Add the following directives to the syntax:
>>
>> /include/ Include a file
>
> Uh.. we already have /include/, which works pretty much exactly as you
> want it to.

Well how about that.  I guess we do.  I learned something today.

> Ok, I quite like the functionality, but I'm not that fond of the
> syntax.  I think I have a similar but neater proposal, at least for
> the adding-stuff parts.  There's two parts to my counter-proposal
>
> 1) This is essentially part of your proposal, but I'm separating it
> out from the /cd/ syntax.
>
> We allow redefinition of properties, nodes, or even the whole device
> tree.  For properties the later definition overrides the earlier.  For
> nodes, or the whole tree, the definitions are merged in the obvious
> way (again with later property definitions overriding earlier).  In
> this way an include could define a base tree, and you could then
> define an "overlay" tree which adds things or changes properties where
> necessary.

Yes, I agree with this.  It's pretty well describes the functionality
that I was thinking about.

> Optional extension: because allowing redefinitions potentially allows
> genuine mistakes to silently generate unexpected output, it might be
> wise to allow only "weak" definitions, marked somehow, to be
> overriden.  I'm not sure what syntax we'd use for that.

Examples?  I'm not clear on what potential mistakes you're thinking about.

That being said, I could see it potentially being valuable to be able
to assign an 'invalid' value to a property so that is *must* get
overridden before dtc will generate valid output.

> I think (1) fits very naturally into the existing syntax.

I agree.  It certainly provides better containment than my /cd/ suggestion.

> 2) The trouble with the above is that having included a template
> device tree, redefining some property deep within it is unpleasantly
> verbose.  You address that with /cd/, which I don't like very much.
> So my counter proposal is that we allow a path instead of just a name
> at the beginning of a node definition.  This would essentially define
> an empty node for all the initial path elements, then let the node
> body define the final path element in the appropriate location.  So:
>
> /include/ template.dtsi;
>
> /somebus@XX/someotherbus@XX/i2c@XX/board-control-widget@XXX {
>        board-specific-property = "whatever";
> };
>
> Optional extension 1: Give an error if the earlier path components
> haven't been defined yet (i.e. _don't+ allow implicit mkdir -p like
> behaviour).  I suspect this would rarely to never be an inconvenience,
> because you don't generally want to define a node with no properties
> at all, and it would catch some genuine mistakes (like a typo which
> adds a / to a node name).

Yeah, this sounds reasonable.

> Optional extension 2: Allow a node label to be invoked at the
> beginning of a node redefinition in.  That would let include files put
> labels on the nodes most likely to be extended or overriden,
> particularly if they're buried deep in the tree and then the necessary
> redefinitions become less verbose again.

I think this is absolutely essential.  With respect to the FPGA use
case, nodes are going to move around, possibly quite a bit as the FPGA
design develops.  It is critical to have some kind of handle to a node
other than the node name or location because they will change.  I
think this might even be able to be handled as part (3) because it
doesn't have the '/' processing issue that part (2) has.  For example:

instead of:
/ {
        parent@1234 {
                child@abcd {
                        new-property = <0x01234567>;
                };
        };
};

do this:

&child-label {
        new-property = <0x01234567>;
};

> (2) is a bit more problematic syntax-wise.  The fact that paths are
> now possible before the node definition raises some lexical issues.
> In particular it means the /-surrounded "reserved words" might no
> longer be clearly lexically distinct from a node definition (I chose
> to make the reserved words surround by / specifically so that that
> would be the case).  I suspect this is not a fatal problem, but I'll
> need to think about it some more.

Actually, as long as I can reference a specific node by label, I don't
think I need the ability to pass in the full path.  Label provides the
functionality I need.

> That still leaves node and property deletion to cover.  In keeping
> with the above approach, I'd like to do that in the form of "negative
> redefinitions" of properties or nodes.  A neat syntax for that doesn't
> immediately occur to be for that yet, though.

hmmm.  I'll think more about it too.  I agree that a negative
redefinition sounds like a reasonable approach.  I do want the ability
to drop nodes easily.  It would make it easy to handle SoC or FPGA
design variants.

>> And that's it.  I think this covers the functionality that I need.
>> What does everyone think?  Are there other important use cases that I
>> should also be addressing?
>
> Probably, but I'm not really sure what they are.
>
> So I think my proposal (1) above accomplishes some of what you want,
> while being unlikely to badly conflict with any of the various paths
> we might want to take in the future.  So, shall we proceed in that
> direction while we think about the rest?

Yeah, I think so.  Okay, so how about some examples then of what I
think you're describing:

1) Add or modify properties to a node
/include/ "base-tree.dtsi"
/ {
        node {
                new-property = <0x1234>;
        };
};

2) Add a new node:
/include/ "base-tree.dtsi"
/ {
        parent {
                new-child {
                        new-properties;
                };
        };
};

3) Add a new node with a label:
/include/ "base-tree.dtsi"
/ {
        parent {
                new-label: new-child {
                        new-properties;
                };
        };
};

4) add a label to an existing node
/include/ "base-tree.dtsi"
/ {
        new-label: existing-node { };
};

5) Start from a labeled node instead of the root node:
/include/ "base-tree.dtsi"
&existing-label {
        new-property = <0xabcd>;
};

Do I have this right?

g.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* RE: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                   ` <fa686aa41002212226i4c83376cn8d88a045dd13fe00-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-02-22 16:13                                                     ` Yoder Stuart-B08248
       [not found]                                                       ` <9696D7A991D0824DBA8DFAC74A9C5FA305B2021A-ofAVchDyotYzzZk0BCvKg5jmvxFtTJ+o0e7PPNI6Mm0@public.gmane.org>
       [not found]                                                       ` <fa686aa41002221359m4d857e4cn3a1c56c32a24d21d@mail <4288fc0b-79a4-42fd-9e77-573dbad79210@SG2EHSMHS004.ehs.local>
  2010-02-23  1:47                                                     ` David Gibson
  1 sibling, 2 replies; 79+ messages in thread
From: Yoder Stuart-B08248 @ 2010-02-22 16:13 UTC (permalink / raw)
  To: Grant Likely, Jon Loeliger, Jeremy Kerr,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Wood Scott-B07421


> > That still leaves node and property deletion to cover.  In keeping
> > with the above approach, I'd like to do that in the form of 
> "negative
> > redefinitions" of properties or nodes.  A neat syntax for 
> that doesn't
> > immediately occur to be for that yet, though.
> 
> hmmm.  I'll think more about it too.  I agree that a negative
> redefinition sounds like a reasonable approach.  I do want the ability
> to drop nodes easily.  It would make it easy to handle SoC or FPGA
> design variants.

We had a similar problem in the Freescale Embedded Hypervisor
to control the generation of guest device trees.   We defined
several 'magic' properties that had special meaning in 
the context of a node update.

   delete-prop   <stringlist>   The value identifies one or more names of
                                properties that should be deleted from the
                                node.

   delete-node   <stringlist>   The value identifies one or more names of
                                nodes that should be deleted. The node and
                                all descendants will be deleted.

We also had the need to prepend to a <stringlist> so that 
compatible properties could be updated.

   prepend-stringlist  <stringlist> The value is a string list that
                                    specifies on or more property name/value
                                    pairs. 

                                    "prop-name1," "prop-value1,"
                                         "prop-name2," "propvalue2,"

                                    Each name/value pair consists of two
                                    strings-the first is the name of the
                                    property, the second is a string
                                    to prepend to the property. If the
                                    property does not already exist it will
                                    be created.

Examples

   / {
        parent {
                child1 {
                        new-property = "stuff";
                        delete-prop = "foo", "bar";
                };
        };
   };

   / {
        parent {
                child1 {
                        delete-node = "childA", "childB";
                };
        };
   };

   / {
        parent {
                child1 {
                        prepend-stringlist = "compatible", "fsl,foo-bar";
                };
        };
   };

Regards,
Stuart

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                       ` <9696D7A991D0824DBA8DFAC74A9C5FA305B2021A-ofAVchDyotYzzZk0BCvKg5jmvxFtTJ+o0e7PPNI6Mm0@public.gmane.org>
@ 2010-02-22 21:59                                                         ` Grant Likely
       [not found]                                                           ` <fa686aa41002221359m4d857e4cn3a1c56c32a24d21d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Grant Likely @ 2010-02-22 21:59 UTC (permalink / raw)
  To: Yoder Stuart-B08248
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	John Williams, Jeremy Kerr

On Mon, Feb 22, 2010 at 9:13 AM, Yoder Stuart-B08248
<B08248-KZfg59tc24xl57MIdRCFDg@public.gmane.org> wrote:
>
>> > That still leaves node and property deletion to cover.  In keeping
>> > with the above approach, I'd like to do that in the form of
>> "negative
>> > redefinitions" of properties or nodes.  A neat syntax for
>> that doesn't
>> > immediately occur to be for that yet, though.
>>
>> hmmm.  I'll think more about it too.  I agree that a negative
>> redefinition sounds like a reasonable approach.  I do want the ability
>> to drop nodes easily.  It would make it easy to handle SoC or FPGA
>> design variants.
>
> We had a similar problem in the Freescale Embedded Hypervisor
> to control the generation of guest device trees.   We defined
> several 'magic' properties that had special meaning in
> the context of a node update.

heh, so the functionality is definitely needed, but boy is that ugly!
:-)  I really do think there needs to be a syntactically distinct
method of deleting nodes and properties.  Magic property names that
look like normal properties worry me.

What about something like this:  Right now nodes are defined by <name>
{ [<property>|<node>]; ... }; and properties are defined by <name>; or
<name> = <value>;  To differentiate a command from either a node or
property definition, perhaps round braces could be used:

so for the definition:
a-node {
        property-1;
        property-2 = "blah";
        child-1 {
                ...
        };
};

you could delete property-2 and node-1 with:
a-node {
        delete-node(child-1);
        delete-property(property-2);
};

> We also had the need to prepend to a <stringlist> so that
> compatible properties could be updated.
>
>   prepend-stringlist  <stringlist> The value is a string list that
>                                    specifies on or more property name/value
>                                    pairs.

This is a bit of a harder problem.  I've go no ideas on how to handle
this in a syntactically elegant way.

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                           ` <fa686aa41002221359m4d857e4cn3a1c56c32a24d21d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-02-22 22:52                                                             ` Scott Wood
  2010-02-23  2:04                                                             ` David Gibson
  2010-03-01 19:15                                                             ` Grant Likely
  2 siblings, 0 replies; 79+ messages in thread
From: Scott Wood @ 2010-02-22 22:52 UTC (permalink / raw)
  To: Grant Likely
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, John Williams, Jeremy Kerr

Grant Likely wrote:
> On Mon, Feb 22, 2010 at 9:13 AM, Yoder Stuart-B08248
>> We had a similar problem in the Freescale Embedded Hypervisor
>> to control the generation of guest device trees.   We defined
>> several 'magic' properties that had special meaning in
>> the context of a node update.
> 
> heh, so the functionality is definitely needed, but boy is that ugly!
> :-)

And we haven't even mentioned node-update-phandle yet. :-)

> I really do think there needs to be a syntactically distinct
> method of deleting nodes and properties.  Magic property names that
> look like normal properties worry me.

The problem in our case is that the updates have to be done at runtime 
(modifications contained in a config tree are applied to a hardware 
devtree node (or hv-generated node) to produce a guest devtree node), so 
to use something that doesn't look like a normal property would require 
dtb format changes.

The whole node-update subtree in such a case could be considered magic.

The problem domain of this thread has no such requirement, of course.

> What about something like this:  Right now nodes are defined by <name>
> { [<property>|<node>]; ... }; and properties are defined by <name>; or
> <name> = <value>;  To differentiate a command from either a node or
> property definition, perhaps round braces could be used:
> 
> so for the definition:
> a-node {
>         property-1;
>         property-2 = "blah";
>         child-1 {
>                 ...
>         };
> };
> 
> you could delete property-2 and node-1 with:
> a-node {
>         delete-node(child-1);
>         delete-property(property-2);
> };
> 
>> We also had the need to prepend to a <stringlist> so that
>> compatible properties could be updated.
>>
>>   prepend-stringlist  <stringlist> The value is a string list that
>>                                    specifies on or more property name/value
>>                                    pairs.
> 
> This is a bit of a harder problem.  I've go no ideas on how to handle
> this in a syntactically elegant way.

As long as we're talking about dts-level static manipulation (i.e. not 
magic properties), we're not limited to one instance of each command 
name, so we could just do:

prepend-stringlist("compatible", "foo,bar");
prepend-stringlist("compatible", "foo,bar-X.Y");
prepend-stringlist("something-else", "aoeuhtns");

We need the quotes around node/property names since comma is a legal 
character in them.

-Scott

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                   ` <fa686aa41002212226i4c83376cn8d88a045dd13fe00-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2010-02-22 16:13                                                     ` Yoder Stuart-B08248
@ 2010-02-23  1:47                                                     ` David Gibson
  2010-02-23  2:17                                                       ` Grant Likely
  1 sibling, 1 reply; 79+ messages in thread
From: David Gibson @ 2010-02-23  1:47 UTC (permalink / raw)
  To: Grant Likely
  Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, John Williams,
	Scott Wood, Jeremy Kerr

On Sun, Feb 21, 2010 at 11:26:18PM -0700, Grant Likely wrote:
> On Sun, Feb 21, 2010 at 6:30 PM, David Gibson
> <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote:
> 
> >> The model that I'm using to approach the problem is to add syntax for
> >> including .dts files (exactly how Jon proposed) and syntax for going
> >> back after the tree is parsed and changing things.  I'm not an expert
> >> on syntax, so I'm open to changes in the details, but this is what I'm
> >> thinking.  Add the following directives to the syntax:
> >>
> >> /include/ Include a file
> >
> > Uh.. we already have /include/, which works pretty much exactly as you
> > want it to.
> 
> Well how about that.  I guess we do.  I learned something today.
> 
> > Ok, I quite like the functionality, but I'm not that fond of the
> > syntax.  I think I have a similar but neater proposal, at least for
> > the adding-stuff parts.  There's two parts to my counter-proposal
> >
> > 1) This is essentially part of your proposal, but I'm separating it
> > out from the /cd/ syntax.
> >
> > We allow redefinition of properties, nodes, or even the whole device
> > tree.  For properties the later definition overrides the earlier.  For
> > nodes, or the whole tree, the definitions are merged in the obvious
> > way (again with later property definitions overriding earlier).  In
> > this way an include could define a base tree, and you could then
> > define an "overlay" tree which adds things or changes properties where
> > necessary.
> 
> Yes, I agree with this.  It's pretty well describes the functionality
> that I was thinking about.
> 
> > Optional extension: because allowing redefinitions potentially allows
> > genuine mistakes to silently generate unexpected output, it might be
> > wise to allow only "weak" definitions, marked somehow, to be
> > overriden.  I'm not sure what syntax we'd use for that.
> 
> Examples?  I'm not clear on what potential mistakes you're thinking
> about.

Erm, I was thinking about making a typo and overriding something you
didn't intend intstead of something you did.  But I can't really come
up with something more concrete than that, so yeah, it's probably not
that big a deal.

> That being said, I could see it potentially being valuable to be able
> to assign an 'invalid' value to a property so that is *must* get
> overridden before dtc will generate valid output.

That is a very good point.  And it ties in with something I've
considered before of having some sort of invalid value (which might or
might not also reserve space in the dtb) to mark things which ought to
be poked by the bootloader before the tree is passed to the kernel.
Thoughts have varied on whether that would be purely a documentation
thing, or whether this would also have a dtb representation so it
could actually be checked at runtime, but then syntax which allows the
first would easily allow a later extension to implement the second.

Obviously that's not quite the same thing as here, since clearly it
would be permissible to generate trees with this sort of invalid
value, unlike your proposal.  But I don't think that's an
insurmountable problem.

> > I think (1) fits very naturally into the existing syntax.
> 
> I agree.  It certainly provides better containment than my /cd/ suggestion.
> 
> > 2) The trouble with the above is that having included a template
> > device tree, redefining some property deep within it is unpleasantly
> > verbose.  You address that with /cd/, which I don't like very much.
> > So my counter proposal is that we allow a path instead of just a name
> > at the beginning of a node definition.  This would essentially define
> > an empty node for all the initial path elements, then let the node
> > body define the final path element in the appropriate location.  So:
> >
> > /include/ template.dtsi;
> >
> > /somebus@XX/someotherbus@XX/i2c@XX/board-control-widget@XXX {
> >        board-specific-property = "whatever";
> > };
> >
> > Optional extension 1: Give an error if the earlier path components
> > haven't been defined yet (i.e. _don't+ allow implicit mkdir -p like
> > behaviour).  I suspect this would rarely to never be an inconvenience,
> > because you don't generally want to define a node with no properties
> > at all, and it would catch some genuine mistakes (like a typo which
> > adds a / to a node name).
> 
> Yeah, this sounds reasonable.
> 
> > Optional extension 2: Allow a node label to be invoked at the
> > beginning of a node redefinition in.  That would let include files put
> > labels on the nodes most likely to be extended or overriden,
> > particularly if they're buried deep in the tree and then the necessary
> > redefinitions become less verbose again.
> 
> I think this is absolutely essential.  With respect to the FPGA use
> case, nodes are going to move around, possibly quite a bit as the FPGA
> design develops.  It is critical to have some kind of handle to a node
> other than the node name or location because they will change.

Yes, I thought that might be the case.

>  I
> think this might even be able to be handled as part (3) because it
> doesn't have the '/' processing issue that part (2) has.  For example:
> 
> instead of:
> / {
>         parent@1234 {
>                 child@abcd {
>                         new-property = <0x01234567>;
>                 };
>         };
> };
> 
> do this:
> 
> &child-label {
>         new-property = <0x01234567>;
> };

And, you know, it turns out '&' is one of the other characters that is
neither in the current grammar for node names, nor does it appear in
any device tree I've encountered.  So this syntax is probably ok,
too.  Ah.. with the proviso that I think to make sense you could only
use this form at the top level (so at the top level nodes would be
introduced by either '/' or '&label' whereas at lowever levels it
would be by a nodepropname token.

[Something to be aware of in the lexical issues that surround node and
property names is that while IEEE1275 specifies a fairly limited set
of characters for them, there exist device trees in the wild (in Apple
and IBM firmwares, mostly) that have characters not in that set.  So
to be pragmatic we have to allow a pretty wide selection here]

> > (2) is a bit more problematic syntax-wise.  The fact that paths are
> > now possible before the node definition raises some lexical issues.
> > In particular it means the /-surrounded "reserved words" might no
> > longer be clearly lexically distinct from a node definition (I chose
> > to make the reserved words surround by / specifically so that that
> > would be the case).  I suspect this is not a fatal problem, but I'll
> > need to think about it some more.
> 
> Actually, as long as I can reference a specific node by label, I don't
> think I need the ability to pass in the full path.  Label provides the
> functionality I need.

You know, I was kind of hoping you'd say that :).  After all it is
still possible to override by explicit path, it's just a bit verbose,
which is ok if it's not needed particularly often.

> > That still leaves node and property deletion to cover.  In keeping
> > with the above approach, I'd like to do that in the form of "negative
> > redefinitions" of properties or nodes.  A neat syntax for that doesn't
> > immediately occur to be for that yet, though.
> 
> hmmm.  I'll think more about it too.  I agree that a negative
> redefinition sounds like a reasonable approach.  I do want the ability
> to drop nodes easily.  It would make it easy to handle SoC or FPGA
> design variants.

Yeah.  Unfortunately we can't use something as simple as '- propname;'
because '-' is a valid character in node and propery names.  For
properties we could maybe do something like:
	obsolete-property = /null/;
But that doesn't extend neatly to node removal.

> >> And that's it.  I think this covers the functionality that I need.
> >> What does everyone think?  Are there other important use cases that I
> >> should also be addressing?
> >
> > Probably, but I'm not really sure what they are.
> >
> > So I think my proposal (1) above accomplishes some of what you want,
> > while being unlikely to badly conflict with any of the various paths
> > we might want to take in the future.  So, shall we proceed in that
> > direction while we think about the rest?
> 
> Yeah, I think so.  Okay, so how about some examples then of what I
> think you're describing:
> 
> 1) Add or modify properties to a node
> /include/ "base-tree.dtsi"
> / {
>         node {
>                 new-property = <0x1234>;
>         };
> };

Yes.

> 2) Add a new node:
> /include/ "base-tree.dtsi"
> / {
>         parent {
>                 new-child {
>                         new-properties;
>                 };
>         };
> };

Yes.

> 3) Add a new node with a label:
> /include/ "base-tree.dtsi"
> / {
>         parent {
>                 new-label: new-child {
>                         new-properties;
>                 };
>         };
> };

Yes.

> 4) add a label to an existing node
> /include/ "base-tree.dtsi"
> / {
>         new-label: existing-node { };
> };

Ah.. yes, hadn't thought of that.  Which reminds me of another
extension I've had in mind for a while, which I suspect we'll want
along with this stuff to avoid having some really weird corner cases.
At present, because of the way things are stored in the internal data
structures, it's only possible to have a single label on a node or
property (which a wart already, since you can have any number of
labels at the same point within a property value).  I think having
redefinitions would significantly increase the chances that this
limitation will be a problem in practice.

> 5) Start from a labeled node instead of the root node:
> /include/ "base-tree.dtsi"
> &existing-label {
>         new-property = <0xabcd>;
> };
> 
> Do I have this right?

I think so.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                           ` <fa686aa41002221359m4d857e4cn3a1c56c32a24d21d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2010-02-22 22:52                                                             ` Scott Wood
@ 2010-02-23  2:04                                                             ` David Gibson
  2010-03-01 19:15                                                             ` Grant Likely
  2 siblings, 0 replies; 79+ messages in thread
From: David Gibson @ 2010-02-23  2:04 UTC (permalink / raw)
  To: Grant Likely
  Cc: Yoder Stuart-B08248, Jeremy Kerr,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, John Williams,
	Wood Scott-B07421

On Mon, Feb 22, 2010 at 02:59:25PM -0700, Grant Likely wrote:
> On Mon, Feb 22, 2010 at 9:13 AM, Yoder Stuart-B08248
> <B08248-KZfg59tc24xl57MIdRCFDg@public.gmane.org> wrote:
> >
> >> > That still leaves node and property deletion to cover.  In keeping
> >> > with the above approach, I'd like to do that in the form of
> >> "negative
> >> > redefinitions" of properties or nodes.  A neat syntax for
> >> that doesn't
> >> > immediately occur to be for that yet, though.
> >>
> >> hmmm.  I'll think more about it too.  I agree that a negative
> >> redefinition sounds like a reasonable approach.  I do want the ability
> >> to drop nodes easily.  It would make it easy to handle SoC or FPGA
> >> design variants.
> >
> > We had a similar problem in the Freescale Embedded Hypervisor
> > to control the generation of guest device trees.   We defined
> > several 'magic' properties that had special meaning in
> > the context of a node update.
> 
> heh, so the functionality is definitely needed, but boy is that ugly!
> :-)  I really do think there needs to be a syntactically distinct
> method of deleting nodes and properties.  Magic property names that
> look like normal properties worry me.

Ah, yeah.  However, as Stuart said, the magic properties need to be
interpreted at runtime, so in that case it kind of makes sense.  What
we're discussing here, does have the interesting possibility that we
could extend it so that with the right flag set from command line
option and/or a special directive in the .dts we could have a mode
where instead of immediately processing node and property
redefinitions in our new syntax, we instead build them into magic
properties in the FEH format.  Doubtless there would be some
complications, but it's something to think about later, maybe.

> What about something like this:  Right now nodes are defined by <name>
> { [<property>|<node>]; ... }; and properties are defined by <name>; or
> <name> = <value>;  To differentiate a command from either a node or
> property definition, perhaps round braces could be used:
> 
> so for the definition:
> a-node {
>         property-1;
>         property-2 = "blah";
>         child-1 {
>                 ...
>         };
> };
> 
> you could delete property-2 and node-1 with:
> a-node {
>         delete-node(child-1);
>         delete-property(property-2);
> };

Hrm.  I don't particularly like it, but I guess it's an option.

> > We also had the need to prepend to a <stringlist> so that
> > compatible properties could be updated.
> >
> >   prepend-stringlist  <stringlist> The value is a string list that
> >                                    specifies on or more property name/value
> >                                    pairs.
> 
> This is a bit of a harder problem.  I've go no ideas on how to handle
> this in a syntactically elegant way.

Actually, that I think we can handle relatively neatly.  We define a
special symbol which can be used in property definitions and expands
to the property's previous value.  So you could do:
	compatible = "newthing", /prev/;
(I don't particularly like '/prev/' as the symbol, but you get the
basic idea).


Actually, here's one thought.  At present, a reference to a node label
expands to the node's full path.  I don't think it's too far out of
keeping with that for a reference to a property label to expand to the
property's value.  Then we could have a special form of that which
means reference to this property's previous value, instead of
explicitly giving a property label.  Still not sure what to make the
actual symbols.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
  2010-02-23  1:47                                                     ` David Gibson
@ 2010-02-23  2:17                                                       ` Grant Likely
       [not found]                                                         ` <fa686aa41002221817s5f15dc4cy5ab873a61de2cb2f-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Grant Likely @ 2010-02-23  2:17 UTC (permalink / raw)
  To: Grant Likely, Jon Loeliger, Jeremy Kerr,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Scott Wood

On Mon, Feb 22, 2010 at 6:47 PM, David Gibson
<david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote:
> On Sun, Feb 21, 2010 at 11:26:18PM -0700, Grant Likely wrote:
>> That being said, I could see it potentially being valuable to be able
>> to assign an 'invalid' value to a property so that is *must* get
>> overridden before dtc will generate valid output.
>
> That is a very good point.  And it ties in with something I've
> considered before of having some sort of invalid value (which might or
> might not also reserve space in the dtb) to mark things which ought to
> be poked by the bootloader before the tree is passed to the kernel.
> Thoughts have varied on whether that would be purely a documentation
> thing, or whether this would also have a dtb representation so it
> could actually be checked at runtime, but then syntax which allows the
> first would easily allow a later extension to implement the second.
>
> Obviously that's not quite the same thing as here, since clearly it
> would be permissible to generate trees with this sort of invalid
> value, unlike your proposal.  But I don't think that's an
> insurmountable problem.

Right, not quite the same thing, but this easy can easily be deferred.
 I don't actually have any real use cases that depend on this, so I
don't think we need to jump through hoops right now to get it.

>>  I
>> think this might even be able to be handled as part (3) because it
>> doesn't have the '/' processing issue that part (2) has.  For example:
>>
>> instead of:
>> / {
>>         parent@1234 {
>>                 child@abcd {
>>                         new-property = <0x01234567>;
>>                 };
>>         };
>> };
>>
>> do this:
>>
>> &child-label {
>>         new-property = <0x01234567>;
>> };
>
> And, you know, it turns out '&' is one of the other characters that is
> neither in the current grammar for node names, nor does it appear in
> any device tree I've encountered.  So this syntax is probably ok,
> too.

I specifically chose this syntax because it matches the "property =
&label;" syntax used when assigning a path to a property, so .dts
authors know that a bare "&label" means the full path to a node.  I
think it helps with clarity.

>   Ah.. with the proviso that I think to make sense you could only
> use this form at the top level (so at the top level nodes would be
> introduced by either '/' or '&label' whereas at lowever levels it
> would be by a nodepropname token.

Absolutely.  I also made the assumption that &label is only valid at
the top level.

> [Something to be aware of in the lexical issues that surround node and
> property names is that while IEEE1275 specifies a fairly limited set
> of characters for them, there exist device trees in the wild (in Apple
> and IBM firmwares, mostly) that have characters not in that set.  So
> to be pragmatic we have to allow a pretty wide selection here]

On that note, does the grammer support an escape sequence for
characters with a special meaning?  ie. a \<char> sequence?  Doing so
would sidestep the issue for any exotic trees that come across.

>> > (2) is a bit more problematic syntax-wise.  The fact that paths are
>> > now possible before the node definition raises some lexical issues.
>> > In particular it means the /-surrounded "reserved words" might no
>> > longer be clearly lexically distinct from a node definition (I chose
>> > to make the reserved words surround by / specifically so that that
>> > would be the case).  I suspect this is not a fatal problem, but I'll
>> > need to think about it some more.
>>
>> Actually, as long as I can reference a specific node by label, I don't
>> think I need the ability to pass in the full path.  Label provides the
>> functionality I need.
>
> You know, I was kind of hoping you'd say that :).  After all it is
> still possible to override by explicit path, it's just a bit verbose,
> which is ok if it's not needed particularly often.

:-)  I'm okay with verbose in this case.

>> 4) add a label to an existing node
>> /include/ "base-tree.dtsi"
>> / {
>>         new-label: existing-node { };
>> };
>
> Ah.. yes, hadn't thought of that.  Which reminds me of another
> extension I've had in mind for a while, which I suspect we'll want
> along with this stuff to avoid having some really weird corner cases.
> At present, because of the way things are stored in the internal data
> structures, it's only possible to have a single label on a node or
> property (which a wart already, since you can have any number of
> labels at the same point within a property value).  I think having
> redefinitions would significantly increase the chances that this
> limitation will be a problem in practice.

Okay, this will probably need to be solved then.  It would probably be
a bad idea to encode limitations into the language that are really
just an artifact of the current implementation.  That being said,
while I would use this, I won't be hamstrung by the lack of this
feature in the near term.

>
>> 5) Start from a labeled node instead of the root node:
>> /include/ "base-tree.dtsi"
>> &existing-label {
>>         new-property = <0xabcd>;
>> };
>>
>> Do I have this right?
>
> I think so.

Cool.  Are you able to prototype the new features?  I have no idea
where to start, and I'm pretty buried in the ARM port at the moment.
However, if you implement it then I'll immediately convert all the
MPC5200 .dts files to use it.

Cheers,
g.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                         ` <fa686aa41002221817s5f15dc4cy5ab873a61de2cb2f-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-02-23  4:10                                                           ` David Gibson
  0 siblings, 0 replies; 79+ messages in thread
From: David Gibson @ 2010-02-23  4:10 UTC (permalink / raw)
  To: Grant Likely
  Cc: devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, John Williams,
	Scott Wood, Jeremy Kerr

On Mon, Feb 22, 2010 at 07:17:55PM -0700, Grant Likely wrote:
> On Mon, Feb 22, 2010 at 6:47 PM, David Gibson
> <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote:
> > On Sun, Feb 21, 2010 at 11:26:18PM -0700, Grant Likely wrote:
> >> That being said, I could see it potentially being valuable to be able
> >> to assign an 'invalid' value to a property so that is *must* get
> >> overridden before dtc will generate valid output.
> >
> > That is a very good point.  And it ties in with something I've
> > considered before of having some sort of invalid value (which might or
> > might not also reserve space in the dtb) to mark things which ought to
> > be poked by the bootloader before the tree is passed to the kernel.
> > Thoughts have varied on whether that would be purely a documentation
> > thing, or whether this would also have a dtb representation so it
> > could actually be checked at runtime, but then syntax which allows the
> > first would easily allow a later extension to implement the second.
> >
> > Obviously that's not quite the same thing as here, since clearly it
> > would be permissible to generate trees with this sort of invalid
> > value, unlike your proposal.  But I don't think that's an
> > insurmountable problem.
> 
> Right, not quite the same thing, but this easy can easily be deferred.
>  I don't actually have any real use cases that depend on this, so I
> don't think we need to jump through hoops right now to get it.

Yes, quite so.

> >>  I
> >> think this might even be able to be handled as part (3) because it
> >> doesn't have the '/' processing issue that part (2) has.  For example:
> >>
> >> instead of:
> >> / {
> >>         parent@1234 {
> >>                 child@abcd {
> >>                         new-property = <0x01234567>;
> >>                 };
> >>         };
> >> };
> >>
> >> do this:
> >>
> >> &child-label {
> >>         new-property = <0x01234567>;
> >> };
> >
> > And, you know, it turns out '&' is one of the other characters that is
> > neither in the current grammar for node names, nor does it appear in
> > any device tree I've encountered.  So this syntax is probably ok,
> > too.
> 
> I specifically chose this syntax because it matches the "property =
> &label;" syntax used when assigning a path to a property, so .dts
> authors know that a bare "&label" means the full path to a node.  I
> think it helps with clarity.

Yes, I concur.

> >   Ah.. with the proviso that I think to make sense you could only
> > use this form at the top level (so at the top level nodes would be
> > introduced by either '/' or '&label' whereas at lowever levels it
> > would be by a nodepropname token.
> 
> Absolutely.  I also made the assumption that &label is only valid at
> the top level.

Excellent.

> > [Something to be aware of in the lexical issues that surround node and
> > property names is that while IEEE1275 specifies a fairly limited set
> > of characters for them, there exist device trees in the wild (in Apple
> > and IBM firmwares, mostly) that have characters not in that set.  So
> > to be pragmatic we have to allow a pretty wide selection here]
> 
> On that note, does the grammer support an escape sequence for
> characters with a special meaning?  ie. a \<char> sequence?  Doing so
> would sidestep the issue for any exotic trees that come across.

Not at present, though I have considered it on several occasions.  My
preferred would probably be that for anything with exotic characters a
quoted string is instead used for the node name (including the C-like
\-escapes which we already support).

One of the uses I had in mind for this is to be able to do -Idtb -Odts
on a mildly corrupted tree and have something that's at least
syntactically correct and reversible.

> >> > (2) is a bit more problematic syntax-wise.  The fact that paths are
> >> > now possible before the node definition raises some lexical issues.
> >> > In particular it means the /-surrounded "reserved words" might no
> >> > longer be clearly lexically distinct from a node definition (I chose
> >> > to make the reserved words surround by / specifically so that that
> >> > would be the case).  I suspect this is not a fatal problem, but I'll
> >> > need to think about it some more.
> >>
> >> Actually, as long as I can reference a specific node by label, I don't
> >> think I need the ability to pass in the full path.  Label provides the
> >> functionality I need.
> >
> > You know, I was kind of hoping you'd say that :).  After all it is
> > still possible to override by explicit path, it's just a bit verbose,
> > which is ok if it's not needed particularly often.
> 
> :-)  I'm okay with verbose in this case.

Seems we agree.

> >> 4) add a label to an existing node
> >> /include/ "base-tree.dtsi"
> >> / {
> >>         new-label: existing-node { };
> >> };
> >
> > Ah.. yes, hadn't thought of that.  Which reminds me of another
> > extension I've had in mind for a while, which I suspect we'll want
> > along with this stuff to avoid having some really weird corner cases.
> > At present, because of the way things are stored in the internal data
> > structures, it's only possible to have a single label on a node or
> > property (which a wart already, since you can have any number of
> > labels at the same point within a property value).  I think having
> > redefinitions would significantly increase the chances that this
> > limitation will be a problem in practice.
> 
> Okay, this will probably need to be solved then.  It would probably be
> a bad idea to encode limitations into the language that are really
> just an artifact of the current implementation.  That being said,
> while I would use this, I won't be hamstrung by the lack of this
> feature in the near term.

Right.

> >> 5) Start from a labeled node instead of the root node:
> >> /include/ "base-tree.dtsi"
> >> &existing-label {
> >>         new-property = <0xabcd>;
> >> };
> >>
> >> Do I have this right?
> >
> > I think so.
> 
> Cool.  Are you able to prototype the new features?  I have no idea
> where to start, and I'm pretty buried in the ARM port at the moment.
> However, if you implement it then I'll immediately convert all the
> MPC5200 .dts files to use it.

Heh, yes, well. I'm pretty busy myself with things of direct interest
to my employer.  So.. I'll see what I can do, but no promises.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                           ` <fa686aa41002221359m4d857e4cn3a1c56c32a24d21d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2010-02-22 22:52                                                             ` Scott Wood
  2010-02-23  2:04                                                             ` David Gibson
@ 2010-03-01 19:15                                                             ` Grant Likely
       [not found]                                                               ` <fa686aa41003011115m1bb0b644g5014340f6c312ee9-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2 siblings, 1 reply; 79+ messages in thread
From: Grant Likely @ 2010-03-01 19:15 UTC (permalink / raw)
  To: Yoder Stuart-B08248
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	John Williams, Jeremy Kerr

On Mon, Feb 22, 2010 at 2:59 PM, Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org> wrote:
> On Mon, Feb 22, 2010 at 9:13 AM, Yoder Stuart-B08248
> <B08248-KZfg59tc24xl57MIdRCFDg@public.gmane.org> wrote:
>>
>>> > That still leaves node and property deletion to cover.  In keeping
>>> > with the above approach, I'd like to do that in the form of
>>> "negative
>>> > redefinitions" of properties or nodes.  A neat syntax for
>>> that doesn't
>>> > immediately occur to be for that yet, though.
>>>
>>> hmmm.  I'll think more about it too.  I agree that a negative
>>> redefinition sounds like a reasonable approach.  I do want the ability
>>> to drop nodes easily.  It would make it easy to handle SoC or FPGA
>>> design variants.
>>
>> We had a similar problem in the Freescale Embedded Hypervisor
>> to control the generation of guest device trees.   We defined
>> several 'magic' properties that had special meaning in
>> the context of a node update.
>
> heh, so the functionality is definitely needed, but boy is that ugly!
> :-)  I really do think there needs to be a syntactically distinct
> method of deleting nodes and properties.  Magic property names that
> look like normal properties worry me.
>
> What about something like this:  Right now nodes are defined by <name>
> { [<property>|<node>]; ... }; and properties are defined by <name>; or
> <name> = <value>;  To differentiate a command from either a node or
> property definition, perhaps round braces could be used:
>
> so for the definition:
> a-node {
>        property-1;
>        property-2 = "blah";
>        child-1 {
>                ...
>        };
> };
>
> you could delete property-2 and node-1 with:
> a-node {
>        delete-node(child-1);
>        delete-property(property-2);
> };

Okay.  So the redefinition of nodes feature got implemented far faster
than I expected it would.  Woohoo!  :-)

That leaves the last bit that I really care about; deleting nodes and
properties.  I can probably find the time to implement the C code for
this, but have no idea how to do the grammer, and I don't think we've
got a consensus on syntax.

Given the following tree...

/ {
        child-label: child {
                prop = <0xbad>;
                grandchild-label: grandchild {
                };
        };
};

...here are the use cases that I see as important (plus some suggested
syntax.  I'm not happy with it though, and I'm open to better ideas).

1) Deleting a property from a node:
&child-label {
        /* syntax to delete "prop" property */
        delete-prop("prop");
        ^prop;  /* this isn't very good, hard to differentiate from
node deletion */
        __delete_property = "prop";
};

2) Delete a child node:
&child-label {
        /* syntax to delete "grandchild" node */
        delete-node("grandchild");
        ^grandchild;
        __delete_node = "grandchild";
        grandchild = ^{};
};

3) Delete a labelled node from the top level:
delete-node(&grandchild-label);

Comments?  Suggestions?  Better ideas?  Please?  Don't inflict pain on
yourself by letting me decide the syntax.

g.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                               ` <fa686aa41003011115m1bb0b644g5014340f6c312ee9-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-03-01 19:38                                                                 ` Scott Wood
  2010-03-01 20:30                                                                 ` Stephen Neuendorffer
  1 sibling, 0 replies; 79+ messages in thread
From: Scott Wood @ 2010-03-01 19:38 UTC (permalink / raw)
  To: Grant Likely
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, John Williams, Jeremy Kerr

Grant Likely wrote:
> Okay.  So the redefinition of nodes feature got implemented far faster
> than I expected it would.  Woohoo!  :-)
> 
> That leaves the last bit that I really care about; deleting nodes and
> properties.  I can probably find the time to implement the C code for
> this, but have no idea how to do the grammer, and I don't think we've
> got a consensus on syntax.
> 
> Given the following tree...
> 
> / {
>         child-label: child {
>                 prop = <0xbad>;
>                 grandchild-label: grandchild {
>                 };
>         };
> };
> 
> ...here are the use cases that I see as important (plus some suggested
> syntax.  I'm not happy with it though, and I'm open to better ideas).
> 
> 1) Deleting a property from a node:
> &child-label {
>         /* syntax to delete "prop" property */
>         delete-prop("prop");
>         ^prop;  /* this isn't very good, hard to differentiate from
> node deletion */
>         __delete_property = "prop";
> };
> 
> 2) Delete a child node:
> &child-label {
>         /* syntax to delete "grandchild" node */
>         delete-node("grandchild");
>         ^grandchild;
>         __delete_node = "grandchild";
>         grandchild = ^{};
> };
> 
> 3) Delete a labelled node from the top level:
> delete-node(&grandchild-label);

I vote for the function-like option -- delete-prop("prop"), etc.

-Scott

^ permalink raw reply	[flat|nested] 79+ messages in thread

* RE: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                               ` <fa686aa41003011115m1bb0b644g5014340f6c312ee9-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2010-03-01 19:38                                                                 ` Scott Wood
@ 2010-03-01 20:30                                                                 ` Stephen Neuendorffer
       [not found]                                                                   ` <4B8C2C4C.8070901@freescale <4B8C44C8.6000105@freescale.com>
  1 sibling, 1 reply; 79+ messages in thread
From: Stephen Neuendorffer @ 2010-03-01 20:30 UTC (permalink / raw)
  To: Grant Likely, Yoder Stuart-B08248
  Cc: Wood Scott-B07421, Jeremy Kerr,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, John Williams

> -----Original Message-----
> From: devicetree-discuss-bounces+stephen.neuendorffer=xilinx.com@lists.ozlabs.org [mailto:devicetree-
> discuss-bounces+stephen.neuendorffer=xilinx.com-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org] On Behalf Of Grant Likely
> Sent: Monday, March 01, 2010 11:16 AM
> To: Yoder Stuart-B08248
> Cc: Wood Scott-B07421; devicetree-discuss-mnsaURCQ41sdnm+yROfE0A@public.gmane.org; John Williams; Jeremy Kerr
> Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
> 
> On Mon, Feb 22, 2010 at 2:59 PM, Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org> wrote:
> > On Mon, Feb 22, 2010 at 9:13 AM, Yoder Stuart-B08248
> > <B08248-KZfg59tc24xl57MIdRCFDg@public.gmane.org> wrote:
> >>
> >>> > That still leaves node and property deletion to cover.  In keeping
> >>> > with the above approach, I'd like to do that in the form of
> >>> "negative
> >>> > redefinitions" of properties or nodes.  A neat syntax for
> >>> that doesn't
> >>> > immediately occur to be for that yet, though.
> >>>
> >>> hmmm.  I'll think more about it too.  I agree that a negative
> >>> redefinition sounds like a reasonable approach.  I do want the ability
> >>> to drop nodes easily.  It would make it easy to handle SoC or FPGA
> >>> design variants.
> >>
> >> We had a similar problem in the Freescale Embedded Hypervisor
> >> to control the generation of guest device trees.   We defined
> >> several 'magic' properties that had special meaning in
> >> the context of a node update.
> >
> > heh, so the functionality is definitely needed, but boy is that ugly!
> > :-)  I really do think there needs to be a syntactically distinct
> > method of deleting nodes and properties.  Magic property names that
> > look like normal properties worry me.
> >
> > What about something like this:  Right now nodes are defined by <name>
> > { [<property>|<node>]; ... }; and properties are defined by <name>; or
> > <name> = <value>;  To differentiate a command from either a node or
> > property definition, perhaps round braces could be used:
> >
> > so for the definition:
> > a-node {
> >        property-1;
> >        property-2 = "blah";
> >        child-1 {
> >                ...
> >        };
> > };
> >
> > you could delete property-2 and node-1 with:
> > a-node {
> >        delete-node(child-1);
> >        delete-property(property-2);
> > };
> 
> Okay.  So the redefinition of nodes feature got implemented far faster
> than I expected it would.  Woohoo!  :-)
> 
> That leaves the last bit that I really care about; deleting nodes and
> properties.  I can probably find the time to implement the C code for
> this, but have no idea how to do the grammer, and I don't think we've
> got a consensus on syntax.
> 
> Given the following tree...
> 
> / {
>         child-label: child {
>                 prop = <0xbad>;
>                 grandchild-label: grandchild {
>                 };
>         };
> };
> 
> ...here are the use cases that I see as important (plus some suggested
> syntax.  I'm not happy with it though, and I'm open to better ideas).
> 
> 1) Deleting a property from a node:
> &child-label {
>         /* syntax to delete "prop" property */
>         delete-prop("prop");
>         ^prop;  /* this isn't very good, hard to differentiate from
> node deletion */
>         __delete_property = "prop";
> };
> 
> 2) Delete a child node:
> &child-label {
>         /* syntax to delete "grandchild" node */
>         delete-node("grandchild");
>         ^grandchild;
>         __delete_node = "grandchild";
>         grandchild = ^{};
> };
> 
> 3) Delete a labelled node from the top level:
> delete-node(&grandchild-label);
> 
> Comments?  Suggestions?  Better ideas?  Please?  Don't inflict pain on
> yourself by letting me decide the syntax.
> 
> g.

One thing I've seen in the past is that there is a sequentialization question in this, which becomes
more apparent once deletion is allowed.

First off, my assumption is that each node name is always unique in a tree, even when overrides are allowed.
Otherwise the sub-node and property ordering becomes important.

foo {
	bar = 2;
	bar = 3; // Illegal
} ;


foo {
	bar = 2;
} 
foo {
	bar = 3; // Legal
};


So, essentially, sequentialization of operation is forced by the concatenation of trees.

Similarly:

foo {
	bar-label: bar = 2;
}
&bar-label = 3;

delete has the similar problem.

foo {
	bar = 2;
	delete(bar); // Should be illegal
}

foo {
	bar-label: bar = 2;
}
delete(&bar-label);  // Legal.
foo {
	bar-label: bar = 4;  // Legal, even though previously deleted
}

So, regardless of the syntax, I think it's important to ensure the above checks and sequentiality.
There's also a canonicalization question, because you can spit out the original source, or the 'reduction'
which results in all the overrides and deletions.   I think from looking at Grant's patch, this is already
the way things work, but I don't think anyone had really explicitly stated that.

One trick is that the below is problematic, or at least hard to verify statically.

foo {
	delete(&bar-label); // Legal.
	delete(bar); // May or may not be Illegal, since don't know what bar-label references
}

So, to syntax: the sequentialization property may be more syntactically obvious if deletion resembles
setting a property or node like:

 ^bar
 !bar
or even
  bar = !;
  bar !;

Which brings up the question 'undeletion question'.  Can you do:

d-label: delete(bar);
delete(&d-label);

Steve




This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                         ` <4288fc0b-79a4-42fd-9e77-573dbad79210-RaUQJvECHiuXHCJdrdq+zrjjLBE8jN/0@public.gmane.org>
@ 2010-03-01 21:06                                                           ` Scott Wood
       [not found]                                                             ` <4B8C2C4C.8070901-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
  2010-03-01 21:49                                                           ` Grant Likely
  1 sibling, 1 reply; 79+ messages in thread
From: Scott Wood @ 2010-03-01 21:06 UTC (permalink / raw)
  To: Stephen Neuendorffer
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Jeremy Kerr, John Williams

Stephen Neuendorffer wrote:
> One thing I've seen in the past is that there is a sequentialization question in this, which becomes
> more apparent once deletion is allowed.
> 
> First off, my assumption is that each node name is always unique in a tree, even when overrides are allowed.
> Otherwise the sub-node and property ordering becomes important.
> 
> foo {
> 	bar = 2;
> 	bar = 3; // Illegal
> } ;
> 
> 
> foo {
> 	bar = 2;
> } 
> foo {
> 	bar = 3; // Legal
> };
> 
> 
> So, essentially, sequentialization of operation is forced by the concatenation of trees.

Hmm, I'd think it would be useful to e.g. include a template and subsequently 
modify it within the same node, rather than a more verbose and error-prone 
process of referencing labels later.

If sequential operations within a tree are supported, I'm not sure that there's 
any remaining need for separate top-level trees -- you could express the same 
thing as top-level property/node redefinitions.

What are the problems with supporting this?

> foo {
> 	bar-label: bar = 2;
> }
> delete(&bar-label);  // Legal.
> foo {
> 	bar-label: bar = 4;  // Legal, even though previously deleted
> }

Is it legal to reuse the label, even though it sort of points to the same spot?

If you don't reuse the label, but bar is redefined, where does bar-label point?

Do all labels to nodes in separate trees that end up referring to the same node 
in the final tree have the same phandle?  Are they interchangeable in subsequent 
delete commands?

> One trick is that the below is problematic, or at least hard to verify statically.
> 
> foo {
> 	delete(&bar-label); // Legal.
> 	delete(bar); // May or may not be Illegal, since don't know what bar-label references
> }

That raises the question of whether it's legal to delete things that aren't 
there.  There may be cases where a dts fragment A doesn't know whether fragment 
B will have defined something, and fragment A wants to make sure it ends up 
undefined one way or another.

> So, to syntax: the sequentialization property may be more syntactically obvious if deletion resembles
> setting a property or node like:
> 
>  ^bar
>  !bar
> or even
>   bar = !;
>   bar !;

What specifically is made more obvious?  Using symbols rather than names seems 
more cryptic to me.

Only the "bar = !" form seems to clearly indicate that, for the purposes of this 
particular tree, you're assigning some special placeholder to bar rather than 
performing an immediate action.  That could just as well be done with something 
like "bar = /delete-prop/".

I'd rather make them actually behave like immediate commands, though.

> Which brings up the question 'undeletion question'.  Can you do:
> 
> d-label: delete(bar);
> delete(&d-label);

I'd say no -- delete operates on data, not commands.

-Scott

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                         ` <4288fc0b-79a4-42fd-9e77-573dbad79210-RaUQJvECHiuXHCJdrdq+zrjjLBE8jN/0@public.gmane.org>
  2010-03-01 21:06                                                           ` Scott Wood
@ 2010-03-01 21:49                                                           ` Grant Likely
       [not found]                                                             ` <fa686aa41003011349i367a423cx2c59953e6afc9b75-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  1 sibling, 1 reply; 79+ messages in thread
From: Grant Likely @ 2010-03-01 21:49 UTC (permalink / raw)
  To: Stephen Neuendorffer
  Cc: Yoder Stuart-B08248, Jeremy Kerr,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, John Williams,
	Wood Scott-B07421

Hi Stephen, good comments...

On Mon, Mar 1, 2010 at 1:30 PM, Stephen Neuendorffer
<stephen.neuendorffer-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org> wrote:
>> Given the following tree...
>>
>> / {
>>         child-label: child {
>>                 prop = <0xbad>;
>>                 grandchild-label: grandchild {
>>                 };
>>         };
>> };
>>
>> ...here are the use cases that I see as important (plus some suggested
>> syntax.  I'm not happy with it though, and I'm open to better ideas).
>>
>> 1) Deleting a property from a node:
>> &child-label {
>>         /* syntax to delete "prop" property */
>>         delete-prop("prop");
>>         ^prop;  /* this isn't very good, hard to differentiate from
>> node deletion */
>>         __delete_property = "prop";
>> };
>>
>> 2) Delete a child node:
>> &child-label {
>>         /* syntax to delete "grandchild" node */
>>         delete-node("grandchild");
>>         ^grandchild;
>>         __delete_node = "grandchild";
>>         grandchild = ^{};
>> };
>>
>> 3) Delete a labelled node from the top level:
>> delete-node(&grandchild-label);
>>
>> Comments?  Suggestions?  Better ideas?  Please?  Don't inflict pain on
>> yourself by letting me decide the syntax.
>>
>> g.
>
> One thing I've seen in the past is that there is a sequentialization question in this, which becomes
> more apparent once deletion is allowed.
>
> First off, my assumption is that each node name is always unique in a tree, even when overrides are allowed.
> Otherwise the sub-node and property ordering becomes important.

Yes, multiple sibling nodes with the same name are not allowed by dtc.
 I believe multiple siblings of the same name is legal with
OpenFirmware, but that is at least partially because in OpenFirmware
the @<addr> portion isn't necessarily part of the name.  (Imagine
having triplets and naming them Sally@1, Sally@2 and Sally@3!)

However, the same name can be used by non-siblings.  For example, the
following is totally legal:

/ {
    foo {
        foo {
        };
    };
};

> foo {
>        bar = 2;
>        bar = 3; // Illegal
> } ;
>
>
> foo {
>        bar = 2;
> }
> foo {
>        bar = 3; // Legal
> };
>
>
> So, essentially, sequentialization of operation is forced by the concatenation of trees.

Yes, you are exactly correct.  The model is to fully form 2 trees, and
then overlay the latter on the former.

> Similarly:
>
> foo {
>        bar-label: bar = 2;
> }
> &bar-label = 3;

This actually isn't legal, but for an entirely different reason.  Even
though labels can be applied to properties, property labels aren't
actually used for anything unless asm output is selected.  All tree
modification as of now is done from the context of nodes.
Redefinition can start from the root node, or it can start from a
labelled node, but there is no syntax defined for modifying a labelled
property.

It is possible to add redefinition of labelled properties, but I'd
like to see a use case first, and why it is better than the current
form (similar to the arguments I put forth for node redefinition by
label).

So, if I rework your example to use nodes...

foo {
        bar-label: bar {
                prop = 2;
        };
};
&bar-label {
        prop = 3;
};

So, yes, prop in the second tree overrides the prop in the first tree
because it is the same property name in the 'bar' node.

> delete has the similar problem.
>
> foo {
>        bar = 2;
>        delete(bar); // Should be illegal
> }
>
> foo {
>        bar-label: bar = 2;
> }
> delete(&bar-label);  // Legal.
> foo {
>        bar-label: bar = 4;  // Legal, even though previously deleted
> }

reworked to use nodes:
foo {
        bar-label: bar {
                prop = 2;
                delete(bar); // should be illegal
        };
};
foo {
        bar-label: bar {  /* legal, adds label to node */
                prop = 3;  /* legal, changes prop */
        };
};
delete-node(&bar-label};  // legal
foo {
        bar-label: bar {  /* Legal, even though previously deleted */
                prop = 4;
        };
};

> So, regardless of the syntax, I think it's important to ensure the above checks and sequentiality.
> There's also a canonicalization question, because you can spit out the original source, or the 'reduction'
> which results in all the overrides and deletions.   I think from looking at Grant's patch, this is already
> the way things work, but I don't think anyone had really explicitly stated that.

Hmmm, perhaps nobody has.  Yes, each node redefinition is fully
processed before going on to the next one.  Think: a stack of
transparencies where each new sheet masks/changed/adds to the one
below it.

> One trick is that the below is problematic, or at least hard to verify statically.
>
> foo {
>        delete(&bar-label); // Legal.

This is never legal.  If deleting by label, it must be at the top
level.  It doesn't make sense to use a label reference inside a node
block, since the node block is already supposed to define where you
are working in the tree.

>        delete(bar); // May or may not be Illegal, since don't know what bar-label references

No longer an issue since the previous line is illegal.

Also, must be either delete-node() or delete-prop() since nodes and
properties can use the same names.

> }
>
> So, to syntax: the sequentialization property may be more syntactically obvious if deletion resembles
> setting a property or node like:
>
>  ^bar
>  !bar
> or even
>  bar = !;
>  bar !;

That's an interesting point.  Perhaps it would be better to use a
syntax that enforces the concept of overlays, and talk about masking
out instead of deleting nodes and properties from the earlier tree.

I kind of like the ^ syntax, but there would have to be syntax
variations for both node and property masking.  I'm not sure it's a
good idea to dedicate otherwise valid node name characters to the
purpose of masking.

>
> Which brings up the question 'undeletion question'.  Can you do:
>
> d-label: delete(bar);
> delete(&d-label);

Not sure I follow.  It certainly isn't be valid to apply a label to a
command like delete().

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* RE: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                             ` <4B8C2C4C.8070901-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
@ 2010-03-01 22:03                                                               ` Stephen Neuendorffer
       [not found]                                                                 ` <4d16ecf4-27b2-4c73-a3be-5b2a8ff95820-+Ck8Kgl/v0+J1bAq5m18RLjjLBE8jN/0@public.gmane.org>
  2010-03-01 22:18                                                               ` Grant Likely
  1 sibling, 1 reply; 79+ messages in thread
From: Stephen Neuendorffer @ 2010-03-01 22:03 UTC (permalink / raw)
  To: Scott Wood
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Jeremy Kerr, John Williams



> -----Original Message-----
> From: Scott Wood [mailto:scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org]
> Sent: Monday, March 01, 2010 1:06 PM
> To: Stephen Neuendorffer
> Cc: grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org; Yoder Stuart-B08248; Wood Scott-B07421;
devicetree-discuss-mnsaURCQ41sdnm+yROfE0A@public.gmane.org;
> John Williams; Jeremy Kerr
> Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS
language.
> 
> Stephen Neuendorffer wrote:
> > One thing I've seen in the past is that there is a sequentialization
question in this, which becomes
> > more apparent once deletion is allowed.
> >
> > First off, my assumption is that each node name is always unique in
a tree, even when overrides are
> allowed.
> > Otherwise the sub-node and property ordering becomes important.
> >
> > foo {
> > 	bar = 2;
> > 	bar = 3; // Illegal
> > } ;
> >
> >
> > foo {
> > 	bar = 2;
> > }
> > foo {
> > 	bar = 3; // Legal
> > };
> >
> >
> > So, essentially, sequentialization of operation is forced by the
concatenation of trees.
> 
> Hmm, I'd think it would be useful to e.g. include a template and
subsequently
> modify it within the same node, rather than a more verbose and
error-prone
> process of referencing labels later.
> 
> If sequential operations within a tree are supported, I'm not sure
that there's
> any remaining need for separate top-level trees -- you could express
the same
> thing as top-level property/node redefinitions.

I agree, *IF* sequential operations are supported.
But then you have a sequential programming language, not a structured
data
description.  I think this is a bad idea.

> What are the problems with supporting this?

Mainly the fact that properties and sub-nodes have a semantically
important ordering.
This can be done, but it's not as clean.

> > foo {
> > 	bar-label: bar = 2;
> > }
> > delete(&bar-label);  // Legal.
> > foo {
> > 	bar-label: bar = 4;  // Legal, even though previously deleted
> > }
> 
> Is it legal to reuse the label, even though it sort of points to the
same spot?
> 
> If you don't reuse the label, but bar is redefined, where does
bar-label point?
> 
> Do all labels to nodes in separate trees that end up referring to the
same node
> in the final tree have the same phandle?  Are they interchangeable in
subsequent
> delete commands?

I think these are all good questions which someone who has a much better
grasp of the
intention of labels probably has to answer.  Since they are somewhat
separate from the point
I was trying to show with the example (and as Grant replied, my examples
are perhaps poorly
formed anyway), I'm just going to duck them.

> > One trick is that the below is problematic, or at least hard to
verify statically.
> >
> > foo {
> > 	delete(&bar-label); // Legal.
> > 	delete(bar); // May or may not be Illegal, since don't know what
bar-label references
> > }
> 
> That raises the question of whether it's legal to delete things that
aren't
> there.  There may be cases where a dts fragment A doesn't know whether
fragment
> B will have defined something, and fragment A wants to make sure it
ends up
> undefined one way or another.

Yes...  A very good question.  I would say that it could probably be
either way
without screwing things up too badly.

> > So, to syntax: the sequentialization property may be more
syntactically obvious if deletion
> resembles
> > setting a property or node like:
> >
> >  ^bar
> >  !bar
> > or even
> >   bar = !;
> >   bar !;
> 
> What specifically is made more obvious?  Using symbols rather than
names seems
> more cryptic to me.
> 
> Only the "bar = !" form seems to clearly indicate that, for the
purposes of this
> particular tree, you're assigning some special placeholder to bar
rather than
> performing an immediate action.  That could just as well be done with
something
> like "bar = /delete-prop/".
> 
> I'd rather make them actually behave like immediate commands, though.

But the question is, what is the semantics of the 'command language'
(where ordering matters)
from the 'structure language' (where ordering is unimportant).  My
suggestion is to cleanly separate
these two.  The only ordering that is defined is between sequential
trees.  Within a sequential tree,
only things which have the same meaning in any ordering of sub-nodes and
properties should be allowed.

> > Which brings up the question 'undeletion question'.  Can you do:
> >
> > d-label: delete(bar);
> > delete(&d-label);
> 
> I'd say no -- delete operates on data, not commands.

This implies that data and commands are different.  And commands have to
be ordered, which means that you have
to keep the order of everything under a node, which chucks alot of the
beauty of device trees, IMHO.

Steve


This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                             ` <fa686aa41003011349i367a423cx2c59953e6afc9b75-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-03-01 22:15                                                               ` Mitch Bradley
       [not found]                                                                 ` <4B8C3C78.5010206-D5eQfiDGL7eakBO8gow8eQ@public.gmane.org>
  2010-03-01 22:17                                                               ` Stephen Neuendorffer
  1 sibling, 1 reply; 79+ messages in thread
From: Mitch Bradley @ 2010-03-01 22:15 UTC (permalink / raw)
  To: Grant Likely
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Jeremy Kerr, John Williams

>
> Yes, multiple sibling nodes with the same name are not allowed by dtc.
>  I believe multiple siblings of the same name is legal with
> OpenFirmware, but that is at least partially because in OpenFirmware
> the @<addr> portion isn't necessarily part of the name.  (Imagine
> having triplets and naming them Sally@1, Sally@2 and Sally@3!)
>
>   

I'm not sure how to parse the above because the word "name" seems to be 
used somewhat informally.

The Open Firmware situation is this:

a) At a given level of the tree, there can be any number of nodes with 
the same value for the "name" property.  For example, you could plug in 
several PCI Ethernet adapters and each would have "ethernet" as the 
value of the "name" property.  In general, the "name" property is not 
intended as a unique identifier, but rather as a mnemonic for human 
convenience.  The unique identifier is the first component of the "reg" 
property (within the context of the parent node).  The whole schema for 
reg properties is driven by this uniqueness requirement, along with the 
observation that the computer hardware must have some physical means of 
addressing specific devices.  The "reg" properties mimic physical 
addresses on various bus domains.

b) A fully-qualified device specifier component includes both the name 
property value and the reg property value (AKA the unit address), for 
example "ethernet@5".

c) It is possible to have a "wildcard" device node that contains an Open 
Firmware driver for a given device, but its bus has not been fully 
probed so you don't yet know the addresses (reg properties) for the 
actual devices.  In that case, you can have a "name" property but no 
"reg" property.  You can have a wildcard node "disk" and some explicit 
nodes "disk@1", "disk@2" as siblings.  When searching the device tree, 
nodes with reg properties take precedence over wildcard nodes, so the 
wildcard node is a "fallback" to use if you can't find an explicit 
"name@reg" match.  In principle, you could have several wildcard nodes 
with the same name at the same level of the tree, but if so, the search 
would find only the most recently defined one, so for all practical 
purposes it is as if only one exists.

Wildcard nodes are useful for Open Firmware driver binding, and could 
potentially be used for OS driver binding for either hot-plugged or 
late-probed devices.  Whether or not they fit well into the dtc scheme, 
I can't say.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* RE: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                             ` <fa686aa41003011349i367a423cx2c59953e6afc9b75-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2010-03-01 22:15                                                               ` Mitch Bradley
@ 2010-03-01 22:17                                                               ` Stephen Neuendorffer
       [not found]                                                                 ` <72f497af-412c-4a05-90c2-5df0be00d93f-+Ck8Kgl/v09CYczPSvLbDrjjLBE8jN/0@public.gmane.org>
  1 sibling, 1 reply; 79+ messages in thread
From: Stephen Neuendorffer @ 2010-03-01 22:17 UTC (permalink / raw)
  To: Grant Likely
  Cc: Yoder Stuart-B08248, Jeremy Kerr,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, John Williams,
	Wood Scott-B07421



> -----Original Message-----
> From: glikely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org [mailto:glikely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org] On Behalf Of Grant Likely
> Sent: Monday, March 01, 2010 1:49 PM
> To: Stephen Neuendorffer
> Cc: Yoder Stuart-B08248; Wood Scott-B07421; devicetree-discuss-mnsaURCQ41sdnm+yROfE0A@public.gmane.org; John Williams; Jeremy Kerr
> Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
> 
> Hi Stephen, good comments...
> 
> On Mon, Mar 1, 2010 at 1:30 PM, Stephen Neuendorffer
> <stephen.neuendorffer-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org> wrote:
> >> Given the following tree...
> >>
> >> / {
> >>         child-label: child {
> >>                 prop = <0xbad>;
> >>                 grandchild-label: grandchild {
> >>                 };
> >>         };
> >> };
> >>
> >> ...here are the use cases that I see as important (plus some suggested
> >> syntax.  I'm not happy with it though, and I'm open to better ideas).
> >>
> >> 1) Deleting a property from a node:
> >> &child-label {
> >>         /* syntax to delete "prop" property */
> >>         delete-prop("prop");
> >>         ^prop;  /* this isn't very good, hard to differentiate from
> >> node deletion */
> >>         __delete_property = "prop";
> >> };
> >>
> >> 2) Delete a child node:
> >> &child-label {
> >>         /* syntax to delete "grandchild" node */
> >>         delete-node("grandchild");
> >>         ^grandchild;
> >>         __delete_node = "grandchild";
> >>         grandchild = ^{};
> >> };
> >>
> >> 3) Delete a labelled node from the top level:
> >> delete-node(&grandchild-label);
> >>
> >> Comments?  Suggestions?  Better ideas?  Please?  Don't inflict pain on
> >> yourself by letting me decide the syntax.
> >>
> >> g.
> >
> > One thing I've seen in the past is that there is a sequentialization question in this, which becomes
> > more apparent once deletion is allowed.
> >
> > First off, my assumption is that each node name is always unique in a tree, even when overrides are
> allowed.
> > Otherwise the sub-node and property ordering becomes important.
> 
> Yes, multiple sibling nodes with the same name are not allowed by dtc.
>  I believe multiple siblings of the same name is legal with
> OpenFirmware, but that is at least partially because in OpenFirmware
> the @<addr> portion isn't necessarily part of the name.  (Imagine
> having triplets and naming them Sally@1, Sally@2 and Sally@3!)
> 
> However, the same name can be used by non-siblings.  For example, the
> following is totally legal:
> 
> / {
>     foo {
>         foo {
>         };
>     };
> };
> 
> > foo {
> >        bar = 2;
> >        bar = 3; // Illegal
> > } ;
> >
> >
> > foo {
> >        bar = 2;
> > }
> > foo {
> >        bar = 3; // Legal
> > };
> >
> >
> > So, essentially, sequentialization of operation is forced by the concatenation of trees.
> 
> Yes, you are exactly correct.  The model is to fully form 2 trees, and
> then overlay the latter on the former.
> 
> > Similarly:
> >
> > foo {
> >        bar-label: bar = 2;
> > }
> > &bar-label = 3;
> 
> This actually isn't legal, but for an entirely different reason.  Even
> though labels can be applied to properties, property labels aren't
> actually used for anything unless asm output is selected.  All tree
> modification as of now is done from the context of nodes.
> Redefinition can start from the root node, or it can start from a
> labelled node, but there is no syntax defined for modifying a labelled
> property.

Ah, OK.
 
> It is possible to add redefinition of labelled properties, but I'd
> like to see a use case first, and why it is better than the current
> form (similar to the arguments I put forth for node redefinition by
> label).

Ah, right, they have separate namespaces.  When I implemented this
in the past, properties and hierarchy shared a single namespace.

> So, if I rework your example to use nodes...
> 
> foo {
>         bar-label: bar {
>                 prop = 2;
>         };
> };
> &bar-label {
>         prop = 3;
> };
> 
> So, yes, prop in the second tree overrides the prop in the first tree
> because it is the same property name in the 'bar' node.
> 
> > delete has the similar problem.
> >
> > foo {
> >        bar = 2;
> >        delete(bar); // Should be illegal
> > }
> >
> > foo {
> >        bar-label: bar = 2;
> > }
> > delete(&bar-label);  // Legal.
> > foo {
> >        bar-label: bar = 4;  // Legal, even though previously deleted
> > }
> 
> reworked to use nodes:
> foo {
>         bar-label: bar {
>                 prop = 2;
>                 delete(bar); // should be illegal
>         };
> };

Um, my original intent was:
foo {
         bar-label: bar {
                 prop = 2;
         };
         delete(bar); // should be illegal
};

> foo {
>         bar-label: bar {  /* legal, adds label to node */
>                 prop = 3;  /* legal, changes prop */
>         };
> };
> delete-node(&bar-label};  // legal
> foo {
>         bar-label: bar {  /* Legal, even though previously deleted */
>                 prop = 4;
>         };
> };
> 
> > So, regardless of the syntax, I think it's important to ensure the above checks and sequentiality.
> > There's also a canonicalization question, because you can spit out the original source, or the
> 'reduction'
> > which results in all the overrides and deletions.   I think from looking at Grant's patch, this is
> already
> > the way things work, but I don't think anyone had really explicitly stated that.
> 
> Hmmm, perhaps nobody has.  Yes, each node redefinition is fully
> processed before going on to the next one.  Think: a stack of
> transparencies where each new sheet masks/changed/adds to the one
> below it.

I think this makes alot of sense. 

> > One trick is that the below is problematic, or at least hard to verify statically.
> >
> > foo {
> >        delete(&bar-label); // Legal.
> 
> This is never legal.  If deleting by label, it must be at the top
> level.  It doesn't make sense to use a label reference inside a node
> block, since the node block is already supposed to define where you
> are working in the tree.
> 
> >        delete(bar); // May or may not be Illegal, since don't know what bar-label references
> 
> No longer an issue since the previous line is illegal.
> 
> Also, must be either delete-node() or delete-prop() since nodes and
> properties can use the same names.

So, is it true that a tree which is overlayed on another tree can be independently verified to
be independent of internal ordering?  This would be nice if so.

> > }
> >
> > So, to syntax: the sequentialization property may be more syntactically obvious if deletion
> resembles
> > setting a property or node like:
> >
> >  ^bar
> >  !bar
> > or even
> >  bar = !;
> >  bar !;
> 
> That's an interesting point.  Perhaps it would be better to use a
> syntax that enforces the concept of overlays, and talk about masking
> out instead of deleting nodes and properties from the earlier tree.
> 
> I kind of like the ^ syntax, but there would have to be syntax
> variations for both node and property masking.  I'm not sure it's a
> good idea to dedicate otherwise valid node name characters to the
> purpose of masking.

I'm not necessarily wild about these syntax options either, BTW...

> > Which brings up the question 'undeletion question'.  Can you do:
> >
> > d-label: delete(bar);
> > delete(&d-label);
> 
> Not sure I follow.  It certainly isn't be valid to apply a label to a
> command like delete().

But the best thing of the above is that there is no longer a distinction between commands and data!
delete is just a tag which gets interpreted during 'reduction' or 'overlay'.

For instance, deleting a subnode could be:

foo {
	bar {
		delete;
	}
}

I guess this ends up conflicting with a property named 'delete' though.

Steve




This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                             ` <4B8C2C4C.8070901-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
  2010-03-01 22:03                                                               ` Stephen Neuendorffer
@ 2010-03-01 22:18                                                               ` Grant Likely
       [not found]                                                                 ` <fa686aa41003011418x339884c9md61c49948b31a8d1-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  1 sibling, 1 reply; 79+ messages in thread
From: Grant Likely @ 2010-03-01 22:18 UTC (permalink / raw)
  To: Scott Wood
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Jeremy Kerr, John Williams

On Mon, Mar 1, 2010 at 2:06 PM, Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org> wrote:
> Stephen Neuendorffer wrote:
>>
>> One thing I've seen in the past is that there is a sequentialization
>> question in this, which becomes
>> more apparent once deletion is allowed.
>>
>> First off, my assumption is that each node name is always unique in a
>> tree, even when overrides are allowed.
>> Otherwise the sub-node and property ordering becomes important.
>>
>> foo {
>>        bar = 2;
>>        bar = 3; // Illegal
>> } ;
>>
>>
>> foo {
>>        bar = 2;
>> } foo {
>>        bar = 3; // Legal
>> };
>>
>>
>> So, essentially, sequentialization of operation is forced by the
>> concatenation of trees.
>
> Hmm, I'd think it would be useful to e.g. include a template and
> subsequently modify it within the same node, rather than a more verbose and
> error-prone process of referencing labels later.
>
> If sequential operations within a tree are supported, I'm not sure that
> there's any remaining need for separate top-level trees -- you could express
> the same thing as top-level property/node redefinitions.
>
> What are the problems with supporting this?

The main problem is that it doesn't fit the use cases I need to solve.
 I need to start with a 'stock' or 'vanilla' tree, and then add into
it board details.  ie. lay down a generic MPC5200 tree (include a .dts
file), and then fill it in with i2c and spi devices.  Or include the
.dts file generated by the XIlinx FPGA toolchain, and then populate it
with board details.  Sequential operations within the tree doesn't do
anything to support this use case because the board level fixups will
be applied all over the tree.

To reverse the question, what is the use case that is best solved with
sequential operations within the root tree?

>> foo {
>>        bar-label: bar = 2;
>> }
>> delete(&bar-label);  // Legal.
>> foo {
>>        bar-label: bar = 4;  // Legal, even though previously deleted
>> }
>
> Is it legal to reuse the label, even though it sort of points to the same
> spot?

In the overlay model that is currently being approached.  Yes.

> If you don't reuse the label, but bar is redefined, where does bar-label
> point?

It doesn't point to anything because when a property is deleted, the
label also goes away.

> Do all labels to nodes in separate trees that end up referring to the same
> node in the final tree have the same phandle?  Are they interchangeable in
> subsequent delete commands?

Yes.

>> One trick is that the below is problematic, or at least hard to verify
>> statically.
>>
>> foo {
>>        delete(&bar-label); // Legal.
>>        delete(bar); // May or may not be Illegal, since don't know what
>> bar-label references
>> }
>
> That raises the question of whether it's legal to delete things that aren't
> there.

It isn't currently, which seems sane to me.

> There may be cases where a dts fragment A doesn't know whether
> fragment B will have defined something, and fragment A wants to make sure it
> ends up undefined one way or another.

Later fragments should always override earlier ones.  So if A is
defined before B, then B can override anything that A does.

>> So, to syntax: the sequentialization property may be more syntactically
>> obvious if deletion resembles
>> setting a property or node like:
>>
>>  ^bar
>>  !bar
>> or even
>>  bar = !;
>>  bar !;
>
> What specifically is made more obvious?  Using symbols rather than names
> seems more cryptic to me.
>
> Only the "bar = !" form seems to clearly indicate that, for the purposes of
> this particular tree, you're assigning some special placeholder to bar
> rather than performing an immediate action.  That could just as well be done
> with something like "bar = /delete-prop/".
>
> I'd rather make them actually behave like immediate commands, though.
>
>> Which brings up the question 'undeletion question'.  Can you do:
>>
>> d-label: delete(bar);
>> delete(&d-label);
>
> I'd say no -- delete operates on data, not commands.

Yes, I agree.  However, the command() syntax may be a bad idea if
following the 'stack of overlays' model to its logical conclusion.  In
a sense, properties and nodes are getting masked out of the earlier
tree, not deleted.  It is more of an operation (mask) than a command
(delete) being applied.  delete-node() may give the misleading
impression that something is being executed at that point in the tree.

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                 ` <4d16ecf4-27b2-4c73-a3be-5b2a8ff95820-+Ck8Kgl/v0+J1bAq5m18RLjjLBE8jN/0@public.gmane.org>
@ 2010-03-01 22:25                                                                   ` Grant Likely
       [not found]                                                                     ` <fa686aa41003011425i734ee434m95b62d57a271bd1f-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Grant Likely @ 2010-03-01 22:25 UTC (permalink / raw)
  To: Stephen Neuendorffer
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Scott Wood, Jeremy Kerr, John Williams

On Mon, Mar 1, 2010 at 3:03 PM, Stephen Neuendorffer
<stephen.neuendorffer-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org> wrote:
> From: Scott Wood [mailto:scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org]
>> If sequential operations within a tree are supported, I'm not sure
> that there's
>> any remaining need for separate top-level trees -- you could express
> the same
>> thing as top-level property/node redefinitions.
>
> I agree, *IF* sequential operations are supported.
> But then you have a sequential programming language, not a structured
> data
> description.  I think this is a bad idea.

Indeed.  We've got lots of sequential programming languages.  I don't
want us to create for ourselves a new (and poorly implemented)
language.

>> I'd rather make them actually behave like immediate commands, though.
>
> But the question is, what is the semantics of the 'command language'
> (where ordering matters)
> from the 'structure language' (where ordering is unimportant).  My
> suggestion is to cleanly separate
> these two.  The only ordering that is defined is between sequential
> trees.  Within a sequential tree,
> only things which have the same meaning in any ordering of sub-nodes and
> properties should be allowed.

Yes, I think I agree with this.  The only ordering that matters is the
ordering of top level node redefinition blocks.

>> > Which brings up the question 'undeletion question'.  Can you do:
>> >
>> > d-label: delete(bar);
>> > delete(&d-label);
>>
>> I'd say no -- delete operates on data, not commands.
>
> This implies that data and commands are different.  And commands have to
> be ordered, which means that you have
> to keep the order of everything under a node, which chucks alot of the
> beauty of device trees, IMHO.

Right, well said.  I think the right thing to do is to avoid the
concept of commands entirely from the tree.

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* RE: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                 ` <fa686aa41003011418x339884c9md61c49948b31a8d1-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-03-01 22:26                                                                   ` Stephen Neuendorffer
       [not found]                                                                     ` <1012f9aa-1642-41ab-b8cd-a4ab4a7b269e-+Ck8Kgl/v0989VwWyyPjfbjjLBE8jN/0@public.gmane.org>
  2010-03-01 22:50                                                                   ` Scott Wood
  1 sibling, 1 reply; 79+ messages in thread
From: Stephen Neuendorffer @ 2010-03-01 22:26 UTC (permalink / raw)
  To: Grant Likely, Scott Wood
  Cc: Yoder Stuart-B08248, Jeremy Kerr,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, John Williams,
	Wood Scott-B07421



> -----Original Message-----
> From: glikely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org [mailto:glikely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org] On Behalf Of Grant Likely
> Sent: Monday, March 01, 2010 2:19 PM
> To: Scott Wood
> Cc: Stephen Neuendorffer; Yoder Stuart-B08248; Wood Scott-B07421; devicetree-discuss-mnsaURCQ41sdnm+yROfE0A@public.gmane.org; John
> Williams; Jeremy Kerr
> Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
> 
> On Mon, Mar 1, 2010 at 2:06 PM, Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org> wrote:
> > Stephen Neuendorffer wrote:
> >>
> >> One thing I've seen in the past is that there is a sequentialization
> >> question in this, which becomes
> >> more apparent once deletion is allowed.
> >>
> >> First off, my assumption is that each node name is always unique in a
> >> tree, even when overrides are allowed.
> >> Otherwise the sub-node and property ordering becomes important.
> >>
> >> foo {
> >>        bar = 2;
> >>        bar = 3; // Illegal
> >> } ;
> >>
> >>
> >> foo {
> >>        bar = 2;
> >> } foo {
> >>        bar = 3; // Legal
> >> };
> >>
> >>
> >> So, essentially, sequentialization of operation is forced by the
> >> concatenation of trees.
> >
> > Hmm, I'd think it would be useful to e.g. include a template and
> > subsequently modify it within the same node, rather than a more verbose and
> > error-prone process of referencing labels later.
> >
> > If sequential operations within a tree are supported, I'm not sure that
> > there's any remaining need for separate top-level trees -- you could express
> > the same thing as top-level property/node redefinitions.
> >
> > What are the problems with supporting this?
> 
> The main problem is that it doesn't fit the use cases I need to solve.
>  I need to start with a 'stock' or 'vanilla' tree, and then add into
> it board details.  ie. lay down a generic MPC5200 tree (include a .dts
> file), and then fill it in with i2c and spi devices.  Or include the
> .dts file generated by the XIlinx FPGA toolchain, and then populate it
> with board details.  Sequential operations within the tree doesn't do
> anything to support this use case because the board level fixups will
> be applied all over the tree.

Aside: I always pictured this the other way round, where the DTS for an
FPGA design includes the DTS for the board.  Then again, as long as they
are independent, it probably doesn't matter.

 
> To reverse the question, what is the use case that is best solved with
> sequential operations within the root tree?
> 
> >> foo {
> >>        bar-label: bar = 2;
> >> }
> >> delete(&bar-label);  // Legal.
> >> foo {
> >>        bar-label: bar = 4;  // Legal, even though previously deleted
> >> }
> >
> > Is it legal to reuse the label, even though it sort of points to the same
> > spot?
> 
> In the overlay model that is currently being approached.  Yes.
> 
> > If you don't reuse the label, but bar is redefined, where does bar-label
> > point?
> 
> It doesn't point to anything because when a property is deleted, the
> label also goes away.
> 
> > Do all labels to nodes in separate trees that end up referring to the same
> > node in the final tree have the same phandle?  Are they interchangeable in
> > subsequent delete commands?
> 
> Yes.
> 
> >> One trick is that the below is problematic, or at least hard to verify
> >> statically.
> >>
> >> foo {
> >>        delete(&bar-label); // Legal.
> >>        delete(bar); // May or may not be Illegal, since don't know what
> >> bar-label references
> >> }
> >
> > That raises the question of whether it's legal to delete things that aren't
> > there.
> 
> It isn't currently, which seems sane to me.
> 
> > There may be cases where a dts fragment A doesn't know whether
> > fragment B will have defined something, and fragment A wants to make sure it
> > ends up undefined one way or another.
> 
> Later fragments should always override earlier ones.  So if A is
> defined before B, then B can override anything that A does.

So the idiom to do this safely would be:

foo {
	bar {} // Ensure that bar exists.
}
foo {
	delete(bar);
}

Seems baroque, but OK...

> >> So, to syntax: the sequentialization property may be more syntactically
> >> obvious if deletion resembles
> >> setting a property or node like:
> >>
> >>  ^bar
> >>  !bar
> >> or even
> >>  bar = !;
> >>  bar !;
> >
> > What specifically is made more obvious?  Using symbols rather than names
> > seems more cryptic to me.
> >
> > Only the "bar = !" form seems to clearly indicate that, for the purposes of
> > this particular tree, you're assigning some special placeholder to bar
> > rather than performing an immediate action.  That could just as well be done
> > with something like "bar = /delete-prop/".
> >
> > I'd rather make them actually behave like immediate commands, though.
> >
> >> Which brings up the question 'undeletion question'.  Can you do:
> >>
> >> d-label: delete(bar);
> >> delete(&d-label);
> >
> > I'd say no -- delete operates on data, not commands.
> 
> Yes, I agree.  However, the command() syntax may be a bad idea if
> following the 'stack of overlays' model to its logical conclusion.  In
> a sense, properties and nodes are getting masked out of the earlier
> tree, not deleted.  It is more of an operation (mask) than a command
> (delete) being applied.  delete-node() may give the misleading
> impression that something is being executed at that point in the tree.

Regardless of what the syntax is, if the *semantics* is overlay, then there
doesn't seem to be any reason to disallow undeletion, and in fact, this semantics
gives a way to implement it.  I'll defer whether this is *needed*: In the case
of device trees it's not clear that it is.

Steve

This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                 ` <fa686aa41003011418x339884c9md61c49948b31a8d1-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2010-03-01 22:26                                                                   ` Stephen Neuendorffer
@ 2010-03-01 22:50                                                                   ` Scott Wood
  1 sibling, 0 replies; 79+ messages in thread
From: Scott Wood @ 2010-03-01 22:50 UTC (permalink / raw)
  To: Grant Likely
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Jeremy Kerr, John Williams

Grant Likely wrote:
> On Mon, Mar 1, 2010 at 2:06 PM, Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org> wrote:
>> Hmm, I'd think it would be useful to e.g. include a template and
>> subsequently modify it within the same node, rather than a more verbose and
>> error-prone process of referencing labels later.
>>
>> If sequential operations within a tree are supported, I'm not sure that
>> there's any remaining need for separate top-level trees -- you could express
>> the same thing as top-level property/node redefinitions.
>>
>> What are the problems with supporting this?
> 
> The main problem is that it doesn't fit the use cases I need to solve.
>  I need to start with a 'stock' or 'vanilla' tree, and then add into
> it board details.  ie. lay down a generic MPC5200 tree (include a .dts
> file), and then fill it in with i2c and spi devices.  Or include the
> .dts file generated by the XIlinx FPGA toolchain, and then populate it
> with board details.  Sequential operations within the tree doesn't do
> anything to support this use case because the board level fixups will
> be applied all over the tree.
> 
> To reverse the question, what is the use case that is best solved with
> sequential operations within the root tree?

The case I had in mind was having includable templates for fragments of the 
tree, rather than starting with a generic full tree.  Though I'd probably end up 
wanting things like template arguments and math as well (is any existing macro 
language going to do cell arithmetic?), so the focus on that kind of use case at 
this point should probably be limited to not defining syntax that's going to 
make things harder on future language extensions.  The only thing that 
immediately comes to mind from that perspective is that symbols are a more 
limited resource than keywords.

>>> foo {
>>>        bar-label: bar = 2;
>>> }
>>> delete(&bar-label);  // Legal.
>>> foo {
>>>        bar-label: bar = 4;  // Legal, even though previously deleted
>>> }
>> Is it legal to reuse the label, even though it sort of points to the same
>> spot?
> 
> In the overlay model that is currently being approached.  Yes.
> 
>> If you don't reuse the label, but bar is redefined, where does bar-label
>> point?
> 
> It doesn't point to anything because when a property is deleted, the
> label also goes away.

Is it the same way with node labels?  What happens to previous references?  Is 
it detected by dtc, or does a bad phandle/path stick around to be found at 
runtime?  And what if the node is added back?

>>> One trick is that the below is problematic, or at least hard to verify
>>> statically.
>>>
>>> foo {
>>>        delete(&bar-label); // Legal.
>>>        delete(bar); // May or may not be Illegal, since don't know what
>>> bar-label references
>>> }
>> That raises the question of whether it's legal to delete things that aren't
>> there.
> 
> It isn't currently, which seems sane to me.
> 
>>  There may be cases where a dts fragment A doesn't know whether
>> fragment B will have defined something, and fragment A wants to make sure it
>> ends up undefined one way or another.
> 
> Later fragments should always override earlier ones.  So if A is
> defined before B, then B can override anything that A does.

Sorry for the confusing enumeration -- A comes after B.

To put it in more concrete terms, suppose you're writing an update wrapper 
around the autogenerated FPGA dts.  In some configurations a given node/property 
will be autogenerated, in others not -- but you want the wrapper to make sure 
it's gone, because it doesn't work with the system the FPGA is connected to.

If it's an error to delete something that doesn't exist, you'd have to have two 
update trees, first adding/replacing the thing in question to make sure it's 
there, and the second to delete it.

Allowing such an operation also lines up better with your suggestion to think of 
it as masking, rather than deleting.

-Scott

^ permalink raw reply	[flat|nested] 79+ messages in thread

* RE: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                     ` <4B8C44C8.6000105-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
@ 2010-03-01 22:56                                                                       ` Stephen Neuendorffer
       [not found]                                                                         ` <7c070166-6cd5-48e4-ab8e-cb062e3dbb00-RaUQJvECHiusiP+nND6G/7jjLBE8jN/0@public.gmane.org>
  2010-03-02  0:10                                                                       ` Grant Likely
  2010-03-02  1:19                                                                       ` David Gibson
  2 siblings, 1 reply; 79+ messages in thread
From: Stephen Neuendorffer @ 2010-03-01 22:56 UTC (permalink / raw)
  To: Scott Wood, grant.likely-s3s/WqlpOiPyB63q8FvJNQ
  Cc: Yoder Stuart-B08248, Jeremy Kerr,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, John Williams,
	Wood Scott-B07421

> >> That raises the question of whether it's legal to delete things
that aren't
> >> there.
> >
> > It isn't currently, which seems sane to me.
> >
> >>  There may be cases where a dts fragment A doesn't know whether
> >> fragment B will have defined something, and fragment A wants to
make sure it
> >> ends up undefined one way or another.
> >
> > Later fragments should always override earlier ones.  So if A is
> > defined before B, then B can override anything that A does.
> 
> Sorry for the confusing enumeration -- A comes after B.
> 
> To put it in more concrete terms, suppose you're writing an update
wrapper
> around the autogenerated FPGA dts.  In some configurations a given
node/property
> will be autogenerated, in others not -- but you want the wrapper to
make sure
> it's gone, because it doesn't work with the system the FPGA is
connected to.
> 
> If it's an error to delete something that doesn't exist, you'd have to
have two
> update trees, first adding/replacing the thing in question to make
sure it's
> there, and the second to delete it.
> 
> Allowing such an operation also lines up better with your suggestion
to think of
> it as masking, rather than deleting.

FWIW, I tend to agree with Scott...  I find it more natural to think of
deletion
as a well-defined total function, rather than as an operation which may
fail.

Steve

This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                 ` <4B8C3C78.5010206-D5eQfiDGL7eakBO8gow8eQ@public.gmane.org>
@ 2010-03-01 23:33                                                                   ` Grant Likely
       [not found]                                                                     ` <fa686aa41003011533x3d2d00abyb8d7cf33344a3bde-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Grant Likely @ 2010-03-01 23:33 UTC (permalink / raw)
  To: Mitch Bradley
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Jeremy Kerr, John Williams

On Mon, Mar 1, 2010 at 3:15 PM, Mitch Bradley <wmb-D5eQfiDGL7eakBO8gow8eQ@public.gmane.org> wrote:
>>
>> Yes, multiple sibling nodes with the same name are not allowed by dtc.
>>  I believe multiple siblings of the same name is legal with
>> OpenFirmware, but that is at least partially because in OpenFirmware
>> the @<addr> portion isn't necessarily part of the name.  (Imagine
>> having triplets and naming them Sally@1, Sally@2 and Sally@3!)
>>
>>
>
> I'm not sure how to parse the above because the word "name" seems to be used
> somewhat informally.
>
> The Open Firmware situation is this:
>
> a) At a given level of the tree, there can be any number of nodes with the
> same value for the "name" property.  For example, you could plug in several
> PCI Ethernet adapters and each would have "ethernet" as the value of the
> "name" property.  In general, the "name" property is not intended as a
> unique identifier, but rather as a mnemonic for human convenience.  The
> unique identifier is the first component of the "reg" property (within the
> context of the parent node).  The whole schema for reg properties is driven
> by this uniqueness requirement, along with the observation that the computer
> hardware must have some physical means of addressing specific devices.  The
> "reg" properties mimic physical addresses on various bus domains.
>
> b) A fully-qualified device specifier component includes both the name
> property value and the reg property value (AKA the unit address), for
> example "ethernet@5".
>
> c) It is possible to have a "wildcard" device node that contains an Open
> Firmware driver for a given device, but its bus has not been fully probed so
> you don't yet know the addresses (reg properties) for the actual devices.
>  In that case, you can have a "name" property but no "reg" property.  You
> can have a wildcard node "disk" and some explicit nodes "disk@1", "disk@2"
> as siblings.  When searching the device tree, nodes with reg properties take
> precedence over wildcard nodes, so the wildcard node is a "fallback" to use
> if you can't find an explicit "name@reg" match.  In principle, you could
> have several wildcard nodes with the same name at the same level of the
> tree, but if so, the search would find only the most recently defined one,
> so for all practical purposes it is as if only one exists.
>
> Wildcard nodes are useful for Open Firmware driver binding, and could
> potentially be used for OS driver binding for either hot-plugged or
> late-probed devices.  Whether or not they fit well into the dtc scheme, I
> can't say.

Thanks for the clarification.  The flat tree does stay with the Open
Firmware standard, however it does have the quirk that the name value
in the flat tree includes the reg address.  This is mostly because
when Linux on PowerPC reads the tree out of Open Firmware and creates
the flat representation it stores the full path including the reg
address.  The dts representation duplicates that behaviour.

I haven't entirely decided whether or not wildcard nodes are a good
idea in the flat representation, but I am leaning in that direction.
You already know about the discussion on how to handle Ethernet PHYs
at an unknown address.  That may very well be the way we decide to
handle it.

However, the node name issue does raise a question about dtc.  Right
now it doesn't do any checks in this regard, but an argument could be
made that dtc should warn or fail if a dts file sets the @<reg>
component in a way inconsistent with the first entry in the reg
property.  Perhaps dtc should also automatically add @<reg> when the
node name string omits it.  (again, this only applies to the flat
representation).

Cheers,
g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                 ` <72f497af-412c-4a05-90c2-5df0be00d93f-+Ck8Kgl/v09CYczPSvLbDrjjLBE8jN/0@public.gmane.org>
@ 2010-03-01 23:42                                                                   ` Grant Likely
  2010-03-02 23:12                                                                   ` David Gibson
  1 sibling, 0 replies; 79+ messages in thread
From: Grant Likely @ 2010-03-01 23:42 UTC (permalink / raw)
  To: Stephen Neuendorffer
  Cc: Yoder Stuart-B08248, Jeremy Kerr,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, John Williams,
	Wood Scott-B07421

On Mon, Mar 1, 2010 at 3:17 PM, Stephen Neuendorffer
<stephen.neuendorffer-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org> wrote:
> From: glikely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org [mailto:glikely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org] On Behalf Of Grant Likely
>> reworked to use nodes:
>> foo {
>>         bar-label: bar {
>>                 prop = 2;
>>                 delete(bar); // should be illegal
>>         };
>> };
>
> Um, my original intent was:
> foo {
>         bar-label: bar {
>                 prop = 2;
>         };
>         delete(bar); // should be illegal
> };

Ah, yes.  And you are right, that should be illegal.

> So, is it true that a tree which is overlayed on another tree can be independently verified to
> be independent of internal ordering?  This would be nice if so.

Yes, I think that is a valid statement, with the assumption that label
references at the top level are first resolved.

>> Not sure I follow.  It certainly isn't be valid to apply a label to a
>> command like delete().
>
> But the best thing of the above is that there is no longer a distinction between commands and data!
> delete is just a tag which gets interpreted during 'reduction' or 'overlay'.
>
> For instance, deleting a subnode could be:
>
> foo {
>        bar {
>                delete;
>        }
> }
>
> I guess this ends up conflicting with a property named 'delete' though.

Right.  It should be something syntactically distinct.

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                     ` <1012f9aa-1642-41ab-b8cd-a4ab4a7b269e-+Ck8Kgl/v0989VwWyyPjfbjjLBE8jN/0@public.gmane.org>
@ 2010-03-02  0:03                                                                       ` Grant Likely
       [not found]                                                                         ` <fa686aa41003011603w12c0a7f1y88b5fc7a008af1d5-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Grant Likely @ 2010-03-02  0:03 UTC (permalink / raw)
  To: Stephen Neuendorffer
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Scott Wood, Jeremy Kerr, John Williams

On Mon, Mar 1, 2010 at 3:26 PM, Stephen Neuendorffer
<stephen.neuendorffer-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org> wrote:
>
>
>> -----Original Message-----
>> From: glikely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org [mailto:glikely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org] On Behalf Of Grant Likely
>> Sent: Monday, March 01, 2010 2:19 PM
>> To: Scott Wood
>> Cc: Stephen Neuendorffer; Yoder Stuart-B08248; Wood Scott-B07421; devicetree-discuss-mnsaURCQ41sdnm+yROfE0A@public.gmane.org; John
>> Williams; Jeremy Kerr
>> Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
>>
>> On Mon, Mar 1, 2010 at 2:06 PM, Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org> wrote:
>> > Stephen Neuendorffer wrote:
>> >>
>> >> One thing I've seen in the past is that there is a sequentialization
>> >> question in this, which becomes
>> >> more apparent once deletion is allowed.
>> >>
>> >> First off, my assumption is that each node name is always unique in a
>> >> tree, even when overrides are allowed.
>> >> Otherwise the sub-node and property ordering becomes important.
>> >>
>> >> foo {
>> >>        bar = 2;
>> >>        bar = 3; // Illegal
>> >> } ;
>> >>
>> >>
>> >> foo {
>> >>        bar = 2;
>> >> } foo {
>> >>        bar = 3; // Legal
>> >> };
>> >>
>> >>
>> >> So, essentially, sequentialization of operation is forced by the
>> >> concatenation of trees.
>> >
>> > Hmm, I'd think it would be useful to e.g. include a template and
>> > subsequently modify it within the same node, rather than a more verbose and
>> > error-prone process of referencing labels later.
>> >
>> > If sequential operations within a tree are supported, I'm not sure that
>> > there's any remaining need for separate top-level trees -- you could express
>> > the same thing as top-level property/node redefinitions.
>> >
>> > What are the problems with supporting this?
>>
>> The main problem is that it doesn't fit the use cases I need to solve.
>>  I need to start with a 'stock' or 'vanilla' tree, and then add into
>> it board details.  ie. lay down a generic MPC5200 tree (include a .dts
>> file), and then fill it in with i2c and spi devices.  Or include the
>> .dts file generated by the XIlinx FPGA toolchain, and then populate it
>> with board details.  Sequential operations within the tree doesn't do
>> anything to support this use case because the board level fixups will
>> be applied all over the tree.
>
> Aside: I always pictured this the other way round, where the DTS for an
> FPGA design includes the DTS for the board.  Then again, as long as they
> are independent, it probably doesn't matter.

Heh, interesting.  Yeah, I suppose it could be done that way too.  The
/include/ directive works pretty much anywhere in the input file, so a
file could either lay down a structure and then include a modifer, or
include a structure and then modify it.  I was thinking in terms of
the board file including the FPGA file because it matches the pattern
for say an SoC where there would be a common SoC .dts file and all the
boards using that SoC would include it.

Also, I was thinking that the SoC or FPGA structure needs to be layed
down first so that the board file has nodes in the tree to anchor new
nodes to.  For example, the FPGA's i2c controller needs to be in place
so that i2c devices can be grafted onto it.

>> > There may be cases where a dts fragment A doesn't know whether
>> > fragment B will have defined something, and fragment A wants to make sure it
>> > ends up undefined one way or another.
>>
>> Later fragments should always override earlier ones.  So if A is
>> defined before B, then B can override anything that A does.
>
> So the idiom to do this safely would be:
>
> foo {
>        bar {} // Ensure that bar exists.
> }
> foo {
>        delete(bar);
> }
>
> Seems baroque, but OK...

Just to make sure I understand you, what bit is striking you as
baroque?  The bit about the node needing to exist before it can be
deleted?

Scott does make a good point in one of his emails, especially within
the 'stack of overlays' model.  Maybe it should be perfectly fine to
mask a node or property, regardless of whether or not it exists in the
previous tree.  Maybe this should be just fine:
foo {
};
foo {
       mask-node(bar);
};


>> following the 'stack of overlays' model to its logical conclusion.  In
>> a sense, properties and nodes are getting masked out of the earlier
>> tree, not deleted.  It is more of an operation (mask) than a command
>> (delete) being applied.  delete-node() may give the misleading
>> impression that something is being executed at that point in the tree.
>
> Regardless of what the syntax is, if the *semantics* is overlay, then there
> doesn't seem to be any reason to disallow undeletion, and in fact, this semantics
> gives a way to implement it.  I'll defer whether this is *needed*: In the case
> of device trees it's not clear that it is.

The only reason is a practical one.  The way the node redefinitions
are currently processed makes this difficult.  dtc fully processes and
resolves a node definition before moving on to the next one.  The data
is already gone by the time any kind of undelete occurs (but a new
node which the same name can certainly be created).

With my current love affair of wanting to know the use-case before
committing to a feature, I'd like to know where undelete would be used
before doing the rework required to implement it.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                     ` <4B8C44C8.6000105-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
  2010-03-01 22:56                                                                       ` Stephen Neuendorffer
@ 2010-03-02  0:10                                                                       ` Grant Likely
  2010-03-02  1:19                                                                       ` David Gibson
  2 siblings, 0 replies; 79+ messages in thread
From: Grant Likely @ 2010-03-02  0:10 UTC (permalink / raw)
  To: Scott Wood
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Jeremy Kerr, John Williams

On Mon, Mar 1, 2010 at 3:50 PM, Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org> wrote:
> Grant Likely wrote:
>>
>> On Mon, Mar 1, 2010 at 2:06 PM, Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
>> wrote:
>>>
>>> Hmm, I'd think it would be useful to e.g. include a template and
>>> subsequently modify it within the same node, rather than a more verbose
>>> and
>>> error-prone process of referencing labels later.
>>>
>>> If sequential operations within a tree are supported, I'm not sure that
>>> there's any remaining need for separate top-level trees -- you could
>>> express
>>> the same thing as top-level property/node redefinitions.
>>>
>>> What are the problems with supporting this?
>>
>> The main problem is that it doesn't fit the use cases I need to solve.
>>  I need to start with a 'stock' or 'vanilla' tree, and then add into
>> it board details.  ie. lay down a generic MPC5200 tree (include a .dts
>> file), and then fill it in with i2c and spi devices.  Or include the
>> .dts file generated by the XIlinx FPGA toolchain, and then populate it
>> with board details.  Sequential operations within the tree doesn't do
>> anything to support this use case because the board level fixups will
>> be applied all over the tree.
>>
>> To reverse the question, what is the use case that is best solved with
>> sequential operations within the root tree?
>
> The case I had in mind was having includable templates for fragments of the
> tree, rather than starting with a generic full tree.  Though I'd probably
> end up wanting things like template arguments and math as well (is any
> existing macro language going to do cell arithmetic?), so the focus on that
> kind of use case at this point should probably be limited to not defining
> syntax that's going to make things harder on future language extensions.
>  The only thing that immediately comes to mind from that perspective is that
> symbols are a more limited resource than keywords.

Right.  I thought about that too, and came to the conclusion that
while it might be nice to have templates and the like, it isn't as big
a deal as handling all the crazy board files duplicating the SoC bits
and subtly changing bits all through the tree.  At least after the SoC
.dts is written, even if it has a lot of similar nodes, it doesn't
really need to have bits added or removed from it on a regular basis.
And on the FPGA, we've got a real programming language (well, TCL) to
do complex tree generation with.

>>> If you don't reuse the label, but bar is redefined, where does bar-label
>>> point?
>>
>> It doesn't point to anything because when a property is deleted, the
>> label also goes away.
>
> Is it the same way with node labels?

yes

>  What happens to previous references?

They are either already resolved (in the case of node redefines at the
top level), or they will fail.

>  Is it detected by dtc, or does a bad phandle/path stick around to be found
> at runtime?  And what if the node is added back?

All phandles are resolved after the tree is fully parsed.  This could
probably use more thought/discussion to think about the implications.

>>>  There may be cases where a dts fragment A doesn't know whether
>>> fragment B will have defined something, and fragment A wants to make sure
>>> it
>>> ends up undefined one way or another.
>>
>> Later fragments should always override earlier ones.  So if A is
>> defined before B, then B can override anything that A does.
>
> Sorry for the confusing enumeration -- A comes after B.
>
> To put it in more concrete terms, suppose you're writing an update wrapper
> around the autogenerated FPGA dts.  In some configurations a given
> node/property will be autogenerated, in others not -- but you want the
> wrapper to make sure it's gone, because it doesn't work with the system the
> FPGA is connected to.
>
> If it's an error to delete something that doesn't exist, you'd have to have
> two update trees, first adding/replacing the thing in question to make sure
> it's there, and the second to delete it.
>
> Allowing such an operation also lines up better with your suggestion to
> think of it as masking, rather than deleting.

This is a good argument.  Let me think about it for a bit, but I think
you're probably right.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* RE: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                         ` <fa686aa41003011603w12c0a7f1y88b5fc7a008af1d5-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-03-02  0:13                                                                           ` Stephen Neuendorffer
       [not found]                                                                             ` <f9885aa5-5c11-4118-9980-f17378d7cbd5-RaUQJvECHiuXHCJdrdq+zrjjLBE8jN/0@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Stephen Neuendorffer @ 2010-03-02  0:13 UTC (permalink / raw)
  To: Grant Likely
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Scott Wood, Jeremy Kerr, John Williams

> >> The main problem is that it doesn't fit the use cases I need to solve.
> >>  I need to start with a 'stock' or 'vanilla' tree, and then add into
> >> it board details.  ie. lay down a generic MPC5200 tree (include a .dts
> >> file), and then fill it in with i2c and spi devices.  Or include the
> >> .dts file generated by the XIlinx FPGA toolchain, and then populate it
> >> with board details.  Sequential operations within the tree doesn't do
> >> anything to support this use case because the board level fixups will
> >> be applied all over the tree.
> >
> > Aside: I always pictured this the other way round, where the DTS for an
> > FPGA design includes the DTS for the board.  Then again, as long as they
> > are independent, it probably doesn't matter.
> 
> Heh, interesting.  Yeah, I suppose it could be done that way too.  The
> /include/ directive works pretty much anywhere in the input file, so a
> file could either lay down a structure and then include a modifer, or
> include a structure and then modify it.  I was thinking in terms of
> the board file including the FPGA file because it matches the pattern
> for say an SoC where there would be a common SoC .dts file and all the
> boards using that SoC would include it.

Yeah, but in FPGA, the board is likely to be more stable than the FPGA design... :)
Or maybe 'some' FPGA designs are that way and others are not.  

> Also, I was thinking that the SoC or FPGA structure needs to be layed
> down first so that the board file has nodes in the tree to anchor new
> nodes to.  For example, the FPGA's i2c controller needs to be in place
> so that i2c devices can be grafted onto it.

Hmm... I think we should try it and make sure that things will work... 
I started to make a 'test case' based on a real system, but all the
device trees I have lying around are moldy and full of dry rot.  I think it should be able
to work either way...

> >> > There may be cases where a dts fragment A doesn't know whether
> >> > fragment B will have defined something, and fragment A wants to make sure it
> >> > ends up undefined one way or another.
> >>
> >> Later fragments should always override earlier ones.  So if A is
> >> defined before B, then B can override anything that A does.
> >
> > So the idiom to do this safely would be:
> >
> > foo {
> >        bar {} // Ensure that bar exists.
> > }
> > foo {
> >        delete(bar);
> > }
> >
> > Seems baroque, but OK...
> 
> Just to make sure I understand you, what bit is striking you as
> baroque?  The bit about the node needing to exist before it can be
> deleted?

Yes, since there is a bizarre workaround I show above, which basically ensures that
the error never occurs.

> Scott does make a good point in one of his emails, especially within
> the 'stack of overlays' model.  Maybe it should be perfectly fine to
> mask a node or property, regardless of whether or not it exists in the
> previous tree.  Maybe this should be just fine:
> foo {
> };
> foo {
>        mask-node(bar);
> };

Yes... I think this should just be allowed... or at the very least I don't see a
reason to make this an error...  It does occur to me that it might be useful to
explicitly note the 'extension' of a previous node, which asserts that it *must*
exist.  i.e.

foo {
	bar + {
		bar = 3;
	}
}

Here it is explicitly clear that bar is an incomplete definition?

Steve




This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                     ` <fa686aa41003011425i734ee434m95b62d57a271bd1f-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-03-02  1:11                                                                       ` David Gibson
  0 siblings, 0 replies; 79+ messages in thread
From: David Gibson @ 2010-03-02  1:11 UTC (permalink / raw)
  To: Grant Likely
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Scott Wood, Jeremy Kerr, John Williams

On Mon, Mar 01, 2010 at 03:25:04PM -0700, Grant Likely wrote:
> On Mon, Mar 1, 2010 at 3:03 PM, Stephen Neuendorffer
> <stephen.neuendorffer-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org> wrote:
> > From: Scott Wood [mailto:scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org]
> >> If sequential operations within a tree are supported, I'm not sure
> > that there's
> >> any remaining need for separate top-level trees -- you could express
> > the same
> >> thing as top-level property/node redefinitions.
> >
> > I agree, *IF* sequential operations are supported.
> > But then you have a sequential programming language, not a structured
> > data
> > description.  I think this is a bad idea.
> 
> Indeed.  We've got lots of sequential programming languages.  I don't
> want us to create for ourselves a new (and poorly implemented)
> language.

I agree that we don't want to turn this into a procedural programming
language.  On the other hand, there is plenty of precedent for
declarative languages where order of declarations remains important
for deciding which takes precedence.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                     ` <4B8C44C8.6000105-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
  2010-03-01 22:56                                                                       ` Stephen Neuendorffer
  2010-03-02  0:10                                                                       ` Grant Likely
@ 2010-03-02  1:19                                                                       ` David Gibson
  2010-03-02  2:10                                                                         ` Grant Likely
  2 siblings, 1 reply; 79+ messages in thread
From: David Gibson @ 2010-03-02  1:19 UTC (permalink / raw)
  To: Scott Wood
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Jeremy Kerr, John Williams

On Mon, Mar 01, 2010 at 04:50:48PM -0600, Scott Wood wrote:
> Grant Likely wrote:
> >On Mon, Mar 1, 2010 at 2:06 PM, Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org> wrote:
> >>Hmm, I'd think it would be useful to e.g. include a template and
> >>subsequently modify it within the same node, rather than a more verbose and
> >>error-prone process of referencing labels later.
> >>
> >>If sequential operations within a tree are supported, I'm not sure that
> >>there's any remaining need for separate top-level trees -- you could express
> >>the same thing as top-level property/node redefinitions.
> >>
> >>What are the problems with supporting this?
> >
> >The main problem is that it doesn't fit the use cases I need to solve.
> > I need to start with a 'stock' or 'vanilla' tree, and then add into
> >it board details.  ie. lay down a generic MPC5200 tree (include a .dts
> >file), and then fill it in with i2c and spi devices.  Or include the
> >.dts file generated by the XIlinx FPGA toolchain, and then populate it
> >with board details.  Sequential operations within the tree doesn't do
> >anything to support this use case because the board level fixups will
> >be applied all over the tree.
> >
> >To reverse the question, what is the use case that is best solved with
> >sequential operations within the root tree?
> 
> The case I had in mind was having includable templates for fragments
> of the tree, rather than starting with a generic full tree.  Though
> I'd probably end up wanting things like template arguments and math
> as well (is any existing macro language going to do cell
> arithmetic?),

m4 can do arithmetic, but it's pretty hideous.  But I still have
allowing expressions as a reasonable extension within dtc itself.
Macros or templates with parameters raise a lot more complex issues.

[snip]
> >>If you don't reuse the label, but bar is redefined, where does bar-label
> >>point?
> >
> >It doesn't point to anything because when a property is deleted, the
> >label also goes away.
> 
> Is it the same way with node labels?

Yes, node labels are attached to the node, so if the node is removed,
so is the label.

> What happens to previous
> references?  Is it detected by dtc, or does a bad phandle/path stick
> around to be found at runtime?  And what if the node is added back?

References aren't resolved until the whole tree is built.  So
references will always resolve to the *last* definition of a label,
and if the last "definition" is an undefinition / deletion, then the
references will fail to resolve and give an error.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                         ` <7c070166-6cd5-48e4-ab8e-cb062e3dbb00-RaUQJvECHiusiP+nND6G/7jjLBE8jN/0@public.gmane.org>
@ 2010-03-02  1:22                                                                           ` David Gibson
  0 siblings, 0 replies; 79+ messages in thread
From: David Gibson @ 2010-03-02  1:22 UTC (permalink / raw)
  To: Stephen Neuendorffer
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Scott Wood, Jeremy Kerr, John Williams

On Mon, Mar 01, 2010 at 02:56:41PM -0800, Stephen Neuendorffer wrote:
> > >> That raises the question of whether it's legal to delete things
> that aren't
> > >> there.
> > >
> > > It isn't currently, which seems sane to me.
> > >
> > >>  There may be cases where a dts fragment A doesn't know whether
> > >> fragment B will have defined something, and fragment A wants to
> make sure it
> > >> ends up undefined one way or another.
> > >
> > > Later fragments should always override earlier ones.  So if A is
> > > defined before B, then B can override anything that A does.
> > 
> > Sorry for the confusing enumeration -- A comes after B.
> > 
> > To put it in more concrete terms, suppose you're writing an update
> wrapper
> > around the autogenerated FPGA dts.  In some configurations a given
> node/property
> > will be autogenerated, in others not -- but you want the wrapper to
> make sure
> > it's gone, because it doesn't work with the system the FPGA is
> connected to.
> > 
> > If it's an error to delete something that doesn't exist, you'd have to
> have two
> > update trees, first adding/replacing the thing in question to make
> sure it's
> > there, and the second to delete it.
> > 
> > Allowing such an operation also lines up better with your suggestion
> to think of
> > it as masking, rather than deleting.
> 
> FWIW, I tend to agree with Scott...  I find it more natural to think
> of deletion as a well-defined total function, rather than as an
> operation which may fail.

I tend to agree, although I'm not sure that "total function" is quite
the right term.

I think the approach that makes the most sense in the context of this
"stack of overlays" approach, is to think of "non-existent" as a
special type of value (which is different from merely empty, of
course).  So, deletion is overriding a node or property's existing
value with "non-existent".

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                             ` <f9885aa5-5c11-4118-9980-f17378d7cbd5-RaUQJvECHiuXHCJdrdq+zrjjLBE8jN/0@public.gmane.org>
@ 2010-03-02  1:25                                                                               ` David Gibson
  2010-03-02  2:08                                                                               ` Grant Likely
  1 sibling, 0 replies; 79+ messages in thread
From: David Gibson @ 2010-03-02  1:25 UTC (permalink / raw)
  To: Stephen Neuendorffer
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Scott Wood, Jeremy Kerr, John Williams

On Mon, Mar 01, 2010 at 04:13:30PM -0800, Stephen Neuendorffer wrote:
[snip]
> Yes... I think this should just be allowed... or at the very least I
> don't see a reason to make this an error...  It does occur to me
> that it might be useful to explicitly note the 'extension' of a
> previous node, which asserts that it *must* exist.  i.e.
> 
> foo {
> 	bar + {
> 		bar = 3;
> 	}
> }
> 
> Here it is explicitly clear that bar is an incomplete definition?

Hrm, interesting idea, and one that could have some merit.  However,
that specific syntax won't work, since '+' is a valid character in
node and property names.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                             ` <f9885aa5-5c11-4118-9980-f17378d7cbd5-RaUQJvECHiuXHCJdrdq+zrjjLBE8jN/0@public.gmane.org>
  2010-03-02  1:25                                                                               ` David Gibson
@ 2010-03-02  2:08                                                                               ` Grant Likely
       [not found]                                                                                 ` <fa686aa41003011808h586e3dc3x11ef14af9c6e5fb8-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  1 sibling, 1 reply; 79+ messages in thread
From: Grant Likely @ 2010-03-02  2:08 UTC (permalink / raw)
  To: Stephen Neuendorffer
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Scott Wood, Jeremy Kerr, John Williams

On Mon, Mar 1, 2010 at 5:13 PM, Stephen Neuendorffer
<stephen.neuendorffer-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org> wrote:
>> >> The main problem is that it doesn't fit the use cases I need to solve.
>> >>  I need to start with a 'stock' or 'vanilla' tree, and then add into
>> >> it board details.  ie. lay down a generic MPC5200 tree (include a .dts
>> >> file), and then fill it in with i2c and spi devices.  Or include the
>> >> .dts file generated by the XIlinx FPGA toolchain, and then populate it
>> >> with board details.  Sequential operations within the tree doesn't do
>> >> anything to support this use case because the board level fixups will
>> >> be applied all over the tree.
>> >
>> > Aside: I always pictured this the other way round, where the DTS for an
>> > FPGA design includes the DTS for the board.  Then again, as long as they
>> > are independent, it probably doesn't matter.
>>
>> Heh, interesting.  Yeah, I suppose it could be done that way too.  The
>> /include/ directive works pretty much anywhere in the input file, so a
>> file could either lay down a structure and then include a modifer, or
>> include a structure and then modify it.  I was thinking in terms of
>> the board file including the FPGA file because it matches the pattern
>> for say an SoC where there would be a common SoC .dts file and all the
>> boards using that SoC would include it.
>
> Yeah, but in FPGA, the board is likely to be more stable than the FPGA design... :)
> Or maybe 'some' FPGA designs are that way and others are not.

Ah, but even the board file has to change depending on the FPGA
design, and nodes will move around depending on the FPGA internal bus
structure, but I understand what you're saying.  This is why being
able to redefine labelled nodes is a critical feature.  For instance,
the following isn't actually very useful because it assumes knowledge
of the exact location of the i2c bus node:

/ {
        plb@0 {
                ranges;
                i2c@c0000000 {
                        #address-cells = <1>;
                        #size-cells = <1>;
                        reg = <0xc0000000 0x1000>;
                };
        };
};

/ {
        plb@0 {
                i2c@c0000000 {
                        rtc@0 {
                               reg = <0>;
                        };
                        eeprom@1 {
                               reg = <1>;
                        };
                };
        };
};

However, the following is really useful because the xilinx toolchain
already generates the device labels, and the i2c node can move without
breaking the board devices:

/ {
        plb@0 {
                ranges;
                i2c-bus-0: i2c@c0000000 {
                        #address-cells = <1>;
                        #size-cells = <1>;
                        reg = <0xc0000000 0x1000>;
                };
        };
};

&i2c-bus-0 {
        rtc@0 {
                reg = <0>;
        };
        eeprom@1 {
               reg = <1>;
        };
};

And this way the Platform Studio toolchain doesn't need to be taught
anything about the board layout.  A board file could look something
like this:

/include/ "fpga-design-file.dts"
&i2c-bus-0 {
        rtc@0 {
                reg = <0>;
        };
        eeprom@1 {
               reg = <1>;
        };
};

Now, if we're talking about Xilinx eval boards, I can see the argument
for having a stock file like ml507.dts, and then a project .dts file
might look something like this:

/include/ "fpga-design-file.dts"
/* Map between FPGA device names and ML507 board file labels by
applying the ml507 labels to the nodes from the FPGA file */
ml507-i2c-bus-0: &fpga-i2c-bus-0 { };
ml507-i2c-bus-1: &fpga-i2c-bus-1 { };
/include/ "ml507.dts"

This needs new syntax of course, but you get the idea, and it doesn't
require teaching the FPGA toochain all kinds of details about the
board or project files.

> Yes... I think this should just be allowed... or at the very least I don't see a
> reason to make this an error...  It does occur to me that it might be useful to
> explicitly note the 'extension' of a previous node, which asserts that it *must*
> exist.  i.e.
>
> foo {
>        bar + {
>                bar = 3;
>        }
> }
>
> Here it is explicitly clear that bar is an incomplete definition?

hmmm... I don't think I like this so much, and I don't yet see a use
case where this is really a required feature.

g.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
  2010-03-02  1:19                                                                       ` David Gibson
@ 2010-03-02  2:10                                                                         ` Grant Likely
       [not found]                                                                           ` <fa686aa41003011810w2e7b6278t6aaaf192f8d7c8c1-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Grant Likely @ 2010-03-02  2:10 UTC (permalink / raw)
  To: Scott Wood, Grant Likely, Wood Scott-B07421,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Yoder Stuart-B08248

On Mon, Mar 1, 2010 at 6:19 PM, David Gibson
<david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote:
> On Mon, Mar 01, 2010 at 04:50:48PM -0600, Scott Wood wrote:
>> Grant Likely wrote:
>> >On Mon, Mar 1, 2010 at 2:06 PM, Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org> wrote:
>> >>Hmm, I'd think it would be useful to e.g. include a template and
>> >>subsequently modify it within the same node, rather than a more verbose and
>> >>error-prone process of referencing labels later.
>> >>
>> >>If sequential operations within a tree are supported, I'm not sure that
>> >>there's any remaining need for separate top-level trees -- you could express
>> >>the same thing as top-level property/node redefinitions.
>> >>
>> >>What are the problems with supporting this?
>> >
>> >The main problem is that it doesn't fit the use cases I need to solve.
>> > I need to start with a 'stock' or 'vanilla' tree, and then add into
>> >it board details.  ie. lay down a generic MPC5200 tree (include a .dts
>> >file), and then fill it in with i2c and spi devices.  Or include the
>> >.dts file generated by the XIlinx FPGA toolchain, and then populate it
>> >with board details.  Sequential operations within the tree doesn't do
>> >anything to support this use case because the board level fixups will
>> >be applied all over the tree.
>> >
>> >To reverse the question, what is the use case that is best solved with
>> >sequential operations within the root tree?
>>
>> The case I had in mind was having includable templates for fragments
>> of the tree, rather than starting with a generic full tree.  Though
>> I'd probably end up wanting things like template arguments and math
>> as well (is any existing macro language going to do cell
>> arithmetic?),
>
> m4 can do arithmetic, but it's pretty hideous.  But I still have
> allowing expressions as a reasonable extension within dtc itself.
> Macros or templates with parameters raise a lot more complex issues.
>
> [snip]
>> >>If you don't reuse the label, but bar is redefined, where does bar-label
>> >>point?
>> >
>> >It doesn't point to anything because when a property is deleted, the
>> >label also goes away.
>>
>> Is it the same way with node labels?
>
> Yes, node labels are attached to the node, so if the node is removed,
> so is the label.
>
>> What happens to previous
>> references?  Is it detected by dtc, or does a bad phandle/path stick
>> around to be found at runtime?  And what if the node is added back?
>
> References aren't resolved until the whole tree is built.  So
> references will always resolve to the *last* definition of a label,
> and if the last "definition" is an undefinition / deletion, then the
> references will fail to resolve and give an error.

...except for when processing node redefinitions by label in the current patch.

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                           ` <fa686aa41003011810w2e7b6278t6aaaf192f8d7c8c1-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-03-02  2:16                                                                             ` Grant Likely
       [not found]                                                                               ` <fa686aa41003011816j534bf335o6fafe6f1c4a63436-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 79+ messages in thread
From: Grant Likely @ 2010-03-02  2:16 UTC (permalink / raw)
  To: Scott Wood, Grant Likely, Wood Scott-B07421,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Yoder Stuart-B08248

On Mon, Mar 1, 2010 at 7:10 PM, Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org> wrote:
> On Mon, Mar 1, 2010 at 6:19 PM, David Gibson
> <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote:
>> On Mon, Mar 01, 2010 at 04:50:48PM -0600, Scott Wood wrote:
>>> Grant Likely wrote:
>>> >On Mon, Mar 1, 2010 at 2:06 PM, Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org> wrote:
>>> >>Hmm, I'd think it would be useful to e.g. include a template and
>>> >>subsequently modify it within the same node, rather than a more verbose and
>>> >>error-prone process of referencing labels later.
>>> >>
>>> >>If sequential operations within a tree are supported, I'm not sure that
>>> >>there's any remaining need for separate top-level trees -- you could express
>>> >>the same thing as top-level property/node redefinitions.
>>> >>
>>> >>What are the problems with supporting this?
>>> >
>>> >The main problem is that it doesn't fit the use cases I need to solve.
>>> > I need to start with a 'stock' or 'vanilla' tree, and then add into
>>> >it board details.  ie. lay down a generic MPC5200 tree (include a .dts
>>> >file), and then fill it in with i2c and spi devices.  Or include the
>>> >.dts file generated by the XIlinx FPGA toolchain, and then populate it
>>> >with board details.  Sequential operations within the tree doesn't do
>>> >anything to support this use case because the board level fixups will
>>> >be applied all over the tree.
>>> >
>>> >To reverse the question, what is the use case that is best solved with
>>> >sequential operations within the root tree?
>>>
>>> The case I had in mind was having includable templates for fragments
>>> of the tree, rather than starting with a generic full tree.  Though
>>> I'd probably end up wanting things like template arguments and math
>>> as well (is any existing macro language going to do cell
>>> arithmetic?),
>>
>> m4 can do arithmetic, but it's pretty hideous.  But I still have
>> allowing expressions as a reasonable extension within dtc itself.
>> Macros or templates with parameters raise a lot more complex issues.
>>
>> [snip]
>>> >>If you don't reuse the label, but bar is redefined, where does bar-label
>>> >>point?
>>> >
>>> >It doesn't point to anything because when a property is deleted, the
>>> >label also goes away.
>>>
>>> Is it the same way with node labels?
>>
>> Yes, node labels are attached to the node, so if the node is removed,
>> so is the label.
>>
>>> What happens to previous
>>> references?  Is it detected by dtc, or does a bad phandle/path stick
>>> around to be found at runtime?  And what if the node is added back?
>>
>> References aren't resolved until the whole tree is built.  So
>> references will always resolve to the *last* definition of a label,
>> and if the last "definition" is an undefinition / deletion, then the
>> references will fail to resolve and give an error.
>
> ...except for when processing node redefinitions by label in the current patch.

In fact, I think this has to be the case, otherwise it would be
possible to create circular references in node redefiniton.

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                     ` <fa686aa41003011533x3d2d00abyb8d7cf33344a3bde-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-03-02  3:59                                                                       ` David Gibson
  0 siblings, 0 replies; 79+ messages in thread
From: David Gibson @ 2010-03-02  3:59 UTC (permalink / raw)
  To: Grant Likely
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Jeremy Kerr, John Williams

On Mon, Mar 01, 2010 at 04:33:29PM -0700, Grant Likely wrote:
> On Mon, Mar 1, 2010 at 3:15 PM, Mitch Bradley <wmb-D5eQfiDGL7eakBO8gow8eQ@public.gmane.org> wrote:
[snip]
> Thanks for the clarification.  The flat tree does stay with the Open
> Firmware standard, however it does have the quirk that the name value
> in the flat tree includes the reg address.  This is mostly because
> when Linux on PowerPC reads the tree out of Open Firmware and creates
> the flat representation it stores the full path including the reg
> address.  The dts representation duplicates that behaviour.

Well, it's more that in the flat tree we treat the "node name" as a
separate entity to the node's name property, and containing the
equivalent of both the name property and unit address as they'd be
treated in real OF.  And having done that, we typically omit the name
property entirely, and just generate it on the fly from the node name
when we need to.

> I haven't entirely decided whether or not wildcard nodes are a good
> idea in the flat representation, but I am leaning in that direction.
> You already know about the discussion on how to handle Ethernet PHYs
> at an unknown address.  That may very well be the way we decide to
> handle it.

Well.. the difficulty with wildcard nodes in a flat tree is that we
have a number of cases where we already use nodes with no reg property
to represent things that aren't really wildcards.  The common use is
for things which are addressable only on a sideband bus which doesn't
form part of the normal reg address space hierarchy, such as DCR
devices on 4xx.

> However, the node name issue does raise a question about dtc.  Right
> now it doesn't do any checks in this regard, but an argument could be
> made that dtc should warn or fail if a dts file sets the @<reg>
> component in a way inconsistent with the first entry in the reg
> property.  Perhaps dtc should also automatically add @<reg> when the
> node name string omits it.  (again, this only applies to the flat
> representation).

I've been intending that for ages.  The complication is that the way
the reg property is formatted into the unit address string is
dependent on the parent bus.  There's no inherent barrier to
implementing this, and indeed the infrastructure in checks.c was
created with this in mind amongst other things, but it's just a
moderately large amount of coding because we need per-bus hooks to
supply unit address formatting functions.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                               ` <fa686aa41003011816j534bf335o6fafe6f1c4a63436-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-03-02  4:20                                                                                 ` David Gibson
  0 siblings, 0 replies; 79+ messages in thread
From: David Gibson @ 2010-03-02  4:20 UTC (permalink / raw)
  To: Grant Likely
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Scott Wood, Jeremy Kerr, John Williams

On Mon, Mar 01, 2010 at 07:16:57PM -0700, Grant Likely wrote:
> On Mon, Mar 1, 2010 at 7:10 PM, Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org> wrote:
> > On Mon, Mar 1, 2010 at 6:19 PM, David Gibson
> > <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote:
> >> On Mon, Mar 01, 2010 at 04:50:48PM -0600, Scott Wood wrote:
> >>> Grant Likely wrote:
> >>> >On Mon, Mar 1, 2010 at 2:06 PM, Scott Wood <scottwood-KZfg59tc24xl57MIdRCFDg@public.gmane.org> wrote:
> >>> >>Hmm, I'd think it would be useful to e.g. include a template and
> >>> >>subsequently modify it within the same node, rather than a more verbose and
> >>> >>error-prone process of referencing labels later.
> >>> >>
> >>> >>If sequential operations within a tree are supported, I'm not sure that
> >>> >>there's any remaining need for separate top-level trees -- you could express
> >>> >>the same thing as top-level property/node redefinitions.
> >>> >>
> >>> >>What are the problems with supporting this?
> >>> >
> >>> >The main problem is that it doesn't fit the use cases I need to solve.
> >>> > I need to start with a 'stock' or 'vanilla' tree, and then add into
> >>> >it board details.  ie. lay down a generic MPC5200 tree (include a .dts
> >>> >file), and then fill it in with i2c and spi devices.  Or include the
> >>> >.dts file generated by the XIlinx FPGA toolchain, and then populate it
> >>> >with board details.  Sequential operations within the tree doesn't do
> >>> >anything to support this use case because the board level fixups will
> >>> >be applied all over the tree.
> >>> >
> >>> >To reverse the question, what is the use case that is best solved with
> >>> >sequential operations within the root tree?
> >>>
> >>> The case I had in mind was having includable templates for fragments
> >>> of the tree, rather than starting with a generic full tree.  Though
> >>> I'd probably end up wanting things like template arguments and math
> >>> as well (is any existing macro language going to do cell
> >>> arithmetic?),
> >>
> >> m4 can do arithmetic, but it's pretty hideous.  But I still have
> >> allowing expressions as a reasonable extension within dtc itself.
> >> Macros or templates with parameters raise a lot more complex issues.
> >>
> >> [snip]
> >>> >>If you don't reuse the label, but bar is redefined, where does bar-label
> >>> >>point?
> >>> >
> >>> >It doesn't point to anything because when a property is deleted, the
> >>> >label also goes away.
> >>>
> >>> Is it the same way with node labels?
> >>
> >> Yes, node labels are attached to the node, so if the node is removed,
> >> so is the label.
> >>
> >>> What happens to previous
> >>> references?  Is it detected by dtc, or does a bad phandle/path stick
> >>> around to be found at runtime?  And what if the node is added back?
> >>
> >> References aren't resolved until the whole tree is built.  So
> >> references will always resolve to the *last* definition of a label,
> >> and if the last "definition" is an undefinition / deletion, then the
> >> references will fail to resolve and give an error.
> >
> > ...except for when processing node redefinitions by label in the current patch.
> 
> In fact, I think this has to be the case, otherwise it would be
> possible to create circular references in node redefiniton.

Ah, yes.  Node redefinition references act in order with the labels.
Which is a potentially nasty inconsistency.  Ugh.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                                 ` <fa686aa41003011808h586e3dc3x11ef14af9c6e5fb8-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-03-02 17:06                                                                                   ` Scott Wood
  0 siblings, 0 replies; 79+ messages in thread
From: Scott Wood @ 2010-03-02 17:06 UTC (permalink / raw)
  To: Grant Likely
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Jeremy Kerr, John Williams

On Mon, Mar 01, 2010 at 07:08:19PM -0700, Grant Likely wrote:
> > Yes... I think this should just be allowed... or at the very least I don't see a
> > reason to make this an error...  It does occur to me that it might be useful to
> > explicitly note the 'extension' of a previous node, which asserts that it *must*
> > exist.  i.e.
> >
> > foo {
> >        bar + {
> >                bar = 3;
> >        }
> > }
> >
> > Here it is explicitly clear that bar is an incomplete definition?
> 
> hmmm... I don't think I like this so much, and I don't yet see a use
> case where this is really a required feature.

I could see it being useful if instead of being an error if bar (the node)
doesn't already exist, it is ignored.  In other words, "if there is a bar,
add this property to it, but don't create a new bar just for me".

-Scott

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
       [not found]                                                                 ` <72f497af-412c-4a05-90c2-5df0be00d93f-+Ck8Kgl/v09CYczPSvLbDrjjLBE8jN/0@public.gmane.org>
  2010-03-01 23:42                                                                   ` Grant Likely
@ 2010-03-02 23:12                                                                   ` David Gibson
  2010-03-03 16:18                                                                     ` Grant Likely
  1 sibling, 1 reply; 79+ messages in thread
From: David Gibson @ 2010-03-02 23:12 UTC (permalink / raw)
  To: Stephen Neuendorffer
  Cc: Wood Scott-B07421, devicetree-discuss-mnsaURCQ41sdnm+yROfE0A,
	Yoder Stuart-B08248, Jeremy Kerr, John Williams

On Mon, Mar 01, 2010 at 02:17:47PM -0800, Stephen Neuendorffer wrote:
> > -----Original Message-----
> > From: glikely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org [mailto:glikely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org] On Behalf Of Grant Likely
> > Sent: Monday, March 01, 2010 1:49 PM
> > To: Stephen Neuendorffer
> > Cc: Yoder Stuart-B08248; Wood Scott-B07421; devicetree-discuss@ozlabs.org; John Williams; Jeremy Kerr
> > Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
[snip]
> > This is never legal.  If deleting by label, it must be at the top
> > level.  It doesn't make sense to use a label reference inside a node
> > block, since the node block is already supposed to define where you
> > are working in the tree.
> > 
> > >        delete(bar); // May or may not be Illegal, since don't know what bar-label references
> > 
> > No longer an issue since the previous line is illegal.
> > 
> > Also, must be either delete-node() or delete-prop() since nodes and
> > properties can use the same names.
> 
> So, is it true that a tree which is overlayed on another tree can be
> independently verified to be independent of internal ordering?  This
> would be nice if so.

Hrm, yes and no.  Most of our tests for duplicate labels and so forth
are only performed after all the overlay/merging is completed.

Which brings up another inconsistency in the current processing.
Although:

	/ {
		foo = "bar";
		foo = "baz";
	};

is illegal and will cause an error, the way that merge_nodes() is
implemented means that the following will be accepted:

	/ {
	};
	/ {
		foo = "bar";
		foo = "baz";
	};

(and the foo property will have the final value "baz").

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
  2010-03-02 23:12                                                                   ` David Gibson
@ 2010-03-03 16:18                                                                     ` Grant Likely
  0 siblings, 0 replies; 79+ messages in thread
From: Grant Likely @ 2010-03-03 16:18 UTC (permalink / raw)
  To: Stephen Neuendorffer, Grant Likely, Yoder Stuart-B08248, Jeremy Kerr

On Tue, Mar 2, 2010 at 4:12 PM, David Gibson
<david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote:
> On Mon, Mar 01, 2010 at 02:17:47PM -0800, Stephen Neuendorffer wrote:
>> > -----Original Message-----
>> > From: glikely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org [mailto:glikely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org] On Behalf Of Grant Likely
>> > Sent: Monday, March 01, 2010 1:49 PM
>> > To: Stephen Neuendorffer
>> > Cc: Yoder Stuart-B08248; Wood Scott-B07421; devicetree-discuss@ozlabs.org; John Williams; Jeremy Kerr
>> > Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
> [snip]
>> > This is never legal.  If deleting by label, it must be at the top
>> > level.  It doesn't make sense to use a label reference inside a node
>> > block, since the node block is already supposed to define where you
>> > are working in the tree.
>> >
>> > >        delete(bar); // May or may not be Illegal, since don't know what bar-label references
>> >
>> > No longer an issue since the previous line is illegal.
>> >
>> > Also, must be either delete-node() or delete-prop() since nodes and
>> > properties can use the same names.
>>
>> So, is it true that a tree which is overlayed on another tree can be
>> independently verified to be independent of internal ordering?  This
>> would be nice if so.
>
> Hrm, yes and no.  Most of our tests for duplicate labels and so forth
> are only performed after all the overlay/merging is completed.
>
> Which brings up another inconsistency in the current processing.
> Although:
>
>        / {
>                foo = "bar";
>                foo = "baz";
>        };
>
> is illegal and will cause an error, the way that merge_nodes() is
> implemented means that the following will be accepted:
>
>        / {
>        };
>        / {
>                foo = "bar";
>                foo = "baz";
>        };
>
> (and the foo property will have the final value "baz").

That should be easy to fix.  How about the following change to prevent
duplicate properties even getting added to the livetree.  This patch
isn't complete, it breaks some of the test cases because it fails in a
different way, and it makes some of the post-checks redundant.

g.

commit f676848929e6764b3a6c14f14eafacdfcaab5f15
Author: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
Date:   Wed Mar 3 09:15:30 2010 -0700

    Don't add duplicate properties to the live tree

diff --git a/dtc-parser.y b/dtc-parser.y
index ed87d3b..053ae67 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -156,6 +156,11 @@ proplist:
 		}
 	| proplist propdef
 		{
+			if (find_property($1, $2->name)) {
+				yyerror("syntax error: duplicate property");
+				YYERROR;
+			}
+
 			$$ = chain_property($2, $1);
 		}
 	;
diff --git a/dtc.h b/dtc.h
index b36ac5d..78033fb 100644
--- a/dtc.h
+++ b/dtc.h
@@ -170,6 +170,7 @@ void add_label(struct label **labels, char *label);
 struct property *build_property(char *name, struct data val);
 struct property *chain_property(struct property *first, struct property *list);
 struct property *reverse_properties(struct property *first);
+struct property *find_property(struct property *proplist, const char *name);

 struct node *build_node(struct property *proplist, struct node *children);
 struct node *name_node(struct node *node, char *name);
diff --git a/livetree.c b/livetree.c
index 13c5f10..924e131 100644
--- a/livetree.c
+++ b/livetree.c
@@ -74,6 +74,15 @@ struct property *reverse_properties(struct property *first)
 	return head;
 }

+struct property *find_property(struct property *proplist, const char *name)
+{
+	for (; proplist; proplist = proplist->next)
+		if (streq(proplist->name, name))
+			return proplist;
+
+	return NULL;
+}
+
 struct node *build_node(struct property *proplist, struct node *children)
 {
 	struct node *new = xmalloc(sizeof(*new));


-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply related	[flat|nested] 79+ messages in thread

end of thread, other threads:[~2010-03-03 16:18 UTC | newest]

Thread overview: 79+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-09-26 20:25 [PATCH 0/9 V3] Implement a new DTS Source Language Jon Loeliger
     [not found] ` <1222460748-20127-1-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-26 20:25   ` [PATCH 1/9 V3] Remove support for the legacy DTS source file format Jon Loeliger
     [not found]     ` <1222460748-20127-2-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-26 20:25       ` [PATCH 2/9 V3] Add conditionalized debug() print macro Jon Loeliger
     [not found]         ` <1222460748-20127-3-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-26 20:25           ` [PATCH 3/9 V3] Enhance source position implementation Jon Loeliger
     [not found]             ` <1222460748-20127-4-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-26 20:25               ` [PATCH 4/9 V3] Add header files for new Internal Representation form Jon Loeliger
     [not found]                 ` <1222460748-20127-5-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-26 20:25                   ` [PATCH 5/9 V3] Add most of the new IR implementation files Jon Loeliger
     [not found]                     ` <1222460748-20127-6-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-26 20:25                       ` [PATCH 6/9 V3] Add the main IR evaluation implementation Jon Loeliger
     [not found]                         ` <1222460748-20127-7-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-26 20:25                           ` [PATCH 7/9 V3] Introduce new DTS language Jon Loeliger
     [not found]                             ` <1222460748-20127-8-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-26 20:25                               ` [PATCH 8/9 V3] Add documentation for the " Jon Loeliger
     [not found]                                 ` <1222460748-20127-9-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-26 20:25                                   ` [PATCH 9/9 V3] Test constant expressions in cell contexts Jon Loeliger
     [not found]                                     ` <1222460748-20127-10-git-send-email-jdl-CYoMK+44s/E@public.gmane.org>
2008-09-30  6:04                                       ` David Gibson
     [not found]                                         ` <20080930060418.GD18695-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
2008-09-30 15:46                                           ` Jon Loeliger
2008-09-30 14:55                                   ` [PATCH 8/9 V3] Add documentation for the new DTS language Grant Likely
     [not found]                                     ` <20080930145537.GJ18313-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
2008-10-01  3:46                                       ` David Gibson
     [not found]                                         ` <20081001034656.GF30810-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
2008-10-01  4:01                                           ` Warner Losh
     [not found]                                             ` <20080930.220151.41675821.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org>
2008-10-01  4:22                                               ` David Gibson
2008-10-01 15:26                                           ` Scott Wood
     [not found]                                             ` <48E396A3.809-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
2008-10-01 15:43                                               ` Warner Losh
     [not found]                                                 ` <20081001.094306.71131107.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org>
2008-10-02  1:20                                                   ` David Gibson
2008-10-02  1:18                                               ` David Gibson
     [not found]                                                 ` <20081002011800.GI25598-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
2008-10-02 15:22                                                   ` Scott Wood
     [not found]                                                     ` <20081002152242.GB22258-VKaLA/mbEU932VTgPCOETVjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
2008-10-02 16:11                                                       ` David Gibson
     [not found]                                                         ` <20081002161150.GA14351-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
2008-10-02 17:22                                                           ` Scott Wood
     [not found]                                                             ` <48E5036D.9040509-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
2008-10-03  2:24                                                               ` David Gibson
     [not found]                                                                 ` <20081003022424.GG3002-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
2008-10-03 15:27                                                                   ` Scott Wood
     [not found]                                                                     ` <20081003152700.GA9115-VKaLA/mbEU932VTgPCOETVjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
2008-10-04  4:52                                                                       ` David Gibson
2008-10-02 19:50                                                       ` M. Warner Losh
     [not found]                                                         ` <20081002.135004.1723231860.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org>
2008-10-02 20:46                                                           ` Jon Loeliger
2008-10-03  0:23                                                             ` David Gibson
2008-10-03  0:23                                                           ` David Gibson
     [not found]                                                             ` <20081003002337.GB3002-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
2008-10-03  1:17                                                               ` M. Warner Losh
     [not found]                                                                 ` <20081002.191705.-108805802.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org>
2008-10-03  4:38                                                                   ` David Gibson
2010-02-20 16:13                                           ` Grant Likely
     [not found]                                             ` <fa686aa41002200813o3fea9a34s198be367ad81b367-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-02-21  6:30                                               ` John Williams
2010-02-22  1:30                                               ` David Gibson
2010-02-22  6:26                                                 ` Grant Likely
     [not found]                                                   ` <fa686aa41002212226i4c83376cn8d88a045dd13fe00-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-02-22 16:13                                                     ` Yoder Stuart-B08248
     [not found]                                                       ` <9696D7A991D0824DBA8DFAC74A9C5FA305B2021A-ofAVchDyotYzzZk0BCvKg5jmvxFtTJ+o0e7PPNI6Mm0@public.gmane.org>
2010-02-22 21:59                                                         ` Grant Likely
     [not found]                                                           ` <fa686aa41002221359m4d857e4cn3a1c56c32a24d21d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-02-22 22:52                                                             ` Scott Wood
2010-02-23  2:04                                                             ` David Gibson
2010-03-01 19:15                                                             ` Grant Likely
     [not found]                                                               ` <fa686aa41003011115m1bb0b644g5014340f6c312ee9-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-03-01 19:38                                                                 ` Scott Wood
2010-03-01 20:30                                                                 ` Stephen Neuendorffer
     [not found]                                                                   ` <4B8C2C4C.8070901@freescale <4B8C44C8.6000105@freescale.com>
     [not found]                                                                     ` <4B8C44C8.6000105-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
2010-03-01 22:56                                                                       ` Stephen Neuendorffer
     [not found]                                                                         ` <7c070166-6cd5-48e4-ab8e-cb062e3dbb00-RaUQJvECHiusiP+nND6G/7jjLBE8jN/0@public.gmane.org>
2010-03-02  1:22                                                                           ` David Gibson
2010-03-02  0:10                                                                       ` Grant Likely
2010-03-02  1:19                                                                       ` David Gibson
2010-03-02  2:10                                                                         ` Grant Likely
     [not found]                                                                           ` <fa686aa41003011810w2e7b6278t6aaaf192f8d7c8c1-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-03-02  2:16                                                                             ` Grant Likely
     [not found]                                                                               ` <fa686aa41003011816j534bf335o6fafe6f1c4a63436-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-03-02  4:20                                                                                 ` David Gibson
     [not found]                                                       ` <fa686aa41002221359m4d857e4cn3a1c56c32a24d21d@mail <4288fc0b-79a4-42fd-9e77-573dbad79210@SG2EHSMHS004.ehs.local>
     [not found]                                                         ` <4288fc0b-79a4-42fd-9e77-573dbad79210-RaUQJvECHiuXHCJdrdq+zrjjLBE8jN/0@public.gmane.org>
2010-03-01 21:06                                                           ` Scott Wood
     [not found]                                                             ` <4B8C2C4C.8070901-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
2010-03-01 22:03                                                               ` Stephen Neuendorffer
     [not found]                                                                 ` <4d16ecf4-27b2-4c73-a3be-5b2a8ff95820-+Ck8Kgl/v0+J1bAq5m18RLjjLBE8jN/0@public.gmane.org>
2010-03-01 22:25                                                                   ` Grant Likely
     [not found]                                                                     ` <fa686aa41003011425i734ee434m95b62d57a271bd1f-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-03-02  1:11                                                                       ` David Gibson
2010-03-01 22:18                                                               ` Grant Likely
     [not found]                                                                 ` <fa686aa41003011418x339884c9md61c49948b31a8d1-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-03-01 22:26                                                                   ` Stephen Neuendorffer
     [not found]                                                                     ` <1012f9aa-1642-41ab-b8cd-a4ab4a7b269e-+Ck8Kgl/v0989VwWyyPjfbjjLBE8jN/0@public.gmane.org>
2010-03-02  0:03                                                                       ` Grant Likely
     [not found]                                                                         ` <fa686aa41003011603w12c0a7f1y88b5fc7a008af1d5-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-03-02  0:13                                                                           ` Stephen Neuendorffer
     [not found]                                                                             ` <f9885aa5-5c11-4118-9980-f17378d7cbd5-RaUQJvECHiuXHCJdrdq+zrjjLBE8jN/0@public.gmane.org>
2010-03-02  1:25                                                                               ` David Gibson
2010-03-02  2:08                                                                               ` Grant Likely
     [not found]                                                                                 ` <fa686aa41003011808h586e3dc3x11ef14af9c6e5fb8-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-03-02 17:06                                                                                   ` Scott Wood
2010-03-01 22:50                                                                   ` Scott Wood
2010-03-01 21:49                                                           ` Grant Likely
     [not found]                                                             ` <fa686aa41003011349i367a423cx2c59953e6afc9b75-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-03-01 22:15                                                               ` Mitch Bradley
     [not found]                                                                 ` <4B8C3C78.5010206-D5eQfiDGL7eakBO8gow8eQ@public.gmane.org>
2010-03-01 23:33                                                                   ` Grant Likely
     [not found]                                                                     ` <fa686aa41003011533x3d2d00abyb8d7cf33344a3bde-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-03-02  3:59                                                                       ` David Gibson
2010-03-01 22:17                                                               ` Stephen Neuendorffer
     [not found]                                                                 ` <72f497af-412c-4a05-90c2-5df0be00d93f-+Ck8Kgl/v09CYczPSvLbDrjjLBE8jN/0@public.gmane.org>
2010-03-01 23:42                                                                   ` Grant Likely
2010-03-02 23:12                                                                   ` David Gibson
2010-03-03 16:18                                                                     ` Grant Likely
2010-02-23  1:47                                                     ` David Gibson
2010-02-23  2:17                                                       ` Grant Likely
     [not found]                                                         ` <fa686aa41002221817s5f15dc4cy5ab873a61de2cb2f-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-02-23  4:10                                                           ` David Gibson
2008-10-02  8:25                               ` [PATCH 7/9 V3] Introduce " David Gibson
2008-09-30  6:03                   ` [PATCH 4/9 V3] Add header files for new Internal Representation form David Gibson
2008-09-30  6:00               ` [PATCH 3/9 V3] Enhance source position implementation David Gibson
2008-09-30  5:57       ` [PATCH 1/9 V3] Remove support for the legacy DTS source file format David Gibson
     [not found]         ` <20080930055716.GA18695-787xzQ0H9iRg7VrjXcPTGA@public.gmane.org>
2008-09-30 16:30           ` Scott Wood
     [not found]             ` <48E2541B.1000801-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
2008-10-01  1:26               ` David Gibson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.