X-Git-Url: http://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/6d0fe9d5f8c513045bf064ea256c822beac19037..2255b3d84eeb947d4c065332f16e410ae4704c63:/src/main.c diff --git a/src/main.c b/src/main.c index 751c064..b429ef9 100644 --- a/src/main.c +++ b/src/main.c @@ -57,8 +57,9 @@ static char *ptypebase; static int signals = 0; /* number of signals */ static int arguments = 0; /* number of named arguments */ -static int overrides = 0; /* number of override functions */ +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 gboolean made_aliases = FALSE; /* if we made any shorthand aliases and need the REALLY UGLY HACK to @@ -203,8 +204,9 @@ print_type(FILE *fp, Type *t, gboolean postfix_to_stars) if(postfix_to_stars) { char *p; /*XXX: this is ugly perhaps we can do this whole postfix thing - in a nicer way, we just count the number of '[' s and from that - we deduce the number of dimensions */ + in a nicer way, we just count the number of '[' s and from + that we deduce the number of dimensions, so that we can print + that many stars */ for(p=t->postfix; p && *p; p++) if(*p == '[') extra++; } @@ -262,9 +264,9 @@ make_method_pointers(Class *c) if(node->type == METHOD_NODE) { Method *m = (Method *)node; - if(m->scope == INIT_METHOD || - m->scope == CLASS_INIT_METHOD || - m->scope == OVERRIDE_METHOD) + if(m->method == INIT_METHOD || + m->method == CLASS_INIT_METHOD || + m->method == OVERRIDE_METHOD) continue; /* in C++ mode don't alias new */ @@ -291,21 +293,19 @@ add_bad_hack_to_avoid_unused_warnings(Class *c) out_printf(out,"\n\n/*REALLY BAD HACK\n" " This is to avoid unused warnings if you don't call\n" - " some method, it pollutes the namespace but the call\n" - " is weird enough. I need to find a better way to do\n" + " some method. I need to find a better way to do\n" " this */\n"); - out_printf(out,"void __%s_really_bad_hack_to_avoid_warnings(void);\n", - funcbase); - out_printf(out,"void\n__%s_really_bad_hack_to_avoid_warnings(void)\n" + out_printf(out,"static void\n" + "__%s_really_bad_hack_to_avoid_warnings(void)\n" "{\n",funcbase); 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->scope == INIT_METHOD || - m->scope == CLASS_INIT_METHOD || - m->scope == OVERRIDE_METHOD) + if(m->method == INIT_METHOD || + m->method == CLASS_INIT_METHOD || + m->method == OVERRIDE_METHOD) continue; /* in C++ mode we don't alias new */ @@ -315,6 +315,8 @@ add_bad_hack_to_avoid_unused_warnings(Class *c) out_printf(out,"\t((void (*)(void))%s)();\n",m->id); } } + out_printf(out, "\t__%s_really_bad_hack_to_avoid_warnings();\n", + funcbase); out_printf(out,"}\n\n"); } @@ -323,20 +325,20 @@ put_variable(Variable *v, FILE *fp) { out_printf(fp,"\t"); print_type(fp,v->vtype,FALSE); - out_printf(fp,"%s%s;\n",v->id, + 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"); } static void put_vs_method(Method *m) { - if(m->scope != SIGNAL_LAST_METHOD && - m->scope != SIGNAL_FIRST_METHOD && - m->scope != PRIVATE_SIGNAL_LAST_METHOD && - m->scope != PRIVATE_SIGNAL_FIRST_METHOD && - m->scope != VIRTUAL_METHOD && - m->scope != PRIVATE_VIRTUAL_METHOD) + if(m->method != SIGNAL_LAST_METHOD && + m->method != SIGNAL_FIRST_METHOD && + m->method != VIRTUAL_METHOD) return; print_method(outh,"\t","(* ",") ",";\n",m,TRUE); @@ -345,39 +347,40 @@ put_vs_method(Method *m) static void put_pub_method(Method *m) { - if(m->scope == PRIVATE_SCOPE || - m->scope == OVERRIDE_METHOD || - m->scope == INIT_METHOD || - m->scope == CLASS_INIT_METHOD || - m->scope == PRIVATE_SIGNAL_LAST_METHOD || - m->scope == PRIVATE_SIGNAL_FIRST_METHOD || - m->scope == PRIVATE_VIRTUAL_METHOD) + if(m->scope != PUBLIC_SCOPE) return; print_method(outh,"","\t","\t",";\n",m,FALSE); } static void -put_priv_method_prot(Method *m) +put_prot_method(Method *m) { - if(m->scope == PUBLIC_SCOPE) + if(m->scope != PROTECTED_SCOPE) return; - if(m->scope == PRIVATE_SIGNAL_LAST_METHOD || - m->scope == PRIVATE_SIGNAL_FIRST_METHOD || - m->scope == PRIVATE_VIRTUAL_METHOD) { - if(m->cbuf && *m->cbuf->str) + if(outph) + print_method(outph,"","\t","\t",";\n",m,FALSE); + else + print_method(out,"","\t","\t",";\n",m,FALSE); +} + +static void +put_priv_method_prot(Method *m) +{ + if(m->method == SIGNAL_LAST_METHOD || + m->method == SIGNAL_FIRST_METHOD || + m->method == VIRTUAL_METHOD) { + if(m->cbuf) print_method(out,"static ","_real_"," ",";\n",m,FALSE); - print_method(out,"static ",""," ",";\n",m,FALSE); - } else if(m->scope == SIGNAL_LAST_METHOD || - m->scope == SIGNAL_FIRST_METHOD || - m->scope == VIRTUAL_METHOD) { - if(!m->cbuf || !*m->cbuf->str) - return; - print_method(out,"static ","_real_"," ",";\n",m,FALSE); - } else { - print_method(out,"static ",""," ",";\n",m,FALSE); } + + if(m->scope == PRIVATE_SCOPE || + m->method == INIT_METHOD || + m->method == CLASS_INIT_METHOD || + (m->method == OVERRIDE_METHOD && + m->cbuf)) + print_method(out,"static ",""," ",";\n",m,FALSE); } static GList * @@ -408,11 +411,11 @@ make_inits(Class *cl) Node *n = li->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; - if(m->scope == INIT_METHOD) { + if(m->method == INIT_METHOD) { if(got_init) print_error(FALSE,"init defined more then once",m->line_no); got_init = TRUE; - } else if(m->scope == CLASS_INIT_METHOD) { + } else if(m->method == CLASS_INIT_METHOD) { if(got_class_init) print_error(FALSE,"class_init defined more then once",m->line_no); got_class_init = TRUE; @@ -420,7 +423,7 @@ make_inits(Class *cl) } } if(!got_class_init) { - node = new_method(CLASS_INIT_METHOD, + 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")), @@ -428,7 +431,7 @@ make_inits(Class *cl) cl->nodes = g_list_prepend(cl->nodes,node); } if(!got_init) { - node = new_method(INIT_METHOD, + 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")), @@ -447,7 +450,7 @@ make_destroy(Class *cl) Node *n = li->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; - if(m->scope == OVERRIDE_METHOD && + if(m->method == OVERRIDE_METHOD && strcmp(m->id,"destroy")==0) { if(strcmp(m->otype,"Gtk:Object")==0) { got_destroy = TRUE; @@ -462,32 +465,132 @@ make_destroy(Class *cl) } } if(!got_destroy) { - node = new_method(OVERRIDE_METHOD, + node = new_method(NO_SCOPE, OVERRIDE_METHOD, (Type *)new_type(0,g_strdup("void"),NULL), g_strdup("Gtk:Object"), NULL,g_strdup("destroy"), make_func_arg("Gtk:Object",FALSE,g_strdup("o")), NULL, - g_string_new("PARENT_HANDLER (o);\n"), + 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 { + char *gtkname; + char *typename; +} our_gtk_type_table[] = { + { "NONE", "void" }, + { "CHAR", "gchar" }, + { "UCHAR", "guchar" }, + { "BOOL", "gboolean" }, + { "INT", "gint" }, + { "UINT", "guint" }, + { "LONG", "glong" }, + { "ULONG", "gulong" }, + { "FLOAT", "gfloat" }, + { "DOUBLE", "gdouble" }, + { "STRING", /*"GtkString"*/"gchar *" }, + { "ENUM", /*"GtkEnum"*/"gint" }, + { "FLAGS", /*"GtkFlags"*/"guint" }, + { "BOXED", /*"GtkBoxed"*/"gpointer" }, + { "POINTER", "gpointer" }, + { "OBJECT", "GtkObject *" }, + { "SIGNAL", /*"GtkSignal"*/"__twopointertype" }, + { "ARGS", /*"GtkArgs"*/"__twopointertype" }, + { "CALLBACK", /*"GtkCallback"*/"__threepointertype" }, + { "C_CALLBACK", /*"GtkCCallback"*/"__twopointertype" }, + { "FOREIGN", /*"GtkForeign"*/"__twopointertype" }, + + { NULL, NULL } +}; + +static const char * +get_cast(char *type) +{ + int i; + for(i=0;our_gtk_type_table[i].gtkname;i++) { + if(strcmp(our_gtk_type_table[i].gtkname,type)==0) { + return our_gtk_type_table[i].typename; + } + } + return NULL; +} + + +/* hash of method -> name of signal prototype */ static GHashTable *marsh = NULL; +/* list of methods with different signal prototypes, + we check this list if we can use a signal prototype of a + previous signal method, there are only uniques here */ +static GList *eq_signal_methods = NULL; + +/* compare a list of strings */ +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) { + return FALSE; + } + } + /* the the lists were different length */ + if(a || b) + return FALSE; + return TRUE; +} + +static Method * +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)) + return mm; + } + return NULL; +} + +static void +print_signal_marsal_args(Method *m) +{ + 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)) { + if(!for_cpp) + out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])", + (char *)li->data,i); + else { + out_printf(out, ",\n\t\t(%s)" + "GTK_VALUE_%s(args[%d])", + get_cast(li->data), + (char *)li->data,i); + } + } + } + out_printf(out, ",\n\t\tfunc_data);\n}\n\n"); +} + + static void add_signal_prots(Method *m) { GList *li; static int sig = 1; char *s; + Method *mm; - if(m->scope != SIGNAL_LAST_METHOD && - m->scope != SIGNAL_FIRST_METHOD && - m->scope != PRIVATE_SIGNAL_LAST_METHOD && - m->scope != PRIVATE_SIGNAL_FIRST_METHOD) + if(m->method != SIGNAL_LAST_METHOD && + m->method != SIGNAL_FIRST_METHOD) return; if(!marsh) @@ -496,21 +599,26 @@ add_signal_prots(Method *m) 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); + return; + } s = g_strdup_printf("__Sig%d",sig++); g_hash_table_insert(marsh,m,s); + eq_signal_methods = g_list_prepend(eq_signal_methods,m); - out_printf(out,"\ntypedef "); - print_type(out,m->mtype,TRUE); - - out_printf(out,"(*%s) (",s); + /* 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),s, typebase); - for(li=m->args;li;li=g_list_next(li)) { - FuncArg *arg = li->data; - print_type(out,arg->atype,TRUE); - out_printf(out,", "); - } + for(li=m->gtktypes->next;li;li=g_list_next(li)) + out_printf(out,"%s, ",get_cast(li->data)); out_printf(out,"gpointer);\n"); out_printf(out,"\nstatic void\n" @@ -521,31 +629,10 @@ add_signal_prots(Method *m) "{\n",s); if(strcmp(m->gtktypes->data,"NONE")==0) { - int i; out_printf(out, "\t%s rfunc;\n\n" "\trfunc = (%s)func;\n\n" "\t(*rfunc)((%s *)object",s,s,typebase); - if(strcmp(m->gtktypes->next->data,"NONE")!=0) { - GList *ali = m->args->next; - for(i=0,li=m->gtktypes->next;li; - i++,li=g_list_next(li)) { - if(!for_cpp || !ali) - out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])", - (char *)li->data,i); - else { - FuncArg *fa = ali->data; - out_printf(out, ",\n\t\t("); - print_type(out,fa->atype,TRUE); - out_printf(out, ")GTK_VALUE_%s(args[%d])", - (char *)li->data,i); - } - - if(ali) ali = ali->next; - } - } - out_printf(out, ",\n\t\tfunc_data);\n}\n\n"); } else { - int i; out_printf(out, "\t%s rfunc;\n\t",s); print_type(out,m->mtype,TRUE); out_printf(out, " *retval;\n\n" @@ -554,26 +641,8 @@ add_signal_prots(Method *m) "\t*retval = (*rfunc)((%s *)object", s,(char *)m->gtktypes->data, g_list_length(m->gtktypes)-1,typebase); - if(strcmp(m->gtktypes->next->data,"NONE")!=0) { - GList *ali = m->args->next; - for(i=0,li=m->gtktypes->next;li; - i++,li=g_list_next(li)) { - if(!for_cpp || !ali) - out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])", - (char *)li->data,i); - else { - FuncArg *fa = ali->data; - out_printf(out, ",\n\t\t("); - print_type(out,fa->atype,TRUE); - out_printf(out, ")GTK_VALUE_%s(args[%d])", - (char *)li->data,i); - } - - if(ali) ali = ali->next; - } - } - out_printf(out, ",\n\t\tfunc_data);\n}\n\n"); } + print_signal_marsal_args(m); } @@ -588,10 +657,8 @@ add_enums(Class *c) Node *n = li->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; - if(m->scope == SIGNAL_LAST_METHOD || - m->scope == SIGNAL_FIRST_METHOD || - m->scope == PRIVATE_SIGNAL_LAST_METHOD || - m->scope == PRIVATE_SIGNAL_FIRST_METHOD) { + if(m->method == SIGNAL_LAST_METHOD || + m->method == SIGNAL_FIRST_METHOD) { char *s = g_strdup(m->id); g_strup(s); out_printf(out,"\t%s_SIGNAL,\n",s); @@ -664,11 +731,10 @@ add_overrides(Class *c, char *oname, gboolean did_gtk_obj) for(li=c->nodes;li;li=g_list_next(li)) { Node *n = li->data; char *f; - Method *m; + Method *m = (Method *)n; if(n->type != METHOD_NODE || - ((Method *)n)->scope != OVERRIDE_METHOD) + m->method != OVERRIDE_METHOD) continue; - m = (Method *)n; s = remove_sep(m->otype); @@ -698,22 +764,18 @@ add_signals(Class *c) out_printf(out,"\n"); for(li=c->nodes;li;li=g_list_next(li)) { Node *n = li->data; - Method *m; char *mar; char *sig; int is_none; int last = FALSE; + Method *m = (Method *)n; if(n->type != METHOD_NODE || - (((Method *)n)->scope != SIGNAL_FIRST_METHOD && - ((Method *)n)->scope != SIGNAL_LAST_METHOD && - ((Method *)n)->scope != PRIVATE_SIGNAL_FIRST_METHOD && - ((Method *)n)->scope != PRIVATE_SIGNAL_LAST_METHOD)) + (m->method != SIGNAL_FIRST_METHOD && + m->method != SIGNAL_LAST_METHOD)) continue; - m = (Method *)n; - if(m->scope == SIGNAL_FIRST_METHOD || - m->scope == PRIVATE_SIGNAL_FIRST_METHOD) + if(m->method == SIGNAL_FIRST_METHOD) last = FALSE; else last = TRUE; @@ -764,27 +826,27 @@ set_def_handlers(Class *c, char *oname) out_printf(out,"\n"); for(li=c->nodes;li;li=g_list_next(li)) { Node *n = li->data; - Method *m; + Method *m = (Method *)n; if(n->type != METHOD_NODE || - (((Method *)n)->scope != SIGNAL_FIRST_METHOD && - ((Method *)n)->scope != SIGNAL_LAST_METHOD && - ((Method *)n)->scope != PRIVATE_SIGNAL_FIRST_METHOD && - ((Method *)n)->scope != PRIVATE_SIGNAL_LAST_METHOD && - ((Method *)n)->scope != VIRTUAL_METHOD && - ((Method *)n)->scope != PRIVATE_VIRTUAL_METHOD && - ((Method *)n)->scope != OVERRIDE_METHOD)) + (m->method != SIGNAL_FIRST_METHOD && + m->method != SIGNAL_LAST_METHOD && + m->method != VIRTUAL_METHOD && + m->method != OVERRIDE_METHOD)) continue; - m = (Method *)n; - if(m->scope == OVERRIDE_METHOD) { + if(m->method == OVERRIDE_METHOD) { char *s; s = replace_sep(m->otype,'_'); g_strdown(s); - out_printf(out,"\t%s_class->%s = %s_%s;\n", - s,m->id,funcbase,m->id); + if(m->cbuf) + out_printf(out,"\t%s_class->%s = %s_%s;\n", + s,m->id,funcbase,m->id); + else + out_printf(out,"\t%s_class->%s = NULL;\n", + s,m->id); } else { - if(m->cbuf && *m->cbuf->str) + if(m->cbuf) out_printf(out,"\t%s->%s = _real_%s_%s;\n", oname,m->id,funcbase,m->id); else @@ -847,7 +909,7 @@ add_inits(Class *c) if(n->type != METHOD_NODE) continue; m = (Method *)n; - if(m->scope == INIT_METHOD) { + 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); @@ -860,7 +922,7 @@ add_inits(Class *c) ((FuncArg *)m->args->data)->name, typebase); } - } else if(m->scope == CLASS_INIT_METHOD) { + } 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); @@ -897,12 +959,12 @@ add_inits(Class *c) } else continue; - if(m->cbuf && *m->cbuf->str) { + if(m->cbuf) { out_printf(out," {\n"); out_addline_infile(out,m->ccode_line); - out_printf(out,"%s\n",m->cbuf->str); + out_printf(out,"%s\n",m->cbuf); out_addline_outfile(out); - out_printf(out," }\n",m->cbuf->str); + out_printf(out," }\n"); } else { out_printf(out,"return;\n"); } @@ -928,7 +990,7 @@ add_getset_arg(Class *c, int is_set) Node *n = li->data; Argument *a; char *s; - GString *cbuf; + char *cbuf; int line_no; if(n->type != ARGUMENT_NODE) continue; @@ -950,7 +1012,7 @@ add_getset_arg(Class *c, int is_set) s,a->gtktype); g_free(s); out_addline_infile(out,line_no); - out_printf(out,"%s\n",cbuf->str); + out_printf(out,"%s\n",cbuf); out_addline_outfile(out); out_printf(out,"\t\t}\n\t\tbreak;\n" "#undef ARG\n"); @@ -962,7 +1024,7 @@ static void print_checks(Method *m, FuncArg *fa) { GList *li; - int is_void; + gboolean is_void; is_void = (strcmp(m->mtype->name,"void")==0 && m->mtype->stars == 0); @@ -1030,7 +1092,7 @@ put_in_gen_code(Method *m) { /* now we only have the freeing of the private structure */ if(privates>0 && - m->scope == OVERRIDE_METHOD && + m->method == OVERRIDE_METHOD && strcmp(m->id,"destroy")==0) { out_printf(out,"\tg_free (%s (%s)->_priv);\n" "\t%s (%s)->_priv = NULL;\n", @@ -1050,62 +1112,80 @@ print_method_body(Method *m, int pre) print_preconditions(m); put_in_gen_code(m); - out_printf(out,"\t{\n"); - - out_addline_infile(out,m->ccode_line); - out_printf(out,"\t\t%s\n",m->cbuf->str); - out_addline_outfile(out); + /* 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_addline_infile(out,m->ccode_line); + out_printf(out,"\t%s}",m->cbuf); + } - out_printf(out,"\t}\n"); out_printf(out,"}\n"); + + if(m->cbuf) + out_addline_outfile(out); +} + +static void +put_signal_args(Method *m) +{ + GList *li; + GList *ali; + 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); + /* 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, + fa->name); + } } static void put_method(Method *m) { char *s; - int private = FALSE; - int is_void; + gboolean is_void; is_void = (strcmp(m->mtype->name,"void")==0 && m->mtype->stars == 0); out_printf(out,"\n"); - switch(m->scope) { - case PUBLIC_SCOPE: - out_addline_infile(out,m->line_no); - print_method(out,"","\n"," ","\n",m,FALSE); - print_method_body(m,TRUE); - break; - case PRIVATE_SCOPE: + switch(m->method) { + case REGULAR_METHOD: out_addline_infile(out,m->line_no); - print_method(out,"static ","\n"," ","\n",m,FALSE); + if(m->scope == PRIVATE_SCOPE) + print_method(out,"static ","\n"," ","\n",m,FALSE); + else /* PUBLIC, PROTECTED */ + print_method(out,"","\n"," ","\n",m,FALSE); print_method_body(m,TRUE); break; - case PRIVATE_SIGNAL_FIRST_METHOD: - case PRIVATE_SIGNAL_LAST_METHOD: - private = TRUE; case SIGNAL_FIRST_METHOD: case SIGNAL_LAST_METHOD: out_addline_infile(out,m->line_no); - print_method(out,private?"static ":"","\n"," ","\n",m,FALSE); + if(m->scope == PRIVATE_SCOPE) + print_method(out,"static ","\n"," ","\n",m,FALSE); + else + print_method(out,"","\n"," ","\n",m,FALSE); out_addline_outfile(out); out_printf(out,"{\n"); s = g_strdup(m->id); g_strup(s); if(strcmp(m->mtype->name,"void")==0 && m->mtype->stars==0) { - GList *li; print_preconditions(m); if(((FuncArg *)m->args->data)->name) out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n" "\t\tobject_signals[%s_SIGNAL]", ((FuncArg *)m->args->data)->name,s); - for(li=m->args->next;li;li=g_list_next(li)) { - FuncArg *fa = li->data; - out_printf(out,",\n\t\t%s",fa->name); - } + put_signal_args(m); out_printf(out,");\n}\n"); } else { - GList *li; out_printf(out,"\t"); print_type(out,m->mtype,TRUE); out_printf(out,"return_val;\n"); @@ -1113,25 +1193,23 @@ put_method(Method *m) out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n" "\t\tobject_signals[%s_SIGNAL]", ((FuncArg *)m->args->data)->name,s); - for(li=m->args->next;li;li=g_list_next(li)) { - FuncArg *fa = li->data; - out_printf(out,",\n\t\t%s",fa->name); - } + put_signal_args(m); out_printf(out,",\n\t\t&return_val);\n" "\treturn return_val;\n}\n"); } - if(!m->cbuf || !*m->cbuf->str) + if(!m->cbuf) break; out_addline_infile(out,m->line_no); print_method(out,"static ","\n_real_"," ","\n",m,FALSE); print_method_body(m,FALSE); break; - case PRIVATE_VIRTUAL_METHOD: - private = TRUE; case VIRTUAL_METHOD: out_addline_infile(out,m->line_no); - print_method(out,private?"static ":"","\n"," ","\n",m,FALSE); + if(m->scope==PRIVATE_SCOPE) + print_method(out,"static ","\n"," ","\n",m,FALSE); + else + print_method(out,"","\n"," ","\n",m,FALSE); out_addline_outfile(out); out_printf(out,"{\n" "\t%sClass *klass;\n",typebase); @@ -1165,13 +1243,15 @@ put_method(Method *m) m->onerror?m->onerror:"0"); } - if(!m->cbuf || !*m->cbuf->str) + if(!m->cbuf) break; out_addline_infile(out,m->line_no); print_method(out,"static ","\n_real_"," ","\n",m,FALSE); print_method_body(m,FALSE); break; case OVERRIDE_METHOD: + if(!m->cbuf) + break; out_addline_infile(out,m->line_no); print_method(out,"static ","\n"," ","\n",m,FALSE); s = replace_sep(m->otype,'_'); @@ -1202,7 +1282,7 @@ put_method(Method *m) } static void -check_duplicate(Class *c,Node *node,char *id, int line_no) +check_duplicate(Class *c, Node *node, char *id, int line_no) { GList *l; for(l=c->nodes;l;l=g_list_next(l)) { @@ -1256,12 +1336,9 @@ check_bad_symbols(Class *c) Node *n = l->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; - if((m->scope == SIGNAL_LAST_METHOD || - m->scope == SIGNAL_FIRST_METHOD || - m->scope == PRIVATE_SIGNAL_LAST_METHOD || - m->scope == PRIVATE_SIGNAL_FIRST_METHOD || - m->scope == VIRTUAL_METHOD || - m->scope == PRIVATE_VIRTUAL_METHOD) && + 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 " @@ -1297,10 +1374,8 @@ check_duplicate_named(Class *c,Node *node,char *id, int line_no) char *s; if(n->type == METHOD_NODE) { Method *m = (Method *)n; - if(m->scope == SIGNAL_LAST_METHOD || - m->scope == SIGNAL_FIRST_METHOD || - m->scope == PRIVATE_SIGNAL_LAST_METHOD || - m->scope == PRIVATE_SIGNAL_FIRST_METHOD) { + if(m->method == SIGNAL_LAST_METHOD || + m->method == SIGNAL_FIRST_METHOD) { nid = m->id; nline_no = m->line_no; } else @@ -1330,10 +1405,8 @@ check_duplicate_signals_args(Class *c) Node *n = l->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; - if(m->scope == SIGNAL_LAST_METHOD || - m->scope == SIGNAL_FIRST_METHOD || - m->scope == PRIVATE_SIGNAL_LAST_METHOD || - m->scope == PRIVATE_SIGNAL_FIRST_METHOD) + 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; @@ -1350,10 +1423,12 @@ check_public_new(Class *c) Node *n = l->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; - if(m->scope!=PUBLIC_SCOPE && - strcmp(m->id,"new")==0) + if((strcmp(m->id,"new")==0) && + (m->method != REGULAR_METHOD || + m->scope != PUBLIC_SCOPE)) print_error(TRUE, - "'new' should be a public method", + "'new' should be a regular\n" + "public method", m->line_no); } } @@ -1369,13 +1444,10 @@ check_vararg(Class *c) Method *m = (Method *)n; if(!m->vararg) continue; - if(m->scope == OVERRIDE_METHOD || - m->scope == SIGNAL_LAST_METHOD || - m->scope == SIGNAL_FIRST_METHOD || - m->scope == PRIVATE_SIGNAL_LAST_METHOD || - m->scope == PRIVATE_SIGNAL_FIRST_METHOD || - m->scope == VIRTUAL_METHOD || - m->scope == PRIVATE_VIRTUAL_METHOD) { + 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 " @@ -1396,13 +1468,10 @@ check_firstarg(Class *c) Method *m = (Method *)n; if(m->args) continue; - if(m->scope == OVERRIDE_METHOD || - m->scope == SIGNAL_LAST_METHOD || - m->scope == SIGNAL_FIRST_METHOD || - m->scope == PRIVATE_SIGNAL_LAST_METHOD || - m->scope == PRIVATE_SIGNAL_FIRST_METHOD || - m->scope == VIRTUAL_METHOD || - m->scope == PRIVATE_VIRTUAL_METHOD) { + 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", @@ -1412,6 +1481,62 @@ check_firstarg(Class *c) } } +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)) + 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 int count_signals(Class *c) { @@ -1421,10 +1546,8 @@ count_signals(Class *c) Node *n = l->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; - if(m->scope == SIGNAL_LAST_METHOD || - m->scope == SIGNAL_FIRST_METHOD || - m->scope == PRIVATE_SIGNAL_LAST_METHOD || - m->scope == PRIVATE_SIGNAL_FIRST_METHOD) + if(m->method == SIGNAL_LAST_METHOD || + m->method == SIGNAL_FIRST_METHOD) num++; } } @@ -1454,7 +1577,7 @@ count_overrides(Class *c) Node *n = l->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; - if(m->scope == OVERRIDE_METHOD) + if(m->method == OVERRIDE_METHOD) num++; } } @@ -1477,6 +1600,22 @@ count_privates(Class *c) 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) @@ -1492,7 +1631,7 @@ open_files(void) else outfileh = g_strconcat(filebase,".h",NULL); - if((privates>0 || always_private_header) && + if((privates>0 || protecteds>0 || always_private_header) && !no_private_header) outfileph = g_strconcat(filebase,"-private.h",NULL); else @@ -1593,13 +1732,22 @@ generate_outfiles(void) out_printf(fp,"\n"); out_addline_infile(fp,cc->line_no); } - out_printf(fp,"%s\n",cc->cbuf->str); + 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); @@ -1626,6 +1774,14 @@ generate_outfiles(void) 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"); @@ -1634,7 +1790,7 @@ generate_outfiles(void) FILE *outfp; /* if we are to stick this into the private - header, otherwise stick it directly into the + header, if not stick it directly into the C file */ if(outph) outfp = outph; @@ -1679,10 +1835,12 @@ generate_outfiles(void) "guint arg_id);\n"); } + out_printf(out,"/* here are local prototypes */\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); } } @@ -1690,9 +1848,8 @@ generate_outfiles(void) if(signals>0) { for(l=c->nodes;l;l=g_list_next(l)) { Node *n = l->data; - if(n->type == METHOD_NODE) { + if(n->type == METHOD_NODE) add_signal_prots((Method *)n); - } } } @@ -1756,16 +1913,19 @@ print_help(void) fprintf(stderr,"Gob version %s\n\n",VERSION); 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-touch-headers Don't touch headers unless they " "really changed\n" "\t--always-private-header Always create a private header " - "file, even if it would be empty\n" + "file,\n" + "\t even if it would be empty\n" "\t--no-private-header Don't create a private header, " - "put private structure inside c " - "file\n"); + "put private\n" + "\t structure and protected " + "prototypes inside c file\n"); } static void @@ -1790,6 +1950,9 @@ parse_options(int argc, char *argv[]) } 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); + exit(0); } else if(strcmp(argv[i],"--exit-on-warn")==0) { exit_on_warn = TRUE; } else if(strcmp(argv[i],"--no-exit-on-warn")==0) { @@ -1836,6 +1999,7 @@ parse_options(int argc, char *argv[]) } } +/* this is a somewhat ugly hack, but it appears to work */ static void compare_and_move_header(void) { @@ -1922,6 +2086,7 @@ main(int argc, char *argv[]) arguments = count_arguments((Class *)class); overrides = count_overrides((Class *)class); privates = count_privates((Class *)class); + protecteds = count_protecteds((Class *)class); make_bases(); make_inits((Class *)class); @@ -1933,6 +2098,8 @@ main(int argc, char *argv[]) check_public_new((Class *)class); check_vararg((Class *)class); check_firstarg((Class *)class); + check_nonvoidempty((Class *)class); + check_signal_args((Class *)class); exit_on_error = TRUE;