]> git.draconx.ca Git - gob-dx.git/blobdiff - src/main.c
Release 1.0.12
[gob-dx.git] / src / main.c
index e145d643c73114aab8ad778355f358e21a4c0e7e..526408b6f1921d6e13f710dc97ff8ff9f5ac37ae 100644 (file)
@@ -67,6 +67,7 @@ static int privates = 0; /* number of private data members */
 static int protecteds = 0; /* number of protected methods */
 static int destructors = 0; /* number of variable destructors */
 static int initializers = 0; /* number of variable initializers */
+static gboolean overrode_get_type = FALSE; /* provided your won _get_type */
 
 static gboolean made_aliases = FALSE;  /* if we made any shorthand aliases
                                          and need the REALLY UGLY HACK to
@@ -93,7 +94,7 @@ gboolean no_gnu = FALSE;
 gboolean exit_on_warn = FALSE;
 gboolean exit_on_error = TRUE;
 gboolean got_error = FALSE;
-gint private_header = PRIVATE_HEADER_ALWAYS;
+gint private_header = PRIVATE_HEADER_ONDEMAND;
 gboolean no_extern_c = FALSE;
 gboolean no_write = FALSE;
 gboolean no_lines = FALSE;
@@ -101,6 +102,14 @@ gboolean no_self_alias = FALSE;
 gboolean no_kill_underscores = FALSE;
 gboolean always_private_struct = FALSE;
 
+gboolean use_m4 = FALSE; /* preprocess sources with m4 */
+gboolean use_m4_clean = FALSE; /* preprocess sources with m4, no m4 flags */
+char *m4_commandline = NULL;
+#define M4_INCLUDE_DIR  PKGDATADIR "/m4"
+#define M4_BASE_FILENAME "gobm4.m4"
+#define M4_FLAGS "-P -s -I" M4_INCLUDE_DIR  " -DGOBM4_GOB_VERSION=" VERSION " " M4_BASE_FILENAME
+#define M4_COMMANDLINE "m4"
+
 int method_unique_id = 1;
 
 static void
@@ -127,7 +136,7 @@ make_bases(void)
 }
 
 static char *
