[gob] Fri Jul 10 14:18:44 2009 Jiri (George) Lebl <jirka 5z com>



commit a06c10ceb85f62c9db197695dd682cf7eb54d112
Author: Jiri (George) Lebl <jirka 5z com>
Date:   Fri Jul 10 14:19:50 2009 -0500

    Fri Jul 10 14:18:44 2009  Jiri (George) Lebl <jirka 5z com>
    
    	* src/main.c, src/parse.y, doc/gob2.1.in, src/treefuncs.def,
    	  src/test.gob: Apply and somewhat rework
    	  the patch by Jean-Yves Lefort jylefort at brutele dot be to
    	  handle finalize, dispose, constructor just as init and
    	  class_init are handled.

 ChangeLog         |    8 ++
 doc/gob2.1.in     |   26 +++++++
 src/main.c        |  209 +++++++++++++++++++++++++++++++++++++----------------
 src/parse.y       |   21 +++++-
 src/test.gob      |   12 +++
 src/treefuncs.def |    3 +
 src/treefuncs.h   |    3 +
 7 files changed, 217 insertions(+), 65 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 37bdf13..0139132 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Fri Jul 10 14:18:44 2009  Jiri (George) Lebl <jirka 5z com>
+
+	* src/main.c, src/parse.y, doc/gob2.1.in, src/treefuncs.def,
+	  src/test.gob: Apply and somewhat rework
+	  the patch by Jean-Yves Lefort jylefort at brutele dot be to
+	  handle finalize, dispose, constructor just as init and
+	  class_init are handled.
+
 Fri Jul 10 12:23:39 2009  Jiri (George) Lebl <jirka 5z com>
 
 	* src/main.c: add G_GNUC_CONST to _get_type, thanks to
diff --git a/doc/gob2.1.in b/doc/gob2.1.in
index af8db64..48e21ca 100644
--- a/doc/gob2.1.in
+++ b/doc/gob2.1.in
@@ -630,6 +630,7 @@ arguments (the first of which is argument number 3).  Only one \'attr\'
 keyword per method is allowed.
 If you have more than one attribute to include, you should
 put them all within the braces.
+Note that function attributes were aded in version 2.0.16.
 .PP
 .B "Error return:"
 .PP
@@ -695,6 +696,31 @@ initialization is taken care of for you by gob itself.  The init function
 should on the other hand be used whenever you need to construct or initialize
 anything in the object to put it into a sane state.
 .PP
+.B "Constructor, dispose, finalize methods:"
+.PP
+Since 2.0.16, you can also easily add code to the object's constructor,
+dispose, and finalize methods.  See GObject documentation on how these are
+run.  The code you add will be run before calling the parents function
+for dispose and finalize, and after the parent function for constructor.
+The syntax is just like init and class_init.
+For example:
+.nf
+
+  constructor (self) {
+	/* constructor method */
+  }
+
+  dispose (self) {
+	/* dispose method */
+  }
+
+  finalize (self) {
+	/* finalize method */
+  }
+
+.fi
+You can also just override those methods as usual, but the above is much easier and nearly as flexible.
+.PP
 .B "Virtual methods:"
 .PP
 Virtual methods are basically pointers in the class structure,
diff --git a/src/main.c b/src/main.c
index c0d28c7..4f6758b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -92,11 +92,16 @@ static gboolean made_aliases = FALSE;  /* if we made any shorthand aliases
 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;
@@ -291,6 +296,9 @@ any_method_to_alias(Class *c)
 			
 			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;
 
@@ -313,6 +321,9 @@ make_method_aliases (Class *c)
 			
 			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;
 
@@ -352,6 +363,9 @@ add_bad_hack_to_avoid_unused_warnings(const Class *c)
 			
 			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;
 
@@ -572,17 +586,15 @@ put_priv_method_prot(const Method *m)
 		g_free(s);
 	} else if(m->scope == PRIVATE_SCOPE ||
 		  m->method == INIT_METHOD ||
-		  m->method == CLASS_INIT_METHOD) {
-	           /* The parser and check_* code is currently set up to
-	              reject attributes to init and class_init methods.  So we
-	              shouldn't see any.  */
-	        if(m->method == INIT_METHOD ||
-                   m->method == CLASS_INIT_METHOD) {
-		  g_assert (m->funcattrs == NULL || strlen(m->funcattrs) == 0);
-	        }
+		  m->method == CLASS_INIT_METHOD ||
+		  m->method == CONSTRUCTOR_METHOD ||
+		  m->method == DISPOSE_METHOD ||
+		  m->method == FINALIZE_METHOD) {
+		out_addline_infile(out, m->line_no);
 		print_method(out, "static ", "", "", " ", "",
 			     no_gnu?";\n":" G_GNUC_UNUSED;\n",
 			     m, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE);
+		out_addline_outfile(out);
 	}
 }
 
