initialization

SVN=128115
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index ac724a0..601acf5 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -877,3 +877,105 @@
 	s->forwtype = t;
 	return t;
 }
+
+// hand-craft the following initialization code
+//	var	init_%%%_done bool;			(1)
+//	func	init_%%%_function()			(2)
+//		if init_%%%_done { return }		(3)
+//		init_%%%_done = true;			(4)
+//		for Y {	
+//			init_%%%_function()		(5)
+//		}
+//		if true { <init stmts> }		(6)
+//		init()	// if any			(7)
+//		return					(8)
+//	}
+//	export	init_%%%_function			(9)
+
+void
+fninit(Node *n)
+{
+	Node *done, *any, *init;
+	Node *a, *b, *r;
+	Iter iter;
+	ulong h;
+	Sym *s;
+
+	r = N;
+
+	// (1)
+	vargen++;
+	snprint(namebuf, sizeof(namebuf), "init_%.3ld_done", vargen);
+	done = newname(lookup(namebuf));
+	addvar(done, types[TBOOL], PEXTERN);
+
+	// (2)
+
+	maxarg = 0;
+	stksize = 0;
+
+	vargen++;
+	h = vargen;
+	if(strcmp(package, "main") == 0)
+		h = 999;
+	snprint(namebuf, sizeof(namebuf), "init_%.3ld_function", h);
+	b = nod(ODCLFUNC, N, N);
+	b->nname = newname(lookup(namebuf));
+	b->type = functype(N, N, N);
+	funchdr(b);
+
+	// (3)
+	a = nod(OIF, N, N);
+	a->ntest = done;
+	a->nbody = nod(ORETURN, N, N);
+	r = list(r, a);
+
+	// (4)
+	a = nod(OAS, done, booltrue);
+	r = list(r, a);
+
+	// (5)
+	init = N;
+	for(h=0; h<NHASH; h++)
+	for(s = hash[h]; s != S; s = s->link) {
+		if(s->name[0] != 'i')
+			continue;
+		if(strstr(s->name, "init") == nil)
+			continue;
+		if(strstr(s->name, "_function") == nil) {
+			if(strcmp(s->name, "init") == 0)
+				init = s->oname;
+			continue;
+		}
+		if(s->oname == N)
+			continue;
+
+		a = nod(OCALL, s->oname, N);
+		r = list(r, a);
+	}
+
+	// (6)
+	r = list(r, n);
+
+	// (7)
+	if(init != N) {
+		a = nod(OCALL, init, N);
+		r = list(r, a);
+	}
+
+	// (8)
+	a = nod(ORETURN, N, N);
+	r = list(r, a);
+
+	// (9)
+	a = nod(OEXPORT, N, N);
+	a->sym = b->nname->sym;
+	markexport(a);
+
+	b->nbody = rev(r);
+//dump("b", b);
+//dump("r", b->nbody);
+
+	popdcl();
+	compile(b);
+}
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index ffc75ad..547be9d 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -542,6 +542,7 @@
 Type*	newtype(Sym*);
 Type*	oldtype(Sym*);
 Type*	forwdcl(Sym*);
+void	fninit(Node*);
 
 /*
  *	export.c
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 0b0e425c..672e53a 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -66,6 +66,7 @@
 	{
 		if(debug['f'])
 			frame(1);
+		fninit($4);
 		testdclstack();
 	}
 
@@ -138,12 +139,17 @@
 |	LEXPORT export_list_r
 	{
 		markexport(rev($2));
+		$$ = N;
 	}
 |	LEXPORT '(' export_list_r ')'
 	{
 		markexport(rev($3));
+		$$ = N;
 	}
 |	xfndcl
+	{
+		$$ = N;
+	}
 |	';'
 	{
 		$$ = N;
@@ -168,9 +174,9 @@
 	}
 |	LCONST '(' constdcl_list_r osemi ')'
 	{
-		$$ = N;
 		iota = 0;
 		lastconst = N;
+		$$ = N;
 	}
 |	LTYPE Atypedcl
 	{
@@ -1089,7 +1095,7 @@
 	xdcl
 |	xdcl_list_r xdcl
 	{
-		$$ = nod(OLIST, $1, $2);
+		$$ = list($1, $2);
 	}
 
 vardcl_list_r:
diff --git a/src/runtime/rt0_amd64.s b/src/runtime/rt0_amd64.s
index aad67cb..5544833 100644
--- a/src/runtime/rt0_amd64.s
+++ b/src/runtime/rt0_amd64.s
@@ -33,6 +33,7 @@
 	MOVQ	24(SP), AX		// copy argv
 	MOVQ	AX, 8(SP)
 	CALL	args(SB)
+	CALL	mainĀ·init_999_function(SB) // initialization
 
 	// create a new goroutine to start program