X-Git-Url: http://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/5b42e9400440d86723a27747b2191ab8cd59c2ee..4d534c82fb65897999ade6867534ab952a9bc019:/src/checks.c diff --git a/src/checks.c b/src/checks.c index f2bb058..cccdedb 100644 --- a/src/checks.c +++ b/src/checks.c @@ -1,5 +1,7 @@ /* GOB C Preprocessor * Copyright (C) 1999-2000 the Free Software Foundation. + * Copyright (C) 2000 Eazel, Inc. + * Copyright (C) 2001-2004 George Lebl * * Author: George Lebl * @@ -24,23 +26,27 @@ #include #include -#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, const char *id, int line_no) { - GList *l; - for(l=c->nodes;l;l=g_list_next(l)) { - Node *n = l->data; - char *nid; + GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; + const char *nid; int nline_no; - char *s; if(n->type == METHOD_NODE) { Method *m = (Method *)n; + + /* override methods are checked separately */ + if(m->method == OVERRIDE_METHOD) + continue; + nid = m->id; nline_no = m->line_no; } else if(n->type == VARIABLE_NODE) { @@ -49,127 +55,176 @@ check_duplicate(Class *c, Node *node, char *id, int line_no) 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); + + error_printf (GOB_ERROR, nline_no, + "symbol '%s' redefined, " + "first defined on line %d", + id, line_no); } } void -check_duplicate_symbols(Class *c) +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) { + GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->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) { + /* override methods are checked separately */ + if (m->method != OVERRIDE_METHOD) { + 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); + check_duplicate (c, n, v->id, v->line_no); } } } +static void +check_duplicate_override (Class *c, Method *method) +{ + GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->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(m->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", + m->id, m->otype, method->line_no); + } +} + +void +check_duplicate_overrides(Class *c) +{ + GList *li; + for(li = c->nodes; li != NULL; li = li->next) { + Node *n = li->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)) { - Node *n = l->data; + GList *li; + for(li = c->nodes; li != NULL; li = li->next) { + Node *n = li->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, "_epv")==0 || + 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(m->id, "init")==0 || + strcmp(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, const char *id, int line_no) { - GList *l; - for(l=c->nodes;l;l=g_list_next(l)) { - Node *n = l->data; - char *nid; + GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; + const char *nid; int nline_no; - char *s; - if(n->type == METHOD_NODE) { + if (n->type == METHOD_NODE) { Method *m = (Method *)n; - if(m->method == SIGNAL_LAST_METHOD || - m->method == SIGNAL_FIRST_METHOD) { + if (m->method == SIGNAL_LAST_METHOD || + m->method == SIGNAL_FIRST_METHOD) { nid = m->id; nline_no = m->line_no; - } else + } else { continue; - } else if(n->type == ARGUMENT_NODE) { + } + } else if (n->type == ARGUMENT_NODE) { Argument *a = (Argument *)n; nid = a->name; nline_no = a->line_no; - } else + } else if (n->type == PROPERTY_NODE) { + Property *p = (Property *)n; + nid = p->name; + nline_no = p->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); } } void -check_duplicate_signals_args(Class *c) +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) { + GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->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) { + check_duplicate_named (c, n, m->id, + m->line_no); + } else if (n->type == PROPERTY_NODE) { + Property *p = (Property *)n; + check_duplicate_named (c, n, p->name, p->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); } } } @@ -177,18 +232,17 @@ check_duplicate_signals_args(Class *c) void check_public_new(Class *c) { - GList *l; - for(l=c->nodes;l;l=g_list_next(l)) { - Node *n = l->data; + GList *li; + for(li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; - if((strcmp(m->id,"new")==0) && + if((strcmp(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"); } } } @@ -196,22 +250,21 @@ check_public_new(Class *c) void check_vararg(Class *c) { - GList *l; - for(l=c->nodes;l;l=g_list_next(l)) { - Node *n = l->data; + GList *li; + for(li = c->nodes; li != NULL; li = li->next) { + Node *n = li->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"); } } } @@ -220,9 +273,9 @@ check_vararg(Class *c) void check_firstarg(Class *c) { - GList *l; - for(l=c->nodes;l;l=g_list_next(l)) { - Node *n = l->data; + GList *li; + for(li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; if(m->args) @@ -231,10 +284,9 @@ check_firstarg(Class *c) 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"); } } } @@ -244,20 +296,19 @@ void check_nonvoidempty(Class *c) { GList *li; - for(li=c->nodes; li; li=g_list_next(li)) { + for(li = c->nodes; li != NULL; li = li->next) { 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 @@ -270,10 +321,10 @@ check_nonvoidempty(Class *c) } void -check_signal_args(Class *c) +check_signal_args (Class *c) { GList *li; - for(li=c->nodes; li; li=g_list_next(li)) { + for (li = c->nodes; li != NULL; li = li->next) { Node *n = li->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; @@ -282,39 +333,167 @@ check_signal_args(Class *c) m->method != SIGNAL_FIRST_METHOD) continue; - for(l=m->gtktypes;l;l=l->next) { - char *s; - if(get_cast(l->data, FALSE)) + for (l = m->gtktypes; l != NULL; l = l->next) { + if (strcmp (l->data, "BOXED") == 0) { + error_printf (GOB_ERROR, m->line_no, + "BOXED not allowed as " + "a signal argument, use " + "POINTER, or BOXED_*"); + continue; + } else if (strcmp (l->data, "FLAGS") == 0) { + error_printf (GOB_ERROR, m->line_no, + "FLAGS not allowed as " + "a signal argument, use " + "UINT"); 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); + } + if (get_cast (l->data, FALSE)) + continue; + error_printf (GOB_ERROR, m->line_no, + "Unknown GTK+ type '%s' " + "among signal types", + (char *)l->data); } } } } void -check_argument_types(Class *c) +check_argument_types (Class *c) { - GList *l; - for(l=c->nodes;l;l=g_list_next(l)) { - Node *n = l->data; + GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->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 GLib type '%s' " + "as argument type", + a->gtktype); + } + } +} + +void +check_property_types (Class *c) +{ + GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; + if (n->type == PROPERTY_NODE) { + Property *p = (Property *)n; + if (get_cast (p->gtktype, FALSE)) + continue; + error_printf (GOB_ERROR, p->line_no, + "Unknown GLib type '%s' " + "as property type", + p->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 = li->next) { + 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 = li->next) { + 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 = li->next) { + Node *n = li->data; + if(n->type == METHOD_NODE) { + Method *m = (Method *)n; + check_func_arg_check_method(m); + } + } +} + +void +check_for_class_destructors (Class *c) +{ + GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; + if (n->type == VARIABLE_NODE) { + Variable *v = (Variable *)n; + if (v->destructor != NULL && + v->scope == CLASS_SCOPE) { + error_print (GOB_WARN, v->line_no, + "classwide members cannot have " + "destructors since the classes " + "are static and never get " + "destroyed anyway"); + } } } } @@ -323,9 +502,9 @@ int count_signals(Class *c) { int num = 0; - GList *l; - for(l=c->nodes;l;l=g_list_next(l)) { - Node *n = l->data; + GList *li; + for(li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; if(m->method == SIGNAL_LAST_METHOD || @@ -337,14 +516,61 @@ count_signals(Class *c) } int -count_arguments(Class *c) +count_set_properties (Class *c) +{ + int num = 0; + GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; + Property *p = li->data; + if (n->type == PROPERTY_NODE && + p->set != NULL) + num ++; + } + return num; +} + +int +count_get_properties (Class *c) { int num = 0; GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; + Property *p = li->data; + if (n->type == PROPERTY_NODE && + p->get != NULL) + num ++; + } + return num; +} + - for(li=c->nodes;li;li=g_list_next(li)) { +int +count_set_arguments(Class *c) +{ + int num = 0; + GList *li; + for(li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; + Argument *a = li->data; + if(n->type == ARGUMENT_NODE && + a->set) + num ++; + } + return num; +} + +int +count_get_arguments(Class *c) +{ + int num = 0; + GList *li; + for(li = c->nodes; li != NULL; li = li->next) { Node *n = li->data; - if(n->type == ARGUMENT_NODE) + Argument *a = li->data; + if(n->type == ARGUMENT_NODE && + a->get) num ++; } return num; @@ -354,9 +580,9 @@ int count_overrides(Class *c) { int num = 0; - GList *l; - for(l=c->nodes;l;l=g_list_next(l)) { - Node *n = l->data; + GList *li; + for(li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; if(m->method == OVERRIDE_METHOD) @@ -370,9 +596,9 @@ int count_privates(Class *c) { int num = 0; - GList *l; - for(l=c->nodes;l;l=g_list_next(l)) { - Node *n = l->data; + GList *li; + for(li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; if(n->type == VARIABLE_NODE) { Variable *v = (Variable *)n; if(v->scope == PRIVATE_SCOPE) @@ -383,12 +609,12 @@ count_privates(Class *c) } int -count_protecteds(Class *c) +count_protecteds (Class *c) { int num = 0; - GList *l; - for(l=c->nodes;l;l=g_list_next(l)) { - Node *n = l->data; + GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; if(n->type == METHOD_NODE) { Method *m = (Method *)n; if(m->scope == PROTECTED_SCOPE) @@ -399,15 +625,17 @@ count_protecteds(Class *c) } int -count_destructors(Class *c) +count_unreftors (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) { + GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; + if (n->type == VARIABLE_NODE) { Variable *v = (Variable *)n; - if(v->destructor) + if (v->destructor != NULL && + v->destructor_unref && + v->scope != CLASS_SCOPE) num++; } } @@ -415,17 +643,75 @@ count_destructors(Class *c) } int -count_initializers(Class *c) +count_destructors (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) { + GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; + if (n->type == VARIABLE_NODE) { Variable *v = (Variable *)n; - if(v->initializer) + if (v->destructor != NULL && + ! v->destructor_unref && + v->scope != CLASS_SCOPE) num++; } } return num; } + +int +count_initializers (Class *c) +{ + int num = 0; + GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; + if (n->type == VARIABLE_NODE) { + Variable *v = (Variable *)n; + if (v->initializer != NULL) + num++; + } + } + return num; +} + +int +count_glade_widgets (Class *c) +{ + int num = 0; + GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; + if (n->type == VARIABLE_NODE) { + Variable *v = (Variable *)n; + if (v->glade_widget) + num++; + } + } + return num; +} + +gboolean +find_get_type (Class *c) +{ + GList *li; + for (li = c->nodes; li != NULL; li = li->next) { + Node *n = li->data; + Method *m = (Method *)n; + if (n->type == METHOD_NODE && + strcmp (m->id, "get_type") == 0) { + if (m->method != REGULAR_METHOD || + m->scope != PUBLIC_SCOPE || + m->args != NULL) { + error_printf (GOB_ERROR, m->line_no, + "get_type method must be a " + "regular public method with " + "no arguments"); + } + return TRUE; + } + } + + return FALSE; +}