]> git.draconx.ca Git - gob-dx.git/blobdiff - src/main.c
Release 2.0.19
[gob-dx.git] / src / main.c
index 1fddc2658791f085a1d73a490d3a3cf8c4fd8136..b4d1b270f4332b126da8e0c428cf6aa081742217 100644 (file)
@@ -1,7 +1,7 @@
 /* GOB C Preprocessor
  * Copyright (C) 1999,2000 the Free Software Foundation.
  * Copyright (C) 2000 Eazel, Inc.
- * Copyright (C) 2001-2004 George (Jiri) Lebl
+ * Copyright (C) 2001-2011 George (Jiri) Lebl
  *
  * Author: George (Jiri) Lebl
  *
@@ -70,7 +70,7 @@ static char *ptypebase;
 
 char *output_dir = NULL;
 
-static char file_sep = '-';
+char file_sep = '-';
 
 static int signals = 0; /* number of signals */
 static int set_properties = 0; /* number of named (set) properties */
@@ -92,16 +92,20 @@ 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;
 FILE *outph = NULL;
-FILE *devnull = NULL;
 
 gboolean no_touch = FALSE;
 gboolean no_touch_headers = FALSE;
@@ -200,6 +204,7 @@ print_method (FILE *fp,
              const char *afterargs,
              const char *postfix,
              const Method *m,
+             gboolean print_funcattrs,
              gboolean one_arg_per_line,
              gboolean no_funcbase,
              gboolean kill_underscore,
@@ -255,7 +260,28 @@ print_method (FILE *fp,
        } else {
                out_printf(fp, "void"); 
        }
-       out_printf(fp, "%s)%s", afterargs, postfix); 
+       /* Slightly icky: sometimes we are called st m->funcattrs
+          hasn't been set, but if so it should be NULL since its been
+          zero-initialized.  */
+       if(print_funcattrs && m->funcattrs != NULL
+          && strlen(m->funcattrs) > 0) {
+               /* To keep the output neat, we trim off the trailing '\n'
+                  from the end of funcattrs for a moment.  */
+               size_t funcattrs_len = strlen(m->funcattrs);
+                gboolean funcattrs_chomped = FALSE;
+               if((m->funcattrs)[funcattrs_len - 1] == '\n') {
+                       m->funcattrs[funcattrs_len - 1] = '\0';
+                        funcattrs_chomped = TRUE;
+               } 
+               out_printf(fp, "%s)\n%s%s", afterargs, m->funcattrs, postfix);
+                /* Put it back like it was (though it shouldn't matter).  */
+               if (funcattrs_chomped) {
+                       (m->funcattrs)[funcattrs_len - 1] = '\n';
+               }
+       }
+       else {
+               out_printf(fp, "%s)%s", afterargs, postfix); 
+       }
 }
 
 static gboolean
@@ -270,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;
 
@@ -292,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;
 
@@ -331,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;
 
@@ -372,11 +407,12 @@ put_vs_method(const Method *m)
 
        /* if a signal mark it as such */
        if(m->method != VIRTUAL_METHOD)
-               print_method(outh, "\t/*signal*/", "(* ", "", ") ", "", ";\n",
-                            m, FALSE, TRUE, TRUE, FALSE, FALSE);
+               print_method(outh, "\t/*signal*/", "(* ", "", ") ", "", ";\n",
+                            m, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE);
        else
-               print_method(outh, "\t", "(* ", "", ") ", "", ";\n",
-                            m, FALSE, TRUE, TRUE, FALSE, FALSE);
+               print_method(outh, "\t", "(* ", "", ") ", "", ";\n",
+                            m, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE);
+
 }
 
 static void
@@ -385,8 +421,10 @@ put_pub_method(const Method *m)
        if(m->scope != PUBLIC_SCOPE)
                return;
 
+       out_addline_infile(outh, m->line_no);
        print_method(outh, "", "\t", "", "\t", "", ";\n", m,
-                    TRUE, FALSE, TRUE, FALSE, FALSE);
+                    TRUE, TRUE, FALSE, TRUE, FALSE, FALSE);
+       out_addline_outfile(outh);
 }
 
 static void
