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 set_arguments = 0; /* number of named (set) arguments */
64 static int get_arguments = 0; /* number of named (get) arguments */
65 static int overrides = 0; /* number of override methods */
66 static int privates = 0; /* number of private data members */
67 static int protecteds = 0; /* number of protected methods */
68 static int destructors = 0; /* number of variable destructors */
69 static int initializers = 0; /* number of variable initializers */
71 static gboolean made_aliases = FALSE; /* if we made any shorthand aliases
72 and need the REALLY UGLY HACK to
75 /* the special variable types we need to define */
76 static gboolean special_array[SPECIAL_LAST] = {0};
77 static gboolean any_special = FALSE;
79 static gboolean need_destroy = FALSE;
80 static Method * destroy_handler = NULL;
82 static gboolean need_finalize = FALSE;
83 static Method * finalize_handler = NULL;
90 gboolean no_touch_headers = FALSE;
91 gboolean for_cpp = FALSE;
92 gboolean no_gnu = FALSE;
93 gboolean exit_on_warn = FALSE;
94 gboolean exit_on_error = TRUE;
95 gboolean got_error = FALSE;
96 gint private_header = PRIVATE_HEADER_ALWAYS;
97 gboolean no_extern_c = FALSE;
98 gboolean no_write = FALSE;
99 gboolean no_lines = FALSE;
100 gboolean no_self_alias = FALSE;
101 gboolean no_kill_underscores = FALSE;
102 gboolean always_private_struct = FALSE;
104 int method_unique_id = 1;
109 filebase = replace_sep(((Class *)class)->otype, '-');
112 funcbase = replace_sep(((Class *)class)->otype, '_');
115 pfuncbase = replace_sep(((Class *)class)->ptype, '_');
116 g_strdown(pfuncbase);
118 macrobase = replace_sep(((Class *)class)->otype, '_');
121 macrois = make_pre_macro(((Class *)class)->otype, "IS");
122 macrotype = make_pre_macro(((Class *)class)->otype, "TYPE");
124 typebase = remove_sep(((Class *)class)->otype);
126 ptypebase = remove_sep(((Class *)class)->ptype);
130 get_type(const Type *t, gboolean postfix_to_stars)
137 s = remove_sep(t->name);
138 gs = g_string_new(s);
142 if(postfix_to_stars) {
144 /*XXX: this is ugly perhaps we can do this whole postfix thing
145 in a nicer way, we just count the number of '[' s and from
146 that we deduce the number of dimensions, so that we can print
148 for(p=t->postfix; p && *p; p++)
149 if(*p == '[') extra++;
151 g_string_append_c(gs, ' ');
154 g_string_append(gs, t->pointer);
155 for(i=0; i < extra; i++)
156 g_string_append_c(gs, '*');
157 g_string_append_c(gs, ' ');
161 g_string_free(gs, FALSE);
166 get_gtk_doc(const char *id)
173 val = g_hash_table_lookup(gtk_doc_hash, id);
175 return g_strdup_printf("/**\n * %s_%s:\n%s **/\n",
176 funcbase, get_real_id(id), val);
177 val = g_hash_table_lookup(gtk_doc_hash, get_real_id(id));
179 return g_strdup_printf("/**\n * %s_%s:\n%s **/\n",
180 funcbase, get_real_id(id), val);
185 print_type(FILE *fp, const Type *t, gboolean postfix_to_stars)
189 s = get_type(t, postfix_to_stars);
190 out_printf(fp, "%s", s);
196 print_method(FILE *fp, const char *typeprefix, const char *nameprefix,
197 const char *subnameprefix,
198 const char *namepostfix, const char *postfix, const Method *m,
199 gboolean one_arg_per_line,
200 gboolean no_funcbase,
201 gboolean kill_underscore)
206 out_printf(fp, "%s", typeprefix);
207 print_type(fp, m->mtype, TRUE);
210 id = get_real_id(m->id);
215 out_printf(fp, "%s%s%s%s(",
216 nameprefix, subnameprefix, id, namepostfix);
218 out_printf(fp, "%s%s_%s%s%s(",
219 nameprefix, funcbase, subnameprefix, id,
223 for(li=m->args; li; li=g_list_next(li)) {
224 FuncArg *arg = li->data;
225 print_type(fp, arg->atype, FALSE);
227 out_printf(fp, "%s%s,%s", arg->name,
228 arg->atype->postfix ?
229 arg->atype->postfix : "",
230 one_arg_per_line ? "\n\t\t\t\t\t" : " ");
232 out_printf(fp, "%s%s", arg->name,
233 arg->atype->postfix ?
234 arg->atype->postfix : "");
237 out_printf(fp, ",%s...",
238 one_arg_per_line ? "\n\t\t\t\t\t" : " ");
240 out_printf(fp, "void");
242 out_printf(fp, ")%s", postfix);
246 any_method_to_alias(Class *c)
250 for(li=c->nodes;li;li=g_list_next(li)) {
251 Node *node = li->data;
252 if(node->type == METHOD_NODE) {
253 Method *m = (Method *)node;
255 if(m->method == INIT_METHOD ||
256 m->method == CLASS_INIT_METHOD ||
257 m->method == OVERRIDE_METHOD)
267 /* just the vararg macros, we use the same func pointers for these as in non-gnu */
269 make_method_gnu_aliases(Class *c)
273 for(li = c->nodes; li != NULL; li = li->next) {
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)
288 out_printf(out, "#define %s(args...) "
289 "%s_%s(##args)\n", m->id,
290 funcbase, get_real_id(m->id));
292 out_printf(out, "#define %s() "
294 funcbase, get_real_id(m->id));
300 make_method_nongnu_aliases(Class *c)
304 gboolean local_made_aliases = FALSE;
306 for(li=c->nodes; li; li=g_list_next(li)) {
307 Node *node = li->data;
308 if(node->type == METHOD_NODE) {
309 Method *m = (Method *)node;
311 if(m->method == INIT_METHOD ||
312 m->method == CLASS_INIT_METHOD ||
313 m->method == OVERRIDE_METHOD)
316 /* in C++ mode don't alias new */
317 if(for_cpp && strcmp(m->id, "new")==0)
320 if( ! local_made_aliases)
321 out_printf(out, "\n/* Short form pointers */\n");
323 print_method(out, "static ", "(* const ", "", ") ", "",
324 m, FALSE, TRUE, FALSE);
325 out_printf(out, " = %s_%s;\n", funcbase,
328 local_made_aliases = TRUE;
331 if(local_made_aliases) {
332 out_printf(out, "\n");
338 add_bad_hack_to_avoid_unused_warnings(Class *c)
342 /* if we haven't had any methods, just return */
347 out_printf(out, "\n\n#if (!defined __GNUC__) || (defined __GNUC__ && defined __STRICT_ANSI__)\n");
349 "/*REALLY BAD HACK\n"
350 " This is to avoid unused warnings if you don't call\n"
351 " some method. I need to find a better way to do\n"
352 " this, not needed in GCC since we use some gcc\n"
353 " extentions to make saner, faster code */\n"
355 "___%s_really_bad_hack_to_avoid_warnings(void)\n"
357 for(li=c->nodes;li;li=g_list_next(li)) {
358 Node *node = li->data;
359 if(node->type == METHOD_NODE) {
360 Method *m = (Method *)node;
362 if(m->method == INIT_METHOD ||
363 m->method == CLASS_INIT_METHOD ||
364 m->method == OVERRIDE_METHOD)
367 /* in C++ mode we don't alias new */
368 if(for_cpp && strcmp(m->id, "new")==0)
371 out_printf(out, "\t((void (*)(void))%s)();\n", m->id);
374 out_printf(out, "\t___%s_really_bad_hack_to_avoid_warnings();\n",
377 out_printf(out, "}\n#endif /* !__GNUC__ || (__GNUC__ && __STRICT_ANSI__) */\n\n");
379 out_printf(out, "}\n\n");
383 put_variable(Variable *v, FILE *fp)
385 out_printf(fp, "\t");
386 print_type(fp, v->vtype, FALSE);
387 out_printf(fp, "%s%s;", v->id,
389 v->vtype->postfix:"");
390 if(v->scope == PROTECTED_SCOPE)
391 out_printf(fp, " /* protected */");
392 out_printf(fp, "\n");
396 put_vs_method(const Method *m)
398 if(m->method != SIGNAL_LAST_METHOD &&
399 m->method != SIGNAL_FIRST_METHOD &&
400 m->method != VIRTUAL_METHOD)
403 /* if a signal mark it as such */
404 if(m->method != VIRTUAL_METHOD)
405 print_method(outh, "\t/*signal*/", "(* ", "", ") ", ";\n",
406 m, FALSE, TRUE, TRUE);
408 print_method(outh, "\t", "(* ", "", ") ", ";\n",
409 m, FALSE, TRUE, TRUE);
413 put_pub_method(const Method *m)
415 if(m->scope != PUBLIC_SCOPE)
418 print_method(outh, "", "\t", "", "\t", ";\n", m, TRUE, FALSE, TRUE);
421 /* I'm starting not to like this idea */
424 put_signal_connect(Method *m)
426 if(m->method != SIGNAL_LAST_METHOD &&
427 m->method != SIGNAL_FIRST_METHOD)
430 out_printf(outh, "guint \t%s_%s__connect_full\t(%s *object,\n"
431 "\t\t\t\t\tconst char *name,\n"
432 "\t\t\t\t\tGtkSignalFunc func,\n"
433 "\t\t\t\t\tGtkCallbackMarshal marshal,\n"
434 "\t\t\t\t\tgpointer data,\n"
435 "\t\t\t\t\tGtkDestroyNotify destroy_func,\n"
436 "\t\t\t\t\tgboolean object_signal,\n"
437 "\t\t\t\t\tgboolean after);\n",
438 funcbase, m->id, typebase);
440 out_printf(outh, "#define %s_%s__connect(object,name,func,data) "
441 "%s_%s__connect_full((object),(name),(func),NULL,"
442 "(data),NULL,FALSE,FALSE)\n",
443 funcbase, m->id, funcbase, m->id);
444 out_printf(outh, "#define %s_%s__connect_after(object,name,func,data) "
445 "%s__connect_%s_full((object),(name),(func),NULL,"
446 "(data),NULL,FALSE,TRUE)\n",
447 funcbase, m->id, funcbase, m->id);
449 out_printf(outh, "guint \t%s_%s__connect_while_alive\t(%s *object,\n"
450 "\t\t\t\t\tconst char *name,\n"
451 "\t\t\t\t\tGtkSignalFunc func,\n"
452 "\t\t\t\t\tgpointer data,\n"
453 "\t\t\t\t\tGtkObject *alive_object);\n\n",
454 funcbase, m->id, typebase);
460 put_prot_method(const Method *m)
462 if(m->scope != PROTECTED_SCOPE)
466 print_method(outph, "", "\t", "", "\t", ";\n",
467 m, FALSE, FALSE, TRUE);
469 print_method(out, "", "\t", "", "\t", ";\n",
470 m, FALSE, FALSE, TRUE);
474 put_priv_method_prot(Method *m)
476 if(m->method == SIGNAL_LAST_METHOD ||
477 m->method == SIGNAL_FIRST_METHOD ||
478 m->method == VIRTUAL_METHOD) {
481 "static ", "___real_", "", " ", ";\n",
482 m, FALSE, FALSE, TRUE);
484 /* no else, here, it might still have a private prototype, it's not
487 if((m->method == OVERRIDE_METHOD &&
490 char *s = g_strdup_printf("___%x_", (guint)m->unique_id);
491 print_method(out, "static ", s, "", " ",
492 no_gnu?";\n":" G_GNUC_UNUSED;\n",
493 m, FALSE, FALSE, FALSE);
495 } else if(m->scope == PRIVATE_SCOPE ||
496 m->method == INIT_METHOD ||
497 m->method == CLASS_INIT_METHOD)
498 print_method(out, "static ", "", "", " ",
499 no_gnu?";\n":" G_GNUC_UNUSED;\n",
500 m, FALSE, FALSE, TRUE);
504 make_func_arg(char *typename, int is_class, char *name)
511 tn = g_strconcat(typename, ":Class", NULL);
513 tn = g_strdup(typename);
515 type = new_type(tn, g_strdup("*"), NULL);
516 node = new_funcarg((Type *)type, name, NULL);
517 return g_list_prepend(NULL, node);
521 make_inits(Class *cl)
523 int got_class_init = FALSE;
524 int got_init = FALSE;
527 for(li=cl->nodes;li;li=g_list_next(li)) {
529 if(n->type == METHOD_NODE) {
530 Method *m = (Method *)n;
531 if(m->method == INIT_METHOD) {
533 error_print(GOB_ERROR, m->line_no, "init defined more then once");
535 } else if(m->method == CLASS_INIT_METHOD) {
537 error_print(GOB_ERROR, m->line_no, "class_init defined more then once");
538 got_class_init = TRUE;
542 if(!got_class_init) {
543 node = new_method(NO_SCOPE, CLASS_INIT_METHOD,
544 (Type *)new_type(g_strdup("void"),
546 NULL, NULL, NULL, g_strdup("class_init"),
547 make_func_arg(cl->otype, TRUE, g_strdup("c")),
548 NULL, NULL, NULL, 0, 0, FALSE,
550 cl->nodes = g_list_prepend(cl->nodes, node);
553 node = new_method(NO_SCOPE, INIT_METHOD,
554 (Type *)new_type(g_strdup("void"),
556 NULL, NULL, NULL, g_strdup("init"),
557 make_func_arg(cl->otype, FALSE, g_strdup("o")),
558 NULL, NULL, NULL, 0, 0, FALSE,
560 cl->nodes = g_list_prepend(cl->nodes, node);
565 find_destroy(Class *cl)
569 destroy_handler = NULL;
570 for(li=cl->nodes;li;li=g_list_next(li)) {
572 if(n->type == METHOD_NODE) {
573 Method *m = (Method *)n;
574 if(m->method == OVERRIDE_METHOD &&
575 strcmp(m->id, "destroy")==0) {
576 if(strcmp(m->otype, "Gtk:Object") != 0) {
577 error_print(GOB_ERROR, m->line_no,
578 "destroy method override "
579 "of class other then "
582 if(g_list_length(m->args) != 1) {
583 error_print(GOB_ERROR, m->line_no,
584 "destroy method override "
585 "with more then one "
596 find_finalize(Class *cl)
600 finalize_handler = NULL;
601 for(li=cl->nodes;li;li=g_list_next(li)) {
603 if(n->type == METHOD_NODE) {
604 Method *m = (Method *)n;
605 if(m->method == OVERRIDE_METHOD &&
606 strcmp(m->id, "finalize")==0) {
607 if(strcmp(m->otype, "Gtk:Object") != 0 &&
608 strcmp(m->otype, "G:Object") != 0) {
609 error_print(GOB_ERROR, m->line_no,
610 "finalize method override "
611 "of class other then "
612 "Gtk:Object (or G:Object"
615 if(g_list_length(m->args) != 1) {
616 error_print(GOB_ERROR, m->line_no,
617 "finalize method override "
618 "with more then one "
621 finalize_handler = m;
629 /* hash of method -> name of signal prototype */
630 static GHashTable *marsh = NULL;
632 /* list of methods with different signal prototypes,
633 we check this list if we can use a signal prototype of a
634 previous signal method, there are only uniques here */
635 static GList *eq_signal_methods = NULL;
637 /* compare a list of strings */
639 is_list_equal(GList *a, GList *b)
641 for(;a && b; a=a->next, b=b->next) {
642 if(strcmp(a->data, b->data)!=0) {
646 /* the the lists were different length */
653 find_same_type_signal(Method *m)
656 for(li=eq_signal_methods;li;li=li->next) {
657 Method *mm = li->data;
658 if(is_list_equal(mm->gtktypes, m->gtktypes))
665 print_signal_marsal_args(Method *m)
667 if(strcmp(m->gtktypes->next->data, "NONE")!=0) {
670 for(i=0, li=m->gtktypes->next;li;
671 i++, li=g_list_next(li)) {
673 out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
674 (char *)li->data, i);
676 out_printf(out, ",\n\t\t(%s)"
677 "GTK_VALUE_%s(args[%d])",
678 get_cast(li->data, FALSE),
679 (char *)li->data, i);
683 out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
688 add_signal_prots(Method *m)
695 if(m->method != SIGNAL_LAST_METHOD &&
696 m->method != SIGNAL_FIRST_METHOD)
700 marsh = g_hash_table_new(NULL, NULL);
702 if(strcmp(m->gtktypes->data, "NONE")==0 &&
703 strcmp(m->gtktypes->next->data, "NONE")==0)
706 /* if we already did a signal prototype just use that */
707 mm = find_same_type_signal(m);
709 s = g_hash_table_lookup(marsh, mm);
710 g_hash_table_insert(marsh, m, s);
714 s = g_strdup_printf("Sig%d", sig++);
716 g_hash_table_insert(marsh, m, s);
717 eq_signal_methods = g_list_prepend(eq_signal_methods, m);
719 /* we know that we'll know all the gtktypes (so get_cast can't fail) */
720 out_printf(out, "\ntypedef %s (*___%s) (%s *, ",
721 get_cast(m->gtktypes->data, FALSE), s, typebase);
723 if(strcmp(m->gtktypes->next->data, "NONE")!=0) {
724 for(li=m->gtktypes->next; li; li=g_list_next(li))
725 out_printf(out, "%s, ", get_cast(li->data, FALSE));
727 out_printf(out, "gpointer);\n");
729 out_printf(out, "\nstatic void\n"
730 "___marshal_%s (GtkObject * object,\n"
731 "\tGtkSignalFunc func,\n"
732 "\tgpointer func_data,\n"
736 if(strcmp(m->gtktypes->data, "NONE")==0) {
737 out_printf(out, "\t___%s rfunc;\n\n"
738 "\trfunc = (___%s)func;\n\n"
739 "\t(*rfunc)((%s *)object", s, s, typebase);
741 const char *retcast = get_cast(m->gtktypes->data, FALSE);
745 "\trfunc = (___%s)func;\n\n"
746 "\tretval = GTK_RETLOC_%s(args[%d]);\n\n"
747 "\t*retval = (*rfunc)((%s *)object",
748 s, retcast, s, (char *)m->gtktypes->data,
749 g_list_length(m->gtktypes)-1, typebase);
751 print_signal_marsal_args(m);
759 out_printf(out, "\n");
761 out_printf(out, "enum {\n");
762 for(li=c->nodes;li;li=g_list_next(li)) {
764 if(n->type == METHOD_NODE) {
765 Method *m = (Method *)n;
766 if(m->method == SIGNAL_LAST_METHOD ||
767 m->method == SIGNAL_FIRST_METHOD) {
768 char *s = g_strdup(get_real_id(m->id));
770 out_printf(out, "\t%s_SIGNAL,\n", s);
775 out_printf(out, "\tLAST_SIGNAL\n};\n\n");
777 if(set_arguments > 0 || get_arguments > 0) {
778 out_printf(out, "enum {\n\tARG_0");
779 for(li=c->nodes;li;li=g_list_next(li)) {
781 if(n->type == ARGUMENT_NODE) {
782 Argument *a = (Argument *)n;
783 char *s = g_strdup(a->name);
785 out_printf(out, ",\n\tARG_%s", s);
789 out_printf(out, "\n};\n\n");
794 "static guint object_signals[LAST_SIGNAL] = {0};\n\n");
796 out_printf(out, "/* pointer to the class of our parent */\n");
797 out_printf(out, "static %sClass *parent_class = NULL;\n\n", ptypebase);
803 char *chunk_size = ((Class*)class)->chunk_size;
807 "%s_get_type (void)\n"
809 "\tstatic guint type = 0;\n\n"
811 "\t\tstatic const GtkTypeInfo info = {\n"
813 "\t\t\tsizeof (%s),\n"
814 "\t\t\tsizeof (%sClass),\n"
815 "\t\t\t(GtkClassInitFunc) %s_class_init,\n"
816 "\t\t\t(GtkObjectInitFunc) %s_init,\n"
817 "\t\t\t/* reserved_1 */ NULL,\n"
818 "\t\t\t/* reserved_2 */ NULL,\n"
819 "\t\t\t(GtkClassInitFunc) NULL\n"
821 "\t\ttype = gtk_type_unique (%s_get_type(), &info);\n",
822 funcbase, typebase, typebase, typebase,
823 funcbase, funcbase, pfuncbase);
827 "\t\tgtk_type_set_chunk_alloc(type, %s);\n"
829 chunk_size, chunk_size);
838 add_overrides(Class *c, const char *oname, gboolean did_base_obj)
844 done = g_hash_table_new(g_str_hash, g_str_equal);
846 s = g_strdup("GtkObject"); /* This was already done */
847 g_hash_table_insert(done, s, s);
848 s = g_strdup("GObject"); /* This was probably already done as well (if using Gtk/Glib 1.3/2.0) */
849 g_hash_table_insert(done, s, s);
851 for(li=c->nodes; li; li=g_list_next(li)) {
854 Method *m = (Method *)n;
855 if(n->type != METHOD_NODE ||
856 m->method != OVERRIDE_METHOD)
859 s = remove_sep(m->otype);
861 if(g_hash_table_lookup(done, s)) {
865 g_hash_table_insert(done, s, s);
867 f = replace_sep(m->otype, '_');
870 out_printf(out, "\t%sClass *%s_class = (%sClass *)%s;\n",
875 g_hash_table_foreach(done, (GHFunc)g_free, NULL);
876 g_hash_table_destroy(done);
880 make_run_signal_flags(Method *m, gboolean last)
894 gs = g_string_new(NULL);
897 g_string_assign(gs, "GTK_RUN_LAST");
899 g_string_assign(gs, "GTK_RUN_FIRST");
901 if(m->scope == PUBLIC_SCOPE)
902 g_string_append(gs, " | GTK_RUN_ACTION");
904 for(li = m->flags; li; li = li->next) {
905 char *flag = li->data;
907 for(i=0;flags[i];i++) {
908 if(strcmp(flags[i], flag)==0)
911 /* if we haven't found it in our list */
913 error_printf(GOB_WARN, m->line_no,
914 "Unknown flag '%s' used, "
915 "perhaps it was misspelled",
918 g_string_sprintfa(gs, " | GTK_RUN_%s", flag);
923 g_string_free(gs, FALSE);
930 add_signals(Class *c)
934 out_printf(out, "\n");
935 for(li=c->nodes;li;li=g_list_next(li)) {
937 char *mar, *sig, *flags;
938 gboolean is_none, last = FALSE;
939 Method *m = (Method *)n;
941 if(n->type != METHOD_NODE ||
942 (m->method != SIGNAL_FIRST_METHOD &&
943 m->method != SIGNAL_LAST_METHOD))
946 if(m->method == SIGNAL_FIRST_METHOD)
951 if(g_hash_table_lookup(marsh, m))
952 mar = g_strconcat("___marshal_",
953 (char *)g_hash_table_lookup(marsh, m),
956 mar = g_strdup("gtk_signal_default_marshaller");
958 is_none = (strcmp(m->gtktypes->next->data, "NONE")==0);
960 sig = g_strdup(get_real_id(m->id));
962 flags = make_run_signal_flags(m, last);
963 out_printf(out, "\tobject_signals[%s_SIGNAL] =\n"
964 "\t\tgtk_signal_new (\"%s\",\n"
965 "\t\t\t(GtkSignalRunType)(%s),\n"
966 "\t\t\tGTK_CLASS_TYPE(gtk_object_class),\n"
967 "\t\t\tGTK_SIGNAL_OFFSET (%sClass, %s),\n"
969 "\t\t\tGTK_TYPE_%s, %d",
970 sig, get_real_id(m->id),
972 typebase, get_real_id(m->id), mar,
973 (char *)m->gtktypes->data,
974 is_none ? 0 : g_list_length(m->gtktypes->next));
981 for(l = m->gtktypes->next; l != NULL; l = l->next)
982 out_printf(out, ",\n\t\t\tGTK_TYPE_%s",
986 out_printf(out, ");\n");
988 if(strcmp(m->gtktypes->data, "NONE") != 0 ||
992 out_printf(out, "\tif(");
993 if(strcmp(m->gtktypes->data, "NONE") != 0) {
994 out_printf(out, "%s sizeof(", sep);
995 print_type(out, m->mtype, FALSE);
996 out_printf(out, "%s",
998 m->mtype->postfix : "");
999 out_printf(out, ") != sizeof(%s)",
1000 get_cast(m->gtktypes->data, FALSE));
1005 for(al = m->args->next, gl = m->gtktypes->next;
1006 al != NULL && gl != NULL;
1007 al = al->next, gl = gl->next) {
1008 FuncArg *arg = al->data;
1009 char *gtkarg = gl->data;
1011 out_printf(out, "%ssizeof(", sep);
1012 print_type(out, arg->atype, FALSE);
1013 out_printf(out, "%s",
1014 arg->atype->postfix ?
1015 arg->atype->postfix : "");
1016 out_printf(out, ") != sizeof(%s)",
1017 get_cast(gtkarg, FALSE));
1021 out_printf(out, ") {\n"
1022 "\t\tg_error(\"%s line %d: Type mismatch "
1023 "of \\\"%s\\\" signal signature\");\n"
1025 filename, m->line_no, get_real_id(m->id));
1029 out_printf(out, "\tgtk_object_class_add_signals (gtk_object_class,\n"
1030 "\t\tobject_signals, LAST_SIGNAL);\n\n");
1034 set_def_handlers(Class *c, const char *oname)
1037 gboolean set_line = FALSE;
1039 out_printf(out, "\n");
1040 for(li = c->nodes; li; li = g_list_next(li)) {
1042 Method *m = (Method *)n;
1044 if(n->type != METHOD_NODE ||
1045 (m->method != SIGNAL_FIRST_METHOD &&
1046 m->method != SIGNAL_LAST_METHOD &&
1047 m->method != VIRTUAL_METHOD &&
1048 m->method != OVERRIDE_METHOD))
1051 if(m->line_no > 0 && m->cbuf) {
1052 out_addline_infile(out, m->line_no);
1054 } else if(set_line) {
1055 out_addline_outfile(out);
1060 if(m->method == OVERRIDE_METHOD) {
1062 s = replace_sep(m->otype, '_');
1067 strcmp(get_real_id(m->id), "destroy") == 0)
1068 out_printf(out, "\tgtk_object_class->destroy "
1070 else if(need_finalize &&
1072 strcmp(get_real_id(m->id), "finalize") == 0)
1074 "#ifdef G_OBJECT_CLASS\n"
1075 "\tg_object_class->finalize = ___finalize;\n"
1076 "#else /* !G_OBJECT_CLASS */\n"
1077 "\tgtk_object_class->finalize = ___finalize;\n"
1078 "#endif /* G_OBJECT_CLASS */\n");
1081 "\t%s_class->%s = ___%x_%s_%s;\n",
1082 s, get_real_id(m->id), (guint)m->unique_id,
1083 funcbase, get_real_id(m->id));
1085 out_printf(out, "\t%s_class->%s = NULL;\n",
1086 s, get_real_id(m->id));
1089 out_printf(out, "\t%s->%s = ___real_%s_%s;\n",
1090 oname, get_real_id(m->id),
1091 funcbase, get_real_id(m->id));
1093 out_printf(out, "\t%s->%s = NULL;\n",
1094 oname, get_real_id(m->id));
1098 out_addline_outfile(out);
1102 make_arguments(Class *c)
1105 char *argflags[] = {
1113 out_printf(out, "\n");
1114 for(li=c->nodes;li;li=g_list_next(li)) {
1120 if(n->type != ARGUMENT_NODE)
1125 if(a->get && a->set)
1126 flags = g_string_new("GTK_ARG_READWRITE");
1128 flags = g_string_new("GTK_ARG_READABLE");
1130 flags = g_string_new("GTK_ARG_WRITABLE");
1132 g_assert(a->get || a->set);
1134 for(l=a->flags;l;l=g_list_next(l)) {
1135 char *flag = l->data;
1137 if(strcmp(flag, "READWRITE")==0 ||
1138 strcmp(flag, "READABLE")==0 ||
1139 strcmp(flag, "WRITABLE")==0) {
1140 error_print(GOB_WARN, a->line_no,
1141 "READWRITE, READABLE and "
1142 "WRITABLE argument flags are "
1143 "set automatically");
1146 for(i = 0; argflags[i]; i++) {
1147 if(strcmp(argflags[i], flag)==0)
1150 /* if we haven't found it in our list */
1151 if( ! argflags[i]) {
1152 error_printf(GOB_WARN, a->line_no,
1153 "Unknown flag '%s' used, "
1154 "perhaps it was misspelled", flag);
1156 g_string_sprintfa(flags, " | GTK_ARG_%s", flag);
1159 s = g_strdup(a->name);
1161 out_printf(out, "\tgtk_object_add_arg_type(\"%s::%s\",\n"
1162 "\t\tGTK_TYPE_%s,\n"
1165 typebase, a->name, a->gtktype, flags->str, s);
1167 g_string_free(flags, TRUE);
1170 out_printf(out, "\n");
1171 if(get_arguments > 0)
1172 out_printf(out, "\tgtk_object_class->get_arg = ___object_get_arg;\n");
1173 if(set_arguments > 0)
1174 out_printf(out, "\tgtk_object_class->set_arg = ___object_set_arg;\n");
1178 print_initializer(Method *m, Variable *v)
1182 if(v->initializer == NULL)
1185 if(v->scope == PRIVATE_SCOPE)
1186 root = g_strconcat(((FuncArg *)m->args->data)->name,
1189 root = g_strdup(((FuncArg *)m->args->data)->name);
1191 if(v->initializer_line > 0)
1192 out_addline_infile(out, v->initializer_line);
1194 out_printf(out, "\t%s->%s = %s;\n",
1195 root, v->id, v->initializer);
1197 if(v->initializer_line > 0)
1198 out_addline_outfile(out);
1204 print_destructor(Variable *v)
1208 if(v->destructor == NULL)
1211 if(v->scope == PRIVATE_SCOPE)
1212 root = "self->_priv";
1216 if(v->destructor_simple) {
1217 if(v->destructor_line > 0)
1218 out_addline_infile(out, v->destructor_line);
1220 out_printf(out, "\tif(%s->%s) { "
1221 "((*(void (*)(void *))%s)) (%s->%s); "
1222 "%s->%s = NULL; }\n",
1223 root, v->id, v->destructor, root, v->id,
1226 if(v->destructor_line > 0)
1227 out_addline_outfile(out);
1229 out_printf(out, "#define VAR (%s->%s)\n", root, v->id);
1230 out_printf(out, "\t{\n");
1231 if(v->destructor_line > 0)
1232 out_addline_infile(out, v->destructor_line);
1234 out_printf(out, "\t%s}\n", v->destructor);
1236 if(v->destructor_line > 0)
1237 out_addline_outfile(out);
1238 out_printf(out, "\tmemset(&VAR, 0, sizeof(VAR));\n");
1239 out_printf(out, "#undef VAR\n");
1244 add_destroy(Class *c)
1246 out_printf(out, "\nstatic void\n"
1247 "___destroy(GtkObject *obj_self)\n"
1250 "#define __GOB_FUNCTION__ \"%s::destroy\"\n",
1253 if(destructors > 0) {
1254 out_printf(out, "\t%s *self = %s (obj_self);\n",
1255 typebase, macrobase);
1258 if(destroy_handler) {
1259 /* so we get possible bad argument warning */
1260 if(destroy_handler->line_no > 0)
1261 out_addline_infile(out, destroy_handler->line_no);
1262 out_printf(out, "\t___%x_%s_destroy(obj_self);\n",
1263 (guint)destroy_handler->unique_id, funcbase);
1264 if(destroy_handler->line_no > 0)
1265 out_addline_outfile(out);
1268 "\tif(GTK_OBJECT_CLASS(parent_class)->destroy) \\\n"
1269 "\t\t(* GTK_OBJECT_CLASS(parent_class)->destroy)(obj_self);\n");
1272 if(destructors > 0) {
1274 for(li = ((Class *)class)->nodes;
1278 Variable *v = (Variable *)n;
1279 if(n->type == VARIABLE_NODE &&
1280 v->scope != CLASS_SCOPE)
1281 print_destructor(v);
1285 out_printf(out, "\treturn;\n");
1287 out_printf(out, "\tself = NULL;\n");
1288 out_printf(out, "}\n"
1289 "#undef __GOB_FUNCTION__\n\n");
1293 add_finalize(Class *c)
1295 /* Sort of a hack to make it work with gtk+ 1.3/2.0 */
1297 "\n#ifdef G_OBJECT_CLASS\n"
1299 "___finalize(GObject *obj_self)\n"
1300 "#else /* !G_OBJECT_CLASS */\n"
1302 "___finalize(GtkObject *obj_self)\n"
1303 "#endif /* G_OBJECT_CLASS */\n"
1306 "#define __GOB_FUNCTION__ \"%s::finalize\"\n",
1310 out_printf(out, "\t%s *self = %s (obj_self);\n",
1311 typebase, macrobase);
1312 out_printf(out, "\tgpointer priv = self->_priv;\n");
1315 if(finalize_handler) {
1316 /* so we get possible bad argument warning */
1317 if(finalize_handler->line_no > 0)
1318 out_addline_infile(out, finalize_handler->line_no);
1319 out_printf(out, "\t___%x_%s_finalize(obj_self);\n",
1320 (guint)finalize_handler->unique_id, funcbase);
1321 if(finalize_handler->line_no > 0)
1322 out_addline_outfile(out);
1324 /* Sort of a hack to make it work with gtk+ 1.3/2.0 */
1326 "#ifdef G_OBJECT_CLASS\n"
1327 "\tif(G_OBJECT_CLASS(parent_class)->finalize) \\\n"
1328 "\t\t(* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);\n"
1329 "#else /* !G_OBJECT_CLASS */\n"
1330 "\tif(GTK_OBJECT_CLASS(parent_class)->finalize) \\\n"
1331 "\t\t(* GTK_OBJECT_CLASS(parent_class)->finalize)(obj_self);\n"
1332 "#endif /* G_OBJECT_CLASS */\n");
1336 out_printf(out, "\tg_free(priv);\n");
1339 out_printf(out, "}\n"
1340 "#undef __GOB_FUNCTION__\n\n");
1347 for(li=c->nodes;li;li=g_list_next(li)) {
1351 gboolean add_unused_class = FALSE;
1353 if(n->type != METHOD_NODE)
1356 if(m->method == INIT_METHOD) {
1358 out_addline_infile(out, m->line_no);
1359 print_method(out, "static ", "\n", "", " ", "\n",
1360 m, FALSE, FALSE, TRUE);
1362 out_addline_outfile(out);
1363 out_printf(out, "{\n"
1364 "#define __GOB_FUNCTION__ \"%s::init\"\n",
1367 out_printf(out, "\t%s->_priv = "
1368 "g_new0 (%sPrivate, 1);\n",
1369 ((FuncArg *)m->args->data)->name,
1371 } else if(always_private_struct) {
1372 out_printf(out, "\t%s->_priv = NULL;\n",
1373 ((FuncArg *)m->args->data)->name);
1375 if(initializers > 0) {
1377 for(li = ((Class *)class)->nodes;
1381 Variable *v = (Variable *)n;
1382 if(n->type != VARIABLE_NODE ||
1383 v->scope == CLASS_SCOPE)
1385 print_initializer(m, v);
1388 } else if(m->method == CLASS_INIT_METHOD) {
1389 gboolean did_base_obj = FALSE;
1392 out_addline_infile(out, m->line_no);
1393 print_method(out, "static ", "\n", "", " ", "\n",
1394 m, FALSE, FALSE, TRUE);
1396 out_addline_outfile(out);
1397 out_printf(out, "{\n"
1398 "#define __GOB_FUNCTION__ \"%s::class_init\"\n",
1401 set_arguments > 0 ||
1402 get_arguments > 0 ||
1405 add_unused_class = TRUE;
1407 "\tGtkObjectClass *"
1408 "gtk_object_class = "
1409 "(GtkObjectClass*) %s;\n",
1410 ((FuncArg *)m->args->data)->name);
1412 "#ifdef G_OBJECT_CLASS\n"
1415 "(GObjectClass*) %s;\n"
1416 "#endif /* G_OBJECT_CLASS */\n",
1417 ((FuncArg *)m->args->data)->name);
1418 did_base_obj = TRUE;
1423 ((FuncArg *)m->args->data)->name,
1426 if(initializers > 0) {
1428 for(li = ((Class *)class)->nodes;
1432 Variable *v = (Variable *)n;
1433 if(n->type == VARIABLE_NODE &&
1434 v->scope == CLASS_SCOPE)
1435 print_initializer(m, v);
1439 out_printf(out, "\n\tparent_class = ");
1441 out_printf(out, "(%sClass *)", ptypebase);
1442 out_printf(out, "gtk_type_class (%s_get_type ());\n",
1448 set_def_handlers(c, ((FuncArg *)m->args->data)->name);
1450 /* if there are no handlers for these things, we
1451 * need to set them up here */
1452 if(need_destroy && !destroy_handler)
1453 out_printf(out, "\tgtk_object_class->destroy "
1455 if(need_finalize && !finalize_handler)
1457 "#ifdef G_OBJECT_CLASS\n"
1458 "\tg_object_class->finalize = ___finalize;\n"
1459 "#else /* !G_OBJECT_CLASS */\n"
1460 "\tgtk_object_class->finalize = ___finalize;\n"
1461 "#endif /* G_OBJECT_CLASS */\n");
1463 if(get_arguments > 0 || set_arguments > 0)
1470 out_printf(out, " {\n");
1471 out_addline_infile(out, m->ccode_line);
1472 out_printf(out, "%s\n", m->cbuf);
1473 out_addline_outfile(out);
1474 out_printf(out, " }\n");
1476 out_printf(out, "\treturn;\n");
1479 ((FuncArg *)m->args->data)->name);
1480 if(add_unused_class) {
1482 "\tgtk_object_class = NULL;\n"
1483 "#ifdef G_OBJECT_CLASS\n"
1484 "\tg_object_class = NULL;\n"
1485 "#endif /* G_OBJECT_CLASS */\n");
1487 out_printf(out, "}\n"
1488 "#undef __GOB_FUNCTION__\n");
1493 add_getset_arg(Class *c, gboolean is_set)
1496 out_printf(out, "\nstatic void\n"
1497 "___object_%s_arg (GtkObject *object,\n"
1500 "#define __GOB_FUNCTION__ \"%s::%s_arg\"\n"
1503 "\tself = %s (object);\n\n"
1504 "\tswitch (arg_id) {\n",
1505 is_set ? "set" : "get",
1506 c->otype, is_set ? "set" : "get",
1507 typebase, macrobase);
1509 for(li=c->nodes;li;li=g_list_next(li)) {
1515 if(n->type != ARGUMENT_NODE)
1520 line_no = a->set_line;
1523 line_no = a->get_line;
1527 s = g_strdup(a->name);
1529 out_printf(out, "\tcase ARG_%s:\n", s);
1530 if(is_set && a->atype) {
1531 char *cast = get_type(a->atype, TRUE);
1532 if(no_gnu || for_cpp) {
1533 out_printf(out, "#define ARG "
1534 "((%s)GTK_VALUE_%s(*arg))\n",
1537 out_printf(out, "#if defined(__GNUC__) && !defined(__STRICT_ANSI__)\n");
1538 if(strcmp(a->gtktype, "OBJECT")==0) {
1539 out_printf(out, "#define ARG "
1541 "GTK_VALUE_POINTER(*arg); "
1545 out_printf(out, "#define ARG "
1547 "GTK_VALUE_%s(*arg); "
1551 out_printf(out, "#else /* __GNUC__ && !__STRICT_ANSI__ */\n");
1552 out_printf(out, "#define ARG "
1553 "((%s)GTK_VALUE_%s(*arg))\n",
1555 out_printf(out, "#endif /* __GNUC__ && !__STRICT_ANSI__ */\n\n");
1557 out_printf(out, "\t\t{\n");
1559 } else if(!is_set && strcmp(a->gtktype, "OBJECT")==0) {
1561 "#define ARG (GTK_VALUE_POINTER(*arg))\n"
1565 "#define ARG (GTK_VALUE_%s(*arg))\n"
1571 out_addline_infile(out, line_no);
1572 out_printf(out, "%s\n", cbuf);
1574 out_addline_outfile(out);
1575 out_printf(out, "\t\t}\n\t\tbreak;\n"
1578 out_printf(out, "\tdefault:\n\t\tbreak;\n\t}\n"
1579 "\treturn;\n\tself = NULL;\n\targ = NULL;\n}\n"
1580 "#undef __GOB_FUNCTION__\n");
1584 print_checks(Method *m, FuncArg *fa)
1588 gboolean checked_null = FALSE;
1589 is_void = (strcmp(m->mtype->name, "void")==0 &&
1590 m->mtype->pointer == NULL);
1592 for(li = fa->checks; li; li = g_list_next(li)) {
1593 Check *ch = li->data;
1595 /* point to the method prot in .gob for failed checks */
1597 out_addline_infile(out, m->line_no);
1599 out_printf(out, "\tg_return_if_fail (");
1601 out_printf(out, "\tg_return_val_if_fail (");
1602 switch(ch->chtype) {
1604 out_printf(out, "%s != NULL", fa->name);
1605 checked_null = TRUE;
1608 s = make_pre_macro(fa->atype->name, "IS");
1610 out_printf(out, "%s (%s)", s, fa->name);
1612 /* if not check null, null may be valid */
1613 out_printf(out, "!(%s) || %s (%s)", fa->name,
1618 out_printf(out, "%s < %s", fa->name, ch->number);
1621 out_printf(out, "%s > %s", fa->name, ch->number);
1624 out_printf(out, "%s <= %s", fa->name, ch->number);
1627 out_printf(out, "%s >= %s", fa->name, ch->number);
1630 out_printf(out, "%s == %s", fa->name, ch->number);
1633 out_printf(out, "%s != %s", fa->name, ch->number);
1637 out_printf(out, ");\n");
1639 out_printf(out, ", (");
1640 print_type(out, m->mtype, TRUE);
1641 out_printf(out, ")%s);\n",
1642 m->onerror?m->onerror:"0");
1648 print_preconditions(Method *m)
1652 for(li=m->args;li;li=g_list_next(li)) {
1653 FuncArg *fa = li->data;
1655 print_checks(m, fa);
1658 out_addline_outfile(out);
1662 print_method_body(Method *m, int pre)
1664 out_printf(out, "{\n"
1665 "#define __GOB_FUNCTION__ \"%s::%s\"\n",
1666 ((Class *)class)->otype,
1667 get_real_id(m->id));
1669 print_preconditions(m);
1671 /* Note: the trailing }'s are on one line, this is so
1672 that we get the no return warning correctly and point to
1673 the correct line in the .gob file, yes this is slightly
1674 ugly in the .c file, but that is not supposed to be
1675 human readable anyway. */
1677 out_printf(out, "{\n");
1679 out_addline_infile(out, m->ccode_line);
1680 out_printf(out, "\t%s}", m->cbuf);
1683 /* Note, there is no \n between the last } and this } so that
1684 * errors/warnings reported on the end of the body get pointed to the
1685 * right line in the .gob source */
1686 out_printf(out, "}\n");
1689 out_addline_outfile(out);
1690 out_printf(out, "#undef __GOB_FUNCTION__\n");
1694 put_signal_args(Method *m)
1698 for(ali = m->gtktypes->next, li=m->args->next;
1700 li=li->next, ali=ali->next) {
1701 FuncArg *fa = li->data;
1702 const char *cast = get_cast(ali->data, FALSE);
1703 /* we should have already proved before that
1704 the we know all the types */
1707 out_printf(out, ",\n\t\t(%s)%s", cast,
1713 get_arg_names_for_macro(Method *m)
1717 GString *gs = g_string_new(NULL);
1719 for(li=m->args;li;li=g_list_next(li)) {
1720 FuncArg *arg = li->data;
1721 g_string_sprintfa(gs, "%s___%s", p, arg->name);
1725 g_string_free(gs, FALSE);
1730 put_method(Method *m)
1732 char *s, *args, *doc;
1734 is_void = (strcmp(m->mtype->name, "void")==0 &&
1735 m->mtype->pointer == NULL);
1736 out_printf(out, "\n");
1737 if(m->method != OVERRIDE_METHOD) {
1738 doc = get_gtk_doc(m->id);
1740 out_printf(out, "%s", doc);
1745 case REGULAR_METHOD:
1747 out_addline_infile(out, m->line_no);
1748 if(m->scope == PRIVATE_SCOPE)
1749 print_method(out, "static ", "\n", "", " ", "\n",
1750 m, FALSE, FALSE, TRUE);
1751 else /* PUBLIC, PROTECTED */
1752 print_method(out, "", "\n", "", " ", "\n",
1753 m, FALSE, FALSE, TRUE);
1754 print_method_body(m, TRUE);
1755 /* the outfile line was added above */
1757 case SIGNAL_FIRST_METHOD:
1758 case SIGNAL_LAST_METHOD:
1760 out_addline_infile(out, m->line_no);
1761 if(m->scope == PRIVATE_SCOPE)
1762 print_method(out, "static ", "\n", "", " ", "\n",
1763 m, FALSE, FALSE, TRUE);
1764 else /* PUBLIC, PROTECTED */
1765 print_method(out, "", "\n", "", " ", "\n",
1766 m, FALSE, FALSE, TRUE);
1767 out_addline_outfile(out);
1768 out_printf(out, "{\n");
1769 s = g_strdup(get_real_id(m->id));
1771 if(strcmp(m->mtype->name, "void") == 0 &&
1772 m->mtype->pointer == NULL) {
1773 print_preconditions(m);
1774 if(((FuncArg *)m->args->data)->name)
1775 out_printf(out, "\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1776 "\t\tobject_signals[%s_SIGNAL]",
1777 ((FuncArg *)m->args->data)->name, s);
1779 out_printf(out, ");\n}\n");
1781 out_printf(out, "\t");
1782 print_type(out, m->mtype, TRUE);
1783 out_printf(out, "return_val = (");
1784 print_type(out, m->mtype, TRUE);
1786 out_printf(out, ")(%s);\n", m->defreturn);
1788 out_printf(out, ")(%s);\n", m->onerror);
1790 out_printf(out, ")(0);\n");
1791 print_preconditions(m);
1792 out_printf(out, "\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1793 "\t\tobject_signals[%s_SIGNAL]",
1794 ((FuncArg *)m->args->data)->name, s);
1796 out_printf(out, ",\n\t\t&return_val);\n"
1797 "\treturn return_val;\n}\n");
1803 out_addline_infile(out, m->line_no);
1804 print_method(out, "static ", "\n___real_", "", " ", "\n",
1805 m, FALSE, FALSE, TRUE);
1806 print_method_body(m, FALSE);
1807 /* the outfile line was added above */
1809 case VIRTUAL_METHOD:
1811 out_addline_infile(out, m->line_no);
1812 if(m->scope==PRIVATE_SCOPE)
1813 print_method(out, "static ", "\n", "", " ", "\n",
1814 m, FALSE, FALSE, TRUE);
1815 else /* PUBLIC, PROTECTED */
1816 print_method(out, "", "\n", "", " ", "\n",
1817 m, FALSE, FALSE, TRUE);
1818 out_addline_outfile(out);
1819 out_printf(out, "{\n"
1820 "\t%sClass *klass;\n", typebase);
1821 print_preconditions(m);
1822 out_printf(out, "\tklass = %s_GET_CLASS(%s);\n\n"
1823 "\tif(klass->%s)\n",
1824 macrobase, ((FuncArg *)m->args->data)->name,
1825 get_real_id(m->id));
1826 if(strcmp(m->mtype->name, "void") == 0 &&
1827 m->mtype->pointer == NULL) {
1829 out_printf(out, "\t\t(*klass->%s)(%s",
1831 ((FuncArg *)m->args->data)->name);
1832 for(li=m->args->next;li;li=g_list_next(li)) {
1833 FuncArg *fa = li->data;
1834 out_printf(out, ",%s", fa->name);
1836 out_printf(out, ");\n}\n");
1839 out_printf(out, "\t\treturn (*klass->%s)(%s",
1841 ((FuncArg *)m->args->data)->name);
1842 for(li=m->args->next;li;li=g_list_next(li)) {
1843 FuncArg *fa = li->data;
1844 out_printf(out, ",%s", fa->name);
1846 out_printf(out, ");\n"
1849 print_type(out, m->mtype, TRUE);
1851 out_printf(out, ")(%s);\n}\n", m->defreturn);
1853 out_printf(out, ")(%s);\n}\n", m->onerror);
1855 out_printf(out, ")(0);\n}\n");
1861 out_addline_infile(out, m->line_no);
1862 print_method(out, "static ", "\n___real_", "", " ", "\n",
1863 m, FALSE, FALSE, TRUE);
1864 print_method_body(m, FALSE);
1865 /* the outfile line was added above */
1867 case OVERRIDE_METHOD:
1871 out_addline_infile(out, m->line_no);
1872 s = g_strdup_printf("\n___%x_", (guint)m->unique_id);
1873 print_method(out, "static ", s, "", " ", "\n",
1874 m, FALSE, FALSE, FALSE);
1876 out_addline_outfile(out);
1877 s = replace_sep(m->otype, '_');
1879 args = get_arg_names_for_macro(m);
1881 out_printf(out, "#define PARENT_HANDLER(%s) \\\n"
1882 "\t{ if(%s_CLASS(parent_class)->%s) \\\n"
1883 "\t\t(* %s_CLASS(parent_class)->%s)(%s); }\n",
1884 args, s, get_real_id(m->id), s, get_real_id(m->id), args);
1886 out_printf(out, "#define PARENT_HANDLER(%s) \\\n"
1887 "\t((%s_CLASS(parent_class)->%s)? \\\n"
1888 "\t\t(* %s_CLASS(parent_class)->%s)(%s): \\\n"
1890 args, s, get_real_id(m->id), s, get_real_id(m->id), args);
1891 out_printf(out, "(");
1892 print_type(out, m->mtype, TRUE);
1893 out_printf(out, ")%s))\n",
1894 m->onerror?m->onerror:"0");
1898 print_method_body(m, TRUE);
1899 /* the outfile line was added above */
1900 out_printf(out, "#undef PARENT_HANDLER\n");
1910 char *outfile, *outfileh, *outfileph;
1913 outfile = g_strconcat(filebase, ".c", NULL);
1915 outfile = g_strconcat(filebase, ".cc", NULL);
1916 if(no_touch_headers)
1917 outfileh = g_strconcat("#gob#", filebase, ".h#gob#", NULL);
1919 outfileh = g_strconcat(filebase, ".h", NULL);
1921 if((privates > 0 || protecteds > 0 ||
1922 private_header == PRIVATE_HEADER_ALWAYS) &&
1923 private_header != PRIVATE_HEADER_NEVER)
1924 outfileph = g_strconcat(filebase, "-private.h", NULL);
1930 devnull = fopen("/dev/null", "w");
1932 g_error("Cannot open null device");
1938 out = fopen(outfile, "w");
1940 g_error("Cannot open outfile: %s", outfile);
1942 outh = fopen(outfileh, "w");
1944 g_error("Cannot open outfile: %s", outfileh);
1946 outph = fopen(outfileph, "w");
1948 g_error("Cannot open outfile: %s", outfileh);
1954 put_argument_nongnu_wrappers(Class *c)
1958 if(get_arguments < 0 && set_arguments < 0)
1961 for(li=c->nodes;li;li=g_list_next(li)) {
1963 Argument *a = (Argument *)n;
1967 if(n->type != ARGUMENT_NODE)
1970 aname = g_strdup(a->name);
1974 cast = get_type(a->atype, TRUE);
1976 cast = g_strdup(get_cast(a->gtktype, TRUE));
1980 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1981 "\"%s\",(%s)(arg)\n",
1982 macrobase, aname, a->name, cast);
1984 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1985 "\"%s\",(%s*)(arg)\n",
1986 macrobase, aname, a->name, cast);
1989 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1991 macrobase, aname, a->name);
1993 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1995 macrobase, aname, a->name);
2003 put_argument_gnu_wrappers(Class *c)
2007 if(get_arguments < 0 && set_arguments < 0)
2010 for(li=c->nodes;li;li=g_list_next(li)) {
2012 Argument *a = (Argument *)n;
2015 if(n->type != ARGUMENT_NODE)
2017 s = g_strdup(a->name);
2020 cast = get_type(a->atype, TRUE);
2022 cast = g_strdup(get_cast(a->gtktype, TRUE));
2025 out_printf(outh, "#define %s_ARG_%s(arg) \t"
2026 "\"%s\",({%sz = (arg); z;})\n",
2027 macrobase, s, a->name, cast);
2029 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
2030 "\"%s\",({%s*z = (arg); z;})\n",
2031 macrobase, s, a->name, cast);
2034 out_printf(outh, "#define %s_ARG_%s(arg) \t"
2036 macrobase, s, a->name);
2038 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
2040 macrobase, s, a->name);
2048 print_ccode_block(CCode *cc)
2051 switch(cc->cctype) {
2053 /* HT code is printed exactly like normal header
2054 code but is printed before */
2057 out_printf(fp, "\n");
2060 /* AT code is printed exactly like normal 'all'
2061 code but is printed before */
2064 out_printf(outph, "\n");
2065 out_printf(outph, "%s\n", cc->cbuf);
2066 out_addline_infile(outph, cc->line_no);
2067 out_addline_outfile(outph);
2069 out_printf(outh, "\n");
2070 out_printf(outh, "%s\n", cc->cbuf);
2072 out_printf(fp, "\n");
2073 out_addline_infile(fp, cc->line_no);
2078 out_printf(fp, "\n");
2079 out_addline_infile(fp, cc->line_no);
2086 out_printf(fp, "\n");
2087 out_addline_infile(fp, cc->line_no);
2090 out_printf(fp, "%s\n", cc->cbuf);
2091 if(cc->cctype == C_CCODE ||
2092 cc->cctype == A_CCODE ||
2093 cc->cctype == AT_CCODE ||
2094 cc->cctype == PH_CCODE)
2095 out_addline_outfile(fp);
2099 print_class_block(Class *c)
2103 gboolean printed_private = FALSE;
2106 out_printf(out, "/* utility types we may need */\n");
2107 if(special_array[SPECIAL_2POINTER])
2108 out_printf(out, "typedef struct { "
2109 "gpointer a; gpointer b; "
2110 "} ___twopointertype;\n");
2111 if(special_array[SPECIAL_3POINTER])
2112 out_printf(out, "typedef struct { "
2113 "gpointer a; gpointer b; "
2115 "} ___threepointertype;\n");
2116 if(special_array[SPECIAL_INT_POINTER])
2117 out_printf(out, "typedef struct { "
2118 "gint a; gpointer b; "
2119 "} ___intpointertype;\n");
2120 out_printf(out, "\n");
2123 out_printf(outh, "\n/*\n"
2124 " * Type checking and casting macros\n"
2126 out_printf(outh, "#define %s\t"
2127 "(%s_get_type())\n",
2128 macrotype, funcbase);
2129 out_printf(outh, "#define %s(obj)\t"
2130 "GTK_CHECK_CAST((obj), %s_get_type(), %s)\n",
2131 macrobase, funcbase, typebase);
2132 out_printf(outh, "#define %s_CONST(obj)\t"
2133 "GTK_CHECK_CAST((obj), %s_get_type(), %s const)\n",
2134 macrobase, funcbase, typebase);
2135 out_printf(outh, "#define %s_CLASS(klass)\t"
2136 "GTK_CHECK_CLASS_CAST((klass), %s_get_type(), %sClass)\n",
2137 macrobase, funcbase, typebase);
2138 out_printf(outh, "#define %s(obj)\t"
2139 "GTK_CHECK_TYPE((obj), %s_get_type ())\n\n",
2141 out_printf(outh, "#ifdef GTK_CHECK_GET_CLASS\n"
2142 "#define %s_GET_CLASS(obj)\t"
2143 "GTK_CHECK_GET_CLASS((obj), %s_get_type(), %sClass)\n",
2144 macrobase, funcbase, typebase);
2145 out_printf(outh, "#else /* !GTK_CHECK_GET_CLASS */\n"
2146 "#define %s_GET_CLASS(obj)\t"
2147 "((%sClass *)GTK_OBJECT(obj)->klass)\n"
2148 "#endif /* GTK_CHECK_GET_CLASS */\n",
2149 macrobase, typebase);
2151 if( ! no_self_alias) {
2152 out_printf(out, "/* self casting macros */\n");
2153 out_printf(out, "#define SELF(x) %s(x)\n", macrobase);
2154 out_printf(out, "#define SELF_CONST(x) %s_CONST(x)\n", macrobase);
2155 out_printf(out, "#define IS_SELF(x) %s(x)\n", macrois);
2156 out_printf(out, "#define SELF_CLASS(x) %s_CLASS(x)\n\n",
2158 out_printf(out, "#define SELF_GET_CLASS(x) %s_GET_CLASS(x)\n\n",
2161 out_printf(out, "/* self typedefs */\n");
2162 out_printf(out, "typedef %s Self;\n", typebase);
2163 out_printf(out, "typedef %sClass SelfClass;\n\n", typebase);
2166 out_printf(out, "/* GTK_CLASS_TYPE for 1.2<->1.3/2.0 GTK+ compatibility */\n");
2168 "#ifndef GTK_CLASS_TYPE\n"
2169 "#define GTK_CLASS_TYPE(x) (GTK_OBJECT_CLASS(x)->type)\n"
2170 "#endif /* GTK_CLASS_TYPE */\n\n");
2172 if(privates > 0 || always_private_struct) {
2173 out_printf(outh, "\n/* Private structure type */\n");
2174 out_printf(outh, "typedef struct _%sPrivate %sPrivate;\n",
2175 typebase, typebase);
2177 out_printf(outh, "/* There are no privates, this "
2178 "structure is thus never defined */\n");
2181 out_printf(outh, "\n/*\n"
2182 " * Main object structure\n"
2184 s = replace_sep(c->otype, '_');
2186 out_printf(outh, "#ifndef __TYPEDEF_%s__\n"
2187 "#define __TYPEDEF_%s__\n", s, s);
2189 out_printf(outh, "typedef struct _%s %s;\n"
2190 "#endif\n", typebase, typebase);
2191 out_printf(outh, "struct _%s {\n\t%s __parent__;\n",
2192 typebase, ptypebase);
2193 for(l=c->nodes; l; l=g_list_next(l)) {
2194 static gboolean printed_public = FALSE;
2196 Variable *v = (Variable *)n;
2197 if(n->type == VARIABLE_NODE &&
2198 v->scope == PUBLIC_SCOPE) {
2199 if( ! printed_public) {
2200 out_printf(outh, "\t/*< public >*/\n");
2201 printed_public = TRUE;
2203 put_variable((Variable *)n, outh);
2206 /* put protecteds always AFTER publics */
2207 for(l=c->nodes; l; l=g_list_next(l)) {
2209 Variable *v = (Variable *)n;
2210 if(n->type == VARIABLE_NODE &&
2211 v->scope == PROTECTED_SCOPE) {
2212 if( ! printed_private) {
2213 out_printf(outh, "\t/*< private >*/\n");
2214 printed_private = TRUE;
2216 put_variable((Variable *)n, outh);
2219 if(privates > 0 || always_private_struct) {
2220 if( ! printed_private)
2221 out_printf(outh, "\t/*< private >*/\n");
2222 out_printf(outh, "\t%sPrivate *_priv;\n", typebase);
2224 out_printf(outh, "};\n");
2229 /* if we are to stick this into the private
2230 header, if not stick it directly into the
2237 out_printf(outfp, "struct _%sPrivate {\n",
2239 for(l=c->nodes; l; l=l->next) {
2241 Variable *v = (Variable *)n;
2242 if(n->type == VARIABLE_NODE &&
2243 v->scope == PRIVATE_SCOPE) {
2244 out_addline_infile(outfp, v->line_no);
2245 put_variable(v, outfp);
2248 out_addline_outfile(outfp);
2249 out_printf(outfp, "};\n");
2252 out_printf(outh, "\n/*\n"
2253 " * Class definition\n"
2255 out_printf(outh, "typedef struct _%sClass %sClass;\n",
2256 typebase, typebase);
2258 "struct _%sClass {\n\t%sClass __parent__;\n",
2259 typebase, ptypebase);
2260 for(l = c->nodes; l != NULL; l = l->next) {
2262 if(n->type == METHOD_NODE)
2263 put_vs_method((Method *)n);
2265 /* put class scope variables */
2266 for(l = c->nodes; l != NULL; l = l->next) {
2268 Variable *v = (Variable *)n;
2269 if(n->type == VARIABLE_NODE &&
2270 v->scope == CLASS_SCOPE)
2271 put_variable((Variable *)n, outh);
2273 out_printf(outh, "};\n\n");
2275 out_printf(out, "/* here are local prototypes */\n");
2276 if(set_arguments > 0) {
2277 out_printf(out, "static void ___object_set_arg "
2278 "(GtkObject *object, GtkArg *arg, "
2279 "guint arg_id);\n");
2281 if(get_arguments > 0) {
2282 out_printf(out, "static void ___object_get_arg "
2283 "(GtkObject *object, GtkArg *arg, "
2284 "guint arg_id);\n");
2287 out_printf(outh, "\n/*\n"
2288 " * Public methods\n"
2291 out_printf(outh, "GtkType\t%s_get_type\t(void)", funcbase);
2293 out_printf(outh, " G_GNUC_CONST;\n");
2295 out_printf(outh, ";\n");
2298 for(l = c->nodes; l != NULL; l = l->next) {
2300 if(n->type == METHOD_NODE) {
2301 put_pub_method((Method *)n);
2302 put_prot_method((Method *)n);
2303 put_priv_method_prot((Method *)n);
2307 /* this idea is less and less apealing to me */
2309 if(!no_signal_connect) {
2311 out_printf(outh, "\n/*\n"
2312 " * Signal connection methods\n"
2316 for(l=c->nodes;l;l=g_list_next(l)) {
2318 if(n->type == METHOD_NODE)
2319 put_signal_connect((Method *)n);
2325 /* argument wrapping macros */
2326 if(get_arguments > 0 || set_arguments > 0) {
2328 out_printf(outh, "\n/*\n"
2329 " * Argument wrapping macros\n"
2331 out_printf(outh, "#if defined(__GNUC__) && !defined(__STRICT_ANSI__)\n");
2332 put_argument_gnu_wrappers(c);
2333 out_printf(outh, "#else /* __GNUC__ && !__STRICT_ANSI__ */\n");
2334 put_argument_nongnu_wrappers(c);
2335 out_printf(outh, "#endif /* __GNUC__ && !__STRICT_ANSI__ */\n\n");
2337 out_printf(outh, "\n/*\n"
2338 " * Argument wrapping macros\n"
2340 put_argument_nongnu_wrappers(c);
2345 for(l = c->nodes; l != NULL; l = l->next) {
2347 if(n->type == METHOD_NODE)
2348 add_signal_prots((Method *)n);
2356 if(any_method_to_alias(c)) {
2358 out_printf(out, "/* Short form macros */\n");
2359 out_printf(out, "#if defined(__GNUC__) && !defined(__STRICT_ANSI__)\n");
2360 make_method_gnu_aliases(c);
2361 out_printf(out, "#endif /* __GNUC__ && !__STRICT_ANSI__ */\n");
2363 make_method_nongnu_aliases(c);
2366 out_printf(out, "/* a macro for creating a new object of our type */\n");
2368 "#define GET_NEW ((%s *)gtk_type_new(%s_get_type()))\n\n",
2369 typebase, funcbase);
2379 if(set_arguments > 0) {
2380 add_getset_arg(c, TRUE);
2383 if(get_arguments > 0) {
2384 add_getset_arg(c, FALSE);
2387 for(l = c->nodes; l != NULL; l = l->next) {
2389 if(n->type == METHOD_NODE)
2390 put_method((Method *)n);
2393 add_bad_hack_to_avoid_unused_warnings(c);
2397 print_version_macros(void)
2399 int major=0, minor=0, pl=0;
2400 sscanf(VERSION, "%d.%d.%d", &major, &minor, &pl);
2402 out_printf(out, "#define GOB_VERSION_MAJOR %d\n", major);
2403 out_printf(out, "#define GOB_VERSION_MINOR %d\n", minor);
2404 out_printf(out, "#define GOB_VERSION_PATCHLEVEL %d\n\n", pl);
2408 print_file_comments(void)
2412 out_printf(outh, "/* Generated by GOB (v%s)"
2413 " (do not edit directly) */\n\n", VERSION);
2415 out_printf(outph, "/* Generated by GOB (v%s)"
2416 " (do not edit directly) */\n\n", VERSION);
2417 out_printf(out, "/* Generated by GOB (v%s) on %s"
2418 " (do not edit directly) */\n\n",
2419 VERSION, ctime(&curtime));
2421 out_printf(out, "/* End world hunger, donate to the World Food Programme, http://www.wfp.org */\n\n");
2425 print_includes(void)
2427 gboolean found_header;
2430 /* We may need string.h for memset */
2431 if(destructors > 0 &&
2432 ! g_list_find_custom(include_files, "string.h", (GCompareFunc)strcmp)) {
2433 out_printf(out, "#include <string.h> /* memset() */\n\n");
2436 p = g_strconcat(filebase, ".h", NULL);
2437 found_header = TRUE;
2438 if( ! g_list_find_custom(include_files, p, (GCompareFunc)strcmp)) {
2439 out_printf(out, "#include \"%s.h\"\n\n", filebase);
2440 found_header = FALSE;
2444 /* if we are creating a private header see if it was included */
2446 p = g_strconcat(filebase, "-private.h", NULL);
2447 if( ! g_list_find_custom(include_files, p,
2448 (GCompareFunc)strcmp)) {
2449 out_printf(out, "#include \"%s-private.h\"\n\n",
2452 error_printf(GOB_WARN, 0,
2453 "Implicit private header include "
2455 "\tsource file, while public "
2456 "header is at a custom location, "
2458 "\texplicitly include "
2459 "the private header below the "
2467 print_header_prefixes(void)
2471 p = replace_sep(((Class *)class)->otype, '_');
2473 out_printf(outh, "#ifndef __%s_H__\n#define __%s_H__\n\n", p, p);
2475 out_printf(outph, "#ifndef __%s_PRIVATE_H__\n"
2476 "#define __%s_PRIVATE_H__\n\n"
2477 "#include \"%s.h\"\n\n", p, p, filebase);
2480 if( ! no_extern_c) {
2481 out_printf(outh, "#ifdef __cplusplus\n"
2483 "#endif /* __cplusplus */\n\n");
2485 out_printf(outph, "#ifdef __cplusplus\n"
2487 "#endif /* __cplusplus */\n\n");
2492 print_header_postfixes(void)
2495 out_printf(outh, "\n#ifdef __cplusplus\n"
2497 "#endif /* __cplusplus */\n");
2498 out_printf(outh, "\n#endif\n");
2501 out_printf(outph, "\n#ifdef __cplusplus\n"
2503 "#endif /* __cplusplus */\n");
2504 out_printf(outph, "\n#endif\n");
2513 /* print the AT_CCODE blocks */
2514 for(li = nodes; li != NULL; li = li->next) {
2515 Node *node = li->data;
2516 if(node->type == CCODE_NODE) {
2517 CCode *cc = (CCode *)node;
2518 if(cc->cctype == AT_CCODE)
2519 print_ccode_block((CCode *)node);
2525 print_header_top(void)
2529 /* mandatory include */
2530 out_printf(outh, "#include <gtk/gtk.h>\n\n");
2532 /* print the HT_CCODE blocks */
2533 for(li=nodes;li;li=g_list_next(li)) {
2534 Node *node = li->data;
2535 if(node->type == CCODE_NODE) {
2536 CCode *cc = (CCode *)node;
2537 if(cc->cctype == HT_CCODE)
2538 print_ccode_block((CCode *)node);
2544 generate_outfiles(void)
2548 print_file_comments();
2554 print_header_prefixes();
2556 print_version_macros();
2560 for(li=nodes;li;li=g_list_next(li)) {
2561 Node *node = li->data;
2562 if(node->type == CCODE_NODE) {
2563 CCode *cc = (CCode *)node;
2564 if(cc->cctype != HT_CCODE &&
2565 cc->cctype != AT_CCODE)
2566 print_ccode_block((CCode *)node);
2567 } else if(node->type == CLASS_NODE) {
2568 print_class_block((Class *)node);
2570 g_assert_not_reached();
2573 print_header_postfixes();
2579 fprintf(stderr, "Gob version %s\n\n", VERSION);
2580 fprintf(stderr, "gob [options] file.gob\n\n");
2581 fprintf(stderr, "Options:\n"
2582 "\t--help,-h,-? Display this help\n"
2583 "\t--version Display version\n"
2584 "\t--exit-on-warn,-w Exit with an error on warnings\n"
2585 "\t--no-exit-on-warn Don't exit on warnings [default]\n"
2586 "\t--for-cpp Create C++ files\n"
2587 "\t--no-extern-c Never print extern \"C\" into the "
2589 "\t--no-gnu Never use GNU extentions\n"
2590 "\t--no-touch-headers Don't touch headers unless they "
2592 "\t--always-private-header Always create a private header "
2594 "\t even if it would be empty "
2596 "\t--ondemand-private-header Create private header only when "
2598 "\t--no-private-header Don't create a private header, "
2600 "\t structure and protected "
2601 "prototypes inside c file\n"
2602 "\t--always-private-struct Always create a private pointer "
2604 "\t the object structure\n"
2605 "\t--no-write,-n Don't write output files, just "
2607 "\t--no-lines Don't print '#line' to output\n"
2608 "\t--no-self-alias Don't create self type and macro "
2610 "\t--no-kill-underscores Don't remove the leading underscore "
2612 "\t short id names\n");
2616 parse_options(int argc, char *argv[])
2619 int got_file = FALSE;
2620 int no_opts = FALSE;
2624 for(i = 1 ; i < argc; i++) {
2626 argv[i][0] != '-') {
2629 fprintf(stderr, "Specify only one file!\n");
2635 } else if(strcmp(argv[i], "--help")==0) {
2638 } else if(strcmp(argv[i], "--version")==0) {
2639 fprintf(stderr, "Gob version %s\n", VERSION);
2641 } else if(strcmp(argv[i], "--exit-on-warn")==0) {
2642 exit_on_warn = TRUE;
2643 } else if(strcmp(argv[i], "--no-exit-on-warn")==0) {
2644 exit_on_warn = FALSE;
2645 } else if(strcmp(argv[i], "--for-cpp")==0) {
2647 } else if(strcmp(argv[i], "--no-touch-headers")==0) {
2648 no_touch_headers = TRUE;
2649 } else if(strcmp(argv[i], "--ondemand-private-header")==0) {
2650 private_header = PRIVATE_HEADER_ONDEMAND;
2651 } else if(strcmp(argv[i], "--always-private-header")==0) {
2652 private_header = PRIVATE_HEADER_ALWAYS;
2653 } else if(strcmp(argv[i], "--no-private-header")==0) {
2654 private_header = PRIVATE_HEADER_NEVER;
2655 } else if(strcmp(argv[i], "--no-gnu")==0) {
2657 } else if(strcmp(argv[i], "--no-extern-c")==0) {
2659 } else if(strcmp(argv[i], "--no-write")==0) {
2661 } else if(strcmp(argv[i], "--no-lines")==0) {
2663 } else if(strcmp(argv[i], "--no-self-alias")==0) {
2664 no_self_alias = TRUE;
2665 } else if(strcmp(argv[i], "--no-kill-underscores")==0) {
2666 no_kill_underscores = TRUE;
2667 } else if(strcmp(argv[i], "--always-private-struct")==0) {
2668 always_private_struct = TRUE;
2669 } else if(strcmp(argv[i], "--")==0) {
2670 /*further arguments are files*/
2672 } else if(strncmp(argv[i], "--", 2)==0) {
2673 /*unknown long option*/
2674 fprintf(stderr, "Unknown option '%s'!\n", argv[i]);
2678 /*by now we know we have a string starting with
2679 - which is a short option string*/
2681 for(p = argv[i] + 1; *p; p++) {
2695 "Unknown option '%c'!\n", *p);
2704 /* this is a somewhat ugly hack, but it appears to work */
2706 compare_and_move_header(void)
2708 char *hfnew = g_strconcat("#gob#", filebase, ".h#gob#", NULL);
2709 char *hf = g_strconcat(filebase, ".h", NULL);
2711 if(stat(hf, &s) == 0) {
2713 s = g_strdup_printf("cmp '%s' '%s' > /dev/null", hf, hfnew);
2714 if(system(s) == 0) {
2715 if(unlink(hfnew) != 0)
2716 error_printf(GOB_ERROR, 0,
2717 "Can't remove new header file");
2725 error_printf(GOB_ERROR, 0,
2726 "Can't remove old header file");
2728 if(rename(hfnew, hf) != 0)
2729 error_printf(GOB_ERROR, 0,
2730 "Can't rename new header file");
2736 main(int argc, char *argv[])
2738 parse_options(argc, argv);
2741 yyin = fopen(filename, "r");
2743 fprintf(stderr, "Error: can't open file '%s'\n",
2750 /* This is where parsing is done */
2753 g_error("Parsing errors, quitting");
2756 error_print(GOB_ERROR, 0, " no class defined");
2759 exit_on_error = FALSE;
2761 signals = count_signals((Class *)class);
2762 set_arguments = count_set_arguments((Class *)class);
2763 get_arguments = count_get_arguments((Class *)class);
2764 overrides = count_overrides((Class *)class);
2765 privates = count_privates((Class *)class);
2766 protecteds = count_protecteds((Class *)class);
2767 destructors = count_destructors((Class *)class);
2768 initializers = count_initializers((Class *)class);
2771 make_inits((Class *)class);
2772 if(destructors > 0) {
2773 need_destroy = TRUE;
2774 find_destroy((Class *)class);
2777 need_finalize = TRUE;
2778 find_finalize((Class *)class);
2780 check_bad_symbols((Class *)class);
2781 check_duplicate_symbols((Class *)class);
2782 check_duplicate_overrides((Class *)class);
2783 check_duplicate_signals_args((Class *)class);
2784 check_public_new((Class *)class);
2785 check_vararg((Class *)class);
2786 check_firstarg((Class *)class);
2787 check_nonvoidempty((Class *)class);
2788 check_signal_args((Class *)class);
2789 check_argument_types((Class *)class);
2790 check_func_arg_checks((Class *)class);
2792 exit_on_error = TRUE;
2797 any_special = setup_special_array((Class *)class, special_array);
2801 generate_outfiles();
2812 if(no_touch_headers &&
2814 compare_and_move_header();