]> git.draconx.ca Git - gob-dx.git/blobdiff - src/main.c
Fix dynamic interface implementation.
[gob-dx.git] / src / main.c
index fab7a2e0d46c5cd718d9c4d4f96607c014b23738..6a0c7911cadee6726195ce40eb05754cb288b28b 100644 (file)
@@ -1,7 +1,8 @@
 /* GOB C Preprocessor
  * Copyright (C) 1999,2000 the Free Software Foundation.
  * Copyright (C) 2000 Eazel, Inc.
- * Copyright (C) 2001-2009 George (Jiri) Lebl
+ * Copyright (C) 2001-2011 George (Jiri) Lebl
+ * Copyright © 2019-2020 Nick Bowler
  *
  * Author: George (Jiri) Lebl
  *
@@ -120,8 +121,12 @@ gboolean no_write = FALSE;
 gboolean no_lines = FALSE;
 gboolean no_self_alias = FALSE;
 gboolean always_private_struct = FALSE;
+gboolean gtk3_ok = FALSE;
+
 gint prealloc = 0;
 
+
+
 gboolean use_m4 = FALSE; /* preprocess sources with m4 */
 gboolean use_m4_clean = FALSE; /* preprocess sources with m4, no m4 flags */
 char *m4_commandline = NULL;
@@ -578,11 +583,13 @@ put_priv_method_prot(const Method *m)
            m->cbuf)) {
                /* add unique ID */
                char *s = g_strdup_printf("___%x_", (guint)m->unique_id);
-               out_addline_infile(out, m->line_no);
+               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, FALSE);
-               out_addline_outfile(out);
+               if (m->line_no > 0)
+                       out_addline_outfile(out);
                g_free(s);
        } else if(m->scope == PRIVATE_SCOPE ||
                  m->method == INIT_METHOD ||
@@ -590,11 +597,13 @@ put_priv_method_prot(const Method *m)
                  m->method == CONSTRUCTOR_METHOD ||
                  m->method == DISPOSE_METHOD ||
                  m->method == FINALIZE_METHOD) {
-               out_addline_infile(out, m->line_no);
+               if (m->line_no > 0)
+                       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);
+               if (m->line_no > 0)
+                       out_addline_outfile(out);
        }
 }
 
@@ -925,10 +934,10 @@ add_signal_prots(Method *m)
                        /* hack because glib is braindamaged */
                        set_func = g_strdup ("g_value_set_uint");
                else
-                       set_func = g_strdup_printf ("g_value_set_%s%s",
-                                                   (char *)m->gtktypes->data,
+                       set_func = g_strdup_printf ("g_value_%s_%s",
                                                    take_ownership ?
-                                                   "_take_ownership" : ""); 
+                                                   "take" : "set",
+                                                   (char *)m->gtktypes->data);
                gob_strdown (set_func);
 
                out_printf (out, "\n\t%s (return_value, v_return);\n",
@@ -1043,17 +1052,26 @@ add_interface_inits (Class *c)
                char *name = replace_sep (interface, '_');
                char *type = remove_sep (interface);
 
-               /* EEEK! evil, we should have some sort of option
-                * to force this for arbitrary interfaces, since
-                * some are Class and some are Iface.  Glib is shite
-                * in consistency. */
-               if (strcmp (type, "GtkEditable") == 0 ||
-                   strcmp (type, "GTypePlugin") == 0)
-                       end = "Class";
+               if(!gtk3_ok)
+               {
+                       /* EEEK! evil, we should have some sort of option
+                        * to force this for arbitrary interfaces, since
+                        * some are Class and some are Iface.  Glib is shite
+                        * in consistency. */
+               
+                       if (strcmp (type, "GtkEditable") == 0 ||
+                           strcmp (type, "GTypePlugin") == 0)
+                               end = "Class";
+                       else
+                               // We'll assume Iface is the standard ending 
+                               end = "Iface";
+                       }
                else
-                       /* We'll assume Iface is the standard ending */
-                       end = "Iface";
-
+               {
+                       /*GTK3 doesn't need Iface end*/
+                       end="Interface";
+               }
+               
                out_printf (out, "\nstatic void\n"
                            "___%s_init (%s%s *iface)\n"
                            "{\n",
@@ -1109,6 +1127,55 @@ add_interfaces (void)
        }
 }
 
