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, const char *id, int line_no,
39 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
43 gboolean here_underscore = FALSE;
44 if(n->type == METHOD_NODE) {
45 Method *m = (Method *)n;
47 /* override methods are checked separately */
48 if(m->method == OVERRIDE_METHOD)
51 nid = get_real_id(m->id);
52 nline_no = m->line_no;
54 if(m->id[0] == '_' && m->id[1] != '\0')
55 here_underscore = TRUE;
56 } else if(n->type == VARIABLE_NODE) {
57 Variable *v = (Variable *)n;
59 nline_no = v->line_no;
64 n->type != node->type ||
67 /* this can only happen if the things were methods and
68 * one had an underscore and the other one didn't */
69 if( ! no_kill_underscores && underscore != here_underscore)
70 error_printf(GOB_ERROR, nline_no,
71 "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 error_printf(GOB_ERROR, nline_no,
78 "symbol '%s' redefined, "
79 "first defined on line %d",
85 check_duplicate_symbols(Class *c)
88 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
90 if(n->type == METHOD_NODE) {
91 Method *m = (Method *)n;
92 gboolean underscore = FALSE;
93 /* override methods are checked separately */
94 if(m->method == OVERRIDE_METHOD)
96 if(m->id[0] == '_' && m->id[1] != '\0')
98 check_duplicate(c, n, get_real_id(m->id), m->line_no,
100 } else if(n->type == VARIABLE_NODE) {
101 Variable *v = (Variable *)n;
102 check_duplicate(c, n, v->id, v->line_no, FALSE);
108 check_duplicate_override(Class *c, Method *method)
111 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
113 Method *m = (Method *)n;
114 if(n->type != METHOD_NODE ||
115 m->method != OVERRIDE_METHOD)
119 method->line_no > m->line_no ||
120 strcmp(get_real_id(m->id), get_real_id(method->id)) != 0 ||
121 strcmp(m->otype, method->otype) != 0)
123 error_printf(GOB_ERROR, m->line_no,
124 "override '%s(%s)' redefined, "
125 "first defined on line %d",
126 get_real_id(m->id), m->otype, method->line_no);
131 check_duplicate_overrides(Class *c)
134 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
136 Method *m = (Method *)n;
137 if(n->type != METHOD_NODE ||
138 m->method != OVERRIDE_METHOD)
140 check_duplicate_override(c, m);
145 check_bad_symbols(Class *c)
148 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
150 if(n->type == METHOD_NODE) {
151 Method *m = (Method *)n;
152 if((m->method == SIGNAL_LAST_METHOD ||
153 m->method == SIGNAL_FIRST_METHOD ||
154 m->method == VIRTUAL_METHOD) &&
155 (strcmp(m->id, "_epv")==0 ||
156 strcmp(m->id, "__parent__")==0 ||
157 strcmp(m->id, "___parent__")==0)) {
158 error_printf(GOB_ERROR, m->line_no,
159 "'%s' not allowed as an "
160 "identifier of signal "
161 "or virtual methods",
164 if(m->method != INIT_METHOD &&
165 m->method != CLASS_INIT_METHOD &&
166 (strcmp(get_real_id(m->id), "init")==0 ||
167 strcmp(get_real_id(m->id), "class_init")==0)) {
168 error_print(GOB_ERROR, m->line_no,
169 "init, or class_init not "
172 "constructor methods");
174 } else if(n->type == VARIABLE_NODE) {
175 Variable *v = (Variable *)n;
176 if(strcmp(v->id, "_priv")==0 ||
177 strcmp(v->id, "__parent__")==0) {
178 error_printf(GOB_ERROR, v->line_no,
179 "'%s' not allowed as a "
180 "data member name", v->id);
187 check_duplicate_named(Class *c, Node *node, const char *id, int line_no)
190 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
194 if(n->type == METHOD_NODE) {
195 Method *m = (Method *)n;
196 if(m->method == SIGNAL_LAST_METHOD ||
197 m->method == SIGNAL_FIRST_METHOD) {
198 nid = get_real_id(m->id);
199 nline_no = m->line_no;
202 } else if(n->type == ARGUMENT_NODE) {
203 Argument *a = (Argument *)n;
205 nline_no = a->line_no;
209 line_no >= nline_no ||
210 g_strcasecmp(nid, id)!=0)
212 error_printf(GOB_ERROR, nline_no,
213 "named symbol (argument or signal) '%s' "
214 "redefined, first defined on line %d "
215 "(case insensitive)",
221 check_duplicate_signals_args(Class *c)
224 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
226 if(n->type == METHOD_NODE) {
227 Method *m = (Method *)n;
228 if(m->method == SIGNAL_LAST_METHOD ||
229 m->method == SIGNAL_FIRST_METHOD)
230 check_duplicate_named(c, n, get_real_id(m->id),
232 } else if(n->type == ARGUMENT_NODE) {
233 Argument *a = (Argument *)n;
234 check_duplicate_named(c, n, a->name, a->line_no);
240 check_public_new(Class *c)
243 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
245 if(n->type == METHOD_NODE) {
246 Method *m = (Method *)n;
247 if((strcmp(get_real_id(m->id), "new")==0) &&
248 (m->method != REGULAR_METHOD ||
249 m->scope != PUBLIC_SCOPE))
250 error_print(GOB_WARN, m->line_no,
251 "'new' should be a regular\n"
258 check_vararg(Class *c)
261 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
263 if(n->type == METHOD_NODE) {
264 Method *m = (Method *)n;
267 if(m->method == OVERRIDE_METHOD ||
268 m->method == SIGNAL_LAST_METHOD ||
269 m->method == SIGNAL_FIRST_METHOD ||
270 m->method == VIRTUAL_METHOD) {
271 error_print(GOB_ERROR, m->line_no,
272 "signals, overrides and virtuals, "
273 "can't have variable argument "
281 check_firstarg(Class *c)
284 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
286 if(n->type == METHOD_NODE) {
287 Method *m = (Method *)n;
290 if(m->method == OVERRIDE_METHOD ||
291 m->method == SIGNAL_LAST_METHOD ||
292 m->method == SIGNAL_FIRST_METHOD ||
293 m->method == VIRTUAL_METHOD) {
294 error_print(GOB_ERROR, m->line_no,
295 "signals, overrides and virtuals, "
296 "can't have no arguments");
303 check_nonvoidempty(Class *c)
306 for(li = c->nodes; li != NULL; li = g_list_next(li)) {
308 if(n->type == METHOD_NODE) {
309 Method *m = (Method *)n;
310 if(m->method != REGULAR_METHOD)
312 if(!(strcmp(m->mtype->name, "void")==0 &&
313 m->mtype->pointer == NULL) &&
315 error_print(GOB_WARN, m->line_no,
316 "non-void empty method found, "
317 "regular non-void function should "
319 /* add a body here, so that the user will also
320 get a warning from gcc, and so that it will
321 at least point him to the prototype of the
322 function in the .gob file */
323 m->cbuf = g_strdup("/*empty*/");
324 m->ccode_line = m->line_no;
331 check_signal_args(Class *c)
334 for(li = c->nodes; li != NULL; li = g_list_next(li)) {
336 if(n->type == METHOD_NODE) {
337 Method *m = (Method *)n;
339 if(m->method != SIGNAL_LAST_METHOD &&
340 m->method != SIGNAL_FIRST_METHOD)
343 for(l=m->gtktypes;l;l=l->next) {
344 if(get_cast(l->data, FALSE))
346 error_printf(GOB_ERROR, m->line_no,
347 "Unknown GTK+ type '%s' "
348 "among signal types",
356 check_argument_types(Class *c)
359 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
361 if(n->type == ARGUMENT_NODE) {
362 Argument *a = (Argument *)n;
363 if(get_cast(a->gtktype, FALSE))
365 /* this could perhaps be a warning, but
366 can there really be a type beyond the
368 error_printf(GOB_ERROR, a->line_no,
369 "Unknown GTK+ type '%s' "
377 check_func_arg_check_func_arg(Method *m, FuncArg *fa)
385 if(strcmp(fa->atype->name, "void") == 0 &&
386 fa->atype->pointer == NULL) {
387 error_print(GOB_ERROR, m->line_no,
388 "Running checks on a void function argument");
392 for(li = fa->checks; li; li = g_list_next(li)) {
393 Check *ch = li->data;
394 if(ch->chtype == TYPE_CHECK) {
396 gboolean got_type = FALSE;
397 s = g_strdup(fa->atype->name);
401 goto type_check_error;
404 if(strcmp(p, "const") != 0) {
407 goto type_check_error;
411 p = strtok(NULL, " ");
415 goto type_check_error;
417 if(fa->atype->pointer == NULL ||
418 (strcmp(fa->atype->pointer, "*") != 0 &&
419 strcmp(fa->atype->pointer, "* const") != 0 &&
420 strcmp(fa->atype->pointer, "const *") != 0))
421 goto type_check_error;
427 if(fa->atype->pointer)
428 error_printf(GOB_ERROR, m->line_no,
429 "Cannot check the type of '%s %s'",
430 fa->atype->name, fa->atype->pointer);
432 error_printf(GOB_ERROR, m->line_no,
433 "Cannot check the type of '%s'",
438 check_func_arg_check_method(Method *m)
441 for(li = m->args; li; li = g_list_next(li)) {
442 FuncArg *fa = li->data;
443 check_func_arg_check_func_arg(m, fa);
448 check_func_arg_checks(Class *c)
451 for(li = c->nodes; li != NULL; li = g_list_next(li)) {
453 if(n->type == METHOD_NODE) {
454 Method *m = (Method *)n;
455 check_func_arg_check_method(m);
461 count_signals(Class *c)
465 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
467 if(n->type == METHOD_NODE) {
468 Method *m = (Method *)n;
469 if(m->method == SIGNAL_LAST_METHOD ||
470 m->method == SIGNAL_FIRST_METHOD)
478 count_set_arguments(Class *c)
482 for(li = c->nodes; li != NULL; li = g_list_next(li)) {
484 Argument *a = li->data;
485 if(n->type == ARGUMENT_NODE &&
493 count_get_arguments(Class *c)
497 for(li = c->nodes; li != NULL; li = g_list_next(li)) {
499 Argument *a = li->data;
500 if(n->type == ARGUMENT_NODE &&
508 count_overrides(Class *c)
512 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
514 if(n->type == METHOD_NODE) {
515 Method *m = (Method *)n;
516 if(m->method == OVERRIDE_METHOD)
524 count_privates(Class *c)
528 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
530 if(n->type == VARIABLE_NODE) {
531 Variable *v = (Variable *)n;
532 if(v->scope == PRIVATE_SCOPE)
540 count_protecteds(Class *c)
544 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
546 if(n->type == METHOD_NODE) {
547 Method *m = (Method *)n;
548 if(m->scope == PROTECTED_SCOPE)
556 count_destructors(Class *c)
560 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
562 if(n->type == VARIABLE_NODE) {
563 Variable *v = (Variable *)n;
572 count_initializers(Class *c)
576 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
578 if(n->type == VARIABLE_NODE) {
579 Variable *v = (Variable *)n;
588 find_get_type (Class *c)
591 for(l = c->nodes; l != NULL; l = g_list_next(l)) {
593 Method *m = (Method *)n;
594 if(n->type == METHOD_NODE &&
595 strcmp (m->id, "get_type") == 0) {
596 if (m->method != REGULAR_METHOD ||
597 m->scope != PUBLIC_SCOPE ||
599 error_printf (GOB_ERROR, m->line_no,
600 "get_type method must be a "
601 "regular public method with "