-get_type(Type *t, gboolean postfix_to_stars)
+get_type(const Type *t, gboolean postfix_to_stars)
 {
        char *s;
        int i;
@@ -140,7 +149,7 @@ get_type(Type *t, gboolean postfix_to_stars)
 
        extra = 0;
        if(postfix_to_stars) {
-               char *p;
+               const char *p;
                /*XXX: this is ugly perhaps we can do this whole postfix thing
                  in a nicer way, we just count the number of '[' s and from
                  that we deduce the number of dimensions, so that we can print
@@ -163,7 +172,7 @@ get_type(Type *t, gboolean postfix_to_stars)
 }
 
 static char *
-get_gtk_doc(char *id)
+get_gtk_doc(const char *id)
 {
        char *val;
 
@@ -182,7 +191,7 @@ get_gtk_doc(char *id)
 }
 
 static void
-print_type(FILE *fp, Type *t, gboolean postfix_to_stars)
+print_type(FILE *fp, const Type *t, gboolean postfix_to_stars)
 {
        char *s;
 
@@ -193,15 +202,20 @@ print_type(FILE *fp, Type *t, gboolean postfix_to_stars)
 
 
 static void
-print_method(FILE *fp, char *typeprefix, char *nameprefix,
-            char *subnameprefix,
-            char *namepostfix, char *postfix, Method *m,
-            gboolean one_arg_per_line,
-            gboolean no_funcbase,
-            gboolean kill_underscore)
+print_method (FILE *fp,
+             const char *typeprefix,
+             const char *nameprefix,
+             const char *subnameprefix,
+             const char *namepostfix,
+             const char *afterargs,
+             const char *postfix,
+             const Method *m,
+             gboolean one_arg_per_line,
+             gboolean no_funcbase,
+             gboolean kill_underscore)
 {
        GList *li;
-       char *id;
+       const char *id;
 
        out_printf(fp, "%s", typeprefix); 
        print_type(fp, m->mtype, TRUE);
@@ -225,21 +239,21 @@ print_method(FILE *fp, char *typeprefix, char *nameprefix,
                        print_type(fp, arg->atype, FALSE);
                        if(li->next)
                                out_printf(fp, "%s%s,%s", arg->name,
-                                          arg->atype->postfix?
-                                          arg->atype->postfix:"",
-                                          one_arg_per_line?"\n\t\t\t\t\t":" ");
+                                          arg->atype->postfix ?
+                                          arg->atype->postfix : "",
+                                          one_arg_per_line ? "\n\t\t\t\t\t" : " ");
                        else
                                out_printf(fp, "%s%s", arg->name,
-                                          arg->atype->postfix?
-                                          arg->atype->postfix:""); 
+                                          arg->atype->postfix ?
+                                          arg->atype->postfix : ""); 
                }
                if(m->vararg)
                        out_printf(fp, ",%s...",
-                                  one_arg_per_line?"\n\t\t\t\t\t":" "); 
+                                  one_arg_per_line ? "\n\t\t\t\t\t" : " "); 
        } else {
                out_printf(fp, "void"); 
        }
-       out_printf(fp, ")%s", postfix); 
+       out_printf(fp, "%s)%s", afterargs, postfix); 
 }
 
 static gboolean
@@ -264,12 +278,13 @@ any_method_to_alias(Class *c)
 }
 
 
+/* just the vararg macros, we use the same func pointers for these as in non-gnu */
 static void
 make_method_gnu_aliases(Class *c)
 {
        GList *li;
        
-       for(li=c->nodes;li;li=g_list_next(li)) {
+       for(li = c->nodes; li != NULL; li = li->next) {
                Node *node = li->data;
                if(node->type == METHOD_NODE) {
                        Method *m = (Method *)node;
@@ -283,13 +298,24 @@ make_method_gnu_aliases(Class *c)
                        if(for_cpp && strcmp(m->id, "new")==0)
                                continue;
 
-                       out_printf(out, "static const typeof(&%s_%s) %s "
-                                  "__attribute__ ((__unused__)) "
-                                  "= %s_%s;\n", funcbase, get_real_id(m->id),
-                                  m->id, funcbase, get_real_id(m->id));
-                       out_printf(out, "#define %s(args...) "
-                                  "%s_%s(##args)\n", m->id,
-                                  funcbase, get_real_id(m->id));
+                       if(m->args != NULL)
+                               out_printf(out, "#define %s(args...) "
+                                          "%s_%s(args)\n", m->id,
+                                          funcbase, get_real_id(m->id));
+                       else
+                               out_printf(out, "#define %s() "
+                                          "%s_%s()\n", m->id,
+                                          funcbase, get_real_id(m->id));
+
+                       /* for compatibility with gob2 */
+                       if(m->args != NULL)
+                               out_printf(out, "#define self_%s(args...) "
+                                          "%s_%s(args)\n", m->id,
+                                          funcbase, get_real_id(m->id));
+                       else
+                               out_printf(out, "#define self_%s() "
+                                          "%s_%s()\n", m->id,
+                                          funcbase, get_real_id(m->id));
                }
        }
 }
@@ -298,6 +324,8 @@ static void
 make_method_nongnu_aliases(Class *c)
 {
        GList *li;
+
+       gboolean local_made_aliases = FALSE;
        
        for(li=c->nodes; li; li=g_list_next(li)) {
                Node *node = li->data;
@@ -313,14 +341,29 @@ make_method_nongnu_aliases(Class *c)
                        if(for_cpp && strcmp(m->id, "new")==0)
                                continue;
 
-                       print_method(out, "static ", "(* ", "", ") ", "",
+                       if( ! local_made_aliases)
+                               out_printf(out, "\n/* Short form pointers */\n");
+
+                       print_method(out, "static ", "(* const ", "", ") ",
+                                    "", "",
                                     m, FALSE, TRUE, FALSE);
                        out_printf(out, " = %s_%s;\n", funcbase,
                                   get_real_id(m->id));
 
-                       made_aliases = TRUE;
+                       /* for compatibility with gob2 */
+                       print_method(out, "static ", "(* const self_", "", ") ",
+                                    "", "",
+                                    m, FALSE, TRUE, FALSE);
+                       out_printf(out, " = %s_%s;\n", funcbase,
+                                  get_real_id(m->id));
+
+                       local_made_aliases = TRUE;
                }
        }
+       if(local_made_aliases) {
+               out_printf(out, "\n");
+               made_aliases = TRUE;
+       }
 }
 
 static void
@@ -329,10 +372,10 @@ add_bad_hack_to_avoid_unused_warnings(Class *c)
        GList *li;
 
        /* if we haven't had any methods, just return */
-       if(!made_aliases)
+       if( ! made_aliases)
                return;
        
-       if(!no_gnu)
+       if( ! no_gnu)
                out_printf(out, "\n\n#if (!defined __GNUC__) || (defined __GNUC__ && defined __STRICT_ANSI__)\n");
        out_printf(out,
                   "/*REALLY BAD HACK\n"
@@ -382,7 +425,7 @@ put_variable(Variable *v, FILE *fp)
 }
 
 static void
-put_vs_method(Method *m)
+put_vs_method(const Method *m)
 {
        if(m->method != SIGNAL_LAST_METHOD &&
           m->method != SIGNAL_FIRST_METHOD &&
@@ -391,71 +434,77 @@ put_vs_method(Method *m)
 
        /* if a signal mark it as such */
        if(m->method != VIRTUAL_METHOD)
-               print_method(outh, "\t/*signal*/", "(* ", "", ") ", ";\n",
+               print_method(outh, "\t/*signal*/", "(* ", "", ") ", "", ";\n",
                             m, FALSE, TRUE, TRUE);
        else
-               print_method(outh, "\t", "(* ", "", ") ", ";\n",
+               print_method(outh, "\t", "(* ", "", ") ", "", ";\n",
                             m, FALSE, TRUE, TRUE);
 }
 
 static void
-put_pub_method(Method *m)
+put_pub_method(const Method *m)
 {
        if(m->scope != PUBLIC_SCOPE)
                return;
 
-       print_method(outh, "", "\t", "", "\t", ";\n", m, TRUE, FALSE, TRUE);
+       print_method(outh, "", "\t", "", "\t", "", ";\n", m, TRUE, FALSE, TRUE);
 }
 
-/* I'm starting not to like this idea */
-#if 0
 static void
-put_signal_connect(Method *m)
+put_signal_macro (const Method *m, gboolean gnu)
 {
+       char *id;
+
        if(m->method != SIGNAL_LAST_METHOD &&
           m->method != SIGNAL_FIRST_METHOD)
                return;
 
-       out_printf(outh, "guint \t%s_%s__connect_full\t(%s *object,\n"
-                  "\t\t\t\t\tconst char *name,\n"
-                  "\t\t\t\t\tGtkSignalFunc func,\n"
-                  "\t\t\t\t\tGtkCallbackMarshal marshal,\n"
-                  "\t\t\t\t\tgpointer data,\n"
-                  "\t\t\t\t\tGtkDestroyNotify destroy_func,\n"
-                  "\t\t\t\t\tgboolean object_signal,\n"
-                  "\t\t\t\t\tgboolean after);\n",
-                  funcbase, m->id, typebase);
-
-       out_printf(outh, "#define %s_%s__connect(object,name,func,data) "
-                  "%s_%s__connect_full((object),(name),(func),NULL,"
-                  "(data),NULL,FALSE,FALSE)\n",
-                  funcbase, m->id, funcbase, m->id);
-       out_printf(outh, "#define %s_%s__connect_after(object,name,func,data) "
-                  "%s__connect_%s_full((object),(name),(func),NULL,"
-                  "(data),NULL,FALSE,TRUE)\n",
-                  funcbase, m->id, funcbase, m->id);
-
-       out_printf(outh, "guint \t%s_%s__connect_while_alive\t(%s *object,\n"
-                  "\t\t\t\t\tconst char *name,\n"
-                  "\t\t\t\t\tGtkSignalFunc func,\n"
-                  "\t\t\t\t\tgpointer data,\n"
-                  "\t\t\t\t\tGtkObject *alive_object);\n\n",
-                  funcbase, m->id, typebase);
+       id = g_strdup (m->id);
+       g_strup (id);
+
+       if ( ! gnu) {
+               out_printf (outh, "#define %s_SIGNAL_%s(func)\t"
+                           "\"%s\",GTK_SIGNAL_FUNC(func)\n",
+                           macrobase, id, get_real_id (m->id));
+       } else {
+               out_printf (outh, "#define %s_SIGNAL_%s(func)\t"
+                           "\"%s\",GTK_SIGNAL_FUNC(({",
+                           macrobase, id, get_real_id (m->id));
+               print_method (outh, "", "(* ___", "", ") ", ", gpointer data ",
+                             " = func; ", m, FALSE, TRUE, TRUE);
+               out_printf (outh, "___%s; }))\n", get_real_id (m->id));
+
+       }
+       g_free (id);
+}
+
+static void
+put_signal_macros (const Class *c, gboolean gnu)
+{
+       const GList *li;
+
+       if (signals < 0)
+               return;
+
+       for (li = c->nodes; li != NULL; li = li->next) {
+               const Node *n = li->data;
+               if (n->type == METHOD_NODE)
+                       put_signal_macro ((Method *)n, gnu);
+       }
 }
-#endif
 
 
 static void
-put_prot_method(Method *m)
+put_prot_method(const Method *m)
 {
        if(m->scope != PROTECTED_SCOPE)
                return;
 
        if(outph)
-               print_method(outph, "", "\t", "", "\t", ";\n",
+               print_method(outph, "", "\t", "", "\t", "", ";\n",
                             m, FALSE, FALSE, TRUE);
        else
-               print_method(out, "", "\t", "", "\t", ";\n",
+               print_method(out, "", "\t", "", "\t", "", ";\n",
                             m, FALSE, FALSE, TRUE);
 }
 
@@ -467,7 +516,7 @@ put_priv_method_prot(Method *m)
           m->method == VIRTUAL_METHOD) {
                if(m->cbuf)
                        print_method(out,
-                                    "static ", "___real_", "", " ", ";\n",
+                                    "static ", "___real_", "", " ", "", ";\n",
                                     m, FALSE, FALSE, TRUE);
        }
        /* no else, here, it might still have a private prototype, it's not
@@ -477,14 +526,14 @@ put_priv_method_prot(Method *m)
            m->cbuf)) {
                /* add unique ID */
                char *s = g_strdup_printf("___%x_", (guint)m->unique_id);
-               print_method(out, "static ", s, "", " ",
+               print_method(out, "static ", s, "", " ", "",
                             no_gnu?";\n":" G_GNUC_UNUSED;\n",
                             m, FALSE, FALSE, FALSE);
                g_free(s);
        } else if(m->scope == PRIVATE_SCOPE ||
                  m->method == INIT_METHOD ||
                  m->method == CLASS_INIT_METHOD)
-               print_method(out, "static ", "", "", " ",
+               print_method(out, "static ", "", "", " ", "",
                             no_gnu?";\n":" G_GNUC_UNUSED;\n",
                             m, FALSE, FALSE, TRUE);
 }
@@ -535,7 +584,8 @@ make_inits(Class *cl)
                                  NULL, NULL, NULL, g_strdup("class_init"),
                                  make_func_arg(cl->otype, TRUE, g_strdup("c")),
                                  NULL, NULL, NULL, 0, 0, FALSE,
-                                 method_unique_id++);
+                                 method_unique_id++,
+                                 FALSE /*bonobo_x_func*/);
                cl->nodes = g_list_prepend(cl->nodes, node);
        }
        if(!got_init) {
@@ -545,7 +595,8 @@ make_inits(Class *cl)
                                  NULL, NULL, NULL, g_strdup("init"),
                                  make_func_arg(cl->otype, FALSE, g_strdup("o")),
                                  NULL, NULL, NULL, 0, 0, FALSE,
-                                 method_unique_id++);
+                                 method_unique_id++,
+                                 FALSE /*bonobo_x_func*/);
                cl->nodes = g_list_prepend(cl->nodes, node);
        }
 }
@@ -651,7 +702,7 @@ find_same_type_signal(Method *m)
 }
 
 static void
