2 * Copyright (C) 1999 the Free Software Foundation.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
31 #include "treefuncs.h"
39 char *filename = NULL;
48 extern GList *include_files;
50 extern GHashTable *gtk_doc_hash;
53 static char *funcbase;
54 static char *pfuncbase;
55 static char *macrobase;
57 static char *macrotype;
58 static char *typebase;
59 static char *ptypebase;
61 static int signals = 0; /* number of signals */
62 static int arguments = 0; /* number of named arguments */
63 static int overrides = 0; /* number of override methods */
64 static int privates = 0; /* number of private data members */
65 static int protecteds = 0; /* number of protected methods */
66 static int destructors = 0; /* number of variable destructors */
67 static int initializers = 0; /* number of variable initializers */
69 static gboolean made_aliases = FALSE; /* if we made any shorthand aliases
70 and need the REALLY UGLY HACK to
73 /* the special variable types we need to define */
74 static gboolean special_array[SPECIAL_LAST] = {0};
75 static gboolean any_special = FALSE;
82 gboolean no_touch_headers = FALSE;
83 gboolean for_cpp = FALSE;
84 gboolean no_gnu = FALSE;
85 gboolean exit_on_warn = FALSE;
86 gboolean exit_on_error = TRUE;
87 gboolean got_error = FALSE;
88 gint private_header = PRIVATE_HEADER_ALWAYS;
89 gboolean no_extern_c = FALSE;
90 gboolean no_write = FALSE;
91 gboolean no_lines = FALSE;
96 filebase = replace_sep(((Class *)class)->otype, '-');
99 funcbase = replace_sep(((Class *)class)->otype, '_');
102 pfuncbase = replace_sep(((Class *)class)->ptype, '_');
103 g_strdown(pfuncbase);
105 macrobase = replace_sep(((Class *)class)->otype, '_');
108 macrois = make_pre_macro(((Class *)class)->otype, "IS");
109 macrotype = make_pre_macro(((Class *)class)->otype, "TYPE");
111 typebase = remove_sep(((Class *)class)->otype);
113 ptypebase = remove_sep(((Class *)class)->ptype);
117 get_type(Type *t, gboolean postfix_to_stars)
124 s = remove_sep(t->name);
125 gs = g_string_new(s);
129 if(postfix_to_stars) {
131 /*XXX: this is ugly perhaps we can do this whole postfix thing
132 in a nicer way, we just count the number of '[' s and from
133 that we deduce the number of dimensions, so that we can print
135 for(p=t->postfix; p && *p; p++)
136 if(*p == '[') extra++;
138 g_string_append_c(gs, ' ');
140 for(i=0; i<(t->stars+extra); i++)
141 g_string_append_c(gs, '*');
144 g_string_free(gs, FALSE);
149 get_gtk_doc(char *id)
156 val = g_hash_table_lookup(gtk_doc_hash, id);
158 return g_strdup_printf("/**\n * %s_%s:\n%s **/\n",
160 s = g_strconcat(funcbase, "_", id, NULL);
161 val = g_hash_table_lookup(gtk_doc_hash, s);
164 return g_strdup_printf("/**\n * %s_%s:\n%s **/\n",
170 print_type(FILE *fp, Type *t, gboolean postfix_to_stars)
174 s = get_type(t, postfix_to_stars);
175 out_printf(fp, "%s", s);
181 print_method(FILE *fp, char *typeprefix, char *nameprefix,
183 char *namepostfix, char *postfix, Method *m,
184 gboolean one_arg_per_line,
185 gboolean no_funcbase)
189 out_printf(fp, "%s", typeprefix);
190 print_type(fp, m->mtype, TRUE);
192 out_printf(fp, "%s%s%s%s(",
193 nameprefix, subnameprefix, m->id, namepostfix);
195 out_printf(fp, "%s%s_%s%s%s(",
196 nameprefix, funcbase, subnameprefix, m->id,
200 for(li=m->args; li; li=g_list_next(li)) {
201 FuncArg *arg = li->data;
202 print_type(fp, arg->atype, FALSE);
204 out_printf(fp, "%s%s,%s", arg->name,
206 arg->atype->postfix:"",
207 one_arg_per_line?"\n\t\t\t\t\t":" ");
209 out_printf(fp, "%s%s", arg->name,
211 arg->atype->postfix:"");
214 out_printf(fp, ",%s...",
215 one_arg_per_line?"\n\t\t\t\t\t":" ");
217 out_printf(fp, "void");
219 out_printf(fp, ")%s", postfix);
223 any_method_to_alias(Class *c)
227 for(li=c->nodes;li;li=g_list_next(li)) {
228 Node *node = li->data;
229 if(node->type == METHOD_NODE) {
230 Method *m = (Method *)node;
232 if(m->method == INIT_METHOD ||
233 m->method == CLASS_INIT_METHOD ||
234 m->method == OVERRIDE_METHOD)
245 make_method_gnu_aliases(Class *c)
249 for(li=c->nodes;li;li=g_list_next(li)) {
250 Node *node = li->data;
251 if(node->type == METHOD_NODE) {
252 Method *m = (Method *)node;
254 if(m->method == INIT_METHOD ||
255 m->method == CLASS_INIT_METHOD ||
256 m->method == OVERRIDE_METHOD)
259 /* in C++ mode don't alias new */
260 if(for_cpp && strcmp(m->id, "new")==0)
263 out_printf(out, "static const typeof(&%s_%s) %s "
264 "__attribute__ ((__unused__)) "
265 "= %s_%s;\n", funcbase, m->id, m->id,
267 out_printf(out, "#define %s(args...) "
268 "%s_%s(##args)\n", m->id, funcbase, m->id);
274 make_method_nongnu_aliases(Class *c)
278 for(li=c->nodes; li; li=g_list_next(li)) {
279 Node *node = li->data;
280 if(node->type == METHOD_NODE) {
281 Method *m = (Method *)node;
283 if(m->method == INIT_METHOD ||
284 m->method == CLASS_INIT_METHOD ||
285 m->method == OVERRIDE_METHOD)
288 /* in C++ mode don't alias new */
289 if(for_cpp && strcmp(m->id, "new")==0)
292 print_method(out, "static ", "(* ", "", ") ", "",
294 out_printf(out, " = %s_%s;\n", funcbase, m->id);
302 add_bad_hack_to_avoid_unused_warnings(Class *c)
306 /* if we haven't had any methods, just return */
311 out_printf(out, "\n\n#ifndef __GNUC__\n");
313 "/*REALLY BAD HACK\n"
314 " This is to avoid unused warnings if you don't call\n"
315 " some method. I need to find a better way to do\n"
316 " this, not needed in GCC since we use some gcc\n"
317 " extentions to make saner, faster code */\n"
319 "___%s_really_bad_hack_to_avoid_warnings(void)\n"
321 for(li=c->nodes;li;li=g_list_next(li)) {
322 Node *node = li->data;
323 if(node->type == METHOD_NODE) {
324 Method *m = (Method *)node;
326 if(m->method == INIT_METHOD ||
327 m->method == CLASS_INIT_METHOD ||
328 m->method == OVERRIDE_METHOD)
331 /* in C++ mode we don't alias new */
332 if(for_cpp && strcmp(m->id, "new")==0)
335 out_printf(out, "\t((void (*)(void))%s)();\n", m->id);
338 out_printf(out, "\t___%s_really_bad_hack_to_avoid_warnings();\n",
341 out_printf(out, "}\n#endif /* __GNUC__ */\n\n");
343 out_printf(out, "}\n\n");
347 put_variable(Variable *v, FILE *fp)
349 out_printf(fp, "\t");
350 print_type(fp, v->vtype, FALSE);
351 out_printf(fp, "%s%s;", v->id,
353 v->vtype->postfix:"");
354 if(v->scope == PROTECTED_SCOPE)
355 out_printf(fp, " /* protected */");
356 out_printf(fp, "\n");
360 put_vs_method(Method *m)
362 if(m->method != SIGNAL_LAST_METHOD &&
363 m->method != SIGNAL_FIRST_METHOD &&
364 m->method != VIRTUAL_METHOD)
367 /* if a signal mark it as such */
368 if(m->method != VIRTUAL_METHOD)
369 print_method(outh, "\t/*signal*/", "(* ", "", ") ", ";\n", m,
372 print_method(outh, "\t", "(* ", "", ") ", ";\n", m, FALSE, TRUE);
376 put_pub_method(Method *m)
378 if(m->scope != PUBLIC_SCOPE)
381 print_method(outh, "", "\t", "", "\t", ";\n", m, TRUE, FALSE);
384 /* I'm starting not to like this idea */
387 put_signal_connect(Method *m)
389 if(m->method != SIGNAL_LAST_METHOD &&
390 m->method != SIGNAL_FIRST_METHOD)
393 out_printf(outh, "guint \t%s_%s__connect_full\t(%s *object,\n"
394 "\t\t\t\t\tconst char *name,\n"
395 "\t\t\t\t\tGtkSignalFunc func,\n"
396 "\t\t\t\t\tGtkCallbackMarshal marshal,\n"
397 "\t\t\t\t\tgpointer data,\n"
398 "\t\t\t\t\tGtkDestroyNotify destroy_func,\n"
399 "\t\t\t\t\tgboolean object_signal,\n"
400 "\t\t\t\t\tgboolean after);\n",
401 funcbase, m->id, typebase);
403 out_printf(outh, "#define %s_%s__connect(object,name,func,data) "
404 "%s_%s__connect_full((object),(name),(func),NULL,"
405 "(data),NULL,FALSE,FALSE)\n",
406 funcbase, m->id, funcbase, m->id);
407 out_printf(outh, "#define %s_%s__connect_after(object,name,func,data) "
408 "%s__connect_%s_full((object),(name),(func),NULL,"
409 "(data),NULL,FALSE,TRUE)\n",
410 funcbase, m->id, funcbase, m->id);
412 out_printf(outh, "guint \t%s_%s__connect_while_alive\t(%s *object,\n"
413 "\t\t\t\t\tconst char *name,\n"
414 "\t\t\t\t\tGtkSignalFunc func,\n"
415 "\t\t\t\t\tgpointer data,\n"
416 "\t\t\t\t\tGtkObject *alive_object);\n\n",
417 funcbase, m->id, typebase);
423 put_prot_method(Method *m)
425 if(m->scope != PROTECTED_SCOPE)
429 print_method(outph, "", "\t", "", "\t", ";\n", m, FALSE, FALSE);
431 print_method(out, "", "\t", "", "\t", ";\n", m, FALSE, FALSE);
435 put_priv_method_prot(Method *m)
437 if(m->method == SIGNAL_LAST_METHOD ||
438 m->method == SIGNAL_FIRST_METHOD ||
439 m->method == VIRTUAL_METHOD) {
442 "static ", "___real_", "", " ", ";\n",
446 if(m->scope == PRIVATE_SCOPE ||
447 m->method == INIT_METHOD ||
448 m->method == CLASS_INIT_METHOD ||
449 (m->method == OVERRIDE_METHOD &&
451 print_method(out, "static ", "", "", " ",
452 no_gnu?";\n":" G_GNUC_UNUSED;\n",
457 make_func_arg(char *typename, int is_class, char *name)
464 tn = g_strconcat(typename, ":Class", NULL);
466 tn = g_strdup(typename);
468 type = new_type(1, tn, NULL);
469 node = new_funcarg((Type *)type, name, NULL);
470 return g_list_prepend(NULL, node);
474 make_inits(Class *cl)
476 int got_class_init = FALSE;
477 int got_init = FALSE;
480 for(li=cl->nodes;li;li=g_list_next(li)) {
482 if(n->type == METHOD_NODE) {
483 Method *m = (Method *)n;
484 if(m->method == INIT_METHOD) {
486 print_error(FALSE, "init defined more then once", m->line_no);
488 } else if(m->method == CLASS_INIT_METHOD) {
490 print_error(FALSE, "class_init defined more then once", m->line_no);
491 got_class_init = TRUE;
495 if(!got_class_init) {
496 node = new_method(NO_SCOPE, CLASS_INIT_METHOD,
497 (Type *)new_type(0, g_strdup("void"), NULL),
498 NULL, NULL, NULL, g_strdup("class_init"),
499 make_func_arg(cl->otype, TRUE, g_strdup("c")),
500 NULL, NULL, NULL, 0, 0, FALSE);
501 cl->nodes = g_list_prepend(cl->nodes, node);
504 node = new_method(NO_SCOPE, INIT_METHOD,
505 (Type *)new_type(0, g_strdup("void"), NULL),
506 NULL, NULL, NULL, g_strdup("init"),
507 make_func_arg(cl->otype, FALSE, g_strdup("o")),
508 NULL, NULL, NULL, 0, 0, FALSE);
509 cl->nodes = g_list_prepend(cl->nodes, node);
514 make_finalize(Class *cl)
516 int got_finalize = FALSE;
519 for(li=cl->nodes;li;li=g_list_next(li)) {
521 if(n->type == METHOD_NODE) {
522 Method *m = (Method *)n;
523 if(m->method == OVERRIDE_METHOD &&
524 strcmp(m->id, "finalize")==0) {
525 if(strcmp(m->otype, "Gtk:Object")==0) {
529 print_error(FALSE, "finalize method override "
530 "of class other then Gtk:Object",
536 node = new_method(NO_SCOPE, OVERRIDE_METHOD,
537 (Type *)new_type(0, g_strdup("void"), NULL),
538 g_strdup("Gtk:Object"),
539 NULL, NULL, g_strdup("finalize"),
540 make_func_arg("Gtk:Object", FALSE, g_strdup("o")),
542 g_strdup("PARENT_HANDLER (o);\n"),
544 cl->nodes = g_list_append(cl->nodes, node);
550 /* hash of method -> name of signal prototype */
551 static GHashTable *marsh = NULL;
553 /* list of methods with different signal prototypes,
554 we check this list if we can use a signal prototype of a
555 previous signal method, there are only uniques here */
556 static GList *eq_signal_methods = NULL;
558 /* compare a list of strings */
560 is_list_equal(GList *a, GList *b)
562 for(;a && b; a=a->next, b=b->next) {
563 if(strcmp(a->data, b->data)!=0) {
567 /* the the lists were different length */
574 find_same_type_signal(Method *m)
577 for(li=eq_signal_methods;li;li=li->next) {
578 Method *mm = li->data;
579 if(is_list_equal(mm->gtktypes, m->gtktypes))
586 print_signal_marsal_args(Method *m)
588 if(strcmp(m->gtktypes->next->data, "NONE")!=0) {
591 for(i=0, li=m->gtktypes->next;li;
592 i++, li=g_list_next(li)) {
594 out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
595 (char *)li->data, i);
597 out_printf(out, ",\n\t\t(%s)"
598 "GTK_VALUE_%s(args[%d])",
599 get_cast(li->data, FALSE),
600 (char *)li->data, i);
604 out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
609 add_signal_prots(Method *m)
616 if(m->method != SIGNAL_LAST_METHOD &&
617 m->method != SIGNAL_FIRST_METHOD)
621 marsh = g_hash_table_new(NULL, NULL);
623 if(strcmp(m->gtktypes->data, "NONE")==0 &&
624 strcmp(m->gtktypes->next->data, "NONE")==0)
627 /* if we already did a signal prototype just use that */
628 mm = find_same_type_signal(m);
630 s = g_hash_table_lookup(marsh, mm);
631 g_hash_table_insert(marsh, m, s);
635 s = g_strdup_printf("Sig%d", sig++);
637 g_hash_table_insert(marsh, m, s);
638 eq_signal_methods = g_list_prepend(eq_signal_methods, m);
640 /* we know that we'll know all the gtktypes (so get_cast can't fail) */
641 out_printf(out, "\ntypedef %s (*___%s) (%s *, ",
642 get_cast(m->gtktypes->data, FALSE), s, typebase);
644 if(strcmp(m->gtktypes->next->data, "NONE")!=0) {
645 for(li=m->gtktypes->next; li; li=g_list_next(li))
646 out_printf(out, "%s, ", get_cast(li->data, FALSE));
648 out_printf(out, "gpointer);\n");
650 out_printf(out, "\nstatic void\n"
651 "___marshal_%s (GtkObject * object,\n"
652 "\tGtkSignalFunc func,\n"
653 "\tgpointer func_data,\n"
657 if(strcmp(m->gtktypes->data, "NONE")==0) {
658 out_printf(out, "\t___%s rfunc;\n\n"
659 "\trfunc = (___%s)func;\n\n"
660 "\t(*rfunc)((%s *)object", s, s, typebase);
662 const char *retcast = get_cast(m->gtktypes->data, FALSE);
666 "\trfunc = (___%s)func;\n\n"
667 "\tretval = GTK_RETLOC_%s(args[%d]);\n\n"
668 "\t*retval = (*rfunc)((%s *)object",
669 s, retcast, s, (char *)m->gtktypes->data,
670 g_list_length(m->gtktypes)-1, typebase);
672 print_signal_marsal_args(m);
680 out_printf(out, "\n");
682 out_printf(out, "enum {\n");
683 for(li=c->nodes;li;li=g_list_next(li)) {
685 if(n->type == METHOD_NODE) {
686 Method *m = (Method *)n;
687 if(m->method == SIGNAL_LAST_METHOD ||
688 m->method == SIGNAL_FIRST_METHOD) {
689 char *s = g_strdup(m->id);
691 out_printf(out, "\t%s_SIGNAL,\n", s);
696 out_printf(out, "\tLAST_SIGNAL\n};\n\n");
699 out_printf(out, "enum {\n\tARG_0");
700 for(li=c->nodes;li;li=g_list_next(li)) {
702 if(n->type == ARGUMENT_NODE) {
703 Argument *a = (Argument *)n;
704 char *s = g_strdup(a->name);
706 out_printf(out, ",\n\tARG_%s", s);
710 out_printf(out, "\n};\n\n");
715 "static guint object_signals[LAST_SIGNAL] = {0};\n\n");
717 out_printf(out, "/* pointer to the class of our parent */\n");
718 out_printf(out, "static %sClass *parent_class = NULL;\n\n", ptypebase);
724 out_printf(out, "guint\n"
725 "%s_get_type (void)\n"
727 "\tstatic guint type = 0;\n\n"
729 "\t\tstatic const GtkTypeInfo info = {\n"
731 "\t\t\tsizeof (%s),\n"
732 "\t\t\tsizeof (%sClass),\n"
733 "\t\t\t(GtkClassInitFunc) %s_class_init,\n"
734 "\t\t\t(GtkObjectInitFunc) %s_init,\n"
735 "\t\t\t/* reserved_1 */ NULL,\n"
736 "\t\t\t/* reserved_2 */ NULL,\n"
737 "\t\t\t(GtkClassInitFunc) NULL,\n"
739 "\t\ttype = gtk_type_unique (%s_get_type(), &info);\n"
743 funcbase, typebase, typebase, typebase,
744 funcbase, funcbase, pfuncbase);
748 add_overrides(Class *c, char *oname, gboolean did_gtk_obj)
754 done = g_hash_table_new(g_str_hash, g_str_equal);
756 s = g_strdup("GtkObject"); /* This was already done */
757 g_hash_table_insert(done, s, s);
759 for(li=c->nodes; li; li=g_list_next(li)) {
762 Method *m = (Method *)n;
763 if(n->type != METHOD_NODE ||
764 m->method != OVERRIDE_METHOD)
767 s = remove_sep(m->otype);
769 if(g_hash_table_lookup(done, s)) {
773 g_hash_table_insert(done, s, s);
775 f = replace_sep(m->otype, '_');
778 out_printf(out, "\t%sClass *%s_class = (%sClass *)%s;\n",
783 g_hash_table_foreach(done, (GHFunc)g_free, NULL);
784 g_hash_table_destroy(done);
788 make_run_signal_flags(Method *m, gboolean last)
802 gs = g_string_new(NULL);
805 g_string_assign(gs, "GTK_RUN_LAST");
807 g_string_assign(gs, "GTK_RUN_FIRST");
809 if(m->scope == PUBLIC_SCOPE)
810 g_string_append(gs, " | GTK_RUN_ACTION");
812 for(li = m->flags; li; li = li->next) {
813 char *flag = li->data;
815 for(i=0;flags[i];i++) {
816 if(strcmp(flags[i], flag)==0)
819 /* if we haven't found it in our list */
822 s = g_strdup_printf("Unknown flag '%s' used, "
823 "perhaps it was misspelled",
825 print_error(TRUE, s, m->line_no);
828 g_string_sprintfa(gs, " | GTK_RUN_%s", flag);
833 g_string_free(gs, FALSE);
840 add_signals(Class *c)
844 out_printf(out, "\n");
845 for(li=c->nodes;li;li=g_list_next(li)) {
847 char *mar, *sig, *flags;
848 gboolean is_none, last = FALSE;
849 Method *m = (Method *)n;
851 if(n->type != METHOD_NODE ||
852 (m->method != SIGNAL_FIRST_METHOD &&
853 m->method != SIGNAL_LAST_METHOD))
856 if(m->method == SIGNAL_FIRST_METHOD)
861 if(g_hash_table_lookup(marsh, m))
862 mar = g_strconcat("___marshal_",
863 (char *)g_hash_table_lookup(marsh, m),
866 mar = g_strdup("gtk_signal_default_marshaller");
868 is_none = (strcmp(m->gtktypes->next->data, "NONE")==0);
870 sig = g_strdup(m->id);
872 flags = make_run_signal_flags(m, last);
873 out_printf(out, "\tobject_signals[%s_SIGNAL] =\n"
874 "\t\tgtk_signal_new (\"%s\",\n"
875 "\t\t\t(GtkSignalRunType)(%s),\n"
876 "\t\t\tgtk_object_class->type,\n"
877 "\t\t\tGTK_SIGNAL_OFFSET (%sClass, %s),\n"
879 "\t\t\tGTK_TYPE_%s, %d",
882 typebase, m->id, mar, (char *)m->gtktypes->data,
883 is_none?0:g_list_length(m->gtktypes->next));
890 for(l=m->gtktypes->next;l;l=g_list_next(l))
891 out_printf(out, ",\n\t\t\tGTK_TYPE_%s",
895 out_printf(out, ");\n");
897 out_printf(out, "\tgtk_object_class_add_signals (gtk_object_class,\n"
898 "\t\tobject_signals, LAST_SIGNAL);\n\n");
902 set_def_handlers(Class *c, char *oname)
905 gboolean set_line = FALSE;
907 out_printf(out, "\n");
908 for(li=c->nodes;li;li=g_list_next(li)) {
910 Method *m = (Method *)n;
911 if(n->type != METHOD_NODE ||
912 (m->method != SIGNAL_FIRST_METHOD &&
913 m->method != SIGNAL_LAST_METHOD &&
914 m->method != VIRTUAL_METHOD &&
915 m->method != OVERRIDE_METHOD))
918 if(m->line_no > 0 && m->cbuf) {
919 out_addline_infile(out, m->line_no);
921 } else if(set_line) {
922 out_addline_outfile(out);
926 if(m->method == OVERRIDE_METHOD) {
928 s = replace_sep(m->otype, '_');
931 out_printf(out, "\t%s_class->%s = %s_%s;\n",
932 s, m->id, funcbase, m->id);
934 out_printf(out, "\t%s_class->%s = NULL;\n",
938 out_printf(out, "\t%s->%s = ___real_%s_%s;\n",
939 oname, m->id, funcbase, m->id);
941 out_printf(out, "\t%s->%s = NULL;\n",
946 out_addline_outfile(out);
950 make_arguments(Class *c)
961 out_printf(out, "\n");
962 for(li=c->nodes;li;li=g_list_next(li)) {
968 if(n->type != ARGUMENT_NODE)
974 flags = g_string_new("GTK_ARG_READWRITE");
976 flags = g_string_new("GTK_ARG_READABLE");
978 flags = g_string_new("GTK_ARG_WRITABLE");
980 for(l=a->flags;l;l=g_list_next(l)) {
981 char *flag = l->data;
983 if(strcmp(flag, "READWRITE")==0 ||
984 strcmp(flag, "READABLE")==0 ||
985 strcmp(flag, "WRITABLE")==0) {
986 print_error(TRUE, "READWRITE, READABLE and "
987 "WRITABLE argument flags are "
988 "set automatically", a->line_no);
991 for(i=0;argflags[i];i++) {
992 if(strcmp(argflags[i], flag)==0)
995 /* if we haven't found it in our list */
998 s = g_strdup_printf("Unknown flag '%s' used, "
999 "perhaps it was misspelled",
1001 print_error(TRUE, s, a->line_no);
1004 g_string_sprintfa(flags, " | GTK_ARG_%s", flag);
1007 s = g_strdup(a->name);
1009 out_printf(out, "\tgtk_object_add_arg_type(\"%s::%s\",\n"
1010 "\t\tGTK_TYPE_%s,\n"
1013 typebase, a->name, a->gtktype, flags->str, s);
1015 g_string_free(flags, TRUE);
1019 "\n\tgtk_object_class->set_arg = ___object_set_arg;\n"
1020 "\tgtk_object_class->get_arg = ___object_get_arg;\n");
1024 print_initializer(Method *m, Variable *v)
1028 if(v->initializer == NULL)
1031 if(v->scope == PRIVATE_SCOPE)
1032 root = g_strconcat(((FuncArg *)m->args->data)->name,
1035 root = g_strdup(((FuncArg *)m->args->data)->name);
1037 if(v->initializer_line > 0)
1038 out_addline_infile(out, v->initializer_line);
1040 out_printf(out, "\t%s->%s = %s;\n",
1041 root, v->id, v->initializer);
1043 if(v->initializer_line > 0)
1044 out_addline_outfile(out);
1053 for(li=c->nodes;li;li=g_list_next(li)) {
1056 if(n->type != METHOD_NODE)
1059 if(m->method == INIT_METHOD) {
1061 out_addline_infile(out, m->line_no);
1062 print_method(out, "static ", "\n", "", " ", "\n",
1065 out_addline_outfile(out);
1066 out_printf(out, "{\n");
1068 out_printf(out, "\t%s->_priv = "
1069 "g_new0 (%sPrivate, 1);\n",
1070 ((FuncArg *)m->args->data)->name,
1073 if(initializers > 0) {
1075 for(li = ((Class *)class)->nodes;
1079 Variable *v = (Variable *)n;
1080 if(n->type != VARIABLE_NODE ||
1081 v->scope == CLASS_SCOPE)
1083 print_initializer(m, v);
1086 } else if(m->method == CLASS_INIT_METHOD) {
1088 out_addline_infile(out, m->line_no);
1089 print_method(out, "static ", "\n", "", " ", "\n",
1092 out_addline_outfile(out);
1093 out_printf(out, "{\n");
1097 "\tGtkObjectClass *"
1098 "gtk_object_class = "
1099 "(GtkObjectClass*) %s;\n",
1100 ((FuncArg *)m->args->data)->name);
1104 ((FuncArg *)m->args->data)->name,
1105 (signals>0 || arguments>0));
1107 if(initializers > 0) {
1109 for(li = ((Class *)class)->nodes;
1113 Variable *v = (Variable *)n;
1114 if(n->type != VARIABLE_NODE ||
1115 v->scope != CLASS_SCOPE)
1117 print_initializer(m, v);
1121 out_printf(out, "\n\tparent_class = ");
1123 out_printf(out, "(%sClass *)", ptypebase);
1124 out_printf(out, "gtk_type_class (%s_get_type ());\n",
1130 set_def_handlers(c, ((FuncArg *)m->args->data)->name);
1139 out_printf(out, " {\n");
1140 out_addline_infile(out, m->ccode_line);
1141 out_printf(out, "%s\n", m->cbuf);
1142 out_addline_outfile(out);
1143 out_printf(out, " }\n");
1145 out_printf(out, "return;\n");
1147 out_printf(out, "}\n");
1152 add_getset_arg(Class *c, gboolean is_set)
1155 out_printf(out, "\nstatic void\n"
1156 "___object_%s_arg (GtkObject *object,\n"
1161 "\tself = %s (object);\n\n"
1162 "\tswitch (arg_id) {\n",
1163 is_set?"set":"get", typebase, macrobase);
1165 for(li=c->nodes;li;li=g_list_next(li)) {
1171 if(n->type != ARGUMENT_NODE)
1176 line_no = a->set_line;
1179 line_no = a->get_line;
1183 s = g_strdup(a->name);
1185 out_printf(out, "\tcase ARG_%s:\n", s);
1186 if(is_set && a->atype) {
1187 char *cast = get_type(a->atype, TRUE);
1188 if(no_gnu || for_cpp) {
1189 out_printf(out, "#define ARG "
1190 "((%s)GTK_VALUE_%s(*arg))\n",
1193 out_printf(out, "#ifdef __GNUC__\n");
1194 if(strcmp(a->gtktype, "OBJECT")==0) {
1195 out_printf(out, "#define ARG "
1197 "GTK_VALUE_POINTER(*arg); "
1201 out_printf(out, "#define ARG "
1203 "GTK_VALUE_%s(*arg); "
1207 out_printf(out, "#else /* __GNUC__ */\n");
1208 out_printf(out, "#define ARG "
1209 "((%s)GTK_VALUE_%s(*arg))\n",
1211 out_printf(out, "#endif /* __GNUC__ */\n\n");
1213 out_printf(out, "\t\t{\n");
1215 } else if(!is_set && strcmp(a->gtktype, "OBJECT")==0) {
1217 "#define ARG (GTK_VALUE_POINTER(*arg))\n"
1221 "#define ARG (GTK_VALUE_%s(*arg))\n"
1227 out_addline_infile(out, line_no);
1228 out_printf(out, "%s\n", cbuf);
1230 out_addline_outfile(out);
1231 out_printf(out, "\t\t}\n\t\tbreak;\n"
1234 out_printf(out, "\tdefault:\n\t\tbreak;\n\t}\n}\n");
1238 print_checks(Method *m, FuncArg *fa)
1242 gboolean checked_null = FALSE;
1243 is_void = (strcmp(m->mtype->name, "void")==0 &&
1244 m->mtype->stars == 0);
1246 for(li=fa->checks;li;li=g_list_next(li)) {
1247 Check *ch = li->data;
1249 /* point to the method prot in .gob for failed checks */
1251 out_addline_infile(out, m->line_no);
1253 out_printf(out, "\tg_return_if_fail (");
1255 out_printf(out, "\tg_return_val_if_fail (");
1256 switch(ch->chtype) {
1258 out_printf(out, "%s != NULL", fa->name);
1259 checked_null = TRUE;
1262 s = make_pre_macro(fa->atype->name, "IS");
1264 out_printf(out, "%s (%s)", s, fa->name);
1266 /* if not check null, null may be valid */
1267 out_printf(out, "!(%s) || %s (%s)", fa->name,
1272 out_printf(out, "%s < %s", fa->name, ch->number);
1275 out_printf(out, "%s > %s", fa->name, ch->number);
1278 out_printf(out, "%s <= %s", fa->name, ch->number);
1281 out_printf(out, "%s >= %s", fa->name, ch->number);
1284 out_printf(out, "%s == %s", fa->name, ch->number);
1287 out_printf(out, "%s != %s", fa->name, ch->number);
1291 out_printf(out, ");\n");
1293 out_printf(out, ", (");
1294 print_type(out, m->mtype, TRUE);
1295 out_printf(out, ")%s);\n",
1296 m->onerror?m->onerror:"0");
1302 print_preconditions(Method *m)
1306 for(li=m->args;li;li=g_list_next(li)) {
1307 FuncArg *fa = li->data;
1309 print_checks(m, fa);
1312 out_addline_outfile(out);
1316 print_destructor(char *self_id, Variable *v)
1320 if(v->destructor == NULL)
1323 if(v->scope == PRIVATE_SCOPE)
1324 root = g_strconcat(self_id, "->_priv", NULL);
1326 root = g_strdup(self_id);
1328 if(v->destructor_simple) {
1329 if(v->destructor_line > 0)
1330 out_addline_infile(out, v->destructor_line);
1332 out_printf(out, "\tif(%s->%s) "
1333 "((*(void (*)(void *))%s)) (%s->%s);\n",
1334 root, v->id, v->destructor, root, v->id);
1336 if(v->destructor_line > 0)
1337 out_addline_outfile(out);
1339 out_printf(out, "#define VAR (%s->%s)\n", root, v->id);
1340 out_printf(out, "\t{\n\t%s *self G_GNUC_UNUSED = %s;\n",
1342 if(v->destructor_line > 0)
1343 out_addline_infile(out, v->destructor_line);
1345 out_printf(out, "\t%s}\n", v->destructor);
1347 if(v->destructor_line > 0)
1348 out_addline_outfile(out);
1349 out_printf(out, "#undef VAR\n");
1355 /* put in code if it's needed */
1357 put_in_gen_code(Method *m)
1359 if(m->method == OVERRIDE_METHOD &&
1360 strcmp(m->id, "finalize")==0) {
1361 if(privates > 0 || destructors > 0) {
1362 out_printf(out, "\t%s *___self = %s (%s);\n",
1363 typebase, macrobase,
1364 ((FuncArg *)m->args->data)->name);
1366 if(destructors > 0) {
1368 for(li = ((Class *)class)->nodes;
1372 Variable *v = (Variable *)n;
1373 if(n->type == VARIABLE_NODE &&
1374 v->scope != CLASS_SCOPE)
1375 print_destructor("___self", v);
1379 out_printf(out, "\tg_free (___self->_priv);\n"
1380 "\t___self->_priv = NULL;\n",
1382 ((FuncArg *)m->args->data)->name,
1384 ((FuncArg *)m->args->data)->name);
1390 print_method_body(Method *m, int pre)
1392 out_printf(out, "{\n");
1394 print_preconditions(m);
1398 /* Note: the trailing }'s are on one line, this is so
1399 that we get the no return warning correctly and point to
1400 the correct line in the .gob file, yes this is slightly
1401 ugly in the .c file, but that is not supposed to be
1402 human readable anyway. */
1404 out_printf(out, "{\n");
1406 out_addline_infile(out, m->ccode_line);
1407 out_printf(out, "\t%s}", m->cbuf);
1410 out_printf(out, "}\n");
1413 out_addline_outfile(out);
1417 put_signal_args(Method *m)
1421 for(ali = m->gtktypes->next, li=m->args->next;
1423 li=li->next, ali=ali->next) {
1424 FuncArg *fa = li->data;
1425 const char *cast = get_cast(ali->data, FALSE);
1426 /* we should have already proved before that
1427 the we know all the types */
1430 out_printf(out, ",\n\t\t(%s)%s", cast,
1436 get_arg_names_for_macro(Method *m)
1440 GString *gs = g_string_new(NULL);
1442 for(li=m->args;li;li=g_list_next(li)) {
1443 FuncArg *arg = li->data;
1444 g_string_sprintfa(gs, "%s___%s", p, arg->name);
1448 g_string_free(gs, FALSE);
1453 put_method(Method *m)
1455 char *s, *args, *doc;
1457 is_void = (strcmp(m->mtype->name, "void")==0 &&
1458 m->mtype->stars == 0);
1459 out_printf(out, "\n");
1460 doc = get_gtk_doc(m->id);
1462 out_printf(out, "%s", doc);
1466 case REGULAR_METHOD:
1468 out_addline_infile(out, m->line_no);
1469 if(m->scope == PRIVATE_SCOPE)
1470 print_method(out, "static ", "\n", "", " ", "\n",
1472 else /* PUBLIC, PROTECTED */
1473 print_method(out, "", "\n", "", " ", "\n",
1475 print_method_body(m, TRUE);
1477 case SIGNAL_FIRST_METHOD:
1478 case SIGNAL_LAST_METHOD:
1480 out_addline_infile(out, m->line_no);
1481 if(m->scope == PRIVATE_SCOPE)
1482 print_method(out, "static ", "\n", "", " ", "\n",
1484 else /* PUBLIC, PROTECTED */
1485 print_method(out, "", "\n", "", " ", "\n", m, FALSE, FALSE);
1486 out_addline_outfile(out);
1487 out_printf(out, "{\n");
1488 s = g_strdup(m->id);
1490 if(strcmp(m->mtype->name, "void")==0 &&
1491 m->mtype->stars==0) {
1492 print_preconditions(m);
1493 if(((FuncArg *)m->args->data)->name)
1494 out_printf(out, "\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1495 "\t\tobject_signals[%s_SIGNAL]",
1496 ((FuncArg *)m->args->data)->name, s);
1498 out_printf(out, ");\n}\n");
1500 out_printf(out, "\t");
1501 print_type(out, m->mtype, TRUE);
1502 out_printf(out, "return_val = (");
1503 print_type(out, m->mtype, TRUE);
1505 out_printf(out, ")(%s);\n", m->defreturn);
1507 out_printf(out, ")(%s);\n", m->onerror);
1509 out_printf(out, ")(0);\n");
1510 print_preconditions(m);
1511 out_printf(out, "\tgtk_signal_emit (GTK_OBJECT (%s),\n"
1512 "\t\tobject_signals[%s_SIGNAL]",
1513 ((FuncArg *)m->args->data)->name, s);
1515 out_printf(out, ",\n\t\t&return_val);\n"
1516 "\treturn return_val;\n}\n");
1522 out_addline_infile(out, m->line_no);
1523 print_method(out, "static ", "\n___real_", "", " ", "\n",
1525 print_method_body(m, FALSE);
1527 case VIRTUAL_METHOD:
1529 out_addline_infile(out, m->line_no);
1530 if(m->scope==PRIVATE_SCOPE)
1531 print_method(out, "static ", "\n", "", " ", "\n",
1533 else /* PUBLIC, PROTECTED */
1534 print_method(out, "", "\n", "", " ", "\n", m, FALSE, FALSE);
1535 out_addline_outfile(out);
1536 out_printf(out, "{\n"
1537 "\t%sClass *klass;\n", typebase);
1538 print_preconditions(m);
1539 out_printf(out, "\tklass = %s_CLASS(GTK_OBJECT(%s)->klass);\n\n"
1540 "\tif(klass->%s)\n",
1541 macrobase, ((FuncArg *)m->args->data)->name, m->id);
1542 if(strcmp(m->mtype->name, "void")==0 &&
1543 m->mtype->stars==0) {
1545 out_printf(out, "\t\t(*klass->%s)(%s", m->id,
1546 ((FuncArg *)m->args->data)->name);
1547 for(li=m->args->next;li;li=g_list_next(li)) {
1548 FuncArg *fa = li->data;
1549 out_printf(out, ",%s", fa->name);
1551 out_printf(out, ");\n}\n");
1554 out_printf(out, "\t\treturn (*klass->%s)(%s", m->id,
1555 ((FuncArg *)m->args->data)->name);
1556 for(li=m->args->next;li;li=g_list_next(li)) {
1557 FuncArg *fa = li->data;
1558 out_printf(out, ",%s", fa->name);
1560 out_printf(out, ");\n"
1563 print_type(out, m->mtype, TRUE);
1565 out_printf(out, ")(%s);\n}\n", m->defreturn);
1567 out_printf(out, ")(%s);\n}\n", m->onerror);
1569 out_printf(out, ")(0);\n}\n");
1575 out_addline_infile(out, m->line_no);
1576 print_method(out, "static ", "\n___real_", "", " ", "\n",
1578 print_method_body(m, FALSE);
1580 case OVERRIDE_METHOD:
1584 out_addline_infile(out, m->line_no);
1585 print_method(out, "static ", "\n", "", " ", "\n",
1587 s = replace_sep(m->otype, '_');
1589 args = get_arg_names_for_macro(m);
1591 out_printf(out, "#define PARENT_HANDLER(%s) \\\n"
1592 "\t{ if(%s_CLASS(parent_class)->%s) \\\n"
1593 "\t\t(* %s_CLASS(parent_class)->%s)(%s); }\n",
1594 args, s, m->id, s, m->id, args);
1596 out_printf(out, "#define PARENT_HANDLER(%s) \\\n"
1597 "\t((%s_CLASS(parent_class)->%s)? \\\n"
1598 "\t\t(* %s_CLASS(parent_class)->%s)(%s): \\\n"
1600 args, s, m->id, s, m->id, args);
1601 out_printf(out, "(");
1602 print_type(out, m->mtype, TRUE);
1603 out_printf(out, ")%s))\n",
1604 m->onerror?m->onerror:"0");
1608 print_method_body(m, TRUE);
1609 out_printf(out, "#undef PARENT_HANDLER\n");
1619 char *outfile, *outfileh, *outfileph;
1622 outfile = g_strconcat(filebase, ".c", NULL);
1624 outfile = g_strconcat(filebase, ".cc", NULL);
1625 if(no_touch_headers)
1626 outfileh = g_strconcat("#gob#", filebase, ".h#gob#", NULL);
1628 outfileh = g_strconcat(filebase, ".h", NULL);
1630 if((privates > 0 || protecteds > 0 ||
1631 private_header == PRIVATE_HEADER_ALWAYS) &&
1632 !private_header != PRIVATE_HEADER_NEVER)
1633 outfileph = g_strconcat(filebase, "-private.h", NULL);
1639 devnull = fopen("/dev/null", "w");
1641 g_error("Cannot open null device");
1647 out = fopen(outfile, "w");
1649 g_error("Cannot open outfile: %s", outfile);
1651 outh = fopen(outfileh, "w");
1653 g_error("Cannot open outfile: %s", outfileh);
1655 outph = fopen(outfileph, "w");
1657 g_error("Cannot open outfile: %s", outfileh);
1663 put_argument_nongnu_wrappers(Class *c)
1670 for(li=c->nodes;li;li=g_list_next(li)) {
1672 Argument *a = (Argument *)n;
1676 if(n->type != ARGUMENT_NODE)
1679 aname = g_strdup(a->name);
1683 cast = get_type(a->atype, TRUE);
1685 cast = g_strdup(get_cast(a->gtktype, TRUE));
1689 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1690 "\"%s\",(%s)(arg)\n",
1691 macrobase, aname, a->name, cast);
1693 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1694 "\"%s\",(%s*)(arg)\n",
1695 macrobase, aname, a->name, cast);
1698 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1700 macrobase, aname, a->name);
1702 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1704 macrobase, aname, a->name);
1712 put_argument_gnu_wrappers(Class *c)
1719 for(li=c->nodes;li;li=g_list_next(li)) {
1721 Argument *a = (Argument *)n;
1724 if(n->type != ARGUMENT_NODE)
1726 s = g_strdup(a->name);
1729 cast = get_type(a->atype, TRUE);
1731 cast = g_strdup(get_cast(a->gtktype, TRUE));
1734 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1735 "\"%s\",({%sz = (arg); z;})\n",
1736 macrobase, s, a->name, cast);
1738 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1739 "\"%s\",({%s*z = (arg); z;})\n",
1740 macrobase, s, a->name, cast);
1743 out_printf(outh, "#define %s_ARG_%s(arg) \t"
1745 macrobase, s, a->name);
1747 out_printf(outh, "#define %s_GET_ARG_%s(arg)\t"
1749 macrobase, s, a->name);
1757 print_ccode_block(CCode *cc)
1760 switch(cc->cctype) {
1762 /* HT code is printed exactly like normal header
1763 code but is printed before */
1766 out_printf(fp, "\n");
1769 /* AT code is printed exactly like normal 'all'
1770 code but is printed before */
1773 out_printf(outph, "\n");
1774 out_printf(outph, "%s\n", cc->cbuf);
1775 out_addline_infile(outph, cc->line_no);
1776 out_addline_outfile(outph);
1778 out_printf(outh, "\n");
1779 out_printf(outh, "%s\n", cc->cbuf);
1781 out_printf(fp, "\n");
1782 out_addline_infile(fp, cc->line_no);
1787 out_printf(fp, "\n");
1788 out_addline_infile(fp, cc->line_no);
1795 out_printf(fp, "\n");
1796 out_addline_infile(fp, cc->line_no);
1799 out_printf(fp, "%s\n", cc->cbuf);
1800 if(cc->cctype == C_CCODE ||
1801 cc->cctype == A_CCODE ||
1802 cc->cctype == AT_CCODE ||
1803 cc->cctype == PH_CCODE)
1804 out_addline_outfile(fp);
1808 print_class_block(Class *c)
1812 gboolean printed_private = FALSE;
1815 out_printf(out, "/* utility types we may need */\n");
1816 if(special_array[SPECIAL_2POINTER])
1817 out_printf(out, "typedef struct { "
1818 "gpointer a; gpointer b; "
1819 "} ___twopointertype;\n");
1820 if(special_array[SPECIAL_3POINTER])
1821 out_printf(out, "typedef struct { "
1822 "gpointer a; gpointer b; "
1824 "} ___threepointertype;\n");
1825 if(special_array[SPECIAL_INT_POINTER])
1826 out_printf(out, "typedef struct { "
1827 "gint a; gpointer b; "
1828 "} ___intpointertype;\n");
1829 out_printf(out, "\n");
1832 out_printf(outh, "\n/*\n"
1833 " * Type checking and casting macros\n"
1835 out_printf(outh, "#define %s\t"
1836 "(%s_get_type())\n",
1837 macrotype, funcbase);
1838 out_printf(outh, "#define %s(obj)\t"
1839 "GTK_CHECK_CAST((obj), %s_get_type(),%s)\n",
1840 macrobase, funcbase, typebase);
1841 out_printf(outh, "#define %s_CLASS(klass)\t"
1842 "GTK_CHECK_CLASS_CAST((klass),%s_get_type(),%sClass)\n",
1843 macrobase, funcbase, typebase);
1844 out_printf(outh, "#define %s(obj)\t"
1845 "GTK_CHECK_TYPE((obj),%s_get_type ())\n\n",
1848 out_printf(out, "/* self casting macros */\n");
1849 out_printf(out, "#define SELF(x) %s(x)\n", macrobase);
1850 out_printf(out, "#define IS_SELF(x) %s(x)\n", macrois);
1851 out_printf(out, "#define SELF_CLASS(x) %s_CLASS(x)\n\n", macrobase);
1854 out_printf(outh, "\n/* Private structure type */\n");
1855 out_printf(outh, "typedef struct _%sPrivate %sPrivate;\n",
1856 typebase, typebase);
1859 out_printf(outh, "\n/*\n"
1860 " * Main object structure\n"
1862 s = replace_sep(c->otype, '_');
1864 out_printf(outh, "#ifndef __TYPEDEF_%s__\n"
1865 "#define __TYPEDEF_%s__\n", s, s);
1867 out_printf(outh, "typedef struct _%s %s;\n"
1868 "#endif\n", typebase, typebase);
1869 out_printf(outh, "struct _%s {\n\t%s __parent__;\n",
1870 typebase, ptypebase);
1871 for(l=c->nodes;l;l=g_list_next(l)) {
1872 static gboolean printed_public = FALSE;
1874 Variable *v = (Variable *)n;
1875 if(n->type == VARIABLE_NODE &&
1876 v->scope == PUBLIC_SCOPE) {
1877 if(!printed_public) {
1878 out_printf(outh, "\t/*< public >*/\n");
1879 printed_public = TRUE;
1881 put_variable((Variable *)n, outh);
1884 /* put protecteds always AFTER publics */
1885 for(l=c->nodes;l;l=g_list_next(l)) {
1887 Variable *v = (Variable *)n;
1888 if(n->type == VARIABLE_NODE &&
1889 v->scope == PROTECTED_SCOPE) {
1890 if(!printed_private) {
1891 out_printf(outh, "\t/*< private >*/\n");
1892 printed_private = TRUE;
1894 put_variable((Variable *)n, outh);
1898 if(!printed_private)
1899 out_printf(outh, "\t/*< private >*/\n");
1900 out_printf(outh, "\t%sPrivate *_priv;\n", typebase);
1902 out_printf(outh, "};\n");
1907 /* if we are to stick this into the private
1908 header, if not stick it directly into the
1915 out_printf(outfp, "struct _%sPrivate {\n",
1917 for(l=c->nodes;l;l=l->next) {
1919 Variable *v = (Variable *)n;
1920 if(n->type == VARIABLE_NODE &&
1921 v->scope == PRIVATE_SCOPE) {
1922 out_addline_infile(outfp, v->line_no);
1923 put_variable(v, outfp);
1926 out_addline_outfile(outfp);
1927 out_printf(outfp, "};\n");
1930 out_printf(outh, "\n/*\n"
1931 " * Class definition\n"
1933 out_printf(outh, "typedef struct _%sClass %sClass;\n",
1934 typebase, typebase);
1936 "struct _%sClass {\n\t%sClass __parent__;\n",
1937 typebase, ptypebase);
1938 for(l=c->nodes;l;l=g_list_next(l)) {
1940 if(n->type == METHOD_NODE)
1941 put_vs_method((Method *)n);
1943 /* put class scope variables */
1944 for(l=c->nodes;l;l=g_list_next(l)) {
1946 Variable *v = (Variable *)n;
1947 if(n->type == VARIABLE_NODE &&
1948 v->scope == CLASS_SCOPE)
1949 put_variable((Variable *)n, outh);
1951 out_printf(outh, "};\n\n");
1953 out_printf(out, "/* here are local prototypes */\n");
1955 out_printf(out, "static void ___object_set_arg "
1956 "(GtkObject *object, GtkArg *arg, "
1958 "static void ___object_get_arg "
1959 "(GtkObject *object, GtkArg *arg, "
1960 "guint arg_id);\n");
1963 out_printf(outh, "\n/*\n"
1964 " * Public methods\n"
1967 out_printf(outh, "guint\t%s_get_type\t(void);\n", funcbase);
1968 for(l=c->nodes;l;l=g_list_next(l)) {
1970 if(n->type == METHOD_NODE) {
1971 put_pub_method((Method *)n);
1972 put_prot_method((Method *)n);
1973 put_priv_method_prot((Method *)n);
1977 /* this idea is less and less apealing to me */
1979 if(!no_signal_connect) {
1981 out_printf(outh, "\n/*\n"
1982 " * Signal connection methods\n"
1986 for(l=c->nodes;l;l=g_list_next(l)) {
1988 if(n->type == METHOD_NODE)
1989 put_signal_connect((Method *)n);
1995 /* argument wrapping macros */
1996 if(arguments>0 && !no_gnu) {
1997 out_printf(outh, "\n/*\n"
1998 " * Argument wrapping macros\n"
2000 out_printf(outh, "#ifdef __GNUC__\n");
2001 put_argument_gnu_wrappers(c);
2002 out_printf(outh, "#else /* __GNUC__ */\n");
2003 put_argument_nongnu_wrappers(c);
2004 out_printf(outh, "#endif /* __GNUC__ */\n\n");
2005 } else if(arguments>0 && no_gnu) {
2006 out_printf(outh, "\n/*\n"
2007 " * Argument wrapping macros\n"
2009 put_argument_nongnu_wrappers(c);
2013 for(l=c->nodes;l;l=g_list_next(l)) {
2015 if(n->type == METHOD_NODE)
2016 add_signal_prots((Method *)n);
2024 if(any_method_to_alias(c)) {
2026 make_method_nongnu_aliases(c);
2028 out_printf(out, "\n#ifdef __GNUC__\n");
2029 make_method_gnu_aliases(c);
2030 out_printf(out, "#else /* __GNUC__ */\n");
2031 make_method_nongnu_aliases(c);
2032 out_printf(out, "#endif /* __GNUC__ */\n\n");
2036 out_printf(out, "/* a macro for creating a new object of our type */\n");
2038 "#define GET_NEW ((%s *)gtk_type_new(%s_get_type()))\n\n",
2039 typebase, funcbase);
2044 add_getset_arg(c, TRUE);
2045 add_getset_arg(c, FALSE);
2048 for(l=c->nodes;l;l=g_list_next(l)) {
2050 if(n->type == METHOD_NODE)
2051 put_method((Method *)n);
2054 add_bad_hack_to_avoid_unused_warnings(c);
2058 print_version_macros(void)
2060 int major=0, minor=0, pl=0;
2061 sscanf(VERSION, "%d.%d.%d", &major, &minor, &pl);
2063 out_printf(out, "#define GOB_VERSION_MAJOR %d\n", major);
2064 out_printf(out, "#define GOB_VERSION_MINOR %d\n", minor);
2065 out_printf(out, "#define GOB_VERSION_PATCHLEVEL %d\n\n", pl);
2069 print_file_comments(void)
2073 out_printf(outh, "/* Generated by GOB (v%s)"
2074 " (do not edit directly) */\n\n", VERSION);
2076 out_printf(outph, "/* Generated by GOB (v%s)"
2077 " (do not edit directly) */\n\n", VERSION);
2078 out_printf(out, "/* Generated by GOB (v%s) on %s"
2079 " (do not edit directly) */\n\n",
2080 VERSION, ctime(&curtime));
2084 print_includes(void)
2086 gboolean found_header;
2089 p = g_strconcat(filebase, ".h", NULL);
2090 found_header = TRUE;
2091 if(!g_list_find_custom(include_files, p, (GCompareFunc)strcmp)) {
2092 out_printf(out, "#include \"%s.h\"\n\n", filebase);
2093 found_header = FALSE;
2097 /* if we are creating a private header see if it was included */
2099 p = g_strconcat(filebase, "-private.h", NULL);
2100 if(!g_list_find_custom(include_files, p, (GCompareFunc)strcmp)) {
2101 out_printf(out, "#include \"%s-private.h\"\n\n",
2105 "Implicit private header include "
2107 "\tsource file, while public "
2108 "header is at a custom location, "
2110 "\texplicitly include "
2111 "the private header below the "
2119 print_header_prefixes(void)
2123 p = replace_sep(((Class *)class)->otype, '_');
2125 out_printf(outh, "#ifndef __%s_H__\n#define __%s_H__\n\n", p, p);
2127 out_printf(outph, "#ifndef __%s_PRIVATE_H__\n"
2128 "#define __%s_PRIVATE_H__\n\n"
2129 "#include \"%s.h\"\n\n", p, p, filebase);
2133 out_printf(outh, "#ifdef __cplusplus\n"
2135 "#endif /* __cplusplus */\n\n");
2137 out_printf(outph, "#ifdef __cplusplus\n"
2139 "#endif /* __cplusplus */\n\n");
2144 print_header_postfixes(void)
2147 out_printf(outh, "\n#ifdef __cplusplus\n"
2149 "#endif /* __cplusplus */\n");
2150 out_printf(outh, "\n#endif\n");
2153 out_printf(outph, "\n#ifdef __cplusplus\n"
2155 "#endif /* __cplusplus */\n");
2156 out_printf(outph, "\n#endif\n");
2165 /* print the AT_CCODE blocks */
2166 for(li=nodes;li;li=g_list_next(li)) {
2167 Node *node = li->data;
2168 if(node->type == CCODE_NODE) {
2169 CCode *cc = (CCode *)node;
2170 if(cc->cctype==AT_CCODE)
2171 print_ccode_block((CCode *)node);
2177 print_header_top(void)
2181 /* mandatory include */
2182 out_printf(outh, "#include <gtk/gtk.h>\n\n");
2184 /* print the HT_CCODE blocks */
2185 for(li=nodes;li;li=g_list_next(li)) {
2186 Node *node = li->data;
2187 if(node->type == CCODE_NODE) {
2188 CCode *cc = (CCode *)node;
2189 if(cc->cctype==HT_CCODE)
2190 print_ccode_block((CCode *)node);
2196 generate_outfiles(void)
2200 print_file_comments();
2206 print_header_prefixes();
2208 print_version_macros();
2212 for(li=nodes;li;li=g_list_next(li)) {
2213 Node *node = li->data;
2214 if(node->type == CCODE_NODE) {
2215 CCode *cc = (CCode *)node;
2216 if(cc->cctype!=HT_CCODE)
2217 print_ccode_block((CCode *)node);
2218 } else if(node->type == CLASS_NODE) {
2219 print_class_block((Class *)node);
2221 g_assert_not_reached();
2224 print_header_postfixes();
2230 fprintf(stderr, "Gob version %s\n\n", VERSION);
2231 fprintf(stderr, "Options:\n"
2232 "\t--help,-h,-? Display this help\n"
2233 "\t--version Display version\n"
2234 "\t--exit-on-warn,-w Exit with an error on warnings\n"
2235 "\t--no-exit-on-warn Don't exit on warnings [default]\n"
2236 "\t--for-cpp Create C++ files\n"
2237 "\t--no-extern-c Never print extern \"C\" into the "
2239 "\t--no-gnu Never use GNU extentions\n"
2240 "\t--no-touch-headers Don't touch headers unless they "
2242 "\t--always-private-header Always create a private header "
2244 "\t even if it would be empty "
2246 "\t--ondemand-private-header Create private header only when "
2248 "\t--no-private-header Don't create a private header, "
2250 "\t structure and protected "
2251 "prototypes inside c file\n"
2252 "\t--no-write,-n Don't write output files, just "
2254 "\t--no-lines Don't print '#line' to output\n");
2258 parse_options(int argc, char *argv[])
2261 int got_file = FALSE;
2262 int no_opts = FALSE;
2266 for(i=1;i<argc;i++) {
2267 if(no_opts || argv[i][0]!='-') {
2270 fprintf(stderr, "Specify only one file!\n");
2276 } else if(strcmp(argv[i], "--help")==0) {
2279 } else if(strcmp(argv[i], "--version")==0) {
2280 fprintf(stderr, "Gob version %s\n", VERSION);
2282 } else if(strcmp(argv[i], "--exit-on-warn")==0) {
2283 exit_on_warn = TRUE;
2284 } else if(strcmp(argv[i], "--no-exit-on-warn")==0) {
2285 exit_on_warn = FALSE;
2286 } else if(strcmp(argv[i], "--for-cpp")==0) {
2288 } else if(strcmp(argv[i], "--no-touch-headers")==0) {
2289 no_touch_headers = TRUE;
2290 } else if(strcmp(argv[i], "--ondemand-private-header")==0) {
2291 private_header == PRIVATE_HEADER_ONDEMAND;
2292 } else if(strcmp(argv[i], "--always-private-header")==0) {
2293 private_header == PRIVATE_HEADER_ALWAYS;
2294 } else if(strcmp(argv[i], "--no-private-header")==0) {
2295 private_header == PRIVATE_HEADER_NEVER;
2296 } else if(strcmp(argv[i], "--no-gnu")==0) {
2298 } else if(strcmp(argv[i], "--no-extern-c")==0) {
2300 } else if(strcmp(argv[i], "--no-write")==0) {
2302 } else if(strcmp(argv[i], "--no-lines")==0) {
2304 } else if(strcmp(argv[i], "--")==0) {
2305 /*further arguments are files*/
2307 } else if(strncmp(argv[i], "--", 2)==0) {
2308 /*unknown long option*/
2309 fprintf(stderr, "Unknown option '%s'!\n", argv[i]);
2313 /*by now we know we have a string starting with
2314 - which is a short option string*/
2315 char *p = argv[i]+1;
2316 for(p=argv[i]+1; *p; p++) {
2330 "Unknown option '%c'!\n", *p);
2339 /* this is a somewhat ugly hack, but it appears to work */
2341 compare_and_move_header(void)
2343 char *hfnew = g_strconcat("#gob#", filebase, ".h#gob#", NULL);
2344 char *hf = g_strconcat(filebase, ".h", NULL);
2346 if(stat(hf, &s)==0) {
2348 s = g_strdup_printf("cmp '%s' '%s' > /dev/null", hf, hfnew);
2350 if(unlink(hfnew)!=0)
2352 "Can't remove new header file", 0);
2360 print_error(FALSE, "Can't remove old header file", 0);
2362 if(rename(hfnew, hf)!=0)
2363 print_error(FALSE, "Can't rename new header file", 0);
2369 main(int argc, char *argv[])
2371 parse_options(argc, argv);
2374 yyin = fopen(filename, "r");
2376 fprintf(stderr, "Error: can't open file '%s'\n",
2385 g_error("Parsing errors, quitting");
2387 print_error(FALSE, " no class defined", 0);
2390 exit_on_error = FALSE;
2392 signals = count_signals((Class *)class);
2393 arguments = count_arguments((Class *)class);
2394 overrides = count_overrides((Class *)class);
2395 privates = count_privates((Class *)class);
2396 protecteds = count_protecteds((Class *)class);
2397 destructors = count_destructors((Class *)class);
2398 initializers = count_initializers((Class *)class);
2401 make_inits((Class *)class);
2403 make_finalize((Class *)class);
2404 check_bad_symbols((Class *)class);
2405 check_duplicate_symbols((Class *)class);
2406 check_duplicate_signals_args((Class *)class);
2407 check_public_new((Class *)class);
2408 check_vararg((Class *)class);
2409 check_firstarg((Class *)class);
2410 check_nonvoidempty((Class *)class);
2411 check_signal_args((Class *)class);
2412 check_argument_types((Class *)class);
2414 exit_on_error = TRUE;
2419 any_special = setup_special_array((Class *)class, special_array);
2423 generate_outfiles();
2434 if(no_touch_headers && !no_write)
2435 compare_and_move_header();