]> git.draconx.ca Git - gob-dx.git/blobdiff - src/main.c
Release 0.90.1
[gob-dx.git] / src / main.c
index be842c647cafe1e18729812dc07fb769b08585e5..0ed34ee56c2827e0ab8d3b9321a1fe0edf842ce0 100644 (file)
@@ -29,6 +29,7 @@
 #include "tree.h"
 #include "parse.h"
 #include "out.h"
+#include "main.h"
 
 char *filename = "stdin";
 
@@ -49,25 +50,30 @@ static char *ptypebase;
 
 static int signals = 0;
 static int arguments = 0;
+static int overrides = 0;
 
 FILE *out;
 FILE *outh;
 
 int exit_on_warn = FALSE;
+int exit_on_error = TRUE;
+int got_error = FALSE;
 
-static void
+void
 print_error(int is_warn, char *error,int line)
 {
        char *w;
        if(is_warn)
                w = "Warning:";
-       else
+       else {
                w = "Error:";
+               got_error = TRUE;
+       }
        if(line>0)
                fprintf(stderr,"%s:%d: %s %s\n",filename,line,w,error);
        else
                fprintf(stderr,"%s: %s %s\n",filename,w,error);
-       if(!is_warn || exit_on_warn)
+       if((!is_warn || exit_on_warn) && exit_on_error)
                exit(1);
 }
 
@@ -251,6 +257,8 @@ print_method(FILE *fp, char *typeprefix, char *nameprefix,
                                out_printf(fp,"%s",arg->name); 
 
                }
+               if(m->vararg)
+                       out_printf(fp,", ..."); 
        } else {
                out_printf(fp,"void"); 
        }
@@ -341,7 +349,7 @@ make_inits(Class *cl)
                                  (Type *)new_type(0,g_strdup("void")),
                                  NULL,NULL,g_strdup("class_init"),
                                  make_init_args(cl,g_strdup("c"),TRUE),
-                                 NULL, NULL,0,0);
+                                 NULL, NULL,0,0,FALSE);
                cl->nodes = g_list_prepend(cl->nodes,node);
        }
        if(!got_init) {
@@ -349,7 +357,7 @@ make_inits(Class *cl)
                                  (Type *)new_type(0,g_strdup("void")),
                                  NULL,NULL,g_strdup("init"),
                                  make_init_args(cl,g_strdup("o"),FALSE),
-                                 NULL, NULL,0,0);
+                                 NULL, NULL,0,0,FALSE);
                cl->nodes = g_list_prepend(cl->nodes,node);
        }
 }
@@ -699,12 +707,19 @@ add_inits(Class *c)
                        print_method(out,"static ","\n"," ","",m);
                        if(m->line_no>0)
                                out_addline_outfile(out);
-                       out_printf(out,"{\n"
-                               "\tGtkObjectClass *gtk_object_class = "
-                               "(GtkObjectClass*) %s;\n",
-                               ((FuncArg *)m->args->data)->name);
+                       out_printf(out,"{\n");
+                       if(signals>0 ||
+                          arguments>0 ||
+                          overrides>0)
+                               out_printf(out,
+                                          "\tGtkObjectClass *"
+                                          "gtk_object_class = "
+                                          "(GtkObjectClass*) %s;\n",
+                                          ((FuncArg *)m->args->data)->name);
                        
-                       add_overrides(c, ((FuncArg *)m->args->data)->name);
+                       if(overrides>0)
+                               add_overrides(c,
+                                             ((FuncArg *)m->args->data)->name);
                        
                        out_printf(out,"\n\tparent_class = "
                                "gtk_type_class (%s_get_type ());\n",
@@ -742,8 +757,8 @@ add_getset_arg(Class *c, int is_set)
                "\tGtkArg *arg,\n"
                "\tguint arg_id)\n"
                "{\n"
-               "\t%s *this;\n\n"
-               "\tthis = %s (object);\n\n"
+               "\t%s *self, *this;\n\n"
+               "\tself = this = %s (object);\n\n"
                "\tswitch (arg_id) {\n",
                is_set?"set":"get",typebase,macrobase);
 