+static void
+add_dynamic_interfaces(void)
+{
+       GList *li = ((Class *)class)->interfaces;
+
+       if (li) {
+               /*
+                * Hack to work around bug in g_type_module_add_interface,
+                * which will fail to add an interface to types that derive
+                * from something that also implements the same interface.
+                *
+                * The actual GType system does not have any such problem,
+                * and the GTypeModule implementation details relied upon
+                * here have not changed once since the feature was first
+                * implemented almost 20 years ago.
+                */
+               out_printf(out, "\t\tstruct _ModuleInterfaceInfo {\n"
+                               "\t\t\tgboolean loaded;\n"
+                               "\t\t\tGType instance_type;\n"
+                               "\t\t\tGType interface_type;\n"
+                               "\t\t\tGInterfaceInfo info;\n"
+                               "\t\t} *modinfo;\n");
+       }
+
+       for (; li; li = li->next) {
+               char *name = replace_sep(li->data, '_');
+               char *type = make_pre_macro(li->data, "TYPE");
+
+               out_printf(out, "\n"
+                               "\t\tmodinfo = g_malloc(sizeof *modinfo);\n"
+                               "\t\tmodinfo->loaded = TRUE;\n"
+                               "\t\tmodinfo->instance_type = %s_type_id;\n"
+                               "\t\tmodinfo->interface_type = %s;\n"
+                               "\t\tmodinfo->info = %s_info;\n"
+                               "\t\tg_type_add_interface_dynamic\n"
+                               "\t\t\t( modinfo->instance_type\n"
+                               "\t\t\t, modinfo->interface_type\n"
+                               "\t\t\t, G_TYPE_PLUGIN(type_module)\n"
+                               "\t\t\t);\n"
+                               "\t\ttype_module->interface_infos = g_slist_prepend\n"
+                               "\t\t\t( type_module->interface_infos\n"
+                               "\t\t\t, modinfo\n"
+                               "\t\t\t);\n", funcbase, type, name);
+
+               g_free(type);
+               g_free(name);
+       }
+}
+
 static void
 add_get_type(void)
 {
@@ -1157,6 +1224,57 @@ add_get_type(void)
                   "}\n\n");
 }
 
