]> git.draconx.ca Git - gob-dx.git/blobdiff - src/checks.c
Release 1.0.2
[gob-dx.git] / src / checks.c
index f2bb05885f1acec246bee6d83712acf692b71429..7c675ee041e20a75ed1fb49b88ad5d3b5a9d1380 100644 (file)
@@ -1,5 +1,6 @@
 /* GOB C Preprocessor
  * Copyright (C) 1999-2000 the Free Software Foundation.
+ * Copyright (C) 2000 Eazel, Inc.
  *
  * Author: George Lebl
  *
 #include <stdio.h>
 #include <glib.h>
 
-#include "tree.h"
+#include "treefuncs.h"
 #include "main.h"
 #include "util.h"
 
 #include "checks.h"
 
-void
-check_duplicate(Class *c, Node *node, char *id, int line_no)
+static void
+check_duplicate(Class *c, Node *node, char *id, int line_no,
+               gboolean underscore)
 {
        GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
                Node *n = l->data;
                char *nid;
                int nline_no;
+               gboolean here_underscore = FALSE;
                char *s;
                if(n->type == METHOD_NODE) {
                        Method *m = (Method *)n;
-                       nid = m->id;
+
+                       /* override methods are checked separately */
+                       if(m->method == OVERRIDE_METHOD)
+                               continue;
+
+                       nid = get_real_id(m->id);
                        nline_no = m->line_no;
+
+                       if(m->id[0] == '_' && m->id[1] != '\0')
+                               here_underscore = TRUE;
                } 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 ||
-                  n->type != node->type)
+               if(n == node ||
+                  line_no > nline_no ||
+                  n->type != node->type ||
+                  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);
+               /* this can only happen if the things were methods and
+                * one had an underscore and the other one didn't */
+               if(!no_kill_underscores && underscore != here_underscore)
+                       s = g_strdup_printf("symbol '%s' ('_%s') redefined, "
+                                           "first defined on line %d. "
+                                           "Note that '%s' and '_%s' are "
+                                           "eqivalent.",
+                                           id, id, line_no, id, id);
+               else
+                       s = g_strdup_printf("symbol '%s' redefined, "
+                                           "first defined on line %d",
+                                           id, line_no);
+               print_error(FALSE, s, nline_no);
+               g_free(s);
        }
 }
 
@@ -65,30 +86,76 @@ void
 check_duplicate_symbols(Class *c)
 {
        GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
+       for(l = c->nodes; l != NULL; 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);
+                       gboolean underscore = FALSE;
+                       /* override methods are checked separately */
+                       if(m->method == OVERRIDE_METHOD)
+                               continue;
+                       if(m->id[0] == '_' && m->id[1] != '\0')
+                               underscore = TRUE;
+                       check_duplicate(c, n, get_real_id(m->id), m->line_no,
+                                       underscore);
                } else if(n->type == VARIABLE_NODE) {
                        Variable *v = (Variable *)n;
-                       check_duplicate(c,n,v->id,v->line_no);
+                       check_duplicate(c, n, v->id, v->line_no, FALSE);
                }
        }
 }
 
