#include "tree.h"
#include "parse.h"
#include "out.h"
+#include "main.h"
char *filename = "stdin";
FILE *outh;
int exit_on_warn = FALSE;
+int exit_on_error = TRUE;
+int got_error = FALSE;
-static void
+void
print_error(int is_warn, char *error,int line)
{
char *w;
if(is_warn)
w = "Warning:";
- else
+ else {
w = "Error:";
+ got_error = TRUE;
+ }
if(line>0)
fprintf(stderr,"%s:%d: %s %s\n",filename,line,w,error);
else
fprintf(stderr,"%s: %s %s\n",filename,w,error);
- if(!is_warn || exit_on_warn)
+ if((!is_warn || exit_on_warn) && exit_on_error)
exit(1);
}
out_printf(fp,"%s",arg->name);
}
+ if(m->vararg)
+ out_printf(fp,", ...");
} else {
out_printf(fp,"void");
}
(Type *)new_type(0,g_strdup("void")),
NULL,NULL,g_strdup("class_init"),
make_init_args(cl,g_strdup("c"),TRUE),
- NULL, NULL,0,0);
+ NULL, NULL,0,0,FALSE);
cl->nodes = g_list_prepend(cl->nodes,node);
}
if(!got_init) {
(Type *)new_type(0,g_strdup("void")),
NULL,NULL,g_strdup("init"),
make_init_args(cl,g_strdup("o"),FALSE),
- NULL, NULL,0,0);
+ NULL, NULL,0,0,FALSE);
cl->nodes = g_list_prepend(cl->nodes,node);
}
}
"\tGtkArg *arg,\n"
"\tguint arg_id)\n"
"{\n"
- "\t%s *this;\n\n"
- "\tthis = %s (object);\n\n"
+ "\t%s *self, *this;\n\n"
+ "\tself = this = %s (object);\n\n"
"\tswitch (arg_id) {\n",
is_set?"set":"get",typebase,macrobase);
m->mtype->stars==0) {
GList *li;
print_preconditions(m);
- out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (this),\n"
- "\t\tobject_signals[%s_SIGNAL]",s);
+ if(((FuncArg *)m->args->data)->name)
+ out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
+ "\t\tobject_signals[%s_SIGNAL]",
+ ((FuncArg *)m->args->data)->name,s);
for(li=m->args->next;li;li=g_list_next(li)) {
FuncArg *fa = li->data;
out_printf(out,",\n\t\t%s",fa->name);
print_type(out,m->mtype);
out_printf(out,"return_val;\n");
print_preconditions(m);
- out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (this),\n"
- "\t\tobject_signals[%s_SIGNAL]",s);
+ out_printf(out,"\tgtk_signal_emit (GTK_OBJECT (%s),\n"
+ "\t\tobject_signals[%s_SIGNAL]",
+ ((FuncArg *)m->args->data)->name,s);
for(li=m->args->next;li;li=g_list_next(li)) {
FuncArg *fa = li->data;
out_printf(out,",\n\t\t%s",fa->name);
out_printf(out,"{\n"
"\t%sClass *class;\n",typebase);
print_preconditions(m);
- out_printf(out,"\tclass = %s_CLASS(GTK_OBJECT(this)->klass);\n\n"
+ out_printf(out,"\tclass = %s_CLASS(GTK_OBJECT(%s)->klass);\n\n"
"\tif(class->%s)\n",
- macrobase,m->id);
+ macrobase, ((FuncArg *)m->args->data)->name, m->id);
if(strcmp(m->mtype->name,"void")==0 &&
m->mtype->stars==0) {
GList *li;
- out_printf(out,"\t\t(*class->%s)(this",m->id);
+ out_printf(out,"\t\t(*class->%s)(%s",m->id,
+ ((FuncArg *)m->args->data)->name);
for(li=m->args->next;li;li=g_list_next(li)) {
FuncArg *fa = li->data;
out_printf(out,",%s",fa->name);
out_printf(out,");\n}\n");
} else {
GList *li;
- out_printf(out,"\t\treturn (*class->%s)(this",m->id);
+ out_printf(out,"\t\treturn (*class->%s)(%s",m->id,
+ ((FuncArg *)m->args->data)->name);
for(li=m->args->next;li;li=g_list_next(li)) {
FuncArg *fa = li->data;
out_printf(out,",%s",fa->name);
}
}
+static void
+check_duplicate(Class *c,Node *node,char *id, int line_no)
+{
+ GList *l;
+ for(l=c->nodes;l;l=g_list_next(l)) {
+ Node *n = l->data;
+ char *nid;
+ int nline_no;
+ char *s;
+ if(n->type == METHOD_NODE) {
+ Method *m = (Method *)n;
+ nid = m->id;
+ nline_no = m->line_no;
+ } else if(n->type == VARIABLE_NODE) {
+ Variable *v = (Variable *)n;
+ nid = v->id;
+ nline_no = v->line_no;
+ } else
+ continue;
+ if(n==node ||
+ line_no>=nline_no ||
+ strcmp(nid,id)!=0)
+ continue;
+ s = g_strdup_printf("symbol '%s' redefined, "
+ "first defined on line %d",
+ id,line_no);
+ print_error(FALSE,s,nline_no);
+ }
+}
+
+static void
+check_duplicate_symbols(Class *c)
+{
+ GList *l;
+ for(l=c->nodes;l;l=g_list_next(l)) {
+ Node *n = l->data;
+ if(n->type == METHOD_NODE) {
+ Method *m = (Method *)n;
+ check_duplicate(c,n,m->id,m->line_no);
+ } else if(n->type == VARIABLE_NODE) {
+ Variable *v = (Variable *)n;
+ check_duplicate(c,n,v->id,v->line_no);
+ }
+ }
+}
+
+static void
+check_duplicate_named(Class *c,Node *node,char *id, int line_no)
+{
+ GList *l;
+ for(l=c->nodes;l;l=g_list_next(l)) {
+ Node *n = l->data;
+ char *nid;
+ int nline_no;
+ char *s;
+ if(n->type == METHOD_NODE) {
+ Method *m = (Method *)n;
+ if(m->scope == SIGNAL_LAST_METHOD ||
+ m->scope == SIGNAL_FIRST_METHOD) {
+ nid = m->id;
+ nline_no = m->line_no;
+ } else
+ continue;
+ } else if(n->type == ARGUMENT_NODE) {
+ Argument *a = (Argument *)n;
+ nid = a->name;
+ nline_no = a->line_no;
+ } else
+ continue;
+ if(n==node ||
+ line_no>=nline_no ||
+ strcmp(nid,id)!=0)
+ continue;
+ s = g_strdup_printf("named symbol (argument or signal) '%s' "
+ "redefined, first defined on line %d",
+ id,line_no);
+ print_error(FALSE,s,nline_no);
+ }
+}
+
+static void
+check_duplicate_signals_args(Class *c)
+{
+ GList *l;
+ for(l=c->nodes;l;l=g_list_next(l)) {
+ Node *n = l->data;
+ if(n->type == METHOD_NODE) {
+ Method *m = (Method *)n;
+ if(m->scope == SIGNAL_LAST_METHOD ||
+ m->scope == SIGNAL_FIRST_METHOD)
+ check_duplicate_named(c,n,m->id,m->line_no);
+ } else if(n->type == ARGUMENT_NODE) {
+ Argument *a = (Argument *)n;
+ check_duplicate_named(c,n,a->name,a->line_no);
+ }
+ }
+}
+
+static void
+check_public_new(Class *c)
+{
+ GList *l;
+ for(l=c->nodes;l;l=g_list_next(l)) {
+ Node *n = l->data;
+ if(n->type == METHOD_NODE) {
+ Method *m = (Method *)n;
+ if(m->scope!=PUBLIC_SCOPE &&
+ strcmp(m->id,"new")==0)
+ print_error(TRUE,
+ "'new' should be a public method",
+ m->line_no);
+ }
+ }
+}
+
+static void
+check_vararg(Class *c)
+{
+ GList *l;
+ for(l=c->nodes;l;l=g_list_next(l)) {
+ Node *n = l->data;
+ if(n->type == METHOD_NODE) {
+ Method *m = (Method *)n;
+ if(!m->vararg)
+ continue;
+ if(m->scope == OVERRIDE_METHOD ||
+ m->scope == SIGNAL_LAST_METHOD ||
+ m->scope == SIGNAL_FIRST_METHOD ||
+ m->scope == VIRTUAL_METHOD) {
+ print_error(FALSE,
+ "signals, overrides and virtuals, "
+ "can't have variable argument "
+ "lists",
+ m->line_no);
+ }
+ }
+ }
+}
+
static int
count_signals(Class *c)
{
make_bases();
+ exit_on_error = FALSE;
make_inits((Class *)class);
+ check_duplicate_symbols((Class *)class);
+ check_duplicate_signals_args((Class *)class);
+ check_public_new((Class *)class);
+ check_vararg((Class *)class);
+ exit_on_error = TRUE;
+ if(got_error)
+ exit(1);
+
open_files();
generate_outfiles();