--- src/main.c.orig	2007-10-17 16:49:04.000000000 +0200
+++ src/main.c	2008-01-21 00:53:57.000000000 +0100
@@ -92,11 +92,16 @@
 static gboolean special_array[SPECIAL_LAST] = {0};
 static gboolean any_special = FALSE;
 
+static gboolean need_constructor = FALSE;
+static Method * user_constructor = NULL;
+
 static gboolean need_dispose = FALSE;
 static Method * dispose_handler = NULL;
+static Method * user_dispose_method = NULL;
 
 static gboolean need_finalize = FALSE;
 static Method * finalize_handler = NULL;
+static Method * user_finalize_method = NULL;
 
 FILE *out = NULL;
 FILE *outh = NULL;
@@ -269,6 +274,9 @@
 			
 			if(m->method == INIT_METHOD ||
 			   m->method == CLASS_INIT_METHOD ||
+			   m->method == CONSTRUCTOR_METHOD ||
+			   m->method == DISPOSE_METHOD ||
+			   m->method == FINALIZE_METHOD ||
 			   m->method == OVERRIDE_METHOD)
 				continue;
 
@@ -291,6 +299,9 @@
 			
 			if(m->method == INIT_METHOD ||
 			   m->method == CLASS_INIT_METHOD ||
+			   m->method == CONSTRUCTOR_METHOD ||
+			   m->method == DISPOSE_METHOD ||
+			   m->method == FINALIZE_METHOD ||
 			   m->method == OVERRIDE_METHOD)
 				continue;
 
@@ -330,6 +341,9 @@
 			
 			if(m->method == INIT_METHOD ||
 			   m->method == CLASS_INIT_METHOD ||
+			   m->method == CONSTRUCTOR_METHOD ||
+			   m->method == DISPOSE_METHOD ||
+			   m->method == FINALIZE_METHOD ||
 			   m->method == OVERRIDE_METHOD)
 				continue;
 
@@ -543,7 +557,10 @@
 		g_free(s);
 	} else if(m->scope == PRIVATE_SCOPE ||
 		  m->method == INIT_METHOD ||
-		  m->method == CLASS_INIT_METHOD) {
+		  m->method == CLASS_INIT_METHOD || 
+		  m->method == CONSTRUCTOR_METHOD ||
+		  m->method == DISPOSE_METHOD ||
+		  m->method == FINALIZE_METHOD) {
 		print_method(out, "static ", "", "", " ", "",
 			     no_gnu?";\n":" G_GNUC_UNUSED;\n",
 			     m, FALSE, FALSE, TRUE, FALSE, FALSE);
@@ -629,66 +646,68 @@
 	}
 }
 
-static void
-find_dispose(const Class *cl)
+static Method *
+find_method(const Class *cl, int method, const char *id)
 {
 	GList *li;
 
-	dispose_handler = NULL;
 	for(li=cl->nodes;li;li=g_list_next(li)) {
 		Node *n = li->data;
 		if(n->type == METHOD_NODE) {
 			Method *m = (Method *)n;
-			if(m->method == OVERRIDE_METHOD &&
-			   strcmp(m->id, "dispose")==0) {
-				if(strcmp(m->otype, "G:Object") != 0) {
-					error_print(GOB_ERROR, m->line_no,
-						    "dispose method override "
-						    "of class other then "
-						    "G:Object");
-				}
-				if(g_list_length(m->args) != 1) {
-					error_print(GOB_ERROR, m->line_no,
-						    "dispose method override "
-						    "with more then one "
-						    "parameter");
-				}
-				dispose_handler = m;
-				break;
-			}
+			if (m->method == method
+			    && (id == NULL || strcmp(m->id, id)==0))
+				return m;
 		}
 	}
+
+	return NULL;
 }
 
 static void
-find_finalize(const Class *cl)
+find_constructor(const Class *cl)
 {
-	GList *li;
+	user_constructor = find_method(cl, CONSTRUCTOR_METHOD, NULL);
+}
 
