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