#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) return p_nil; d=(DataMember*)m; if(d->kind!=DATA_DIRECT) return p_nil; return p_fmt("\t~ ~;\n", p_type(&d->type), p_c_ident(m->name)); } PNode* p_object_body(ObjectDef* o){ return p_fmt("struct _~ {\n" "\t~ parent;\n" "~" "};\n", p_primtype(DEF(o)->type), p_primtype(o->parent), p_for(o->members, p_object_member, p_nil)); } PNode* p_object_decl(ObjectDef* o){ PrimType* n=DEF(o)->type; return p_fmt("typedef struct _~ ~;\n", p_primtype(n), p_primtype(n)); } PNode* p_class_member(Member* m){ ParamOptions o = {TRUE,FALSE,TRUE}; if(m->membertype == MEMBER_DATA){ DataMember* d=(DataMember*)m; if(d->kind != DATA_STATIC_VIRTUAL) return p_nil; else return p_fmt("\t~ ~;\n", p_type(&d->type), p_c_ident(m->name)); }else if (m->membertype == MEMBER_METHOD){ Method* d=(Method*)m; FunParams* p; PNode* parnode; if(d->kind==METH_STATIC || d->kind==METH_DIRECT) return p_nil; p=fparams("tp", &m->my_class->self_type[d->self_const], p_nil, p_nil, d->params); parnode=p_params(p, &o); fparams_free(p); return p_fmt("\t~ (*~) (~);\n", p_type(&d->ret_type), p_c_ident(m->name), parnode); }else return p_nil; } PNode* p_class_name(PrimType* o){ return p_fmt("~Class", p_primtype(o)); } PNode* p_impl_name(ObjectDef* o){ return p_fmt("~Impl", p_primtype(DEF(o)->type)); } PNode* p_class_body(ObjectDef* o){ return p_fmt("struct _~ {\n" "\t~ parent_class;\n" "~" "};\n", p_class_name(DEF(o)->type), p_class_name(o->parent), p_for(o->members, p_class_member, p_nil)); } PNode* p_class_decl(ObjectDef* o){ return p_fmt("typedef struct _~ ~;\n", p_class_name(DEF(o)->type), p_class_name(DEF(o)->type)); } PNode* p_real_varname(PrimType* t, PNode* name){ return p_fmt("~_real", p_varname(t, name)); } PNode* p_signal_handler_type(Method* s){ Member* m=MEMBER(s); return p_fmt("~Handler_~", p_primtype(DEF(m->my_class)->type), p_c_ident(m->name)); } void output_connector(PRoot* out, Method* m){ FunParams* par=fparams("t", &MEMBER(m)->my_class->self_type[m->self_const], p_self_name(MEMBER(m)), p_nil); output_func(out, "functions", &m->ret_type, p_varname(DEF(MEMBER(m)->my_class)->type, p_fmt("connect_~", p_c_ident(MEMBER(m)->name))), p_fmt("\n\t~ handler,\n\tgpointer user_data", p_signal_handler_type(m)), par, p_fmt("\t~gtk_signal_connect((GtkObject*)~,\n" "\t\t\"~\",\n" "\t\t(GtkSignalFunc)handler,\n" "\t\tuser_data);\n", m->ret_type.prim?p_str("return "):p_nil, p_self_name(MEMBER(m)), p_str(MEMBER(m)->name))); output_var_import(out, DEF(MEMBER(m)->my_class)->type, p_fmt("connect_~", p_c_ident(MEMBER(m)->name))); } PNode* p_param_marshtype(gpointer p){ Param* param=p; return p_fmt(",\n\t\t~", p_gtktype(¶m->type)); } void output_method(PRoot* out, Method* m){ PrimType* t=DEF(MEMBER(m)->my_class)->type; PNode* name=p_c_ident(MEMBER(m)->name); MethodKind k=m->kind; ParamOptions o={TRUE, TRUE, FALSE}; FunParams* par; PNode* dispatch; GSList* params; if(k == METH_STATIC) par = fparams("p", m->params); else par = fparams("tp", &MEMBER(m)->my_class->self_type[m->self_const], p_self_name(MEMBER(m)), p_nil, m->params); switch(k){ SignalType* sig; case METH_EMIT_PRE: case METH_EMIT_POST: case METH_EMIT_BOTH: sig=sig_type(m); output_var(out, NULL, p_str("guint"), p_signal_id(m)); o.names=FALSE; o.types=TRUE; pr_put(out, "source_sigtypes", sig); pr_put(out, "member_class_init", p_fmt("\t~ =\n" "\tgtk_signal_new(\"~\",\n" "\t\tGTK_RUN_~,\n" "\t\tobklass->type,\n" "\t\tGTK_SIGNAL_OFFSET (~, ~),\n" "\t\t~,\n" "\t\t~,\n" "\t\t~" "~);\n" "\tgtk_object_class_add_signals(obklass,\n" "\t\t&~,\n" "\t\t1);\n", p_signal_id(m), p_str(MEMBER(m)->name), p_str(m->kind==METH_EMIT_PRE ?"FIRST" :m->kind==METH_EMIT_POST ?"LAST" :"BOTH"), p_class_name(t), name, p_signal_demarshaller_name(sig), p_gtktype(&m->ret_type), p_prf("%d", g_slist_length(m->params)), p_for(m->params, p_param_marshtype, p_nil), p_signal_id(m))); pr_put(out, "functions", p_fmt("typedef ~ (*~)(" "~,\n" "\tgpointer);\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_sig_marshalling(m); break; case METH_STATIC: case METH_DIRECT:{ PNode* impl_name; o.names=TRUE; o.types=FALSE; impl_name=p_fmt("~_~", p_c_macro(t->name), p_c_macro(MEMBER(m)->name)); dispatch=p_fmt("#ifdef ~\n" "\t~~ (~);\n" "#else\n" "\tg_error(\"Not implemented: ~.~.~\");\n" "#endif\n", impl_name, m->ret_type.prim ? p_str("return ") : p_nil, impl_name, p_params(par, &o), p_str(t->module->package->name), p_str(t->name), p_str(MEMBER(m)->name)); break; } case METH_VIRTUAL: 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, p_params(par, &o)); break; } output_func (out, m->prot==METH_PUBLIC?"functions":"protected", &m->ret_type, p_varname(t, name), p_nil, par, dispatch); output_var_import(out, t, name); for(params = m->params; params; params = params->next) pr_put(out, m->prot==METH_PUBLIC?"func_depends":"prot_depends", ((Param*)(params->data))->type.prim->module); 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], self, p_nil, &m->type, name, p_nil); output_var_import(out, t, p_fmt("set_~", name)); output_func(out, "functions", NULL, p_varname(t, p_fmt("set_~", name)), p_nil, par, 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); } /* fall through */ case DATA_READONLY: pr_put(out, "func_depends", m->type.prim->module); par=fparams("t", &MEMBER(m)->my_class->self_type[TRUE], self, p_nil); output_var_import(out, t, name); output_func(out, "functions", &m->type, p_varname(t, name), p_nil, par, p_fmt("\treturn ~->~;\n", self, name)); fparams_free(par); /* fall through */ case DATA_PROTECTED: pr_put(out, "prot_depends", m->type.prim->module); } } void output_member(PRoot* out, Member* m){ switch(m->membertype){ case MEMBER_METHOD: output_method(out, (Method*)m); break; case MEMBER_DATA: output_data_member(out, (DataMember*)m); break; } } void output_member_cb(gpointer a, gpointer b){ output_member(b, a); } void output_class_macros(PRoot* out, ObjectDef* o){ PrimType* t=DEF(o)->type; pr_put(out, "type", p_fmt("#define ~(o) GTK_CHECK_TYPE(o, ~)\n" "#define ~(o) GTK_CHECK_CAST(o, ~, ~)\n", p_macro_name(t, "is", NULL), p_macro_name(t, "type", NULL), p_macro_name(t, NULL, NULL), p_macro_name(t, "type", NULL), p_primtype(t))); output_macro_import(out, t, "is", NULL); output_macro_import(out, t, NULL, NULL); } void output_object_type_init(PRoot* out, ObjectDef* o){ PrimType* t=DEF(o)->type; PNode* type_var=p_internal_varname(t, p_str("type")); output_func(out, "type", NULL, p_internal_varname(t, p_str("init_type")), p_nil, NULL, p_fmt("\tstatic GtkTypeInfo info = {\n" "\t\t\"~\",\n" "\t\tsizeof (~),\n" "\t\tsizeof (~),\n" "\t\t(GtkClassInitFunc) ~,\n" "\t\t(GtkObjectInitFunc) ~,\n" "\t\tNULL,\n" "\t\tNULL,\n" "\t\tNULL,\n" "\t};\n" "\tif (!~)\n" "\t\t~ = gtk_type_unique (~, &info);\n", p_primtype(t), p_primtype(t), p_class_name(t), p_varname(t, p_str("class_init")), p_varname(t, p_str("init")), type_var, type_var, p_macro_name(o->parent, "type", NULL), type_var)); } void output_object_init(PRoot* out, ObjectDef* o){ PrimType* t = DEF(o)->type; output_func(out, NULL, NULL, p_varname(t, p_str("init")), p_fmt("~ ~", p_type(&o->self_type[FALSE]), p_c_ident(t->name)), NULL, p_fmt("\t(void) ~;\n" "#ifdef ~_INIT\n" "\t~_INIT (~);\n" "#endif\n", p_c_ident(t->name), p_c_macro(t->name), p_c_macro(t->name), p_c_ident(t->name))); } void output_class_init(PRoot* out, ObjectDef* o){ PrimType* t = DEF(o)->type; output_func(out, NULL, NULL, p_varname(t, p_str("class_init")), p_fmt("~* klass", p_class_name(t)), NULL, p_fmt("\tGtkObjectClass* obklass = " "(GtkObjectClass*) klass;\n" "~" "\t(void) obklass;\n" "~" "#ifdef ~_CLASS_INIT\n" "\t~_CLASS_INIT (klass);\n" "#endif\n", p_col("class_init_head", NULL), p_col("member_class_init", NULL), p_c_macro(t->name), p_c_macro(t->name))); } void output_object(PRoot* out, Def* d){ ObjectDef* o = (ObjectDef*)d; pr_put(out, "func_depends", d->type->module); pr_put(out, "func_parent_depends", o->parent->module); pr_put(out, "prot_parent_depends", o->parent->module); pr_put(out, "source_prot_depends", d->type->module); pr_put(out, "import_depends", o->parent->module); output_object_type_init(out, o); output_class_init(out, o); output_object_init(out, o); pr_put(out, "protected", p_class_decl(o)); pr_put(out, "protected", p_class_body(o)); pr_put(out, "type", p_object_decl(o)); output_class_macros(out, o); pr_put(out, "protected", p_object_body(o)); g_slist_foreach(o->members, output_member_cb, out); }