-	finalize_handler = NULL;
-	for(li=cl->nodes;li;li=g_list_next(li)) {
-		Node *n = li->data;
-		if(n->type == METHOD_NODE) {
-			Method *m = (Method *)n;
-			if(m->method == OVERRIDE_METHOD &&
-			   strcmp(m->id, "finalize")==0) {
-				if(strcmp(m->otype, "G:Object") != 0) {
-					error_print(GOB_ERROR, m->line_no,
-						    "finalize method override "
-						    "of class other then "
-						    "G:Object");
-				}
-				if(g_list_length(m->args) != 1) {
-					error_print(GOB_ERROR, m->line_no,
-						    "finalize method override "
-						    "with more then one "
-						    "parameter");
-				}
-				finalize_handler = m;
-				break;
-			}
-		}
+static void
+find_dispose(const Class *cl)
+{
+	dispose_handler = find_method(cl, OVERRIDE_METHOD, "dispose");
+	if (dispose_handler != NULL) {
+		if(strcmp(dispose_handler->otype, "G:Object") != 0)
+			error_print(GOB_ERROR, dispose_handler->line_no,
+				    "dispose method override "
+				    "of class other then "
+				    "G:Object");
+		if(g_list_length(dispose_handler->args) != 1)
+			error_print(GOB_ERROR, dispose_handler->line_no,
+				    "dispose method override "
+				    "with more then one "
+				    "parameter");
 	}
+
+	user_dispose_method = find_method(cl, DISPOSE_METHOD, NULL);
+}
+
+static void
+find_finalize(const Class *cl)
+{
+	finalize_handler = find_method(cl, OVERRIDE_METHOD, "finalize");
+	if (finalize_handler != NULL) {
+		if(strcmp(finalize_handler->otype, "G:Object") != 0)
+			error_print(GOB_ERROR, finalize_handler->line_no,
+				    "finalize method override "
+				    "of class other then "
+				    "G:Object");
+		if(g_list_length(finalize_handler->args) != 1)
+			error_print(GOB_ERROR, finalize_handler->line_no,
+				    "finalize method override "
+				    "with more then one "
+				    "parameter");
+	}
+
+	user_finalize_method = find_method(cl, FINALIZE_METHOD, NULL);
 }
 
 
@@ -2118,6 +2137,33 @@
 }
 
 static void
