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