+static void
+check_duplicate_override(Class *c, Method *method)
+{
+       GList *l;
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
+               Node *n = l->data;
+               Method *m = (Method *)n;
+               char *s;
+               if(n->type != METHOD_NODE ||
+                  m->method != OVERRIDE_METHOD)
+                       continue;
+
+               if(method == m ||
+                  method->line_no > m->line_no ||
+                  strcmp(m->id, method->id) != 0 ||
+                  strcmp(m->otype, method->otype) != 0)
+                       continue;
+               s = g_strdup_printf("override '%s(%s)' redefined, "
+                                   "first defined on line %d",
+                                   m->id, m->otype, method->line_no);
+               print_error(FALSE, s, m->line_no);
+               g_free(s);
+       }
+}
+
+void
+check_duplicate_overrides(Class *c)
+{
+       GList *l;
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
+               Node *n = l->data;
+               Method *m = (Method *)n;
+               if(n->type != METHOD_NODE ||
+                  m->method != OVERRIDE_METHOD)
+                       continue;
+               check_duplicate_override(c, m);
+       }
+}
+
 void
 check_bad_symbols(Class *c)
 {
        GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
                Node *n = l->data;
                if(n->type == METHOD_NODE) {
                        Method *m = (Method *)n;
                        if((m->method == SIGNAL_LAST_METHOD ||
                            m->method == SIGNAL_FIRST_METHOD ||
                            m->method == VIRTUAL_METHOD) &&
-                          strcmp(m->id,"__parent__")==0) {
+                          strcmp(m->id, "__parent__")==0) {
                                char *s;
                                s = g_strdup_printf("'%s' not allowed as an "
                                                    "identifier of signal "
@@ -99,33 +166,32 @@ check_bad_symbols(Class *c)
                        }
                        if(m->method != INIT_METHOD &&
                           m->method != CLASS_INIT_METHOD &&
-                          (strcmp(m->id,"init")==0 ||
-                           strcmp(m->id,"class_init")==0)) {
+                          (strcmp(m->id, "init")==0 ||
+                           strcmp(m->id, "class_init")==0)) {
                                print_error(FALSE,"init, or class_init not "
                                            "allowed as an "
                                            "identifier of non-"
-                                           "constructor methods",m->line_no);
+                                           "constructor methods", m->line_no);
                        }
                } else if(n->type == VARIABLE_NODE) {
                        Variable *v = (Variable *)n;
-                       if(strcmp(v->id,"_priv")==0 ||
-                          strcmp(v->id,"__parent__")==0) {
+                       if(strcmp(v->id, "_priv")==0 ||
+                          strcmp(v->id, "__parent__")==0) {
                                char *s;
                                s = g_strdup_printf("'%s' not allowed as a "
-                                                   "data member name",v->id);
-                               print_error(FALSE,s,v->line_no);
+                                                   "data member name", v->id);
+                               print_error(FALSE, s, v->line_no);
                                g_free(s);
                        }
                }
        }
 }
 
