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