@@ -424,7 +462,7 @@ put_signal_macro (const Method *m, gboolean gnu)
                            "(GCallback) __extension__ ({",
                            funcbase, m->id, macrobase, typebase, m->id);
                print_method (outh, "", "(* ___", "", ") ", ", gpointer ___data ",
-                             " = (func); ", m, FALSE, TRUE, TRUE, FALSE, TRUE);
+                             " = (func); ", m, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE);
                out_printf (outh, "___%s; }), (data))\n", m->id);
 
                /* connect_after */
@@ -435,7 +473,7 @@ put_signal_macro (const Method *m, gboolean gnu)
                            "(GCallback) __extension__ ({",
                            funcbase, m->id, macrobase, typebase, m->id);
                print_method (outh, "", "(* ___", "", ") ", ", gpointer ___data ",
-                             " = (func); ", m, FALSE, TRUE, TRUE, FALSE, TRUE);
+                             " = (func); ", m, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE);
                out_printf (outh, "___%s; }), (data))\n", m->id);
 
                /* connect_data */
@@ -447,7 +485,7 @@ put_signal_macro (const Method *m, gboolean gnu)
                            "(GCallback) __extension__ ({",
                            funcbase, m->id, macrobase, typebase, m->id);
                print_method (outh, "", "(* ___", "", ") ", ", gpointer ___data ",
-                             " = (func); ", m, FALSE, TRUE, TRUE, FALSE, TRUE);
+                             " = (func); ", m, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE);
                out_printf (outh, "___%s; }), (data), (destroy_data), (GConnectFlags)(flags))\n", m->id);
        }
 }
@@ -509,15 +547,17 @@ put_local_signal_macros (const Class *c)
 static void
 put_prot_method(const Method *m)
 {
-       if(m->scope != PROTECTED_SCOPE)
-               return;
+       FILE *f;
 
-       if(outph)
-               print_method(outph, "", "\t", "", "\t", "", ";\n",
-                            m, FALSE, FALSE, TRUE, FALSE, FALSE);
-       else
-               print_method(out, "", "\t", "", "\t", "", ";\n",
-                            m, FALSE, FALSE, TRUE, FALSE, FALSE);
+       if(m->scope != PROTECTED_SCOPE)
+               return;
+       f = outph ? outph : out;
+
+       out_addline_infile(f, m->line_no);
+       print_method(f, "", "\t", "", "\t", "", ";\n",
+                    m, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE);
+       out_addline_outfile(f);
 }
 
 static void
@@ -529,7 +569,7 @@ put_priv_method_prot(const Method *m)
                if(m->cbuf)
                        print_method(out,
                                     "static ", "___real_", "", " ", "", ";\n",
-                                    m, FALSE, FALSE, TRUE, FALSE, FALSE);
+                                    m, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE);
        }
        /* no else, here, it might still have a private prototype, it's not
         * exclusive */
@@ -538,16 +578,27 @@ put_priv_method_prot(const Method *m)
            m->cbuf)) {
                /* add unique ID */
                char *s = g_strdup_printf("___%x_", (guint)m->unique_id);
+               if (m->line_no > 0)
+                       out_addline_infile(out, m->line_no);
                print_method(out, "static ", s, "", " ", "",
                             no_gnu?";\n":" G_GNUC_UNUSED;\n",
-                            m, FALSE, FALSE, FALSE, FALSE, FALSE);
+                            m, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE);
+               if (m->line_no > 0)
+                       out_addline_outfile(out);
                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) {
+               if (m->line_no > 0)
+                       out_addline_infile(out, m->line_no);
                print_method(out, "static ", "", "", " ", "",
                             no_gnu?";\n":" G_GNUC_UNUSED;\n",
-                            m, FALSE, FALSE, TRUE, FALSE, FALSE);
+                            m, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE);
+               if (m->line_no > 0)
+                       out_addline_outfile(out);
        }
 }
 
@@ -630,66 +681,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);
 }
 
 
