]> git.draconx.ca Git - gob-dx.git/blob - src/main.c
e1cfe4b9313c425a70cdd14f3b30988638c2f398
[gob-dx.git] / src / main.c
1 /* GOB C Preprocessor
2  * Copyright (C) 1999,2000 the Free Software Foundation.
3  * Copyright (C) 2000 Eazel, Inc.
4  * Copyright (C) 2001-2004 George (Jiri) Lebl
5  *
6  * Author: George (Jiri) Lebl
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the  Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21  * USA.
22  */
23
24 #include "config.h"
25 #include <glib.h>
26 #include <time.h>
27 #include <stdio.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <sys/stat.h>
33
34 #include "treefuncs.h"
35 #include "parse.h"
36 #include "out.h"
37 #include "util.h"
38 #include "checks.h"
39
40 #include "main.h"
41
42 char *filename = NULL;
43
44 int yyparse(void);
45
46 extern int yydebug;
47 extern FILE * yyin;
48 extern Node *class;
49 extern GList *nodes;
50 extern GList *enums;
51
52 extern GList *include_files;
53
54 extern GHashTable *gtk_doc_hash;
55
56 char *filebase;
57 char *fullfilebase;
58 static char *outfilebase;
59 static char *outfilehbase;
60 static char *outfilephbase;
61 static char *funcbase;
62 static char *pfuncbase;
63 static char *macrobase;
64 static char *macrois;
65 static char *pmacrois;
66 static char *macrotype;
67 static char *pmacrotype;
68 static char *typebase;
69 static char *ptypebase;
70
71 char *output_dir = NULL;
72
73 char file_sep = '-';
74
75 static int signals = 0; /* number of signals */
76 static int set_properties = 0; /* number of named (set) properties */
77 static int get_properties = 0; /* number of named (get) properties */
78 static int overrides = 0; /* number of override methods */
79 static int privates = 0; /* number of private data members */
80 static int protecteds = 0; /* number of protected methods */
81 static int unreftors = 0; /* number of variable unreffing destructors */
82 static int destructors = 0; /* number of variable non-unreffing destructors */
83 static int initializers = 0; /* number of variable initializers */
84 static int glade_widgets = 0; /* number of glade widgets */
85 static gboolean overrode_get_type = FALSE; /* provided your won _get_type */
86
87 static gboolean made_aliases = FALSE;  /* if we made any shorthand aliases
88                                           and need the REALLY UGLY HACK to
89                                           avoid warnings */
90
91 /* the special variable types we need to define */
92 static gboolean special_array[SPECIAL_LAST] = {0};
93 static gboolean any_special = FALSE;
94
95 static gboolean need_dispose = FALSE;
96 static Method * dispose_handler = NULL;
97
98 static gboolean need_finalize = FALSE;
99 static Method * finalize_handler = NULL;
100
101 FILE *out = NULL;
102 FILE *outh = NULL;
103 FILE *outph = NULL;
104
105 gboolean no_touch = FALSE;
106 gboolean no_touch_headers = FALSE;
107 gboolean for_cpp = FALSE;
108 gboolean no_gnu = FALSE;
109 gboolean exit_on_warn = FALSE;
110 gboolean exit_on_error = TRUE;
111 gboolean got_error = FALSE;
112 gint private_header = PRIVATE_HEADER_ONDEMAND;
113 gboolean no_extern_c = FALSE;
114 gboolean no_write = FALSE;
115 gboolean no_lines = FALSE;
116 gboolean no_self_alias = FALSE;
117 gboolean always_private_struct = FALSE;
118 gint prealloc = 0;
119
120 gboolean use_m4 = FALSE; /* preprocess sources with m4 */
121 gboolean use_m4_clean = FALSE; /* preprocess sources with m4, no m4 flags */
122 char *m4_commandline = NULL;
123 #define M4_INCLUDE_DIR  PKGDATADIR "/m4"
124 #define M4_BASE_FILENAME "gobm4.m4"
125 #define M4_FLAGS "-P -s -I" M4_INCLUDE_DIR  " -DGOBM4_GOB_VERSION=" VERSION " " M4_BASE_FILENAME
126 #define M4_COMMANDLINE "m4"
127
128 int method_unique_id = 1;
129
130 static void
131 make_bases (void)
132 {
133         filebase = replace_sep (((Class *)class)->otype, file_sep);
134         gob_strdown (filebase);
135
136         if (output_dir != NULL &&
137             output_dir[0] != '\0') {
138                 fullfilebase = g_build_filename (output_dir, filebase, NULL);
139         } else {
140                 fullfilebase = g_strdup (filebase);
141         }
142
143         funcbase = replace_sep (((Class *)class)->otype, '_');
144         gob_strdown (funcbase);
145
146         pfuncbase = replace_sep (((Class *)class)->ptype, '_');
147         gob_strdown (pfuncbase);
148
149         macrobase = replace_sep (((Class *)class)->otype, '_');
150         gob_strup (macrobase);
151         
152         macrois = make_pre_macro (((Class *)class)->otype, "IS");
153         pmacrois = make_pre_macro (((Class *)class)->ptype, "IS");
154
155         macrotype = make_pre_macro (((Class *)class)->otype, "TYPE");
156         pmacrotype = make_pre_macro (((Class *)class)->ptype, "TYPE");
157
158         typebase = remove_sep (((Class *)class)->otype);
159
160         ptypebase = remove_sep (((Class *)class)->ptype);
161 }
162
163 static char *
164 get_gtk_doc (const char *id)
165 {
166         char *val;
167
168         if(!gtk_doc_hash)
169                 return NULL;
170
171         val = g_hash_table_lookup(gtk_doc_hash, id);
172         if(val)
173                 return g_strdup_printf("/**\n * %s_%s:\n%s **/\n",
174                                        funcbase, id, val);
175         val = g_hash_table_lookup(gtk_doc_hash, id);
176         if(val)
177                 return g_strdup_printf("/**\n * %s_%s:\n%s **/\n",
178                                        funcbase, id, val);
179         return NULL;
180 }
181
182 static void
183 print_type(FILE *fp, const Type *t, gboolean postfix_to_stars)
184 {
185         char *s;
186
187         s = get_type(t, postfix_to_stars);
188         out_printf(fp, "%s", s); 
189         g_free(s);
190 }
191
192
193 static void
194 print_method (FILE *fp,
195               const char *typeprefix,
196               const char *nameprefix,
197               const char *subnameprefix,
198               const char *namepostfix,
199               const char *afterargs,
200               const char *postfix,
201               const Method *m,
202               gboolean one_arg_per_line,
203               gboolean no_funcbase,
204               gboolean kill_underscore,
205               gboolean first_unused,
206               gboolean fake_names)
207 {
208         GList *li;
209         const char *id;
210
211         out_printf(fp, "%s", typeprefix); 
212         print_type(fp, m->mtype, TRUE);
213
214         id = m->id;
215
216         if(no_funcbase)
217                 out_printf(fp, "%s%s%s%s(",
218                            nameprefix, subnameprefix, id, namepostfix); 
219         else
220                 out_printf(fp, "%s%s_%s%s%s(",
221                            nameprefix, funcbase, subnameprefix, id,
222                            namepostfix); 
223         
224         if(m->args) {
225                 for(li=m->args; li; li=g_list_next(li)) {
226                         FuncArg *arg = li->data;
227                         const char *unused = "";
228
229                         if ( ! no_gnu &&
230                              ! for_cpp && /* g++ has a cow with this */
231                             li == m->args &&
232                             first_unused) {
233                                 unused = " G_GNUC_UNUSED";
234                         }
235
236                         print_type(fp, arg->atype, FALSE);
237                         if (fake_names)
238                                 out_printf (fp, "___fake___");
239                         if(li->next)
240                                 out_printf(fp, "%s%s%s,%s", arg->name,
241                                            arg->atype->postfix ?
242                                            arg->atype->postfix : "",
243                                            unused,
244                                            one_arg_per_line ? "\n\t\t\t\t\t" : " ");
245                         else
246                                 out_printf(fp, "%s%s%s", arg->name,
247                                            arg->atype->postfix ?
248                                            arg->atype->postfix : "",
249                                            unused); 
250                 }
251                 if(m->vararg)
252                         out_printf(fp, ",%s...",
253                                    one_arg_per_line ? "\n\t\t\t\t\t" : " "); 
254         } else {
255                 out_printf(fp, "void"); 
256         }
257         out_printf(fp, "%s)%s", afterargs, postfix); 
258 }
259
260 static gboolean
261 any_method_to_alias(Class *c)
262 {
263         GList *li;
264         
265         for(li=c->nodes;li;li=g_list_next(li)) {
266                 Node *node = li->data;
267                 if(node->type == METHOD_NODE) {
268                         Method *m = (Method *)node;
269                         
270                         if(m->method == INIT_METHOD ||
271                            m->method == CLASS_INIT_METHOD ||
272                            m->method == OVERRIDE_METHOD)
273                                 continue;
274
275                         return TRUE;
276                 }
277         }
278         return FALSE;
279 }
280
281
282 static void
283 make_method_aliases (Class *c)
284 {
285         GList *li;
286         
287         for(li = c->nodes; li != NULL; li = li->next) {
288                 Node *node = li->data;
289                 if(node->type == METHOD_NODE) {
290                         Method *m = (Method *)node;
291                         
292                         if(m->method == INIT_METHOD ||
293                            m->method == CLASS_INIT_METHOD ||
294                            m->method == OVERRIDE_METHOD)
295                                 continue;
296
297                         out_printf (out, "#define self_%s %s_%s\n",
298                                     m->id,
299                                     funcbase,
300                                     m->id);
301                 }
302         }
303 }
304
305 static void
306 add_bad_hack_to_avoid_unused_warnings(const Class *c)
307 {
308         GList *li;
309
310         /* if we haven't had any methods, just return */
311         if( ! made_aliases)
312                 return;
313         
314         if( ! no_gnu)
315                 out_printf(out, "\n\n#if (!defined __GNUC__) || (defined __GNUC__ && defined __STRICT_ANSI__)\n");
316         out_printf(out,
317                    "/*REALLY BAD HACK\n"
318                    "  This is to avoid unused warnings if you don't call\n"
319                    "  some method.  I need to find a better way to do\n"
320                    "  this, not needed in GCC since we use some gcc\n"
321                    "  extentions to make saner, faster code */\n"
322                    "static void\n"
323                    "___%s_really_bad_hack_to_avoid_warnings(void)\n"
324                    "{\n", funcbase);
325         out_printf(out, "\t((void (*)(void))GET_NEW_VARG)();\n");
326         for(li=c->nodes;li;li=g_list_next(li)) {
327                 Node *node = li->data;
328                 if(node->type == METHOD_NODE) {
329                         Method *m = (Method *)node;
330                         
331                         if(m->method == INIT_METHOD ||
332                            m->method == CLASS_INIT_METHOD ||
333                            m->method == OVERRIDE_METHOD)
334                                 continue;
335
336                         /* in C++ mode we don't alias new */
337                         if(for_cpp && strcmp(m->id, "new")==0)
338                                 continue;
339
340                         out_printf(out, "\t((void (*)(void))self_%s)();\n", m->id);
341                 }
342         }
343         out_printf(out, "\t___%s_really_bad_hack_to_avoid_warnings();\n",
344                    funcbase);
345         if(!no_gnu)
346                 out_printf(out, "}\n#endif /* !__GNUC__ || (__GNUC__ && __STRICT_ANSI__) */\n\n");
347         else
348                 out_printf(out, "}\n\n");
349 }
350
351 static void
352 put_variable(const Variable *v, FILE *fp)
353 {
354         out_printf(fp, "\t");
355         print_type(fp, v->vtype, FALSE);
356         out_printf(fp, "%s%s;", v->id,
357                    v->vtype->postfix?
358                    v->vtype->postfix:""); 
359         if(v->scope == PROTECTED_SCOPE)
360                 out_printf(fp, " /* protected */");
361         out_printf(fp, "\n");
362 }
363
364 static void
365 put_vs_method(const Method *m)
366 {
367         if(m->method != SIGNAL_LAST_METHOD &&
368            m->method != SIGNAL_FIRST_METHOD &&
369            m->method != VIRTUAL_METHOD)
370                 return;
371
372         /* if a signal mark it as such */
373         if(m->method != VIRTUAL_METHOD)
374                 print_method(outh, "\t/*signal*/", "(* ", "", ") ", "", ";\n",
375                              m, FALSE, TRUE, TRUE, FALSE, FALSE);
376         else
377                 print_method(outh, "\t", "(* ", "", ") ", "", ";\n",
378                              m, FALSE, TRUE, TRUE, FALSE, FALSE);
379 }
380
381 static void
382 put_pub_method(const Method *m)
383 {
384         if(m->scope != PUBLIC_SCOPE)
385                 return;
386
387         print_method(outh, "", "\t", "", "\t", "", ";\n", m,
388                      TRUE, FALSE, TRUE, FALSE, FALSE);
389 }
390
391 static void
392 put_signal_macro (const Method *m, gboolean gnu)
393 {
394         if(m->method != SIGNAL_LAST_METHOD &&
395            m->method != SIGNAL_FIRST_METHOD)
396                 return;
397
398         if ( ! gnu) {
399                 /* connect */
400                 out_printf (outh, "#define %s_connect__%s(object,func,data)\t"
401                             "g_signal_connect(%s(object),\"%s\","
402                             "(GCallback)(func),(data))\n",
403                             funcbase, m->id, macrobase, m->id);
404
405                 /* connect_after */
406                 out_printf (outh, "#define %s_connect_after__%s(object,func,data)\t"
407                             "g_signal_connect_after(%s(object),\"%s\","
408                             "(GCallback)(func),(data))\n",
409                             funcbase, m->id, macrobase, m->id);
410
411                 /* connect_data */
412                 out_printf (outh, "#define %s_connect_data__%s"
413                             "(object,func,data,destroy_data,flags)\t"
414                             "g_signal_connect_data(%s(object),\"%s\","
415                             "(GCallback)(func),(data),(destroy_data),(GConnectFlags)(flags))\n",
416                             funcbase, m->id, macrobase, m->id);
417         } else {
418                 /* connect */
419                 out_printf (outh, "#define %s_connect__%s(object,func,data)\t"
420                             "g_signal_connect("
421                             "%s(__extension__ ({%s *___object = (object); ___object; })),"
422                             "\"%s\","
423                             "(GCallback) __extension__ ({",
424                             funcbase, m->id, macrobase, typebase, m->id);
425                 print_method (outh, "", "(* ___", "", ") ", ", gpointer ___data ",
426                               " = (func); ", m, FALSE, TRUE, TRUE, FALSE, TRUE);
427                 out_printf (outh, "___%s; }), (data))\n", m->id);
428
429                 /* connect_after */
430                 out_printf (outh, "#define %s_connect_after__%s(object,func,data)\t"
431                             "g_signal_connect_after("
432                             "%s(__extension__ ({%s *___object = (object); ___object; })),"
433                             "\"%s\","
434                             "(GCallback) __extension__ ({",
435                             funcbase, m->id, macrobase, typebase, m->id);
436                 print_method (outh, "", "(* ___", "", ") ", ", gpointer ___data ",
437                               " = (func); ", m, FALSE, TRUE, TRUE, FALSE, TRUE);
438                 out_printf (outh, "___%s; }), (data))\n", m->id);
439
440                 /* connect_data */
441                 out_printf (outh, "#define %s_connect_data__%s"
442                             "(object,func,data,destroy_data,flags)\t"
443                             "g_signal_connect_data("
444                             "%s(__extension__ ({%s *___object = (object); ___object; })),"
445                             "\"%s\","
446                             "(GCallback) __extension__ ({",
447                             funcbase, m->id, macrobase, typebase, m->id);
448                 print_method (outh, "", "(* ___", "", ") ", ", gpointer ___data ",
449                               " = (func); ", m, FALSE, TRUE, TRUE, FALSE, TRUE);
450                 out_printf (outh, "___%s; }), (data), (destroy_data), (GConnectFlags)(flags))\n", m->id);
451         }
452 }
453
454 static void
455 put_signal_macros (const Class *c, gboolean gnu)
456 {
457         const GList *li;
458
459         if (signals < 0)
460                 return;
461
462         for (li = c->nodes; li != NULL; li = li->next) {
463                 const Node *n = li->data;
464                 if (n->type == METHOD_NODE)
465                         put_signal_macro ((Method *)n, gnu);
466         }
467 }
468
469 static void
470 put_local_signal_macro (const Method *m)
471 {
472         if(m->method != SIGNAL_LAST_METHOD &&
473            m->method != SIGNAL_FIRST_METHOD)
474                 return;
475
476         /* connect */
477         out_printf (out, "#define self_connect__%s(object,func,data)\t"
478                     "%s_connect__%s((object),(func),(data))\n",
479                     m->id, funcbase, m->id);
480
481         /* connect_after */
482         out_printf (out, "#define self_connect_after__%s(object,func,data)\t"
483                     "%s_connect_after__%s((object),(func),(data))\n",
484                     m->id, funcbase, m->id);
485
486         /* connect_data */
487         out_printf (out, "#define self_connect_data__%s(object,func,data,destroy_data,flags)\t"
488                     "%s_connect_data__%s((object),(func),(data),(destroy_data),(flags))\n",
489                     m->id, funcbase, m->id);
490 }
491
492 static void
493 put_local_signal_macros (const Class *c)
494 {
495         const GList *li;
496
497         if (signals < 0)
498                 return;
499
500         for (li = c->nodes; li != NULL; li = li->next) {
501                 const Node *n = li->data;
502                 if (n->type == METHOD_NODE)
503                         put_local_signal_macro ((Method *)n);
504         }
505 }
506
507
508 static void
509 put_prot_method(const Method *m)
510 {
511         if(m->scope != PROTECTED_SCOPE)
512                 return;
513
514         if(outph)
515                 print_method(outph, "", "\t", "", "\t", "", ";\n",
516                              m, FALSE, FALSE, TRUE, FALSE, FALSE);
517         else
518                 print_method(out, "", "\t", "", "\t", "", ";\n",
519                              m, FALSE, FALSE, TRUE, FALSE, FALSE);
520 }
521
522 static void
523 put_priv_method_prot(const Method *m)
524 {
525         if(m->method == SIGNAL_LAST_METHOD ||
526            m->method == SIGNAL_FIRST_METHOD ||
527            m->method == VIRTUAL_METHOD) {
528                 if(m->cbuf)
529                         print_method(out,
530                                      "static ", "___real_", "", " ", "", ";\n",
531                                      m, FALSE, FALSE, TRUE, FALSE, FALSE);
532         }
533         /* no else, here, it might still have a private prototype, it's not
534          * exclusive */
535
536         if((m->method == OVERRIDE_METHOD &&
537             m->cbuf)) {
538                 /* add unique ID */
539                 char *s = g_strdup_printf("___%x_", (guint)m->unique_id);
540                 print_method(out, "static ", s, "", " ", "",
541                              no_gnu?";\n":" G_GNUC_UNUSED;\n",
542                              m, FALSE, FALSE, FALSE, FALSE, FALSE);
543                 g_free(s);
544         } else if(m->scope == PRIVATE_SCOPE ||
545                   m->method == INIT_METHOD ||
546                   m->method == CLASS_INIT_METHOD) {
547                 print_method(out, "static ", "", "", " ", "",
548                              no_gnu?";\n":" G_GNUC_UNUSED;\n",
549                              m, FALSE, FALSE, TRUE, FALSE, FALSE);
550         }
551 }
552
553 static GList *
554 make_func_arg (const char *typename, gboolean is_class, const char *name)
555 {
556         Node *node;
557         Node *type;
558         char *tn;
559         
560         if (is_class)
561                 tn = g_strconcat (typename, ":Class", NULL);
562         else
563                 tn = g_strdup (typename);
564
565         type = node_new (TYPE_NODE,
566                          "name:steal", tn,
567                          "pointer", "*",
568                          NULL);
569         node = node_new (FUNCARG_NODE,
570                          "atype:steal", (Type *)type,
571                          "name", name,
572                          NULL);
573         return g_list_prepend (NULL, node);
574 }
575
576 static void
577 make_inits(Class *cl)
578 {
579         int got_class_init = FALSE;
580         int got_init = FALSE;
581         GList *li;
582         Node *node;
583         for(li=cl->nodes;li;li=g_list_next(li)) {
584                 Node *n = li->data;
585                 if(n->type == METHOD_NODE) {
586                         Method *m = (Method *)n;
587                         if(m->method == INIT_METHOD) {
588                                 if(got_init)
589                                         error_print(GOB_ERROR, m->line_no, "init defined more then once");
590                                 got_init = TRUE;
591                         } else if(m->method == CLASS_INIT_METHOD) {
592                                 if(got_class_init)
593                                         error_print(GOB_ERROR, m->line_no, "class_init defined more then once");
594                                 got_class_init = TRUE;
595                         }
596                 }
597         }
598         if(!got_class_init) {
599                 Type *type = (Type *)node_new (TYPE_NODE,
600                                                "name", "void",
601                                                NULL);
602                 node = node_new (METHOD_NODE,
603                                  "scope", NO_SCOPE,
604                                  "method", CLASS_INIT_METHOD,
605                                  "mtype:steal", type,
606                                  "id", "class_init",
607                                  "args:steal", make_func_arg (cl->otype,
608                                                               TRUE /* is_class */,
609                                                               "c" /* name */),
610                                  "unique_id", method_unique_id++,
611                                  NULL);
612                 cl->nodes = g_list_prepend(cl->nodes, node);
613         }
614         if(!got_init) {
615                 Type *type = (Type *)node_new (TYPE_NODE,
616                                                "name", "void",
617                                                NULL);
618                 node = node_new (METHOD_NODE,
619                                  "scope", NO_SCOPE,
620                                  "method", INIT_METHOD,
621                                  "mtype:steal", type,
622                                  "id", "init",
623                                  "args:steal", make_func_arg (cl->otype,
624                                                               FALSE /* is_class */,
625                                                               "o" /* name */),
626                                  "unique_id", method_unique_id++,
627                                  NULL);
628                 cl->nodes = g_list_prepend(cl->nodes, node);
629         }
630 }
631
632 static void
633 find_dispose(const Class *cl)
634 {
635         GList *li;
636
637         dispose_handler = NULL;
638         for(li=cl->nodes;li;li=g_list_next(li)) {
639                 Node *n = li->data;
640                 if(n->type == METHOD_NODE) {
641                         Method *m = (Method *)n;
642                         if(m->method == OVERRIDE_METHOD &&
643                            strcmp(m->id, "dispose")==0) {
644                                 if(strcmp(m->otype, "G:Object") != 0) {
645                                         error_print(GOB_ERROR, m->line_no,
646                                                     "dispose method override "
647                                                     "of class other then "
648                                                     "G:Object");
649                                 }
650                                 if(g_list_length(m->args) != 1) {
651                                         error_print(GOB_ERROR, m->line_no,
652                                                     "dispose method override "
653                                                     "with more then one "
654                                                     "parameter");
655                                 }
656                                 dispose_handler = m;
657                                 break;
658                         }
659                 }
660         }
661 }
662
663 static void
664 find_finalize(const Class *cl)
665 {
666         GList *li;
667
668         finalize_handler = NULL;
669         for(li=cl->nodes;li;li=g_list_next(li)) {
670                 Node *n = li->data;
671                 if(n->type == METHOD_NODE) {
672                         Method *m = (Method *)n;
673                         if(m->method == OVERRIDE_METHOD &&
674                            strcmp(m->id, "finalize")==0) {
675                                 if(strcmp(m->otype, "G:Object") != 0) {
676                                         error_print(GOB_ERROR, m->line_no,
677                                                     "finalize method override "
678                                                     "of class other then "
679                                                     "G:Object");
680                                 }
681                                 if(g_list_length(m->args) != 1) {
682                                         error_print(GOB_ERROR, m->line_no,
683                                                     "finalize method override "
684                                                     "with more then one "
685                                                     "parameter");
686                                 }
687                                 finalize_handler = m;
688                                 break;
689                         }
690                 }
691         }
692 }
693
694
695 /* hash of method -> name of signal prototype */
696 static GHashTable *marsh = NULL;
697
698 /* list of methods with different signal prototypes,
699    we check this list if we can use a signal prototype of a
700    previous signal method, there are only uniques here */
701 static GList *eq_signal_methods = NULL;
702
703 /* compare a list of strings */
704 static gboolean
705 is_list_equal(const GList *a, const GList *b)
706 {
707         for(;a && b; a=a->next, b=b->next) {
708                 if(strcmp(a->data, b->data)!=0) {
709                         return FALSE;
710                 }
711         }
712         /* the the lists were different length */
713         if(a || b)
714                 return FALSE;
715         return TRUE;
716 }
717
718 static Method *
719 find_same_type_signal(const Method *m)
720 {
721         GList *li;
722         for(li=eq_signal_methods;li;li=li->next) {
723                 Method *mm = li->data;
724                 if(is_list_equal(mm->gtktypes, m->gtktypes))
725                         return mm;
726         }
727         return NULL;
728 }
729
730 static void
731 print_signal_marsal_args (const Method *m)
732 {
733         if (strcmp (m->gtktypes->next->data, "NONE") != 0) {
734                 GList *li;
735                 int i;
736                 for (i = 0, li = m->gtktypes->next;
737                      li != NULL;
738                      i++, li = li->next) {
739                         char *get_func;
740
741                         if (strcmp (li->data, "UNICHAR") == 0)
742                                 /* hack because glib is braindamaged */
743                                 get_func = g_strdup ("g_value_get_uint");
744                         else if (strncmp(li->data, "BOXED_", 6) == 0)
745                                 get_func = g_strdup ("g_value_get_boxed");
746                         else
747                                 get_func = g_strdup_printf
748                                         ("g_value_get_%s", (char *)li->data);
749
750                         gob_strdown (get_func);
751                         out_printf (out, ",\n\t\t(%s) "
752                                     "%s (param_values + %d)",
753                                     get_cast (li->data, FALSE),
754                                     get_func, i + 1);
755                         g_free (get_func);
756                 }
757         }
758         out_printf (out, ",\n\t\tdata2);\n");
759 }
760
761
762 static void
763 add_signal_prots(Method *m)
764 {
765         GList *li;
766         static int sig = 1;
767         char *s;
768         Method *mm;
769         gboolean ret_none = FALSE;
770         gboolean arglist_none = FALSE;
771         const char *retcast;
772         const char *unused = "";
773
774         if ( ! no_gnu && ! for_cpp /* g++ has a cow with this */) {
775                 unused = " G_GNUC_UNUSED";
776         }
777         
778         if (m->method != SIGNAL_LAST_METHOD &&
779             m->method != SIGNAL_FIRST_METHOD)
780                 return;
781
782         if (marsh == NULL)
783                 marsh = g_hash_table_new(NULL, NULL);
784
785         g_assert (m->gtktypes->next != NULL);
786
787         ret_none = strcmp(m->gtktypes->data, "NONE") == 0;
788         arglist_none = strcmp(m->gtktypes->next->data, "NONE") == 0;
789         
790         if (ret_none && arglist_none)
791                 return;
792
793         /* if we already did a signal prototype just use that */
794         mm = find_same_type_signal (m);
795         if (mm != NULL) {
796                 s = g_hash_table_lookup (marsh, mm);
797                 g_hash_table_insert (marsh, m, s);
798                 return;
799         }
800
801         if (ret_none)
802                 retcast = NULL;
803         else
804                 retcast = get_cast (m->gtktypes->data, FALSE);
805         
806         s = g_strdup_printf("Sig%d", sig++);
807         
808         g_hash_table_insert(marsh, m, s);
809         eq_signal_methods = g_list_prepend(eq_signal_methods, m);
810         
811         /* we know that we'll know all the gtktypes (so get_cast can't fail) */
812         out_printf(out, "\ntypedef %s (*___%s) (%s *, ",
813                    get_cast(m->gtktypes->data, FALSE), s, typebase);
814         
815         if ( ! arglist_none) {
816                 for (li = m->gtktypes->next; li != NULL; li = li->next)
817                         out_printf (out, "%s, ", get_cast (li->data, FALSE));
818         }
819         out_printf (out, "gpointer);\n"); 
820         
821         out_printf (out, "\nstatic void\n"
822                     "___marshal_%s (GClosure *closure,\n"
823                     "\tGValue *return_value%s,\n"
824                     "\tguint n_param_values,\n"
825                     "\tconst GValue *param_values,\n"
826                     "\tgpointer invocation_hint%s,\n"
827                     "\tgpointer marshal_data)\n"
828                     "{\n",
829                     s,
830                     unused,
831                     unused);
832
833         if ( ! ret_none)
834                 out_printf (out, "\t%s v_return;\n", retcast);
835
836         out_printf (out, "\tregister ___%s callback;\n"
837                     "\tregister GCClosure *cc = (GCClosure*) closure;\n"
838                     "\tregister gpointer data1, data2;\n\n",
839                     s);
840
841         out_printf (out, "\tg_return_if_fail (n_param_values == %d);\n\n",
842                     arglist_none ? 1 : g_list_length (m->gtktypes));
843
844         out_printf (out,
845                     "\tif (G_CCLOSURE_SWAP_DATA (closure)) {\n"
846                     "\t\tdata1 = closure->data;\n"
847                     "\t\tdata2 = g_value_peek_pointer (param_values + 0);\n"
848                     "\t} else {\n"
849                     "\t\tdata1 = g_value_peek_pointer (param_values + 0);\n"
850                     "\t\tdata2 = closure->data;\n"
851                     "\t}\n\n");
852
853         out_printf (out, "\tcallback = (___%s) "
854                     "(marshal_data != NULL ? marshal_data : cc->callback);"
855                     "\n\n", s);
856         
857         if (ret_none) {
858                 out_printf (out, "\tcallback ((%s *)data1", typebase);
859         } else {
860                 out_printf (out, "\tv_return = callback ((%s *)data1",
861                             typebase);
862         }
863
864         print_signal_marsal_args (m);
865
866         if ( ! ret_none) {
867                 /* FIXME: This code is so fucking ugly it hurts */
868                 gboolean take_ownership = 
869                         (strcmp ((char *)m->gtktypes->data, "STRING") == 0 ||
870                          strcmp ((char *)m->gtktypes->data, "BOXED") == 0);
871                 char *set_func;
872
873
874                 if (strcmp (m->gtktypes->data, "UNICHAR") == 0)
875                         /* hack because glib is braindamaged */
876                         set_func = g_strdup ("g_value_set_uint");
877                 else
878                         set_func = g_strdup_printf ("g_value_set_%s%s",
879                                                     (char *)m->gtktypes->data,
880                                                     take_ownership ?
881                                                     "_take_ownership" : ""); 
882                 gob_strdown (set_func);
883
884                 out_printf (out, "\n\t%s (return_value, v_return);\n",
885                             set_func);
886
887                 g_free (set_func);
888         }
889         if (no_gnu || for_cpp /* g++ has a cow with G_GNUC_UNUSED */) {
890                 if (ret_none)
891                         out_printf (out, "\n\treturn_value = NULL;\n");
892                 out_printf (out, "\tinvocation_hint = NULL;\n");
893
894         }
895         out_printf (out, "}\n\n");
896 }
897
898 static void
899 add_enums(Class *c)
900 {
901         GList *li;
902         out_printf(out, "\n");
903         if(signals>0) {
904                 out_printf(out, "enum {\n");
905                 for(li=c->nodes;li;li=g_list_next(li)) {
906                         Node *n = li->data;
907                         if(n->type == METHOD_NODE) {
908                                 Method *m = (Method *)n;
909                                 if(m->method == SIGNAL_LAST_METHOD ||
910                                    m->method == SIGNAL_FIRST_METHOD) {
911                                         char *s = g_strdup(m->id);
912                                         gob_strup(s);
913                                         out_printf(out, "\t%s_SIGNAL,\n", s);
914                                         g_free(s);
915                                 }
916                         }
917                 }
918                 out_printf(out, "\tLAST_SIGNAL\n};\n\n");
919         }
920         if (set_properties > 0 ||
921             get_properties > 0) {
922                 out_printf(out, "enum {\n\tPROP_0");
923                 for(li=c->nodes;li;li=g_list_next(li)) {
924                         Node *n = li->data;
925                         if (n->type == PROPERTY_NODE) {
926                                 Property *p = (Property *)n;
927                                 char *s = g_strdup (p->name);
928                                 gob_strup (s);
929                                 out_printf (out, ",\n\tPROP_%s", s);
930                                 g_free(s);
931                         } else if (n->type == ARGUMENT_NODE) {
932                                 Argument *a = (Argument *)n;
933                                 char *s = g_strdup(a->name);
934                                 gob_strup (s);
935                                 out_printf(out, ",\n\tPROP_%s", s);
936                                 g_free(s);
937                         }
938                 }
939                 out_printf(out, "\n};\n\n");
940         }
941
942         if (signals > 0)
943                 out_printf(out,
944                            "static guint object_signals[LAST_SIGNAL] = {0};\n\n");
945
946         out_printf(out, "/* pointer to the class of our parent */\n");
947         out_printf(out, "static %sClass *parent_class = NULL;\n\n", ptypebase);
948 }
949
950 static void
951 add_interface_methods (Class *c, const char *interface)
952 {
953         GList *li;
954         gboolean added_line = FALSE;
955
956         for (li = c->nodes; li != NULL; li = li->next) {
957                 Node *n = li->data;
958                 Method *m = (Method *)n;
959                 if (n->type != METHOD_NODE ||
960                     m->method == OVERRIDE_METHOD ||
961                     m->interface == NULL ||
962                     strcmp (m->interface, interface) != 0)
963                         continue;
964
965                 if (m->line_no > 0) {
966                         out_addline_infile (out, m->line_no);
967                         added_line = TRUE;
968                 } else if (m->line_no == 0 &&
969                            added_line) {
970                         out_addline_outfile (out);
971                         added_line = FALSE;
972                 }
973                 out_printf (out, "\tiface->%s = self_%s;\n",
974                             m->id, m->id);
975         }
976         if (added_line)
977                 out_addline_outfile (out);
978 }
979
980 static void
981 add_interface_inits (Class *c)
982 {
983         GList *li;
984
985         if (c->interfaces == NULL)
986                 return;
987
988         out_printf(out, "\n");
989
990         for (li = c->interfaces; li != NULL; li = li->next) {
991                 const char *interface = li->data;
992                 const char *end;
993                 char *name = replace_sep (interface, '_');
994                 char *type = remove_sep (interface);
995
996                 /* EEEK! evil, we should have some sort of option
997                  * to force this for arbitrary interfaces, since
998                  * some are Class and some are Iface.  Glib is shite
999                  * in consistency. */
1000                 if (strcmp (type, "GtkEditable") == 0 ||
1001                     strcmp (type, "GTypePlugin") == 0)
1002                         end = "Class";
1003                 else
1004                         /* We'll assume Iface is the standard ending */
1005                         end = "Iface";
1006
1007                 out_printf (out, "\nstatic void\n"
1008                             "___%s_init (%s%s *iface)\n"
1009                             "{\n",
1010                             name, type, end);
1011
1012                 add_interface_methods (c, interface);
1013
1014                 out_printf (out, "}\n\n");
1015
1016                 g_free (name);
1017                 g_free (type);
1018         }
1019 }
1020
1021 static void
1022 add_interface_infos (void)
1023 {
1024         GList *li;
1025         for (li = ((Class *)class)->interfaces;
1026              li != NULL;
1027              li = li->next) {
1028                 char *name = replace_sep (li->data, '_');
1029                 out_printf (out,
1030                             "\t\tstatic const GInterfaceInfo %s_info = {\n"
1031                             "\t\t\t(GInterfaceInitFunc) ___%s_init,\n"
1032                             "\t\t\tNULL,\n"
1033                             "\t\t\tNULL\n"
1034                             "\t\t};\n\n",
1035                             name, name);
1036                 g_free (name);
1037         }
1038 }
1039
1040 static void
1041 add_interfaces (void)
1042 {
1043         GList *li;
1044         for (li = ((Class *)class)->interfaces;
1045              li != NULL;
1046              li = li->next) {
1047                 char *name = replace_sep (li->data, '_');
1048                 char *type = make_pre_macro (li->data, "TYPE");
1049
1050                 out_printf (out,
1051                             "\t\tg_type_add_interface_static (type,\n"
1052                             "\t\t\t%s,\n"
1053                             "\t\t\t&%s_info);\n",
1054                             type,
1055                             name);
1056
1057                 g_free (type);
1058                 g_free (name);
1059         }
1060 }
1061
1062 static void
1063 add_get_type(void)
1064 {
1065         /*char *chunk_size = ((Class*)class)->chunk_size;*/
1066
1067         out_printf(out,
1068                    "GType\n"
1069                    "%s_get_type (void)\n"
1070                    "{\n"
1071                    "\tstatic GType type = 0;\n\n"
1072                    "\tif ___GOB_UNLIKELY(type == 0) {\n"
1073                    "\t\tstatic const GTypeInfo info = {\n"
1074                    "\t\t\tsizeof (%sClass),\n"
1075                    "\t\t\t(GBaseInitFunc) NULL,\n"
1076                    "\t\t\t(GBaseFinalizeFunc) NULL,\n"
1077                    "\t\t\t(GClassInitFunc) %s_class_init,\n"
1078                    "\t\t\t(GClassFinalizeFunc) NULL,\n"
1079                    "\t\t\tNULL /* class_data */,\n"
1080                    "\t\t\tsizeof (%s),\n"
1081                    "\t\t\t%d /* n_preallocs */,\n"
1082                    "\t\t\t(GInstanceInitFunc) %s_init,\n"
1083                    "\t\t\tNULL\n"
1084                    "\t\t};\n\n",
1085                    funcbase, typebase, funcbase, typebase, prealloc, funcbase);
1086
1087         add_interface_infos ();
1088
1089         out_printf (out,
1090                     "\t\ttype = g_type_register_static (%s, \"%s\", &info, (GTypeFlags)%s);\n",
1091                     pmacrotype, typebase, ((Class *)class)->abstract ? "G_TYPE_FLAG_ABSTRACT" : "0");
1092
1093         add_interfaces ();
1094
1095         /*
1096         if(chunk_size)  {
1097                 out_printf(out,
1098                            "#if %s > 0\n"
1099                            "\t\tgtk_type_set_chunk_alloc(type, %s);\n"
1100                            "#endif\n", 
1101                            chunk_size, chunk_size);
1102         }
1103         */
1104         out_printf(out,
1105                    "\t}\n\n"
1106                    "\treturn type;\n"
1107                    "}\n\n");
1108 }
1109
1110 static void
1111 add_bonobo_object_get_type (void)
1112 {
1113         /* char *chunk_size = ((Class*)class)->chunk_size; */
1114         /* _vicious_ spanks seth with a rusty nail
1115         out_printf(out,
1116                    "\n#warning \"Bonobo isn't fully ported to glib 2.0 and "
1117                    "gob2 doesn't officially support it yet. It'd be safer "
1118                    "and a lot more fun to blow goats.\"\n");
1119                    */
1120
1121         out_printf (out,
1122                     "GType\n"
1123                     "%s_get_type (void)\n" /* 1 */
1124                     "{\n"
1125                     "\tstatic GType type = 0;\n\n"
1126                     "\tif ___GOB_UNLIKELY(type == 0) {\n"
1127                     "\t\tstatic const GTypeInfo info = {\n"
1128                     "\t\t\tsizeof (%sClass),\n" /* 2 */
1129                     "\t\t\t(GBaseInitFunc) NULL,\n"
1130                     "\t\t\t(GBaseFinalizeFunc) NULL,\n"
1131                     "\t\t\t(GClassInitFunc) %s_class_init,\n" /* 3 */
1132                     "\t\t\tNULL, /* class_finalize */\n"
1133                     "\t\t\tNULL, /* class_data */\n"
1134                     "\t\t\tsizeof (%s),\n" /* 4 */
1135                     "\t\t\t0, /* n_preallocs */\n"
1136                     "\t\t\t(GInstanceInitFunc)  %s_init,\n" /* 5 */
1137                     "\t\t\tNULL\n"
1138                     "\t\t};\n\n",
1139                     funcbase /* 1 */,
1140                     typebase /* 2 */,
1141                     funcbase /* 3 */,
1142                     typebase /* 4 */,
1143                     funcbase /* 5 */);
1144
1145         add_interface_infos ();
1146
1147         out_printf (out,
1148                    "\t\ttype = bonobo_type_unique (\n"
1149                    "\t\t\tBONOBO_OBJECT_TYPE,\n"
1150                    "\t\t\tPOA_%s__init, NULL,\n" /* 1 */
1151                    "\t\t\tG_STRUCT_OFFSET (%sClass, _epv),\n" /* 2 */
1152                    "\t\t\t&info, \"%s\");\n", /* 3 */
1153                    ((Class*)class)->bonobo_object_class /* 1 */,
1154                    typebase /* 2 */,
1155                    typebase /* 3 */);
1156
1157         add_interfaces ();
1158
1159         /*if(chunk_size)  {
1160                 out_printf(out,
1161                            "#if %s > 0\n"
1162                            "\t\tgtk_type_set_chunk_alloc(type, %s);\n"
1163                            "#endif\n", 
1164                            chunk_size, chunk_size);
1165         }*/
1166         out_printf(out,
1167                    "\t}\n\n"
1168                    "\treturn type;\n"
1169                    "}\n\n");
1170 }
1171
1172 static void
1173 add_overrides(Class *c, const char *oname,
1174               gboolean did_base_obj)
1175 {
1176         GList *li;
1177         GHashTable *done;
1178         char *s;
1179         
1180         done = g_hash_table_new (g_str_hash, g_str_equal);
1181         if (did_base_obj) {
1182                 s = g_strdup ("GObject");
1183                 g_hash_table_insert (done, s, s);
1184         }
1185         for (li = c->nodes; li != NULL; li = li->next) {
1186                 Node *n = li->data;
1187                 char *f;
1188                 Method *m = (Method *)n;
1189                 if(n->type != METHOD_NODE ||
1190                    m->method != OVERRIDE_METHOD)
1191                         continue;
1192
1193                 s = remove_sep(m->otype);
1194                 
1195                 if(g_hash_table_lookup(done, s)) {
1196                         g_free(s);
1197                         continue;
1198                 }
1199                 g_hash_table_insert(done, s, s);
1200
1201                 f = replace_sep(m->otype, '_');
1202                 gob_strdown(f);
1203
1204                 out_printf(out, "\t%sClass *%s_class = (%sClass *)%s;\n",
1205                            s, f, s, oname);
1206                 
1207                 g_free(f);
1208         }
1209         g_hash_table_foreach (done, (GHFunc)g_free, NULL);
1210         g_hash_table_destroy (done);
1211 }
1212
1213 static char *
1214 make_run_signal_flags(Method *m, gboolean last)
1215 {
1216         GList *li;
1217         GString *gs;
1218         char *flags[] = {
1219                 "RUN_FIRST",
1220                 "RUN_LAST",
1221                 "RUN_CLEANUP",
1222                 "NO_RECURSE",
1223                 "DETAILED",
1224                 "ACTION",
1225                 "NO_HOOKS",
1226                 NULL
1227         };
1228
1229         gs = g_string_new(NULL);
1230
1231         if(last)
1232                 g_string_assign(gs, "G_SIGNAL_RUN_LAST");
1233         else
1234                 g_string_assign(gs, "G_SIGNAL_RUN_FIRST");
1235
1236         if(m->scope == PUBLIC_SCOPE)
1237                 g_string_append(gs, " | G_SIGNAL_ACTION");
1238
1239         for(li = m->flags; li; li = li->next) {
1240                 char *flag = li->data;
1241                 int i;
1242                 for(i=0;flags[i];i++) {
1243                         if(strcmp(flags[i], flag)==0)
1244                                 break;
1245                 }
1246                 /* if we haven't found it in our list */
1247                 if( ! flags[i]) {
1248                         error_printf(GOB_WARN, m->line_no,
1249                                      "Unknown flag '%s' used, "
1250                                      "perhaps it was misspelled",
1251                                      flag);
1252                 }
1253                 g_string_sprintfa(gs, " | G_SIGNAL_%s", flag);
1254         }
1255
1256         {
1257                 char *ret = gs->str;
1258                 g_string_free(gs, FALSE);
1259                 return ret;
1260         }
1261 }
1262                 
1263
1264 static void
1265 add_signals(Class *c)
1266 {
1267         GList *li;
1268
1269         out_printf(out, "\n");
1270         for(li=c->nodes;li;li=g_list_next(li)) {
1271                 Node *n = li->data;
1272                 char *mar, *sig, *flags;
1273                 gboolean is_none, last = FALSE;
1274                 Method *m = (Method *)n;
1275
1276                 if(n->type != METHOD_NODE ||
1277                    (m->method != SIGNAL_FIRST_METHOD &&
1278                     m->method != SIGNAL_LAST_METHOD))
1279                         continue;
1280
1281                 if(m->method == SIGNAL_FIRST_METHOD)
1282                         last = FALSE;
1283                 else
1284                         last = TRUE;
1285
1286                 if(g_hash_table_lookup(marsh, m))
1287                         mar = g_strconcat("___marshal_",
1288                                           (char *)g_hash_table_lookup(marsh, m),
1289                                           NULL);
1290                 else
1291                         mar = g_strdup("g_cclosure_marshal_VOID__VOID");
1292                 
1293                 is_none = (strcmp(m->gtktypes->next->data, "NONE")==0);
1294
1295                 sig = g_strdup (m->id);
1296                 gob_strup (sig);
1297                 flags = make_run_signal_flags (m, last);
1298                 out_printf (out, "\tobject_signals[%s_SIGNAL] =\n"
1299                             "\t\tg_signal_new (\"%s\",\n"
1300                             "\t\t\tG_TYPE_FROM_CLASS (g_object_class),\n"
1301                             "\t\t\t(GSignalFlags)(%s),\n"
1302                             "\t\t\tG_STRUCT_OFFSET (%sClass, %s),\n"
1303                             "\t\t\tNULL, NULL,\n"
1304                             "\t\t\t%s,\n"
1305                             "\t\t\tG_TYPE_%s, %d",
1306                             sig, m->id,
1307                             flags,
1308                             typebase, m->id, mar,
1309                             (char *)m->gtktypes->data,
1310                             is_none ? 0 : g_list_length(m->gtktypes->next));
1311                 g_free(mar);
1312                 g_free(sig);
1313                 g_free(flags);
1314                 
1315                 if( ! is_none) {
1316                         GList *l;
1317                         char  *t;
1318                         for(l = m->gtktypes->next; l != NULL; l = l->next) {
1319                                 char *str = l->data;
1320                                 if (strncmp (str, "BOXED_", 6) == 0)
1321                                         t = g_strdup (&(str[6]));
1322                                 else
1323                                         t = g_strconcat ("G_TYPE_", str, NULL);
1324                                 out_printf (out, ",\n\t\t\t%s", t);
1325                                 g_free (t);
1326                         }
1327                 }
1328
1329                 out_printf(out, ");\n");
1330
1331                 if(strcmp(m->gtktypes->data, "NONE") != 0 ||
1332                    ! is_none) {
1333                         GList *gl, *al;
1334                         out_printf(out, "\tif ___GOB_UNLIKELY(");
1335                         if(strcmp(m->gtktypes->data, "NONE") != 0) {
1336                                 out_printf(out, "sizeof(");
1337                                 print_type(out, m->mtype, FALSE);
1338                                 out_printf(out, "%s",
1339                                            m->mtype->postfix ?
1340                                            m->mtype->postfix : ""); 
1341                                 out_printf(out, ") != sizeof(%s) || ",
1342                                            get_cast(m->gtktypes->data, FALSE));
1343                         }
1344
1345                         for(al = m->args->next, gl = m->gtktypes->next;
1346                             al != NULL && gl != NULL;
1347                             al = al->next, gl = gl->next) {
1348                                 FuncArg *arg = al->data;
1349                                 char *gtkarg = gl->data;
1350
1351                                 out_printf(out, "sizeof(");
1352                                 print_type(out, arg->atype, FALSE);
1353                                 out_printf(out, "%s",
1354                                            arg->atype->postfix ?
1355                                            arg->atype->postfix : ""); 
1356                                 out_printf(out, ") != sizeof(%s) || ",
1357                                            get_cast(gtkarg, FALSE));
1358                         }
1359
1360                         out_printf (out,
1361                                     "parent_class == NULL /* avoid warning */");
1362
1363                         out_printf(out, ") {\n"
1364                                    "\t\tg_error(\"%s line %d: Type mismatch "
1365                                    "of \\\"%s\\\" signal signature\");\n"
1366                                    "\t}\n",
1367                                    filename, m->line_no, m->id);
1368
1369                 }
1370         }
1371 }
1372
1373 static void
1374 set_def_handlers(Class *c, const char *oname)
1375 {
1376         GList *li;
1377         gboolean set_line = FALSE;
1378
1379         out_printf(out, "\n");
1380         for(li = c->nodes; li; li = g_list_next(li)) {
1381                 Node *n = li->data;
1382                 Method *m = (Method *)n;
1383
1384                 if(n->type != METHOD_NODE ||
1385                    (m->method != SIGNAL_FIRST_METHOD &&
1386                     m->method != SIGNAL_LAST_METHOD &&
1387                     m->method != VIRTUAL_METHOD &&
1388                     m->method != OVERRIDE_METHOD))
1389                         continue;
1390
1391                 if(m->line_no > 0 && m->cbuf) {
1392                         out_addline_infile(out, m->line_no);
1393                         set_line = TRUE;
1394                 } else if(set_line) {
1395                         out_addline_outfile(out);
1396                         set_line = FALSE;
1397                 }
1398
1399
1400                 if (m->method == OVERRIDE_METHOD) {
1401                         char *s;
1402                         s = replace_sep (m->otype, '_');
1403                         gob_strdown (s);
1404
1405                         if (need_dispose &&
1406                             dispose_handler != NULL &&
1407                             strcmp (m->id, "dispose") == 0)
1408                                 out_printf (out, "\tg_object_class->dispose "
1409                                             "= ___dispose;\n");
1410                         else if (need_finalize &&
1411                                 finalize_handler &&
1412                                 strcmp(m->id, "finalize") == 0)
1413                                 out_printf(out,
1414                                            "\tg_object_class->finalize = ___finalize;\n");
1415                         else if (m->cbuf != NULL)
1416                                 out_printf(out,
1417                                            "\t%s_class->%s = ___%x_%s_%s;\n",
1418                                            s, m->id, (guint)m->unique_id,
1419                                            funcbase, m->id);
1420                         else
1421                                 out_printf(out, "\t%s_class->%s = NULL;\n",
1422                                            s, m->id);
1423                 } else {
1424                         if(m->cbuf)
1425                                 out_printf(out, "\t%s->%s = ___real_%s_%s;\n",
1426                                            oname, m->id,
1427                                            funcbase, m->id);
1428                         else
1429                                 out_printf(out, "\t%s->%s = NULL;\n",
1430                                            oname, m->id);
1431                 }
1432         }
1433         if(set_line)
1434                 out_addline_outfile(out);
1435 }
1436
1437 static void
1438 make_argument (Argument *a)
1439 {
1440         GString *flags;
1441         GList *l;
1442         char *s;
1443         char *argflags[] = {
1444                 "CONSTRUCT",
1445                 "CONSTRUCT_ONLY",
1446                 "LAX_VALIDATION",
1447                 "PRIVATE",
1448                 NULL
1449         };
1450
1451         flags = g_string_new ("(GParamFlags)(");
1452
1453         if(a->get && a->set)
1454                 g_string_append (flags, "G_PARAM_READABLE | G_PARAM_WRITABLE");
1455         else if(a->get)
1456                 g_string_append (flags, "G_PARAM_READABLE");
1457         else
1458                 g_string_append (flags, "G_PARAM_WRITABLE");
1459
1460         g_assert(a->get || a->set);
1461
1462         for (l = a->flags; l != NULL; l = l->next) {
1463                 char *flag = l->data;
1464                 int i;
1465                 if(strcmp (flag, "READABLE") == 0 ||
1466                    strcmp (flag, "WRITABLE") == 0) {
1467                         error_print(GOB_WARN, a->line_no,
1468                                     "READABLE and "
1469                                     "WRITABLE argument flags are "
1470                                     "set automatically");
1471                         continue;
1472                 }
1473                 for(i = 0; argflags[i]; i++) {
1474                         if(strcmp(argflags[i], flag)==0)
1475                                 break;
1476                 }
1477                 g_string_sprintfa(flags, " | %s%s", argflags[i] ? "G_PARAM_" : "", flag);
1478         }
1479
1480         g_string_append (flags, ")");
1481
1482         s = g_strdup(a->name);
1483         gob_strup (s);
1484         if (!strcmp (a->gtktype, "ENUM"))
1485                 out_printf(out, "\tparam_spec = g_param_spec_enum (\"%s\", NULL, NULL,\n"
1486                            "\t\tG_TYPE_ENUM, 0,\n"
1487                            "\t\t%s);\n",
1488                            a->name, flags->str);
1489         if (!strcmp (a->gtktype, "FLAGS"))
1490                 out_printf(out, "\tparam_spec = g_param_spec_flags (\"%s\", NULL, NULL,\n"
1491                            "\t\tG_TYPE_FLAGS, 0,\n"
1492                            "\t\t%s);\n",
1493                            a->name, flags->str);
1494         else if (!strcmp (a->gtktype, "OBJECT"))
1495                 out_printf(out, "\tparam_spec = g_param_spec_object (\"%s\", NULL, NULL,\n"
1496                            "\t\tG_TYPE_OBJECT,\n"
1497                            "\t\t%s);\n",
1498                            a->name, flags->str);
1499         else if (!strcmp (a->gtktype, "STRING"))
1500                 out_printf(out, "\tparam_spec = g_param_spec_string (\"%s\", NULL, NULL,\n"
1501                            "\t\tNULL,\n"
1502                            "\t\t%s);\n",
1503                            a->name, flags->str);
1504         else if (!strcmp (a->gtktype, "INT"))
1505                 out_printf(out, "\tparam_spec = g_param_spec_int (\"%s\", NULL, NULL,\n"
1506                            "\t\tG_MININT, G_MAXINT,\n"
1507                            "\t\t0,\n"
1508                            "\t\t%s);\n",
1509                            a->name, flags->str);
1510         else if (!strcmp (a->gtktype, "UINT"))
1511                 out_printf(out, "\tparam_spec = g_param_spec_uint (\"%s\", NULL, NULL,\n"
1512                            "\t\t0, G_MAXUINT,\n"
1513                            "\t\t0,\n"
1514                            "\t\t%s);\n",
1515                            a->name, flags->str);
1516         else if (!strcmp (a->gtktype, "INT"))
1517                 out_printf(out, "\tparam_spec = g_param_spec_int (\"%s\", NULL, NULL,\n"
1518                            "\t\tG_MININT, G_MAXINT,\n"
1519                            "\t\t0,\n"
1520                            "\t\t%s);\n",
1521                            a->name, flags->str);
1522         else if (!strcmp (a->gtktype, "CHAR"))
1523                 out_printf(out, "\tparam_spec = g_param_spec_char (\"%s\", NULL, NULL,\n"
1524                            "\t\t-128, 127,\n"
1525                            "\t\t0,\n"
1526                            "\t\t%s);\n",
1527                            a->name, flags->str);
1528         else if (!strcmp (a->gtktype, "UCHAR"))
1529                 out_printf(out, "\tparam_spec = g_param_spec_uchar (\"%s\", NULL, NULL,\n"
1530                            "\t\t0, 0xFF,\n"
1531                            "\t\t0,\n"
1532                            "\t\t%s);\n",
1533                            a->name, flags->str);
1534         else if (!strcmp (a->gtktype, "BOOL") ||
1535                  !strcmp (a->gtktype, "BOOLEAN"))
1536                 out_printf(out, "\tparam_spec = g_param_spec_boolean (\"%s\", NULL, NULL,\n"
1537                            "\t\tFALSE,\n"
1538                            "\t\t%s);\n",
1539                            a->name, flags->str);
1540         else if (!strcmp (a->gtktype, "LONG"))
1541                 out_printf(out, "\tparam_spec = g_param_spec_long (\"%s\", NULL, NULL,\n"
1542                            "\t\tG_MINLONG, G_MAXLONG,\n"
1543                            "\t\t0,\n"
1544                            "\t\t%s);\n",
1545                            a->name, flags->str);
1546         else if (!strcmp (a->gtktype, "ULONG"))
1547                 out_printf(out, "\tparam_spec = g_param_spec_ulong (\"%s\", NULL, NULL,\n"
1548                            "\t\t0, G_MAXULONG,\n"
1549                            "\t\t0,\n"
1550                            "\t\t%s);\n",
1551                            a->name, flags->str);
1552         else if (!strcmp (a->gtktype, "INT64"))
1553                 out_printf(out, "\tparam_spec = g_param_spec_int64 (\"%s\", NULL, NULL,\n"
1554                            "\t\tG_MININT64, G_MAXINT64,\n"
1555                            "\t\t0,\n"
1556                            "\t\t%s);\n",
1557                            a->name, flags->str);
1558         else if (!strcmp (a->gtktype, "UINT64"))
1559                 out_printf(out, "\tparam_spec = g_param_spec_uint64 (\"%s\", NULL, NULL,\n"
1560                            "\t\t0, G_MAXUINT64,\n"
1561                            "\t\t0,\n"
1562                            "\t\t%s);\n",
1563                            a->name, flags->str);
1564         else if (!strcmp (a->gtktype, "FLOAT"))
1565                 out_printf(out, "\tparam_spec = g_param_spec_float (\"%s\", NULL, NULL,\n"
1566                            "\t\tG_MINFLOAT, G_MAXFLOAT,\n"
1567                            "\t\t0,\n"
1568                            "\t\t%s);\n",
1569                            a->name, flags->str);
1570         else if (!strcmp (a->gtktype, "DOUBLE"))
1571                 out_printf(out, "\tparam_spec = g_param_spec_double (\"%s\", NULL, NULL,\n"
1572                            "\t\tG_MINDOUBLE, G_MAXDOUBLE,\n"
1573                            "\t\t0,\n"
1574                            "\t\t%s);\n",
1575                            a->name, flags->str);
1576         else if (!strcmp (a->gtktype, "POINTER"))
1577                 out_printf(out, "\tparam_spec = g_param_spec_pointer (\"%s\", NULL, NULL,\n"
1578                            "\t\t%s);\n",
1579                            a->name, flags->str);
1580         else
1581                 error_printf (GOB_ERROR, a->line_no,
1582                               "%s type is not supported for arguments, try using properties",
1583                               a->gtktype);
1584
1585         out_printf(out, "\tg_object_class_install_property (g_object_class,\n"
1586                    "\t\tPROP_%s, param_spec);\n", s);
1587
1588
1589         g_free(s);
1590         g_string_free(flags, TRUE);
1591 }
1592
1593 #define value_for_print(str, alt) (str != NULL ? str : alt)
1594
1595 static void
1596 make_property (Property *p)
1597 {
1598         char *s;
1599
1600         if (p->get == NULL && p->set == NULL) {
1601                 error_print (GOB_ERROR, p->line_no,
1602                              "Property has no getter nor setter");
1603         }
1604
1605         if (p->override) {
1606                 if (p->flags != NULL)
1607                         error_print (GOB_WARN, p->line_no,
1608                                      "Overriden property, flags ignored");
1609                 if (p->nick != NULL)
1610                         error_print (GOB_WARN, p->line_no,
1611                                      "Overriden property, nick ignored");
1612                 if (p->blurb != NULL)
1613                         error_print (GOB_WARN, p->line_no,
1614                                      "Overriden property, blurb ignored");
1615                 if (p->minimum != NULL)
1616                         error_print (GOB_WARN, p->line_no,
1617                                      "Overriden property, minimum ignored");
1618                 if (p->maximum != NULL)
1619                         error_print (GOB_WARN, p->line_no,
1620                                      "Overriden property, maximum ignored");
1621                 if (p->default_value != NULL)
1622                         error_print (GOB_WARN, p->line_no,
1623                                      "Overriden property, default_value ignored");
1624
1625                 s = g_strdup (p->name);
1626                 gob_strup (s);
1627                 out_printf (out, "\tg_object_class_override_property (g_object_class,\n"
1628                             "\t\tPROP_%s,\n"
1629                             "\t\t\"%s\");\n", s, p->name);
1630                 g_free (s);
1631         } else {
1632                 GString *flags;
1633                 GList *l;
1634                 char *argflags[] = {
1635                         "CONSTRUCT",
1636                         "CONSTRUCT_ONLY",
1637                         "LAX_VALIDATION",
1638                         "PRIVATE",
1639                         NULL
1640                 };
1641
1642                 flags = g_string_new ("(GParamFlags)(");
1643
1644                 if (p->get != NULL && p->set != NULL)
1645                         g_string_append (flags, "G_PARAM_READABLE | G_PARAM_WRITABLE");
1646                 else if (p->get != NULL)
1647                         g_string_append (flags, "G_PARAM_READABLE");
1648                 else
1649                         g_string_append (flags, "G_PARAM_WRITABLE");
1650
1651
1652                 for (l = p->flags; l != NULL; l = l->next) {
1653                         char *flag = l->data;
1654                         int i;
1655                         if(strcmp (flag, "READABLE") == 0 ||
1656                            strcmp (flag, "WRITABLE") == 0) {
1657                                 error_print(GOB_WARN, p->line_no,
1658                                             "READABLE and "
1659                                             "WRITABLE argument flags are "
1660                                             "set automatically");
1661                                 continue;
1662                         }
1663                         for(i = 0; argflags[i]; i++) {
1664                                 if(strcmp(argflags[i], flag)==0)
1665                                         break;
1666                         }
1667                         g_string_sprintfa(flags, " | %s%s", argflags[i] ? "G_PARAM_" : "", flag);
1668                 }
1669
1670                 g_string_append (flags, ")");
1671
1672                 if (strcmp (p->gtktype, "CHAR") == 0) {
1673                         out_printf (out, "\tparam_spec = g_param_spec_char\n"
1674                                     "\t\t(\"%s\" /* name */,\n"
1675                                     "\t\t %s /* nick */,\n"
1676                                     "\t\t %s /* blurb */,\n"
1677                                     "\t\t %s /* minimum */,\n"
1678                                     "\t\t %s /* maximum */,\n"
1679                                     "\t\t %s /* default_value */,\n"
1680                                     "\t\t %s);\n",
1681                                     p->name,
1682                                     value_for_print (p->nick, "NULL"),
1683                                     value_for_print (p->blurb, "NULL"),
1684                                     value_for_print (p->minimum, "-128"),
1685                                     value_for_print (p->maximum, "127"),
1686                                     value_for_print (p->default_value, "0"),
1687                                     flags->str);
1688                 } else if (strcmp (p->gtktype, "UCHAR") == 0) {
1689                         out_printf (out, "\tparam_spec = g_param_spec_uchar\n"
1690                                     "\t\t(\"%s\" /* name */,\n"
1691                                     "\t\t %s /* nick */,\n"
1692                                     "\t\t %s /* blurb */,\n"
1693                                     "\t\t %s /* minimum */,\n"
1694                                     "\t\t %s /* maximum */,\n"
1695                                     "\t\t %s /* default_value */,\n"
1696                                     "\t\t %s);\n",
1697                                     p->name,
1698                                     value_for_print (p->nick, "NULL"),
1699                                     value_for_print (p->blurb, "NULL"),
1700                                     value_for_print (p->minimum, "0"),
1701                                     value_for_print (p->maximum, "0xFF"),
1702                                     value_for_print (p->default_value, "0"),
1703                                     flags->str);
1704                 } else if (strcmp (p->gtktype, "BOOLEAN") == 0) {
1705                         out_printf (out, "\tparam_spec = g_param_spec_boolean\n"
1706                                     "\t\t(\"%s\" /* name */,\n"
1707                                     "\t\t %s /* nick */,\n"
1708                                     "\t\t %s /* blurb */,\n"
1709                                     "\t\t %s /* default_value */,\n"
1710                                     "\t\t %s);\n",
1711                                     p->name,
1712                                     value_for_print (p->nick, "NULL"),
1713                                     value_for_print (p->blurb, "NULL"),
1714                                     value_for_print (p->default_value, "FALSE"),
1715                                     flags->str);
1716                 } else if (strcmp (p->gtktype, "INT") == 0) {
1717                         out_printf (out, "\tparam_spec = g_param_spec_int\n"
1718                                     "\t\t(\"%s\" /* name */,\n"
1719                                     "\t\t %s /* nick */,\n"
1720                                     "\t\t %s /* blurb */,\n"
1721                                     "\t\t %s /* minimum */,\n"
1722                                     "\t\t %s /* maximum */,\n"
1723                                     "\t\t %s /* default_value */,\n"
1724                                     "\t\t %s);\n",
1725                                     p->name,
1726                                     value_for_print (p->nick, "NULL"),
1727                                     value_for_print (p->blurb, "NULL"),
1728                                     value_for_print (p->minimum, "G_MININT"),
1729                                     value_for_print (p->maximum, "G_MAXINT"),
1730                                     value_for_print (p->default_value, "0"),
1731                                     flags->str);
1732                 } else if (strcmp (p->gtktype, "UINT") == 0) {
1733                         out_printf (out, "\tparam_spec = g_param_spec_uint\n"
1734                                     "\t\t(\"%s\" /* name */,\n"
1735                                     "\t\t %s /* nick */,\n"
1736                                     "\t\t %s /* blurb */,\n"
1737                                     "\t\t %s /* minimum */,\n"
1738                                     "\t\t %s /* maximum */,\n"
1739                                     "\t\t %s /* default_value */,\n"
1740                                     "\t\t %s);\n",
1741                                     p->name,
1742                                     value_for_print (p->nick, "NULL"),
1743                                     value_for_print (p->blurb, "NULL"),
1744                                     value_for_print (p->minimum, "0"),
1745                                     value_for_print (p->maximum, "G_MAXUINT"),
1746                                     value_for_print (p->default_value, "0"),
1747                                     flags->str);
1748                 } else if (strcmp (p->gtktype, "LONG") == 0) {
1749                         out_printf (out, "\tparam_spec = g_param_spec_long\n"
1750                                     "\t\t(\"%s\" /* name */,\n"
1751                                     "\t\t %s /* nick */,\n"
1752                                     "\t\t %s /* blurb */,\n"
1753                                     "\t\t %s /* minimum */,\n"
1754                                     "\t\t %s /* maximum */,\n"
1755                                     "\t\t %s /* default_value */,\n"
1756                                     "\t\t %s);\n",
1757                                     p->name,
1758                                     value_for_print (p->nick, "NULL"),
1759                                     value_for_print (p->blurb, "NULL"),
1760                                     value_for_print (p->minimum, "G_MINLONG"),
1761                                     value_for_print (p->maximum, "G_MAXLONG"),
1762                                     value_for_print (p->default_value, "0"),
1763                                     flags->str);
1764                 } else if (strcmp (p->gtktype, "ULONG") == 0) {
1765                         out_printf (out, "\tparam_spec = g_param_spec_ulong\n"
1766                                     "\t\t(\"%s\" /* name */,\n"
1767                                     "\t\t %s /* nick */,\n"
1768                                     "\t\t %s /* blurb */,\n"
1769                                     "\t\t %s /* minimum */,\n"
1770                                     "\t\t %s /* maximum */,\n"
1771                                     "\t\t %s /* default_value */,\n"
1772                                     "\t\t %s);\n",
1773                                     p->name,
1774                                     value_for_print (p->nick, "NULL"),
1775                                     value_for_print (p->blurb, "NULL"),
1776                                     value_for_print (p->minimum, "0"),
1777                                     value_for_print (p->maximum, "G_MAXULONG"),
1778                                     value_for_print (p->default_value, "0"),
1779                                     flags->str);
1780                 } else if (strcmp (p->gtktype, "INT64") == 0) {
1781                         out_printf (out, "\tparam_spec = g_param_spec_int64\n"
1782                                     "\t\t(\"%s\" /* name */,\n"
1783                                     "\t\t %s /* nick */,\n"
1784                                     "\t\t %s /* blurb */,\n"
1785                                     "\t\t %s /* minimum */,\n"
1786                                     "\t\t %s /* maximum */,\n"
1787                                     "\t\t %s /* default_value */,\n"
1788                                     "\t\t %s);\n",
1789                                     p->name,
1790                                     value_for_print (p->nick, "NULL"),
1791                                     value_for_print (p->blurb, "NULL"),
1792                                     value_for_print (p->minimum, "G_MININT64"),
1793                                     value_for_print (p->maximum, "G_MAXINT64"),
1794                                     value_for_print (p->default_value, "0"),
1795                                     flags->str);
1796                 } else if (strcmp (p->gtktype, "UINT64") == 0) {
1797                         out_printf (out, "\tparam_spec = g_param_spec_uint64\n"
1798                                     "\t\t(\"%s\" /* name */,\n"
1799                                     "\t\t %s /* nick */,\n"
1800                                     "\t\t %s /* blurb */,\n"
1801                                     "\t\t %s /* minimum */,\n"
1802                                     "\t\t %s /* maximum */,\n"
1803                                     "\t\t %s /* default_value */,\n"
1804                                     "\t\t %s);\n",
1805                                     p->name,
1806                                     value_for_print (p->nick, "NULL"),
1807                                     value_for_print (p->blurb, "NULL"),
1808                                     value_for_print (p->minimum, "0"),
1809                                     value_for_print (p->maximum, "G_MAXUINT64"),
1810                                     value_for_print (p->default_value, "0"),
1811                                     flags->str);
1812                 } else if (strcmp (p->gtktype, "UNICHAR") == 0) {
1813                         out_printf (out, "\tparam_spec = g_param_spec_unichar\n"
1814                                     "\t\t(\"%s\" /* name */,\n"
1815                                     "\t\t %s /* nick */,\n"
1816                                     "\t\t %s /* blurb */,\n"
1817                                     "\t\t %s /* default_value */,\n"
1818                                     "\t\t %s);\n",
1819                                     p->name,
1820                                     value_for_print (p->nick, "NULL"),
1821                                     value_for_print (p->blurb, "NULL"),
1822                                     value_for_print (p->default_value, "0"),
1823                                     flags->str);
1824                 } else if (strcmp (p->gtktype, "ENUM") == 0) {
1825                         char *type = make_me_type (p->extra_gtktype,
1826                                                    "G_TYPE_ENUM");
1827                         out_printf (out, "\tparam_spec = g_param_spec_enum\n"
1828                                     "\t\t(\"%s\" /* name */,\n"
1829                                     "\t\t %s /* nick */,\n"
1830                                     "\t\t %s /* blurb */,\n"
1831                                     "\t\t %s /* enum_type */,\n"
1832                                     "\t\t %s /* default_value */,\n"
1833                                     "\t\t %s);\n",
1834                                     p->name,
1835                                     value_for_print (p->nick, "NULL"),
1836                                     value_for_print (p->blurb, "NULL"),
1837                                     type,
1838                                     value_for_print (p->default_value, "0"),
1839                                     flags->str);
1840                         g_free (type);
1841                 } else if (strcmp (p->gtktype, "FLAGS") == 0) {
1842                         char *type = make_me_type (p->extra_gtktype,
1843                                                    "G_TYPE_FLAGS");
1844                         out_printf (out, "\tparam_spec = g_param_spec_flags\n"
1845                                     "\t\t(\"%s\" /* name */,\n"
1846                                     "\t\t %s /* nick */,\n"
1847                                     "\t\t %s /* blurb */,\n"
1848                                     "\t\t %s /* flags_type */,\n"
1849                                     "\t\t %s /* default_value */,\n"
1850                                     "\t\t %s);\n",
1851                                     p->name,
1852                                     value_for_print (p->nick, "NULL"),
1853                                     value_for_print (p->blurb, "NULL"),
1854                                     type,
1855                                     value_for_print (p->default_value, "0"),
1856                                     flags->str);
1857                         g_free (type);
1858                 } else if (strcmp (p->gtktype, "FLOAT") == 0) {
1859                         out_printf (out, "\tparam_spec = g_param_spec_float\n"
1860                                     "\t\t(\"%s\" /* name */,\n"
1861                                     "\t\t %s /* nick */,\n"
1862                                     "\t\t %s /* blurb */,\n"
1863                                     "\t\t %s /* minimum */,\n"
1864                                     "\t\t %s /* maximum */,\n"
1865                                     "\t\t %s /* default_value */,\n"
1866                                     "\t\t %s);\n",
1867                                     p->name,
1868                                     value_for_print (p->nick, "NULL"),
1869                                     value_for_print (p->blurb, "NULL"),
1870                                     value_for_print (p->minimum, "G_MINFLOAT"),
1871                                     value_for_print (p->maximum, "G_MAXFLOAT"),
1872                                     value_for_print (p->default_value, "0.0"),
1873                                     flags->str);
1874                 } else if (strcmp (p->gtktype, "DOUBLE") == 0) {
1875                         out_printf (out, "\tparam_spec = g_param_spec_double\n"
1876                                     "\t\t(\"%s\" /* name */,\n"
1877                                     "\t\t %s /* nick */,\n"
1878                                     "\t\t %s /* blurb */,\n"
1879                                     "\t\t %s /* minimum */,\n"
1880                                     "\t\t %s /* maximum */,\n"
1881                                     "\t\t %s /* default_value */,\n"
1882                                     "\t\t %s);\n",
1883                                     p->name,
1884                                     value_for_print (p->nick, "NULL"),
1885                                     value_for_print (p->blurb, "NULL"),
1886                                     value_for_print (p->minimum, "G_MINDOUBLE"),
1887                                     value_for_print (p->maximum, "G_MAXDOUBLE"),
1888                                     value_for_print (p->default_value, "0.0"),
1889                                     flags->str);
1890                 } else if (strcmp (p->gtktype, "STRING") == 0) {
1891                         out_printf (out, "\tparam_spec = g_param_spec_string\n"
1892                                     "\t\t(\"%s\" /* name */,\n"
1893                                     "\t\t %s /* nick */,\n"
1894                                     "\t\t %s /* blurb */,\n"
1895                                     "\t\t %s /* default_value */,\n"
1896                                     "\t\t %s);\n",
1897                                     p->name,
1898                                     value_for_print (p->nick, "NULL"),
1899                                     value_for_print (p->blurb, "NULL"),
1900                                     value_for_print (p->default_value, "NULL"),
1901                                     flags->str);
1902                 } else if (strcmp (p->gtktype, "PARAM") == 0) {
1903                         char *type = make_me_type (p->extra_gtktype,
1904                                                    "G_TYPE_PARAM");
1905                         out_printf (out, "\tparam_spec = g_param_spec_param\n"
1906                                     "\t\t(\"%s\" /* name */,\n"
1907                                     "\t\t %s /* nick */,\n"
1908                                     "\t\t %s /* blurb */,\n"
1909                                     "\t\t %s /* param_type */,\n"
1910                                     "\t\t %s);\n",
1911                                     p->name,
1912                                     value_for_print (p->nick, "NULL"),
1913                                     value_for_print (p->blurb, "NULL"),
1914                                     type,
1915                                     flags->str);
1916                         g_free (type);
1917                 } else if (strcmp (p->gtktype, "BOXED") == 0) {
1918                         char *type = make_me_type (p->extra_gtktype,
1919                                                    "G_TYPE_BOXED");
1920                         out_printf (out, "\tparam_spec = g_param_spec_boxed\n"
1921                                     "\t\t(\"%s\" /* name */,\n"
1922                                     "\t\t %s /* nick */,\n"
1923                                     "\t\t %s /* blurb */,\n"
1924                                     "\t\t %s /* boxed_type */,\n"
1925                                     "\t\t %s);\n",
1926                                     p->name,
1927                                     value_for_print (p->nick, "NULL"),
1928                                     value_for_print (p->blurb, "NULL"),
1929                                     type,
1930                                     flags->str);
1931                         g_free (type);
1932                 } else if (strcmp (p->gtktype, "POINTER") == 0) {
1933                         out_printf (out, "\tparam_spec = g_param_spec_pointer\n"
1934                                     "\t\t(\"%s\" /* name */,\n"
1935                                     "\t\t %s /* nick */,\n"
1936                                     "\t\t %s /* blurb */,\n"
1937                                     "\t\t %s);\n",
1938                                     p->name,
1939                                     value_for_print (p->nick, "NULL"),
1940                                     value_for_print (p->blurb, "NULL"),
1941                                     flags->str);
1942                 /* FIXME: VALUE_ARRAY */
1943                 } else if (strcmp (p->gtktype, "CLOSURE") == 0) {
1944                         out_printf (out, "\tparam_spec = g_param_spec_pointer\n"
1945                                     "\t\t(\"%s\" /* name */,\n"
1946                                     "\t\t %s /* nick */,\n"
1947                                     "\t\t %s /* blurb */,\n"
1948                                     "\t\t %s);\n",
1949                                     p->name,
1950                                     value_for_print (p->nick, "NULL"),
1951                                     value_for_print (p->blurb, "NULL"),
1952                                     flags->str);
1953                 } else if (strcmp (p->gtktype, "OBJECT") == 0) {
1954                         char *type = make_me_type (p->extra_gtktype,
1955                                                    "G_TYPE_BOXED");
1956                         out_printf (out, "\tparam_spec = g_param_spec_object\n"
1957                                     "\t\t(\"%s\" /* name */,\n"
1958                                     "\t\t %s /* nick */,\n"
1959                                     "\t\t %s /* blurb */,\n"
1960                                     "\t\t %s /* object_type */,\n"
1961                                     "\t\t %s);\n",
1962                                     p->name,
1963                                     value_for_print (p->nick, "NULL"),
1964                                     value_for_print (p->blurb, "NULL"),
1965                                     type,
1966                                     flags->str);
1967                         g_free (type);
1968                 } else {
1969                         error_printf (GOB_ERROR, p->line_no,
1970                                       "%s type is not supported by properties",
1971                                       p->gtktype);
1972                 }
1973
1974                 s = g_strdup (p->name);
1975                 gob_strup (s);
1976                 out_printf (out, "\tg_object_class_install_property (g_object_class,\n"
1977                             "\t\tPROP_%s,\n"
1978                             "\t\tparam_spec);\n", s);
1979                 g_free (s);
1980
1981                 g_string_free (flags, TRUE);
1982         }
1983 }
1984
1985 static void
1986 make_arguments(Class *c)
1987 {
1988         GList *li;
1989         if (get_properties > 0)
1990                 out_printf(out, "\tg_object_class->get_property = ___object_get_property;\n");
1991         if (set_properties > 0)
1992                 out_printf(out, "\tg_object_class->set_property = ___object_set_property;\n");
1993         out_printf (out, "    {\n");
1994         for (li = c->nodes; li != NULL; li = li->next) {
1995                 Node *n = li->data;
1996                 if ((n->type == PROPERTY_NODE && ! ((Property *) n)->override)
1997                     || n->type == ARGUMENT_NODE) {
1998                         out_printf(out, "\tGParamSpec   *param_spec;\n\n");
1999                         break;
2000                 }
2001         }
2002
2003         for (li = c->nodes; li != NULL; li = li->next) {
2004                 Node *n = li->data;
2005                 if (n->type == PROPERTY_NODE)
2006                         make_property ((Property *)n);
2007                 else if (n->type == ARGUMENT_NODE)
2008                         make_argument ((Argument *)n);
2009         }
2010         out_printf(out, "    }\n");
2011 }
2012
2013 static void
2014 print_initializer(Method *m, Variable *v)
2015 {
2016         char *root;
2017         
2018         if(v->glade_widget)
2019                 return;
2020
2021         if(v->initializer == NULL)
2022                 return;
2023
2024         if(v->scope == PRIVATE_SCOPE)
2025                 root = g_strconcat(((FuncArg *)m->args->data)->name,
2026                                    "->_priv", NULL);
2027         else
2028                 root = g_strdup(((FuncArg *)m->args->data)->name);
2029
2030         if(v->initializer_line > 0)
2031                 out_addline_infile(out, v->initializer_line);
2032
2033         if (v->initializer_simple)
2034                 out_printf(out, "\t%s->%s = %s;\n",
2035                    root, v->id, v->initializer);
2036         else if (!strcmp(v->id, "_glade_xml"))
2037                 out_printf(out,v->initializer, ((FuncArg *)m->args->data)->name);
2038         else
2039                 out_printf(out,v->initializer);
2040
2041         if(v->initializer_line > 0)
2042                 out_addline_outfile(out);
2043
2044         g_free(root);
2045 }
2046
2047 static void
2048 print_glade_widget(Method *m, Variable *v)
2049 {
2050         char *root;
2051   char *cast;
2052         
2053         if(!v->glade_widget)
2054                 return;
2055
2056         if(v->scope == PRIVATE_SCOPE)
2057                 root = g_strconcat(((FuncArg *)m->args->data)->name,
2058                                    "->_priv", NULL);
2059         else
2060                 root = g_strdup(((FuncArg *)m->args->data)->name);
2061
2062         cast = get_type(v->vtype, FALSE);
2063         out_printf(out, "\t%s->%s = (%s)glade_xml_get_widget(%s->_glade_xml, \"%s\");\n",
2064                    root, v->id, cast, root, v->id);
2065
2066         g_free(root);
2067 }
2068         
2069 static void
2070 print_destructor (Variable *v)
2071 {
2072         const char *root;
2073
2074         if(v->destructor == NULL)
2075                 return;
2076
2077         if(v->scope == PRIVATE_SCOPE)
2078                 root = "self->_priv";
2079         else
2080                 root = "self";
2081
2082         if(v->destructor_simple) {
2083                 if(v->destructor_line > 0)
2084                         out_addline_infile(out, v->destructor_line);
2085
2086                 if (for_cpp) {
2087                         out_printf(out, "\tif(%s->%s) { "
2088                                    "(reinterpret_cast<void (*)(void *)>(%s)) ((gpointer)%s->%s); "
2089                                    "%s->%s = NULL; }\n",
2090                                    root, v->id, v->destructor, root, v->id,
2091                                    root, v->id);
2092                 } else {
2093                         out_printf(out, "\tif(%s->%s) { "
2094                                    "%s ((gpointer) %s->%s); "
2095                                    "%s->%s = NULL; }\n",
2096                                    root, v->id, v->destructor, root, v->id,
2097                                    root, v->id);
2098                 }
2099
2100                 if(v->destructor_line > 0)
2101                         out_addline_outfile(out);
2102         } else {
2103                 out_printf(out, "#define %s (%s->%s)\n", v->id, root, v->id);
2104                 out_printf(out, "#define VAR %s\n", v->id);
2105                 out_printf(out, "\t{\n");
2106                 if(v->destructor_line > 0)
2107                         out_addline_infile(out, v->destructor_line);
2108
2109                 out_printf(out, "\t%s}\n", v->destructor);
2110
2111                 if(v->destructor_line > 0)
2112                         out_addline_outfile(out);
2113                 out_printf(out, "\tmemset(&%s, 0, sizeof(%s));\n",
2114                            v->id, v->id);
2115                 out_printf(out, "#undef VAR\n");
2116                 out_printf(out, "#undef %s\n", v->id);
2117         }
2118 }
2119
2120 static void
2121 add_dispose (Class *c)
2122 {
2123         out_printf(out, "\nstatic void\n"
2124                    "___dispose (GObject *obj_self)\n"
2125                    "{\n");
2126         out_printf(out,
2127                    "#define __GOB_FUNCTION__ \"%s::dispose\"\n",
2128                    c->otype);
2129
2130         if (unreftors > 0) {
2131                 out_printf (out, "\t%s *self%s = %s (obj_self);\n",
2132                             typebase,
2133                             ! no_gnu ? " G_GNUC_UNUSED" : "",
2134                             macrobase);
2135         }
2136
2137         if (dispose_handler != NULL) {
2138                 /* so we get possible bad argument warning */
2139                 if (dispose_handler->line_no > 0)
2140                         out_addline_infile (out, dispose_handler->line_no);
2141                 out_printf (out, "\t___%x_%s_dispose(obj_self);\n",
2142                             (guint)dispose_handler->unique_id, funcbase);
2143                 if (dispose_handler->line_no > 0)
2144                         out_addline_outfile (out);
2145         } else {
2146                 out_printf (out,
2147                             "\tif (G_OBJECT_CLASS (parent_class)->dispose) \\\n"
2148                             "\t\t(* G_OBJECT_CLASS (parent_class)->dispose) (obj_self);\n");
2149         }
2150
2151         if (unreftors > 0) {
2152                 GList *li;
2153                 for(li = ((Class *)class)->nodes;
2154                     li != NULL;
2155                     li = li->next) {
2156                         Node *n = li->data;
2157                         Variable *v = (Variable *)n;
2158                         if (n->type == VARIABLE_NODE &&
2159                             v->scope != CLASS_SCOPE &&
2160                             v->destructor_unref)
2161                                 print_destructor (v);
2162                 }
2163         }
2164
2165         out_printf(out, "}\n"
2166                    "#undef __GOB_FUNCTION__\n\n");
2167 }
2168
2169 static void
2170 add_finalize (Class *c)
2171 {
2172         out_printf(out,
2173                    "\nstatic void\n"
2174                    "___finalize(GObject *obj_self)\n"
2175                    "{\n");
2176         out_printf(out,
2177                    "#define __GOB_FUNCTION__ \"%s::finalize\"\n",
2178                    c->otype);
2179
2180         if (privates > 0 ||
2181             destructors > 0) {
2182                 const char *unused = "";
2183                 if ( ! no_gnu)
2184                         unused = " G_GNUC_UNUSED";
2185                 out_printf(out, "\t%s *self%s = %s (obj_self);\n",
2186                            typebase, unused, macrobase);
2187         }
2188         if (privates > 0) {
2189                 const char *unused = "";
2190                 if ( ! no_gnu)
2191                         unused = " G_GNUC_UNUSED";
2192                 out_printf(out, "\tgpointer priv%s = self->_priv;\n",
2193                            unused);
2194         }
2195
2196         if(finalize_handler) {
2197                 /* so we get possible bad argument warning */
2198                 if(finalize_handler->line_no > 0)
2199                         out_addline_infile(out, finalize_handler->line_no);
2200                 out_printf(out, "\t___%x_%s_finalize(obj_self);\n",
2201                            (guint)finalize_handler->unique_id, funcbase);
2202                 if(finalize_handler->line_no > 0)
2203                         out_addline_outfile(out);
2204         } else {
2205                 out_printf(out,
2206                            "\tif(G_OBJECT_CLASS(parent_class)->finalize) \\\n"
2207                            "\t\t(* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);\n");
2208         }
2209
2210         if (destructors > 0) {
2211                 GList *li;
2212                 for (li = ((Class *)class)->nodes;
2213                      li != NULL;
2214                      li = li->next) {
2215                         Node *n = li->data;
2216                         Variable *v = (Variable *)n;
2217                         if (n->type == VARIABLE_NODE &&
2218                             v->scope != CLASS_SCOPE &&
2219                             ! v->destructor_unref)
2220                                 print_destructor (v);
2221                 }
2222         }
2223
2224         out_printf(out, "}\n"
2225                    "#undef __GOB_FUNCTION__\n\n");
2226 }
2227
2228 static void
2229 make_bonobo_object_epv (Class *c, const char *classname)
2230 {
2231         GList *li;
2232         gboolean added_line = FALSE;
2233
2234         for (li = c->nodes; li != NULL; li = li->next) {
2235                 Node *n = li->data;
2236                 Method *m = (Method *)n;
2237                 if(n->type != METHOD_NODE ||
2238                    m->method == OVERRIDE_METHOD)
2239                         continue;
2240
2241                 if (m->bonobo_object_func) {
2242                         if(m->line_no > 0) {
2243                                 out_addline_infile(out, m->line_no);
2244                                 added_line = TRUE;
2245                         } else if (m->line_no == 0 &&
2246                                    added_line) {
2247                                 out_addline_outfile(out);
2248                                 added_line = FALSE;
2249                         }
2250                         out_printf (out, "\t%s->_epv.%s = self_%s;\n",
2251                                     classname, m->id, m->id);
2252                 }
2253         }
2254         if (added_line)
2255                 out_addline_outfile(out);
2256 }
2257
2258 static void
2259 add_inits(Class *c)
2260 {
2261         const char *unused = "";
2262         GList *li;
2263
2264         if ( ! no_gnu)
2265                 unused = " G_GNUC_UNUSED";
2266
2267         for(li=c->nodes;li;li=g_list_next(li)) {
2268                 Node *n = li->data;
2269                 Method *m;
2270
2271                 if(n->type != METHOD_NODE)
2272                         continue;
2273                 m = (Method *)n;
2274                 if(m->method == INIT_METHOD) {
2275                         if(m->line_no > 0)
2276                                 out_addline_infile(out, m->line_no);
2277                         print_method(out, "static ", "\n", "", " ", "", "\n",
2278                                      m, FALSE, FALSE, TRUE, TRUE, FALSE);
2279                         if(m->line_no > 0)
2280                                 out_addline_outfile(out);
2281                         out_printf(out, "{\n"
2282                                    "#define __GOB_FUNCTION__ \"%s::init\"\n",
2283                                    c->otype);
2284                         if (privates > 0) {
2285                                 out_printf(out, "\t%s->_priv = "
2286                                                 "G_TYPE_INSTANCE_GET_PRIVATE(%s,%s,%sPrivate);\n",
2287                                                 ((FuncArg *)m->args->data)->name,
2288                                                 ((FuncArg *)m->args->data)->name,
2289                                                 macrotype,
2290                                                 typebase);
2291                         } else if(always_private_struct) {
2292                                 out_printf(out, "\t%s->_priv = NULL;\n",
2293                                            ((FuncArg *)m->args->data)->name);
2294                         }
2295                         if(initializers > 0) {
2296                                 GList *li;
2297                                 for(li = ((Class *)class)->nodes;
2298                                     li != NULL;
2299                                     li = li->next) {
2300                                         Node *n = li->data;
2301                                         Variable *v = (Variable *)n;
2302                                         if(n->type != VARIABLE_NODE ||
2303                                            v->scope == CLASS_SCOPE)
2304                                                 continue;
2305                                         print_initializer(m, v);
2306                                 }
2307                         }
2308                         if(glade_widgets > 0) {
2309                                 GList *li;
2310                                 for(li = ((Class *)class)->nodes;
2311                                     li != NULL;
2312                                     li = li->next) {
2313                                         Node *n = li->data;
2314                                         Variable *v = (Variable *)n;
2315                                         if(n->type != VARIABLE_NODE ||
2316                                            v->scope == CLASS_SCOPE)
2317                                                 continue;
2318                                         print_glade_widget(m, v);
2319                                 }
2320                         }
2321                 } else if(m->method == CLASS_INIT_METHOD) {
2322                         gboolean did_base_obj = FALSE;
2323
2324                         if(m->line_no > 0)
2325                                 out_addline_infile(out, m->line_no);
2326                         print_method(out, "static ", "\n", "", " ", "", "\n",
2327                                      m, FALSE, FALSE, TRUE, TRUE, FALSE);
2328                         if(m->line_no > 0)
2329                                 out_addline_outfile(out);
2330                         out_printf(out, "{\n"
2331                                    "#define __GOB_FUNCTION__ \"%s::class_init\"\n",
2332                                    c->otype);
2333                         if (set_properties > 0 ||
2334                             get_properties > 0 ||
2335                             signals > 0 ||
2336                             need_dispose ||
2337                             need_finalize) {
2338                                 out_printf(out,
2339                                            "\tGObjectClass *"
2340                                            "g_object_class%s = "
2341                                            "(GObjectClass*) %s;\n",
2342                                            unused,
2343                                            ((FuncArg *)m->args->data)->name);
2344                                 did_base_obj = TRUE;
2345                         }
2346
2347                         if (overrides > 0)
2348                                 add_overrides (c,
2349                                                ((FuncArg *)m->args->data)->name,
2350                                                did_base_obj);
2351
2352                         if (privates > 0)
2353                                 out_printf (out,
2354                                             "\n\tg_type_class_add_private(%s,sizeof(%sPrivate));\n",
2355                                             ((FuncArg *)m->args->data)->name,
2356                                             typebase);
2357
2358                         if (initializers > 0) {
2359                                 GList *li;
2360                                 for(li = ((Class *)class)->nodes;
2361                                     li != NULL;
2362                                     li = li->next) {
2363                                         Node *n = li->data;
2364                                         Variable *v = (Variable *)n;
2365                                         if(n->type == VARIABLE_NODE &&
2366                                            v->scope == CLASS_SCOPE)
2367                                                 print_initializer(m, v);
2368                                 }
2369                         }
2370                         
2371                         out_printf(out, "\n\tparent_class = ");
2372                         if(for_cpp)
2373                                 out_printf(out, "(%sClass *)", ptypebase);
2374                         out_printf(out, "g_type_class_ref (%s);\n",
2375                                    pmacrotype);
2376
2377                         if(signals > 0)
2378                                 add_signals(c);
2379
2380                         set_def_handlers(c, ((FuncArg *)m->args->data)->name);
2381
2382                         /* if there are no handlers for these things, we
2383                          * need to set them up here */
2384                         if(need_dispose && !dispose_handler)
2385                                 out_printf(out, "\tg_object_class->dispose "
2386                                            "= ___dispose;\n");
2387                         if(need_finalize && !finalize_handler)
2388                                 out_printf(out, "\tg_object_class->finalize = "
2389                                            "___finalize;\n");
2390                         
2391                         if(get_properties > 0 || set_properties > 0)
2392                                 make_arguments(c);
2393
2394                         if (c->bonobo_object_class != NULL) {
2395                                 make_bonobo_object_epv (c, ((FuncArg *)m->args->data)->name);
2396                         }
2397                 } else
2398                         continue;
2399
2400                 if(m->cbuf) {
2401                         out_printf(out, " {\n");
2402                         out_addline_infile(out, m->ccode_line);
2403                         out_printf(out, "%s\n", m->cbuf);
2404                         out_addline_outfile(out);
2405                         out_printf(out, " }\n");
2406                 }
2407                 out_printf(out, "}\n"
2408                            "#undef __GOB_FUNCTION__\n");
2409         }
2410 }
2411
2412 static void
2413 add_argument (Argument *a, gboolean is_set)
2414 {
2415         char *s;
2416         char *cbuf;
2417         char *the_type_lower;
2418         int line_no;
2419
2420         if(is_set) {
2421                 cbuf = a->set;
2422                 line_no = a->set_line;
2423         } else {
2424                 cbuf = a->get;
2425                 line_no = a->get_line;
2426         }
2427         if (cbuf == NULL)
2428                 return;
2429         s = g_strdup(a->name);
2430         gob_strup (s);
2431         out_printf(out, "\tcase PROP_%s:\n\t{", s);
2432
2433         the_type_lower = g_strdup (a->gtktype);
2434         gob_strdown (the_type_lower);
2435
2436         /* HACK because there is no g_value_set/get for unichar */
2437         if (strcmp (the_type_lower, "unichar") == 0) {
2438                 g_free (the_type_lower);
2439                 the_type_lower = g_strdup ("uint");
2440         }
2441
2442         if (is_set) {
2443                 char *cast;
2444                 const char *unused = "";
2445
2446                 if ( ! no_gnu && ! for_cpp /* g++ has a cow with this */) {
2447                         unused = " G_GNUC_UNUSED";
2448                 }
2449
2450                 if (a->atype != NULL &&
2451                     /* gcc -Wbad-function-cast is wanking stupid, moronic
2452                        and otherwise evil so we should just use a (gint)
2453                        or (guint) cast, not the specific type cast */
2454                     (for_cpp ||
2455                      (strcmp (a->gtktype, "ENUM") != 0 &&
2456                      strcmp (a->gtktype, "FLAGS") != 0)))
2457                         cast = get_type (a->atype, TRUE);
2458                 else
2459                         cast = g_strdup (get_cast (a->gtktype, FALSE));
2460
2461                 out_printf (out, "\t%s ARG%s = (%s) g_value_get_%s (VAL);\n",
2462                             cast, unused, cast, the_type_lower);
2463
2464                 g_free (cast);
2465         } else if ( ! is_set) {
2466                 char *cast;
2467
2468                 if (a->atype != NULL)
2469                         cast = get_type (a->atype, TRUE);
2470                 else
2471                         cast = g_strdup (get_cast (a->gtktype, FALSE));
2472                 out_printf (out, "\t%s ARG;\n"
2473                             "\tmemset (&ARG, 0, sizeof (%s));\n",
2474                             cast, cast);
2475
2476                 g_free(cast);
2477         }
2478         g_free (s);
2479         out_printf(out, "\t\t{\n");
2480         if (line_no > 0)
2481                 out_addline_infile (out, line_no);
2482         out_printf (out, "%s\n", cbuf);
2483         if (line_no > 0)
2484                 out_addline_outfile (out);
2485         out_printf (out, "\t\t}\n");
2486         if ( ! is_set) {
2487                 if (strcmp (a->gtktype, "OBJECT") == 0)
2488                         out_printf (out, "\t\tg_value_set_%s (VAL, G_OBJECT (ARG));\n",
2489                                     the_type_lower);
2490                 else
2491                         out_printf (out, "\t\t"
2492                                     "g_value_set_%s (VAL, ARG);\n",
2493                                     the_type_lower);
2494         }
2495         g_free (the_type_lower);
2496
2497         if (is_set &&
2498             (no_gnu || for_cpp /* g++ has a cow with G_GNUC_UNUSED */)) {
2499                 out_printf (out, "\t\tif (&ARG) break;\n");
2500         }
2501
2502         out_printf (out, "\t\tbreak;\n");
2503
2504         out_printf (out, "\t}\n");
2505 }
2506
2507 static void
2508 add_property (Property *p, gboolean is_set)
2509 {
2510         const char *cbuf;
2511         char *the_type_lower;
2512         char *name_upper;
2513         int line_no;
2514
2515         if (is_set) {
2516                 cbuf = p->set;
2517                 line_no = p->set_line;
2518         } else {
2519                 cbuf = p->get;
2520                 line_no = p->get_line;
2521         }
2522         if (cbuf == NULL)
2523                 return;
2524
2525         name_upper = g_strdup (p->name);
2526         gob_strup (name_upper);
2527         the_type_lower = g_strdup (p->gtktype);
2528         gob_strdown (the_type_lower);
2529
2530         out_printf (out, "\tcase PROP_%s:\n", name_upper);
2531
2532         out_printf(out, "\t\t{\n");
2533         if (line_no > 0)
2534                 out_addline_infile (out, line_no);
2535         out_printf (out, "%s\n", cbuf);
2536         if (line_no > 0)
2537                 out_addline_outfile (out);
2538         out_printf (out, "\t\t}\n");
2539
2540         g_free (name_upper);
2541         g_free (the_type_lower);
2542
2543         out_printf (out, "\t\tbreak;\n");
2544 }
2545
2546 static void
2547 add_getset_arg(Class *c, gboolean is_set)
2548 {
2549         GList *li;
2550         const char *unused = "";
2551         const char *hack_unused = "";
2552
2553         if ( ! no_gnu && ! for_cpp /* g++ has a cow with this */) {
2554                 unused = " G_GNUC_UNUSED";
2555         } else {
2556                 hack_unused = "if (&VAL || &pspec) break;\n\t\t";
2557         }
2558
2559         out_printf(out, "\nstatic void\n"
2560                    "___object_%s_property (GObject *object,\n"
2561                    "\tguint property_id,\n"
2562                    "\t%sGValue *VAL%s,\n"
2563                    "\tGParamSpec *pspec%s)\n"
2564                    "#define __GOB_FUNCTION__ \"%s::%s_property\"\n"
2565                    "{\n"
2566                    "\t%s *self%s;\n\n"
2567                    "\tself = %s (object);\n\n"
2568                    "\tswitch (property_id) {\n",
2569                    is_set ? "set" : "get",
2570                    is_set ? "const " : "",
2571                    unused,
2572                    unused,
2573                    c->otype,
2574                    is_set ? "set" : "get",
2575                    typebase,
2576                    unused,
2577                    macrobase);
2578
2579         for (li = c->nodes; li != NULL; li = li->next) {
2580                 Node *n = li->data;
2581                 if (n->type == PROPERTY_NODE)
2582                         add_property ((Property *)n, is_set);
2583                 else if (n->type == ARGUMENT_NODE)
2584                         add_argument ((Argument *)n, is_set);
2585         }
2586         out_printf (out, "\tdefault:\n"
2587                     "/* Apparently in g++ this is needed, glib is b0rk */\n"
2588                     "#ifndef __PRETTY_FUNCTION__\n"
2589                     "#  undef G_STRLOC\n"
2590                     "#  define G_STRLOC __FILE__ \":\" G_STRINGIFY (__LINE__)\n"
2591                     "#endif\n"
2592                     "\t\tG_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);\n"
2593                     "\t\t%sbreak;\n\t}\n"
2594                     "}\n"
2595                     "#undef __GOB_FUNCTION__\n", hack_unused);
2596 }
2597
2598 static void
2599 print_checks (Method *m, FuncArg *fa)
2600 {
2601         GList *li;
2602         gboolean is_void;
2603         gboolean checked_null = FALSE;
2604         is_void = (strcmp(m->mtype->name, "void")==0 &&
2605                    m->mtype->pointer == NULL);
2606         
2607         for(li = fa->checks; li != NULL; li = li->next) {
2608                 Check *ch = li->data;
2609                 char *s;
2610                 /* point to the method prot in .gob for failed checks */
2611                 if(m->line_no > 0)
2612                         out_addline_infile(out, m->line_no);
2613                 if(is_void)
2614                         out_printf(out, "\tg_return_if_fail (");
2615                 else
2616                         out_printf(out, "\tg_return_val_if_fail (");
2617                 switch(ch->chtype) {
2618                 case NULL_CHECK:
2619                         out_printf(out, "%s != NULL", fa->name);
2620                         checked_null = TRUE;
2621                         break;
2622                 case TYPE_CHECK:
2623                         s = make_pre_macro(fa->atype->name, "IS");
2624                         if(checked_null)
2625                                 out_printf(out, "%s (%s)", s, fa->name);
2626                         else
2627                                 /* if not check null, null may be valid */
2628                                 out_printf(out, "!(%s) || %s (%s)", fa->name,
2629                                            s, fa->name);
2630                         g_free(s);
2631                         break;
2632                 case LT_CHECK:
2633                         out_printf(out, "%s < %s", fa->name, ch->number);
2634                         break;
2635                 case GT_CHECK:
2636                         out_printf(out, "%s > %s", fa->name, ch->number);
2637                         break;
2638                 case LE_CHECK:
2639                         out_printf(out, "%s <= %s", fa->name, ch->number);
2640                         break;
2641                 case GE_CHECK:
2642                         out_printf(out, "%s >= %s", fa->name, ch->number);
2643                         break;
2644                 case EQ_CHECK:
2645                         out_printf(out, "%s == %s", fa->name, ch->number);
2646                         break;
2647                 case NE_CHECK:
2648                         out_printf(out, "%s != %s", fa->name, ch->number);
2649                         break;
2650                 }
2651                 if(is_void)
2652                         out_printf(out, ");\n");
2653                 else {
2654                         out_printf(out, ", (");
2655                         print_type(out, m->mtype, TRUE);
2656                         out_printf(out, ")%s);\n",
2657                                 m->onerror?m->onerror:"0");
2658                 }
2659         }
2660 }
2661
2662 static void
2663 print_preconditions(Method *m)
2664 {
2665         GList *li;
2666         
2667         for(li=m->args;li;li=g_list_next(li)) {
2668                 FuncArg *fa = li->data;
2669                 if(fa->checks)
2670                         print_checks(m, fa);
2671         }
2672         if(m->line_no>0)
2673                 out_addline_outfile(out);
2674 }
2675
2676 static void
2677 print_method_body (Method *m, gboolean pre, gboolean unused_self)
2678 {
2679         if (m->line_no > 0)
2680                 out_addline_outfile(out);
2681         out_printf(out, "{\n"
2682                    "#define __GOB_FUNCTION__ \"%s::%s\"\n",
2683                    ((Class *)class)->otype,
2684                    m->id);
2685         if (pre)
2686                 print_preconditions(m);
2687
2688         if ( ! pre &&
2689              unused_self &&
2690             (no_gnu || for_cpp) &&
2691             m->args != NULL &&
2692             ((FuncArg *)(m->args->data))->name != NULL &&
2693             strcmp (((FuncArg *)(m->args->data))->name, "self") == 0) {
2694                 out_printf (out, "\tif (&self) { ; }\n");
2695         }
2696
2697         /* Note: the trailing }'s are on one line, this is so
2698            that we get the no return warning correctly and point to
2699            the correct line in the .gob file, yes this is slightly
2700            ugly in the .c file, but that is not supposed to be
2701            human readable anyway. */
2702         if(m->cbuf) {
2703                 out_printf(out, "{\n");
2704                 if(m->ccode_line>0)
2705                         out_addline_infile(out, m->ccode_line);
2706                 out_printf(out, "\t%s}", m->cbuf);
2707         }
2708
2709         /* Note, there is no \n between the last } and this } so that
2710          * errors/warnings reported on the end of the body get pointed to the
2711          * right line in the .gob source */
2712         out_printf(out, "}\n");
2713
2714         if(m->cbuf)
2715                 out_addline_outfile(out);
2716         out_printf(out, "#undef __GOB_FUNCTION__\n");
2717 }
2718
2719 static void
2720 put_signal_args (Method *m)
2721 {
2722         GList *li;
2723         GList *ali;
2724         int i;
2725
2726         if (m->args->next == NULL)
2727                 return;
2728
2729         for (ali = m->gtktypes->next, li = m->args->next, i = 1;
2730              li != NULL && ali != NULL;
2731              li = li->next, ali = ali->next, i++) {
2732                 FuncArg *fa = li->data;
2733                 char *str = ali->data;
2734                 char *cast = g_strdup (get_cast (str, FALSE));
2735                 /* FIXME: This code is so fucking ugly it hurts */
2736                 gboolean do_static = 
2737                         (strcmp  (str, "STRING") == 0 ||
2738                          strcmp  (str, "BOXED") == 0 ||
2739                          strncmp (str, "BOXED_", 6) == 0);
2740                 char *set_func;
2741                 char *t;
2742
2743                 if (cast == NULL) {
2744                         cast = get_type (fa->atype, TRUE);
2745                 }
2746                 /* we should have already proved before that
2747                    the we know all the types */
2748                 g_assert (cast != NULL);
2749
2750                 if (strncmp (str, "BOXED_", 6) == 0)
2751                         t = g_strdup (&(str[6]));
2752                 else
2753                         t = g_strconcat ("G_TYPE_", str, NULL);
2754
2755                 out_printf (out,
2756                             "\t___param_values[%d].g_type = 0;\n"
2757                             "\tg_value_init (&___param_values[%d], %s);\n",
2758                             i, i, t);
2759                 g_free (t);
2760
2761                 if (strcmp (str, "UNICHAR") == 0)
2762                         /* hack because glib is braindamaged */
2763                         set_func = g_strdup ("g_value_set_uint");
2764                 else if (strncmp (str, "BOXED_", 6) == 0)
2765                         set_func = g_strdup ("g_value_set_static_boxed");
2766                 else
2767                         set_func = g_strdup_printf ("g_value_set%s_%s",
2768                                                     do_static ? "_static" : "",
2769                                                     str);
2770                 gob_strdown (set_func);
2771
2772                 out_printf (out, "\t%s (&___param_values[%d], (%s) %s);\n\n",
2773                             set_func, i, cast, fa->name);
2774
2775                 g_free (set_func);
2776                 g_free (cast);
2777         }
2778 }
2779
2780 static void
2781 clear_signal_args (Method *m)
2782 {
2783         GList *li;
2784         int i;
2785
2786         out_printf (out, "\n\tg_value_unset (&___param_values[0]);\n");
2787
2788         if (m->args->next == NULL)
2789                 return;
2790
2791         for (li = m->args->next, i = 1;
2792              li != NULL;
2793              li = li->next, i++) {
2794                 out_printf (out,
2795                             "\tg_value_unset (&___param_values[%d]);\n", i);
2796         }
2797 }
2798
2799 static char *
2800 get_arg_names_for_macro (Method *m)
2801 {
2802         const char *sep;
2803         GList *li;
2804         GString *gs = g_string_new(NULL);
2805         sep = "";
2806         for(li=m->args;li;li=g_list_next(li)) {
2807                 FuncArg *arg = li->data;
2808                 g_string_sprintfa (gs, "%s___%s", sep, arg->name);
2809                 sep = ",";
2810         }
2811         return g_string_free (gs, FALSE);
2812 }
2813
2814 static void
2815 put_method(Method *m)
2816 {
2817         char *s, *args, *doc;
2818         gboolean is_void;
2819         is_void = (strcmp(m->mtype->name, "void")==0 &&
2820                    m->mtype->pointer == NULL);
2821         out_printf(out, "\n");
2822         if(m->method != OVERRIDE_METHOD) {
2823                 doc = get_gtk_doc(m->id);
2824                 if(doc) {
2825                         out_printf(out, "%s", doc);
2826                         g_free(doc);
2827                 }
2828         }
2829         switch(m->method) {
2830         case REGULAR_METHOD:
2831                 if(m->line_no > 0)
2832                         out_addline_infile(out, m->line_no);
2833                 if(m->scope == PRIVATE_SCOPE)
2834                         print_method(out, "static ", "\n", "", " ", "", "\n",
2835                                      m, FALSE, FALSE, TRUE, FALSE, FALSE);
2836                 else /* PUBLIC, PROTECTED */
2837                         print_method(out, "", "\n", "", " ", "", "\n",
2838                                      m, FALSE, FALSE, TRUE, FALSE, FALSE);
2839                 print_method_body(m, TRUE, TRUE);
2840                 /* the outfile line was added above */
2841                 break;
2842         case SIGNAL_FIRST_METHOD:
2843         case SIGNAL_LAST_METHOD:
2844                 if(m->line_no > 0)
2845                         out_addline_infile(out, m->line_no);
2846                 if(m->scope == PRIVATE_SCOPE)
2847                         print_method(out, "static ", "\n", "", " ", "", "\n",
2848                                      m, FALSE, FALSE, TRUE, FALSE, FALSE);
2849                 else /* PUBLIC, PROTECTED */
2850                         print_method(out, "", "\n", "", " ", "", "\n",
2851                                      m, FALSE, FALSE, TRUE, FALSE, FALSE);
2852                 out_addline_outfile (out);
2853
2854                 out_printf (out, "{\n");
2855
2856                 out_printf (out,
2857                             "\tGValue ___param_values[%d];\n"
2858                             "\tGValue ___return_val;\n\n"
2859                             "memset (&___return_val, 0, "
2860                               "sizeof (___return_val));\n"
2861                             "memset (&___param_values, 0, "
2862                               "sizeof (___param_values));\n\n",
2863                             g_list_length (m->args));
2864
2865                 print_preconditions (m);
2866
2867                 out_printf (out,
2868                             "\n\t___param_values[0].g_type = 0;\n"
2869                             "\tg_value_init (&___param_values[0], G_TYPE_FROM_INSTANCE (%s));\n"
2870                             "\tg_value_set_instance (&___param_values[0], (gpointer) %s);\n\n",
2871                             ((FuncArg *)m->args->data)->name,
2872                             ((FuncArg *)m->args->data)->name);
2873
2874                 put_signal_args (m);
2875
2876                 if (strcmp (m->gtktypes->data, "NONE") != 0) {
2877                         const char *defret = NULL;
2878
2879                         out_printf (out, "\tg_value_init (&___return_val, G_TYPE_%s);\n",
2880                                     (char *)m->gtktypes->data);
2881
2882                         if (m->defreturn != NULL)
2883                                 defret = m->defreturn;
2884                         else if (m->onerror != NULL)
2885                                 defret = m->onerror;
2886
2887                         if (defret != NULL) {
2888                                 char *set_func;
2889                                 /* FIXME: This code is so fucking ugly it hurts */
2890                                 gboolean do_static = 
2891                                         (strcmp ((char *)m->gtktypes->data, "STRING") == 0 ||
2892                                          strcmp ((char *)m->gtktypes->data, "BOXED") == 0);
2893                                 char *cast = g_strdup (get_cast (m->gtktypes->data, FALSE));
2894                                 if (cast == NULL)
2895                                         cast = get_type (m->mtype, TRUE);
2896
2897                                 if (strcmp (m->gtktypes->data, "UNICHAR") == 0)
2898                                         /* hack because glib is braindamaged */
2899                                         set_func = g_strdup ("g_value_set_uint");
2900                                 else
2901                                         set_func = g_strdup_printf ("g_value_set%s_%s",
2902                                                                     do_static ? "_static" : "",
2903                                                                     (char *)m->gtktypes->data);
2904                                 gob_strdown (set_func);
2905
2906                                 out_printf (out, "\t%s (&___return_val, (%s) (%s));\n",
2907                                             set_func, cast, defret);
2908
2909                                 g_free (set_func);
2910                                 g_free (cast);
2911                         }
2912                         out_printf (out, "\n");
2913                 }
2914
2915                 s = g_strdup (m->id);
2916                 gob_strup (s);
2917
2918                 out_printf(out, "\tg_signal_emitv (___param_values,\n"
2919                            "\t\tobject_signals[%s_SIGNAL],\n"
2920                            "\t\t0 /* detail */,\n"
2921                            "\t\t&___return_val);\n", s);
2922
2923                 g_free (s);
2924
2925                 clear_signal_args (m);
2926
2927                 if (strcmp (m->gtktypes->data, "NONE") != 0) {
2928                         char *cast = g_strdup (get_cast (m->gtktypes->data, FALSE));
2929                         char *getfunc;
2930                         /* Hack because glib is very very braindead */
2931                         gboolean do_dup = 
2932                                 (strcmp ((char *)m->gtktypes->data, "STRING") == 0 ||
2933                                  strcmp ((char *)m->gtktypes->data, "BOXED") == 0 ||
2934                                  strcmp ((char *)m->gtktypes->data, "OBJECT") == 0 ||
2935                                  strcmp ((char *)m->gtktypes->data, "PARAM") == 0);
2936
2937                         if (strcmp (m->gtktypes->data, "UNICHAR") == 0)
2938                                 /* hack because glib is braindamaged */
2939                                 getfunc = g_strdup ("g_value_get_uint");
2940                         else
2941                                 getfunc = g_strdup_printf ("g_value_%s_%s",
2942                                                            do_dup ? "dup" : "get",
2943                                                            (char *)m->gtktypes->data);
2944                         gob_strdown (getfunc);
2945
2946                         if (cast == NULL)
2947                                 cast = get_type (m->mtype, TRUE);
2948
2949                         out_printf (out,
2950                                     "\n\t{\n"
2951                                     "\t\t");
2952                         print_type (out, m->mtype, TRUE);
2953                         out_printf (out,
2954                                     " ___ret = (%s) %s (&___return_val);\n"
2955                                     "\t\tg_value_unset (&___return_val);\n"
2956                                     "\t\treturn ___ret;\n"
2957                                     "\t}\n",
2958                                     cast, getfunc);
2959
2960                         g_free (cast);
2961                         g_free (getfunc);
2962                 }
2963                 out_printf(out, "}\n");
2964
2965                 if(!m->cbuf)
2966                         break;
2967                 if(m->line_no > 0)
2968                         out_addline_infile(out, m->line_no);
2969                 print_method(out, "static ", "\n___real_", "", " ", "", "\n",
2970                              m, FALSE, FALSE, TRUE, TRUE, FALSE);
2971                 print_method_body(m, FALSE, TRUE);
2972                 /* the outfile line was added above */
2973                 break;
2974         case VIRTUAL_METHOD:
2975                 if(m->line_no > 0)
2976                         out_addline_infile(out, m->line_no);
2977                 if(m->scope==PRIVATE_SCOPE)
2978                         print_method(out, "static ", "\n", "", " ", "", "\n",
2979                                      m, FALSE, FALSE, TRUE, FALSE, FALSE);
2980                 else /* PUBLIC, PROTECTED */
2981                         print_method(out, "", "\n", "", " ", "", "\n",
2982                                      m, FALSE, FALSE, TRUE, FALSE, FALSE);
2983                 out_addline_outfile(out);
2984                 out_printf(out, "{\n"
2985                         "\t%sClass *klass;\n", typebase);
2986                 print_preconditions(m);
2987                 out_printf(out, "\tklass = %s_GET_CLASS(%s);\n\n"
2988                         "\tif(klass->%s)\n",
2989                         macrobase, ((FuncArg *)m->args->data)->name,
2990                         m->id);
2991                 if(strcmp(m->mtype->name, "void") == 0 &&
2992                    m->mtype->pointer == NULL) {
2993                         GList *li;
2994                         out_printf(out, "\t\t(*klass->%s)(%s",
2995                                    m->id,
2996                                    ((FuncArg *)m->args->data)->name);
2997                         for(li=m->args->next;li;li=g_list_next(li)) {
2998                                 FuncArg *fa = li->data;
2999                                 out_printf(out, ",%s", fa->name);
3000                         }
3001                         out_printf(out, ");\n}\n");
3002                 } else {
3003                         GList *li;
3004                         out_printf(out, "\t\treturn (*klass->%s)(%s",
3005                                    m->id,
3006                                    ((FuncArg *)m->args->data)->name);
3007                         for(li=m->args->next;li;li=g_list_next(li)) {
3008                                 FuncArg *fa = li->data;
3009                                 out_printf(out, ",%s", fa->name);
3010                         }
3011                         out_printf(out, ");\n"
3012                                 "\telse\n"
3013                                 "\t\treturn (");
3014                         print_type(out, m->mtype, TRUE);
3015                         if(m->defreturn)
3016                                 out_printf(out, ")(%s);\n}\n", m->defreturn);
3017                         else if(m->onerror)
3018                                 out_printf(out, ")(%s);\n}\n", m->onerror);
3019                         else
3020                                 out_printf(out, ")(0);\n}\n");
3021                 }
3022
3023                 if(!m->cbuf)
3024                         break;
3025                 if(m->line_no > 0)
3026                         out_addline_infile(out, m->line_no);
3027                 print_method(out, "static ", "\n___real_", "", " ", "", "\n",
3028                              m, FALSE, FALSE, TRUE, TRUE, FALSE);
3029                 print_method_body(m, FALSE, TRUE);
3030                 /* the outfile line was added above */
3031                 break;
3032         case OVERRIDE_METHOD:
3033                 if(!m->cbuf)
3034                         break;
3035                 if(m->line_no > 0)
3036                         out_addline_infile(out, m->line_no);
3037                 s = g_strdup_printf("\n___%x_", (guint)m->unique_id);
3038                 print_method(out, "static ", s, "", " ", "", "\n",
3039                              m, FALSE, FALSE, FALSE, TRUE, FALSE);
3040                 g_free(s);
3041                 out_addline_outfile(out);
3042                 s = replace_sep(m->otype, '_');
3043                 gob_strup (s);
3044                 args = get_arg_names_for_macro(m);
3045                 if(is_void) {
3046                         out_printf(out, "#define PARENT_HANDLER(%s) \\\n"
3047                                    "\t{ if(%s_CLASS(parent_class)->%s) \\\n"
3048                                    "\t\t(* %s_CLASS(parent_class)->%s)(%s); }\n",
3049                                    args, s, m->id, s, m->id, args);
3050                 } else {
3051                         out_printf(out, "#define PARENT_HANDLER(%s) \\\n"
3052                                    "\t((%s_CLASS(parent_class)->%s)? \\\n"
3053                                    "\t\t(* %s_CLASS(parent_class)->%s)(%s): \\\n"
3054                                    "\t\t(",
3055                                    args, s, m->id, s, m->id, args);
3056                         out_printf(out, "(");
3057                         print_type(out, m->mtype, TRUE);
3058                         out_printf(out, ")%s))\n",
3059                                    m->onerror?m->onerror:"0");
3060                 }
3061                 g_free(args);
3062                 g_free(s);
3063                 print_method_body(m, TRUE, TRUE);
3064                 /* the outfile line was added above */
3065                 out_printf(out, "#undef PARENT_HANDLER\n");
3066                 break;
3067         default:
3068                 break;
3069         }
3070 }
3071
3072 static void
3073 open_files(void)
3074 {
3075         char *outfile, *outfileh, *outfileph;
3076
3077         outfilebase = g_strconcat (fullfilebase, for_cpp ? ".cc" : ".c", NULL);
3078         outfile = g_strconcat(outfilebase, no_touch ? "#gob#" : "", NULL);
3079
3080         outfilehbase = g_strconcat (fullfilebase, ".h", NULL);
3081         outfileh = g_strconcat(outfilehbase, no_touch_headers ? "#gob#" : "", NULL);
3082
3083         if ((privates > 0 || protecteds > 0 ||
3084              private_header == PRIVATE_HEADER_ALWAYS) &&
3085             private_header != PRIVATE_HEADER_NEVER) {
3086                 char sep[2] = {0,0};
3087                 if (file_sep != 0)
3088                         sep[0] = file_sep;
3089                 outfilephbase = g_strconcat (fullfilebase, sep, "private.h", NULL);
3090                 outfileph = g_strconcat (outfilephbase, no_touch ? "#gob#" : "", NULL);
3091         } else {
3092                 outfilephbase = NULL;
3093                 outfileph = NULL;
3094         }
3095
3096         
3097         if ( ! no_write) {
3098                 out = fopen (outfile, "w");
3099                 if (out == NULL) {
3100                         error_printf (GOB_ERROR, 0,
3101                                       "Cannot open outfile: %s", outfile);
3102                 }
3103                 outh = fopen (outfileh, "w");
3104                 if (outh == NULL) {
3105                         error_printf (GOB_ERROR, 0,
3106                                       "Cannot open outfile: %s", outfileh);
3107                 }
3108                 if (outfileph != NULL) {
3109                         outph = fopen (outfileph, "w");
3110                         if (outph == NULL) {
3111                                 error_printf (GOB_ERROR, 0,
3112                                               "Cannot open outfile: %s",
3113                                               outfileph);
3114                         }
3115                 }
3116         }
3117 }
3118
3119 static void
3120 put_argument_nongnu_wrappers (Class *c)
3121 {
3122         GList *li;
3123
3124         if (get_properties < 0 && set_properties < 0)
3125                 return;
3126
3127         for (li = c->nodes; li != NULL; li = li->next) {
3128                 Node *n = li->data;
3129                 const char *name, *gtktype;
3130                 gboolean get, set;
3131                 Type *atype;
3132                 char *aname;
3133                 char *cast;
3134
3135                 if (n->type == ARGUMENT_NODE) {
3136                         Argument *a = (Argument *)n;
3137                         name = a->name;
3138                         gtktype = a->gtktype;
3139                         atype = a->atype;
3140                         get = a->get != NULL;
3141                         set = a->set != NULL;
3142                 } else if (n->type == PROPERTY_NODE) {
3143                         Property *p = (Property *)n;
3144                         name = p->name;
3145                         gtktype = p->gtktype;
3146                         atype = p->ptype;
3147                         get = p->get != NULL;
3148                         set = p->set != NULL;
3149                 } else {
3150                         continue;
3151                 }
3152
3153                 aname = g_strdup (name);
3154                 gob_strup (aname);
3155
3156                 if (atype != NULL)
3157                         cast = get_type (atype, TRUE);
3158                 else
3159                         cast = g_strdup (get_cast (gtktype, TRUE));
3160
3161                 if (cast != NULL) {
3162                         if (set)
3163                                 out_printf (outh, "#define %s_PROP_%s(arg)    \t"
3164                                             "\"%s\",(%s)(arg)\n",
3165                                             macrobase, aname, name, cast);
3166                         if (get)
3167                                 out_printf (outh, "#define %s_GET_PROP_%s(arg)\t"
3168                                             "\"%s\",(%s*)(arg)\n",
3169                                             macrobase, aname, name, cast);
3170                 } else {
3171                         if(set)
3172                                 out_printf (outh, "#define %s_PROP_%s(arg)    \t"
3173                                             "\"%s\",(arg)\n",
3174                                             macrobase, aname, name);
3175                         if(get)
3176                                 out_printf (outh, "#define %s_GET_PROP_%s(arg)\t"
3177                                             "\"%s\",(arg)\n",
3178                                             macrobase, aname, name);
3179                 }
3180                 g_free (cast);
3181                 g_free (aname);
3182         }
3183 }
3184
3185 static void
3186 put_argument_gnu_wrappers(Class *c)
3187 {
3188         GList *li;
3189
3190         if(get_properties < 0 && set_properties < 0)
3191                 return;
3192
3193         for (li = c->nodes; li != NULL; li = li->next) {
3194                 Node *n = li->data;
3195                 const char *name, *gtktype;
3196                 gboolean get, set;
3197                 Type *atype;
3198                 char *aname;
3199                 char *cast;
3200
3201                 if (n->type == ARGUMENT_NODE) {
3202                         Argument *a = (Argument *)n;
3203                         name = a->name;
3204                         gtktype = a->gtktype;
3205                         atype = a->atype;
3206                         get = a->get != NULL;
3207                         set = a->set != NULL;
3208                 } else if (n->type == PROPERTY_NODE) {
3209                         Property *p = (Property *)n;
3210                         name = p->name;
3211                         gtktype = p->gtktype;
3212                         atype = p->ptype;
3213                         get = p->get != NULL;
3214                         set = p->set != NULL;
3215                 } else {
3216                         continue;
3217                 }
3218
3219                 aname = g_strdup (name);
3220                 gob_strup (aname);
3221
3222                 if (atype != NULL)
3223                         cast = get_type (atype, TRUE);
3224                 else
3225                         cast = g_strdup (get_cast (gtktype, TRUE));
3226
3227                 if (cast != NULL) {
3228                         if (set)
3229                                 out_printf (outh, "#define %s_PROP_%s(arg)    \t"
3230                                            "\"%s\", __extension__ ({%sz = (arg); z;})\n",
3231                                            macrobase, aname, name, cast);
3232                         if (get)
3233                                 out_printf (outh, "#define %s_GET_PROP_%s(arg)\t"
3234                                            "\"%s\", __extension__ ({%s*z = (arg); z;})\n",
3235                                            macrobase, aname, name, cast);
3236                 } else {
3237                         if (set)
3238                                 out_printf (outh, "#define %s_PROP_%s(arg)    \t"
3239                                            "\"%s\",(arg)\n",
3240                                            macrobase, aname, name);
3241                         if (get)
3242                                 out_printf (outh, "#define %s_GET_PROP_%s(arg)\t"
3243                                            "\"%s\",(arg)\n",
3244                                            macrobase, aname, name);
3245                 }
3246                 g_free (cast);
3247                 g_free (aname);
3248         }
3249 }
3250
3251 static void
3252 print_ccode_block(CCode *cc)
3253 {
3254         FILE *fp;
3255         switch(cc->cctype) {
3256         case HT_CCODE:
3257                 /* HT code is printed exactly like normal header
3258                    code but is printed before */
3259         case H_CCODE:
3260                 fp = outh;
3261                 out_printf(fp, "\n");
3262                 break;
3263         case AT_CCODE:
3264                 /* AT code is printed exactly like normal 'all'
3265                    code but is printed before */
3266         case A_CCODE:
3267                 if(outph) {
3268                         out_printf(outph, "\n");
3269                         out_printf(outph, "%s\n", cc->cbuf);
3270                         out_addline_infile(outph, cc->line_no);
3271                         out_addline_outfile(outph);
3272                 }
3273                 out_printf(outh, "\n");
3274                 out_printf(outh, "%s\n", cc->cbuf);
3275                 fp = out;
3276                 out_printf(fp, "\n");
3277                 out_addline_infile(fp, cc->line_no);
3278                 break;
3279         default:
3280         case C_CCODE:
3281                 fp = out;
3282                 out_printf(fp, "\n");
3283                 out_addline_infile(fp, cc->line_no);
3284                 break;
3285         case PH_CCODE:
3286                 if(outph)
3287                         fp = outph;
3288                 else
3289                         fp = out;
3290                 out_printf(fp, "\n");
3291                 out_addline_infile(fp, cc->line_no);
3292                 break;
3293         }
3294         out_printf(fp, "%s\n", cc->cbuf);
3295         if(cc->cctype == C_CCODE ||
3296            cc->cctype == A_CCODE ||
3297            cc->cctype == AT_CCODE ||
3298            cc->cctype == PH_CCODE)
3299                 out_addline_outfile(fp);
3300 }
3301
3302 static void
3303 print_class_block(Class *c)
3304 {
3305         GList *li;
3306         char *s;
3307         gboolean printed_private = FALSE;
3308
3309         if (c->glade_xml)
3310         {
3311                 out_printf(outph ? outph : outh, "#include <gtk/gtk.h>\n");
3312                 out_printf(outph ? outph : outh, "#include <glade/glade-xml.h>\n\n");
3313         }
3314         
3315         if(any_special) {
3316                 out_printf(out, "/* utility types we may need */\n");
3317                 if(special_array[SPECIAL_2POINTER])
3318                         out_printf(out, "typedef struct { "
3319                                    "gpointer a; gpointer b; "
3320                                    "} ___twopointertype;\n");
3321                 if(special_array[SPECIAL_3POINTER])
3322                         out_printf(out, "typedef struct { "
3323                                    "gpointer a; gpointer b; "
3324                                    "gpointer c; "
3325                                    "} ___threepointertype;\n");
3326                 if(special_array[SPECIAL_INT_POINTER])
3327                         out_printf(out, "typedef struct { "
3328                                    "gint a; gpointer b; "
3329                                    "} ___intpointertype;\n");
3330                 out_printf(out, "\n");
3331         }
3332
3333         out_printf(outh, "\n/*\n"
3334                    " * Type checking and casting macros\n"
3335                    " */\n");
3336         out_printf(outh, "#define %s\t"
3337                    "(%s_get_type())\n",
3338                    macrotype, funcbase);
3339         out_printf(outh, "#define %s(obj)\t"
3340                    "G_TYPE_CHECK_INSTANCE_CAST((obj), %s_get_type(), %s)\n",
3341                    macrobase, funcbase, typebase);
3342         out_printf(outh, "#define %s_CONST(obj)\t"
3343                    "G_TYPE_CHECK_INSTANCE_CAST((obj), %s_get_type(), %s const)\n",
3344                    macrobase, funcbase, typebase); 
3345         out_printf(outh, "#define %s_CLASS(klass)\t"
3346                    "G_TYPE_CHECK_CLASS_CAST((klass), %s_get_type(), %sClass)\n",
3347                    macrobase, funcbase, typebase);
3348         out_printf(outh, "#define %s(obj)\t"
3349                    "G_TYPE_CHECK_INSTANCE_TYPE((obj), %s_get_type ())\n\n",
3350                    macrois, funcbase);
3351         out_printf(outh,
3352                    "#define %s_GET_CLASS(obj)\t"
3353                    "G_TYPE_INSTANCE_GET_CLASS((obj), %s_get_type(), %sClass)\n",
3354                    macrobase, funcbase, typebase);
3355
3356         if ( ! no_self_alias) {
3357                 out_printf(out, "/* self casting macros */\n");
3358                 out_printf(out, "#define SELF(x) %s(x)\n", macrobase);
3359                 out_printf(out, "#define SELF_CONST(x) %s_CONST(x)\n", macrobase);
3360                 out_printf(out, "#define IS_SELF(x) %s(x)\n", macrois);
3361                 out_printf(out, "#define TYPE_SELF %s\n", macrotype);
3362                 out_printf(out, "#define SELF_CLASS(x) %s_CLASS(x)\n\n",
3363                            macrobase);
3364                 out_printf(out, "#define SELF_GET_CLASS(x) %s_GET_CLASS(x)\n\n",
3365                            macrobase);
3366
3367                 out_printf(out, "/* self typedefs */\n");
3368                 out_printf(out, "typedef %s Self;\n", typebase);
3369                 out_printf(out, "typedef %sClass SelfClass;\n\n", typebase);
3370         }
3371
3372         if (privates > 0 ||
3373             always_private_struct) {
3374                 out_printf (outh, "\n/* Private structure type */\n");
3375                 out_printf (outh, "typedef struct _%sPrivate %sPrivate;\n",
3376                            typebase, typebase);
3377                 if (privates == 0)
3378                         out_printf (outh, "/* There are no privates, this "
3379                                     "structure is thus never defined */\n");
3380         }
3381
3382         out_printf (outh, "\n/*\n"
3383                     " * Main object structure\n"
3384                     " */\n");
3385         s = replace_sep (c->otype, '_');
3386         gob_strup (s);
3387         out_printf (outh, "#ifndef __TYPEDEF_%s__\n"
3388                     "#define __TYPEDEF_%s__\n", s, s);
3389         g_free (s);
3390         out_printf (outh, "typedef struct _%s %s;\n"
3391                     "#endif\n", typebase, typebase);
3392         out_printf (outh, "struct _%s {\n\t%s __parent__;\n",
3393                     typebase, ptypebase);
3394         for (li = c->nodes; li; li=li->next) {
3395                 static gboolean printed_public = FALSE;
3396                 Node *n = li->data;
3397                 Variable *v = (Variable *)n;
3398                 if(n->type == VARIABLE_NODE &&
3399                    v->scope == PUBLIC_SCOPE) {
3400                         if( ! printed_public) {
3401                                 out_printf(outh, "\t/*< public >*/\n");
3402                                 printed_public = TRUE;
3403                         }
3404                         put_variable((Variable *)n, outh);
3405                 }
3406         }
3407         /* put protecteds always AFTER publics */
3408         for (li = c->nodes; li != NULL; li = li->next) {
3409                 Node *n = li->data;
3410                 Variable *v = (Variable *)n;
3411                 if (n->type == VARIABLE_NODE &&
3412                     v->scope == PROTECTED_SCOPE) {
3413                         if ( ! printed_private) {
3414                                 out_printf (outh, "\t/*< private >*/\n");
3415                                 printed_private = TRUE;
3416                         }
3417                         put_variable ((Variable *)n, outh);
3418                 }
3419         }
3420         if (privates > 0 ||
3421             always_private_struct) {
3422                 if ( ! printed_private)
3423                         out_printf (outh, "\t/*< private >*/\n");
3424                 out_printf (outh, "\t%sPrivate *_priv;\n", typebase);
3425         }
3426         out_printf (outh, "};\n");
3427
3428         if (privates > 0) {
3429                 FILE *outfp;
3430
3431                 /* if we are to stick this into the private
3432                    header, if not stick it directly into the
3433                    C file */
3434                 if (outph != NULL) 
3435                         outfp = outph;
3436                 else
3437                         outfp = out;
3438
3439                 out_printf (outfp, "struct _%sPrivate {\n",
3440                             typebase);
3441                 if (privates > 0)
3442                 {
3443                  for(li=c->nodes; li; li=li->next) {
3444                          Node *n = li->data;
3445                          Variable *v = (Variable *)n;
3446                          if(n->type == VARIABLE_NODE &&
3447                                         v->scope == PRIVATE_SCOPE) {
3448                                  out_addline_infile(outfp, v->line_no);
3449                                  put_variable(v, outfp);
3450                          }
3451                         }
3452                         out_addline_outfile(outfp);
3453                 }
3454                 out_printf(outfp, "};\n");
3455         }
3456
3457         out_printf(outh, "\n/*\n"
3458                    " * Class definition\n"
3459                    " */\n");
3460         out_printf(outh, "typedef struct _%sClass %sClass;\n",
3461                    typebase, typebase);
3462         out_printf(outh,
3463                    "struct _%sClass {\n\t%sClass __parent__;\n",
3464                    typebase, ptypebase);
3465         for(li = c->nodes; li != NULL; li = li->next) {
3466                 Node *n = li->data;
3467                 if(n->type == METHOD_NODE)
3468                         put_vs_method((Method *)n);
3469         }
3470         /* If BonoboX type class put down the epv */
3471         if (c->bonobo_object_class != NULL) {
3472                 out_printf (outh,
3473                             "\t/* Bonobo object epv */\n"
3474                             "\tPOA_%s__epv _epv;\n",
3475                             c->bonobo_object_class);
3476         }
3477         /* put class scope variables */
3478         for (li = c->nodes; li != NULL; li = li->next) {
3479                 Node *n = li->data;
3480                 Variable *v = (Variable *)n;
3481                 if (n->type == VARIABLE_NODE &&
3482                     v->scope == CLASS_SCOPE)
3483                         put_variable ((Variable *)n, outh);
3484         }
3485         out_printf (outh, "};\n\n");
3486
3487         out_printf (out, "/* here are local prototypes */\n");
3488         if (set_properties > 0) {
3489                 out_printf (out, "static void ___object_set_property "
3490                             "(GObject *object, guint property_id, "
3491                             "const GValue *value, GParamSpec *pspec);\n");
3492         }
3493         if (get_properties > 0) {
3494                 out_printf (out, "static void ___object_get_property "
3495                             "(GObject *object, guint property_id, "
3496                             "GValue *value, GParamSpec *pspec);\n");
3497         }
3498
3499         out_printf (outh, "\n/*\n"
3500                     " * Public methods\n"
3501                     " */\n");
3502
3503         if ( ! overrode_get_type) {
3504                 out_printf (outh, "GType\t%s_get_type\t(void);\n", funcbase);
3505         }
3506
3507         for(li = c->nodes; li != NULL; li = li->next) {
3508                 Node *n = li->data;
3509                 if(n->type == METHOD_NODE) {
3510                         put_pub_method((Method *)n);
3511                         put_prot_method((Method *)n);
3512                         put_priv_method_prot((Method *)n);
3513                 }
3514         }
3515
3516         /* this idea is less and less apealing to me */
3517         if (signals > 0) {
3518                 out_printf (outh, "\n/*\n"
3519                             " * Signal connection wrapper macros\n"
3520                             " */\n");
3521                 if( ! no_gnu) {
3522                         out_printf(outh, "#if defined(__GNUC__) && !defined(__STRICT_ANSI__)\n");
3523                         put_signal_macros (c, TRUE);
3524                         out_printf(outh, "#else /* __GNUC__ && !__STRICT_ANSI__ */\n");
3525                         put_signal_macros (c, FALSE);
3526                         out_printf(outh, "#endif /* __GNUC__ && !__STRICT_ANSI__ */\n");
3527                 } else {
3528                         put_signal_macros (c, FALSE);
3529                         out_printf(outh, "\n");
3530                 }
3531
3532                 out_printf (out, "\n/*\n"
3533                             " * Signal connection wrapper macro shortcuts\n"
3534                             " */\n");
3535                 put_local_signal_macros (c);
3536                 out_printf(outh, "\n");
3537         }
3538
3539         /* argument wrapping macros */
3540         if(get_properties > 0 || set_properties > 0) {
3541                 out_printf(outh, "\n/*\n"
3542                            " * Argument wrapping macros\n"
3543                            " */\n");
3544                 if( ! no_gnu) {
3545                         out_printf(outh, "#if defined(__GNUC__) && !defined(__STRICT_ANSI__)\n");
3546                         put_argument_gnu_wrappers(c);
3547                         out_printf(outh, "#else /* __GNUC__ && !__STRICT_ANSI__ */\n");
3548                         put_argument_nongnu_wrappers(c);
3549                         out_printf(outh, "#endif /* __GNUC__ && !__STRICT_ANSI__ */\n\n");
3550                 } else {
3551                         put_argument_nongnu_wrappers(c);
3552                 }
3553         }
3554
3555         if(signals > 0) {
3556                 for(li = c->nodes; li != NULL; li = li->next) {
3557                         Node *n = li->data;
3558                         if(n->type == METHOD_NODE)
3559                                 add_signal_prots((Method *)n);
3560                 }
3561         }
3562
3563         add_enums (c);
3564
3565         if(any_method_to_alias(c)) {
3566                 out_printf (out, "/* Short form macros */\n");
3567                 make_method_aliases (c);
3568         }
3569
3570         add_interface_inits (c);
3571
3572         if ( ! overrode_get_type) {
3573                 if (c->bonobo_object_class != NULL)
3574                         add_bonobo_object_get_type ();
3575                 else
3576                         add_get_type ();
3577         }
3578
3579         out_printf (out, "/* a macro for creating a new object of our type */\n");
3580         out_printf (out,
3581                     "#define GET_NEW ((%s *)g_object_new(%s_get_type(), NULL))\n\n",
3582                     typebase, funcbase);
3583
3584         out_printf (out, "/* a function for creating a new object of our type */\n");
3585         out_printf (out, "#include <stdarg.h>\n");
3586         out_printf (out,
3587                     "static %s * GET_NEW_VARG (const char *first, ...)%s;\n"
3588                     "static %s *\nGET_NEW_VARG (const char *first, ...)\n"
3589                     "{\n\t%s *ret;\n\tva_list ap;\n"
3590                     "\tva_start (ap, first);\n"
3591                     "\tret = (%s *)g_object_new_valist (%s_get_type (), "
3592                     "first, ap);\n"
3593                     "\tva_end (ap);\n"
3594                     "\treturn ret;\n}\n\n",
3595                     typebase,
3596                     no_gnu ? "" : " G_GNUC_UNUSED",
3597                     typebase, typebase, typebase, funcbase);
3598
3599         if (c->glade_xml)
3600         {
3601                 out_printf (out, "/* a function to connect glade callback */\n");
3602                 out_printf (out,"static void\n"
3603                             "___glade_xml_connect_foreach(const gchar *handler_name,\n"
3604                             "GObject *object,\n"
3605                             "const gchar *signal_name,\n"
3606                             "const gchar *signal_data,\n"
3607                             "GObject *connect_object,\n"
3608                             "gboolean after,\n"
3609                             "gpointer user_data)\n"
3610                             "{\n"
3611                             "\tstatic GModule * allsymbols = NULL;\n"
3612                             "   \n"
3613                             "\tif (!allsymbols) allsymbols = g_module_open(NULL, 0);\n"
3614                             "\tif (allsymbols) {\n"
3615                             "\t\tgchar * func_name = g_strdup_printf(\"%s_%%s\", handler_name);\n"
3616                             "\t\tGCallback func;\n"
3617                             "\n"
3618                             "\t\tif (!g_module_symbol(allsymbols, func_name, (gpointer)&func)){\n"
3619                             "\t\t\tif (!g_module_symbol(allsymbols, handler_name, (gpointer)&func)) {\n"
3620                             "\t\t\t\tg_warning(\"could not find signal handler '%%s'.\", func_name);\n"
3621                             "\t\t\t\tg_free(func_name);\n"
3622                             "\t\t\t\treturn;\n"
3623                             "\t\t\t}\n"
3624                             "\t\t}\n"
3625                             "\t\tif (after)\n"
3626                             "\t\t\tg_signal_connect_data(object, signal_name, func, user_data, NULL, G_CONNECT_AFTER | G_CONNECT_SWAPPED);\n"
3627                             "\t\telse\n"
3628                             "\t\t\tg_signal_connect_data(object, signal_name, func, user_data, NULL, G_CONNECT_SWAPPED);\n"
3629                             "\t\tg_free(func_name);\n"
3630                             "\t}\n"
3631                             "}\n"
3632                             "\n",
3633                             funcbase);
3634         }
3635
3636         if (need_dispose)
3637                 add_dispose (c);
3638
3639         if (need_finalize)
3640                 add_finalize (c);
3641
3642         add_inits(c);
3643
3644         if(set_properties > 0) {
3645                 add_getset_arg(c, TRUE);
3646         }
3647
3648         if(get_properties > 0) {
3649                 add_getset_arg(c, FALSE);
3650         }
3651
3652         for(li = c->nodes; li != NULL; li = li->next) {
3653                 Node *n = li->data;
3654                 if(n->type == METHOD_NODE)
3655                         put_method((Method *)n);
3656         }
3657
3658         add_bad_hack_to_avoid_unused_warnings(c);
3659 }
3660
3661 static void
3662 print_useful_macros(void)
3663 {
3664         int major = 0, minor = 0, pl = 0;
3665
3666         /* Version stuff */
3667         sscanf (VERSION, "%d.%d.%d", &major, &minor, &pl);
3668         out_printf (out, "#define GOB_VERSION_MAJOR %d\n", major);
3669         out_printf (out, "#define GOB_VERSION_MINOR %d\n", minor);
3670         out_printf (out, "#define GOB_VERSION_PATCHLEVEL %d\n\n", pl);
3671
3672         /* Useful priv macro thingie */
3673         /* FIXME: this should be done the same way that priv is, as a var,
3674          * not a define */
3675         out_printf (out, "#define selfp (self->_priv)\n\n");
3676 }
3677
3678 static void
3679 print_more_useful_macros (void)
3680 {
3681         if (no_gnu) {
3682                 out_printf (out, "#define ___GOB_LIKELY(expr) (expr)\n");
3683                 out_printf (out, "#define ___GOB_UNLIKELY(expr) (expr)\n");
3684         } else {
3685                 out_printf (out, "#ifdef G_LIKELY\n");
3686                 out_printf (out, "#define ___GOB_LIKELY(expr) G_LIKELY(expr)\n");
3687                 out_printf (out, "#define ___GOB_UNLIKELY(expr) G_UNLIKELY(expr)\n");
3688                 out_printf (out, "#else /* ! G_LIKELY */\n");
3689                 out_printf (out, "#define ___GOB_LIKELY(expr) (expr)\n");
3690                 out_printf (out, "#define ___GOB_UNLIKELY(expr) (expr)\n");
3691                 out_printf (out, "#endif /* G_LIKELY */\n");
3692         }
3693 }
3694
3695 static void
3696 print_file_comments(void)
3697 {
3698         out_printf(outh, "/* Generated by GOB (v%s)"
3699                    "   (do not edit directly) */\n\n", VERSION);
3700         if(outph)
3701                 out_printf(outph, "/* Generated by GOB (v%s)"
3702                            "   (do not edit directly) */\n\n", VERSION);
3703         out_printf(out, "/* Generated by GOB (v%s)"
3704                    "   (do not edit directly) */\n\n", VERSION);
3705
3706         out_printf(out, "/* End world hunger, donate to the World Food Programme, http://www.wfp.org */\n\n");
3707 }
3708
3709 static void
3710 print_includes(void)
3711 {
3712         gboolean found_header;
3713         char *p;
3714
3715         /* We may need string.h for memset */
3716         if ( ! g_list_find_custom(include_files, "string.h", (GCompareFunc)strcmp)) {
3717                 out_printf(out, "#include <string.h> /* memset() */\n\n");
3718         }
3719
3720         p = g_strconcat(filebase, ".h", NULL);
3721         found_header = TRUE;
3722         if( ! g_list_find_custom(include_files, p, (GCompareFunc)strcmp)) {
3723                 out_printf(out, "#include \"%s.h\"\n\n", filebase);
3724                 found_header = FALSE;
3725         }
3726         g_free(p);
3727
3728         /* if we are creating a private header see if it was included */
3729         if(outph) {
3730                 char sep[2] = {0,0};
3731                 if (file_sep != 0)
3732                         sep[0] = file_sep;
3733                 p = g_strconcat(filebase, sep, "private.h", NULL);
3734                 if( ! g_list_find_custom(include_files, p,
3735                                          (GCompareFunc)strcmp)) {
3736                         out_printf(out, "#include \"%s%cprivate.h\"\n\n",
3737                                    filebase,
3738                                    file_sep);
3739                         if(found_header)
3740                                 error_printf(GOB_WARN, 0,
3741                                             "Implicit private header include "
3742                                             "added to top of\n"
3743                                             "\tsource file, while public "
3744                                             "header is at a custom location, "
3745                                             "you should\n"
3746                                             "\texplicitly include "
3747                                             "the private header below the "
3748                                             "public one.");
3749                 }
3750                 g_free(p);
3751         }
3752 }
3753
3754 static void
3755 print_header_prefixes(void)
3756 {
3757         char *p;
3758
3759         p = replace_sep(((Class *)class)->otype, '_');
3760         gob_strup (p);
3761         out_printf(outh, "#ifndef __%s_H__\n#define __%s_H__\n\n", p, p);
3762         if(outph)
3763                 out_printf(outph, "#ifndef __%s_PRIVATE_H__\n"
3764                            "#define __%s_PRIVATE_H__\n\n"
3765                            "#include \"%s.h\"\n\n", p, p, filebase);
3766         g_free(p);
3767
3768         if( ! no_extern_c) {
3769                 out_printf(outh, "#ifdef __cplusplus\n"
3770                            "extern \"C\" {\n"
3771                            "#endif /* __cplusplus */\n\n");
3772                 if(outph)
3773                         out_printf(outph, "#ifdef __cplusplus\n"
3774                                    "extern \"C\" {\n"
3775                                    "#endif /* __cplusplus */\n\n");
3776         }
3777 }
3778
3779 static void
3780 print_header_postfixes(void)
3781 {
3782         if( ! no_extern_c)
3783                 out_printf(outh, "\n#ifdef __cplusplus\n"
3784                            "}\n"
3785                            "#endif /* __cplusplus */\n");
3786         out_printf(outh, "\n#endif\n");
3787         if(outph) {
3788                 if( ! no_extern_c)
3789                         out_printf(outph, "\n#ifdef __cplusplus\n"
3790                                    "}\n"
3791                                    "#endif /* __cplusplus */\n");
3792                 out_printf(outph, "\n#endif\n");
3793         }
3794 }
3795
3796 static void
3797 print_all_top(void)
3798 {
3799         GList *li;
3800
3801         /* print the AT_CCODE blocks */
3802         for(li = nodes; li != NULL; li = li->next) {
3803                 Node *node = li->data;
3804                 if(node->type == CCODE_NODE) {
3805                         CCode *cc = (CCode *)node;
3806                         if(cc->cctype == AT_CCODE)
3807                                 print_ccode_block((CCode *)node);
3808                 }
3809         }
3810 }
3811
3812 static void
3813 print_header_top(void)
3814 {
3815         GList *li;
3816
3817         /* mandatory includes */
3818         out_printf (outh, "#include <glib.h>\n");
3819         out_printf (outh, "#include <glib-object.h>\n");
3820
3821         /* print the HT_CCODE blocks */
3822         for (li = nodes; li != NULL; li = li->next) {
3823                 Node *node = li->data;
3824                 if (node->type == CCODE_NODE) {
3825                         CCode *cc = (CCode *)node;
3826                         if (cc->cctype == HT_CCODE)
3827                                 print_ccode_block ((CCode *)node);
3828                 }
3829         }
3830 }
3831
3832 static void
3833 print_enum (EnumDef *enode)
3834 {
3835         GList *li;
3836         char *funcprefix;
3837         char *type;
3838         char *str;
3839
3840         funcprefix = replace_sep (enode->etype, '_');
3841         gob_strdown (funcprefix);
3842         out_printf (out, "static const GEnumValue _%s_values[] = {\n",
3843                     funcprefix);
3844         type = remove_sep (enode->etype);
3845
3846         out_printf (outh, "\ntypedef enum {\n");
3847
3848         for (li = enode->values; li != NULL; li = li->next) {
3849                 EnumValue *value = li->data; 
3850                 char *p;
3851                 char *sname = gob_strdown (g_strdup (value->name));
3852
3853                 while ((p = strchr (sname, '_')) != NULL)
3854                         *p = '-';
3855
3856                 out_printf (outh, "\t%s_%s", enode->prefix, value->name);
3857                 if (value->value != NULL)
3858                         out_printf (outh, " = %s", value->value);
3859                 if (li->next != NULL)
3860                         out_printf (outh, ",\n");
3861                 else
3862                         out_printf (outh, "\n");
3863
3864                 out_printf (out, "\t{ %s_%s, (char *)\"%s_%s\", (char *)\"%s\" },\n",
3865                             enode->prefix, value->name,
3866                             enode->prefix, value->name,
3867                             sname);
3868
3869                 g_free (sname);
3870         }
3871
3872         out_printf (out, "\t{ 0, NULL, NULL }\n};\n\n");
3873
3874         out_printf (outh, "} %s;\n", type);
3875
3876         str = make_pre_macro (enode->etype, "TYPE");
3877         out_printf (outh, "#define %s ", str);
3878         g_free (str);
3879
3880         out_printf (outh, "%s_get_type()\n", funcprefix);
3881         out_printf (outh, "GType %s_get_type (void);\n\n", funcprefix);
3882
3883         out_printf (out,
3884                     "GType\n%s_get_type (void)\n"
3885                     "{\n"
3886                     "\tstatic GType type = 0;\n"
3887                     "\tif ___GOB_UNLIKELY(type == 0)\n"
3888                     "\t\ttype = g_enum_register_static (\"%s\", _%s_values);\n"
3889                     "\treturn type;\n"
3890                     "}\n\n",
3891                     funcprefix, type, funcprefix);
3892
3893         g_free (funcprefix);
3894         g_free (type);
3895 }
3896
3897 static void
3898 print_flags (Flags *fnode)
3899 {
3900         GList *li;
3901         char *funcprefix;
3902         char *type;
3903         char *str;
3904         int i;
3905
3906         funcprefix = replace_sep (fnode->ftype, '_');
3907         gob_strdown (funcprefix);
3908         out_printf (out, "static const GFlagsValue _%s_values[] = {\n",
3909                     funcprefix);
3910         type = remove_sep (fnode->ftype);
3911
3912         out_printf (outh, "\ntypedef enum {\n");
3913
3914         for (i = 0, li = fnode->values; li != NULL; i++, li = li->next) {
3915                 const char *name = li->data; 
3916                 char *p;
3917                 char *sname = gob_strdown (g_strdup (name));
3918
3919                 while ((p = strchr (sname, '_')) != NULL)
3920                         *p = '-';
3921
3922                 out_printf (outh, "\t%s_%s = 1<<%d",
3923                             fnode->prefix, name, i);
3924                 if (li->next != NULL)
3925                         out_printf (outh, ",\n");
3926                 else
3927                         out_printf (outh, "\n");
3928
3929                 out_printf (out, "\t{ %s_%s, (char *)\"%s_%s\", (char *)\"%s\" },\n",
3930                             fnode->prefix, name,
3931                             fnode->prefix, name,
3932                             sname);
3933
3934                 g_free (sname);
3935         }
3936
3937         out_printf (out, "\t{ 0, NULL, NULL }\n};\n\n");
3938
3939         out_printf (outh, "} %s;\n", type);
3940
3941         str = make_pre_macro (fnode->ftype, "TYPE");
3942         out_printf (outh, "#define %s ", str);
3943         g_free (str);
3944
3945         out_printf (outh, "%s_get_type()\n", funcprefix);
3946         out_printf (outh, "GType %s_get_type (void);\n\n", funcprefix);
3947
3948         out_printf (out,
3949                     "GType\n%s_get_type (void)\n"
3950                     "{\n"
3951                     "\tstatic GType type = 0;\n"
3952                     "\tif ___GOB_UNLIKELY(type == 0)\n"
3953                     "\t\ttype = g_flags_register_static (\"%s\", _%s_values);\n"
3954                     "\treturn type;\n"
3955                     "}\n\n",
3956                     funcprefix, type, funcprefix);
3957
3958         g_free (funcprefix);
3959         g_free (type);
3960 }
3961
3962 static void
3963 print_error (Error *enode)
3964 {
3965         GList *li;
3966         char *funcprefix;
3967         char *type;
3968         char *str;
3969
3970         funcprefix = replace_sep (enode->etype, '_');
3971         gob_strdown (funcprefix);
3972         out_printf (out, "static const GEnumValue _%s_values[] = {\n",
3973                     funcprefix);
3974         type = remove_sep (enode->etype);
3975
3976         out_printf (outh, "\ntypedef enum {\n");
3977
3978         for (li = enode->values; li != NULL; li = li->next) {
3979                 const char *name = li->data;
3980                 char *p;
3981                 char *sname = gob_strdown (g_strdup (name));
3982
3983                 while ((p = strchr (sname, '_')) != NULL)
3984                         *p = '-';
3985
3986                 out_printf (outh, "\t%s_%s", enode->prefix, name);
3987                 if (li->next != NULL)
3988                         out_printf (outh, ",\n");
3989                 else
3990                         out_printf (outh, "\n");
3991
3992                 out_printf (out, "\t{ %s_%s, (char *)\"%s_%s\", (char *)\"%s\" },\n",
3993                             enode->prefix, name,
3994                             enode->prefix, name,
3995                             sname);
3996
3997                 g_free (sname);
3998         }
3999
4000         out_printf (out, "\t{ 0, NULL, NULL }\n};\n\n");
4001
4002         out_printf (outh, "} %s;\n", type);
4003
4004         str = make_pre_macro (enode->etype, "TYPE");
4005         out_printf (outh, "#define %s ", str);
4006         g_free (str);
4007
4008         out_printf (outh, "%s_get_type ()\n", funcprefix);
4009         out_printf (outh, "GType %s_get_type (void);\n\n", funcprefix);
4010
4011         out_printf (out,
4012                     "GType\n%s_get_type (void)\n"
4013                     "{\n"
4014                     "\tstatic GType type = 0;\n"
4015                     "\tif ___GOB_UNLIKELY(type == 0)\n"
4016                     "\t\ttype = g_enum_register_static (\"%s\", _%s_values);\n"
4017                     "\treturn type;\n"
4018                     "}\n\n",
4019                     funcprefix, type, funcprefix);
4020
4021         out_printf (outh, "#define %s %s_quark ()\n", enode->prefix, funcprefix);
4022         out_printf (outh, "GQuark %s_quark (void);\n\n", funcprefix);
4023
4024         str = replace_sep (enode->etype, '-');
4025         gob_strdown (str);
4026
4027         out_printf (out,
4028                     "GQuark\n%s_quark (void)\n"
4029                     "{\n"
4030                     "\tstatic GQuark q = 0;\n"
4031                     "\tif (q == 0)\n"
4032                     "\t\tq = g_quark_from_static_string (\"%s\");\n"
4033                     "\treturn q;\n"
4034                     "}\n\n",
4035                     funcprefix, str);
4036
4037         g_free (str);
4038
4039         g_free (funcprefix);
4040         g_free (type);
4041 }
4042
4043 static void
4044 generate_outfiles(void)
4045 {
4046         GList *li;
4047
4048         print_file_comments();
4049
4050         print_all_top();
4051
4052         print_header_top();
4053
4054         print_header_prefixes();
4055
4056         print_useful_macros();
4057
4058         print_includes();
4059
4060         print_more_useful_macros ();
4061
4062         for (li = nodes; li != NULL; li = li->next) {
4063                 Node *node = li->data;
4064                 if (node->type == CCODE_NODE) {
4065                         CCode *cc = (CCode *)node;
4066                         if (cc->cctype != HT_CCODE &&
4067                             cc->cctype != AT_CCODE)
4068                                 print_ccode_block ((CCode *)node);
4069                 } else if (node->type == CLASS_NODE) {
4070                         print_class_block ((Class *)node);
4071                 } else if (node->type == ENUMDEF_NODE) {
4072                         print_enum ((EnumDef *)node);
4073                 } else if (node->type == FLAGS_NODE) {
4074                         print_flags ((Flags *)node);
4075                 } else if (node->type == ERROR_NODE) {
4076                         print_error ((Error *)node);
4077                 } else {
4078                         g_assert_not_reached();
4079                 }
4080         }
4081
4082         print_header_postfixes();
4083 }
4084
4085 static void
4086 print_help(void)
4087 {
4088         fprintf(stderr, "Gob version %s\n\n", VERSION);
4089         fprintf(stderr, "gob [options] file.gob\n\n");
4090         fprintf(stderr, "Options:\n"
4091                 "\t--help,-h,-?            Display this help\n"
4092                 "\t--version               Display version\n"
4093                 "\t--exit-on-warn,-w       Exit with an error on warnings\n"
4094                 "\t--no-exit-on-warn       Don't exit on warnings [default]\n"
4095                 "\t--for-cpp               Create C++ files\n"
4096                 "\t--no-extern-c           Never print extern \"C\" into the "
4097                                           "header\n"
4098                 "\t--no-gnu                Never use GNU extentions\n"
4099                 "\t--no-touch              Don't touch output files unless they "
4100                                           "really\n"
4101                 "\t                        changed (implies --no-touch-headers)\n"
4102                 "\t--no-touch-headers      Don't touch headers unless they "
4103                                           "really changed\n"
4104                 "\t--always-private-header Always create a private header "
4105                                           "file,\n"
4106                 "\t                        even if it would be empty\n"
4107                 "\t--ondemand-private-header Create private header only when "
4108                                           "needed\n"
4109                 "\t                        [default]\n"
4110                 "\t--no-private-header     Don't create a private header, "
4111                                           "put private\n"
4112                 "\t                        structure and protected "
4113                                           "prototypes inside c file\n"
4114                 "\t--always-private-struct Always create a private pointer "
4115                                           "in\n"
4116                 "\t                        the object structure\n"
4117                 "\t--m4                    Preprocess source with m4. "
4118                                           "Following args will\n"
4119                 "\t                        be passed to m4\n"
4120                 "\t--m4-dir                Print directory that will be "
4121                                           "searched for m4\n"
4122                 "\t                        files\n"
4123                 "\t--no-write,-n           Don't write output files, just "
4124                                           "check syntax\n"
4125                 "\t--no-lines              Don't print '#line' to output\n"
4126                 "\t--no-self-alias         Don't create self type and macro "
4127                                           "aliases\n"
4128                 "\t--no-kill-underscores   Ignored for compatibility\n"
4129                 "\t-o,--output-dir         The directory where output "
4130                                           "should be placed\n"
4131                 "\t--file-sep[=c]          replace default \'-\' file "
4132                                           "name separator\n");
4133 }
4134
4135 static void
4136 parse_options(int argc, char *argv[])
4137 {
4138         int i;
4139         int got_file = FALSE;
4140         int no_opts = FALSE;
4141         int m4_opts = FALSE; /* if we are just passing on args to m4 */
4142
4143         filename = NULL;
4144
4145         for(i = 1 ; i < argc; i++) {
4146                 if(m4_opts) {
4147                         char *new_commandline;
4148                         g_assert(m4_commandline!=NULL);
4149
4150                         /* check whether this one looks like the filename */
4151                         if((!strcmp(argv[i],"-") || argv[i][0] != '-') 
4152                            && !got_file) {
4153                                 const gchar *m4_flags=use_m4_clean?"":M4_FLAGS;
4154                                 filename = argv[i];
4155                                 got_file = TRUE;
4156                                 
4157                                 /* insert flags before the filename */
4158                                 new_commandline=g_strconcat(m4_commandline,
4159                                                             " ",
4160                                                             m4_flags, 
4161                                                             " ",
4162                                                             argv[i],
4163                                                             NULL);
4164                         }
4165
4166                         /* just an ordinary option */
4167                         else                      
4168                           new_commandline=g_strconcat(m4_commandline,
4169                                                       " ",
4170                                                       argv[i],
4171                                                       NULL);
4172
4173                         /* free old commandline */
4174                         g_free(m4_commandline);
4175                         m4_commandline=new_commandline;
4176
4177                 } else if(no_opts ||
4178                    argv[i][0] != '-') {
4179                         /*must be a file*/
4180                         if(got_file) {
4181                                 fprintf(stderr, "Specify only one file!\n");
4182                                 print_help();
4183                                 exit(1);
4184                         }
4185                         filename = argv[i];
4186                         got_file = TRUE;
4187                 } else if(strcmp(argv[i], "--help")==0) {
4188                         print_help();
4189                         exit(0);
4190                 } else if(strcmp(argv[i], "--version")==0) {
4191                         fprintf(stderr, "Gob version %s\n", VERSION);
4192                         exit(0);
4193                 } else if(strcmp(argv[i], "--exit-on-warn")==0) {
4194                         exit_on_warn = TRUE;
4195                 } else if(strcmp(argv[i], "--no-exit-on-warn")==0) {
4196                         exit_on_warn = FALSE;
4197                 } else if(strcmp(argv[i], "--for-cpp")==0) {
4198                         for_cpp = TRUE;
4199                 } else if(strcmp(argv[i], "--no-touch")==0) {
4200                         no_touch = TRUE;
4201                         no_touch_headers = TRUE;
4202                 } else if(strcmp(argv[i], "--no-touch-headers")==0) {
4203                         no_touch_headers = TRUE;
4204                 } else if(strcmp(argv[i], "--ondemand-private-header")==0) {
4205                         private_header = PRIVATE_HEADER_ONDEMAND;
4206                 } else if(strcmp(argv[i], "--always-private-header")==0) {
4207                         private_header = PRIVATE_HEADER_ALWAYS;
4208                 } else if(strcmp(argv[i], "--no-private-header")==0) {
4209                         private_header = PRIVATE_HEADER_NEVER;
4210                 } else if(strcmp(argv[i], "--no-gnu")==0) {
4211                         no_gnu = TRUE;
4212                 } else if(strcmp(argv[i], "--no-extern-c")==0) {
4213                         no_extern_c = TRUE;
4214                 } else if(strcmp(argv[i], "--no-write")==0) {
4215                         no_write = TRUE;
4216                 } else if(strcmp(argv[i], "--no-lines")==0) {
4217                         no_lines = TRUE;
4218                 } else if(strcmp(argv[i], "--no-self-alias")==0) {
4219                         no_self_alias = TRUE;
4220                 } else if(strcmp(argv[i], "--no-kill-underscores")==0) {
4221                         /* no op */;
4222                 } else if(strcmp(argv[i], "--always-private-struct")==0) {
4223                         always_private_struct = TRUE;
4224                 } else if(strcmp(argv[i], "--m4-dir")==0) {
4225                         printf("%s\n",M4_INCLUDE_DIR);
4226                         exit(0);
4227                 } else if(strcmp(argv[i], "--m4")==0) {
4228                         use_m4 = TRUE;
4229                         use_m4_clean=FALSE;
4230                         m4_opts = TRUE;
4231                         m4_commandline=g_strdup(M4_COMMANDLINE);
4232                 } else if(strcmp(argv[i], "--m4-clean")==0) {
4233                         use_m4 = TRUE;
4234                         use_m4_clean=TRUE;
4235                         m4_opts = TRUE;
4236                         m4_commandline=g_strdup(M4_COMMANDLINE);
4237                 } else if (strcmp (argv[i], "-o") == 0 || 
4238                            strcmp (argv[i], "--output-dir") == 0) {
4239                         if (i+1 < argc) {
4240                                 output_dir = g_strdup (argv[i+1]);
4241                                 i++;
4242                         } else {
4243                                 output_dir = NULL;
4244                         }
4245                 } else if (strncmp (argv[i], "-o=", strlen ("-o=")) == 0 || 
4246                            strncmp (argv[i],
4247                                     "--output-dir=",
4248                                     strlen ("--output-dir=")) == 0) {
4249                         char *p = strchr (argv[i], '=');
4250                         g_assert (p != NULL);
4251                         output_dir = g_strdup (p+1);
4252                 } else if (strncmp (argv[i], "--file-sep=",
4253                                     strlen ("--file-sep=")) == 0) {
4254                         char *p = strchr (argv[i], '=');
4255                         g_assert (p != NULL);
4256                         file_sep = *(p+1);
4257                 } else if (strncmp (argv[i], "--file-sep",
4258                                     strlen ("--file-sep")) == 0) {
4259                         if (i+1 < argc) {
4260                                 file_sep = (argv[i+1])[0];
4261                                 i++;
4262                         } else {
4263                                 file_sep = 0;
4264                         }
4265                 } else if(strcmp(argv[i], "--")==0) {
4266                         /*further arguments are files*/
4267                         no_opts = TRUE;
4268                 } else if(strncmp(argv[i], "--", 2)==0) {
4269                         /*unknown long option*/
4270                         fprintf(stderr, "Unknown option '%s'!\n", argv[i]);
4271                         print_help();
4272                         exit(1);
4273                 } else {
4274                         /*by now we know we have a string starting with
4275                           - which is a short option string*/
4276                         char *p;
4277                         for(p = argv[i] + 1; *p; p++) {
4278                                 switch(*p) {
4279                                 case 'w':
4280                                         exit_on_warn=TRUE;
4281                                         break;
4282                                 case 'n':
4283                                         no_write = TRUE;
4284                                         break;
4285                                 case 'h':
4286                                 case '?':
4287                                         print_help();
4288                                         exit(0);
4289                                 default:
4290                                         fprintf(stderr,
4291                                                 "Unknown option '%c'!\n", *p);
4292                                         print_help();
4293                                         exit(1);
4294                                 }
4295                         }
4296                 }
4297         }
4298
4299 #if 0
4300         /* if we are using m4, and got no filename, append m4 flags now */
4301         if(!got_file && use_m4 && !use_m4_clean) {
4302                 char *new_commandline;
4303                 new_commandline=g_strconcat(m4_commandline,
4304                                             " ",
4305                                             M4_FLAGS,
4306                                             NULL);
4307                 g_free(m4_commandline);
4308                 m4_commandline=new_commandline;
4309         }
4310 #endif
4311 }
4312
4313 static void
4314 compare_and_move (const char *old_filename)
4315 {
4316         char *new_filename = g_strconcat (old_filename, "#gob#", NULL);
4317         FILE *old_f;
4318         gboolean equal = FALSE;
4319
4320         old_f = fopen (old_filename, "r");
4321         if (old_f) {
4322                 FILE *new_f;
4323                 gboolean error = FALSE;
4324
4325                 new_f = fopen (new_filename, "r");
4326                 if (new_f) {
4327                         char new_buf[1024];
4328                         char old_buf[1024];
4329
4330                         while (TRUE) {
4331                                 size_t new_n;
4332                                 size_t old_n;
4333
4334                                 new_n = fread (new_buf, 1, sizeof (new_buf), new_f);
4335                                 if (ferror (new_f)) {
4336                                         error = TRUE;
4337                                         error_printf (GOB_ERROR, 0,
4338                                                       "Can't read %s: %s",
4339                                                       new_filename,
4340                                                       g_strerror (errno));
4341                                         break;
4342                                 }
4343
4344                                 old_n = fread (old_buf, 1, sizeof (old_buf), old_f);
4345                                 if (ferror (old_f)
4346                                     || feof (new_f) != feof (old_f)
4347                                     || new_n != old_n
4348                                     || memcmp (new_buf, old_buf, new_n) != 0)
4349                                         break;
4350
4351                                 if (feof (new_f)) {
4352                                         equal = TRUE;
4353                                         break;
4354                                 }
4355                         }
4356                 } else
4357                         error_printf (GOB_ERROR, 0, "Can't open %s: %s",
4358                                       new_filename, g_strerror (errno));
4359
4360                 fclose (old_f);
4361                 fclose (new_f);
4362
4363                 if (error)
4364                         goto end;
4365
4366                 if (! equal && unlink (old_filename) != 0) {
4367                         error_printf (GOB_ERROR, 0, "Can't remove %s: %s",
4368                                       old_filename, g_strerror (errno));
4369                         goto end;
4370                 }
4371         }
4372
4373         if (equal) {
4374                 if (unlink (new_filename) != 0)
4375                         error_printf (GOB_ERROR, 0, "Can't remove %s: %s",
4376                                       new_filename, g_strerror (errno));
4377         } else {
4378                 if (rename (new_filename, old_filename) != 0)
4379                         error_printf (GOB_ERROR, 0, "Can't rename %s to %s: %s",
4380                                       new_filename, old_filename,
4381                                       g_strerror (errno));
4382         }
4383
4384  end:
4385         g_free (new_filename);
4386 }
4387
4388 int
4389 main(int argc, char *argv[])
4390 {
4391         parse_options(argc, argv);
4392         
4393         if(use_m4) {
4394                 yyin = popen(m4_commandline, "r");
4395                 if(!yyin) {
4396                         fprintf(stderr, "Error: can't open pipe from '%s'\n",
4397                                 m4_commandline);
4398                         exit(1);
4399                 }
4400         } else if(filename) {
4401                 yyin = fopen(filename, "r");
4402                 if(!yyin) {
4403                         fprintf(stderr, "Error: can't open file '%s'\n",
4404                                 filename);
4405                         exit(1);
4406                 }
4407         }
4408
4409         if(filename==NULL)
4410                 filename = "stdin";
4411
4412         /* This is where parsing is done */
4413         /*yydebug = 1;*/
4414         if(yyparse() != 0)
4415                 error_print (GOB_ERROR, 0, "Parsing errors, quitting");
4416
4417         /* close input file */
4418         if(use_m4) pclose(yyin);
4419         else fclose(yyin);
4420         yyin=stdin;
4421
4422         if( ! class)
4423                 error_print (GOB_ERROR, 0, "no class defined");
4424         
4425
4426         exit_on_error = FALSE;
4427
4428         signals = count_signals ((Class *)class);
4429         set_properties = count_set_properties ((Class *)class) +
4430                 count_set_arguments ((Class *)class);
4431         get_properties = count_get_properties ((Class *)class) +
4432                 count_get_arguments ((Class *)class);
4433         overrides = count_overrides ((Class *)class);
4434         privates = count_privates ((Class *)class);
4435         protecteds = count_protecteds ((Class *)class);
4436         unreftors = count_unreftors ((Class *)class);
4437         destructors = count_destructors ((Class *)class);
4438         initializers = count_initializers ((Class *)class);
4439         glade_widgets = count_glade_widgets ((Class *)class);
4440         overrode_get_type = find_get_type ((Class *)class);
4441
4442         make_bases ();
4443         make_inits ((Class *)class);
4444         if(unreftors > 0) {
4445                 need_dispose = TRUE;
4446                 find_dispose ((Class *)class);
4447         }
4448         if (destructors > 0 ||
4449             privates > 0) {
4450                 need_finalize = TRUE;
4451                 find_finalize ((Class *)class);
4452         }
4453         check_bad_symbols ((Class *)class);
4454         check_duplicate_symbols ((Class *)class);
4455         check_duplicate_overrides ((Class *)class);
4456         check_duplicate_signals_args ((Class *)class);
4457         check_public_new ((Class *)class);
4458         check_vararg ((Class *)class);
4459         check_firstarg ((Class *)class);
4460         check_nonvoidempty ((Class *)class);
4461         check_signal_args ((Class *)class);
4462         check_property_types ((Class *)class);
4463         check_argument_types ((Class *)class);
4464         check_func_arg_checks ((Class *)class);
4465         check_for_class_destructors ((Class *)class);
4466
4467         exit_on_error = TRUE;
4468         
4469         if (got_error)
4470                 exit (1);
4471
4472         any_special = setup_special_array ((Class *)class, special_array);
4473
4474         open_files ();
4475         
4476         generate_outfiles ();
4477
4478         if (out)
4479                 fclose (out);
4480         if (outh)
4481                 fclose (outh);
4482         if (outph)
4483                 fclose (outph);
4484
4485         if (! no_write) {
4486                 if (no_touch) {
4487                         compare_and_move (outfilebase);
4488                         if (outfilephbase)
4489                                 compare_and_move (outfilephbase);
4490                 }
4491                 if (no_touch_headers)
4492                         compare_and_move (outfilehbase);
4493         }
4494         
4495         return 0;
4496 }