-print_signal_marsal_args(Method *m)
+print_signal_marsal_args_gtk1 (Method *m)
 {
        if(strcmp(m->gtktypes->next->data, "NONE")!=0) {
                GList *li;
@@ -672,6 +723,146 @@ print_signal_marsal_args(Method *m)
        out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
 }
 
+static void
+add_marshal_gtk1 (Method *m, const char *mname)
+{
+       out_printf(out, "\nstatic void\n"
+               "___marshal_%s (GtkObject * object,\n"
+               "\tGtkSignalFunc func,\n"
+               "\tgpointer func_data,\n"
+               "\tGtkArg * args)\n"
+               "{\n", mname);
+       
+       if(strcmp(m->gtktypes->data, "NONE")==0) {
+               out_printf(out, "\t___%s rfunc;\n\n"
+                       "\trfunc = (___%s)func;\n\n"
+                       "\t(*rfunc)((%s *)object", mname, mname, typebase);
+       } else {
+               const char *retcast = get_cast(m->gtktypes->data, FALSE);
+               gboolean is_none = (strcmp(m->gtktypes->next->data, "NONE")==0);
+               out_printf(out,
+                          "\t___%s rfunc;\n\t"
+                          "%s *retval;\n\n"
+                          "\trfunc = (___%s)func;\n\n"
+                          "\tretval = GTK_RETLOC_%s(args[%d]);\n\n"
+                          "\t*retval = (*rfunc)((%s *)object",
+                          mname, retcast, mname,
+                          (char *)m->gtktypes->data,
+                          g_list_length(m->gtktypes) - (is_none ? 2 : 1),
+                          typebase);
+       }
+       print_signal_marsal_args_gtk1 (m);
+}
+
+static const char *
+gtk2_debool (const char *s)
+{
+       if (strcmp (s, "BOOL") == 0)
+               return "BOOLEAN";
+       else
+               return s;
+}
+
+static void
+print_signal_marsal_args_gtk2 (Method *m)
+{
+       if (strcmp (m->gtktypes->next->data, "NONE") != 0) {
+               GList *li;
+               int i;
+               for (i = 0, li = m->gtktypes->next;
+                    li != NULL;
+                    i++, li = li->next) {
+                       char *get_func = g_strdup_printf
+                               ("g_value_get_%s",
+                                (char *)gtk2_debool (li->data));
+                       g_strdown (get_func);
+                       out_printf (out, ",\n\t\t(%s) "
+                                   "%s (param_values + %d)",
+                                   get_cast (li->data, FALSE),
+                                   get_func, i + 1);
+                       g_free (get_func);
+               }
+       }
+       out_printf (out, ",\n\t\tdata2);\n");
+}
+
+static void
+add_marshal_gtk2 (Method *m, const char *mname)
+{
+       gboolean ret_none;
+       gboolean arglist_none;
+       const char *retcast;
+
+       ret_none = strcmp (m->gtktypes->data, "NONE") == 0;
+       arglist_none = strcmp (m->gtktypes->next->data, "NONE") == 0;
+
+       if (ret_none)
+               retcast = NULL;
+       else
+               retcast = get_cast (m->gtktypes->data, FALSE);
+
+       out_printf (out, "\nstatic void\n"
+                   "___marshal_%s (GClosure *closure,\n"
+                   "\tGValue *return_value,\n"
+                   "\tguint n_param_values,\n"
+                   "\tconst GValue *param_values,\n"
+                   "\tgpointer invocation_hint,\n"
+                   "\tgpointer marshal_data)\n"
+                   "{\n", mname);
+
+       if ( ! ret_none)
+               out_printf (out, "\t%s v_return;\n", retcast);
+
+       out_printf (out, "\tregister ___%s callback;\n"
+                   "\tregister GCClosure *cc = (GCClosure*) closure;\n"
+                   "\tregister gpointer data1, data2;\n\n",
+                   mname);
+
+       out_printf (out, "\tg_return_if_fail (n_param_values == %d);\n\n",
+                   arglist_none ? 1 : g_list_length (m->gtktypes));
+
+       out_printf (out,
+                   "\tif (G_CCLOSURE_SWAP_DATA (closure)) {\n"
+                   "\t\tdata1 = closure->data;\n"
+                   "\t\tdata2 = g_value_peek_pointer (param_values + 0);\n"
+                   "\t} else {\n"
+                   "\t\tdata1 = g_value_peek_pointer (param_values + 0);\n"
+                   "\t\tdata2 = closure->data;\n"
+                   "\t}\n\n");
+
+       out_printf (out, "\tcallback = (___%s) "
+                   "(marshal_data != NULL ? marshal_data : cc->callback);"
+                   "\n\n", mname);
+       
+       if (ret_none) {
+               out_printf (out, "\tcallback ((%s *)data1", typebase);
+       } else {
+               out_printf (out, "\tv_return = callback ((%s *)data1",
+                           typebase);
+       }
+
+       print_signal_marsal_args_gtk2 (m);
+
+       if ( ! ret_none) {
+               /* FIXME: This code is so fucking ugly it hurts */
+               gboolean take_ownership = 
+                       (strcmp ((char *)m->gtktypes->data, "STRING") == 0 ||
+                        strcmp ((char *)m->gtktypes->data, "BOXED") == 0);
+               char *set_func = g_strdup_printf ("g_value_set_%s%s",
+                                                 (char *)gtk2_debool (m->gtktypes->data),
+                                                 take_ownership ?
+                                                   "_take_ownership" : ""); 
+               g_strdown (set_func);
+
+               out_printf (out, "\n\t%s (return_value, v_return);\n",
+                           set_func);
+
+               g_free (set_func);
+       }
+       out_printf (out, "}\n\n");
+}
+
+
 
 static void
 add_signal_prots(Method *m)
@@ -704,41 +895,23 @@ add_signal_prots(Method *m)
        
        g_hash_table_insert(marsh, m, s);
        eq_signal_methods = g_list_prepend(eq_signal_methods, m);
-       
+
        /* we know that we'll know all the gtktypes (so get_cast can't fail) */
        out_printf(out, "\ntypedef %s (*___%s) (%s *, ",
                   get_cast(m->gtktypes->data, FALSE), s, typebase);
        
-       if(strcmp(m->gtktypes->next->data, "NONE")!=0) {
-               for(li=m->gtktypes->next; li; li=g_list_next(li))
+       if (strcmp (m->gtktypes->next->data, "NONE") != 0) {
+               for (li = m->gtktypes->next; li != NULL; li = li->next)
                        out_printf(out, "%s, ", get_cast(li->data, FALSE));
        }
-       out_printf(out, "gpointer);\n"); 
+       out_printf (out, "gpointer);\n"); 
        
-       out_printf(out, "\nstatic void\n"
-               "___marshal_%s (GtkObject * object,\n"
-               "\tGtkSignalFunc func,\n"
-               "\tgpointer func_data,\n"
-               "\tGtkArg * args)\n"
-               "{\n", s);
-       
-       if(strcmp(m->gtktypes->data, "NONE")==0) {
-               out_printf(out, "\t___%s rfunc;\n\n"
-                       "\trfunc = (___%s)func;\n\n"
-                       "\t(*rfunc)((%s *)object", s, s, typebase);
-       } else {
-               const char *retcast = get_cast(m->gtktypes->data, FALSE);
-               out_printf(out,
-                          "\t___%s rfunc;\n\t"
-                          "%s *retval;\n\n"
-                          "\trfunc = (___%s)func;\n\n"
-                          "\tretval = GTK_RETLOC_%s(args[%d]);\n\n"
-                          "\t*retval = (*rfunc)((%s *)object",
-                          s, retcast, s, (char *)m->gtktypes->data,
-                          g_list_length(m->gtktypes)-1, typebase);
-       }
-       print_signal_marsal_args(m);
 
+       out_printf (out, "\n#ifdef G_OBJECT_CLASS\n");
+       add_marshal_gtk2 (m, s);
+       out_printf (out, "#else /* ! G_OBJECT_CLASS */\n");
+       add_marshal_gtk1 (m, s);
+       out_printf (out, "#endif /* G_OBJECT_CLASS */\n\n");
 }
 
 static void
@@ -791,37 +964,83 @@ add_get_type(void)
 {
        char *chunk_size = ((Class*)class)->chunk_size;
        
-       out_printf(out, "guint\n"
-               "%s_get_type (void)\n"
-               "{\n"
-               "\tstatic guint type = 0;\n\n"
-               "\tif (!type) {\n"
-               "\t\tstatic const GtkTypeInfo info = {\n"
-               "\t\t\t\"%s\",\n"
-               "\t\t\tsizeof (%s),\n"
-               "\t\t\tsizeof (%sClass),\n"
-               "\t\t\t(GtkClassInitFunc) %s_class_init,\n"
-               "\t\t\t(GtkObjectInitFunc) %s_init,\n"
-               "\t\t\t/* reserved_1 */ NULL,\n"
-               "\t\t\t/* reserved_2 */ NULL,\n"
-               "\t\t\t(GtkClassInitFunc) NULL\n"
-               "\t\t};\n\n"
-               "\t\ttype = gtk_type_unique (%s_get_type(), &info);\n",
-               funcbase, typebase, typebase, typebase,
-               funcbase, funcbase, pfuncbase);
+       out_printf(out,
+                  "GtkType\n"
+                  "%s_get_type (void)\n"
+                  "{\n"
+                  "\tstatic GtkType type = 0;\n\n"
+                  "\tif (type == 0) {\n"
+                  "\t\tstatic const GtkTypeInfo info = {\n"
+                  "\t\t\t\"%s\",\n"
+                  "\t\t\tsizeof (%s),\n"
+                  "\t\t\tsizeof (%sClass),\n"
+                  "\t\t\t(GtkClassInitFunc) %s_class_init,\n"
+                  "\t\t\t(GtkObjectInitFunc) %s_init,\n"
+                  "\t\t\t/* reserved_1 */ NULL,\n"
+                  "\t\t\t/* reserved_2 */ NULL,\n"
+                  "\t\t\t(GtkClassInitFunc) NULL\n"
+                  "\t\t};\n\n"
+                  "\t\ttype = gtk_type_unique (%s_get_type(), &info);\n",
+                  funcbase, typebase, typebase, typebase,
+                  funcbase, funcbase, pfuncbase);
+       if(chunk_size)  {
+               out_printf(out,
+                          "#if %s > 0\n"
+                          "\t\tgtk_type_set_chunk_alloc(type, %s);\n"
+                          "#endif\n", 
+                          chunk_size, chunk_size);
+       }
+       out_printf(out,
+                  "\t}\n\n"
+                  "\treturn type;\n"
+                  "}\n\n");
+}
+
+static void
+add_bonobo_x_get_type (void)
+{
+       char *chunk_size = ((Class*)class)->chunk_size;
+       
+       out_printf(out,
+                  "GtkType\n"
+                  "%s_get_type (void)\n"
+                  "{\n"
+                  "\tstatic GtkType type = 0;\n\n"
+                  "\tif (type == 0) {\n"
+                  "\t\tstatic const GtkTypeInfo info = {\n"
+                  "\t\t\t\"%s\",\n"
+                  "\t\t\tsizeof (%s),\n"
+                  "\t\t\tsizeof (%sClass),\n"
+                  "\t\t\t(GtkClassInitFunc) %s_class_init,\n"
+                  "\t\t\t(GtkObjectInitFunc) %s_init,\n"
+                  "\t\t\t/* reserved_1 */ NULL,\n"
+                  "\t\t\t/* reserved_2 */ NULL,\n"
+                  "\t\t\t(GtkClassInitFunc) NULL\n"
+                  "\t\t};\n\n"
+                  "\t\ttype = bonobo_x_type_unique\n"
+                  "\t\t\t(%s_get_type (),\n"
+                  "\t\t\tPOA_%s__init, NULL,\n"
+                  "\t\t\tGTK_STRUCT_OFFSET (%sClass, _epv),\n"
+                  "\t\t\t&info);\n",
+                  funcbase, typebase, typebase, typebase,
+                  funcbase, funcbase, pfuncbase,
+                  ((Class*)class)->bonobo_x_class,
+                  typebase);
        if(chunk_size)  {
-               out_printf(out, "#if %s > 0\n"
-                               "\t\tgtk_type_set_chunk_alloc(type,%s);\n"
-                               "#endif\n", 
-                               chunk_size,  chunk_size);
+               out_printf(out,
+                          "#if %s > 0\n"
+                          "\t\tgtk_type_set_chunk_alloc(type, %s);\n"
+                          "#endif\n", 
+                          chunk_size, chunk_size);
        }
-       out_printf(out,"\t}\n\n"
-               "\treturn type;\n"
-               "}\n\n");
+       out_printf(out,
+                  "\t}\n\n"
+                  "\treturn type;\n"
+                  "}\n\n");
 }
 
 static void
-add_overrides(Class *c, char *oname, gboolean did_base_obj)
+add_overrides(Class *c, const char *oname, gboolean did_base_obj)
 {
        GList *li;
        GHashTable *done;
@@ -1012,12 +1231,14 @@ add_signals(Class *c)
 
                }
        }
-       out_printf(out, "\tgtk_object_class_add_signals (gtk_object_class,\n"
-               "\t\tobject_signals, LAST_SIGNAL);\n\n");
+       out_printf (out, "#ifndef G_OBJECT_CLASS\n");
+       out_printf (out, "\tgtk_object_class_add_signals (gtk_object_class,\n"
+                   "\t\tobject_signals, LAST_SIGNAL);\n");
+       out_printf (out, "#endif /* ! G_OBJECT_CLASS */\n\n");
 }
 
 static void
-set_def_handlers(Class *c, char *oname)
+set_def_handlers(Class *c, const char *oname)
 {
        GList *li;
        gboolean set_line = FALSE;
@@ -1073,11 +1294,11 @@ set_def_handlers(Class *c, char *oname)
                } else {
                        if(m->cbuf)
                                out_printf(out, "\t%s->%s = ___real_%s_%s;\n",
-                                       oname, get_real_id(m->id),
-                                       funcbase, get_real_id(m->id));
+                                          oname, get_real_id(m->id),
+                                          funcbase, get_real_id(m->id));
                        else
                                out_printf(out, "\t%s->%s = NULL;\n",
-                                       oname, get_real_id(m->id));
+                                          oname, get_real_id(m->id));
                }
        }
        if(set_line)
