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