-
-void
-check_duplicate_named(Class *c,Node *node,char *id, int 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)) {
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
                Node *n = l->data;
                char *nid;
                int nline_no;
@@ -160,7 +226,7 @@ void
 check_duplicate_signals_args(Class *c)
 {
        GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
                Node *n = l->data;
                if(n->type == METHOD_NODE) {
                        Method *m = (Method *)n;
@@ -178,7 +244,7 @@ void
 check_public_new(Class *c)
 {
        GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
                Node *n = l->data;
                if(n->type == METHOD_NODE) {
                        Method *m = (Method *)n;
@@ -197,7 +263,7 @@ void
 check_vararg(Class *c)
 {
        GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
                Node *n = l->data;
                if(n->type == METHOD_NODE) {
                        Method *m = (Method *)n;
@@ -221,7 +287,7 @@ void
 check_firstarg(Class *c)
 {
        GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
                Node *n = l->data;
                if(n->type == METHOD_NODE) {
                        Method *m = (Method *)n;
@@ -244,14 +310,14 @@ void
 check_nonvoidempty(Class *c)
 {
        GList *li;
-       for(li=c->nodes; li; li=g_list_next(li)) {
+       for(li = c->nodes; li != NULL; li = g_list_next(li)) {
                Node *n = li->data;
                if(n->type == METHOD_NODE) {
                        Method *m = (Method *)n;
                        if(m->method != REGULAR_METHOD)
                                continue;
                        if(!(strcmp(m->mtype->name, "void")==0 &&
-                            m->mtype->stars == 0) &&
+                            m->mtype->pointer == NULL) &&
                           !m->cbuf) {
                                print_error(TRUE,
                                            "non-void empty method found, "
@@ -273,7 +339,7 @@ void
 check_signal_args(Class *c)
 {
        GList *li;
-       for(li=c->nodes; li; li=g_list_next(li)) {
+       for(li = c->nodes; li != NULL; li = g_list_next(li)) {
                Node *n = li->data;
                if(n->type == METHOD_NODE) {
                        Method *m = (Method *)n;
@@ -300,7 +366,7 @@ void
 check_argument_types(Class *c)
 {
        GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
                Node *n = l->data;
                if(n->type == ARGUMENT_NODE) {
                        Argument *a = (Argument *)n;
@@ -319,12 +385,95 @@ check_argument_types(Class *c)
        }
 }
 
+static void
+check_func_arg_check_func_arg(Method *m, FuncArg *fa)
+{
+       GList *li;
+       char *s;
+
+       if( ! fa->checks)
+               return;
+
+       if(strcmp(fa->atype->name, "void") == 0 &&
+          fa->atype->pointer == NULL) {
+               print_error(FALSE, "Running checks on a void function "
+                           "argument", m->line_no);
+               return;
+       }
+       
+       for(li = fa->checks; li; li = g_list_next(li)) {
+               Check *ch = li->data;
+               if(ch->chtype == TYPE_CHECK) {
+                       char *p;
+                       gboolean got_type = FALSE;
+                       s = g_strdup(fa->atype->name);
+                       p = strtok(s, " ");
+                       if( ! p) {
+                               g_free(s);
+                               goto type_check_error;
+                       }
+                       while(p) {
+                               if(strcmp(p, "const") != 0) {
+                                       if(got_type) {
+                                               g_free(s);
+                                               goto type_check_error;
+                                       }
+                                       got_type = TRUE;
+                               }
+                               p = strtok(NULL, " ");
+                       }
+                       g_free(s);
+                       if( ! got_type)
+                               goto type_check_error;
+
+                       if(fa->atype->pointer == NULL ||
+                          (strcmp(fa->atype->pointer, "*") != 0 &&
+                           strcmp(fa->atype->pointer, "* const") != 0))
+                               goto type_check_error;
+               }
+       }
+       return;
+
+type_check_error:
+       if(fa->atype->pointer)
+               s = g_strdup_printf("Cannot check the type of '%s %s'",
+                                   fa->atype->name, fa->atype->pointer);
+       else
+               s = g_strdup_printf("Cannot check the type of '%s'",
+                                   fa->atype->name);
+       print_error(FALSE, s, m->line_no);
+       g_free(s);
+}
+
+static void
+check_func_arg_check_method(Method *m)
+{
+       GList *li;
+       for(li = m->args; li; li = g_list_next(li)) {
+               FuncArg *fa = li->data;
+               check_func_arg_check_func_arg(m, fa);
+       }
+}
+
+void
+check_func_arg_checks(Class *c)
+{
+       GList *li;
+       for(li = c->nodes; li != NULL; li = g_list_next(li)) {
+               Node *n = li->data;
+               if(n->type == METHOD_NODE) {
+                       Method *m = (Method *)n;
+                       check_func_arg_check_method(m);
+               }
+       }
+}
+
 int
 count_signals(Class *c)
 {
        int num = 0;
        GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
                Node *n = l->data;
                if(n->type == METHOD_NODE) {
                        Method *m = (Method *)n;
@@ -341,8 +490,7 @@ count_arguments(Class *c)
 {
        int num = 0;
        GList *li;
-
-       for(li=c->nodes;li;li=g_list_next(li)) {
+       for(li = c->nodes; li != NULL; li = g_list_next(li)) {
                Node *n = li->data;
                if(n->type == ARGUMENT_NODE)
                        num ++;
@@ -355,7 +503,7 @@ count_overrides(Class *c)
 {
        int num = 0;
        GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
                Node *n = l->data;
                if(n->type == METHOD_NODE) {
                        Method *m = (Method *)n;
@@ -371,7 +519,7 @@ count_privates(Class *c)
 {
        int num = 0;
        GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
                Node *n = l->data;
                if(n->type == VARIABLE_NODE) {
                        Variable *v = (Variable *)n;
@@ -387,7 +535,7 @@ count_protecteds(Class *c)
 {
        int num = 0;
        GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
                Node *n = l->data;
                if(n->type == METHOD_NODE) {
                        Method *m = (Method *)n;
@@ -403,7 +551,7 @@ count_destructors(Class *c)
 {
        int num = 0;
        GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
                Node *n = l->data;
                if(n->type == VARIABLE_NODE) {
                        Variable *v = (Variable *)n;
@@ -419,7 +567,7 @@ count_initializers(Class *c)
 {
        int num = 0;
        GList *l;
-       for(l=c->nodes;l;l=g_list_next(l)) {
+       for(l = c->nodes; l != NULL; l = g_list_next(l)) {
                Node *n = l->data;
                if(n->type == VARIABLE_NODE) {
                        Variable *v = (Variable *)n;