@@ -1326,6 +1547,36 @@ add_finalize(Class *c)
                   "#undef __GOB_FUNCTION__\n\n");
 }
 
+static void
+make_bonobo_x_epv (Class *c, const char *classname)
+{
+       GList *li;
+       gboolean added_line = FALSE;
+
+       for (li = c->nodes; li != NULL; li = li->next) {
+               Node *n = li->data;
+               Method *m = (Method *)n;
+               if(n->type != METHOD_NODE ||
+                  m->method == OVERRIDE_METHOD)
+                       continue;
+
+               if (m->bonobo_x_func) {
+                       if(m->line_no > 0) {
+                               out_addline_infile(out, m->line_no);
+                               added_line = TRUE;
+                       } else if (m->line_no == 0 &&
+                                  added_line) {
+                               out_addline_outfile(out);
+                               added_line = FALSE;
+                       }
+                       out_printf (out, "\t%s->_epv.%s = %s;\n",
+                                   classname, m->id, m->id);
+               }
+       }
+       if (added_line)
+               out_addline_outfile(out);
+}
+
 static void
 add_inits(Class *c)
 {
@@ -1342,7 +1593,7 @@ add_inits(Class *c)
                if(m->method == INIT_METHOD) {
                        if(m->line_no > 0)
                                out_addline_infile(out, m->line_no);
-                       print_method(out, "static ", "\n", "", " ", "\n",
+                       print_method(out, "static ", "\n", "", " ", "", "\n",
                                     m, FALSE, FALSE, TRUE);
                        if(m->line_no > 0)
                                out_addline_outfile(out);
@@ -1376,7 +1627,7 @@ add_inits(Class *c)
 
                        if(m->line_no > 0)
                                out_addline_infile(out, m->line_no);
-                       print_method(out, "static ", "\n", "", " ", "\n",
+                       print_method(out, "static ", "\n", "", " ", "", "\n",
                                     m, FALSE, FALSE, TRUE);
                        if(m->line_no > 0)
                                out_addline_outfile(out);
@@ -1449,6 +1700,9 @@ add_inits(Class *c)
                        if(get_arguments > 0 || set_arguments > 0)
                                make_arguments(c);
 
+                       if (c->bonobo_x_class != NULL) {
+                               make_bonobo_x_epv (c, ((FuncArg *)m->args->data)->name);
+                       }
                } else
                        continue;
 
@@ -1647,6 +1901,8 @@ print_preconditions(Method *m)
 static void
 print_method_body(Method *m, int pre)
 {
+       if (m->line_no > 0)
+               out_addline_outfile(out);
        out_printf(out, "{\n"
                   "#define __GOB_FUNCTION__ \"%s::%s\"\n",
                   ((Class *)class)->otype,
@@ -1732,10 +1988,10 @@ put_method(Method *m)
                if(m->line_no > 0)
                        out_addline_infile(out, m->line_no);
                if(m->scope == PRIVATE_SCOPE)
-                       print_method(out, "static ", "\n", "", " ", "\n",
+                       print_method(out, "static ", "\n", "", " ", "", "\n",
                                     m, FALSE, FALSE, TRUE);
                else /* PUBLIC, PROTECTED */
-                       print_method(out, "", "\n", "", " ", "\n",
+                       print_method(out, "", "\n", "", " ", "", "\n",
                                     m, FALSE, FALSE, TRUE);
                print_method_body(m, TRUE);
                /* the outfile line was added above */
@@ -1745,10 +2001,10 @@ put_method(Method *m)
                if(m->line_no > 0)
                        out_addline_infile(out, m->line_no);
                if(m->scope == PRIVATE_SCOPE)
-                       print_method(out, "static ", "\n", "", " ", "\n",
+                       print_method(out, "static ", "\n", "", " ", "", "\n",
                                     m, FALSE, FALSE, TRUE);
                else /* PUBLIC, PROTECTED */
-                       print_method(out, "", "\n", "", " ", "\n",
+                       print_method(out, "", "\n", "", " ", "", "\n",
                                     m, FALSE, FALSE, TRUE);
                out_addline_outfile(out);
                out_printf(out, "{\n");
@@ -1787,7 +2043,7 @@ put_method(Method *m)
                        break;
                if(m->line_no > 0)
                        out_addline_infile(out, m->line_no);
-               print_method(out, "static ", "\n___real_", "", " ", "\n",
+               print_method(out, "static ", "\n___real_", "", " ", "", "\n",
                             m, FALSE, FALSE, TRUE);
                print_method_body(m, FALSE);
                /* the outfile line was added above */
@@ -1796,10 +2052,10 @@ put_method(Method *m)
                if(m->line_no > 0)
                        out_addline_infile(out, m->line_no);
                if(m->scope==PRIVATE_SCOPE)
-                       print_method(out, "static ", "\n", "", " ", "\n",
+                       print_method(out, "static ", "\n", "", " ", "", "\n",
                                     m, FALSE, FALSE, TRUE);
                else /* PUBLIC, PROTECTED */
-                       print_method(out, "", "\n", "", " ", "\n",
+                       print_method(out, "", "\n", "", " ", "", "\n",
                                     m, FALSE, FALSE, TRUE);
                out_addline_outfile(out);
                out_printf(out, "{\n"
@@ -1845,7 +2101,7 @@ put_method(Method *m)
                        break;
                if(m->line_no > 0)
                        out_addline_infile(out, m->line_no);
-               print_method(out, "static ", "\n___real_", "", " ", "\n",
+               print_method(out, "static ", "\n___real_", "", " ", "", "\n",
                             m, FALSE, FALSE, TRUE);
                print_method_body(m, FALSE);
                /* the outfile line was added above */
@@ -1856,7 +2112,7 @@ put_method(Method *m)
                if(m->line_no > 0)
                        out_addline_infile(out, m->line_no);
                s = g_strdup_printf("\n___%x_", (guint)m->unique_id);
-               print_method(out, "static ", s, "", " ", "\n",
+               print_method(out, "static ", s, "", " ", "", "\n",
                             m, FALSE, FALSE, FALSE);
                g_free(s);
                out_addline_outfile(out);
@@ -2139,6 +2395,7 @@ print_class_block(Class *c)
                out_printf(out, "#define SELF(x) %s(x)\n", macrobase);
                out_printf(out, "#define SELF_CONST(x) %s_CONST(x)\n", macrobase);
                out_printf(out, "#define IS_SELF(x) %s(x)\n", macrois);
+               out_printf(out, "#define TYPE_SELF %s\n", macrotype);
                out_printf(out, "#define SELF_CLASS(x) %s_CLASS(x)\n\n",
                           macrobase);
                out_printf(out, "#define SELF_GET_CLASS(x) %s_GET_CLASS(x)\n\n",
@@ -2248,6 +2505,13 @@ print_class_block(Class *c)
                if(n->type == METHOD_NODE)
                        put_vs_method((Method *)n);
        }
+       /* If BonoboX type class put down the epv */
+       if (c->bonobo_x_class != NULL) {
+               out_printf (outh,
+                           "\t/* Bonobo object epv */\n"
+                           "\tPOA_%s__epv _epv;\n",
+                           c->bonobo_x_class);
+       }
        /* put class scope variables */
        for(l = c->nodes; l != NULL; l = l->next) {
                Node *n = l->data;
@@ -2274,7 +2538,15 @@ print_class_block(Class *c)
                   " * Public methods\n"
                   " */\n");
 
-       out_printf(outh, "guint\t%s_get_type\t(void);\n", funcbase);
+       if ( ! overrode_get_type) {
+               out_printf(outh, "GtkType\t%s_get_type\t(void)", funcbase);
+               if ( ! no_gnu) {
+                       out_printf(outh, " G_GNUC_CONST;\n");
+               } else {
+                       out_printf(outh, ";\n");
+               }
+       }
+
        for(l = c->nodes; l != NULL; l = l->next) {
                Node *n = l->data;
                if(n->type == METHOD_NODE) {
@@ -2284,39 +2556,34 @@ print_class_block(Class *c)
                }
        }
 
-/* this idea is less and less apealing to me */
-#if 0
-       if(!no_signal_connect) {
-               if(signals>0) {
-                       out_printf(outh, "\n/*\n"
-                                  " * Signal connection methods\n"
-                                  " */\n");
-               }
-
-               for(l=c->nodes;l;l=g_list_next(l)) {
-                       Node *n = l->data;
-                       if(n->type == METHOD_NODE)
-                               put_signal_connect((Method *)n);
+       /* this idea is less and less apealing to me */
+       if (signals > 0) {
+               out_printf (outh, "\n/*\n"
+                           " * Signal connection wrapper macros\n"
+                           " */\n");
+               if( ! no_gnu) {
+                       out_printf(outh, "#if defined(__GNUC__) && !defined(__STRICT_ANSI__)\n");
+                       put_signal_macros (c, TRUE);
+                       out_printf(outh, "#else /* __GNUC__ && !__STRICT_ANSI__ */\n");
+                       put_signal_macros (c, FALSE);
+                       out_printf(outh, "#endif /* __GNUC__ && !__STRICT_ANSI__ */\n\n");
+               } else {
+                       put_signal_macros (c, FALSE);
                }
        }
-#endif
-
 
        /* argument wrapping macros */
        if(get_arguments > 0 || set_arguments > 0) {
+               out_printf(outh, "\n/*\n"
+                          " * Argument wrapping macros\n"
+                          " */\n");
                if( ! no_gnu) {
-                       out_printf(outh, "\n/*\n"
-                                  " * Argument wrapping macros\n"
-                                  " */\n");
                        out_printf(outh, "#if defined(__GNUC__) && !defined(__STRICT_ANSI__)\n");
                        put_argument_gnu_wrappers(c);
                        out_printf(outh, "#else /* __GNUC__ && !__STRICT_ANSI__ */\n");
                        put_argument_nongnu_wrappers(c);
                        out_printf(outh, "#endif /* __GNUC__ && !__STRICT_ANSI__ */\n\n");
                } else {
-                       out_printf(outh, "\n/*\n"
-                                  " * Argument wrapping macros\n"
-                                  " */\n");
                        put_argument_nongnu_wrappers(c);
                }
        }
@@ -2331,18 +2598,21 @@ print_class_block(Class *c)
 
        add_enums(c);
 
-       add_get_type();
+       if ( ! overrode_get_type) {
+               if (c->bonobo_x_class != NULL)
+                       add_bonobo_x_get_type ();
+               else
+                       add_get_type ();
+       }
 
        if(any_method_to_alias(c)) {
-               if(no_gnu)
-                       make_method_nongnu_aliases(c);
-               else {
-                       out_printf(out, "\n#if defined(__GNUC__) && !defined(__STRICT_ANSI__)\n");
+               if( ! no_gnu) {
+                       out_printf(out, "/* Short form macros */\n");
+                       out_printf(out, "#if defined(__GNUC__) && !defined(__STRICT_ANSI__)\n");
                        make_method_gnu_aliases(c);
-                       out_printf(out, "#else /* __GNUC__ && !__STRICT_ANSI__ */\n");
-                       make_method_nongnu_aliases(c);
-                       out_printf(out, "#endif /* __GNUC__ && !__STRICT_ANSI__ */\n\n");
+                       out_printf(out, "#endif /* __GNUC__ && !__STRICT_ANSI__ */\n");
                }
+               make_method_nongnu_aliases(c);
        }
 
        out_printf(out, "/* a macro for creating a new object of our type */\n");
@@ -2399,6 +2669,8 @@ print_file_comments(void)
        out_printf(out, "/* Generated by GOB (v%s) on %s"
                   "   (do not edit directly) */\n\n",
                   VERSION, ctime(&curtime));
+
+       out_printf(out, "/* End world hunger, donate to the World Food Programme, http://www.wfp.org */\n\n");
 }
 
 static void
@@ -2582,6 +2854,12 @@ print_help(void)
                "\t--always-private-struct Always create a private pointer "
                                          "in\n"
                "\t                        the object structure\n"
+               "\t--m4                    Preprocess source with m4. "
+                                         "Following args will\n"
+               "\t                        be passed to m4\n"
+               "\t--m4-dir                Print directory that will be "
+                                         "searched for m4\n"
+               "\t                        files\n"
                "\t--no-write,-n           Don't write output files, just "
                                          "check syntax\n"
                "\t--no-lines              Don't print '#line' to output\n"
@@ -2598,11 +2876,43 @@ parse_options(int argc, char *argv[])
        int i;
        int got_file = FALSE;
        int no_opts = FALSE;
+       int m4_opts = FALSE; /* if we are just passing on args to m4 */
 
        filename = NULL;
 
        for(i = 1 ; i < argc; i++) {
-               if(no_opts ||
+               if(m4_opts) {
+                       char *new_commandline;
+                       g_assert(m4_commandline!=NULL);
+
+                       /* check whether this one looks like the filename */
+                       if((!strcmp(argv[i],"-") || argv[i][0] != '-') 
+                          && !got_file) {
+                               const gchar *m4_flags=use_m4_clean?"":M4_FLAGS;
+                               filename = argv[i];
+                               got_file = TRUE;
+                               
+                               /* insert flags before the filename */
+                               new_commandline=g_strconcat(m4_commandline,
+                                                           " ",
+                                                           m4_flags, 
+                                                           " ",
+                                                           argv[i],
+                                                           NULL);
+                       }
+
+                       /* just an ordinary option */
+                       else                      
+                         new_commandline=g_strconcat(m4_commandline,
+                                                     " ",
+                                                     argv[i],
+                                                     NULL);
+
+                       /* free old commandline */
+                       g_free(m4_commandline);
+                       m4_commandline=new_commandline;
+
+               } else if(no_opts ||
                   argv[i][0] != '-') {
                        /*must be a file*/
                        if(got_file) {
@@ -2646,6 +2956,19 @@ parse_options(int argc, char *argv[])
                        no_kill_underscores = TRUE;
                } else if(strcmp(argv[i], "--always-private-struct")==0) {
                        always_private_struct = TRUE;
+               } else if(strcmp(argv[i], "--m4-dir")==0) {
+                       printf("%s\n",M4_INCLUDE_DIR);
+                       exit(0);
+               } else if(strcmp(argv[i], "--m4")==0) {
+                       use_m4 = TRUE;
+                       use_m4_clean=FALSE;
+                       m4_opts = TRUE;
+                       m4_commandline=g_strdup(M4_COMMANDLINE);
+               } else if(strcmp(argv[i], "--m4-clean")==0) {
+                       use_m4 = TRUE;
+                       use_m4_clean=TRUE;
+                       m4_opts = TRUE;
+                       m4_commandline=g_strdup(M4_COMMANDLINE);
                } else if(strcmp(argv[i], "--")==0) {
                        /*further arguments are files*/
                        no_opts = TRUE;
@@ -2679,6 +3002,19 @@ parse_options(int argc, char *argv[])
                        }
                }
        }
+
+#if 0
+       /* if we are using m4, and got no filename, append m4 flags now */
+       if(!got_file && use_m4 && !use_m4_clean) {
+               char *new_commandline;
+               new_commandline=g_strconcat(m4_commandline,
+                                           " ",
+                                           M4_FLAGS,
+                                           NULL);
+               g_free(m4_commandline);
+               m4_commandline=new_commandline;
+       }
+#endif
 }
 
 /* this is a somewhat ugly hack, but it appears to work */
@@ -2717,14 +3053,23 @@ main(int argc, char *argv[])
 {
        parse_options(argc, argv);
        
-       if(filename) {
+       if(use_m4) {
+               yyin = popen(m4_commandline, "r");
+               if(!yyin) {
+                       fprintf(stderr, "Error: can't open pipe from '%s'\n",
+                               m4_commandline);
+                       exit(1);
+               }
+       } else if(filename) {
                yyin = fopen(filename, "r");
                if(!yyin) {
                        fprintf(stderr, "Error: can't open file '%s'\n",
                                filename);
                        exit(1);
                }
-       } else
+       }
+
+       if(filename==NULL)
                filename = "stdin";
 
        /* This is where parsing is done */
@@ -2732,6 +3077,11 @@ main(int argc, char *argv[])
        if(yyparse() != 0)
                g_error("Parsing errors, quitting");
 
+       /* close input file */
+       if(use_m4) pclose(yyin);
+       else fclose(yyin);
+       yyin=stdin;
+
        if( ! class)
                error_print(GOB_ERROR, 0, " no class defined");
        
@@ -2746,6 +3096,7 @@ main(int argc, char *argv[])
        protecteds = count_protecteds((Class *)class);
        destructors = count_destructors((Class *)class);
        initializers = count_initializers((Class *)class);
+       overrode_get_type = find_get_type((Class *)class);
 
        make_bases();
        make_inits((Class *)class);