@@ -1564,13 +1617,13 @@ make_argument (Argument *a)
                           a->name, flags->str);
        else if (!strcmp (a->gtktype, "FLOAT"))
                out_printf(out, "\tparam_spec = g_param_spec_float (\"%s\", NULL, NULL,\n"
-                          "\t\tG_MINFLOAT, G_MAXFLOAT,\n"
+                          "\t\t-G_MAXFLOAT, G_MAXFLOAT,\n"
                           "\t\t0,\n"
                           "\t\t%s);\n",
                           a->name, flags->str);
        else if (!strcmp (a->gtktype, "DOUBLE"))
                out_printf(out, "\tparam_spec = g_param_spec_double (\"%s\", NULL, NULL,\n"
-                          "\t\tG_MINDOUBLE, G_MAXDOUBLE,\n"
+                          "\t\t-G_MAXDOUBLE, G_MAXDOUBLE,\n"
                           "\t\t0,\n"
                           "\t\t%s);\n",
                           a->name, flags->str);
@@ -1606,22 +1659,22 @@ make_property (Property *p)
        if (p->override) {
                if (p->flags != NULL)
                        error_print (GOB_WARN, p->line_no,
-                                    "Overriden property, flags ignored");
+                                    "Overridden property, flags ignored");
                if (p->nick != NULL)
                        error_print (GOB_WARN, p->line_no,
-                                    "Overriden property, nick ignored");
+                                    "Overridden property, nick ignored");
                if (p->blurb != NULL)
                        error_print (GOB_WARN, p->line_no,
-                                    "Overriden property, blurb ignored");
+                                    "Overridden property, blurb ignored");
                if (p->minimum != NULL)
                        error_print (GOB_WARN, p->line_no,
-                                    "Overriden property, minimum ignored");
+                                    "Overridden property, minimum ignored");
                if (p->maximum != NULL)
                        error_print (GOB_WARN, p->line_no,
-                                    "Overriden property, maximum ignored");
+                                    "Overridden property, maximum ignored");
                if (p->default_value != NULL)
                        error_print (GOB_WARN, p->line_no,
-                                    "Overriden property, default_value ignored");
+                                    "Overridden property, default_value ignored");
 
                s = g_strdup (p->name);
                gob_strup (s);
@@ -1868,7 +1921,7 @@ make_property (Property *p)
                                    p->name,
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
-                                   value_for_print (p->minimum, "G_MINFLOAT"),
+                                   value_for_print (p->minimum, "-G_MAXFLOAT"),
                                    value_for_print (p->maximum, "G_MAXFLOAT"),
                                    value_for_print (p->default_value, "0.0"),
                                    flags->str);
@@ -1884,7 +1937,7 @@ make_property (Property *p)
                                    p->name,
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
-                                   value_for_print (p->minimum, "G_MINDOUBLE"),
+                                   value_for_print (p->minimum, "-G_MAXDOUBLE"),
                                    value_for_print (p->maximum, "G_MAXDOUBLE"),
                                    value_for_print (p->default_value, "0.0"),
                                    flags->str);
@@ -2034,10 +2087,12 @@ print_initializer(Method *m, Variable *v)
        if (v->initializer_simple)
                out_printf(out, "\t%s->%s = %s;\n",
                   root, v->id, v->initializer);
-       else if (!strcmp(v->id, "_glade_xml"))
+       else if (strcmp(v->id, "_glade_xml") == 0)
+               /* This is OK, this v->initializer string is set internally
+                  and it will eat exactly one string! */
                out_printf(out,v->initializer, ((FuncArg *)m->args->data)->name);
        else
-               out_printf(out,v->initializer);
+               out_printf(out, "%s", v->initializer);
 
        if(v->initializer_line > 0)
                out_addline_outfile(out);
@@ -2111,13 +2166,56 @@ print_destructor (Variable *v)
 
                if(v->destructor_line > 0)
                        out_addline_outfile(out);
-               out_printf(out, "\tmemset(&%s, 0, sizeof(%s));\n",
+               out_printf(out, "\tmemset(&(%s), 0, sizeof(%s));\n",
                           v->id, v->id);
                out_printf(out, "#undef VAR\n");
                out_printf(out, "#undef %s\n", v->id);
        }
 }
 
