Initial label support.  Also switch to glr-parser mode and get rid of
hacks that were necessary without it.
diff --git a/Makefile b/Makefile
index 1dca00b..f9a1050 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,10 @@
 TARGETS = dtc
 CFLAGS = -Wall -g
 
+BISON = bison
+
 OBJS = dtc.o livetree.o flattree.o data.o treesource.o fstree.o \
-	y.tab.o lex.yy.o
+	dtc-parser.tab.o lex.yy.o
 
 all: $(TARGETS)
 
@@ -11,13 +13,13 @@
 
 $(OBJS): dtc.h
 
-y.tab.c y.tab.h: dtc-parser.y
-	$(YACC) -d $<
+dtc-parser.tab.c dtc-parser.tab.h dtc-parser.output: dtc-parser.y
+	$(BISON) -d -v $<
 
 lex.yy.c: dtc-lexer.l
 	$(LEX) $<
 
-lex.yy.o: lex.yy.c y.tab.h
+lex.yy.o: lex.yy.c dtc-parser.tab.h
 
 dtc-parser.c:	dtc-lexer.c
 
diff --git a/TODO b/TODO
index 7136979..3342474 100644
--- a/TODO
+++ b/TODO
@@ -4,8 +4,6 @@
 	* Report line/column numbers for syntax errors
 	* Better categorization of errors into severity levels
 - Generate mem reserve map
-	* Command line options to place a number of blank entries to be
-	  filled in by bootloader
 	* memory reserve section in source
 - Testsuite
 - Actually number releases, revision control, all that kind of jazz
diff --git a/comment-test.dts b/comment-test.dts
index b8d5637..0174347 100644
--- a/comment-test.dts
+++ b/comment-test.dts
@@ -31,5 +31,8 @@
 	/** try this */
 	prop9;
 	/* and this **/
+	prop10;
+	child /* finally */ {
+	};
 };
 /* final comment */
diff --git a/dtc-lexer.l b/dtc-lexer.l
index 02283a9..4819e54 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -32,9 +32,9 @@
 %{
 #include "dtc.h"
 
-#include "y.tab.h"
+#include "dtc-parser.tab.h"
 
-#undef LEXDEBUG	1
+/*#define LEXDEBUG	1 */
 
 %}
 
@@ -83,14 +83,6 @@
 			return ']';
 		}
 
-{PROPCHAR}+(@{UNITCHAR}+)?/{WS}*\{ {
-#ifdef LEXDEBUG
-			fprintf(stderr, "NodeName: %s\n", yytext);
-#endif
-			yylval.str = strdup(yytext);
-			return DT_NODENAME;
-		}
-
 {PROPCHAR}+	{
 #ifdef LEXDEBUG
 			fprintf(stderr, "PropName: %s\n", yytext);
@@ -99,6 +91,23 @@
 			return DT_PROPNAME;
 		}
 
+{PROPCHAR}+(@{UNITCHAR}+)? {
+#ifdef LEXDEBUG
+			fprintf(stderr, "NodeName: %s\n", yytext);
+#endif
+			yylval.str = strdup(yytext);
+			return DT_NODENAME;
+		}
+
+
+[a-zA-Z_][a-zA-Z0-9_]*:	{
+#ifdef LEXDEBUG
+			fprintf(stderr, "Label: %s\n", yytext);
+#endif
+			yylval.str = strdup(yytext);
+			yylval.str[yyleng-1] = '\0';
+			return DT_LABEL;
+		}
 
 <*>{WS}+	/* eat whitespace */
 
diff --git a/dtc-parser.y b/dtc-parser.y
index f177fb7..785acd1 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -47,6 +47,7 @@
 %token <byte> DT_BYTE
 %token <data> DT_STRING
 %token <str> DT_UNIT
+%token <str> DT_LABEL
 
 %type <data> propdata
 %type <data> celllist
@@ -57,12 +58,16 @@
 %type <node> nodedef
 %type <node> subnode
 %type <nodelist> subnodes
+%type <str> label
+%type <str> nodename
+
+%glr-parser
 
 %%
 
 devicetree:	{
 			assert(device_tree == NULL);
-		} '/' nodedef { device_tree = name_node($3, ""); }
+		} '/' nodedef { device_tree = name_node($3, "", NULL); }
 	;
 
 nodedef:	'{' proplist subnodes '}' ';' {
@@ -78,11 +83,11 @@
 		}
 	;
 
