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;
82 print_error(int is_warn, char *error,int line)
92 fprintf(stderr,"%s:%d: %s %s\n",filename,line,w,error);
94 fprintf(stderr,"%s: %s %s\n",filename,w,error);
95 if((!is_warn || exit_on_warn) && exit_on_error)
100 remove_sep(char *base)
103 char *s = g_strdup(base);
104 while((p=strchr(s,':')))
110 replace_sep(char *base, char r)
113 char *s = g_strdup(base);
114 while((p=strchr(s,':')))
124 /*separate the namespace part and then replace rest of
127 separns_replace_sep(char *base, char **ns, char **name, char r)
130 char *s = g_strdup(base);
132 if((p=strchr(s,':')) && p!=s) {
139 while((p=strchr(s,':')))
142 *name = g_strdup(s+1);
148 /* make a macro with some prefix before the name but after
151 make_pre_macro(char *base, char *pre)
156 separns_replace_sep(base,&s1,&s2,'_');
158 s = g_strconcat(s1,"_",pre,"_",s2,NULL);
160 s = g_strconcat(pre,"_",s2,NULL);
173 filebase = replace_sep(((Class *)class)->otype,'-');
176 funcbase = replace_sep(((Class *)class)->otype,'_');
179 pfuncbase = replace_sep(((Class *)class)->ptype,'_');
180 g_strdown(pfuncbase);
182 macrobase = replace_sep(((Class *)class)->otype,'_');
185 macrois = make_pre_macro(((Class *)class)->otype,"IS");
186 macrotype = make_pre_macro(((Class *)class)->otype,"TYPE");
188 typebase = remove_sep(((Class *)class)->otype);
190 ptypebase = remove_sep(((Class *)class)->ptype);
194 get_type(Type *t, gboolean postfix_to_stars)
201 s = remove_sep(t->name);
202 gs = g_string_new(s);
207 if(postfix_to_stars) {
209 /*XXX: this is ugly perhaps we can do this whole postfix thing
210 in a nicer way, we just count the number of '[' s and from
211 that we deduce the number of dimensions, so that we can print
213 for(p=t->postfix; p && *p; p++)
214 if(*p == '[') extra++;
216 g_string_append_c(gs,' ');
218 for(i=0;i<(t->stars+extra);i++)
219 g_string_append_c(gs,'*');
222 g_string_free(gs,FALSE);
227 print_type(FILE *fp, Type *t, gboolean postfix_to_stars)
231 s = get_type(t,postfix_to_stars);
232 out_printf(fp,"%s",s);
238 print_method(FILE *fp, char *typeprefix, char *nameprefix,
239 char *namepostfix,char *postfix, Method *m,
240 gboolean no_funcbase)
244 out_printf(fp,"%s",typeprefix);
245 print_type(fp,m->mtype,TRUE);
247 out_printf(fp,"%s%s%s(",
248 nameprefix,m->id,namepostfix);
250 out_printf(fp,"%s%s_%s%s(",
251 nameprefix,funcbase,m->id,namepostfix);
254 for(li=m->args;li;li=g_list_next(li)) {
255 FuncArg *arg = li->data;
256 print_type(fp,arg->atype,FALSE);
258 out_printf(fp,"%s%s, ",arg->name,
260 arg->atype->postfix:"");
262 out_printf(fp,"%s%s",arg->name,
264 arg->atype->postfix:"");
267 out_printf(fp,", ...");
269 out_printf(fp,"void");
271 out_printf(fp,")%s",postfix);
276 make_method_gnu_aliases(Class *c)
280 for(li=c->nodes;li;li=g_list_next(li)) {
281 Node *node = li->data;
282 if(node->type == METHOD_NODE) {
283 Method *m = (Method *)node;
285 if(m->method == INIT_METHOD ||
286 m->method == CLASS_INIT_METHOD ||
287 m->method == OVERRIDE_METHOD)
290 /* in C++ mode don't alias new */
291 if(for_cpp && strcmp(m->id, "new")==0)
294 out_printf(out, "static const typeof(&%s_%s) %s "
295 "__attribute__ ((__unused__)) "
296 "= %s_%s;\n", funcbase, m->id, m->id,
298 out_printf(out, "#define %s(args...) "
299 "%s_%s(##args)\n", m->id, funcbase, m->id);
305 make_method_nongnu_aliases(Class *c)
309 for(li=c->nodes;li;li=g_list_next(li)) {
310 Node *node = li->data;
311 if(node->type == METHOD_NODE) {
312 Method *m = (Method *)node;
314 if(m->method == INIT_METHOD ||
315 m->method == CLASS_INIT_METHOD ||
316 m->method == OVERRIDE_METHOD)
319 /* in C++ mode don't alias new */
320 if(for_cpp && strcmp(m->id,"new")==0)
323 print_method(out,"static ","(* ",") ","",m,TRUE);
324 out_printf(out," = %s_%s;\n",funcbase,m->id);
332 add_bad_hack_to_avoid_unused_warnings(Class *c)
336 /* if we haven't had any methods, just return */
341 out_printf(out,"\n\n#ifndef __GNUC__\n");
343 "/*REALLY BAD HACK\n"
344 " This is to avoid unused warnings if you don't call\n"
345 " some method. I need to find a better way to do\n"
346 " this, not needed in GCC since we use some gcc\n"
347 " extentions to make saner, faster code */\n"
349 "___%s_really_bad_hack_to_avoid_warnings(void)\n"
351 for(li=c->nodes;li;li=g_list_next(li)) {
352 Node *node = li->data;
353 if(node->type == METHOD_NODE) {
354 Method *m = (Method *)node;
356 if(m->method == INIT_METHOD ||
357 m->method == CLASS_INIT_METHOD ||
358 m->method == OVERRIDE_METHOD)
361 /* in C++ mode we don't alias new */
362 if(for_cpp && strcmp(m->id,"new")==0)
365 out_printf(out,"\t((void (*)(void))%s)();\n",m->id);
368 out_printf(out, "\t___%s_really_bad_hack_to_avoid_warnings();\n",
371 out_printf(out,"}\n#endif /* __GNUC__ */\n\n");
373 out_printf(out,"}\n\n");
377 put_variable(Variable *v, FILE *fp)
380 print_type(fp,v->vtype,FALSE);
381 out_printf(fp,"%s%s;",v->id,
383 v->vtype->postfix:"");
384 if(v->scope == PROTECTED_SCOPE)
385 out_printf(fp," /* protected */");
390 put_vs_method(Method *m)
392 if(m->method != SIGNAL_LAST_METHOD &&
393 m->method != SIGNAL_FIRST_METHOD &&
394 m->method != VIRTUAL_METHOD)
397 print_method(outh,"\t","(* ",") ",";\n",m,TRUE);
401 put_pub_method(Method *m)
403 if(m->scope != PUBLIC_SCOPE)
406 print_method(outh,"","\t","\t",";\n",m,FALSE);
410 put_prot_method(Method *m)
412 if(m->scope != PROTECTED_SCOPE)
416 print_method(outph,"","\t","\t",";\n",m,FALSE);
418 print_method(out,"","\t","\t",";\n",m,FALSE);
422 put_priv_method_prot(Method *m)
424 if(m->method == SIGNAL_LAST_METHOD ||
425 m->method == SIGNAL_FIRST_METHOD ||
426 m->method == VIRTUAL_METHOD) {
428 print_method(out,"static ","_real_"," ",";\n",m,FALSE);
431 if(m->scope == PRIVATE_SCOPE ||
432 m->method == INIT_METHOD ||
433 m->method == CLASS_INIT_METHOD ||
434 (m->method == OVERRIDE_METHOD &&
436 print_method(out,"static ",""," ",
437 no_gnu?";\n":" ___NO_UNUSED_WARNING;\n"
442 make_func_arg(char *typename, int is_class, char *name)
449 tn = g_strconcat(typename,":Class",NULL);
451 tn = g_strdup(typename);
453 type = new_type(1,tn,NULL);
454 node = new_funcarg((Type *)type,name,NULL);
455 return g_list_prepend(NULL, node);
459 make_inits(Class *cl)
461 int got_class_init = FALSE;
462 int got_init = FALSE;
465 for(li=cl->nodes;li;li=g_list_next(li)) {
467 if(n->type == METHOD_NODE) {
468 Method *m = (Method *)n;
469 if(m->method == INIT_METHOD) {
471 print_error(FALSE,"init defined more then once",m->line_no);
473 } else if(m->method == CLASS_INIT_METHOD) {
475 print_error(FALSE,"class_init defined more then once",m->line_no);
476 got_class_init = TRUE;
480 if(!got_class_init) {
481 node = new_method(NO_SCOPE, CLASS_INIT_METHOD,
482 (Type *)new_type(0,g_strdup("void"),NULL),
483 NULL,NULL,g_strdup("class_init"),
484 make_func_arg(cl->otype,TRUE,g_strdup("c")),
485 NULL, NULL,0,0,FALSE);
486 cl->nodes = g_list_prepend(cl->nodes,node);
489 node = new_method(NO_SCOPE, INIT_METHOD,
490 (Type *)new_type(0,g_strdup("void"),NULL),
491 NULL,NULL,g_strdup("init"),
492 make_func_arg(cl->otype,FALSE,g_strdup("o")),
493 NULL, NULL,0,0,FALSE);
494 cl->nodes = g_list_prepend(cl->nodes,node);
499 make_finalize(Class *cl)
501 int got_finalize = FALSE;
504 for(li=cl->nodes;li;li=g_list_next(li)) {
506 if(n->type == METHOD_NODE) {
507 Method *m = (Method *)n;
508 if(m->method == OVERRIDE_METHOD &&
509 strcmp(m->id,"finalize")==0) {
510 if(strcmp(m->otype,"Gtk:Object")==0) {
514 print_error(FALSE,"finalize method override "
515 "of class other then Gtk:Object",
523 node = new_method(NO_SCOPE, OVERRIDE_METHOD,
524 (Type *)new_type(0,g_strdup("void"),NULL),
525 g_strdup("Gtk:Object"),
526 NULL,g_strdup("finalize"),
527 make_func_arg("Gtk:Object",FALSE,g_strdup("o")),
529 g_strdup("PARENT_HANDLER (o);\n"),
531 cl->nodes = g_list_append(cl->nodes,node);
536 /* here we will find out how inconsistent gtk really is :) */
537 /* the commented out types mean that these types don't actually
538 exist. so we "emulate them" with an equivalent */
543 } our_gtk_type_table[] = {
544 { TRUE, "NONE", "void " },
545 { TRUE, "CHAR", "gchar " },
546 { TRUE, "UCHAR", "guchar " },
547 { TRUE, "BOOL", "gboolean " },
548 { TRUE, "INT", "gint " },
549 { TRUE, "UINT", "guint " },
550 { TRUE, "LONG", "glong " },
551 { TRUE, "ULONG", "gulong " },
552 { TRUE, "FLOAT", "gfloat " },
553 { TRUE, "DOUBLE", "gdouble " },
554 { TRUE, "STRING", /*"GtkString"*/"gchar *" },
555 { TRUE, "ENUM", /*"GtkEnum"*/"gint " },
556 { TRUE, "FLAGS", /*"GtkFlags"*/"guint " },
557 { TRUE, "BOXED", /*"GtkBoxed"*/"gpointer " },
558 { TRUE, "POINTER", "gpointer " },
559 { TRUE, "OBJECT", "GtkObject *" },
560 { FALSE, "SIGNAL", /*"GtkSignal"*/"___twopointertype " },
561 { FALSE, "ARGS", /*"GtkArgs"*/"___twopointertype " },
562 { FALSE, "CALLBACK", /*"GtkCallback"*/"___threepointertype " },
563 { FALSE, "C_CALLBACK", /*"GtkCCallback"*/"___twopointertype " },
564 { FALSE, "FOREIGN", /*"GtkForeign"*/"___twopointertype " },
566 { FALSE, NULL, NULL }
570 get_cast(char *type, gboolean simple_only)
573 for(i=0;our_gtk_type_table[i].gtkname;i++) {
574 if(strcmp(our_gtk_type_table[i].gtkname,type)==0) {
576 !our_gtk_type_table[i].simple)
578 return our_gtk_type_table[i].typename;
585 /* hash of method -> name of signal prototype */
586 static GHashTable *marsh = NULL;
588 /* list of methods with different signal prototypes,
589 we check this list if we can use a signal prototype of a
590 previous signal method, there are only uniques here */
591 static GList *eq_signal_methods = NULL;
593 /* compare a list of strings */
595 is_list_equal(GList *a, GList *b)
597 for(;a && b; a=a->next, b=b->next) {
598 if(strcmp(a->data,b->data)!=0) {
602 /* the the lists were different length */
609 find_same_type_signal(Method *m)
612 for(li=eq_signal_methods;li;li=li->next) {
613 Method *mm = li->data;
614 if(is_list_equal(mm->gtktypes,m->gtktypes))
621 print_signal_marsal_args(Method *m)
623 if(strcmp(m->gtktypes->next->data,"NONE")!=0) {
626 for(i=0,li=m->gtktypes->next;li;
627 i++,li=g_list_next(li)) {
629 out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
632 out_printf(out, ",\n\t\t(%s)"
633 "GTK_VALUE_%s(args[%d])",
634 get_cast(li->data,FALSE),
639 out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
644 add_signal_prots(Method *m)
651 if(m->method != SIGNAL_LAST_METHOD &&
652 m->method != SIGNAL_FIRST_METHOD)
656 marsh = g_hash_table_new(NULL,NULL);
658 if(strcmp(m->gtktypes->data,"NONE")==0 &&
659 strcmp(m->gtktypes->next->data,"NONE")==0)
662 /* if we already did a signal prototype just use that */
663 mm = find_same_type_signal(m);
665 s = g_hash_table_lookup(marsh,mm);
666 g_hash_table_insert(marsh,m,s);
670 s = g_strdup_printf("Sig%d",sig++);
672 g_hash_table_insert(marsh,m,s);
673 eq_signal_methods = g_list_prepend(eq_signal_methods,m);
675 /* we know that we'll know all the gtktypes (so get_cast can't fail) */
676 out_printf(out,"\ntypedef %s (*%s) (%s *, ",
677 get_cast(m->gtktypes->data,FALSE),s, typebase);
679 for(li=m->gtktypes->next;li;li=g_list_next(li))
680 out_printf(out,"%s, ",get_cast(li->data,FALSE));
681 out_printf(out,"gpointer);\n");
683 out_printf(out,"\nstatic void\n"
684 "___marshal_%s (GtkObject * object,\n"
685 "\tGtkSignalFunc func,\n"
686 "\tgpointer func_data,\n"
690 if(strcmp(m->gtktypes->data,"NONE")==0) {
691 out_printf(out, "\t%s rfunc;\n\n"
692 "\trfunc = (%s)func;\n\n"
693 "\t(*rfunc)((%s *)object",s,s,typebase);
695 out_printf(out, "\t%s rfunc;\n\t",s);
696 print_type(out,m->mtype,TRUE);
697 out_printf(out, " *retval;\n\n"
698 "\trfunc = (%s)func;\n\n"
699 "\tretval = GTK_RETLOC_%s(args[%d]);\n\n"
700 "\t*retval = (*rfunc)((%s *)object",
701 s,(char *)m->gtktypes->data,
702 g_list_length(m->gtktypes)-1,typebase);
704 print_signal_marsal_args(m);
712 out_printf(out,"\n");
714 out_printf(out,"enum {\n");
715 for(li=c->nodes;li;li=g_list_next(li)) {
717 if(n->type == METHOD_NODE) {
718 Method *m = (Method *)n;
719 if(m->method == SIGNAL_LAST_METHOD ||
720 m->method == SIGNAL_FIRST_METHOD) {
721 char *s = g_strdup(m->id);
723 out_printf(out,"\t%s_SIGNAL,\n",s);
728 out_printf(out,"\tLAST_SIGNAL\n};\n\n");
731 out_printf(out,"enum {\n\tARG_0,\n");
732 for(li=c->nodes;li;li=g_list_next(li)) {
734 if(n->type == ARGUMENT_NODE) {
735 Argument *a = (Argument *)n;
736 char *s = g_strdup(a->name);
738 out_printf(out,"\tARG_%s,\n",s);
742 out_printf(out, "};\n\n");
747 "static guint object_signals[LAST_SIGNAL] = {0};\n\n");
749 out_printf(out, "static %sClass *parent_class = NULL;\n\n",ptypebase);
755 out_printf(out, "guint\n"
756 "%s_get_type (void)\n"
758 "\tstatic guint type = 0;\n\n"
760 "\t\tstatic const GtkTypeInfo info = {\n"
762 "\t\t\tsizeof (%s),\n"
763 "\t\t\tsizeof (%sClass),\n"
764 "\t\t\t(GtkClassInitFunc) %s_class_init,\n"
765 "\t\t\t(GtkObjectInitFunc) %s_init,\n"
766 "\t\t\t/* reserved_1 */ NULL,\n"
767 "\t\t\t/* reserved_2 */ NULL,\n"
768 "\t\t\t(GtkClassInitFunc) NULL,\n"
770 "\t\ttype = gtk_type_unique (%s_get_type(), &info);\n"
774 funcbase,typebase,typebase,typebase,
775 funcbase,funcbase,pfuncbase);
779 add_overrides(Class *c, char *oname, gboolean did_gtk_obj)
785 done = g_hash_table_new(g_str_hash,g_str_equal);
787 s = g_strdup("GtkObject"); /* This was already done */
788 g_hash_table_insert(done,s,s);
790 for(li=c->nodes;li;li=g_list_next(li)) {
793 Method *m = (Method *)n;
794 if(n->type != METHOD_NODE ||
795 m->method != OVERRIDE_METHOD)
798 s = remove_sep(m->otype);
800 if(g_hash_table_lookup(done,s)) {
804 g_hash_table_insert(done,s,s);
806 f = replace_sep(m->otype,'_');
809 out_printf(out,"\t%sClass *%s_class = (%sClass *)%s;\n",
814 g_hash_table_foreach(done,(GHFunc)g_free,NULL);
815 g_hash_table_destroy(done);
819 add_signals(Class *c)
823 out_printf(out,"\n");
824 for(li=c->nodes;li;li=g_list_next(li)) {
830 Method *m = (Method *)n;
831 if(n->type != METHOD_NODE ||
832 (m->method != SIGNAL_FIRST_METHOD &&
833 m->method != SIGNAL_LAST_METHOD))
837 if(m->method == SIGNAL_FIRST_METHOD)
842 if(g_hash_table_lookup(marsh,m))
843 mar = g_strconcat("___marshal_",
844 (char *)g_hash_table_lookup(marsh,m),
847 mar = g_strdup("gtk_signal_default_marshaller");
849 is_none = (strcmp(m->gtktypes->next->data,"NONE")==0);
851 sig = g_strdup(m->id);
853 out_printf(out,"\tobject_signals[%s_SIGNAL] =\n"
854 "\t\tgtk_signal_new (\"%s\",\n"
855 "\t\t\tGTK_RUN_%s,\n"
856 "\t\t\tgtk_object_class->type,\n"
857 "\t\t\tGTK_SIGNAL_OFFSET (%sClass, %s),\n"
859 "\t\t\tGTK_TYPE_%s, %d",
862 typebase,m->id,mar,(char *)m->gtktypes->data,
863 is_none?0:g_list_length(m->gtktypes->next));
869 for(l=m->gtktypes->next;l;l=g_list_next(l))
870 out_printf(out,",\n\t\t\tGTK_TYPE_%s",
874 out_printf(out,");\n");
876 out_printf(out,"\tgtk_object_class_add_signals (gtk_object_class,\n"
877 "\t\tobject_signals, LAST_SIGNAL);\n\n");
881 set_def_handlers(Class *c, char *oname)
885 out_printf(out,"\n");
886 for(li=c->nodes;li;li=g_list_next(li)) {
888 Method *m = (Method *)n;
889 if(n->type != METHOD_NODE ||
890 (m->method != SIGNAL_FIRST_METHOD &&
891 m->method != SIGNAL_LAST_METHOD &&
892 m->method != VIRTUAL_METHOD &&
893 m->method != OVERRIDE_METHOD))
897 if(m->method == OVERRIDE_METHOD) {
899 s = replace_sep(m->otype,'_');
902 out_printf(out,"\t%s_class->%s = %s_%s;\n",
903 s,m->id,funcbase,m->id);
905 out_printf(out,"\t%s_class->%s = NULL;\n",
909 out_printf(out,"\t%s->%s = _real_%s_%s;\n",
910 oname,m->id,funcbase,m->id);
912 out_printf(out,"\t%s->%s = NULL;\n",
919 make_arguments(Class *c)
930 out_printf(out,"\n");
931 for(li=c->nodes;li;li=g_list_next(li)) {
937 if(n->type != ARGUMENT_NODE)
943 flags = g_string_new("GTK_ARG_READWRITE");
945 flags = g_string_new("GTK_ARG_READABLE");
947 flags = g_string_new("GTK_ARG_WRITABLE");
949 for(l=a->flags;l;l=g_list_next(l)) {
950 char *flag = l->data;
952 if(strcmp(flag,"READWRITE")==0 ||
953 strcmp(flag,"READABLE")==0 ||
954 strcmp(flag,"WRITABLE")==0) {
955 print_error(TRUE,"READWRITE, READABLE and "
956 "WRITABLE argument flags are "
957 "set automatically",a->line_no);
960 for(i=0;argflags[i];i++) {
961 if(strcmp(argflags[i],flag)==0)
964 /* if we haven't found it in our list */
967 s = g_strdup_printf("Unknown flag '%s' used, "
968 "perhaps it was misspelled",
970 print_error(TRUE,s,a->line_no);
973 g_string_sprintfa(flags, " | GTK_ARG_%s",flag);
976 s = g_strdup(a->name);
978 out_printf(out,"\tgtk_object_add_arg_type(\"%s::%s\",\n"
982 typebase,a->name,a->gtktype,flags->str,s);
984 g_string_free(flags,TRUE);
988 "\n\tgtk_object_class->set_arg = ___object_set_arg;\n"
989 "\tgtk_object_class->get_arg = ___object_get_arg;\n");
996 for(li=c->nodes;li;li=g_list_next(li)) {
999 if(n->type != METHOD_NODE)
1002 if(m->method == INIT_METHOD) {
1004 out_addline_infile(out,m->line_no);
1005 print_method(out,"static ","\n"," ","\n",m,FALSE);
1007 out_addline_outfile(out);
1008 out_printf(out,"{\n");
1010 out_printf(out,"\t%s->_priv = "
1011 "g_new0 (%sPrivate,1);\n",
1012 ((FuncArg *)m->args->data)->name,
1015 } else if(m->method == CLASS_INIT_METHOD) {
1017 out_addline_infile(out,m->line_no);
1018 print_method(out,"static ","\n"," ","\n",m,FALSE);
1020 out_addline_outfile(out);
1021 out_printf(out,"{\n");
1025 "\tGtkObjectClass *"
1026 "gtk_object_class = "
1027 "(GtkObjectClass*) %s;\n",
1028 ((FuncArg *)m->args->data)->name);
1032 ((FuncArg *)m->args->data)->name,
1033 (signals>0 || arguments>0));
1035 out_printf(out,"\n\tparent_class = ");
1037 out_printf(out,"(%sClass *)",ptypebase);
1038 out_printf(out,"gtk_type_class (%s_get_type ());\n",
1044 set_def_handlers(c, ((FuncArg *)m->args->data)->name);
1053 out_printf(out," {\n");
1054 out_addline_infile(out,m->ccode_line);
1055 out_printf(out,"%s\n",m->cbuf);
1056 out_addline_outfile(out);
1057 out_printf(out," }\n");
1059 out_printf(out,"return;\n");
1061 out_printf(out,"}\n");
1066 add_getset_arg(Class *c, int is_set)
1069 out_printf(out,"\nstatic void\n"
1070 "___object_%s_arg (GtkObject *object,\n"
1075 "\tself = %s (object);\n\n"
1076 "\tswitch (arg_id) {\n",
1077 is_set?"set":"get",typebase,macrobase);
1079 for(li=c->nodes;li;li=g_list_next(li)) {
1085 if(n->type != ARGUMENT_NODE)
1090 line_no = a->set_line;
1093 line_no = a->get_line;
1097 s = g_strdup(a->name);
1099 out_printf(out,"\tcase ARG_%s:\n"
1100 "#define ARG (GTK_VALUE_%s(*arg))\n"
1104 out_addline_infile(out,line_no);
1105 out_printf(out,"%s\n",cbuf);
1106 out_addline_outfile(out);
1107 out_printf(out,"\t\t}\n\t\tbreak;\n"
1110 out_printf(out,"\tdefault:\n\t\tbreak;\n\t}\n}\n");
1114 print_checks(Method *m, FuncArg *fa)
1118 gboolean checked_null = FALSE;
1119 is_void = (strcmp(m->mtype->name,"void")==0 &&
1120 m->mtype->stars == 0);
1122 for(li=fa->checks;li;li=g_list_next(li)) {
1123 Check *ch = li->data;
1125 /* point to the method prot in .gob for failed checks */
1127 out_addline_infile(out,m->line_no);
1129 out_printf(out,"\tg_return_if_fail (");
1131 out_printf(out,"\tg_return_val_if_fail (");
1132 switch(ch->chtype) {
1134 out_printf(out,"%s != NULL",fa->name);
1135 checked_null = TRUE;
1138 s = make_pre_macro(fa->atype->name,"IS");
1140 out_printf(out,"%s (%s)",s,fa->name);
1142 /* if not check null, null may be valid */
1143 out_printf(out,"!(%s) || %s (%s)",fa->name,s,
1148 out_printf(out,"%s < %s",fa->name,ch->number);
1151 out_printf(out,"%s > %s",fa->name,ch->number);
1154 out_printf(out,"%s <= %s",fa->name,ch->number);
1157 out_printf(out,"%s >= %s",fa->name,ch->number);
1160 out_printf(out,"%s == %s",fa->name,ch->number);
1163 out_printf(out,"%s != %s",fa->name,ch->number);
1167 out_printf(out,");\n");
1169 out_printf(out,", (");
1170 print_type(out,m->mtype,TRUE);
1171 out_printf(out,")%s);\n",
1172 m->onerror?m->onerror:"0");
1178 print_preconditions(Method *m)
1182 for(li=m->args;li;li=g_list_next(li)) {
1183 FuncArg *fa = li->data;
1188 out_addline_outfile(out);
1191 /* put in code if it's needed */
1193 put_in_gen_code(Method *m)
1195 /* now we only have the freeing of the private structure */
1197 m->method == OVERRIDE_METHOD &&
1198 strcmp(m->id,"finalize")==0) {
1199 out_printf(out,"\tg_free (%s (%s)->_priv);\n"
1200 "\t%s (%s)->_priv = NULL;\n",
1202 ((FuncArg *)m->args->data)->name,
1204 ((FuncArg *)m->args->data)->name);
1209 print_method_body(Method *m, int pre)
1211 out_printf(out,"{\n");
1213 print_preconditions(m);
1217 /* Note: the trailing }'s are on one line, this is so
1218 that we get the no return warning correctly and point to
1219 the correct line in the .gob file, yes this is slightly
1220 ugly in the .c file, but that is not supposed to be
1221 human readable anyway. */
1223 out_printf(out,"{\n");
1225 out_addline_infile(out,m->ccode_line);
1226 out_printf(out,"\t%s}",m->cbuf);
1229 out_printf(out,"}\n");
1232 out_addline_outfile(out);
1236 put_signal_args(Method *m)
1240 for(ali = m->gtktypes->next,li=m->args->next;
1242 li=li->next, ali=ali->next) {
1243 FuncArg *fa = li->data;
1244 const char *cast = get_cast(ali->data,FALSE);
1245 /* we should have already proved before that
1246 the we know all the types */
1249 out_printf(out,",\n\t\t(%s)%s",cast,
1255 get_arg_names_for_macro(Method *m)
1259 GString *gs = g_string_new("");
1261 for(li=m->args;li;li=g_list_next(li)) {
1262 FuncArg *arg = li->data;
1263 g_string_sprintfa(gs, "%s___%s", p, arg->name);
1267 g_string_free(gs,FALSE);
1272 put_method(Method *m)
1276 is_void = (strcmp(m->mtype->name,"void")==0 &&
1277 m->mtype->stars == 0);
1278 out_printf(out,"\n");
1280 case REGULAR_METHOD:
1282 out_addline_infile(out,m->line_no);
1283 if(m->scope == PRIVATE_SCOPE)
1284 print_method(out,"static ","\n"," ","\n",m,FALSE);
1285 else /* PUBLIC, PROTECTED */
1286 print_method(out,"","\n"," ","\n",m,FALSE);
1287 print_method_body(m,TRUE);
1289 case SIGNAL_FIRST_METHOD:
1290 case SIGNAL_LAST_METHOD:
1292 out_addline_infile(out,m->line_no);
1293 if(m->scope == PRIVATE_SCOPE)
1294 print_method(out,"static ","\n"," ","\n",m,FALSE);
1296 print_method(out,"","\n"," ","\n",m,FALSE);
1297 out_addline_outfile(out);
1298 out_printf(out,"{\n");
1299 s = g_strdup(m->id);
1301 if(strcmp(m->mtype->name,"void")==0 &&
1302 m->mtype->stars==0) {
1303 print_preconditions(m);
1304 if(((FuncArg *)m->args->data)->name)
1305 out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1306 "\t\tobject_signals[%s_SIGNAL]",
1307 ((FuncArg *)m->args->data)->name,s);
1309 out_printf(out,");\n}\n");
1311 out_printf(out,"\t");
1312 print_type(out,m->mtype,TRUE);
1313 out_printf(out,"return_val;\n");
1314 print_preconditions(m);
1315 out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1316 "\t\tobject_signals[%s_SIGNAL]",
1317 ((FuncArg *)m->args->data)->name,s);
1319 out_printf(out,",\n\t\t&return_val);\n"
1320 "\treturn return_val;\n}\n");
1326 out_addline_infile(out,m->line_no);
1327 print_method(out,"static ","\n_real_"," ","\n",m,FALSE);
1328 print_method_body(m,FALSE);
1330 case VIRTUAL_METHOD:
1332 out_addline_infile(out,m->line_no);
1333 if(m->scope==PRIVATE_SCOPE)
1334 print_method(out,"static ","\n"," ","\n",m,FALSE);
1336 print_method(out,"","\n"," ","\n",m,FALSE);
1337 out_addline_outfile(out);
1338 out_printf(out,"{\n"
1339 "\t%sClass *klass;\n",typebase);
1340 print_preconditions(m);
1341 out_printf(out,"\tklass = %s_CLASS(GTK_OBJECT(%s)->klass);\n\n"
1342 "\tif(klass->%s)\n",
1343 macrobase, ((FuncArg *)m->args->data)->name, m->id);
1344 if(strcmp(m->mtype->name,"void")==0 &&
1345 m->mtype->stars==0) {
1347 out_printf(out,"\t\t(*klass->%s)(%s",m->id,
1348 ((FuncArg *)m->args->data)->name);
1349 for(li=m->args->next;li;li=g_list_next(li)) {
1350 FuncArg *fa = li->data;
1351 out_printf(out,",%s",fa->name);
1353 out_printf(out,");\n}\n");
1356 out_printf(out,"\t\treturn (*klass->%s)(%s",m->id,
1357 ((FuncArg *)m->args->data)->name);
1358 for(li=m->args->next;li;li=g_list_next(li)) {
1359 FuncArg *fa = li->data;
1360 out_printf(out,",%s",fa->name);
1362 out_printf(out,");\n"
1365 print_type(out,m->mtype,TRUE);
1366 out_printf(out,")(%s);\n}\n",
1367 m->onerror?m->onerror:"0");
1373 out_addline_infile(out,m->line_no);
1374 print_method(out,"static ","\n_real_"," ","\n",m,FALSE);
1375 print_method_body(m,FALSE);
1377 case OVERRIDE_METHOD:
1381 out_addline_infile(out,m->line_no);
1382 print_method(out,"static ","\n"," ","\n",m,FALSE);
1383 s = replace_sep(m->otype,'_');
1385 args = get_arg_names_for_macro(m);
1387 out_printf(out,"#define PARENT_HANDLER(%s) \\\n"
1388 "\t{ if(%s_CLASS(parent_class)->%s) \\\n"
1389 "\t\t(* %s_CLASS(parent_class)->%s)(%s); }\n",
1390 args,s,m->id,s,m->id,args);
1392 out_printf(out,"#define PARENT_HANDLER(%s) \\\n"
1393 "\t((%s_CLASS(parent_class)->%s)? \\\n"
1394 "\t\t(* %s_CLASS(parent_class)->%s)(%s): \\\n"
1396 args,s,m->id,s,m->id,args);
1397 out_printf(out,"(");
1398 print_type(out,m->mtype,TRUE);
1399 out_printf(out,")%s))\n",
1400 m->onerror?m->onerror:"0");
1404 print_method_body(m,TRUE);
1405 out_printf(out,"#undef PARENT_HANDLER\n");
1413 check_duplicate(Class *c, Node *node, char *id, int line_no)
1416 for(l=c->nodes;l;l=g_list_next(l)) {
1421 if(n->type == METHOD_NODE) {
1422 Method *m = (Method *)n;
1424 nline_no = m->line_no;
1425 } else if(n->type == VARIABLE_NODE) {
1426 Variable *v = (Variable *)n;
1428 nline_no = v->line_no;
1432 line_no>=nline_no ||
1433 strcmp(nid,id)!=0 ||
1434 n->type != node->type)
1436 s = g_strdup_printf("symbol '%s' redefined, "
1437 "first defined on line %d",
1439 print_error(FALSE,s,nline_no);
1444 check_duplicate_symbols(Class *c)
1447 for(l=c->nodes;l;l=g_list_next(l)) {
1449 if(n->type == METHOD_NODE) {
1450 Method *m = (Method *)n;
1451 check_duplicate(c,n,m->id,m->line_no);
1452 } else if(n->type == VARIABLE_NODE) {
1453 Variable *v = (Variable *)n;
1454 check_duplicate(c,n,v->id,v->line_no);
1460 check_bad_symbols(Class *c)
1463 for(l=c->nodes;l;l=g_list_next(l)) {
1465 if(n->type == METHOD_NODE) {
1466 Method *m = (Method *)n;
1467 if((m->method == SIGNAL_LAST_METHOD ||
1468 m->method == SIGNAL_FIRST_METHOD ||
1469 m->method == VIRTUAL_METHOD) &&
1470 strcmp(m->id,"__parent__")==0) {
1472 s = g_strdup_printf("'%s' not allowed as an "
1473 "identifier of signal "
1474 "or virtual methods",
1476 print_error(FALSE,s,m->line_no);
1479 if(m->method != INIT_METHOD &&
1480 m->method != CLASS_INIT_METHOD &&
1481 (strcmp(m->id,"init")==0 ||
1482 strcmp(m->id,"class_init")==0)) {
1483 print_error(FALSE,"init, or class_init not "
1485 "identifier of non-"
1486 "constructor methods",m->line_no);
1488 } else if(n->type == VARIABLE_NODE) {
1489 Variable *v = (Variable *)n;
1490 if(strcmp(v->id,"_priv")==0 ||
1491 strcmp(v->id,"__parent__")==0) {
1493 s = g_strdup_printf("'%s' not allowed as a "
1494 "data member name",v->id);
1495 print_error(FALSE,s,v->line_no);
1504 check_duplicate_named(Class *c,Node *node,char *id, int line_no)
1507 for(l=c->nodes;l;l=g_list_next(l)) {
1512 if(n->type == METHOD_NODE) {
1513 Method *m = (Method *)n;
1514 if(m->method == SIGNAL_LAST_METHOD ||
1515 m->method == SIGNAL_FIRST_METHOD) {
1517 nline_no = m->line_no;
1520 } else if(n->type == ARGUMENT_NODE) {
1521 Argument *a = (Argument *)n;
1523 nline_no = a->line_no;
1527 line_no>=nline_no ||
1530 s = g_strdup_printf("named symbol (argument or signal) '%s' "
1531 "redefined, first defined on line %d",
1533 print_error(FALSE,s,nline_no);
1538 check_duplicate_signals_args(Class *c)
1541 for(l=c->nodes;l;l=g_list_next(l)) {
1543 if(n->type == METHOD_NODE) {
1544 Method *m = (Method *)n;
1545 if(m->method == SIGNAL_LAST_METHOD ||
1546 m->method == SIGNAL_FIRST_METHOD)
1547 check_duplicate_named(c,n,m->id,m->line_no);
1548 } else if(n->type == ARGUMENT_NODE) {
1549 Argument *a = (Argument *)n;
1550 check_duplicate_named(c,n,a->name,a->line_no);
1556 check_public_new(Class *c)
1559 for(l=c->nodes;l;l=g_list_next(l)) {
1561 if(n->type == METHOD_NODE) {
1562 Method *m = (Method *)n;
1563 if((strcmp(m->id,"new")==0) &&
1564 (m->method != REGULAR_METHOD ||
1565 m->scope != PUBLIC_SCOPE))
1567 "'new' should be a regular\n"
1575 check_vararg(Class *c)
1578 for(l=c->nodes;l;l=g_list_next(l)) {
1580 if(n->type == METHOD_NODE) {
1581 Method *m = (Method *)n;
1584 if(m->method == OVERRIDE_METHOD ||
1585 m->method == SIGNAL_LAST_METHOD ||
1586 m->method == SIGNAL_FIRST_METHOD ||
1587 m->method == VIRTUAL_METHOD) {
1589 "signals, overrides and virtuals, "
1590 "can't have variable argument "
1599 check_firstarg(Class *c)
1602 for(l=c->nodes;l;l=g_list_next(l)) {
1604 if(n->type == METHOD_NODE) {
1605 Method *m = (Method *)n;
1608 if(m->method == OVERRIDE_METHOD ||
1609 m->method == SIGNAL_LAST_METHOD ||
1610 m->method == SIGNAL_FIRST_METHOD ||
1611 m->method == VIRTUAL_METHOD) {
1613 "signals, overrides and virtuals, "
1614 "can't have no arguments",
1622 check_nonvoidempty(Class *c)
1625 for(l=c->nodes;l;l=g_list_next(l)) {
1627 if(n->type == METHOD_NODE) {
1628 Method *m = (Method *)n;
1629 if(m->method != REGULAR_METHOD)
1631 if(!(strcmp(m->mtype->name,"void")==0 &&
1632 m->mtype->stars == 0) &&
1635 "non-void empty method found, "
1636 "regular non-void function should "
1639 /* add a body here, so that the user will also
1640 get a warning from gcc, and so that it will
1641 at least point him to the prototype of the
1642 function in the .gob file */
1643 m->cbuf = g_strdup("/*empty*/");
1644 m->ccode_line = m->line_no;
1651 check_signal_args(Class *c)
1654 for(l=c->nodes;l;l=g_list_next(l)) {
1656 if(n->type == METHOD_NODE) {
1657 Method *m = (Method *)n;
1659 if(m->method != SIGNAL_LAST_METHOD &&
1660 m->method != SIGNAL_FIRST_METHOD)
1663 for(l=m->gtktypes;l;l=l->next) {
1665 if(get_cast(l->data,FALSE))
1667 s = g_strdup_printf("Unknown GTK+ type '%s' "
1668 "among signal types",
1670 print_error(FALSE, s, m->line_no);
1678 check_argument_types(Class *c)
1681 for(l=c->nodes;l;l=g_list_next(l)) {
1683 if(n->type == ARGUMENT_NODE) {
1684 Argument *a = (Argument *)n;
1686 if(get_cast(a->gtktype,FALSE))
1688 s = g_strdup_printf("Unknown GTK+ type '%s' "
1691 /* this could perhaps be a warning, but
1692 can there really be a type beyond the
1694 print_error(FALSE, s, a->line_no);
1701 count_signals(Class *c)
1705 for(l=c->nodes;l;l=g_list_next(l)) {
1707 if(n->type == METHOD_NODE) {
1708 Method *m = (Method *)n;
1709 if(m->method == SIGNAL_LAST_METHOD ||
1710 m->method == SIGNAL_FIRST_METHOD)
1718 count_arguments(Class *c)
1723 for(li=c->nodes;li;li=g_list_next(li)) {
1725 if(n->type == ARGUMENT_NODE)
1732 count_overrides(Class *c)
1736 for(l=c->nodes;l;l=g_list_next(l)) {
1738 if(n->type == METHOD_NODE) {
1739 Method *m = (Method *)n;
1740 if(m->method == OVERRIDE_METHOD)
1748 count_privates(Class *c)
1752 for(l=c->nodes;l;l=g_list_next(l)) {
1754 if(n->type == VARIABLE_NODE) {
1755 Variable *v = (Variable *)n;
1756 if(v->scope == PRIVATE_SCOPE)
1764 count_protecteds(Class *c)
1768 for(l=c->nodes;l;l=g_list_next(l)) {
1770 if(n->type == METHOD_NODE) {
1771 Method *m = (Method *)n;
1772 if(m->scope == PROTECTED_SCOPE)
1783 char *outfile,*outfileh,*outfileph;
1786 outfile = g_strconcat(filebase,".c",NULL);
1788 outfile = g_strconcat(filebase,".cc",NULL);
1789 if(no_touch_headers)
1790 outfileh = g_strconcat("#gob#",filebase,".h#gob#",NULL);
1792 outfileh = g_strconcat(filebase,".h",NULL);
1794 if((privates>0 || protecteds>0 || always_private_header) &&
1796 outfileph = g_strconcat(filebase,"-private.h",NULL);
1801 out = fopen(outfile,"w");
1803 g_error("Cannot open outfile: %s",outfile);
1805 outh = fopen(outfileh,"w");
1807 g_error("Cannot open outfile: %s",outfileh);
1810 outph = fopen(outfileph,"w");
1812 g_error("Cannot open outfile: %s",outfileh);
1818 put_argument_nongnu_wrappers(Class *c)
1825 for(li=c->nodes;li;li=g_list_next(li)) {
1827 Argument *a = (Argument *)n;
1830 if(n->type != ARGUMENT_NODE)
1832 s = g_strdup(a->name);
1835 cast = get_type(a->atype,TRUE);
1837 cast = g_strdup(get_cast(a->gtktype,TRUE));
1841 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1842 "\"%s\",(%s)(arg)\n",
1843 macrobase, s, a->name, cast);
1845 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1846 "\"%s\",(%s*)(arg)\n",
1847 macrobase, s, a->name, cast);
1850 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1852 macrobase, s, a->name);
1854 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1856 macrobase, s, a->name);
1864 put_argument_gnu_wrappers(Class *c)
1871 for(li=c->nodes;li;li=g_list_next(li)) {
1873 Argument *a = (Argument *)n;
1876 if(n->type != ARGUMENT_NODE)
1878 s = g_strdup(a->name);
1881 cast = get_type(a->atype,TRUE);
1883 cast = g_strdup(get_cast(a->gtktype,TRUE));
1886 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1887 "\"%s\",({%sz = (arg); z;})\n",
1888 macrobase, s, a->name, cast);
1890 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1891 "\"%s\",({%s*z = (arg); z;})\n",
1892 macrobase, s, a->name, cast);
1895 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1897 macrobase, s, a->name);
1899 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1901 macrobase, s, a->name);
1909 generate_outfiles(void)
1914 gboolean found_header;
1917 out_printf(outh,"/* Generated by GOB (v%s)"
1918 " (do not edit directly) */\n\n",VERSION);
1920 out_printf(outph,"/* Generated by GOB (v%s)"
1921 " (do not edit directly) */\n\n",VERSION);
1922 out_printf(out,"/* Generated by GOB (v%s) on %s"
1923 " (do not edit directly) */\n\n",VERSION,ctime(&curtime));
1926 int major=0,minor=0,pl=0;
1927 sscanf(VERSION,"%d.%d.%d",&major,&minor,&pl);
1929 out_printf(out,"#define GOB_VERSION_MAJOR %d\n", major);
1930 out_printf(out,"#define GOB_VERSION_MINOR %d\n", minor);
1931 out_printf(out,"#define GOB_VERSION_PATCHLEVEL %d\n\n", pl);
1934 p = replace_sep(((Class *)class)->otype,'_');
1936 out_printf(outh,"#ifndef __%s_H__\n#define __%s_H__\n\n"
1937 "#include <gtk/gtk.h>\n\n",p,p);
1939 out_printf(outph,"#ifndef __%s_PRIVATE_H__\n"
1940 "#define __%s_PRIVATE_H__\n\n"
1941 "#include \"%s.h\"\n\n",p,p,filebase);
1945 out_printf(outh,"#ifdef __cplusplus\n"
1947 "#endif /* __cplusplus */\n\n");
1949 out_printf(outph,"#ifdef __cplusplus\n"
1951 "#endif /* __cplusplus */\n\n");
1954 p = g_strconcat(filebase,".h",NULL);
1955 found_header = TRUE;
1956 if(!g_list_find_custom(include_files,p,(GCompareFunc)strcmp)) {
1957 out_printf(out,"#include \"%s.h\"\n\n",filebase);
1958 found_header = FALSE;
1962 /* if we are creating a private header see if it was included */
1964 p = g_strconcat(filebase,"-private.h",NULL);
1965 if(!g_list_find_custom(include_files,p,(GCompareFunc)strcmp)) {
1966 out_printf(out,"#include \"%s-private.h\"\n\n",
1970 "Implicit private header include "
1972 "\tsource file, while public "
1973 "header is at a custom location, "
1975 "\texplicitly include "
1976 "the private header below the "
1982 for(li=nodes;li;li=g_list_next(li)) {
1983 Node *node = li->data;
1984 if(node->type == CCODE_NODE) {
1985 CCode *cc = (CCode *)node;
1989 out_printf(fp,"\n");
1992 out_printf(fp,"\n");
1993 out_addline_infile(fp,cc->line_no);
1995 out_printf(fp,"%s\n",cc->cbuf);
1997 out_addline_outfile(fp);
1998 } else if(node->type == CLASS_NODE) {
1999 Class *c = (Class *)class;
2002 out_printf(out,"/* utility types we may need */\n");
2003 out_printf(out,"typedef struct { "
2004 "gpointer a; gpointer b; "
2005 "} ___twopointertype;\n");
2006 out_printf(out,"typedef struct { "
2007 "gpointer a; gpointer b; "
2009 "} ___threepointertype;\n");
2011 out_printf(outh,"\n#define %s\t"
2012 "(%s_get_type())\n",
2013 macrotype,funcbase);
2014 out_printf(outh,"#define %s(obj)\t"
2015 "GTK_CHECK_CAST((obj),%s_get_type(),%s)\n",
2016 macrobase,funcbase,typebase);
2017 out_printf(outh,"#define %s_CLASS(klass)\t"
2018 "GTK_CHECK_CLASS_CAST((klass),%s_get_type(),%sClass)\n",
2019 macrobase,funcbase,typebase);
2020 out_printf(outh,"#define %s(obj)\t"
2021 "GTK_CHECK_TYPE((obj), %s_get_type ())\n\n",
2024 /* argument wrapping macros */
2025 if(arguments>0 && !no_gnu) {
2026 out_printf(outh,"\n#ifdef __GNUC__\n");
2027 put_argument_gnu_wrappers(c);
2028 out_printf(outh,"#else /* __GNUC__ */\n");
2029 put_argument_nongnu_wrappers(c);
2030 out_printf(outh,"#endif /* __GNUC__ */\n\n");
2031 } else if(arguments>0 && no_gnu) {
2032 put_argument_nongnu_wrappers(c);
2036 out_printf(outh,"\ntypedef struct _%sPrivate %sPrivate;\n",typebase,typebase);
2038 out_printf(outh,"\ntypedef struct _%s %s;\n",typebase,typebase);
2039 out_printf(outh,"struct _%s {\n\t%s __parent__;\n",
2040 typebase,ptypebase);
2041 for(l=c->nodes;l;l=g_list_next(l)) {
2043 Variable *v = (Variable *)n;
2044 if(n->type == VARIABLE_NODE &&
2045 v->scope == PUBLIC_SCOPE)
2046 put_variable((Variable *)n,outh);
2048 /* put protecteds always AFTER publics */
2049 for(l=c->nodes;l;l=g_list_next(l)) {
2051 Variable *v = (Variable *)n;
2052 if(n->type == VARIABLE_NODE &&
2053 v->scope == PROTECTED_SCOPE)
2054 put_variable((Variable *)n,outh);
2057 out_printf(outh,"\t%sPrivate *_priv;\n",typebase);
2058 out_printf(outh,"};\n");
2063 /* if we are to stick this into the private
2064 header, if not stick it directly into the
2071 out_printf(outfp,"struct _%sPrivate {\n",
2073 for(l=c->nodes;l;l=l->next) {
2075 Variable *v = (Variable *)n;
2076 if(n->type == VARIABLE_NODE &&
2077 v->scope == PRIVATE_SCOPE) {
2078 out_addline_infile(outfp,v->line_no);
2079 put_variable(v,outfp);
2082 out_addline_outfile(outfp);
2083 out_printf(outfp,"};\n");
2086 out_printf(outh,"\ntypedef struct _%sClass %sClass;\n",
2089 "struct _%sClass {\n\t%sClass __parent__;\n",
2090 typebase,ptypebase);
2091 for(l=c->nodes;l;l=g_list_next(l)) {
2093 if(n->type == METHOD_NODE)
2094 put_vs_method((Method *)n);
2096 out_printf(outh,"};\n\n");
2098 out_printf(outh,"guint\t%s_get_type\t(void);\n",funcbase);
2100 out_printf(out,"/* here are local prototypes */\n");
2102 out_printf(out,"#ifdef __GNUC__\n"
2103 "#define ___NO_UNUSED_WARNING "
2104 "__attribute__ ((__unused__))\n"
2105 "#else /* __GNUC__ */\n"
2106 "#define ___NO_UNUSED_WARNING\n"
2107 "#endif /* __GNUC__ */\n");
2110 out_printf(out,"static void ___object_set_arg "
2111 "(GtkObject *object, GtkArg *arg, "
2113 "static void ___object_get_arg "
2114 "(GtkObject *object, GtkArg *arg, "
2115 "guint arg_id);\n");
2118 for(l=c->nodes;l;l=g_list_next(l)) {
2120 if(n->type == METHOD_NODE) {
2121 put_pub_method((Method *)n);
2122 put_prot_method((Method *)n);
2123 put_priv_method_prot((Method *)n);
2128 for(l=c->nodes;l;l=g_list_next(l)) {
2130 if(n->type == METHOD_NODE)
2131 add_signal_prots((Method *)n);
2136 out_printf(out,"#undef ___NO_UNUSED_WARNING\n");
2143 make_method_nongnu_aliases(c);
2145 out_printf(out,"\n#ifdef __GNUC__\n");
2146 make_method_gnu_aliases(c);
2147 out_printf(out,"#else /* __GNUC__ */\n");
2148 make_method_nongnu_aliases(c);
2149 out_printf(out,"#endif /* __GNUC__ */\n\n");
2152 out_printf(out,"#define GET_NEW (gtk_type_new(%s_get_type()))\n",
2158 add_getset_arg(c, TRUE);
2159 add_getset_arg(c, FALSE);
2162 for(l=c->nodes;l;l=g_list_next(l)) {
2164 if(n->type == METHOD_NODE) {
2165 put_method((Method *)n);
2169 out_printf(out,"#undef GET_NEW\n");
2171 add_bad_hack_to_avoid_unused_warnings(c);
2173 g_assert_not_reached();
2177 out_printf(outh,"\n#ifdef __cplusplus\n"
2179 "#endif /* __cplusplus */\n");
2180 out_printf(outh,"\n#endif");
2183 out_printf(outph,"\n#ifdef __cplusplus\n"
2185 "#endif /* __cplusplus */\n");
2186 out_printf(outph,"\n#endif");
2192 usage(poptContext optCon, int exitcode, char *error, char *addl)
2194 poptPrintUsage(optCon, stderr, 0);
2195 if (error) fprintf(stderr, "%s: %s", error, addl);
2203 fprintf(stderr,"Gob version %s\n\n",VERSION);
2204 fprintf(stderr,"Options:\n"
2205 "\t--help,-h,-? Display this help\n"
2206 "\t--version Display version\n"
2207 "\t--exit-on-warn,-w Exit with an error on warnings\n"
2208 "\t--no-exit-on-warn Don't exit on warnings [default]\n"
2209 "\t--for-cpp Create C++ files\n"
2210 "\t--no-gnu Never use GNU extentions\n"
2211 "\t--no-touch-headers Don't touch headers unless they "
2213 "\t--always-private-header Always create a private header "
2215 "\t even if it would be empty\n"
2216 "\t--no-private-header Don't create a private header, "
2218 "\t structure and protected "
2219 "prototypes inside c file\n");
2223 parse_options(int argc, char *argv[])
2226 int got_file = FALSE;
2227 int no_opts = FALSE;
2231 for(i=1;i<argc;i++) {
2232 if(no_opts || argv[i][0]!='-') {
2235 fprintf(stderr,"Specify only one file!\n");
2241 } else if(strcmp(argv[i],"--help")==0) {
2244 } else if(strcmp(argv[i],"--version")==0) {
2245 fprintf(stderr,"Gob version %s\n",VERSION);
2247 } else if(strcmp(argv[i],"--exit-on-warn")==0) {
2248 exit_on_warn = TRUE;
2249 } else if(strcmp(argv[i],"--no-exit-on-warn")==0) {
2250 exit_on_warn = FALSE;
2251 } else if(strcmp(argv[i],"--for-cpp")==0) {
2253 } else if(strcmp(argv[i],"--no-touch-headers")==0) {
2254 no_touch_headers = TRUE;
2255 } else if(strcmp(argv[i],"--always-private-header")==0) {
2256 no_private_header = FALSE;
2257 always_private_header = TRUE;
2258 } else if(strcmp(argv[i],"--no-private-header")==0) {
2259 always_private_header = FALSE;
2260 no_private_header = TRUE;
2261 } else if(strcmp(argv[i],"--no-gnu")==0) {
2263 } else if(strcmp(argv[i],"--")==0) {
2264 /*further arguments are files*/
2266 } else if(strncmp(argv[i],"--",2)==0) {
2267 /*unknown long option*/
2268 fprintf(stderr,"Unknown option '%s'!\n",argv[i]);
2272 /*by now we know we have a string starting with
2273 - which is a short option string*/
2274 char *p = argv[i]+1;
2275 for(p=argv[i]+1;*p;p++) {
2286 "Unknown option '%c'!\n",*p);
2295 /* this is a somewhat ugly hack, but it appears to work */
2297 compare_and_move_header(void)
2299 char *hfnew = g_strconcat("#gob#",filebase,".h#gob#",NULL);
2300 char *hf = g_strconcat(filebase,".h",NULL);
2302 if(stat(hf,&s)==0) {
2304 s = g_strdup_printf("cmp '%s' '%s' > /dev/null",hf,hfnew);
2306 if(unlink(hfnew)!=0)
2307 print_error(FALSE,"Can't remove new header file",0);
2315 print_error(FALSE,"Can't remove old header file",0);
2317 if(rename(hfnew,hf)!=0)
2318 print_error(FALSE,"Can't rename new header file",0);
2324 main(int argc, char *argv[])
2330 struct poptOption optionsTable[] = {
2331 { "exit-on-warn", 'w', 0, &exit_on_warn, 0,
2332 "exit on warnings" },
2334 { NULL, 0, 0, NULL, 0 }
2337 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
2338 poptSetOtherOptionHelp(optCon, "[OPTIONS]* [filename]");
2340 while ((c = poptGetNextOpt(optCon)) >= 0)
2343 filename = poptGetArg(optCon);
2344 if(!(poptPeekArg(optCon) == NULL))
2345 usage(optCon, 1, "Specify only one file",
2346 ".e.g., filename.gob");
2349 /* an error occurred during option processing */
2350 fprintf(stderr, "%s: %s\n",
2351 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
2357 parse_options(argc,argv);
2360 yyin = fopen(filename,"r");
2362 fprintf(stderr,"Error: can't open file '%s'\n",
2371 g_error("Parsing errors, quitting");
2373 print_error(FALSE," no class defined",0);
2376 exit_on_error = FALSE;
2378 signals = count_signals((Class *)class);
2379 arguments = count_arguments((Class *)class);
2380 overrides = count_overrides((Class *)class);
2381 privates = count_privates((Class *)class);
2382 protecteds = count_protecteds((Class *)class);
2385 make_inits((Class *)class);
2387 make_finalize((Class *)class);
2388 check_bad_symbols((Class *)class);
2389 check_duplicate_symbols((Class *)class);
2390 check_duplicate_signals_args((Class *)class);
2391 check_public_new((Class *)class);
2392 check_vararg((Class *)class);
2393 check_firstarg((Class *)class);
2394 check_nonvoidempty((Class *)class);
2395 check_signal_args((Class *)class);
2396 check_argument_types((Class *)class);
2398 exit_on_error = TRUE;
2405 generate_outfiles();
2410 if(no_touch_headers)
2411 compare_and_move_header();
2414 poptFreeContext(optCon);