]> git.draconx.ca Git - gob-dx.git/blobdiff - src/main.c
Release 0.90.0
[gob-dx.git] / src / main.c
index e418b4e2814ea101a5a585fbc3a4574163da8d8b..54293fca1ee59b654fe545eb8ac4a8757f6f0659 100644 (file)
@@ -29,6 +29,7 @@
 #include "tree.h"
 #include "parse.h"
 #include "out.h"
+#include "main.h"
 
 char *filename = "stdin";
 
@@ -55,20 +56,24 @@ 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);
 }
 
@@ -750,8 +755,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);
 
@@ -901,8 +906,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);
@@ -914,8 +921,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);
@@ -937,13 +945,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);
@@ -951,7 +960,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);
@@ -980,6 +990,121 @@ 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 int
 count_signals(Class *c)
 {
@@ -1254,8 +1379,16 @@ 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);
+       exit_on_error = TRUE;
        
+       if(got_error)
+               exit(1);
+
        open_files();
        
        generate_outfiles();