/* GOB C Preprocessor
* Copyright (C) 1999-2000 the Free Software Foundation.
+ * Copyright (C) 2000 Eazel, Inc.
*
* Author: George Lebl
*
#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;
- char *s;
+ gboolean here_underscore = FALSE;
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)
+ error_printf(GOB_ERROR, nline_no,
+ "symbol '%s' ('_%s') redefined, "
+ "first defined on line %d. "
+ "Note that '%s' and '_%s' are "
+ "eqivalent.",
+ id, id, line_no, id, id);
+ else
+ error_printf(GOB_ERROR, nline_no,
+ "symbol '%s' redefined, "
+ "first defined on line %d",
+ id, line_no);
}
}
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;
+ if(n->type != METHOD_NODE ||
+ m->method != OVERRIDE_METHOD)
+ continue;
+
+ if(method == m ||
+ method->line_no > m->line_no ||
+ strcmp(get_real_id(m->id), get_real_id(method->id)) != 0 ||
+ strcmp(m->otype, method->otype) != 0)
+ continue;
+ error_printf(GOB_ERROR, m->line_no,
+ "override '%s(%s)' redefined, "
+ "first defined on line %d",
+ get_real_id(m->id), m->otype, method->line_no);
+ }
+}
+
+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) {
- 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);
+ (strcmp(m->id, "__parent__")==0 ||
+ strcmp(m->id, "___parent__")==0)) {
+ error_printf(GOB_ERROR, m->line_no,
+ "'%s' not allowed as an "
+ "identifier of signal "
+ "or virtual methods",
+ m->id);
}
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 "
+ (strcmp(get_real_id(m->id), "init")==0 ||
+ strcmp(get_real_id(m->id), "class_init")==0)) {
+ error_print(GOB_ERROR, m->line_no,
+ "init, or class_init not "
"allowed as an "
"identifier of non-"
- "constructor methods",m->line_no);
+ "constructor methods");
}
} 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);
+ if(strcmp(v->id, "_priv")==0 ||
+ strcmp(v->id, "__parent__")==0) {
+ error_printf(GOB_ERROR, v->line_no,
+ "'%s' not allowed as a "
+ "data member name", v->id);
}
}
}
}
-
-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;
- 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;
+ nid = get_real_id(m->id);
nline_no = m->line_no;
} else
continue;
nline_no = a->line_no;
} else
continue;
- if(n==node ||
- line_no>=nline_no ||
- g_strcasecmp(nid,id)!=0)
+ if(n == node ||
+ line_no >= nline_no ||
+ g_strcasecmp(nid, id)!=0)
continue;
- s = g_strdup_printf("named symbol (argument or signal) '%s' "
- "redefined, first defined on line %d "
- "(case insensitive)",
- id,line_no);
- print_error(FALSE,s,nline_no);
+ error_printf(GOB_ERROR, nline_no,
+ "named symbol (argument or signal) '%s' "
+ "redefined, first defined on line %d "
+ "(case insensitive)",
+ id, line_no);
}
}
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;
if(m->method == SIGNAL_LAST_METHOD ||
m->method == SIGNAL_FIRST_METHOD)
- check_duplicate_named(c,n,m->id,m->line_no);
+ check_duplicate_named(c, n, get_real_id(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);
+ check_duplicate_named(c, n, a->name, a->line_no);
}
}
}
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;
- if((strcmp(m->id,"new")==0) &&
+ if((strcmp(get_real_id(m->id), "new")==0) &&
(m->method != REGULAR_METHOD ||
m->scope != PUBLIC_SCOPE))
- print_error(TRUE,
+ error_print(GOB_WARN, m->line_no,
"'new' should be a regular\n"
- "public method",
- m->line_no);
+ "public method");
}
}
}
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;
- if(!m->vararg)
+ 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,
+ error_print(GOB_ERROR, m->line_no,
"signals, overrides and virtuals, "
"can't have variable argument "
- "lists",
- m->line_no);
+ "lists");
}
}
}
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;
m->method == SIGNAL_LAST_METHOD ||
m->method == SIGNAL_FIRST_METHOD ||
m->method == VIRTUAL_METHOD) {
- print_error(FALSE,
+ error_print(GOB_ERROR, m->line_no,
"signals, overrides and virtuals, "
- "can't have no arguments",
- m->line_no);
+ "can't have no arguments");
}
}
}
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,
+ error_print(GOB_WARN, m->line_no,
"non-void empty method found, "
"regular non-void function should "
- "not be empty.",
- m->line_no);
+ "not be empty.");
/* 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
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;
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);
+ error_printf(GOB_ERROR, m->line_no,
+ "Unknown GTK+ type '%s' "
+ "among signal types",
+ (char *)l->data);
}
}
}
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;
- 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);
+ error_printf(GOB_ERROR, a->line_no,
+ "Unknown GTK+ type '%s' "
+ "as argument type",
+ a->gtktype);
+ }
+ }
+}
+
+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) {
+ error_print(GOB_ERROR, m->line_no,
+ "Running checks on a void function argument");
+ 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 &&
+ strcmp(fa->atype->pointer, "const *") != 0))
+ goto type_check_error;
+ }
+ }
+ return;
+
+type_check_error:
+ if(fa->atype->pointer)
+ error_printf(GOB_ERROR, m->line_no,
+ "Cannot check the type of '%s %s'",
+ fa->atype->name, fa->atype->pointer);
+ else
+ error_printf(GOB_ERROR, m->line_no,
+ "Cannot check the type of '%s'",
+ fa->atype->name);
+}
+
+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 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;
}
int
-count_arguments(Class *c)
+count_set_arguments(Class *c)
{
int num = 0;
GList *li;
+ for(li = c->nodes; li != NULL; li = g_list_next(li)) {
+ Node *n = li->data;
+ Argument *a = li->data;
+ if(n->type == ARGUMENT_NODE &&
+ a->set)
+ num ++;
+ }
+ return num;
+}
- for(li=c->nodes;li;li=g_list_next(li)) {
+int
+count_get_arguments(Class *c)
+{
+ int num = 0;
+ GList *li;
+ for(li = c->nodes; li != NULL; li = g_list_next(li)) {
Node *n = li->data;
- if(n->type == ARGUMENT_NODE)
+ Argument *a = li->data;
+ if(n->type == ARGUMENT_NODE &&
+ a->get)
num ++;
}
return num;
{
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;
{
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;
{
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;
{
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;
{
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;