2 * Copyright (C) 1999-2000 the Free Software Foundation.
3 * Copyright (C) 2000 Eazel, Inc.
4 * Copyright (C) 2001-2004 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 (strcmp (l->data, "BOXED") == 0) {
338 error_printf (GOB_ERROR, m->line_no,
339 "BOXED not allowed as "
340 "a signal argument, use "
341 "POINTER, or BOXED_*");
343 } else if (strcmp (l->data, "FLAGS") == 0) {
344 error_printf (GOB_ERROR, m->line_no,
345 "FLAGS not allowed as "
346 "a signal argument, use "
350 if (get_cast (l->data, FALSE))
352 error_printf (GOB_ERROR, m->line_no,
353 "Unknown GTK+ type '%s' "
354 "among signal types",
362 check_argument_types (Class *c)
365 for (li = c->nodes; li != NULL; li = li->next) {
367 if(n->type == ARGUMENT_NODE) {
368 Argument *a = (Argument *)n;
369 if(get_cast(a->gtktype, FALSE))
371 error_printf(GOB_ERROR, a->line_no,
372 "Unknown GLib type '%s' "
380 check_property_types (Class *c)
383 for (li = c->nodes; li != NULL; li = li->next) {
385 if (n->type == PROPERTY_NODE) {
386 Property *p = (Property *)n;
387 if (get_cast (p->gtktype, FALSE))
389 error_printf (GOB_ERROR, p->line_no,
390 "Unknown GLib type '%s' "
398 check_func_arg_check_func_arg(Method *m, FuncArg *fa)
406 if(strcmp(fa->atype->name, "void") == 0 &&
407 fa->atype->pointer == NULL) {
408 error_print(GOB_ERROR, m->line_no,
409 "Running checks on a void function argument");
413 for(li = fa->checks; li; li = li->next) {
414 Check *ch = li->data;
415 if(ch->chtype == TYPE_CHECK) {
417 gboolean got_type = FALSE;
418 s = g_strdup(fa->atype->name);
422 goto type_check_error;
425 if(strcmp(p, "const") != 0) {
428 goto type_check_error;
432 p = strtok(NULL, " ");
436 goto type_check_error;
438 if(fa->atype->pointer == NULL ||
439 (strcmp(fa->atype->pointer, "*") != 0 &&
440 strcmp(fa->atype->pointer, "* const") != 0 &&
441 strcmp(fa->atype->pointer, "const *") != 0))
442 goto type_check_error;
448 if(fa->atype->pointer)
449 error_printf(GOB_ERROR, m->line_no,
450 "Cannot check the type of '%s %s'",
451 fa->atype->name, fa->atype->pointer);
453 error_printf(GOB_ERROR, m->line_no,
454 "Cannot check the type of '%s'",
459 check_func_arg_check_method(Method *m)
462 for(li = m->args; li; li = li->next) {
463 FuncArg *fa = li->data;
464 check_func_arg_check_func_arg(m, fa);
469 check_func_arg_checks(Class *c)
472 for(li = c->nodes; li != NULL; li = li->next) {
474 if(n->type == METHOD_NODE) {
475 Method *m = (Method *)n;
476 check_func_arg_check_method(m);
482 check_for_class_destructors (Class *c)
485 for (li = c->nodes; li != NULL; li = li->next) {
487 if (n->type == VARIABLE_NODE) {
488 Variable *v = (Variable *)n;
489 if (v->destructor != NULL &&
490 v->scope == CLASS_SCOPE) {
491 error_print (GOB_WARN, v->line_no,
492 "classwide members cannot have "
493 "destructors since the classes "
494 "are static and never get "
502 count_signals(Class *c)
506 for(li = c->nodes; li != NULL; li = li->next) {
508 if(n->type == METHOD_NODE) {
509 Method *m = (Method *)n;
510 if(m->method == SIGNAL_LAST_METHOD ||
511 m->method == SIGNAL_FIRST_METHOD)
519 count_set_properties (Class *c)
523 for (li = c->nodes; li != NULL; li = li->next) {
525 Property *p = li->data;
526 if (n->type == PROPERTY_NODE &&
534 count_get_properties (Class *c)
538 for (li = c->nodes; li != NULL; li = li->next) {
540 Property *p = li->data;
541 if (n->type == PROPERTY_NODE &&
550 count_set_arguments(Class *c)
554 for(li = c->nodes; li != NULL; li = li->next) {
556 Argument *a = li->data;
557 if(n->type == ARGUMENT_NODE &&
565 count_get_arguments(Class *c)
569 for(li = c->nodes; li != NULL; li = li->next) {
571 Argument *a = li->data;
572 if(n->type == ARGUMENT_NODE &&
580 count_overrides(Class *c)
584 for(li = c->nodes; li != NULL; li = li->next) {
586 if(n->type == METHOD_NODE) {
587 Method *m = (Method *)n;
588 if(m->method == OVERRIDE_METHOD)
596 count_privates(Class *c)
600 for(li = c->nodes; li != NULL; li = li->next) {
602 if(n->type == VARIABLE_NODE) {
603 Variable *v = (Variable *)n;
604 if(v->scope == PRIVATE_SCOPE)
612 count_protecteds (Class *c)
616 for (li = c->nodes; li != NULL; li = li->next) {
618 if(n->type == METHOD_NODE) {
619 Method *m = (Method *)n;
620 if(m->scope == PROTECTED_SCOPE)
628 count_unreftors (Class *c)
632 for (li = c->nodes; li != NULL; li = li->next) {
634 if (n->type == VARIABLE_NODE) {
635 Variable *v = (Variable *)n;
636 if (v->destructor != NULL &&
637 v->destructor_unref &&
638 v->scope != CLASS_SCOPE)
646 count_destructors (Class *c)
650 for (li = c->nodes; li != NULL; li = li->next) {
652 if (n->type == VARIABLE_NODE) {
653 Variable *v = (Variable *)n;
654 if (v->destructor != NULL &&
655 ! v->destructor_unref &&
656 v->scope != CLASS_SCOPE)
664 count_initializers (Class *c)
668 for (li = c->nodes; li != NULL; li = li->next) {
670 if (n->type == VARIABLE_NODE) {
671 Variable *v = (Variable *)n;
672 if (v->initializer != NULL)
680 count_glade_widgets (Class *c)
684 for (li = c->nodes; li != NULL; li = li->next) {
686 if (n->type == VARIABLE_NODE) {
687 Variable *v = (Variable *)n;
696 find_get_type (Class *c)
699 for (li = c->nodes; li != NULL; li = li->next) {
701 Method *m = (Method *)n;
702 if (n->type == METHOD_NODE &&
703 strcmp (m->id, "get_type") == 0) {
704 if (m->method != REGULAR_METHOD ||
705 m->scope != PUBLIC_SCOPE ||
707 error_printf (GOB_ERROR, m->line_no,
708 "get_type method must be a "
709 "regular public method with "