-propdef:	DT_PROPNAME '=' propdata ';' {
-			$$ = build_property($1, $3);
+propdef:	label DT_PROPNAME '=' propdata ';' {
+			$$ = build_property($2, $4, $1);
 		}
-	|	DT_PROPNAME ';' {
-			$$ = build_empty_property($1);
+	|	label DT_PROPNAME ';' {
+			$$ = build_empty_property($2, $1);
 		}
 	;
 
@@ -105,7 +110,15 @@
 	|	/* empty */ { $$ = NULL; }
 	;
 
-subnode:	DT_NODENAME nodedef { $$ = name_node($2, $1); }
+subnode:	label nodename nodedef { $$ = name_node($3, $2, $1); }
+	;
+
+nodename:	DT_NODENAME	{ $$ = $1; }
+	|	DT_PROPNAME	{ $$ = $1; }
+	;
+
+label:		DT_LABEL	{ $$ = $1; }
+	|	/* empty */	{ $$ = NULL; }
 	;
 
 %%
diff --git a/dtc.h b/dtc.h
index 75a1ac5..cbd5eb7 100644
--- a/dtc.h
+++ b/dtc.h
@@ -115,6 +115,8 @@
 	struct data val;
 
 	struct property *next;
+
+	char *label;
 };
 
 struct node {
@@ -130,6 +132,8 @@
 
 	cell_t phandle;
 	int addr_cells, size_cells;
+
+	char *label;
 };
 
 #define for_each_property(n, p) \
@@ -138,12 +142,12 @@
 #define for_each_child(n, c)	\
 	for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
 
-struct property *build_property(char *name, struct data val);
-struct property *build_empty_property(char *name);
+struct property *build_property(char *name, struct data val, char *label);
+struct property *build_empty_property(char *name, char *label);
 struct property *chain_property(struct property *first, struct property *list);
 
 struct node *build_node(struct property *proplist, struct node *children);
-struct node *name_node(struct node *node, char *name);
+struct node *name_node(struct node *node, char *name, char *label);
 struct node *chain_node(struct node *first, struct node *list);
 
 void add_property(struct node *node, struct property *prop);
diff --git a/flattree.c b/flattree.c
index 76d7e5d..f5b7ca1 100644
--- a/flattree.c
+++ b/flattree.c
@@ -80,9 +80,9 @@
 	void (*string)(void *, char *, int);
 	void (*align)(void *, int);
 	void (*data)(void *, struct data);
-	void (*beginnode)(void *);
-	void (*endnode)(void *);
-	void (*property)(void *);
+	void (*beginnode)(void *, char *);
+	void (*endnode)(void *, char *);
+	void (*property)(void *, char *);
 };
 
 static void bin_emit_cell(void *e, cell_t val)
@@ -117,17 +117,17 @@
 	*dtbuf = data_append_data(*dtbuf, d.val, d.len);
 }
 
-static void bin_emit_beginnode(void *e)
+static void bin_emit_beginnode(void *e, char *label)
 {
 	bin_emit_cell(e, OF_DT_BEGIN_NODE);
 }
 
-static void bin_emit_endnode(void *e)
+static void bin_emit_endnode(void *e, char *label)
 {
 	bin_emit_cell(e, OF_DT_END_NODE);
 }
 
-static void bin_emit_property(void *e)
+static void bin_emit_property(void *e, char *label)
 {
 	bin_emit_cell(e, OF_DT_PROP);
 }
@@ -142,6 +142,13 @@
 	.property = bin_emit_property,	
 };
 
+void emit_label(FILE *f, char *prefix, char *label)
+{
+	fprintf(f, "\t.globl\t%s_%s\n", prefix, label);
+	fprintf(f, "%s_%s:\n", prefix, label);
+	fprintf(f, "_%s_%s:\n", prefix, label);
+}
+
 static void asm_emit_cell(void *e, cell_t val)
 {
 	FILE *f = e;
@@ -199,24 +206,36 @@
 	assert(off == d.len);
 }
 
-static void asm_emit_beginnode(void *e)
+static void asm_emit_beginnode(void *e, char *label)
 {
 	FILE *f = e;
 
+	if (label) {
+		fprintf(f, "\t.globl\t%s\n", label);
+		fprintf(f, "%s:\n", label);
+	}
 	fprintf(f, "\t.long\tOF_DT_BEGIN_NODE\n");
 }
 
-static void asm_emit_endnode(void *e)
+static void asm_emit_endnode(void *e, char *label)
 {
 	FILE *f = e;
 
 	fprintf(f, "\t.long\tOF_DT_END_NODE\n");
+	if (label) {
+		fprintf(f, "\t.globl\t%s_end\n", label);
+		fprintf(f, "%s_end:\n", label);
+	}
 }
 
-static void asm_emit_property(void *e)
+static void asm_emit_property(void *e, char *label)
 {
 	FILE *f = e;
 
+	if (label) {
+		fprintf(f, "\t.globl\t%s\n", label);
+		fprintf(f, "%s:\n", label);
+	}
 	fprintf(f, "\t.long\tOF_DT_PROP\n");
 }
 
@@ -253,7 +272,7 @@
 	struct node *child;
 	int seen_name_prop = 0;
 
