From f633c7da4e59df581d8b4280d7aa85a43580253d Mon Sep 17 00:00:00 2001 From: Lauri Alanko Date: Sat, 21 Nov 1998 20:24:18 +0000 Subject: [PATCH] Added signal demarshallers. Currently they are generated for each module (= compilation unit) separately, which is bound to cause some code duplication.. --- tools/gcg/ChangeLog | 4 ++ tools/gcg/TODO | 1 - tools/gcg/ex/ostream.gc | 6 +- tools/gcg/ex/strtest.c | 12 ++++ tools/gcg/gcg.c | 8 ++- tools/gcg/marshall.c | 142 ++++++++++++++++++++++++++++++-------- tools/gcg/marshall.h | 4 ++ tools/gcg/output_object.c | 15 ++-- tools/gcg/pnode.c | 46 ++++-------- 9 files changed, 161 insertions(+), 77 deletions(-) diff --git a/tools/gcg/ChangeLog b/tools/gcg/ChangeLog index cdac77baa7..5b52220d8e 100644 --- a/tools/gcg/ChangeLog +++ b/tools/gcg/ChangeLog @@ -1,5 +1,9 @@ 1998-11-21 Lauri Alanko + * Added signal demarshallers. Currently they are generated for + each module (= compilation unit) separately, which is bound to + cause some code duplication.. + * Added import headers and some more example stuff. * It actually runs now, with a zillion caveats, but anyway.. diff --git a/tools/gcg/TODO b/tools/gcg/TODO index 2c3bef1cfb..880791d843 100644 --- a/tools/gcg/TODO +++ b/tools/gcg/TODO @@ -5,4 +5,3 @@ Not in any order: - Pretty formatted comments from doc strings - HTML doc output - IDL output -- Demarshallers diff --git a/tools/gcg/ex/ostream.gc b/tools/gcg/ex/ostream.gc index e31216572c..fbc85536be 100644 --- a/tools/gcg/ex/ostream.gc +++ b/tools/gcg/ex/ostream.gc @@ -6,7 +6,7 @@ import g; class Ostream { public virtual void putchar (char c); - public virtual void putstring (char* str); - public virtual void flush (); - public virtual void close (); + public pre-emit void putstring (char* str); + public pre-emit void flush (); + public pre-emit void close (); } diff --git a/tools/gcg/ex/strtest.c b/tools/gcg/ex/strtest.c index c15ad6a4fd..48cd2b7d7e 100644 --- a/tools/gcg/ex/strtest.c +++ b/tools/gcg/ex/strtest.c @@ -1,7 +1,19 @@ #include +void putstring_handler(Ostream* o, gchar* msg, gpointer data){ + gchar* s = data; + g_print("Putstring: %s (%p), \"%s\"..\n", s, o, msg); +} + +void close_handler(Ostream* o, gpointer data){ + gchar* s = data; + g_print("Closed: %s (%p)!\n", s, o); +} + int main(void){ Ostream* x = OSTREAM(file_ostream_open("foo")); + ostream_connect_putstring(putstring_handler, "foo", x); + ostream_connect_close(close_handler, "foo", x); ostream_putstring(x, "Whammo!\n"); ostream_close(x); return 0; diff --git a/tools/gcg/gcg.c b/tools/gcg/gcg.c index 1bb6f43708..eb1c484218 100644 --- a/tools/gcg/gcg.c +++ b/tools/gcg/gcg.c @@ -5,6 +5,7 @@ #include "parse.h" #include #include "output.h" +#include "marshall.h" #ifndef CPP #define CPP "cpp" @@ -123,11 +124,13 @@ int main(int argc, char* argv[]){ if(!f) g_error("Unable to open file %s: %s", source_name, strerror(errno)); - p_write(p_fmt("~~~" + p_write(p_fmt("~~~~~" "#include \"~\"\n", p_col("source_prot_depends", p_prot_include), p_col("source_head", NULL), + p_col("source_sigtypes", p_sigdemarsh_decl), p_col("source", NULL), + p_col("source_sigtypes", p_demarshaller), p_str(impl_name)), f, out); fclose(f); @@ -147,7 +150,8 @@ int main(int argc, char* argv[]){ out); open_out(p_prot_header, "prot", - p_fmt("~~~", + p_fmt("~~~~", + p_func_include(current_module), p_col("prot_parent_depends", p_prot_include), p_col("prot_depends", p_type_include), p_col("protected", NULL)), diff --git a/tools/gcg/marshall.c b/tools/gcg/marshall.c index 8d5a2bf420..09d7365370 100644 --- a/tools/gcg/marshall.c +++ b/tools/gcg/marshall.c @@ -3,6 +3,8 @@ #include "marshall.h" +static GHashTable* sigtype_hash; + typedef enum { MARSHALL_INT, MARSHALL_DOUBLE, @@ -14,6 +16,7 @@ typedef enum { struct _SignalType { Id package; + Id module; MarshallType rettype; GSList* argtypes; }; @@ -42,12 +45,18 @@ MarshallType marshalling_type(Type* t){ } } +/* Yes, this is hyperbly kludgetical */ SignalType* sig_type(Method* m){ - SignalType *t=g_new(SignalType, 1); + SignalType *t=g_new(SignalType, 1), *s; GSList* p=m->params, *a=NULL; + PNode* g; + gchar* f; t->package = DEF(MEMBER(m)->my_class)->type->module->package->name; + t->module = DEF(MEMBER(m)->my_class)->type->module->name; t->rettype = marshalling_type(&m->ret_type); + if(!sigtype_hash) + sigtype_hash = g_hash_table_new(g_str_hash, g_str_equal); while(p){ Param* param=p->data; MarshallType* t=g_new(MarshallType, 1); @@ -57,7 +66,19 @@ SignalType* sig_type(Method* m){ } a=g_slist_reverse(a); t->argtypes=a; - return t; + g = p_signal_demarshaller_name(t); + f = p_to_str(g, NULL); + p_unref(g); + s = g_hash_table_lookup(sigtype_hash, f); + if(!s){ + g_hash_table_insert(sigtype_hash, f, t); + return t; + } + else{ + sig_type_free(t); + g_free(f); + return s; + } } void sig_type_free(SignalType* t){ @@ -70,32 +91,52 @@ void sig_type_free(SignalType* t){ g_free(t); } -PNode* p_gtype_name(MarshallType t, gboolean abbr){ +typedef enum{ + GTKNAME, + ENCODING, + CTYPE +} MMap; + + +PNode* p_gtype_name(MarshallType t, MMap map){ static const struct GTypeName{ MarshallType type; - Id name; - Id aname; + Id gtkname; + Id encoding; + Id ctype; }names[]={ - {MARSHALL_POINTER, "POINTER", "P"}, - {MARSHALL_INT, "INT", "I"}, - {MARSHALL_DOUBLE, "DOUBLE", "D"}, - {MARSHALL_LONG, "LONG", "L"}, - {MARSHALL_VOID, "NONE", "0"}, + {MARSHALL_POINTER, "POINTER", "P", "gpointer"}, + {MARSHALL_INT, "INT", "I", "gint"}, + {MARSHALL_DOUBLE, "DOUBLE", "D", "gdouble"}, + {MARSHALL_LONG, "LONG", "L", "glong"}, + {MARSHALL_VOID, "NONE", "0", "void"}, }; gint i; for(i=0;i<(gint)(sizeof(names)/sizeof(names[0]));i++) - if(names[i].type==t) - return p_str(abbr - ?names[i].aname - :names[i].name); + if(names[i].type==t){ + Id id; + switch(map){ + case GTKNAME: + id = names[i].gtkname; + break; + case ENCODING: + id = names[i].encoding; + break; + case CTYPE: + id = names[i].ctype; + break; + } + return p_str(id); + } + g_assert_not_reached(); return NULL; } PNode* p_gtabbr(gpointer p){ MarshallType* t=p; - return p_gtype_name(*t, TRUE); + return p_gtype_name(*t, ENCODING); } @@ -136,11 +177,20 @@ PNode* p_gtktype(Type* t){ PNode* p_signal_func_name(SignalType* t, PNode* basename){ - return p_fmt("_~_~_~_~", +#if 1 + return p_fmt("_~_~_~_~~", + p_c_ident(t->package), + p_c_ident(t->module), + basename, + p_gtype_name(t->rettype, ENCODING), + p_for(t->argtypes, p_gtabbr, p_nil)); +#else + return p_fmt("_~_~_~~", p_c_ident(t->package), basename, - p_gtype_name(t->rettype, TRUE), + p_gtype_name(t->rettype, ENCODING), p_for(t->argtypes, p_gtabbr, p_nil)); +#endif } PNode* p_signal_marshaller_name(SignalType* t){ @@ -152,10 +202,18 @@ PNode* p_signal_demarshaller_name(SignalType* t){ } PNode* p_handler_type(SignalType* t){ - return p_fmt("_~Handler_~_~", +#if 1 + return p_fmt("_~~Handler_~~", p_str(t->package), - p_gtype_name(t->rettype, TRUE), + p_str(t->module), + p_gtype_name(t->rettype, ENCODING), p_for(t->argtypes, p_gtabbr, p_nil)); +#else + return p_fmt("_~Handler_~~", + p_str(t->package), + p_gtype_name(t->rettype, ENCODING), + p_for(t->argtypes, p_gtabbr, p_nil)); +#endif } PNode* p_signal_id(Method* s){ @@ -179,7 +237,7 @@ PNode* p_arg_marsh(gpointer p, gpointer d){ "\tGTK_VALUE_~(args[~]) = ~;\n", /* p_prf("%d", *idx), p_gtktype(&par->type), */ - p_gtype_name(marshalling_type(&par->type), FALSE), + p_gtype_name(marshalling_type(&par->type), GTKNAME), p_prf("%d", *idx), p_c_ident(par->name)); } @@ -217,18 +275,44 @@ PNode* p_sig_marshalling(Method* m){ PNode* p_arg_demarsh(gpointer p, gpointer d){ MarshallType* t=p; - ArgMarshData* data=d; - return p_fmt("\t\tGTK_VALUE_~(~[~]),\n", + gint* data=d; + (*data)++; + return p_fmt("\t\tGTK_VALUE_~(args[~]),\n", p_gtype_name(*t, FALSE), - data->args, - p_fmt("%d", data->idx++)); + p_prf("%d", *data)); +} + +PNode* p_sig_arg_ctype(MarshallType* t){ + return p_fmt(", ~", p_gtype_name(*t, CTYPE)); +} + +PNode* p_sigdemarsh_decl(SignalType* t){ +#if 1 + return p_fmt("static void ~ (GtkObject*, GtkSignalFunc, " + "gpointer, GtkArg*);\n" + "typedef ~ (*~)(GtkObject*~, gpointer);\n", + p_signal_demarshaller_name(t), + p_gtype_name(t->rettype, CTYPE), + p_handler_type(t), + p_for(t->argtypes, p_sig_arg_ctype, p_nil)); +#else + return p_fmt("extern void ~ (GtkObject*, GtkSignalFunc, " + "gpointer, GtkArg*);\n", + p_signal_demarshaller_name(t)); +#endif } PNode* p_demarshaller(SignalType* t){ - gint idx=0; - - - return p_fmt("~~", + gint idx=-1; + return p_fmt("static void ~ (\n" + "\tGtkObject* object,\n" + "\tGtkSignalFunc func,\n" + "\tgpointer user_data,\n" + "\tGtkArg* args){\n" + "\t(void)args;\n" + "~~" + "}\n", + p_signal_demarshaller_name(t), (t->rettype==TYPE_NONE) ? p_fmt("\t*(GTK_RETLOC_~(args[~])) =\n", p_gtype_name(t->rettype, FALSE), @@ -240,5 +324,3 @@ PNode* p_demarshaller(SignalType* t){ p_cast(p_handler_type(t), p_str("func")), p_for(t->argtypes, p_arg_demarsh, &idx))); } - - diff --git a/tools/gcg/marshall.h b/tools/gcg/marshall.h index 4708d84c68..94760ec73d 100644 --- a/tools/gcg/marshall.h +++ b/tools/gcg/marshall.h @@ -14,6 +14,10 @@ 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); +PNode* p_sigdemarsh_decl(SignalType* t); +PNode* p_demarshaller(SignalType* t); + + #endif diff --git a/tools/gcg/output_object.c b/tools/gcg/output_object.c index 50da2b3a01..b4b2a2e83a 100644 --- a/tools/gcg/output_object.c +++ b/tools/gcg/output_object.c @@ -128,7 +128,7 @@ void output_connector(PRoot* out, Method* m){ m->ret_type.prim?p_str("return "):p_nil, p_self_name(MEMBER(m)), p_str(MEMBER(m)->name))); - output_var_import(out, m->ret_type.prim, + output_var_import(out, DEF(MEMBER(m)->my_class)->type, p_fmt("connect_~", p_c_ident(MEMBER(m)->name))); } @@ -168,10 +168,7 @@ void output_method(PRoot* out, Method* m){ p_signal_id(m)); o.names=FALSE; o.types=TRUE; - pr_put(out, "class_init_head", - p_fmt("\textern void ~ (GtkObject*, GtkSignalFunc, " - "gpointer, GtkArg*);\n", - p_signal_demarshaller_name(sig))); + pr_put(out, "source_sigtypes", sig); pr_put(out, "member_class_init", p_fmt("\t~ =\n" "\tgtk_signal_new(\"~\",\n" @@ -184,8 +181,7 @@ void output_method(PRoot* out, Method* m){ "~);\n" "\tgtk_object_class_add_signals(obklass,\n" "\t\t&~,\n" - "\t\t1);\n" - "\t}\n", + "\t\t1);\n", p_signal_id(m), p_str(MEMBER(m)->name), p_str(m->kind==METH_EMIT_PRE @@ -415,7 +411,7 @@ void output_object_init(PRoot* out, ObjectDef* o){ void output_class_init(PRoot* out, ObjectDef* o){ pr_put(out, "source_head", - p_fmt("static inline void ~ (~* klass);\n", + p_fmt("static void ~ (~* klass);\n", p_varname(DEF(o)->type, p_str("class_init_real")), p_class_name(DEF(o)->type))); output_func(out, NULL, @@ -426,8 +422,8 @@ void output_class_init(PRoot* out, ObjectDef* o){ NULL, p_fmt("\tGtkObjectClass* obklass = " "(GtkObjectClass*) klass;\n" - "\t(void) obklass;\n" "~" + "\t(void) obklass;\n" "~" "\t~ (klass);\n", p_col("class_init_head", NULL), @@ -439,7 +435,6 @@ 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_depends", d->type->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); diff --git a/tools/gcg/pnode.c b/tools/gcg/pnode.c index fa6a1c813e..b5f8604ff9 100644 --- a/tools/gcg/pnode.c +++ b/tools/gcg/pnode.c @@ -114,23 +114,6 @@ void p_unref(PNode* node){ g_mem_chunk_free(p_node_chunk, node); } -typedef struct{ - FILE* f; - PRoot* p; - PNode* n; -} PCollect; - -void cb_pwrite(gpointer key, gpointer value, gpointer data){ - PCollect* c = data; - PNodeCreateFunc func = c->n->u.c.func; - (void)key; - if(func) - p_write(func(value), c->f, c->p); - else - p_write(value, c->f, c->p); -} - - void p_write(PNode* node, FILE* f, PRoot* r){ g_assert(f); BE_NODE(node); @@ -150,14 +133,17 @@ void p_write(PNode* node, FILE* f, PRoot* r){ break; case NODE_COLLECT: if(r){ - GHashTable* h = g_datalist_id_get_data(&r->data, - node->u.c.tag); - PCollect c; - c.f = f; - c.p = r; - c.n = node; - if(h) - g_hash_table_foreach(h, cb_pwrite, &c); + GList* l = g_datalist_id_get_data(&r->data, + node->u.c.tag); + l = g_list_last(l); + + if(node->u.c.func) + for(; l; l = l->prev) + p_write(node->u.c.func(l->data), + f, r); + else + for(; l; l = l->prev) + p_write(l->data, f, r); } break; } @@ -297,13 +283,11 @@ PRoot* pr_new(void){ } */ void pr_put(PRoot* pr, const gchar* tag, gpointer datum){ - GHashTable* h = g_datalist_get_data(&pr->data, tag); - if(!h){ - h = g_hash_table_new(NULL, NULL); - g_datalist_set_data(&pr->data, tag, h); - } + GList* l = g_datalist_get_data(&pr->data, tag); - g_hash_table_insert(h, datum, datum); + if(!g_list_find(l, datum)) + g_datalist_set_data(&pr->data, tag, + g_list_prepend(l, datum)); }