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