@@ -893,8 +908,10 @@ put_method(Method *m)
                   m->mtype->stars==0) {
                        GList *li;
                        print_preconditions(m);
-                       out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (this),\n"
-                               "\t\tobject_signals[%s_SIGNAL]",s);
+                       if(((FuncArg *)m->args->data)->name)
+                       out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
+                               "\t\tobject_signals[%s_SIGNAL]",
+                               ((FuncArg *)m->args->data)->name,s);
                        for(li=m->args->next;li;li=g_list_next(li)) {
                                FuncArg *fa = li->data;
                                out_printf(out,",\n\t\t%s",fa->name);
@@ -906,8 +923,9 @@ put_method(Method *m)
                        print_type(out,m->mtype);
                        out_printf(out,"return_val;\n");
                        print_preconditions(m);
-                       out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (this),\n"
-                               "\t\tobject_signals[%s_SIGNAL]",s);
+                       out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
+                               "\t\tobject_signals[%s_SIGNAL]",
+                               ((FuncArg *)m->args->data)->name,s);
                        for(li=m->args->next;li;li=g_list_next(li)) {
                                FuncArg *fa = li->data;
                                out_printf(out,",\n\t\t%s",fa->name);
@@ -929,13 +947,14 @@ put_method(Method *m)
                out_printf(out,"{\n"
                        "\t%sClass *class;\n",typebase);
                print_preconditions(m);
-               out_printf(out,"\tclass = %s_CLASS(GTK_OBJECT(this)->klass);\n\n"
+               out_printf(out,"\tclass = %s_CLASS(GTK_OBJECT(%s)->klass);\n\n"
                        "\tif(class->%s)\n",
-                       macrobase,m->id);
+                       macrobase, ((FuncArg *)m->args->data)->name, m->id);
                if(strcmp(m->mtype->name,"void")==0 &&
                   m->mtype->stars==0) {
                        GList *li;
-                       out_printf(out,"\t\t(*class->%s)(this",m->id);
+                       out_printf(out,"\t\t(*class->%s)(%s",m->id,
+                                  ((FuncArg *)m->args->data)->name);
                        for(li=m->args->next;li;li=g_list_next(li)) {
                                FuncArg *fa = li->data;
                                out_printf(out,",%s",fa->name);
@@ -943,7 +962,8 @@ put_method(Method *m)
                        out_printf(out,");\n}\n");
                } else {
                        GList *li;
-                       out_printf(out,"\t\treturn (*class->%s)(this",m->id);
+                       out_printf(out,"\t\treturn (*class->%s)(%s",m->id,
+                                  ((FuncArg *)m->args->data)->name);
                        for(li=m->args->next;li;li=g_list_next(li)) {
                                FuncArg *fa = li->data;
                                out_printf(out,",%s",fa->name);
@@ -972,6 +992,145 @@ put_method(Method *m)
        }
 }
 
+static void
+check_duplicate(Class *c,Node *node,char *id, int line_no)
+{
+       GList *l;
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               char *nid;
+               int nline_no;
+               char *s;
+               if(n->type == METHOD_NODE) {
+                       Method *m = (Method *)n;
+                       nid = m->id;
+                       nline_no = m->line_no;
+               } else if(n->type == VARIABLE_NODE) {
+                       Variable *v = (Variable *)n;
+                       nid = v->id;
+                       nline_no = v->line_no;
+               } else
+                       continue;
+               if(n==node ||
+                  line_no>=nline_no ||
+                  strcmp(nid,id)!=0)
+                       continue;
+               s = g_strdup_printf("symbol '%s' redefined, "
+                                   "first defined on line %d",
+                                   id,line_no);
+               print_error(FALSE,s,nline_no);
+       }
+}
+
+static void
+check_duplicate_symbols(Class *c)
+{
+       GList *l;
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               if(n->type == METHOD_NODE) {
+                       Method *m = (Method *)n;
+                       check_duplicate(c,n,m->id,m->line_no);
+               } else if(n->type == VARIABLE_NODE) {
+                       Variable *v = (Variable *)n;
+                       check_duplicate(c,n,v->id,v->line_no);
+               }
+       }
+}
+
+static void
+check_duplicate_named(Class *c,Node *node,char *id, int line_no)
+{
+       GList *l;
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               char *nid;
+               int nline_no;
+               char *s;
+               if(n->type == METHOD_NODE) {
+                       Method *m = (Method *)n;
+                       if(m->scope == SIGNAL_LAST_METHOD ||
+                          m->scope == SIGNAL_FIRST_METHOD) {
+                               nid = m->id;
+                               nline_no = m->line_no;
+                       } else
+                               continue;
+               } else if(n->type == ARGUMENT_NODE) {
+                       Argument *a = (Argument *)n;
+                       nid = a->name;
+                       nline_no = a->line_no;
+               } else
+                       continue;
+               if(n==node ||
+                  line_no>=nline_no ||
+                  strcmp(nid,id)!=0)
+                       continue;
+               s = g_strdup_printf("named symbol (argument or signal) '%s' "
+                                   "redefined, first defined on line %d",
+                                   id,line_no);
+               print_error(FALSE,s,nline_no);
+       }
+}
+
+static void
+check_duplicate_signals_args(Class *c)
+{
+       GList *l;
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               if(n->type == METHOD_NODE) {
+                       Method *m = (Method *)n;
+                       if(m->scope == SIGNAL_LAST_METHOD ||
+                          m->scope == SIGNAL_FIRST_METHOD)
+                               check_duplicate_named(c,n,m->id,m->line_no);
+               } else if(n->type == ARGUMENT_NODE) {
+                       Argument *a = (Argument *)n;
+                       check_duplicate_named(c,n,a->name,a->line_no);
+               }
+       }
+}
+
+static void
+check_public_new(Class *c)
+{
+       GList *l;
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               if(n->type == METHOD_NODE) {
+                       Method *m = (Method *)n;
+                       if(m->scope!=PUBLIC_SCOPE &&
+                          strcmp(m->id,"new")==0)
+                               print_error(TRUE,
+                                           "'new' should be a public method",
+                                           m->line_no);
+               }
+       }
+}
+
+static void
+check_vararg(Class *c)
+{
+       GList *l;
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               if(n->type == METHOD_NODE) {
+                       Method *m = (Method *)n;
+                       if(!m->vararg)
+                               continue;
+                       if(m->scope == OVERRIDE_METHOD ||
+                          m->scope == SIGNAL_LAST_METHOD ||
+                          m->scope == SIGNAL_FIRST_METHOD ||
+                          m->scope == VIRTUAL_METHOD) {
+                               print_error(FALSE,
+                                           "signals, overrides and virtuals, "
+                                           "can't have variable argument "
+                                           "lists",
+                                           m->line_no);
+                       }
+               }
+       }
+}
+
 static int
 count_signals(Class *c)
 {
@@ -1003,6 +1162,21 @@ count_arguments(Class *c)
        return num;
 }
 
+static int
+count_overrides(Class *c)
+{
+       int num = 0;
+       GList *l;
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               if(n->type == METHOD_NODE) {
+                       Method *m = (Method *)n;
+                       if(m->scope == OVERRIDE_METHOD)
+                               num++;
+               }
+       }
+       return num;
+}
 
 
 static void
@@ -1069,6 +1243,7 @@ generate_outfiles(void)
 
                        signals = count_signals(c);
                        arguments = count_arguments(c);
+                       overrides = count_overrides(c);
                        
                        out_printf(outh,"\n#define %s(obj)\t"
                                "GTK_CHECK_CAST((obj),%s_get_type(),%s)\n",
@@ -1230,8 +1405,17 @@ main(int argc, char *argv[])
        
        make_bases();
        
+       exit_on_error = FALSE;
        make_inits((Class *)class);
+       check_duplicate_symbols((Class *)class);
+       check_duplicate_signals_args((Class *)class);
+       check_public_new((Class *)class);
+       check_vararg((Class *)class);
+       exit_on_error = TRUE;
        
+       if(got_error)
+               exit(1);
+
        open_files();
        
        generate_outfiles();