@@ -665,66 +677,68 @@ make_inits(Class *cl)
 	}
 }
 
-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);
 }
 
 
@@ -2156,6 +2170,33 @@ print_destructor (Variable *v)
 }
 
 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"
@@ -2165,7 +2206,7 @@ add_dispose (Class *c)
 		   "#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" : "",
@@ -2181,6 +2222,14 @@ add_dispose (Class *c)
 		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");
@@ -2216,7 +2265,8 @@ add_finalize (Class *c)
 		   c->otype);
 
 	if (privates > 0 ||
-	    destructors > 0) {
+	    destructors > 0 ||
+	    user_finalize_method != NULL) {
 		const char *unused = "";
 		if ( ! no_gnu)
 			unused = " G_GNUC_UNUSED";
@@ -2240,6 +2290,14 @@ add_finalize (Class *c)
 		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");
@@ -2375,6 +2433,7 @@ add_inits(Class *c)
 			if (set_properties > 0 ||
 			    get_properties > 0 ||
 			    signals > 0 ||
+			    need_constructor ||
 			    need_dispose ||
 			    need_finalize) {
 				out_printf(out,
@@ -2423,6 +2482,9 @@ add_inits(Class *c)
 
 			/* 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");
@@ -2891,10 +2953,10 @@ put_method(Method *m)
 		else /* PUBLIC, PROTECTED */
 			print_method(out, "", "\n", "", " ", "", "\n",
 				     m, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE);
-		out_addline_outfile (out);
-
 		out_printf (out, "{\n");
 
+		out_addline_outfile (out);
+
 		out_printf (out,
 			    "\tGValue ___param_values[%d];\n"
 			    "\tGValue ___return_val;\n\n"
@@ -3106,6 +3168,15 @@ put_method(Method *m)
 		/* 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, FALSE, TRUE, TRUE, FALSE);
+		print_method_body(m, TRUE, TRUE);
+		/* the outfile line was added above */
 	default:
 		break;
 	}
@@ -3675,6 +3746,9 @@ print_class_block(Class *c)
 			    funcbase);
 	}
 
+	if (need_constructor)
+		add_constructor (c);
+
 	if (need_dispose)
 		add_dispose (c);
 
@@ -4483,15 +4557,24 @@ main(int argc, char *argv[])
 
 	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);
diff --git a/src/parse.y b/src/parse.y
index e4a8aa5..f03e8da 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -1819,13 +1819,30 @@ method:		SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' methodmods codenoc
 				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;
 			}
 						}
diff --git a/src/test.gob b/src/test.gob
index 468fe47..c9b2ead 100644
--- a/src/test.gob
+++ b/src/test.gob
@@ -284,6 +284,18 @@ class Test:Object from /*G:Object*/ Gtk:Container
 		return self_blah(self,wid,h) > 0 ? g_strdup ("foo") : g_strdup ("bar");
 	}
 
+	constructor(self) {
+		/* constructor stuff */
+	}
+
+	dispose(self) {
+		/* dispose stuff */
+	}
+
+	finalize(self) {
+		/* finalize stuff */
+	}
+
 	private
 	char *
 	test_handler (self, GObject *w, int h, gpointer data)
diff --git a/src/treefuncs.def b/src/treefuncs.def
index 7f2845a..ce5e373 100644
--- a/src/treefuncs.def
+++ b/src/treefuncs.def
@@ -40,6 +40,9 @@ enum {
 	REGULAR_METHOD,
 	INIT_METHOD,
 	CLASS_INIT_METHOD,
+	CONSTRUCTOR_METHOD,
+	DISPOSE_METHOD,
+	FINALIZE_METHOD,
 	VIRTUAL_METHOD,
 	SIGNAL_LAST_METHOD,
 	SIGNAL_FIRST_METHOD,
diff --git a/src/treefuncs.h b/src/treefuncs.h
index bf18b34..a8aaf99 100644
--- a/src/treefuncs.h
+++ b/src/treefuncs.h
@@ -41,6 +41,9 @@ enum {
 	REGULAR_METHOD,
 	INIT_METHOD,
 	CLASS_INIT_METHOD,
+	CONSTRUCTOR_METHOD,
+	DISPOSE_METHOD,
+	FINALIZE_METHOD,
 	VIRTUAL_METHOD,
 	SIGNAL_LAST_METHOD,
 	SIGNAL_FIRST_METHOD,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]