]> git.draconx.ca Git - gob-dx.git/blobdiff - src/main.c
Release 0.92.2
[gob-dx.git] / src / main.c
index d58aef46636ea6ab001ab8e28e5a1d4144f7fd3c..d86697d83cd8b2852fce037ce075f5740f21628a 100644 (file)
@@ -21,9 +21,6 @@
 
 #include "config.h"
 #include <glib.h>
-#if 0
-#include <popt.h>
-#endif
 #include <time.h>
 #include <stdio.h>
 #include <string.h>
@@ -33,6 +30,9 @@
 #include "tree.h"
 #include "parse.h"
 #include "out.h"
+#include "util.h"
+#include "checks.h"
+
 #include "main.h"
 
 char *filename = NULL;
@@ -77,95 +77,7 @@ gboolean exit_on_error = TRUE;
 gboolean got_error = FALSE;
 gboolean always_private_header = FALSE;
 gboolean no_private_header = FALSE;
-
-void
-print_error(int is_warn, char *error,int line)
-{
-       char *w;
-       if(is_warn)
-               w = "Warning:";
-       else {
-               w = "Error:";
-               got_error = TRUE;
-       }
-       if(line>0)
-               fprintf(stderr,"%s:%d: %s %s\n",filename,line,w,error);
-       else
-               fprintf(stderr,"%s: %s %s\n",filename,w,error);
-       if((!is_warn || exit_on_warn) && exit_on_error)
-               exit(1);
-}
-
-static char *
-remove_sep(char *base)
-{
-       char *p;
-       char *s = g_strdup(base);
-       while((p=strchr(s,':')))
-               strcpy(p,p+1);
-       return s;
-}
-
-static char *
-replace_sep(char *base, char r)
-{
-       char *p;
-       char *s = g_strdup(base);
-       while((p=strchr(s,':')))
-               *p = r;
-       if(*s == r) {
-               p = g_strdup(s+1);
-               g_free(s);
-               return p;
-       }
-       return s;
-}
-
-/*separate the namespace part and then replace rest of
-  separators with r*/
-static void
-separns_replace_sep(char *base, char **ns, char **name, char r)
-{
-       char *p;
-       char *s = g_strdup(base);
-       *ns = NULL;
-       if((p=strchr(s,':')) && p!=s) {
-               *p = '\0';
-               *ns = g_strdup(s);
-               p = g_strdup(p+1);
-               g_free(s);
-               s = p;
-       }
-       while((p=strchr(s,':')))
-               *p = r;
-       if(*s == r) {
-               *name = g_strdup(s+1);
-               g_free(s);
-       } else
-               *name = s;
-}
-
-/* make a macro with some prefix before the name but after
-   namespace */
-static char *
-make_pre_macro(char *base, char *pre)
-{
-       char *s1,*s2;
-       char *s;
-
-       separns_replace_sep(base,&s1,&s2,'_');
-       if(s1)
-               s = g_strconcat(s1,"_",pre,"_",s2,NULL);
-       else
-               s = g_strconcat(pre,"_",s2,NULL);
-
-       g_strup(s);
-       
-       g_free(s1);
-       g_free(s2);
-
-       return s;
-}
+gboolean no_extern_c = FALSE;
 
 static void
 make_bases(void)
@@ -425,7 +337,7 @@ put_priv_method_prot(Method *m)
           m->method == SIGNAL_FIRST_METHOD ||
           m->method == VIRTUAL_METHOD) {
                if(m->cbuf)
-                       print_method(out,"static ","_real_"," ",";\n",m,FALSE);
+                       print_method(out,"static ","___real_"," ",";\n",m,FALSE);
        }
 
        if(m->scope == PRIVATE_SCOPE ||
@@ -533,54 +445,6 @@ make_finalize(Class *cl)
        }
 }
 
-/* here we will find out how inconsistent gtk really is :) */
-/* the commented out types mean that these types don't actually
-   exist. so we "emulate them" with an equivalent */
-const struct {
-       gboolean simple;
-       char *gtkname;
-       char *typename;
-} our_gtk_type_table[] = {
-       { TRUE, "NONE", "void " },
-       { TRUE, "CHAR", "gchar " },
-       { TRUE, "UCHAR",        "guchar " },
-       { TRUE, "BOOL", "gboolean " },
-       { TRUE, "INT",  "gint " },
-       { TRUE, "UINT", "guint " },
-       { TRUE, "LONG", "glong " },
-       { TRUE, "ULONG",        "gulong " },
-       { TRUE, "FLOAT",        "gfloat " },
-       { TRUE, "DOUBLE",       "gdouble " },
-       { TRUE, "STRING",       /*"GtkString"*/"gchar *" },
-       { TRUE, "ENUM", /*"GtkEnum"*/"gint " },
-       { TRUE, "FLAGS",        /*"GtkFlags"*/"guint " },
-       { TRUE, "BOXED",        /*"GtkBoxed"*/"gpointer " },
-       { TRUE, "POINTER",      "gpointer " },
-       { TRUE, "OBJECT",       "GtkObject *" },
-       { FALSE, "SIGNAL",      /*"GtkSignal"*/"___twopointertype " },
-       { FALSE, "ARGS",        /*"GtkArgs"*/"___twopointertype " },
-       { FALSE, "CALLBACK",    /*"GtkCallback"*/"___threepointertype " },
-       { FALSE, "C_CALLBACK",  /*"GtkCCallback"*/"___twopointertype " },
-       { FALSE, "FOREIGN",     /*"GtkForeign"*/"___twopointertype " },
-
-       { FALSE, NULL, NULL }
-};
-
-static const char *
-get_cast(char *type, gboolean simple_only)
-{
-       int i;
-       for(i=0;our_gtk_type_table[i].gtkname;i++) {
-               if(strcmp(our_gtk_type_table[i].gtkname,type)==0) {
-                       if(simple_only &&
-                          !our_gtk_type_table[i].simple)
-                               return NULL;
-                       return our_gtk_type_table[i].typename;
-               }
-       }
-       return NULL;
-}
-
 
 /* hash of method -> name of signal prototype */
 static GHashTable *marsh = NULL;
@@ -673,7 +537,7 @@ add_signal_prots(Method *m)
        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 *, ",
+       out_printf(out,"\ntypedef %s (*___%s) (%s *, ",
                   get_cast(m->gtktypes->data,FALSE),s, typebase);
        
        for(li=m->gtktypes->next;li;li=g_list_next(li))
@@ -688,14 +552,14 @@ add_signal_prots(Method *m)
                "{\n",s);
        
        if(strcmp(m->gtktypes->data,"NONE")==0) {
-               out_printf(out, "\t%s rfunc;\n\n"
-                       "\trfunc = (%s)func;\n\n"
+               out_printf(out, "\t___%s rfunc;\n\n"
+                       "\trfunc = (___%s)func;\n\n"
                        "\t(*rfunc)((%s *)object",s,s,typebase);
        } else {
-               out_printf(out, "\t%s rfunc;\n\t",s);
+               out_printf(out, "\t___%s rfunc;\n\t",s);
                print_type(out,m->mtype,TRUE);
                out_printf(out, " *retval;\n\n"
-                       "\trfunc = (%s)func;\n\n"
+                       "\trfunc = (___%s)func;\n\n"
                        "\tretval = GTK_RETLOC_%s(args[%d]);\n\n"
                        "\t*retval = (*rfunc)((%s *)object",
                        s,(char *)m->gtktypes->data,
@@ -906,7 +770,7 @@ set_def_handlers(Class *c, char *oname)
                                           s,m->id);
                } else {
                        if(m->cbuf)
-                               out_printf(out,"\t%s->%s = _real_%s_%s;\n",
+                               out_printf(out,"\t%s->%s = ___real_%s_%s;\n",
                                        oname,m->id,funcbase,m->id);
                        else
                                out_printf(out,"\t%s->%s = NULL;\n",
@@ -1324,7 +1188,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",m,FALSE);
+               print_method(out,"static ","\n___real_"," ","\n",m,FALSE);
                print_method_body(m,FALSE);
                break;
        case VIRTUAL_METHOD:
@@ -1371,7 +1235,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",m,FALSE);
+               print_method(out,"static ","\n___real_"," ","\n",m,FALSE);
                print_method_body(m,FALSE);
                break;
        case OVERRIDE_METHOD:
@@ -1409,374 +1273,6 @@ put_method(Method *m)
        }
 }
 
-static void
-check_duplicate(Class *c, Node *node, char *id, int line_no)
-{
-       GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
-               Node *n = l->data;
-               char *nid;
-               int nline_no;
-               char *s;
-               if(n->type == METHOD_NODE) {
-                       Method *m = (Method *)n;
-                       nid = m->id;
-                       nline_no = m->line_no;
-               } else if(n->type == VARIABLE_NODE) {
-                       Variable *v = (Variable *)n;
-                       nid = v->id;
-                       nline_no = v->line_no;
-               } else
-                       continue;
-               if(n==node ||
-                  line_no>=nline_no ||
-                  strcmp(nid,id)!=0 ||
-                  n->type != node->type)
-                       continue;
-               s = g_strdup_printf("symbol '%s' redefined, "
-                                   "first defined on line %d",
-                                   id,line_no);
-               print_error(FALSE,s,nline_no);
-       }
-}
-
-static void
-check_duplicate_symbols(Class *c)
-{
-       GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
-               Node *n = l->data;
-               if(n->type == METHOD_NODE) {
-                       Method *m = (Method *)n;
-                       check_duplicate(c,n,m->id,m->line_no);
-               } else if(n->type == VARIABLE_NODE) {
-                       Variable *v = (Variable *)n;
-                       check_duplicate(c,n,v->id,v->line_no);
-               }
-       }
-}
-
-static void
-check_bad_symbols(Class *c)
-{
-       GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
-               Node *n = l->data;
-               if(n->type == METHOD_NODE) {
-                       Method *m = (Method *)n;
-                       if((m->method == SIGNAL_LAST_METHOD ||
-                           m->method == SIGNAL_FIRST_METHOD ||
-                           m->method == VIRTUAL_METHOD) &&
-                          strcmp(m->id,"__parent__")==0) {
-                               char *s;
-                               s = g_strdup_printf("'%s' not allowed as an "
-                                                   "identifier of signal "
-                                                   "or virtual methods",
-                                                   m->id);
-                               print_error(FALSE,s,m->line_no);
-                               g_free(s);
-                       }
-                       if(m->method != INIT_METHOD &&
-                          m->method != CLASS_INIT_METHOD &&
-                          (strcmp(m->id,"init")==0 ||
-                           strcmp(m->id,"class_init")==0)) {
-                               print_error(FALSE,"init, or class_init not "
-                                           "allowed as an "
-                                           "identifier of non-"
-                                           "constructor methods",m->line_no);
-                       }
-               } else if(n->type == VARIABLE_NODE) {
-                       Variable *v = (Variable *)n;
-                       if(strcmp(v->id,"_priv")==0 ||
-                          strcmp(v->id,"__parent__")==0) {
-                               char *s;
-                               s = g_strdup_printf("'%s' not allowed as a "
-                                                   "data member name",v->id);
-                               print_error(FALSE,s,v->line_no);
-                               g_free(s);
-                       }
-               }
-       }
-}
-
-
-static void
-check_duplicate_named(Class *c,Node *node,char *id, int line_no)
-{
-       GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
-               Node *n = l->data;
-               char *nid;
-               int nline_no;
-               char *s;
-               if(n->type == METHOD_NODE) {
-                       Method *m = (Method *)n;
-                       if(m->method == SIGNAL_LAST_METHOD ||
-                          m->method == SIGNAL_FIRST_METHOD) {
-                               nid = m->id;
-                               nline_no = m->line_no;
-                       } else
-                               continue;
-               } else if(n->type == ARGUMENT_NODE) {
-                       Argument *a = (Argument *)n;
-                       nid = a->name;
-                       nline_no = a->line_no;
-               } else
-                       continue;
-               if(n==node ||
-                  line_no>=nline_no ||
-                  strcmp(nid,id)!=0)
-                       continue;
-               s = g_strdup_printf("named symbol (argument or signal) '%s' "
-                                   "redefined, first defined on line %d",
-                                   id,line_no);
-               print_error(FALSE,s,nline_no);
-       }
-}
-
-static void
-check_duplicate_signals_args(Class *c)
-{
-       GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
-               Node *n = l->data;
-               if(n->type == METHOD_NODE) {
-                       Method *m = (Method *)n;
-                       if(m->method == SIGNAL_LAST_METHOD ||
-                          m->method == SIGNAL_FIRST_METHOD)
-                               check_duplicate_named(c,n,m->id,m->line_no);
-               } else if(n->type == ARGUMENT_NODE) {
-                       Argument *a = (Argument *)n;
-                       check_duplicate_named(c,n,a->name,a->line_no);
-               }
-       }
-}
-
-static void
-check_public_new(Class *c)
-{
-       GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
-               Node *n = l->data;
-               if(n->type == METHOD_NODE) {
-                       Method *m = (Method *)n;
-                       if((strcmp(m->id,"new")==0) &&
-                          (m->method != REGULAR_METHOD ||
-                           m->scope != PUBLIC_SCOPE))
-                               print_error(TRUE,
-                                           "'new' should be a regular\n"
-                                           "public method",
-                                           m->line_no);
-               }
-       }
-}
-
-static void
-check_vararg(Class *c)
-{
-       GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
-               Node *n = l->data;
-               if(n->type == METHOD_NODE) {
-                       Method *m = (Method *)n;
-                       if(!m->vararg)
-                               continue;
-                       if(m->method == OVERRIDE_METHOD ||
-                          m->method == SIGNAL_LAST_METHOD ||
-                          m->method == SIGNAL_FIRST_METHOD ||
-                          m->method == VIRTUAL_METHOD) {
-                               print_error(FALSE,
-                                           "signals, overrides and virtuals, "
-                                           "can't have variable argument "
-                                           "lists",
-                                           m->line_no);
-                       }
-               }
-       }
-}
-
-static void
-check_firstarg(Class *c)
-{
-       GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
-               Node *n = l->data;
-               if(n->type == METHOD_NODE) {
-                       Method *m = (Method *)n;
-                       if(m->args)
-                               continue;
-                       if(m->method == OVERRIDE_METHOD ||
-                          m->method == SIGNAL_LAST_METHOD ||
-                          m->method == SIGNAL_FIRST_METHOD ||
-                          m->method == VIRTUAL_METHOD) {
-                               print_error(FALSE,
-                                           "signals, overrides and virtuals, "
-                                           "can't have no arguments",
-                                           m->line_no);
-                       }
-               }
-       }
-}
-
-static void
-check_nonvoidempty(Class *c)
-{
-       GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
-               Node *n = l->data;
-               if(n->type == METHOD_NODE) {
-                       Method *m = (Method *)n;
-                       if(m->method != REGULAR_METHOD)
-                               continue;
-                       if(!(strcmp(m->mtype->name,"void")==0 &&
-                            m->mtype->stars == 0) &&
-                          !m->cbuf) {
-                               print_error(TRUE,
-                                           "non-void empty method found, "
-                                           "regular non-void function should "
-                                           "not be empty.",
-                                           m->line_no);
-                               /* add a body here, so that the user will also
-                                  get a warning from gcc, and so that it will
-                                  at least point him to the prototype of the
-                                  function in the .gob file */
-                               m->cbuf = g_strdup("/*empty*/");
-                               m->ccode_line = m->line_no;
-                       }
-               }
-       }
-}
-
-static void
-check_signal_args(Class *c)
-{
-       GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
-               Node *n = l->data;
-               if(n->type == METHOD_NODE) {
-                       Method *m = (Method *)n;
-                       GList *l;
-                       if(m->method != SIGNAL_LAST_METHOD &&
-                          m->method != SIGNAL_FIRST_METHOD)
-                               continue;
-
-                       for(l=m->gtktypes;l;l=l->next) {
-                               char *s;
-                               if(get_cast(l->data,FALSE))
-                                       continue;
-                               s = g_strdup_printf("Unknown GTK+ type '%s' "
-                                                   "among signal types",
-                                                   (char *)l->data);
-                               print_error(FALSE, s, m->line_no);
-                               g_free(s);
-                       }
-               }
-       }
-}
-
-static void
-check_argument_types(Class *c)
-{
-       GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
-               Node *n = l->data;
-               if(n->type == ARGUMENT_NODE) {
-                       Argument *a = (Argument *)n;
-                       char *s;
-                       if(get_cast(a->gtktype,FALSE))
-                               continue;
-                       s = g_strdup_printf("Unknown GTK+ type '%s' "
-                                           "as argument type",
-                                           a->gtktype);
-                       /* this could perhaps be a warning, but
-                          can there really be a type beyond the
-                          fundementals? */
-                       print_error(FALSE, s, a->line_no);
-                       g_free(s);
-               }
-       }
-}
-
-static int
-count_signals(Class *c)
-{
-       int num = 0;
-       GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
-               Node *n = l->data;
-               if(n->type == METHOD_NODE) {
-                       Method *m = (Method *)n;
-                       if(m->method == SIGNAL_LAST_METHOD ||
-                          m->method == SIGNAL_FIRST_METHOD)
-                               num++;
-               }
-       }
-       return num;
-}
-
-static int
-count_arguments(Class *c)
-{
-       int num = 0;
-       GList *li;
-
-       for(li=c->nodes;li;li=g_list_next(li)) {
-               Node *n = li->data;
-               if(n->type == ARGUMENT_NODE)
-                       num ++;
-       }
-       return num;
-}
-
-static int
-count_overrides(Class *c)
-{
-       int num = 0;
-       GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
-               Node *n = l->data;
-               if(n->type == METHOD_NODE) {
-                       Method *m = (Method *)n;
-                       if(m->method == OVERRIDE_METHOD)
-                               num++;
-               }
-       }
-       return num;
-}
-
-static int
-count_privates(Class *c)
-{
-       int num = 0;
-       GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
-               Node *n = l->data;
-               if(n->type == VARIABLE_NODE) {
-                       Variable *v = (Variable *)n;
-                       if(v->scope == PRIVATE_SCOPE)
-                               num++;
-               }
-       }
-       return num;
-}
-
-static int
-count_protecteds(Class *c)
-{
-       int num = 0;
-       GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
-               Node *n = l->data;
-               if(n->type == METHOD_NODE) {
-                       Method *m = (Method *)n;
-                       if(m->scope == PROTECTED_SCOPE)
-                               num++;
-               }
-       }
-       return num;
-}
-
-
 static void
 open_files(void)
 {
@@ -1906,13 +1402,237 @@ put_argument_gnu_wrappers(Class *c)
 }
 
 static void
-generate_outfiles(void)
+print_ccode_block(CCode *cc)
+{
+       FILE *fp;
+       switch(cc->cctype) {
+       case HT_CCODE:
+               /* HT code is printed exactly like normal header
+                  code but is printed before */
+       case H_CCODE:
+               fp = outh;
+               out_printf(fp,"\n");
+               break;
+       default:
+       case C_CCODE:
+               fp = out;
+               out_printf(fp,"\n");
+               out_addline_infile(fp,cc->line_no);
+               break;
+       case PH_CCODE:
+               if(outph)
+                       fp = outph;
+               else
+                       fp = out;
+               out_printf(fp,"\n");
+               out_addline_infile(fp,cc->line_no);
+               break;
+       }
+       out_printf(fp,"%s\n",cc->cbuf);
+       if(cc->cctype == C_CCODE ||
+          cc->cctype == PH_CCODE)
+               out_addline_outfile(fp);
+}
+
+static void
+print_class_block(Class *c)
 {
-       char *p;
-       GList *li;
-       time_t curtime;
-       gboolean found_header;
+       GList *l;
+       char *s;
+
+       out_printf(out,"/* utility types we may need */\n");
+       out_printf(out,"typedef struct { "
+                  "gpointer a; gpointer b; "
+                  "} ___twopointertype;\n");
+       out_printf(out,"typedef struct { "
+                  "gpointer a; gpointer b; "
+                  "gpointer c; "
+                  "} ___threepointertype;\n");
+
+       out_printf(outh,"\n#define %s\t"
+                  "(%s_get_type())\n",
+                  macrotype,funcbase);
+       out_printf(outh,"#define %s(obj)\t"
+                  "GTK_CHECK_CAST((obj),%s_get_type(),%s)\n",
+                  macrobase,funcbase,typebase);
+       out_printf(outh,"#define %s_CLASS(klass)\t"
+                  "GTK_CHECK_CLASS_CAST((klass),%s_get_type(),%sClass)\n",
+                  macrobase,funcbase,typebase);
+       out_printf(outh,"#define %s(obj)\t"
+                  "GTK_CHECK_TYPE((obj), %s_get_type ())\n\n",
+                  macrois,funcbase);
+
+       /* argument wrapping macros */
+       if(arguments>0 && !no_gnu) {
+               out_printf(outh,"\n#ifdef __GNUC__\n");
+               put_argument_gnu_wrappers(c);
+               out_printf(outh,"#else /* __GNUC__ */\n");
+               put_argument_nongnu_wrappers(c);
+               out_printf(outh,"#endif /* __GNUC__ */\n\n");
+       } else if(arguments>0 && no_gnu) {
+               put_argument_nongnu_wrappers(c);
+       }
+
+       if(privates>0)
+               out_printf(outh,"\ntypedef struct _%sPrivate %sPrivate;\n",typebase,typebase);
+
+       s = replace_sep(c->otype,'_');
+       g_strup(s);
+       out_printf(outh,"#ifndef __TYPEDEF_%s__\n"
+                  "#define __TYPEDEF_%s__\n",s,s);
+       g_free(s);
+       out_printf(outh,"typedef struct _%s %s;\n"
+                  "#endif\n",typebase,typebase);
+       out_printf(outh,"struct _%s {\n\t%s __parent__;\n",
+                  typebase,ptypebase);
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               Variable *v = (Variable *)n;
+               if(n->type == VARIABLE_NODE &&
+                  v->scope == PUBLIC_SCOPE)
+                       put_variable((Variable *)n,outh);
+       }
+       /* put protecteds always AFTER publics */
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               Variable *v = (Variable *)n;
+               if(n->type == VARIABLE_NODE &&
+                  v->scope == PROTECTED_SCOPE)
+                       put_variable((Variable *)n,outh);
+       }
+       if(privates>0)
+               out_printf(outh,"\t%sPrivate *_priv;\n",typebase);
+       out_printf(outh,"};\n");
+
+       if(privates>0) {
+               FILE *outfp;
+
+               /* if we are to stick this into the private
+                  header, if not stick it directly into the
+                  C file */
+               if(outph) 
+                       outfp = outph;
+               else
+                       outfp = out;
+
+               out_printf(outfp,"struct _%sPrivate {\n",
+                          typebase);
+               for(l=c->nodes;l;l=l->next) {
+                       Node *n = l->data;
+                       Variable *v = (Variable *)n;
+                       if(n->type == VARIABLE_NODE &&
+                          v->scope == PRIVATE_SCOPE) {
+                               out_addline_infile(outfp,v->line_no);
+                               put_variable(v,outfp);
+                       }
+               }
+               out_addline_outfile(outfp);
+               out_printf(outfp,"};\n");
+       }
+
+       out_printf(outh,"\ntypedef struct _%sClass %sClass;\n",
+                  typebase,typebase);
+       out_printf(outh,
+                  "struct _%sClass {\n\t%sClass __parent__;\n",
+                  typebase,ptypebase);
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               if(n->type == METHOD_NODE)
+                       put_vs_method((Method *)n);
+       }
+       out_printf(outh,"};\n\n");
+
+       out_printf(outh,"guint\t%s_get_type\t(void);\n",funcbase);
+
+       out_printf(out,"/* here are local prototypes */\n");
+       if(!no_gnu) {
+               out_printf(out,"#ifdef __GNUC__\n"
+                          "#define ___NO_UNUSED_WARNING "
+                          "__attribute__ ((__unused__))\n"
+                          "#else /* __GNUC__ */\n"
+                          "#define ___NO_UNUSED_WARNING\n"
+                          "#endif /* __GNUC__ */\n");
+       }
+       if(arguments>0) {
+               out_printf(out,"static void ___object_set_arg "
+                          "(GtkObject *object, GtkArg *arg, "
+                          "guint arg_id);\n"
+                          "static void ___object_get_arg "
+                          "(GtkObject *object, GtkArg *arg, "
+                          "guint arg_id);\n");
+       }
+
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               if(n->type == METHOD_NODE) {
+                       put_pub_method((Method *)n);
+                       put_prot_method((Method *)n);
+                       put_priv_method_prot((Method *)n);
+               }
+       }
+
+       if(signals>0) {
+               for(l=c->nodes;l;l=g_list_next(l)) {
+                       Node *n = l->data;
+                       if(n->type == METHOD_NODE)
+                               add_signal_prots((Method *)n);
+               }
+       }
+
+       if(!no_gnu)
+               out_printf(out,"#undef ___NO_UNUSED_WARNING\n");
+
+       add_enums(c);
+
+       add_get_type();
+
+       if(no_gnu)
+               make_method_nongnu_aliases(c);
+       else {
+               out_printf(out,"\n#ifdef __GNUC__\n");
+               make_method_gnu_aliases(c);
+               out_printf(out,"#else /* __GNUC__ */\n");
+               make_method_nongnu_aliases(c);
+               out_printf(out,"#endif /* __GNUC__ */\n\n");
+       }
 
+       out_printf(out,"#define GET_NEW (gtk_type_new(%s_get_type()))\n",
+                  funcbase);
+
+       add_inits(c);
+
+       if(arguments>0) {
+               add_getset_arg(c, TRUE);
+               add_getset_arg(c, FALSE);
+       }
+
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               if(n->type == METHOD_NODE) {
+                       put_method((Method *)n);
+               }
+       }
+
+       out_printf(out,"#undef GET_NEW\n");
+
+       add_bad_hack_to_avoid_unused_warnings(c);
+}
+
+static void
+print_version_macros(void)
+{
+       int major=0,minor=0,pl=0;
+       sscanf(VERSION,"%d.%d.%d",&major,&minor,&pl);
+
+       out_printf(out,"#define GOB_VERSION_MAJOR %d\n", major);
+       out_printf(out,"#define GOB_VERSION_MINOR %d\n", minor);
+       out_printf(out,"#define GOB_VERSION_PATCHLEVEL %d\n\n", pl);
+}
+
+static void
+print_file_comments(void)
+{
+       time_t curtime;
        time(&curtime);
        out_printf(outh,"/* Generated by GOB (v%s)"
               "   (do not edit directly) */\n\n",VERSION);
@@ -1921,36 +1641,14 @@ generate_outfiles(void)
                           "   (do not edit directly) */\n\n",VERSION);
        out_printf(out,"/* Generated by GOB (v%s) on %s"
               "   (do not edit directly) */\n\n",VERSION,ctime(&curtime));
+}
 
-       {
-               int major=0,minor=0,pl=0;
-               sscanf(VERSION,"%d.%d.%d",&major,&minor,&pl);
-
-               out_printf(out,"#define GOB_VERSION_MAJOR %d\n", major);
-               out_printf(out,"#define GOB_VERSION_MINOR %d\n", minor);
-               out_printf(out,"#define GOB_VERSION_PATCHLEVEL %d\n\n", pl);
-       }
-       
-       p = replace_sep(((Class *)class)->otype,'_');
-       g_strup(p);
-       out_printf(outh,"#ifndef __%s_H__\n#define __%s_H__\n\n"
-               "#include <gtk/gtk.h>\n\n",p,p);
-       if(outph)
-               out_printf(outph,"#ifndef __%s_PRIVATE_H__\n"
-                          "#define __%s_PRIVATE_H__\n\n"
-                          "#include \"%s.h\"\n\n",p,p,filebase);
-       g_free(p);
+static void
+print_includes(void)
+{
+       gboolean found_header;
+       char *p;
 
-       if(!for_cpp) {
-               out_printf(outh,"#ifdef __cplusplus\n"
-                          "extern \"C\" {\n"
-                          "#endif /* __cplusplus */\n\n");
-               if(outph)
-                       out_printf(outph,"#ifdef __cplusplus\n"
-                                  "extern \"C\" {\n"
-                                  "#endif /* __cplusplus */\n\n");
-       }
-       
        p = g_strconcat(filebase,".h",NULL);
        found_header = TRUE;
        if(!g_list_find_custom(include_files,p,(GCompareFunc)strcmp)) {
@@ -1978,208 +1676,43 @@ generate_outfiles(void)
                }
                g_free(p);
        }
+}
 
-       for(li=nodes;li;li=g_list_next(li)) {
-               Node *node = li->data;
-               if(node->type == CCODE_NODE) {
-                       CCode *cc = (CCode *)node;
-                       FILE *fp;
-                       if(cc->header) {
-                               fp = outh;
-                               out_printf(fp,"\n");
-                       } else {
-                               fp = out;
-                               out_printf(fp,"\n");
-                               out_addline_infile(fp,cc->line_no);
-                       }
-                       out_printf(fp,"%s\n",cc->cbuf);
-                       if(!cc->header)
-                               out_addline_outfile(fp);
-               } else if(node->type == CLASS_NODE) {
-                       Class *c = (Class *)class;
-                       GList *l;
-
-                       out_printf(out,"/* utility types we may need */\n");
-                       out_printf(out,"typedef struct { "
-                                  "gpointer a; gpointer b; "
-                                  "} ___twopointertype;\n");
-                       out_printf(out,"typedef struct { "
-                                  "gpointer a; gpointer b; "
-                                  "gpointer c; "
-                                  "} ___threepointertype;\n");
-
-                       out_printf(outh,"\n#define %s\t"
-                               "(%s_get_type())\n",
-                               macrotype,funcbase);
-                       out_printf(outh,"#define %s(obj)\t"
-                               "GTK_CHECK_CAST((obj),%s_get_type(),%s)\n",
-                               macrobase,funcbase,typebase);
-                       out_printf(outh,"#define %s_CLASS(klass)\t"
-                               "GTK_CHECK_CLASS_CAST((klass),%s_get_type(),%sClass)\n",
-                               macrobase,funcbase,typebase);
-                       out_printf(outh,"#define %s(obj)\t"
-                               "GTK_CHECK_TYPE((obj), %s_get_type ())\n\n",
-                               macrois,funcbase);
-
-                       /* argument wrapping macros */
-                       if(arguments>0 && !no_gnu) {
-                               out_printf(outh,"\n#ifdef __GNUC__\n");
-                               put_argument_gnu_wrappers(c);
-                               out_printf(outh,"#else /* __GNUC__ */\n");
-                               put_argument_nongnu_wrappers(c);
-                               out_printf(outh,"#endif /* __GNUC__ */\n\n");
-                       } else if(arguments>0 && no_gnu) {
-                               put_argument_nongnu_wrappers(c);
-                       }
-
-                       if(privates>0)
-                               out_printf(outh,"\ntypedef struct _%sPrivate %sPrivate;\n",typebase,typebase);
-
-                       out_printf(outh,"\ntypedef struct _%s %s;\n",typebase,typebase);
-                       out_printf(outh,"struct _%s {\n\t%s __parent__;\n",
-                                  typebase,ptypebase);
-                       for(l=c->nodes;l;l=g_list_next(l)) {
-                               Node *n = l->data;
-                               Variable *v = (Variable *)n;
-                               if(n->type == VARIABLE_NODE &&
-                                  v->scope == PUBLIC_SCOPE)
-                                       put_variable((Variable *)n,outh);
-                       }
-                       /* put protecteds always AFTER publics */
-                       for(l=c->nodes;l;l=g_list_next(l)) {
-                               Node *n = l->data;
-                               Variable *v = (Variable *)n;
-                               if(n->type == VARIABLE_NODE &&
-                                  v->scope == PROTECTED_SCOPE)
-                                       put_variable((Variable *)n,outh);
-                       }
-                       if(privates>0)
-                               out_printf(outh,"\t%sPrivate *_priv;\n",typebase);
-                       out_printf(outh,"};\n");
-
-                       if(privates>0) {
-                               FILE *outfp;
-
-                               /* if we are to stick this into the private
-                                  header, if not stick it directly into the
-                                  C file */
-                               if(outph) 
-                                       outfp = outph;
-                               else
-                                       outfp = out;
-
-                               out_printf(outfp,"struct _%sPrivate {\n",
-                                          typebase);
-                               for(l=c->nodes;l;l=l->next) {
-                                       Node *n = l->data;
-                                       Variable *v = (Variable *)n;
-                                       if(n->type == VARIABLE_NODE &&
-                                          v->scope == PRIVATE_SCOPE) {
-                                               out_addline_infile(outfp,v->line_no);
-                                               put_variable(v,outfp);
-                                       }
-                               }
-                               out_addline_outfile(outfp);
-                               out_printf(outfp,"};\n");
-                       }
-
-                       out_printf(outh,"\ntypedef struct _%sClass %sClass;\n",
-                               typebase,typebase);
-                       out_printf(outh,
-                               "struct _%sClass {\n\t%sClass __parent__;\n",
-                               typebase,ptypebase);
-                       for(l=c->nodes;l;l=g_list_next(l)) {
-                               Node *n = l->data;
-                               if(n->type == METHOD_NODE)
-                                       put_vs_method((Method *)n);
-                       }
-                       out_printf(outh,"};\n\n");
-
-                       out_printf(outh,"guint\t%s_get_type\t(void);\n",funcbase);
-                       
-                       out_printf(out,"/* here are local prototypes */\n");
-                       if(!no_gnu) {
-                               out_printf(out,"#ifdef __GNUC__\n"
-                                          "#define ___NO_UNUSED_WARNING "
-                                          "__attribute__ ((__unused__))\n"
-                                          "#else /* __GNUC__ */\n"
-                                          "#define ___NO_UNUSED_WARNING\n"
-                                          "#endif /* __GNUC__ */\n");
-                       }
-                       if(arguments>0) {
-                               out_printf(out,"static void ___object_set_arg "
-                                          "(GtkObject *object, GtkArg *arg, "
-                                          "guint arg_id);\n"
-                                          "static void ___object_get_arg "
-                                          "(GtkObject *object, GtkArg *arg, "
-                                          "guint arg_id);\n");
-                       }
-
-                       for(l=c->nodes;l;l=g_list_next(l)) {
-                               Node *n = l->data;
-                               if(n->type == METHOD_NODE) {
-                                       put_pub_method((Method *)n);
-                                       put_prot_method((Method *)n);
-                                       put_priv_method_prot((Method *)n);
-                               }
-                       }
-
-                       if(signals>0) {
-                               for(l=c->nodes;l;l=g_list_next(l)) {
-                                       Node *n = l->data;
-                                       if(n->type == METHOD_NODE)
-                                               add_signal_prots((Method *)n);
-                               }
-                       }
-
-                       if(!no_gnu)
-                               out_printf(out,"#undef ___NO_UNUSED_WARNING\n");
-                       
-                       add_enums(c);
-                       
-                       add_get_type();
-
-                       if(no_gnu)
-                               make_method_nongnu_aliases(c);
-                       else {
-                               out_printf(out,"\n#ifdef __GNUC__\n");
-                               make_method_gnu_aliases(c);
-                               out_printf(out,"#else /* __GNUC__ */\n");
-                               make_method_nongnu_aliases(c);
-                               out_printf(out,"#endif /* __GNUC__ */\n\n");
-                       }
-
-                       out_printf(out,"#define GET_NEW (gtk_type_new(%s_get_type()))\n",
-                                  funcbase);
-
-                       add_inits(c);
-
-                       if(arguments>0) {
-                               add_getset_arg(c, TRUE);
-                               add_getset_arg(c, FALSE);
-                       }
-
-                       for(l=c->nodes;l;l=g_list_next(l)) {
-                               Node *n = l->data;
-                               if(n->type == METHOD_NODE) {
-                                       put_method((Method *)n);
-                               }
-                       }
+static void
+print_header_prefixes(void)
+{
+       char *p;
 
-                       out_printf(out,"#undef GET_NEW\n");
+       p = replace_sep(((Class *)class)->otype,'_');
+       g_strup(p);
+       out_printf(outh,"#ifndef __%s_H__\n#define __%s_H__\n\n",p,p);
+       if(outph)
+               out_printf(outph,"#ifndef __%s_PRIVATE_H__\n"
+                          "#define __%s_PRIVATE_H__\n\n"
+                          "#include \"%s.h\"\n\n",p,p,filebase);
+       g_free(p);
 
-                       add_bad_hack_to_avoid_unused_warnings(c);
-               } else
-                       g_assert_not_reached();
+       if(!no_extern_c) {
+               out_printf(outh,"#ifdef __cplusplus\n"
+                          "extern \"C\" {\n"
+                          "#endif /* __cplusplus */\n\n");
+               if(outph)
+                       out_printf(outph,"#ifdef __cplusplus\n"
+                                  "extern \"C\" {\n"
+                                  "#endif /* __cplusplus */\n\n");
        }
+}
 
-       if(!for_cpp)
+static void
+print_header_postfixes(void)
+{
+       if(!no_extern_c)
                out_printf(outh,"\n#ifdef __cplusplus\n"
                           "}\n"
                           "#endif /* __cplusplus */\n");
        out_printf(outh,"\n#endif");
        if(outph) {
-               if(!for_cpp)
+               if(!no_extern_c)
                        out_printf(outph,"\n#ifdef __cplusplus\n"
                                   "}\n"
                                   "#endif /* __cplusplus */\n");
@@ -2187,15 +1720,54 @@ generate_outfiles(void)
        }
 }
 
-#if 0
 static void
-usage(poptContext optCon, int exitcode, char *error, char *addl)
+print_header_top(void)
+{
+       GList *li;
+
+       /* mandatory include */
+       out_printf(outh,"#include <gtk/gtk.h>\n\n");
+
+       /* print the HT_CCODE blocks */
+       for(li=nodes;li;li=g_list_next(li)) {
+               Node *node = li->data;
+               if(node->type == CCODE_NODE) {
+                       CCode *cc = (CCode *)node;
+                       if(cc->cctype==HT_CCODE)
+                               print_ccode_block((CCode *)node);
+               }
+       }
+}
+
+static void
+generate_outfiles(void)
 {
-       poptPrintUsage(optCon, stderr, 0);
-       if (error) fprintf(stderr, "%s: %s", error, addl);
-       exit(exitcode);
+       GList *li;
+
+       print_file_comments();
+
+       print_header_top();
+
+       print_header_prefixes();
+
+       print_version_macros();
+       
+       print_includes();
+
+       for(li=nodes;li;li=g_list_next(li)) {
+               Node *node = li->data;
+               if(node->type == CCODE_NODE) {
+                       CCode *cc = (CCode *)node;
+                       if(cc->cctype!=HT_CCODE)
+                               print_ccode_block((CCode *)node);
+               } else if(node->type == CLASS_NODE) {
+                       print_class_block((Class *)node);
+               } else
+                       g_assert_not_reached();
+       }
+
+       print_header_postfixes();
 }
-#endif
 
 static void
 print_help(void)
@@ -2207,6 +1779,8 @@ print_help(void)
                "\t--exit-on-warn,-w       Exit with an error on warnings\n"
                "\t--no-exit-on-warn       Don't exit on warnings [default]\n"
                "\t--for-cpp               Create C++ files\n"
+               "\t--no-extern-c           Never print extern \"C\" into the "
+                                         "header\n"
                "\t--no-gnu                Never use GNU extentions\n"
                "\t--no-touch-headers      Don't touch headers unless they "
                                          "really changed\n"
@@ -2260,6 +1834,8 @@ parse_options(int argc, char *argv[])
                        no_private_header = TRUE;
                } else if(strcmp(argv[i],"--no-gnu")==0) {
                        no_gnu = TRUE;
+               } else if(strcmp(argv[i],"--no-extern-c")==0) {
+                       no_extern_c = TRUE;
                } else if(strcmp(argv[i],"--")==0) {
                        /*further arguments are files*/
                        no_opts = TRUE;
@@ -2323,37 +1899,6 @@ compare_and_move_header(void)
 int
 main(int argc, char *argv[])
 {
-#if 0
-       int c;
-       poptContext optCon;
-       
-       struct poptOption optionsTable[] = {
-               { "exit-on-warn", 'w', 0, &exit_on_warn, 0,
-                        "exit on warnings" },
-               POPT_AUTOHELP
-               { NULL, 0, 0, NULL, 0 }
-       };
-       
-       optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
-       poptSetOtherOptionHelp(optCon, "[OPTIONS]* [filename]");
-       
-       while ((c = poptGetNextOpt(optCon)) >= 0)
-               ;
-       
-       filename = poptGetArg(optCon);
-       if(!(poptPeekArg(optCon) == NULL))
-               usage(optCon, 1, "Specify only one file",
-                     ".e.g., filename.gob");
-                       
-       if (c < -1) {
-               /* an error occurred during option processing */
-               fprintf(stderr, "%s: %s\n",
-                       poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
-                       poptStrerror(c));
-               return 1;
-       }
-#endif
-
        parse_options(argc,argv);
        
        if(filename) {
@@ -2410,8 +1955,5 @@ main(int argc, char *argv[])
        if(no_touch_headers)
                compare_and_move_header();
        
-#if 0
-       poptFreeContext(optCon);
-#endif
        return 0;
 }