2 * Copyright (C) 1999,2000 the Free Software Foundation.
3 * Copyright (C) 2000 Eazel, Inc.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
32 #include "treefuncs.h"
40 char *filename = NULL;
49 extern GList *include_files;
51 extern GHashTable *gtk_doc_hash;
54 static char *funcbase;
55 static char *pfuncbase;
56 static char *macrobase;
58 static char *macrotype;
59 static char *typebase;
60 static char *ptypebase;
62 static int signals = 0; /* number of signals */
63 static int arguments = 0; /* number of named arguments */
64 static int overrides = 0; /* number of override methods */
65 static int privates = 0; /* number of private data members */
66 static int protecteds = 0; /* number of protected methods */
67 static int destructors = 0; /* number of variable destructors */
68 static int initializers = 0; /* number of variable initializers */
70 static gboolean made_aliases = FALSE; /* if we made any shorthand aliases
71 and need the REALLY UGLY HACK to
74 /* the special variable types we need to define */
75 static gboolean special_array[SPECIAL_LAST] = {0};
76 static gboolean any_special = FALSE;
78 static gboolean need_destroy = FALSE;
79 static Method * destroy_handler = NULL;
81 static gboolean need_finalize = FALSE;
82 static Method * finalize_handler = NULL;
89 gboolean no_touch_headers = FALSE;
90 gboolean for_cpp = FALSE;
91 gboolean no_gnu = FALSE;
92 gboolean exit_on_warn = FALSE;
93 gboolean exit_on_error = TRUE;
94 gboolean got_error = FALSE;
95 gint private_header = PRIVATE_HEADER_ALWAYS;
96 gboolean no_extern_c = FALSE;
97 gboolean no_write = FALSE;
98 gboolean no_lines = FALSE;
99 gboolean no_self_alias = FALSE;
100 gboolean no_kill_underscores = FALSE;
102 int method_unique_id = 1;
107 filebase = replace_sep(((Class *)class)->otype, '-');
110 funcbase = replace_sep(((Class *)class)->otype, '_');
113 pfuncbase = replace_sep(((Class *)class)->ptype, '_');
114 g_strdown(pfuncbase);
116 macrobase = replace_sep(((Class *)class)->otype, '_');
119 macrois = make_pre_macro(((Class *)class)->otype, "IS");
120 macrotype = make_pre_macro(((Class *)class)->otype, "TYPE");
122 typebase = remove_sep(((Class *)class)->otype);
124 ptypebase = remove_sep(((Class *)class)->ptype);
128 get_type(Type *t, gboolean postfix_to_stars)
135 s = remove_sep(t->name);
136 gs = g_string_new(s);
140 if(postfix_to_stars) {
142 /*XXX: this is ugly perhaps we can do this whole postfix thing
143 in a nicer way, we just count the number of '[' s and from
144 that we deduce the number of dimensions, so that we can print
146 for(p=t->postfix; p && *p; p++)
147 if(*p == '[') extra++;
149 g_string_append_c(gs, ' ');
151 for(i=0; i<(t->stars+extra); i++)
152 g_string_append_c(gs, '*');
155 g_string_free(gs, FALSE);
160 get_gtk_doc(char *id)
167 val = g_hash_table_lookup(gtk_doc_hash, id);
169 return g_strdup_printf("/**\n * %s_%s:\n%s **/\n",
170 funcbase, get_real_id(id), val);
171 s = g_strconcat(funcbase, "_", get_real_id(id), NULL);
172 val = g_hash_table_lookup(gtk_doc_hash, s);
175 return g_strdup_printf("/**\n * %s_%s:\n%s **/\n",
176 funcbase, get_real_id(id), val);
181 print_type(FILE *fp, Type *t, gboolean postfix_to_stars)
185 s = get_type(t, postfix_to_stars);
186 out_printf(fp, "%s", s);
192 print_method(FILE *fp, char *typeprefix, char *nameprefix,
194 char *namepostfix, char *postfix, Method *m,
195 gboolean one_arg_per_line,
196 gboolean no_funcbase,
197 gboolean kill_underscore)
202 out_printf(fp, "%s", typeprefix);
203 print_type(fp, m->mtype, TRUE);
206 id = get_real_id(m->id);
211 out_printf(fp, "%s%s%s%s(",
212 nameprefix, subnameprefix, id, namepostfix);
214 out_printf(fp, "%s%s_%s%s%s(",
215 nameprefix, funcbase, subnameprefix, id,
219 for(li=m->args; li; li=g_list_next(li)) {
220 FuncArg *arg = li->data;
221 print_type(fp, arg->atype, FALSE);
223 out_printf(fp, "%s%s,%s", arg->name,
225 arg->atype->postfix:"",
226 one_arg_per_line?"\n\t\t\t\t\t":" ");
228 out_printf(fp, "%s%s", arg->name,
230 arg->atype->postfix:"");
233 out_printf(fp, ",%s...",
234 one_arg_per_line?"\n\t\t\t\t\t":" ");
236 out_printf(fp, "void");
238 out_printf(fp, ")%s", postfix);
242 any_method_to_alias(Class *c)
246 for(li=c->nodes;li;li=g_list_next(li)) {
247 Node *node = li->data;
248 if(node->type == METHOD_NODE) {
249 Method *m = (Method *)node;
251 if(m->method == INIT_METHOD ||
252 m->method == CLASS_INIT_METHOD ||
253 m->method == OVERRIDE_METHOD)
264 make_method_gnu_aliases(Class *c)
268 for(li=c->nodes;li;li=g_list_next(li)) {
269 Node *node = li->data;
270 if(node->type == METHOD_NODE) {
271 Method *m = (Method *)node;
273 if(m->method == INIT_METHOD ||
274 m->method == CLASS_INIT_METHOD ||
275 m->method == OVERRIDE_METHOD)
278 /* in C++ mode don't alias new */
279 if(for_cpp && strcmp(m->id, "new")==0)
282 out_printf(out, "static const typeof(&%s_%s) %s "
283 "__attribute__ ((__unused__)) "
284 "= %s_%s;\n", funcbase, get_real_id(m->id),
285 m->id, funcbase, get_real_id(m->id));
286 out_printf(out, "#define %s(args...) "
287 "%s_%s(##args)\n", m->id,
288 funcbase, get_real_id(m->id));
294 make_method_nongnu_aliases(Class *c)
298 for(li=c->nodes; li; li=g_list_next(li)) {
299 Node *node = li->data;
300 if(node->type == METHOD_NODE) {
301 Method *m = (Method *)node;
303 if(m->method == INIT_METHOD ||
304 m->method == CLASS_INIT_METHOD ||
305 m->method == OVERRIDE_METHOD)
308 /* in C++ mode don't alias new */
309 if(for_cpp && strcmp(m->id, "new")==0)
312 print_method(out, "static ", "(* ", "", ") ", "",
313 m, FALSE, TRUE, FALSE);
314 out_printf(out, " = %s_%s;\n", funcbase,
323 add_bad_hack_to_avoid_unused_warnings(Class *c)
327 /* if we haven't had any methods, just return */
332 out_printf(out, "\n\n#ifndef __GNUC__\n");
334 "/*REALLY BAD HACK\n"
335 " This is to avoid unused warnings if you don't call\n"
336 " some method. I need to find a better way to do\n"
337 " this, not needed in GCC since we use some gcc\n"
338 " extentions to make saner, faster code */\n"
340 "___%s_really_bad_hack_to_avoid_warnings(void)\n"
342 for(li=c->nodes;li;li=g_list_next(li)) {
343 Node *node = li->data;
344 if(node->type == METHOD_NODE) {
345 Method *m = (Method *)node;
347 if(m->method == INIT_METHOD ||
348 m->method == CLASS_INIT_METHOD ||
349 m->method == OVERRIDE_METHOD)
352 /* in C++ mode we don't alias new */
353 if(for_cpp && strcmp(m->id, "new")==0)
356 out_printf(out, "\t((void (*)(void))%s)();\n", m->id);
359 out_printf(out, "\t___%s_really_bad_hack_to_avoid_warnings();\n",
362 out_printf(out, "}\n#endif /* __GNUC__ */\n\n");
364 out_printf(out, "}\n\n");
368 put_variable(Variable *v, FILE *fp)
370 out_printf(fp, "\t");
371 print_type(fp, v->vtype, FALSE);
372 out_printf(fp, "%s%s;", v->id,
374 v->vtype->postfix:"");
375 if(v->scope == PROTECTED_SCOPE)
376 out_printf(fp, " /* protected */");
377 out_printf(fp, "\n");
381 put_vs_method(Method *m)
383 if(m->method != SIGNAL_LAST_METHOD &&
384 m->method != SIGNAL_FIRST_METHOD &&
385 m->method != VIRTUAL_METHOD)
388 /* if a signal mark it as such */
389 if(m->method != VIRTUAL_METHOD)
390 print_method(outh, "\t/*signal*/", "(* ", "", ") ", ";\n",
391 m, FALSE, TRUE, TRUE);
393 print_method(outh, "\t", "(* ", "", ") ", ";\n",
394 m, FALSE, TRUE, TRUE);
398 put_pub_method(Method *m)
400 if(m->scope != PUBLIC_SCOPE)
403 print_method(outh, "", "\t", "", "\t", ";\n", m, TRUE, FALSE, TRUE);
406 /* I'm starting not to like this idea */
409 put_signal_connect(Method *m)
411 if(m->method != SIGNAL_LAST_METHOD &&
412 m->method != SIGNAL_FIRST_METHOD)
415 out_printf(outh, "guint \t%s_%s__connect_full\t(%s *object,\n"
416 "\t\t\t\t\tconst char *name,\n"
417 "\t\t\t\t\tGtkSignalFunc func,\n"
418 "\t\t\t\t\tGtkCallbackMarshal marshal,\n"
419 "\t\t\t\t\tgpointer data,\n"
420 "\t\t\t\t\tGtkDestroyNotify destroy_func,\n"
421 "\t\t\t\t\tgboolean object_signal,\n"
422 "\t\t\t\t\tgboolean after);\n",
423 funcbase, m->id, typebase);
425 out_printf(outh, "#define %s_%s__connect(object,name,func,data) "
426 "%s_%s__connect_full((object),(name),(func),NULL,"
427 "(data),NULL,FALSE,FALSE)\n",
428 funcbase, m->id, funcbase, m->id);
429 out_printf(outh, "#define %s_%s__connect_after(object,name,func,data) "
430 "%s__connect_%s_full((object),(name),(func),NULL,"
431 "(data),NULL,FALSE,TRUE)\n",
432 funcbase, m->id, funcbase, m->id);
434 out_printf(outh, "guint \t%s_%s__connect_while_alive\t(%s *object,\n"
435 "\t\t\t\t\tconst char *name,\n"
436 "\t\t\t\t\tGtkSignalFunc func,\n"
437 "\t\t\t\t\tgpointer data,\n"
438 "\t\t\t\t\tGtkObject *alive_object);\n\n",
439 funcbase, m->id, typebase);
445 put_prot_method(Method *m)
447 if(m->scope != PROTECTED_SCOPE)
451 print_method(outph, "", "\t", "", "\t", ";\n",
452 m, FALSE, FALSE, TRUE);
454 print_method(out, "", "\t", "", "\t", ";\n",
455 m, FALSE, FALSE, TRUE);
459 put_priv_method_prot(Method *m)
461 if(m->method == SIGNAL_LAST_METHOD ||
462 m->method == SIGNAL_FIRST_METHOD ||
463 m->method == VIRTUAL_METHOD) {
466 "static ", "___real_", "", " ", ";\n",
467 m, FALSE, FALSE, TRUE);
469 /* no else, here, it might still have a private prototype, it's not
472 if((m->method == OVERRIDE_METHOD &&
475 char *s = g_strdup_printf("___%x_", (guint)m->unique_id);
476 print_method(out, "static ", s, "", " ",
477 no_gnu?";\n":" G_GNUC_UNUSED;\n",
478 m, FALSE, FALSE, FALSE);
480 } else if(m->scope == PRIVATE_SCOPE ||
481 m->method == INIT_METHOD ||
482 m->method == CLASS_INIT_METHOD)
483 print_method(out, "static ", "", "", " ",
484 no_gnu?";\n":" G_GNUC_UNUSED;\n",
485 m, FALSE, FALSE, TRUE);
489 make_func_arg(char *typename, int is_class, char *name)
496 tn = g_strconcat(typename, ":Class", NULL);
498 tn = g_strdup(typename);
500 type = new_type(1, tn, NULL);
501 node = new_funcarg((Type *)type, name, NULL);
502 return g_list_prepend(NULL, node);
506 make_inits(Class *cl)
508 int got_class_init = FALSE;
509 int got_init = FALSE;
512 for(li=cl->nodes;li;li=g_list_next(li)) {
514 if(n->type == METHOD_NODE) {
515 Method *m = (Method *)n;
516 if(m->method == INIT_METHOD) {
518 print_error(FALSE, "init defined more then once", m->line_no);
520 } else if(m->method == CLASS_INIT_METHOD) {
522 print_error(FALSE, "class_init defined more then once", m->line_no);
523 got_class_init = TRUE;
527 if(!got_class_init) {
528 node = new_method(NO_SCOPE, CLASS_INIT_METHOD,
529 (Type *)new_type(0, g_strdup("void"), NULL),
530 NULL, NULL, NULL, g_strdup("class_init"),
531 make_func_arg(cl->otype, TRUE, g_strdup("c")),
532 NULL, NULL, NULL, 0, 0, FALSE,
534 cl->nodes = g_list_prepend(cl->nodes, node);
537 node = new_method(NO_SCOPE, INIT_METHOD,
538 (Type *)new_type(0, g_strdup("void"), NULL),
539 NULL, NULL, NULL, g_strdup("init"),
540 make_func_arg(cl->otype, FALSE, g_strdup("o")),
541 NULL, NULL, NULL, 0, 0, FALSE,
543 cl->nodes = g_list_prepend(cl->nodes, node);
548 find_destroy(Class *cl)
553 destroy_handler = NULL;
554 for(li=cl->nodes;li;li=g_list_next(li)) {
556 if(n->type == METHOD_NODE) {
557 Method *m = (Method *)n;
558 if(m->method == OVERRIDE_METHOD &&
559 strcmp(m->id, "destroy")==0) {
560 if(strcmp(m->otype, "Gtk:Object") != 0) {
562 "destroy method override "
563 "of class other then "
567 if(g_list_length(m->args) != 1) {
569 "destroy method override "
570 "with more then one "
582 find_finalize(Class *cl)
587 finalize_handler = NULL;
588 for(li=cl->nodes;li;li=g_list_next(li)) {
590 if(n->type == METHOD_NODE) {
591 Method *m = (Method *)n;
592 if(m->method == OVERRIDE_METHOD &&
593 strcmp(m->id, "finalize")==0) {
594 if(strcmp(m->otype, "Gtk:Object") != 0) {
596 "finalize method override "
597 "of class other then "
601 if(g_list_length(m->args) != 1) {
603 "finalize method override "
604 "with more then one "
608 finalize_handler = m;
616 /* hash of method -> name of signal prototype */
617 static GHashTable *marsh = NULL;
619 /* list of methods with different signal prototypes,
620 we check this list if we can use a signal prototype of a
621 previous signal method, there are only uniques here */
622 static GList *eq_signal_methods = NULL;
624 /* compare a list of strings */
626 is_list_equal(GList *a, GList *b)
628 for(;a && b; a=a->next, b=b->next) {
629 if(strcmp(a->data, b->data)!=0) {
633 /* the the lists were different length */
640 find_same_type_signal(Method *m)
643 for(li=eq_signal_methods;li;li=li->next) {
644 Method *mm = li->data;
645 if(is_list_equal(mm->gtktypes, m->gtktypes))
652 print_signal_marsal_args(Method *m)
654 if(strcmp(m->gtktypes->next->data, "NONE")!=0) {
657 for(i=0, li=m->gtktypes->next;li;
658 i++, li=g_list_next(li)) {
660 out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
661 (char *)li->data, i);
663 out_printf(out, ",\n\t\t(%s)"
664 "GTK_VALUE_%s(args[%d])",
665 get_cast(li->data, FALSE),
666 (char *)li->data, i);
670 out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
675 add_signal_prots(Method *m)
682 if(m->method != SIGNAL_LAST_METHOD &&
683 m->method != SIGNAL_FIRST_METHOD)
687 marsh = g_hash_table_new(NULL, NULL);
689 if(strcmp(m->gtktypes->data, "NONE")==0 &&
690 strcmp(m->gtktypes->next->data, "NONE")==0)
693 /* if we already did a signal prototype just use that */
694 mm = find_same_type_signal(m);
696 s = g_hash_table_lookup(marsh, mm);
697 g_hash_table_insert(marsh, m, s);
701 s = g_strdup_printf("Sig%d", sig++);
703 g_hash_table_insert(marsh, m, s);
704 eq_signal_methods = g_list_prepend(eq_signal_methods, m);
706 /* we know that we'll know all the gtktypes (so get_cast can't fail) */
707 out_printf(out, "\ntypedef %s (*___%s) (%s *, ",
708 get_cast(m->gtktypes->data, FALSE), s, typebase);
710 if(strcmp(m->gtktypes->next->data, "NONE")!=0) {
711 for(li=m->gtktypes->next; li; li=g_list_next(li))
712 out_printf(out, "%s, ", get_cast(li->data, FALSE));
714 out_printf(out, "gpointer);\n");
716 out_printf(out, "\nstatic void\n"
717 "___marshal_%s (GtkObject * object,\n"
718 "\tGtkSignalFunc func,\n"
719 "\tgpointer func_data,\n"
723 if(strcmp(m->gtktypes->data, "NONE")==0) {
724 out_printf(out, "\t___%s rfunc;\n\n"
725 "\trfunc = (___%s)func;\n\n"
726 "\t(*rfunc)((%s *)object", s, s, typebase);
728 const char *retcast = get_cast(m->gtktypes->data, FALSE);
732 "\trfunc = (___%s)func;\n\n"
733 "\tretval = GTK_RETLOC_%s(args[%d]);\n\n"
734 "\t*retval = (*rfunc)((%s *)object",
735 s, retcast, s, (char *)m->gtktypes->data,
736 g_list_length(m->gtktypes)-1, typebase);
738 print_signal_marsal_args(m);
746 out_printf(out, "\n");
748 out_printf(out, "enum {\n");
749 for(li=c->nodes;li;li=g_list_next(li)) {
751 if(n->type == METHOD_NODE) {
752 Method *m = (Method *)n;
753 if(m->method == SIGNAL_LAST_METHOD ||
754 m->method == SIGNAL_FIRST_METHOD) {
755 char *s = g_strdup(get_real_id(m->id));
757 out_printf(out, "\t%s_SIGNAL,\n", s);
762 out_printf(out, "\tLAST_SIGNAL\n};\n\n");
765 out_printf(out, "enum {\n\tARG_0");
766 for(li=c->nodes;li;li=g_list_next(li)) {
768 if(n->type == ARGUMENT_NODE) {
769 Argument *a = (Argument *)n;
770 char *s = g_strdup(a->name);
772 out_printf(out, ",\n\tARG_%s", s);
776 out_printf(out, "\n};\n\n");
781 "static guint object_signals[LAST_SIGNAL] = {0};\n\n");
783 out_printf(out, "/* pointer to the class of our parent */\n");
784 out_printf(out, "static %sClass *parent_class = NULL;\n\n", ptypebase);
790 out_printf(out, "guint\n"
791 "%s_get_type (void)\n"
793 "\tstatic guint type = 0;\n\n"
795 "\t\tstatic const GtkTypeInfo info = {\n"
797 "\t\t\tsizeof (%s),\n"
798 "\t\t\tsizeof (%sClass),\n"
799 "\t\t\t(GtkClassInitFunc) %s_class_init,\n"
800 "\t\t\t(GtkObjectInitFunc) %s_init,\n"
801 "\t\t\t/* reserved_1 */ NULL,\n"
802 "\t\t\t/* reserved_2 */ NULL,\n"
803 "\t\t\t(GtkClassInitFunc) NULL,\n"
805 "\t\ttype = gtk_type_unique (%s_get_type(), &info);\n"
809 funcbase, typebase, typebase, typebase,
810 funcbase, funcbase, pfuncbase);
814 add_overrides(Class *c, char *oname, gboolean did_gtk_obj)
820 done = g_hash_table_new(g_str_hash, g_str_equal);
822 s = g_strdup("GtkObject"); /* This was already done */
823 g_hash_table_insert(done, s, s);
825 for(li=c->nodes; li; li=g_list_next(li)) {
828 Method *m = (Method *)n;
829 if(n->type != METHOD_NODE ||
830 m->method != OVERRIDE_METHOD)
833 s = remove_sep(m->otype);
835 if(g_hash_table_lookup(done, s)) {
839 g_hash_table_insert(done, s, s);
841 f = replace_sep(m->otype, '_');
844 out_printf(out, "\t%sClass *%s_class = (%sClass *)%s;\n",
849 g_hash_table_foreach(done, (GHFunc)g_free, NULL);
850 g_hash_table_destroy(done);
854 make_run_signal_flags(Method *m, gboolean last)
868 gs = g_string_new(NULL);
871 g_string_assign(gs, "GTK_RUN_LAST");
873 g_string_assign(gs, "GTK_RUN_FIRST");
875 if(m->scope == PUBLIC_SCOPE)
876 g_string_append(gs, " | GTK_RUN_ACTION");
878 for(li = m->flags; li; li = li->next) {
879 char *flag = li->data;
881 for(i=0;flags[i];i++) {
882 if(strcmp(flags[i], flag)==0)
885 /* if we haven't found it in our list */
888 s = g_strdup_printf("Unknown flag '%s' used, "
889 "perhaps it was misspelled",
891 print_error(TRUE, s, m->line_no);
894 g_string_sprintfa(gs, " | GTK_RUN_%s", flag);
899 g_string_free(gs, FALSE);
906 add_signals(Class *c)
910 out_printf(out, "\n");
911 for(li=c->nodes;li;li=g_list_next(li)) {
913 char *mar, *sig, *flags;
914 gboolean is_none, last = FALSE;
915 Method *m = (Method *)n;
917 if(n->type != METHOD_NODE ||
918 (m->method != SIGNAL_FIRST_METHOD &&
919 m->method != SIGNAL_LAST_METHOD))
922 if(m->method == SIGNAL_FIRST_METHOD)
927 if(g_hash_table_lookup(marsh, m))
928 mar = g_strconcat("___marshal_",
929 (char *)g_hash_table_lookup(marsh, m),
932 mar = g_strdup("gtk_signal_default_marshaller");
934 is_none = (strcmp(m->gtktypes->next->data, "NONE")==0);
936 sig = g_strdup(get_real_id(m->id));
938 flags = make_run_signal_flags(m, last);
939 out_printf(out, "\tobject_signals[%s_SIGNAL] =\n"
940 "\t\tgtk_signal_new (\"%s\",\n"
941 "\t\t\t(GtkSignalRunType)(%s),\n"
942 "\t\t\tgtk_object_class->type,\n"
943 "\t\t\tGTK_SIGNAL_OFFSET (%sClass, %s),\n"
945 "\t\t\tGTK_TYPE_%s, %d",
946 sig, get_real_id(m->id),
948 typebase, get_real_id(m->id), mar,
949 (char *)m->gtktypes->data,
950 is_none?0:g_list_length(m->gtktypes->next));
957 for(l=m->gtktypes->next;l;l=g_list_next(l))
958 out_printf(out, ",\n\t\t\tGTK_TYPE_%s",
962 out_printf(out, ");\n");
964 out_printf(out, "\tgtk_object_class_add_signals (gtk_object_class,\n"
965 "\t\tobject_signals, LAST_SIGNAL);\n\n");
969 set_def_handlers(Class *c, char *oname)
972 gboolean set_line = FALSE;
974 out_printf(out, "\n");
975 for(li = c->nodes; li; li = g_list_next(li)) {
977 Method *m = (Method *)n;
980 if(n->type != METHOD_NODE ||
981 (m->method != SIGNAL_FIRST_METHOD &&
982 m->method != SIGNAL_LAST_METHOD &&
983 m->method != VIRTUAL_METHOD &&
984 m->method != OVERRIDE_METHOD))
987 if(m->line_no > 0 && m->cbuf) {
988 out_addline_infile(out, m->line_no);
990 } else if(set_line) {
991 out_addline_outfile(out);
996 if(m->method == OVERRIDE_METHOD) {
998 s = replace_sep(m->otype, '_');
1003 strcmp(m->id, "destroy") == 0)
1004 out_printf(out, "\tgtk_object_class->destroy "
1006 else if(need_finalize &&
1008 strcmp(m->id, "finalize") == 0)
1009 out_printf(out, "\tgtk_object_class->finalize "
1010 "= ___finalize;\n");
1013 "\t%s_class->%s = ___%x_%s_%s;\n",
1014 s, m->id, (guint)m->unique_id,
1017 out_printf(out, "\t%s_class->%s = NULL;\n",
1021 out_printf(out, "\t%s->%s = ___real_%s_%s;\n",
1022 oname, get_real_id(m->id),
1023 funcbase, get_real_id(m->id));
1025 out_printf(out, "\t%s->%s = NULL;\n",
1026 oname, get_real_id(m->id));
1030 out_addline_outfile(out);
1034 make_arguments(Class *c)
1037 char *argflags[] = {
1045 out_printf(out, "\n");
1046 for(li=c->nodes;li;li=g_list_next(li)) {
1052 if(n->type != ARGUMENT_NODE)
1057 if(a->get && a->set)
1058 flags = g_string_new("GTK_ARG_READWRITE");
1060 flags = g_string_new("GTK_ARG_READABLE");
1062 flags = g_string_new("GTK_ARG_WRITABLE");
1064 for(l=a->flags;l;l=g_list_next(l)) {
1065 char *flag = l->data;
1067 if(strcmp(flag, "READWRITE")==0 ||
1068 strcmp(flag, "READABLE")==0 ||
1069 strcmp(flag, "WRITABLE")==0) {
1070 print_error(TRUE, "READWRITE, READABLE and "
1071 "WRITABLE argument flags are "
1072 "set automatically", a->line_no);
1075 for(i=0;argflags[i];i++) {
1076 if(strcmp(argflags[i], flag)==0)
1079 /* if we haven't found it in our list */
1082 s = g_strdup_printf("Unknown flag '%s' used, "
1083 "perhaps it was misspelled",
1085 print_error(TRUE, s, a->line_no);
1088 g_string_sprintfa(flags, " | GTK_ARG_%s", flag);
1091 s = g_strdup(a->name);
1093 out_printf(out, "\tgtk_object_add_arg_type(\"%s::%s\",\n"
1094 "\t\tGTK_TYPE_%s,\n"
1097 typebase, a->name, a->gtktype, flags->str, s);
1099 g_string_free(flags, TRUE);
1103 "\n\tgtk_object_class->set_arg = ___object_set_arg;\n"
1104 "\tgtk_object_class->get_arg = ___object_get_arg;\n");
1108 print_initializer(Method *m, Variable *v)
1112 if(v->initializer == NULL)
1115 if(v->scope == PRIVATE_SCOPE)
1116 root = g_strconcat(((FuncArg *)m->args->data)->name,
1119 root = g_strdup(((FuncArg *)m->args->data)->name);
1121 if(v->initializer_line > 0)
1122 out_addline_infile(out, v->initializer_line);
1124 out_printf(out, "\t%s->%s = %s;\n",
1125 root, v->id, v->initializer);
1127 if(v->initializer_line > 0)
1128 out_addline_outfile(out);
1134 print_destructor(Variable *v)
1138 if(v->destructor == NULL)
1141 if(v->scope == PRIVATE_SCOPE)
1142 root = "self->_priv";
1146 if(v->destructor_simple) {
1147 if(v->destructor_line > 0)
1148 out_addline_infile(out, v->destructor_line);
1150 out_printf(out, "\tif(%s->%s) { "
1151 "((*(void (*)(void *))%s)) (%s->%s); "
1152 "%s->%s = NULL; }\n",
1153 root, v->id, v->destructor, root, v->id,
1156 if(v->destructor_line > 0)
1157 out_addline_outfile(out);
1159 out_printf(out, "#define VAR (%s->%s)\n", root, v->id);
1160 out_printf(out, "\t{\n");
1161 if(v->destructor_line > 0)
1162 out_addline_infile(out, v->destructor_line);
1164 out_printf(out, "\t%s}\n", v->destructor);
1166 if(v->destructor_line > 0)
1167 out_addline_outfile(out);
1168 out_printf(out, "\tmemset(&VAR, 0, sizeof(VAR));\n");
1169 out_printf(out, "#undef VAR\n");
1174 add_destroy(Class *c)
1176 out_printf(out, "\nstatic void\n"
1177 "___destroy(GtkObject *obj_self)\n"
1180 if(destructors > 0) {
1181 out_printf(out, "\t%s *self G_GNUC_UNUSED = %s (obj_self);\n",
1182 typebase, macrobase);
1185 if(destroy_handler) {
1186 /* so we get possible bad argument warning */
1187 if(destroy_handler->line_no > 0)
1188 out_addline_infile(out, destroy_handler->line_no);
1189 out_printf(out, "\t___%x_%s_destroy(obj_self);\n",
1190 (guint)destroy_handler->unique_id, funcbase);
1191 if(destroy_handler->line_no > 0)
1192 out_addline_outfile(out);
1195 if(destructors > 0) {
1197 for(li = ((Class *)class)->nodes;
1201 Variable *v = (Variable *)n;
1202 if(n->type == VARIABLE_NODE &&
1203 v->scope != CLASS_SCOPE)
1204 print_destructor(v);
1208 out_printf(out, "}\n\n");
1212 add_finalize(Class *c)
1214 out_printf(out, "\nstatic void\n"
1215 "___finalize(GtkObject *obj_self)\n"
1219 out_printf(out, "\t%s *self = %s (obj_self);\n",
1220 typebase, macrobase);
1223 if(finalize_handler) {
1224 /* so we get possible bad argument warning */
1225 if(finalize_handler->line_no > 0)
1226 out_addline_infile(out, finalize_handler->line_no);
1227 out_printf(out, "\t___%x_%s_finalize(obj_self);\n",
1228 (guint)finalize_handler->unique_id, funcbase);
1229 if(finalize_handler->line_no > 0)
1230 out_addline_outfile(out);
1234 out_printf(out, "\tg_free (self->_priv);\n"
1235 "\tself->_priv = NULL;\n");
1238 out_printf(out, "}\n\n");
1245 for(li=c->nodes;li;li=g_list_next(li)) {
1248 if(n->type != METHOD_NODE)
1251 if(m->method == INIT_METHOD) {
1253 out_addline_infile(out, m->line_no);
1254 print_method(out, "static ", "\n", "", " ", "\n",
1255 m, FALSE, FALSE, TRUE);
1257 out_addline_outfile(out);
1258 out_printf(out, "{\n");
1260 out_printf(out, "\t%s->_priv = "
1261 "g_new0 (%sPrivate, 1);\n",
1262 ((FuncArg *)m->args->data)->name,
1265 if(initializers > 0) {
1267 for(li = ((Class *)class)->nodes;
1271 Variable *v = (Variable *)n;
1272 if(n->type != VARIABLE_NODE ||
1273 v->scope == CLASS_SCOPE)
1275 print_initializer(m, v);
1278 } else if(m->method == CLASS_INIT_METHOD) {
1279 gboolean did_gtk_obj = FALSE;
1282 out_addline_infile(out, m->line_no);
1283 print_method(out, "static ", "\n", "", " ", "\n",
1284 m, FALSE, FALSE, TRUE);
1286 out_addline_outfile(out);
1287 out_printf(out, "{\n");
1293 "\tGtkObjectClass *"
1294 "gtk_object_class = "
1295 "(GtkObjectClass*) %s;\n",
1296 ((FuncArg *)m->args->data)->name);
1302 ((FuncArg *)m->args->data)->name,
1305 if(initializers > 0) {
1307 for(li = ((Class *)class)->nodes;
1311 Variable *v = (Variable *)n;
1312 if(n->type != VARIABLE_NODE ||
1313 v->scope != CLASS_SCOPE)
1315 print_initializer(m, v);
1319 out_printf(out, "\n\tparent_class = ");
1321 out_printf(out, "(%sClass *)", ptypebase);
1322 out_printf(out, "gtk_type_class (%s_get_type ());\n",
1328 set_def_handlers(c, ((FuncArg *)m->args->data)->name);
1330 /* if there are no handlers for these things, we
1331 * need to set them up here */
1332 if(need_destroy && !destroy_handler)
1333 out_printf(out, "\tgtk_object_class->destroy "
1335 if(need_finalize && !finalize_handler)
1336 out_printf(out, "\tgtk_object_class->finalize "
1337 "= ___finalize;\n");
1346 out_printf(out, " {\n");
1347 out_addline_infile(out, m->ccode_line);
1348 out_printf(out, "%s\n", m->cbuf);
1349 out_addline_outfile(out);
1350 out_printf(out, " }\n");
1352 out_printf(out, "return;\n");
1354 out_printf(out, "}\n");
1359 add_getset_arg(Class *c, gboolean is_set)
1362 out_printf(out, "\nstatic void\n"
1363 "___object_%s_arg (GtkObject *object,\n"
1368 "\tself = %s (object);\n\n"
1369 "\tswitch (arg_id) {\n",
1370 is_set?"set":"get", typebase, macrobase);
1372 for(li=c->nodes;li;li=g_list_next(li)) {
1378 if(n->type != ARGUMENT_NODE)
1383 line_no = a->set_line;
1386 line_no = a->get_line;
1390 s = g_strdup(a->name);
1392 out_printf(out, "\tcase ARG_%s:\n", s);
1393 if(is_set && a->atype) {
1394 char *cast = get_type(a->atype, TRUE);
1395 if(no_gnu || for_cpp) {
1396 out_printf(out, "#define ARG "
1397 "((%s)GTK_VALUE_%s(*arg))\n",
1400 out_printf(out, "#ifdef __GNUC__\n");
1401 if(strcmp(a->gtktype, "OBJECT")==0) {
1402 out_printf(out, "#define ARG "
1404 "GTK_VALUE_POINTER(*arg); "
1408 out_printf(out, "#define ARG "
1410 "GTK_VALUE_%s(*arg); "
1414 out_printf(out, "#else /* __GNUC__ */\n");
1415 out_printf(out, "#define ARG "
1416 "((%s)GTK_VALUE_%s(*arg))\n",
1418 out_printf(out, "#endif /* __GNUC__ */\n\n");
1420 out_printf(out, "\t\t{\n");
1422 } else if(!is_set && strcmp(a->gtktype, "OBJECT")==0) {
1424 "#define ARG (GTK_VALUE_POINTER(*arg))\n"
1428 "#define ARG (GTK_VALUE_%s(*arg))\n"
1434 out_addline_infile(out, line_no);
1435 out_printf(out, "%s\n", cbuf);
1437 out_addline_outfile(out);
1438 out_printf(out, "\t\t}\n\t\tbreak;\n"
1441 out_printf(out, "\tdefault:\n\t\tbreak;\n\t}\n}\n");
1445 print_checks(Method *m, FuncArg *fa)
1449 gboolean checked_null = FALSE;
1450 is_void = (strcmp(m->mtype->name, "void")==0 &&
1451 m->mtype->stars == 0);
1453 for(li=fa->checks;li;li=g_list_next(li)) {
1454 Check *ch = li->data;
1456 /* point to the method prot in .gob for failed checks */
1458 out_addline_infile(out, m->line_no);
1460 out_printf(out, "\tg_return_if_fail (");
1462 out_printf(out, "\tg_return_val_if_fail (");
1463 switch(ch->chtype) {
1465 out_printf(out, "%s != NULL", fa->name);
1466 checked_null = TRUE;
1469 s = make_pre_macro(fa->atype->name, "IS");
1471 out_printf(out, "%s (%s)", s, fa->name);
1473 /* if not check null, null may be valid */
1474 out_printf(out, "!(%s) || %s (%s)", fa->name,
1479 out_printf(out, "%s < %s", fa->name, ch->number);
1482 out_printf(out, "%s > %s", fa->name, ch->number);
1485 out_printf(out, "%s <= %s", fa->name, ch->number);
1488 out_printf(out, "%s >= %s", fa->name, ch->number);
1491 out_printf(out, "%s == %s", fa->name, ch->number);
1494 out_printf(out, "%s != %s", fa->name, ch->number);
1498 out_printf(out, ");\n");
1500 out_printf(out, ", (");
1501 print_type(out, m->mtype, TRUE);
1502 out_printf(out, ")%s);\n",
1503 m->onerror?m->onerror:"0");
1509 print_preconditions(Method *m)
1513 for(li=m->args;li;li=g_list_next(li)) {
1514 FuncArg *fa = li->data;
1516 print_checks(m, fa);
1519 out_addline_outfile(out);
1523 print_method_body(Method *m, int pre)
1525 out_printf(out, "{\n");
1527 print_preconditions(m);
1529 /* Note: the trailing }'s are on one line, this is so
1530 that we get the no return warning correctly and point to
1531 the correct line in the .gob file, yes this is slightly
1532 ugly in the .c file, but that is not supposed to be
1533 human readable anyway. */
1535 out_printf(out, "{\n");
1537 out_addline_infile(out, m->ccode_line);
1538 out_printf(out, "\t%s}", m->cbuf);
1541 out_printf(out, "}\n");
1544 out_addline_outfile(out);
1548 put_signal_args(Method *m)
1552 for(ali = m->gtktypes->next, li=m->args->next;
1554 li=li->next, ali=ali->next) {
1555 FuncArg *fa = li->data;
1556 const char *cast = get_cast(ali->data, FALSE);
1557 /* we should have already proved before that
1558 the we know all the types */
1561 out_printf(out, ",\n\t\t(%s)%s", cast,
1567 get_arg_names_for_macro(Method *m)
1571 GString *gs = g_string_new(NULL);
1573 for(li=m->args;li;li=g_list_next(li)) {
1574 FuncArg *arg = li->data;
1575 g_string_sprintfa(gs, "%s___%s", p, arg->name);
1579 g_string_free(gs, FALSE);
1584 put_method(Method *m)
1586 char *s, *args, *doc;
1588 is_void = (strcmp(m->mtype->name, "void")==0 &&
1589 m->mtype->stars == 0);
1590 out_printf(out, "\n");
1591 if(m->method != OVERRIDE_METHOD) {
1592 doc = get_gtk_doc(m->id);
1594 out_printf(out, "%s", doc);
1599 case REGULAR_METHOD:
1601 out_addline_infile(out, m->line_no);
1602 if(m->scope == PRIVATE_SCOPE)
1603 print_method(out, "static ", "\n", "", " ", "\n",
1604 m, FALSE, FALSE, TRUE);
1605 else /* PUBLIC, PROTECTED */
1606 print_method(out, "", "\n", "", " ", "\n",
1607 m, FALSE, FALSE, TRUE);
1608 print_method_body(m, TRUE);
1609 /* the outfile line was added above */
1611 case SIGNAL_FIRST_METHOD:
1612 case SIGNAL_LAST_METHOD:
1614 out_addline_infile(out, m->line_no);
1615 if(m->scope == PRIVATE_SCOPE)
1616 print_method(out, "static ", "\n", "", " ", "\n",
1617 m, FALSE, FALSE, TRUE);
1618 else /* PUBLIC, PROTECTED */
1619 print_method(out, "", "\n", "", " ", "\n",
1620 m, FALSE, FALSE, TRUE);
1621 out_addline_outfile(out);
1622 out_printf(out, "{\n");
1623 s = g_strdup(get_real_id(m->id));
1625 if(strcmp(m->mtype->name, "void")==0 &&
1626 m->mtype->stars==0) {
1627 print_preconditions(m);
1628 if(((FuncArg *)m->args->data)->name)
1629 out_printf(out, "\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1630 "\t\tobject_signals[%s_SIGNAL]",
1631 ((FuncArg *)m->args->data)->name, s);
1633 out_printf(out, ");\n}\n");
1635 out_printf(out, "\t");
1636 print_type(out, m->mtype, TRUE);
1637 out_printf(out, "return_val = (");
1638 print_type(out, m->mtype, TRUE);
1640 out_printf(out, ")(%s);\n", m->defreturn);
1642 out_printf(out, ")(%s);\n", m->onerror);
1644 out_printf(out, ")(0);\n");
1645 print_preconditions(m);
1646 out_printf(out, "\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1647 "\t\tobject_signals[%s_SIGNAL]",
1648 ((FuncArg *)m->args->data)->name, s);
1650 out_printf(out, ",\n\t\t&return_val);\n"
1651 "\treturn return_val;\n}\n");
1657 out_addline_infile(out, m->line_no);
1658 print_method(out, "static ", "\n___real_", "", " ", "\n",
1659 m, FALSE, FALSE, TRUE);
1660 print_method_body(m, FALSE);
1661 /* the outfile line was added above */
1663 case VIRTUAL_METHOD:
1665 out_addline_infile(out, m->line_no);
1666 if(m->scope==PRIVATE_SCOPE)
1667 print_method(out, "static ", "\n", "", " ", "\n",
1668 m, FALSE, FALSE, TRUE);
1669 else /* PUBLIC, PROTECTED */
1670 print_method(out, "", "\n", "", " ", "\n",
1671 m, FALSE, FALSE, TRUE);
1672 out_addline_outfile(out);
1673 out_printf(out, "{\n"
1674 "\t%sClass *klass;\n", typebase);
1675 print_preconditions(m);
1676 out_printf(out, "\tklass = %s_CLASS(GTK_OBJECT(%s)->klass);\n\n"
1677 "\tif(klass->%s)\n",
1678 macrobase, ((FuncArg *)m->args->data)->name,
1679 get_real_id(m->id));
1680 if(strcmp(m->mtype->name, "void")==0 &&
1681 m->mtype->stars==0) {
1683 out_printf(out, "\t\t(*klass->%s)(%s",
1685 ((FuncArg *)m->args->data)->name);
1686 for(li=m->args->next;li;li=g_list_next(li)) {
1687 FuncArg *fa = li->data;
1688 out_printf(out, ",%s", fa->name);
1690 out_printf(out, ");\n}\n");
1693 out_printf(out, "\t\treturn (*klass->%s)(%s",
1695 ((FuncArg *)m->args->data)->name);
1696 for(li=m->args->next;li;li=g_list_next(li)) {
1697 FuncArg *fa = li->data;
1698 out_printf(out, ",%s", fa->name);
1700 out_printf(out, ");\n"
1703 print_type(out, m->mtype, TRUE);
1705 out_printf(out, ")(%s);\n}\n", m->defreturn);
1707 out_printf(out, ")(%s);\n}\n", m->onerror);
1709 out_printf(out, ")(0);\n}\n");
1715 out_addline_infile(out, m->line_no);
1716 print_method(out, "static ", "\n___real_", "", " ", "\n",
1717 m, FALSE, FALSE, TRUE);
1718 print_method_body(m, FALSE);
1719 /* the outfile line was added above */
1721 case OVERRIDE_METHOD:
1725 out_addline_infile(out, m->line_no);
1726 s = g_strdup_printf("\n___%x_", (guint)m->unique_id);
1727 print_method(out, "static ", s, "", " ", "\n",
1728 m, FALSE, FALSE, FALSE);
1730 out_addline_outfile(out);
1731 s = replace_sep(m->otype, '_');
1733 args = get_arg_names_for_macro(m);
1735 out_printf(out, "#define PARENT_HANDLER(%s) \\\n"
1736 "\t{ if(%s_CLASS(parent_class)->%s) \\\n"
1737 "\t\t(* %s_CLASS(parent_class)->%s)(%s); }\n",
1738 args, s, m->id, s, m->id, args);
1740 out_printf(out, "#define PARENT_HANDLER(%s) \\\n"
1741 "\t((%s_CLASS(parent_class)->%s)? \\\n"
1742 "\t\t(* %s_CLASS(parent_class)->%s)(%s): \\\n"
1744 args, s, m->id, s, m->id, args);
1745 out_printf(out, "(");
1746 print_type(out, m->mtype, TRUE);
1747 out_printf(out, ")%s))\n",
1748 m->onerror?m->onerror:"0");
1752 print_method_body(m, TRUE);
1753 /* the outfile line was added above */
1754 out_printf(out, "#undef PARENT_HANDLER\n");
1764 char *outfile, *outfileh, *outfileph;
1767 outfile = g_strconcat(filebase, ".c", NULL);
1769 outfile = g_strconcat(filebase, ".cc", NULL);
1770 if(no_touch_headers)
1771 outfileh = g_strconcat("#gob#", filebase, ".h#gob#", NULL);
1773 outfileh = g_strconcat(filebase, ".h", NULL);
1775 if((privates > 0 || protecteds > 0 ||
1776 private_header == PRIVATE_HEADER_ALWAYS) &&
1777 !private_header != PRIVATE_HEADER_NEVER)
1778 outfileph = g_strconcat(filebase, "-private.h", NULL);
1784 devnull = fopen("/dev/null", "w");
1786 g_error("Cannot open null device");
1792 out = fopen(outfile, "w");
1794 g_error("Cannot open outfile: %s", outfile);
1796 outh = fopen(outfileh, "w");
1798 g_error("Cannot open outfile: %s", outfileh);
1800 outph = fopen(outfileph, "w");
1802 g_error("Cannot open outfile: %s", outfileh);
1808 put_argument_nongnu_wrappers(Class *c)
1815 for(li=c->nodes;li;li=g_list_next(li)) {
1817 Argument *a = (Argument *)n;
1821 if(n->type != ARGUMENT_NODE)
1824 aname = g_strdup(a->name);
1828 cast = get_type(a->atype, TRUE);
1830 cast = g_strdup(get_cast(a->gtktype, TRUE));
1834 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1835 "\"%s\",(%s)(arg)\n",
1836 macrobase, aname, a->name, cast);
1838 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1839 "\"%s\",(%s*)(arg)\n",
1840 macrobase, aname, a->name, cast);
1843 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1845 macrobase, aname, a->name);
1847 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1849 macrobase, aname, a->name);
1857 put_argument_gnu_wrappers(Class *c)
1864 for(li=c->nodes;li;li=g_list_next(li)) {
1866 Argument *a = (Argument *)n;
1869 if(n->type != ARGUMENT_NODE)
1871 s = g_strdup(a->name);
1874 cast = get_type(a->atype, TRUE);
1876 cast = g_strdup(get_cast(a->gtktype, TRUE));
1879 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1880 "\"%s\",({%sz = (arg); z;})\n",
1881 macrobase, s, a->name, cast);
1883 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1884 "\"%s\",({%s*z = (arg); z;})\n",
1885 macrobase, s, a->name, cast);
1888 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1890 macrobase, s, a->name);
1892 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1894 macrobase, s, a->name);
1902 print_ccode_block(CCode *cc)
1905 switch(cc->cctype) {
1907 /* HT code is printed exactly like normal header
1908 code but is printed before */
1911 out_printf(fp, "\n");
1914 /* AT code is printed exactly like normal 'all'
1915 code but is printed before */
1918 out_printf(outph, "\n");
1919 out_printf(outph, "%s\n", cc->cbuf);
1920 out_addline_infile(outph, cc->line_no);
1921 out_addline_outfile(outph);
1923 out_printf(outh, "\n");
1924 out_printf(outh, "%s\n", cc->cbuf);
1926 out_printf(fp, "\n");
1927 out_addline_infile(fp, cc->line_no);
1932 out_printf(fp, "\n");
1933 out_addline_infile(fp, cc->line_no);
1940 out_printf(fp, "\n");
1941 out_addline_infile(fp, cc->line_no);
1944 out_printf(fp, "%s\n", cc->cbuf);
1945 if(cc->cctype == C_CCODE ||
1946 cc->cctype == A_CCODE ||
1947 cc->cctype == AT_CCODE ||
1948 cc->cctype == PH_CCODE)
1949 out_addline_outfile(fp);
1953 print_class_block(Class *c)
1957 gboolean printed_private = FALSE;
1960 out_printf(out, "/* utility types we may need */\n");
1961 if(special_array[SPECIAL_2POINTER])
1962 out_printf(out, "typedef struct { "
1963 "gpointer a; gpointer b; "
1964 "} ___twopointertype;\n");
1965 if(special_array[SPECIAL_3POINTER])
1966 out_printf(out, "typedef struct { "
1967 "gpointer a; gpointer b; "
1969 "} ___threepointertype;\n");
1970 if(special_array[SPECIAL_INT_POINTER])
1971 out_printf(out, "typedef struct { "
1972 "gint a; gpointer b; "
1973 "} ___intpointertype;\n");
1974 out_printf(out, "\n");
1977 out_printf(outh, "\n/*\n"
1978 " * Type checking and casting macros\n"
1980 out_printf(outh, "#define %s\t"
1981 "(%s_get_type())\n",
1982 macrotype, funcbase);
1983 out_printf(outh, "#define %s(obj)\t"
1984 "GTK_CHECK_CAST((obj), %s_get_type(),%s)\n",
1985 macrobase, funcbase, typebase);
1986 out_printf(outh, "#define %s_CLASS(klass)\t"
1987 "GTK_CHECK_CLASS_CAST((klass),%s_get_type(),%sClass)\n",
1988 macrobase, funcbase, typebase);
1989 out_printf(outh, "#define %s(obj)\t"
1990 "GTK_CHECK_TYPE((obj),%s_get_type ())\n\n",
1993 if(!no_self_alias) {
1994 out_printf(out, "/* self casting macros */\n");
1995 out_printf(out, "#define SELF(x) %s(x)\n", macrobase);
1996 out_printf(out, "#define IS_SELF(x) %s(x)\n", macrois);
1997 out_printf(out, "#define SELF_CLASS(x) %s_CLASS(x)\n\n",
2000 out_printf(out, "/* self typedefs */\n");
2001 out_printf(out, "typedef %s Self;\n", typebase);
2002 out_printf(out, "typedef %sClass SelfClass;\n\n", typebase);
2006 out_printf(outh, "\n/* Private structure type */\n");
2007 out_printf(outh, "typedef struct _%sPrivate %sPrivate;\n",
2008 typebase, typebase);
2011 out_printf(outh, "\n/*\n"
2012 " * Main object structure\n"
2014 s = replace_sep(c->otype, '_');
2016 out_printf(outh, "#ifndef __TYPEDEF_%s__\n"
2017 "#define __TYPEDEF_%s__\n", s, s);
2019 out_printf(outh, "typedef struct _%s %s;\n"
2020 "#endif\n", typebase, typebase);
2021 out_printf(outh, "struct _%s {\n\t%s __parent__;\n",
2022 typebase, ptypebase);
2023 for(l=c->nodes;l;l=g_list_next(l)) {
2024 static gboolean printed_public = FALSE;
2026 Variable *v = (Variable *)n;
2027 if(n->type == VARIABLE_NODE &&
2028 v->scope == PUBLIC_SCOPE) {
2029 if(!printed_public) {
2030 out_printf(outh, "\t/*< public >*/\n");
2031 printed_public = TRUE;
2033 put_variable((Variable *)n, outh);
2036 /* put protecteds always AFTER publics */
2037 for(l=c->nodes;l;l=g_list_next(l)) {
2039 Variable *v = (Variable *)n;
2040 if(n->type == VARIABLE_NODE &&
2041 v->scope == PROTECTED_SCOPE) {
2042 if(!printed_private) {
2043 out_printf(outh, "\t/*< private >*/\n");
2044 printed_private = TRUE;
2046 put_variable((Variable *)n, outh);
2050 if(!printed_private)
2051 out_printf(outh, "\t/*< private >*/\n");
2052 out_printf(outh, "\t%sPrivate *_priv;\n", typebase);
2054 out_printf(outh, "};\n");
2059 /* if we are to stick this into the private
2060 header, if not stick it directly into the
2067 out_printf(outfp, "struct _%sPrivate {\n",
2069 for(l=c->nodes;l;l=l->next) {
2071 Variable *v = (Variable *)n;
2072 if(n->type == VARIABLE_NODE &&
2073 v->scope == PRIVATE_SCOPE) {
2074 out_addline_infile(outfp, v->line_no);
2075 put_variable(v, outfp);
2078 out_addline_outfile(outfp);
2079 out_printf(outfp, "};\n");
2082 out_printf(outh, "\n/*\n"
2083 " * Class definition\n"
2085 out_printf(outh, "typedef struct _%sClass %sClass;\n",
2086 typebase, typebase);
2088 "struct _%sClass {\n\t%sClass __parent__;\n",
2089 typebase, ptypebase);
2090 for(l=c->nodes;l;l=g_list_next(l)) {
2092 if(n->type == METHOD_NODE)
2093 put_vs_method((Method *)n);
2095 /* put class scope variables */
2096 for(l=c->nodes;l;l=g_list_next(l)) {
2098 Variable *v = (Variable *)n;
2099 if(n->type == VARIABLE_NODE &&
2100 v->scope == CLASS_SCOPE)
2101 put_variable((Variable *)n, outh);
2103 out_printf(outh, "};\n\n");
2105 out_printf(out, "/* here are local prototypes */\n");
2107 out_printf(out, "static void ___object_set_arg "
2108 "(GtkObject *object, GtkArg *arg, "
2110 "static void ___object_get_arg "
2111 "(GtkObject *object, GtkArg *arg, "
2112 "guint arg_id);\n");
2115 out_printf(outh, "\n/*\n"
2116 " * Public methods\n"
2119 out_printf(outh, "guint\t%s_get_type\t(void);\n", funcbase);
2120 for(l=c->nodes;l;l=g_list_next(l)) {
2122 if(n->type == METHOD_NODE) {
2123 put_pub_method((Method *)n);
2124 put_prot_method((Method *)n);
2125 put_priv_method_prot((Method *)n);
2129 /* this idea is less and less apealing to me */
2131 if(!no_signal_connect) {
2133 out_printf(outh, "\n/*\n"
2134 " * Signal connection methods\n"
2138 for(l=c->nodes;l;l=g_list_next(l)) {
2140 if(n->type == METHOD_NODE)
2141 put_signal_connect((Method *)n);
2147 /* argument wrapping macros */
2148 if(arguments>0 && !no_gnu) {
2149 out_printf(outh, "\n/*\n"
2150 " * Argument wrapping macros\n"
2152 out_printf(outh, "#ifdef __GNUC__\n");
2153 put_argument_gnu_wrappers(c);
2154 out_printf(outh, "#else /* __GNUC__ */\n");
2155 put_argument_nongnu_wrappers(c);
2156 out_printf(outh, "#endif /* __GNUC__ */\n\n");
2157 } else if(arguments>0 && no_gnu) {
2158 out_printf(outh, "\n/*\n"
2159 " * Argument wrapping macros\n"
2161 put_argument_nongnu_wrappers(c);
2165 for(l=c->nodes;l;l=g_list_next(l)) {
2167 if(n->type == METHOD_NODE)
2168 add_signal_prots((Method *)n);
2176 if(any_method_to_alias(c)) {
2178 make_method_nongnu_aliases(c);
2180 out_printf(out, "\n#ifdef __GNUC__\n");
2181 make_method_gnu_aliases(c);
2182 out_printf(out, "#else /* __GNUC__ */\n");
2183 make_method_nongnu_aliases(c);
2184 out_printf(out, "#endif /* __GNUC__ */\n\n");
2188 out_printf(out, "/* a macro for creating a new object of our type */\n");
2190 "#define GET_NEW ((%s *)gtk_type_new(%s_get_type()))\n\n",
2191 typebase, funcbase);
2202 add_getset_arg(c, TRUE);
2203 add_getset_arg(c, FALSE);
2206 for(l=c->nodes;l;l=g_list_next(l)) {
2208 if(n->type == METHOD_NODE)
2209 put_method((Method *)n);
2212 add_bad_hack_to_avoid_unused_warnings(c);
2216 print_version_macros(void)
2218 int major=0, minor=0, pl=0;
2219 sscanf(VERSION, "%d.%d.%d", &major, &minor, &pl);
2221 out_printf(out, "#define GOB_VERSION_MAJOR %d\n", major);
2222 out_printf(out, "#define GOB_VERSION_MINOR %d\n", minor);
2223 out_printf(out, "#define GOB_VERSION_PATCHLEVEL %d\n\n", pl);
2227 print_file_comments(void)
2231 out_printf(outh, "/* Generated by GOB (v%s)"
2232 " (do not edit directly) */\n\n", VERSION);
2234 out_printf(outph, "/* Generated by GOB (v%s)"
2235 " (do not edit directly) */\n\n", VERSION);
2236 out_printf(out, "/* Generated by GOB (v%s) on %s"
2237 " (do not edit directly) */\n\n",
2238 VERSION, ctime(&curtime));
2242 print_includes(void)
2244 gboolean found_header;
2247 /* We may need string.h for memset */
2249 out_printf(out, "#include <string.h> /* memset() */\n\n");
2251 p = g_strconcat(filebase, ".h", NULL);
2252 found_header = TRUE;
2253 if(!g_list_find_custom(include_files, p, (GCompareFunc)strcmp)) {
2254 out_printf(out, "#include \"%s.h\"\n\n", filebase);
2255 found_header = FALSE;
2259 /* if we are creating a private header see if it was included */
2261 p = g_strconcat(filebase, "-private.h", NULL);
2262 if(!g_list_find_custom(include_files, p, (GCompareFunc)strcmp)) {
2263 out_printf(out, "#include \"%s-private.h\"\n\n",
2267 "Implicit private header include "
2269 "\tsource file, while public "
2270 "header is at a custom location, "
2272 "\texplicitly include "
2273 "the private header below the "
2281 print_header_prefixes(void)
2285 p = replace_sep(((Class *)class)->otype, '_');
2287 out_printf(outh, "#ifndef __%s_H__\n#define __%s_H__\n\n", p, p);
2289 out_printf(outph, "#ifndef __%s_PRIVATE_H__\n"
2290 "#define __%s_PRIVATE_H__\n\n"
2291 "#include \"%s.h\"\n\n", p, p, filebase);
2295 out_printf(outh, "#ifdef __cplusplus\n"
2297 "#endif /* __cplusplus */\n\n");
2299 out_printf(outph, "#ifdef __cplusplus\n"
2301 "#endif /* __cplusplus */\n\n");
2306 print_header_postfixes(void)
2309 out_printf(outh, "\n#ifdef __cplusplus\n"
2311 "#endif /* __cplusplus */\n");
2312 out_printf(outh, "\n#endif\n");
2315 out_printf(outph, "\n#ifdef __cplusplus\n"
2317 "#endif /* __cplusplus */\n");
2318 out_printf(outph, "\n#endif\n");
2327 /* print the AT_CCODE blocks */
2328 for(li=nodes;li;li=g_list_next(li)) {
2329 Node *node = li->data;
2330 if(node->type == CCODE_NODE) {
2331 CCode *cc = (CCode *)node;
2332 if(cc->cctype==AT_CCODE)
2333 print_ccode_block((CCode *)node);
2339 print_header_top(void)
2343 /* mandatory include */
2344 out_printf(outh, "#include <gtk/gtk.h>\n\n");
2346 /* print the HT_CCODE blocks */
2347 for(li=nodes;li;li=g_list_next(li)) {
2348 Node *node = li->data;
2349 if(node->type == CCODE_NODE) {
2350 CCode *cc = (CCode *)node;
2351 if(cc->cctype==HT_CCODE)
2352 print_ccode_block((CCode *)node);
2358 generate_outfiles(void)
2362 print_file_comments();
2368 print_header_prefixes();
2370 print_version_macros();
2374 for(li=nodes;li;li=g_list_next(li)) {
2375 Node *node = li->data;
2376 if(node->type == CCODE_NODE) {
2377 CCode *cc = (CCode *)node;
2378 if(cc->cctype!=HT_CCODE)
2379 print_ccode_block((CCode *)node);
2380 } else if(node->type == CLASS_NODE) {
2381 print_class_block((Class *)node);
2383 g_assert_not_reached();
2386 print_header_postfixes();
2392 fprintf(stderr, "Gob version %s\n\n", VERSION);
2393 fprintf(stderr, "Options:\n"
2394 "\t--help,-h,-? Display this help\n"
2395 "\t--version Display version\n"
2396 "\t--exit-on-warn,-w Exit with an error on warnings\n"
2397 "\t--no-exit-on-warn Don't exit on warnings [default]\n"
2398 "\t--for-cpp Create C++ files\n"
2399 "\t--no-extern-c Never print extern \"C\" into the "
2401 "\t--no-gnu Never use GNU extentions\n"
2402 "\t--no-touch-headers Don't touch headers unless they "
2404 "\t--always-private-header Always create a private header "
2406 "\t even if it would be empty "
2408 "\t--ondemand-private-header Create private header only when "
2410 "\t--no-private-header Don't create a private header, "
2412 "\t structure and protected "
2413 "prototypes inside c file\n"
2414 "\t--no-write,-n Don't write output files, just "
2416 "\t--no-lines Don't print '#line' to output\n"
2417 "\t--no-self-alias Don't create self type and macro "
2419 "\t--no-kill-underscores Don't remove the leading underscore "
2420 "from short id names");
2424 parse_options(int argc, char *argv[])
2427 int got_file = FALSE;
2428 int no_opts = FALSE;
2432 for(i=1;i<argc;i++) {
2433 if(no_opts || argv[i][0]!='-') {
2436 fprintf(stderr, "Specify only one file!\n");
2442 } else if(strcmp(argv[i], "--help")==0) {
2445 } else if(strcmp(argv[i], "--version")==0) {
2446 fprintf(stderr, "Gob version %s\n", VERSION);
2448 } else if(strcmp(argv[i], "--exit-on-warn")==0) {
2449 exit_on_warn = TRUE;
2450 } else if(strcmp(argv[i], "--no-exit-on-warn")==0) {
2451 exit_on_warn = FALSE;
2452 } else if(strcmp(argv[i], "--for-cpp")==0) {
2454 } else if(strcmp(argv[i], "--no-touch-headers")==0) {
2455 no_touch_headers = TRUE;
2456 } else if(strcmp(argv[i], "--ondemand-private-header")==0) {
2457 private_header == PRIVATE_HEADER_ONDEMAND;
2458 } else if(strcmp(argv[i], "--always-private-header")==0) {
2459 private_header == PRIVATE_HEADER_ALWAYS;
2460 } else if(strcmp(argv[i], "--no-private-header")==0) {
2461 private_header == PRIVATE_HEADER_NEVER;
2462 } else if(strcmp(argv[i], "--no-gnu")==0) {
2464 } else if(strcmp(argv[i], "--no-extern-c")==0) {
2466 } else if(strcmp(argv[i], "--no-write")==0) {
2468 } else if(strcmp(argv[i], "--no-lines")==0) {
2470 } else if(strcmp(argv[i], "--no-self-alias")==0) {
2471 no_self_alias = TRUE;
2472 } else if(strcmp(argv[i], "--no-kill-underscores")==0) {
2473 no_kill_underscores = TRUE;
2474 } else if(strcmp(argv[i], "--")==0) {
2475 /*further arguments are files*/
2477 } else if(strncmp(argv[i], "--", 2)==0) {
2478 /*unknown long option*/
2479 fprintf(stderr, "Unknown option '%s'!\n", argv[i]);
2483 /*by now we know we have a string starting with
2484 - which is a short option string*/
2485 char *p = argv[i]+1;
2486 for(p=argv[i]+1; *p; p++) {
2500 "Unknown option '%c'!\n", *p);
2509 /* this is a somewhat ugly hack, but it appears to work */
2511 compare_and_move_header(void)
2513 char *hfnew = g_strconcat("#gob#", filebase, ".h#gob#", NULL);
2514 char *hf = g_strconcat(filebase, ".h", NULL);
2516 if(stat(hf, &s)==0) {
2518 s = g_strdup_printf("cmp '%s' '%s' > /dev/null", hf, hfnew);
2520 if(unlink(hfnew)!=0)
2522 "Can't remove new header file", 0);
2530 print_error(FALSE, "Can't remove old header file", 0);
2532 if(rename(hfnew, hf)!=0)
2533 print_error(FALSE, "Can't rename new header file", 0);
2539 main(int argc, char *argv[])
2541 parse_options(argc, argv);
2544 yyin = fopen(filename, "r");
2546 fprintf(stderr, "Error: can't open file '%s'\n",
2555 g_error("Parsing errors, quitting");
2557 print_error(FALSE, " no class defined", 0);
2560 exit_on_error = FALSE;
2562 signals = count_signals((Class *)class);
2563 arguments = count_arguments((Class *)class);
2564 overrides = count_overrides((Class *)class);
2565 privates = count_privates((Class *)class);
2566 protecteds = count_protecteds((Class *)class);
2567 destructors = count_destructors((Class *)class);
2568 initializers = count_initializers((Class *)class);
2571 make_inits((Class *)class);
2572 if(destructors > 0) {
2573 need_destroy = TRUE;
2574 find_destroy((Class *)class);
2577 need_finalize = TRUE;
2578 find_finalize((Class *)class);
2580 check_bad_symbols((Class *)class);
2581 check_duplicate_symbols((Class *)class);
2582 check_duplicate_overrides((Class *)class);
2583 check_duplicate_signals_args((Class *)class);
2584 check_public_new((Class *)class);
2585 check_vararg((Class *)class);
2586 check_firstarg((Class *)class);
2587 check_nonvoidempty((Class *)class);
2588 check_signal_args((Class *)class);
2589 check_argument_types((Class *)class);
2591 exit_on_error = TRUE;
2596 any_special = setup_special_array((Class *)class, special_array);
2600 generate_outfiles();
2611 if(no_touch_headers && !no_write)
2612 compare_and_move_header();