2 * Copyright (C) 1999-2000 the Free Software Foundation.
3 * Copyright (C) 2000 Eazel, Inc.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
28 #include "treefuncs.h"
35 check_duplicate(Class *c, Node *node, char *id, int line_no,
39 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
43 gboolean here_underscore = FALSE;
45 if(n->type == METHOD_NODE) {
46 Method *m = (Method *)n;
48 /* override methods are checked separately */
49 if(m->method == OVERRIDE_METHOD)
52 nid = get_real_id(m->id);
53 nline_no = m->line_no;
55 if(m->id[0] == '_' && m->id[1] != '\0')
56 here_underscore = TRUE;
57 } else if(n->type == VARIABLE_NODE) {
58 Variable *v = (Variable *)n;
60 nline_no = v->line_no;
65 n->type != node->type ||
68 /* this can only happen if the things were methods and
69 * one had an underscore and the other one didn't */
70 if(!no_kill_underscores && underscore != here_underscore)
71 s = g_strdup_printf("symbol '%s' ('_%s') redefined, "
72 "first defined on line %d. "
73 "Note that '%s' and '_%s' are "
75 id, id, line_no, id, id);
77 s = g_strdup_printf("symbol '%s' redefined, "
78 "first defined on line %d",
80 print_error(FALSE, s, nline_no);
86 check_duplicate_symbols(Class *c)
89 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
91 if(n->type == METHOD_NODE) {
92 Method *m = (Method *)n;
93 gboolean underscore = FALSE;
94 /* override methods are checked separately */
95 if(m->method == OVERRIDE_METHOD)
97 if(m->id[0] == '_' && m->id[1] != '\0')
99 check_duplicate(c, n, get_real_id(m->id), m->line_no,
101 } else if(n->type == VARIABLE_NODE) {
102 Variable *v = (Variable *)n;
103 check_duplicate(c, n, v->id, v->line_no, FALSE);
109 check_duplicate_override(Class *c, Method *method)
112 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
114 Method *m = (Method *)n;
116 if(n->type != METHOD_NODE ||
117 m->method != OVERRIDE_METHOD)
121 method->line_no > m->line_no ||
122 strcmp(m->id, method->id) != 0 ||
123 strcmp(m->otype, method->otype) != 0)
125 s = g_strdup_printf("override '%s(%s)' redefined, "
126 "first defined on line %d",
127 m->id, m->otype, method->line_no);
128 print_error(FALSE, s, m->line_no);
134 check_duplicate_overrides(Class *c)
137 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
139 Method *m = (Method *)n;
140 if(n->type != METHOD_NODE ||
141 m->method != OVERRIDE_METHOD)
143 check_duplicate_override(c, m);
148 check_bad_symbols(Class *c)
151 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
153 if(n->type == METHOD_NODE) {
154 Method *m = (Method *)n;
155 if((m->method == SIGNAL_LAST_METHOD ||
156 m->method == SIGNAL_FIRST_METHOD ||
157 m->method == VIRTUAL_METHOD) &&
158 strcmp(m->id, "__parent__")==0) {
160 s = g_strdup_printf("'%s' not allowed as an "
161 "identifier of signal "
162 "or virtual methods",
164 print_error(FALSE,s,m->line_no);
167 if(m->method != INIT_METHOD &&
168 m->method != CLASS_INIT_METHOD &&
169 (strcmp(m->id, "init")==0 ||
170 strcmp(m->id, "class_init")==0)) {
171 print_error(FALSE,"init, or class_init not "
174 "constructor methods", m->line_no);
176 } else if(n->type == VARIABLE_NODE) {
177 Variable *v = (Variable *)n;
178 if(strcmp(v->id, "_priv")==0 ||
179 strcmp(v->id, "__parent__")==0) {
181 s = g_strdup_printf("'%s' not allowed as a "
182 "data member name", v->id);
183 print_error(FALSE, s, v->line_no);
191 check_duplicate_named(Class *c, Node *node, char *id, int line_no)
194 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
199 if(n->type == METHOD_NODE) {
200 Method *m = (Method *)n;
201 if(m->method == SIGNAL_LAST_METHOD ||
202 m->method == SIGNAL_FIRST_METHOD) {
204 nline_no = m->line_no;
207 } else if(n->type == ARGUMENT_NODE) {
208 Argument *a = (Argument *)n;
210 nline_no = a->line_no;
215 g_strcasecmp(nid,id)!=0)
217 s = g_strdup_printf("named symbol (argument or signal) '%s' "
218 "redefined, first defined on line %d "
219 "(case insensitive)",
221 print_error(FALSE,s,nline_no);
226 check_duplicate_signals_args(Class *c)
229 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
231 if(n->type == METHOD_NODE) {
232 Method *m = (Method *)n;
233 if(m->method == SIGNAL_LAST_METHOD ||
234 m->method == SIGNAL_FIRST_METHOD)
235 check_duplicate_named(c,n,m->id,m->line_no);
236 } else if(n->type == ARGUMENT_NODE) {
237 Argument *a = (Argument *)n;
238 check_duplicate_named(c,n,a->name,a->line_no);
244 check_public_new(Class *c)
247 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
249 if(n->type == METHOD_NODE) {
250 Method *m = (Method *)n;
251 if((strcmp(m->id,"new")==0) &&
252 (m->method != REGULAR_METHOD ||
253 m->scope != PUBLIC_SCOPE))
255 "'new' should be a regular\n"
263 check_vararg(Class *c)
266 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
268 if(n->type == METHOD_NODE) {
269 Method *m = (Method *)n;
272 if(m->method == OVERRIDE_METHOD ||
273 m->method == SIGNAL_LAST_METHOD ||
274 m->method == SIGNAL_FIRST_METHOD ||
275 m->method == VIRTUAL_METHOD) {
277 "signals, overrides and virtuals, "
278 "can't have variable argument "
287 check_firstarg(Class *c)
290 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
292 if(n->type == METHOD_NODE) {
293 Method *m = (Method *)n;
296 if(m->method == OVERRIDE_METHOD ||
297 m->method == SIGNAL_LAST_METHOD ||
298 m->method == SIGNAL_FIRST_METHOD ||
299 m->method == VIRTUAL_METHOD) {
301 "signals, overrides and virtuals, "
302 "can't have no arguments",
310 check_nonvoidempty(Class *c)
313 for(li = c->nodes; li != NULL; li = g_list_next(li)) {
315 if(n->type == METHOD_NODE) {
316 Method *m = (Method *)n;
317 if(m->method != REGULAR_METHOD)
319 if(!(strcmp(m->mtype->name, "void")==0 &&
320 m->mtype->pointer == NULL) &&
323 "non-void empty method found, "
324 "regular non-void function should "
327 /* add a body here, so that the user will also
328 get a warning from gcc, and so that it will
329 at least point him to the prototype of the
330 function in the .gob file */
331 m->cbuf = g_strdup("/*empty*/");
332 m->ccode_line = m->line_no;
339 check_signal_args(Class *c)
342 for(li = c->nodes; li != NULL; li = g_list_next(li)) {
344 if(n->type == METHOD_NODE) {
345 Method *m = (Method *)n;
347 if(m->method != SIGNAL_LAST_METHOD &&
348 m->method != SIGNAL_FIRST_METHOD)
351 for(l=m->gtktypes;l;l=l->next) {
353 if(get_cast(l->data, FALSE))
355 s = g_strdup_printf("Unknown GTK+ type '%s' "
356 "among signal types",
358 print_error(FALSE, s, m->line_no);
366 check_argument_types(Class *c)
369 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
371 if(n->type == ARGUMENT_NODE) {
372 Argument *a = (Argument *)n;
374 if(get_cast(a->gtktype, FALSE))
376 s = g_strdup_printf("Unknown GTK+ type '%s' "
379 /* this could perhaps be a warning, but
380 can there really be a type beyond the
382 print_error(FALSE, s, a->line_no);
389 check_func_arg_check_func_arg(Method *m, FuncArg *fa)
397 if(strcmp(fa->atype->name, "void") == 0 &&
398 fa->atype->pointer == NULL) {
399 print_error(FALSE, "Running checks on a void function "
400 "argument", m->line_no);
404 for(li = fa->checks; li; li = g_list_next(li)) {
405 Check *ch = li->data;
406 if(ch->chtype == TYPE_CHECK) {
408 gboolean got_type = FALSE;
409 s = g_strdup(fa->atype->name);
413 goto type_check_error;
416 if(strcmp(p, "const") != 0) {
419 goto type_check_error;
423 p = strtok(NULL, " ");
427 goto type_check_error;
429 if(fa->atype->pointer == NULL ||
430 (strcmp(fa->atype->pointer, "*") != 0 &&
431 strcmp(fa->atype->pointer, "* const") != 0))
432 goto type_check_error;
438 if(fa->atype->pointer)
439 s = g_strdup_printf("Cannot check the type of '%s %s'",
440 fa->atype->name, fa->atype->pointer);
442 s = g_strdup_printf("Cannot check the type of '%s'",
444 print_error(FALSE, s, m->line_no);
449 check_func_arg_check_method(Method *m)
452 for(li = m->args; li; li = g_list_next(li)) {
453 FuncArg *fa = li->data;
454 check_func_arg_check_func_arg(m, fa);
459 check_func_arg_checks(Class *c)
462 for(li = c->nodes; li != NULL; li = g_list_next(li)) {
464 if(n->type == METHOD_NODE) {
465 Method *m = (Method *)n;
466 check_func_arg_check_method(m);
472 count_signals(Class *c)
476 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
478 if(n->type == METHOD_NODE) {
479 Method *m = (Method *)n;
480 if(m->method == SIGNAL_LAST_METHOD ||
481 m->method == SIGNAL_FIRST_METHOD)
489 count_arguments(Class *c)
493 for(li = c->nodes; li != NULL; li = g_list_next(li)) {
495 if(n->type == ARGUMENT_NODE)
502 count_overrides(Class *c)
506 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
508 if(n->type == METHOD_NODE) {
509 Method *m = (Method *)n;
510 if(m->method == OVERRIDE_METHOD)
518 count_privates(Class *c)
522 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
524 if(n->type == VARIABLE_NODE) {
525 Variable *v = (Variable *)n;
526 if(v->scope == PRIVATE_SCOPE)
534 count_protecteds(Class *c)
538 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
540 if(n->type == METHOD_NODE) {
541 Method *m = (Method *)n;
542 if(m->scope == PROTECTED_SCOPE)
550 count_destructors(Class *c)
554 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
556 if(n->type == VARIABLE_NODE) {
557 Variable *v = (Variable *)n;
566 count_initializers(Class *c)
570 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
572 if(n->type == VARIABLE_NODE) {
573 Variable *v = (Variable *)n;