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 if (n == node || line_no >= nline_no
200 || gob_strcasecmp (nid, id) != 0)
204 error_printf (GOB_ERROR, nline_no,
205 "named symbol (argument or signal) '%s' "
206 "redefined, first defined on line %d "
207 "(case insensitive)",
213 check_duplicate_signals_args (Class *c)
216 for (li = c->nodes; li != NULL; li = li->next) {
218 if (n->type == METHOD_NODE) {
219 Method *m = (Method *)n;
220 if(m->method == SIGNAL_LAST_METHOD ||
221 m->method == SIGNAL_FIRST_METHOD)
222 check_duplicate_named (c, n, m->id,
224 } else if (n->type == PROPERTY_NODE) {
225 Property *p = (Property *)n;
226 check_duplicate_named (c, n, p->name, p->line_no);
227 } else if (n->type == ARGUMENT_NODE) {
228 Argument *a = (Argument *)n;
229 check_duplicate_named (c, n, a->name, a->line_no);
235 check_public_new(Class *c)
238 for(li = c->nodes; li != NULL; li = li->next) {
240 if(n->type == METHOD_NODE) {
241 Method *m = (Method *)n;
242 if((strcmp(m->id, "new")==0) &&
243 (m->method != REGULAR_METHOD ||
244 m->scope != PUBLIC_SCOPE))
245 error_print(GOB_WARN, m->line_no,
246 "'new' should be a regular\n"
253 check_vararg(Class *c)
256 for(li = c->nodes; li != NULL; li = li->next) {
258 if(n->type == METHOD_NODE) {
259 Method *m = (Method *)n;
262 if(m->method == OVERRIDE_METHOD ||
263 m->method == SIGNAL_LAST_METHOD ||
264 m->method == SIGNAL_FIRST_METHOD ||
265 m->method == VIRTUAL_METHOD) {
266 error_print(GOB_ERROR, m->line_no,
267 "signals, overrides and virtuals, "
268 "can't have variable argument "
276 check_firstarg(Class *c)
279 for(li = c->nodes; li != NULL; li = li->next) {
281 if(n->type == METHOD_NODE) {
282 Method *m = (Method *)n;
285 if(m->method == OVERRIDE_METHOD ||
286 m->method == SIGNAL_LAST_METHOD ||
287 m->method == SIGNAL_FIRST_METHOD ||
288 m->method == VIRTUAL_METHOD) {
289 error_print(GOB_ERROR, m->line_no,
290 "signals, overrides and virtuals, "
291 "can't have no arguments");
298 check_nonvoidempty(Class *c)
301 for(li = c->nodes; li != NULL; li = li->next) {
303 if(n->type == METHOD_NODE) {
304 Method *m = (Method *)n;
305 if(m->method != REGULAR_METHOD)
307 if(!(strcmp(m->mtype->name, "void")==0 &&
308 m->mtype->pointer == NULL) &&
310 error_print(GOB_WARN, m->line_no,
311 "non-void empty method found, "
312 "regular non-void function should "
314 /* add a body here, so that the user will also
315 get a warning from gcc, and so that it will
316 at least point him to the prototype of the
317 function in the .gob file */
318 m->cbuf = g_strdup("/*empty*/");
319 m->ccode_line = m->line_no;
326 check_signal_args (Class *c)
329 for (li = c->nodes; li != NULL; li = li->next) {
331 if(n->type == METHOD_NODE) {
332 Method *m = (Method *)n;
334 if(m->method != SIGNAL_LAST_METHOD &&
335 m->method != SIGNAL_FIRST_METHOD)
338 for (l = m->gtktypes; l != NULL; l = l->next) {
339 if (strcmp (l->data, "BOXED") == 0) {
340 error_printf (GOB_ERROR, m->line_no,
341 "BOXED not allowed as "
342 "a signal argument, use "
343 "POINTER, or BOXED_*");
345 } else if (strcmp (l->data, "FLAGS") == 0) {
346 error_printf (GOB_ERROR, m->line_no,
347 "FLAGS not allowed as "
348 "a signal argument, use "
352 if (get_cast (l->data, FALSE))
354 error_printf (GOB_ERROR, m->line_no,
355 "Unknown GTK+ type '%s' "
356 "among signal types",
364 check_argument_types (Class *c)
367 for (li = c->nodes; li != NULL; li = li->next) {
369 if(n->type == ARGUMENT_NODE) {
370 Argument *a = (Argument *)n;
371 if(get_cast(a->gtktype, FALSE))
373 error_printf(GOB_ERROR, a->line_no,
374 "Unknown GLib type '%s' "
382 check_property_types (Class *c)
385 for (li = c->nodes; li != NULL; li = li->next) {
387 if (n->type == PROPERTY_NODE) {
388 Property *p = (Property *)n;
389 if (get_cast (p->gtktype, FALSE))
391 error_printf (GOB_ERROR, p->line_no,
392 "Unknown GLib type '%s' "
400 check_func_arg_check_func_arg(Method *m, FuncArg *fa)
408 if(strcmp(fa->atype->name, "void") == 0 &&
409 fa->atype->pointer == NULL) {
410 error_print(GOB_ERROR, m->line_no,
411 "Running checks on a void function argument");
415 for(li = fa->checks; li; li = li->next) {
416 Check *ch = li->data;
417 if(ch->chtype == TYPE_CHECK) {
419 gboolean got_type = FALSE;
420 s = g_strdup(fa->atype->name);
424 goto type_check_error;
427 if(strcmp(p, "const") != 0) {
430 goto type_check_error;
434 p = strtok(NULL, " ");
438 goto type_check_error;
440 if(fa->atype->pointer == NULL ||
441 (strcmp(fa->atype->pointer, "*") != 0 &&
442 strcmp(fa->atype->pointer, "* const") != 0 &&
443 strcmp(fa->atype->pointer, "const *") != 0))
444 goto type_check_error;
450 if(fa->atype->pointer)
451 error_printf(GOB_ERROR, m->line_no,
452 "Cannot check the type of '%s %s'",
453 fa->atype->name, fa->atype->pointer);
455 error_printf(GOB_ERROR, m->line_no,
456 "Cannot check the type of '%s'",
461 check_func_arg_check_method(Method *m)
464 for(li = m->args; li; li = li->next) {
465 FuncArg *fa = li->data;
466 check_func_arg_check_func_arg(m, fa);
471 check_func_arg_checks(Class *c)
474 for(li = c->nodes; li != NULL; li = li->next) {
476 if(n->type == METHOD_NODE) {
477 Method *m = (Method *)n;
478 check_func_arg_check_method(m);
484 check_func_attrs(Class *c)
487 for (li = c->nodes; li != NULL; li = li->next) {
489 if (n->type == METHOD_NODE) {
490 Method *m = (Method *)n;
491 if ((m->method == INIT_METHOD ||
492 m->method == CLASS_INIT_METHOD)
493 && (m->funcattrs != NULL && strlen(m->funcattrs) != 0)) {
494 /* This is actually dead code at the moment, since the parser
495 doesn't accept attributes to the init or class_init
496 syntactic forms anyway. But it could easily be made to do
497 so, and also for virtual override and signal methods, and
498 then we could give kinder error messages here. */
499 error_print (GOB_ERROR, m->line_no,
500 "function attributes (G_GNUC_PRINTF, etc.) aren't "
501 "supported for the init or class_init methods");
508 check_for_class_destructors (Class *c)
511 for (li = c->nodes; li != NULL; li = li->next) {
513 if (n->type == VARIABLE_NODE) {
514 Variable *v = (Variable *)n;
515 if (v->destructor != NULL &&
516 v->scope == CLASS_SCOPE) {
517 error_print (GOB_WARN, v->line_no,
518 "classwide members cannot have "
519 "destructors since the classes "
520 "are static and never get "
528 count_signals(Class *c)
532 for(li = c->nodes; li != NULL; li = li->next) {
534 if(n->type == METHOD_NODE) {
535 Method *m = (Method *)n;
536 if(m->method == SIGNAL_LAST_METHOD ||
537 m->method == SIGNAL_FIRST_METHOD)
545 count_set_properties (Class *c)
549 for (li = c->nodes; li != NULL; li = li->next) {
551 Property *p = li->data;
552 if (n->type == PROPERTY_NODE &&
560 count_get_properties (Class *c)
564 for (li = c->nodes; li != NULL; li = li->next) {
566 Property *p = li->data;
567 if (n->type == PROPERTY_NODE &&
576 count_set_arguments(Class *c)
580 for(li = c->nodes; li != NULL; li = li->next) {
582 Argument *a = li->data;
583 if(n->type == ARGUMENT_NODE &&
591 count_get_arguments(Class *c)
595 for(li = c->nodes; li != NULL; li = li->next) {
597 Argument *a = li->data;
598 if(n->type == ARGUMENT_NODE &&
606 count_overrides(Class *c)
610 for(li = c->nodes; li != NULL; li = li->next) {
612 if(n->type == METHOD_NODE) {
613 Method *m = (Method *)n;
614 if(m->method == OVERRIDE_METHOD)
622 count_privates(Class *c)
626 for(li = c->nodes; li != NULL; li = li->next) {
628 if(n->type == VARIABLE_NODE) {
629 Variable *v = (Variable *)n;
630 if(v->scope == PRIVATE_SCOPE)
638 count_protecteds (Class *c)
642 for (li = c->nodes; li != NULL; li = li->next) {
644 if(n->type == METHOD_NODE) {
645 Method *m = (Method *)n;
646 if(m->scope == PROTECTED_SCOPE)
654 count_unreftors (Class *c)
658 for (li = c->nodes; li != NULL; li = li->next) {
660 if (n->type == VARIABLE_NODE) {
661 Variable *v = (Variable *)n;
662 if (v->destructor != NULL &&
663 v->destructor_unref &&
664 v->scope != CLASS_SCOPE)
672 count_destructors (Class *c)
676 for (li = c->nodes; li != NULL; li = li->next) {
678 if (n->type == VARIABLE_NODE) {
679 Variable *v = (Variable *)n;
680 if (v->destructor != NULL &&
681 ! v->destructor_unref &&
682 v->scope != CLASS_SCOPE)
690 count_initializers (Class *c)
694 for (li = c->nodes; li != NULL; li = li->next) {
696 if (n->type == VARIABLE_NODE) {
697 Variable *v = (Variable *)n;
698 if (v->initializer != NULL)
706 count_glade_widgets (Class *c)
710 for (li = c->nodes; li != NULL; li = li->next) {
712 if (n->type == VARIABLE_NODE) {
713 Variable *v = (Variable *)n;
722 find_get_type (Class *c)
725 for (li = c->nodes; li != NULL; li = li->next) {
727 Method *m = (Method *)n;
728 if (n->type == METHOD_NODE &&
729 strcmp (m->id, "get_type") == 0) {
730 if (m->method != REGULAR_METHOD ||
731 m->scope != PUBLIC_SCOPE ||
733 error_printf (GOB_ERROR, m->line_no,
734 "get_type method must be a "
735 "regular public method with "