+static void
+add_dynamic_get_type (void)
+{
+       out_printf(out,
+                  "static GType %s_type_id;\n\n"
+                  "GType\n"
+                  "%s_get_type (void)\n"
+                  "{\n"
+                  "\treturn %s_type_id;\n"
+                  "}\n\n",
+                  funcbase, funcbase, funcbase);
+
+       out_printf(out,
+                  "void\n"
+                  "%s_register_type (GTypeModule *type_module)\n"
+                  "{\n"
+                  "\tstatic const GTypeInfo info = {\n"
+                  "\t\tsizeof (%sClass),\n"
+                  "\t\t(GBaseInitFunc) NULL,\n"
+                  "\t\t(GBaseFinalizeFunc) NULL,\n"
+                  "\t\t(GClassInitFunc) %s_class_init,\n"
+                  "\t\t(GClassFinalizeFunc) NULL,\n"
+                  "\t\tNULL /* class_data */,\n"
+                  "\t\tsizeof (%s),\n"
+                  "\t\t%d /* n_preallocs */,\n"
+                  "\t\t(GInstanceInitFunc) %s_init,\n"
+                  "\t\tNULL\n"
+                  "\t};\n\n",
+                  funcbase, typebase, funcbase, typebase, prealloc, funcbase);
+
+       add_interface_infos();
+
+       out_printf(out,
+                  "\t%s_type_id = g_type_module_register_type(\n"
+                  "\t\ttype_module,\n"
+                  "\t\t%s,\n"
+                  "\t\t\"%s\",\n"
+                  "\t\t&info,\n"
+                  "\t\t(GTypeFlags)%s\n"
+                  "\t);\n\n"
+                  "\t{\n",
+                  funcbase, pmacrotype, typebase,
+                  ((Class *)class)->abstract ? "G_TYPE_FLAG_ABSTRACT" : "0");
+
+       add_dynamic_interfaces();
+
+       out_printf(out,
+                  "\t}\n"
+                  "}\n\n");
+}
+
 static void
 add_bonobo_object_get_type (void)
 {
@@ -1346,14 +1464,14 @@ add_signals(Class *c)
                gob_strup (sig);
                flags = make_run_signal_flags (m, last);
                out_printf (out, "\tobject_signals[%s_SIGNAL] =\n"
-                           "\t\tg_signal_new (\"%s\",\n"
+                           "\t\tg_signal_new (%s,\n"
                            "\t\t\tG_TYPE_FROM_CLASS (g_object_class),\n"
                            "\t\t\t(GSignalFlags)(%s),\n"
                            "\t\t\tG_STRUCT_OFFSET (%sClass, %s),\n"
                            "\t\t\tNULL, NULL,\n"
                            "\t\t\t%s,\n"
                            "\t\t\tG_TYPE_%s, %d",
-                           sig, m->id,
+                           sig, m->signal_name /*m->id* if not given signal_name*/,
                            flags,
                            typebase, m->id, mar,
                            (char *)m->gtktypes->data,
@@ -1655,28 +1773,28 @@ 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);
                out_printf (out, "\tg_object_class_override_property (g_object_class,\n"
                            "\t\tPROP_%s,\n"
-                           "\t\t\"%s\");\n", s, p->name);
+                           "\t\t\"%s\");\n", s, value_for_print (p->canonical_name, p->name) );
                g_free (s);
        } else {
                GString *flags;
@@ -1728,7 +1846,7 @@ make_property (Property *p)
                                    "\t\t %s /* maximum */,\n"
                                    "\t\t %s /* default_value */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    value_for_print (p->minimum, "-128"),
@@ -1744,7 +1862,7 @@ make_property (Property *p)
                                    "\t\t %s /* maximum */,\n"
                                    "\t\t %s /* default_value */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    value_for_print (p->minimum, "0"),
@@ -1758,7 +1876,7 @@ make_property (Property *p)
                                    "\t\t %s /* blurb */,\n"
                                    "\t\t %s /* default_value */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    value_for_print (p->default_value, "FALSE"),
@@ -1772,7 +1890,7 @@ make_property (Property *p)
                                    "\t\t %s /* maximum */,\n"
                                    "\t\t %s /* default_value */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    value_for_print (p->minimum, "G_MININT"),
@@ -1788,7 +1906,7 @@ make_property (Property *p)
                                    "\t\t %s /* maximum */,\n"
                                    "\t\t %s /* default_value */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    value_for_print (p->minimum, "0"),
@@ -1804,7 +1922,7 @@ make_property (Property *p)
                                    "\t\t %s /* maximum */,\n"
                                    "\t\t %s /* default_value */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    value_for_print (p->minimum, "G_MINLONG"),
@@ -1820,7 +1938,7 @@ make_property (Property *p)
                                    "\t\t %s /* maximum */,\n"
                                    "\t\t %s /* default_value */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    value_for_print (p->minimum, "0"),
@@ -1836,7 +1954,7 @@ make_property (Property *p)
                                    "\t\t %s /* maximum */,\n"
                                    "\t\t %s /* default_value */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    value_for_print (p->minimum, "G_MININT64"),
@@ -1852,7 +1970,7 @@ make_property (Property *p)
                                    "\t\t %s /* maximum */,\n"
                                    "\t\t %s /* default_value */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    value_for_print (p->minimum, "0"),
@@ -1866,7 +1984,7 @@ make_property (Property *p)
                                    "\t\t %s /* blurb */,\n"
                                    "\t\t %s /* default_value */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    value_for_print (p->default_value, "0"),
@@ -1881,7 +1999,7 @@ make_property (Property *p)
                                    "\t\t %s /* enum_type */,\n"
                                    "\t\t %s /* default_value */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    type,
@@ -1898,7 +2016,7 @@ make_property (Property *p)
                                    "\t\t %s /* flags_type */,\n"
                                    "\t\t %s /* default_value */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    type,
@@ -1914,7 +2032,7 @@ make_property (Property *p)
                                    "\t\t %s /* maximum */,\n"
                                    "\t\t %s /* default_value */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    value_for_print (p->minimum, "-G_MAXFLOAT"),
@@ -1930,7 +2048,7 @@ make_property (Property *p)
                                    "\t\t %s /* maximum */,\n"
                                    "\t\t %s /* default_value */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    value_for_print (p->minimum, "-G_MAXDOUBLE"),
@@ -1944,7 +2062,7 @@ make_property (Property *p)
                                    "\t\t %s /* blurb */,\n"
                                    "\t\t %s /* default_value */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    value_for_print (p->default_value, "NULL"),
@@ -1958,7 +2076,7 @@ make_property (Property *p)
                                    "\t\t %s /* blurb */,\n"
                                    "\t\t %s /* param_type */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    type,
@@ -1973,7 +2091,7 @@ make_property (Property *p)
                                    "\t\t %s /* blurb */,\n"
                                    "\t\t %s /* boxed_type */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    type,
@@ -1985,7 +2103,7 @@ make_property (Property *p)
                                    "\t\t %s /* nick */,\n"
                                    "\t\t %s /* blurb */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    flags->str);
@@ -1996,7 +2114,7 @@ make_property (Property *p)
                                    "\t\t %s /* nick */,\n"
                                    "\t\t %s /* blurb */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    flags->str);
@@ -2009,7 +2127,7 @@ make_property (Property *p)
                                    "\t\t %s /* blurb */,\n"
                                    "\t\t %s /* object_type */,\n"
                                    "\t\t %s);\n",
-                                   p->name,
+                                   value_for_print (p->canonical_name, p->name),
                                    value_for_print (p->nick, "NULL"),
                                    value_for_print (p->blurb, "NULL"),
                                    type,
@@ -2162,7 +2280,7 @@ 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);
@@ -2196,6 +2314,22 @@ add_constructor (Class *c)
                   "#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)
 {
@@ -2214,6 +2348,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);
@@ -2230,29 +2368,35 @@ add_dispose (Class *c)
                                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)
 {
@@ -2282,6 +2426,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);
@@ -2298,25 +2446,15 @@ add_finalize (Class *c)
                                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");
 }
