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_gtk_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);
838 for(li=c->nodes; li; li=g_list_next(li)) {
841 Method *m = (Method *)n;
842 if(n->type != METHOD_NODE ||
843 m->method != OVERRIDE_METHOD)
846 s = remove_sep(m->otype);
848 if(g_hash_table_lookup(done, s)) {
852 g_hash_table_insert(done, s, s);
854 f = replace_sep(m->otype, '_');
857 out_printf(out, "\t%sClass *%s_class = (%sClass *)%s;\n",
862 g_hash_table_foreach(done, (GHFunc)g_free, NULL);
863 g_hash_table_destroy(done);
867 make_run_signal_flags(Method *m, gboolean last)
881 gs = g_string_new(NULL);
884 g_string_assign(gs, "GTK_RUN_LAST");
886 g_string_assign(gs, "GTK_RUN_FIRST");
888 if(m->scope == PUBLIC_SCOPE)
889 g_string_append(gs, " | GTK_RUN_ACTION");
891 for(li = m->flags; li; li = li->next) {
892 char *flag = li->data;
894 for(i=0;flags[i];i++) {
895 if(strcmp(flags[i], flag)==0)
898 /* if we haven't found it in our list */
901 s = g_strdup_printf("Unknown flag '%s' used, "
902 "perhaps it was misspelled",
904 print_error(TRUE, s, m->line_no);
907 g_string_sprintfa(gs, " | GTK_RUN_%s", flag);
912 g_string_free(gs, FALSE);
919 add_signals(Class *c)
923 out_printf(out, "\n");
924 for(li=c->nodes;li;li=g_list_next(li)) {
926 char *mar, *sig, *flags;
927 gboolean is_none, last = FALSE;
928 Method *m = (Method *)n;
930 if(n->type != METHOD_NODE ||
931 (m->method != SIGNAL_FIRST_METHOD &&
932 m->method != SIGNAL_LAST_METHOD))
935 if(m->method == SIGNAL_FIRST_METHOD)
940 if(g_hash_table_lookup(marsh, m))
941 mar = g_strconcat("___marshal_",
942 (char *)g_hash_table_lookup(marsh, m),
945 mar = g_strdup("gtk_signal_default_marshaller");
947 is_none = (strcmp(m->gtktypes->next->data, "NONE")==0);
949 sig = g_strdup(get_real_id(m->id));
951 flags = make_run_signal_flags(m, last);
952 out_printf(out, "\tobject_signals[%s_SIGNAL] =\n"
953 "\t\tgtk_signal_new (\"%s\",\n"
954 "\t\t\t(GtkSignalRunType)(%s),\n"
955 "\t\t\tgtk_object_class->type,\n"
956 "\t\t\tGTK_SIGNAL_OFFSET (%sClass, %s),\n"
958 "\t\t\tGTK_TYPE_%s, %d",
959 sig, get_real_id(m->id),
961 typebase, get_real_id(m->id), mar,
962 (char *)m->gtktypes->data,
963 is_none?0:g_list_length(m->gtktypes->next));
970 for(l=m->gtktypes->next;l;l=g_list_next(l))
971 out_printf(out, ",\n\t\t\tGTK_TYPE_%s",
975 out_printf(out, ");\n");
977 out_printf(out, "\tgtk_object_class_add_signals (gtk_object_class,\n"
978 "\t\tobject_signals, LAST_SIGNAL);\n\n");
982 set_def_handlers(Class *c, char *oname)
985 gboolean set_line = FALSE;
987 out_printf(out, "\n");
988 for(li = c->nodes; li; li = g_list_next(li)) {
990 Method *m = (Method *)n;
992 if(n->type != METHOD_NODE ||
993 (m->method != SIGNAL_FIRST_METHOD &&
994 m->method != SIGNAL_LAST_METHOD &&
995 m->method != VIRTUAL_METHOD &&
996 m->method != OVERRIDE_METHOD))
999 if(m->line_no > 0 && m->cbuf) {
1000 out_addline_infile(out, m->line_no);
1002 } else if(set_line) {
1003 out_addline_outfile(out);
1008 if(m->method == OVERRIDE_METHOD) {
1010 s = replace_sep(m->otype, '_');
1015 strcmp(m->id, "destroy") == 0)
1016 out_printf(out, "\tgtk_object_class->destroy "
1018 else if(need_finalize &&
1020 strcmp(m->id, "finalize") == 0)
1021 out_printf(out, "\tgtk_object_class->finalize "
1022 "= ___finalize;\n");
1025 "\t%s_class->%s = ___%x_%s_%s;\n",
1026 s, m->id, (guint)m->unique_id,
1029 out_printf(out, "\t%s_class->%s = NULL;\n",
1033 out_printf(out, "\t%s->%s = ___real_%s_%s;\n",
1034 oname, get_real_id(m->id),
1035 funcbase, get_real_id(m->id));
1037 out_printf(out, "\t%s->%s = NULL;\n",
1038 oname, get_real_id(m->id));
1042 out_addline_outfile(out);
1046 make_arguments(Class *c)
1049 char *argflags[] = {
1057 out_printf(out, "\n");
1058 for(li=c->nodes;li;li=g_list_next(li)) {
1064 if(n->type != ARGUMENT_NODE)
1069 if(a->get && a->set)
1070 flags = g_string_new("GTK_ARG_READWRITE");
1072 flags = g_string_new("GTK_ARG_READABLE");
1074 flags = g_string_new("GTK_ARG_WRITABLE");
1076 for(l=a->flags;l;l=g_list_next(l)) {
1077 char *flag = l->data;
1079 if(strcmp(flag, "READWRITE")==0 ||
1080 strcmp(flag, "READABLE")==0 ||
1081 strcmp(flag, "WRITABLE")==0) {
1082 print_error(TRUE, "READWRITE, READABLE and "
1083 "WRITABLE argument flags are "
1084 "set automatically", a->line_no);
1087 for(i=0;argflags[i];i++) {
1088 if(strcmp(argflags[i], flag)==0)
1091 /* if we haven't found it in our list */
1094 s = g_strdup_printf("Unknown flag '%s' used, "
1095 "perhaps it was misspelled",
1097 print_error(TRUE, s, a->line_no);
1100 g_string_sprintfa(flags, " | GTK_ARG_%s", flag);
1103 s = g_strdup(a->name);
1105 out_printf(out, "\tgtk_object_add_arg_type(\"%s::%s\",\n"
1106 "\t\tGTK_TYPE_%s,\n"
1109 typebase, a->name, a->gtktype, flags->str, s);
1111 g_string_free(flags, TRUE);
1115 "\n\tgtk_object_class->set_arg = ___object_set_arg;\n"
1116 "\tgtk_object_class->get_arg = ___object_get_arg;\n");
1120 print_initializer(Method *m, Variable *v)
1124 if(v->initializer == NULL)
1127 if(v->scope == PRIVATE_SCOPE)
1128 root = g_strconcat(((FuncArg *)m->args->data)->name,
1131 root = g_strdup(((FuncArg *)m->args->data)->name);
1133 if(v->initializer_line > 0)
1134 out_addline_infile(out, v->initializer_line);
1136 out_printf(out, "\t%s->%s = %s;\n",
1137 root, v->id, v->initializer);
1139 if(v->initializer_line > 0)
1140 out_addline_outfile(out);
1146 print_destructor(Variable *v)
1150 if(v->destructor == NULL)
1153 if(v->scope == PRIVATE_SCOPE)
1154 root = "self->_priv";
1158 if(v->destructor_simple) {
1159 if(v->destructor_line > 0)
1160 out_addline_infile(out, v->destructor_line);
1162 out_printf(out, "\tif(%s->%s) { "
1163 "((*(void (*)(void *))%s)) (%s->%s); "
1164 "%s->%s = NULL; }\n",
1165 root, v->id, v->destructor, root, v->id,
1168 if(v->destructor_line > 0)
1169 out_addline_outfile(out);
1171 out_printf(out, "#define VAR (%s->%s)\n", root, v->id);
1172 out_printf(out, "\t{\n");
1173 if(v->destructor_line > 0)
1174 out_addline_infile(out, v->destructor_line);
1176 out_printf(out, "\t%s}\n", v->destructor);
1178 if(v->destructor_line > 0)
1179 out_addline_outfile(out);
1180 out_printf(out, "\tmemset(&VAR, 0, sizeof(VAR));\n");
1181 out_printf(out, "#undef VAR\n");
1186 add_destroy(Class *c)
1188 out_printf(out, "\nstatic void\n"
1189 "___destroy(GtkObject *obj_self)\n"
1192 if(destructors > 0) {
1193 out_printf(out, "\t%s *self G_GNUC_UNUSED = %s (obj_self);\n",
1194 typebase, macrobase);
1197 if(destroy_handler) {
1198 /* so we get possible bad argument warning */
1199 if(destroy_handler->line_no > 0)
1200 out_addline_infile(out, destroy_handler->line_no);
1201 out_printf(out, "\t___%x_%s_destroy(obj_self);\n",
1202 (guint)destroy_handler->unique_id, funcbase);
1203 if(destroy_handler->line_no > 0)
1204 out_addline_outfile(out);
1207 if(destructors > 0) {
1209 for(li = ((Class *)class)->nodes;
1213 Variable *v = (Variable *)n;
1214 if(n->type == VARIABLE_NODE &&
1215 v->scope != CLASS_SCOPE)
1216 print_destructor(v);
1220 out_printf(out, "}\n\n");
1224 add_finalize(Class *c)
1226 out_printf(out, "\nstatic void\n"
1227 "___finalize(GtkObject *obj_self)\n"
1231 out_printf(out, "\t%s *self = %s (obj_self);\n",
1232 typebase, macrobase);
1235 if(finalize_handler) {
1236 /* so we get possible bad argument warning */
1237 if(finalize_handler->line_no > 0)
1238 out_addline_infile(out, finalize_handler->line_no);
1239 out_printf(out, "\t___%x_%s_finalize(obj_self);\n",
1240 (guint)finalize_handler->unique_id, funcbase);
1241 if(finalize_handler->line_no > 0)
1242 out_addline_outfile(out);
1246 out_printf(out, "\tg_free (self->_priv);\n"
1247 "\tself->_priv = NULL;\n");
1250 out_printf(out, "}\n\n");
1257 for(li=c->nodes;li;li=g_list_next(li)) {
1260 if(n->type != METHOD_NODE)
1263 if(m->method == INIT_METHOD) {
1265 out_addline_infile(out, m->line_no);
1266 print_method(out, "static ", "\n", "", " ", "\n",
1267 m, FALSE, FALSE, TRUE);
1269 out_addline_outfile(out);
1270 out_printf(out, "{\n"
1271 "#define __GOB_FUNCTION__ \"%s::init\"\n",
1274 out_printf(out, "\t%s->_priv = "
1275 "g_new0 (%sPrivate, 1);\n",
1276 ((FuncArg *)m->args->data)->name,
1278 } else if(always_private_struct) {
1279 out_printf(out, "\t%s->_priv = NULL;\n",
1280 ((FuncArg *)m->args->data)->name);
1282 if(initializers > 0) {
1284 for(li = ((Class *)class)->nodes;
1288 Variable *v = (Variable *)n;
1289 if(n->type != VARIABLE_NODE ||
1290 v->scope == CLASS_SCOPE)
1292 print_initializer(m, v);
1295 } else if(m->method == CLASS_INIT_METHOD) {
1296 gboolean did_gtk_obj = FALSE;
1299 out_addline_infile(out, m->line_no);
1300 print_method(out, "static ", "\n", "", " ", "\n",
1301 m, FALSE, FALSE, TRUE);
1303 out_addline_outfile(out);
1304 out_printf(out, "{\n"
1305 "#define __GOB_FUNCTION__ \"%s::class_init\"\n",
1312 "\tGtkObjectClass *"
1313 "gtk_object_class = "
1314 "(GtkObjectClass*) %s;\n",
1315 ((FuncArg *)m->args->data)->name);
1321 ((FuncArg *)m->args->data)->name,
1324 if(initializers > 0) {
1326 for(li = ((Class *)class)->nodes;
1330 Variable *v = (Variable *)n;
1331 if(n->type != VARIABLE_NODE ||
1332 v->scope != CLASS_SCOPE)
1334 print_initializer(m, v);
1338 out_printf(out, "\n\tparent_class = ");
1340 out_printf(out, "(%sClass *)", ptypebase);
1341 out_printf(out, "gtk_type_class (%s_get_type ());\n",
1347 set_def_handlers(c, ((FuncArg *)m->args->data)->name);
1349 /* if there are no handlers for these things, we
1350 * need to set them up here */
1351 if(need_destroy && !destroy_handler)
1352 out_printf(out, "\tgtk_object_class->destroy "
1354 if(need_finalize && !finalize_handler)
1355 out_printf(out, "\tgtk_object_class->finalize "
1356 "= ___finalize;\n");
1365 out_printf(out, " {\n");
1366 out_addline_infile(out, m->ccode_line);
1367 out_printf(out, "%s\n", m->cbuf);
1368 out_addline_outfile(out);
1369 out_printf(out, " }\n");
1371 out_printf(out, "return;\n");
1373 out_printf(out, "}\n"
1374 "#undef __GOB_FUNCTION__\n");
1379 add_getset_arg(Class *c, gboolean is_set)
1382 out_printf(out, "\nstatic void\n"
1383 "___object_%s_arg (GtkObject *object,\n"
1386 "#define __GOB_FUNCTION__ \"%s::%s_arg\"\n"
1389 "\tself = %s (object);\n\n"
1390 "\tswitch (arg_id) {\n",
1391 is_set ? "set" : "get",
1392 c->otype, is_set ? "set" : "get",
1393 typebase, macrobase);
1395 for(li=c->nodes;li;li=g_list_next(li)) {
1401 if(n->type != ARGUMENT_NODE)
1406 line_no = a->set_line;
1409 line_no = a->get_line;
1413 s = g_strdup(a->name);
1415 out_printf(out, "\tcase ARG_%s:\n", s);
1416 if(is_set && a->atype) {
1417 char *cast = get_type(a->atype, TRUE);
1418 if(no_gnu || for_cpp) {
1419 out_printf(out, "#define ARG "
1420 "((%s)GTK_VALUE_%s(*arg))\n",
1423 out_printf(out, "#ifdef __GNUC__\n");
1424 if(strcmp(a->gtktype, "OBJECT")==0) {
1425 out_printf(out, "#define ARG "
1427 "GTK_VALUE_POINTER(*arg); "
1431 out_printf(out, "#define ARG "
1433 "GTK_VALUE_%s(*arg); "
1437 out_printf(out, "#else /* __GNUC__ */\n");
1438 out_printf(out, "#define ARG "
1439 "((%s)GTK_VALUE_%s(*arg))\n",
1441 out_printf(out, "#endif /* __GNUC__ */\n\n");
1443 out_printf(out, "\t\t{\n");
1445 } else if(!is_set && strcmp(a->gtktype, "OBJECT")==0) {
1447 "#define ARG (GTK_VALUE_POINTER(*arg))\n"
1451 "#define ARG (GTK_VALUE_%s(*arg))\n"
1457 out_addline_infile(out, line_no);
1458 out_printf(out, "%s\n", cbuf);
1460 out_addline_outfile(out);
1461 out_printf(out, "\t\t}\n\t\tbreak;\n"
1464 out_printf(out, "\tdefault:\n\t\tbreak;\n\t}\n}\n"
1465 "#undef __GOB_FUNCTION__\n");
1469 print_checks(Method *m, FuncArg *fa)
1473 gboolean checked_null = FALSE;
1474 is_void = (strcmp(m->mtype->name, "void")==0 &&
1475 m->mtype->pointer == NULL);
1477 for(li = fa->checks; li; li = g_list_next(li)) {
1478 Check *ch = li->data;
1480 /* point to the method prot in .gob for failed checks */
1482 out_addline_infile(out, m->line_no);
1484 out_printf(out, "\tg_return_if_fail (");
1486 out_printf(out, "\tg_return_val_if_fail (");
1487 switch(ch->chtype) {
1489 out_printf(out, "%s != NULL", fa->name);
1490 checked_null = TRUE;
1493 s = make_pre_macro(fa->atype->name, "IS");
1495 out_printf(out, "%s (%s)", s, fa->name);
1497 /* if not check null, null may be valid */
1498 out_printf(out, "!(%s) || %s (%s)", fa->name,
1503 out_printf(out, "%s < %s", fa->name, ch->number);
1506 out_printf(out, "%s > %s", fa->name, ch->number);
1509 out_printf(out, "%s <= %s", fa->name, ch->number);
1512 out_printf(out, "%s >= %s", fa->name, ch->number);
1515 out_printf(out, "%s == %s", fa->name, ch->number);
1518 out_printf(out, "%s != %s", fa->name, ch->number);
1522 out_printf(out, ");\n");
1524 out_printf(out, ", (");
1525 print_type(out, m->mtype, TRUE);
1526 out_printf(out, ")%s);\n",
1527 m->onerror?m->onerror:"0");
1533 print_preconditions(Method *m)
1537 for(li=m->args;li;li=g_list_next(li)) {
1538 FuncArg *fa = li->data;
1540 print_checks(m, fa);
1543 out_addline_outfile(out);
1547 print_method_body(Method *m, int pre)
1549 out_printf(out, "{\n"
1550 "#define __GOB_FUNCTION__ \"%s::%s\"\n",
1551 ((Class *)class)->otype,
1552 get_real_id(m->id));
1554 print_preconditions(m);
1556 /* Note: the trailing }'s are on one line, this is so
1557 that we get the no return warning correctly and point to
1558 the correct line in the .gob file, yes this is slightly
1559 ugly in the .c file, but that is not supposed to be
1560 human readable anyway. */
1562 out_printf(out, "{\n");
1564 out_addline_infile(out, m->ccode_line);
1565 out_printf(out, "\t%s}", m->cbuf);
1568 /* Note, there is no \n between the last } and this } so that
1569 * errors/warnings reported on the end of the body get pointed to the
1570 * right line in the .gob source */
1571 out_printf(out, "}\n");
1574 out_addline_outfile(out);
1575 out_printf(out, "#undef __GOB_FUNCTION__\n");
1579 put_signal_args(Method *m)
1583 for(ali = m->gtktypes->next, li=m->args->next;
1585 li=li->next, ali=ali->next) {
1586 FuncArg *fa = li->data;
1587 const char *cast = get_cast(ali->data, FALSE);
1588 /* we should have already proved before that
1589 the we know all the types */
1592 out_printf(out, ",\n\t\t(%s)%s", cast,
1598 get_arg_names_for_macro(Method *m)
1602 GString *gs = g_string_new(NULL);
1604 for(li=m->args;li;li=g_list_next(li)) {
1605 FuncArg *arg = li->data;
1606 g_string_sprintfa(gs, "%s___%s", p, arg->name);
1610 g_string_free(gs, FALSE);
1615 put_method(Method *m)
1617 char *s, *args, *doc;
1619 is_void = (strcmp(m->mtype->name, "void")==0 &&
1620 m->mtype->pointer == NULL);
1621 out_printf(out, "\n");
1622 if(m->method != OVERRIDE_METHOD) {
1623 doc = get_gtk_doc(m->id);
1625 out_printf(out, "%s", doc);
1630 case REGULAR_METHOD:
1632 out_addline_infile(out, m->line_no);
1633 if(m->scope == PRIVATE_SCOPE)
1634 print_method(out, "static ", "\n", "", " ", "\n",
1635 m, FALSE, FALSE, TRUE);
1636 else /* PUBLIC, PROTECTED */
1637 print_method(out, "", "\n", "", " ", "\n",
1638 m, FALSE, FALSE, TRUE);
1639 print_method_body(m, TRUE);
1640 /* the outfile line was added above */
1642 case SIGNAL_FIRST_METHOD:
1643 case SIGNAL_LAST_METHOD:
1645 out_addline_infile(out, m->line_no);
1646 if(m->scope == PRIVATE_SCOPE)
1647 print_method(out, "static ", "\n", "", " ", "\n",
1648 m, FALSE, FALSE, TRUE);
1649 else /* PUBLIC, PROTECTED */
1650 print_method(out, "", "\n", "", " ", "\n",
1651 m, FALSE, FALSE, TRUE);
1652 out_addline_outfile(out);
1653 out_printf(out, "{\n");
1654 s = g_strdup(get_real_id(m->id));
1656 if(strcmp(m->mtype->name, "void") == 0 &&
1657 m->mtype->pointer == NULL) {
1658 print_preconditions(m);
1659 if(((FuncArg *)m->args->data)->name)
1660 out_printf(out, "\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1661 "\t\tobject_signals[%s_SIGNAL]",
1662 ((FuncArg *)m->args->data)->name, s);
1664 out_printf(out, ");\n}\n");
1666 out_printf(out, "\t");
1667 print_type(out, m->mtype, TRUE);
1668 out_printf(out, "return_val = (");
1669 print_type(out, m->mtype, TRUE);
1671 out_printf(out, ")(%s);\n", m->defreturn);
1673 out_printf(out, ")(%s);\n", m->onerror);
1675 out_printf(out, ")(0);\n");
1676 print_preconditions(m);
1677 out_printf(out, "\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1678 "\t\tobject_signals[%s_SIGNAL]",
1679 ((FuncArg *)m->args->data)->name, s);
1681 out_printf(out, ",\n\t\t&return_val);\n"
1682 "\treturn return_val;\n}\n");
1688 out_addline_infile(out, m->line_no);
1689 print_method(out, "static ", "\n___real_", "", " ", "\n",
1690 m, FALSE, FALSE, TRUE);
1691 print_method_body(m, FALSE);
1692 /* the outfile line was added above */
1694 case VIRTUAL_METHOD:
1696 out_addline_infile(out, m->line_no);
1697 if(m->scope==PRIVATE_SCOPE)
1698 print_method(out, "static ", "\n", "", " ", "\n",
1699 m, FALSE, FALSE, TRUE);
1700 else /* PUBLIC, PROTECTED */
1701 print_method(out, "", "\n", "", " ", "\n",
1702 m, FALSE, FALSE, TRUE);
1703 out_addline_outfile(out);
1704 out_printf(out, "{\n"
1705 "\t%sClass *klass;\n", typebase);
1706 print_preconditions(m);
1707 out_printf(out, "\tklass = %s_CLASS(GTK_OBJECT(%s)->klass);\n\n"
1708 "\tif(klass->%s)\n",
1709 macrobase, ((FuncArg *)m->args->data)->name,
1710 get_real_id(m->id));
1711 if(strcmp(m->mtype->name, "void") == 0 &&
1712 m->mtype->pointer == NULL) {
1714 out_printf(out, "\t\t(*klass->%s)(%s",
1716 ((FuncArg *)m->args->data)->name);
1717 for(li=m->args->next;li;li=g_list_next(li)) {
1718 FuncArg *fa = li->data;
1719 out_printf(out, ",%s", fa->name);
1721 out_printf(out, ");\n}\n");
1724 out_printf(out, "\t\treturn (*klass->%s)(%s",
1726 ((FuncArg *)m->args->data)->name);
1727 for(li=m->args->next;li;li=g_list_next(li)) {
1728 FuncArg *fa = li->data;
1729 out_printf(out, ",%s", fa->name);
1731 out_printf(out, ");\n"
1734 print_type(out, m->mtype, TRUE);
1736 out_printf(out, ")(%s);\n}\n", m->defreturn);
1738 out_printf(out, ")(%s);\n}\n", m->onerror);
1740 out_printf(out, ")(0);\n}\n");
1746 out_addline_infile(out, m->line_no);
1747 print_method(out, "static ", "\n___real_", "", " ", "\n",
1748 m, FALSE, FALSE, TRUE);
1749 print_method_body(m, FALSE);
1750 /* the outfile line was added above */
1752 case OVERRIDE_METHOD:
1756 out_addline_infile(out, m->line_no);
1757 s = g_strdup_printf("\n___%x_", (guint)m->unique_id);
1758 print_method(out, "static ", s, "", " ", "\n",
1759 m, FALSE, FALSE, FALSE);
1761 out_addline_outfile(out);
1762 s = replace_sep(m->otype, '_');
1764 args = get_arg_names_for_macro(m);
1766 out_printf(out, "#define PARENT_HANDLER(%s) \\\n"
1767 "\t{ if(%s_CLASS(parent_class)->%s) \\\n"
1768 "\t\t(* %s_CLASS(parent_class)->%s)(%s); }\n",
1769 args, s, m->id, s, m->id, args);
1771 out_printf(out, "#define PARENT_HANDLER(%s) \\\n"
1772 "\t((%s_CLASS(parent_class)->%s)? \\\n"
1773 "\t\t(* %s_CLASS(parent_class)->%s)(%s): \\\n"
1775 args, s, m->id, s, m->id, args);
1776 out_printf(out, "(");
1777 print_type(out, m->mtype, TRUE);
1778 out_printf(out, ")%s))\n",
1779 m->onerror?m->onerror:"0");
1783 print_method_body(m, TRUE);
1784 /* the outfile line was added above */
1785 out_printf(out, "#undef PARENT_HANDLER\n");
1795 char *outfile, *outfileh, *outfileph;
1798 outfile = g_strconcat(filebase, ".c", NULL);
1800 outfile = g_strconcat(filebase, ".cc", NULL);
1801 if(no_touch_headers)
1802 outfileh = g_strconcat("#gob#", filebase, ".h#gob#", NULL);
1804 outfileh = g_strconcat(filebase, ".h", NULL);
1806 if((privates > 0 || protecteds > 0 ||
1807 private_header == PRIVATE_HEADER_ALWAYS) &&
1808 private_header != PRIVATE_HEADER_NEVER)
1809 outfileph = g_strconcat(filebase, "-private.h", NULL);
1815 devnull = fopen("/dev/null", "w");
1817 g_error("Cannot open null device");
1823 out = fopen(outfile, "w");
1825 g_error("Cannot open outfile: %s", outfile);
1827 outh = fopen(outfileh, "w");
1829 g_error("Cannot open outfile: %s", outfileh);
1831 outph = fopen(outfileph, "w");
1833 g_error("Cannot open outfile: %s", outfileh);
1839 put_argument_nongnu_wrappers(Class *c)
1846 for(li=c->nodes;li;li=g_list_next(li)) {
1848 Argument *a = (Argument *)n;
1852 if(n->type != ARGUMENT_NODE)
1855 aname = g_strdup(a->name);
1859 cast = get_type(a->atype, TRUE);
1861 cast = g_strdup(get_cast(a->gtktype, TRUE));
1865 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1866 "\"%s\",(%s)(arg)\n",
1867 macrobase, aname, a->name, cast);
1869 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1870 "\"%s\",(%s*)(arg)\n",
1871 macrobase, aname, a->name, cast);
1874 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1876 macrobase, aname, a->name);
1878 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1880 macrobase, aname, a->name);
1888 put_argument_gnu_wrappers(Class *c)
1895 for(li=c->nodes;li;li=g_list_next(li)) {
1897 Argument *a = (Argument *)n;
1900 if(n->type != ARGUMENT_NODE)
1902 s = g_strdup(a->name);
1905 cast = get_type(a->atype, TRUE);
1907 cast = g_strdup(get_cast(a->gtktype, TRUE));
1910 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1911 "\"%s\",({%sz = (arg); z;})\n",
1912 macrobase, s, a->name, cast);
1914 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1915 "\"%s\",({%s*z = (arg); z;})\n",
1916 macrobase, s, a->name, cast);
1919 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1921 macrobase, s, a->name);
1923 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1925 macrobase, s, a->name);
1933 print_ccode_block(CCode *cc)
1936 switch(cc->cctype) {
1938 /* HT code is printed exactly like normal header
1939 code but is printed before */
1942 out_printf(fp, "\n");
1945 /* AT code is printed exactly like normal 'all'
1946 code but is printed before */
1949 out_printf(outph, "\n");
1950 out_printf(outph, "%s\n", cc->cbuf);
1951 out_addline_infile(outph, cc->line_no);
1952 out_addline_outfile(outph);
1954 out_printf(outh, "\n");
1955 out_printf(outh, "%s\n", cc->cbuf);
1957 out_printf(fp, "\n");
1958 out_addline_infile(fp, cc->line_no);
1963 out_printf(fp, "\n");
1964 out_addline_infile(fp, cc->line_no);
1971 out_printf(fp, "\n");
1972 out_addline_infile(fp, cc->line_no);
1975 out_printf(fp, "%s\n", cc->cbuf);
1976 if(cc->cctype == C_CCODE ||
1977 cc->cctype == A_CCODE ||
1978 cc->cctype == AT_CCODE ||
1979 cc->cctype == PH_CCODE)
1980 out_addline_outfile(fp);
1984 print_class_block(Class *c)
1988 gboolean printed_private = FALSE;
1991 out_printf(out, "/* utility types we may need */\n");
1992 if(special_array[SPECIAL_2POINTER])
1993 out_printf(out, "typedef struct { "
1994 "gpointer a; gpointer b; "
1995 "} ___twopointertype;\n");
1996 if(special_array[SPECIAL_3POINTER])
1997 out_printf(out, "typedef struct { "
1998 "gpointer a; gpointer b; "
2000 "} ___threepointertype;\n");
2001 if(special_array[SPECIAL_INT_POINTER])
2002 out_printf(out, "typedef struct { "
2003 "gint a; gpointer b; "
2004 "} ___intpointertype;\n");
2005 out_printf(out, "\n");
2008 out_printf(outh, "\n/*\n"
2009 " * Type checking and casting macros\n"
2011 out_printf(outh, "#define %s\t"
2012 "(%s_get_type())\n",
2013 macrotype, funcbase);
2014 out_printf(outh, "#define %s(obj)\t"
2015 "GTK_CHECK_CAST((obj), %s_get_type(),%s)\n",
2016 macrobase, funcbase, typebase);
2017 out_printf(outh, "#define %s_CLASS(klass)\t"
2018 "GTK_CHECK_CLASS_CAST((klass),%s_get_type(),%sClass)\n",
2019 macrobase, funcbase, typebase);
2020 out_printf(outh, "#define %s(obj)\t"
2021 "GTK_CHECK_TYPE((obj),%s_get_type ())\n\n",
2024 if( ! no_self_alias) {
2025 out_printf(out, "/* self casting macros */\n");
2026 out_printf(out, "#define SELF(x) %s(x)\n", macrobase);
2027 out_printf(out, "#define IS_SELF(x) %s(x)\n", macrois);
2028 out_printf(out, "#define SELF_CLASS(x) %s_CLASS(x)\n\n",
2031 out_printf(out, "/* self typedefs */\n");
2032 out_printf(out, "typedef %s Self;\n", typebase);
2033 out_printf(out, "typedef %sClass SelfClass;\n\n", typebase);
2036 if(privates > 0 || always_private_struct) {
2037 out_printf(outh, "\n/* Private structure type */\n");
2038 out_printf(outh, "typedef struct _%sPrivate %sPrivate;\n",
2039 typebase, typebase);
2041 out_printf(outh, "/* There are no privates, this "
2042 "structure is thus never defined */\n");
2045 out_printf(outh, "\n/*\n"
2046 " * Main object structure\n"
2048 s = replace_sep(c->otype, '_');
2050 out_printf(outh, "#ifndef __TYPEDEF_%s__\n"
2051 "#define __TYPEDEF_%s__\n", s, s);
2053 out_printf(outh, "typedef struct _%s %s;\n"
2054 "#endif\n", typebase, typebase);
2055 out_printf(outh, "struct _%s {\n\t%s __parent__;\n",
2056 typebase, ptypebase);
2057 for(l=c->nodes; l; l=g_list_next(l)) {
2058 static gboolean printed_public = FALSE;
2060 Variable *v = (Variable *)n;
2061 if(n->type == VARIABLE_NODE &&
2062 v->scope == PUBLIC_SCOPE) {
2063 if( ! printed_public) {
2064 out_printf(outh, "\t/*< public >*/\n");
2065 printed_public = TRUE;
2067 put_variable((Variable *)n, outh);
2070 /* put protecteds always AFTER publics */
2071 for(l=c->nodes; l; l=g_list_next(l)) {
2073 Variable *v = (Variable *)n;
2074 if(n->type == VARIABLE_NODE &&
2075 v->scope == PROTECTED_SCOPE) {
2076 if( ! printed_private) {
2077 out_printf(outh, "\t/*< private >*/\n");
2078 printed_private = TRUE;
2080 put_variable((Variable *)n, outh);
2083 if(privates > 0 || always_private_struct) {
2084 if( ! printed_private)
2085 out_printf(outh, "\t/*< private >*/\n");
2086 out_printf(outh, "\t%sPrivate *_priv;\n", typebase);
2088 out_printf(outh, "};\n");
2093 /* if we are to stick this into the private
2094 header, if not stick it directly into the
2101 out_printf(outfp, "struct _%sPrivate {\n",
2103 for(l=c->nodes; l; l=l->next) {
2105 Variable *v = (Variable *)n;
2106 if(n->type == VARIABLE_NODE &&
2107 v->scope == PRIVATE_SCOPE) {
2108 out_addline_infile(outfp, v->line_no);
2109 put_variable(v, outfp);
2112 out_addline_outfile(outfp);
2113 out_printf(outfp, "};\n");
2116 out_printf(outh, "\n/*\n"
2117 " * Class definition\n"
2119 out_printf(outh, "typedef struct _%sClass %sClass;\n",
2120 typebase, typebase);
2122 "struct _%sClass {\n\t%sClass __parent__;\n",
2123 typebase, ptypebase);
2124 for(l=c->nodes;l;l=g_list_next(l)) {
2126 if(n->type == METHOD_NODE)
2127 put_vs_method((Method *)n);
2129 /* put class scope variables */
2130 for(l=c->nodes;l;l=g_list_next(l)) {
2132 Variable *v = (Variable *)n;
2133 if(n->type == VARIABLE_NODE &&
2134 v->scope == CLASS_SCOPE)
2135 put_variable((Variable *)n, outh);
2137 out_printf(outh, "};\n\n");
2139 out_printf(out, "/* here are local prototypes */\n");
2141 out_printf(out, "static void ___object_set_arg "
2142 "(GtkObject *object, GtkArg *arg, "
2144 "static void ___object_get_arg "
2145 "(GtkObject *object, GtkArg *arg, "
2146 "guint arg_id);\n");
2149 out_printf(outh, "\n/*\n"
2150 " * Public methods\n"
2153 out_printf(outh, "guint\t%s_get_type\t(void);\n", funcbase);
2154 for(l=c->nodes;l;l=g_list_next(l)) {
2156 if(n->type == METHOD_NODE) {
2157 put_pub_method((Method *)n);
2158 put_prot_method((Method *)n);
2159 put_priv_method_prot((Method *)n);
2163 /* this idea is less and less apealing to me */
2165 if(!no_signal_connect) {
2167 out_printf(outh, "\n/*\n"
2168 " * Signal connection methods\n"
2172 for(l=c->nodes;l;l=g_list_next(l)) {
2174 if(n->type == METHOD_NODE)
2175 put_signal_connect((Method *)n);
2181 /* argument wrapping macros */
2182 if(arguments>0 && !no_gnu) {
2183 out_printf(outh, "\n/*\n"
2184 " * Argument wrapping macros\n"
2186 out_printf(outh, "#ifdef __GNUC__\n");
2187 put_argument_gnu_wrappers(c);
2188 out_printf(outh, "#else /* __GNUC__ */\n");
2189 put_argument_nongnu_wrappers(c);
2190 out_printf(outh, "#endif /* __GNUC__ */\n\n");
2191 } else if(arguments>0 && no_gnu) {
2192 out_printf(outh, "\n/*\n"
2193 " * Argument wrapping macros\n"
2195 put_argument_nongnu_wrappers(c);
2199 for(l=c->nodes;l;l=g_list_next(l)) {
2201 if(n->type == METHOD_NODE)
2202 add_signal_prots((Method *)n);
2210 if(any_method_to_alias(c)) {
2212 make_method_nongnu_aliases(c);
2214 out_printf(out, "\n#ifdef __GNUC__\n");
2215 make_method_gnu_aliases(c);
2216 out_printf(out, "#else /* __GNUC__ */\n");
2217 make_method_nongnu_aliases(c);
2218 out_printf(out, "#endif /* __GNUC__ */\n\n");
2222 out_printf(out, "/* a macro for creating a new object of our type */\n");
2224 "#define GET_NEW ((%s *)gtk_type_new(%s_get_type()))\n\n",
2225 typebase, funcbase);
2236 add_getset_arg(c, TRUE);
2237 add_getset_arg(c, FALSE);
2240 for(l=c->nodes;l;l=g_list_next(l)) {
2242 if(n->type == METHOD_NODE)
2243 put_method((Method *)n);
2246 add_bad_hack_to_avoid_unused_warnings(c);
2250 print_version_macros(void)
2252 int major=0, minor=0, pl=0;
2253 sscanf(VERSION, "%d.%d.%d", &major, &minor, &pl);
2255 out_printf(out, "#define GOB_VERSION_MAJOR %d\n", major);
2256 out_printf(out, "#define GOB_VERSION_MINOR %d\n", minor);
2257 out_printf(out, "#define GOB_VERSION_PATCHLEVEL %d\n\n", pl);
2261 print_file_comments(void)
2265 out_printf(outh, "/* Generated by GOB (v%s)"
2266 " (do not edit directly) */\n\n", VERSION);
2268 out_printf(outph, "/* Generated by GOB (v%s)"
2269 " (do not edit directly) */\n\n", VERSION);
2270 out_printf(out, "/* Generated by GOB (v%s) on %s"
2271 " (do not edit directly) */\n\n",
2272 VERSION, ctime(&curtime));
2276 print_includes(void)
2278 gboolean found_header;
2281 /* We may need string.h for memset */
2283 out_printf(out, "#include <string.h> /* memset() */\n\n");
2285 p = g_strconcat(filebase, ".h", NULL);
2286 found_header = TRUE;
2287 if(!g_list_find_custom(include_files, p, (GCompareFunc)strcmp)) {
2288 out_printf(out, "#include \"%s.h\"\n\n", filebase);
2289 found_header = FALSE;
2293 /* if we are creating a private header see if it was included */
2295 p = g_strconcat(filebase, "-private.h", NULL);
2296 if(!g_list_find_custom(include_files, p, (GCompareFunc)strcmp)) {
2297 out_printf(out, "#include \"%s-private.h\"\n\n",
2301 "Implicit private header include "
2303 "\tsource file, while public "
2304 "header is at a custom location, "
2306 "\texplicitly include "
2307 "the private header below the "
2315 print_header_prefixes(void)
2319 p = replace_sep(((Class *)class)->otype, '_');
2321 out_printf(outh, "#ifndef __%s_H__\n#define __%s_H__\n\n", p, p);
2323 out_printf(outph, "#ifndef __%s_PRIVATE_H__\n"
2324 "#define __%s_PRIVATE_H__\n\n"
2325 "#include \"%s.h\"\n\n", p, p, filebase);
2329 out_printf(outh, "#ifdef __cplusplus\n"
2331 "#endif /* __cplusplus */\n\n");
2333 out_printf(outph, "#ifdef __cplusplus\n"
2335 "#endif /* __cplusplus */\n\n");
2340 print_header_postfixes(void)
2343 out_printf(outh, "\n#ifdef __cplusplus\n"
2345 "#endif /* __cplusplus */\n");
2346 out_printf(outh, "\n#endif\n");
2349 out_printf(outph, "\n#ifdef __cplusplus\n"
2351 "#endif /* __cplusplus */\n");
2352 out_printf(outph, "\n#endif\n");
2361 /* print the AT_CCODE blocks */
2362 for(li=nodes;li;li=g_list_next(li)) {
2363 Node *node = li->data;
2364 if(node->type == CCODE_NODE) {
2365 CCode *cc = (CCode *)node;
2366 if(cc->cctype==AT_CCODE)
2367 print_ccode_block((CCode *)node);
2373 print_header_top(void)
2377 /* mandatory include */
2378 out_printf(outh, "#include <gtk/gtk.h>\n\n");
2380 /* print the HT_CCODE blocks */
2381 for(li=nodes;li;li=g_list_next(li)) {
2382 Node *node = li->data;
2383 if(node->type == CCODE_NODE) {
2384 CCode *cc = (CCode *)node;
2385 if(cc->cctype==HT_CCODE)
2386 print_ccode_block((CCode *)node);
2392 generate_outfiles(void)
2396 print_file_comments();
2402 print_header_prefixes();
2404 print_version_macros();
2408 for(li=nodes;li;li=g_list_next(li)) {
2409 Node *node = li->data;
2410 if(node->type == CCODE_NODE) {
2411 CCode *cc = (CCode *)node;
2412 if(cc->cctype!=HT_CCODE)
2413 print_ccode_block((CCode *)node);
2414 } else if(node->type == CLASS_NODE) {
2415 print_class_block((Class *)node);
2417 g_assert_not_reached();
2420 print_header_postfixes();
2426 fprintf(stderr, "Gob version %s\n\n", VERSION);
2427 fprintf(stderr, "gob [options] file.gob\n\n");
2428 fprintf(stderr, "Options:\n"
2429 "\t--help,-h,-? Display this help\n"
2430 "\t--version Display version\n"
2431 "\t--exit-on-warn,-w Exit with an error on warnings\n"
2432 "\t--no-exit-on-warn Don't exit on warnings [default]\n"
2433 "\t--for-cpp Create C++ files\n"
2434 "\t--no-extern-c Never print extern \"C\" into the "
2436 "\t--no-gnu Never use GNU extentions\n"
2437 "\t--no-touch-headers Don't touch headers unless they "
2439 "\t--always-private-header Always create a private header "
2441 "\t even if it would be empty "
2443 "\t--ondemand-private-header Create private header only when "
2445 "\t--no-private-header Don't create a private header, "
2447 "\t structure and protected "
2448 "prototypes inside c file\n"
2449 "\t--always-private-struct Always create a private pointer "
2451 "\t the object structure\n"
2452 "\t--no-write,-n Don't write output files, just "
2454 "\t--no-lines Don't print '#line' to output\n"
2455 "\t--no-self-alias Don't create self type and macro "
2457 "\t--no-kill-underscores Don't remove the leading underscore "
2459 "\t short id names\n");
2463 parse_options(int argc, char *argv[])
2466 int got_file = FALSE;
2467 int no_opts = FALSE;
2471 for(i=1;i<argc;i++) {
2472 if(no_opts || argv[i][0]!='-') {
2475 fprintf(stderr, "Specify only one file!\n");
2481 } else if(strcmp(argv[i], "--help")==0) {
2484 } else if(strcmp(argv[i], "--version")==0) {
2485 fprintf(stderr, "Gob version %s\n", VERSION);
2487 } else if(strcmp(argv[i], "--exit-on-warn")==0) {
2488 exit_on_warn = TRUE;
2489 } else if(strcmp(argv[i], "--no-exit-on-warn")==0) {
2490 exit_on_warn = FALSE;
2491 } else if(strcmp(argv[i], "--for-cpp")==0) {
2493 } else if(strcmp(argv[i], "--no-touch-headers")==0) {
2494 no_touch_headers = TRUE;
2495 } else if(strcmp(argv[i], "--ondemand-private-header")==0) {
2496 private_header = PRIVATE_HEADER_ONDEMAND;
2497 } else if(strcmp(argv[i], "--always-private-header")==0) {
2498 private_header = PRIVATE_HEADER_ALWAYS;
2499 } else if(strcmp(argv[i], "--no-private-header")==0) {
2500 private_header = PRIVATE_HEADER_NEVER;
2501 } else if(strcmp(argv[i], "--no-gnu")==0) {
2503 } else if(strcmp(argv[i], "--no-extern-c")==0) {
2505 } else if(strcmp(argv[i], "--no-write")==0) {
2507 } else if(strcmp(argv[i], "--no-lines")==0) {
2509 } else if(strcmp(argv[i], "--no-self-alias")==0) {
2510 no_self_alias = TRUE;
2511 } else if(strcmp(argv[i], "--no-kill-underscores")==0) {
2512 no_kill_underscores = TRUE;
2513 } else if(strcmp(argv[i], "--always-private-struct")==0) {
2514 always_private_struct = TRUE;
2515 } else if(strcmp(argv[i], "--")==0) {
2516 /*further arguments are files*/
2518 } else if(strncmp(argv[i], "--", 2)==0) {
2519 /*unknown long option*/
2520 fprintf(stderr, "Unknown option '%s'!\n", argv[i]);
2524 /*by now we know we have a string starting with
2525 - which is a short option string*/
2526 char *p = argv[i]+1;
2527 for(p=argv[i]+1; *p; p++) {
2541 "Unknown option '%c'!\n", *p);
2550 /* this is a somewhat ugly hack, but it appears to work */
2552 compare_and_move_header(void)
2554 char *hfnew = g_strconcat("#gob#", filebase, ".h#gob#", NULL);
2555 char *hf = g_strconcat(filebase, ".h", NULL);
2557 if(stat(hf, &s)==0) {
2559 s = g_strdup_printf("cmp '%s' '%s' > /dev/null", hf, hfnew);
2561 if(unlink(hfnew)!=0)
2563 "Can't remove new header file", 0);
2571 print_error(FALSE, "Can't remove old header file", 0);
2573 if(rename(hfnew, hf)!=0)
2574 print_error(FALSE, "Can't rename new header file", 0);
2580 main(int argc, char *argv[])
2582 parse_options(argc, argv);
2585 yyin = fopen(filename, "r");
2587 fprintf(stderr, "Error: can't open file '%s'\n",
2596 g_error("Parsing errors, quitting");
2598 print_error(FALSE, " no class defined", 0);
2601 exit_on_error = FALSE;
2603 signals = count_signals((Class *)class);
2604 arguments = count_arguments((Class *)class);
2605 overrides = count_overrides((Class *)class);
2606 privates = count_privates((Class *)class);
2607 protecteds = count_protecteds((Class *)class);
2608 destructors = count_destructors((Class *)class);
2609 initializers = count_initializers((Class *)class);
2612 make_inits((Class *)class);
2613 if(destructors > 0) {
2614 need_destroy = TRUE;
2615 find_destroy((Class *)class);
2618 need_finalize = TRUE;
2619 find_finalize((Class *)class);
2621 check_bad_symbols((Class *)class);
2622 check_duplicate_symbols((Class *)class);
2623 check_duplicate_overrides((Class *)class);
2624 check_duplicate_signals_args((Class *)class);
2625 check_public_new((Class *)class);
2626 check_vararg((Class *)class);
2627 check_firstarg((Class *)class);
2628 check_nonvoidempty((Class *)class);
2629 check_signal_args((Class *)class);
2630 check_argument_types((Class *)class);
2631 check_func_arg_checks((Class *)class);
2633 exit_on_error = TRUE;
2638 any_special = setup_special_array((Class *)class, special_array);
2642 generate_outfiles();
2653 if(no_touch_headers && !no_write)
2654 compare_and_move_header();