]> git.draconx.ca Git - gob-dx.git/blob - src/main.c
Release 0.90.2
[gob-dx.git] / src / main.c
1 /* GOB C Preprocessor
2  * Copyright (C) 1999 the Free Software Foundation.
3  *
4  * Author: George Lebl
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the  Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19  * USA.
20  */
21
22 #include "config.h"
23 #include <glib.h>
24 #include <popt.h>
25 #include <time.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #include "tree.h"
30 #include "parse.h"
31 #include "out.h"
32 #include "main.h"
33
34 char *filename = "stdin";
35
36 int yyparse(void);
37
38 extern int yydebug;
39 extern FILE * yyin;
40 extern Node *class;
41 extern GList *nodes;
42
43 char *filebase;
44 static char *funcbase;
45 static char *pfuncbase;
46 static char *macrobase;
47 static char *macrois;
48 static char *typebase;
49 static char *ptypebase;
50
51 static int signals = 0;
52 static int arguments = 0;
53 static int overrides = 0;
54
55 FILE *out;
56 FILE *outh;
57
58 int exit_on_warn = FALSE;
59 int exit_on_error = TRUE;
60 int got_error = FALSE;
61
62 void
63 print_error(int is_warn, char *error,int line)
64 {
65         char *w;
66         if(is_warn)
67                 w = "Warning:";
68         else {
69                 w = "Error:";
70                 got_error = TRUE;
71         }
72         if(line>0)
73                 fprintf(stderr,"%s:%d: %s %s\n",filename,line,w,error);
74         else
75                 fprintf(stderr,"%s: %s %s\n",filename,w,error);
76         if((!is_warn || exit_on_warn) && exit_on_error)
77                 exit(1);
78 }
79
80 static char *
81 remove_sep(char *base)
82 {
83         char *p;
84         char *s = g_strdup(base);
85         while((p=strchr(s,':')))
86                 strcpy(p,p+1);
87         return s;
88 }
89
90 static char *
91 replace_sep(char *base, char r)
92 {
93         char *p;
94         char *s = g_strdup(base);
95         while((p=strchr(s,':')))
96                 *p = r;
97         if(*s == r) {
98                 p = g_strdup(s+1);
99                 g_free(s);
100                 return p;
101         }
102         return s;
103 }
104
105 /*separate the namespace part and then replace rest of
106   separators with r*/
107 static void
108 separns_replace_sep(char *base, char **ns, char **name, char r)
109 {
110         char *p;
111         char *s = g_strdup(base);
112         *ns = NULL;
113         if((p=strchr(s,':')) && p!=s) {
114                 *p = '\0';
115                 *ns = g_strdup(s);
116                 p = g_strdup(p+1);
117                 g_free(s);
118                 s = p;
119         }
120         while((p=strchr(s,':')))
121                 *p = r;
122         if(*s == r) {
123                 *name = g_strdup(s+1);
124                 g_free(s);
125         } else
126                 *name = s;
127 }
128
129 static char *
130 make_is_macro(char *base)
131 {
132         char *s1,*s2;
133         char *s;
134
135         separns_replace_sep(base,&s1,&s2,'_');
136         if(s1)
137                 s = g_strconcat(s1,"_IS_",s2,NULL);
138         else
139                 s = g_strconcat("IS_",s2,NULL);
140
141         g_strup(s);
142         
143         g_free(s1);
144         g_free(s2);
145
146         return s;
147 }
148
149 static void
150 make_bases(void)
151 {
152         filebase = replace_sep(((Class *)class)->otype,'-');
153         g_strdown(filebase);
154
155         funcbase = replace_sep(((Class *)class)->otype,'_');
156         g_strdown(funcbase);
157
158         pfuncbase = replace_sep(((Class *)class)->ptype,'_');
159         g_strdown(pfuncbase);
160
161         macrobase = replace_sep(((Class *)class)->otype,'_');
162         g_strup(macrobase);
163         
164         macrois = make_is_macro(((Class *)class)->otype);
165
166         typebase = remove_sep(((Class *)class)->otype);
167
168         ptypebase = remove_sep(((Class *)class)->ptype);
169 }
170
171 static void
172 def_methods(Class *c)
173 {
174         GList *li;
175         
176         out_printf(out,"\n");
177         for(li=c->nodes;li;li=g_list_next(li)) {
178                 Node *node = li->data;
179                 if(node->type == METHOD_NODE) {
180                         Method *m = (Method *)node;
181                         
182                         if(m->scope == INIT_METHOD ||
183                            m->scope == CLASS_INIT_METHOD ||
184                            m->scope == OVERRIDE_METHOD)
185                                 continue;
186                         
187                         out_printf(out,"#define %s %s_%s\n",m->id,funcbase,m->id); 
188                 }
189         }
190         out_printf(out,"\n");
191 }
192
193 static void
194 undef_methods(Class *c)
195 {
196         GList *li;
197         
198         out_printf(out,"\n");
199         for(li=c->nodes;li;li=g_list_next(li)) {
200                 Node *node = li->data;
201                 if(node->type == METHOD_NODE) {
202                         Method *m = (Method *)node;
203
204                         if(m->scope == INIT_METHOD ||
205                            m->scope == CLASS_INIT_METHOD ||
206                            m->scope == OVERRIDE_METHOD)
207                                 continue;
208                         
209                         out_printf(out,"#undef %s\n",m->id); 
210                 }
211         }
212         out_printf(out,"\n");
213 }
214
215 static void
216 print_type(FILE *fp, Type *t)
217 {
218         char *s;
219         int i;
220         s = remove_sep(t->name);
221         out_printf(fp,"%s ",s); 
222         g_free(s);
223         
224         for(i=0;i<t->stars;i++)
225                 out_printf(fp,"*"); 
226 }
227
228 static void
229 put_variable(Variable *v)
230 {
231         out_printf(outh,"\t");
232         if(v->scope == PRIVATE_SCOPE)
233                 out_printf(outh,"/* private */ "); 
234         print_type(outh,v->vtype);
235
236         out_printf(outh,"%s;\n",v->id); 
237 }
238
239 static void
240 print_method(FILE *fp, char *typeprefix, char *nameprefix,
241              char *namepostfix,char *postfix, Method *m)
242 {
243         GList *li;
244
245         out_printf(fp,"%s",typeprefix); 
246         print_type(fp,m->mtype);
247         out_printf(fp,"%s%s_%s%s(",
248                 nameprefix,funcbase,m->id,namepostfix); 
249         
250         if(m->args) {
251                 for(li=m->args;li;li=g_list_next(li)) {
252                         FuncArg *arg = li->data;
253                         print_type(fp,arg->atype);
254                         if(li->next)
255                                 out_printf(fp,"%s, ",arg->name); 
256                         else
257                                 out_printf(fp,"%s",arg->name); 
258
259                 }
260                 if(m->vararg)
261                         out_printf(fp,", ..."); 
262         } else {
263                 out_printf(fp,"void"); 
264         }
265         out_printf(fp,")%s\n",postfix); 
266 }
267
268 static void
269 put_vs_method(Method *m)
270 {
271         if(m->scope != SIGNAL_LAST_METHOD &&
272            m->scope != SIGNAL_FIRST_METHOD &&
273            m->scope != PRIVATE_SIGNAL_LAST_METHOD &&
274            m->scope != PRIVATE_SIGNAL_FIRST_METHOD &&
275            m->scope != VIRTUAL_METHOD &&
276            m->scope != PRIVATE_VIRTUAL_METHOD)
277                 return;
278
279         print_method(outh,"\t","(* ",") ",";",m);
280 }
281
282 static void
283 put_pub_method(Method *m)
284 {
285         if(m->scope == PRIVATE_SCOPE ||
286            m->scope == OVERRIDE_METHOD ||
287            m->scope == INIT_METHOD ||
288            m->scope == CLASS_INIT_METHOD ||
289            m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
290            m->scope == PRIVATE_SIGNAL_FIRST_METHOD ||
291            m->scope == PRIVATE_VIRTUAL_METHOD)
292                 return;
293
294         print_method(outh,"","\t","\t",";",m);
295 }
296
297 static void
298 put_priv_method_prot(Method *m)
299 {
300         if(m->scope == PUBLIC_SCOPE)
301                 return;
302
303         if(m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
304            m->scope == PRIVATE_SIGNAL_FIRST_METHOD ||
305            m->scope == PRIVATE_VIRTUAL_METHOD) {
306                 if(m->cbuf)
307                         print_method(out,"static ","_real_"," ",";",m);
308                 print_method(out,"static ",""," ",";",m);
309         } else if(m->scope == SIGNAL_LAST_METHOD ||
310                   m->scope == SIGNAL_FIRST_METHOD ||
311                   m->scope == VIRTUAL_METHOD) {
312                 if(!m->cbuf)
313                         return;
314                 print_method(out,"static ","_real_"," ",";",m);
315         } else {
316                 print_method(out,"static ",""," ",";",m);
317         }
318 }
319
320 static GList *
321 make_init_args(Class *cl, char *name, int is_class)
322 {
323         Node *node;
324         Node *type;
325         char *tn;
326         
327         if(is_class)
328                 tn = g_strconcat(cl->otype,":Class",NULL);
329         else
330                 tn = g_strdup(cl->otype);
331
332         type = new_type(1,tn);
333         node = new_funcarg((Type *)type,name,NULL);
334         return g_list_prepend(NULL, node);
335 }
336
337 static void
338 make_inits(Class *cl)
339 {
340         int got_class_init = FALSE;
341         int got_init = FALSE;
342         GList *li;
343         Node *node;
344         for(li=cl->nodes;li;li=g_list_next(li)) {
345                 Node *n = li->data;
346                 if(n->type == METHOD_NODE) {
347                         Method *m = (Method *)n;
348                         if(m->scope == INIT_METHOD) {
349                                 if(got_init)
350                                         print_error(FALSE,"init defined more then once",m->line_no);
351                                 got_init = TRUE;
352                         } else if(m->scope == CLASS_INIT_METHOD) {
353                                 if(got_class_init)
354                                         print_error(FALSE,"class_init defined more then once",m->line_no);
355                                 got_class_init = TRUE;
356                         }
357                 }
358         }
359         if(!got_class_init) {
360                 node = new_method(CLASS_INIT_METHOD,
361                                   (Type *)new_type(0,g_strdup("void")),
362                                   NULL,NULL,g_strdup("class_init"),
363                                   make_init_args(cl,g_strdup("c"),TRUE),
364                                   NULL, NULL,0,0,FALSE);
365                 cl->nodes = g_list_prepend(cl->nodes,node);
366         }
367         if(!got_init) {
368                 node = new_method(INIT_METHOD,
369                                   (Type *)new_type(0,g_strdup("void")),
370                                   NULL,NULL,g_strdup("init"),
371                                   make_init_args(cl,g_strdup("o"),FALSE),
372                                   NULL, NULL,0,0,FALSE);
373                 cl->nodes = g_list_prepend(cl->nodes,node);
374         }
375 }
376
377 static GHashTable *marsh = NULL;
378
379 static void
380 add_signal_prots(Method *m)
381 {
382         GList *li;
383         static int sig = 1;
384         char *s;
385         
386         if(m->scope != SIGNAL_LAST_METHOD &&
387            m->scope != SIGNAL_FIRST_METHOD &&
388            m->scope != PRIVATE_SIGNAL_LAST_METHOD &&
389            m->scope != PRIVATE_SIGNAL_FIRST_METHOD)
390                 return;
391
392         if(!marsh)
393                 marsh = g_hash_table_new(NULL,NULL);
394         
395         if(strcmp(m->gtktypes->data,"NONE")==0 &&
396            strcmp(m->gtktypes->next->data,"NONE")==0)
397                 return;
398         
399         s = g_strdup_printf("__Sig%d",sig++);
400         
401         g_hash_table_insert(marsh,m,s);
402         
403         out_printf(out,"\ntypedef ");
404         print_type(out,m->mtype);
405         
406         out_printf(out,"(*%s) (",s);
407         
408         for(li=m->args;li;li=g_list_next(li)) {
409                 FuncArg *arg = li->data;
410                 print_type(out,arg->atype);
411                 out_printf(out,", "); 
412         }
413         out_printf(out,"gpointer);\n"); 
414         
415         out_printf(out,"\nstatic void\n"
416                 "marshal_%s (GtkObject * object,\n"
417                 "\tGtkSignalFunc func,\n"
418                 "\tgpointer func_data,\n"
419                 "\tGtkArg * args)\n"
420                 "{\n",s);
421         
422         if(strcmp(m->gtktypes->data,"NONE")==0) {
423                 int i;
424                 out_printf(out, "\t%s rfunc;\n\n"
425                         "\trfunc = (%s)func;\n\n"
426                         "\t(*rfunc)((%s *)object",s,s,typebase);
427                 if(strcmp(m->gtktypes->next->data,"NONE")!=0) {
428                         for(i=0,li=m->gtktypes->next;li;
429                             i++,li=g_list_next(li)) {
430                                 out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
431                                         (char *)li->data,i);
432                         }
433                 }
434                 out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
435         } else {
436                 int i;
437                 out_printf(out, "\t%s rfunc;\n\t",s);
438                 print_type(out,m->mtype);
439                 out_printf(out, " *retval;\n\n"
440                         "\trfunc = (%s)func;\n\n"
441                         "\tretval = GTK_RETLOC_%s(args[%d]);\n\n"
442                         "\t*retval = (*rfunc)((%s *)object",
443                         s,(char *)m->gtktypes->data,
444                         g_list_length(m->gtktypes)-1,typebase);
445                 if(strcmp(m->gtktypes->next->data,"NONE")!=0) {
446                         for(i=0,li=m->gtktypes->next;li;
447                             i++,li=g_list_next(li)) {
448                                 out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
449                                         (char *)li->data,i);
450                         }
451                 }
452                 out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
453         }
454
455 }
456
457 static void
458 add_enums(Class *c)
459 {
460         GList *li;
461         out_printf(out,"\n");
462         if(signals>0) {
463                 out_printf(out,"enum {\n");
464                 for(li=c->nodes;li;li=g_list_next(li)) {
465                         Node *n = li->data;
466                         if(n->type == METHOD_NODE) {
467                                 Method *m = (Method *)n;
468                                 if(m->scope == SIGNAL_LAST_METHOD ||
469                                    m->scope == SIGNAL_FIRST_METHOD ||
470                                    m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
471                                    m->scope == PRIVATE_SIGNAL_FIRST_METHOD) {
472                                         char *s = g_strdup(m->id);
473                                         g_strup(s);
474                                         out_printf(out,"\t%s_SIGNAL,\n",s);
475                                         g_free(s);
476                                 }
477                         }
478                 }
479                 out_printf(out,"\tLAST_SIGNAL\n};\n\n");
480         }
481         if(arguments>0) {
482                 out_printf(out,"enum {\n\tARG_0,\n");
483                 for(li=c->nodes;li;li=g_list_next(li)) {
484                         Node *n = li->data;
485                         if(n->type == ARGUMENT_NODE) {
486                                 Argument *a = (Argument *)n;
487                                 char *s = g_strdup(a->name);
488                                 g_strup(s);
489                                 out_printf(out,"\tARG_%s,\n",s);
490                                 g_free(s);
491                         }
492                 }
493                 out_printf(out, "};\n\n");
494         }
495
496         if(signals>0)
497                 out_printf(out,
498                            "static guint object_signals[LAST_SIGNAL] = {0};\n\n");
499
500         out_printf(out, "static %sClass *parent_class = NULL;\n\n",ptypebase);
501 }
502
503 static void
504 add_get_type(void)
505 {
506         out_printf(out, "guint\n"
507                 "%s_get_type (void)\n"
508                 "{\n"
509                 "\tstatic guint type = 0;\n\n"
510                 "\tif (!type) {\n"
511                 "\t\tstatic const GtkTypeInfo info = {\n"
512                 "\t\t\t\"%s\",\n"
513                 "\t\t\tsizeof (%s),\n"
514                 "\t\t\tsizeof (%sClass),\n"
515                 "\t\t\t(GtkClassInitFunc) %s_class_init,\n"
516                 "\t\t\t(GtkObjectInitFunc) %s_init,\n"
517                 "\t\t\t/* reserved_1 */ NULL,\n"
518                 "\t\t\t/* reserved_2 */ NULL,\n"
519                 "\t\t\t(GtkClassInitFunc) NULL,\n"
520                 "\t\t};\n\n"
521                 "\t\ttype = gtk_type_unique (%s_get_type(), &info);\n"
522                 "\t}\n\n"
523                 "\treturn type;\n"
524                 "}\n\n",
525                 funcbase,typebase,typebase,typebase,
526                 funcbase,funcbase,pfuncbase);
527 }
528
529 static void
530 add_overrides(Class *c, char *oname)
531 {
532         GList *li;
533         GHashTable *done;
534         char *s;
535         
536         done = g_hash_table_new(g_str_hash,g_str_equal);
537         s = g_strdup("GtkObject"); /* This was already done */
538         g_hash_table_insert(done,s,s);
539         for(li=c->nodes;li;li=g_list_next(li)) {
540                 Node *n = li->data;
541                 char *f;
542                 Method *m;
543                 if(n->type != METHOD_NODE ||
544                    ((Method *)n)->scope != OVERRIDE_METHOD)
545                         continue;
546                 m = (Method *)n;
547                 
548                 s = remove_sep(m->otype);
549                 
550                 if(g_hash_table_lookup(done,s)) {
551                         g_free(s);
552                         continue;
553                 }
554                 g_hash_table_insert(done,s,s);
555
556                 f = replace_sep(m->otype,'_');
557                 g_strdown(f);
558
559                 out_printf(out,"\t%sClass *%s_class = (%sClass *)%s;\n",
560                         s,f,s,oname);
561                 
562                 g_free(f);
563         }
564         g_hash_table_foreach(done,(GHFunc)g_free,NULL);
565         g_hash_table_destroy(done);
566 }
567
568 static void
569 add_signals(Class *c)
570 {
571         GList *li;
572
573         out_printf(out,"\n");
574         for(li=c->nodes;li;li=g_list_next(li)) {
575                 Node *n = li->data;
576                 Method *m;
577                 char *mar;
578                 char *sig;
579                 int is_none;
580                 int last = FALSE;
581                 if(n->type != METHOD_NODE ||
582                    (((Method *)n)->scope != SIGNAL_FIRST_METHOD &&
583                     ((Method *)n)->scope != SIGNAL_LAST_METHOD &&
584                     ((Method *)n)->scope != PRIVATE_SIGNAL_FIRST_METHOD &&
585                     ((Method *)n)->scope != PRIVATE_SIGNAL_LAST_METHOD))
586                         continue;
587
588                 m = (Method *)n;
589                 
590                 if(m->scope == SIGNAL_FIRST_METHOD ||
591                    m->scope == PRIVATE_SIGNAL_FIRST_METHOD)
592                         last = FALSE;
593                 else
594                         last = TRUE;
595
596                 if(g_hash_table_lookup(marsh,m))
597                         mar = g_strconcat("marshal_",
598                                           (char *)g_hash_table_lookup(marsh,m),
599                                           NULL);
600                 else
601                         mar = g_strdup("gtk_signal_default_marshaller");
602                 
603                 is_none = (strcmp(m->gtktypes->next->data,"NONE")==0);
604                 
605                 sig = g_strdup(m->id);
606                 g_strup(sig);
607                 out_printf(out,"\tobject_signals[%s_SIGNAL] =\n"
608                         "\t\tgtk_signal_new (\"%s\",\n"
609                         "\t\t\tGTK_RUN_%s,\n"
610                         "\t\t\tgtk_object_class->type,\n"
611                         "\t\t\tGTK_SIGNAL_OFFSET (%sClass, %s),\n"
612                         "\t\t\t%s,\n"
613                         "\t\t\tGTK_TYPE_%s, %d",
614                         sig,m->id,
615                         last?"LAST":"FIRST",
616                         typebase,m->id,mar,(char *)m->gtktypes->data,
617                         is_none?0:g_list_length(m->gtktypes->next));
618                 g_free(mar);
619                 g_free(sig);
620                 
621                 if(!is_none) {
622                         GList *l;
623                         for(l=m->gtktypes->next;l;l=g_list_next(l))
624                                 out_printf(out,",\n\t\t\tGTK_TYPE_%s",
625                                         (char *)l->data);
626                 }
627
628                 out_printf(out,");\n");
629         }
630         out_printf(out,"\tgtk_object_class_add_signals (gtk_object_class,\n"
631                 "\t\tobject_signals, LAST_SIGNAL);\n\n");
632 }
633
634 static void
635 set_def_handlers(Class *c, char *oname)
636 {
637         GList *li;
638
639         out_printf(out,"\n");
640         for(li=c->nodes;li;li=g_list_next(li)) {
641                 Node *n = li->data;
642                 Method *m;
643                 if(n->type != METHOD_NODE ||
644                    (((Method *)n)->scope != SIGNAL_FIRST_METHOD &&
645                     ((Method *)n)->scope != SIGNAL_LAST_METHOD &&
646                     ((Method *)n)->scope != PRIVATE_SIGNAL_FIRST_METHOD &&
647                     ((Method *)n)->scope != PRIVATE_SIGNAL_LAST_METHOD &&
648                     ((Method *)n)->scope != VIRTUAL_METHOD &&
649                     ((Method *)n)->scope != PRIVATE_VIRTUAL_METHOD &&
650                     ((Method *)n)->scope != OVERRIDE_METHOD))
651                         continue;
652
653                 m = (Method *)n;
654
655                 if(m->scope == OVERRIDE_METHOD) {
656                         char *s;
657                         s = replace_sep(m->otype,'_');
658                         g_strdown(s);
659                         out_printf(out,"\t%s_class->%s = %s_%s;\n",
660                                 s,m->id,funcbase,m->id);
661                 } else {
662                         if(m->cbuf)
663                                 out_printf(out,"\t%s->%s = _real_%s_%s;\n",
664                                         oname,m->id,funcbase,m->id);
665                         else
666                                 out_printf(out,"\t%s->%s = NULL;\n",
667                                         oname,m->id);
668                 }
669         }
670 }
671
672 static void
673 make_arguments(Class *c)
674 {
675         GList *li;
676
677         out_printf(out,"\n");
678         for(li=c->nodes;li;li=g_list_next(li)) {
679                 Node *n = li->data;
680                 Argument *a;
681                 GString *flags;
682                 GList *l;
683                 char *s;
684                 if(n->type != ARGUMENT_NODE)
685                         continue;
686
687                 a = (Argument *)n;
688                 
689                 if(a->get && a->set)
690                         flags = g_string_new("GTK_ARG_READWRITE");
691                 else if(a->get)
692                         flags = g_string_new("GTK_ARG_READABLE");
693                 else
694                         flags = g_string_new("GTK_ARG_WRITABLE");
695                 
696                 for(l=a->flags;l;l=g_list_next(l))
697                         g_string_sprintfa(flags," | GTK_ARG_%s",(char *)l->data);
698
699                 s = g_strdup(a->name);
700                 g_strup(s);
701                 out_printf(out,"\tgtk_object_add_arg_type(\"%s::%s\",\n"
702                         "\t\tGTK_TYPE_%s,\n"
703                         "\t\t%s,\n"
704                         "\t\tARG_%s);\n",
705                         typebase,a->name,a->gtktype,flags->str,s);
706                 g_free(s);
707                 g_string_free(flags,TRUE);
708         }
709         
710         out_printf(out,
711                    "\n\tgtk_object_class->set_arg = __object_set_arg;\n"
712                    "\tgtk_object_class->get_arg = __object_get_arg;\n");
713 }
714
715 static void
716 add_inits(Class *c)
717 {
718         GList *li;
719         for(li=c->nodes;li;li=g_list_next(li)) {
720                 Node *n = li->data;
721                 Method *m;
722                 if(n->type != METHOD_NODE)
723                         continue;
724                 m = (Method *)n;
725                 if(m->scope == INIT_METHOD) {
726                         if(m->line_no>0)
727                                 out_addline_infile(out,m->line_no);
728                         print_method(out,"static ","\n"," ","",m);
729                         if(m->line_no>0)
730                                 out_addline_outfile(out);
731                         out_printf(out,"{\n");
732                 } else if(m->scope == CLASS_INIT_METHOD) {
733                         if(m->line_no>0)
734                                 out_addline_infile(out,m->line_no);
735                         print_method(out,"static ","\n"," ","",m);
736                         if(m->line_no>0)
737                                 out_addline_outfile(out);
738                         out_printf(out,"{\n");
739                         if(signals>0 ||
740                            arguments>0 ||
741                            overrides>0)
742                                 out_printf(out,
743                                            "\tGtkObjectClass *"
744                                            "gtk_object_class = "
745                                            "(GtkObjectClass*) %s;\n",
746                                            ((FuncArg *)m->args->data)->name);
747                         
748                         if(overrides>0)
749                                 add_overrides(c,
750                                               ((FuncArg *)m->args->data)->name);
751                         
752                         out_printf(out,"\n\tparent_class = "
753                                 "gtk_type_class (%s_get_type ());\n",
754                                 pfuncbase);
755
756                         if(signals>0)
757                                 add_signals(c);
758
759                         set_def_handlers(c, ((FuncArg *)m->args->data)->name);
760                         
761                         if(arguments>0)
762                                 make_arguments(c);
763                 } else
764                         continue;
765
766                 if(m->cbuf) {
767                         out_printf(out," {\n");
768                         out_addline_infile(out,m->ccode_line);
769                         out_printf(out,"%s\n",m->cbuf->str);
770                         out_addline_outfile(out);
771                         out_printf(out," }\n",m->cbuf->str);
772                 } else {
773                         out_printf(out,"return;\n");
774                 }
775                 out_printf(out,"}\n");
776         }
777 }
778
779 static void
780 add_getset_arg(Class *c, int is_set)
781 {
782         GList *li;
783         out_printf(out,"\nstatic void\n"
784                 "__object_%s_arg (GtkObject *object,\n"
785                 "\tGtkArg *arg,\n"
786                 "\tguint arg_id)\n"
787                 "{\n"
788                 "\t%s *self, *this;\n\n"
789                 "\tself = this = %s (object);\n\n"
790                 "\tswitch (arg_id) {\n",
791                 is_set?"set":"get",typebase,macrobase);
792
793         for(li=c->nodes;li;li=g_list_next(li)) {
794                 Node *n = li->data;
795                 Argument *a;
796                 char *s;
797                 GString *cbuf;
798                 int line_no;
799                 if(n->type != ARGUMENT_NODE)
800                         continue;
801                 a = (Argument *)n;
802                 if(is_set) {
803                         cbuf = a->set;
804                         line_no = a->set_line;
805                 } else {
806                         cbuf = a->get;
807                         line_no = a->get_line;
808                 }
809                 if(!cbuf)
810                         continue;
811                 s = g_strdup(a->name);
812                 g_strup(s);
813                 out_printf(out,"\tcase ARG_%s:\n"
814                         "#define ARG (GTK_VALUE_%s(*arg))\n"
815                         "\t\t{\n",
816                         s,a->gtktype);
817                 g_free(s);
818                 out_addline_infile(out,line_no);
819                 out_printf(out,"%s\n",cbuf->str);
820                 out_addline_outfile(out);
821                 out_printf(out,"\t\t}\n\t\tbreak;\n"
822                         "#undef ARG\n");
823         }
824         out_printf(out,"\tdefault:\n\t\tbreak;\n\t}\n}\n");
825 }
826
827 static void
828 print_checks(Method *m, FuncArg *fa)
829 {
830         GList *li;
831         int is_void;
832         is_void = (strcmp(m->mtype->name,"void")==0 &&
833                    m->mtype->stars == 0);
834         
835         for(li=fa->checks;li;li=g_list_next(li)) {
836                 Check *ch = li->data;
837                 char *s;
838                 if(is_void)
839                         out_printf(out,"\tg_return_if_fail (");
840                 else
841                         out_printf(out,"\tg_return_val_if_fail (");
842                 switch(ch->chtype) {
843                 case NULL_CHECK:
844                         out_printf(out,"%s != NULL",fa->name);
845                         break;
846                 case TYPE_CHECK:
847                         s = make_is_macro(fa->atype->name);
848                         out_printf(out,"%s (%s)",s,fa->name);
849                         g_free(s);
850                         break;
851                 case LT_CHECK:
852                         out_printf(out,"%s < %s",fa->name,ch->number);
853                         break;
854                 case GT_CHECK:
855                         out_printf(out,"%s > %s",fa->name,ch->number);
856                         break;
857                 case LE_CHECK:
858                         out_printf(out,"%s <= %s",fa->name,ch->number);
859                         break;
860                 case GE_CHECK:
861                         out_printf(out,"%s >= %s",fa->name,ch->number);
862                         break;
863                 case EQ_CHECK:
864                         out_printf(out,"%s == %s",fa->name,ch->number);
865                         break;
866                 case NE_CHECK:
867                         out_printf(out,"%s != %s",fa->name,ch->number);
868                         break;
869                 }
870                 if(is_void)
871                         out_printf(out,");\n");
872                 else {
873                         out_printf(out,", (");
874                         print_type(out,m->mtype);
875                         out_printf(out,")%s);\n",
876                                 m->onerror?m->onerror:"0");
877                 }
878         }
879 }
880
881 static void
882 print_preconditions(Method *m)
883 {
884         GList *li;
885         
886         for(li=m->args;li;li=g_list_next(li)) {
887                 FuncArg *fa = li->data;
888                 if(fa->checks)
889                         print_checks(m,fa);
890         }
891 }
892
893 static void
894 print_method_body(Method *m, int pre)
895 {
896         out_printf(out,"{\n");
897         if(pre) {
898                 print_preconditions(m);
899                 out_printf(out,"\t{\n");
900         }
901
902         out_addline_infile(out,m->ccode_line);
903         out_printf(out,"\t\t%s\n",m->cbuf->str);
904         out_addline_outfile(out);
905
906         if(pre)
907                 out_printf(out,"\t}\n");
908         out_printf(out,"}\n");
909 }
910
911 static void
912 put_method(Method *m)
913 {
914         char *s;
915         int private = FALSE;
916         out_printf(out,"\n");
917         switch(m->scope) {
918         case PUBLIC_SCOPE:
919                 out_addline_infile(out,m->line_no);
920                 print_method(out,"","\n"," ","",m);
921                 print_method_body(m,TRUE);
922                 break;
923         case PRIVATE_SCOPE:
924                 out_addline_infile(out,m->line_no);
925                 print_method(out,"static ","\n"," ","",m);
926                 print_method_body(m,TRUE);
927                 break;
928         case PRIVATE_SIGNAL_FIRST_METHOD:
929         case PRIVATE_SIGNAL_LAST_METHOD:
930                 private = TRUE;
931         case SIGNAL_FIRST_METHOD:
932         case SIGNAL_LAST_METHOD:
933                 out_addline_infile(out,m->line_no);
934                 print_method(out,private?"static ":"","\n"," ","",m);
935                 out_addline_outfile(out);
936                 out_printf(out,"{\n");
937                 s = g_strdup(m->id);
938                 g_strup(s);
939                 if(strcmp(m->mtype->name,"void")==0 &&
940                    m->mtype->stars==0) {
941                         GList *li;
942                         print_preconditions(m);
943                         if(((FuncArg *)m->args->data)->name)
944                         out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
945                                 "\t\tobject_signals[%s_SIGNAL]",
946                                 ((FuncArg *)m->args->data)->name,s);
947                         for(li=m->args->next;li;li=g_list_next(li)) {
948                                 FuncArg *fa = li->data;
949                                 out_printf(out,",\n\t\t%s",fa->name);
950                         }
951                         out_printf(out,");\n}\n");
952                 } else {
953                         GList *li;
954                         out_printf(out,"\t");
955                         print_type(out,m->mtype);
956                         out_printf(out,"return_val;\n");
957                         print_preconditions(m);
958                         out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
959                                 "\t\tobject_signals[%s_SIGNAL]",
960                                 ((FuncArg *)m->args->data)->name,s);
961                         for(li=m->args->next;li;li=g_list_next(li)) {
962                                 FuncArg *fa = li->data;
963                                 out_printf(out,",\n\t\t%s",fa->name);
964                         }
965                         out_printf(out,",\n\t\t&return_val);\n"
966                                 "\treturn return_val;\n}\n");
967                 }
968
969                 if(!m->cbuf)
970                         break;
971                 out_addline_infile(out,m->line_no);
972                 print_method(out,"static ","\n_real_"," ","",m);
973                 print_method_body(m,FALSE);
974                 break;
975         case PRIVATE_VIRTUAL_METHOD:
976                 private = TRUE;
977         case VIRTUAL_METHOD:
978                 out_addline_infile(out,m->line_no);
979                 print_method(out,private?"static ":"","\n"," ","",m);
980                 out_addline_outfile(out);
981                 out_printf(out,"{\n"
982                         "\t%sClass *class;\n",typebase);
983                 print_preconditions(m);
984                 out_printf(out,"\tclass = %s_CLASS(GTK_OBJECT(%s)->klass);\n\n"
985                         "\tif(class->%s)\n",
986                         macrobase, ((FuncArg *)m->args->data)->name, m->id);
987                 if(strcmp(m->mtype->name,"void")==0 &&
988                    m->mtype->stars==0) {
989                         GList *li;
990                         out_printf(out,"\t\t(*class->%s)(%s",m->id,
991                                    ((FuncArg *)m->args->data)->name);
992                         for(li=m->args->next;li;li=g_list_next(li)) {
993                                 FuncArg *fa = li->data;
994                                 out_printf(out,",%s",fa->name);
995                         }
996                         out_printf(out,");\n}\n");
997                 } else {
998                         GList *li;
999                         out_printf(out,"\t\treturn (*class->%s)(%s",m->id,
1000                                    ((FuncArg *)m->args->data)->name);
1001                         for(li=m->args->next;li;li=g_list_next(li)) {
1002                                 FuncArg *fa = li->data;
1003                                 out_printf(out,",%s",fa->name);
1004                         }
1005                         out_printf(out,");\n"
1006                                 "\telse\n"
1007                                 "\t\treturn (");
1008                         print_type(out,m->mtype);
1009                         out_printf(out,")(%s);\n}\n",
1010                                 m->onerror?m->onerror:"0");
1011                 }
1012
1013                 if(!m->cbuf)
1014                         break;
1015                 out_addline_infile(out,m->line_no);
1016                 print_method(out,"static ","\n_real_"," ","",m);
1017                 print_method_body(m,FALSE);
1018                 break;
1019         case OVERRIDE_METHOD:
1020                 out_addline_infile(out,m->line_no);
1021                 print_method(out,"static ","\n"," ","",m);
1022                 print_method_body(m,TRUE);
1023                 break;
1024         default:
1025                 break;
1026         }
1027 }
1028
1029 static void
1030 check_duplicate(Class *c,Node *node,char *id, int line_no)
1031 {
1032         GList *l;
1033         for(l=c->nodes;l;l=g_list_next(l)) {
1034                 Node *n = l->data;
1035                 char *nid;
1036                 int nline_no;
1037                 char *s;
1038                 if(n->type == METHOD_NODE) {
1039                         Method *m = (Method *)n;
1040                         nid = m->id;
1041                         nline_no = m->line_no;
1042                 } else if(n->type == VARIABLE_NODE) {
1043                         Variable *v = (Variable *)n;
1044                         nid = v->id;
1045                         nline_no = v->line_no;
1046                 } else
1047                         continue;
1048                 if(n==node ||
1049                    line_no>=nline_no ||
1050                    strcmp(nid,id)!=0)
1051                         continue;
1052                 s = g_strdup_printf("symbol '%s' redefined, "
1053                                     "first defined on line %d",
1054                                     id,line_no);
1055                 print_error(FALSE,s,nline_no);
1056         }
1057 }
1058
1059 static void
1060 check_duplicate_symbols(Class *c)
1061 {
1062         GList *l;
1063         for(l=c->nodes;l;l=g_list_next(l)) {
1064                 Node *n = l->data;
1065                 if(n->type == METHOD_NODE) {
1066                         Method *m = (Method *)n;
1067                         check_duplicate(c,n,m->id,m->line_no);
1068                 } else if(n->type == VARIABLE_NODE) {
1069                         Variable *v = (Variable *)n;
1070                         check_duplicate(c,n,v->id,v->line_no);
1071                 }
1072         }
1073 }
1074
1075 static void
1076 check_duplicate_named(Class *c,Node *node,char *id, int line_no)
1077 {
1078         GList *l;
1079         for(l=c->nodes;l;l=g_list_next(l)) {
1080                 Node *n = l->data;
1081                 char *nid;
1082                 int nline_no;
1083                 char *s;
1084                 if(n->type == METHOD_NODE) {
1085                         Method *m = (Method *)n;
1086                         if(m->scope == SIGNAL_LAST_METHOD ||
1087                            m->scope == SIGNAL_FIRST_METHOD ||
1088                            m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1089                            m->scope == PRIVATE_SIGNAL_FIRST_METHOD) {
1090                                 nid = m->id;
1091                                 nline_no = m->line_no;
1092                         } else
1093                                 continue;
1094                 } else if(n->type == ARGUMENT_NODE) {
1095                         Argument *a = (Argument *)n;
1096                         nid = a->name;
1097                         nline_no = a->line_no;
1098                 } else
1099                         continue;
1100                 if(n==node ||
1101                    line_no>=nline_no ||
1102                    strcmp(nid,id)!=0)
1103                         continue;
1104                 s = g_strdup_printf("named symbol (argument or signal) '%s' "
1105                                     "redefined, first defined on line %d",
1106                                     id,line_no);
1107                 print_error(FALSE,s,nline_no);
1108         }
1109 }
1110
1111 static void
1112 check_duplicate_signals_args(Class *c)
1113 {
1114         GList *l;
1115         for(l=c->nodes;l;l=g_list_next(l)) {
1116                 Node *n = l->data;
1117                 if(n->type == METHOD_NODE) {
1118                         Method *m = (Method *)n;
1119                         if(m->scope == SIGNAL_LAST_METHOD ||
1120                            m->scope == SIGNAL_FIRST_METHOD ||
1121                            m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1122                            m->scope == PRIVATE_SIGNAL_FIRST_METHOD)
1123                                 check_duplicate_named(c,n,m->id,m->line_no);
1124                 } else if(n->type == ARGUMENT_NODE) {
1125                         Argument *a = (Argument *)n;
1126                         check_duplicate_named(c,n,a->name,a->line_no);
1127                 }
1128         }
1129 }
1130
1131 static void
1132 check_public_new(Class *c)
1133 {
1134         GList *l;
1135         for(l=c->nodes;l;l=g_list_next(l)) {
1136                 Node *n = l->data;
1137                 if(n->type == METHOD_NODE) {
1138                         Method *m = (Method *)n;
1139                         if(m->scope!=PUBLIC_SCOPE &&
1140                            strcmp(m->id,"new")==0)
1141                                 print_error(TRUE,
1142                                             "'new' should be a public method",
1143                                             m->line_no);
1144                 }
1145         }
1146 }
1147
1148 static void
1149 check_vararg(Class *c)
1150 {
1151         GList *l;
1152         for(l=c->nodes;l;l=g_list_next(l)) {
1153                 Node *n = l->data;
1154                 if(n->type == METHOD_NODE) {
1155                         Method *m = (Method *)n;
1156                         if(!m->vararg)
1157                                 continue;
1158                         if(m->scope == OVERRIDE_METHOD ||
1159                            m->scope == SIGNAL_LAST_METHOD ||
1160                            m->scope == SIGNAL_FIRST_METHOD ||
1161                            m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1162                            m->scope == PRIVATE_SIGNAL_FIRST_METHOD ||
1163                            m->scope == VIRTUAL_METHOD ||
1164                            m->scope == PRIVATE_VIRTUAL_METHOD) {
1165                                 print_error(FALSE,
1166                                             "signals, overrides and virtuals, "
1167                                             "can't have variable argument "
1168                                             "lists",
1169                                             m->line_no);
1170                         }
1171                 }
1172         }
1173 }
1174
1175 static int
1176 count_signals(Class *c)
1177 {
1178         int num = 0;
1179         GList *l;
1180         for(l=c->nodes;l;l=g_list_next(l)) {
1181                 Node *n = l->data;
1182                 if(n->type == METHOD_NODE) {
1183                         Method *m = (Method *)n;
1184                         if(m->scope == SIGNAL_LAST_METHOD ||
1185                            m->scope == SIGNAL_FIRST_METHOD ||
1186                            m->scope == PRIVATE_SIGNAL_LAST_METHOD ||
1187                            m->scope == PRIVATE_SIGNAL_FIRST_METHOD)
1188                                 num++;
1189                 }
1190         }
1191         return num;
1192 }
1193
1194 static int
1195 count_arguments(Class *c)
1196 {
1197         int num = 0;
1198         GList *li;
1199
1200         for(li=c->nodes;li;li=g_list_next(li)) {
1201                 Node *n = li->data;
1202                 if(n->type == ARGUMENT_NODE)
1203                         num ++;
1204         }
1205         return num;
1206 }
1207
1208 static int
1209 count_overrides(Class *c)
1210 {
1211         int num = 0;
1212         GList *l;
1213         for(l=c->nodes;l;l=g_list_next(l)) {
1214                 Node *n = l->data;
1215                 if(n->type == METHOD_NODE) {
1216                         Method *m = (Method *)n;
1217                         if(m->scope == OVERRIDE_METHOD)
1218                                 num++;
1219                 }
1220         }
1221         return num;
1222 }
1223
1224
1225 static void
1226 open_files(void)
1227 {
1228         char *outfile,*outfileh;
1229
1230         outfile = g_strconcat(filebase,".c",NULL);
1231         outfileh = g_strconcat(filebase,".h",NULL);
1232         
1233         out = fopen(outfile,"w");
1234         if(!out) {
1235                 g_error("Cannot open outfile: %s",outfile);
1236         }
1237         outh = fopen(outfileh,"w");
1238         if(!outh) {
1239                 g_error("Cannot open outfile: %s",outfileh);
1240         }
1241 }
1242
1243 static void
1244 generate_outfiles(void)
1245 {
1246         char *p;
1247         GList *li;
1248         time_t curtime;
1249
1250         time(&curtime);
1251         out_printf(outh,"/* Generated by GOB (v%s) on %s"
1252                "   (do not edit directly) */\n\n",VERSION,ctime(&curtime));
1253         out_printf(out,"/* Generated by GOB (v%s) on %s"
1254                "   (do not edit directly) */\n\n",VERSION,ctime(&curtime));
1255         
1256         p = replace_sep(((Class *)class)->otype,'_');
1257         g_strup(p);
1258         out_printf(outh,"#ifndef __%s_H__\n#define __%s_H__\n\n"
1259                 "#include <gtk/gtk.h>\n\n",p,p);
1260         g_free(p);
1261
1262         out_printf(outh,"#ifdef __cplusplus\n"
1263                 "extern \"C\" {\n"
1264                 "#endif /* __cplusplus */\n\n");
1265         
1266         out_printf(out,"#include \"%s.h\"\n\n",filebase);
1267         
1268         for(li=nodes;li;li=g_list_next(li)) {
1269                 Node *node = li->data;
1270                 if(node->type == CCODE_NODE) {
1271                         CCode *cc = (CCode *)node;
1272                         FILE *fp;
1273                         if(cc->header)
1274                                 fp = outh;
1275                         else {
1276                                 fp = out;
1277                                 out_addline_infile(fp,cc->line_no);
1278                         }
1279                         out_printf(fp,"\n%s\n",cc->cbuf->str);
1280                         if(!cc->header)
1281                                 out_addline_outfile(fp);
1282                 } else if(node->type == CLASS_NODE) {
1283                         GList *l;
1284                         Class *c = (Class *)class;
1285                         char *otype,*ptype;
1286
1287                         signals = count_signals(c);
1288                         arguments = count_arguments(c);
1289                         overrides = count_overrides(c);
1290                         
1291                         out_printf(outh,"\n#define %s(obj)\t"
1292                                 "GTK_CHECK_CAST((obj),%s_get_type(),%s)\n",
1293                                 macrobase,funcbase,typebase);
1294                         out_printf(outh,"#define %s_CLASS(klass)\t"
1295                                 "GTK_CHECK_CLASS_CAST((klass),%s_get_type(),%sClass)\n",
1296                                 macrobase,funcbase,typebase);
1297                         out_printf(outh,"#define %s(obj)\t"
1298                                 "GTK_CHECK_TYPE((obj), %s_get_type ())\n\n",
1299                                 macrois,funcbase);
1300
1301                         otype = remove_sep(c->otype);
1302                         ptype = remove_sep(c->ptype);
1303                         out_printf(outh,"\ntypedef struct _%s %s;\n",otype,otype);
1304                         out_printf(outh,"struct _%s {\n\t%s __parent__;\n",
1305                                    otype,ptype);
1306                         for(l=c->nodes;l;l=g_list_next(l)) {
1307                                 Node *n = l->data;
1308                                 if(n->type == VARIABLE_NODE)
1309                                         put_variable((Variable *)n);
1310                         }
1311                         out_printf(outh,"};\n");
1312
1313                         out_printf(outh,"\ntypedef struct _%sClass %sClass;\n",
1314                                 otype,otype);
1315                         out_printf(outh,
1316                                 "struct _%sClass {\n\t%sClass __parent__;\n",
1317                                 otype,ptype);
1318                         for(l=c->nodes;l;l=g_list_next(l)) {
1319                                 Node *n = l->data;
1320                                 if(n->type == METHOD_NODE)
1321                                         put_vs_method((Method *)n);
1322                         }
1323                         out_printf(outh,"};\n\n");
1324
1325                         out_printf(outh,"guint\t%s_get_type\t(void);\n",funcbase);
1326                         
1327                         if(arguments>0) {
1328                                 out_printf(out,"static void __object_set_arg "
1329                                            "(GtkObject *object, GtkArg *arg, "
1330                                            "guint arg_id);\n"
1331                                            "static void __object_get_arg "
1332                                            "(GtkObject *object, GtkArg *arg, "
1333                                            "guint arg_id);\n");
1334                         }
1335
1336                         for(l=c->nodes;l;l=g_list_next(l)) {
1337                                 Node *n = l->data;
1338                                 if(n->type == METHOD_NODE) {
1339                                         put_pub_method((Method *)n);
1340                                         put_priv_method_prot((Method *)n);
1341                                 }
1342                         }
1343
1344                         if(signals>0) {
1345                                 for(l=c->nodes;l;l=g_list_next(l)) {
1346                                         Node *n = l->data;
1347                                         if(n->type == METHOD_NODE) {
1348                                                 add_signal_prots((Method *)n);
1349                                         }
1350                                 }
1351                         }
1352                         
1353                         add_enums(c);
1354                         
1355                         add_get_type();
1356
1357                         def_methods(c);
1358
1359                         out_printf(out,"#define GET_NEW (gtk_type_new(%s_get_type()))\n",
1360                                 funcbase);
1361                         
1362                         add_inits(c);
1363
1364                         if(arguments>0) {
1365                                 add_getset_arg(c, TRUE);
1366                                 add_getset_arg(c, FALSE);
1367                         }
1368
1369                         for(l=c->nodes;l;l=g_list_next(l)) {
1370                                 Node *n = l->data;
1371                                 if(n->type == METHOD_NODE) {
1372                                         put_method((Method *)n);
1373                                 }
1374                         }
1375
1376                         out_printf(out,"#undef GET_NEW\n");
1377
1378                         undef_methods(c);
1379
1380                         g_free(otype);
1381                         g_free(ptype);
1382                 } else
1383                         g_assert_not_reached();
1384         }
1385
1386         out_printf(outh,"\n#ifdef __cplusplus\n"
1387                 "}\n"
1388                 "#endif /* __cplusplus */\n\n"
1389                 "#endif");
1390 }
1391
1392 static void
1393 usage(poptContext optCon, int exitcode, char *error, char *addl)
1394 {
1395         poptPrintUsage(optCon, stderr, 0);
1396         if (error) fprintf(stderr, "%s: %s", error, addl);
1397         exit(exitcode);
1398 }
1399
1400
1401 int
1402 main(int argc, char *argv[])
1403 {
1404         int c;
1405         poptContext optCon;
1406         
1407         struct poptOption optionsTable[] = {
1408                 { "exit-on-warn", 'w', 0, &exit_on_warn, 0,
1409                          "exit on warnings" },
1410                 POPT_AUTOHELP
1411                 { NULL, 0, 0, NULL, 0 }
1412         };
1413         
1414         optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
1415         poptSetOtherOptionHelp(optCon, "[OPTIONS]* [filename]");
1416         
1417         while ((c = poptGetNextOpt(optCon)) >= 0)
1418                 ;
1419         
1420         filename = poptGetArg(optCon);
1421         if(!(poptPeekArg(optCon) == NULL))
1422                 usage(optCon, 1, "Specify only one file",
1423                       ".e.g., filename.gob");
1424                         
1425         if (c < -1) {
1426                 /* an error occurred during option processing */
1427                 fprintf(stderr, "%s: %s\n",
1428                         poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
1429                         poptStrerror(c));
1430                 return 1;
1431         }
1432         
1433         if(filename) {
1434                 yyin = fopen(filename,"r");
1435                 if(!yyin) {
1436                         fprintf(stderr,"Error: can't open file '%s'\n",
1437                                 filename);
1438                         exit(1);
1439                 }
1440         } else
1441                 filename = "stdin";
1442
1443         /*yydebug = 1;*/
1444         if(yyparse()!=0)
1445                 g_error("Parsing errors, quitting");
1446         if(!class)
1447                 print_error(FALSE," no class defined",0);
1448         
1449         make_bases();
1450         
1451         exit_on_error = FALSE;
1452         make_inits((Class *)class);
1453         check_duplicate_symbols((Class *)class);
1454         check_duplicate_signals_args((Class *)class);
1455         check_public_new((Class *)class);
1456         check_vararg((Class *)class);
1457         exit_on_error = TRUE;
1458         
1459         if(got_error)
1460                 exit(1);
1461
1462         open_files();
1463         
1464         generate_outfiles();
1465
1466         fclose(out);
1467         fclose(outh);
1468         
1469         poptFreeContext(optCon);
1470         return 0;
1471 }