+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
+print_unreftors (Class *c)
+{
+       GList *li;
+       for(li = ((Class *)class)->nodes;
+           li != NULL;
+           li = li->next) {
+               Node *n = li->data;
+               Variable *v = (Variable *)n;
+               if (n->type == VARIABLE_NODE &&
+                   v->scope != CLASS_SCOPE &&
+                   v->destructor_unref)
+                       print_destructor (v);
+       }
+}
+
 static void
 add_dispose (Class *c)
 {
@@ -2128,7 +2226,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" : "",
@@ -2136,6 +2234,10 @@ add_dispose (Class *c)
        }
 
        if (dispose_handler != NULL) {
+               if (unreftors > 0) {
+                       print_unreftors (c);
+               }
+
                /* so we get possible bad argument warning */
                if (dispose_handler->line_no > 0)
                        out_addline_infile (out, dispose_handler->line_no);
@@ -2144,29 +2246,43 @@ 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);
+               }
+
+               if (unreftors > 0) {
+                       print_unreftors (c);
+               }
+
                out_printf (out,
                            "\tif (G_OBJECT_CLASS (parent_class)->dispose) \\\n"
                            "\t\t(* G_OBJECT_CLASS (parent_class)->dispose) (obj_self);\n");
        }
 
-       if (unreftors > 0) {
-               GList *li;
-               for(li = ((Class *)class)->nodes;
-                   li != NULL;
-                   li = li->next) {
-                       Node *n = li->data;
-                       Variable *v = (Variable *)n;
-                       if (n->type == VARIABLE_NODE &&
-                           v->scope != CLASS_SCOPE &&
-                           v->destructor_unref)
-                               print_destructor (v);
-               }
-       }
-
        out_printf(out, "}\n"
                   "#undef __GOB_FUNCTION__\n\n");
 }
 
+static void
+print_destructors (Class *c)
+{
+       GList *li;
+       for (li = ((Class *)class)->nodes;
+            li != NULL;
+            li = li->next) {
+               Node *n = li->data;
+               Variable *v = (Variable *)n;
+               if (n->type == VARIABLE_NODE &&
+                   v->scope != CLASS_SCOPE &&
+                   ! v->destructor_unref)
+                       print_destructor (v);
+       }
+}
+
 static void
 add_finalize (Class *c)
 {
@@ -2179,7 +2295,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";
@@ -2195,6 +2312,10 @@ add_finalize (Class *c)
        }
 
        if(finalize_handler) {
+               if (destructors > 0) {
+                       print_destructors (c);
+               }
+
                /* so we get possible bad argument warning */
                if(finalize_handler->line_no > 0)
                        out_addline_infile(out, finalize_handler->line_no);
@@ -2203,25 +2324,23 @@ 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);
+               }
+
+               if (destructors > 0) {
+                       print_destructors (c);
+               }
+
                out_printf(out,
                           "\tif(G_OBJECT_CLASS(parent_class)->finalize) \\\n"
                           "\t\t(* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);\n");
        }
 
-       if (destructors > 0) {
-               GList *li;
-               for (li = ((Class *)class)->nodes;
-                    li != NULL;
-                    li = li->next) {
-                       Node *n = li->data;
-                       Variable *v = (Variable *)n;
-                       if (n->type == VARIABLE_NODE &&
-                           v->scope != CLASS_SCOPE &&
-                           ! v->destructor_unref)
-                               print_destructor (v);
-               }
-       }
-
        out_printf(out, "}\n"
                   "#undef __GOB_FUNCTION__\n\n");
 }
@@ -2276,10 +2395,12 @@ add_inits(Class *c)
                        if(m->line_no > 0)
                                out_addline_infile(out, m->line_no);
                        print_method(out, "static ", "\n", "", " ", "", "\n",
-                                    m, FALSE, FALSE, TRUE, TRUE, FALSE);
+                                    m, FALSE, FALSE, FALSE, TRUE, TRUE,
+                                    FALSE);
+                       out_printf(out, "{\n");
                        if(m->line_no > 0)
                                out_addline_outfile(out);
