2 * Copyright (C) 1999,2000 the Free Software Foundation.
3 * Copyright (C) 2000 Eazel, Inc.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
32 #include "treefuncs.h"
40 char *filename = NULL;
49 extern GList *include_files;
51 extern GHashTable *gtk_doc_hash;
54 static char *funcbase;
55 static char *pfuncbase;
56 static char *macrobase;
58 static char *macrotype;
59 static char *typebase;
60 static char *ptypebase;
62 static int signals = 0; /* number of signals */
63 static int arguments = 0; /* number of named arguments */
64 static int overrides = 0; /* number of override methods */
65 static int privates = 0; /* number of private data members */
66 static int protecteds = 0; /* number of protected methods */
67 static int destructors = 0; /* number of variable destructors */
68 static int initializers = 0; /* number of variable initializers */
70 static gboolean made_aliases = FALSE; /* if we made any shorthand aliases
71 and need the REALLY UGLY HACK to
74 /* the special variable types we need to define */
75 static gboolean special_array[SPECIAL_LAST] = {0};
76 static gboolean any_special = FALSE;
78 static gboolean need_destroy = FALSE;
79 static Method * destroy_handler = NULL;
81 static gboolean need_finalize = FALSE;
82 static Method * finalize_handler = NULL;
89 gboolean no_touch_headers = FALSE;
90 gboolean for_cpp = FALSE;
91 gboolean no_gnu = FALSE;
92 gboolean exit_on_warn = FALSE;
93 gboolean exit_on_error = TRUE;
94 gboolean got_error = FALSE;
95 gint private_header = PRIVATE_HEADER_ALWAYS;
96 gboolean no_extern_c = FALSE;
97 gboolean no_write = FALSE;
98 gboolean no_lines = FALSE;
99 gboolean no_self_alias = FALSE;
100 gboolean no_kill_underscores = FALSE;
101 gboolean always_private_struct = FALSE;
103 int method_unique_id = 1;
108 filebase = replace_sep(((Class *)class)->otype, '-');
111 funcbase = replace_sep(((Class *)class)->otype, '_');
114 pfuncbase = replace_sep(((Class *)class)->ptype, '_');
115 g_strdown(pfuncbase);
117 macrobase = replace_sep(((Class *)class)->otype, '_');
120 macrois = make_pre_macro(((Class *)class)->otype, "IS");
121 macrotype = make_pre_macro(((Class *)class)->otype, "TYPE");
123 typebase = remove_sep(((Class *)class)->otype);
125 ptypebase = remove_sep(((Class *)class)->ptype);
129 get_type(Type *t, gboolean postfix_to_stars)
136 s = remove_sep(t->name);
137 gs = g_string_new(s);
141 if(postfix_to_stars) {
143 /*XXX: this is ugly perhaps we can do this whole postfix thing
144 in a nicer way, we just count the number of '[' s and from
145 that we deduce the number of dimensions, so that we can print
147 for(p=t->postfix; p && *p; p++)
148 if(*p == '[') extra++;
150 g_string_append_c(gs, ' ');
153 g_string_append(gs, t->pointer);
154 for(i=0; i < extra; i++)
155 g_string_append_c(gs, '*');
156 g_string_append_c(gs, ' ');
160 g_string_free(gs, FALSE);
165 get_gtk_doc(char *id)
172 val = g_hash_table_lookup(gtk_doc_hash, id);
174 return g_strdup_printf("/**\n * %s_%s:\n%s **/\n",
175 funcbase, get_real_id(id), val);
176 s = g_strconcat(funcbase, "_", get_real_id(id), NULL);
177 val = g_hash_table_lookup(gtk_doc_hash, s);
180 return g_strdup_printf("/**\n * %s_%s:\n%s **/\n",
181 funcbase, get_real_id(id), val);
186 print_type(FILE *fp, Type *t, gboolean postfix_to_stars)
190 s = get_type(t, postfix_to_stars);
191 out_printf(fp, "%s", s);
197 print_method(FILE *fp, char *typeprefix, char *nameprefix,
199 char *namepostfix, char *postfix, Method *m,
200 gboolean one_arg_per_line,
201 gboolean no_funcbase,
202 gboolean kill_underscore)
207 out_printf(fp, "%s", typeprefix);
208 print_type(fp, m->mtype, TRUE);
211 id = get_real_id(m->id);
216 out_printf(fp, "%s%s%s%s(",
217 nameprefix, subnameprefix, id, namepostfix);
219 out_printf(fp, "%s%s_%s%s%s(",
220 nameprefix, funcbase, subnameprefix, id,
224 for(li=m->args; li; li=g_list_next(li)) {
225 FuncArg *arg = li->data;
226 print_type(fp, arg->atype, FALSE);
228 out_printf(fp, "%s%s,%s", arg->name,
230 arg->atype->postfix:"",
231 one_arg_per_line?"\n\t\t\t\t\t":" ");
233 out_printf(fp, "%s%s", arg->name,
235 arg->atype->postfix:"");
238 out_printf(fp, ",%s...",
239 one_arg_per_line?"\n\t\t\t\t\t":" ");
241 out_printf(fp, "void");
243 out_printf(fp, ")%s", postfix);
247 any_method_to_alias(Class *c)
251 for(li=c->nodes;li;li=g_list_next(li)) {
252 Node *node = li->data;
253 if(node->type == METHOD_NODE) {
254 Method *m = (Method *)node;
256 if(m->method == INIT_METHOD ||
257 m->method == CLASS_INIT_METHOD ||
258 m->method == OVERRIDE_METHOD)
269 make_method_gnu_aliases(Class *c)
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->method == INIT_METHOD ||
279 m->method == CLASS_INIT_METHOD ||
280 m->method == OVERRIDE_METHOD)
283 /* in C++ mode don't alias new */
284 if(for_cpp && strcmp(m->id, "new")==0)
287 out_printf(out, "static const typeof(&%s_%s) %s "
288 "__attribute__ ((__unused__)) "
289 "= %s_%s;\n", funcbase, get_real_id(m->id),
290 m->id, funcbase, get_real_id(m->id));
291 out_printf(out, "#define %s(args...) "
292 "%s_%s(##args)\n", m->id,
293 funcbase, get_real_id(m->id));
299 make_method_nongnu_aliases(Class *c)
303 for(li=c->nodes; li; li=g_list_next(li)) {
304 Node *node = li->data;
305 if(node->type == METHOD_NODE) {
306 Method *m = (Method *)node;
308 if(m->method == INIT_METHOD ||
309 m->method == CLASS_INIT_METHOD ||
310 m->method == OVERRIDE_METHOD)
313 /* in C++ mode don't alias new */
314 if(for_cpp && strcmp(m->id, "new")==0)
317 print_method(out, "static ", "(* ", "", ") ", "",
318 m, FALSE, TRUE, FALSE);
319 out_printf(out, " = %s_%s;\n", funcbase,
328 add_bad_hack_to_avoid_unused_warnings(Class *c)
332 /* if we haven't had any methods, just return */
337 out_printf(out, "\n\n#ifndef __GNUC__\n");
339 "/*REALLY BAD HACK\n"
340 " This is to avoid unused warnings if you don't call\n"
341 " some method. I need to find a better way to do\n"
342 " this, not needed in GCC since we use some gcc\n"
343 " extentions to make saner, faster code */\n"
345 "___%s_really_bad_hack_to_avoid_warnings(void)\n"
347 for(li=c->nodes;li;li=g_list_next(li)) {
348 Node *node = li->data;
349 if(node->type == METHOD_NODE) {
350 Method *m = (Method *)node;
352 if(m->method == INIT_METHOD ||
353 m->method == CLASS_INIT_METHOD ||
354 m->method == OVERRIDE_METHOD)
357 /* in C++ mode we don't alias new */
358 if(for_cpp && strcmp(m->id, "new")==0)
361 out_printf(out, "\t((void (*)(void))%s)();\n", m->id);
364 out_printf(out, "\t___%s_really_bad_hack_to_avoid_warnings();\n",
367 out_printf(out, "}\n#endif /* __GNUC__ */\n\n");
369 out_printf(out, "}\n\n");
373 put_variable(Variable *v, FILE *fp)
375 out_printf(fp, "\t");
376 print_type(fp, v->vtype, FALSE);
377 out_printf(fp, "%s%s;", v->id,
379 v->vtype->postfix:"");
380 if(v->scope == PROTECTED_SCOPE)
381 out_printf(fp, " /* protected */");
382 out_printf(fp, "\n");
386 put_vs_method(Method *m)
388 if(m->method != SIGNAL_LAST_METHOD &&
389 m->method != SIGNAL_FIRST_METHOD &&
390 m->method != VIRTUAL_METHOD)
393 /* if a signal mark it as such */
394 if(m->method != VIRTUAL_METHOD)
395 print_method(outh, "\t/*signal*/", "(* ", "", ") ", ";\n",
396 m, FALSE, TRUE, TRUE);
398 print_method(outh, "\t", "(* ", "", ") ", ";\n",
399 m, FALSE, TRUE, TRUE);
403 put_pub_method(Method *m)
405 if(m->scope != PUBLIC_SCOPE)
408 print_method(outh, "", "\t", "", "\t", ";\n", m, TRUE, FALSE, TRUE);
411 /* I'm starting not to like this idea */
414 put_signal_connect(Method *m)
416 if(m->method != SIGNAL_LAST_METHOD &&
417 m->method != SIGNAL_FIRST_METHOD)
420 out_printf(outh, "guint \t%s_%s__connect_full\t(%s *object,\n"
421 "\t\t\t\t\tconst char *name,\n"
422 "\t\t\t\t\tGtkSignalFunc func,\n"
423 "\t\t\t\t\tGtkCallbackMarshal marshal,\n"
424 "\t\t\t\t\tgpointer data,\n"
425 "\t\t\t\t\tGtkDestroyNotify destroy_func,\n"
426 "\t\t\t\t\tgboolean object_signal,\n"
427 "\t\t\t\t\tgboolean after);\n",
428 funcbase, m->id, typebase);
430 out_printf(outh, "#define %s_%s__connect(object,name,func,data) "
431 "%s_%s__connect_full((object),(name),(func),NULL,"
432 "(data),NULL,FALSE,FALSE)\n",
433 funcbase, m->id, funcbase, m->id);
434 out_printf(outh, "#define %s_%s__connect_after(object,name,func,data) "
435 "%s__connect_%s_full((object),(name),(func),NULL,"
436 "(data),NULL,FALSE,TRUE)\n",
437 funcbase, m->id, funcbase, m->id);
439 out_printf(outh, "guint \t%s_%s__connect_while_alive\t(%s *object,\n"
440 "\t\t\t\t\tconst char *name,\n"
441 "\t\t\t\t\tGtkSignalFunc func,\n"
442 "\t\t\t\t\tgpointer data,\n"
443 "\t\t\t\t\tGtkObject *alive_object);\n\n",
444 funcbase, m->id, typebase);
450 put_prot_method(Method *m)
452 if(m->scope != PROTECTED_SCOPE)
456 print_method(outph, "", "\t", "", "\t", ";\n",
457 m, FALSE, FALSE, TRUE);
459 print_method(out, "", "\t", "", "\t", ";\n",
460 m, FALSE, FALSE, TRUE);
464 put_priv_method_prot(Method *m)
466 if(m->method == SIGNAL_LAST_METHOD ||
467 m->method == SIGNAL_FIRST_METHOD ||
468 m->method == VIRTUAL_METHOD) {
471 "static ", "___real_", "", " ", ";\n",
472 m, FALSE, FALSE, TRUE);
474 /* no else, here, it might still have a private prototype, it's not
477 if((m->method == OVERRIDE_METHOD &&
480 char *s = g_strdup_printf("___%x_", (guint)m->unique_id);
481 print_method(out, "static ", s, "", " ",
482 no_gnu?";\n":" G_GNUC_UNUSED;\n",
483 m, FALSE, FALSE, FALSE);
485 } else if(m->scope == PRIVATE_SCOPE ||
486 m->method == INIT_METHOD ||
487 m->method == CLASS_INIT_METHOD)
488 print_method(out, "static ", "", "", " ",
489 no_gnu?";\n":" G_GNUC_UNUSED;\n",
490 m, FALSE, FALSE, TRUE);
494 make_func_arg(char *typename, int is_class, char *name)
501 tn = g_strconcat(typename, ":Class", NULL);
503 tn = g_strdup(typename);
505 type = new_type(tn, g_strdup("*"), NULL);
506 node = new_funcarg((Type *)type, name, NULL);
507 return g_list_prepend(NULL, node);
511 make_inits(Class *cl)
513 int got_class_init = FALSE;
514 int got_init = FALSE;
517 for(li=cl->nodes;li;li=g_list_next(li)) {
519 if(n->type == METHOD_NODE) {
520 Method *m = (Method *)n;
521 if(m->method == INIT_METHOD) {
523 print_error(FALSE, "init defined more then once", m->line_no);
525 } else if(m->method == CLASS_INIT_METHOD) {
527 print_error(FALSE, "class_init defined more then once", m->line_no);
528 got_class_init = TRUE;
532 if(!got_class_init) {
533 node = new_method(NO_SCOPE, CLASS_INIT_METHOD,
534 (Type *)new_type(g_strdup("void"),
536 NULL, NULL, NULL, g_strdup("class_init"),
537 make_func_arg(cl->otype, TRUE, g_strdup("c")),
538 NULL, NULL, NULL, 0, 0, FALSE,
540 cl->nodes = g_list_prepend(cl->nodes, node);
543 node = new_method(NO_SCOPE, INIT_METHOD,
544 (Type *)new_type(g_strdup("void"),
546 NULL, NULL, NULL, g_strdup("init"),
547 make_func_arg(cl->otype, FALSE, g_strdup("o")),
548 NULL, NULL, NULL, 0, 0, FALSE,
550 cl->nodes = g_list_prepend(cl->nodes, node);
555 find_destroy(Class *cl)
559 destroy_handler = NULL;
560 for(li=cl->nodes;li;li=g_list_next(li)) {
562 if(n->type == METHOD_NODE) {
563 Method *m = (Method *)n;
564 if(m->method == OVERRIDE_METHOD &&
565 strcmp(m->id, "destroy")==0) {
566 if(strcmp(m->otype, "Gtk:Object") != 0) {
568 "destroy method override "
569 "of class other then "
573 if(g_list_length(m->args) != 1) {
575 "destroy method override "
576 "with more then one "
588 find_finalize(Class *cl)
592 finalize_handler = NULL;
593 for(li=cl->nodes;li;li=g_list_next(li)) {
595 if(n->type == METHOD_NODE) {
596 Method *m = (Method *)n;
597 if(m->method == OVERRIDE_METHOD &&
598 strcmp(m->id, "finalize")==0) {
599 if(strcmp(m->otype, "Gtk:Object") != 0) {
601 "finalize method override "
602 "of class other then "
606 if(g_list_length(m->args) != 1) {
608 "finalize method override "
609 "with more then one "
613 finalize_handler = m;
621 /* hash of method -> name of signal prototype */
622 static GHashTable *marsh = NULL;
624 /* list of methods with different signal prototypes,
625 we check this list if we can use a signal prototype of a
626 previous signal method, there are only uniques here */
627 static GList *eq_signal_methods = NULL;
629 /* compare a list of strings */
631 is_list_equal(GList *a, GList *b)
633 for(;a && b; a=a->next, b=b->next) {
634 if(strcmp(a->data, b->data)!=0) {
638 /* the the lists were different length */
645 find_same_type_signal(Method *m)
648 for(li=eq_signal_methods;li;li=li->next) {
649 Method *mm = li->data;
650 if(is_list_equal(mm->gtktypes, m->gtktypes))
657 print_signal_marsal_args(Method *m)
659 if(strcmp(m->gtktypes->next->data, "NONE")!=0) {
662 for(i=0, li=m->gtktypes->next;li;
663 i++, li=g_list_next(li)) {
665 out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
666 (char *)li->data, i);
668 out_printf(out, ",\n\t\t(%s)"
669 "GTK_VALUE_%s(args[%d])",
670 get_cast(li->data, FALSE),
671 (char *)li->data, i);
675 out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
680 add_signal_prots(Method *m)
687 if(m->method != SIGNAL_LAST_METHOD &&
688 m->method != SIGNAL_FIRST_METHOD)
692 marsh = g_hash_table_new(NULL, NULL);
694 if(strcmp(m->gtktypes->data, "NONE")==0 &&
695 strcmp(m->gtktypes->next->data, "NONE")==0)
698 /* if we already did a signal prototype just use that */
699 mm = find_same_type_signal(m);
701 s = g_hash_table_lookup(marsh, mm);
702 g_hash_table_insert(marsh, m, s);
706 s = g_strdup_printf("Sig%d", sig++);
708 g_hash_table_insert(marsh, m, s);
709 eq_signal_methods = g_list_prepend(eq_signal_methods, m);
711 /* we know that we'll know all the gtktypes (so get_cast can't fail) */
712 out_printf(out, "\ntypedef %s (*___%s) (%s *, ",
713 get_cast(m->gtktypes->data, FALSE), s, typebase);
715 if(strcmp(m->gtktypes->next->data, "NONE")!=0) {
716 for(li=m->gtktypes->next; li; li=g_list_next(li))
717 out_printf(out, "%s, ", get_cast(li->data, FALSE));
719 out_printf(out, "gpointer);\n");
721 out_printf(out, "\nstatic void\n"
722 "___marshal_%s (GtkObject * object,\n"
723 "\tGtkSignalFunc func,\n"
724 "\tgpointer func_data,\n"
728 if(strcmp(m->gtktypes->data, "NONE")==0) {
729 out_printf(out, "\t___%s rfunc;\n\n"
730 "\trfunc = (___%s)func;\n\n"
731 "\t(*rfunc)((%s *)object", s, s, typebase);
733 const char *retcast = get_cast(m->gtktypes->data, FALSE);
737 "\trfunc = (___%s)func;\n\n"
738 "\tretval = GTK_RETLOC_%s(args[%d]);\n\n"
739 "\t*retval = (*rfunc)((%s *)object",
740 s, retcast, s, (char *)m->gtktypes->data,
741 g_list_length(m->gtktypes)-1, typebase);
743 print_signal_marsal_args(m);
751 out_printf(out, "\n");
753 out_printf(out, "enum {\n");
754 for(li=c->nodes;li;li=g_list_next(li)) {
756 if(n->type == METHOD_NODE) {
757 Method *m = (Method *)n;
758 if(m->method == SIGNAL_LAST_METHOD ||
759 m->method == SIGNAL_FIRST_METHOD) {
760 char *s = g_strdup(get_real_id(m->id));
762 out_printf(out, "\t%s_SIGNAL,\n", s);
767 out_printf(out, "\tLAST_SIGNAL\n};\n\n");
770 out_printf(out, "enum {\n\tARG_0");
771 for(li=c->nodes;li;li=g_list_next(li)) {
773 if(n->type == ARGUMENT_NODE) {
774 Argument *a = (Argument *)n;
775 char *s = g_strdup(a->name);
777 out_printf(out, ",\n\tARG_%s", s);
781 out_printf(out, "\n};\n\n");
786 "static guint object_signals[LAST_SIGNAL] = {0};\n\n");
788 out_printf(out, "/* pointer to the class of our parent */\n");
789 out_printf(out, "static %sClass *parent_class = NULL;\n\n", ptypebase);
795 char *chunk_size = ((Class*)class)->chunk_size;
797 out_printf(out, "guint\n"
798 "%s_get_type (void)\n"
800 "\tstatic guint type = 0;\n\n"
802 "\t\tstatic const GtkTypeInfo info = {\n"
804 "\t\t\tsizeof (%s),\n"
805 "\t\t\tsizeof (%sClass),\n"
806 "\t\t\t(GtkClassInitFunc) %s_class_init,\n"
807 "\t\t\t(GtkObjectInitFunc) %s_init,\n"
808 "\t\t\t/* reserved_1 */ NULL,\n"
809 "\t\t\t/* reserved_2 */ NULL,\n"
810 "\t\t\t(GtkClassInitFunc) NULL\n"
812 "\t\ttype = gtk_type_unique (%s_get_type(), &info);\n",
813 funcbase, typebase, typebase, typebase,
814 funcbase, funcbase, pfuncbase);
816 out_printf(out, "#if %s > 0\n"
817 "\t\tgtk_type_set_chunk_alloc(type,%s);\n"
819 chunk_size, chunk_size);
821 out_printf(out,"\t}\n\n"
827 add_overrides(Class *c, char *oname, gboolean did_base_obj)
833 done = g_hash_table_new(g_str_hash, g_str_equal);
835 s = g_strdup("GtkObject"); /* This was already done */
836 g_hash_table_insert(done, s, s);
837 s = g_strdup("GObject"); /* This was probably already done as well (if using Gtk/Glib 1.3/2.0) */
838 g_hash_table_insert(done, s, s);
840 for(li=c->nodes; li; li=g_list_next(li)) {
843 Method *m = (Method *)n;
844 if(n->type != METHOD_NODE ||
845 m->method != OVERRIDE_METHOD)
848 s = remove_sep(m->otype);
850 if(g_hash_table_lookup(done, s)) {
854 g_hash_table_insert(done, s, s);
856 f = replace_sep(m->otype, '_');
859 out_printf(out, "\t%sClass *%s_class = (%sClass *)%s;\n",
864 g_hash_table_foreach(done, (GHFunc)g_free, NULL);
865 g_hash_table_destroy(done);
869 make_run_signal_flags(Method *m, gboolean last)
883 gs = g_string_new(NULL);
886 g_string_assign(gs, "GTK_RUN_LAST");
888 g_string_assign(gs, "GTK_RUN_FIRST");
890 if(m->scope == PUBLIC_SCOPE)
891 g_string_append(gs, " | GTK_RUN_ACTION");
893 for(li = m->flags; li; li = li->next) {
894 char *flag = li->data;
896 for(i=0;flags[i];i++) {
897 if(strcmp(flags[i], flag)==0)
900 /* if we haven't found it in our list */
903 s = g_strdup_printf("Unknown flag '%s' used, "
904 "perhaps it was misspelled",
906 print_error(TRUE, s, m->line_no);
909 g_string_sprintfa(gs, " | GTK_RUN_%s", flag);
914 g_string_free(gs, FALSE);
921 add_signals(Class *c)
925 out_printf(out, "\n");
926 for(li=c->nodes;li;li=g_list_next(li)) {
928 char *mar, *sig, *flags;
929 gboolean is_none, last = FALSE;
930 Method *m = (Method *)n;
932 if(n->type != METHOD_NODE ||
933 (m->method != SIGNAL_FIRST_METHOD &&
934 m->method != SIGNAL_LAST_METHOD))
937 if(m->method == SIGNAL_FIRST_METHOD)
942 if(g_hash_table_lookup(marsh, m))
943 mar = g_strconcat("___marshal_",
944 (char *)g_hash_table_lookup(marsh, m),
947 mar = g_strdup("gtk_signal_default_marshaller");
949 is_none = (strcmp(m->gtktypes->next->data, "NONE")==0);
951 sig = g_strdup(get_real_id(m->id));
953 flags = make_run_signal_flags(m, last);
954 out_printf(out, "\tobject_signals[%s_SIGNAL] =\n"
955 "\t\tgtk_signal_new (\"%s\",\n"
956 "\t\t\t(GtkSignalRunType)(%s),\n"
957 "\t\t\tGTK_CLASS_TYPE(gtk_object_class),\n"
958 "\t\t\tGTK_SIGNAL_OFFSET (%sClass, %s),\n"
960 "\t\t\tGTK_TYPE_%s, %d",
961 sig, get_real_id(m->id),
963 typebase, get_real_id(m->id), mar,
964 (char *)m->gtktypes->data,
965 is_none?0:g_list_length(m->gtktypes->next));
972 for(l=m->gtktypes->next;l;l=g_list_next(l))
973 out_printf(out, ",\n\t\t\tGTK_TYPE_%s",
977 out_printf(out, ");\n");
979 out_printf(out, "\tgtk_object_class_add_signals (gtk_object_class,\n"
980 "\t\tobject_signals, LAST_SIGNAL);\n\n");
984 set_def_handlers(Class *c, char *oname)
987 gboolean set_line = FALSE;
989 out_printf(out, "\n");
990 for(li = c->nodes; li; li = g_list_next(li)) {
992 Method *m = (Method *)n;
994 if(n->type != METHOD_NODE ||
995 (m->method != SIGNAL_FIRST_METHOD &&
996 m->method != SIGNAL_LAST_METHOD &&
997 m->method != VIRTUAL_METHOD &&
998 m->method != OVERRIDE_METHOD))
1001 if(m->line_no > 0 && m->cbuf) {
1002 out_addline_infile(out, m->line_no);
1004 } else if(set_line) {
1005 out_addline_outfile(out);
1010 if(m->method == OVERRIDE_METHOD) {
1012 s = replace_sep(m->otype, '_');
1017 strcmp(m->id, "destroy") == 0)
1018 out_printf(out, "\tgtk_object_class->destroy "
1020 else if(need_finalize &&
1022 strcmp(m->id, "finalize") == 0)
1024 "#ifdef G_OBJECT_CLASS\n"
1025 "\tg_object_class->finalize = ___finalize;\n"
1026 "#else /* !G_OBJECT_CLASS */\n"
1027 "\tgtk_object_class->finalize = ___finalize;\n"
1028 "#endif /* G_OBJECT_CLASS */\n");
1031 "\t%s_class->%s = ___%x_%s_%s;\n",
1032 s, m->id, (guint)m->unique_id,
1035 out_printf(out, "\t%s_class->%s = NULL;\n",
1039 out_printf(out, "\t%s->%s = ___real_%s_%s;\n",
1040 oname, get_real_id(m->id),
1041 funcbase, get_real_id(m->id));
1043 out_printf(out, "\t%s->%s = NULL;\n",
1044 oname, get_real_id(m->id));
1048 out_addline_outfile(out);
1052 make_arguments(Class *c)
1055 char *argflags[] = {
1063 out_printf(out, "\n");
1064 for(li=c->nodes;li;li=g_list_next(li)) {
1070 if(n->type != ARGUMENT_NODE)
1075 if(a->get && a->set)
1076 flags = g_string_new("GTK_ARG_READWRITE");
1078 flags = g_string_new("GTK_ARG_READABLE");
1080 flags = g_string_new("GTK_ARG_WRITABLE");
1082 for(l=a->flags;l;l=g_list_next(l)) {
1083 char *flag = l->data;
1085 if(strcmp(flag, "READWRITE")==0 ||
1086 strcmp(flag, "READABLE")==0 ||
1087 strcmp(flag, "WRITABLE")==0) {
1088 print_error(TRUE, "READWRITE, READABLE and "
1089 "WRITABLE argument flags are "
1090 "set automatically", a->line_no);
1093 for(i=0;argflags[i];i++) {
1094 if(strcmp(argflags[i], flag)==0)
1097 /* if we haven't found it in our list */
1100 s = g_strdup_printf("Unknown flag '%s' used, "
1101 "perhaps it was misspelled",
1103 print_error(TRUE, s, a->line_no);
1106 g_string_sprintfa(flags, " | GTK_ARG_%s", flag);
1109 s = g_strdup(a->name);
1111 out_printf(out, "\tgtk_object_add_arg_type(\"%s::%s\",\n"
1112 "\t\tGTK_TYPE_%s,\n"
1115 typebase, a->name, a->gtktype, flags->str, s);
1117 g_string_free(flags, TRUE);
1121 "\n\tgtk_object_class->set_arg = ___object_set_arg;\n"
1122 "\tgtk_object_class->get_arg = ___object_get_arg;\n");
1126 print_initializer(Method *m, Variable *v)
1130 if(v->initializer == NULL)
1133 if(v->scope == PRIVATE_SCOPE)
1134 root = g_strconcat(((FuncArg *)m->args->data)->name,
1137 root = g_strdup(((FuncArg *)m->args->data)->name);
1139 if(v->initializer_line > 0)
1140 out_addline_infile(out, v->initializer_line);
1142 out_printf(out, "\t%s->%s = %s;\n",
1143 root, v->id, v->initializer);
1145 if(v->initializer_line > 0)
1146 out_addline_outfile(out);
1152 print_destructor(Variable *v)
1156 if(v->destructor == NULL)
1159 if(v->scope == PRIVATE_SCOPE)
1160 root = "self->_priv";
1164 if(v->destructor_simple) {
1165 if(v->destructor_line > 0)
1166 out_addline_infile(out, v->destructor_line);
1168 out_printf(out, "\tif(%s->%s) { "
1169 "((*(void (*)(void *))%s)) (%s->%s); "
1170 "%s->%s = NULL; }\n",
1171 root, v->id, v->destructor, root, v->id,
1174 if(v->destructor_line > 0)
1175 out_addline_outfile(out);
1177 out_printf(out, "#define VAR (%s->%s)\n", root, v->id);
1178 out_printf(out, "\t{\n");
1179 if(v->destructor_line > 0)
1180 out_addline_infile(out, v->destructor_line);
1182 out_printf(out, "\t%s}\n", v->destructor);
1184 if(v->destructor_line > 0)
1185 out_addline_outfile(out);
1186 out_printf(out, "\tmemset(&VAR, 0, sizeof(VAR));\n");
1187 out_printf(out, "#undef VAR\n");
1192 add_destroy(Class *c)
1194 out_printf(out, "\nstatic void\n"
1195 "___destroy(GtkObject *obj_self)\n"
1198 "#define __GOB_FUNCTION__ \"%s::destroy\"\n",
1201 if(destructors > 0) {
1202 out_printf(out, "\t%s *self G_GNUC_UNUSED = %s (obj_self);\n",
1203 typebase, macrobase);
1206 if(destroy_handler) {
1207 /* so we get possible bad argument warning */
1208 if(destroy_handler->line_no > 0)
1209 out_addline_infile(out, destroy_handler->line_no);
1210 out_printf(out, "\t___%x_%s_destroy(obj_self);\n",
1211 (guint)destroy_handler->unique_id, funcbase);
1212 if(destroy_handler->line_no > 0)
1213 out_addline_outfile(out);
1216 "\tif(GTK_OBJECT_CLASS(parent_class)->destroy) \\\n"
1217 "\t\t(* GTK_OBJECT_CLASS(parent_class)->destroy)(obj_self);\n");
1220 if(destructors > 0) {
1222 for(li = ((Class *)class)->nodes;
1226 Variable *v = (Variable *)n;
1227 if(n->type == VARIABLE_NODE &&
1228 v->scope != CLASS_SCOPE)
1229 print_destructor(v);
1233 out_printf(out, "}\n"
1234 "#undef __GOB_FUNCTION__\n\n");
1238 add_finalize(Class *c)
1240 /* Sort of a hack to make it work with gtk+ 1.3/2.0 */
1242 "\n#ifdef G_OBJECT_CLASS\n"
1244 "___finalize(GObject *obj_self)\n"
1245 "#else /* !G_OBJECT_CLASS */\n"
1247 "___finalize(GtkObject *obj_self)\n"
1248 "#endif /* G_OBJECT_CLASS */\n"
1251 "#define __GOB_FUNCTION__ \"%s::finalize\"\n",
1255 out_printf(out, "\t%s *self = %s (obj_self);\n",
1256 typebase, macrobase);
1259 if(finalize_handler) {
1260 /* so we get possible bad argument warning */
1261 if(finalize_handler->line_no > 0)
1262 out_addline_infile(out, finalize_handler->line_no);
1263 out_printf(out, "\t___%x_%s_finalize(obj_self);\n",
1264 (guint)finalize_handler->unique_id, funcbase);
1265 if(finalize_handler->line_no > 0)
1266 out_addline_outfile(out);
1268 /* Sort of a hack to make it work with gtk+ 1.3/2.0 */
1270 "#ifdef G_OBJECT_CLASS\n"
1271 "\tif(G_OBJECT_CLASS(parent_class)->finalize) \\\n"
1272 "\t\t(* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);\n"
1273 "#else /* !G_OBJECT_CLASS */\n"
1274 "\tif(GTK_OBJECT_CLASS(parent_class)->finalize) \\\n"
1275 "\t\t(* GTK_OBJECT_CLASS(parent_class)->finalize)(obj_self);\n"
1276 "#endif /* G_OBJECT_CLASS */\n");
1280 out_printf(out, "\tg_free (self->_priv);\n"
1281 "\tself->_priv = NULL;\n");
1284 out_printf(out, "}\n"
1285 "#undef __GOB_FUNCTION__\n\n");
1292 for(li=c->nodes;li;li=g_list_next(li)) {
1295 if(n->type != METHOD_NODE)
1298 if(m->method == INIT_METHOD) {
1300 out_addline_infile(out, m->line_no);
1301 print_method(out, "static ", "\n", "", " ", "\n",
1302 m, FALSE, FALSE, TRUE);
1304 out_addline_outfile(out);
1305 out_printf(out, "{\n"
1306 "#define __GOB_FUNCTION__ \"%s::init\"\n",
1309 out_printf(out, "\t%s->_priv = "
1310 "g_new0 (%sPrivate, 1);\n",
1311 ((FuncArg *)m->args->data)->name,
1313 } else if(always_private_struct) {
1314 out_printf(out, "\t%s->_priv = NULL;\n",
1315 ((FuncArg *)m->args->data)->name);
1317 if(initializers > 0) {
1319 for(li = ((Class *)class)->nodes;
1323 Variable *v = (Variable *)n;
1324 if(n->type != VARIABLE_NODE ||
1325 v->scope == CLASS_SCOPE)
1327 print_initializer(m, v);
1330 } else if(m->method == CLASS_INIT_METHOD) {
1331 gboolean did_base_obj = FALSE;
1334 out_addline_infile(out, m->line_no);
1335 print_method(out, "static ", "\n", "", " ", "\n",
1336 m, FALSE, FALSE, TRUE);
1338 out_addline_outfile(out);
1339 out_printf(out, "{\n"
1340 "#define __GOB_FUNCTION__ \"%s::class_init\"\n",
1347 "\tGtkObjectClass *"
1348 "gtk_object_class G_GNUC_UNUSED = "
1349 "(GtkObjectClass*) %s;\n",
1350 ((FuncArg *)m->args->data)->name);
1352 "#ifdef G_OBJECT_CLASS\n"
1354 "g_object_class G_GNUC_UNUSED = "
1355 "(GObjectClass*) %s;\n"
1356 "#endif /* G_OBJECT_CLASS */\n",
1357 ((FuncArg *)m->args->data)->name);
1358 did_base_obj = TRUE;
1363 ((FuncArg *)m->args->data)->name,
1366 if(initializers > 0) {
1368 for(li = ((Class *)class)->nodes;
1372 Variable *v = (Variable *)n;
1373 if(n->type != VARIABLE_NODE ||
1374 v->scope != CLASS_SCOPE)
1376 print_initializer(m, v);
1380 out_printf(out, "\n\tparent_class = ");
1382 out_printf(out, "(%sClass *)", ptypebase);
1383 out_printf(out, "gtk_type_class (%s_get_type ());\n",
1389 set_def_handlers(c, ((FuncArg *)m->args->data)->name);
1391 /* if there are no handlers for these things, we
1392 * need to set them up here */
1393 if(need_destroy && !destroy_handler)
1394 out_printf(out, "\tgtk_object_class->destroy "
1396 if(need_finalize && !finalize_handler)
1398 "#ifdef G_OBJECT_CLASS\n"
1399 "\tg_object_class->finalize = ___finalize;\n"
1400 "#else /* !G_OBJECT_CLASS */\n"
1401 "\tgtk_object_class->finalize = ___finalize;\n"
1402 "#endif /* G_OBJECT_CLASS */\n");
1411 out_printf(out, " {\n");
1412 out_addline_infile(out, m->ccode_line);
1413 out_printf(out, "%s\n", m->cbuf);
1414 out_addline_outfile(out);
1415 out_printf(out, " }\n");
1417 out_printf(out, "return;\n");
1419 out_printf(out, "}\n"
1420 "#undef __GOB_FUNCTION__\n");
1425 add_getset_arg(Class *c, gboolean is_set)
1428 out_printf(out, "\nstatic void\n"
1429 "___object_%s_arg (GtkObject *object,\n"
1432 "#define __GOB_FUNCTION__ \"%s::%s_arg\"\n"
1435 "\tself = %s (object);\n\n"
1436 "\tswitch (arg_id) {\n",
1437 is_set ? "set" : "get",
1438 c->otype, is_set ? "set" : "get",
1439 typebase, macrobase);
1441 for(li=c->nodes;li;li=g_list_next(li)) {
1447 if(n->type != ARGUMENT_NODE)
1452 line_no = a->set_line;
1455 line_no = a->get_line;
1459 s = g_strdup(a->name);
1461 out_printf(out, "\tcase ARG_%s:\n", s);
1462 if(is_set && a->atype) {
1463 char *cast = get_type(a->atype, TRUE);
1464 if(no_gnu || for_cpp) {
1465 out_printf(out, "#define ARG "
1466 "((%s)GTK_VALUE_%s(*arg))\n",
1469 out_printf(out, "#ifdef __GNUC__\n");
1470 if(strcmp(a->gtktype, "OBJECT")==0) {
1471 out_printf(out, "#define ARG "
1473 "GTK_VALUE_POINTER(*arg); "
1477 out_printf(out, "#define ARG "
1479 "GTK_VALUE_%s(*arg); "
1483 out_printf(out, "#else /* __GNUC__ */\n");
1484 out_printf(out, "#define ARG "
1485 "((%s)GTK_VALUE_%s(*arg))\n",
1487 out_printf(out, "#endif /* __GNUC__ */\n\n");
1489 out_printf(out, "\t\t{\n");
1491 } else if(!is_set && strcmp(a->gtktype, "OBJECT")==0) {
1493 "#define ARG (GTK_VALUE_POINTER(*arg))\n"
1497 "#define ARG (GTK_VALUE_%s(*arg))\n"
1503 out_addline_infile(out, line_no);
1504 out_printf(out, "%s\n", cbuf);
1506 out_addline_outfile(out);
1507 out_printf(out, "\t\t}\n\t\tbreak;\n"
1510 out_printf(out, "\tdefault:\n\t\tbreak;\n\t}\n}\n"
1511 "#undef __GOB_FUNCTION__\n");
1515 print_checks(Method *m, FuncArg *fa)
1519 gboolean checked_null = FALSE;
1520 is_void = (strcmp(m->mtype->name, "void")==0 &&
1521 m->mtype->pointer == NULL);
1523 for(li = fa->checks; li; li = g_list_next(li)) {
1524 Check *ch = li->data;
1526 /* point to the method prot in .gob for failed checks */
1528 out_addline_infile(out, m->line_no);
1530 out_printf(out, "\tg_return_if_fail (");
1532 out_printf(out, "\tg_return_val_if_fail (");
1533 switch(ch->chtype) {
1535 out_printf(out, "%s != NULL", fa->name);
1536 checked_null = TRUE;
1539 s = make_pre_macro(fa->atype->name, "IS");
1541 out_printf(out, "%s (%s)", s, fa->name);
1543 /* if not check null, null may be valid */
1544 out_printf(out, "!(%s) || %s (%s)", fa->name,
1549 out_printf(out, "%s < %s", fa->name, ch->number);
1552 out_printf(out, "%s > %s", fa->name, ch->number);
1555 out_printf(out, "%s <= %s", fa->name, ch->number);
1558 out_printf(out, "%s >= %s", fa->name, ch->number);
1561 out_printf(out, "%s == %s", fa->name, ch->number);
1564 out_printf(out, "%s != %s", fa->name, ch->number);
1568 out_printf(out, ");\n");
1570 out_printf(out, ", (");
1571 print_type(out, m->mtype, TRUE);
1572 out_printf(out, ")%s);\n",
1573 m->onerror?m->onerror:"0");
1579 print_preconditions(Method *m)
1583 for(li=m->args;li;li=g_list_next(li)) {
1584 FuncArg *fa = li->data;
1586 print_checks(m, fa);
1589 out_addline_outfile(out);
1593 print_method_body(Method *m, int pre)
1595 out_printf(out, "{\n"
1596 "#define __GOB_FUNCTION__ \"%s::%s\"\n",
1597 ((Class *)class)->otype,
1598 get_real_id(m->id));
1600 print_preconditions(m);
1602 /* Note: the trailing }'s are on one line, this is so
1603 that we get the no return warning correctly and point to
1604 the correct line in the .gob file, yes this is slightly
1605 ugly in the .c file, but that is not supposed to be
1606 human readable anyway. */
1608 out_printf(out, "{\n");
1610 out_addline_infile(out, m->ccode_line);
1611 out_printf(out, "\t%s}", m->cbuf);
1614 /* Note, there is no \n between the last } and this } so that
1615 * errors/warnings reported on the end of the body get pointed to the
1616 * right line in the .gob source */
1617 out_printf(out, "}\n");
1620 out_addline_outfile(out);
1621 out_printf(out, "#undef __GOB_FUNCTION__\n");
1625 put_signal_args(Method *m)
1629 for(ali = m->gtktypes->next, li=m->args->next;
1631 li=li->next, ali=ali->next) {
1632 FuncArg *fa = li->data;
1633 const char *cast = get_cast(ali->data, FALSE);
1634 /* we should have already proved before that
1635 the we know all the types */
1638 out_printf(out, ",\n\t\t(%s)%s", cast,
1644 get_arg_names_for_macro(Method *m)
1648 GString *gs = g_string_new(NULL);
1650 for(li=m->args;li;li=g_list_next(li)) {
1651 FuncArg *arg = li->data;
1652 g_string_sprintfa(gs, "%s___%s", p, arg->name);
1656 g_string_free(gs, FALSE);
1661 put_method(Method *m)
1663 char *s, *args, *doc;
1665 is_void = (strcmp(m->mtype->name, "void")==0 &&
1666 m->mtype->pointer == NULL);
1667 out_printf(out, "\n");
1668 if(m->method != OVERRIDE_METHOD) {
1669 doc = get_gtk_doc(m->id);
1671 out_printf(out, "%s", doc);
1676 case REGULAR_METHOD:
1678 out_addline_infile(out, m->line_no);
1679 if(m->scope == PRIVATE_SCOPE)
1680 print_method(out, "static ", "\n", "", " ", "\n",
1681 m, FALSE, FALSE, TRUE);
1682 else /* PUBLIC, PROTECTED */
1683 print_method(out, "", "\n", "", " ", "\n",
1684 m, FALSE, FALSE, TRUE);
1685 print_method_body(m, TRUE);
1686 /* the outfile line was added above */
1688 case SIGNAL_FIRST_METHOD:
1689 case SIGNAL_LAST_METHOD:
1691 out_addline_infile(out, m->line_no);
1692 if(m->scope == PRIVATE_SCOPE)
1693 print_method(out, "static ", "\n", "", " ", "\n",
1694 m, FALSE, FALSE, TRUE);
1695 else /* PUBLIC, PROTECTED */
1696 print_method(out, "", "\n", "", " ", "\n",
1697 m, FALSE, FALSE, TRUE);
1698 out_addline_outfile(out);
1699 out_printf(out, "{\n");
1700 s = g_strdup(get_real_id(m->id));
1702 if(strcmp(m->mtype->name, "void") == 0 &&
1703 m->mtype->pointer == NULL) {
1704 print_preconditions(m);
1705 if(((FuncArg *)m->args->data)->name)
1706 out_printf(out, "\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1707 "\t\tobject_signals[%s_SIGNAL]",
1708 ((FuncArg *)m->args->data)->name, s);
1710 out_printf(out, ");\n}\n");
1712 out_printf(out, "\t");
1713 print_type(out, m->mtype, TRUE);
1714 out_printf(out, "return_val = (");
1715 print_type(out, m->mtype, TRUE);
1717 out_printf(out, ")(%s);\n", m->defreturn);
1719 out_printf(out, ")(%s);\n", m->onerror);
1721 out_printf(out, ")(0);\n");
1722 print_preconditions(m);
1723 out_printf(out, "\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1724 "\t\tobject_signals[%s_SIGNAL]",
1725 ((FuncArg *)m->args->data)->name, s);
1727 out_printf(out, ",\n\t\t&return_val);\n"
1728 "\treturn return_val;\n}\n");
1734 out_addline_infile(out, m->line_no);
1735 print_method(out, "static ", "\n___real_", "", " ", "\n",
1736 m, FALSE, FALSE, TRUE);
1737 print_method_body(m, FALSE);
1738 /* the outfile line was added above */
1740 case VIRTUAL_METHOD:
1742 out_addline_infile(out, m->line_no);
1743 if(m->scope==PRIVATE_SCOPE)
1744 print_method(out, "static ", "\n", "", " ", "\n",
1745 m, FALSE, FALSE, TRUE);
1746 else /* PUBLIC, PROTECTED */
1747 print_method(out, "", "\n", "", " ", "\n",
1748 m, FALSE, FALSE, TRUE);
1749 out_addline_outfile(out);
1750 out_printf(out, "{\n"
1751 "\t%sClass *klass;\n", typebase);
1752 print_preconditions(m);
1753 out_printf(out, "\tklass = %s_GET_CLASS(%s);\n\n"
1754 "\tif(klass->%s)\n",
1755 macrobase, ((FuncArg *)m->args->data)->name,
1756 get_real_id(m->id));
1757 if(strcmp(m->mtype->name, "void") == 0 &&
1758 m->mtype->pointer == NULL) {
1760 out_printf(out, "\t\t(*klass->%s)(%s",
1762 ((FuncArg *)m->args->data)->name);
1763 for(li=m->args->next;li;li=g_list_next(li)) {
1764 FuncArg *fa = li->data;
1765 out_printf(out, ",%s", fa->name);
1767 out_printf(out, ");\n}\n");
1770 out_printf(out, "\t\treturn (*klass->%s)(%s",
1772 ((FuncArg *)m->args->data)->name);
1773 for(li=m->args->next;li;li=g_list_next(li)) {
1774 FuncArg *fa = li->data;
1775 out_printf(out, ",%s", fa->name);
1777 out_printf(out, ");\n"
1780 print_type(out, m->mtype, TRUE);
1782 out_printf(out, ")(%s);\n}\n", m->defreturn);
1784 out_printf(out, ")(%s);\n}\n", m->onerror);
1786 out_printf(out, ")(0);\n}\n");
1792 out_addline_infile(out, m->line_no);
1793 print_method(out, "static ", "\n___real_", "", " ", "\n",
1794 m, FALSE, FALSE, TRUE);
1795 print_method_body(m, FALSE);
1796 /* the outfile line was added above */
1798 case OVERRIDE_METHOD:
1802 out_addline_infile(out, m->line_no);
1803 s = g_strdup_printf("\n___%x_", (guint)m->unique_id);
1804 print_method(out, "static ", s, "", " ", "\n",
1805 m, FALSE, FALSE, FALSE);
1807 out_addline_outfile(out);
1808 s = replace_sep(m->otype, '_');
1810 args = get_arg_names_for_macro(m);
1812 out_printf(out, "#define PARENT_HANDLER(%s) \\\n"
1813 "\t{ if(%s_CLASS(parent_class)->%s) \\\n"
1814 "\t\t(* %s_CLASS(parent_class)->%s)(%s); }\n",
1815 args, s, m->id, s, m->id, args);
1817 out_printf(out, "#define PARENT_HANDLER(%s) \\\n"
1818 "\t((%s_CLASS(parent_class)->%s)? \\\n"
1819 "\t\t(* %s_CLASS(parent_class)->%s)(%s): \\\n"
1821 args, s, m->id, s, m->id, args);
1822 out_printf(out, "(");
1823 print_type(out, m->mtype, TRUE);
1824 out_printf(out, ")%s))\n",
1825 m->onerror?m->onerror:"0");
1829 print_method_body(m, TRUE);
1830 /* the outfile line was added above */
1831 out_printf(out, "#undef PARENT_HANDLER\n");
1841 char *outfile, *outfileh, *outfileph;
1844 outfile = g_strconcat(filebase, ".c", NULL);
1846 outfile = g_strconcat(filebase, ".cc", NULL);
1847 if(no_touch_headers)
1848 outfileh = g_strconcat("#gob#", filebase, ".h#gob#", NULL);
1850 outfileh = g_strconcat(filebase, ".h", NULL);
1852 if((privates > 0 || protecteds > 0 ||
1853 private_header == PRIVATE_HEADER_ALWAYS) &&
1854 private_header != PRIVATE_HEADER_NEVER)
1855 outfileph = g_strconcat(filebase, "-private.h", NULL);
1861 devnull = fopen("/dev/null", "w");
1863 g_error("Cannot open null device");
1869 out = fopen(outfile, "w");
1871 g_error("Cannot open outfile: %s", outfile);
1873 outh = fopen(outfileh, "w");
1875 g_error("Cannot open outfile: %s", outfileh);
1877 outph = fopen(outfileph, "w");
1879 g_error("Cannot open outfile: %s", outfileh);
1885 put_argument_nongnu_wrappers(Class *c)
1892 for(li=c->nodes;li;li=g_list_next(li)) {
1894 Argument *a = (Argument *)n;
1898 if(n->type != ARGUMENT_NODE)
1901 aname = g_strdup(a->name);
1905 cast = get_type(a->atype, TRUE);
1907 cast = g_strdup(get_cast(a->gtktype, TRUE));
1911 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1912 "\"%s\",(%s)(arg)\n",
1913 macrobase, aname, a->name, cast);
1915 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1916 "\"%s\",(%s*)(arg)\n",
1917 macrobase, aname, a->name, cast);
1920 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1922 macrobase, aname, a->name);
1924 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1926 macrobase, aname, a->name);
1934 put_argument_gnu_wrappers(Class *c)
1941 for(li=c->nodes;li;li=g_list_next(li)) {
1943 Argument *a = (Argument *)n;
1946 if(n->type != ARGUMENT_NODE)
1948 s = g_strdup(a->name);
1951 cast = get_type(a->atype, TRUE);
1953 cast = g_strdup(get_cast(a->gtktype, TRUE));
1956 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1957 "\"%s\",({%sz = (arg); z;})\n",
1958 macrobase, s, a->name, cast);
1960 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1961 "\"%s\",({%s*z = (arg); z;})\n",
1962 macrobase, s, a->name, cast);
1965 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1967 macrobase, s, a->name);
1969 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1971 macrobase, s, a->name);
1979 print_ccode_block(CCode *cc)
1982 switch(cc->cctype) {
1984 /* HT code is printed exactly like normal header
1985 code but is printed before */
1988 out_printf(fp, "\n");
1991 /* AT code is printed exactly like normal 'all'
1992 code but is printed before */
1995 out_printf(outph, "\n");
1996 out_printf(outph, "%s\n", cc->cbuf);
1997 out_addline_infile(outph, cc->line_no);
1998 out_addline_outfile(outph);
2000 out_printf(outh, "\n");
2001 out_printf(outh, "%s\n", cc->cbuf);
2003 out_printf(fp, "\n");
2004 out_addline_infile(fp, cc->line_no);
2009 out_printf(fp, "\n");
2010 out_addline_infile(fp, cc->line_no);
2017 out_printf(fp, "\n");
2018 out_addline_infile(fp, cc->line_no);
2021 out_printf(fp, "%s\n", cc->cbuf);
2022 if(cc->cctype == C_CCODE ||
2023 cc->cctype == A_CCODE ||
2024 cc->cctype == AT_CCODE ||
2025 cc->cctype == PH_CCODE)
2026 out_addline_outfile(fp);
2030 print_class_block(Class *c)
2034 gboolean printed_private = FALSE;
2037 out_printf(out, "/* utility types we may need */\n");
2038 if(special_array[SPECIAL_2POINTER])
2039 out_printf(out, "typedef struct { "
2040 "gpointer a; gpointer b; "
2041 "} ___twopointertype;\n");
2042 if(special_array[SPECIAL_3POINTER])
2043 out_printf(out, "typedef struct { "
2044 "gpointer a; gpointer b; "
2046 "} ___threepointertype;\n");
2047 if(special_array[SPECIAL_INT_POINTER])
2048 out_printf(out, "typedef struct { "
2049 "gint a; gpointer b; "
2050 "} ___intpointertype;\n");
2051 out_printf(out, "\n");
2054 out_printf(outh, "\n/*\n"
2055 " * Type checking and casting macros\n"
2057 out_printf(outh, "#define %s\t"
2058 "(%s_get_type())\n",
2059 macrotype, funcbase);
2060 out_printf(outh, "#define %s(obj)\t"
2061 "GTK_CHECK_CAST((obj), %s_get_type(), %s)\n",
2062 macrobase, funcbase, typebase);
2063 out_printf(outh, "#define %s_CONST(obj)\t"
2064 "GTK_CHECK_CAST((obj), %s_get_type(), %s const)\n",
2065 macrobase, funcbase, typebase);
2066 out_printf(outh, "#define %s_CLASS(klass)\t"
2067 "GTK_CHECK_CLASS_CAST((klass), %s_get_type(), %sClass)\n",
2068 macrobase, funcbase, typebase);
2069 out_printf(outh, "#define %s(obj)\t"
2070 "GTK_CHECK_TYPE((obj), %s_get_type ())\n\n",
2072 out_printf(outh, "#ifdef GTK_CHECK_GET_CLASS\n"
2073 "#define %s_GET_CLASS(obj)\t"
2074 "GTK_CHECK_GET_CLASS((obj), %s_get_type(), %sClass)\n",
2075 macrobase, funcbase, typebase);
2076 out_printf(outh, "#else /* !GTK_CHECK_GET_CLASS */\n"
2077 "#define %s_GET_CLASS(obj)\t"
2078 "((%sClass *)GTK_OBJECT(obj)->klass)\n"
2079 "#endif /* GTK_CHECK_GET_CLASS */\n",
2080 macrobase, typebase);
2082 if( ! no_self_alias) {
2083 out_printf(out, "/* self casting macros */\n");
2084 out_printf(out, "#define SELF(x) %s(x)\n", macrobase);
2085 out_printf(out, "#define SELF_CONST(x) %s_CONST(x)\n", macrobase);
2086 out_printf(out, "#define IS_SELF(x) %s(x)\n", macrois);
2087 out_printf(out, "#define SELF_CLASS(x) %s_CLASS(x)\n\n",
2089 out_printf(out, "#define SELF_GET_CLASS(x) %s_GET_CLASS(x)\n\n",
2092 out_printf(out, "/* self typedefs */\n");
2093 out_printf(out, "typedef %s Self;\n", typebase);
2094 out_printf(out, "typedef %sClass SelfClass;\n\n", typebase);
2097 out_printf(out, "/* GTK_CLASS_TYPE for 1.2<->1.3/2.0 GTK+ compatibility */\n");
2099 "#ifndef GTK_CLASS_TYPE\n"
2100 "#define GTK_CLASS_TYPE(x) (GTK_OBJECT_CLASS(x)->type)\n"
2101 "#endif /* GTK_CLASS_TYPE */\n\n");
2103 if(privates > 0 || always_private_struct) {
2104 out_printf(outh, "\n/* Private structure type */\n");
2105 out_printf(outh, "typedef struct _%sPrivate %sPrivate;\n",
2106 typebase, typebase);
2108 out_printf(outh, "/* There are no privates, this "
2109 "structure is thus never defined */\n");
2112 out_printf(outh, "\n/*\n"
2113 " * Main object structure\n"
2115 s = replace_sep(c->otype, '_');
2117 out_printf(outh, "#ifndef __TYPEDEF_%s__\n"
2118 "#define __TYPEDEF_%s__\n", s, s);
2120 out_printf(outh, "typedef struct _%s %s;\n"
2121 "#endif\n", typebase, typebase);
2122 out_printf(outh, "struct _%s {\n\t%s __parent__;\n",
2123 typebase, ptypebase);
2124 for(l=c->nodes; l; l=g_list_next(l)) {
2125 static gboolean printed_public = FALSE;
2127 Variable *v = (Variable *)n;
2128 if(n->type == VARIABLE_NODE &&
2129 v->scope == PUBLIC_SCOPE) {
2130 if( ! printed_public) {
2131 out_printf(outh, "\t/*< public >*/\n");
2132 printed_public = TRUE;
2134 put_variable((Variable *)n, outh);
2137 /* put protecteds always AFTER publics */
2138 for(l=c->nodes; l; l=g_list_next(l)) {
2140 Variable *v = (Variable *)n;
2141 if(n->type == VARIABLE_NODE &&
2142 v->scope == PROTECTED_SCOPE) {
2143 if( ! printed_private) {
2144 out_printf(outh, "\t/*< private >*/\n");
2145 printed_private = TRUE;
2147 put_variable((Variable *)n, outh);
2150 if(privates > 0 || always_private_struct) {
2151 if( ! printed_private)
2152 out_printf(outh, "\t/*< private >*/\n");
2153 out_printf(outh, "\t%sPrivate *_priv;\n", typebase);
2155 out_printf(outh, "};\n");
2160 /* if we are to stick this into the private
2161 header, if not stick it directly into the
2168 out_printf(outfp, "struct _%sPrivate {\n",
2170 for(l=c->nodes; l; l=l->next) {
2172 Variable *v = (Variable *)n;
2173 if(n->type == VARIABLE_NODE &&
2174 v->scope == PRIVATE_SCOPE) {
2175 out_addline_infile(outfp, v->line_no);
2176 put_variable(v, outfp);
2179 out_addline_outfile(outfp);
2180 out_printf(outfp, "};\n");
2183 out_printf(outh, "\n/*\n"
2184 " * Class definition\n"
2186 out_printf(outh, "typedef struct _%sClass %sClass;\n",
2187 typebase, typebase);
2189 "struct _%sClass {\n\t%sClass __parent__;\n",
2190 typebase, ptypebase);
2191 for(l = c->nodes; l != NULL; l = l->next) {
2193 if(n->type == METHOD_NODE)
2194 put_vs_method((Method *)n);
2196 /* put class scope variables */
2197 for(l = c->nodes; l != NULL; l = l->next) {
2199 Variable *v = (Variable *)n;
2200 if(n->type == VARIABLE_NODE &&
2201 v->scope == CLASS_SCOPE)
2202 put_variable((Variable *)n, outh);
2204 out_printf(outh, "};\n\n");
2206 out_printf(out, "/* here are local prototypes */\n");
2208 out_printf(out, "static void ___object_set_arg "
2209 "(GtkObject *object, GtkArg *arg, "
2211 "static void ___object_get_arg "
2212 "(GtkObject *object, GtkArg *arg, "
2213 "guint arg_id);\n");
2216 out_printf(outh, "\n/*\n"
2217 " * Public methods\n"
2220 out_printf(outh, "guint\t%s_get_type\t(void);\n", funcbase);
2221 for(l = c->nodes; l != NULL; l = l->next) {
2223 if(n->type == METHOD_NODE) {
2224 put_pub_method((Method *)n);
2225 put_prot_method((Method *)n);
2226 put_priv_method_prot((Method *)n);
2230 /* this idea is less and less apealing to me */
2232 if(!no_signal_connect) {
2234 out_printf(outh, "\n/*\n"
2235 " * Signal connection methods\n"
2239 for(l=c->nodes;l;l=g_list_next(l)) {
2241 if(n->type == METHOD_NODE)
2242 put_signal_connect((Method *)n);
2248 /* argument wrapping macros */
2249 if(arguments > 0 && ! no_gnu) {
2250 out_printf(outh, "\n/*\n"
2251 " * Argument wrapping macros\n"
2253 out_printf(outh, "#ifdef __GNUC__\n");
2254 put_argument_gnu_wrappers(c);
2255 out_printf(outh, "#else /* __GNUC__ */\n");
2256 put_argument_nongnu_wrappers(c);
2257 out_printf(outh, "#endif /* __GNUC__ */\n\n");
2258 } else if(arguments > 0 && no_gnu) {
2259 out_printf(outh, "\n/*\n"
2260 " * Argument wrapping macros\n"
2262 put_argument_nongnu_wrappers(c);
2266 for(l = c->nodes; l != NULL; l = l->next) {
2268 if(n->type == METHOD_NODE)
2269 add_signal_prots((Method *)n);
2277 if(any_method_to_alias(c)) {
2279 make_method_nongnu_aliases(c);
2281 out_printf(out, "\n#ifdef __GNUC__\n");
2282 make_method_gnu_aliases(c);
2283 out_printf(out, "#else /* __GNUC__ */\n");
2284 make_method_nongnu_aliases(c);
2285 out_printf(out, "#endif /* __GNUC__ */\n\n");
2289 out_printf(out, "/* a macro for creating a new object of our type */\n");
2291 "#define GET_NEW ((%s *)gtk_type_new(%s_get_type()))\n\n",
2292 typebase, funcbase);
2303 add_getset_arg(c, TRUE);
2304 add_getset_arg(c, FALSE);
2307 for(l = c->nodes; l != NULL; l = l->next) {
2309 if(n->type == METHOD_NODE)
2310 put_method((Method *)n);
2313 add_bad_hack_to_avoid_unused_warnings(c);
2317 print_version_macros(void)
2319 int major=0, minor=0, pl=0;
2320 sscanf(VERSION, "%d.%d.%d", &major, &minor, &pl);
2322 out_printf(out, "#define GOB_VERSION_MAJOR %d\n", major);
2323 out_printf(out, "#define GOB_VERSION_MINOR %d\n", minor);
2324 out_printf(out, "#define GOB_VERSION_PATCHLEVEL %d\n\n", pl);
2328 print_file_comments(void)
2332 out_printf(outh, "/* Generated by GOB (v%s)"
2333 " (do not edit directly) */\n\n", VERSION);
2335 out_printf(outph, "/* Generated by GOB (v%s)"
2336 " (do not edit directly) */\n\n", VERSION);
2337 out_printf(out, "/* Generated by GOB (v%s) on %s"
2338 " (do not edit directly) */\n\n",
2339 VERSION, ctime(&curtime));
2343 print_includes(void)
2345 gboolean found_header;
2348 /* We may need string.h for memset */
2350 out_printf(out, "#include <string.h> /* memset() */\n\n");
2352 p = g_strconcat(filebase, ".h", NULL);
2353 found_header = TRUE;
2354 if(!g_list_find_custom(include_files, p, (GCompareFunc)strcmp)) {
2355 out_printf(out, "#include \"%s.h\"\n\n", filebase);
2356 found_header = FALSE;
2360 /* if we are creating a private header see if it was included */
2362 p = g_strconcat(filebase, "-private.h", NULL);
2363 if(!g_list_find_custom(include_files, p, (GCompareFunc)strcmp)) {
2364 out_printf(out, "#include \"%s-private.h\"\n\n",
2368 "Implicit private header include "
2370 "\tsource file, while public "
2371 "header is at a custom location, "
2373 "\texplicitly include "
2374 "the private header below the "
2382 print_header_prefixes(void)
2386 p = replace_sep(((Class *)class)->otype, '_');
2388 out_printf(outh, "#ifndef __%s_H__\n#define __%s_H__\n\n", p, p);
2390 out_printf(outph, "#ifndef __%s_PRIVATE_H__\n"
2391 "#define __%s_PRIVATE_H__\n\n"
2392 "#include \"%s.h\"\n\n", p, p, filebase);
2396 out_printf(outh, "#ifdef __cplusplus\n"
2398 "#endif /* __cplusplus */\n\n");
2400 out_printf(outph, "#ifdef __cplusplus\n"
2402 "#endif /* __cplusplus */\n\n");
2407 print_header_postfixes(void)
2410 out_printf(outh, "\n#ifdef __cplusplus\n"
2412 "#endif /* __cplusplus */\n");
2413 out_printf(outh, "\n#endif\n");
2416 out_printf(outph, "\n#ifdef __cplusplus\n"
2418 "#endif /* __cplusplus */\n");
2419 out_printf(outph, "\n#endif\n");
2428 /* print the AT_CCODE blocks */
2429 for(li=nodes;li;li=g_list_next(li)) {
2430 Node *node = li->data;
2431 if(node->type == CCODE_NODE) {
2432 CCode *cc = (CCode *)node;
2433 if(cc->cctype==AT_CCODE)
2434 print_ccode_block((CCode *)node);
2440 print_header_top(void)
2444 /* mandatory include */
2445 out_printf(outh, "#include <gtk/gtk.h>\n\n");
2447 /* print the HT_CCODE blocks */
2448 for(li=nodes;li;li=g_list_next(li)) {
2449 Node *node = li->data;
2450 if(node->type == CCODE_NODE) {
2451 CCode *cc = (CCode *)node;
2452 if(cc->cctype==HT_CCODE)
2453 print_ccode_block((CCode *)node);
2459 generate_outfiles(void)
2463 print_file_comments();
2469 print_header_prefixes();
2471 print_version_macros();
2475 for(li=nodes;li;li=g_list_next(li)) {
2476 Node *node = li->data;
2477 if(node->type == CCODE_NODE) {
2478 CCode *cc = (CCode *)node;
2479 if(cc->cctype!=HT_CCODE)
2480 print_ccode_block((CCode *)node);
2481 } else if(node->type == CLASS_NODE) {
2482 print_class_block((Class *)node);
2484 g_assert_not_reached();
2487 print_header_postfixes();
2493 fprintf(stderr, "Gob version %s\n\n", VERSION);
2494 fprintf(stderr, "gob [options] file.gob\n\n");
2495 fprintf(stderr, "Options:\n"
2496 "\t--help,-h,-? Display this help\n"
2497 "\t--version Display version\n"
2498 "\t--exit-on-warn,-w Exit with an error on warnings\n"
2499 "\t--no-exit-on-warn Don't exit on warnings [default]\n"
2500 "\t--for-cpp Create C++ files\n"
2501 "\t--no-extern-c Never print extern \"C\" into the "
2503 "\t--no-gnu Never use GNU extentions\n"
2504 "\t--no-touch-headers Don't touch headers unless they "
2506 "\t--always-private-header Always create a private header "
2508 "\t even if it would be empty "
2510 "\t--ondemand-private-header Create private header only when "
2512 "\t--no-private-header Don't create a private header, "
2514 "\t structure and protected "
2515 "prototypes inside c file\n"
2516 "\t--always-private-struct Always create a private pointer "
2518 "\t the object structure\n"
2519 "\t--no-write,-n Don't write output files, just "
2521 "\t--no-lines Don't print '#line' to output\n"
2522 "\t--no-self-alias Don't create self type and macro "
2524 "\t--no-kill-underscores Don't remove the leading underscore "
2526 "\t short id names\n");
2530 parse_options(int argc, char *argv[])
2533 int got_file = FALSE;
2534 int no_opts = FALSE;
2538 for(i=1;i<argc;i++) {
2539 if(no_opts || argv[i][0]!='-') {
2542 fprintf(stderr, "Specify only one file!\n");
2548 } else if(strcmp(argv[i], "--help")==0) {
2551 } else if(strcmp(argv[i], "--version")==0) {
2552 fprintf(stderr, "Gob version %s\n", VERSION);
2554 } else if(strcmp(argv[i], "--exit-on-warn")==0) {
2555 exit_on_warn = TRUE;
2556 } else if(strcmp(argv[i], "--no-exit-on-warn")==0) {
2557 exit_on_warn = FALSE;
2558 } else if(strcmp(argv[i], "--for-cpp")==0) {
2560 } else if(strcmp(argv[i], "--no-touch-headers")==0) {
2561 no_touch_headers = TRUE;
2562 } else if(strcmp(argv[i], "--ondemand-private-header")==0) {
2563 private_header = PRIVATE_HEADER_ONDEMAND;
2564 } else if(strcmp(argv[i], "--always-private-header")==0) {
2565 private_header = PRIVATE_HEADER_ALWAYS;
2566 } else if(strcmp(argv[i], "--no-private-header")==0) {
2567 private_header = PRIVATE_HEADER_NEVER;
2568 } else if(strcmp(argv[i], "--no-gnu")==0) {
2570 } else if(strcmp(argv[i], "--no-extern-c")==0) {
2572 } else if(strcmp(argv[i], "--no-write")==0) {
2574 } else if(strcmp(argv[i], "--no-lines")==0) {
2576 } else if(strcmp(argv[i], "--no-self-alias")==0) {
2577 no_self_alias = TRUE;
2578 } else if(strcmp(argv[i], "--no-kill-underscores")==0) {
2579 no_kill_underscores = TRUE;
2580 } else if(strcmp(argv[i], "--always-private-struct")==0) {
2581 always_private_struct = TRUE;
2582 } else if(strcmp(argv[i], "--")==0) {
2583 /*further arguments are files*/
2585 } else if(strncmp(argv[i], "--", 2)==0) {
2586 /*unknown long option*/
2587 fprintf(stderr, "Unknown option '%s'!\n", argv[i]);
2591 /*by now we know we have a string starting with
2592 - which is a short option string*/
2593 char *p = argv[i]+1;
2594 for(p=argv[i]+1; *p; p++) {
2608 "Unknown option '%c'!\n", *p);
2617 /* this is a somewhat ugly hack, but it appears to work */
2619 compare_and_move_header(void)
2621 char *hfnew = g_strconcat("#gob#", filebase, ".h#gob#", NULL);
2622 char *hf = g_strconcat(filebase, ".h", NULL);
2624 if(stat(hf, &s)==0) {
2626 s = g_strdup_printf("cmp '%s' '%s' > /dev/null", hf, hfnew);
2628 if(unlink(hfnew)!=0)
2630 "Can't remove new header file", 0);
2638 print_error(FALSE, "Can't remove old header file", 0);
2640 if(rename(hfnew, hf)!=0)
2641 print_error(FALSE, "Can't rename new header file", 0);
2647 main(int argc, char *argv[])
2649 parse_options(argc, argv);
2652 yyin = fopen(filename, "r");
2654 fprintf(stderr, "Error: can't open file '%s'\n",
2663 g_error("Parsing errors, quitting");
2665 print_error(FALSE, " no class defined", 0);
2668 exit_on_error = FALSE;
2670 signals = count_signals((Class *)class);
2671 arguments = count_arguments((Class *)class);
2672 overrides = count_overrides((Class *)class);
2673 privates = count_privates((Class *)class);
2674 protecteds = count_protecteds((Class *)class);
2675 destructors = count_destructors((Class *)class);
2676 initializers = count_initializers((Class *)class);
2679 make_inits((Class *)class);
2680 if(destructors > 0) {
2681 need_destroy = TRUE;
2682 find_destroy((Class *)class);
2685 need_finalize = TRUE;
2686 find_finalize((Class *)class);
2688 check_bad_symbols((Class *)class);
2689 check_duplicate_symbols((Class *)class);
2690 check_duplicate_overrides((Class *)class);
2691 check_duplicate_signals_args((Class *)class);
2692 check_public_new((Class *)class);
2693 check_vararg((Class *)class);
2694 check_firstarg((Class *)class);
2695 check_nonvoidempty((Class *)class);
2696 check_signal_args((Class *)class);
2697 check_argument_types((Class *)class);
2698 check_func_arg_checks((Class *)class);
2700 exit_on_error = TRUE;
2705 any_special = setup_special_array((Class *)class, special_array);
2709 generate_outfiles();
2720 if(no_touch_headers && !no_write)
2721 compare_and_move_header();