2 * Copyright (C) 1999 the Free Software Foundation.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
38 char *filename = NULL;
47 extern GList *include_files;
50 static char *funcbase;
51 static char *pfuncbase;
52 static char *macrobase;
54 static char *macrotype;
55 static char *typebase;
56 static char *ptypebase;
58 static int signals = 0; /* number of signals */
59 static int arguments = 0; /* number of named arguments */
60 static int overrides = 0; /* number of override methods */
61 static int privates = 0; /* number of private data members */
62 static int protecteds = 0; /* number of protected methods */
64 static gboolean made_aliases = FALSE; /* if we made any shorthand aliases
65 and need the REALLY UGLY HACK to
72 gboolean no_touch_headers = FALSE;
73 gboolean for_cpp = FALSE;
74 gboolean no_gnu = FALSE;
75 gboolean exit_on_warn = FALSE;
76 gboolean exit_on_error = TRUE;
77 gboolean got_error = FALSE;
78 gboolean always_private_header = FALSE;
79 gboolean no_private_header = FALSE;
80 gboolean no_extern_c = FALSE;
85 filebase = replace_sep(((Class *)class)->otype,'-');
88 funcbase = replace_sep(((Class *)class)->otype,'_');
91 pfuncbase = replace_sep(((Class *)class)->ptype,'_');
94 macrobase = replace_sep(((Class *)class)->otype,'_');
97 macrois = make_pre_macro(((Class *)class)->otype,"IS");
98 macrotype = make_pre_macro(((Class *)class)->otype,"TYPE");
100 typebase = remove_sep(((Class *)class)->otype);
102 ptypebase = remove_sep(((Class *)class)->ptype);
106 get_type(Type *t, gboolean postfix_to_stars)
113 s = remove_sep(t->name);
114 gs = g_string_new(s);
119 if(postfix_to_stars) {
121 /*XXX: this is ugly perhaps we can do this whole postfix thing
122 in a nicer way, we just count the number of '[' s and from
123 that we deduce the number of dimensions, so that we can print
125 for(p=t->postfix; p && *p; p++)
126 if(*p == '[') extra++;
128 g_string_append_c(gs,' ');
130 for(i=0;i<(t->stars+extra);i++)
131 g_string_append_c(gs,'*');
134 g_string_free(gs,FALSE);
139 print_type(FILE *fp, Type *t, gboolean postfix_to_stars)
143 s = get_type(t,postfix_to_stars);
144 out_printf(fp,"%s",s);
150 print_method(FILE *fp, char *typeprefix, char *nameprefix,
151 char *namepostfix,char *postfix, Method *m,
152 gboolean no_funcbase)
156 out_printf(fp,"%s",typeprefix);
157 print_type(fp,m->mtype,TRUE);
159 out_printf(fp,"%s%s%s(",
160 nameprefix,m->id,namepostfix);
162 out_printf(fp,"%s%s_%s%s(",
163 nameprefix,funcbase,m->id,namepostfix);
166 for(li=m->args;li;li=g_list_next(li)) {
167 FuncArg *arg = li->data;
168 print_type(fp,arg->atype,FALSE);
170 out_printf(fp,"%s%s, ",arg->name,
172 arg->atype->postfix:"");
174 out_printf(fp,"%s%s",arg->name,
176 arg->atype->postfix:"");
179 out_printf(fp,", ...");
181 out_printf(fp,"void");
183 out_printf(fp,")%s",postfix);
188 make_method_gnu_aliases(Class *c)
192 for(li=c->nodes;li;li=g_list_next(li)) {
193 Node *node = li->data;
194 if(node->type == METHOD_NODE) {
195 Method *m = (Method *)node;
197 if(m->method == INIT_METHOD ||
198 m->method == CLASS_INIT_METHOD ||
199 m->method == OVERRIDE_METHOD)
202 /* in C++ mode don't alias new */
203 if(for_cpp && strcmp(m->id, "new")==0)
206 out_printf(out, "static const typeof(&%s_%s) %s "
207 "__attribute__ ((__unused__)) "
208 "= %s_%s;\n", funcbase, m->id, m->id,
210 out_printf(out, "#define %s(args...) "
211 "%s_%s(##args)\n", m->id, funcbase, m->id);
217 make_method_nongnu_aliases(Class *c)
221 for(li=c->nodes;li;li=g_list_next(li)) {
222 Node *node = li->data;
223 if(node->type == METHOD_NODE) {
224 Method *m = (Method *)node;
226 if(m->method == INIT_METHOD ||
227 m->method == CLASS_INIT_METHOD ||
228 m->method == OVERRIDE_METHOD)
231 /* in C++ mode don't alias new */
232 if(for_cpp && strcmp(m->id,"new")==0)
235 print_method(out,"static ","(* ",") ","",m,TRUE);
236 out_printf(out," = %s_%s;\n",funcbase,m->id);
244 add_bad_hack_to_avoid_unused_warnings(Class *c)
248 /* if we haven't had any methods, just return */
253 out_printf(out,"\n\n#ifndef __GNUC__\n");
255 "/*REALLY BAD HACK\n"
256 " This is to avoid unused warnings if you don't call\n"
257 " some method. I need to find a better way to do\n"
258 " this, not needed in GCC since we use some gcc\n"
259 " extentions to make saner, faster code */\n"
261 "___%s_really_bad_hack_to_avoid_warnings(void)\n"
263 for(li=c->nodes;li;li=g_list_next(li)) {
264 Node *node = li->data;
265 if(node->type == METHOD_NODE) {
266 Method *m = (Method *)node;
268 if(m->method == INIT_METHOD ||
269 m->method == CLASS_INIT_METHOD ||
270 m->method == OVERRIDE_METHOD)
273 /* in C++ mode we don't alias new */
274 if(for_cpp && strcmp(m->id,"new")==0)
277 out_printf(out,"\t((void (*)(void))%s)();\n",m->id);
280 out_printf(out, "\t___%s_really_bad_hack_to_avoid_warnings();\n",
283 out_printf(out,"}\n#endif /* __GNUC__ */\n\n");
285 out_printf(out,"}\n\n");
289 put_variable(Variable *v, FILE *fp)
292 print_type(fp,v->vtype,FALSE);
293 out_printf(fp,"%s%s;",v->id,
295 v->vtype->postfix:"");
296 if(v->scope == PROTECTED_SCOPE)
297 out_printf(fp," /* protected */");
302 put_vs_method(Method *m)
304 if(m->method != SIGNAL_LAST_METHOD &&
305 m->method != SIGNAL_FIRST_METHOD &&
306 m->method != VIRTUAL_METHOD)
309 print_method(outh,"\t","(* ",") ",";\n",m,TRUE);
313 put_pub_method(Method *m)
315 if(m->scope != PUBLIC_SCOPE)
318 print_method(outh,"","\t","\t",";\n",m,FALSE);
322 put_prot_method(Method *m)
324 if(m->scope != PROTECTED_SCOPE)
328 print_method(outph,"","\t","\t",";\n",m,FALSE);
330 print_method(out,"","\t","\t",";\n",m,FALSE);
334 put_priv_method_prot(Method *m)
336 if(m->method == SIGNAL_LAST_METHOD ||
337 m->method == SIGNAL_FIRST_METHOD ||
338 m->method == VIRTUAL_METHOD) {
340 print_method(out,"static ","___real_"," ",";\n",m,FALSE);
343 if(m->scope == PRIVATE_SCOPE ||
344 m->method == INIT_METHOD ||
345 m->method == CLASS_INIT_METHOD ||
346 (m->method == OVERRIDE_METHOD &&
348 print_method(out,"static ",""," ",
349 no_gnu?";\n":" ___NO_UNUSED_WARNING;\n"
354 make_func_arg(char *typename, int is_class, char *name)
361 tn = g_strconcat(typename,":Class",NULL);
363 tn = g_strdup(typename);
365 type = new_type(1,tn,NULL);
366 node = new_funcarg((Type *)type,name,NULL);
367 return g_list_prepend(NULL, node);
371 make_inits(Class *cl)
373 int got_class_init = FALSE;
374 int got_init = FALSE;
377 for(li=cl->nodes;li;li=g_list_next(li)) {
379 if(n->type == METHOD_NODE) {
380 Method *m = (Method *)n;
381 if(m->method == INIT_METHOD) {
383 print_error(FALSE,"init defined more then once",m->line_no);
385 } else if(m->method == CLASS_INIT_METHOD) {
387 print_error(FALSE,"class_init defined more then once",m->line_no);
388 got_class_init = TRUE;
392 if(!got_class_init) {
393 node = new_method(NO_SCOPE, CLASS_INIT_METHOD,
394 (Type *)new_type(0,g_strdup("void"),NULL),
395 NULL,NULL,g_strdup("class_init"),
396 make_func_arg(cl->otype,TRUE,g_strdup("c")),
397 NULL, NULL,0,0,FALSE);
398 cl->nodes = g_list_prepend(cl->nodes,node);
401 node = new_method(NO_SCOPE, INIT_METHOD,
402 (Type *)new_type(0,g_strdup("void"),NULL),
403 NULL,NULL,g_strdup("init"),
404 make_func_arg(cl->otype,FALSE,g_strdup("o")),
405 NULL, NULL,0,0,FALSE);
406 cl->nodes = g_list_prepend(cl->nodes,node);
411 make_finalize(Class *cl)
413 int got_finalize = FALSE;
416 for(li=cl->nodes;li;li=g_list_next(li)) {
418 if(n->type == METHOD_NODE) {
419 Method *m = (Method *)n;
420 if(m->method == OVERRIDE_METHOD &&
421 strcmp(m->id,"finalize")==0) {
422 if(strcmp(m->otype,"Gtk:Object")==0) {
426 print_error(FALSE,"finalize method override "
427 "of class other then Gtk:Object",
435 node = new_method(NO_SCOPE, OVERRIDE_METHOD,
436 (Type *)new_type(0,g_strdup("void"),NULL),
437 g_strdup("Gtk:Object"),
438 NULL,g_strdup("finalize"),
439 make_func_arg("Gtk:Object",FALSE,g_strdup("o")),
441 g_strdup("PARENT_HANDLER (o);\n"),
443 cl->nodes = g_list_append(cl->nodes,node);
449 /* hash of method -> name of signal prototype */
450 static GHashTable *marsh = NULL;
452 /* list of methods with different signal prototypes,
453 we check this list if we can use a signal prototype of a
454 previous signal method, there are only uniques here */
455 static GList *eq_signal_methods = NULL;
457 /* compare a list of strings */
459 is_list_equal(GList *a, GList *b)
461 for(;a && b; a=a->next, b=b->next) {
462 if(strcmp(a->data,b->data)!=0) {
466 /* the the lists were different length */
473 find_same_type_signal(Method *m)
476 for(li=eq_signal_methods;li;li=li->next) {
477 Method *mm = li->data;
478 if(is_list_equal(mm->gtktypes,m->gtktypes))
485 print_signal_marsal_args(Method *m)
487 if(strcmp(m->gtktypes->next->data,"NONE")!=0) {
490 for(i=0,li=m->gtktypes->next;li;
491 i++,li=g_list_next(li)) {
493 out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
496 out_printf(out, ",\n\t\t(%s)"
497 "GTK_VALUE_%s(args[%d])",
498 get_cast(li->data,FALSE),
503 out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
508 add_signal_prots(Method *m)
515 if(m->method != SIGNAL_LAST_METHOD &&
516 m->method != SIGNAL_FIRST_METHOD)
520 marsh = g_hash_table_new(NULL,NULL);
522 if(strcmp(m->gtktypes->data,"NONE")==0 &&
523 strcmp(m->gtktypes->next->data,"NONE")==0)
526 /* if we already did a signal prototype just use that */
527 mm = find_same_type_signal(m);
529 s = g_hash_table_lookup(marsh,mm);
530 g_hash_table_insert(marsh,m,s);
534 s = g_strdup_printf("Sig%d",sig++);
536 g_hash_table_insert(marsh,m,s);
537 eq_signal_methods = g_list_prepend(eq_signal_methods,m);
539 /* we know that we'll know all the gtktypes (so get_cast can't fail) */
540 out_printf(out,"\ntypedef %s (*___%s) (%s *, ",
541 get_cast(m->gtktypes->data,FALSE),s, typebase);
543 for(li=m->gtktypes->next;li;li=g_list_next(li))
544 out_printf(out,"%s, ",get_cast(li->data,FALSE));
545 out_printf(out,"gpointer);\n");
547 out_printf(out,"\nstatic void\n"
548 "___marshal_%s (GtkObject * object,\n"
549 "\tGtkSignalFunc func,\n"
550 "\tgpointer func_data,\n"
554 if(strcmp(m->gtktypes->data,"NONE")==0) {
555 out_printf(out, "\t___%s rfunc;\n\n"
556 "\trfunc = (___%s)func;\n\n"
557 "\t(*rfunc)((%s *)object",s,s,typebase);
559 out_printf(out, "\t___%s rfunc;\n\t",s);
560 print_type(out,m->mtype,TRUE);
561 out_printf(out, " *retval;\n\n"
562 "\trfunc = (___%s)func;\n\n"
563 "\tretval = GTK_RETLOC_%s(args[%d]);\n\n"
564 "\t*retval = (*rfunc)((%s *)object",
565 s,(char *)m->gtktypes->data,
566 g_list_length(m->gtktypes)-1,typebase);
568 print_signal_marsal_args(m);
576 out_printf(out,"\n");
578 out_printf(out,"enum {\n");
579 for(li=c->nodes;li;li=g_list_next(li)) {
581 if(n->type == METHOD_NODE) {
582 Method *m = (Method *)n;
583 if(m->method == SIGNAL_LAST_METHOD ||
584 m->method == SIGNAL_FIRST_METHOD) {
585 char *s = g_strdup(m->id);
587 out_printf(out,"\t%s_SIGNAL,\n",s);
592 out_printf(out,"\tLAST_SIGNAL\n};\n\n");
595 out_printf(out,"enum {\n\tARG_0,\n");
596 for(li=c->nodes;li;li=g_list_next(li)) {
598 if(n->type == ARGUMENT_NODE) {
599 Argument *a = (Argument *)n;
600 char *s = g_strdup(a->name);
602 out_printf(out,"\tARG_%s,\n",s);
606 out_printf(out, "};\n\n");
611 "static guint object_signals[LAST_SIGNAL] = {0};\n\n");
613 out_printf(out, "static %sClass *parent_class = NULL;\n\n",ptypebase);
619 out_printf(out, "guint\n"
620 "%s_get_type (void)\n"
622 "\tstatic guint type = 0;\n\n"
624 "\t\tstatic const GtkTypeInfo info = {\n"
626 "\t\t\tsizeof (%s),\n"
627 "\t\t\tsizeof (%sClass),\n"
628 "\t\t\t(GtkClassInitFunc) %s_class_init,\n"
629 "\t\t\t(GtkObjectInitFunc) %s_init,\n"
630 "\t\t\t/* reserved_1 */ NULL,\n"
631 "\t\t\t/* reserved_2 */ NULL,\n"
632 "\t\t\t(GtkClassInitFunc) NULL,\n"
634 "\t\ttype = gtk_type_unique (%s_get_type(), &info);\n"
638 funcbase,typebase,typebase,typebase,
639 funcbase,funcbase,pfuncbase);
643 add_overrides(Class *c, char *oname, gboolean did_gtk_obj)
649 done = g_hash_table_new(g_str_hash,g_str_equal);
651 s = g_strdup("GtkObject"); /* This was already done */
652 g_hash_table_insert(done,s,s);
654 for(li=c->nodes;li;li=g_list_next(li)) {
657 Method *m = (Method *)n;
658 if(n->type != METHOD_NODE ||
659 m->method != OVERRIDE_METHOD)
662 s = remove_sep(m->otype);
664 if(g_hash_table_lookup(done,s)) {
668 g_hash_table_insert(done,s,s);
670 f = replace_sep(m->otype,'_');
673 out_printf(out,"\t%sClass *%s_class = (%sClass *)%s;\n",
678 g_hash_table_foreach(done,(GHFunc)g_free,NULL);
679 g_hash_table_destroy(done);
683 add_signals(Class *c)
687 out_printf(out,"\n");
688 for(li=c->nodes;li;li=g_list_next(li)) {
694 Method *m = (Method *)n;
695 if(n->type != METHOD_NODE ||
696 (m->method != SIGNAL_FIRST_METHOD &&
697 m->method != SIGNAL_LAST_METHOD))
701 if(m->method == SIGNAL_FIRST_METHOD)
706 if(g_hash_table_lookup(marsh,m))
707 mar = g_strconcat("___marshal_",
708 (char *)g_hash_table_lookup(marsh,m),
711 mar = g_strdup("gtk_signal_default_marshaller");
713 is_none = (strcmp(m->gtktypes->next->data,"NONE")==0);
715 sig = g_strdup(m->id);
717 out_printf(out,"\tobject_signals[%s_SIGNAL] =\n"
718 "\t\tgtk_signal_new (\"%s\",\n"
719 "\t\t\tGTK_RUN_%s,\n"
720 "\t\t\tgtk_object_class->type,\n"
721 "\t\t\tGTK_SIGNAL_OFFSET (%sClass, %s),\n"
723 "\t\t\tGTK_TYPE_%s, %d",
726 typebase,m->id,mar,(char *)m->gtktypes->data,
727 is_none?0:g_list_length(m->gtktypes->next));
733 for(l=m->gtktypes->next;l;l=g_list_next(l))
734 out_printf(out,",\n\t\t\tGTK_TYPE_%s",
738 out_printf(out,");\n");
740 out_printf(out,"\tgtk_object_class_add_signals (gtk_object_class,\n"
741 "\t\tobject_signals, LAST_SIGNAL);\n\n");
745 set_def_handlers(Class *c, char *oname)
749 out_printf(out,"\n");
750 for(li=c->nodes;li;li=g_list_next(li)) {
752 Method *m = (Method *)n;
753 if(n->type != METHOD_NODE ||
754 (m->method != SIGNAL_FIRST_METHOD &&
755 m->method != SIGNAL_LAST_METHOD &&
756 m->method != VIRTUAL_METHOD &&
757 m->method != OVERRIDE_METHOD))
761 if(m->method == OVERRIDE_METHOD) {
763 s = replace_sep(m->otype,'_');
766 out_printf(out,"\t%s_class->%s = %s_%s;\n",
767 s,m->id,funcbase,m->id);
769 out_printf(out,"\t%s_class->%s = NULL;\n",
773 out_printf(out,"\t%s->%s = ___real_%s_%s;\n",
774 oname,m->id,funcbase,m->id);
776 out_printf(out,"\t%s->%s = NULL;\n",
783 make_arguments(Class *c)
794 out_printf(out,"\n");
795 for(li=c->nodes;li;li=g_list_next(li)) {
801 if(n->type != ARGUMENT_NODE)
807 flags = g_string_new("GTK_ARG_READWRITE");
809 flags = g_string_new("GTK_ARG_READABLE");
811 flags = g_string_new("GTK_ARG_WRITABLE");
813 for(l=a->flags;l;l=g_list_next(l)) {
814 char *flag = l->data;
816 if(strcmp(flag,"READWRITE")==0 ||
817 strcmp(flag,"READABLE")==0 ||
818 strcmp(flag,"WRITABLE")==0) {
819 print_error(TRUE,"READWRITE, READABLE and "
820 "WRITABLE argument flags are "
821 "set automatically",a->line_no);
824 for(i=0;argflags[i];i++) {
825 if(strcmp(argflags[i],flag)==0)
828 /* if we haven't found it in our list */
831 s = g_strdup_printf("Unknown flag '%s' used, "
832 "perhaps it was misspelled",
834 print_error(TRUE,s,a->line_no);
837 g_string_sprintfa(flags, " | GTK_ARG_%s",flag);
840 s = g_strdup(a->name);
842 out_printf(out,"\tgtk_object_add_arg_type(\"%s::%s\",\n"
846 typebase,a->name,a->gtktype,flags->str,s);
848 g_string_free(flags,TRUE);
852 "\n\tgtk_object_class->set_arg = ___object_set_arg;\n"
853 "\tgtk_object_class->get_arg = ___object_get_arg;\n");
860 for(li=c->nodes;li;li=g_list_next(li)) {
863 if(n->type != METHOD_NODE)
866 if(m->method == INIT_METHOD) {
868 out_addline_infile(out,m->line_no);
869 print_method(out,"static ","\n"," ","\n",m,FALSE);
871 out_addline_outfile(out);
872 out_printf(out,"{\n");
874 out_printf(out,"\t%s->_priv = "
875 "g_new0 (%sPrivate,1);\n",
876 ((FuncArg *)m->args->data)->name,
879 } else if(m->method == CLASS_INIT_METHOD) {
881 out_addline_infile(out,m->line_no);
882 print_method(out,"static ","\n"," ","\n",m,FALSE);
884 out_addline_outfile(out);
885 out_printf(out,"{\n");
890 "gtk_object_class = "
891 "(GtkObjectClass*) %s;\n",
892 ((FuncArg *)m->args->data)->name);
896 ((FuncArg *)m->args->data)->name,
897 (signals>0 || arguments>0));
899 out_printf(out,"\n\tparent_class = ");
901 out_printf(out,"(%sClass *)",ptypebase);
902 out_printf(out,"gtk_type_class (%s_get_type ());\n",
908 set_def_handlers(c, ((FuncArg *)m->args->data)->name);
917 out_printf(out," {\n");
918 out_addline_infile(out,m->ccode_line);
919 out_printf(out,"%s\n",m->cbuf);
920 out_addline_outfile(out);
921 out_printf(out," }\n");
923 out_printf(out,"return;\n");
925 out_printf(out,"}\n");
930 add_getset_arg(Class *c, int is_set)
933 out_printf(out,"\nstatic void\n"
934 "___object_%s_arg (GtkObject *object,\n"
939 "\tself = %s (object);\n\n"
940 "\tswitch (arg_id) {\n",
941 is_set?"set":"get",typebase,macrobase);
943 for(li=c->nodes;li;li=g_list_next(li)) {
949 if(n->type != ARGUMENT_NODE)
954 line_no = a->set_line;
957 line_no = a->get_line;
961 s = g_strdup(a->name);
963 out_printf(out,"\tcase ARG_%s:\n"
964 "#define ARG (GTK_VALUE_%s(*arg))\n"
968 out_addline_infile(out,line_no);
969 out_printf(out,"%s\n",cbuf);
970 out_addline_outfile(out);
971 out_printf(out,"\t\t}\n\t\tbreak;\n"
974 out_printf(out,"\tdefault:\n\t\tbreak;\n\t}\n}\n");
978 print_checks(Method *m, FuncArg *fa)
982 gboolean checked_null = FALSE;
983 is_void = (strcmp(m->mtype->name,"void")==0 &&
984 m->mtype->stars == 0);
986 for(li=fa->checks;li;li=g_list_next(li)) {
987 Check *ch = li->data;
989 /* point to the method prot in .gob for failed checks */
991 out_addline_infile(out,m->line_no);
993 out_printf(out,"\tg_return_if_fail (");
995 out_printf(out,"\tg_return_val_if_fail (");
998 out_printf(out,"%s != NULL",fa->name);
1002 s = make_pre_macro(fa->atype->name,"IS");
1004 out_printf(out,"%s (%s)",s,fa->name);
1006 /* if not check null, null may be valid */
1007 out_printf(out,"!(%s) || %s (%s)",fa->name,s,
1012 out_printf(out,"%s < %s",fa->name,ch->number);
1015 out_printf(out,"%s > %s",fa->name,ch->number);
1018 out_printf(out,"%s <= %s",fa->name,ch->number);
1021 out_printf(out,"%s >= %s",fa->name,ch->number);
1024 out_printf(out,"%s == %s",fa->name,ch->number);
1027 out_printf(out,"%s != %s",fa->name,ch->number);
1031 out_printf(out,");\n");
1033 out_printf(out,", (");
1034 print_type(out,m->mtype,TRUE);
1035 out_printf(out,")%s);\n",
1036 m->onerror?m->onerror:"0");
1042 print_preconditions(Method *m)
1046 for(li=m->args;li;li=g_list_next(li)) {
1047 FuncArg *fa = li->data;
1052 out_addline_outfile(out);
1055 /* put in code if it's needed */
1057 put_in_gen_code(Method *m)
1059 /* now we only have the freeing of the private structure */
1061 m->method == OVERRIDE_METHOD &&
1062 strcmp(m->id,"finalize")==0) {
1063 out_printf(out,"\tg_free (%s (%s)->_priv);\n"
1064 "\t%s (%s)->_priv = NULL;\n",
1066 ((FuncArg *)m->args->data)->name,
1068 ((FuncArg *)m->args->data)->name);
1073 print_method_body(Method *m, int pre)
1075 out_printf(out,"{\n");
1077 print_preconditions(m);
1081 /* Note: the trailing }'s are on one line, this is so
1082 that we get the no return warning correctly and point to
1083 the correct line in the .gob file, yes this is slightly
1084 ugly in the .c file, but that is not supposed to be
1085 human readable anyway. */
1087 out_printf(out,"{\n");
1089 out_addline_infile(out,m->ccode_line);
1090 out_printf(out,"\t%s}",m->cbuf);
1093 out_printf(out,"}\n");
1096 out_addline_outfile(out);
1100 put_signal_args(Method *m)
1104 for(ali = m->gtktypes->next,li=m->args->next;
1106 li=li->next, ali=ali->next) {
1107 FuncArg *fa = li->data;
1108 const char *cast = get_cast(ali->data,FALSE);
1109 /* we should have already proved before that
1110 the we know all the types */
1113 out_printf(out,",\n\t\t(%s)%s",cast,
1119 get_arg_names_for_macro(Method *m)
1123 GString *gs = g_string_new("");
1125 for(li=m->args;li;li=g_list_next(li)) {
1126 FuncArg *arg = li->data;
1127 g_string_sprintfa(gs, "%s___%s", p, arg->name);
1131 g_string_free(gs,FALSE);
1136 put_method(Method *m)
1140 is_void = (strcmp(m->mtype->name,"void")==0 &&
1141 m->mtype->stars == 0);
1142 out_printf(out,"\n");
1144 case REGULAR_METHOD:
1146 out_addline_infile(out,m->line_no);
1147 if(m->scope == PRIVATE_SCOPE)
1148 print_method(out,"static ","\n"," ","\n",m,FALSE);
1149 else /* PUBLIC, PROTECTED */
1150 print_method(out,"","\n"," ","\n",m,FALSE);
1151 print_method_body(m,TRUE);
1153 case SIGNAL_FIRST_METHOD:
1154 case SIGNAL_LAST_METHOD:
1156 out_addline_infile(out,m->line_no);
1157 if(m->scope == PRIVATE_SCOPE)
1158 print_method(out,"static ","\n"," ","\n",m,FALSE);
1160 print_method(out,"","\n"," ","\n",m,FALSE);
1161 out_addline_outfile(out);
1162 out_printf(out,"{\n");
1163 s = g_strdup(m->id);
1165 if(strcmp(m->mtype->name,"void")==0 &&
1166 m->mtype->stars==0) {
1167 print_preconditions(m);
1168 if(((FuncArg *)m->args->data)->name)
1169 out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1170 "\t\tobject_signals[%s_SIGNAL]",
1171 ((FuncArg *)m->args->data)->name,s);
1173 out_printf(out,");\n}\n");
1175 out_printf(out,"\t");
1176 print_type(out,m->mtype,TRUE);
1177 out_printf(out,"return_val;\n");
1178 print_preconditions(m);
1179 out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1180 "\t\tobject_signals[%s_SIGNAL]",
1181 ((FuncArg *)m->args->data)->name,s);
1183 out_printf(out,",\n\t\t&return_val);\n"
1184 "\treturn return_val;\n}\n");
1190 out_addline_infile(out,m->line_no);
1191 print_method(out,"static ","\n___real_"," ","\n",m,FALSE);
1192 print_method_body(m,FALSE);
1194 case VIRTUAL_METHOD:
1196 out_addline_infile(out,m->line_no);
1197 if(m->scope==PRIVATE_SCOPE)
1198 print_method(out,"static ","\n"," ","\n",m,FALSE);
1200 print_method(out,"","\n"," ","\n",m,FALSE);
1201 out_addline_outfile(out);
1202 out_printf(out,"{\n"
1203 "\t%sClass *klass;\n",typebase);
1204 print_preconditions(m);
1205 out_printf(out,"\tklass = %s_CLASS(GTK_OBJECT(%s)->klass);\n\n"
1206 "\tif(klass->%s)\n",
1207 macrobase, ((FuncArg *)m->args->data)->name, m->id);
1208 if(strcmp(m->mtype->name,"void")==0 &&
1209 m->mtype->stars==0) {
1211 out_printf(out,"\t\t(*klass->%s)(%s",m->id,
1212 ((FuncArg *)m->args->data)->name);
1213 for(li=m->args->next;li;li=g_list_next(li)) {
1214 FuncArg *fa = li->data;
1215 out_printf(out,",%s",fa->name);
1217 out_printf(out,");\n}\n");
1220 out_printf(out,"\t\treturn (*klass->%s)(%s",m->id,
1221 ((FuncArg *)m->args->data)->name);
1222 for(li=m->args->next;li;li=g_list_next(li)) {
1223 FuncArg *fa = li->data;
1224 out_printf(out,",%s",fa->name);
1226 out_printf(out,");\n"
1229 print_type(out,m->mtype,TRUE);
1230 out_printf(out,")(%s);\n}\n",
1231 m->onerror?m->onerror:"0");
1237 out_addline_infile(out,m->line_no);
1238 print_method(out,"static ","\n___real_"," ","\n",m,FALSE);
1239 print_method_body(m,FALSE);
1241 case OVERRIDE_METHOD:
1245 out_addline_infile(out,m->line_no);
1246 print_method(out,"static ","\n"," ","\n",m,FALSE);
1247 s = replace_sep(m->otype,'_');
1249 args = get_arg_names_for_macro(m);
1251 out_printf(out,"#define PARENT_HANDLER(%s) \\\n"
1252 "\t{ if(%s_CLASS(parent_class)->%s) \\\n"
1253 "\t\t(* %s_CLASS(parent_class)->%s)(%s); }\n",
1254 args,s,m->id,s,m->id,args);
1256 out_printf(out,"#define PARENT_HANDLER(%s) \\\n"
1257 "\t((%s_CLASS(parent_class)->%s)? \\\n"
1258 "\t\t(* %s_CLASS(parent_class)->%s)(%s): \\\n"
1260 args,s,m->id,s,m->id,args);
1261 out_printf(out,"(");
1262 print_type(out,m->mtype,TRUE);
1263 out_printf(out,")%s))\n",
1264 m->onerror?m->onerror:"0");
1268 print_method_body(m,TRUE);
1269 out_printf(out,"#undef PARENT_HANDLER\n");
1279 char *outfile,*outfileh,*outfileph;
1282 outfile = g_strconcat(filebase,".c",NULL);
1284 outfile = g_strconcat(filebase,".cc",NULL);
1285 if(no_touch_headers)
1286 outfileh = g_strconcat("#gob#",filebase,".h#gob#",NULL);
1288 outfileh = g_strconcat(filebase,".h",NULL);
1290 if((privates>0 || protecteds>0 || always_private_header) &&
1292 outfileph = g_strconcat(filebase,"-private.h",NULL);
1297 out = fopen(outfile,"w");
1299 g_error("Cannot open outfile: %s",outfile);
1301 outh = fopen(outfileh,"w");
1303 g_error("Cannot open outfile: %s",outfileh);
1306 outph = fopen(outfileph,"w");
1308 g_error("Cannot open outfile: %s",outfileh);
1314 put_argument_nongnu_wrappers(Class *c)
1321 for(li=c->nodes;li;li=g_list_next(li)) {
1323 Argument *a = (Argument *)n;
1326 if(n->type != ARGUMENT_NODE)
1328 s = g_strdup(a->name);
1331 cast = get_type(a->atype,TRUE);
1333 cast = g_strdup(get_cast(a->gtktype,TRUE));
1337 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1338 "\"%s\",(%s)(arg)\n",
1339 macrobase, s, a->name, cast);
1341 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1342 "\"%s\",(%s*)(arg)\n",
1343 macrobase, s, a->name, cast);
1346 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1348 macrobase, s, a->name);
1350 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1352 macrobase, s, a->name);
1360 put_argument_gnu_wrappers(Class *c)
1367 for(li=c->nodes;li;li=g_list_next(li)) {
1369 Argument *a = (Argument *)n;
1372 if(n->type != ARGUMENT_NODE)
1374 s = g_strdup(a->name);
1377 cast = get_type(a->atype,TRUE);
1379 cast = g_strdup(get_cast(a->gtktype,TRUE));
1382 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1383 "\"%s\",({%sz = (arg); z;})\n",
1384 macrobase, s, a->name, cast);
1386 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1387 "\"%s\",({%s*z = (arg); z;})\n",
1388 macrobase, s, a->name, cast);
1391 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1393 macrobase, s, a->name);
1395 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1397 macrobase, s, a->name);
1405 print_ccode_block(CCode *cc)
1408 switch(cc->cctype) {
1410 /* HT code is printed exactly like normal header
1411 code but is printed before */
1414 out_printf(fp,"\n");
1419 out_printf(fp,"\n");
1420 out_addline_infile(fp,cc->line_no);
1427 out_printf(fp,"\n");
1428 out_addline_infile(fp,cc->line_no);
1431 out_printf(fp,"%s\n",cc->cbuf);
1432 if(cc->cctype == C_CCODE ||
1433 cc->cctype == PH_CCODE)
1434 out_addline_outfile(fp);
1438 print_class_block(Class *c)
1443 out_printf(out,"/* utility types we may need */\n");
1444 out_printf(out,"typedef struct { "
1445 "gpointer a; gpointer b; "
1446 "} ___twopointertype;\n");
1447 out_printf(out,"typedef struct { "
1448 "gpointer a; gpointer b; "
1450 "} ___threepointertype;\n");
1452 out_printf(outh,"\n#define %s\t"
1453 "(%s_get_type())\n",
1454 macrotype,funcbase);
1455 out_printf(outh,"#define %s(obj)\t"
1456 "GTK_CHECK_CAST((obj),%s_get_type(),%s)\n",
1457 macrobase,funcbase,typebase);
1458 out_printf(outh,"#define %s_CLASS(klass)\t"
1459 "GTK_CHECK_CLASS_CAST((klass),%s_get_type(),%sClass)\n",
1460 macrobase,funcbase,typebase);
1461 out_printf(outh,"#define %s(obj)\t"
1462 "GTK_CHECK_TYPE((obj), %s_get_type ())\n\n",
1465 /* argument wrapping macros */
1466 if(arguments>0 && !no_gnu) {
1467 out_printf(outh,"\n#ifdef __GNUC__\n");
1468 put_argument_gnu_wrappers(c);
1469 out_printf(outh,"#else /* __GNUC__ */\n");
1470 put_argument_nongnu_wrappers(c);
1471 out_printf(outh,"#endif /* __GNUC__ */\n\n");
1472 } else if(arguments>0 && no_gnu) {
1473 put_argument_nongnu_wrappers(c);
1477 out_printf(outh,"\ntypedef struct _%sPrivate %sPrivate;\n",typebase,typebase);
1479 s = replace_sep(c->otype,'_');
1481 out_printf(outh,"#ifndef __TYPEDEF_%s__\n"
1482 "#define __TYPEDEF_%s__\n",s,s);
1484 out_printf(outh,"typedef struct _%s %s;\n"
1485 "#endif\n",typebase,typebase);
1486 out_printf(outh,"struct _%s {\n\t%s __parent__;\n",
1487 typebase,ptypebase);
1488 for(l=c->nodes;l;l=g_list_next(l)) {
1490 Variable *v = (Variable *)n;
1491 if(n->type == VARIABLE_NODE &&
1492 v->scope == PUBLIC_SCOPE)
1493 put_variable((Variable *)n,outh);
1495 /* put protecteds always AFTER publics */
1496 for(l=c->nodes;l;l=g_list_next(l)) {
1498 Variable *v = (Variable *)n;
1499 if(n->type == VARIABLE_NODE &&
1500 v->scope == PROTECTED_SCOPE)
1501 put_variable((Variable *)n,outh);
1504 out_printf(outh,"\t%sPrivate *_priv;\n",typebase);
1505 out_printf(outh,"};\n");
1510 /* if we are to stick this into the private
1511 header, if not stick it directly into the
1518 out_printf(outfp,"struct _%sPrivate {\n",
1520 for(l=c->nodes;l;l=l->next) {
1522 Variable *v = (Variable *)n;
1523 if(n->type == VARIABLE_NODE &&
1524 v->scope == PRIVATE_SCOPE) {
1525 out_addline_infile(outfp,v->line_no);
1526 put_variable(v,outfp);
1529 out_addline_outfile(outfp);
1530 out_printf(outfp,"};\n");
1533 out_printf(outh,"\ntypedef struct _%sClass %sClass;\n",
1536 "struct _%sClass {\n\t%sClass __parent__;\n",
1537 typebase,ptypebase);
1538 for(l=c->nodes;l;l=g_list_next(l)) {
1540 if(n->type == METHOD_NODE)
1541 put_vs_method((Method *)n);
1543 out_printf(outh,"};\n\n");
1545 out_printf(outh,"guint\t%s_get_type\t(void);\n",funcbase);
1547 out_printf(out,"/* here are local prototypes */\n");
1549 out_printf(out,"#ifdef __GNUC__\n"
1550 "#define ___NO_UNUSED_WARNING "
1551 "__attribute__ ((__unused__))\n"
1552 "#else /* __GNUC__ */\n"
1553 "#define ___NO_UNUSED_WARNING\n"
1554 "#endif /* __GNUC__ */\n");
1557 out_printf(out,"static void ___object_set_arg "
1558 "(GtkObject *object, GtkArg *arg, "
1560 "static void ___object_get_arg "
1561 "(GtkObject *object, GtkArg *arg, "
1562 "guint arg_id);\n");
1565 for(l=c->nodes;l;l=g_list_next(l)) {
1567 if(n->type == METHOD_NODE) {
1568 put_pub_method((Method *)n);
1569 put_prot_method((Method *)n);
1570 put_priv_method_prot((Method *)n);
1575 for(l=c->nodes;l;l=g_list_next(l)) {
1577 if(n->type == METHOD_NODE)
1578 add_signal_prots((Method *)n);
1583 out_printf(out,"#undef ___NO_UNUSED_WARNING\n");
1590 make_method_nongnu_aliases(c);
1592 out_printf(out,"\n#ifdef __GNUC__\n");
1593 make_method_gnu_aliases(c);
1594 out_printf(out,"#else /* __GNUC__ */\n");
1595 make_method_nongnu_aliases(c);
1596 out_printf(out,"#endif /* __GNUC__ */\n\n");
1599 out_printf(out,"#define GET_NEW (gtk_type_new(%s_get_type()))\n",
1605 add_getset_arg(c, TRUE);
1606 add_getset_arg(c, FALSE);
1609 for(l=c->nodes;l;l=g_list_next(l)) {
1611 if(n->type == METHOD_NODE) {
1612 put_method((Method *)n);
1616 out_printf(out,"#undef GET_NEW\n");
1618 add_bad_hack_to_avoid_unused_warnings(c);
1622 print_version_macros(void)
1624 int major=0,minor=0,pl=0;
1625 sscanf(VERSION,"%d.%d.%d",&major,&minor,&pl);
1627 out_printf(out,"#define GOB_VERSION_MAJOR %d\n", major);
1628 out_printf(out,"#define GOB_VERSION_MINOR %d\n", minor);
1629 out_printf(out,"#define GOB_VERSION_PATCHLEVEL %d\n\n", pl);
1633 print_file_comments(void)
1637 out_printf(outh,"/* Generated by GOB (v%s)"
1638 " (do not edit directly) */\n\n",VERSION);
1640 out_printf(outph,"/* Generated by GOB (v%s)"
1641 " (do not edit directly) */\n\n",VERSION);
1642 out_printf(out,"/* Generated by GOB (v%s) on %s"
1643 " (do not edit directly) */\n\n",VERSION,ctime(&curtime));
1647 print_includes(void)
1649 gboolean found_header;
1652 p = g_strconcat(filebase,".h",NULL);
1653 found_header = TRUE;
1654 if(!g_list_find_custom(include_files,p,(GCompareFunc)strcmp)) {
1655 out_printf(out,"#include \"%s.h\"\n\n",filebase);
1656 found_header = FALSE;
1660 /* if we are creating a private header see if it was included */
1662 p = g_strconcat(filebase,"-private.h",NULL);
1663 if(!g_list_find_custom(include_files,p,(GCompareFunc)strcmp)) {
1664 out_printf(out,"#include \"%s-private.h\"\n\n",
1668 "Implicit private header include "
1670 "\tsource file, while public "
1671 "header is at a custom location, "
1673 "\texplicitly include "
1674 "the private header below the "
1682 print_header_prefixes(void)
1686 p = replace_sep(((Class *)class)->otype,'_');
1688 out_printf(outh,"#ifndef __%s_H__\n#define __%s_H__\n\n",p,p);
1690 out_printf(outph,"#ifndef __%s_PRIVATE_H__\n"
1691 "#define __%s_PRIVATE_H__\n\n"
1692 "#include \"%s.h\"\n\n",p,p,filebase);
1696 out_printf(outh,"#ifdef __cplusplus\n"
1698 "#endif /* __cplusplus */\n\n");
1700 out_printf(outph,"#ifdef __cplusplus\n"
1702 "#endif /* __cplusplus */\n\n");
1707 print_header_postfixes(void)
1710 out_printf(outh,"\n#ifdef __cplusplus\n"
1712 "#endif /* __cplusplus */\n");
1713 out_printf(outh,"\n#endif");
1716 out_printf(outph,"\n#ifdef __cplusplus\n"
1718 "#endif /* __cplusplus */\n");
1719 out_printf(outph,"\n#endif");
1724 print_header_top(void)
1728 /* mandatory include */
1729 out_printf(outh,"#include <gtk/gtk.h>\n\n");
1731 /* print the HT_CCODE blocks */
1732 for(li=nodes;li;li=g_list_next(li)) {
1733 Node *node = li->data;
1734 if(node->type == CCODE_NODE) {
1735 CCode *cc = (CCode *)node;
1736 if(cc->cctype==HT_CCODE)
1737 print_ccode_block((CCode *)node);
1743 generate_outfiles(void)
1747 print_file_comments();
1751 print_header_prefixes();
1753 print_version_macros();
1757 for(li=nodes;li;li=g_list_next(li)) {
1758 Node *node = li->data;
1759 if(node->type == CCODE_NODE) {
1760 CCode *cc = (CCode *)node;
1761 if(cc->cctype!=HT_CCODE)
1762 print_ccode_block((CCode *)node);
1763 } else if(node->type == CLASS_NODE) {
1764 print_class_block((Class *)node);
1766 g_assert_not_reached();
1769 print_header_postfixes();
1775 fprintf(stderr,"Gob version %s\n\n",VERSION);
1776 fprintf(stderr,"Options:\n"
1777 "\t--help,-h,-? Display this help\n"
1778 "\t--version Display version\n"
1779 "\t--exit-on-warn,-w Exit with an error on warnings\n"
1780 "\t--no-exit-on-warn Don't exit on warnings [default]\n"
1781 "\t--for-cpp Create C++ files\n"
1782 "\t--no-extern-c Never print extern \"C\" into the "
1784 "\t--no-gnu Never use GNU extentions\n"
1785 "\t--no-touch-headers Don't touch headers unless they "
1787 "\t--always-private-header Always create a private header "
1789 "\t even if it would be empty\n"
1790 "\t--no-private-header Don't create a private header, "
1792 "\t structure and protected "
1793 "prototypes inside c file\n");
1797 parse_options(int argc, char *argv[])
1800 int got_file = FALSE;
1801 int no_opts = FALSE;
1805 for(i=1;i<argc;i++) {
1806 if(no_opts || argv[i][0]!='-') {
1809 fprintf(stderr,"Specify only one file!\n");
1815 } else if(strcmp(argv[i],"--help")==0) {
1818 } else if(strcmp(argv[i],"--version")==0) {
1819 fprintf(stderr,"Gob version %s\n",VERSION);
1821 } else if(strcmp(argv[i],"--exit-on-warn")==0) {
1822 exit_on_warn = TRUE;
1823 } else if(strcmp(argv[i],"--no-exit-on-warn")==0) {
1824 exit_on_warn = FALSE;
1825 } else if(strcmp(argv[i],"--for-cpp")==0) {
1827 } else if(strcmp(argv[i],"--no-touch-headers")==0) {
1828 no_touch_headers = TRUE;
1829 } else if(strcmp(argv[i],"--always-private-header")==0) {
1830 no_private_header = FALSE;
1831 always_private_header = TRUE;
1832 } else if(strcmp(argv[i],"--no-private-header")==0) {
1833 always_private_header = FALSE;
1834 no_private_header = TRUE;
1835 } else if(strcmp(argv[i],"--no-gnu")==0) {
1837 } else if(strcmp(argv[i],"--no-extern-c")==0) {
1839 } else if(strcmp(argv[i],"--")==0) {
1840 /*further arguments are files*/
1842 } else if(strncmp(argv[i],"--",2)==0) {
1843 /*unknown long option*/
1844 fprintf(stderr,"Unknown option '%s'!\n",argv[i]);
1848 /*by now we know we have a string starting with
1849 - which is a short option string*/
1850 char *p = argv[i]+1;
1851 for(p=argv[i]+1;*p;p++) {
1862 "Unknown option '%c'!\n",*p);
1871 /* this is a somewhat ugly hack, but it appears to work */
1873 compare_and_move_header(void)
1875 char *hfnew = g_strconcat("#gob#",filebase,".h#gob#",NULL);
1876 char *hf = g_strconcat(filebase,".h",NULL);
1878 if(stat(hf,&s)==0) {
1880 s = g_strdup_printf("cmp '%s' '%s' > /dev/null",hf,hfnew);
1882 if(unlink(hfnew)!=0)
1883 print_error(FALSE,"Can't remove new header file",0);
1891 print_error(FALSE,"Can't remove old header file",0);
1893 if(rename(hfnew,hf)!=0)
1894 print_error(FALSE,"Can't rename new header file",0);
1900 main(int argc, char *argv[])
1902 parse_options(argc,argv);
1905 yyin = fopen(filename,"r");
1907 fprintf(stderr,"Error: can't open file '%s'\n",
1916 g_error("Parsing errors, quitting");
1918 print_error(FALSE," no class defined",0);
1921 exit_on_error = FALSE;
1923 signals = count_signals((Class *)class);
1924 arguments = count_arguments((Class *)class);
1925 overrides = count_overrides((Class *)class);
1926 privates = count_privates((Class *)class);
1927 protecteds = count_protecteds((Class *)class);
1930 make_inits((Class *)class);
1932 make_finalize((Class *)class);
1933 check_bad_symbols((Class *)class);
1934 check_duplicate_symbols((Class *)class);
1935 check_duplicate_signals_args((Class *)class);
1936 check_public_new((Class *)class);
1937 check_vararg((Class *)class);
1938 check_firstarg((Class *)class);
1939 check_nonvoidempty((Class *)class);
1940 check_signal_args((Class *)class);
1941 check_argument_types((Class *)class);
1943 exit_on_error = TRUE;
1950 generate_outfiles();
1955 if(no_touch_headers)
1956 compare_and_move_header();