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 functions */
61 static int privates = 0; /* number of private data members */
66 gboolean no_touch_headers = FALSE;
67 gboolean for_cpp = FALSE;
68 gboolean exit_on_warn = FALSE;
69 gboolean exit_on_error = TRUE;
70 gboolean got_error = FALSE;
73 print_error(int is_warn, char *error,int line)
83 fprintf(stderr,"%s:%d: %s %s\n",filename,line,w,error);
85 fprintf(stderr,"%s: %s %s\n",filename,w,error);
86 if((!is_warn || exit_on_warn) && exit_on_error)
91 remove_sep(char *base)
94 char *s = g_strdup(base);
95 while((p=strchr(s,':')))
101 replace_sep(char *base, char r)
104 char *s = g_strdup(base);
105 while((p=strchr(s,':')))
115 /*separate the namespace part and then replace rest of
118 separns_replace_sep(char *base, char **ns, char **name, char r)
121 char *s = g_strdup(base);
123 if((p=strchr(s,':')) && p!=s) {
130 while((p=strchr(s,':')))
133 *name = g_strdup(s+1);
139 /* make a macro with some prefix before the name but after
142 make_pre_macro(char *base, char *pre)
147 separns_replace_sep(base,&s1,&s2,'_');
149 s = g_strconcat(s1,"_",pre,"_",s2,NULL);
151 s = g_strconcat(pre,"_",s2,NULL);
164 filebase = replace_sep(((Class *)class)->otype,'-');
167 funcbase = replace_sep(((Class *)class)->otype,'_');
170 pfuncbase = replace_sep(((Class *)class)->ptype,'_');
171 g_strdown(pfuncbase);
173 macrobase = replace_sep(((Class *)class)->otype,'_');
176 macrois = make_pre_macro(((Class *)class)->otype,"IS");
177 macrotype = make_pre_macro(((Class *)class)->otype,"TYPE");
179 typebase = remove_sep(((Class *)class)->otype);
181 ptypebase = remove_sep(((Class *)class)->ptype);
185 print_type(FILE *fp, Type *t)
189 s = remove_sep(t->name);
190 out_printf(fp,"%s ",s);
193 for(i=0;i<t->stars;i++)
198 print_method(FILE *fp, char *typeprefix, char *nameprefix,
199 char *namepostfix,char *postfix, Method *m,
200 gboolean no_funcbase)
204 out_printf(fp,"%s",typeprefix);
205 print_type(fp,m->mtype);
207 out_printf(fp,"%s%s%s(",
208 nameprefix,m->id,namepostfix);
210 out_printf(fp,"%s%s_%s%s(",
211 nameprefix,funcbase,m->id,namepostfix);
214 for(li=m->args;li;li=g_list_next(li)) {
215 FuncArg *arg = li->data;
216 print_type(fp,arg->atype);
218 out_printf(fp,"%s, ",arg->name);
220 out_printf(fp,"%s",arg->name);
224 out_printf(fp,", ...");
226 out_printf(fp,"void");
228 out_printf(fp,")%s",postfix);
233 make_method_pointers(Class *c)
237 out_printf(out,"\n");
238 for(li=c->nodes;li;li=g_list_next(li)) {
239 Node *node = li->data;
240 if(node->type == METHOD_NODE) {
241 Method *m = (Method *)node;
243 if(m->scope == INIT_METHOD ||
244 m->scope == CLASS_INIT_METHOD ||
245 m->scope == OVERRIDE_METHOD)
248 /* in C++ mode don't alias new */
249 if(for_cpp && strcmp(m->id,"new")==0)
252 print_method(out,"static ","(* ",") ","",m,TRUE);
253 out_printf(out," = %s_%s;\n",funcbase,m->id);
256 out_printf(out,"\n");
260 add_bad_hack_to_avoid_unused_warnings(Class *c)
264 out_printf(out,"\n\n/*REALLY BAD HACK\n"
265 " This is to avoid unused warnings if you don't call\n"
266 " some method, it pollutes the namespace but the call\n"
267 " is weird enough. I need to find a better way to do\n"
269 out_printf(out,"void __%s_really_bad_hack_to_avoid_warnings(void);\n",
271 out_printf(out,"void\n__%s_really_bad_hack_to_avoid_warnings(void)\n"
273 for(li=c->nodes;li;li=g_list_next(li)) {
274 Node *node = li->data;
275 if(node->type == METHOD_NODE) {
276 Method *m = (Method *)node;
278 if(m->scope == INIT_METHOD ||
279 m->scope == CLASS_INIT_METHOD ||
280 m->scope == OVERRIDE_METHOD)
283 /* in C++ mode we don't alias new */
284 if(for_cpp && strcmp(m->id,"new")==0)
287 out_printf(out,"\t((void (*)(void))%s)();\n",m->id);
290 out_printf(out,"}\n\n");
294 put_variable(Variable *v, FILE *fp, int priv)
296 if(v->scope == PRIVATE_SCOPE) {
303 print_type(fp,v->vtype);
304 out_printf(fp,"%s;\n",v->id);
308 put_vs_method(Method *m)
310 if(m->scope != SIGNAL_LAST_METHOD &&
311 m->scope != SIGNAL_FIRST_METHOD &&
312 m->scope != PRIVATE_SIGNAL_LAST_METHOD &&
313 m->scope != PRIVATE_SIGNAL_FIRST_METHOD &&
314 m->scope != VIRTUAL_METHOD &&
315 m->scope != PRIVATE_VIRTUAL_METHOD)
318 print_method(outh,"\t","(* ",") ",";\n",m,TRUE);
322 put_pub_method(Method *m)
324 if(m->scope == PRIVATE_SCOPE ||
325 m->scope == OVERRIDE_METHOD ||
326 m->scope == INIT_METHOD ||
327 m->scope == CLASS_INIT_METHOD ||
328 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
329 m->scope == PRIVATE_SIGNAL_FIRST_METHOD ||
330 m->scope == PRIVATE_VIRTUAL_METHOD)
333 print_method(outh,"","\t","\t",";\n",m,FALSE);
337 put_priv_method_prot(Method *m)
339 if(m->scope == PUBLIC_SCOPE)
342 if(m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
343 m->scope == PRIVATE_SIGNAL_FIRST_METHOD ||
344 m->scope == PRIVATE_VIRTUAL_METHOD) {
346 print_method(out,"static ","_real_"," ",";\n",m,FALSE);
347 print_method(out,"static ",""," ",";\n",m,FALSE);
348 } else if(m->scope == SIGNAL_LAST_METHOD ||
349 m->scope == SIGNAL_FIRST_METHOD ||
350 m->scope == VIRTUAL_METHOD) {
353 print_method(out,"static ","_real_"," ",";\n",m,FALSE);
355 print_method(out,"static ",""," ",";\n",m,FALSE);
360 make_func_arg(char *typename, int is_class, char *name)
367 tn = g_strconcat(typename,":Class",NULL);
369 tn = g_strdup(typename);
371 type = new_type(1,tn);
372 node = new_funcarg((Type *)type,name,NULL);
373 return g_list_prepend(NULL, node);
377 make_inits(Class *cl)
379 int got_class_init = FALSE;
380 int got_init = FALSE;
383 for(li=cl->nodes;li;li=g_list_next(li)) {
385 if(n->type == METHOD_NODE) {
386 Method *m = (Method *)n;
387 if(m->scope == INIT_METHOD) {
389 print_error(FALSE,"init defined more then once",m->line_no);
391 } else if(m->scope == CLASS_INIT_METHOD) {
393 print_error(FALSE,"class_init defined more then once",m->line_no);
394 got_class_init = TRUE;
398 if(!got_class_init) {
399 node = new_method(CLASS_INIT_METHOD,
400 (Type *)new_type(0,g_strdup("void")),
401 NULL,NULL,g_strdup("class_init"),
402 make_func_arg(cl->otype,TRUE,g_strdup("c")),
403 NULL, NULL,0,0,FALSE);
404 cl->nodes = g_list_prepend(cl->nodes,node);
407 node = new_method(INIT_METHOD,
408 (Type *)new_type(0,g_strdup("void")),
409 NULL,NULL,g_strdup("init"),
410 make_func_arg(cl->otype,FALSE,g_strdup("o")),
411 NULL, NULL,0,0,FALSE);
412 cl->nodes = g_list_prepend(cl->nodes,node);
417 make_destroy(Class *cl)
419 int got_destroy = FALSE;
422 for(li=cl->nodes;li;li=g_list_next(li)) {
424 if(n->type == METHOD_NODE) {
425 Method *m = (Method *)n;
426 if(m->scope == OVERRIDE_METHOD &&
427 strcmp(m->id,"destroy")==0) {
428 if(strcmp(m->otype,"Gtk:Object")==0) {
432 print_error(FALSE,"destroy method override "
433 "of class other then Gtk:Object",
441 node = new_method(OVERRIDE_METHOD,
442 (Type *)new_type(0,g_strdup("void")),
443 g_strdup("Gtk:Object"),
444 NULL,g_strdup("destroy"),
445 make_func_arg("Gtk:Object",FALSE,g_strdup("o")),
447 g_string_new("PARENT_HANDLER (o);\n"),
449 cl->nodes = g_list_append(cl->nodes,node);
454 static GHashTable *marsh = NULL;
457 add_signal_prots(Method *m)
463 if(m->scope != SIGNAL_LAST_METHOD &&
464 m->scope != SIGNAL_FIRST_METHOD &&
465 m->scope != PRIVATE_SIGNAL_LAST_METHOD &&
466 m->scope != PRIVATE_SIGNAL_FIRST_METHOD)
470 marsh = g_hash_table_new(NULL,NULL);
472 if(strcmp(m->gtktypes->data,"NONE")==0 &&
473 strcmp(m->gtktypes->next->data,"NONE")==0)
476 s = g_strdup_printf("__Sig%d",sig++);
478 g_hash_table_insert(marsh,m,s);
480 out_printf(out,"\ntypedef ");
481 print_type(out,m->mtype);
483 out_printf(out,"(*%s) (",s);
485 for(li=m->args;li;li=g_list_next(li)) {
486 FuncArg *arg = li->data;
487 print_type(out,arg->atype);
488 out_printf(out,", ");
490 out_printf(out,"gpointer);\n");
492 out_printf(out,"\nstatic void\n"
493 "marshal_%s (GtkObject * object,\n"
494 "\tGtkSignalFunc func,\n"
495 "\tgpointer func_data,\n"
499 if(strcmp(m->gtktypes->data,"NONE")==0) {
501 out_printf(out, "\t%s rfunc;\n\n"
502 "\trfunc = (%s)func;\n\n"
503 "\t(*rfunc)((%s *)object",s,s,typebase);
504 if(strcmp(m->gtktypes->next->data,"NONE")!=0) {
505 GList *ali = m->args->next;
506 for(i=0,li=m->gtktypes->next;li;
507 i++,li=g_list_next(li)) {
509 out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
512 FuncArg *fa = ali->data;
513 out_printf(out, ",\n\t\t(");
514 print_type(out,fa->atype);
515 out_printf(out, ")GTK_VALUE_%s(args[%d])",
519 if(ali) ali = ali->next;
522 out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
525 out_printf(out, "\t%s rfunc;\n\t",s);
526 print_type(out,m->mtype);
527 out_printf(out, " *retval;\n\n"
528 "\trfunc = (%s)func;\n\n"
529 "\tretval = GTK_RETLOC_%s(args[%d]);\n\n"
530 "\t*retval = (*rfunc)((%s *)object",
531 s,(char *)m->gtktypes->data,
532 g_list_length(m->gtktypes)-1,typebase);
533 if(strcmp(m->gtktypes->next->data,"NONE")!=0) {
534 GList *ali = m->args->next;
535 for(i=0,li=m->gtktypes->next;li;
536 i++,li=g_list_next(li)) {
538 out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
541 FuncArg *fa = ali->data;
542 out_printf(out, ",\n\t\t(");
543 print_type(out,fa->atype);
544 out_printf(out, ")GTK_VALUE_%s(args[%d])",
548 if(ali) ali = ali->next;
551 out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
560 out_printf(out,"\n");
562 out_printf(out,"enum {\n");
563 for(li=c->nodes;li;li=g_list_next(li)) {
565 if(n->type == METHOD_NODE) {
566 Method *m = (Method *)n;
567 if(m->scope == SIGNAL_LAST_METHOD ||
568 m->scope == SIGNAL_FIRST_METHOD ||
569 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
570 m->scope == PRIVATE_SIGNAL_FIRST_METHOD) {
571 char *s = g_strdup(m->id);
573 out_printf(out,"\t%s_SIGNAL,\n",s);
578 out_printf(out,"\tLAST_SIGNAL\n};\n\n");
581 out_printf(out,"enum {\n\tARG_0,\n");
582 for(li=c->nodes;li;li=g_list_next(li)) {
584 if(n->type == ARGUMENT_NODE) {
585 Argument *a = (Argument *)n;
586 char *s = g_strdup(a->name);
588 out_printf(out,"\tARG_%s,\n",s);
592 out_printf(out, "};\n\n");
597 "static guint object_signals[LAST_SIGNAL] = {0};\n\n");
599 out_printf(out, "static %sClass *parent_class = NULL;\n\n",ptypebase);
605 out_printf(out, "guint\n"
606 "%s_get_type (void)\n"
608 "\tstatic guint type = 0;\n\n"
610 "\t\tstatic const GtkTypeInfo info = {\n"
612 "\t\t\tsizeof (%s),\n"
613 "\t\t\tsizeof (%sClass),\n"
614 "\t\t\t(GtkClassInitFunc) %s_class_init,\n"
615 "\t\t\t(GtkObjectInitFunc) %s_init,\n"
616 "\t\t\t/* reserved_1 */ NULL,\n"
617 "\t\t\t/* reserved_2 */ NULL,\n"
618 "\t\t\t(GtkClassInitFunc) NULL,\n"
620 "\t\ttype = gtk_type_unique (%s_get_type(), &info);\n"
624 funcbase,typebase,typebase,typebase,
625 funcbase,funcbase,pfuncbase);
629 add_overrides(Class *c, char *oname, gboolean did_gtk_obj)
635 done = g_hash_table_new(g_str_hash,g_str_equal);
637 s = g_strdup("GtkObject"); /* This was already done */
638 g_hash_table_insert(done,s,s);
640 for(li=c->nodes;li;li=g_list_next(li)) {
644 if(n->type != METHOD_NODE ||
645 ((Method *)n)->scope != OVERRIDE_METHOD)
649 s = remove_sep(m->otype);
651 if(g_hash_table_lookup(done,s)) {
655 g_hash_table_insert(done,s,s);
657 f = replace_sep(m->otype,'_');
660 out_printf(out,"\t%sClass *%s_class = (%sClass *)%s;\n",
665 g_hash_table_foreach(done,(GHFunc)g_free,NULL);
666 g_hash_table_destroy(done);
670 add_signals(Class *c)
674 out_printf(out,"\n");
675 for(li=c->nodes;li;li=g_list_next(li)) {
682 if(n->type != METHOD_NODE ||
683 (((Method *)n)->scope != SIGNAL_FIRST_METHOD &&
684 ((Method *)n)->scope != SIGNAL_LAST_METHOD &&
685 ((Method *)n)->scope != PRIVATE_SIGNAL_FIRST_METHOD &&
686 ((Method *)n)->scope != PRIVATE_SIGNAL_LAST_METHOD))
691 if(m->scope == SIGNAL_FIRST_METHOD ||
692 m->scope == PRIVATE_SIGNAL_FIRST_METHOD)
697 if(g_hash_table_lookup(marsh,m))
698 mar = g_strconcat("marshal_",
699 (char *)g_hash_table_lookup(marsh,m),
702 mar = g_strdup("gtk_signal_default_marshaller");
704 is_none = (strcmp(m->gtktypes->next->data,"NONE")==0);
706 sig = g_strdup(m->id);
708 out_printf(out,"\tobject_signals[%s_SIGNAL] =\n"
709 "\t\tgtk_signal_new (\"%s\",\n"
710 "\t\t\tGTK_RUN_%s,\n"
711 "\t\t\tgtk_object_class->type,\n"
712 "\t\t\tGTK_SIGNAL_OFFSET (%sClass, %s),\n"
714 "\t\t\tGTK_TYPE_%s, %d",
717 typebase,m->id,mar,(char *)m->gtktypes->data,
718 is_none?0:g_list_length(m->gtktypes->next));
724 for(l=m->gtktypes->next;l;l=g_list_next(l))
725 out_printf(out,",\n\t\t\tGTK_TYPE_%s",
729 out_printf(out,");\n");
731 out_printf(out,"\tgtk_object_class_add_signals (gtk_object_class,\n"
732 "\t\tobject_signals, LAST_SIGNAL);\n\n");
736 set_def_handlers(Class *c, char *oname)
740 out_printf(out,"\n");
741 for(li=c->nodes;li;li=g_list_next(li)) {
744 if(n->type != METHOD_NODE ||
745 (((Method *)n)->scope != SIGNAL_FIRST_METHOD &&
746 ((Method *)n)->scope != SIGNAL_LAST_METHOD &&
747 ((Method *)n)->scope != PRIVATE_SIGNAL_FIRST_METHOD &&
748 ((Method *)n)->scope != PRIVATE_SIGNAL_LAST_METHOD &&
749 ((Method *)n)->scope != VIRTUAL_METHOD &&
750 ((Method *)n)->scope != PRIVATE_VIRTUAL_METHOD &&
751 ((Method *)n)->scope != OVERRIDE_METHOD))
756 if(m->scope == OVERRIDE_METHOD) {
758 s = replace_sep(m->otype,'_');
760 out_printf(out,"\t%s_class->%s = %s_%s;\n",
761 s,m->id,funcbase,m->id);
764 out_printf(out,"\t%s->%s = _real_%s_%s;\n",
765 oname,m->id,funcbase,m->id);
767 out_printf(out,"\t%s->%s = NULL;\n",
774 make_arguments(Class *c)
778 out_printf(out,"\n");
779 for(li=c->nodes;li;li=g_list_next(li)) {
785 if(n->type != ARGUMENT_NODE)
791 flags = g_string_new("GTK_ARG_READWRITE");
793 flags = g_string_new("GTK_ARG_READABLE");
795 flags = g_string_new("GTK_ARG_WRITABLE");
797 for(l=a->flags;l;l=g_list_next(l))
798 g_string_sprintfa(flags," | GTK_ARG_%s",(char *)l->data);
800 s = g_strdup(a->name);
802 out_printf(out,"\tgtk_object_add_arg_type(\"%s::%s\",\n"
806 typebase,a->name,a->gtktype,flags->str,s);
808 g_string_free(flags,TRUE);
812 "\n\tgtk_object_class->set_arg = __object_set_arg;\n"
813 "\tgtk_object_class->get_arg = __object_get_arg;\n");
820 for(li=c->nodes;li;li=g_list_next(li)) {
823 if(n->type != METHOD_NODE)
826 if(m->scope == INIT_METHOD) {
828 out_addline_infile(out,m->line_no);
829 print_method(out,"static ","\n"," ","\n",m,FALSE);
831 out_addline_outfile(out);
832 out_printf(out,"{\n");
834 out_printf(out,"\t%s->_priv = "
835 "g_new0 (%sPrivate,1);\n",
836 ((FuncArg *)m->args->data)->name,
839 } else if(m->scope == CLASS_INIT_METHOD) {
841 out_addline_infile(out,m->line_no);
842 print_method(out,"static ","\n"," ","\n",m,FALSE);
844 out_addline_outfile(out);
845 out_printf(out,"{\n");
850 "gtk_object_class = "
851 "(GtkObjectClass*) %s;\n",
852 ((FuncArg *)m->args->data)->name);
856 ((FuncArg *)m->args->data)->name,
857 (signals>0 || arguments>0));
859 out_printf(out,"\n\tparent_class = ");
861 out_printf(out,"(%sClass *)",ptypebase);
862 out_printf(out,"gtk_type_class (%s_get_type ());\n",
868 set_def_handlers(c, ((FuncArg *)m->args->data)->name);
877 out_printf(out," {\n");
878 out_addline_infile(out,m->ccode_line);
879 out_printf(out,"%s\n",m->cbuf->str);
880 out_addline_outfile(out);
881 out_printf(out," }\n",m->cbuf->str);
883 out_printf(out,"return;\n");
885 out_printf(out,"}\n");
890 add_getset_arg(Class *c, int is_set)
893 out_printf(out,"\nstatic void\n"
894 "__object_%s_arg (GtkObject *object,\n"
899 "\tself = %s (object);\n\n"
900 "\tswitch (arg_id) {\n",
901 is_set?"set":"get",typebase,macrobase);
903 for(li=c->nodes;li;li=g_list_next(li)) {
909 if(n->type != ARGUMENT_NODE)
914 line_no = a->set_line;
917 line_no = a->get_line;
921 s = g_strdup(a->name);
923 out_printf(out,"\tcase ARG_%s:\n"
924 "#define ARG (GTK_VALUE_%s(*arg))\n"
928 out_addline_infile(out,line_no);
929 out_printf(out,"%s\n",cbuf->str);
930 out_addline_outfile(out);
931 out_printf(out,"\t\t}\n\t\tbreak;\n"
934 out_printf(out,"\tdefault:\n\t\tbreak;\n\t}\n}\n");
938 print_checks(Method *m, FuncArg *fa)
942 is_void = (strcmp(m->mtype->name,"void")==0 &&
943 m->mtype->stars == 0);
945 for(li=fa->checks;li;li=g_list_next(li)) {
946 Check *ch = li->data;
949 out_printf(out,"\tg_return_if_fail (");
951 out_printf(out,"\tg_return_val_if_fail (");
954 out_printf(out,"%s != NULL",fa->name);
957 s = make_pre_macro(fa->atype->name,"IS");
958 out_printf(out,"%s (%s)",s,fa->name);
962 out_printf(out,"%s < %s",fa->name,ch->number);
965 out_printf(out,"%s > %s",fa->name,ch->number);
968 out_printf(out,"%s <= %s",fa->name,ch->number);
971 out_printf(out,"%s >= %s",fa->name,ch->number);
974 out_printf(out,"%s == %s",fa->name,ch->number);
977 out_printf(out,"%s != %s",fa->name,ch->number);
981 out_printf(out,");\n");
983 out_printf(out,", (");
984 print_type(out,m->mtype);
985 out_printf(out,")%s);\n",
986 m->onerror?m->onerror:"0");
992 print_preconditions(Method *m)
996 for(li=m->args;li;li=g_list_next(li)) {
997 FuncArg *fa = li->data;
1003 /* put in code if it's needed */
1005 put_in_gen_code(Method *m)
1007 /* now we only have the freeing of the private structure */
1009 m->scope == OVERRIDE_METHOD &&
1010 strcmp(m->id,"destroy")==0) {
1011 out_printf(out,"\tg_free (%s (%s)->_priv);\n"
1012 "\t%s (%s)->_priv = NULL;\n",
1014 ((FuncArg *)m->args->data)->name,
1016 ((FuncArg *)m->args->data)->name);
1022 print_method_body(Method *m, int pre)
1024 out_printf(out,"{\n");
1026 print_preconditions(m);
1029 out_printf(out,"\t{\n");
1031 out_addline_infile(out,m->ccode_line);
1032 out_printf(out,"\t\t%s\n",m->cbuf->str);
1033 out_addline_outfile(out);
1035 out_printf(out,"\t}\n");
1036 out_printf(out,"}\n");
1040 put_method(Method *m)
1043 int private = FALSE;
1044 out_printf(out,"\n");
1047 out_addline_infile(out,m->line_no);
1048 print_method(out,"","\n"," ","\n",m,FALSE);
1049 print_method_body(m,TRUE);
1052 out_addline_infile(out,m->line_no);
1053 print_method(out,"static ","\n"," ","\n",m,FALSE);
1054 print_method_body(m,TRUE);
1056 case PRIVATE_SIGNAL_FIRST_METHOD:
1057 case PRIVATE_SIGNAL_LAST_METHOD:
1059 case SIGNAL_FIRST_METHOD:
1060 case SIGNAL_LAST_METHOD:
1061 out_addline_infile(out,m->line_no);
1062 print_method(out,private?"static ":"","\n"," ","\n",m,FALSE);
1063 out_addline_outfile(out);
1064 out_printf(out,"{\n");
1065 s = g_strdup(m->id);
1067 if(strcmp(m->mtype->name,"void")==0 &&
1068 m->mtype->stars==0) {
1070 print_preconditions(m);
1071 if(((FuncArg *)m->args->data)->name)
1072 out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1073 "\t\tobject_signals[%s_SIGNAL]",
1074 ((FuncArg *)m->args->data)->name,s);
1075 for(li=m->args->next;li;li=g_list_next(li)) {
1076 FuncArg *fa = li->data;
1077 out_printf(out,",\n\t\t%s",fa->name);
1079 out_printf(out,");\n}\n");
1082 out_printf(out,"\t");
1083 print_type(out,m->mtype);
1084 out_printf(out,"return_val;\n");
1085 print_preconditions(m);
1086 out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1087 "\t\tobject_signals[%s_SIGNAL]",
1088 ((FuncArg *)m->args->data)->name,s);
1089 for(li=m->args->next;li;li=g_list_next(li)) {
1090 FuncArg *fa = li->data;
1091 out_printf(out,",\n\t\t%s",fa->name);
1093 out_printf(out,",\n\t\t&return_val);\n"
1094 "\treturn return_val;\n}\n");
1099 out_addline_infile(out,m->line_no);
1100 print_method(out,"static ","\n_real_"," ","\n",m,FALSE);
1101 print_method_body(m,FALSE);
1103 case PRIVATE_VIRTUAL_METHOD:
1105 case VIRTUAL_METHOD:
1106 out_addline_infile(out,m->line_no);
1107 print_method(out,private?"static ":"","\n"," ","\n",m,FALSE);
1108 out_addline_outfile(out);
1109 out_printf(out,"{\n"
1110 "\t%sClass *klass;\n",typebase);
1111 print_preconditions(m);
1112 out_printf(out,"\tklass = %s_CLASS(GTK_OBJECT(%s)->klass);\n\n"
1113 "\tif(klass->%s)\n",
1114 macrobase, ((FuncArg *)m->args->data)->name, m->id);
1115 if(strcmp(m->mtype->name,"void")==0 &&
1116 m->mtype->stars==0) {
1118 out_printf(out,"\t\t(*klass->%s)(%s",m->id,
1119 ((FuncArg *)m->args->data)->name);
1120 for(li=m->args->next;li;li=g_list_next(li)) {
1121 FuncArg *fa = li->data;
1122 out_printf(out,",%s",fa->name);
1124 out_printf(out,");\n}\n");
1127 out_printf(out,"\t\treturn (*klass->%s)(%s",m->id,
1128 ((FuncArg *)m->args->data)->name);
1129 for(li=m->args->next;li;li=g_list_next(li)) {
1130 FuncArg *fa = li->data;
1131 out_printf(out,",%s",fa->name);
1133 out_printf(out,");\n"
1136 print_type(out,m->mtype);
1137 out_printf(out,")(%s);\n}\n",
1138 m->onerror?m->onerror:"0");
1143 out_addline_infile(out,m->line_no);
1144 print_method(out,"static ","\n_real_"," ","\n",m,FALSE);
1145 print_method_body(m,FALSE);
1147 case OVERRIDE_METHOD:
1148 out_addline_infile(out,m->line_no);
1149 print_method(out,"static ","\n"," ","\n",m,FALSE);
1150 s = replace_sep(m->otype,'_');
1152 out_printf(out,"#define PARENT_HANDLER(args...) \\\n"
1153 "\t{ if(%s_CLASS(parent_class)->%s) \\\n"
1154 "\t\t(* %s_CLASS(parent_class)->%s)(##args); }\n",
1157 print_method_body(m,TRUE);
1158 out_printf(out,"#undef PARENT_HANDLER\n");
1166 check_duplicate(Class *c,Node *node,char *id, int line_no)
1169 for(l=c->nodes;l;l=g_list_next(l)) {
1174 if(n->type == METHOD_NODE) {
1175 Method *m = (Method *)n;
1177 nline_no = m->line_no;
1178 } else if(n->type == VARIABLE_NODE) {
1179 Variable *v = (Variable *)n;
1181 nline_no = v->line_no;
1185 line_no>=nline_no ||
1186 strcmp(nid,id)!=0 ||
1187 n->type != node->type)
1189 s = g_strdup_printf("symbol '%s' redefined, "
1190 "first defined on line %d",
1192 print_error(FALSE,s,nline_no);
1197 check_duplicate_symbols(Class *c)
1200 for(l=c->nodes;l;l=g_list_next(l)) {
1202 if(n->type == METHOD_NODE) {
1203 Method *m = (Method *)n;
1204 check_duplicate(c,n,m->id,m->line_no);
1205 } else if(n->type == VARIABLE_NODE) {
1206 Variable *v = (Variable *)n;
1207 check_duplicate(c,n,v->id,v->line_no);
1213 check_bad_symbols(Class *c)
1216 for(l=c->nodes;l;l=g_list_next(l)) {
1218 if(n->type == METHOD_NODE) {
1219 Method *m = (Method *)n;
1220 if((m->scope == SIGNAL_LAST_METHOD ||
1221 m->scope == SIGNAL_FIRST_METHOD ||
1222 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1223 m->scope == PRIVATE_SIGNAL_FIRST_METHOD ||
1224 m->scope == VIRTUAL_METHOD ||
1225 m->scope == PRIVATE_VIRTUAL_METHOD) &&
1226 strcmp(m->id,"__parent__")==0) {
1228 s = g_strdup_printf("'%s' not allowed as an "
1229 "identifier of signal "
1230 "or virtual methods",
1232 print_error(FALSE,s,m->line_no);
1235 } else if(n->type == VARIABLE_NODE) {
1236 Variable *v = (Variable *)n;
1237 if(strcmp(v->id,"_priv")==0 ||
1238 strcmp(v->id,"__parent__")==0) {
1240 s = g_strdup_printf("'%s' not allowed as a data "
1241 "member name",v->id);
1242 print_error(FALSE,s,v->line_no);
1251 check_duplicate_named(Class *c,Node *node,char *id, int line_no)
1254 for(l=c->nodes;l;l=g_list_next(l)) {
1259 if(n->type == METHOD_NODE) {
1260 Method *m = (Method *)n;
1261 if(m->scope == SIGNAL_LAST_METHOD ||
1262 m->scope == SIGNAL_FIRST_METHOD ||
1263 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1264 m->scope == PRIVATE_SIGNAL_FIRST_METHOD) {
1266 nline_no = m->line_no;
1269 } else if(n->type == ARGUMENT_NODE) {
1270 Argument *a = (Argument *)n;
1272 nline_no = a->line_no;
1276 line_no>=nline_no ||
1279 s = g_strdup_printf("named symbol (argument or signal) '%s' "
1280 "redefined, first defined on line %d",
1282 print_error(FALSE,s,nline_no);
1287 check_duplicate_signals_args(Class *c)
1290 for(l=c->nodes;l;l=g_list_next(l)) {
1292 if(n->type == METHOD_NODE) {
1293 Method *m = (Method *)n;
1294 if(m->scope == SIGNAL_LAST_METHOD ||
1295 m->scope == SIGNAL_FIRST_METHOD ||
1296 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1297 m->scope == PRIVATE_SIGNAL_FIRST_METHOD)
1298 check_duplicate_named(c,n,m->id,m->line_no);
1299 } else if(n->type == ARGUMENT_NODE) {
1300 Argument *a = (Argument *)n;
1301 check_duplicate_named(c,n,a->name,a->line_no);
1307 check_public_new(Class *c)
1310 for(l=c->nodes;l;l=g_list_next(l)) {
1312 if(n->type == METHOD_NODE) {
1313 Method *m = (Method *)n;
1314 if(m->scope!=PUBLIC_SCOPE &&
1315 strcmp(m->id,"new")==0)
1317 "'new' should be a public method",
1324 check_vararg(Class *c)
1327 for(l=c->nodes;l;l=g_list_next(l)) {
1329 if(n->type == METHOD_NODE) {
1330 Method *m = (Method *)n;
1333 if(m->scope == OVERRIDE_METHOD ||
1334 m->scope == SIGNAL_LAST_METHOD ||
1335 m->scope == SIGNAL_FIRST_METHOD ||
1336 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1337 m->scope == PRIVATE_SIGNAL_FIRST_METHOD ||
1338 m->scope == VIRTUAL_METHOD ||
1339 m->scope == PRIVATE_VIRTUAL_METHOD) {
1341 "signals, overrides and virtuals, "
1342 "can't have variable argument "
1351 check_firstarg(Class *c)
1354 for(l=c->nodes;l;l=g_list_next(l)) {
1356 if(n->type == METHOD_NODE) {
1357 Method *m = (Method *)n;
1360 if(m->scope == OVERRIDE_METHOD ||
1361 m->scope == SIGNAL_LAST_METHOD ||
1362 m->scope == SIGNAL_FIRST_METHOD ||
1363 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1364 m->scope == PRIVATE_SIGNAL_FIRST_METHOD ||
1365 m->scope == VIRTUAL_METHOD ||
1366 m->scope == PRIVATE_VIRTUAL_METHOD) {
1368 "signals, overrides and virtuals, "
1369 "can't have no arguments",
1377 count_signals(Class *c)
1381 for(l=c->nodes;l;l=g_list_next(l)) {
1383 if(n->type == METHOD_NODE) {
1384 Method *m = (Method *)n;
1385 if(m->scope == SIGNAL_LAST_METHOD ||
1386 m->scope == SIGNAL_FIRST_METHOD ||
1387 m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1388 m->scope == PRIVATE_SIGNAL_FIRST_METHOD)
1396 count_arguments(Class *c)
1401 for(li=c->nodes;li;li=g_list_next(li)) {
1403 if(n->type == ARGUMENT_NODE)
1410 count_overrides(Class *c)
1414 for(l=c->nodes;l;l=g_list_next(l)) {
1416 if(n->type == METHOD_NODE) {
1417 Method *m = (Method *)n;
1418 if(m->scope == OVERRIDE_METHOD)
1426 count_privates(Class *c)
1430 for(l=c->nodes;l;l=g_list_next(l)) {
1432 if(n->type == VARIABLE_NODE) {
1433 Variable *v = (Variable *)n;
1434 if(v->scope == PRIVATE_SCOPE)
1445 char *outfile,*outfileh;
1448 outfile = g_strconcat(filebase,".c",NULL);
1450 outfile = g_strconcat(filebase,".cc",NULL);
1451 if(no_touch_headers)
1452 outfileh = g_strconcat("#gob#",filebase,".h#gob#",NULL);
1454 outfileh = g_strconcat(filebase,".h",NULL);
1456 out = fopen(outfile,"w");
1458 g_error("Cannot open outfile: %s",outfile);
1460 outh = fopen(outfileh,"w");
1462 g_error("Cannot open outfile: %s",outfileh);
1467 generate_outfiles(void)
1474 out_printf(outh,"/* Generated by GOB (v%s)"
1475 " (do not edit directly) */\n\n",VERSION);
1476 out_printf(out,"/* Generated by GOB (v%s) on %s"
1477 " (do not edit directly) */\n\n",VERSION,ctime(&curtime));
1479 p = replace_sep(((Class *)class)->otype,'_');
1481 out_printf(outh,"#ifndef __%s_H__\n#define __%s_H__\n\n"
1482 "#include <gtk/gtk.h>\n\n",p,p);
1486 out_printf(outh,"#ifdef __cplusplus\n"
1488 "#endif /* __cplusplus */\n\n");
1490 p = g_strconcat(filebase,".h",NULL);
1491 if(!g_list_find_custom(include_files,p,(GCompareFunc)strcmp))
1492 out_printf(out,"#include \"%s.h\"\n\n",filebase);
1495 for(li=nodes;li;li=g_list_next(li)) {
1496 Node *node = li->data;
1497 if(node->type == CCODE_NODE) {
1498 CCode *cc = (CCode *)node;
1502 out_printf(fp,"\n");
1505 out_printf(fp,"\n");
1506 out_addline_infile(fp,cc->line_no);
1508 out_printf(fp,"%s\n",cc->cbuf->str);
1510 out_addline_outfile(fp);
1511 } else if(node->type == CLASS_NODE) {
1512 Class *c = (Class *)class;
1515 out_printf(outh,"\n#define %s\t"
1516 "(%s_get_type())\n",
1517 macrotype,funcbase);
1518 out_printf(outh,"#define %s(obj)\t"
1519 "GTK_CHECK_CAST((obj),%s_get_type(),%s)\n",
1520 macrobase,funcbase,typebase);
1521 out_printf(outh,"#define %s_CLASS(klass)\t"
1522 "GTK_CHECK_CLASS_CAST((klass),%s_get_type(),%sClass)\n",
1523 macrobase,funcbase,typebase);
1524 out_printf(outh,"#define %s(obj)\t"
1525 "GTK_CHECK_TYPE((obj), %s_get_type ())\n\n",
1529 out_printf(outh,"\ntypedef struct _%sPrivate %sPrivate;\n",typebase,typebase);
1531 out_printf(outh,"\ntypedef struct _%s %s;\n",typebase,typebase);
1532 out_printf(outh,"struct _%s {\n\t%s __parent__;\n",
1533 typebase,ptypebase);
1534 for(l=c->nodes;l;l=g_list_next(l)) {
1536 if(n->type == VARIABLE_NODE)
1537 put_variable((Variable *)n,outh,FALSE);
1540 out_printf(outh,"\t%sPrivate *_priv;\n",typebase);
1541 out_printf(outh,"};\n");
1544 out_printf(out,"struct _%sPrivate {\n",
1546 for(l=c->nodes;l;l=l->next) {
1548 if(n->type == VARIABLE_NODE) {
1549 Variable *v = (Variable *)n;
1550 out_addline_infile(out,v->line_no);
1551 put_variable(v,out,TRUE);
1554 out_addline_outfile(out);
1555 out_printf(out,"};\n");
1558 out_printf(outh,"\ntypedef struct _%sClass %sClass;\n",
1561 "struct _%sClass {\n\t%sClass __parent__;\n",
1562 typebase,ptypebase);
1563 for(l=c->nodes;l;l=g_list_next(l)) {
1565 if(n->type == METHOD_NODE)
1566 put_vs_method((Method *)n);
1568 out_printf(outh,"};\n\n");
1570 out_printf(outh,"guint\t%s_get_type\t(void);\n",funcbase);
1573 out_printf(out,"static void __object_set_arg "
1574 "(GtkObject *object, GtkArg *arg, "
1576 "static void __object_get_arg "
1577 "(GtkObject *object, GtkArg *arg, "
1578 "guint arg_id);\n");
1581 for(l=c->nodes;l;l=g_list_next(l)) {
1583 if(n->type == METHOD_NODE) {
1584 put_pub_method((Method *)n);
1585 put_priv_method_prot((Method *)n);
1590 for(l=c->nodes;l;l=g_list_next(l)) {
1592 if(n->type == METHOD_NODE) {
1593 add_signal_prots((Method *)n);
1602 make_method_pointers(c);
1604 out_printf(out,"#define GET_NEW (gtk_type_new(%s_get_type()))\n",
1610 add_getset_arg(c, TRUE);
1611 add_getset_arg(c, FALSE);
1614 for(l=c->nodes;l;l=g_list_next(l)) {
1616 if(n->type == METHOD_NODE) {
1617 put_method((Method *)n);
1621 out_printf(out,"#undef GET_NEW\n");
1623 add_bad_hack_to_avoid_unused_warnings(c);
1625 g_assert_not_reached();
1629 out_printf(outh,"\n#ifdef __cplusplus\n"
1631 "#endif /* __cplusplus */\n");
1632 out_printf(outh,"\n#endif");
1637 usage(poptContext optCon, int exitcode, char *error, char *addl)
1639 poptPrintUsage(optCon, stderr, 0);
1640 if (error) fprintf(stderr, "%s: %s", error, addl);
1648 fprintf(stderr,"Gob version %s\n\n",VERSION);
1649 fprintf(stderr,"Options:\n"
1650 "\t--help,-h,-? Display this help\n"
1651 "\t--exit-on-warn,-w Exit with an error on warnings\n"
1652 "\t--no-exit-on-warn Don't exit on warnings [default]\n"
1653 "\t--for-cpp Create C++ files\n"
1654 "\t--no-touch-headers Don't touch headers unless they "
1655 "really changed\n");
1659 parse_options(int argc, char *argv[])
1662 int got_file = FALSE;
1663 int no_opts = FALSE;
1667 for(i=1;i<argc;i++) {
1668 if(no_opts || argv[i][0]!='-') {
1671 fprintf(stderr,"Specify only one file!\n");
1677 } else if(strcmp(argv[i],"--help")==0) {
1680 } else if(strcmp(argv[i],"--exit-on-warn")==0) {
1681 exit_on_warn = TRUE;
1682 } else if(strcmp(argv[i],"--no-exit-on-warn")==0) {
1683 exit_on_warn = FALSE;
1684 } else if(strcmp(argv[i],"--for-cpp")==0) {
1686 } else if(strcmp(argv[i],"--no-touch-headers")==0) {
1687 no_touch_headers = TRUE;
1688 } else if(strcmp(argv[i],"--")==0) {
1689 /*further arguments are files*/
1691 } else if(strncmp(argv[i],"--",2)==0) {
1692 /*unknown long option*/
1693 fprintf(stderr,"Unknown option '%s'!\n",argv[i]);
1697 /*by now we know we have a string starting with
1698 - which is a short option string*/
1699 char *p = argv[i]+1;
1700 for(p=argv[i]+1;*p;p++) {
1711 "Unknown option '%c'!\n",*p);
1721 compare_and_move_header(void)
1723 char *hfnew = g_strconcat("#gob#",filebase,".h#gob#",NULL);
1724 char *hf = g_strconcat(filebase,".h",NULL);
1726 if(stat(hf,&s)==0) {
1728 s = g_strdup_printf("cmp '%s' '%s' > /dev/null",hf,hfnew);
1730 if(unlink(hfnew)!=0)
1731 print_error(FALSE,"Can't remove new header file",0);
1739 print_error(FALSE,"Can't remove old header file",0);
1741 if(rename(hfnew,hf)!=0)
1742 print_error(FALSE,"Can't rename new header file",0);
1748 main(int argc, char *argv[])
1754 struct poptOption optionsTable[] = {
1755 { "exit-on-warn", 'w', 0, &exit_on_warn, 0,
1756 "exit on warnings" },
1758 { NULL, 0, 0, NULL, 0 }
1761 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
1762 poptSetOtherOptionHelp(optCon, "[OPTIONS]* [filename]");
1764 while ((c = poptGetNextOpt(optCon)) >= 0)
1767 filename = poptGetArg(optCon);
1768 if(!(poptPeekArg(optCon) == NULL))
1769 usage(optCon, 1, "Specify only one file",
1770 ".e.g., filename.gob");
1773 /* an error occurred during option processing */
1774 fprintf(stderr, "%s: %s\n",
1775 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
1781 parse_options(argc,argv);
1784 yyin = fopen(filename,"r");
1786 fprintf(stderr,"Error: can't open file '%s'\n",
1795 g_error("Parsing errors, quitting");
1797 print_error(FALSE," no class defined",0);
1800 exit_on_error = FALSE;
1802 signals = count_signals((Class *)class);
1803 arguments = count_arguments((Class *)class);
1804 overrides = count_overrides((Class *)class);
1805 privates = count_privates((Class *)class);
1808 make_inits((Class *)class);
1810 make_destroy((Class *)class);
1811 check_bad_symbols((Class *)class);
1812 check_duplicate_symbols((Class *)class);
1813 check_duplicate_signals_args((Class *)class);
1814 check_public_new((Class *)class);
1815 check_vararg((Class *)class);
1816 check_firstarg((Class *)class);
1818 exit_on_error = TRUE;
1825 generate_outfiles();
1830 if(no_touch_headers)
1831 compare_and_move_header();
1834 poptFreeContext(optCon);