2 * Copyright (C) 1999-2000 the Free Software Foundation.
3 * Copyright (C) 2000 Eazel, Inc.
4 * Copyright (C) 2001 George Lebl
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
29 #include "treefuncs.h"
36 check_duplicate (Class *c, Node *node, const char *id, int line_no)
39 for (li = c->nodes; li != NULL; li = li->next) {
43 if(n->type == METHOD_NODE) {
44 Method *m = (Method *)n;
46 /* override methods are checked separately */
47 if(m->method == OVERRIDE_METHOD)
51 nline_no = m->line_no;
52 } else if(n->type == VARIABLE_NODE) {
53 Variable *v = (Variable *)n;
55 nline_no = v->line_no;
60 n->type != node->type ||
64 error_printf (GOB_ERROR, nline_no,
65 "symbol '%s' redefined, "
66 "first defined on line %d",
72 check_duplicate_symbols (Class *c)
75 for (li = c->nodes; li != NULL; li = li->next) {
78 if (n->type == METHOD_NODE) {
79 Method *m = (Method *)n;
80 /* override methods are checked separately */
81 if (m->method != OVERRIDE_METHOD) {
82 check_duplicate (c, n, m->id, m->line_no);
84 } else if (n->type == VARIABLE_NODE) {
85 Variable *v = (Variable *)n;
86 check_duplicate (c, n, v->id, v->line_no);
92 check_duplicate_override (Class *c, Method *method)
95 for (li = c->nodes; li != NULL; li = li->next) {
97 Method *m = (Method *)n;
98 if(n->type != METHOD_NODE ||
99 m->method != OVERRIDE_METHOD)
103 method->line_no > m->line_no ||
104 strcmp(m->id, method->id) != 0 ||
105 strcmp(m->otype, method->otype) != 0)
107 error_printf(GOB_ERROR, m->line_no,
108 "override '%s(%s)' redefined, "
109 "first defined on line %d",
110 m->id, m->otype, method->line_no);
115 check_duplicate_overrides(Class *c)
118 for(li = c->nodes; li != NULL; li = li->next) {
120 Method *m = (Method *)n;
121 if(n->type != METHOD_NODE ||
122 m->method != OVERRIDE_METHOD)
124 check_duplicate_override(c, m);
129 check_bad_symbols(Class *c)
132 for(li = c->nodes; li != NULL; li = li->next) {
134 if(n->type == METHOD_NODE) {
135 Method *m = (Method *)n;
136 if((m->method == SIGNAL_LAST_METHOD ||
137 m->method == SIGNAL_FIRST_METHOD ||
138 m->method == VIRTUAL_METHOD) &&
139 (strcmp(m->id, "_epv")==0 ||
140 strcmp(m->id, "__parent__")==0 ||
141 strcmp(m->id, "___parent__")==0)) {
142 error_printf(GOB_ERROR, m->line_no,
143 "'%s' not allowed as an "
144 "identifier of signal "
145 "or virtual methods",
148 if(m->method != INIT_METHOD &&
149 m->method != CLASS_INIT_METHOD &&
150 (strcmp(m->id, "init")==0 ||
151 strcmp(m->id, "class_init")==0)) {
152 error_print(GOB_ERROR, m->line_no,
153 "init, or class_init not "
156 "constructor methods");
158 } else if(n->type == VARIABLE_NODE) {
159 Variable *v = (Variable *)n;
160 if(strcmp(v->id, "_priv")==0 ||
161 strcmp(v->id, "__parent__")==0) {
162 error_printf(GOB_ERROR, v->line_no,
163 "'%s' not allowed as a "
164 "data member name", v->id);
171 check_duplicate_named (Class *c, Node *node, const char *id, int line_no)
174 for (li = c->nodes; li != NULL; li = li->next) {
178 if (n->type == METHOD_NODE) {
179 Method *m = (Method *)n;
180 if (m->method == SIGNAL_LAST_METHOD ||
181 m->method == SIGNAL_FIRST_METHOD) {
183 nline_no = m->line_no;
187 } else if (n->type == ARGUMENT_NODE) {
188 Argument *a = (Argument *)n;
190 nline_no = a->line_no;
191 } else if (n->type == PROPERTY_NODE) {
192 Property *p = (Property *)n;
194 nline_no = p->line_no;
199 line_no >= nline_no ||
200 g_strcasecmp (nid, id) != 0)
202 error_printf (GOB_ERROR, nline_no,
203 "named symbol (argument or signal) '%s' "
204 "redefined, first defined on line %d "
205 "(case insensitive)",
211 check_duplicate_signals_args (Class *c)
214 for (li = c->nodes; li != NULL; li = li->next) {
216 if (n->type == METHOD_NODE) {
217 Method *m = (Method *)n;
218 if(m->method == SIGNAL_LAST_METHOD ||
219 m->method == SIGNAL_FIRST_METHOD)
220 check_duplicate_named (c, n, m->id,
222 } else if (n->type == PROPERTY_NODE) {
223 Property *p = (Property *)n;
224 check_duplicate_named (c, n, p->name, p->line_no);
225 } else if (n->type == ARGUMENT_NODE) {
226 Argument *a = (Argument *)n;
227 check_duplicate_named (c, n, a->name, a->line_no);
233 check_public_new(Class *c)
236 for(li = c->nodes; li != NULL; li = li->next) {
238 if(n->type == METHOD_NODE) {
239 Method *m = (Method *)n;
240 if((strcmp(m->id, "new")==0) &&
241 (m->method != REGULAR_METHOD ||
242 m->scope != PUBLIC_SCOPE))
243 error_print(GOB_WARN, m->line_no,
244 "'new' should be a regular\n"
251 check_vararg(Class *c)
254 for(li = c->nodes; li != NULL; li = li->next) {
256 if(n->type == METHOD_NODE) {
257 Method *m = (Method *)n;
260 if(m->method == OVERRIDE_METHOD ||
261 m->method == SIGNAL_LAST_METHOD ||
262 m->method == SIGNAL_FIRST_METHOD ||
263 m->method == VIRTUAL_METHOD) {
264 error_print(GOB_ERROR, m->line_no,
265 "signals, overrides and virtuals, "
266 "can't have variable argument "
274 check_firstarg(Class *c)
277 for(li = c->nodes; li != NULL; li = li->next) {
279 if(n->type == METHOD_NODE) {
280 Method *m = (Method *)n;
283 if(m->method == OVERRIDE_METHOD ||
284 m->method == SIGNAL_LAST_METHOD ||
285 m->method == SIGNAL_FIRST_METHOD ||
286 m->method == VIRTUAL_METHOD) {
287 error_print(GOB_ERROR, m->line_no,
288 "signals, overrides and virtuals, "
289 "can't have no arguments");
296 check_nonvoidempty(Class *c)
299 for(li = c->nodes; li != NULL; li = li->next) {
301 if(n->type == METHOD_NODE) {
302 Method *m = (Method *)n;
303 if(m->method != REGULAR_METHOD)
305 if(!(strcmp(m->mtype->name, "void")==0 &&
306 m->mtype->pointer == NULL) &&
308 error_print(GOB_WARN, m->line_no,
309 "non-void empty method found, "
310 "regular non-void function should "
312 /* add a body here, so that the user will also
313 get a warning from gcc, and so that it will
314 at least point him to the prototype of the
315 function in the .gob file */
316 m->cbuf = g_strdup("/*empty*/");
317 m->ccode_line = m->line_no;
324 check_signal_args (Class *c)
327 for (li = c->nodes; li != NULL; li = li->next) {
329 if(n->type == METHOD_NODE) {
330 Method *m = (Method *)n;
332 if(m->method != SIGNAL_LAST_METHOD &&
333 m->method != SIGNAL_FIRST_METHOD)
336 for (l = m->gtktypes; l != NULL; l = l->next) {
337 if (get_cast (l->data, FALSE))
339 error_printf (GOB_ERROR, m->line_no,
340 "Unknown GTK+ type '%s' "
341 "among signal types",
349 check_argument_types (Class *c)
352 for (li = c->nodes; li != NULL; li = li->next) {
354 if(n->type == ARGUMENT_NODE) {
355 Argument *a = (Argument *)n;
356 if(get_cast(a->gtktype, FALSE))
358 error_printf(GOB_ERROR, a->line_no,
359 "Unknown GLib type '%s' "
367 check_property_types (Class *c)
370 for (li = c->nodes; li != NULL; li = li->next) {
372 if (n->type == PROPERTY_NODE) {
373 Property *p = (Property *)n;
374 if (get_cast (p->gtktype, FALSE))
376 error_printf (GOB_ERROR, p->line_no,
377 "Unknown GLib type '%s' "
385 check_func_arg_check_func_arg(Method *m, FuncArg *fa)
393 if(strcmp(fa->atype->name, "void") == 0 &&
394 fa->atype->pointer == NULL) {
395 error_print(GOB_ERROR, m->line_no,
396 "Running checks on a void function argument");
400 for(li = fa->checks; li; li = li->next) {
401 Check *ch = li->data;
402 if(ch->chtype == TYPE_CHECK) {
404 gboolean got_type = FALSE;
405 s = g_strdup(fa->atype->name);
409 goto type_check_error;
412 if(strcmp(p, "const") != 0) {
415 goto type_check_error;
419 p = strtok(NULL, " ");
423 goto type_check_error;
425 if(fa->atype->pointer == NULL ||
426 (strcmp(fa->atype->pointer, "*") != 0 &&
427 strcmp(fa->atype->pointer, "* const") != 0 &&
428 strcmp(fa->atype->pointer, "const *") != 0))
429 goto type_check_error;
435 if(fa->atype->pointer)
436 error_printf(GOB_ERROR, m->line_no,
437 "Cannot check the type of '%s %s'",
438 fa->atype->name, fa->atype->pointer);
440 error_printf(GOB_ERROR, m->line_no,
441 "Cannot check the type of '%s'",
446 check_func_arg_check_method(Method *m)
449 for(li = m->args; li; li = li->next) {
450 FuncArg *fa = li->data;
451 check_func_arg_check_func_arg(m, fa);
456 check_func_arg_checks(Class *c)
459 for(li = c->nodes; li != NULL; li = li->next) {
461 if(n->type == METHOD_NODE) {
462 Method *m = (Method *)n;
463 check_func_arg_check_method(m);
469 count_signals(Class *c)
473 for(li = c->nodes; li != NULL; li = li->next) {
475 if(n->type == METHOD_NODE) {
476 Method *m = (Method *)n;
477 if(m->method == SIGNAL_LAST_METHOD ||
478 m->method == SIGNAL_FIRST_METHOD)
486 count_set_properties (Class *c)
490 for (li = c->nodes; li != NULL; li = li->next) {
492 Property *p = li->data;
493 if (n->type == PROPERTY_NODE &&
501 count_get_properties (Class *c)
505 for (li = c->nodes; li != NULL; li = li->next) {
507 Property *p = li->data;
508 if (n->type == PROPERTY_NODE &&
517 count_set_arguments(Class *c)
521 for(li = c->nodes; li != NULL; li = li->next) {
523 Argument *a = li->data;
524 if(n->type == ARGUMENT_NODE &&
532 count_get_arguments(Class *c)
536 for(li = c->nodes; li != NULL; li = li->next) {
538 Argument *a = li->data;
539 if(n->type == ARGUMENT_NODE &&
547 count_overrides(Class *c)
551 for(li = c->nodes; li != NULL; li = li->next) {
553 if(n->type == METHOD_NODE) {
554 Method *m = (Method *)n;
555 if(m->method == OVERRIDE_METHOD)
563 count_privates(Class *c)
567 for(li = c->nodes; li != NULL; li = li->next) {
569 if(n->type == VARIABLE_NODE) {
570 Variable *v = (Variable *)n;
571 if(v->scope == PRIVATE_SCOPE)
579 count_protecteds (Class *c)
583 for (li = c->nodes; li != NULL; li = li->next) {
585 if(n->type == METHOD_NODE) {
586 Method *m = (Method *)n;
587 if(m->scope == PROTECTED_SCOPE)
595 count_unreftors (Class *c)
599 for (li = c->nodes; li != NULL; li = li->next) {
601 if (n->type == VARIABLE_NODE) {
602 Variable *v = (Variable *)n;
603 if (v->destructor != NULL &&
612 count_destructors (Class *c)
616 for (li = c->nodes; li != NULL; li = li->next) {
618 if (n->type == VARIABLE_NODE) {
619 Variable *v = (Variable *)n;
620 if (v->destructor != NULL &&
621 ! v->destructor_unref)
629 count_initializers (Class *c)
633 for (li = c->nodes; li != NULL; li = li->next) {
635 if (n->type == VARIABLE_NODE) {
636 Variable *v = (Variable *)n;
637 if (v->initializer != NULL)
645 find_get_type (Class *c)
648 for (li = c->nodes; li != NULL; li = li->next) {
650 Method *m = (Method *)n;
651 if (n->type == METHOD_NODE &&
652 strcmp (m->id, "get_type") == 0) {
653 if (m->method != REGULAR_METHOD ||
654 m->scope != PUBLIC_SCOPE ||
656 error_printf (GOB_ERROR, m->line_no,
657 "get_type method must be a "
658 "regular public method with "