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