mirror of https://github.com/GNOME/gimp.git
Changed lotsa internal stuff. Started work on signal wrappers
and marshallers.
This commit is contained in:
parent
4d0d391c88
commit
a8abef068c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(¶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);
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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:
|
||||
;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue