X-Git-Url: https://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/774037b15064dcc6e4995c0bba3b24abb1bde35f..486240dc4c5d57b0afaddba60d87fe375112bed5:/src/main.c diff --git a/src/main.c b/src/main.c index d58aef4..691d5df 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,6 @@ /* GOB C Preprocessor - * Copyright (C) 1999 the Free Software Foundation. + * Copyright (C) 1999,2000 the Free Software Foundation. + * Copyright (C) 2000 Eazel, Inc. * * Author: George Lebl * @@ -21,18 +22,19 @@ #include "config.h" #include -#if 0 -#include -#endif #include #include #include #include +#include #include -#include "tree.h" +#include "treefuncs.h" #include "parse.h" #include "out.h" +#include "util.h" +#include "checks.h" + #include "main.h" char *filename = NULL; @@ -46,6 +48,8 @@ extern GList *nodes; extern GList *include_files; +extern GHashTable *gtk_doc_hash; + char *filebase; static char *funcbase; static char *pfuncbase; @@ -60,14 +64,27 @@ static int arguments = 0; /* number of named arguments */ static int overrides = 0; /* number of override methods */ 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 made_aliases = FALSE; /* if we made any shorthand aliases and need the REALLY UGLY HACK to avoid warnings */ +/* the special variable types we need to define */ +static gboolean special_array[SPECIAL_LAST] = {0}; +static gboolean any_special = FALSE; + +static gboolean need_destroy = FALSE; +static Method * destroy_handler = NULL; + +static gboolean need_finalize = FALSE; +static Method * finalize_handler = NULL; + FILE *out = NULL; FILE *outh = NULL; FILE *outph = NULL; +FILE *devnull = NULL; gboolean no_touch_headers = FALSE; gboolean for_cpp = FALSE; @@ -75,115 +92,33 @@ gboolean no_gnu = FALSE; gboolean exit_on_warn = FALSE; 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); +gint private_header = PRIVATE_HEADER_ALWAYS; +gboolean no_extern_c = FALSE; +gboolean no_write = FALSE; +gboolean no_lines = FALSE; +gboolean no_self_alias = FALSE; +gboolean no_kill_underscores = FALSE; +gboolean always_private_struct = FALSE; - return s; -} +int method_unique_id = 1; static void make_bases(void) { - filebase = replace_sep(((Class *)class)->otype,'-'); + filebase = replace_sep(((Class *)class)->otype, '-'); g_strdown(filebase); - funcbase = replace_sep(((Class *)class)->otype,'_'); + funcbase = replace_sep(((Class *)class)->otype, '_'); g_strdown(funcbase); - pfuncbase = replace_sep(((Class *)class)->ptype,'_'); + pfuncbase = replace_sep(((Class *)class)->ptype, '_'); g_strdown(pfuncbase); - macrobase = replace_sep(((Class *)class)->otype,'_'); + macrobase = replace_sep(((Class *)class)->otype, '_'); g_strup(macrobase); - macrois = make_pre_macro(((Class *)class)->otype,"IS"); - macrotype = make_pre_macro(((Class *)class)->otype,"TYPE"); + macrois = make_pre_macro(((Class *)class)->otype, "IS"); + macrotype = make_pre_macro(((Class *)class)->otype, "TYPE"); typebase = remove_sep(((Class *)class)->otype); @@ -202,7 +137,6 @@ get_type(Type *t, gboolean postfix_to_stars) gs = g_string_new(s); g_free(s); - extra = 0; if(postfix_to_stars) { char *p; @@ -213,62 +147,121 @@ get_type(Type *t, gboolean postfix_to_stars) for(p=t->postfix; p && *p; p++) if(*p == '[') extra++; } - g_string_append_c(gs,' '); - - for(i=0;i<(t->stars+extra);i++) - g_string_append_c(gs,'*'); + g_string_append_c(gs, ' '); + if(t->pointer) { + g_string_append(gs, t->pointer); + for(i=0; i < extra; i++) + g_string_append_c(gs, '*'); + g_string_append_c(gs, ' '); + } + s = gs->str; - g_string_free(gs,FALSE); + g_string_free(gs, FALSE); return s; } +static char * +get_gtk_doc(char *id) +{ + char *val, *s; + + if(!gtk_doc_hash) + return NULL; + + val = g_hash_table_lookup(gtk_doc_hash, id); + if(val) + return g_strdup_printf("/**\n * %s_%s:\n%s **/\n", + funcbase, get_real_id(id), val); + s = g_strconcat(funcbase, "_", get_real_id(id), NULL); + val = g_hash_table_lookup(gtk_doc_hash, s); + g_free(s); + if(val) + return g_strdup_printf("/**\n * %s_%s:\n%s **/\n", + funcbase, get_real_id(id), val); + return NULL; +} + static void print_type(FILE *fp, Type *t, gboolean postfix_to_stars) { char *s; - s = get_type(t,postfix_to_stars); - out_printf(fp,"%s",s); + s = get_type(t, postfix_to_stars); + out_printf(fp, "%s", s); g_free(s); } static void print_method(FILE *fp, char *typeprefix, char *nameprefix, - char *namepostfix,char *postfix, Method *m, - gboolean no_funcbase) + char *subnameprefix, + char *namepostfix, char *postfix, Method *m, + gboolean one_arg_per_line, + gboolean no_funcbase, + gboolean kill_underscore) { GList *li; + char *id; + + out_printf(fp, "%s", typeprefix); + print_type(fp, m->mtype, TRUE); + + if(kill_underscore) + id = get_real_id(m->id); + else + id = m->id; - out_printf(fp,"%s",typeprefix); - print_type(fp,m->mtype,TRUE); if(no_funcbase) - out_printf(fp,"%s%s%s(", - nameprefix,m->id,namepostfix); + out_printf(fp, "%s%s%s%s(", + nameprefix, subnameprefix, id, namepostfix); else - out_printf(fp,"%s%s_%s%s(", - nameprefix,funcbase,m->id,namepostfix); + out_printf(fp, "%s%s_%s%s%s(", + nameprefix, funcbase, subnameprefix, id, + namepostfix); if(m->args) { - for(li=m->args;li;li=g_list_next(li)) { + for(li=m->args; li; li=g_list_next(li)) { FuncArg *arg = li->data; - print_type(fp,arg->atype,FALSE); + print_type(fp, arg->atype, FALSE); if(li->next) - out_printf(fp,"%s%s, ",arg->name, + out_printf(fp, "%s%s,%s", arg->name, arg->atype->postfix? - arg->atype->postfix:""); + arg->atype->postfix:"", + one_arg_per_line?"\n\t\t\t\t\t":" "); else - out_printf(fp,"%s%s",arg->name, + out_printf(fp, "%s%s", arg->name, arg->atype->postfix? arg->atype->postfix:""); } if(m->vararg) - out_printf(fp,", ..."); + out_printf(fp, ",%s...", + one_arg_per_line?"\n\t\t\t\t\t":" "); } else { - out_printf(fp,"void"); + out_printf(fp, "void"); } - out_printf(fp,")%s",postfix); + out_printf(fp, ")%s", postfix); +} + +static gboolean +any_method_to_alias(Class *c) +{ + GList *li; + + for(li=c->nodes;li;li=g_list_next(li)) { + Node *node = li->data; + if(node->type == METHOD_NODE) { + Method *m = (Method *)node; + + if(m->method == INIT_METHOD || + m->method == CLASS_INIT_METHOD || + m->method == OVERRIDE_METHOD) + continue; + + return TRUE; + } + } + return FALSE; } @@ -293,10 +286,11 @@ make_method_gnu_aliases(Class *c) out_printf(out, "static const typeof(&%s_%s) %s " "__attribute__ ((__unused__)) " - "= %s_%s;\n", funcbase, m->id, m->id, - funcbase, m->id); + "= %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, m->id); + "%s_%s(##args)\n", m->id, + funcbase, get_real_id(m->id)); } } } @@ -306,7 +300,7 @@ make_method_nongnu_aliases(Class *c) { GList *li; - for(li=c->nodes;li;li=g_list_next(li)) { + for(li=c->nodes; li; li=g_list_next(li)) { Node *node = li->data; if(node->type == METHOD_NODE) { Method *m = (Method *)node; @@ -317,11 +311,13 @@ make_method_nongnu_aliases(Class *c) continue; /* in C++ mode don't alias new */ - if(for_cpp && strcmp(m->id,"new")==0) + if(for_cpp && strcmp(m->id, "new")==0) continue; - print_method(out,"static ","(* ",") ","",m,TRUE); - out_printf(out," = %s_%s;\n",funcbase,m->id); + print_method(out, "static ", "(* ", "", ") ", "", + m, FALSE, TRUE, FALSE); + out_printf(out, " = %s_%s;\n", funcbase, + get_real_id(m->id)); made_aliases = TRUE; } @@ -338,7 +334,7 @@ add_bad_hack_to_avoid_unused_warnings(Class *c) return; if(!no_gnu) - out_printf(out,"\n\n#ifndef __GNUC__\n"); + out_printf(out, "\n\n#ifndef __GNUC__\n"); out_printf(out, "/*REALLY BAD HACK\n" " This is to avoid unused warnings if you don't call\n" @@ -347,7 +343,7 @@ add_bad_hack_to_avoid_unused_warnings(Class *c) " extentions to make saner, faster code */\n" "static void\n" "___%s_really_bad_hack_to_avoid_warnings(void)\n" - "{\n",funcbase); + "{\n", funcbase); for(li=c->nodes;li;li=g_list_next(li)) { Node *node = li->data; if(node->type == METHOD_NODE) { @@ -359,31 +355,31 @@ add_bad_hack_to_avoid_unused_warnings(Class *c) continue; /* in C++ mode we don't alias new */ - if(for_cpp && strcmp(m->id,"new")==0) + if(for_cpp && strcmp(m->id, "new")==0) continue; - out_printf(out,"\t((void (*)(void))%s)();\n",m->id); + out_printf(out, "\t((void (*)(void))%s)();\n", m->id); } } out_printf(out, "\t___%s_really_bad_hack_to_avoid_warnings();\n", funcbase); if(!no_gnu) - out_printf(out,"}\n#endif /* __GNUC__ */\n\n"); + out_printf(out, "}\n#endif /* __GNUC__ */\n\n"); else - out_printf(out,"}\n\n"); + out_printf(out, "}\n\n"); } static void put_variable(Variable *v, FILE *fp) { - out_printf(fp,"\t"); - print_type(fp,v->vtype,FALSE); - out_printf(fp,"%s%s;",v->id, + out_printf(fp, "\t"); + print_type(fp, v->vtype, FALSE); + out_printf(fp, "%s%s;", v->id, v->vtype->postfix? v->vtype->postfix:""); if(v->scope == PROTECTED_SCOPE) - out_printf(fp," /* protected */"); - out_printf(fp,"\n"); + out_printf(fp, " /* protected */"); + out_printf(fp, "\n"); } static void @@ -394,7 +390,13 @@ put_vs_method(Method *m) m->method != VIRTUAL_METHOD) return; - print_method(outh,"\t","(* ",") ",";\n",m,TRUE); + /* if a signal mark it as such */ + if(m->method != VIRTUAL_METHOD) + print_method(outh, "\t/*signal*/", "(* ", "", ") ", ";\n", + m, FALSE, TRUE, TRUE); + else + print_method(outh, "\t", "(* ", "", ") ", ";\n", + m, FALSE, TRUE, TRUE); } static void @@ -403,8 +405,46 @@ put_pub_method(Method *m) if(m->scope != PUBLIC_SCOPE) return; - print_method(outh,"","\t","\t",";\n",m,FALSE); + 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) +{ + 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); } +#endif + static void put_prot_method(Method *m) @@ -413,9 +453,11 @@ put_prot_method(Method *m) return; if(outph) - print_method(outph,"","\t","\t",";\n",m,FALSE); + print_method(outph, "", "\t", "", "\t", ";\n", + m, FALSE, FALSE, TRUE); else - print_method(out,"","\t","\t",";\n",m,FALSE); + print_method(out, "", "\t", "", "\t", ";\n", + m, FALSE, FALSE, TRUE); } static void @@ -425,17 +467,27 @@ 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); - } - - if(m->scope == PRIVATE_SCOPE || + print_method(out, + "static ", "___real_", "", " ", ";\n", + m, FALSE, FALSE, TRUE); + } + /* no else, here, it might still have a private prototype, it's not + * exclusive */ + + if((m->method == OVERRIDE_METHOD && + m->cbuf)) { + /* add unique ID */ + char *s = g_strdup_printf("___%x_", (guint)m->unique_id); + 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 || - (m->method == OVERRIDE_METHOD && - m->cbuf)) - print_method(out,"static ",""," ", - no_gnu?";\n":" ___NO_UNUSED_WARNING;\n" - ,m,FALSE); + m->method == CLASS_INIT_METHOD) + print_method(out, "static ", "", "", " ", + no_gnu?";\n":" G_GNUC_UNUSED;\n", + m, FALSE, FALSE, TRUE); } static GList * @@ -446,12 +498,12 @@ make_func_arg(char *typename, int is_class, char *name) char *tn; if(is_class) - tn = g_strconcat(typename,":Class",NULL); + tn = g_strconcat(typename, ":Class", NULL); else tn = g_strdup(typename); - type = new_type(1,tn,NULL); - node = new_funcarg((Type *)type,name,NULL); + type = new_type(tn, g_strdup("*"), NULL); + node = new_funcarg((Type *)type, name, NULL); return g_list_prepend(NULL, node); } @@ -468,117 +520,101 @@ make_inits(Class *cl) Method *m = (Method *)n; if(m->method == INIT_METHOD) { if(got_init) - print_error(FALSE,"init defined more then once",m->line_no); + print_error(FALSE, "init defined more then once", m->line_no); got_init = TRUE; } else if(m->method == CLASS_INIT_METHOD) { if(got_class_init) - print_error(FALSE,"class_init defined more then once",m->line_no); + print_error(FALSE, "class_init defined more then once", m->line_no); got_class_init = TRUE; } } } if(!got_class_init) { node = new_method(NO_SCOPE, CLASS_INIT_METHOD, - (Type *)new_type(0,g_strdup("void"),NULL), - NULL,NULL,g_strdup("class_init"), - make_func_arg(cl->otype,TRUE,g_strdup("c")), - NULL, NULL,0,0,FALSE); - cl->nodes = g_list_prepend(cl->nodes,node); + (Type *)new_type(g_strdup("void"), + NULL, NULL), + 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++); + cl->nodes = g_list_prepend(cl->nodes, node); } if(!got_init) { node = new_method(NO_SCOPE, INIT_METHOD, - (Type *)new_type(0,g_strdup("void"),NULL), - NULL,NULL,g_strdup("init"), - make_func_arg(cl->otype,FALSE,g_strdup("o")), - NULL, NULL,0,0,FALSE); - cl->nodes = g_list_prepend(cl->nodes,node); + (Type *)new_type(g_strdup("void"), + NULL, NULL), + NULL, NULL, NULL, g_strdup("init"), + make_func_arg(cl->otype, FALSE, g_strdup("o")), + NULL, NULL, NULL, 0, 0, FALSE, + method_unique_id++); + cl->nodes = g_list_prepend(cl->nodes, node); } } static void -make_finalize(Class *cl) +find_destroy(Class *cl) { - int got_finalize = FALSE; GList *li; - Node *node; + + destroy_handler = NULL; for(li=cl->nodes;li;li=g_list_next(li)) { Node *n = li->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; if(m->method == OVERRIDE_METHOD && - strcmp(m->id,"finalize")==0) { - if(strcmp(m->otype,"Gtk:Object")==0) { - got_finalize = TRUE; - break; - } else { - print_error(FALSE,"finalize method override " - "of class other then Gtk:Object", + strcmp(m->id, "destroy")==0) { + if(strcmp(m->otype, "Gtk:Object") != 0) { + print_error(FALSE, + "destroy method override " + "of class other then " + "Gtk:Object", m->line_no); } - + if(g_list_length(m->args) != 1) { + print_error(FALSE, + "destroy method override " + "with more then one " + "parameter", + m->line_no); + } + destroy_handler = m; + break; } } } - if(!got_finalize) { - node = new_method(NO_SCOPE, OVERRIDE_METHOD, - (Type *)new_type(0,g_strdup("void"),NULL), - g_strdup("Gtk:Object"), - NULL,g_strdup("finalize"), - make_func_arg("Gtk:Object",FALSE,g_strdup("o")), - NULL, - g_strdup("PARENT_HANDLER (o);\n"), - 0,0,FALSE); - cl->nodes = g_list_append(cl->nodes,node); - overrides++; - } } -/* 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) +static void +find_finalize(Class *cl) { - 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; + GList *li; + + finalize_handler = NULL; + for(li=cl->nodes;li;li=g_list_next(li)) { + Node *n = li->data; + if(n->type == METHOD_NODE) { + Method *m = (Method *)n; + if(m->method == OVERRIDE_METHOD && + strcmp(m->id, "finalize")==0) { + if(strcmp(m->otype, "Gtk:Object") != 0) { + print_error(FALSE, + "finalize method override " + "of class other then " + "Gtk:Object", + m->line_no); + } + if(g_list_length(m->args) != 1) { + print_error(FALSE, + "finalize method override " + "with more then one " + "parameter", + m->line_no); + } + finalize_handler = m; + break; + } } } - return NULL; } @@ -595,7 +631,7 @@ static gboolean is_list_equal(GList *a, GList *b) { for(;a && b; a=a->next, b=b->next) { - if(strcmp(a->data,b->data)!=0) { + if(strcmp(a->data, b->data)!=0) { return FALSE; } } @@ -611,7 +647,7 @@ find_same_type_signal(Method *m) GList *li; for(li=eq_signal_methods;li;li=li->next) { Method *mm = li->data; - if(is_list_equal(mm->gtktypes,m->gtktypes)) + if(is_list_equal(mm->gtktypes, m->gtktypes)) return mm; } return NULL; @@ -620,19 +656,19 @@ find_same_type_signal(Method *m) static void print_signal_marsal_args(Method *m) { - if(strcmp(m->gtktypes->next->data,"NONE")!=0) { + if(strcmp(m->gtktypes->next->data, "NONE")!=0) { GList *li; int i; - for(i=0,li=m->gtktypes->next;li; - i++,li=g_list_next(li)) { + for(i=0, li=m->gtktypes->next;li; + i++, li=g_list_next(li)) { if(!for_cpp) out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])", - (char *)li->data,i); + (char *)li->data, i); else { out_printf(out, ",\n\t\t(%s)" "GTK_VALUE_%s(args[%d])", - get_cast(li->data,FALSE), - (char *)li->data,i); + get_cast(li->data, FALSE), + (char *)li->data, i); } } } @@ -653,53 +689,56 @@ add_signal_prots(Method *m) return; if(!marsh) - marsh = g_hash_table_new(NULL,NULL); + marsh = g_hash_table_new(NULL, NULL); - if(strcmp(m->gtktypes->data,"NONE")==0 && - strcmp(m->gtktypes->next->data,"NONE")==0) + if(strcmp(m->gtktypes->data, "NONE")==0 && + strcmp(m->gtktypes->next->data, "NONE")==0) return; /* if we already did a signal prototype just use that */ mm = find_same_type_signal(m); if(mm) { - s = g_hash_table_lookup(marsh,mm); - g_hash_table_insert(marsh,m,s); + s = g_hash_table_lookup(marsh, mm); + g_hash_table_insert(marsh, m, s); return; } - s = g_strdup_printf("Sig%d",sig++); + s = g_strdup_printf("Sig%d", sig++); - g_hash_table_insert(marsh,m,s); - eq_signal_methods = g_list_prepend(eq_signal_methods,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); + 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)) - out_printf(out,"%s, ",get_cast(li->data,FALSE)); - out_printf(out,"gpointer);\n"); + if(strcmp(m->gtktypes->next->data, "NONE")!=0) { + for(li=m->gtktypes->next; li; li=g_list_next(li)) + out_printf(out, "%s, ", get_cast(li->data, FALSE)); + } + out_printf(out, "gpointer);\n"); - out_printf(out,"\nstatic void\n" + out_printf(out, "\nstatic void\n" "___marshal_%s (GtkObject * object,\n" "\tGtkSignalFunc func,\n" "\tgpointer func_data,\n" "\tGtkArg * args)\n" - "{\n",s); + "{\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); + 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 { - 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" - "\tretval = GTK_RETLOC_%s(args[%d]);\n\n" - "\t*retval = (*rfunc)((%s *)object", - s,(char *)m->gtktypes->data, - g_list_length(m->gtktypes)-1,typebase); + 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); @@ -709,49 +748,52 @@ static void add_enums(Class *c) { GList *li; - out_printf(out,"\n"); + out_printf(out, "\n"); if(signals>0) { - out_printf(out,"enum {\n"); + out_printf(out, "enum {\n"); for(li=c->nodes;li;li=g_list_next(li)) { Node *n = li->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; if(m->method == SIGNAL_LAST_METHOD || m->method == SIGNAL_FIRST_METHOD) { - char *s = g_strdup(m->id); + char *s = g_strdup(get_real_id(m->id)); g_strup(s); - out_printf(out,"\t%s_SIGNAL,\n",s); + out_printf(out, "\t%s_SIGNAL,\n", s); g_free(s); } } } - out_printf(out,"\tLAST_SIGNAL\n};\n\n"); + out_printf(out, "\tLAST_SIGNAL\n};\n\n"); } if(arguments>0) { - out_printf(out,"enum {\n\tARG_0,\n"); + out_printf(out, "enum {\n\tARG_0"); for(li=c->nodes;li;li=g_list_next(li)) { Node *n = li->data; if(n->type == ARGUMENT_NODE) { Argument *a = (Argument *)n; char *s = g_strdup(a->name); g_strup(s); - out_printf(out,"\tARG_%s,\n",s); + out_printf(out, ",\n\tARG_%s", s); g_free(s); } } - out_printf(out, "};\n\n"); + out_printf(out, "\n};\n\n"); } if(signals>0) out_printf(out, "static guint object_signals[LAST_SIGNAL] = {0};\n\n"); - out_printf(out, "static %sClass *parent_class = NULL;\n\n",ptypebase); + out_printf(out, "/* pointer to the class of our parent */\n"); + out_printf(out, "static %sClass *parent_class = NULL;\n\n", ptypebase); } static void add_get_type(void) { + char *chunk_size = ((Class*)class)->chunk_size; + out_printf(out, "guint\n" "%s_get_type (void)\n" "{\n" @@ -767,12 +809,18 @@ add_get_type(void) "\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" - "\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", - funcbase,typebase,typebase,typebase, - funcbase,funcbase,pfuncbase); + "}\n\n"); } static void @@ -782,98 +830,151 @@ add_overrides(Class *c, char *oname, gboolean did_gtk_obj) GHashTable *done; char *s; - done = g_hash_table_new(g_str_hash,g_str_equal); + done = g_hash_table_new(g_str_hash, g_str_equal); if(did_gtk_obj) { s = g_strdup("GtkObject"); /* This was already done */ - g_hash_table_insert(done,s,s); + g_hash_table_insert(done, s, s); } - for(li=c->nodes;li;li=g_list_next(li)) { + for(li=c->nodes; li; li=g_list_next(li)) { Node *n = li->data; char *f; Method *m = (Method *)n; if(n->type != METHOD_NODE || m->method != OVERRIDE_METHOD) continue; - + s = remove_sep(m->otype); - if(g_hash_table_lookup(done,s)) { + if(g_hash_table_lookup(done, s)) { g_free(s); continue; } - g_hash_table_insert(done,s,s); + g_hash_table_insert(done, s, s); - f = replace_sep(m->otype,'_'); + f = replace_sep(m->otype, '_'); g_strdown(f); - out_printf(out,"\t%sClass *%s_class = (%sClass *)%s;\n", - s,f,s,oname); + out_printf(out, "\t%sClass *%s_class = (%sClass *)%s;\n", + s, f, s, oname); g_free(f); } - g_hash_table_foreach(done,(GHFunc)g_free,NULL); + g_hash_table_foreach(done, (GHFunc)g_free, NULL); g_hash_table_destroy(done); } +static char * +make_run_signal_flags(Method *m, gboolean last) +{ + GList *li; + GString *gs; + char *flags[] = { + "FIRST", + "LAST", + "BOTH", + "NO_RECURSE", + "ACTION", + "NO_HOOKS", + NULL + }; + + gs = g_string_new(NULL); + + if(last) + g_string_assign(gs, "GTK_RUN_LAST"); + else + g_string_assign(gs, "GTK_RUN_FIRST"); + + if(m->scope == PUBLIC_SCOPE) + g_string_append(gs, " | GTK_RUN_ACTION"); + + for(li = m->flags; li; li = li->next) { + char *flag = li->data; + int i; + for(i=0;flags[i];i++) { + if(strcmp(flags[i], flag)==0) + break; + } + /* if we haven't found it in our list */ + if(!flags[i]) { + char *s; + s = g_strdup_printf("Unknown flag '%s' used, " + "perhaps it was misspelled", + flag); + print_error(TRUE, s, m->line_no); + g_free(s); + } + g_string_sprintfa(gs, " | GTK_RUN_%s", flag); + } + + { + char *ret = gs->str; + g_string_free(gs, FALSE); + return ret; + } +} + + static void add_signals(Class *c) { GList *li; - out_printf(out,"\n"); + out_printf(out, "\n"); for(li=c->nodes;li;li=g_list_next(li)) { Node *n = li->data; - char *mar; - char *sig; - int is_none; - int last = FALSE; + char *mar, *sig, *flags; + gboolean is_none, last = FALSE; Method *m = (Method *)n; + if(n->type != METHOD_NODE || (m->method != SIGNAL_FIRST_METHOD && m->method != SIGNAL_LAST_METHOD)) continue; - if(m->method == SIGNAL_FIRST_METHOD) last = FALSE; else last = TRUE; - if(g_hash_table_lookup(marsh,m)) + if(g_hash_table_lookup(marsh, m)) mar = g_strconcat("___marshal_", - (char *)g_hash_table_lookup(marsh,m), + (char *)g_hash_table_lookup(marsh, m), NULL); else mar = g_strdup("gtk_signal_default_marshaller"); - is_none = (strcmp(m->gtktypes->next->data,"NONE")==0); - - sig = g_strdup(m->id); + is_none = (strcmp(m->gtktypes->next->data, "NONE")==0); + + sig = g_strdup(get_real_id(m->id)); g_strup(sig); - out_printf(out,"\tobject_signals[%s_SIGNAL] =\n" + flags = make_run_signal_flags(m, last); + out_printf(out, "\tobject_signals[%s_SIGNAL] =\n" "\t\tgtk_signal_new (\"%s\",\n" - "\t\t\tGTK_RUN_%s,\n" + "\t\t\t(GtkSignalRunType)(%s),\n" "\t\t\tgtk_object_class->type,\n" "\t\t\tGTK_SIGNAL_OFFSET (%sClass, %s),\n" "\t\t\t%s,\n" "\t\t\tGTK_TYPE_%s, %d", - sig,m->id, - last?"LAST":"FIRST", - typebase,m->id,mar,(char *)m->gtktypes->data, + sig, get_real_id(m->id), + flags, + typebase, get_real_id(m->id), mar, + (char *)m->gtktypes->data, is_none?0:g_list_length(m->gtktypes->next)); g_free(mar); g_free(sig); + g_free(flags); if(!is_none) { GList *l; for(l=m->gtktypes->next;l;l=g_list_next(l)) - out_printf(out,",\n\t\t\tGTK_TYPE_%s", + out_printf(out, ",\n\t\t\tGTK_TYPE_%s", (char *)l->data); } - out_printf(out,");\n"); + out_printf(out, ");\n"); } - out_printf(out,"\tgtk_object_class_add_signals (gtk_object_class,\n" + out_printf(out, "\tgtk_object_class_add_signals (gtk_object_class,\n" "\t\tobject_signals, LAST_SIGNAL);\n\n"); } @@ -881,11 +982,13 @@ static void set_def_handlers(Class *c, char *oname) { GList *li; + gboolean set_line = FALSE; - out_printf(out,"\n"); - for(li=c->nodes;li;li=g_list_next(li)) { + out_printf(out, "\n"); + for(li = c->nodes; li; li = g_list_next(li)) { Node *n = li->data; Method *m = (Method *)n; + if(n->type != METHOD_NODE || (m->method != SIGNAL_FIRST_METHOD && m->method != SIGNAL_LAST_METHOD && @@ -893,26 +996,50 @@ set_def_handlers(Class *c, char *oname) m->method != OVERRIDE_METHOD)) continue; + if(m->line_no > 0 && m->cbuf) { + out_addline_infile(out, m->line_no); + set_line = TRUE; + } else if(set_line) { + out_addline_outfile(out); + set_line = FALSE; + } + if(m->method == OVERRIDE_METHOD) { char *s; - s = replace_sep(m->otype,'_'); + s = replace_sep(m->otype, '_'); g_strdown(s); - if(m->cbuf) - out_printf(out,"\t%s_class->%s = %s_%s;\n", - s,m->id,funcbase,m->id); + + if(need_destroy && + destroy_handler && + strcmp(m->id, "destroy") == 0) + out_printf(out, "\tgtk_object_class->destroy " + "= ___destroy;\n"); + else if(need_finalize && + finalize_handler && + strcmp(m->id, "finalize") == 0) + out_printf(out, "\tgtk_object_class->finalize " + "= ___finalize;\n"); + else if(m->cbuf) + out_printf(out, + "\t%s_class->%s = ___%x_%s_%s;\n", + s, m->id, (guint)m->unique_id, + funcbase, m->id); else - out_printf(out,"\t%s_class->%s = NULL;\n", - s,m->id); + out_printf(out, "\t%s_class->%s = NULL;\n", + s, m->id); } else { if(m->cbuf) - out_printf(out,"\t%s->%s = _real_%s_%s;\n", - oname,m->id,funcbase,m->id); + out_printf(out, "\t%s->%s = ___real_%s_%s;\n", + oname, get_real_id(m->id), + funcbase, get_real_id(m->id)); else - out_printf(out,"\t%s->%s = NULL;\n", - oname,m->id); + out_printf(out, "\t%s->%s = NULL;\n", + oname, get_real_id(m->id)); } } + if(set_line) + out_addline_outfile(out); } static void @@ -927,7 +1054,7 @@ make_arguments(Class *c) NULL }; - out_printf(out,"\n"); + out_printf(out, "\n"); for(li=c->nodes;li;li=g_list_next(li)) { Node *n = li->data; Argument *a; @@ -949,16 +1076,16 @@ make_arguments(Class *c) for(l=a->flags;l;l=g_list_next(l)) { char *flag = l->data; int i; - if(strcmp(flag,"READWRITE")==0 || - strcmp(flag,"READABLE")==0 || - strcmp(flag,"WRITABLE")==0) { - print_error(TRUE,"READWRITE, READABLE and " + if(strcmp(flag, "READWRITE")==0 || + strcmp(flag, "READABLE")==0 || + strcmp(flag, "WRITABLE")==0) { + print_error(TRUE, "READWRITE, READABLE and " "WRITABLE argument flags are " - "set automatically",a->line_no); + "set automatically", a->line_no); continue; } for(i=0;argflags[i];i++) { - if(strcmp(argflags[i],flag)==0) + if(strcmp(argflags[i], flag)==0) break; } /* if we haven't found it in our list */ @@ -967,21 +1094,21 @@ make_arguments(Class *c) s = g_strdup_printf("Unknown flag '%s' used, " "perhaps it was misspelled", flag); - print_error(TRUE,s,a->line_no); + print_error(TRUE, s, a->line_no); g_free(s); } - g_string_sprintfa(flags, " | GTK_ARG_%s",flag); + g_string_sprintfa(flags, " | GTK_ARG_%s", flag); } s = g_strdup(a->name); g_strup(s); - out_printf(out,"\tgtk_object_add_arg_type(\"%s::%s\",\n" + out_printf(out, "\tgtk_object_add_arg_type(\"%s::%s\",\n" "\t\tGTK_TYPE_%s,\n" "\t\t%s,\n" "\t\tARG_%s);\n", - typebase,a->name,a->gtktype,flags->str,s); + typebase, a->name, a->gtktype, flags->str, s); g_free(s); - g_string_free(flags,TRUE); + g_string_free(flags, TRUE); } out_printf(out, @@ -989,6 +1116,140 @@ make_arguments(Class *c) "\tgtk_object_class->get_arg = ___object_get_arg;\n"); } +static void +print_initializer(Method *m, Variable *v) +{ + char *root; + + if(v->initializer == NULL) + return; + + if(v->scope == PRIVATE_SCOPE) + root = g_strconcat(((FuncArg *)m->args->data)->name, + "->_priv", NULL); + else + root = g_strdup(((FuncArg *)m->args->data)->name); + + if(v->initializer_line > 0) + out_addline_infile(out, v->initializer_line); + + out_printf(out, "\t%s->%s = %s;\n", + root, v->id, v->initializer); + + if(v->initializer_line > 0) + out_addline_outfile(out); + + g_free(root); +} + +static void +print_destructor(Variable *v) +{ + char *root; + + if(v->destructor == NULL) + return; + + if(v->scope == PRIVATE_SCOPE) + root = "self->_priv"; + else + root = "self"; + + if(v->destructor_simple) { + if(v->destructor_line > 0) + out_addline_infile(out, v->destructor_line); + + out_printf(out, "\tif(%s->%s) { " + "((*(void (*)(void *))%s)) (%s->%s); " + "%s->%s = NULL; }\n", + root, v->id, v->destructor, root, v->id, + root, v->id); + + if(v->destructor_line > 0) + out_addline_outfile(out); + } else { + out_printf(out, "#define VAR (%s->%s)\n", root, v->id); + out_printf(out, "\t{\n"); + if(v->destructor_line > 0) + out_addline_infile(out, v->destructor_line); + + out_printf(out, "\t%s}\n", v->destructor); + + if(v->destructor_line > 0) + out_addline_outfile(out); + out_printf(out, "\tmemset(&VAR, 0, sizeof(VAR));\n"); + out_printf(out, "#undef VAR\n"); + } +} + +static void +add_destroy(Class *c) +{ + out_printf(out, "\nstatic void\n" + "___destroy(GtkObject *obj_self)\n" + "{\n"); + + if(destructors > 0) { + out_printf(out, "\t%s *self G_GNUC_UNUSED = %s (obj_self);\n", + typebase, macrobase); + } + + if(destroy_handler) { + /* so we get possible bad argument warning */ + if(destroy_handler->line_no > 0) + out_addline_infile(out, destroy_handler->line_no); + out_printf(out, "\t___%x_%s_destroy(obj_self);\n", + (guint)destroy_handler->unique_id, funcbase); + if(destroy_handler->line_no > 0) + out_addline_outfile(out); + } + + if(destructors > 0) { + GList *li; + for(li = ((Class *)class)->nodes; + li != NULL; + li = li->next) { + Node *n = li->data; + Variable *v = (Variable *)n; + if(n->type == VARIABLE_NODE && + v->scope != CLASS_SCOPE) + print_destructor(v); + } + } + + out_printf(out, "}\n\n"); +} + +static void +add_finalize(Class *c) +{ + out_printf(out, "\nstatic void\n" + "___finalize(GtkObject *obj_self)\n" + "{\n"); + + if(privates > 0) { + out_printf(out, "\t%s *self = %s (obj_self);\n", + typebase, macrobase); + } + + if(finalize_handler) { + /* so we get possible bad argument warning */ + if(finalize_handler->line_no > 0) + out_addline_infile(out, finalize_handler->line_no); + out_printf(out, "\t___%x_%s_finalize(obj_self);\n", + (guint)finalize_handler->unique_id, funcbase); + if(finalize_handler->line_no > 0) + out_addline_outfile(out); + } + + if(privates > 0) { + out_printf(out, "\tg_free (self->_priv);\n" + "\tself->_priv = NULL;\n"); + } + + out_printf(out, "}\n\n"); +} + static void add_inits(Class *c) { @@ -1000,81 +1261,136 @@ add_inits(Class *c) continue; m = (Method *)n; if(m->method == INIT_METHOD) { - if(m->line_no>0) - out_addline_infile(out,m->line_no); - print_method(out,"static ","\n"," ","\n",m,FALSE); - if(m->line_no>0) + if(m->line_no > 0) + out_addline_infile(out, m->line_no); + print_method(out, "static ", "\n", "", " ", "\n", + m, FALSE, FALSE, TRUE); + if(m->line_no > 0) out_addline_outfile(out); - out_printf(out,"{\n"); - if(privates>0) { - out_printf(out,"\t%s->_priv = " - "g_new0 (%sPrivate,1);\n", + out_printf(out, "{\n" + "#define __GOB_FUNCTION__ \"%s::init\"\n", + c->otype); + if(privates > 0) { + out_printf(out, "\t%s->_priv = " + "g_new0 (%sPrivate, 1);\n", ((FuncArg *)m->args->data)->name, typebase); + } else if(always_private_struct) { + out_printf(out, "\t%s->_priv = NULL;\n", + ((FuncArg *)m->args->data)->name); + } + if(initializers > 0) { + GList *li; + for(li = ((Class *)class)->nodes; + li != NULL; + li = li->next) { + Node *n = li->data; + Variable *v = (Variable *)n; + if(n->type != VARIABLE_NODE || + v->scope == CLASS_SCOPE) + continue; + print_initializer(m, v); + } } } else if(m->method == CLASS_INIT_METHOD) { - if(m->line_no>0) - out_addline_infile(out,m->line_no); - print_method(out,"static ","\n"," ","\n",m,FALSE); - if(m->line_no>0) + gboolean did_gtk_obj = FALSE; + + if(m->line_no > 0) + out_addline_infile(out, m->line_no); + print_method(out, "static ", "\n", "", " ", "\n", + m, FALSE, FALSE, TRUE); + if(m->line_no > 0) out_addline_outfile(out); - out_printf(out,"{\n"); - if(signals>0 || - arguments>0) + out_printf(out, "{\n" + "#define __GOB_FUNCTION__ \"%s::class_init\"\n", + c->otype); + if(signals > 0 || + arguments > 0 || + need_destroy || + need_finalize) { out_printf(out, "\tGtkObjectClass *" "gtk_object_class = " "(GtkObjectClass*) %s;\n", ((FuncArg *)m->args->data)->name); + did_gtk_obj = TRUE; + } - if(overrides>0) + if(overrides > 0) add_overrides(c, ((FuncArg *)m->args->data)->name, - (signals>0 || arguments>0)); + did_gtk_obj); + + if(initializers > 0) { + GList *li; + for(li = ((Class *)class)->nodes; + li != NULL; + li = li->next) { + Node *n = li->data; + Variable *v = (Variable *)n; + if(n->type != VARIABLE_NODE || + v->scope != CLASS_SCOPE) + continue; + print_initializer(m, v); + } + } - out_printf(out,"\n\tparent_class = "); + out_printf(out, "\n\tparent_class = "); if(for_cpp) - out_printf(out,"(%sClass *)",ptypebase); - out_printf(out,"gtk_type_class (%s_get_type ());\n", + out_printf(out, "(%sClass *)", ptypebase); + out_printf(out, "gtk_type_class (%s_get_type ());\n", pfuncbase); - if(signals>0) + if(signals > 0) add_signals(c); set_def_handlers(c, ((FuncArg *)m->args->data)->name); + + /* if there are no handlers for these things, we + * need to set them up here */ + if(need_destroy && !destroy_handler) + out_printf(out, "\tgtk_object_class->destroy " + "= ___destroy;\n"); + if(need_finalize && !finalize_handler) + out_printf(out, "\tgtk_object_class->finalize " + "= ___finalize;\n"); - if(arguments>0) + if(arguments > 0) make_arguments(c); } else continue; if(m->cbuf) { - out_printf(out," {\n"); - out_addline_infile(out,m->ccode_line); - out_printf(out,"%s\n",m->cbuf); + out_printf(out, " {\n"); + out_addline_infile(out, m->ccode_line); + out_printf(out, "%s\n", m->cbuf); out_addline_outfile(out); - out_printf(out," }\n"); + out_printf(out, " }\n"); } else { - out_printf(out,"return;\n"); + out_printf(out, "return;\n"); } - out_printf(out,"}\n"); + out_printf(out, "}\n" + "#undef __GOB_FUNCTION__\n"); } } static void -add_getset_arg(Class *c, int is_set) +add_getset_arg(Class *c, gboolean is_set) { GList *li; - out_printf(out,"\nstatic void\n" - "___object_%s_arg (GtkObject *object,\n" - "\tGtkArg *arg,\n" - "\tguint arg_id)\n" - "{\n" - "\t%s *self;\n\n" - "\tself = %s (object);\n\n" - "\tswitch (arg_id) {\n", - is_set?"set":"get",typebase,macrobase); + out_printf(out, "\nstatic void\n" + "___object_%s_arg (GtkObject *object,\n" + "\tGtkArg *arg,\n" + "\tguint arg_id)\n" + "#define __GOB_FUNCTION__ \"%s::%s_arg\"\n" + "{\n" + "\t%s *self;\n\n" + "\tself = %s (object);\n\n" + "\tswitch (arg_id) {\n", + is_set ? "set" : "get", + c->otype, is_set ? "set" : "get", + typebase, macrobase); for(li=c->nodes;li;li=g_list_next(li)) { Node *n = li->data; @@ -1096,18 +1412,57 @@ add_getset_arg(Class *c, int is_set) continue; s = g_strdup(a->name); g_strup(s); - out_printf(out,"\tcase ARG_%s:\n" - "#define ARG (GTK_VALUE_%s(*arg))\n" - "\t\t{\n", - s,a->gtktype); + out_printf(out, "\tcase ARG_%s:\n", s); + if(is_set && a->atype) { + char *cast = get_type(a->atype, TRUE); + if(no_gnu || for_cpp) { + out_printf(out, "#define ARG " + "((%s)GTK_VALUE_%s(*arg))\n", + cast, a->gtktype); + } else { + out_printf(out, "#ifdef __GNUC__\n"); + if(strcmp(a->gtktype, "OBJECT")==0) { + out_printf(out, "#define ARG " + "({%s foo = " + "GTK_VALUE_POINTER(*arg); " + "foo; })\n", + cast); + } else { + out_printf(out, "#define ARG " + "({%s foo = " + "GTK_VALUE_%s(*arg); " + "foo; })\n", + cast, a->gtktype); + } + out_printf(out, "#else /* __GNUC__ */\n"); + out_printf(out, "#define ARG " + "((%s)GTK_VALUE_%s(*arg))\n", + cast, a->gtktype); + out_printf(out, "#endif /* __GNUC__ */\n\n"); + } + out_printf(out, "\t\t{\n"); + g_free(cast); + } else if(!is_set && strcmp(a->gtktype, "OBJECT")==0) { + out_printf(out, + "#define ARG (GTK_VALUE_POINTER(*arg))\n" + "\t\t{\n"); + } else { + out_printf(out, + "#define ARG (GTK_VALUE_%s(*arg))\n" + "\t\t{\n", + a->gtktype); + } g_free(s); - out_addline_infile(out,line_no); - out_printf(out,"%s\n",cbuf); - out_addline_outfile(out); - out_printf(out,"\t\t}\n\t\tbreak;\n" + if(line_no > 0) + out_addline_infile(out, line_no); + out_printf(out, "%s\n", cbuf); + if(line_no > 0) + out_addline_outfile(out); + out_printf(out, "\t\t}\n\t\tbreak;\n" "#undef ARG\n"); } - out_printf(out,"\tdefault:\n\t\tbreak;\n\t}\n}\n"); + out_printf(out, "\tdefault:\n\t\tbreak;\n\t}\n}\n" + "#undef __GOB_FUNCTION__\n"); } static void @@ -1116,59 +1471,59 @@ print_checks(Method *m, FuncArg *fa) GList *li; gboolean is_void; gboolean checked_null = FALSE; - is_void = (strcmp(m->mtype->name,"void")==0 && - m->mtype->stars == 0); + is_void = (strcmp(m->mtype->name, "void")==0 && + m->mtype->pointer == NULL); - for(li=fa->checks;li;li=g_list_next(li)) { + for(li = fa->checks; li; li = g_list_next(li)) { Check *ch = li->data; char *s; /* point to the method prot in .gob for failed checks */ - if(m->line_no>0) - out_addline_infile(out,m->line_no); + if(m->line_no > 0) + out_addline_infile(out, m->line_no); if(is_void) - out_printf(out,"\tg_return_if_fail ("); + out_printf(out, "\tg_return_if_fail ("); else - out_printf(out,"\tg_return_val_if_fail ("); + out_printf(out, "\tg_return_val_if_fail ("); switch(ch->chtype) { case NULL_CHECK: - out_printf(out,"%s != NULL",fa->name); + out_printf(out, "%s != NULL", fa->name); checked_null = TRUE; break; case TYPE_CHECK: - s = make_pre_macro(fa->atype->name,"IS"); + s = make_pre_macro(fa->atype->name, "IS"); if(checked_null) - out_printf(out,"%s (%s)",s,fa->name); + out_printf(out, "%s (%s)", s, fa->name); else /* if not check null, null may be valid */ - out_printf(out,"!(%s) || %s (%s)",fa->name,s, - fa->name); + out_printf(out, "!(%s) || %s (%s)", fa->name, + s, fa->name); g_free(s); break; case LT_CHECK: - out_printf(out,"%s < %s",fa->name,ch->number); + out_printf(out, "%s < %s", fa->name, ch->number); break; case GT_CHECK: - out_printf(out,"%s > %s",fa->name,ch->number); + out_printf(out, "%s > %s", fa->name, ch->number); break; case LE_CHECK: - out_printf(out,"%s <= %s",fa->name,ch->number); + out_printf(out, "%s <= %s", fa->name, ch->number); break; case GE_CHECK: - out_printf(out,"%s >= %s",fa->name,ch->number); + out_printf(out, "%s >= %s", fa->name, ch->number); break; case EQ_CHECK: - out_printf(out,"%s == %s",fa->name,ch->number); + out_printf(out, "%s == %s", fa->name, ch->number); break; case NE_CHECK: - out_printf(out,"%s != %s",fa->name,ch->number); + out_printf(out, "%s != %s", fa->name, ch->number); break; } if(is_void) - out_printf(out,");\n"); + out_printf(out, ");\n"); else { - out_printf(out,", ("); - print_type(out,m->mtype,TRUE); - out_printf(out,")%s);\n", + out_printf(out, ", ("); + print_type(out, m->mtype, TRUE); + out_printf(out, ")%s);\n", m->onerror?m->onerror:"0"); } } @@ -1182,54 +1537,42 @@ print_preconditions(Method *m) for(li=m->args;li;li=g_list_next(li)) { FuncArg *fa = li->data; if(fa->checks) - print_checks(m,fa); + print_checks(m, fa); } if(m->line_no>0) out_addline_outfile(out); } -/* put in code if it's needed */ -static void -put_in_gen_code(Method *m) -{ - /* now we only have the freeing of the private structure */ - if(privates>0 && - m->method == OVERRIDE_METHOD && - strcmp(m->id,"finalize")==0) { - out_printf(out,"\tg_free (%s (%s)->_priv);\n" - "\t%s (%s)->_priv = NULL;\n", - macrobase, - ((FuncArg *)m->args->data)->name, - macrobase, - ((FuncArg *)m->args->data)->name); - } -} - static void print_method_body(Method *m, int pre) { - out_printf(out,"{\n"); + out_printf(out, "{\n" + "#define __GOB_FUNCTION__ \"%s::%s\"\n", + ((Class *)class)->otype, + get_real_id(m->id)); if(pre) print_preconditions(m); - put_in_gen_code(m); - /* Note: the trailing }'s are on one line, this is so that we get the no return warning correctly and point to the correct line in the .gob file, yes this is slightly ugly in the .c file, but that is not supposed to be human readable anyway. */ if(m->cbuf) { - out_printf(out,"{\n"); + out_printf(out, "{\n"); if(m->ccode_line>0) - out_addline_infile(out,m->ccode_line); - out_printf(out,"\t%s}",m->cbuf); + out_addline_infile(out, m->ccode_line); + out_printf(out, "\t%s}", m->cbuf); } - out_printf(out,"}\n"); + /* Note, there is no \n between the last } and this } so that + * errors/warnings reported on the end of the body get pointed to the + * right line in the .gob source */ + out_printf(out, "}\n"); if(m->cbuf) out_addline_outfile(out); + out_printf(out, "#undef __GOB_FUNCTION__\n"); } static void @@ -1237,16 +1580,16 @@ put_signal_args(Method *m) { GList *li; GList *ali; - for(ali = m->gtktypes->next,li=m->args->next; + for(ali = m->gtktypes->next, li=m->args->next; li && ali; li=li->next, ali=ali->next) { FuncArg *fa = li->data; - const char *cast = get_cast(ali->data,FALSE); + const char *cast = get_cast(ali->data, FALSE); /* we should have already proved before that the we know all the types */ g_assert(cast); - out_printf(out,",\n\t\t(%s)%s",cast, + out_printf(out, ",\n\t\t(%s)%s", cast, fa->name); } } @@ -1256,7 +1599,7 @@ get_arg_names_for_macro(Method *m) { char *p; GList *li; - GString *gs = g_string_new(""); + GString *gs = g_string_new(NULL); p = ""; for(li=m->args;li;li=g_list_next(li)) { FuncArg *arg = li->data; @@ -1264,552 +1607,230 @@ get_arg_names_for_macro(Method *m) p = ","; } p = gs->str; - g_string_free(gs,FALSE); + g_string_free(gs, FALSE); return p; } static void put_method(Method *m) { - char *s,*args; + char *s, *args, *doc; gboolean is_void; - is_void = (strcmp(m->mtype->name,"void")==0 && - m->mtype->stars == 0); - out_printf(out,"\n"); + is_void = (strcmp(m->mtype->name, "void")==0 && + m->mtype->pointer == NULL); + out_printf(out, "\n"); + if(m->method != OVERRIDE_METHOD) { + doc = get_gtk_doc(m->id); + if(doc) { + out_printf(out, "%s", doc); + g_free(doc); + } + } switch(m->method) { case REGULAR_METHOD: - if(m->line_no>0) - out_addline_infile(out,m->line_no); + if(m->line_no > 0) + out_addline_infile(out, m->line_no); if(m->scope == PRIVATE_SCOPE) - print_method(out,"static ","\n"," ","\n",m,FALSE); + print_method(out, "static ", "\n", "", " ", "\n", + m, FALSE, FALSE, TRUE); else /* PUBLIC, PROTECTED */ - print_method(out,"","\n"," ","\n",m,FALSE); - print_method_body(m,TRUE); + print_method(out, "", "\n", "", " ", "\n", + m, FALSE, FALSE, TRUE); + print_method_body(m, TRUE); + /* the outfile line was added above */ break; case SIGNAL_FIRST_METHOD: case SIGNAL_LAST_METHOD: - if(m->line_no>0) - out_addline_infile(out,m->line_no); + if(m->line_no > 0) + out_addline_infile(out, m->line_no); if(m->scope == PRIVATE_SCOPE) - print_method(out,"static ","\n"," ","\n",m,FALSE); - else - print_method(out,"","\n"," ","\n",m,FALSE); + print_method(out, "static ", "\n", "", " ", "\n", + m, FALSE, FALSE, TRUE); + else /* PUBLIC, PROTECTED */ + print_method(out, "", "\n", "", " ", "\n", + m, FALSE, FALSE, TRUE); out_addline_outfile(out); - out_printf(out,"{\n"); - s = g_strdup(m->id); + out_printf(out, "{\n"); + s = g_strdup(get_real_id(m->id)); g_strup(s); - if(strcmp(m->mtype->name,"void")==0 && - m->mtype->stars==0) { + if(strcmp(m->mtype->name, "void") == 0 && + m->mtype->pointer == NULL) { print_preconditions(m); if(((FuncArg *)m->args->data)->name) - out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n" + out_printf(out, "\tgtk_signal_emit (GTK_OBJECT (%s),\n" "\t\tobject_signals[%s_SIGNAL]", - ((FuncArg *)m->args->data)->name,s); + ((FuncArg *)m->args->data)->name, s); put_signal_args(m); - out_printf(out,");\n}\n"); + out_printf(out, ");\n}\n"); } else { - out_printf(out,"\t"); - print_type(out,m->mtype,TRUE); - out_printf(out,"return_val;\n"); + out_printf(out, "\t"); + print_type(out, m->mtype, TRUE); + out_printf(out, "return_val = ("); + print_type(out, m->mtype, TRUE); + if(m->defreturn) + out_printf(out, ")(%s);\n", m->defreturn); + else if(m->onerror) + out_printf(out, ")(%s);\n", m->onerror); + else + out_printf(out, ")(0);\n"); print_preconditions(m); - out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n" + out_printf(out, "\tgtk_signal_emit (GTK_OBJECT (%s),\n" "\t\tobject_signals[%s_SIGNAL]", - ((FuncArg *)m->args->data)->name,s); + ((FuncArg *)m->args->data)->name, s); put_signal_args(m); - out_printf(out,",\n\t\t&return_val);\n" + out_printf(out, ",\n\t\t&return_val);\n" "\treturn return_val;\n}\n"); } if(!m->cbuf) break; - if(m->line_no>0) - out_addline_infile(out,m->line_no); - print_method(out,"static ","\n_real_"," ","\n",m,FALSE); - print_method_body(m,FALSE); + if(m->line_no > 0) + out_addline_infile(out, m->line_no); + print_method(out, "static ", "\n___real_", "", " ", "\n", + m, FALSE, FALSE, TRUE); + print_method_body(m, FALSE); + /* the outfile line was added above */ break; case VIRTUAL_METHOD: - if(m->line_no>0) - out_addline_infile(out,m->line_no); + if(m->line_no > 0) + out_addline_infile(out, m->line_no); if(m->scope==PRIVATE_SCOPE) - print_method(out,"static ","\n"," ","\n",m,FALSE); - else - print_method(out,"","\n"," ","\n",m,FALSE); + print_method(out, "static ", "\n", "", " ", "\n", + m, FALSE, FALSE, TRUE); + else /* PUBLIC, PROTECTED */ + print_method(out, "", "\n", "", " ", "\n", + m, FALSE, FALSE, TRUE); out_addline_outfile(out); - out_printf(out,"{\n" - "\t%sClass *klass;\n",typebase); + out_printf(out, "{\n" + "\t%sClass *klass;\n", typebase); print_preconditions(m); - out_printf(out,"\tklass = %s_CLASS(GTK_OBJECT(%s)->klass);\n\n" + out_printf(out, "\tklass = %s_CLASS(GTK_OBJECT(%s)->klass);\n\n" "\tif(klass->%s)\n", - macrobase, ((FuncArg *)m->args->data)->name, m->id); - if(strcmp(m->mtype->name,"void")==0 && - m->mtype->stars==0) { + macrobase, ((FuncArg *)m->args->data)->name, + get_real_id(m->id)); + if(strcmp(m->mtype->name, "void") == 0 && + m->mtype->pointer == NULL) { GList *li; - out_printf(out,"\t\t(*klass->%s)(%s",m->id, + out_printf(out, "\t\t(*klass->%s)(%s", + get_real_id(m->id), ((FuncArg *)m->args->data)->name); for(li=m->args->next;li;li=g_list_next(li)) { FuncArg *fa = li->data; - out_printf(out,",%s",fa->name); + out_printf(out, ",%s", fa->name); } - out_printf(out,");\n}\n"); + out_printf(out, ");\n}\n"); } else { GList *li; - out_printf(out,"\t\treturn (*klass->%s)(%s",m->id, + out_printf(out, "\t\treturn (*klass->%s)(%s", + get_real_id(m->id), ((FuncArg *)m->args->data)->name); for(li=m->args->next;li;li=g_list_next(li)) { FuncArg *fa = li->data; - out_printf(out,",%s",fa->name); + out_printf(out, ",%s", fa->name); } - out_printf(out,");\n" + out_printf(out, ");\n" "\telse\n" "\t\treturn ("); - print_type(out,m->mtype,TRUE); - out_printf(out,")(%s);\n}\n", - m->onerror?m->onerror:"0"); + print_type(out, m->mtype, TRUE); + if(m->defreturn) + out_printf(out, ")(%s);\n}\n", m->defreturn); + else if(m->onerror) + out_printf(out, ")(%s);\n}\n", m->onerror); + else + out_printf(out, ")(0);\n}\n"); } if(!m->cbuf) break; - if(m->line_no>0) - out_addline_infile(out,m->line_no); - print_method(out,"static ","\n_real_"," ","\n",m,FALSE); - print_method_body(m,FALSE); + if(m->line_no > 0) + out_addline_infile(out, m->line_no); + print_method(out, "static ", "\n___real_", "", " ", "\n", + m, FALSE, FALSE, TRUE); + print_method_body(m, FALSE); + /* the outfile line was added above */ break; case OVERRIDE_METHOD: if(!m->cbuf) break; - if(m->line_no>0) - out_addline_infile(out,m->line_no); - print_method(out,"static ","\n"," ","\n",m,FALSE); - s = replace_sep(m->otype,'_'); + 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", + m, FALSE, FALSE, FALSE); + g_free(s); + out_addline_outfile(out); + s = replace_sep(m->otype, '_'); g_strup(s); args = get_arg_names_for_macro(m); if(is_void) { - out_printf(out,"#define PARENT_HANDLER(%s) \\\n" + out_printf(out, "#define PARENT_HANDLER(%s) \\\n" "\t{ if(%s_CLASS(parent_class)->%s) \\\n" "\t\t(* %s_CLASS(parent_class)->%s)(%s); }\n", - args,s,m->id,s,m->id,args); + args, s, m->id, s, m->id, args); } else { - out_printf(out,"#define PARENT_HANDLER(%s) \\\n" + out_printf(out, "#define PARENT_HANDLER(%s) \\\n" "\t((%s_CLASS(parent_class)->%s)? \\\n" "\t\t(* %s_CLASS(parent_class)->%s)(%s): \\\n" "\t\t(", - args,s,m->id,s,m->id,args); - out_printf(out,"("); - print_type(out,m->mtype,TRUE); - out_printf(out,")%s))\n", + args, s, m->id, s, m->id, args); + out_printf(out, "("); + print_type(out, m->mtype, TRUE); + out_printf(out, ")%s))\n", m->onerror?m->onerror:"0"); } g_free(args); g_free(s); - print_method_body(m,TRUE); - out_printf(out,"#undef PARENT_HANDLER\n"); + print_method_body(m, TRUE); + /* the outfile line was added above */ + out_printf(out, "#undef PARENT_HANDLER\n"); break; default: break; } } -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) { - char *outfile,*outfileh,*outfileph; + char *outfile, *outfileh, *outfileph; if(!for_cpp) - outfile = g_strconcat(filebase,".c",NULL); + outfile = g_strconcat(filebase, ".c", NULL); else - outfile = g_strconcat(filebase,".cc",NULL); + outfile = g_strconcat(filebase, ".cc", NULL); if(no_touch_headers) - outfileh = g_strconcat("#gob#",filebase,".h#gob#",NULL); + outfileh = g_strconcat("#gob#", filebase, ".h#gob#", NULL); else - outfileh = g_strconcat(filebase,".h",NULL); + outfileh = g_strconcat(filebase, ".h", NULL); - if((privates>0 || protecteds>0 || always_private_header) && - !no_private_header) - outfileph = g_strconcat(filebase,"-private.h",NULL); + if((privates > 0 || protecteds > 0 || + private_header == PRIVATE_HEADER_ALWAYS) && + private_header != PRIVATE_HEADER_NEVER) + outfileph = g_strconcat(filebase, "-private.h", NULL); else outfileph = NULL; - out = fopen(outfile,"w"); - if(!out) { - g_error("Cannot open outfile: %s",outfile); - } - outh = fopen(outfileh,"w"); - if(!outh) { - g_error("Cannot open outfile: %s",outfileh); - } - if(outfileph) { - outph = fopen(outfileph,"w"); - if(!outph) { - g_error("Cannot open outfile: %s",outfileh); + if(no_write) { + devnull = fopen("/dev/null", "w"); + if(!devnull) + g_error("Cannot open null device"); + out = devnull; + outh = devnull; + if(outfileph) + outph = devnull; + } else { + out = fopen(outfile, "w"); + if(!out) { + g_error("Cannot open outfile: %s", outfile); + } + outh = fopen(outfileh, "w"); + if(!outh) + g_error("Cannot open outfile: %s", outfileh); + if(outfileph) { + outph = fopen(outfileph, "w"); + if(!outph) + g_error("Cannot open outfile: %s", outfileh); } } } @@ -1825,38 +1846,41 @@ put_argument_nongnu_wrappers(Class *c) for(li=c->nodes;li;li=g_list_next(li)) { Node *n = li->data; Argument *a = (Argument *)n; - char *s; + char *aname; char *cast; + if(n->type != ARGUMENT_NODE) continue; - s = g_strdup(a->name); - g_strup(s); + + aname = g_strdup(a->name); + g_strup(aname); + if(a->atype) - cast = get_type(a->atype,TRUE); + cast = get_type(a->atype, TRUE); else - cast = g_strdup(get_cast(a->gtktype,TRUE)); + cast = g_strdup(get_cast(a->gtktype, TRUE)); if(cast) { if(a->set) out_printf(outh, "#define %s_ARG_%s(arg) \t" "\"%s\",(%s)(arg)\n", - macrobase, s, a->name, cast); + macrobase, aname, a->name, cast); if(a->get) out_printf(outh, "#define %s_GET_ARG_%s(arg)\t" "\"%s\",(%s*)(arg)\n", - macrobase, s, a->name, cast); + macrobase, aname, a->name, cast); } else { if(a->set) out_printf(outh, "#define %s_ARG_%s(arg) \t" "\"%s\",(arg)\n", - macrobase, s, a->name); + macrobase, aname, a->name); if(a->get) out_printf(outh, "#define %s_GET_ARG_%s(arg)\t" "\"%s\",(arg)\n", - macrobase, s, a->name); + macrobase, aname, a->name); } g_free(cast); - g_free(s); + g_free(aname); } } @@ -1878,9 +1902,9 @@ put_argument_gnu_wrappers(Class *c) s = g_strdup(a->name); g_strup(s); if(a->atype) - cast = get_type(a->atype,TRUE); + cast = get_type(a->atype, TRUE); else - cast = g_strdup(get_cast(a->gtktype,TRUE)); + cast = g_strdup(get_cast(a->gtktype, TRUE)); if(cast) { if(a->set) out_printf(outh, "#define %s_ARG_%s(arg) \t" @@ -1906,64 +1930,371 @@ 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; + case AT_CCODE: + /* AT code is printed exactly like normal 'all' + code but is printed before */ + case A_CCODE: + if(outph) { + out_printf(outph, "\n"); + out_printf(outph, "%s\n", cc->cbuf); + out_addline_infile(outph, cc->line_no); + out_addline_outfile(outph); + } + out_printf(outh, "\n"); + out_printf(outh, "%s\n", cc->cbuf); + fp = out; + out_printf(fp, "\n"); + out_addline_infile(fp, cc->line_no); + 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 == A_CCODE || + cc->cctype == AT_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; + gboolean printed_private = FALSE; - time(&curtime); - out_printf(outh,"/* Generated by GOB (v%s)" - " (do not edit directly) */\n\n",VERSION); - if(outph) - out_printf(outph,"/* Generated by GOB (v%s)" - " (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)); + if(any_special) { + out_printf(out, "/* utility types we may need */\n"); + if(special_array[SPECIAL_2POINTER]) + out_printf(out, "typedef struct { " + "gpointer a; gpointer b; " + "} ___twopointertype;\n"); + if(special_array[SPECIAL_3POINTER]) + out_printf(out, "typedef struct { " + "gpointer a; gpointer b; " + "gpointer c; " + "} ___threepointertype;\n"); + if(special_array[SPECIAL_INT_POINTER]) + out_printf(out, "typedef struct { " + "gint a; gpointer b; " + "} ___intpointertype;\n"); + out_printf(out, "\n"); + } + + out_printf(outh, "\n/*\n" + " * Type checking and casting macros\n" + " */\n"); + out_printf(outh, "#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); + + if( ! no_self_alias) { + out_printf(out, "/* self casting macros */\n"); + out_printf(out, "#define SELF(x) %s(x)\n", macrobase); + out_printf(out, "#define IS_SELF(x) %s(x)\n", macrois); + out_printf(out, "#define SELF_CLASS(x) %s_CLASS(x)\n\n", + macrobase); + + out_printf(out, "/* self typedefs */\n"); + out_printf(out, "typedef %s Self;\n", typebase); + out_printf(out, "typedef %sClass SelfClass;\n\n", typebase); + } + + if(privates > 0 || always_private_struct) { + out_printf(outh, "\n/* Private structure type */\n"); + out_printf(outh, "typedef struct _%sPrivate %sPrivate;\n", + typebase, typebase); + if(privates == 0) + out_printf(outh, "/* There are no privates, this " + "structure is thus never defined */\n"); + } + + out_printf(outh, "\n/*\n" + " * Main object structure\n" + " */\n"); + 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)) { + static gboolean printed_public = FALSE; + Node *n = l->data; + Variable *v = (Variable *)n; + if(n->type == VARIABLE_NODE && + v->scope == PUBLIC_SCOPE) { + if( ! printed_public) { + out_printf(outh, "\t/*< public >*/\n"); + printed_public = TRUE; + } + 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) { + if( ! printed_private) { + out_printf(outh, "\t/*< private >*/\n"); + printed_private = TRUE; + } + put_variable((Variable *)n, outh); + } + } + if(privates > 0 || always_private_struct) { + if( ! printed_private) + out_printf(outh, "\t/*< private >*/\n"); + out_printf(outh, "\t%sPrivate *_priv;\n", typebase); + } + out_printf(outh, "};\n"); - { - int major=0,minor=0,pl=0; - sscanf(VERSION,"%d.%d.%d",&major,&minor,&pl); + 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, "\n/*\n" + " * Class definition\n" + " */\n"); + out_printf(outh, "typedef 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); + } + /* put class scope variables */ + 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 == CLASS_SCOPE) + put_variable((Variable *)n, outh); + } + out_printf(outh, "};\n\n"); - 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); + out_printf(out, "/* here are local prototypes */\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"); } - - p = replace_sep(((Class *)class)->otype,'_'); - g_strup(p); - out_printf(outh,"#ifndef __%s_H__\n#define __%s_H__\n\n" - "#include \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); - 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"); + out_printf(outh, "\n/*\n" + " * Public methods\n" + " */\n"); + + out_printf(outh, "guint\t%s_get_type\t(void);\n", funcbase); + 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); + } } - - p = g_strconcat(filebase,".h",NULL); + +/* 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); + } + } +#endif + + + /* argument wrapping macros */ + if(arguments>0 && !no_gnu) { + out_printf(outh, "\n/*\n" + " * Argument wrapping macros\n" + " */\n"); + out_printf(outh, "#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) { + out_printf(outh, "\n/*\n" + " * Argument wrapping macros\n" + " */\n"); + put_argument_nongnu_wrappers(c); + } + + 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); + } + } + + add_enums(c); + + add_get_type(); + + if(any_method_to_alias(c)) { + 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, "/* a macro for creating a new object of our type */\n"); + out_printf(out, + "#define GET_NEW ((%s *)gtk_type_new(%s_get_type()))\n\n", + typebase, funcbase); + + if(need_destroy) + add_destroy(c); + + if(need_finalize) + add_finalize(c); + + 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); + } + + 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); + if(outph) + out_printf(outph, "/* Generated by GOB (v%s)" + " (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)); +} + +static void +print_includes(void) +{ + gboolean found_header; + char *p; + + /* We may need string.h for memset */ + if(destructors > 0) + out_printf(out, "#include /* memset() */\n\n"); + + p = g_strconcat(filebase, ".h", NULL); found_header = TRUE; - if(!g_list_find_custom(include_files,p,(GCompareFunc)strcmp)) { - out_printf(out,"#include \"%s.h\"\n\n",filebase); + if(!g_list_find_custom(include_files, p, (GCompareFunc)strcmp)) { + out_printf(out, "#include \"%s.h\"\n\n", filebase); found_header = FALSE; } g_free(p); /* if we are creating a private header see if it was included */ if(outph) { - p = g_strconcat(filebase,"-private.h",NULL); - if(!g_list_find_custom(include_files,p,(GCompareFunc)strcmp)) { - out_printf(out,"#include \"%s-private.h\"\n\n", + p = g_strconcat(filebase, "-private.h", NULL); + if(!g_list_find_custom(include_files, p, (GCompareFunc)strcmp)) { + out_printf(out, "#include \"%s-private.h\"\n\n", filebase); if(found_header) print_error(TRUE, @@ -1978,245 +2309,154 @@ 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; +static void +print_header_prefixes(void) +{ + char *p; - 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"); + 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); - 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(!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(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"); - } +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\n"); + if(outph) { + if(!no_extern_c) + out_printf(outph, "\n#ifdef __cplusplus\n" + "}\n" + "#endif /* __cplusplus */\n"); + out_printf(outph, "\n#endif\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"); +static void +print_all_top(void) +{ + GList *li; - 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"); - } + /* print the AT_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==AT_CCODE) + print_ccode_block((CCode *)node); + } + } +} - 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); - } - } +static void +print_header_top(void) +{ + GList *li; - 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); - } - } + /* mandatory include */ + out_printf(outh, "#include \n\n"); - if(!no_gnu) - out_printf(out,"#undef ___NO_UNUSED_WARNING\n"); - - add_enums(c); - - add_get_type(); + /* 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); + } + } +} - 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"); - } +static void +generate_outfiles(void) +{ + GList *li; - out_printf(out,"#define GET_NEW (gtk_type_new(%s_get_type()))\n", - funcbase); + print_file_comments(); - add_inits(c); + print_all_top(); - if(arguments>0) { - add_getset_arg(c, TRUE); - add_getset_arg(c, FALSE); - } + print_header_top(); - for(l=c->nodes;l;l=g_list_next(l)) { - Node *n = l->data; - if(n->type == METHOD_NODE) { - put_method((Method *)n); - } - } + print_header_prefixes(); - out_printf(out,"#undef GET_NEW\n"); + print_version_macros(); - add_bad_hack_to_avoid_unused_warnings(c); + 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(); } - if(!for_cpp) - out_printf(outh,"\n#ifdef __cplusplus\n" - "}\n" - "#endif /* __cplusplus */\n"); - out_printf(outh,"\n#endif"); - if(outph) { - if(!for_cpp) - out_printf(outph,"\n#ifdef __cplusplus\n" - "}\n" - "#endif /* __cplusplus */\n"); - out_printf(outph,"\n#endif"); - } + print_header_postfixes(); } -#if 0 -static void -usage(poptContext optCon, int exitcode, char *error, char *addl) -{ - poptPrintUsage(optCon, stderr, 0); - if (error) fprintf(stderr, "%s: %s", error, addl); - exit(exitcode); -} -#endif - static void print_help(void) { - fprintf(stderr,"Gob version %s\n\n",VERSION); - fprintf(stderr,"Options:\n" + fprintf(stderr, "Gob version %s\n\n", VERSION); + fprintf(stderr, "gob [options] file.gob\n\n"); + fprintf(stderr, "Options:\n" "\t--help,-h,-? Display this help\n" "\t--version Display version\n" "\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" "\t--always-private-header Always create a private header " "file,\n" - "\t even if it would be empty\n" + "\t even if it would be empty " + "[default]\n" + "\t--ondemand-private-header Create private header only when " + "needed\n" "\t--no-private-header Don't create a private header, " "put private\n" "\t structure and protected " - "prototypes inside c file\n"); + "prototypes inside c file\n" + "\t--always-private-struct Always create a private pointer " + "in\n" + "\t the object structure\n" + "\t--no-write,-n Don't write output files, just " + "check syntax\n" + "\t--no-lines Don't print '#line' to output\n" + "\t--no-self-alias Don't create self type and macro " + "aliases\n" + "\t--no-kill-underscores Don't remove the leading underscore " + "from\n" + "\t short id names\n"); } static void @@ -2232,58 +2472,73 @@ parse_options(int argc, char *argv[]) if(no_opts || argv[i][0]!='-') { /*must be a file*/ if(got_file) { - fprintf(stderr,"Specify only one file!\n"); + fprintf(stderr, "Specify only one file!\n"); print_help(); exit(1); } filename = argv[i]; got_file = TRUE; - } else if(strcmp(argv[i],"--help")==0) { + } else if(strcmp(argv[i], "--help")==0) { print_help(); exit(0); - } else if(strcmp(argv[i],"--version")==0) { - fprintf(stderr,"Gob version %s\n",VERSION); + } else if(strcmp(argv[i], "--version")==0) { + fprintf(stderr, "Gob version %s\n", VERSION); exit(0); - } else if(strcmp(argv[i],"--exit-on-warn")==0) { + } else if(strcmp(argv[i], "--exit-on-warn")==0) { exit_on_warn = TRUE; - } else if(strcmp(argv[i],"--no-exit-on-warn")==0) { + } else if(strcmp(argv[i], "--no-exit-on-warn")==0) { exit_on_warn = FALSE; - } else if(strcmp(argv[i],"--for-cpp")==0) { + } else if(strcmp(argv[i], "--for-cpp")==0) { for_cpp = TRUE; - } else if(strcmp(argv[i],"--no-touch-headers")==0) { + } else if(strcmp(argv[i], "--no-touch-headers")==0) { no_touch_headers = TRUE; - } else if(strcmp(argv[i],"--always-private-header")==0) { - no_private_header = FALSE; - always_private_header = TRUE; - } else if(strcmp(argv[i],"--no-private-header")==0) { - always_private_header = FALSE; - no_private_header = TRUE; - } else if(strcmp(argv[i],"--no-gnu")==0) { + } else if(strcmp(argv[i], "--ondemand-private-header")==0) { + private_header = PRIVATE_HEADER_ONDEMAND; + } else if(strcmp(argv[i], "--always-private-header")==0) { + private_header = PRIVATE_HEADER_ALWAYS; + } else if(strcmp(argv[i], "--no-private-header")==0) { + private_header = PRIVATE_HEADER_NEVER; + } else if(strcmp(argv[i], "--no-gnu")==0) { no_gnu = TRUE; - } else if(strcmp(argv[i],"--")==0) { + } else if(strcmp(argv[i], "--no-extern-c")==0) { + no_extern_c = TRUE; + } else if(strcmp(argv[i], "--no-write")==0) { + no_write = TRUE; + } else if(strcmp(argv[i], "--no-lines")==0) { + no_lines = TRUE; + } else if(strcmp(argv[i], "--no-self-alias")==0) { + no_self_alias = TRUE; + } else if(strcmp(argv[i], "--no-kill-underscores")==0) { + no_kill_underscores = TRUE; + } else if(strcmp(argv[i], "--always-private-struct")==0) { + always_private_struct = TRUE; + } else if(strcmp(argv[i], "--")==0) { /*further arguments are files*/ no_opts = TRUE; - } else if(strncmp(argv[i],"--",2)==0) { + } else if(strncmp(argv[i], "--", 2)==0) { /*unknown long option*/ - fprintf(stderr,"Unknown option '%s'!\n",argv[i]); + fprintf(stderr, "Unknown option '%s'!\n", argv[i]); print_help(); exit(1); } else { /*by now we know we have a string starting with - which is a short option string*/ char *p = argv[i]+1; - for(p=argv[i]+1;*p;p++) { + for(p=argv[i]+1; *p; p++) { switch(*p) { case 'w': exit_on_warn=TRUE; break; + case 'n': + no_write = TRUE; + break; case 'h': case '?': print_help(); exit(0); default: fprintf(stderr, - "Unknown option '%c'!\n",*p); + "Unknown option '%c'!\n", *p); print_help(); exit(1); } @@ -2296,15 +2551,16 @@ parse_options(int argc, char *argv[]) static void compare_and_move_header(void) { - char *hfnew = g_strconcat("#gob#",filebase,".h#gob#",NULL); - char *hf = g_strconcat(filebase,".h",NULL); + char *hfnew = g_strconcat("#gob#", filebase, ".h#gob#", NULL); + char *hf = g_strconcat(filebase, ".h", NULL); struct stat s; - if(stat(hf,&s)==0) { + if(stat(hf, &s)==0) { char *s; - s = g_strdup_printf("cmp '%s' '%s' > /dev/null",hf,hfnew); + s = g_strdup_printf("cmp '%s' '%s' > /dev/null", hf, hfnew); if(system(s)==0) { if(unlink(hfnew)!=0) - print_error(FALSE,"Can't remove new header file",0); + print_error(FALSE, + "Can't remove new header file", 0); g_free(hfnew); g_free(hf); g_free(s); @@ -2312,10 +2568,10 @@ compare_and_move_header(void) } g_free(s); if(unlink(hf)!=0) - print_error(FALSE,"Can't remove old header file",0); + print_error(FALSE, "Can't remove old header file", 0); } - if(rename(hfnew,hf)!=0) - print_error(FALSE,"Can't rename new header file",0); + if(rename(hfnew, hf)!=0) + print_error(FALSE, "Can't rename new header file", 0); g_free(hfnew); g_free(hf); } @@ -2323,43 +2579,12 @@ 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); + parse_options(argc, argv); if(filename) { - yyin = fopen(filename,"r"); + yyin = fopen(filename, "r"); if(!yyin) { - fprintf(stderr,"Error: can't open file '%s'\n", + fprintf(stderr, "Error: can't open file '%s'\n", filename); exit(1); } @@ -2370,7 +2595,7 @@ main(int argc, char *argv[]) if(yyparse()!=0) g_error("Parsing errors, quitting"); if(!class) - print_error(FALSE," no class defined",0); + print_error(FALSE, " no class defined", 0); exit_on_error = FALSE; @@ -2380,13 +2605,22 @@ main(int argc, char *argv[]) overrides = count_overrides((Class *)class); privates = count_privates((Class *)class); protecteds = count_protecteds((Class *)class); + destructors = count_destructors((Class *)class); + initializers = count_initializers((Class *)class); make_bases(); make_inits((Class *)class); - if(privates>0) - make_finalize((Class *)class); + if(destructors > 0) { + need_destroy = TRUE; + find_destroy((Class *)class); + } + if(privates > 0) { + need_finalize = TRUE; + find_finalize((Class *)class); + } check_bad_symbols((Class *)class); check_duplicate_symbols((Class *)class); + check_duplicate_overrides((Class *)class); check_duplicate_signals_args((Class *)class); check_public_new((Class *)class); check_vararg((Class *)class); @@ -2394,24 +2628,30 @@ main(int argc, char *argv[]) check_nonvoidempty((Class *)class); check_signal_args((Class *)class); check_argument_types((Class *)class); + check_func_arg_checks((Class *)class); exit_on_error = TRUE; if(got_error) exit(1); + any_special = setup_special_array((Class *)class, special_array); + open_files(); generate_outfiles(); - fclose(out); - fclose(outh); + if(devnull) + fclose(devnull); + else { + fclose(out); + fclose(outh); + if(outph) + fclose(outph); + } - if(no_touch_headers) + if(no_touch_headers && !no_write) compare_and_move_header(); -#if 0 - poptFreeContext(optCon); -#endif return 0; }