-                       out_printf(out, "{\n"
+                       out_printf(out,
                                   "#define __GOB_FUNCTION__ \"%s::init\"\n",
                                   c->otype);
                        if (privates > 0) {
@@ -2325,15 +2446,18 @@ add_inits(Class *c)
                        if(m->line_no > 0)
                                out_addline_infile(out, m->line_no);
                        print_method(out, "static ", "\n", "", " ", "", "\n",
-                                    m, FALSE, FALSE, TRUE, TRUE, FALSE);
+                                    m, FALSE, FALSE, FALSE, TRUE, TRUE,
+                                    FALSE);
+                       out_printf(out, "{\n");
                        if(m->line_no > 0)
                                out_addline_outfile(out);
-                       out_printf(out, "{\n"
+                       out_printf(out,
                                   "#define __GOB_FUNCTION__ \"%s::class_init\"\n",
                                   c->otype);
                        if (set_properties > 0 ||
                            get_properties > 0 ||
                            signals > 0 ||
+                           need_constructor ||
                            need_dispose ||
                            need_finalize) {
                                out_printf(out,
@@ -2382,6 +2506,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");
@@ -2677,10 +2804,10 @@ print_preconditions(Method *m)
 static void
 print_method_body (Method *m, gboolean pre, gboolean unused_self)
 {
+       out_printf(out, "{\n");
        if (m->line_no > 0)
                out_addline_outfile(out);
-       out_printf(out, "{\n"
-                  "#define __GOB_FUNCTION__ \"%s::%s\"\n",
+       out_printf(out, "#define __GOB_FUNCTION__ \"%s::%s\"\n",
                   ((Class *)class)->otype,
                   m->id);
        if (pre)
@@ -2833,10 +2960,10 @@ put_method(Method *m)
                        out_addline_infile(out, m->line_no);
                if(m->scope == PRIVATE_SCOPE)
                        print_method(out, "static ", "\n", "", " ", "", "\n",
-                                    m, FALSE, FALSE, TRUE, FALSE, FALSE);
+                                    m, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE);
                else /* PUBLIC, PROTECTED */
                        print_method(out, "", "\n", "", " ", "", "\n",
-                                    m, FALSE, FALSE, TRUE, FALSE, FALSE);
+                                    m, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE);
                print_method_body(m, TRUE, TRUE);
                /* the outfile line was added above */
                break;
@@ -2846,14 +2973,14 @@ put_method(Method *m)
                        out_addline_infile(out, m->line_no);
                if(m->scope == PRIVATE_SCOPE)
                        print_method(out, "static ", "\n", "", " ", "", "\n",
-                                    m, FALSE, FALSE, TRUE, FALSE, FALSE);
+                                    m, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE);
                else /* PUBLIC, PROTECTED */
                        print_method(out, "", "\n", "", " ", "", "\n",
-                                    m, FALSE, FALSE, TRUE, FALSE, FALSE);
-               out_addline_outfile (out);
-
+                                    m, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE);
                out_printf (out, "{\n");
 
+               out_addline_outfile (out);
+
                out_printf (out,
                            "\tGValue ___param_values[%d];\n"
                            "\tGValue ___return_val;\n\n"
@@ -2968,7 +3095,7 @@ put_method(Method *m)
                if(m->line_no > 0)
                        out_addline_infile(out, m->line_no);
                print_method(out, "static ", "\n___real_", "", " ", "", "\n",
-                            m, FALSE, FALSE, TRUE, TRUE, FALSE);
+                            m, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE);
                print_method_body(m, FALSE, TRUE);
                /* the outfile line was added above */
                break;
@@ -2977,13 +3104,13 @@ put_method(Method *m)
                        out_addline_infile(out, m->line_no);
                if(m->scope==PRIVATE_SCOPE)
                        print_method(out, "static ", "\n", "", " ", "", "\n",
-                                    m, FALSE, FALSE, TRUE, FALSE, FALSE);
+                                    m, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE);
                else /* PUBLIC, PROTECTED */
                        print_method(out, "", "\n", "", " ", "", "\n",
-                                    m, FALSE, FALSE, TRUE, FALSE, FALSE);
+                                    m, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE);
+               out_printf(out, "{\n");
                out_addline_outfile(out);
-               out_printf(out, "{\n"
-                       "\t%sClass *klass;\n", typebase);
+               out_printf(out, "\t%sClass *klass;\n", typebase);
                print_preconditions(m);
                out_printf(out, "\tklass = %s_GET_CLASS(%s);\n\n"
                        "\tif(klass->%s)\n",
@@ -3026,7 +3153,7 @@ put_method(Method *m)
                if(m->line_no > 0)
                        out_addline_infile(out, m->line_no);
                print_method(out, "static ", "\n___real_", "", " ", "", "\n",
-                            m, FALSE, FALSE, TRUE, TRUE, FALSE);
+                            m, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE);
                print_method_body(m, FALSE, TRUE);
                /* the outfile line was added above */
                break;
@@ -3037,7 +3164,7 @@ put_method(Method *m)
                        out_addline_infile(out, m->line_no);
                s = g_strdup_printf("\n___%x_", (guint)m->unique_id);
                print_method(out, "static ", s, "", " ", "", "\n",
-                            m, FALSE, FALSE, FALSE, TRUE, FALSE);
+                            m, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
                g_free(s);
                out_addline_outfile(out);
                s = replace_sep(m->otype, '_');
@@ -3065,6 +3192,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;
        }
@@ -3095,15 +3231,7 @@ open_files(void)
        }
 
        
