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