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 */
70 static gboolean overrode_get_type = FALSE; /* provided your won _get_type */
72 static gboolean made_aliases = FALSE; /* if we made any shorthand aliases
73 and need the REALLY UGLY HACK to
76 /* the special variable types we need to define */
77 static gboolean special_array[SPECIAL_LAST] = {0};
78 static gboolean any_special = FALSE;
80 static gboolean need_destroy = FALSE;
81 static Method * destroy_handler = NULL;
83 static gboolean need_finalize = FALSE;
84 static Method * finalize_handler = NULL;
91 gboolean no_touch_headers = FALSE;
92 gboolean for_cpp = FALSE;
93 gboolean no_gnu = FALSE;
94 gboolean exit_on_warn = FALSE;
95 gboolean exit_on_error = TRUE;
96 gboolean got_error = FALSE;
97 gint private_header = PRIVATE_HEADER_ALWAYS;
98 gboolean no_extern_c = FALSE;
99 gboolean no_write = FALSE;
100 gboolean no_lines = FALSE;
101 gboolean no_self_alias = FALSE;
102 gboolean no_kill_underscores = FALSE;
103 gboolean always_private_struct = FALSE;
105 int method_unique_id = 1;
110 filebase = replace_sep(((Class *)class)->otype, '-');
113 funcbase = replace_sep(((Class *)class)->otype, '_');
116 pfuncbase = replace_sep(((Class *)class)->ptype, '_');
117 g_strdown(pfuncbase);
119 macrobase = replace_sep(((Class *)class)->otype, '_');
122 macrois = make_pre_macro(((Class *)class)->otype, "IS");
123 macrotype = make_pre_macro(((Class *)class)->otype, "TYPE");
125 typebase = remove_sep(((Class *)class)->otype);
127 ptypebase = remove_sep(((Class *)class)->ptype);
131 get_type(const Type *t, gboolean postfix_to_stars)
138 s = remove_sep(t->name);
139 gs = g_string_new(s);
143 if(postfix_to_stars) {
145 /*XXX: this is ugly perhaps we can do this whole postfix thing
146 in a nicer way, we just count the number of '[' s and from
147 that we deduce the number of dimensions, so that we can print
149 for(p=t->postfix; p && *p; p++)
150 if(*p == '[') extra++;
152 g_string_append_c(gs, ' ');
155 g_string_append(gs, t->pointer);
156 for(i=0; i < extra; i++)
157 g_string_append_c(gs, '*');
158 g_string_append_c(gs, ' ');
162 g_string_free(gs, FALSE);
167 get_gtk_doc(const char *id)
174 val = g_hash_table_lookup(gtk_doc_hash, id);
176 return g_strdup_printf("/**\n * %s_%s:\n%s **/\n",
177 funcbase, get_real_id(id), val);
178 val = g_hash_table_lookup(gtk_doc_hash, get_real_id(id));
180 return g_strdup_printf("/**\n * %s_%s:\n%s **/\n",
181 funcbase, get_real_id(id), val);
186 print_type(FILE *fp, const 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,
198 const char *typeprefix,
199 const char *nameprefix,
200 const char *subnameprefix,
201 const char *namepostfix,
202 const char *afterargs,
205 gboolean one_arg_per_line,
206 gboolean no_funcbase,
207 gboolean kill_underscore)
212 out_printf(fp, "%s", typeprefix);
213 print_type(fp, m->mtype, TRUE);
216 id = get_real_id(m->id);
221 out_printf(fp, "%s%s%s%s(",
222 nameprefix, subnameprefix, id, namepostfix);
224 out_printf(fp, "%s%s_%s%s%s(",
225 nameprefix, funcbase, subnameprefix, id,
229 for(li=m->args; li; li=g_list_next(li)) {
230 FuncArg *arg = li->data;
231 print_type(fp, arg->atype, FALSE);
233 out_printf(fp, "%s%s,%s", arg->name,
234 arg->atype->postfix ?
235 arg->atype->postfix : "",
236 one_arg_per_line ? "\n\t\t\t\t\t" : " ");
238 out_printf(fp, "%s%s", arg->name,
239 arg->atype->postfix ?
240 arg->atype->postfix : "");
243 out_printf(fp, ",%s...",
244 one_arg_per_line ? "\n\t\t\t\t\t" : " ");
246 out_printf(fp, "void");
248 out_printf(fp, "%s)%s", afterargs, postfix);
252 any_method_to_alias(Class *c)
256 for(li=c->nodes;li;li=g_list_next(li)) {
257 Node *node = li->data;
258 if(node->type == METHOD_NODE) {
259 Method *m = (Method *)node;
261 if(m->method == INIT_METHOD ||
262 m->method == CLASS_INIT_METHOD ||
263 m->method == OVERRIDE_METHOD)
273 /* just the vararg macros, we use the same func pointers for these as in non-gnu */
275 make_method_gnu_aliases(Class *c)
279 for(li = c->nodes; li != NULL; li = li->next) {
280 Node *node = li->data;
281 if(node->type == METHOD_NODE) {
282 Method *m = (Method *)node;
284 if(m->method == INIT_METHOD ||
285 m->method == CLASS_INIT_METHOD ||
286 m->method == OVERRIDE_METHOD)
289 /* in C++ mode don't alias new */
290 if(for_cpp && strcmp(m->id, "new")==0)
294 out_printf(out, "#define %s(args...) "
295 "%s_%s(args)\n", m->id,
296 funcbase, get_real_id(m->id));
298 out_printf(out, "#define %s() "
300 funcbase, get_real_id(m->id));
306 make_method_nongnu_aliases(Class *c)
310 gboolean local_made_aliases = FALSE;
312 for(li=c->nodes; li; li=g_list_next(li)) {
313 Node *node = li->data;
314 if(node->type == METHOD_NODE) {
315 Method *m = (Method *)node;
317 if(m->method == INIT_METHOD ||
318 m->method == CLASS_INIT_METHOD ||
319 m->method == OVERRIDE_METHOD)
322 /* in C++ mode don't alias new */
323 if(for_cpp && strcmp(m->id, "new")==0)
326 if( ! local_made_aliases)
327 out_printf(out, "\n/* Short form pointers */\n");
329 print_method(out, "static ", "(* const ", "", ") ",
331 m, FALSE, TRUE, FALSE);
332 out_printf(out, " = %s_%s;\n", funcbase,
335 local_made_aliases = TRUE;
338 if(local_made_aliases) {
339 out_printf(out, "\n");
345 add_bad_hack_to_avoid_unused_warnings(Class *c)
349 /* if we haven't had any methods, just return */
354 out_printf(out, "\n\n#if (!defined __GNUC__) || (defined __GNUC__ && defined __STRICT_ANSI__)\n");
356 "/*REALLY BAD HACK\n"
357 " This is to avoid unused warnings if you don't call\n"
358 " some method. I need to find a better way to do\n"
359 " this, not needed in GCC since we use some gcc\n"
360 " extentions to make saner, faster code */\n"
362 "___%s_really_bad_hack_to_avoid_warnings(void)\n"
364 for(li=c->nodes;li;li=g_list_next(li)) {
365 Node *node = li->data;
366 if(node->type == METHOD_NODE) {
367 Method *m = (Method *)node;
369 if(m->method == INIT_METHOD ||
370 m->method == CLASS_INIT_METHOD ||
371 m->method == OVERRIDE_METHOD)
374 /* in C++ mode we don't alias new */
375 if(for_cpp && strcmp(m->id, "new")==0)
378 out_printf(out, "\t((void (*)(void))%s)();\n", m->id);
381 out_printf(out, "\t___%s_really_bad_hack_to_avoid_warnings();\n",
384 out_printf(out, "}\n#endif /* !__GNUC__ || (__GNUC__ && __STRICT_ANSI__) */\n\n");
386 out_printf(out, "}\n\n");
390 put_variable(Variable *v, FILE *fp)
392 out_printf(fp, "\t");
393 print_type(fp, v->vtype, FALSE);
394 out_printf(fp, "%s%s;", v->id,
396 v->vtype->postfix:"");
397 if(v->scope == PROTECTED_SCOPE)
398 out_printf(fp, " /* protected */");
399 out_printf(fp, "\n");
403 put_vs_method(const Method *m)
405 if(m->method != SIGNAL_LAST_METHOD &&
406 m->method != SIGNAL_FIRST_METHOD &&
407 m->method != VIRTUAL_METHOD)
410 /* if a signal mark it as such */
411 if(m->method != VIRTUAL_METHOD)
412 print_method(outh, "\t/*signal*/", "(* ", "", ") ", "", ";\n",
413 m, FALSE, TRUE, TRUE);
415 print_method(outh, "\t", "(* ", "", ") ", "", ";\n",
416 m, FALSE, TRUE, TRUE);
420 put_pub_method(const Method *m)
422 if(m->scope != PUBLIC_SCOPE)
425 print_method(outh, "", "\t", "", "\t", "", ";\n", m, TRUE, FALSE, TRUE);
429 put_signal_macro (const Method *m, gboolean gnu)
433 if(m->method != SIGNAL_LAST_METHOD &&
434 m->method != SIGNAL_FIRST_METHOD)
437 id = g_strdup (m->id);
441 out_printf (outh, "#define %s_SIGNAL_%s(func)\t"
442 "\"%s\",GTK_SIGNAL_FUNC(func)\n",
443 macrobase, id, get_real_id (m->id));
445 out_printf (outh, "#define %s_SIGNAL_%s(func)\t"
446 "\"%s\",GTK_SIGNAL_FUNC(({",
447 macrobase, id, get_real_id (m->id));
448 print_method (outh, "", "(* ___", "", ") ", ", gpointer data ",
449 " = func; ", m, FALSE, TRUE, TRUE);
450 out_printf (outh, "___%s; }))\n", get_real_id (m->id));
457 put_signal_macros (const Class *c, gboolean gnu)
464 for (li = c->nodes; li != NULL; li = li->next) {
465 const Node *n = li->data;
466 if (n->type == METHOD_NODE)
467 put_signal_macro ((Method *)n, gnu);
473 put_prot_method(const Method *m)
475 if(m->scope != PROTECTED_SCOPE)
479 print_method(outph, "", "\t", "", "\t", "", ";\n",
480 m, FALSE, FALSE, TRUE);
482 print_method(out, "", "\t", "", "\t", "", ";\n",
483 m, FALSE, FALSE, TRUE);
487 put_priv_method_prot(Method *m)
489 if(m->method == SIGNAL_LAST_METHOD ||
490 m->method == SIGNAL_FIRST_METHOD ||
491 m->method == VIRTUAL_METHOD) {
494 "static ", "___real_", "", " ", "", ";\n",
495 m, FALSE, FALSE, TRUE);
497 /* no else, here, it might still have a private prototype, it's not
500 if((m->method == OVERRIDE_METHOD &&
503 char *s = g_strdup_printf("___%x_", (guint)m->unique_id);
504 print_method(out, "static ", s, "", " ", "",
505 no_gnu?";\n":" G_GNUC_UNUSED;\n",
506 m, FALSE, FALSE, FALSE);
508 } else if(m->scope == PRIVATE_SCOPE ||
509 m->method == INIT_METHOD ||
510 m->method == CLASS_INIT_METHOD)
511 print_method(out, "static ", "", "", " ", "",
512 no_gnu?";\n":" G_GNUC_UNUSED;\n",
513 m, FALSE, FALSE, TRUE);
517 make_func_arg(char *typename, int is_class, char *name)
524 tn = g_strconcat(typename, ":Class", NULL);
526 tn = g_strdup(typename);
528 type = new_type(tn, g_strdup("*"), NULL);
529 node = new_funcarg((Type *)type, name, NULL);
530 return g_list_prepend(NULL, node);
534 make_inits(Class *cl)
536 int got_class_init = FALSE;
537 int got_init = FALSE;
540 for(li=cl->nodes;li;li=g_list_next(li)) {
542 if(n->type == METHOD_NODE) {
543 Method *m = (Method *)n;
544 if(m->method == INIT_METHOD) {
546 error_print(GOB_ERROR, m->line_no, "init defined more then once");
548 } else if(m->method == CLASS_INIT_METHOD) {
550 error_print(GOB_ERROR, m->line_no, "class_init defined more then once");
551 got_class_init = TRUE;
555 if(!got_class_init) {
556 node = new_method(NO_SCOPE, CLASS_INIT_METHOD,
557 (Type *)new_type(g_strdup("void"),
559 NULL, NULL, NULL, g_strdup("class_init"),
560 make_func_arg(cl->otype, TRUE, g_strdup("c")),
561 NULL, NULL, NULL, 0, 0, FALSE,
563 cl->nodes = g_list_prepend(cl->nodes, node);
566 node = new_method(NO_SCOPE, INIT_METHOD,
567 (Type *)new_type(g_strdup("void"),
569 NULL, NULL, NULL, g_strdup("init"),
570 make_func_arg(cl->otype, FALSE, g_strdup("o")),
571 NULL, NULL, NULL, 0, 0, FALSE,
573 cl->nodes = g_list_prepend(cl->nodes, node);
578 find_destroy(Class *cl)
582 destroy_handler = NULL;
583 for(li=cl->nodes;li;li=g_list_next(li)) {
585 if(n->type == METHOD_NODE) {
586 Method *m = (Method *)n;
587 if(m->method == OVERRIDE_METHOD &&
588 strcmp(m->id, "destroy")==0) {
589 if(strcmp(m->otype, "Gtk:Object") != 0) {
590 error_print(GOB_ERROR, m->line_no,
591 "destroy method override "
592 "of class other then "
595 if(g_list_length(m->args) != 1) {
596 error_print(GOB_ERROR, m->line_no,
597 "destroy method override "
598 "with more then one "
609 find_finalize(Class *cl)
613 finalize_handler = NULL;
614 for(li=cl->nodes;li;li=g_list_next(li)) {
616 if(n->type == METHOD_NODE) {
617 Method *m = (Method *)n;
618 if(m->method == OVERRIDE_METHOD &&
619 strcmp(m->id, "finalize")==0) {
620 if(strcmp(m->otype, "Gtk:Object") != 0 &&
621 strcmp(m->otype, "G:Object") != 0) {
622 error_print(GOB_ERROR, m->line_no,
623 "finalize method override "
624 "of class other then "
625 "Gtk:Object (or G:Object"
628 if(g_list_length(m->args) != 1) {
629 error_print(GOB_ERROR, m->line_no,
630 "finalize method override "
631 "with more then one "
634 finalize_handler = m;
642 /* hash of method -> name of signal prototype */
643 static GHashTable *marsh = NULL;
645 /* list of methods with different signal prototypes,
646 we check this list if we can use a signal prototype of a
647 previous signal method, there are only uniques here */
648 static GList *eq_signal_methods = NULL;
650 /* compare a list of strings */
652 is_list_equal(GList *a, GList *b)
654 for(;a && b; a=a->next, b=b->next) {
655 if(strcmp(a->data, b->data)!=0) {
659 /* the the lists were different length */
666 find_same_type_signal(Method *m)
669 for(li=eq_signal_methods;li;li=li->next) {
670 Method *mm = li->data;
671 if(is_list_equal(mm->gtktypes, m->gtktypes))
678 print_signal_marsal_args(Method *m)
680 if(strcmp(m->gtktypes->next->data, "NONE")!=0) {
683 for(i=0, li=m->gtktypes->next;li;
684 i++, li=g_list_next(li)) {
686 out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
687 (char *)li->data, i);
689 out_printf(out, ",\n\t\t(%s)"
690 "GTK_VALUE_%s(args[%d])",
691 get_cast(li->data, FALSE),
692 (char *)li->data, i);
696 out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
701 add_signal_prots(Method *m)
708 if(m->method != SIGNAL_LAST_METHOD &&
709 m->method != SIGNAL_FIRST_METHOD)
713 marsh = g_hash_table_new(NULL, NULL);
715 if(strcmp(m->gtktypes->data, "NONE")==0 &&
716 strcmp(m->gtktypes->next->data, "NONE")==0)
719 /* if we already did a signal prototype just use that */
720 mm = find_same_type_signal(m);
722 s = g_hash_table_lookup(marsh, mm);
723 g_hash_table_insert(marsh, m, s);
727 s = g_strdup_printf("Sig%d", sig++);
729 g_hash_table_insert(marsh, m, s);
730 eq_signal_methods = g_list_prepend(eq_signal_methods, m);
732 /* we know that we'll know all the gtktypes (so get_cast can't fail) */
733 out_printf(out, "\ntypedef %s (*___%s) (%s *, ",
734 get_cast(m->gtktypes->data, FALSE), s, typebase);
736 if(strcmp(m->gtktypes->next->data, "NONE")!=0) {
737 for(li=m->gtktypes->next; li; li=g_list_next(li))
738 out_printf(out, "%s, ", get_cast(li->data, FALSE));
740 out_printf(out, "gpointer);\n");
742 out_printf(out, "\nstatic void\n"
743 "___marshal_%s (GtkObject * object,\n"
744 "\tGtkSignalFunc func,\n"
745 "\tgpointer func_data,\n"
749 if(strcmp(m->gtktypes->data, "NONE")==0) {
750 out_printf(out, "\t___%s rfunc;\n\n"
751 "\trfunc = (___%s)func;\n\n"
752 "\t(*rfunc)((%s *)object", s, s, typebase);
754 const char *retcast = get_cast(m->gtktypes->data, FALSE);
755 gboolean is_none = (strcmp(m->gtktypes->next->data, "NONE")==0);
759 "\trfunc = (___%s)func;\n\n"
760 "\tretval = GTK_RETLOC_%s(args[%d]);\n\n"
761 "\t*retval = (*rfunc)((%s *)object",
763 (char *)m->gtktypes->data,
764 g_list_length(m->gtktypes) - (is_none ? 2 : 1),
767 print_signal_marsal_args(m);
775 out_printf(out, "\n");
777 out_printf(out, "enum {\n");
778 for(li=c->nodes;li;li=g_list_next(li)) {
780 if(n->type == METHOD_NODE) {
781 Method *m = (Method *)n;
782 if(m->method == SIGNAL_LAST_METHOD ||
783 m->method == SIGNAL_FIRST_METHOD) {
784 char *s = g_strdup(get_real_id(m->id));
786 out_printf(out, "\t%s_SIGNAL,\n", s);
791 out_printf(out, "\tLAST_SIGNAL\n};\n\n");
793 if(set_arguments > 0 || get_arguments > 0) {
794 out_printf(out, "enum {\n\tARG_0");
795 for(li=c->nodes;li;li=g_list_next(li)) {
797 if(n->type == ARGUMENT_NODE) {
798 Argument *a = (Argument *)n;
799 char *s = g_strdup(a->name);
801 out_printf(out, ",\n\tARG_%s", s);
805 out_printf(out, "\n};\n\n");
810 "static guint object_signals[LAST_SIGNAL] = {0};\n\n");
812 out_printf(out, "/* pointer to the class of our parent */\n");
813 out_printf(out, "static %sClass *parent_class = NULL;\n\n", ptypebase);
819 char *chunk_size = ((Class*)class)->chunk_size;
823 "%s_get_type (void)\n"
825 "\tstatic GtkType type = 0;\n\n"
826 "\tif (type == 0) {\n"
827 "\t\tstatic const GtkTypeInfo info = {\n"
829 "\t\t\tsizeof (%s),\n"
830 "\t\t\tsizeof (%sClass),\n"
831 "\t\t\t(GtkClassInitFunc) %s_class_init,\n"
832 "\t\t\t(GtkObjectInitFunc) %s_init,\n"
833 "\t\t\t/* reserved_1 */ NULL,\n"
834 "\t\t\t/* reserved_2 */ NULL,\n"
835 "\t\t\t(GtkClassInitFunc) NULL\n"
837 "\t\ttype = gtk_type_unique (%s_get_type(), &info);\n",
838 funcbase, typebase, typebase, typebase,
839 funcbase, funcbase, pfuncbase);
843 "\t\tgtk_type_set_chunk_alloc(type, %s);\n"
845 chunk_size, chunk_size);
854 add_overrides(Class *c, const char *oname, gboolean did_base_obj)
860 done = g_hash_table_new(g_str_hash, g_str_equal);
862 s = g_strdup("GtkObject"); /* This was already done */
863 g_hash_table_insert(done, s, s);
864 s = g_strdup("GObject"); /* This was probably already done as well (if using Gtk/Glib 1.3/2.0) */
865 g_hash_table_insert(done, s, s);
867 for(li=c->nodes; li; li=g_list_next(li)) {
870 Method *m = (Method *)n;
871 if(n->type != METHOD_NODE ||
872 m->method != OVERRIDE_METHOD)
875 s = remove_sep(m->otype);
877 if(g_hash_table_lookup(done, s)) {
881 g_hash_table_insert(done, s, s);
883 f = replace_sep(m->otype, '_');
886 out_printf(out, "\t%sClass *%s_class = (%sClass *)%s;\n",
891 g_hash_table_foreach(done, (GHFunc)g_free, NULL);
892 g_hash_table_destroy(done);
896 make_run_signal_flags(Method *m, gboolean last)
910 gs = g_string_new(NULL);
913 g_string_assign(gs, "GTK_RUN_LAST");
915 g_string_assign(gs, "GTK_RUN_FIRST");
917 if(m->scope == PUBLIC_SCOPE)
918 g_string_append(gs, " | GTK_RUN_ACTION");
920 for(li = m->flags; li; li = li->next) {
921 char *flag = li->data;
923 for(i=0;flags[i];i++) {
924 if(strcmp(flags[i], flag)==0)
927 /* if we haven't found it in our list */
929 error_printf(GOB_WARN, m->line_no,
930 "Unknown flag '%s' used, "
931 "perhaps it was misspelled",
934 g_string_sprintfa(gs, " | GTK_RUN_%s", flag);
939 g_string_free(gs, FALSE);
946 add_signals(Class *c)
950 out_printf(out, "\n");
951 for(li=c->nodes;li;li=g_list_next(li)) {
953 char *mar, *sig, *flags;
954 gboolean is_none, last = FALSE;
955 Method *m = (Method *)n;
957 if(n->type != METHOD_NODE ||
958 (m->method != SIGNAL_FIRST_METHOD &&
959 m->method != SIGNAL_LAST_METHOD))
962 if(m->method == SIGNAL_FIRST_METHOD)
967 if(g_hash_table_lookup(marsh, m))
968 mar = g_strconcat("___marshal_",
969 (char *)g_hash_table_lookup(marsh, m),
972 mar = g_strdup("gtk_signal_default_marshaller");
974 is_none = (strcmp(m->gtktypes->next->data, "NONE")==0);
976 sig = g_strdup(get_real_id(m->id));
978 flags = make_run_signal_flags(m, last);
979 out_printf(out, "\tobject_signals[%s_SIGNAL] =\n"
980 "\t\tgtk_signal_new (\"%s\",\n"
981 "\t\t\t(GtkSignalRunType)(%s),\n"
982 "\t\t\tGTK_CLASS_TYPE(gtk_object_class),\n"
983 "\t\t\tGTK_SIGNAL_OFFSET (%sClass, %s),\n"
985 "\t\t\tGTK_TYPE_%s, %d",
986 sig, get_real_id(m->id),
988 typebase, get_real_id(m->id), mar,
989 (char *)m->gtktypes->data,
990 is_none ? 0 : g_list_length(m->gtktypes->next));
997 for(l = m->gtktypes->next; l != NULL; l = l->next)
998 out_printf(out, ",\n\t\t\tGTK_TYPE_%s",
1002 out_printf(out, ");\n");
1004 if(strcmp(m->gtktypes->data, "NONE") != 0 ||
1008 out_printf(out, "\tif(");
1009 if(strcmp(m->gtktypes->data, "NONE") != 0) {
1010 out_printf(out, "%s sizeof(", sep);
1011 print_type(out, m->mtype, FALSE);
1012 out_printf(out, "%s",
1014 m->mtype->postfix : "");
1015 out_printf(out, ") != sizeof(%s)",
1016 get_cast(m->gtktypes->data, FALSE));
1021 for(al = m->args->next, gl = m->gtktypes->next;
1022 al != NULL && gl != NULL;
1023 al = al->next, gl = gl->next) {
1024 FuncArg *arg = al->data;
1025 char *gtkarg = gl->data;
1027 out_printf(out, "%ssizeof(", sep);
1028 print_type(out, arg->atype, FALSE);
1029 out_printf(out, "%s",
1030 arg->atype->postfix ?
1031 arg->atype->postfix : "");
1032 out_printf(out, ") != sizeof(%s)",
1033 get_cast(gtkarg, FALSE));
1037 out_printf(out, ") {\n"
1038 "\t\tg_error(\"%s line %d: Type mismatch "
1039 "of \\\"%s\\\" signal signature\");\n"
1041 filename, m->line_no, get_real_id(m->id));
1045 out_printf(out, "\tgtk_object_class_add_signals (gtk_object_class,\n"
1046 "\t\tobject_signals, LAST_SIGNAL);\n\n");
1050 set_def_handlers(Class *c, const char *oname)
1053 gboolean set_line = FALSE;
1055 out_printf(out, "\n");
1056 for(li = c->nodes; li; li = g_list_next(li)) {
1058 Method *m = (Method *)n;
1060 if(n->type != METHOD_NODE ||
1061 (m->method != SIGNAL_FIRST_METHOD &&
1062 m->method != SIGNAL_LAST_METHOD &&
1063 m->method != VIRTUAL_METHOD &&
1064 m->method != OVERRIDE_METHOD))
1067 if(m->line_no > 0 && m->cbuf) {
1068 out_addline_infile(out, m->line_no);
1070 } else if(set_line) {
1071 out_addline_outfile(out);
1076 if(m->method == OVERRIDE_METHOD) {
1078 s = replace_sep(m->otype, '_');
1083 strcmp(get_real_id(m->id), "destroy") == 0)
1084 out_printf(out, "\tgtk_object_class->destroy "
1086 else if(need_finalize &&
1088 strcmp(get_real_id(m->id), "finalize") == 0)
1090 "#ifdef G_OBJECT_CLASS\n"
1091 "\tg_object_class->finalize = ___finalize;\n"
1092 "#else /* !G_OBJECT_CLASS */\n"
1093 "\tgtk_object_class->finalize = ___finalize;\n"
1094 "#endif /* G_OBJECT_CLASS */\n");
1097 "\t%s_class->%s = ___%x_%s_%s;\n",
1098 s, get_real_id(m->id), (guint)m->unique_id,
1099 funcbase, get_real_id(m->id));
1101 out_printf(out, "\t%s_class->%s = NULL;\n",
1102 s, get_real_id(m->id));
1105 out_printf(out, "\t%s->%s = ___real_%s_%s;\n",
1106 oname, get_real_id(m->id),
1107 funcbase, get_real_id(m->id));
1109 out_printf(out, "\t%s->%s = NULL;\n",
1110 oname, get_real_id(m->id));
1114 out_addline_outfile(out);
1118 make_arguments(Class *c)
1121 char *argflags[] = {
1129 out_printf(out, "\n");
1130 for(li=c->nodes;li;li=g_list_next(li)) {
1136 if(n->type != ARGUMENT_NODE)
1141 if(a->get && a->set)
1142 flags = g_string_new("GTK_ARG_READWRITE");
1144 flags = g_string_new("GTK_ARG_READABLE");
1146 flags = g_string_new("GTK_ARG_WRITABLE");
1148 g_assert(a->get || a->set);
1150 for(l=a->flags;l;l=g_list_next(l)) {
1151 char *flag = l->data;
1153 if(strcmp(flag, "READWRITE")==0 ||
1154 strcmp(flag, "READABLE")==0 ||
1155 strcmp(flag, "WRITABLE")==0) {
1156 error_print(GOB_WARN, a->line_no,
1157 "READWRITE, READABLE and "
1158 "WRITABLE argument flags are "
1159 "set automatically");
1162 for(i = 0; argflags[i]; i++) {
1163 if(strcmp(argflags[i], flag)==0)
1166 /* if we haven't found it in our list */
1167 if( ! argflags[i]) {
1168 error_printf(GOB_WARN, a->line_no,
1169 "Unknown flag '%s' used, "
1170 "perhaps it was misspelled", flag);
1172 g_string_sprintfa(flags, " | GTK_ARG_%s", flag);
1175 s = g_strdup(a->name);
1177 out_printf(out, "\tgtk_object_add_arg_type(\"%s::%s\",\n"
1178 "\t\tGTK_TYPE_%s,\n"
1181 typebase, a->name, a->gtktype, flags->str, s);
1183 g_string_free(flags, TRUE);
1186 out_printf(out, "\n");
1187 if(get_arguments > 0)
1188 out_printf(out, "\tgtk_object_class->get_arg = ___object_get_arg;\n");
1189 if(set_arguments > 0)
1190 out_printf(out, "\tgtk_object_class->set_arg = ___object_set_arg;\n");
1194 print_initializer(Method *m, Variable *v)
1198 if(v->initializer == NULL)
1201 if(v->scope == PRIVATE_SCOPE)
1202 root = g_strconcat(((FuncArg *)m->args->data)->name,
1205 root = g_strdup(((FuncArg *)m->args->data)->name);
1207 if(v->initializer_line > 0)
1208 out_addline_infile(out, v->initializer_line);
1210 out_printf(out, "\t%s->%s = %s;\n",
1211 root, v->id, v->initializer);
1213 if(v->initializer_line > 0)
1214 out_addline_outfile(out);
1220 print_destructor(Variable *v)
1224 if(v->destructor == NULL)
1227 if(v->scope == PRIVATE_SCOPE)
1228 root = "self->_priv";
1232 if(v->destructor_simple) {
1233 if(v->destructor_line > 0)
1234 out_addline_infile(out, v->destructor_line);
1236 out_printf(out, "\tif(%s->%s) { "
1237 "((*(void (*)(void *))%s)) (%s->%s); "
1238 "%s->%s = NULL; }\n",
1239 root, v->id, v->destructor, root, v->id,
1242 if(v->destructor_line > 0)
1243 out_addline_outfile(out);
1245 out_printf(out, "#define VAR (%s->%s)\n", root, v->id);
1246 out_printf(out, "\t{\n");
1247 if(v->destructor_line > 0)
1248 out_addline_infile(out, v->destructor_line);
1250 out_printf(out, "\t%s}\n", v->destructor);
1252 if(v->destructor_line > 0)
1253 out_addline_outfile(out);
1254 out_printf(out, "\tmemset(&VAR, 0, sizeof(VAR));\n");
1255 out_printf(out, "#undef VAR\n");
1260 add_destroy(Class *c)
1262 out_printf(out, "\nstatic void\n"
1263 "___destroy(GtkObject *obj_self)\n"
1266 "#define __GOB_FUNCTION__ \"%s::destroy\"\n",
1269 if(destructors > 0) {
1270 out_printf(out, "\t%s *self = %s (obj_self);\n",
1271 typebase, macrobase);
1274 if(destroy_handler) {
1275 /* so we get possible bad argument warning */
1276 if(destroy_handler->line_no > 0)
1277 out_addline_infile(out, destroy_handler->line_no);
1278 out_printf(out, "\t___%x_%s_destroy(obj_self);\n",
1279 (guint)destroy_handler->unique_id, funcbase);
1280 if(destroy_handler->line_no > 0)
1281 out_addline_outfile(out);
1284 "\tif(GTK_OBJECT_CLASS(parent_class)->destroy) \\\n"
1285 "\t\t(* GTK_OBJECT_CLASS(parent_class)->destroy)(obj_self);\n");
1288 if(destructors > 0) {
1290 for(li = ((Class *)class)->nodes;
1294 Variable *v = (Variable *)n;
1295 if(n->type == VARIABLE_NODE &&
1296 v->scope != CLASS_SCOPE)
1297 print_destructor(v);
1301 out_printf(out, "\treturn;\n");
1303 out_printf(out, "\tself = NULL;\n");
1304 out_printf(out, "}\n"
1305 "#undef __GOB_FUNCTION__\n\n");
1309 add_finalize(Class *c)
1311 /* Sort of a hack to make it work with gtk+ 1.3/2.0 */
1313 "\n#ifdef G_OBJECT_CLASS\n"
1315 "___finalize(GObject *obj_self)\n"
1316 "#else /* !G_OBJECT_CLASS */\n"
1318 "___finalize(GtkObject *obj_self)\n"
1319 "#endif /* G_OBJECT_CLASS */\n"
1322 "#define __GOB_FUNCTION__ \"%s::finalize\"\n",
1326 out_printf(out, "\t%s *self = %s (obj_self);\n",
1327 typebase, macrobase);
1328 out_printf(out, "\tgpointer priv = self->_priv;\n");
1331 if(finalize_handler) {
1332 /* so we get possible bad argument warning */
1333 if(finalize_handler->line_no > 0)
1334 out_addline_infile(out, finalize_handler->line_no);
1335 out_printf(out, "\t___%x_%s_finalize(obj_self);\n",
1336 (guint)finalize_handler->unique_id, funcbase);
1337 if(finalize_handler->line_no > 0)
1338 out_addline_outfile(out);
1340 /* Sort of a hack to make it work with gtk+ 1.3/2.0 */
1342 "#ifdef G_OBJECT_CLASS\n"
1343 "\tif(G_OBJECT_CLASS(parent_class)->finalize) \\\n"
1344 "\t\t(* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);\n"
1345 "#else /* !G_OBJECT_CLASS */\n"
1346 "\tif(GTK_OBJECT_CLASS(parent_class)->finalize) \\\n"
1347 "\t\t(* GTK_OBJECT_CLASS(parent_class)->finalize)(obj_self);\n"
1348 "#endif /* G_OBJECT_CLASS */\n");
1352 out_printf(out, "\tg_free(priv);\n");
1355 out_printf(out, "}\n"
1356 "#undef __GOB_FUNCTION__\n\n");
1363 for(li=c->nodes;li;li=g_list_next(li)) {
1367 gboolean add_unused_class = FALSE;
1369 if(n->type != METHOD_NODE)
1372 if(m->method == INIT_METHOD) {
1374 out_addline_infile(out, m->line_no);
1375 print_method(out, "static ", "\n", "", " ", "", "\n",
1376 m, FALSE, FALSE, TRUE);
1378 out_addline_outfile(out);
1379 out_printf(out, "{\n"
1380 "#define __GOB_FUNCTION__ \"%s::init\"\n",
1383 out_printf(out, "\t%s->_priv = "
1384 "g_new0 (%sPrivate, 1);\n",
1385 ((FuncArg *)m->args->data)->name,
1387 } else if(always_private_struct) {
1388 out_printf(out, "\t%s->_priv = NULL;\n",
1389 ((FuncArg *)m->args->data)->name);
1391 if(initializers > 0) {
1393 for(li = ((Class *)class)->nodes;
1397 Variable *v = (Variable *)n;
1398 if(n->type != VARIABLE_NODE ||
1399 v->scope == CLASS_SCOPE)
1401 print_initializer(m, v);
1404 } else if(m->method == CLASS_INIT_METHOD) {
1405 gboolean did_base_obj = FALSE;
1408 out_addline_infile(out, m->line_no);
1409 print_method(out, "static ", "\n", "", " ", "", "\n",
1410 m, FALSE, FALSE, TRUE);
1412 out_addline_outfile(out);
1413 out_printf(out, "{\n"
1414 "#define __GOB_FUNCTION__ \"%s::class_init\"\n",
1417 set_arguments > 0 ||
1418 get_arguments > 0 ||
1421 add_unused_class = TRUE;
1423 "\tGtkObjectClass *"
1424 "gtk_object_class = "
1425 "(GtkObjectClass*) %s;\n",
1426 ((FuncArg *)m->args->data)->name);
1428 "#ifdef G_OBJECT_CLASS\n"
1431 "(GObjectClass*) %s;\n"
1432 "#endif /* G_OBJECT_CLASS */\n",
1433 ((FuncArg *)m->args->data)->name);
1434 did_base_obj = TRUE;
1439 ((FuncArg *)m->args->data)->name,
1442 if(initializers > 0) {
1444 for(li = ((Class *)class)->nodes;
1448 Variable *v = (Variable *)n;
1449 if(n->type == VARIABLE_NODE &&
1450 v->scope == CLASS_SCOPE)
1451 print_initializer(m, v);
1455 out_printf(out, "\n\tparent_class = ");
1457 out_printf(out, "(%sClass *)", ptypebase);
1458 out_printf(out, "gtk_type_class (%s_get_type ());\n",
1464 set_def_handlers(c, ((FuncArg *)m->args->data)->name);
1466 /* if there are no handlers for these things, we
1467 * need to set them up here */
1468 if(need_destroy && !destroy_handler)
1469 out_printf(out, "\tgtk_object_class->destroy "
1471 if(need_finalize && !finalize_handler)
1473 "#ifdef G_OBJECT_CLASS\n"
1474 "\tg_object_class->finalize = ___finalize;\n"
1475 "#else /* !G_OBJECT_CLASS */\n"
1476 "\tgtk_object_class->finalize = ___finalize;\n"
1477 "#endif /* G_OBJECT_CLASS */\n");
1479 if(get_arguments > 0 || set_arguments > 0)
1486 out_printf(out, " {\n");
1487 out_addline_infile(out, m->ccode_line);
1488 out_printf(out, "%s\n", m->cbuf);
1489 out_addline_outfile(out);
1490 out_printf(out, " }\n");
1492 out_printf(out, "\treturn;\n");
1495 ((FuncArg *)m->args->data)->name);
1496 if(add_unused_class) {
1498 "\tgtk_object_class = NULL;\n"
1499 "#ifdef G_OBJECT_CLASS\n"
1500 "\tg_object_class = NULL;\n"
1501 "#endif /* G_OBJECT_CLASS */\n");
1503 out_printf(out, "}\n"
1504 "#undef __GOB_FUNCTION__\n");
1509 add_getset_arg(Class *c, gboolean is_set)
1512 out_printf(out, "\nstatic void\n"
1513 "___object_%s_arg (GtkObject *object,\n"
1516 "#define __GOB_FUNCTION__ \"%s::%s_arg\"\n"
1519 "\tself = %s (object);\n\n"
1520 "\tswitch (arg_id) {\n",
1521 is_set ? "set" : "get",
1522 c->otype, is_set ? "set" : "get",
1523 typebase, macrobase);
1525 for(li=c->nodes;li;li=g_list_next(li)) {
1531 if(n->type != ARGUMENT_NODE)
1536 line_no = a->set_line;
1539 line_no = a->get_line;
1543 s = g_strdup(a->name);
1545 out_printf(out, "\tcase ARG_%s:\n", s);
1546 if(is_set && a->atype) {
1547 char *cast = get_type(a->atype, TRUE);
1548 if(no_gnu || for_cpp) {
1549 out_printf(out, "#define ARG "
1550 "((%s)GTK_VALUE_%s(*arg))\n",
1553 out_printf(out, "#if defined(__GNUC__) && !defined(__STRICT_ANSI__)\n");
1554 if(strcmp(a->gtktype, "OBJECT")==0) {
1555 out_printf(out, "#define ARG "
1557 "GTK_VALUE_POINTER(*arg); "
1561 out_printf(out, "#define ARG "
1563 "GTK_VALUE_%s(*arg); "
1567 out_printf(out, "#else /* __GNUC__ && !__STRICT_ANSI__ */\n");
1568 out_printf(out, "#define ARG "
1569 "((%s)GTK_VALUE_%s(*arg))\n",
1571 out_printf(out, "#endif /* __GNUC__ && !__STRICT_ANSI__ */\n\n");
1573 out_printf(out, "\t\t{\n");
1575 } else if(!is_set && strcmp(a->gtktype, "OBJECT")==0) {
1577 "#define ARG (GTK_VALUE_POINTER(*arg))\n"
1581 "#define ARG (GTK_VALUE_%s(*arg))\n"
1587 out_addline_infile(out, line_no);
1588 out_printf(out, "%s\n", cbuf);
1590 out_addline_outfile(out);
1591 out_printf(out, "\t\t}\n\t\tbreak;\n"
1594 out_printf(out, "\tdefault:\n\t\tbreak;\n\t}\n"
1595 "\treturn;\n\tself = NULL;\n\targ = NULL;\n}\n"
1596 "#undef __GOB_FUNCTION__\n");
1600 print_checks(Method *m, FuncArg *fa)
1604 gboolean checked_null = FALSE;
1605 is_void = (strcmp(m->mtype->name, "void")==0 &&
1606 m->mtype->pointer == NULL);
1608 for(li = fa->checks; li; li = g_list_next(li)) {
1609 Check *ch = li->data;
1611 /* point to the method prot in .gob for failed checks */
1613 out_addline_infile(out, m->line_no);
1615 out_printf(out, "\tg_return_if_fail (");
1617 out_printf(out, "\tg_return_val_if_fail (");
1618 switch(ch->chtype) {
1620 out_printf(out, "%s != NULL", fa->name);
1621 checked_null = TRUE;
1624 s = make_pre_macro(fa->atype->name, "IS");
1626 out_printf(out, "%s (%s)", s, fa->name);
1628 /* if not check null, null may be valid */
1629 out_printf(out, "!(%s) || %s (%s)", fa->name,
1634 out_printf(out, "%s < %s", fa->name, ch->number);
1637 out_printf(out, "%s > %s", fa->name, ch->number);
1640 out_printf(out, "%s <= %s", fa->name, ch->number);
1643 out_printf(out, "%s >= %s", fa->name, ch->number);
1646 out_printf(out, "%s == %s", fa->name, ch->number);
1649 out_printf(out, "%s != %s", fa->name, ch->number);
1653 out_printf(out, ");\n");
1655 out_printf(out, ", (");
1656 print_type(out, m->mtype, TRUE);
1657 out_printf(out, ")%s);\n",
1658 m->onerror?m->onerror:"0");
1664 print_preconditions(Method *m)
1668 for(li=m->args;li;li=g_list_next(li)) {
1669 FuncArg *fa = li->data;
1671 print_checks(m, fa);
1674 out_addline_outfile(out);
1678 print_method_body(Method *m, int pre)
1680 out_printf(out, "{\n"
1681 "#define __GOB_FUNCTION__ \"%s::%s\"\n",
1682 ((Class *)class)->otype,
1683 get_real_id(m->id));
1685 print_preconditions(m);
1687 /* Note: the trailing }'s are on one line, this is so
1688 that we get the no return warning correctly and point to
1689 the correct line in the .gob file, yes this is slightly
1690 ugly in the .c file, but that is not supposed to be
1691 human readable anyway. */
1693 out_printf(out, "{\n");
1695 out_addline_infile(out, m->ccode_line);
1696 out_printf(out, "\t%s}", m->cbuf);
1699 /* Note, there is no \n between the last } and this } so that
1700 * errors/warnings reported on the end of the body get pointed to the
1701 * right line in the .gob source */
1702 out_printf(out, "}\n");
1705 out_addline_outfile(out);
1706 out_printf(out, "#undef __GOB_FUNCTION__\n");
1710 put_signal_args(Method *m)
1714 for(ali = m->gtktypes->next, li=m->args->next;
1716 li=li->next, ali=ali->next) {
1717 FuncArg *fa = li->data;
1718 const char *cast = get_cast(ali->data, FALSE);
1719 /* we should have already proved before that
1720 the we know all the types */
1723 out_printf(out, ",\n\t\t(%s)%s", cast,
1729 get_arg_names_for_macro(Method *m)
1733 GString *gs = g_string_new(NULL);
1735 for(li=m->args;li;li=g_list_next(li)) {
1736 FuncArg *arg = li->data;
1737 g_string_sprintfa(gs, "%s___%s", p, arg->name);
1741 g_string_free(gs, FALSE);
1746 put_method(Method *m)
1748 char *s, *args, *doc;
1750 is_void = (strcmp(m->mtype->name, "void")==0 &&
1751 m->mtype->pointer == NULL);
1752 out_printf(out, "\n");
1753 if(m->method != OVERRIDE_METHOD) {
1754 doc = get_gtk_doc(m->id);
1756 out_printf(out, "%s", doc);
1761 case REGULAR_METHOD:
1763 out_addline_infile(out, m->line_no);
1764 if(m->scope == PRIVATE_SCOPE)
1765 print_method(out, "static ", "\n", "", " ", "", "\n",
1766 m, FALSE, FALSE, TRUE);
1767 else /* PUBLIC, PROTECTED */
1768 print_method(out, "", "\n", "", " ", "", "\n",
1769 m, FALSE, FALSE, TRUE);
1770 print_method_body(m, TRUE);
1771 /* the outfile line was added above */
1773 case SIGNAL_FIRST_METHOD:
1774 case SIGNAL_LAST_METHOD:
1776 out_addline_infile(out, m->line_no);
1777 if(m->scope == PRIVATE_SCOPE)
1778 print_method(out, "static ", "\n", "", " ", "", "\n",
1779 m, FALSE, FALSE, TRUE);
1780 else /* PUBLIC, PROTECTED */
1781 print_method(out, "", "\n", "", " ", "", "\n",
1782 m, FALSE, FALSE, TRUE);
1783 out_addline_outfile(out);
1784 out_printf(out, "{\n");
1785 s = g_strdup(get_real_id(m->id));
1787 if(strcmp(m->mtype->name, "void") == 0 &&
1788 m->mtype->pointer == NULL) {
1789 print_preconditions(m);
1790 if(((FuncArg *)m->args->data)->name)
1791 out_printf(out, "\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1792 "\t\tobject_signals[%s_SIGNAL]",
1793 ((FuncArg *)m->args->data)->name, s);
1795 out_printf(out, ");\n}\n");
1797 out_printf(out, "\t");
1798 print_type(out, m->mtype, TRUE);
1799 out_printf(out, "return_val = (");
1800 print_type(out, m->mtype, TRUE);
1802 out_printf(out, ")(%s);\n", m->defreturn);
1804 out_printf(out, ")(%s);\n", m->onerror);
1806 out_printf(out, ")(0);\n");
1807 print_preconditions(m);
1808 out_printf(out, "\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1809 "\t\tobject_signals[%s_SIGNAL]",
1810 ((FuncArg *)m->args->data)->name, s);
1812 out_printf(out, ",\n\t\t&return_val);\n"
1813 "\treturn return_val;\n}\n");
1819 out_addline_infile(out, m->line_no);
1820 print_method(out, "static ", "\n___real_", "", " ", "", "\n",
1821 m, FALSE, FALSE, TRUE);
1822 print_method_body(m, FALSE);
1823 /* the outfile line was added above */
1825 case VIRTUAL_METHOD:
1827 out_addline_infile(out, m->line_no);
1828 if(m->scope==PRIVATE_SCOPE)
1829 print_method(out, "static ", "\n", "", " ", "", "\n",
1830 m, FALSE, FALSE, TRUE);
1831 else /* PUBLIC, PROTECTED */
1832 print_method(out, "", "\n", "", " ", "", "\n",
1833 m, FALSE, FALSE, TRUE);
1834 out_addline_outfile(out);
1835 out_printf(out, "{\n"
1836 "\t%sClass *klass;\n", typebase);
1837 print_preconditions(m);
1838 out_printf(out, "\tklass = %s_GET_CLASS(%s);\n\n"
1839 "\tif(klass->%s)\n",
1840 macrobase, ((FuncArg *)m->args->data)->name,
1841 get_real_id(m->id));
1842 if(strcmp(m->mtype->name, "void") == 0 &&
1843 m->mtype->pointer == NULL) {
1845 out_printf(out, "\t\t(*klass->%s)(%s",
1847 ((FuncArg *)m->args->data)->name);
1848 for(li=m->args->next;li;li=g_list_next(li)) {
1849 FuncArg *fa = li->data;
1850 out_printf(out, ",%s", fa->name);
1852 out_printf(out, ");\n}\n");
1855 out_printf(out, "\t\treturn (*klass->%s)(%s",
1857 ((FuncArg *)m->args->data)->name);
1858 for(li=m->args->next;li;li=g_list_next(li)) {
1859 FuncArg *fa = li->data;
1860 out_printf(out, ",%s", fa->name);
1862 out_printf(out, ");\n"
1865 print_type(out, m->mtype, TRUE);
1867 out_printf(out, ")(%s);\n}\n", m->defreturn);
1869 out_printf(out, ")(%s);\n}\n", m->onerror);
1871 out_printf(out, ")(0);\n}\n");
1877 out_addline_infile(out, m->line_no);
1878 print_method(out, "static ", "\n___real_", "", " ", "", "\n",
1879 m, FALSE, FALSE, TRUE);
1880 print_method_body(m, FALSE);
1881 /* the outfile line was added above */
1883 case OVERRIDE_METHOD:
1887 out_addline_infile(out, m->line_no);
1888 s = g_strdup_printf("\n___%x_", (guint)m->unique_id);
1889 print_method(out, "static ", s, "", " ", "", "\n",
1890 m, FALSE, FALSE, FALSE);
1892 out_addline_outfile(out);
1893 s = replace_sep(m->otype, '_');
1895 args = get_arg_names_for_macro(m);
1897 out_printf(out, "#define PARENT_HANDLER(%s) \\\n"
1898 "\t{ if(%s_CLASS(parent_class)->%s) \\\n"
1899 "\t\t(* %s_CLASS(parent_class)->%s)(%s); }\n",
1900 args, s, get_real_id(m->id), s, get_real_id(m->id), args);
1902 out_printf(out, "#define PARENT_HANDLER(%s) \\\n"
1903 "\t((%s_CLASS(parent_class)->%s)? \\\n"
1904 "\t\t(* %s_CLASS(parent_class)->%s)(%s): \\\n"
1906 args, s, get_real_id(m->id), s, get_real_id(m->id), args);
1907 out_printf(out, "(");
1908 print_type(out, m->mtype, TRUE);
1909 out_printf(out, ")%s))\n",
1910 m->onerror?m->onerror:"0");
1914 print_method_body(m, TRUE);
1915 /* the outfile line was added above */
1916 out_printf(out, "#undef PARENT_HANDLER\n");
1926 char *outfile, *outfileh, *outfileph;
1929 outfile = g_strconcat(filebase, ".c", NULL);
1931 outfile = g_strconcat(filebase, ".cc", NULL);
1932 if(no_touch_headers)
1933 outfileh = g_strconcat("#gob#", filebase, ".h#gob#", NULL);
1935 outfileh = g_strconcat(filebase, ".h", NULL);
1937 if((privates > 0 || protecteds > 0 ||
1938 private_header == PRIVATE_HEADER_ALWAYS) &&
1939 private_header != PRIVATE_HEADER_NEVER)
1940 outfileph = g_strconcat(filebase, "-private.h", NULL);
1946 devnull = fopen("/dev/null", "w");
1948 g_error("Cannot open null device");
1954 out = fopen(outfile, "w");
1956 g_error("Cannot open outfile: %s", outfile);
1958 outh = fopen(outfileh, "w");
1960 g_error("Cannot open outfile: %s", outfileh);
1962 outph = fopen(outfileph, "w");
1964 g_error("Cannot open outfile: %s", outfileh);
1970 put_argument_nongnu_wrappers(Class *c)
1974 if(get_arguments < 0 && set_arguments < 0)
1977 for(li=c->nodes;li;li=g_list_next(li)) {
1979 Argument *a = (Argument *)n;
1983 if(n->type != ARGUMENT_NODE)
1986 aname = g_strdup(a->name);
1990 cast = get_type(a->atype, TRUE);
1992 cast = g_strdup(get_cast(a->gtktype, TRUE));
1996 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1997 "\"%s\",(%s)(arg)\n",
1998 macrobase, aname, a->name, cast);
2000 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
2001 "\"%s\",(%s*)(arg)\n",
2002 macrobase, aname, a->name, cast);
2005 out_printf(outh, "#define %s_ARG_%s(arg) \t"
2007 macrobase, aname, a->name);
2009 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
2011 macrobase, aname, a->name);
2019 put_argument_gnu_wrappers(Class *c)
2023 if(get_arguments < 0 && set_arguments < 0)
2026 for(li=c->nodes;li;li=g_list_next(li)) {
2028 Argument *a = (Argument *)n;
2031 if(n->type != ARGUMENT_NODE)
2033 s = g_strdup(a->name);
2036 cast = get_type(a->atype, TRUE);
2038 cast = g_strdup(get_cast(a->gtktype, TRUE));
2041 out_printf(outh, "#define %s_ARG_%s(arg) \t"
2042 "\"%s\",({%sz = (arg); z;})\n",
2043 macrobase, s, a->name, cast);
2045 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
2046 "\"%s\",({%s*z = (arg); z;})\n",
2047 macrobase, s, a->name, cast);
2050 out_printf(outh, "#define %s_ARG_%s(arg) \t"
2052 macrobase, s, a->name);
2054 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
2056 macrobase, s, a->name);
2064 print_ccode_block(CCode *cc)
2067 switch(cc->cctype) {
2069 /* HT code is printed exactly like normal header
2070 code but is printed before */
2073 out_printf(fp, "\n");
2076 /* AT code is printed exactly like normal 'all'
2077 code but is printed before */
2080 out_printf(outph, "\n");
2081 out_printf(outph, "%s\n", cc->cbuf);
2082 out_addline_infile(outph, cc->line_no);
2083 out_addline_outfile(outph);
2085 out_printf(outh, "\n");
2086 out_printf(outh, "%s\n", cc->cbuf);
2088 out_printf(fp, "\n");
2089 out_addline_infile(fp, cc->line_no);
2094 out_printf(fp, "\n");
2095 out_addline_infile(fp, cc->line_no);
2102 out_printf(fp, "\n");
2103 out_addline_infile(fp, cc->line_no);
2106 out_printf(fp, "%s\n", cc->cbuf);
2107 if(cc->cctype == C_CCODE ||
2108 cc->cctype == A_CCODE ||
2109 cc->cctype == AT_CCODE ||
2110 cc->cctype == PH_CCODE)
2111 out_addline_outfile(fp);
2115 print_class_block(Class *c)
2119 gboolean printed_private = FALSE;
2122 out_printf(out, "/* utility types we may need */\n");
2123 if(special_array[SPECIAL_2POINTER])
2124 out_printf(out, "typedef struct { "
2125 "gpointer a; gpointer b; "
2126 "} ___twopointertype;\n");
2127 if(special_array[SPECIAL_3POINTER])
2128 out_printf(out, "typedef struct { "
2129 "gpointer a; gpointer b; "
2131 "} ___threepointertype;\n");
2132 if(special_array[SPECIAL_INT_POINTER])
2133 out_printf(out, "typedef struct { "
2134 "gint a; gpointer b; "
2135 "} ___intpointertype;\n");
2136 out_printf(out, "\n");
2139 out_printf(outh, "\n/*\n"
2140 " * Type checking and casting macros\n"
2142 out_printf(outh, "#define %s\t"
2143 "(%s_get_type())\n",
2144 macrotype, funcbase);
2145 out_printf(outh, "#define %s(obj)\t"
2146 "GTK_CHECK_CAST((obj), %s_get_type(), %s)\n",
2147 macrobase, funcbase, typebase);
2148 out_printf(outh, "#define %s_CONST(obj)\t"
2149 "GTK_CHECK_CAST((obj), %s_get_type(), %s const)\n",
2150 macrobase, funcbase, typebase);
2151 out_printf(outh, "#define %s_CLASS(klass)\t"
2152 "GTK_CHECK_CLASS_CAST((klass), %s_get_type(), %sClass)\n",
2153 macrobase, funcbase, typebase);
2154 out_printf(outh, "#define %s(obj)\t"
2155 "GTK_CHECK_TYPE((obj), %s_get_type ())\n\n",
2157 out_printf(outh, "#ifdef GTK_CHECK_GET_CLASS\n"
2158 "#define %s_GET_CLASS(obj)\t"
2159 "GTK_CHECK_GET_CLASS((obj), %s_get_type(), %sClass)\n",
2160 macrobase, funcbase, typebase);
2161 out_printf(outh, "#else /* !GTK_CHECK_GET_CLASS */\n"
2162 "#define %s_GET_CLASS(obj)\t"
2163 "((%sClass *)GTK_OBJECT(obj)->klass)\n"
2164 "#endif /* GTK_CHECK_GET_CLASS */\n",
2165 macrobase, typebase);
2167 if( ! no_self_alias) {
2168 out_printf(out, "/* self casting macros */\n");
2169 out_printf(out, "#define SELF(x) %s(x)\n", macrobase);
2170 out_printf(out, "#define SELF_CONST(x) %s_CONST(x)\n", macrobase);
2171 out_printf(out, "#define IS_SELF(x) %s(x)\n", macrois);
2172 out_printf(out, "#define SELF_CLASS(x) %s_CLASS(x)\n\n",
2174 out_printf(out, "#define SELF_GET_CLASS(x) %s_GET_CLASS(x)\n\n",
2177 out_printf(out, "/* self typedefs */\n");
2178 out_printf(out, "typedef %s Self;\n", typebase);
2179 out_printf(out, "typedef %sClass SelfClass;\n\n", typebase);
2182 out_printf(out, "/* GTK_CLASS_TYPE for 1.2<->1.3/2.0 GTK+ compatibility */\n");
2184 "#ifndef GTK_CLASS_TYPE\n"
2185 "#define GTK_CLASS_TYPE(x) (GTK_OBJECT_CLASS(x)->type)\n"
2186 "#endif /* GTK_CLASS_TYPE */\n\n");
2188 if(privates > 0 || always_private_struct) {
2189 out_printf(outh, "\n/* Private structure type */\n");
2190 out_printf(outh, "typedef struct _%sPrivate %sPrivate;\n",
2191 typebase, typebase);
2193 out_printf(outh, "/* There are no privates, this "
2194 "structure is thus never defined */\n");
2197 out_printf(outh, "\n/*\n"
2198 " * Main object structure\n"
2200 s = replace_sep(c->otype, '_');
2202 out_printf(outh, "#ifndef __TYPEDEF_%s__\n"
2203 "#define __TYPEDEF_%s__\n", s, s);
2205 out_printf(outh, "typedef struct _%s %s;\n"
2206 "#endif\n", typebase, typebase);
2207 out_printf(outh, "struct _%s {\n\t%s __parent__;\n",
2208 typebase, ptypebase);
2209 for(l=c->nodes; l; l=g_list_next(l)) {
2210 static gboolean printed_public = FALSE;
2212 Variable *v = (Variable *)n;
2213 if(n->type == VARIABLE_NODE &&
2214 v->scope == PUBLIC_SCOPE) {
2215 if( ! printed_public) {
2216 out_printf(outh, "\t/*< public >*/\n");
2217 printed_public = TRUE;
2219 put_variable((Variable *)n, outh);
2222 /* put protecteds always AFTER publics */
2223 for(l=c->nodes; l; l=g_list_next(l)) {
2225 Variable *v = (Variable *)n;
2226 if(n->type == VARIABLE_NODE &&
2227 v->scope == PROTECTED_SCOPE) {
2228 if( ! printed_private) {
2229 out_printf(outh, "\t/*< private >*/\n");
2230 printed_private = TRUE;
2232 put_variable((Variable *)n, outh);
2235 if(privates > 0 || always_private_struct) {
2236 if( ! printed_private)
2237 out_printf(outh, "\t/*< private >*/\n");
2238 out_printf(outh, "\t%sPrivate *_priv;\n", typebase);
2240 out_printf(outh, "};\n");
2245 /* if we are to stick this into the private
2246 header, if not stick it directly into the
2253 out_printf(outfp, "struct _%sPrivate {\n",
2255 for(l=c->nodes; l; l=l->next) {
2257 Variable *v = (Variable *)n;
2258 if(n->type == VARIABLE_NODE &&
2259 v->scope == PRIVATE_SCOPE) {
2260 out_addline_infile(outfp, v->line_no);
2261 put_variable(v, outfp);
2264 out_addline_outfile(outfp);
2265 out_printf(outfp, "};\n");
2268 out_printf(outh, "\n/*\n"
2269 " * Class definition\n"
2271 out_printf(outh, "typedef struct _%sClass %sClass;\n",
2272 typebase, typebase);
2274 "struct _%sClass {\n\t%sClass __parent__;\n",
2275 typebase, ptypebase);
2276 for(l = c->nodes; l != NULL; l = l->next) {
2278 if(n->type == METHOD_NODE)
2279 put_vs_method((Method *)n);
2281 /* put class scope variables */
2282 for(l = c->nodes; l != NULL; l = l->next) {
2284 Variable *v = (Variable *)n;
2285 if(n->type == VARIABLE_NODE &&
2286 v->scope == CLASS_SCOPE)
2287 put_variable((Variable *)n, outh);
2289 out_printf(outh, "};\n\n");
2291 out_printf(out, "/* here are local prototypes */\n");
2292 if(set_arguments > 0) {
2293 out_printf(out, "static void ___object_set_arg "
2294 "(GtkObject *object, GtkArg *arg, "
2295 "guint arg_id);\n");
2297 if(get_arguments > 0) {
2298 out_printf(out, "static void ___object_get_arg "
2299 "(GtkObject *object, GtkArg *arg, "
2300 "guint arg_id);\n");
2303 out_printf(outh, "\n/*\n"
2304 " * Public methods\n"
2307 out_printf(outh, "GtkType\t%s_get_type\t(void)", funcbase);
2309 out_printf(outh, " G_GNUC_CONST;\n");
2311 out_printf(outh, ";\n");
2314 for(l = c->nodes; l != NULL; l = l->next) {
2316 if(n->type == METHOD_NODE) {
2317 put_pub_method((Method *)n);
2318 put_prot_method((Method *)n);
2319 put_priv_method_prot((Method *)n);
2323 /* this idea is less and less apealing to me */
2325 out_printf (outh, "\n/*\n"
2326 " * Signal connection wrapper macros\n"
2329 out_printf(outh, "#if defined(__GNUC__) && !defined(__STRICT_ANSI__)\n");
2330 put_signal_macros (c, TRUE);
2331 out_printf(outh, "#else /* __GNUC__ && !__STRICT_ANSI__ */\n");
2332 put_signal_macros (c, FALSE);
2333 out_printf(outh, "#endif /* __GNUC__ && !__STRICT_ANSI__ */\n\n");
2335 put_signal_macros (c, FALSE);
2339 /* argument wrapping macros */
2340 if(get_arguments > 0 || set_arguments > 0) {
2341 out_printf(outh, "\n/*\n"
2342 " * Argument wrapping macros\n"
2345 out_printf(outh, "#if defined(__GNUC__) && !defined(__STRICT_ANSI__)\n");
2346 put_argument_gnu_wrappers(c);
2347 out_printf(outh, "#else /* __GNUC__ && !__STRICT_ANSI__ */\n");
2348 put_argument_nongnu_wrappers(c);
2349 out_printf(outh, "#endif /* __GNUC__ && !__STRICT_ANSI__ */\n\n");
2351 put_argument_nongnu_wrappers(c);
2356 for(l = c->nodes; l != NULL; l = l->next) {
2358 if(n->type == METHOD_NODE)
2359 add_signal_prots((Method *)n);
2365 if ( ! overrode_get_type)
2368 if(any_method_to_alias(c)) {
2370 out_printf(out, "/* Short form macros */\n");
2371 out_printf(out, "#if defined(__GNUC__) && !defined(__STRICT_ANSI__)\n");
2372 make_method_gnu_aliases(c);
2373 out_printf(out, "#endif /* __GNUC__ && !__STRICT_ANSI__ */\n");
2375 make_method_nongnu_aliases(c);
2378 out_printf(out, "/* a macro for creating a new object of our type */\n");
2380 "#define GET_NEW ((%s *)gtk_type_new(%s_get_type()))\n\n",
2381 typebase, funcbase);
2391 if(set_arguments > 0) {
2392 add_getset_arg(c, TRUE);
2395 if(get_arguments > 0) {
2396 add_getset_arg(c, FALSE);
2399 for(l = c->nodes; l != NULL; l = l->next) {
2401 if(n->type == METHOD_NODE)
2402 put_method((Method *)n);
2405 add_bad_hack_to_avoid_unused_warnings(c);
2409 print_version_macros(void)
2411 int major=0, minor=0, pl=0;
2412 sscanf(VERSION, "%d.%d.%d", &major, &minor, &pl);
2414 out_printf(out, "#define GOB_VERSION_MAJOR %d\n", major);
2415 out_printf(out, "#define GOB_VERSION_MINOR %d\n", minor);
2416 out_printf(out, "#define GOB_VERSION_PATCHLEVEL %d\n\n", pl);
2420 print_file_comments(void)
2424 out_printf(outh, "/* Generated by GOB (v%s)"
2425 " (do not edit directly) */\n\n", VERSION);
2427 out_printf(outph, "/* Generated by GOB (v%s)"
2428 " (do not edit directly) */\n\n", VERSION);
2429 out_printf(out, "/* Generated by GOB (v%s) on %s"
2430 " (do not edit directly) */\n\n",
2431 VERSION, ctime(&curtime));
2433 out_printf(out, "/* End world hunger, donate to the World Food Programme, http://www.wfp.org */\n\n");
2437 print_includes(void)
2439 gboolean found_header;
2442 /* We may need string.h for memset */
2443 if(destructors > 0 &&
2444 ! g_list_find_custom(include_files, "string.h", (GCompareFunc)strcmp)) {
2445 out_printf(out, "#include <string.h> /* memset() */\n\n");
2448 p = g_strconcat(filebase, ".h", NULL);
2449 found_header = TRUE;
2450 if( ! g_list_find_custom(include_files, p, (GCompareFunc)strcmp)) {
2451 out_printf(out, "#include \"%s.h\"\n\n", filebase);
2452 found_header = FALSE;
2456 /* if we are creating a private header see if it was included */
2458 p = g_strconcat(filebase, "-private.h", NULL);
2459 if( ! g_list_find_custom(include_files, p,
2460 (GCompareFunc)strcmp)) {
2461 out_printf(out, "#include \"%s-private.h\"\n\n",
2464 error_printf(GOB_WARN, 0,
2465 "Implicit private header include "
2467 "\tsource file, while public "
2468 "header is at a custom location, "
2470 "\texplicitly include "
2471 "the private header below the "
2479 print_header_prefixes(void)
2483 p = replace_sep(((Class *)class)->otype, '_');
2485 out_printf(outh, "#ifndef __%s_H__\n#define __%s_H__\n\n", p, p);
2487 out_printf(outph, "#ifndef __%s_PRIVATE_H__\n"
2488 "#define __%s_PRIVATE_H__\n\n"
2489 "#include \"%s.h\"\n\n", p, p, filebase);
2492 if( ! no_extern_c) {
2493 out_printf(outh, "#ifdef __cplusplus\n"
2495 "#endif /* __cplusplus */\n\n");
2497 out_printf(outph, "#ifdef __cplusplus\n"
2499 "#endif /* __cplusplus */\n\n");
2504 print_header_postfixes(void)
2507 out_printf(outh, "\n#ifdef __cplusplus\n"
2509 "#endif /* __cplusplus */\n");
2510 out_printf(outh, "\n#endif\n");
2513 out_printf(outph, "\n#ifdef __cplusplus\n"
2515 "#endif /* __cplusplus */\n");
2516 out_printf(outph, "\n#endif\n");
2525 /* print the AT_CCODE blocks */
2526 for(li = nodes; li != NULL; li = li->next) {
2527 Node *node = li->data;
2528 if(node->type == CCODE_NODE) {
2529 CCode *cc = (CCode *)node;
2530 if(cc->cctype == AT_CCODE)
2531 print_ccode_block((CCode *)node);
2537 print_header_top(void)
2541 /* mandatory include */
2542 out_printf(outh, "#include <gtk/gtk.h>\n\n");
2544 /* print the HT_CCODE blocks */
2545 for(li=nodes;li;li=g_list_next(li)) {
2546 Node *node = li->data;
2547 if(node->type == CCODE_NODE) {
2548 CCode *cc = (CCode *)node;
2549 if(cc->cctype == HT_CCODE)
2550 print_ccode_block((CCode *)node);
2556 generate_outfiles(void)
2560 print_file_comments();
2566 print_header_prefixes();
2568 print_version_macros();
2572 for(li=nodes;li;li=g_list_next(li)) {
2573 Node *node = li->data;
2574 if(node->type == CCODE_NODE) {
2575 CCode *cc = (CCode *)node;
2576 if(cc->cctype != HT_CCODE &&
2577 cc->cctype != AT_CCODE)
2578 print_ccode_block((CCode *)node);
2579 } else if(node->type == CLASS_NODE) {
2580 print_class_block((Class *)node);
2582 g_assert_not_reached();
2585 print_header_postfixes();
2591 fprintf(stderr, "Gob version %s\n\n", VERSION);
2592 fprintf(stderr, "gob [options] file.gob\n\n");
2593 fprintf(stderr, "Options:\n"
2594 "\t--help,-h,-? Display this help\n"
2595 "\t--version Display version\n"
2596 "\t--exit-on-warn,-w Exit with an error on warnings\n"
2597 "\t--no-exit-on-warn Don't exit on warnings [default]\n"
2598 "\t--for-cpp Create C++ files\n"
2599 "\t--no-extern-c Never print extern \"C\" into the "
2601 "\t--no-gnu Never use GNU extentions\n"
2602 "\t--no-touch-headers Don't touch headers unless they "
2604 "\t--always-private-header Always create a private header "
2606 "\t even if it would be empty "
2608 "\t--ondemand-private-header Create private header only when "
2610 "\t--no-private-header Don't create a private header, "
2612 "\t structure and protected "
2613 "prototypes inside c file\n"
2614 "\t--always-private-struct Always create a private pointer "
2616 "\t the object structure\n"
2617 "\t--no-write,-n Don't write output files, just "
2619 "\t--no-lines Don't print '#line' to output\n"
2620 "\t--no-self-alias Don't create self type and macro "
2622 "\t--no-kill-underscores Don't remove the leading underscore "
2624 "\t short id names\n");
2628 parse_options(int argc, char *argv[])
2631 int got_file = FALSE;
2632 int no_opts = FALSE;
2636 for(i = 1 ; i < argc; i++) {
2638 argv[i][0] != '-') {
2641 fprintf(stderr, "Specify only one file!\n");
2647 } else if(strcmp(argv[i], "--help")==0) {
2650 } else if(strcmp(argv[i], "--version")==0) {
2651 fprintf(stderr, "Gob version %s\n", VERSION);
2653 } else if(strcmp(argv[i], "--exit-on-warn")==0) {
2654 exit_on_warn = TRUE;
2655 } else if(strcmp(argv[i], "--no-exit-on-warn")==0) {
2656 exit_on_warn = FALSE;
2657 } else if(strcmp(argv[i], "--for-cpp")==0) {
2659 } else if(strcmp(argv[i], "--no-touch-headers")==0) {
2660 no_touch_headers = TRUE;
2661 } else if(strcmp(argv[i], "--ondemand-private-header")==0) {
2662 private_header = PRIVATE_HEADER_ONDEMAND;
2663 } else if(strcmp(argv[i], "--always-private-header")==0) {
2664 private_header = PRIVATE_HEADER_ALWAYS;
2665 } else if(strcmp(argv[i], "--no-private-header")==0) {
2666 private_header = PRIVATE_HEADER_NEVER;
2667 } else if(strcmp(argv[i], "--no-gnu")==0) {
2669 } else if(strcmp(argv[i], "--no-extern-c")==0) {
2671 } else if(strcmp(argv[i], "--no-write")==0) {
2673 } else if(strcmp(argv[i], "--no-lines")==0) {
2675 } else if(strcmp(argv[i], "--no-self-alias")==0) {
2676 no_self_alias = TRUE;
2677 } else if(strcmp(argv[i], "--no-kill-underscores")==0) {
2678 no_kill_underscores = TRUE;
2679 } else if(strcmp(argv[i], "--always-private-struct")==0) {
2680 always_private_struct = TRUE;
2681 } else if(strcmp(argv[i], "--")==0) {
2682 /*further arguments are files*/
2684 } else if(strncmp(argv[i], "--", 2)==0) {
2685 /*unknown long option*/
2686 fprintf(stderr, "Unknown option '%s'!\n", argv[i]);
2690 /*by now we know we have a string starting with
2691 - which is a short option string*/
2693 for(p = argv[i] + 1; *p; p++) {
2707 "Unknown option '%c'!\n", *p);
2716 /* this is a somewhat ugly hack, but it appears to work */
2718 compare_and_move_header(void)
2720 char *hfnew = g_strconcat("#gob#", filebase, ".h#gob#", NULL);
2721 char *hf = g_strconcat(filebase, ".h", NULL);
2723 if(stat(hf, &s) == 0) {
2725 s = g_strdup_printf("cmp '%s' '%s' > /dev/null", hf, hfnew);
2726 if(system(s) == 0) {
2727 if(unlink(hfnew) != 0)
2728 error_printf(GOB_ERROR, 0,
2729 "Can't remove new header file");
2737 error_printf(GOB_ERROR, 0,
2738 "Can't remove old header file");
2740 if(rename(hfnew, hf) != 0)
2741 error_printf(GOB_ERROR, 0,
2742 "Can't rename new header file");
2748 main(int argc, char *argv[])
2750 parse_options(argc, argv);
2753 yyin = fopen(filename, "r");
2755 fprintf(stderr, "Error: can't open file '%s'\n",
2762 /* This is where parsing is done */
2765 g_error("Parsing errors, quitting");
2768 error_print(GOB_ERROR, 0, " no class defined");
2771 exit_on_error = FALSE;
2773 signals = count_signals((Class *)class);
2774 set_arguments = count_set_arguments((Class *)class);
2775 get_arguments = count_get_arguments((Class *)class);
2776 overrides = count_overrides((Class *)class);
2777 privates = count_privates((Class *)class);
2778 protecteds = count_protecteds((Class *)class);
2779 destructors = count_destructors((Class *)class);
2780 initializers = count_initializers((Class *)class);
2781 overrode_get_type = find_get_type((Class *)class);
2784 make_inits((Class *)class);
2785 if(destructors > 0) {
2786 need_destroy = TRUE;
2787 find_destroy((Class *)class);
2790 need_finalize = TRUE;
2791 find_finalize((Class *)class);
2793 check_bad_symbols((Class *)class);
2794 check_duplicate_symbols((Class *)class);
2795 check_duplicate_overrides((Class *)class);
2796 check_duplicate_signals_args((Class *)class);
2797 check_public_new((Class *)class);
2798 check_vararg((Class *)class);
2799 check_firstarg((Class *)class);
2800 check_nonvoidempty((Class *)class);
2801 check_signal_args((Class *)class);
2802 check_argument_types((Class *)class);
2803 check_func_arg_checks((Class *)class);
2805 exit_on_error = TRUE;
2810 any_special = setup_special_array((Class *)class, special_array);
2814 generate_outfiles();
2825 if(no_touch_headers &&
2827 compare_and_move_header();