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 *typebase;
53 static char *ptypebase;
55 static int signals = 0;
56 static int arguments = 0;
57 static int overrides = 0;
62 gboolean no_touch_headers = FALSE;
63 gboolean for_cpp = FALSE;
64 gboolean exit_on_warn = FALSE;
65 gboolean exit_on_error = TRUE;
66 gboolean got_error = FALSE;
69 print_error(int is_warn, char *error,int line)
79 fprintf(stderr,"%s:%d: %s %s\n",filename,line,w,error);
81 fprintf(stderr,"%s: %s %s\n",filename,w,error);
82 if((!is_warn || exit_on_warn) && exit_on_error)
87 remove_sep(char *base)
90 char *s = g_strdup(base);
91 while((p=strchr(s,':')))
97 replace_sep(char *base, char r)
100 char *s = g_strdup(base);
101 while((p=strchr(s,':')))
111 /*separate the namespace part and then replace rest of
114 separns_replace_sep(char *base, char **ns, char **name, char r)
117 char *s = g_strdup(base);
119 if((p=strchr(s,':')) && p!=s) {
126 while((p=strchr(s,':')))
129 *name = g_strdup(s+1);
136 make_is_macro(char *base)
141 separns_replace_sep(base,&s1,&s2,'_');
143 s = g_strconcat(s1,"_IS_",s2,NULL);
145 s = g_strconcat("IS_",s2,NULL);
158 filebase = replace_sep(((Class *)class)->otype,'-');
161 funcbase = replace_sep(((Class *)class)->otype,'_');
164 pfuncbase = replace_sep(((Class *)class)->ptype,'_');
165 g_strdown(pfuncbase);
167 macrobase = replace_sep(((Class *)class)->otype,'_');
170 macrois = make_is_macro(((Class *)class)->otype);
172 typebase = remove_sep(((Class *)class)->otype);
174 ptypebase = remove_sep(((Class *)class)->ptype);
178 print_type(FILE *fp, Type *t)
182 s = remove_sep(t->name);
183 out_printf(fp,"%s ",s);
186 for(i=0;i<t->stars;i++)
191 print_method(FILE *fp, char *typeprefix, char *nameprefix,
192 char *namepostfix,char *postfix, Method *m,
193 gboolean no_funcbase)
197 out_printf(fp,"%s",typeprefix);
198 print_type(fp,m->mtype);
200 out_printf(fp,"%s%s%s(",
201 nameprefix,m->id,namepostfix);
203 out_printf(fp,"%s%s_%s%s(",
204 nameprefix,funcbase,m->id,namepostfix);
207 for(li=m->args;li;li=g_list_next(li)) {
208 FuncArg *arg = li->data;
209 print_type(fp,arg->atype);
211 out_printf(fp,"%s, ",arg->name);
213 out_printf(fp,"%s",arg->name);
217 out_printf(fp,", ...");
219 out_printf(fp,"void");
221 out_printf(fp,")%s",postfix);
226 make_method_pointers(Class *c)
230 out_printf(out,"\n");
231 for(li=c->nodes;li;li=g_list_next(li)) {
232 Node *node = li->data;
233 if(node->type == METHOD_NODE) {
234 Method *m = (Method *)node;
236 if(m->scope == INIT_METHOD ||
237 m->scope == CLASS_INIT_METHOD ||
238 m->scope == OVERRIDE_METHOD)
241 /* in C++ mode don't alias new */
242 if(for_cpp && strcmp(m->id,"new")==0)
245 print_method(out,"static ","(* ",") ","",m,TRUE);
246 out_printf(out," = %s_%s;\n",funcbase,m->id);
249 out_printf(out,"\n");
253 add_bad_hack_to_avoid_unused_warnings(Class *c)
257 out_printf(out,"\n\n/*REALLY BAD HACK\n"
258 " This is to avoid unused warnings if you don't call\n"
259 " some method, it pollutes the namespace but the call\n"
260 " is weird enough. I need to find a better way to do\n"
262 out_printf(out,"void __%s_really_bad_hack_to_avoid_warnings(void);\n",
264 out_printf(out,"void\n__%s_really_bad_hack_to_avoid_warnings(void)\n"
266 for(li=c->nodes;li;li=g_list_next(li)) {
267 Node *node = li->data;
268 if(node->type == METHOD_NODE) {
269 Method *m = (Method *)node;
271 if(m->scope == INIT_METHOD ||
272 m->scope == CLASS_INIT_METHOD ||
273 m->scope == OVERRIDE_METHOD)
276 /* in C++ mode we don't alias new */
277 if(for_cpp && strcmp(m->id,"new")==0)
280 out_printf(out,"\t((void (*)(void))%s)();\n",m->id);
283 out_printf(out,"}\n\n");
287 put_variable(Variable *v)
289 out_printf(outh,"\t");
290 if(v->scope == PRIVATE_SCOPE)
291 out_printf(outh,"/* private */ ");
292 print_type(outh,v->vtype);
294 out_printf(outh,"%s;\n",v->id);
298 put_vs_method(Method *m)
300 if(m->scope != SIGNAL_LAST_METHOD &&
301 m->scope != SIGNAL_FIRST_METHOD &&
302 m->scope != PRIVATE_SIGNAL_LAST_METHOD &&
303 m->scope != PRIVATE_SIGNAL_FIRST_METHOD &&
304 m->scope != VIRTUAL_METHOD &&
305 m->scope != PRIVATE_VIRTUAL_METHOD)
308 print_method(outh,"\t","(* ",") ",";\n",m,TRUE);
312 put_pub_method(Method *m)
314 if(m->scope == PRIVATE_SCOPE ||
315 m->scope == OVERRIDE_METHOD ||
316 m->scope == INIT_METHOD ||
317 m->scope == CLASS_INIT_METHOD ||
318 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
319 m->scope == PRIVATE_SIGNAL_FIRST_METHOD ||
320 m->scope == PRIVATE_VIRTUAL_METHOD)
323 print_method(outh,"","\t","\t",";\n",m,FALSE);
327 put_priv_method_prot(Method *m)
329 if(m->scope == PUBLIC_SCOPE)
332 if(m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
333 m->scope == PRIVATE_SIGNAL_FIRST_METHOD ||
334 m->scope == PRIVATE_VIRTUAL_METHOD) {
336 print_method(out,"static ","_real_"," ",";\n",m,FALSE);
337 print_method(out,"static ",""," ",";\n",m,FALSE);
338 } else if(m->scope == SIGNAL_LAST_METHOD ||
339 m->scope == SIGNAL_FIRST_METHOD ||
340 m->scope == VIRTUAL_METHOD) {
343 print_method(out,"static ","_real_"," ",";\n",m,FALSE);
345 print_method(out,"static ",""," ",";\n",m,FALSE);
350 make_init_args(Class *cl, char *name, int is_class)
357 tn = g_strconcat(cl->otype,":Class",NULL);
359 tn = g_strdup(cl->otype);
361 type = new_type(1,tn);
362 node = new_funcarg((Type *)type,name,NULL);
363 return g_list_prepend(NULL, node);
367 make_inits(Class *cl)
369 int got_class_init = FALSE;
370 int got_init = FALSE;
373 for(li=cl->nodes;li;li=g_list_next(li)) {
375 if(n->type == METHOD_NODE) {
376 Method *m = (Method *)n;
377 if(m->scope == INIT_METHOD) {
379 print_error(FALSE,"init defined more then once",m->line_no);
381 } else if(m->scope == CLASS_INIT_METHOD) {
383 print_error(FALSE,"class_init defined more then once",m->line_no);
384 got_class_init = TRUE;
388 if(!got_class_init) {
389 node = new_method(CLASS_INIT_METHOD,
390 (Type *)new_type(0,g_strdup("void")),
391 NULL,NULL,g_strdup("class_init"),
392 make_init_args(cl,g_strdup("c"),TRUE),
393 NULL, NULL,0,0,FALSE);
394 cl->nodes = g_list_prepend(cl->nodes,node);
397 node = new_method(INIT_METHOD,
398 (Type *)new_type(0,g_strdup("void")),
399 NULL,NULL,g_strdup("init"),
400 make_init_args(cl,g_strdup("o"),FALSE),
401 NULL, NULL,0,0,FALSE);
402 cl->nodes = g_list_prepend(cl->nodes,node);
406 static GHashTable *marsh = NULL;
409 add_signal_prots(Method *m)
415 if(m->scope != SIGNAL_LAST_METHOD &&
416 m->scope != SIGNAL_FIRST_METHOD &&
417 m->scope != PRIVATE_SIGNAL_LAST_METHOD &&
418 m->scope != PRIVATE_SIGNAL_FIRST_METHOD)
422 marsh = g_hash_table_new(NULL,NULL);
424 if(strcmp(m->gtktypes->data,"NONE")==0 &&
425 strcmp(m->gtktypes->next->data,"NONE")==0)
428 s = g_strdup_printf("__Sig%d",sig++);
430 g_hash_table_insert(marsh,m,s);
432 out_printf(out,"\ntypedef ");
433 print_type(out,m->mtype);
435 out_printf(out,"(*%s) (",s);
437 for(li=m->args;li;li=g_list_next(li)) {
438 FuncArg *arg = li->data;
439 print_type(out,arg->atype);
440 out_printf(out,", ");
442 out_printf(out,"gpointer);\n");
444 out_printf(out,"\nstatic void\n"
445 "marshal_%s (GtkObject * object,\n"
446 "\tGtkSignalFunc func,\n"
447 "\tgpointer func_data,\n"
451 if(strcmp(m->gtktypes->data,"NONE")==0) {
453 out_printf(out, "\t%s rfunc;\n\n"
454 "\trfunc = (%s)func;\n\n"
455 "\t(*rfunc)((%s *)object",s,s,typebase);
456 if(strcmp(m->gtktypes->next->data,"NONE")!=0) {
457 GList *ali = m->args->next;
458 for(i=0,li=m->gtktypes->next;li;
459 i++,li=g_list_next(li)) {
461 out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
464 FuncArg *fa = ali->data;
465 out_printf(out, ",\n\t\t(");
466 print_type(out,fa->atype);
467 out_printf(out, ")GTK_VALUE_%s(args[%d])",
471 if(ali) ali = ali->next;
474 out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
477 out_printf(out, "\t%s rfunc;\n\t",s);
478 print_type(out,m->mtype);
479 out_printf(out, " *retval;\n\n"
480 "\trfunc = (%s)func;\n\n"
481 "\tretval = GTK_RETLOC_%s(args[%d]);\n\n"
482 "\t*retval = (*rfunc)((%s *)object",
483 s,(char *)m->gtktypes->data,
484 g_list_length(m->gtktypes)-1,typebase);
485 if(strcmp(m->gtktypes->next->data,"NONE")!=0) {
486 GList *ali = m->args->next;
487 for(i=0,li=m->gtktypes->next;li;
488 i++,li=g_list_next(li)) {
490 out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
493 FuncArg *fa = ali->data;
494 out_printf(out, ",\n\t\t(");
495 print_type(out,fa->atype);
496 out_printf(out, ")GTK_VALUE_%s(args[%d])",
500 if(ali) ali = ali->next;
503 out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
512 out_printf(out,"\n");
514 out_printf(out,"enum {\n");
515 for(li=c->nodes;li;li=g_list_next(li)) {
517 if(n->type == METHOD_NODE) {
518 Method *m = (Method *)n;
519 if(m->scope == SIGNAL_LAST_METHOD ||
520 m->scope == SIGNAL_FIRST_METHOD ||
521 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
522 m->scope == PRIVATE_SIGNAL_FIRST_METHOD) {
523 char *s = g_strdup(m->id);
525 out_printf(out,"\t%s_SIGNAL,\n",s);
530 out_printf(out,"\tLAST_SIGNAL\n};\n\n");
533 out_printf(out,"enum {\n\tARG_0,\n");
534 for(li=c->nodes;li;li=g_list_next(li)) {
536 if(n->type == ARGUMENT_NODE) {
537 Argument *a = (Argument *)n;
538 char *s = g_strdup(a->name);
540 out_printf(out,"\tARG_%s,\n",s);
544 out_printf(out, "};\n\n");
549 "static guint object_signals[LAST_SIGNAL] = {0};\n\n");
551 out_printf(out, "static %sClass *parent_class = NULL;\n\n",ptypebase);
557 out_printf(out, "guint\n"
558 "%s_get_type (void)\n"
560 "\tstatic guint type = 0;\n\n"
562 "\t\tstatic const GtkTypeInfo info = {\n"
564 "\t\t\tsizeof (%s),\n"
565 "\t\t\tsizeof (%sClass),\n"
566 "\t\t\t(GtkClassInitFunc) %s_class_init,\n"
567 "\t\t\t(GtkObjectInitFunc) %s_init,\n"
568 "\t\t\t/* reserved_1 */ NULL,\n"
569 "\t\t\t/* reserved_2 */ NULL,\n"
570 "\t\t\t(GtkClassInitFunc) NULL,\n"
572 "\t\ttype = gtk_type_unique (%s_get_type(), &info);\n"
576 funcbase,typebase,typebase,typebase,
577 funcbase,funcbase,pfuncbase);
581 add_overrides(Class *c, char *oname, gboolean did_gtk_obj)
587 done = g_hash_table_new(g_str_hash,g_str_equal);
589 s = g_strdup("GtkObject"); /* This was already done */
590 g_hash_table_insert(done,s,s);
592 for(li=c->nodes;li;li=g_list_next(li)) {
596 if(n->type != METHOD_NODE ||
597 ((Method *)n)->scope != OVERRIDE_METHOD)
601 s = remove_sep(m->otype);
603 if(g_hash_table_lookup(done,s)) {
607 g_hash_table_insert(done,s,s);
609 f = replace_sep(m->otype,'_');
612 out_printf(out,"\t%sClass *%s_class = (%sClass *)%s;\n",
617 g_hash_table_foreach(done,(GHFunc)g_free,NULL);
618 g_hash_table_destroy(done);
622 add_signals(Class *c)
626 out_printf(out,"\n");
627 for(li=c->nodes;li;li=g_list_next(li)) {
634 if(n->type != METHOD_NODE ||
635 (((Method *)n)->scope != SIGNAL_FIRST_METHOD &&
636 ((Method *)n)->scope != SIGNAL_LAST_METHOD &&
637 ((Method *)n)->scope != PRIVATE_SIGNAL_FIRST_METHOD &&
638 ((Method *)n)->scope != PRIVATE_SIGNAL_LAST_METHOD))
643 if(m->scope == SIGNAL_FIRST_METHOD ||
644 m->scope == PRIVATE_SIGNAL_FIRST_METHOD)
649 if(g_hash_table_lookup(marsh,m))
650 mar = g_strconcat("marshal_",
651 (char *)g_hash_table_lookup(marsh,m),
654 mar = g_strdup("gtk_signal_default_marshaller");
656 is_none = (strcmp(m->gtktypes->next->data,"NONE")==0);
658 sig = g_strdup(m->id);
660 out_printf(out,"\tobject_signals[%s_SIGNAL] =\n"
661 "\t\tgtk_signal_new (\"%s\",\n"
662 "\t\t\tGTK_RUN_%s,\n"
663 "\t\t\tgtk_object_class->type,\n"
664 "\t\t\tGTK_SIGNAL_OFFSET (%sClass, %s),\n"
666 "\t\t\tGTK_TYPE_%s, %d",
669 typebase,m->id,mar,(char *)m->gtktypes->data,
670 is_none?0:g_list_length(m->gtktypes->next));
676 for(l=m->gtktypes->next;l;l=g_list_next(l))
677 out_printf(out,",\n\t\t\tGTK_TYPE_%s",
681 out_printf(out,");\n");
683 out_printf(out,"\tgtk_object_class_add_signals (gtk_object_class,\n"
684 "\t\tobject_signals, LAST_SIGNAL);\n\n");
688 set_def_handlers(Class *c, char *oname)
692 out_printf(out,"\n");
693 for(li=c->nodes;li;li=g_list_next(li)) {
696 if(n->type != METHOD_NODE ||
697 (((Method *)n)->scope != SIGNAL_FIRST_METHOD &&
698 ((Method *)n)->scope != SIGNAL_LAST_METHOD &&
699 ((Method *)n)->scope != PRIVATE_SIGNAL_FIRST_METHOD &&
700 ((Method *)n)->scope != PRIVATE_SIGNAL_LAST_METHOD &&
701 ((Method *)n)->scope != VIRTUAL_METHOD &&
702 ((Method *)n)->scope != PRIVATE_VIRTUAL_METHOD &&
703 ((Method *)n)->scope != OVERRIDE_METHOD))
708 if(m->scope == OVERRIDE_METHOD) {
710 s = replace_sep(m->otype,'_');
712 out_printf(out,"\t%s_class->%s = %s_%s;\n",
713 s,m->id,funcbase,m->id);
716 out_printf(out,"\t%s->%s = _real_%s_%s;\n",
717 oname,m->id,funcbase,m->id);
719 out_printf(out,"\t%s->%s = NULL;\n",
726 make_arguments(Class *c)
730 out_printf(out,"\n");
731 for(li=c->nodes;li;li=g_list_next(li)) {
737 if(n->type != ARGUMENT_NODE)
743 flags = g_string_new("GTK_ARG_READWRITE");
745 flags = g_string_new("GTK_ARG_READABLE");
747 flags = g_string_new("GTK_ARG_WRITABLE");
749 for(l=a->flags;l;l=g_list_next(l))
750 g_string_sprintfa(flags," | GTK_ARG_%s",(char *)l->data);
752 s = g_strdup(a->name);
754 out_printf(out,"\tgtk_object_add_arg_type(\"%s::%s\",\n"
758 typebase,a->name,a->gtktype,flags->str,s);
760 g_string_free(flags,TRUE);
764 "\n\tgtk_object_class->set_arg = __object_set_arg;\n"
765 "\tgtk_object_class->get_arg = __object_get_arg;\n");
772 for(li=c->nodes;li;li=g_list_next(li)) {
775 if(n->type != METHOD_NODE)
778 if(m->scope == INIT_METHOD) {
780 out_addline_infile(out,m->line_no);
781 print_method(out,"static ","\n"," ","\n",m,FALSE);
783 out_addline_outfile(out);
784 out_printf(out,"{\n");
785 } else if(m->scope == CLASS_INIT_METHOD) {
787 out_addline_infile(out,m->line_no);
788 print_method(out,"static ","\n"," ","\n",m,FALSE);
790 out_addline_outfile(out);
791 out_printf(out,"{\n");
796 "gtk_object_class = "
797 "(GtkObjectClass*) %s;\n",
798 ((FuncArg *)m->args->data)->name);
802 ((FuncArg *)m->args->data)->name,
803 (signals>0 || arguments>0));
805 out_printf(out,"\n\tparent_class = ");
807 out_printf(out,"(%sClass *)",ptypebase);
808 out_printf(out,"gtk_type_class (%s_get_type ());\n",
814 set_def_handlers(c, ((FuncArg *)m->args->data)->name);
823 out_printf(out," {\n");
824 out_addline_infile(out,m->ccode_line);
825 out_printf(out,"%s\n",m->cbuf->str);
826 out_addline_outfile(out);
827 out_printf(out," }\n",m->cbuf->str);
829 out_printf(out,"return;\n");
831 out_printf(out,"}\n");
836 add_getset_arg(Class *c, int is_set)
839 out_printf(out,"\nstatic void\n"
840 "__object_%s_arg (GtkObject *object,\n"
845 "\tself = %s (object);\n\n"
846 "\tswitch (arg_id) {\n",
847 is_set?"set":"get",typebase,macrobase);
849 for(li=c->nodes;li;li=g_list_next(li)) {
855 if(n->type != ARGUMENT_NODE)
860 line_no = a->set_line;
863 line_no = a->get_line;
867 s = g_strdup(a->name);
869 out_printf(out,"\tcase ARG_%s:\n"
870 "#define ARG (GTK_VALUE_%s(*arg))\n"
874 out_addline_infile(out,line_no);
875 out_printf(out,"%s\n",cbuf->str);
876 out_addline_outfile(out);
877 out_printf(out,"\t\t}\n\t\tbreak;\n"
880 out_printf(out,"\tdefault:\n\t\tbreak;\n\t}\n}\n");
884 print_checks(Method *m, FuncArg *fa)
888 is_void = (strcmp(m->mtype->name,"void")==0 &&
889 m->mtype->stars == 0);
891 for(li=fa->checks;li;li=g_list_next(li)) {
892 Check *ch = li->data;
895 out_printf(out,"\tg_return_if_fail (");
897 out_printf(out,"\tg_return_val_if_fail (");
900 out_printf(out,"%s != NULL",fa->name);
903 s = make_is_macro(fa->atype->name);
904 out_printf(out,"%s (%s)",s,fa->name);
908 out_printf(out,"%s < %s",fa->name,ch->number);
911 out_printf(out,"%s > %s",fa->name,ch->number);
914 out_printf(out,"%s <= %s",fa->name,ch->number);
917 out_printf(out,"%s >= %s",fa->name,ch->number);
920 out_printf(out,"%s == %s",fa->name,ch->number);
923 out_printf(out,"%s != %s",fa->name,ch->number);
927 out_printf(out,");\n");
929 out_printf(out,", (");
930 print_type(out,m->mtype);
931 out_printf(out,")%s);\n",
932 m->onerror?m->onerror:"0");
938 print_preconditions(Method *m)
942 for(li=m->args;li;li=g_list_next(li)) {
943 FuncArg *fa = li->data;
950 print_method_body(Method *m, int pre)
952 out_printf(out,"{\n");
954 print_preconditions(m);
955 out_printf(out,"\t{\n");
958 out_addline_infile(out,m->ccode_line);
959 out_printf(out,"\t\t%s\n",m->cbuf->str);
960 out_addline_outfile(out);
963 out_printf(out,"\t}\n");
964 out_printf(out,"}\n");
968 put_method(Method *m)
972 out_printf(out,"\n");
975 out_addline_infile(out,m->line_no);
976 print_method(out,"","\n"," ","\n",m,FALSE);
977 print_method_body(m,TRUE);
980 out_addline_infile(out,m->line_no);
981 print_method(out,"static ","\n"," ","\n",m,FALSE);
982 print_method_body(m,TRUE);
984 case PRIVATE_SIGNAL_FIRST_METHOD:
985 case PRIVATE_SIGNAL_LAST_METHOD:
987 case SIGNAL_FIRST_METHOD:
988 case SIGNAL_LAST_METHOD:
989 out_addline_infile(out,m->line_no);
990 print_method(out,private?"static ":"","\n"," ","\n",m,FALSE);
991 out_addline_outfile(out);
992 out_printf(out,"{\n");
995 if(strcmp(m->mtype->name,"void")==0 &&
996 m->mtype->stars==0) {
998 print_preconditions(m);
999 if(((FuncArg *)m->args->data)->name)
1000 out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1001 "\t\tobject_signals[%s_SIGNAL]",
1002 ((FuncArg *)m->args->data)->name,s);
1003 for(li=m->args->next;li;li=g_list_next(li)) {
1004 FuncArg *fa = li->data;
1005 out_printf(out,",\n\t\t%s",fa->name);
1007 out_printf(out,");\n}\n");
1010 out_printf(out,"\t");
1011 print_type(out,m->mtype);
1012 out_printf(out,"return_val;\n");
1013 print_preconditions(m);
1014 out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1015 "\t\tobject_signals[%s_SIGNAL]",
1016 ((FuncArg *)m->args->data)->name,s);
1017 for(li=m->args->next;li;li=g_list_next(li)) {
1018 FuncArg *fa = li->data;
1019 out_printf(out,",\n\t\t%s",fa->name);
1021 out_printf(out,",\n\t\t&return_val);\n"
1022 "\treturn return_val;\n}\n");
1027 out_addline_infile(out,m->line_no);
1028 print_method(out,"static ","\n_real_"," ","\n",m,FALSE);
1029 print_method_body(m,FALSE);
1031 case PRIVATE_VIRTUAL_METHOD:
1033 case VIRTUAL_METHOD:
1034 out_addline_infile(out,m->line_no);
1035 print_method(out,private?"static ":"","\n"," ","\n",m,FALSE);
1036 out_addline_outfile(out);
1037 out_printf(out,"{\n"
1038 "\t%sClass *klass;\n",typebase);
1039 print_preconditions(m);
1040 out_printf(out,"\tklass = %s_CLASS(GTK_OBJECT(%s)->klass);\n\n"
1041 "\tif(klass->%s)\n",
1042 macrobase, ((FuncArg *)m->args->data)->name, m->id);
1043 if(strcmp(m->mtype->name,"void")==0 &&
1044 m->mtype->stars==0) {
1046 out_printf(out,"\t\t(*klass->%s)(%s",m->id,
1047 ((FuncArg *)m->args->data)->name);
1048 for(li=m->args->next;li;li=g_list_next(li)) {
1049 FuncArg *fa = li->data;
1050 out_printf(out,",%s",fa->name);
1052 out_printf(out,");\n}\n");
1055 out_printf(out,"\t\treturn (*klass->%s)(%s",m->id,
1056 ((FuncArg *)m->args->data)->name);
1057 for(li=m->args->next;li;li=g_list_next(li)) {
1058 FuncArg *fa = li->data;
1059 out_printf(out,",%s",fa->name);
1061 out_printf(out,");\n"
1064 print_type(out,m->mtype);
1065 out_printf(out,")(%s);\n}\n",
1066 m->onerror?m->onerror:"0");
1071 out_addline_infile(out,m->line_no);
1072 print_method(out,"static ","\n_real_"," ","\n",m,FALSE);
1073 print_method_body(m,FALSE);
1075 case OVERRIDE_METHOD:
1076 out_addline_infile(out,m->line_no);
1077 print_method(out,"static ","\n"," ","\n",m,FALSE);
1078 print_method_body(m,TRUE);
1086 check_duplicate(Class *c,Node *node,char *id, int line_no)
1089 for(l=c->nodes;l;l=g_list_next(l)) {
1094 if(n->type == METHOD_NODE) {
1095 Method *m = (Method *)n;
1097 nline_no = m->line_no;
1098 } else if(n->type == VARIABLE_NODE) {
1099 Variable *v = (Variable *)n;
1101 nline_no = v->line_no;
1105 line_no>=nline_no ||
1108 s = g_strdup_printf("symbol '%s' redefined, "
1109 "first defined on line %d",
1111 print_error(FALSE,s,nline_no);
1116 check_duplicate_symbols(Class *c)
1119 for(l=c->nodes;l;l=g_list_next(l)) {
1121 if(n->type == METHOD_NODE) {
1122 Method *m = (Method *)n;
1123 check_duplicate(c,n,m->id,m->line_no);
1124 } else if(n->type == VARIABLE_NODE) {
1125 Variable *v = (Variable *)n;
1126 check_duplicate(c,n,v->id,v->line_no);
1132 check_duplicate_named(Class *c,Node *node,char *id, int line_no)
1135 for(l=c->nodes;l;l=g_list_next(l)) {
1140 if(n->type == METHOD_NODE) {
1141 Method *m = (Method *)n;
1142 if(m->scope == SIGNAL_LAST_METHOD ||
1143 m->scope == SIGNAL_FIRST_METHOD ||
1144 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1145 m->scope == PRIVATE_SIGNAL_FIRST_METHOD) {
1147 nline_no = m->line_no;
1150 } else if(n->type == ARGUMENT_NODE) {
1151 Argument *a = (Argument *)n;
1153 nline_no = a->line_no;
1157 line_no>=nline_no ||
1160 s = g_strdup_printf("named symbol (argument or signal) '%s' "
1161 "redefined, first defined on line %d",
1163 print_error(FALSE,s,nline_no);
1168 check_duplicate_signals_args(Class *c)
1171 for(l=c->nodes;l;l=g_list_next(l)) {
1173 if(n->type == METHOD_NODE) {
1174 Method *m = (Method *)n;
1175 if(m->scope == SIGNAL_LAST_METHOD ||
1176 m->scope == SIGNAL_FIRST_METHOD ||
1177 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1178 m->scope == PRIVATE_SIGNAL_FIRST_METHOD)
1179 check_duplicate_named(c,n,m->id,m->line_no);
1180 } else if(n->type == ARGUMENT_NODE) {
1181 Argument *a = (Argument *)n;
1182 check_duplicate_named(c,n,a->name,a->line_no);
1188 check_public_new(Class *c)
1191 for(l=c->nodes;l;l=g_list_next(l)) {
1193 if(n->type == METHOD_NODE) {
1194 Method *m = (Method *)n;
1195 if(m->scope!=PUBLIC_SCOPE &&
1196 strcmp(m->id,"new")==0)
1198 "'new' should be a public method",
1205 check_vararg(Class *c)
1208 for(l=c->nodes;l;l=g_list_next(l)) {
1210 if(n->type == METHOD_NODE) {
1211 Method *m = (Method *)n;
1214 if(m->scope == OVERRIDE_METHOD ||
1215 m->scope == SIGNAL_LAST_METHOD ||
1216 m->scope == SIGNAL_FIRST_METHOD ||
1217 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1218 m->scope == PRIVATE_SIGNAL_FIRST_METHOD ||
1219 m->scope == VIRTUAL_METHOD ||
1220 m->scope == PRIVATE_VIRTUAL_METHOD) {
1222 "signals, overrides and virtuals, "
1223 "can't have variable argument "
1232 count_signals(Class *c)
1236 for(l=c->nodes;l;l=g_list_next(l)) {
1238 if(n->type == METHOD_NODE) {
1239 Method *m = (Method *)n;
1240 if(m->scope == SIGNAL_LAST_METHOD ||
1241 m->scope == SIGNAL_FIRST_METHOD ||
1242 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1243 m->scope == PRIVATE_SIGNAL_FIRST_METHOD)
1251 count_arguments(Class *c)
1256 for(li=c->nodes;li;li=g_list_next(li)) {
1258 if(n->type == ARGUMENT_NODE)
1265 count_overrides(Class *c)
1269 for(l=c->nodes;l;l=g_list_next(l)) {
1271 if(n->type == METHOD_NODE) {
1272 Method *m = (Method *)n;
1273 if(m->scope == OVERRIDE_METHOD)
1284 char *outfile,*outfileh;
1287 outfile = g_strconcat(filebase,".c",NULL);
1289 outfile = g_strconcat(filebase,".cc",NULL);
1290 if(no_touch_headers)
1291 outfileh = g_strconcat("#gob#",filebase,".h#gob#",NULL);
1293 outfileh = g_strconcat(filebase,".h",NULL);
1295 out = fopen(outfile,"w");
1297 g_error("Cannot open outfile: %s",outfile);
1299 outh = fopen(outfileh,"w");
1301 g_error("Cannot open outfile: %s",outfileh);
1306 generate_outfiles(void)
1313 out_printf(outh,"/* Generated by GOB (v%s)"
1314 " (do not edit directly) */\n\n",VERSION);
1315 out_printf(out,"/* Generated by GOB (v%s) on %s"
1316 " (do not edit directly) */\n\n",VERSION,ctime(&curtime));
1318 p = replace_sep(((Class *)class)->otype,'_');
1320 out_printf(outh,"#ifndef __%s_H__\n#define __%s_H__\n\n"
1321 "#include <gtk/gtk.h>\n\n",p,p);
1325 out_printf(outh,"#ifdef __cplusplus\n"
1327 "#endif /* __cplusplus */\n\n");
1329 out_printf(out,"#include \"%s.h\"\n\n",filebase);
1331 for(li=nodes;li;li=g_list_next(li)) {
1332 Node *node = li->data;
1333 if(node->type == CCODE_NODE) {
1334 CCode *cc = (CCode *)node;
1338 out_printf(fp,"\n");
1341 out_printf(fp,"\n");
1342 out_addline_infile(fp,cc->line_no);
1344 out_printf(fp,"%s\n",cc->cbuf->str);
1346 out_addline_outfile(fp);
1347 } else if(node->type == CLASS_NODE) {
1349 Class *c = (Class *)class;
1352 signals = count_signals(c);
1353 arguments = count_arguments(c);
1354 overrides = count_overrides(c);
1356 out_printf(outh,"\n#define %s(obj)\t"
1357 "GTK_CHECK_CAST((obj),%s_get_type(),%s)\n",
1358 macrobase,funcbase,typebase);
1359 out_printf(outh,"#define %s_CLASS(klass)\t"
1360 "GTK_CHECK_CLASS_CAST((klass),%s_get_type(),%sClass)\n",
1361 macrobase,funcbase,typebase);
1362 out_printf(outh,"#define %s(obj)\t"
1363 "GTK_CHECK_TYPE((obj), %s_get_type ())\n\n",
1366 otype = remove_sep(c->otype);
1367 ptype = remove_sep(c->ptype);
1368 out_printf(outh,"\ntypedef struct _%s %s;\n",otype,otype);
1369 out_printf(outh,"struct _%s {\n\t%s __parent__;\n",
1371 for(l=c->nodes;l;l=g_list_next(l)) {
1373 if(n->type == VARIABLE_NODE)
1374 put_variable((Variable *)n);
1376 out_printf(outh,"};\n");
1378 out_printf(outh,"\ntypedef struct _%sClass %sClass;\n",
1381 "struct _%sClass {\n\t%sClass __parent__;\n",
1383 for(l=c->nodes;l;l=g_list_next(l)) {
1385 if(n->type == METHOD_NODE)
1386 put_vs_method((Method *)n);
1388 out_printf(outh,"};\n\n");
1390 out_printf(outh,"guint\t%s_get_type\t(void);\n",funcbase);
1393 out_printf(out,"static void __object_set_arg "
1394 "(GtkObject *object, GtkArg *arg, "
1396 "static void __object_get_arg "
1397 "(GtkObject *object, GtkArg *arg, "
1398 "guint arg_id);\n");
1401 for(l=c->nodes;l;l=g_list_next(l)) {
1403 if(n->type == METHOD_NODE) {
1404 put_pub_method((Method *)n);
1405 put_priv_method_prot((Method *)n);
1410 for(l=c->nodes;l;l=g_list_next(l)) {
1412 if(n->type == METHOD_NODE) {
1413 add_signal_prots((Method *)n);
1422 make_method_pointers(c);
1424 out_printf(out,"#define GET_NEW (gtk_type_new(%s_get_type()))\n",
1430 add_getset_arg(c, TRUE);
1431 add_getset_arg(c, FALSE);
1434 for(l=c->nodes;l;l=g_list_next(l)) {
1436 if(n->type == METHOD_NODE) {
1437 put_method((Method *)n);
1441 out_printf(out,"#undef GET_NEW\n");
1443 add_bad_hack_to_avoid_unused_warnings(c);
1448 g_assert_not_reached();
1452 out_printf(outh,"\n#ifdef __cplusplus\n"
1454 "#endif /* __cplusplus */\n");
1455 out_printf(outh,"\n#endif");
1460 usage(poptContext optCon, int exitcode, char *error, char *addl)
1462 poptPrintUsage(optCon, stderr, 0);
1463 if (error) fprintf(stderr, "%s: %s", error, addl);
1471 fprintf(stderr,"Gob version %s\n\n",VERSION);
1472 fprintf(stderr,"Options:\n"
1473 "\t--help,-h,-? Display this help\n"
1474 "\t--exit-on-warn,-w Exit with an error on warnings\n"
1475 "\t--no-exit-on-warn Don't exit on warnings [default]\n"
1476 "\t--for-cpp Create C++ files\n"
1477 "\t--no-touch-headers Don't touch headers unless they "
1478 "really changed\n");
1482 parse_options(int argc, char *argv[])
1485 int got_file = FALSE;
1486 int no_opts = FALSE;
1490 for(i=1;i<argc;i++) {
1491 if(no_opts || argv[i][0]!='-') {
1494 fprintf(stderr,"Specify only one file!\n");
1500 } else if(strcmp(argv[i],"--help")==0) {
1503 } else if(strcmp(argv[i],"--exit-on-warn")==0) {
1504 exit_on_warn = TRUE;
1505 } else if(strcmp(argv[i],"--no-exit-on-warn")==0) {
1506 exit_on_warn = FALSE;
1507 } else if(strcmp(argv[i],"--for-cpp")==0) {
1509 } else if(strcmp(argv[i],"--no-touch-headers")==0) {
1510 no_touch_headers = TRUE;
1511 } else if(strcmp(argv[i],"--")==0) {
1512 /*further arguments are files*/
1514 } else if(strncmp(argv[i],"--",2)==0) {
1515 /*unknown long option*/
1516 fprintf(stderr,"Unknown option '%s'!\n",argv[i]);
1520 /*by now we know we have a string starting with
1521 - which is a short option string*/
1522 char *p = argv[i]+1;
1523 for(p=argv[i]+1;*p;p++) {
1534 "Unknown option '%c'!\n",*p);
1544 compare_and_move_header(void)
1546 char *hfnew = g_strconcat("#gob#",filebase,".h#gob#",NULL);
1547 char *hf = g_strconcat(filebase,".h",NULL);
1549 if(stat(hf,&s)==0) {
1551 s = g_strdup_printf("cmp '%s' '%s' > /dev/null",hf,hfnew);
1553 if(unlink(hfnew)!=0)
1554 print_error(FALSE,"Can't remove new header file",0);
1562 print_error(FALSE,"Can't remove old header file",0);
1564 if(rename(hfnew,hf)!=0)
1565 print_error(FALSE,"Can't rename new header file",0);
1571 main(int argc, char *argv[])
1577 struct poptOption optionsTable[] = {
1578 { "exit-on-warn", 'w', 0, &exit_on_warn, 0,
1579 "exit on warnings" },
1581 { NULL, 0, 0, NULL, 0 }
1584 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
1585 poptSetOtherOptionHelp(optCon, "[OPTIONS]* [filename]");
1587 while ((c = poptGetNextOpt(optCon)) >= 0)
1590 filename = poptGetArg(optCon);
1591 if(!(poptPeekArg(optCon) == NULL))
1592 usage(optCon, 1, "Specify only one file",
1593 ".e.g., filename.gob");
1596 /* an error occurred during option processing */
1597 fprintf(stderr, "%s: %s\n",
1598 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
1604 parse_options(argc,argv);
1607 yyin = fopen(filename,"r");
1609 fprintf(stderr,"Error: can't open file '%s'\n",
1618 g_error("Parsing errors, quitting");
1620 print_error(FALSE," no class defined",0);
1624 exit_on_error = FALSE;
1625 make_inits((Class *)class);
1626 check_duplicate_symbols((Class *)class);
1627 check_duplicate_signals_args((Class *)class);
1628 check_public_new((Class *)class);
1629 check_vararg((Class *)class);
1630 exit_on_error = TRUE;
1637 generate_outfiles();
1642 if(no_touch_headers)
1643 compare_and_move_header();
1646 poptFreeContext(optCon);