@@ -3390,6 +3528,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");
@@ -3614,8 +3753,23 @@ print_class_block(Class *c)
                    " * Public methods\n"
                    " */\n");
 
-       if ( ! overrode_get_type) {
-               out_printf (outh, "GType\t%s_get_type\t(void) G_GNUC_CONST;\n", funcbase);
+       if (!overrode_get_type) {
+               /*
+                * For ordinary "static" types it should be safe to mark the
+                * get_type implementation as const, since the get_type
+                * function return really is constant at the call boundary
+                * (even though there is an initial setup on the first call).
+                * But for dynamic types, since the registration is explicitly
+                * separated, we need to settle for "pure" as the results of
+                * get_type differ before and after type registration.
+                */
+               out_printf(outh, "GType\t%s_get_type\t(void) %s;\n", funcbase,
+                                c->dynamic ? "G_GNUC_PURE" : "G_GNUC_CONST");
+       }
+
+       if (c->dynamic) {
+               out_printf(outh, "void\t%s_register_type\t(GTypeModule *);\n",
+                                funcbase);
        }
 
        for(li = c->nodes; li != NULL; li = li->next) {
@@ -3683,11 +3837,13 @@ print_class_block(Class *c)
 
        add_interface_inits (c);
 
-       if ( ! overrode_get_type) {
+       if (!overrode_get_type) {
                if (c->bonobo_object_class != NULL)
-                       add_bonobo_object_get_type ();
+                       add_bonobo_object_get_type();
+               else if (c->dynamic)
+                       add_dynamic_get_type();
                else
-                       add_get_type ();
+                       add_get_type();
        }
 
        out_printf (out, "/* a macro for creating a new object of our type */\n");
@@ -3859,9 +4015,9 @@ print_includes(void)
                p = g_strconcat(filebase, sep, "private.h", NULL);
                if( ! g_list_find_custom(include_files, p,
                                         (GCompareFunc)strcmp)) {
-                       out_printf(out, "#include \"%s%cprivate.h\"\n\n",
+                       out_printf(out, "#include \"%s%sprivate.h\"\n\n",
                                   filebase,
-                                  file_sep);
+                                  sep);
                        if(found_header)
                                error_printf(GOB_WARN, 0,
                                            "Implicit private header include "
@@ -3924,12 +4080,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);
                }
        }
@@ -4256,7 +4413,9 @@ 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\n");
+                                         "name separator\n\n"
+               "\t--gtk3                  Use gtk+3\n"
+               );
        fprintf(stderr, "End world hunger, donate to the World Food Programme, http://www.wfp.org\n");
 }
 
@@ -4390,6 +4549,8 @@ parse_options(int argc, char *argv[])
                        } else {
                                file_sep = 0;
                        }
+               } else if(strcmp(argv[i], "--gtk3")==0) {
+                       gtk3_ok = TRUE;
                } else if(strcmp(argv[i], "--")==0) {
                        /*further arguments are files*/
                        no_opts = TRUE;