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_func_attrs(Class *c)
485 for (li = c->nodes; li != NULL; li = li->next) {
487 if (n->type == METHOD_NODE) {
488 Method *m = (Method *)n;
489 if ((m->method == INIT_METHOD ||
490 m->method == CLASS_INIT_METHOD)
491 && (m->funcattrs != NULL && strlen(m->funcattrs) != 0)) {
492 /* This is actually dead code at the moment, since the parser
493 doesn't accept attributes to the init or class_init
494 syntactic forms anyway. But it could easily be made to do
495 so, and also for virtual override and signal methods, and
496 then we could give kinder error messages here. */
497 error_print (GOB_ERROR, m->line_no,
498 "function attributes (G_GNUC_PRINTF, etc.) aren't "
499 "supported for the init or class_init methods");
506 check_for_class_destructors (Class *c)
509 for (li = c->nodes; li != NULL; li = li->next) {
511 if (n->type == VARIABLE_NODE) {
512 Variable *v = (Variable *)n;
513 if (v->destructor != NULL &&
514 v->scope == CLASS_SCOPE) {
515 error_print (GOB_WARN, v->line_no,
516 "classwide members cannot have "
517 "destructors since the classes "
518 "are static and never get "
526 count_signals(Class *c)
530 for(li = c->nodes; li != NULL; li = li->next) {
532 if(n->type == METHOD_NODE) {
533 Method *m = (Method *)n;
534 if(m->method == SIGNAL_LAST_METHOD ||
535 m->method == SIGNAL_FIRST_METHOD)
543 count_set_properties (Class *c)
547 for (li = c->nodes; li != NULL; li = li->next) {
549 Property *p = li->data;
550 if (n->type == PROPERTY_NODE &&
558 count_get_properties (Class *c)
562 for (li = c->nodes; li != NULL; li = li->next) {
564 Property *p = li->data;
565 if (n->type == PROPERTY_NODE &&
574 count_set_arguments(Class *c)
578 for(li = c->nodes; li != NULL; li = li->next) {
580 Argument *a = li->data;
581 if(n->type == ARGUMENT_NODE &&
589 count_get_arguments(Class *c)
593 for(li = c->nodes; li != NULL; li = li->next) {
595 Argument *a = li->data;
596 if(n->type == ARGUMENT_NODE &&
604 count_overrides(Class *c)
608 for(li = c->nodes; li != NULL; li = li->next) {
610 if(n->type == METHOD_NODE) {
611 Method *m = (Method *)n;
612 if(m->method == OVERRIDE_METHOD)
620 count_privates(Class *c)
624 for(li = c->nodes; li != NULL; li = li->next) {
626 if(n->type == VARIABLE_NODE) {
627 Variable *v = (Variable *)n;
628 if(v->scope == PRIVATE_SCOPE)
636 count_protecteds (Class *c)
640 for (li = c->nodes; li != NULL; li = li->next) {
642 if(n->type == METHOD_NODE) {
643 Method *m = (Method *)n;
644 if(m->scope == PROTECTED_SCOPE)
652 count_unreftors (Class *c)
656 for (li = c->nodes; li != NULL; li = li->next) {
658 if (n->type == VARIABLE_NODE) {
659 Variable *v = (Variable *)n;
660 if (v->destructor != NULL &&
661 v->destructor_unref &&
662 v->scope != CLASS_SCOPE)
670 count_destructors (Class *c)
674 for (li = c->nodes; li != NULL; li = li->next) {
676 if (n->type == VARIABLE_NODE) {
677 Variable *v = (Variable *)n;
678 if (v->destructor != NULL &&
679 ! v->destructor_unref &&
680 v->scope != CLASS_SCOPE)
688 count_initializers (Class *c)
692 for (li = c->nodes; li != NULL; li = li->next) {
694 if (n->type == VARIABLE_NODE) {
695 Variable *v = (Variable *)n;
696 if (v->initializer != NULL)
704 count_glade_widgets (Class *c)
708 for (li = c->nodes; li != NULL; li = li->next) {
710 if (n->type == VARIABLE_NODE) {
711 Variable *v = (Variable *)n;
720 find_get_type (Class *c)
723 for (li = c->nodes; li != NULL; li = li->next) {
725 Method *m = (Method *)n;
726 if (n->type == METHOD_NODE &&
727 strcmp (m->id, "get_type") == 0) {
728 if (m->method != REGULAR_METHOD ||
729 m->scope != PUBLIC_SCOPE ||
731 error_printf (GOB_ERROR, m->line_no,
732 "get_type method must be a "
733 "regular public method with "