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