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;
48 static char *funcbase;
49 static char *pfuncbase;
50 static char *macrobase;
52 static char *macrotype;
53 static char *typebase;
54 static char *ptypebase;
56 static int signals = 0;
57 static int arguments = 0;
58 static int overrides = 0;
63 gboolean no_touch_headers = FALSE;
64 gboolean for_cpp = FALSE;
65 gboolean exit_on_warn = FALSE;
66 gboolean exit_on_error = TRUE;
67 gboolean got_error = FALSE;
70 print_error(int is_warn, char *error,int line)
80 fprintf(stderr,"%s:%d: %s %s\n",filename,line,w,error);
82 fprintf(stderr,"%s: %s %s\n",filename,w,error);
83 if((!is_warn || exit_on_warn) && exit_on_error)
88 remove_sep(char *base)
91 char *s = g_strdup(base);
92 while((p=strchr(s,':')))
98 replace_sep(char *base, char r)
101 char *s = g_strdup(base);
102 while((p=strchr(s,':')))
112 /*separate the namespace part and then replace rest of
115 separns_replace_sep(char *base, char **ns, char **name, char r)
118 char *s = g_strdup(base);
120 if((p=strchr(s,':')) && p!=s) {
127 while((p=strchr(s,':')))
130 *name = g_strdup(s+1);
136 /* make a macro with some prefix before the name but after
139 make_pre_macro(char *base, char *pre)
144 separns_replace_sep(base,&s1,&s2,'_');
146 s = g_strconcat(s1,"_",pre,"_",s2,NULL);
148 s = g_strconcat(pre,"_",s2,NULL);
161 filebase = replace_sep(((Class *)class)->otype,'-');
164 funcbase = replace_sep(((Class *)class)->otype,'_');
167 pfuncbase = replace_sep(((Class *)class)->ptype,'_');
168 g_strdown(pfuncbase);
170 macrobase = replace_sep(((Class *)class)->otype,'_');
173 macrois = make_pre_macro(((Class *)class)->otype,"IS");
174 macrotype = make_pre_macro(((Class *)class)->otype,"TYPE");
176 typebase = remove_sep(((Class *)class)->otype);
178 ptypebase = remove_sep(((Class *)class)->ptype);
182 print_type(FILE *fp, Type *t)
186 s = remove_sep(t->name);
187 out_printf(fp,"%s ",s);
190 for(i=0;i<t->stars;i++)
195 print_method(FILE *fp, char *typeprefix, char *nameprefix,
196 char *namepostfix,char *postfix, Method *m,
197 gboolean no_funcbase)
201 out_printf(fp,"%s",typeprefix);
202 print_type(fp,m->mtype);
204 out_printf(fp,"%s%s%s(",
205 nameprefix,m->id,namepostfix);
207 out_printf(fp,"%s%s_%s%s(",
208 nameprefix,funcbase,m->id,namepostfix);
211 for(li=m->args;li;li=g_list_next(li)) {
212 FuncArg *arg = li->data;
213 print_type(fp,arg->atype);
215 out_printf(fp,"%s, ",arg->name);
217 out_printf(fp,"%s",arg->name);
221 out_printf(fp,", ...");
223 out_printf(fp,"void");
225 out_printf(fp,")%s",postfix);
230 make_method_pointers(Class *c)
234 out_printf(out,"\n");
235 for(li=c->nodes;li;li=g_list_next(li)) {
236 Node *node = li->data;
237 if(node->type == METHOD_NODE) {
238 Method *m = (Method *)node;
240 if(m->scope == INIT_METHOD ||
241 m->scope == CLASS_INIT_METHOD ||
242 m->scope == OVERRIDE_METHOD)
245 /* in C++ mode don't alias new */
246 if(for_cpp && strcmp(m->id,"new")==0)
249 print_method(out,"static ","(* ",") ","",m,TRUE);
250 out_printf(out," = %s_%s;\n",funcbase,m->id);
253 out_printf(out,"\n");
257 add_bad_hack_to_avoid_unused_warnings(Class *c)
261 out_printf(out,"\n\n/*REALLY BAD HACK\n"
262 " This is to avoid unused warnings if you don't call\n"
263 " some method, it pollutes the namespace but the call\n"
264 " is weird enough. I need to find a better way to do\n"
266 out_printf(out,"void __%s_really_bad_hack_to_avoid_warnings(void);\n",
268 out_printf(out,"void\n__%s_really_bad_hack_to_avoid_warnings(void)\n"
270 for(li=c->nodes;li;li=g_list_next(li)) {
271 Node *node = li->data;
272 if(node->type == METHOD_NODE) {
273 Method *m = (Method *)node;
275 if(m->scope == INIT_METHOD ||
276 m->scope == CLASS_INIT_METHOD ||
277 m->scope == OVERRIDE_METHOD)
280 /* in C++ mode we don't alias new */
281 if(for_cpp && strcmp(m->id,"new")==0)
284 out_printf(out,"\t((void (*)(void))%s)();\n",m->id);
287 out_printf(out,"}\n\n");
291 put_variable(Variable *v)
293 out_printf(outh,"\t");
294 if(v->scope == PRIVATE_SCOPE)
295 out_printf(outh,"/* private */ ");
296 print_type(outh,v->vtype);
298 out_printf(outh,"%s;\n",v->id);
302 put_vs_method(Method *m)
304 if(m->scope != SIGNAL_LAST_METHOD &&
305 m->scope != SIGNAL_FIRST_METHOD &&
306 m->scope != PRIVATE_SIGNAL_LAST_METHOD &&
307 m->scope != PRIVATE_SIGNAL_FIRST_METHOD &&
308 m->scope != VIRTUAL_METHOD &&
309 m->scope != PRIVATE_VIRTUAL_METHOD)
312 print_method(outh,"\t","(* ",") ",";\n",m,TRUE);
316 put_pub_method(Method *m)
318 if(m->scope == PRIVATE_SCOPE ||
319 m->scope == OVERRIDE_METHOD ||
320 m->scope == INIT_METHOD ||
321 m->scope == CLASS_INIT_METHOD ||
322 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
323 m->scope == PRIVATE_SIGNAL_FIRST_METHOD ||
324 m->scope == PRIVATE_VIRTUAL_METHOD)
327 print_method(outh,"","\t","\t",";\n",m,FALSE);
331 put_priv_method_prot(Method *m)
333 if(m->scope == PUBLIC_SCOPE)
336 if(m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
337 m->scope == PRIVATE_SIGNAL_FIRST_METHOD ||
338 m->scope == PRIVATE_VIRTUAL_METHOD) {
340 print_method(out,"static ","_real_"," ",";\n",m,FALSE);
341 print_method(out,"static ",""," ",";\n",m,FALSE);
342 } else if(m->scope == SIGNAL_LAST_METHOD ||
343 m->scope == SIGNAL_FIRST_METHOD ||
344 m->scope == VIRTUAL_METHOD) {
347 print_method(out,"static ","_real_"," ",";\n",m,FALSE);
349 print_method(out,"static ",""," ",";\n",m,FALSE);
354 make_init_args(Class *cl, char *name, int is_class)
361 tn = g_strconcat(cl->otype,":Class",NULL);
363 tn = g_strdup(cl->otype);
365 type = new_type(1,tn);
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->scope == INIT_METHOD) {
383 print_error(FALSE,"init defined more then once",m->line_no);
385 } else if(m->scope == 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(CLASS_INIT_METHOD,
394 (Type *)new_type(0,g_strdup("void")),
395 NULL,NULL,g_strdup("class_init"),
396 make_init_args(cl,g_strdup("c"),TRUE),
397 NULL, NULL,0,0,FALSE);
398 cl->nodes = g_list_prepend(cl->nodes,node);
401 node = new_method(INIT_METHOD,
402 (Type *)new_type(0,g_strdup("void")),
403 NULL,NULL,g_strdup("init"),
404 make_init_args(cl,g_strdup("o"),FALSE),
405 NULL, NULL,0,0,FALSE);
406 cl->nodes = g_list_prepend(cl->nodes,node);
410 static GHashTable *marsh = NULL;
413 add_signal_prots(Method *m)
419 if(m->scope != SIGNAL_LAST_METHOD &&
420 m->scope != SIGNAL_FIRST_METHOD &&
421 m->scope != PRIVATE_SIGNAL_LAST_METHOD &&
422 m->scope != PRIVATE_SIGNAL_FIRST_METHOD)
426 marsh = g_hash_table_new(NULL,NULL);
428 if(strcmp(m->gtktypes->data,"NONE")==0 &&
429 strcmp(m->gtktypes->next->data,"NONE")==0)
432 s = g_strdup_printf("__Sig%d",sig++);
434 g_hash_table_insert(marsh,m,s);
436 out_printf(out,"\ntypedef ");
437 print_type(out,m->mtype);
439 out_printf(out,"(*%s) (",s);
441 for(li=m->args;li;li=g_list_next(li)) {
442 FuncArg *arg = li->data;
443 print_type(out,arg->atype);
444 out_printf(out,", ");
446 out_printf(out,"gpointer);\n");
448 out_printf(out,"\nstatic void\n"
449 "marshal_%s (GtkObject * object,\n"
450 "\tGtkSignalFunc func,\n"
451 "\tgpointer func_data,\n"
455 if(strcmp(m->gtktypes->data,"NONE")==0) {
457 out_printf(out, "\t%s rfunc;\n\n"
458 "\trfunc = (%s)func;\n\n"
459 "\t(*rfunc)((%s *)object",s,s,typebase);
460 if(strcmp(m->gtktypes->next->data,"NONE")!=0) {
461 GList *ali = m->args->next;
462 for(i=0,li=m->gtktypes->next;li;
463 i++,li=g_list_next(li)) {
465 out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
468 FuncArg *fa = ali->data;
469 out_printf(out, ",\n\t\t(");
470 print_type(out,fa->atype);
471 out_printf(out, ")GTK_VALUE_%s(args[%d])",
475 if(ali) ali = ali->next;
478 out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
481 out_printf(out, "\t%s rfunc;\n\t",s);
482 print_type(out,m->mtype);
483 out_printf(out, " *retval;\n\n"
484 "\trfunc = (%s)func;\n\n"
485 "\tretval = GTK_RETLOC_%s(args[%d]);\n\n"
486 "\t*retval = (*rfunc)((%s *)object",
487 s,(char *)m->gtktypes->data,
488 g_list_length(m->gtktypes)-1,typebase);
489 if(strcmp(m->gtktypes->next->data,"NONE")!=0) {
490 GList *ali = m->args->next;
491 for(i=0,li=m->gtktypes->next;li;
492 i++,li=g_list_next(li)) {
494 out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
497 FuncArg *fa = ali->data;
498 out_printf(out, ",\n\t\t(");
499 print_type(out,fa->atype);
500 out_printf(out, ")GTK_VALUE_%s(args[%d])",
504 if(ali) ali = ali->next;
507 out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
516 out_printf(out,"\n");
518 out_printf(out,"enum {\n");
519 for(li=c->nodes;li;li=g_list_next(li)) {
521 if(n->type == METHOD_NODE) {
522 Method *m = (Method *)n;
523 if(m->scope == SIGNAL_LAST_METHOD ||
524 m->scope == SIGNAL_FIRST_METHOD ||
525 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
526 m->scope == PRIVATE_SIGNAL_FIRST_METHOD) {
527 char *s = g_strdup(m->id);
529 out_printf(out,"\t%s_SIGNAL,\n",s);
534 out_printf(out,"\tLAST_SIGNAL\n};\n\n");
537 out_printf(out,"enum {\n\tARG_0,\n");
538 for(li=c->nodes;li;li=g_list_next(li)) {
540 if(n->type == ARGUMENT_NODE) {
541 Argument *a = (Argument *)n;
542 char *s = g_strdup(a->name);
544 out_printf(out,"\tARG_%s,\n",s);
548 out_printf(out, "};\n\n");
553 "static guint object_signals[LAST_SIGNAL] = {0};\n\n");
555 out_printf(out, "static %sClass *parent_class = NULL;\n\n",ptypebase);
561 out_printf(out, "guint\n"
562 "%s_get_type (void)\n"
564 "\tstatic guint type = 0;\n\n"
566 "\t\tstatic const GtkTypeInfo info = {\n"
568 "\t\t\tsizeof (%s),\n"
569 "\t\t\tsizeof (%sClass),\n"
570 "\t\t\t(GtkClassInitFunc) %s_class_init,\n"
571 "\t\t\t(GtkObjectInitFunc) %s_init,\n"
572 "\t\t\t/* reserved_1 */ NULL,\n"
573 "\t\t\t/* reserved_2 */ NULL,\n"
574 "\t\t\t(GtkClassInitFunc) NULL,\n"
576 "\t\ttype = gtk_type_unique (%s_get_type(), &info);\n"
580 funcbase,typebase,typebase,typebase,
581 funcbase,funcbase,pfuncbase);
585 add_overrides(Class *c, char *oname, gboolean did_gtk_obj)
591 done = g_hash_table_new(g_str_hash,g_str_equal);
593 s = g_strdup("GtkObject"); /* This was already done */
594 g_hash_table_insert(done,s,s);
596 for(li=c->nodes;li;li=g_list_next(li)) {
600 if(n->type != METHOD_NODE ||
601 ((Method *)n)->scope != OVERRIDE_METHOD)
605 s = remove_sep(m->otype);
607 if(g_hash_table_lookup(done,s)) {
611 g_hash_table_insert(done,s,s);
613 f = replace_sep(m->otype,'_');
616 out_printf(out,"\t%sClass *%s_class = (%sClass *)%s;\n",
621 g_hash_table_foreach(done,(GHFunc)g_free,NULL);
622 g_hash_table_destroy(done);
626 add_signals(Class *c)
630 out_printf(out,"\n");
631 for(li=c->nodes;li;li=g_list_next(li)) {
638 if(n->type != METHOD_NODE ||
639 (((Method *)n)->scope != SIGNAL_FIRST_METHOD &&
640 ((Method *)n)->scope != SIGNAL_LAST_METHOD &&
641 ((Method *)n)->scope != PRIVATE_SIGNAL_FIRST_METHOD &&
642 ((Method *)n)->scope != PRIVATE_SIGNAL_LAST_METHOD))
647 if(m->scope == SIGNAL_FIRST_METHOD ||
648 m->scope == PRIVATE_SIGNAL_FIRST_METHOD)
653 if(g_hash_table_lookup(marsh,m))
654 mar = g_strconcat("marshal_",
655 (char *)g_hash_table_lookup(marsh,m),
658 mar = g_strdup("gtk_signal_default_marshaller");
660 is_none = (strcmp(m->gtktypes->next->data,"NONE")==0);
662 sig = g_strdup(m->id);
664 out_printf(out,"\tobject_signals[%s_SIGNAL] =\n"
665 "\t\tgtk_signal_new (\"%s\",\n"
666 "\t\t\tGTK_RUN_%s,\n"
667 "\t\t\tgtk_object_class->type,\n"
668 "\t\t\tGTK_SIGNAL_OFFSET (%sClass, %s),\n"
670 "\t\t\tGTK_TYPE_%s, %d",
673 typebase,m->id,mar,(char *)m->gtktypes->data,
674 is_none?0:g_list_length(m->gtktypes->next));
680 for(l=m->gtktypes->next;l;l=g_list_next(l))
681 out_printf(out,",\n\t\t\tGTK_TYPE_%s",
685 out_printf(out,");\n");
687 out_printf(out,"\tgtk_object_class_add_signals (gtk_object_class,\n"
688 "\t\tobject_signals, LAST_SIGNAL);\n\n");
692 set_def_handlers(Class *c, char *oname)
696 out_printf(out,"\n");
697 for(li=c->nodes;li;li=g_list_next(li)) {
700 if(n->type != METHOD_NODE ||
701 (((Method *)n)->scope != SIGNAL_FIRST_METHOD &&
702 ((Method *)n)->scope != SIGNAL_LAST_METHOD &&
703 ((Method *)n)->scope != PRIVATE_SIGNAL_FIRST_METHOD &&
704 ((Method *)n)->scope != PRIVATE_SIGNAL_LAST_METHOD &&
705 ((Method *)n)->scope != VIRTUAL_METHOD &&
706 ((Method *)n)->scope != PRIVATE_VIRTUAL_METHOD &&
707 ((Method *)n)->scope != OVERRIDE_METHOD))
712 if(m->scope == OVERRIDE_METHOD) {
714 s = replace_sep(m->otype,'_');
716 out_printf(out,"\t%s_class->%s = %s_%s;\n",
717 s,m->id,funcbase,m->id);
720 out_printf(out,"\t%s->%s = _real_%s_%s;\n",
721 oname,m->id,funcbase,m->id);
723 out_printf(out,"\t%s->%s = NULL;\n",
730 make_arguments(Class *c)
734 out_printf(out,"\n");
735 for(li=c->nodes;li;li=g_list_next(li)) {
741 if(n->type != ARGUMENT_NODE)
747 flags = g_string_new("GTK_ARG_READWRITE");
749 flags = g_string_new("GTK_ARG_READABLE");
751 flags = g_string_new("GTK_ARG_WRITABLE");
753 for(l=a->flags;l;l=g_list_next(l))
754 g_string_sprintfa(flags," | GTK_ARG_%s",(char *)l->data);
756 s = g_strdup(a->name);
758 out_printf(out,"\tgtk_object_add_arg_type(\"%s::%s\",\n"
762 typebase,a->name,a->gtktype,flags->str,s);
764 g_string_free(flags,TRUE);
768 "\n\tgtk_object_class->set_arg = __object_set_arg;\n"
769 "\tgtk_object_class->get_arg = __object_get_arg;\n");
776 for(li=c->nodes;li;li=g_list_next(li)) {
779 if(n->type != METHOD_NODE)
782 if(m->scope == INIT_METHOD) {
784 out_addline_infile(out,m->line_no);
785 print_method(out,"static ","\n"," ","\n",m,FALSE);
787 out_addline_outfile(out);
788 out_printf(out,"{\n");
789 } else if(m->scope == CLASS_INIT_METHOD) {
791 out_addline_infile(out,m->line_no);
792 print_method(out,"static ","\n"," ","\n",m,FALSE);
794 out_addline_outfile(out);
795 out_printf(out,"{\n");
800 "gtk_object_class = "
801 "(GtkObjectClass*) %s;\n",
802 ((FuncArg *)m->args->data)->name);
806 ((FuncArg *)m->args->data)->name,
807 (signals>0 || arguments>0));
809 out_printf(out,"\n\tparent_class = ");
811 out_printf(out,"(%sClass *)",ptypebase);
812 out_printf(out,"gtk_type_class (%s_get_type ());\n",
818 set_def_handlers(c, ((FuncArg *)m->args->data)->name);
827 out_printf(out," {\n");
828 out_addline_infile(out,m->ccode_line);
829 out_printf(out,"%s\n",m->cbuf->str);
830 out_addline_outfile(out);
831 out_printf(out," }\n",m->cbuf->str);
833 out_printf(out,"return;\n");
835 out_printf(out,"}\n");
840 add_getset_arg(Class *c, int is_set)
843 out_printf(out,"\nstatic void\n"
844 "__object_%s_arg (GtkObject *object,\n"
849 "\tself = %s (object);\n\n"
850 "\tswitch (arg_id) {\n",
851 is_set?"set":"get",typebase,macrobase);
853 for(li=c->nodes;li;li=g_list_next(li)) {
859 if(n->type != ARGUMENT_NODE)
864 line_no = a->set_line;
867 line_no = a->get_line;
871 s = g_strdup(a->name);
873 out_printf(out,"\tcase ARG_%s:\n"
874 "#define ARG (GTK_VALUE_%s(*arg))\n"
878 out_addline_infile(out,line_no);
879 out_printf(out,"%s\n",cbuf->str);
880 out_addline_outfile(out);
881 out_printf(out,"\t\t}\n\t\tbreak;\n"
884 out_printf(out,"\tdefault:\n\t\tbreak;\n\t}\n}\n");
888 print_checks(Method *m, FuncArg *fa)
892 is_void = (strcmp(m->mtype->name,"void")==0 &&
893 m->mtype->stars == 0);
895 for(li=fa->checks;li;li=g_list_next(li)) {
896 Check *ch = li->data;
899 out_printf(out,"\tg_return_if_fail (");
901 out_printf(out,"\tg_return_val_if_fail (");
904 out_printf(out,"%s != NULL",fa->name);
907 s = make_pre_macro(fa->atype->name,"IS");
908 out_printf(out,"%s (%s)",s,fa->name);
912 out_printf(out,"%s < %s",fa->name,ch->number);
915 out_printf(out,"%s > %s",fa->name,ch->number);
918 out_printf(out,"%s <= %s",fa->name,ch->number);
921 out_printf(out,"%s >= %s",fa->name,ch->number);
924 out_printf(out,"%s == %s",fa->name,ch->number);
927 out_printf(out,"%s != %s",fa->name,ch->number);
931 out_printf(out,");\n");
933 out_printf(out,", (");
934 print_type(out,m->mtype);
935 out_printf(out,")%s);\n",
936 m->onerror?m->onerror:"0");
942 print_preconditions(Method *m)
946 for(li=m->args;li;li=g_list_next(li)) {
947 FuncArg *fa = li->data;
954 print_method_body(Method *m, int pre)
956 out_printf(out,"{\n");
958 print_preconditions(m);
959 out_printf(out,"\t{\n");
962 out_addline_infile(out,m->ccode_line);
963 out_printf(out,"\t\t%s\n",m->cbuf->str);
964 out_addline_outfile(out);
967 out_printf(out,"\t}\n");
968 out_printf(out,"}\n");
972 put_method(Method *m)
976 out_printf(out,"\n");
979 out_addline_infile(out,m->line_no);
980 print_method(out,"","\n"," ","\n",m,FALSE);
981 print_method_body(m,TRUE);
984 out_addline_infile(out,m->line_no);
985 print_method(out,"static ","\n"," ","\n",m,FALSE);
986 print_method_body(m,TRUE);
988 case PRIVATE_SIGNAL_FIRST_METHOD:
989 case PRIVATE_SIGNAL_LAST_METHOD:
991 case SIGNAL_FIRST_METHOD:
992 case SIGNAL_LAST_METHOD:
993 out_addline_infile(out,m->line_no);
994 print_method(out,private?"static ":"","\n"," ","\n",m,FALSE);
995 out_addline_outfile(out);
996 out_printf(out,"{\n");
999 if(strcmp(m->mtype->name,"void")==0 &&
1000 m->mtype->stars==0) {
1002 print_preconditions(m);
1003 if(((FuncArg *)m->args->data)->name)
1004 out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1005 "\t\tobject_signals[%s_SIGNAL]",
1006 ((FuncArg *)m->args->data)->name,s);
1007 for(li=m->args->next;li;li=g_list_next(li)) {
1008 FuncArg *fa = li->data;
1009 out_printf(out,",\n\t\t%s",fa->name);
1011 out_printf(out,");\n}\n");
1014 out_printf(out,"\t");
1015 print_type(out,m->mtype);
1016 out_printf(out,"return_val;\n");
1017 print_preconditions(m);
1018 out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1019 "\t\tobject_signals[%s_SIGNAL]",
1020 ((FuncArg *)m->args->data)->name,s);
1021 for(li=m->args->next;li;li=g_list_next(li)) {
1022 FuncArg *fa = li->data;
1023 out_printf(out,",\n\t\t%s",fa->name);
1025 out_printf(out,",\n\t\t&return_val);\n"
1026 "\treturn return_val;\n}\n");
1031 out_addline_infile(out,m->line_no);
1032 print_method(out,"static ","\n_real_"," ","\n",m,FALSE);
1033 print_method_body(m,FALSE);
1035 case PRIVATE_VIRTUAL_METHOD:
1037 case VIRTUAL_METHOD:
1038 out_addline_infile(out,m->line_no);
1039 print_method(out,private?"static ":"","\n"," ","\n",m,FALSE);
1040 out_addline_outfile(out);
1041 out_printf(out,"{\n"
1042 "\t%sClass *klass;\n",typebase);
1043 print_preconditions(m);
1044 out_printf(out,"\tklass = %s_CLASS(GTK_OBJECT(%s)->klass);\n\n"
1045 "\tif(klass->%s)\n",
1046 macrobase, ((FuncArg *)m->args->data)->name, m->id);
1047 if(strcmp(m->mtype->name,"void")==0 &&
1048 m->mtype->stars==0) {
1050 out_printf(out,"\t\t(*klass->%s)(%s",m->id,
1051 ((FuncArg *)m->args->data)->name);
1052 for(li=m->args->next;li;li=g_list_next(li)) {
1053 FuncArg *fa = li->data;
1054 out_printf(out,",%s",fa->name);
1056 out_printf(out,");\n}\n");
1059 out_printf(out,"\t\treturn (*klass->%s)(%s",m->id,
1060 ((FuncArg *)m->args->data)->name);
1061 for(li=m->args->next;li;li=g_list_next(li)) {
1062 FuncArg *fa = li->data;
1063 out_printf(out,",%s",fa->name);
1065 out_printf(out,");\n"
1068 print_type(out,m->mtype);
1069 out_printf(out,")(%s);\n}\n",
1070 m->onerror?m->onerror:"0");
1075 out_addline_infile(out,m->line_no);
1076 print_method(out,"static ","\n_real_"," ","\n",m,FALSE);
1077 print_method_body(m,FALSE);
1079 case OVERRIDE_METHOD:
1080 out_addline_infile(out,m->line_no);
1081 print_method(out,"static ","\n"," ","\n",m,FALSE);
1082 s = replace_sep(m->otype,'_');
1084 out_printf(out,"#define PARENT_HANDLER(args...) \\\n"
1085 "\t{ if(%s_CLASS(parent_class)->%s) \\\n"
1086 "\t\t(* %s_CLASS(parent_class)->%s)(##args); }\n",
1089 print_method_body(m,TRUE);
1090 out_printf(out,"#undef PARENT_HANDLER\n");
1098 check_duplicate(Class *c,Node *node,char *id, int line_no)
1101 for(l=c->nodes;l;l=g_list_next(l)) {
1106 if(n->type == METHOD_NODE) {
1107 Method *m = (Method *)n;
1109 nline_no = m->line_no;
1110 } else if(n->type == VARIABLE_NODE) {
1111 Variable *v = (Variable *)n;
1113 nline_no = v->line_no;
1117 line_no>=nline_no ||
1118 strcmp(nid,id)!=0 ||
1119 n->type != node->type)
1121 s = g_strdup_printf("symbol '%s' redefined, "
1122 "first defined on line %d",
1124 print_error(FALSE,s,nline_no);
1129 check_duplicate_symbols(Class *c)
1132 for(l=c->nodes;l;l=g_list_next(l)) {
1134 if(n->type == METHOD_NODE) {
1135 Method *m = (Method *)n;
1136 check_duplicate(c,n,m->id,m->line_no);
1137 } else if(n->type == VARIABLE_NODE) {
1138 Variable *v = (Variable *)n;
1139 check_duplicate(c,n,v->id,v->line_no);
1145 check_duplicate_named(Class *c,Node *node,char *id, int line_no)
1148 for(l=c->nodes;l;l=g_list_next(l)) {
1153 if(n->type == METHOD_NODE) {
1154 Method *m = (Method *)n;
1155 if(m->scope == SIGNAL_LAST_METHOD ||
1156 m->scope == SIGNAL_FIRST_METHOD ||
1157 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1158 m->scope == PRIVATE_SIGNAL_FIRST_METHOD) {
1160 nline_no = m->line_no;
1163 } else if(n->type == ARGUMENT_NODE) {
1164 Argument *a = (Argument *)n;
1166 nline_no = a->line_no;
1170 line_no>=nline_no ||
1173 s = g_strdup_printf("named symbol (argument or signal) '%s' "
1174 "redefined, first defined on line %d",
1176 print_error(FALSE,s,nline_no);
1181 check_duplicate_signals_args(Class *c)
1184 for(l=c->nodes;l;l=g_list_next(l)) {
1186 if(n->type == METHOD_NODE) {
1187 Method *m = (Method *)n;
1188 if(m->scope == SIGNAL_LAST_METHOD ||
1189 m->scope == SIGNAL_FIRST_METHOD ||
1190 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1191 m->scope == PRIVATE_SIGNAL_FIRST_METHOD)
1192 check_duplicate_named(c,n,m->id,m->line_no);
1193 } else if(n->type == ARGUMENT_NODE) {
1194 Argument *a = (Argument *)n;
1195 check_duplicate_named(c,n,a->name,a->line_no);
1201 check_public_new(Class *c)
1204 for(l=c->nodes;l;l=g_list_next(l)) {
1206 if(n->type == METHOD_NODE) {
1207 Method *m = (Method *)n;
1208 if(m->scope!=PUBLIC_SCOPE &&
1209 strcmp(m->id,"new")==0)
1211 "'new' should be a public method",
1218 check_vararg(Class *c)
1221 for(l=c->nodes;l;l=g_list_next(l)) {
1223 if(n->type == METHOD_NODE) {
1224 Method *m = (Method *)n;
1227 if(m->scope == OVERRIDE_METHOD ||
1228 m->scope == SIGNAL_LAST_METHOD ||
1229 m->scope == SIGNAL_FIRST_METHOD ||
1230 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1231 m->scope == PRIVATE_SIGNAL_FIRST_METHOD ||
1232 m->scope == VIRTUAL_METHOD ||
1233 m->scope == PRIVATE_VIRTUAL_METHOD) {
1235 "signals, overrides and virtuals, "
1236 "can't have variable argument "
1245 count_signals(Class *c)
1249 for(l=c->nodes;l;l=g_list_next(l)) {
1251 if(n->type == METHOD_NODE) {
1252 Method *m = (Method *)n;
1253 if(m->scope == SIGNAL_LAST_METHOD ||
1254 m->scope == SIGNAL_FIRST_METHOD ||
1255 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1256 m->scope == PRIVATE_SIGNAL_FIRST_METHOD)
1264 count_arguments(Class *c)
1269 for(li=c->nodes;li;li=g_list_next(li)) {
1271 if(n->type == ARGUMENT_NODE)
1278 count_overrides(Class *c)
1282 for(l=c->nodes;l;l=g_list_next(l)) {
1284 if(n->type == METHOD_NODE) {
1285 Method *m = (Method *)n;
1286 if(m->scope == OVERRIDE_METHOD)
1297 char *outfile,*outfileh;
1300 outfile = g_strconcat(filebase,".c",NULL);
1302 outfile = g_strconcat(filebase,".cc",NULL);
1303 if(no_touch_headers)
1304 outfileh = g_strconcat("#gob#",filebase,".h#gob#",NULL);
1306 outfileh = g_strconcat(filebase,".h",NULL);
1308 out = fopen(outfile,"w");
1310 g_error("Cannot open outfile: %s",outfile);
1312 outh = fopen(outfileh,"w");
1314 g_error("Cannot open outfile: %s",outfileh);
1319 generate_outfiles(void)
1326 out_printf(outh,"/* Generated by GOB (v%s)"
1327 " (do not edit directly) */\n\n",VERSION);
1328 out_printf(out,"/* Generated by GOB (v%s) on %s"
1329 " (do not edit directly) */\n\n",VERSION,ctime(&curtime));
1331 p = replace_sep(((Class *)class)->otype,'_');
1333 out_printf(outh,"#ifndef __%s_H__\n#define __%s_H__\n\n"
1334 "#include <gtk/gtk.h>\n\n",p,p);
1338 out_printf(outh,"#ifdef __cplusplus\n"
1340 "#endif /* __cplusplus */\n\n");
1342 out_printf(out,"#include \"%s.h\"\n\n",filebase);
1344 for(li=nodes;li;li=g_list_next(li)) {
1345 Node *node = li->data;
1346 if(node->type == CCODE_NODE) {
1347 CCode *cc = (CCode *)node;
1351 out_printf(fp,"\n");
1354 out_printf(fp,"\n");
1355 out_addline_infile(fp,cc->line_no);
1357 out_printf(fp,"%s\n",cc->cbuf->str);
1359 out_addline_outfile(fp);
1360 } else if(node->type == CLASS_NODE) {
1362 Class *c = (Class *)class;
1365 signals = count_signals(c);
1366 arguments = count_arguments(c);
1367 overrides = count_overrides(c);
1369 out_printf(outh,"\n#define %s\t"
1370 "(%s_get_type())\n",
1371 macrotype,funcbase);
1372 out_printf(outh,"#define %s(obj)\t"
1373 "GTK_CHECK_CAST((obj),%s_get_type(),%s)\n",
1374 macrobase,funcbase,typebase);
1375 out_printf(outh,"#define %s_CLASS(klass)\t"
1376 "GTK_CHECK_CLASS_CAST((klass),%s_get_type(),%sClass)\n",
1377 macrobase,funcbase,typebase);
1378 out_printf(outh,"#define %s(obj)\t"
1379 "GTK_CHECK_TYPE((obj), %s_get_type ())\n\n",
1382 otype = remove_sep(c->otype);
1383 ptype = remove_sep(c->ptype);
1384 out_printf(outh,"\ntypedef struct _%s %s;\n",otype,otype);
1385 out_printf(outh,"struct _%s {\n\t%s __parent__;\n",
1387 for(l=c->nodes;l;l=g_list_next(l)) {
1389 if(n->type == VARIABLE_NODE)
1390 put_variable((Variable *)n);
1392 out_printf(outh,"};\n");
1394 out_printf(outh,"\ntypedef struct _%sClass %sClass;\n",
1397 "struct _%sClass {\n\t%sClass __parent__;\n",
1399 for(l=c->nodes;l;l=g_list_next(l)) {
1401 if(n->type == METHOD_NODE)
1402 put_vs_method((Method *)n);
1404 out_printf(outh,"};\n\n");
1406 out_printf(outh,"guint\t%s_get_type\t(void);\n",funcbase);
1409 out_printf(out,"static void __object_set_arg "
1410 "(GtkObject *object, GtkArg *arg, "
1412 "static void __object_get_arg "
1413 "(GtkObject *object, GtkArg *arg, "
1414 "guint arg_id);\n");
1417 for(l=c->nodes;l;l=g_list_next(l)) {
1419 if(n->type == METHOD_NODE) {
1420 put_pub_method((Method *)n);
1421 put_priv_method_prot((Method *)n);
1426 for(l=c->nodes;l;l=g_list_next(l)) {
1428 if(n->type == METHOD_NODE) {
1429 add_signal_prots((Method *)n);
1438 make_method_pointers(c);
1440 out_printf(out,"#define GET_NEW (gtk_type_new(%s_get_type()))\n",
1446 add_getset_arg(c, TRUE);
1447 add_getset_arg(c, FALSE);
1450 for(l=c->nodes;l;l=g_list_next(l)) {
1452 if(n->type == METHOD_NODE) {
1453 put_method((Method *)n);
1457 out_printf(out,"#undef GET_NEW\n");
1459 add_bad_hack_to_avoid_unused_warnings(c);
1464 g_assert_not_reached();
1468 out_printf(outh,"\n#ifdef __cplusplus\n"
1470 "#endif /* __cplusplus */\n");
1471 out_printf(outh,"\n#endif");
1476 usage(poptContext optCon, int exitcode, char *error, char *addl)
1478 poptPrintUsage(optCon, stderr, 0);
1479 if (error) fprintf(stderr, "%s: %s", error, addl);
1487 fprintf(stderr,"Gob version %s\n\n",VERSION);
1488 fprintf(stderr,"Options:\n"
1489 "\t--help,-h,-? Display this help\n"
1490 "\t--exit-on-warn,-w Exit with an error on warnings\n"
1491 "\t--no-exit-on-warn Don't exit on warnings [default]\n"
1492 "\t--for-cpp Create C++ files\n"
1493 "\t--no-touch-headers Don't touch headers unless they "
1494 "really changed\n");
1498 parse_options(int argc, char *argv[])
1501 int got_file = FALSE;
1502 int no_opts = FALSE;
1506 for(i=1;i<argc;i++) {
1507 if(no_opts || argv[i][0]!='-') {
1510 fprintf(stderr,"Specify only one file!\n");
1516 } else if(strcmp(argv[i],"--help")==0) {
1519 } else if(strcmp(argv[i],"--exit-on-warn")==0) {
1520 exit_on_warn = TRUE;
1521 } else if(strcmp(argv[i],"--no-exit-on-warn")==0) {
1522 exit_on_warn = FALSE;
1523 } else if(strcmp(argv[i],"--for-cpp")==0) {
1525 } else if(strcmp(argv[i],"--no-touch-headers")==0) {
1526 no_touch_headers = TRUE;
1527 } else if(strcmp(argv[i],"--")==0) {
1528 /*further arguments are files*/
1530 } else if(strncmp(argv[i],"--",2)==0) {
1531 /*unknown long option*/
1532 fprintf(stderr,"Unknown option '%s'!\n",argv[i]);
1536 /*by now we know we have a string starting with
1537 - which is a short option string*/
1538 char *p = argv[i]+1;
1539 for(p=argv[i]+1;*p;p++) {
1550 "Unknown option '%c'!\n",*p);
1560 compare_and_move_header(void)
1562 char *hfnew = g_strconcat("#gob#",filebase,".h#gob#",NULL);
1563 char *hf = g_strconcat(filebase,".h",NULL);
1565 if(stat(hf,&s)==0) {
1567 s = g_strdup_printf("cmp '%s' '%s' > /dev/null",hf,hfnew);
1569 if(unlink(hfnew)!=0)
1570 print_error(FALSE,"Can't remove new header file",0);
1578 print_error(FALSE,"Can't remove old header file",0);
1580 if(rename(hfnew,hf)!=0)
1581 print_error(FALSE,"Can't rename new header file",0);
1587 main(int argc, char *argv[])
1593 struct poptOption optionsTable[] = {
1594 { "exit-on-warn", 'w', 0, &exit_on_warn, 0,
1595 "exit on warnings" },
1597 { NULL, 0, 0, NULL, 0 }
1600 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
1601 poptSetOtherOptionHelp(optCon, "[OPTIONS]* [filename]");
1603 while ((c = poptGetNextOpt(optCon)) >= 0)
1606 filename = poptGetArg(optCon);
1607 if(!(poptPeekArg(optCon) == NULL))
1608 usage(optCon, 1, "Specify only one file",
1609 ".e.g., filename.gob");
1612 /* an error occurred during option processing */
1613 fprintf(stderr, "%s: %s\n",
1614 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
1620 parse_options(argc,argv);
1623 yyin = fopen(filename,"r");
1625 fprintf(stderr,"Error: can't open file '%s'\n",
1634 g_error("Parsing errors, quitting");
1636 print_error(FALSE," no class defined",0);
1640 exit_on_error = FALSE;
1641 make_inits((Class *)class);
1642 check_duplicate_symbols((Class *)class);
1643 check_duplicate_signals_args((Class *)class);
1644 check_public_new((Class *)class);
1645 check_vararg((Class *)class);
1646 exit_on_error = TRUE;
1653 generate_outfiles();
1658 if(no_touch_headers)
1659 compare_and_move_header();
1662 poptFreeContext(optCon);