Signal marshalling should be pretty complete now. Demarshalling isn't

quite yet, though..
This commit is contained in:
Lauri Alanko 1998-11-18 11:25:11 +00:00
parent 056691c594
commit 72b48d5259
9 changed files with 272 additions and 111 deletions

View File

@ -1,3 +1,8 @@
1998-11-18 Lauri Alanko <la@iki.fi>
* Signal marshalling should be pretty complete now. Demarshalling
isn't quite yet, though..
1998-11-17 Lauri Alanko <la@iki.fi>
* Misc enhancements.

View File

@ -14,7 +14,7 @@ PrimType* get_type(Id modname, Id name){
p=g_new(PrimType, 1);
p->module=m;
p->name=name;
p->kind=GTK_TYPE_INVALID;
p->kind=TYPE_INVALID;
p->decl_header=NULL;
p->def_header=NULL;
p->definition=NULL;

View File

@ -1,7 +1,6 @@
#ifndef __GCG_H__
#define __GCG_H__
#include <glib.h>
#include <gtk/gtktypeutils.h>
extern gboolean in_ident;
@ -25,6 +24,17 @@ typedef struct _DefClass DefClass;
typedef struct _Param Param;
typedef struct _Module Module;
typedef enum{
TYPE_INVALID,
TYPE_NONE,
TYPE_INT,
TYPE_LONG,
TYPE_DOUBLE,
TYPE_ENUM,
TYPE_FLAGS,
TYPE_FOREIGN,
TYPE_OBJECT
} TypeKind;
struct _Module {
Id name;
@ -35,7 +45,7 @@ struct _Module {
struct _PrimType {
Module* module;
Id name;
GtkFundamentalType kind;
TypeKind kind;
Id decl_header;
Id def_header;
Def* definition;

View File

@ -37,8 +37,8 @@ class Image : Object{
g.int num-cols;
read-only BaseType base-type;
read-write g.int foobar;
Layer* active-layer;
Layer* floating-sel;
read-write Layer& active-layer;
read-write Layer* floating-sel;
public static Image* new(g.int width,
g.int height,
BaseType base-type);
@ -46,6 +46,19 @@ class Image : Object{
public static g.int foo-1(Layer* x);
public direct g.int foo-2(Layer* x);
public abstract void foo-3(g.int x);
public pre-emit void foo-4(g.int x) const;
public post-emit void foo-5(g.int x, Drawable**& n, Image* z);
protected pre-emit void foo-4(g.int x) const;
public post-emit g.int foo-5(g.int x, Drawable**& n, Image* z);
public post-emit g.int foo-6(g.int a1,
g.int a2,
g.int a3,
g.int a4,
g.int a5,
g.int a6,
g.int a7,
g.int a8,
g.int a9,
g.int a10,
g.int a11,
g.int a12,
g.int a13);
};

View File

@ -2,12 +2,47 @@
#include "output.h"
#include "marshall.h"
typedef enum {
MARSHALL_INT,
MARSHALL_DOUBLE,
MARSHALL_POINTER,
MARSHALL_VOID,
MARSHALL_LONG
} MarshallType;
struct _SignalType {
Id package;
GtkType rettype;
MarshallType rettype;
GSList* argtypes;
};
MarshallType marshalling_type(Type* t){
if(!t)
return MARSHALL_VOID;
if(t->indirection)
return MARSHALL_POINTER;
if(!t->prim)
return MARSHALL_VOID;
switch(t->prim->kind){
case TYPE_INT:
case TYPE_FLAGS:
case TYPE_ENUM:
return MARSHALL_INT;
case TYPE_LONG:
return MARSHALL_LONG;
case TYPE_DOUBLE:
return MARSHALL_DOUBLE;
case TYPE_NONE:
return MARSHALL_VOID;
default:
g_assert_not_reached();
return MARSHALL_VOID;
}
}
SignalType* sig_type(Method* m){
SignalType *t=g_new(SignalType, 1);
GSList* p=m->params, *a=NULL;
@ -15,7 +50,7 @@ SignalType* sig_type(Method* m){
t->rettype = marshalling_type(&m->ret_type);
while(p){
Param* param=p->data;
GtkType* t=g_new(GtkType, 1);
MarshallType* t=g_new(MarshallType, 1);
*t=marshalling_type(&param->type);
a=g_slist_prepend(a, t);
p=p->next;
@ -35,63 +70,61 @@ void sig_type_free(SignalType* t){
g_free(t);
}
PNode* p_gtype_name(GtkType t, gboolean abbr){
PNode* p_gtype_name(MarshallType t, gboolean abbr){
static const struct GTypeName{
GtkType type;
MarshallType type;
Id name;
Id aname;
}names[]={
{GTK_TYPE_POINTER, "POINTER", "P"},
{GTK_TYPE_INT, "INT", "I"},
{GTK_TYPE_DOUBLE, "DOUBLE", "D"},
{GTK_TYPE_LONG, "LONG", "L"},
{GTK_TYPE_CHAR, "CHAR", "C"},
{GTK_TYPE_NONE, "NONE", "0"},
{MARSHALL_POINTER, "POINTER", "P"},
{MARSHALL_INT, "INT", "I"},
{MARSHALL_DOUBLE, "DOUBLE", "D"},
{MARSHALL_LONG, "LONG", "L"},
{MARSHALL_VOID, "NONE", "0"},
};
gint i;
for(i=0;i<sizeof(names)/sizeof(names[0]);i++)
for(i=0;i<(gint)(sizeof(names)/sizeof(names[0]));i++)
if(names[i].type==t)
if(abbr)
return p_str(names[i].aname);
else
return p_str(names[i].name);
return p_str(abbr
?names[i].aname
:names[i].name);
g_assert_not_reached();
return NULL;
}
PNode* p_gtabbr(gpointer p){
GtkType* t=p;
MarshallType* t=p;
return p_gtype_name(*t, TRUE);
}
GtkType marshalling_type(Type* t){
g_assert(t);
if(!t->prim)
return GTK_TYPE_NONE;
g_assert(t->prim->kind!=GTK_TYPE_INVALID);
if(t->indirection)
return GTK_TYPE_POINTER;
switch(t->prim->kind){
case GTK_TYPE_UINT:
case GTK_TYPE_BOOL:
case GTK_TYPE_FLAGS:
case GTK_TYPE_ENUM:
return GTK_TYPE_INT;
case GTK_TYPE_STRING:
return GTK_TYPE_POINTER;
case GTK_TYPE_UCHAR:
return GTK_TYPE_CHAR;
case GTK_TYPE_ULONG:
return GTK_TYPE_LONG;
default:
return t->prim->kind;
}
PNode* p_gtktype(Type* t){
if(t->indirection==0){
if(!t->prim)
return p_str("GTK_TYPE_NONE");
switch(t->prim->kind){
case TYPE_INT:
return p_str("GTK_TYPE_INT");
case TYPE_DOUBLE:
return p_str("GTK_TYPE_DOUBLE");
case TYPE_ENUM:
case TYPE_FLAGS:
return p_macro_name(t->prim, "TYPE", NULL);
default:
g_assert_not_reached();
return p_str("GTK_TYPE_NONE");
}
}else if(t->indirection==1
&& t->prim
&& (t->prim->kind==TYPE_FOREIGN
|| t->prim->kind==TYPE_OBJECT))
return p_macro_name(t->prim, "TYPE", NULL);
else
return p_str("GTK_TYPE_POINTER");
}
PNode* p_signal_func_name(SignalType* t, PNode* basename){
return p_fmt("_~_~_~_~",
@ -116,15 +149,65 @@ PNode* p_handler_type(SignalType* t){
p_for(t->argtypes, p_gtabbr, p_nil));
}
PNode* p_signal_id(Method* s){
PrimType* t=DEF(MEMBER(s)->my_class)->type;
return p_fmt("_~_~_signal_~",
p_c_ident(t->module->name),
p_c_ident(t->name),
p_c_ident(MEMBER(s)->name));
}
typedef struct{
PNode* args;
gint idx;
}ArgMarshData;
PNode* p_arg_marsh(gpointer p, gpointer d){
GtkType* t=p;
Param* par=p;
gint* idx=d;
(*idx)++;
return p_fmt(/* "\targs[~].type=~;\n" unnecessary... */
"\tGTK_VALUE_~(args[~]) = ~;\n",
/* p_prf("%d", *idx),
p_gtktype(&par->type), */
p_gtype_name(marshalling_type(&par->type), FALSE),
p_prf("%d", *idx),
p_c_ident(par->name));
}
PNode* p_sig_marshalling(Method* m){
gint idx=-1;
gboolean ret=marshalling_type(&m->ret_type)!=MARSHALL_VOID;
return p_fmt("\t{\n"
"\tGtkArg args[~];\n"
"~"
"~"
"~"
"\tgtk_signal_emitv((GtkObject*)~, ~, args);\n"
"~"
"\t}\n",
p_prf("%d",
g_slist_length(m->params)+ret),
ret
?p_fmt("\t~ retval;\n",
p_type(&m->ret_type))
:p_nil,
p_for(m->params, p_arg_marsh, &idx),
ret
/* cannot use retloc here, ansi forbids casted lvalues */
?p_fmt("\tGTK_VALUE_POINTER(args[~]) = &retval;\n",
p_prf("%d", g_slist_length(m->params)))
:p_nil,
p_c_ident(DEF(MEMBER(m)->my_class)->type->name),
p_signal_id(m),
ret
?p_str("\treturn retval;\n")
:p_nil);
}
PNode* p_arg_demarsh(gpointer p, gpointer d){
MarshallType* t=p;
ArgMarshData* data=d;
return p_fmt("\t\tGTK_VALUE_~(~[~]),\n",
p_gtype_name(*t, FALSE),
@ -136,7 +219,7 @@ PNode* p_demarshaller(SignalType* t){
gint idx=0;
return p_lst((t->rettype==GTK_TYPE_NONE)
return p_lst((t->rettype==TYPE_NONE)
? p_fmt("\t*(GTK_RETLOC_~(args[~])) =\n",
p_gtype_name(t->rettype, FALSE),
p_prf("%d", g_slist_length(t->argtypes)))
@ -145,7 +228,7 @@ PNode* p_demarshaller(SignalType* t){
"~"
"\tuser_data);\n",
p_cast(p_handler_type(t), p_str("func")),
p_for(t->argtypes, p_arg_marsh, &idx)),
p_for(t->argtypes, p_arg_demarsh, &idx)),
p_nil);
}

View File

@ -7,11 +7,13 @@
typedef struct _SignalType SignalType;
SignalType* sig_type(Method* m);
void sig_type_free(SignalType* t);
PNode* p_gtype_name(GtkType t, gboolean abbr);
PNode* p_gtabbr(gpointer p);
GtkType marshalling_type(Type* t);
PNode* p_signal_marshaller_name(SignalType* s);
PNode* p_signal_demarshaller_name(SignalType* s);
PNode* p_arg_marsh(gpointer p, gpointer d);
PNode* p_gtktype(Type* t);
PNode* p_signal_id(Method* s);
PNode* p_sig_marshalling(Method* m);
#endif

View File

@ -129,7 +129,7 @@ PNode* p_type_guard(Type* t, PNode* var){
((t->indirection && t->notnull
? p_fmt("\tg_assert (~);\n", var)
: p_nil),
((t->indirection==1 && p->kind == GTK_TYPE_OBJECT)
((t->indirection==1 && p->kind == TYPE_OBJECT)
? (t->notnull
? p_fmt("\tg_assert (~(~));\n",
p_macro_name(p, "IS", NULL),
@ -139,11 +139,11 @@ PNode* p_type_guard(Type* t, PNode* var){
p_macro_name(p, "IS", NULL),
var))
: (t->indirection==0
? ((p->kind == GTK_TYPE_ENUM)
? ((p->kind == TYPE_ENUM)
? p_fmt("\tg_assert (~ <= ~);\n",
var,
p_macro_name(p, NULL, "LAST"))
: ((p->kind == GTK_TYPE_FLAGS)
: ((p->kind == TYPE_FLAGS)
? p_fmt("\tg_assert ((~ << 1) < ~);\n",
var,
p_macro_name(p, NULL, "LAST"))
@ -172,6 +172,23 @@ PNode* p_prototype(Type* rettype, PNode* name,
p_params(args2, &o));
}
void output_var_alias(PRoot* out, PrimType* t, PNode* basename){
pr_add(out, "import_alias",
p_fmt("#define ~ ~_~\n",
basename,
p_c_ident(t->module->name),
basename));
}
void output_type_alias(PRoot* out, PrimType* t, PNode* basename){
pr_add(out, "import_alias",
p_fmt("typedef ~~ ~;\n",
p_str(t->module->name),
basename,
basename));
}
void output_func(PRoot* out,
Id tag,
Type* rettype,
@ -239,13 +256,13 @@ void output_def(PRoot* out, Def* d){
p_str("GtkType"),
type_var);
switch(d->type->kind){
case GTK_TYPE_OBJECT:
case TYPE_OBJECT:
output_object(out, d);
break;
case GTK_TYPE_ENUM:
case TYPE_ENUM:
output_enum(out, d);
break;
case GTK_TYPE_FLAGS:
case TYPE_FLAGS:
output_flags(out, d);
break;
default:

View File

@ -1,6 +1,10 @@
#include "output.h"
#include "marshall.h"
PNode* p_self_name(Member* o){
return p_c_ident(DEF(o->my_class)->type->name);
}
PNode* p_object_member(Member* m){
DataMember* d;
if(m->membertype != MEMBER_DATA)
@ -94,13 +98,6 @@ PNode* p_real_varname(PrimType* t, PNode* name){
p_varname(t, name));
}
PNode* p_signal_id(Method* s){
PrimType* t=DEF(MEMBER(s)->my_class)->type;
return p_fmt("_~_~_signal_~",
p_c_ident(t->module->name),
p_c_ident(t->name),
p_c_ident(MEMBER(s)->name));
}
PNode* p_signal_handler_type(Method* s){
Member* m=MEMBER(s);
@ -112,9 +109,9 @@ PNode* p_signal_handler_type(Method* s){
void output_connector(PRoot* out, Method* m){
FunParams* par=fparams("t",
&MEMBER(m)->my_class->self_type[m->self_const],
p_c_ident(DEF(MEMBER(m)->my_class)->type->name),
p_nil);
&MEMBER(m)->my_class->self_type[m->self_const],
p_self_name(MEMBER(m)),
p_nil);
output_func(out, "functions",
&m->ret_type,
@ -129,7 +126,7 @@ void output_connector(PRoot* out, Method* m){
"\t\t(GtkSignalFunc)handler,\n"
"\t\tuser_data);\n",
m->ret_type.prim?p_str("return "):p_nil,
p_c_ident(DEF(MEMBER(m)->my_class)->type->name),
p_self_name(MEMBER(m)),
p_str(MEMBER(m)->name)));
}
@ -148,9 +145,9 @@ void output_method(PRoot* out, Method* m){
else
par = fparams("tp",
&MEMBER(m)->my_class->self_type[m->self_const],
p_c_ident(t->name),
p_nil,
m->params);
p_self_name(MEMBER(m)),
p_nil,
m->params);
switch(k){
SignalType* sig;
case METH_EMIT_PRE:
@ -158,22 +155,19 @@ void output_method(PRoot* out, Method* m){
case METH_EMIT_BOTH:
sig=sig_type(m);
output_var(out, NULL,
p_str("GtkSignal"),
p_str("GtkSignalID"),
p_signal_id(m));
o.names=FALSE;
o.types=TRUE;
pr_add(out, "functions",
p_fmt("typedef ~ (*~)(~);\n",
p_fmt("typedef ~ (*~)(~, gpointer);\n",
p_type(&m->ret_type),
p_signal_handler_type(m),
p_params(par, &o)));
output_connector(out, m);
o.names=TRUE;
o.types=FALSE;
dispatch=p_fmt("~(~, (GtkObject*)~)",
p_signal_marshaller_name(sig),
p_signal_id(m),
p_params(par, &o));
dispatch=p_sig_marshalling(m);
break;
case METH_STATIC:
case METH_DIRECT:
@ -185,12 +179,18 @@ void output_method(PRoot* out, Method* m){
p_real_varname(t, name),
p_params(par, &o)));
o.types=FALSE;
dispatch=p_fmt("~(~)",
dispatch=p_fmt("\t~ ~(~);\n",
m->ret_type.prim?
p_str("return "):
p_nil,
p_real_varname(t, name),
p_params(par, &o));
break;
case METH_VIRTUAL:
dispatch=p_fmt("((~*)((GtkObject*)~)->klass)->~(~)",
dispatch=p_fmt("\t~((~*)((GtkObject*)~)->klass)->~(~);\n",
m->ret_type.prim?
p_str("return "):
p_nil,
p_class_name(DEF(MEMBER(m)->my_class)->type),
p_c_ident(t->name),
name,
@ -204,21 +204,22 @@ void output_method(PRoot* out, Method* m){
p_varname(t, name),
p_nil,
par,
p_fmt("\t~~;\n",
m->ret_type.prim ? p_str("return ") : p_nil,
dispatch));
fparams_free(par);
dispatch);
fparams_free(par);
}
void output_data_member(PRoot* out, DataMember* m){
PrimType* t=DEF(MEMBER(m)->my_class)->type;
PNode* name = p_c_ident(MEMBER(m)->name);
PNode* self = p_self_name(MEMBER(m));
switch(m->prot){
FunParams* par;
case DATA_READWRITE: {
par=fparams("tt", &MEMBER(m)->my_class->self_type[FALSE],
p_str("self"),
self,
p_nil,
&m->type,
name,
@ -229,7 +230,32 @@ void output_data_member(PRoot* out, DataMember* m){
p_varname(t, p_fmt("set_~", name)),
p_nil,
par,
p_fmt("\tself->~ = ~;\n",
p_fmt("~"
"\t~->~ = ~;\n",
(m->type.prim->kind==TYPE_OBJECT
&& m->type.indirection==1)
?m->type.notnull
?p_fmt("\tgtk_object_ref "
"((GtkObject*) ~);\n"
"\tgtk_object_unref "
"((GtkObject*) ~->~);\n",
name,
self,
name)
:p_fmt("\tif(~)\n"
"\t\tgtk_object_ref "
"((GtkObject*) ~);\n"
"\tif(~->~)\n"
"\t\tgtk_object_unref "
"((GtkObject*) ~->~);\n",
name,
name,
self,
name,
self,
name)
:p_nil,
self,
name,
name));
fparams_free(par);
@ -237,7 +263,7 @@ void output_data_member(PRoot* out, DataMember* m){
/* fall through */
case DATA_READONLY:
par=fparams("t", &MEMBER(m)->my_class->self_type[TRUE],
p_str("self"),
self,
p_nil);
output_func(out,
"functions",
@ -245,7 +271,8 @@ void output_data_member(PRoot* out, DataMember* m){
p_varname(t, name),
p_nil,
par,
p_fmt("\treturn self->~;\n",
p_fmt("\treturn ~->~;\n",
self,
name));
fparams_free(par);
case DATA_PROTECTED:
@ -310,8 +337,8 @@ void output_object_type_init(PRoot* out, ObjectDef* o){
PNode* p_param_marshtype(gpointer p){
Param* param=p;
return p_fmt(",\n\t\tGTK_TYPE_~",
p_gtype_name(marshalling_type(&param->type), FALSE));
return p_fmt(",\n\t\t~",
p_gtktype(&param->type));
}
PNode* p_member_class_init(gpointer m, gpointer o){
@ -327,18 +354,23 @@ PNode* p_member_class_init(gpointer m, gpointer o){
case METH_EMIT_PRE:
case METH_EMIT_POST:
case METH_EMIT_BOTH:
return p_fmt("\t~ =\n"
return p_fmt("\t{\n"
"\textern void ~ (GtkObject*, GtkSignalFunc, "
"gpointer, GtkArg*);\n"
"\t~ =\n"
"\tgtk_signal_new(\"~\",\n"
"\t\tGTK_RUN_~,\n"
"\t\tobklass->type,\n"
"\t\tGTK_SIGNAL_OFFSET (~, ~),\n"
"\t\t~,\n"
"\t\tGTK_TYPE_~,\n"
"\t\t~,\n"
"\t\t~"
"~);\n"
"\tgtk_object_class_add_signals(obklass,\n"
"\t\t&~,\n"
"\t\t1);\n",
"\t\t1);\n"
"\t}\n",
p_signal_demarshaller_name(sig),
p_signal_id(meth),
p_str(mem->name),
p_str(meth->kind==METH_EMIT_PRE
@ -349,8 +381,7 @@ PNode* p_member_class_init(gpointer m, gpointer o){
p_class_name(DEF(ob)->type),
p_c_ident(mem->name),
p_signal_demarshaller_name(sig),
p_gtype_name(marshalling_type(&meth->ret_type),
FALSE),
p_gtktype(&meth->ret_type),
p_prf("%d", g_slist_length(meth->params)),
p_for(meth->params, p_param_marshtype, p_nil),
p_signal_id(meth));
@ -377,7 +408,7 @@ void output_object_init(PRoot* out, ObjectDef* o){
p_type(&o->self_type[FALSE]),
p_c_ident(DEF(o)->type->name)),
NULL,
p_fmt("\t\t~ (~);\n",
p_fmt("\t~ (~);\n",
p_varname(DEF(o)->type, p_str("init_real")),
p_c_ident(DEF(o)->type->name)));
}
@ -396,7 +427,7 @@ void output_class_init(PRoot* out, ObjectDef* o){
p_fmt("\tGtkObjectClass* obklass = \n"
"\t\t(GtkObjectClass*) klass;\n"
"~"
"\t\t~ (klass);\n",
"\t~ (klass);\n",
p_for(o->members, p_member_class_init, o),
p_varname(DEF(o)->type, p_str("class_init_real"))));
}

View File

@ -29,7 +29,7 @@ static GSList* imports_list;
EmitDef emit_def;
gboolean bool;
Type type;
GtkFundamentalType fund_type;
TypeKind fund_type;
};
%token T_MODULE
@ -135,21 +135,21 @@ decllist: /* empty */ | decllist decl;
decl: simpledecl ;/* | classdecl | opaquedecl | protclassdecl;*/
fundtype: T_INT {
$$ = GTK_TYPE_INT;
$$ = TYPE_INT;
} | T_DOUBLE {
$$ = GTK_TYPE_DOUBLE;
$$ = TYPE_DOUBLE;
} | T_BOXED {
$$ = GTK_TYPE_BOXED;
$$ = TYPE_FOREIGN;
} | T_CLASS {
$$ = GTK_TYPE_OBJECT;
$$ = TYPE_OBJECT;
} | T_ENUM {
$$ = GTK_TYPE_ENUM;
$$ = TYPE_ENUM;
} | T_FLAGS {
$$ = GTK_TYPE_FLAGS;
$$ = TYPE_FLAGS;
}
simpledecl: fundtype primtype T_END {
g_assert($2->kind==GTK_TYPE_INVALID);
g_assert($2->kind==TYPE_INVALID);
$2->kind = $1;
};
@ -273,7 +273,7 @@ def: classdef | enumdef | flagsdef;
enumdef: T_ENUM primtype T_OPEN_B idlist T_CLOSE_B docstring T_END {
EnumDef* d=g_new(EnumDef, 1);
g_assert($2->kind==GTK_TYPE_ENUM);
g_assert($2->kind==TYPE_ENUM);
d->alternatives = $4;
$$=DEF(d);
$$->type=$2;
@ -282,7 +282,7 @@ enumdef: T_ENUM primtype T_OPEN_B idlist T_CLOSE_B docstring T_END {
flagsdef: T_FLAGS primtype T_OPEN_B idlist T_CLOSE_B docstring T_END {
FlagsDef* d=g_new(FlagsDef, 1);
g_assert($2->kind==GTK_TYPE_ENUM);
g_assert($2->kind==TYPE_ENUM);
d->flags = $4;
$$=DEF(d);
$$->type=$2;
@ -296,8 +296,8 @@ parent: /* empty */{
}
classdef: T_CLASS primtype parent docstring T_OPEN_B {
g_assert($2->kind==GTK_TYPE_OBJECT);
g_assert(!$3 || $3->kind==GTK_TYPE_OBJECT);
g_assert($2->kind==TYPE_OBJECT);
g_assert(!$3 || $3->kind==TYPE_OBJECT);
current_class=g_new(ObjectDef, 1);
} classbody T_CLOSE_B T_END {
Type t={FALSE, 1, TRUE, $2};
@ -305,7 +305,7 @@ classdef: T_CLASS primtype parent docstring T_OPEN_B {
t.is_const=TRUE;
current_class->self_type[1]=t;
current_class->parent = $3;
current_class->members = $7;
current_class->members = g_slist_reverse($7);
$$=DEF(current_class);
current_class=NULL;
$$->type = $2;