diff --git a/tools/gcg/ChangeLog b/tools/gcg/ChangeLog index e8ecf1dbd4..eeb29e4efc 100644 --- a/tools/gcg/ChangeLog +++ b/tools/gcg/ChangeLog @@ -1,3 +1,8 @@ +1998-11-14 Lauri Alanko + + * Changed lotsa internal stuff. Started work on signal wrappers + and marshallers. + 1998-10-24 Lauri Alanko * Redid the backend. It takes more time and memory now, but should diff --git a/tools/gcg/Makefile.am b/tools/gcg/Makefile.am index 3b61e24d81..87658449df 100644 --- a/tools/gcg/Makefile.am +++ b/tools/gcg/Makefile.am @@ -31,6 +31,8 @@ gcg_SOURCES = \ output_enum.c \ output_flags.c \ output_object.c \ + fp.c \ + marshall.c \ parser.h gcg_DEPENDS = parser.h diff --git a/tools/gcg/db.c b/tools/gcg/db.c index 834247125b..8729b83924 100644 --- a/tools/gcg/db.c +++ b/tools/gcg/db.c @@ -1,25 +1,72 @@ #include "gcg.h" -void put_decl(PrimType* t){ - g_hash_table_insert(decl_hash, &t->name, t); +static GHashTable* module_hash; + +void init_db(void){ + module_hash=g_hash_table_new(NULL, NULL); +} + +PrimType* get_type(Id modname, Id name){ + Module* m = get_mod(modname); + PrimType* p = g_hash_table_lookup(m->decl_hash, name); + if(!p){ + p=g_new(PrimType, 1); + p->module=m; + p->name=name; + p->kind=GTK_TYPE_INVALID; + p->decl_header=NULL; + p->def_header=NULL; + p->definition=NULL; + g_hash_table_insert(m->decl_hash, name, p); + } + return p; } void put_def(Def* d){ - g_hash_table_insert(def_hash, &d->type->name, d); + PrimType* t=d->type; + g_assert(t); + t->definition=d; } -Def* get_def(Id module, Id type){ - TypeName n; - n.module=module; - n.type=type; - return g_hash_table_lookup(def_hash, &n); +Def* get_def(Id modname, Id type){ + PrimType* t=get_type(modname, type); + g_assert(t); + return t->definition; } -PrimType* get_decl(Id module, Id type){ - TypeName n; - n.module=module; - n.type=type; - return g_hash_table_lookup(decl_hash, &n); +Module* get_mod(Id modname){ + Module* m=g_hash_table_lookup(module_hash, modname); + if(!m){ + m=g_new(Module, 1); + m->name=modname; + m->decl_hash=g_hash_table_new(NULL, NULL); + m->common_header=NULL; + g_hash_table_insert(module_hash, modname, m); + } + return m; } +typedef struct{ + DefFunc f; + gpointer user_data; +}DFEdata; + +void dfe_bar(gpointer key, gpointer p, gpointer foo){ + PrimType* t=p; + DFEdata* d=foo; + if(t->definition) + (d->f)(t->definition, d->user_data); +} + + +void dfe_foo(gpointer key, gpointer p, gpointer dfed){ + Module* m=p; + g_hash_table_foreach(m->decl_hash, dfe_bar, dfed); +} + +void foreach_def(DefFunc f, gpointer user_data){ + DFEdata d={f,user_data}; + g_hash_table_foreach(module_hash, dfe_foo, &d); +}; + diff --git a/tools/gcg/fp.c b/tools/gcg/fp.c new file mode 100644 index 0000000000..22eef75291 --- /dev/null +++ b/tools/gcg/fp.c @@ -0,0 +1,63 @@ +#include "output.h" + + +FunParams* fparams(const gchar* fmt, ...){ + FunParams* first; + FunParams** last=&first; + gint i; + va_list args; + + va_start(args, fmt); + for(i=0;fmt[i];i++) switch(fmt[i]){ + FunParams* f; + GSList* l; + case 'p': + l=va_arg(args, GSList*); + while(l){ + Param* p=l->data; + f=g_new(FunParams, 1); + f->type=p->type; + f->name=p_c_ident(p->name); + f->doc=p_nil; + *last=f; + last=&f->next; + l=l->next; + } + break; + case 't': + f=g_new(FunParams, 1); + f->type=*va_arg(args, Type*); + f->name=va_arg(args, PNode*); + p_ref(f->name); + f->doc=va_arg(args, PNode*); + p_ref(f->doc); + *last=f; + last=&f->next; + break; + case 's': + f=g_new(FunParams, 1); + f->type.prim=va_arg(args, PrimType*); + f->type.indirection=va_arg(args, gint); + f->type.notnull=va_arg(args, gboolean); + f->name=va_arg(args, PNode*); + p_ref(f->name); + f->doc=va_arg(args, PNode*); + p_ref(f->doc); + *last=f; + last=&f->next; + break; + } + *last=NULL; + return first; +} + +void fparams_free(FunParams* f){ + while(f){ + FunParams* n=f->next; + p_unref(f->name); + p_unref(f->doc); + g_free(f); + f=n; + } +} + diff --git a/tools/gcg/gcg.c b/tools/gcg/gcg.c index 4f6ad54d7d..ed2f82368a 100644 --- a/tools/gcg/gcg.c +++ b/tools/gcg/gcg.c @@ -5,13 +5,6 @@ #include #include "output.h" -GHashTable* decl_hash; -GHashTable* def_hash; -Id current_module; -Method* current_method; -ObjectDef* current_class; -Id current_header; -GSList* imports; Type* type_gtk_type; Id func_hdr_name; @@ -54,30 +47,21 @@ void get_options(int argc, char* argv[]){ }while(x!=EOF); } - -guint type_name_hash(gconstpointer c){ - const TypeName* t=c; - return g_str_hash(t->module) ^ g_str_hash(t->type); -} - -gboolean type_name_cmp(gconstpointer a, gconstpointer b){ - const TypeName *t1=a, *t2=b; - return (t1->type == t2->type) && (t1->module == t2->module); -} - -void output_cb(gpointer typename, gpointer def, gpointer ctx){ - (void)typename; /* Shut off warnings */ - output_def(ctx, def); +void output_cb(Def* def, gpointer out){ + output_def(out, def); } int main(int argc, char* argv[]){ /* target=stdout;*/ - OutCtx ctx; + PRoot* out=pr_new(); + const gchar* tag_type="type"; + const gchar* tag_source="source"; + const gchar* tag_source_head="source_head"; + const gchar* tag_functions="functions"; + const gchar* tag_protected="protected"; FILE* f; - - decl_hash=g_hash_table_new(type_name_hash, type_name_cmp); - def_hash=g_hash_table_new(type_name_hash, type_name_cmp); + init_db(); yydebug=0; get_options(argc, argv); yyin=fopen(argv[optind], "r"); @@ -87,24 +71,19 @@ int main(int argc, char* argv[]){ type_gtk_type->is_const=FALSE; type_gtk_type->indirection=0; type_gtk_type->notnull=FALSE; - type_gtk_type->prim=get_decl(GET_ID("Gtk"), GET_ID("Type")); + type_gtk_type->prim=get_type(GET_ID("Gtk"), GET_ID("Type")); g_assert(type_gtk_type->prim); - ctx.type_hdr=pr_new(); - ctx.func_hdr=pr_new(); - ctx.prot_hdr=pr_new(); - ctx.pvt_hdr=pr_new(); - ctx.src=pr_new(); - g_hash_table_foreach(def_hash, output_cb, &ctx); + foreach_def(output_cb, out); f=fopen(type_hdr_name, "w+"); - pr_write(ctx.type_hdr, f); + pr_write(out, f, &tag_type, 1); f=fopen(source_name, "w+"); - pr_write(ctx.pvt_hdr, f); - pr_write(ctx.src, f); + pr_write(out, f, &tag_source_head, 1); + pr_write(out, f, &tag_source, 1); f=fopen(func_hdr_name, "w+"); - pr_write(ctx.func_hdr, f); + pr_write(out, f, &tag_functions, 1); f=fopen(prot_hdr_name, "w+"); - pr_write(ctx.prot_hdr, f); + pr_write(out, f, &tag_protected, 1); return 0; } diff --git a/tools/gcg/gcg.h b/tools/gcg/gcg.h index b1b48321eb..6cfabab96d 100644 --- a/tools/gcg/gcg.h +++ b/tools/gcg/gcg.h @@ -12,7 +12,6 @@ typedef const gchar* Id; typedef const gchar* Header; typedef struct _Member Member; -typedef struct _TypeName TypeName; typedef struct _PrimType PrimType; typedef struct _Type Type; typedef struct _ObjectDef ObjectDef; @@ -24,17 +23,22 @@ typedef struct _Method Method; typedef struct _MemberClass MemberClass; typedef struct _DefClass DefClass; typedef struct _Param Param; +typedef struct _Module Module; -struct _TypeName { - Id module; - Id type; + +struct _Module { + Id name; + Id common_header; + GHashTable* decl_hash; }; struct _PrimType { - TypeName name; + Module* module; + Id name; GtkFundamentalType kind; Id decl_header; Id def_header; + Def* definition; }; struct _Type { @@ -59,6 +63,7 @@ extern DefClass enum_class; struct _EnumDef { Def def; + PrimType* parent; GSList* alternatives; /* list of Id */ }; @@ -66,6 +71,7 @@ extern DefClass flags_class; struct _FlagsDef { Def def; + PrimType* parent; /* flags to extend */ GSList* flags; /* list of Id */ }; @@ -79,16 +85,10 @@ struct _ObjectDef { }; typedef enum { - KIND_DIRECT, - KIND_ABSTRACT, - KIND_STATIC -} MemberKind; - -typedef enum { - VIS_PUBLIC, - VIS_PROTECTED, + METH_PUBLIC, + METH_PROTECTED, VIS_PRIVATE -} Visibility; +} MethProtection; typedef enum { DATA_READWRITE, @@ -105,13 +105,25 @@ typedef enum _EmitDef{ typedef enum _MemberType{ MEMBER_DATA, MEMBER_METHOD, - MEMBER_SIGNAL } MemberType; +typedef enum _DataMemberKind{ + DATA_STATIC, + DATA_DIRECT, + DATA_STATIC_VIRTUAL +} DataMemberKind; + +typedef enum _MethodKind{ + METH_STATIC, + METH_DIRECT, + METH_VIRTUAL, + METH_EMIT_PRE, + METH_EMIT_POST, + METH_EMIT_BOTH +} MethodKind; struct _Member{ MemberType membertype; - MemberKind kind; ObjectDef* my_class; Id name; GString* doc; @@ -121,19 +133,20 @@ struct _Member{ struct _DataMember { Member member; + DataMemberKind kind; DataProtection prot; Type type; }; struct _Method { Member member; - Visibility prot; + MethodKind kind; + MethProtection prot; GSList* params; /* list of Param* */ gboolean self_const; Type ret_type; }; - struct _Param { Id name; Method* method; @@ -141,22 +154,21 @@ struct _Param { Type type; }; +typedef void (*DefFunc)(Def* def, gpointer user_data); +void init_db(void); void put_decl(PrimType* t); void put_def(Def* d); -PrimType* get_decl(Id module, Id type); +PrimType* get_type(Id module, Id type); Def* get_def(Id module, Id type); +Module* get_mod(Id module); +void foreach_def(DefFunc f, gpointer user_data); + + + extern Type* type_gtk_type; -extern Id current_header; -extern Id current_module; -extern ObjectDef* current_class; -extern GSList* imports; -extern Method* current_method; - -extern GHashTable* def_hash; -extern GHashTable* decl_hash; diff --git a/tools/gcg/gimpimage.def b/tools/gcg/gimpimage.def index 5001ea6536..7027a00c10 100644 --- a/tools/gcg/gimpimage.def +++ b/tools/gcg/gimpimage.def @@ -1,56 +1,51 @@ // this is just a simple test input file module g { - header { - @int int; - }; - + @int int; }; module Gtk { - header { - @int Type; - }; + @int Type; }; module Gimp{ - header { class Object; - }; - header { class Layer; - }; - - header { class Drawable; - }; - - header { class Image; enum ImageType; enum ChannelType; enum BaseType; - }; - enum ImageType{ - rgb, rgba, gray, graya, indexed, indexeda - }; - enum ChannelType{ - red, green, blue, gray, indexed, auxillary - }; - enum BaseType{ - rgb, gray, indexed - }; - - class Image : Object{ - read-only g.int width; - read-only g.int height; - g.int num-cols; - read-only BaseType base-type; - Layer* active-layer; - Layer* floating-sel; - - public static Image* new(g.int width, - g.int height, - BaseType base-type); - }; +}; + + +module Gimp; + +enum ImageType{ + rgb, rgba, gray, graya, indexed, indexeda +}; +enum ChannelType{ + red, green, blue, gray, indexed, auxillary +}; +enum BaseType{ + rgb, gray, indexed +}; + +class Image : Object{ + read-only g.int width; + read-only g.int height; + g.int num-cols; + read-only BaseType base-type; + read-write g.int foobar; + Layer* active-layer; + Layer* floating-sel; + public static Image* new(g.int width, + g.int height, + BaseType base-type); + public void add-layer(Layer* l); + 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); }; diff --git a/tools/gcg/lexer.l b/tools/gcg/lexer.l index 9b4444e297..2c2705e9aa 100644 --- a/tools/gcg/lexer.l +++ b/tools/gcg/lexer.l @@ -10,6 +10,7 @@ header <[[:alnum:]/.]+> ws [ \n\t\r] comment \/\/[^\n]*\n string \"(([^\"]*)|\\\"|\\\\)*\" +preproc ^#.*\n %% @@ -34,7 +35,7 @@ opaque return T_OPAQUE; void return T_VOID; enum return T_ENUM; -lags return T_FLAGS; +flags return T_FLAGS; @int return T_INT; real return T_DOUBLE; boxed return T_BOXED; @@ -51,6 +52,9 @@ boxed return T_BOXED; {ws} { } +{preproc} { +} + {header} { yylval.id=g_quark_to_string(g_quark_from_string(yytext)); return T_HEADERNAME; diff --git a/tools/gcg/marshall.c b/tools/gcg/marshall.c new file mode 100644 index 0000000000..a16c6782ec --- /dev/null +++ b/tools/gcg/marshall.c @@ -0,0 +1,144 @@ +#include "gcg.h" +#include "output.h" + +typedef struct { + Id package; + GtkType rettype; + GSList* argtypes; +} SignalType; + +PNode* p_gtype_name(GtkType t, gboolean abbr){ + static const struct GTypeName{ + GtkType 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"}, + }; + gint i; + + for(i=0;iprim) + 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_signal_func_name(Method* s, PNode* basename){ + SignalType t; + GSList* p=s->params, *a=NULL; + PNode* ret; + t.package = DEF(MEMBER(s)->my_class)->type->module->name; + t.rettype = marshalling_type(&s->ret_type); + while(p){ + Param* param=p->data; + GtkType* t=g_new(GtkType, 1); + *t=marshalling_type(¶m->type); + a=g_slist_prepend(a, t); + p=p->next; + } + a=g_slist_reverse(a); + t.argtypes=a; + ret=p_fmt("_~_~_~_~", + p_c_ident(t.package), + basename, + p_gtype_name(t.rettype, TRUE), + p_for(t.argtypes, p_gtabbr, p_nil)); + while(a){ + g_free(a->data); + a=a->next; + } + g_slist_free(a); + return ret; +} + +PNode* p_signal_marshaller_name(Method* m){ + return p_signal_func_name(m, p_str("marshall")); +} + +PNode* p_signal_demarshaller_name(Method* m){ + return p_signal_func_name(m, p_str("demarshall")); +} + +PNode* p_handler_type(SignalType* t){ + return p_fmt("_~Handler_~_~", + p_str(t->package), + p_gtype_name(t->rettype, TRUE), + p_for(t->argtypes, p_gtabbr, p_nil)); +} + + +typedef struct{ + PNode* args; + gint idx; +}ArgMarshData; + + +PNode* p_arg_marsh(gpointer p, gpointer d){ + GtkType* t=p; + ArgMarshData* data=d; + return p_fmt("\t\tGTK_VALUE_~(~[~]),\n", + p_gtype_name(*t, FALSE), + data->args, + p_fmt("%d", data->idx++)); +} + +PNode* p_demarshaller(SignalType* t){ + gint idx=0; + + + return p_lst((t->rettype==GTK_TYPE_NONE) + ? p_fmt("\t*(GTK_RETLOC_~(args[~])) =\n", + p_gtype_name(t->rettype, FALSE), + p_prf("%d", g_slist_length(t->argtypes))) + : p_nil, + p_fmt("\t~(object,\n" + "~" + "\tuser_data);\n", + p_cast(p_handler_type(t), p_str("func")), + p_for(t->argtypes, p_arg_marsh, &idx)), + p_nil); +} + + diff --git a/tools/gcg/marshall.h b/tools/gcg/marshall.h new file mode 100644 index 0000000000..db2afe037d --- /dev/null +++ b/tools/gcg/marshall.h @@ -0,0 +1,13 @@ +#ifndef __MARSHALL_H__ +#define __MARSHALL_H__ + +#include "gcg.h" +#include "pnode.h" +PNode* p_gtype_name(GtkType t, gboolean abbr); +PNode* p_gtabbr(gpointer p); +GtkType marshalling_type(Type* t); +PNode* p_signal_marshaller_name(Method* s); +PNode* p_signal_demarshaller_name(Method* s); +PNode* p_arg_marsh(gpointer p, gpointer d); + +#endif diff --git a/tools/gcg/output.c b/tools/gcg/output.c index 18a3f0b9aa..f0ab6482dc 100644 --- a/tools/gcg/output.c +++ b/tools/gcg/output.c @@ -38,35 +38,43 @@ PNode* p_c_macro(Id id){ return n; } -PNode* p_param(Param* p, ParamOptions* opt){ +PNode* p_param(FunParams* p, ParamOptions* opt){ return p_lst(opt->first ? p_nil : p_str(", "), opt->types ? p_type(&p->type) : p_nil, opt->types && opt->names ? p_str(" ") : p_nil, - opt->names ? p_c_ident(p->name) : p_nil, + opt->names ? p->name : p_nil, NULL); } -PNode* p_params(GSList* args, ParamOptions* opt){ +PNode* p_params(FunParams* args, ParamOptions* opt){ ParamOptions o=*opt; - - return (args - ? (o.first - ? p_lst(p_param(args->data, opt), - (o.first=FALSE, - p_for(args->next, p_param, &o)), - NULL) - : p_for(args, p_param, &o)) - : (o.first - ? p_str("void") - : p_nil)); + PNode* n=p_nil; + while(args){ + n=p_lst(n, p_param(args, &o), NULL); + args=args->next; + o.first=FALSE; + } + if(n==p_nil) + if(opt->first) + return p_str("void"); + else + return p_nil; + else + return n; } PNode* p_primtype(PrimType* t){ - return p_lst(p_str(t->name.module), - p_str(t->name.type), + return p_lst(p_str(t->module->name), + p_str(t->name), NULL); } +PNode* p_cast(PNode* force_type, PNode* expression){ + return p_fmt("((~)~)", + force_type, + expression); +} + PNode* p_type(Type* t){ if(t && t->prim){ PNode* node; @@ -88,170 +96,153 @@ PNode* p_self_type(ObjectDef* o, PBool const_self){ p_primtype(DEF(o)->type)); } -PNode* p_varname(PrimType* t, Id name){ +PNode* p_varname(PrimType* t, PNode* name){ return p_fmt("~_~_~", - p_c_ident(t->name.module), - p_c_ident(t->name.type), - p_c_ident(name)); + p_c_ident(t->module->name), + p_c_ident(t->name), + name); } -PNode* p_internal_varname(PrimType* t, Id name){ +PNode* p_internal_varname(PrimType* t, PNode* name){ return p_fmt("_~", p_varname(t, name)); } -PNode* p_prototype(PrimType* type, Id funcname, - GSList* params, Type* rettype, gboolean internal){ - ParamOptions o={TRUE, TRUE, TRUE}; - return p_fmt("~ ~ (~)", - p_type(rettype), - (internal?p_internal_varname:p_varname)(type, funcname), - p_params(params, &o)); -} -PNode* p_type_guard(Param* p){ - Type* t=&p->type; + +PNode* p_type_guard(Type* t, PNode* var){ + PrimType* p=t->prim; + /* + if(t->notnull && (p->indirection>1 || p->kind!=GTK_TYPE_OBJECT)) + return p_fmt("\tg_assert (~);\n", var); + else if(p->kind==GTK_TYPE_OBJECT) + return p_fmt("\tg_assert (~ + kind != + */ return p_lst ((t->indirection && t->notnull - ? p_fmt("\tg_assert (%s);\n", p->name) + ? p_fmt("\tg_assert (~);\n", var) : p_nil), - ((t->indirection==1 && t->prim->kind == GTK_TYPE_OBJECT) + ((t->indirection==1 && p->kind == GTK_TYPE_OBJECT) ? (t->notnull - ? p_fmt("\tg_assert (%3(%1));\n", - p_macro_name(t->prim, "IS", NULL), - p_c_ident(p->name)) - : p_fmt("\tg_assert (!%1 || %3(%s));\n", - p_c_ident(p->name), - p_macro_name(t->prim, "IS", NULL), - p_c_ident(p->name))) + ? p_fmt("\tg_assert (~(~));\n", + p_macro_name(p, "IS", NULL), + var) + : p_fmt("\tg_assert (!~ || ~(~));\n", + var, + p_macro_name(p, "IS", NULL), + var)) : (t->indirection==0 - ? ((t->prim->kind == GTK_TYPE_ENUM) - ? p_fmt("\tg_assert (%1 <= %3);\n", - p_c_ident(p->name), - p_macro_name(t->prim, NULL, "LAST")) - : ((t->prim->kind == GTK_TYPE_FLAGS) - ? p_fmt("\tg_assert ((%s << 1) < %3);\n", - p_c_ident(p->name), - p_macro_name(t->prim, NULL, "LAST")) - : p_nil)) - : p_nil)), + ? ((p->kind == GTK_TYPE_ENUM) + ? p_fmt("\tg_assert (~ <= ~);\n", + var, + p_macro_name(p, NULL, "LAST")) + : ((p->kind == GTK_TYPE_FLAGS) + ? p_fmt("\tg_assert ((~ << 1) < ~);\n", + var, + p_macro_name(p, NULL, "LAST")) + : p_nil)) + : p_nil)), NULL); } - -void output_func(OutCtx* ctx, - PrimType* type, Id funcname, GSList* params, Type* rettype, - Visibility scope, ObjectDef* self, gboolean self_const, - gboolean internal, PNode* body){ - GSList l; - Param p; - PRoot* root; - - if(self){ - p.type.prim=DEF(self)->type; - p.type.indirection=1; - p.type.is_const=self_const; - p.type.notnull=TRUE; - p.name="self"; - l.data=&p; - l.next=params; - params=&l; - } - switch(scope){ - case VIS_PUBLIC: - root = ctx->func_hdr; - break; - case VIS_PROTECTED: - root = ctx->prot_hdr; - break; - case VIS_PRIVATE: - root = ctx->pvt_hdr; - break; +PNode* p_type_guards(FunParams* args){ + PNode* p=p_nil; + while(args){ + p=p_lst(p, p_type_guard(&args->type, args->name), NULL); + args=args->next; } - - pr_add(root, p_fmt("~~;\n", - scope==VIS_PRIVATE - ? p_str("static ") - : p_nil, - p_prototype(type, funcname, params, - rettype, internal))); - pr_add(ctx->src, p_fmt("~~{\n" - "~" - "~" - "}\n\n", - scope != VIS_PRIVATE - ? p_nil - : p_str("static "), - p_prototype(type, funcname, params, - rettype, internal), - p_for(params, p_type_guard, p_nil), - body)); + return p; +} + +PNode* p_prototype(Type* rettype, PNode* name, + PNode* args1, + FunParams* args2){ + ParamOptions o={(!args1 || args1==p_nil), TRUE, TRUE}; + return p_fmt("~ ~ (~~)", + p_type(rettype), + name, + args1, + p_params(args2, &o)); +} + +void output_func(PRoot* out, + Id tag, + Type* rettype, + PNode* name, + PNode* args1, + FunParams* args2, + PNode* body){ + pr_add(out, tag ? tag : "source_head", + p_fmt("~~;\n", + tag + ? p_nil + : p_str("static "), + p_prototype(rettype, name, args1, args2))); + pr_add(out, "source", + p_fmt("~~{\n" + "~" + "~" + "}\n\n", + tag + ? p_nil + : p_str("static "), + p_prototype(rettype, name, args1, args2), + p_type_guards(args2), + body)); } PNode* p_macro_name(PrimType* t, Id mid, Id post){ return p_fmt("~~_~~", - p_c_macro(t->name.module), + p_c_macro(t->module->name), mid ? p_lst(p_str("_"), p_c_macro(mid), NULL) : p_nil, - p_c_macro(t->name.type), + p_c_macro(t->name), post ? p_lst(p_str("_"), p_c_macro(post), NULL) : p_nil); } -void output_var(OutCtx* ctx, Def* d, Type* t, Id varname, Visibility scope, - gboolean internal){ - PRoot* root; - switch(scope){ - case VIS_PUBLIC: - root = ctx->func_hdr; - break; - case VIS_PROTECTED: - root = ctx->prot_hdr; - break; - case VIS_PRIVATE: - root = ctx->pvt_hdr; - break; - } - - pr_add(root, p_fmt("extern ~ ~;\n", - p_type(t), - (internal - ? p_internal_varname - : p_varname) (d->type, varname))); - pr_add(ctx->src, p_fmt("~~ ~;\n", - scope == VIS_PRIVATE - ? p_nil - : p_str("static "), - p_type(t), - (internal - ? p_internal_varname - : p_varname) (d->type, varname))); +void output_var(PRoot* out, Id tag, PNode* type, PNode* name){ + if(tag) + pr_add(out, tag, + p_fmt("extern ~ ~;\n", + type, + name)); + pr_add(out, "source_head", + p_fmt("~~ ~;\n", + tag?p_nil:p_str("static "), + type, + name)); } -void output_def(OutCtx* ctx, Def* d){ +void output_def(PRoot* out, Def* d){ PrimType* t=d->type; + PNode* type_var=p_internal_varname(t, p_str("type")); + /* GTK_TYPE_FOO macro */ - pr_add(ctx->type_hdr, p_str("\n\n")); - pr_add(ctx->src, p_str("\n")); - pr_add(ctx->prot_hdr, p_str("\n\n")); - pr_add(ctx->pvt_hdr, p_str("\n")); - pr_add(ctx->type_hdr, p_fmt("#define ~ \\\n" - " (~ ? ~ : ~())\n", - p_macro_name(t, "TYPE", NULL), - p_internal_varname(t, "type"), - p_internal_varname(t, "type"), - p_internal_varname(t, "init_type"))); - output_var(ctx, d, type_gtk_type, "type", VIS_PUBLIC, TRUE); + pr_add(out, "type", p_str("\n\n")); + pr_add(out, "source", p_str("\n")); + pr_add(out, "protected", p_str("\n\n")); + pr_add(out, "source_head", p_str("\n")); + pr_add(out, "type", p_fmt("#define ~ \\\n" + " (~ ? ~ : ~())\n", + p_macro_name(t, "TYPE", NULL), + type_var, + type_var, + p_internal_varname(t, p_str("init_type")))); + output_var(out, "type", + p_str("GtkType"), + type_var); switch(d->type->kind){ case GTK_TYPE_OBJECT: - output_object(ctx, d); + output_object(out, d); break; case GTK_TYPE_ENUM: - output_enum(ctx, d); + output_enum(out, d); break; case GTK_TYPE_FLAGS: - output_flags(ctx, d); + output_flags(out, d); break; default: ; diff --git a/tools/gcg/output.h b/tools/gcg/output.h index 2d6587a4ed..864d0f1c91 100644 --- a/tools/gcg/output.h +++ b/tools/gcg/output.h @@ -9,13 +9,18 @@ typedef gconstpointer PBool; extern const PBool ptrue; extern const PBool pfalse; -typedef struct{ - PRoot* type_hdr; - PRoot* func_hdr; - PRoot* prot_hdr; - PRoot* src; - PRoot* pvt_hdr; -}OutCtx; + +typedef struct _FunParams FunParams; +struct _FunParams{ + FunParams* next; + Type type; + PNode* name; + PNode* doc; +}; + +FunParams* fparams(const gchar* fmt, ...); +void fparams_free(FunParams* f); + typedef struct{ gboolean first : 1; @@ -24,20 +29,22 @@ typedef struct{ /* gboolean docs : 1; */ } ParamOptions; -PNode* p_params(GSList* args, ParamOptions* opt); +PNode* p_cast(PNode* type, PNode* expr); +PNode* p_params(FunParams* args, ParamOptions* opt); PNode* p_primtype(PrimType* t); PNode* p_type(Type* t); -PNode* p_self_type(ObjectDef* c, PBool const_self); -PNode* p_varname(PrimType* t, Id name); -PNode* p_internal_varname(PrimType* t, Id name); +PNode* p_varname(PrimType* t, PNode* name); +PNode* p_internal_varname(PrimType* t, PNode* name); PNode* p_object_member(Member* m); PNode* p_object_body(ObjectDef* c); PNode* p_object_decl(ObjectDef* c); PNode* p_class_member(Member* m); PNode* p_class_body(ObjectDef* c); PNode* p_class_decl(ObjectDef* c); -PNode* p_prototype(PrimType* type, Id funcname, - GSList* params, Type* rettype, gboolean internal); +PNode* p_prototype(Type* rettype, PNode* name, + PNode* args1, + FunParams* args2); + PNode* p_macro_name(PrimType* t, Id mid, Id post); @@ -51,17 +58,20 @@ PNode* p_guard_end(const gchar *c); PNode* p_c_ident(Id id); PNode* p_c_macro(Id id); - -void output_func(OutCtx* out, PrimType* type, Id funcname, GSList* params, - Type* rettype, Visibility scope, ObjectDef* self, - gboolean self_const, gboolean internal, PNode* body); -void output_var(OutCtx* out, Def* d, Type* t, Id varname, Visibility scope, - gboolean internal); +void output_func(PRoot* out, + Id tag, + Type* rettype, + PNode* name, + PNode* args1, + FunParams* args2, + PNode* body); -void output_def(OutCtx* out, Def* d); -void output_object(OutCtx* out, ObjectDef* d); -void output_enum(OutCtx* out, EnumDef* d); -void output_flags(OutCtx* out, FlagsDef* d); + +void output_var(PRoot* out, Id tag, PNode* type, PNode* name); +void output_def(PRoot* out, Def* d); +void output_object(PRoot* out, ObjectDef* d); +void output_enum(PRoot* out, EnumDef* d); +void output_flags(PRoot* out, FlagsDef* d); #endif diff --git a/tools/gcg/output_enum.c b/tools/gcg/output_enum.c index 5f3e47ff7b..ee61aea80d 100644 --- a/tools/gcg/output_enum.c +++ b/tools/gcg/output_enum.c @@ -27,25 +27,29 @@ PNode* p_enum_value(Id i, PrimType* t){ p_str(i)); } -void output_enum_type_init(OutCtx* out, EnumDef* e){ +void output_enum_type_init(PRoot* out, EnumDef* e){ PrimType* t=DEF(e)->type; - output_func(out, t, "init_type", NULL, type_gtk_type, TRUE, NULL, - FALSE, TRUE, + output_func(out, + "type", + type_gtk_type, + p_internal_varname(t, p_str("init_type")), + p_nil, + NULL, p_fmt("\tstatic GtkEnumValue values[~] = {\n" "~" "\t\t{0, NULL, NULL}\n" "\t};\n" - "\t%2 = gtk_type_register_enum (\"%1\", values);\n" - "\treturn %2;\n", + "\t~ = gtk_type_register_enum (\"~\", values);\n" + "\treturn ~;\n", p_prf("%d", g_slist_length(e->alternatives)+1), p_for(e->alternatives, p_enum_value, t), - p_internal_varname(t, "type"), + p_internal_varname(t, p_str("type")), p_primtype(t), - p_internal_varname(t, "type"))); + p_internal_varname(t, p_str("type")))); } -void output_enum(OutCtx* out, EnumDef* e){ +void output_enum(PRoot* out, EnumDef* e){ output_enum_type_init(out, e); - pr_add(out->type_hdr, p_enum_decl(e)); + pr_add(out, "type", p_enum_decl(e)); } diff --git a/tools/gcg/output_flags.c b/tools/gcg/output_flags.c index 8620b7b274..60bca7d53e 100644 --- a/tools/gcg/output_flags.c +++ b/tools/gcg/output_flags.c @@ -37,10 +37,14 @@ PNode* p_flags_value(Id i, PrimType* t){ p_str(i)); } -void output_flags_type_init(OutCtx* ctx, FlagsDef* e){ +void output_flags_type_init(PRoot* out, FlagsDef* e){ PrimType* t=DEF(e)->type; - output_func(ctx, t, "init_type", NULL, type_gtk_type, VIS_PUBLIC, - NULL, FALSE, TRUE, + output_func(out, + "type", + NULL, + p_internal_varname(t, p_str("init_type")), + p_nil, + NULL, p_fmt("\tstatic GtkFlagValue values[~] = {\n" "~" "\t\t{0, NULL, NULL}\n" @@ -49,13 +53,13 @@ void output_flags_type_init(OutCtx* ctx, FlagsDef* e){ "\treturn ~;\n", p_prf("%d", g_slist_length(e->flags)+1), p_for(e->flags, p_flags_value, t), - p_internal_varname(t, "type"), + p_internal_varname(t, p_str("type")), p_primtype(t), - p_internal_varname(t, "type"))); + p_internal_varname(t, p_str("type")))); } -void output_flags(OutCtx* ctx, FlagsDef* e){ - pr_add(ctx->type_hdr, p_flags_decl(e)); - output_flags_type_init(ctx, e); +void output_flags(PRoot* out, FlagsDef* e){ + pr_add(out, "type", p_flags_decl(e)); + output_flags_type_init(out, e); } diff --git a/tools/gcg/output_object.c b/tools/gcg/output_object.c index 15f034bf31..c1d4aeface 100644 --- a/tools/gcg/output_object.c +++ b/tools/gcg/output_object.c @@ -1,11 +1,13 @@ #include "output.h" +#include "marshall.h" PNode* p_object_member(Member* m){ DataMember* d; - if(m->membertype != MEMBER_DATA - || m->kind != KIND_DIRECT) + 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)); @@ -35,20 +37,32 @@ PNode* p_object_decl(ObjectDef* o){ PNode* p_class_member(Member* m){ ParamOptions o = {FALSE,FALSE,TRUE}; - if(m->kind != KIND_ABSTRACT) - return p_nil; if(m->membertype == MEMBER_DATA){ DataMember* d=(DataMember*)m; - return p_fmt("\t~ ~;\n", - p_type(&d->type), - p_c_ident(m->name)); + 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; - return p_fmt("\t~ (*~) (~~);\n", + 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), - p_type(&m->my_class->self_type[d->self_const]), - p_params(d->params, &o)); + parnode); }else return p_nil; } @@ -79,76 +93,128 @@ PNode* p_class_decl(ObjectDef* o){ p_class_name(DEF(o)->type)); } -PNode* p_abstract_member(PrimType* t, Id name){ +PNode* p_abstract_member(PrimType* t, PNode* name){ return p_fmt("~(GTK_OBJECT(self)->klass)->~", p_macro_name(t, NULL, "CLASS"), - p_c_ident(name)); + name); } -PNode* p_real_varname(PrimType* t, Id name){ +PNode* p_real_varname(PrimType* t, PNode* name){ return p_fmt("~_real", p_varname(t, name)); } -void output_method(OutCtx* ctx, Method* m){ - PrimType* t=DEF(MEMBER(m)->my_class)->type; - Id name=MEMBER(m)->name; - MemberKind k=MEMBER(m)->kind; - ParamOptions o={k==KIND_STATIC, TRUE, FALSE}; - output_func - (ctx,t, name, m->params, &m->ret_type, m->prot, - (k == KIND_STATIC) ? NULL : MEMBER(m)->my_class, - m->self_const, FALSE, - p_fmt("\t~~(~~);\n", - m->ret_type.prim ? p_str("return ") : p_nil, - (k == KIND_ABSTRACT - ? p_abstract_member - : p_real_varname)(t, name), - MEMBER(m)->kind != KIND_STATIC - ? p_nil - : p_str("self"), - p_params(m->params, &o))); +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)); } -void output_data_member(OutCtx* ctx, DataMember* m){ +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; + + if(k == METH_STATIC) + par = fparams("p", m->params); + else + par = fparams("tp", + &MEMBER(m)->my_class->self_type[m->self_const], + p_str("self"), + p_nil, + m->params); + switch(k){ + case METH_EMIT_PRE: + case METH_EMIT_POST: + case METH_EMIT_BOTH: + output_var(out, NULL, + p_str("GtkSignal"), + p_signal_id(m)); + dispatch=p_fmt("~(~, ~)", + p_signal_marshaller_name(m), + p_signal_id(m), + p_params(par, &o)); + break; + case METH_STATIC: + case METH_DIRECT: + dispatch=p_fmt("~(~)", + p_real_varname(t, name), + p_params(par, &o)); + break; + case METH_VIRTUAL: + dispatch=p_fmt("~(~)", + p_abstract_member(t, 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, + p_fmt("\t~~;\n", + m->ret_type.prim ? p_str("return ") : p_nil, + 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); switch(m->prot){ + FunParams* par; case DATA_READWRITE: { - gchar* set_name=g_strconcat("set_", name, NULL); - Param p; - GSList l; - p.type=m->type; - p.name=MEMBER(m)->name; - l.data=&p; - l.next=NULL; - output_func(ctx, t, set_name, &l, NULL, VIS_PUBLIC, - MEMBER(m)->my_class, FALSE, FALSE, - p_fmt("\tself->~ = 1~;\n", + par=fparams("tt", &MEMBER(m)->my_class->self_type[FALSE], + p_str("self"), + p_nil, + &m->type, + name, + p_nil); + output_func(out, + "functions", + NULL, + p_varname(t, p_fmt("set_~", name)), + p_nil, + par, + p_fmt("\tself->~ = ~;\n", name, name)); - g_free(set_name); + fparams_free(par); } /* fall through */ case DATA_READONLY: - output_func(ctx, t, MEMBER(m)->name, NULL, &m->type, VIS_PUBLIC, - MEMBER(m)->my_class, TRUE, FALSE, + par=fparams("t", &MEMBER(m)->my_class->self_type[TRUE], + p_str("self"), + p_nil); + output_func(out, + "functions", + NULL, + p_varname(t, name), + p_nil, + par, p_fmt("\treturn self->~;\n", name)); + fparams_free(par); case DATA_PROTECTED: } } -void output_member(OutCtx* ctx, Member* m){ +void output_member(PRoot* out, Member* m){ switch(m->membertype){ case MEMBER_METHOD: - output_method(ctx, (Method*)m); + output_method(out, (Method*)m); break; case MEMBER_DATA: - if(m->kind==KIND_DIRECT) - output_data_member(ctx, (DataMember*)m); + output_data_member(out, (DataMember*)m); break; } } @@ -168,11 +234,16 @@ PNode* p_class_macros(ObjectDef* o ){ p_macro_name(t, "TYPE", NULL)); } -void output_object_type_init(OutCtx* out, ObjectDef* o){ +void output_object_type_init(PRoot* out, ObjectDef* o){ PrimType* t=DEF(o)->type; - output_func(out, t, "init_type", NULL, type_gtk_type, - VIS_PUBLIC, NULL, FALSE, TRUE, - p_fmt("\tstatic GtkTypeInfo info = {\n" + PNode* type_var=p_internal_varname(t, p_str("type")); + output_func(out, + "type", + type_gtk_type, + p_internal_varname(t, p_str("init_type")), + p_nil, + NULL, + p_fmt("\tstatic const GtkTypeInfo info = {\n" "\t\t\"~\",\n" "\t\tsizeof (~),\n" "\t\tsizeof (~),\n" @@ -182,37 +253,93 @@ void output_object_type_init(OutCtx* out, ObjectDef* o){ "\t\tNULL,\n" "\t\tNULL,\n" "\t};\n" - "\t~ = gtk_type_unique (~, &info);\n" + "\tif (!~)\n" + "\t\t~ = gtk_type_unique (~, &info);\n" "\treturn ~;\n", p_primtype(t), p_primtype(t), - p_class_name(DEF(o)->type), - p_varname(t, "class_init"), - p_varname(t, "init"), - p_internal_varname(t, "type"), + 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), - p_internal_varname(t, "type"))); + type_var)); } +PNode* p_param_marshtype(gpointer p){ + Param* param=p; + return p_fmt(",\n\t\tGTK_TYPE_~", + p_gtype_name(marshalling_type(¶m->type), FALSE)); +} -void output_object(OutCtx* out, ObjectDef* o){ +PNode* p_member_class_init(gpointer m, gpointer o){ + ObjectDef* ob=o; + Member* mem=m; + Method* meth; + if(mem->membertype!=MEMBER_METHOD) + return p_nil; + meth=m; + switch(meth->kind){ + case METH_EMIT_PRE: + case METH_EMIT_POST: + case METH_EMIT_BOTH: + return 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\tGTK_TYPE_~,\n" + "\t\t~" + "~);\n" + "\tgtk_object_class_add_signals(obklass,\n" + "\t\t&~,\n" + "\t\t1);\n", + p_signal_id(meth), + p_str(mem->name), + p_str(meth->kind==METH_EMIT_PRE + ?"FIRST" + :meth->kind==METH_EMIT_POST + ?"LAST" + :"BOTH"), + p_class_name(DEF(ob)->type), + p_c_ident(mem->name), + p_signal_demarshaller_name(m), + p_gtype_name(marshalling_type(&meth->ret_type), + FALSE), + p_prf("%d", g_slist_length(meth->params)), + p_for(meth->params, p_param_marshtype, p_nil), + p_signal_id(meth)); + break; + default: + return p_nil; + break; + } +} + + + + +void output_class_init(PRoot* out, ObjectDef* o){ + output_func(out, NULL, + NULL, + p_varname(DEF(o)->type, p_str("class_init")), + p_fmt("~* klass", + p_class_name(DEF(o)->type)), + NULL, + p_fmt("\tGtkObjectClass* obklass = \n" + "\t\t(GtkObjectClass*) klass;\n" + "~", + p_for(o->members, p_member_class_init, o))); +} + +void output_object(PRoot* out, ObjectDef* o){ output_object_type_init(out, o); - pr_add(out->prot_hdr, p_class_body(o)); - pr_add(out->prot_hdr, p_class_decl(o)); - pr_add(out->type_hdr, p_object_decl(o)); - pr_add(out->prot_hdr, p_object_body(o)); + output_class_init(out, o); + pr_add(out, "protected", p_class_decl(o)); + pr_add(out, "protected", p_class_body(o)); + pr_add(out, "type", p_object_decl(o)); + pr_add(out, "protected", p_object_body(o)); g_slist_foreach(o->members, output_member_cb, out); } -/* -PNode* p_gtype(Type* t){ - if((t->indirection==0 && t->prim->kind==TYPE_TRANSPARENT) - || (t->indirection==1 && t->prim->kind==TYPE_CLASS)) - p_macro_name(s, t->prim, "TYPE", NULL); - else if(t->indirection) - return p_fmt( "GTK_TYPE_POINTER"); - else - g_error("Illegal non-pointer type ~~\n", - t->prim->name.module, - t->prim->name.type); -} -*/ diff --git a/tools/gcg/parser.y b/tools/gcg/parser.y index c218c1d585..396b3aaa54 100644 --- a/tools/gcg/parser.y +++ b/tools/gcg/parser.y @@ -1,17 +1,27 @@ %{ #include "gcg.h" #define YYDEBUG 1 + +static Module* current_module; +static Id current_header; +static ObjectDef* current_class; +static GSList* imports; +static Method* current_method; + +static GSList* imports_list; + %} %union { GSList* list; Id id; GString* str; - TypeName typename; PrimType* primtype; - Visibility methprot; + MethodKind methkind; + DataMemberKind datakind; + MethProtection methprot; DataProtection dataprot; - MemberKind kind; + MethodKind kind; Def* def; ObjectDef* class_def; Member* member; @@ -33,6 +43,7 @@ %token T_CLASS %token T_PRE_EMIT %token T_POST_EMIT +%token T_DUAL_EMIT %token T_SCOPE %token T_ABSTRACT %token T_EMPTY @@ -58,6 +69,7 @@ %token T_INT %token T_DOUBLE %token T_BOXED +%token T_SIGNAL %token T_IDENT %token T_HEADERNAME @@ -68,12 +80,12 @@ %type type %type typeorvoid %type semitype -%type typename %type primtype %type parent %type paramlist %type idlist -%type kinddef +%type methkind +%type datakind %type methprot %type dataprot %type classbody @@ -94,27 +106,29 @@ start_symbol: deffile ; -deffile: /* empty */ | deffile import | deffile modulescope; +deffile: declarations definitions; + +declarations: /* empty */ | declarations modulescope; + +definitions: current_module_def deflist; + +deflist: /* empty */ | deflist def { + put_def($2); +}; import: T_IMPORT ident T_END { imports=g_slist_prepend(imports, (gpointer)($2)); } modulescope: T_MODULE ident T_OPEN_B { - current_module=$2; -} modulebody T_CLOSE_B { + current_module=get_mod($2); +} decllist T_CLOSE_B { current_module=NULL; } T_END; -modulebody: /* empty */ | modulebody headerdef | modulebody def { - put_def ($2); - }; - -headerdef: T_HEADER T_HEADERNAME T_OPEN_B { - current_header=$2; -} decllist T_CLOSE_B { - current_header=NULL; -} T_END; +current_module_def: T_MODULE ident T_END { + current_module=get_mod($2); +}; decllist: /* empty */ | decllist decl; @@ -134,42 +148,11 @@ fundtype: T_INT { $$ = GTK_TYPE_FLAGS; } -simpledecl: fundtype typename T_END { - PrimType* t=g_new(PrimType, 1); - g_assert(!get_decl($2.module, $2.type)); - t->name = $2; - t->kind = $1; - t->decl_header = current_header; - t->def_header = NULL; - put_decl(t); +simpledecl: fundtype primtype T_END { + g_assert($2->kind==GTK_TYPE_INVALID); + $2->kind = $1; }; -/* -protclassdecl: T_PROTECTED T_CLASS typename T_END { - PrimType* t; - t=get_decl($3.module, $3.type); - if(!t){ - t=g_new(PrimType, 1); - t->name=$3; - t->kind=TYPE_CLASS; - t->decl_header=current_header; - } - g_assert(t->kind==TYPE_CLASS); - t->def_header=current_header; - put_decl(t); -} - -opaquedecl: T_OPAQUE typename T_END { - PrimType* t=g_new(PrimType, 1); - t->name = $2; - t->kind=TYPE_OPAQUE; - t->decl_header = NULL; - t->def_header = current_header; - g_assert(!get_decl($2.module, $2.type)); - put_decl(t); -}; -*/ - semitype: const_def primtype { $$.is_const = $1; $$.indirection = 0; @@ -184,7 +167,8 @@ type: semitype | semitype T_NOTNULLPTR { $$ = $1; $$.indirection++; $$.notnull = TRUE; -} +}; + ident: T_IDENT; @@ -193,20 +177,13 @@ typeorvoid: type | T_VOID { $$.indirection = 0; $$.is_const = FALSE; $$.notnull = FALSE; -} - -primtype: typename { - $$=get_decl($1.module, $1.type); - g_assert($$); }; -typename: ident T_SCOPE ident { - $$.module=$1; - $$.type=$3; + +primtype: ident T_SCOPE ident { + $$ = get_type($1, $3); } | ident { - g_assert(current_module); - $$.module=current_module; - $$.type=$1; + $$ = get_type(current_module->name, $1); }; paramlist: /* empty */ { @@ -229,20 +206,38 @@ param: type ident docstring { $$->type=$1; }; -kinddef: T_ABSTRACT { - $$ = KIND_ABSTRACT; +methkind: T_ABSTRACT { + $$ = METH_VIRTUAL; } | T_DIRECT { - $$ = KIND_DIRECT; + $$ = METH_DIRECT; } | /* empty */ { - $$ = KIND_DIRECT; + $$ = METH_DIRECT; } | T_STATIC { - $$ = KIND_STATIC; + $$ = METH_STATIC; +} | T_PRE_EMIT { + $$ = METH_EMIT_PRE; +} | T_POST_EMIT { + $$ = METH_EMIT_POST; +} | T_DUAL_EMIT { + $$ = METH_EMIT_BOTH; }; + +datakind: T_ABSTRACT { + $$ = DATA_STATIC_VIRTUAL; +} | T_DIRECT { + $$ = DATA_DIRECT; +} | /* empty */ { + $$ = DATA_DIRECT; +} | T_STATIC { + $$ = DATA_STATIC; +}; + + methprot: T_PROTECTED{ - $$ = VIS_PROTECTED; + $$ = METH_PROTECTED; } | T_PUBLIC { - $$ = VIS_PUBLIC; + $$ = METH_PUBLIC; }; dataprot: /* empty */ { @@ -320,29 +315,30 @@ classdef: T_CLASS primtype parent docstring T_OPEN_B { member_def: data_member_def | method_def; -data_member_def: dataprot kinddef type ident emitdef docstring T_END { + +data_member_def: dataprot datakind type ident emitdef docstring T_END { DataMember* m = g_new(DataMember, 1); m->prot = $1; m->type = $3; + m->kind = $2; $$ = MEMBER(m); $$->membertype = MEMBER_DATA; - $$->kind = $2; $$->name = $4; /* $$->emit = $5; */ $$->doc = $6; }; -method_def: methprot kinddef typeorvoid ident T_OPEN_P { +method_def: methprot methkind typeorvoid ident T_OPEN_P { current_method = g_new(Method, 1); } paramlist T_CLOSE_P const_def emitdef docstring T_END { current_method->prot = $1; current_method->ret_type = $3; current_method->self_const = $9; current_method->params = $7; + current_method->kind = $2; $$=MEMBER(current_method); current_method=NULL; $$->membertype = MEMBER_METHOD; - $$->kind = $2; $$->name = $4; /* $$->emit = $10; */ $$->doc = $11; @@ -371,4 +367,5 @@ GHashTable* class_hash; int yyerror (char* s){ g_error ("Parser error: %s", s); + return 0; } diff --git a/tools/gcg/pnode.c b/tools/gcg/pnode.c index 458e028812..2945eb47a8 100644 --- a/tools/gcg/pnode.c +++ b/tools/gcg/pnode.c @@ -5,11 +5,13 @@ const gconstpointer p_no_data = &p_no_data; static const gconstpointer p_node_magic_tag = &p_node_magic_tag; + #define BE_NODE(x) (g_assert((x) && ((PNode*)(x))->magic == &p_node_magic_tag)) static GMemChunk* p_node_chunk; static GList* p_float_list; +static GHashTable* p_str_hash; struct _PNode{ gconstpointer magic; @@ -46,7 +48,8 @@ static PNode* p_make(void){ void p_ref(PNode* node){ BE_NODE(node); - g_assert(node!=p_nil); + if(node==p_nil) + return; if(!node->ref_count){ p_float_list = g_list_remove_link(p_float_list, node->float_link); @@ -57,15 +60,19 @@ void p_ref(PNode* node){ void p_unref(PNode* node){ BE_NODE(node); - g_assert(node!=p_nil); + if(node==p_nil) + return; node->ref_count--; if(node->ref_count>0) return; else{ GSList* l; - for(l = node->children;l;l = l->next) - p_unref(l->data); - g_slist_free(node->children); + if(node->children){ + for(l = node->children;l;l = l->next) + p_unref(l->data); + g_slist_free(node->children); + } else + g_hash_table_remove(p_str_hash, node->str); g_free((gpointer)node->str); g_mem_chunk_free(p_node_chunk, node); } @@ -110,8 +117,16 @@ void p_traverse(PNode* node, PNodeTraverseFunc func, gpointer user_data){ } PNode* p_str(const gchar* str){ - PNode* n = p_make(); - n->str = g_strdup(str); + PNode* n; + + if(!p_str_hash) + p_str_hash = g_hash_table_new(g_str_hash, g_str_equal); + n = g_hash_table_lookup(p_str_hash, str); + if(!n){ + n = p_make(); + n->str = g_strdup(str); + g_hash_table_insert(p_str_hash, n->str, n); + } return n; } @@ -125,11 +140,11 @@ PNode* p_prf(const gchar* format, ...){ PNode* p_fmt(const gchar* f, ...){ va_list args; - PNode* n = p_make(); + gchar* b = f; + PNode* n; GSList* l = NULL; va_start(args, f); g_assert(f); - n->str = g_strdup(f); while(*f){ while(*f && *f != '~') f++; @@ -144,6 +159,10 @@ PNode* p_fmt(const gchar* f, ...){ f++; } } + if(!l) + return p_str(f); + n = p_make(); + n->str = g_strdup(b); n->children = g_slist_reverse(l); return n; } @@ -151,7 +170,8 @@ PNode* p_fmt(const gchar* f, ...){ PNode* p_lst(PNode* n, ...){ va_list args; GSList* l = NULL; - PNode* node = p_make(); + PNode* node; + g_assert(n); va_start(args, n); while(n){ BE_NODE(n); @@ -161,6 +181,7 @@ PNode* p_lst(PNode* n, ...){ } n = va_arg(args, PNode*); } + node = p_make(); node->children = g_slist_reverse(l); return node; } @@ -186,39 +207,64 @@ PNode* p_for(GSList* l, PNodeCreateFunc func, gpointer user_data){ return n; } +typedef struct _PRNode{ + GQuark tag; + PNode* node; +} PRNode; + + struct _PRoot{ GList* nodes; }; + PRoot* pr_new(void){ PRoot* pr = g_new(PRoot, 1); pr->nodes = NULL; return pr; } -void pr_add(PRoot* pr, PNode* node){ +void pr_add(PRoot* pr, const gchar* tag, PNode* node){ + PRNode* n; g_assert(pr); BE_NODE(node); if(node == p_nil) return; - pr->nodes=g_list_prepend(pr->nodes, node); + n = g_new(PRNode, 1); + n->tag = g_quark_from_string(tag); + n->node = node; + pr->nodes = g_list_prepend(pr->nodes, n); p_ref(node); } -void pr_write(PRoot* pr, FILE* stream){ +void pr_write(PRoot* pr, FILE* stream, const gchar** tags, gint n){ GList* l; + GQuark* quarks; + gint i; + + quarks=g_new(GQuark, n); + for(i=0;inodes); - while(l){ - p_write(l->data, stream); - l= l->prev; + for(l=g_list_last(pr->nodes);l;l=l->prev){ + PRNode* node = l->data; + for(i=0;itag==quarks[i]) + break; + if(i==n) + continue; + p_write(node->node, stream); } } void pr_free(PRoot* pr){ GList* l; - for(l=pr->nodes;l;l = l->next) - p_unref(l->data); + for(l=pr->nodes;l;l = l->next){ + PRNode* n = l->data; + p_unref(n->node); + g_free(n); + } g_list_free(pr->nodes); g_free(pr); } diff --git a/tools/gcg/pnode.h b/tools/gcg/pnode.h index ed4d7a33a3..973557e71a 100644 --- a/tools/gcg/pnode.h +++ b/tools/gcg/pnode.h @@ -1,9 +1,12 @@ +#ifndef __PNODE_H__ +#define __PNODE_H__ #include #include typedef struct _PNode PNode; typedef struct _PRoot PRoot; -PNode* p_nil; +typedef const gconstpointer Tag; +extern PNode* p_nil; typedef void (*PNodeTraverseFunc) (PNode* n, gpointer user_data); typedef PNode* (*PNodeCreateFunc) (); @@ -20,7 +23,9 @@ PNode* p_for(GSList* l, PNodeCreateFunc func, gpointer user_data); void p_traverse(PNode* node, PNodeTraverseFunc func, gpointer user_data); PRoot* pr_new(void); -void pr_add(PRoot* root, PNode* node); -void pr_write(PRoot* root, FILE* stream); +void pr_add(PRoot* root, const gchar* tag, PNode* node); +void pr_write(PRoot* pr, FILE* stream, const gchar** tags, gint n); void pr_free(PRoot* root); + +#endif