-       if (no_write) {
-               devnull = fopen ("/dev/null", "w");
-               if (devnull == NULL)
-                       error_print (GOB_ERROR, 0, "Cannot open null device");
-               out = devnull;
-               outh = devnull;
-               if (outfileph != NULL)
-                       outph = devnull;
-       } else {
+       if ( ! no_write) {
                out = fopen (outfile, "w");
                if (out == NULL) {
                        error_printf (GOB_ERROR, 0,
@@ -3286,6 +3414,7 @@ print_ccode_block(CCode *cc)
                out_addline_infile(fp, cc->line_no);
                break;
        default:
+       case CT_CCODE:
        case C_CCODE:
                fp = out;
                out_printf(fp, "\n");
@@ -3302,6 +3431,7 @@ print_ccode_block(CCode *cc)
        }
        out_printf(fp, "%s\n", cc->cbuf);
        if(cc->cctype == C_CCODE ||
+          cc->cctype == AD_CCODE ||
           cc->cctype == A_CCODE ||
           cc->cctype == AT_CCODE ||
           cc->cctype == PH_CCODE)
@@ -3510,7 +3640,7 @@ print_class_block(Class *c)
                    " */\n");
 
        if ( ! overrode_get_type) {
-               out_printf (outh, "GType\t%s_get_type\t(void);\n", funcbase);
+               out_printf (outh, "GType\t%s_get_type\t(void) G_GNUC_CONST;\n", funcbase);
        }
 
        for(li = c->nodes; li != NULL; li = li->next) {
@@ -3642,6 +3772,18 @@ print_class_block(Class *c)
                            funcbase);
        }
 
+       for (li = nodes; li != NULL; li = li->next) {
+               Node *node = li->data;
+               if (node->type == CCODE_NODE) {
+                       CCode *cc = (CCode *)node;
+                       if (cc->cctype == AD_CCODE)
+                               print_ccode_block (cc);
+               }
+       }
+
+       if (need_constructor)
+               add_constructor (c);
+
        if (need_dispose)
                add_dispose (c);
 
@@ -3736,11 +3878,15 @@ print_includes(void)
 
        /* if we are creating a private header see if it was included */
        if(outph) {
-               p = g_strconcat(filebase, "-private.h", NULL);
+               char sep[2] = {0,0};
+               if (file_sep != 0)
+                       sep[0] = file_sep;
+               p = g_strconcat(filebase, sep, "private.h", NULL);
                if( ! g_list_find_custom(include_files, p,
                                         (GCompareFunc)strcmp)) {
-                       out_printf(out, "#include \"%s-private.h\"\n\n",
-                                  filebase);
+                       out_printf(out, "#include \"%s%sprivate.h\"\n\n",
+                                  filebase,
+                                  sep);
                        if(found_header)
                                error_printf(GOB_WARN, 0,
                                            "Implicit private header include "
@@ -3803,12 +3949,13 @@ print_all_top(void)
 {
        GList *li;
 
-       /* print the AT_CCODE blocks */
+       /* print the AT_CCODE and CT_CCODE blocks */
        for(li = nodes; li != NULL; li = li->next) {
                Node *node = li->data;
                if(node->type == CCODE_NODE) {
                        CCode *cc = (CCode *)node;
-                       if(cc->cctype == AT_CCODE)
+                       if (cc->cctype == AT_CCODE ||
+                           cc->cctype == CT_CCODE)
                                print_ccode_block((CCode *)node);
                }
        }
@@ -3883,7 +4030,7 @@ print_enum (EnumDef *enode)
        g_free (str);
 
        out_printf (outh, "%s_get_type()\n", funcprefix);
-       out_printf (outh, "GType %s_get_type (void);\n\n", funcprefix);
+       out_printf (outh, "GType %s_get_type (void) G_GNUC_CONST;\n\n", funcprefix);
 
        out_printf (out,
                    "GType\n%s_get_type (void)\n"
@@ -3948,7 +4095,7 @@ print_flags (Flags *fnode)
        g_free (str);
 
        out_printf (outh, "%s_get_type()\n", funcprefix);
-       out_printf (outh, "GType %s_get_type (void);\n\n", funcprefix);
+       out_printf (outh, "GType %s_get_type (void) G_GNUC_CONST;\n\n", funcprefix);
 
        out_printf (out,
                    "GType\n%s_get_type (void)\n"
@@ -4011,7 +4158,7 @@ print_error (Error *enode)
        g_free (str);
 
        out_printf (outh, "%s_get_type ()\n", funcprefix);
-       out_printf (outh, "GType %s_get_type (void);\n\n", funcprefix);
+       out_printf (outh, "GType %s_get_type (void) G_GNUC_CONST;\n\n", funcprefix);
 
        out_printf (out,
                    "GType\n%s_get_type (void)\n"
@@ -4069,7 +4216,8 @@ generate_outfiles(void)
                if (node->type == CCODE_NODE) {
                        CCode *cc = (CCode *)node;
                        if (cc->cctype != HT_CCODE &&
-                           cc->cctype != AT_CCODE)
+                           cc->cctype != AT_CCODE &&
+                           cc->cctype != AD_CCODE)
                                print_ccode_block ((CCode *)node);
                } else if (node->type == CLASS_NODE) {
                        print_class_block ((Class *)node);
@@ -4134,7 +4282,8 @@ print_help(void)
                "\t-o,--output-dir         The directory where output "
                                          "should be placed\n"
                "\t--file-sep[=c]          replace default \'-\' file "
-                                         "name separator\n");
+                                         "name separator\n\n");
+       fprintf(stderr, "End world hunger, donate to the World Food Programme, http://www.wfp.org\n");
 }
 
 static void
@@ -4394,7 +4543,7 @@ int
 main(int argc, char *argv[])
 {
        parse_options(argc, argv);
-       
+
        if(use_m4) {
                yyin = popen(m4_commandline, "r");
                if(!yyin) {
@@ -4446,15 +4595,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);
@@ -4467,6 +4625,7 @@ main(int argc, char *argv[])
        check_property_types ((Class *)class);
        check_argument_types ((Class *)class);
        check_func_arg_checks ((Class *)class);
+       check_func_attrs ((Class *)class);
        check_for_class_destructors ((Class *)class);
 
        exit_on_error = TRUE;
@@ -4480,14 +4639,12 @@ main(int argc, char *argv[])
        
        generate_outfiles ();
 
-       if (devnull) {
-               fclose (devnull);
-       } else {
+       if (out)
                fclose (out);
+       if (outh)
                fclose (outh);
-               if (outph)
-                       fclose (outph);
-       }
+       if (outph)
+               fclose (outph);
 
        if (! no_write) {
                if (no_touch) {