Changed lotsa internal stuff. Started work on signal wrappers

and marshallers.
This commit is contained in:
Lauri Alanko 1998-11-14 18:03:33 +00:00
parent 4d0d391c88
commit a8abef068c
18 changed files with 920 additions and 472 deletions

View File

@ -1,3 +1,8 @@
1998-11-14 Lauri Alanko <la@iki.fi>
* Changed lotsa internal stuff. Started work on signal wrappers
and marshallers.
1998-10-24 Lauri Alanko <la@iki.fi>
* Redid the backend. It takes more time and memory now, but should

View File

@ -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

View File

@ -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);
};

63
tools/gcg/fp.c Normal file
View File

@ -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;
}
}

View File

@ -5,13 +5,6 @@
#include <unistd.h>
#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;
}

View File

@ -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;

View File

@ -1,56 +1,51 @@
// this is just a simple test input file
module g {
header <glib.h> {
@int int;
};
@int int;
};
module Gtk {
header <gtk/gtktypeutils.h> {
@int Type;
};
@int Type;
};
module Gimp{
header <gimpobject.h> {
class Object;
};
header <gimplayer.h> {
class Layer;
};
header <gimpdrawable.h> {
class Drawable;
};
header <gimpimage.h> {
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);
};

View File

@ -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;

144
tools/gcg/marshall.c Normal file
View File

@ -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;i<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);
g_assert_not_reached();
return NULL;
}
PNode* p_gtabbr(gpointer p){
GtkType* 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_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(&param->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);
}

13
tools/gcg/marshall.h Normal file
View File

@ -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

View File

@ -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:
;

View File

@ -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

View File

@ -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));
}

View File

@ -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);
}

View File

@ -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(&param->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);
}
*/

View File

@ -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<id> T_IDENT
%token<id> T_HEADERNAME
@ -68,12 +80,12 @@
%type<type> type
%type<type> typeorvoid
%type<type> semitype
%type<typename> typename
%type<primtype> primtype
%type<primtype> parent
%type<list> paramlist
%type<list> idlist
%type<kind> kinddef
%type<methkind> methkind
%type<datakind> datakind
%type<methprot> methprot
%type<dataprot> dataprot
%type<list> 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;
}

View File

@ -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;i<n;i++)
quarks[i]=g_quark_from_string(tags[i]);
g_assert(pr);
l = g_list_last(pr->nodes);
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;i<n;i++)
if(node->tag==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);
}

View File

@ -1,9 +1,12 @@
#ifndef __PNODE_H__
#define __PNODE_H__
#include <glib.h>
#include <stdio.h>
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