+add_constructor (Class *c)
+{
+	out_printf(out, "\nstatic GObject *\n"
+		   "___constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties)\n"
+		   "{\n");
+	out_printf(out,
+		   "#define __GOB_FUNCTION__ \"%s::constructor\"\n",
+		   c->otype);
+
+	out_printf(out, "\tGObject *obj_self;\n");
+	out_printf(out, "\t%s *self;\n", typebase);
+
+	out_printf(out, "\tobj_self = G_OBJECT_CLASS (parent_class)->constructor (type, n_construct_properties, construct_properties);\n");
+	out_printf(out, "\tself = %s (obj_self);\n", macrobase);
+
+	if (user_constructor->line_no > 0)
+		out_addline_infile (out, user_constructor->line_no);
+	out_printf (out, "\t%s_constructor (self);\n", funcbase);
+	if (user_constructor->line_no > 0)
+		out_addline_outfile (out);
+
+	out_printf(out, "\treturn obj_self;\n");
+	out_printf(out, "}\n"
+		   "#undef __GOB_FUNCTION__\n\n");
+}
+
+static void
 add_dispose (Class *c)
 {
 	out_printf(out, "\nstatic void\n"
@@ -2127,7 +2173,7 @@
 		   "#define __GOB_FUNCTION__ \"%s::dispose\"\n",
 		   c->otype);
 
-	if (unreftors > 0) {
+	if (unreftors > 0 || user_dispose_method != NULL) {
 		out_printf (out, "\t%s *self%s = %s (obj_self);\n",
 			    typebase,
 			    ! no_gnu ? " G_GNUC_UNUSED" : "",
@@ -2143,6 +2189,14 @@
 		if (dispose_handler->line_no > 0)
 			out_addline_outfile (out);
 	} else {
+		if (user_dispose_method != NULL) {
+			if (user_dispose_method->line_no > 0)
+				out_addline_infile (out, user_dispose_method->line_no);
+			out_printf (out, "\t%s_dispose (self);\n", funcbase);
+			if (user_dispose_method->line_no > 0)
+				out_addline_outfile (out);
+		}
+
 		out_printf (out,
 			    "\tif (G_OBJECT_CLASS (parent_class)->dispose) \\\n"
 			    "\t\t(* G_OBJECT_CLASS (parent_class)->dispose) (obj_self);\n");
@@ -2178,7 +2232,8 @@
 		   c->otype);
 
 	if (privates > 0 ||
-	    destructors > 0) {
+	    destructors > 0 ||
+	    user_finalize_method != NULL) {
 		const char *unused = "";
 		if ( ! no_gnu)
 			unused = " G_GNUC_UNUSED";
@@ -2202,6 +2257,14 @@
 		if(finalize_handler->line_no > 0)
 			out_addline_outfile(out);
 	} else {
+		if (user_finalize_method != NULL) {
+			if (user_finalize_method->line_no > 0)
+				out_addline_infile (out, user_finalize_method->line_no);
+			out_printf (out, "\t%s_finalize (self);\n", funcbase);
+			if (user_finalize_method->line_no > 0)
+				out_addline_outfile (out);
+		}
+
 		out_printf(out,
 			   "\tif(G_OBJECT_CLASS(parent_class)->finalize) \\\n"
 			   "\t\t(* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);\n");
@@ -2381,6 +2444,9 @@
 
 			/* if there are no handlers for these things, we
 			 * need to set them up here */
+			if(need_constructor)
+				out_printf(out, "\tg_object_class->constructor "
+					   "= ___constructor;\n");
 			if(need_dispose && !dispose_handler)
 				out_printf(out, "\tg_object_class->dispose "
 					   "= ___dispose;\n");
@@ -3064,6 +3130,15 @@
 		/* the outfile line was added above */
 		out_printf(out, "#undef PARENT_HANDLER\n");
 		break;
+	case CONSTRUCTOR_METHOD:
+	case DISPOSE_METHOD:
+	case FINALIZE_METHOD:
+		if(m->line_no > 0)
+			out_addline_infile(out, m->line_no);
+		print_method(out, "static ", "\n", "", " ", "", "\n",
+			     m, FALSE, FALSE, TRUE, FALSE, FALSE);
+		print_method_body(m, TRUE, TRUE);
+		/* the outfile line was added above */
 	default:
 		break;
 	}
@@ -3633,6 +3708,9 @@
 			    funcbase);
 	}
 
+	if (need_constructor)
+		add_constructor (c);
+
 	if (need_dispose)
 		add_dispose (c);
 
@@ -4441,15 +4519,24 @@
 
 	make_bases ();
 	make_inits ((Class *)class);
-	if(unreftors > 0) {
+
+	find_constructor ((Class *)class);
+	if (user_constructor != NULL)
+		need_constructor = TRUE;
+
+	find_dispose ((Class *)class);
+	if (unreftors > 0 ||
+	    dispose_handler != NULL ||
+	    user_dispose_method != NULL)
 		need_dispose = TRUE;
-		find_dispose ((Class *)class);
-	}
+
+	find_finalize ((Class *)class);
 	if (destructors > 0 ||
-	    privates > 0) {
+	    privates > 0 ||
+	    user_finalize_method != NULL) {
 		need_finalize = TRUE;
-		find_finalize ((Class *)class);
 	}
+
 	check_bad_symbols ((Class *)class);
 	check_duplicate_symbols ((Class *)class);
 	check_duplicate_overrides ((Class *)class);
--- src/parse.y.orig	2007-03-09 18:46:14.000000000 +0100
+++ src/parse.y	2008-01-21 00:53:13.000000000 +0100
@@ -155,7 +155,11 @@
 
 	g_assert(scope != CLASS_SCOPE);
        
-	if(method == INIT_METHOD || method == CLASS_INIT_METHOD) {
+	if(method == INIT_METHOD
+	   || method == CLASS_INIT_METHOD
+	   || method == CONSTRUCTOR_METHOD
+	   || method == DISPOSE_METHOD
+	   || method == FINALIZE_METHOD) {
 		type = (Type *)node_new (TYPE_NODE,
 					 "name", "void",
 					 NULL);
@@ -1767,13 +1771,29 @@
 				push_function(NO_SCOPE, CLASS_INIT_METHOD, NULL,
 					      $<id>1, $<cbuf>5, $<line>2,
 					      ccode_line, FALSE, NULL);
+			} else if(strcmp($<id>1, "constructor")==0) {
+				push_init_arg($<id>3, FALSE);
+				push_function(NO_SCOPE, CONSTRUCTOR_METHOD, NULL,
+					      $<id>1, $<cbuf>5, $<line>2,
+					      ccode_line, FALSE, NULL);
+			} else if(strcmp($<id>1, "dispose")==0) {
+				push_init_arg($<id>3, FALSE);
+				push_function(NO_SCOPE, DISPOSE_METHOD, NULL,
+					      $<id>1, $<cbuf>5, $<line>2,
+					      ccode_line, FALSE, NULL);
+			} else if(strcmp($<id>1, "finalize")==0) {
+				push_init_arg($<id>3, FALSE);
+				push_function(NO_SCOPE, FINALIZE_METHOD, NULL,
+					      $<id>1, $<cbuf>5, $<line>2,
+					      ccode_line, FALSE, NULL);
 			} else {
 				g_free($<id>1);
 				g_free($<id>3);
 				g_string_free($<cbuf>5,TRUE);
 				yyerror(_("parse error "
-					  "(untyped blocks must be init or "
-					  "class_init)"));
+					  "(untyped blocks must be init, "
+					  "class_init, constructor, dispose "
+					  "or finalize)"));
 				YYERROR;
 			}
 						}
--- src/treefuncs.def.orig	2007-03-09 18:46:14.000000000 +0100
+++ src/treefuncs.def	2008-01-21 00:53:13.000000000 +0100
@@ -40,6 +40,9 @@
 	REGULAR_METHOD,
 	INIT_METHOD,
 	CLASS_INIT_METHOD,
+	CONSTRUCTOR_METHOD,
+	DISPOSE_METHOD,
+	FINALIZE_METHOD,
 	VIRTUAL_METHOD,
 	SIGNAL_LAST_METHOD,
 	SIGNAL_FIRST_METHOD,

