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