]> git.draconx.ca Git - gob-dx.git/blobdiff - src/checks.c
Release 0.92.2
[gob-dx.git] / src / checks.c
diff --git a/src/checks.c b/src/checks.c
new file mode 100644 (file)
index 0000000..73b10d8
--- /dev/null
@@ -0,0 +1,398 @@
+/* GOB C Preprocessor
+ * Copyright (C) 1999-2000 the Free Software Foundation.
+ *
+ * Author: George Lebl
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the  Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include "config.h"
+#include <string.h>
+#include <stdio.h>
+#include <glib.h>
+
+#include "tree.h"
+#include "main.h"
+#include "util.h"
+
+#include "checks.h"
+
+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 ||
+                  n->type != node->type)
+                       continue;
+               s = g_strdup_printf("symbol '%s' redefined, "
+                                   "first defined on line %d",
+                                   id,line_no);
+               print_error(FALSE,s,nline_no);
+       }
+}
+
+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);
+               }
+       }
+}
+
+void
+check_bad_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;
+                       if((m->method == SIGNAL_LAST_METHOD ||
+                           m->method == SIGNAL_FIRST_METHOD ||
+                           m->method == VIRTUAL_METHOD) &&
+                          strcmp(m->id,"__parent__")==0) {
+                               char *s;
+                               s = g_strdup_printf("'%s' not allowed as an "
+                                                   "identifier of signal "
+                                                   "or virtual methods",
+                                                   m->id);
+                               print_error(FALSE,s,m->line_no);
+                               g_free(s);
+                       }
+                       if(m->method != INIT_METHOD &&
+                          m->method != CLASS_INIT_METHOD &&
+                          (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);
+                       }
+               } else if(n->type == VARIABLE_NODE) {
+                       Variable *v = (Variable *)n;
+                       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);
+                               g_free(s);
+                       }
+               }
+       }
+}
+
+
+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->method == SIGNAL_LAST_METHOD ||
+                          m->method == 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);
+       }
+}
+
+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->method == SIGNAL_LAST_METHOD ||
+                          m->method == 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);
+               }
+       }
+}
+
+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((strcmp(m->id,"new")==0) &&
+                          (m->method != REGULAR_METHOD ||
+                           m->scope != PUBLIC_SCOPE))
+                               print_error(TRUE,
+                                           "'new' should be a regular\n"
+                                           "public method",
+                                           m->line_no);
+               }
+       }
+}
+
+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->method == OVERRIDE_METHOD ||
+                          m->method == SIGNAL_LAST_METHOD ||
+                          m->method == SIGNAL_FIRST_METHOD ||
+                          m->method == VIRTUAL_METHOD) {
+                               print_error(FALSE,
+                                           "signals, overrides and virtuals, "
+                                           "can't have variable argument "
+                                           "lists",
+                                           m->line_no);
+                       }
+               }
+       }
+}
+
+void
+check_firstarg(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->args)
+                               continue;
+                       if(m->method == OVERRIDE_METHOD ||
+                          m->method == SIGNAL_LAST_METHOD ||
+                          m->method == SIGNAL_FIRST_METHOD ||
+                          m->method == VIRTUAL_METHOD) {
+                               print_error(FALSE,
+                                           "signals, overrides and virtuals, "
+                                           "can't have no arguments",
+                                           m->line_no);
+                       }
+               }
+       }
+}
+
+void
+check_nonvoidempty(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->method != REGULAR_METHOD)
+                               continue;
+                       if(!(strcmp(m->mtype->name,"void")==0 &&
+                            m->mtype->stars == 0) &&
+                          !m->cbuf) {
+                               print_error(TRUE,
+                                           "non-void empty method found, "
+                                           "regular non-void function should "
+                                           "not be empty.",
+                                           m->line_no);
+                               /* add a body here, so that the user will also
+                                  get a warning from gcc, and so that it will
+                                  at least point him to the prototype of the
+                                  function in the .gob file */
+                               m->cbuf = g_strdup("/*empty*/");
+                               m->ccode_line = m->line_no;
+                       }
+               }
+       }
+}
+
+void
+check_signal_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;
+                       GList *l;
+                       if(m->method != SIGNAL_LAST_METHOD &&
+                          m->method != SIGNAL_FIRST_METHOD)
+                               continue;
+
+                       for(l=m->gtktypes;l;l=l->next) {
+                               char *s;
+                               if(get_cast(l->data,FALSE))
+                                       continue;
+                               s = g_strdup_printf("Unknown GTK+ type '%s' "
+                                                   "among signal types",
+                                                   (char *)l->data);
+                               print_error(FALSE, s, m->line_no);
+                               g_free(s);
+                       }
+               }
+       }
+}
+
+void
+check_argument_types(Class *c)
+{
+       GList *l;
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               if(n->type == ARGUMENT_NODE) {
+                       Argument *a = (Argument *)n;
+                       char *s;
+                       if(get_cast(a->gtktype,FALSE))
+                               continue;
+                       s = g_strdup_printf("Unknown GTK+ type '%s' "
+                                           "as argument type",
+                                           a->gtktype);
+                       /* this could perhaps be a warning, but
+                          can there really be a type beyond the
+                          fundementals? */
+                       print_error(FALSE, s, a->line_no);
+                       g_free(s);
+               }
+       }
+}
+
+int
+count_signals(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->method == SIGNAL_LAST_METHOD ||
+                          m->method == SIGNAL_FIRST_METHOD)
+                               num++;
+               }
+       }
+       return num;
+}
+
+int
+count_arguments(Class *c)
+{
+       int num = 0;
+       GList *li;
+
+       for(li=c->nodes;li;li=g_list_next(li)) {
+               Node *n = li->data;
+               if(n->type == ARGUMENT_NODE)
+                       num ++;
+       }
+       return num;
+}
+
+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->method == OVERRIDE_METHOD)
+                               num++;
+               }
+       }
+       return num;
+}
+
+int
+count_privates(Class *c)
+{
+       int num = 0;
+       GList *l;
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               if(n->type == VARIABLE_NODE) {
+                       Variable *v = (Variable *)n;
+                       if(v->scope == PRIVATE_SCOPE)
+                               num++;
+               }
+       }
+       return num;
+}
+
+int
+count_protecteds(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 == PROTECTED_SCOPE)
+                               num++;
+               }
+       }
+       return num;
+}