-	emit->beginnode(etarget);
+	emit->beginnode(etarget, tree->label);
 
 	if (vi->flags & FTF_FULLPATH)
 		emit->string(etarget, tree->fullpath, 0);
@@ -270,7 +289,7 @@
 
 		nameoff = stringtable_insert(strbuf, prop->name);
 
-		emit->property(etarget);
+		emit->property(etarget, prop->label);
 		emit->cell(etarget, prop->val.len);
 		emit->cell(etarget, nameoff);
 
@@ -282,7 +301,7 @@
 	}
 
 	if ((vi->flags & FTF_NAMEPROPS) && !seen_name_prop) {
-		emit->property(etarget);
+		emit->property(etarget, NULL);
 		emit->cell(etarget, tree->basenamelen+1);
 		emit->cell(etarget, stringtable_insert(strbuf, "name"));
 
@@ -296,7 +315,7 @@
 		flatten_tree(child, emit, etarget, strbuf, vi);
 	}
 
-	emit->endnode(etarget);
+	emit->endnode(etarget, tree->label);
 }
 
 static void make_bph(struct boot_param_header *bph,
@@ -377,13 +396,6 @@
 	}
 }
 
-void emit_label(FILE *f, char *prefix, char *label)
-{
-	fprintf(f, "\t.globl\t%s_%s\n", prefix, label);
-	fprintf(f, "%s_%s:\n", prefix, label);
-	fprintf(f, "_%s_%s:\n", prefix, label);
-}
-
 void write_dt_asm(FILE *f, struct node *tree, int version, int reservenum)
 {
 	struct version_info *vi = NULL;
@@ -566,7 +578,7 @@
 
 	val = flat_read_data(dtbuf, proplen);
 
-	return build_property(name, val);
+	return build_property(name, val, NULL);
 }
 
 static char *nodename_from_path(char *ppath, char *cpath)
diff --git a/fstree.c b/fstree.c
index 5fe8e40..0b85aa8 100644
--- a/fstree.c
+++ b/fstree.c
@@ -60,7 +60,8 @@
 			} else {
 				prop = build_property(strdup(de->d_name),
 						      data_copy_file(pfile,
-								     st.st_size));
+								     st.st_size),
+						      NULL);
 				add_property(tree, prop);
 				fclose(pfile);
 			}
@@ -68,7 +69,8 @@
 			struct node *newchild;
 
 			newchild = read_fstree(tmpnam);
-			newchild = name_node(newchild, strdup(de->d_name));
+			newchild = name_node(newchild, strdup(de->d_name),
+					     NULL);
 			add_child(tree, newchild);
 		}
 
@@ -83,7 +85,7 @@
 	struct node *tree;
 
 	tree = read_fstree(dirname);
-	tree = name_node(tree, "");
+	tree = name_node(tree, "", NULL);
 
 	fill_fullpaths(tree, "");
 
diff --git a/livetree.c b/livetree.c
index 227b5e8..04f5228 100644
--- a/livetree.c
+++ b/livetree.c
@@ -24,7 +24,7 @@
  * Tree building functions
  */
 
-struct property *build_property(char *name, struct data val)
+struct property *build_property(char *name, struct data val, char *label)
 {
 	struct property *new = xmalloc(sizeof(*new));
 
@@ -33,10 +33,12 @@
 
 	new->next = NULL;
 
+	new->label = label;
+
 	return new;
 }
 
-struct property *build_empty_property(char *name)
+struct property *build_empty_property(char *name, char *label)
 {
 	struct property *new = xmalloc(sizeof(*new));
 
@@ -46,6 +48,8 @@
 
 	new->next = NULL;
 
+	new->label = label;
+
 	return new;
 }
 
@@ -74,11 +78,14 @@
 	return new;
 }
 
-struct node *name_node(struct node *node, char *name)
+struct node *name_node(struct node *node, char *name, char * label)
 {
 	assert(node->name == NULL);
 
 	node->name = name;
+
+	node->label = label;
+
 	return node;
 }
 
diff --git a/test.dts b/test.dts
index bda4288..dce7c52 100644
--- a/test.dts
+++ b/test.dts
@@ -2,9 +2,9 @@
 	model = "MyBoardName";
 	compatible = "MyBoardFamilyName";
 	#address-cells = <2>;
-	#size-cells = <2>;
+	label1: #size-cells = <2>;
 
-	cpus {
+	label2: cpus {
 		linux,phandle = <1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -15,12 +15,14 @@
 			clock-frequency = <5f5e1000>;
 			linux,boot-cpu;
 			linux,phandle = <2>;
+			i-cache-size = <10000>;
+			d-cache-size = <8000>;
 		};
 
 	};
 
 	randomnode {
-		string = "\xff\0stuffstuff\t\t\t\n\n\n\n";
+		string = "\xff\0stuffstuff\t\t\t\n\n\n";
 		blob = [0a 0b 0c 0d de ea ad be ef];
 	};